# HG changeset patch # User Matti Hamalainen # Date 1483844918 -7200 # Node ID 8efbb045d44d85f50901beff75d2bd045e4d9cd2 # Parent 1ada0cb9bdd96ea4442f8d7b1037e06147fd07df weather: Implement searching for nearest of measurement stations based on given lat/long coordinates. The distance calculation is naive pythagoraean one, should be changed to "Great circle distance" https://en.wikipedia.org/wiki/Great-circle_distance. (C implementation already done, just needs TCL-ization.) diff -r 1ada0cb9bdd9 -r 8efbb045d44d config.weather.example --- a/config.weather.example Sun Jan 08 04:56:54 2017 +0200 +++ b/config.weather.example Sun Jan 08 05:08:38 2017 +0200 @@ -35,7 +35,7 @@ ### ### Messages ### -set weather_msg_list_station [list "\002@station@\002 ( http://www.google.fi/maps/@@c_lat@,@c_lng@,15z )"] +set weather_msg_list_station [list "\002@station@\002 ( http://www.google.fi/maps/@@c_lat@,@c_lng@,18z )"] set weather_msg_result [list "\002@station@\002, mitattu klo @ctime@: \002@temp@°C\002"] @@ -51,6 +51,12 @@ set weather_msg_usage_prefix_1 "Käyttö: !sää " set weather_msg_usage_prefix_2 " !sää " +set weather_msg_list_nearest $weather_msg_list_station +set weather_msg_usage_nearest "lähin \[, \] -- näyttää annettuja koordinaatteja lähimpänä olevat mittausasemat" +set weather_msg_usage_nearest_invalid "lähin \[, \] -- näyttää annettuja koordinaatteja lähimpänä olevat mittausasemat" +set weather_msg_nearest_stations "Lähimmät mittausasemat (%1, %2): %3" + + set weather_msg_usage_def_set "vakio \[;\] -- asettaa vakiohavaintoaseman\nvakio -- näyttää nykyisen" set weather_msg_usage_alias "alias = (Lisää alias-nimen, esim. alias perse = turku)" set weather_msg_usage_unalias "unalias (Poistaa aliaksen)" diff -r 1ada0cb9bdd9 -r 8efbb045d44d weather.tcl --- a/weather.tcl Sun Jan 08 04:56:54 2017 +0200 +++ b/weather.tcl Sun Jan 08 05:08:38 2017 +0200 @@ -286,7 +286,8 @@ global weather_msg_aliased weather_msg_unaliased weather_msg_no_access global weather_msg_def_set weather_msg_def_not_set weather_msg_aliases global weather_msg_usage_stations weather_msg_stations weather_msg_list_station - global weather_msg_result + global weather_msg_list_nearest weather_msg_usage_nearest weather_msg_usage_nearest_invalid + global weather_msg_nearest_stations weather_msg_result # Check and handle arguments set rarglist [::textutil::split::splitx $uargs {\s+}] @@ -316,6 +317,47 @@ set res [join $result " ; "] weather_msg $upublic $unick $uchan $weather_msg_stations [list $res] return 0 + } elseif {$rarg == "lahin" || $rarg == "lähin" || $rarg == "closest" || $rarg == "nearest"} { + # List stations nearest to given coordinates + set qlist [::textutil::split::splitx [join [lrange $rarglist 1 end] " "] {\s*,\s*}] + set nlist [lsearch -all -inline -not -exact $qlist ""] + if {[llength $nlist] < 2} { + weather_usage $upublic $unick $uchan $weather_msg_usage_nearest + return 0 + } + + # Check argument types + set d_lat [lindex $nlist 0] + set d_lng [lindex $nlist 1] + if {![string is double -strict $d_lat] || ![string is double -strict $d_lng]} { + weather_msg $upublic $unick $uchan $weather_msg_usage_nearest_invalid + return 0 + } + + # Calculate distances between given coordinates for each location + set result {} + foreach {ukey uvalue} [array get weather_data] { + if {![string match "w_*" $ukey]} { + set delta_lat [expr {$d_lat - [lindex $uvalue 2]}] + set delta_lng [expr {$d_lng - [lindex $uvalue 3]}] + set dist [expr { sqrt($delta_lat * $delta_lat + $delta_lng * $delta_lng) }] + lappend result [list $ukey $dist] + } + } + + # Sort the list by distance + set usorted [lsort -real -index 1 $result] + + # Create a result list for few best/first matches + set uresult {} + foreach {uval} [lrange $usorted 0 2] { + lappend uresult [weather_get_str $weather_data([lindex $uval 0]) $weather_msg_list_nearest] + } + + # Print out the result + set res [join $uresult " ; "] + weather_msg $upublic $unick $uchan $weather_msg_nearest_stations [list $d_lat $d_lng $res] + return 0 } elseif {$rarg == "vakio" || $rarg == "default" || $rarg == "vakiot" || $rarg == "defaults"} { # List or set the default weather station name patterns for this user