comparison weather.tcl @ 430:8efbb045d44d

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.)
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 08 Jan 2017 05:08:38 +0200
parents 1ada0cb9bdd9
children 3c816fdc302f
comparison
equal deleted inserted replaced
429:1ada0cb9bdd9 430:8efbb045d44d
284 global weather_msg_no_results weather_msg_no_data_for_location 284 global weather_msg_no_results weather_msg_no_data_for_location
285 global weather_msg_usage_alias weather_msg_usage_unalias weather_msg_defloc 285 global weather_msg_usage_alias weather_msg_usage_unalias weather_msg_defloc
286 global weather_msg_aliased weather_msg_unaliased weather_msg_no_access 286 global weather_msg_aliased weather_msg_unaliased weather_msg_no_access
287 global weather_msg_def_set weather_msg_def_not_set weather_msg_aliases 287 global weather_msg_def_set weather_msg_def_not_set weather_msg_aliases
288 global weather_msg_usage_stations weather_msg_stations weather_msg_list_station 288 global weather_msg_usage_stations weather_msg_stations weather_msg_list_station
289 global weather_msg_result 289 global weather_msg_list_nearest weather_msg_usage_nearest weather_msg_usage_nearest_invalid
290 global weather_msg_nearest_stations weather_msg_result
290 291
291 # Check and handle arguments 292 # Check and handle arguments
292 set rarglist [::textutil::split::splitx $uargs {\s+}] 293 set rarglist [::textutil::split::splitx $uargs {\s+}]
293 set rarg [lindex $rarglist 0] 294 set rarg [lindex $rarglist 0]
294 295
313 } 314 }
314 } 315 }
315 316
316 set res [join $result " ; "] 317 set res [join $result " ; "]
317 weather_msg $upublic $unick $uchan $weather_msg_stations [list $res] 318 weather_msg $upublic $unick $uchan $weather_msg_stations [list $res]
319 return 0
320 } elseif {$rarg == "lahin" || $rarg == "lähin" || $rarg == "closest" || $rarg == "nearest"} {
321 # List stations nearest to given coordinates
322 set qlist [::textutil::split::splitx [join [lrange $rarglist 1 end] " "] {\s*,\s*}]
323 set nlist [lsearch -all -inline -not -exact $qlist ""]
324 if {[llength $nlist] < 2} {
325 weather_usage $upublic $unick $uchan $weather_msg_usage_nearest
326 return 0
327 }
328
329 # Check argument types
330 set d_lat [lindex $nlist 0]
331 set d_lng [lindex $nlist 1]
332 if {![string is double -strict $d_lat] || ![string is double -strict $d_lng]} {
333 weather_msg $upublic $unick $uchan $weather_msg_usage_nearest_invalid
334 return 0
335 }
336
337 # Calculate distances between given coordinates for each location
338 set result {}
339 foreach {ukey uvalue} [array get weather_data] {
340 if {![string match "w_*" $ukey]} {
341 set delta_lat [expr {$d_lat - [lindex $uvalue 2]}]
342 set delta_lng [expr {$d_lng - [lindex $uvalue 3]}]
343 set dist [expr { sqrt($delta_lat * $delta_lat + $delta_lng * $delta_lng) }]
344 lappend result [list $ukey $dist]
345 }
346 }
347
348 # Sort the list by distance
349 set usorted [lsort -real -index 1 $result]
350
351 # Create a result list for few best/first matches
352 set uresult {}
353 foreach {uval} [lrange $usorted 0 2] {
354 lappend uresult [weather_get_str $weather_data([lindex $uval 0]) $weather_msg_list_nearest]
355 }
356
357 # Print out the result
358 set res [join $uresult " ; "]
359 weather_msg $upublic $unick $uchan $weather_msg_nearest_stations [list $d_lat $d_lng $res]
318 return 0 360 return 0
319 } elseif {$rarg == "vakio" || $rarg == "default" || $rarg == "vakiot" || $rarg == "defaults"} { 361 } elseif {$rarg == "vakio" || $rarg == "default" || $rarg == "vakiot" || $rarg == "defaults"} {
320 # List or set the default weather station name patterns for this user 362 # List or set the default weather station name patterns for this user
321 363
322 # Access check 364 # Access check