#!/usr/bin/wish source yarrglib.tcl source panner.tcl package require http set debug 0 proc debug {m} { global debug if {$debug} { puts "DEBUG $m" } } proc badusage {m} { puts stderr "where-vessels: bad usage: $m" exit 1 } proc nextarg {} { global ai argv if {$ai >= [llength $argv]} { badusage "option [lindex $argv [expr {$ai-1}]] needs a value" } set v [lindex $argv $ai] incr ai return $v } proc glset {n val} { upvar #0 $n var set var $val } set notes_loc vessel-notes set scraper {./yppedia-ocean-scraper --chart} proc parseargs {} { global ai argv global debug scraper set ai 0 while {[regexp {^\-} [set arg [lindex $argv $ai]]]} { incr ai switch -exact -- $arg { -- { break } --pirate { glset pirate [string totitle [nextarg]] } --ocean { glset ocean [string totitle [nextarg]] } --clipboard-file { load-clipboard-file [nextarg] } --local-html-dir { lappend scraper --local-html-dir=[nextarg] } --notes { glset notes_loc [nextarg] } --debug { incr debug } default { badusage "unknown option $arg" } } } set argv [lrange $argv $ai end] if {[llength $argv]} { badusage "non-option args not allowed" } } proc argdefaults {} { global ocean notes_loc pirate scraper if {![info exists ocean] || ![info exists pirate]} { set cmd {./yarrg --find-window-only --quiet} if {[info exists ocean]} { lappend cmd --ocean $ocean } if {[info exists pirate]} { lappend cmd --pirate $pirate } manyset [split [eval exec $cmd] " "] ocean pirate } lappend scraper $ocean } proc load-notes {} { global notes_loc notes catch { unset notes } if {[regexp {^\w+\:} $notes_loc]} { vwait idletasks debug "FETCHING NOTES" ::http::geturl $notes_loc switch -glob [::http::status].[::http::ncode] { ok.200 { } ok.* { error "retrieving vessel-notes $url: [::http::code]" } * { error "retrieving vessel-notes $url: [::http::error]" } } set notes_data [::http::data] ::http::cleanup } else { set vn [open $notes_loc] set notes_data [read $vn] close $vn } foreach l [split $notes_data "\n"] { regsub -all {\t+} $l "\t" l manyset [split $l "\t"] vname vid owner note set nk $vid.$vname debug "SET NOTE $nk" set notes($nk) [list $owner $note] } } proc vessel {vin} { global pirate notes_used upvar 1 $vin vi switch -exact $vi(vesselClass) { smsloop { set sz 00sl } lgsloop { set sz 01ct } dhow { set sz 02dh } longship { set sz 03ls } baghlah { set sz 04bg } merchbrig { set sz 05mb } warbrig { set sz 06wb } xebec { set sz 07xe } warfrig { set sz 08wf } merchgal { set sz 09mg } grandfrig { set sz 10gf } default { error "$vi(vesselClass) ?" } } set abbrev $sz switch -exact $vi(vesselSubclass) { null { } icy { append abbrev F } default { error "$vi(vesselSubclass) ?" } } switch -exact $vi(isLocked)/$vi(isBattleReady) { true/false { append abbrev 2- } false/false { append abbrev 1+ } false/true { append abbrev 0* } default { error "$vi(isLocked)/$vi(isBattleReady) ?" } } switch -exact $vi(inPort) { true { } false { append abbrev ? } default { error "$vi(inPort) ?" } } set nk $vi(vesselId).$vi(vesselName) upvar #0 notes($nk) note if {[info exists note]} { manyset $note owner xabbrev if {![string compare $owner $pirate]} { append abbrev = } else { append abbrev - } append abbrev $xabbrev set notes_used($nk) 1 } else { debug "UNKNOWN $nk" } set kk "$vi(islandName) $abbrev" upvar #0 count($kk) k if {![info exists k]} { set k 0 } incr k } set clipboard {} proc parse-clipboard {} { global clipboard count notes notes_used catch { unset count } catch { unset notes_used } set itemre { (\w+) = ([^=]*) } set manyitemre "^\\\[ $itemre ( (?: ,\\ $itemre)* ) \\]\$" debug $manyitemre foreach l [split $clipboard "\n"] { if {![string length $l]} continue catch { unset vi } while 1 { if {![regexp -expanded $manyitemre $l dummy \ thiskey thisval rhs]} { error "$l ?" } set vi($thiskey) $thisval if {![string length $rhs]} break regsub {^, } $rhs {} rhs set l "\[$rhs\]" } vessel vi } foreach nk [lsort [array names notes]] { if {![info exists notes_used($nk)]} { debug "IGNORED NOTE $nk" } } } proc load-clipboard-file {fn} { set f [open $fn] glset clipboard [read $f] close $f } proc load-chart {} { global chart scraper debug "FETCHING CHART" set chart [eval exec $scraper [list | perl -we { use strict; use CommodsScrape; use IO::File; use IO::Handle; yppedia_chart_parse(\*STDIN, (new IO::File ">/dev/null"), sub { sprintf "%d %d", @_; }, sub { printf "archlabel %d %d %s\n", @_; }, sub { printf "island %s %s\n", @_; }, sub { printf "league %s %s %s.\n", @_; }, sub { printf STDERR "warning: %s: incomprehensible: %s", @_; } ); STDOUT->error and die $!; }]] } set scale 16 proc coord {c} { global scale return [expr {$c * $scale}] } proc chart-got/archlabel {args} { } proc chart-got/island {x y args} { # debug "ISLE $x $y $args" global canvas isleloc set isleloc($args) [list $x $y] set sz 5 # $canvas create oval \ # [expr {[coord $x] - $sz}] [expr {[coord $y] - $sz}] \ # [expr {[coord $x] + $sz}] [expr {[coord $y] + $sz}] \ # -fill blue $canvas create text [coord $x] [coord $y] \ -text $args -anchor s } proc chart-got/league {x1 y1 x2 y2 kind} { # debug "LEAGUE $x1 $y1 $x2 $y2 $kind" global canvas set l [$canvas create line \ [coord $x1] [coord $y1] \ [coord $x2] [coord $y2]] if {![string compare $kind .]} { $canvas itemconfigure $l -dash . } } proc draw {} { global chart count isleloc canvas foreach l [split $chart "\n"] { # debug "CHART-GOT $l" set proc [lindex $l 0] eval chart-got/$proc [lrange $l 1 end] } set lastislandname {} foreach key [lsort [array names count]] { set c $count($key) # debug "SHOWING $key $c" regexp {^(.*) (\S+)$} $key dummy islandname abbrev if {[string compare $lastislandname $islandname]} { manyset $isleloc($islandname) x y set x [coord $x] set y [coord $y] set lastislandname $islandname # debug "START Y $y" } set text $abbrev regsub -all {[0-9]} $text {} text if {$c > 1} { set text [format "%2d%s" $c $text] } else { set text [format " %s" $text] } set id [$canvas create text $x $y \ -anchor nw -font fixed \ -text $text] set bbox [$canvas bbox $id] set bid [eval $canvas create rectangle $bbox -fill white] $canvas lower $bid $id manyset $bbox dummy dummy dummy y # debug "NEW Y $y" } panner::updatecanvas-bbox .ctrl.pan } proc widgets-setup {} { global canvas debug frame .f -border 1 -relief groove set canvas .f.c canvas $canvas pack $canvas -expand 1 -fill both pack .f -expand 1 -fill both -side left frame .ctrl pack .ctrl -side right debug "BBOX [$canvas bbox all]" panner::canvas-scroll-bbox .f.c panner::create .ctrl.pan .f.c 120 120 $debug pack .ctrl.pan -side top -pady 10 -padx 5 frame .ctrl.zoom pack .ctrl.zoom -side top button .ctrl.zoom.out -text - -font {Courier 16} -command {zoom /2} button .ctrl.zoom.in -text + -font {Courier 16} -command {zoom *2} pack .ctrl.zoom.out .ctrl.zoom.in -side left wm geometry . 1024x480 } proc zoom {extail} { global scale canvas set nscale [expr "\$scale $extail"] debug "ZOOM $scale $nscale" if {$nscale < 1 || $nscale > 200} return set scale $nscale $canvas delete all draw } parseargs argdefaults httpclientsetup where-vessels load-chart widgets-setup load-notes parse-clipboard draw