Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
graphs.tcl
Go to the documentation of this file.
1 ### graph.tcl: part of Scid.
2 
3 # ::tools::graphs::Save
4 #
5 # Saves a graph (e.g. tree graph, filter graph, rating graph) to a
6 # color or greyscale Postscript file.
7 #
8 # The mode should be "color" or "gray".
9 #
10 proc ::tools::graphs::Save {mode w} {
11  if {! [winfo exists $w]} { return}
12  set ftypes {{"PostScript files" {.eps .ps}} {"All files" *}}
13  set fname [tk_getSaveFile -filetypes $ftypes -parent $w -defaultextension ".eps" -title "Scid: Save Graph"]
14  if {$fname == ""} { return}
15 
16  if {[file extension $fname] != ".eps" && [file extension $fname] != ".ps" } {
17  append fname ".eps"
18  }
19 
20  if {[catch {$w postscript -file $fname -colormode $mode} result]} {
21  tk_messageBox -icon info -parent $w -title "Scid" -message $result
22  }
23 }
24 
25 ########################################
26 # Configure Filter graph window
27 
28 if { ! [info exists FilterMinElo] } {
29  set FilterMinElo 2100
30  set FilterMaxElo 2800
31  set FilterStepElo 100
32  set FilterGuessELO 1
33  set FilterMaxYear [clock format [clock seconds] -format {%Y}]
34  set FilterMinYear [expr {$FilterMaxYear - 12}]
35  set FilterStepYear 1
36  set FilterMinMoves 5
37  set FilterMaxMoves 80
38  set FilterStepMoves 1
39 }
40 
41 #Check for illegal Values and set to default values
42 proc checkConfigFilterGraph {} {
43  global FilterMaxMoves FilterMinMoves FilterStepMoves FilterMaxElo FilterMinElo FilterStepElo FilterMaxYear FilterMinYear FilterStepYear
44  if { $FilterStepMoves < 1 } { set FilterStepMoves 1}
45  if { $FilterStepElo < 1 } { set FilterStepElo 100}
46  if { $FilterStepYear < 1 } { set FilterStepYear 1}
47  if { $FilterMinMoves < 1 } { set FilterMinMoves 5}
48  if { $FilterMinElo < 0 } { set FilterMinElo 2100}
49  if { $FilterMinYear < 1 } { set FilterMinYear [expr {$FilterMaxYear - 12}]}
50  if { $FilterMaxMoves < 1 } { set FilterMaxMoves 80}
51  if { $FilterMaxElo < 1 } { set FilterMaxElo 2800}
52  if { $FilterMaxYear < 1 } { set FilterMaxYear [clock format [clock seconds] -format {%Y}]}
53 }
54 
55 proc configureFilterGraph {} {
56  global FilterMaxMoves FilterMinMoves FilterStepMoves FilterMaxElo FilterMinElo FilterStepElo FilterMaxYear FilterMinYear FilterStepYear FilterGuessELO
57 
58  set w .configFilterGraph
59  if {[winfo exists $w]} {
60  destroy $w
61  }
62 
64  wm title $w $::tr(ConfigureFilter)
66  bind $w <F1> {helpWindow Graphs Filter}
67  ttk::labelframe $w.filternew -text "Config $::tr(Year) $::tr(Rating)"
68  set col 0
69  set row 0
70  #Create input for each configurationvalue
71  foreach { i n } { Year Year Elo Rating Moves moves} {
72  ttk::label $w.filternew.label$i -text $::tr($n): -font font_Bold
73  grid $w.filternew.label$i -row $row -column $col -sticky w
74  incr col
75  foreach {j k} { FilterMin " " FilterMax " - " FilterStep " Interval:"} {
76  ttk::label $w.filternew.label$j$i -text $k
77  ttk::entry $w.filternew.i$j$i -textvariable $j$i -justify right -width 5 -validate all -validatecommand { regexp {^[0-9]{0,4}$} %P }
78  grid $w.filternew.label$j$i -row $row -column $col -sticky w
79  incr col
80  grid $w.filternew.i$j$i -row $row -column $col -sticky w
81  incr col
82  }
83  if { $i == "Elo" } {
84  ttk::checkbutton $w.filternew.iEloGuess -text $::tr(FilterEstimate) -onvalue 1 -offvalue 0 -variable FilterGuessELO
85  grid $w.filternew.iEloGuess -row $row -column $col -sticky w -padx "5 0"
86  }
87  incr row
88  set col 0
89  }
90  if { [winfo exists .statsWin]} {
91  ttk::labelframe $w.filterold -text "Config StatYear StatElo OldYear OldElo"
92  foreach { i h v s } { Elo OprepStatBoth r* "+" Year OprepStatSince y* ".01.01" } {
93  ttk::frame $w.filterold.old$i
94  ttk::label $w.filterold.old$i.label -textvariable ::tr($h) -font font_Bold
95  ttk::scrollbar $w.filterold.old$i.ybar -command "$w.filterold.old$i.list yview"
96  listbox $w.filterold.old$i.list -yscrollcommand "$w.filterold.old$i.ybar set" \
97  -height 7 -width 10 -selectmode multiple -exportselection 0
98  pack $w.filterold.old$i.label -side top -anchor w
99  pack $w.filterold.old$i.ybar -side right -fill y
100  pack $w.filterold.old$i.list -side left -fill both -expand 1
101  set j 0
102  foreach y [lsort -decreasing [array names ::windows::stats::display $v]] {
103  set value [string range $y 1 end]
104  $w.filterold.old$i.list insert end "$value$s"
105  if { $::windows::stats::display($y) } {
106  $w.filterold.old$i.list selection set $j
107  }
108  incr j
109  }
110  }
111  pack $w.filterold.oldElo -side left -expand 1 -in $w.filterold -fill both -padx "0 10"
112  pack $w.filterold.oldYear -side left -expand 1 -fill both -in $w.filterold
113  }
114 
115  ttk::frame $w.buttons
116  ttk::button $w.buttons.close -textvar ::tr(Close) -command {
117  checkConfigFilterGraph; ::tools::graphs::filter::Refresh
118  ::tools::graphs::absfilter::Refresh; destroy .configFilterGraph }
119  ttk::button $w.buttons.standard -textvar ::tr(Defaults) -command {
120  set FilterMinElo 2100
121  set FilterMaxElo 2800
122  set FilterStepElo 100
123  set FilterMaxYear [clock format [clock seconds] -format {%Y}]
124  set FilterMinYear [expr {$FilterMaxYear - 12}]
125  set FilterStepYear 1
126  set FilterMinMoves 5
127  set FilterMaxMoves 80
128  set FilterStepMoves 1
129  set FilterGuessELO 1
130  }
131  if { [winfo exists .statsWin]} {
132  ttk::button $w.buttons.update -textvar ::tr(Update) -command { checkConfigFilterGraph
133  set j 0
134  foreach i [lsort -decreasing [array names ::windows::stats::display y*]] {
135  set ::windows::stats::display($i) [.configFilterGraph.filterold.oldYear.list selection includes $j]
136  incr j
137  }
138  set j 0
139  foreach i [lsort -decreasing [array names ::windows::stats::display r*]] {
140  set ::windows::stats::display($i) [.configFilterGraph.filterold.oldElo.list selection includes $j]
141  incr j
142  }
143  ::tools::graphs::absfilter::Refresh;
144  ::tools::graphs::filter::Refresh
145  ::windows::stats::refresh_wnd
146  }
147  } else {
148  ttk::button $w.buttons.update -textvar ::tr(Update) -command { checkConfigFilterGraph
149  ::tools::graphs::absfilter::Refresh;
150  ::tools::graphs::filter::Refresh
151  }
152  }
153 
154  pack $w.filternew -side top -fill x
155  if { [winfo exists .statsWin]} {
156  pack $w.filterold -side top -fill both -expand 1 -pady "10 0"
157  }
158  pack $w.buttons -anchor e
159  packdlgbuttons $w.buttons.close $w.buttons.update $w.buttons.standard
160  focus $w.filternew.iFilterMinYear
161  bind $w <Configure> "recordWinSize $w"
162 }
163 
164 #####################
165 # Filter graph window
166 
167 # ::tools::graphs::filter::type
168 # can be "decade", "year" or "elo" , "move"
169 #
170 set ::tools::graphs::filter::type year
171 
172 proc tools::graphs::filter::Open {} {
173  global filterGraph
174  set w .fgraph
175  if {[winfo exists $w]} {
176  focus .
177  destroy $w
178  set filterGraph 0
179  return
180  }
181  win::createDialog $w 0
182  menu $w.menu
183  ::setMenu $w $w.menu
184  $w.menu add cascade -label GraphFile -menu $w.menu.file
185  configMenuText $w.menu 0 GraphFile $::language
186  menu $w.menu.file
187  $w.menu.file add command -label GraphFileColor -command "::tools::graphs::Save color $w.c"
188  configMenuText $w.menu.file 0 GraphFileColor $::language
189  $w.menu.file add command -label GraphFileGrey -command "::tools::graphs::Save gray $w.c"
190  configMenuText $w.menu.file 1 GraphFileGrey $::language
191  $w.menu.file add separator
192  $w.menu.file add command -label GraphFileClose -command "destroy $w"
193  configMenuText $w.menu.file 3 GraphFileClose $::language
194  wm title $w $::tr(TitleFilterGraph)
195  set filterGraph 1
196  bind $w <Destroy> {set filterGraph 0}
197 
198  ttk::frame $w.b
199  pack $w.b -side top -fill x
200  ttk::label $w.b.status -width 1 -font font_Small -anchor w
201 
202  canvas $w.c -width 600 -height 400 -selectforeground [ttk::style lookup . -foreground] -background [ttk::style lookup . -background]
203  $w.c create text 25 5 -tag title -justify center -width 1 \
204  -font font_Small -anchor n
205  $w.c create text 250 295 -tag type -justify center -width 1 \
206  -font font_Small -anchor s
207  pack $w.c -side top -expand yes -fill both
209 
210  bind $w <F1> {helpWindow Graphs Filter}
211  bind $w <Configure> {
212  .fgraph.c itemconfigure title -width [expr {[winfo width .fgraph.c] - 50}]
213  .fgraph.c coords title [expr {[winfo width .fgraph.c] / 2}] 10
214  .fgraph.c itemconfigure type -width [expr {[winfo width .fgraph.c] - 50}]
215  .fgraph.c coords type [expr {[winfo width .fgraph.c] / 2}] \
216  [expr {[winfo height .fgraph.c] - 10}]
217  ::utils::graph::configure filter -height [expr {[winfo height .fgraph.c] - 80}]
218  ::utils::graph::configure filter -width [expr {[winfo width .fgraph.c] - 60}]
219  ::utils::graph::redraw filter
220  }
221  bind $w.c <1> tools::graphs::filter::Switch
222  bind $w.c <$::MB3> ::tools::graphs::filter::Refresh
223 
224  foreach {name text} {decade Decade year Year elo Rating move moves} {
225  ttk::radiobutton $w.b.$name -text $::tr($text) \
226  -variable ::tools::graphs::filter::type -value $name \
227  -command ::tools::graphs::filter::Refresh
228  pack $w.b.$name -side left -padx 1 -pady 2
229  }
230  ttk::button $w.b.setup -image tb_config -command configureFilterGraph
231  pack $w.b.decade $w.b.elo -side left -padx 1 -pady 2
232  pack $w.b.setup -side right -pady 2
233  pack $w.b.status -side left -padx 2 -pady 2 -fill x -expand yes
234 
236 }
237 
238 proc tools::graphs::filter::Switch {} {
239  variable type
240  switch $type {
241  "decade" { set type "year"}
242  "year" { set type "elo"}
243  "elo" { set type "move"}
244  "move" { set type "decade"}
245  }
247 }
248 
249 proc ::tools::graphs::filter::Refresh {} {
250  global FilterMaxMoves FilterMinMoves FilterStepMoves FilterMaxElo FilterMinElo FilterStepElo FilterMaxYear FilterMinYear FilterStepYear FilterGuessELO
251 
252  set w .fgraph
253  if {! [winfo exists $w]} { return}
254 
255  $w.c itemconfigure title -width [expr {[winfo width $w.c] - 50}]
256  $w.c coords title [expr {[winfo width $w.c] / 2}] 10
257  $w.c itemconfigure type -width [expr {[winfo width $w.c] - 50}]
258  $w.c coords type [expr {[winfo width $w.c] / 2}] \
259  [expr {[winfo height $w.c] - 10}]
260  set height [expr {[winfo height $w.c] - 80}]
261  set width [expr {[winfo width $w.c] - 60}]
262  set vlines {}
263  if {$::tools::graphs::filter::type == "elo"} {
264  # Vertical lines for Elo-range graph:
265  for {set i 1} {$i <= $FilterMaxElo- $FilterMinElo} { incr i} {
266  lappend vlines [list gray80 1 at $i.5]
267  }
268  } elseif {$::tools::graphs::filter::type == "year"} {
269  # Vertical lines for Year-range graph:
270  for {set i 1} {$i <= $FilterMaxYear- $FilterMinYear} {incr i} {
271  lappend vlines [list gray80 1 at $i.5]
272  }
273  } elseif {$::tools::graphs::filter::type == "decade"} {
274  # Vertical lines for Decade graph: most are gray, but those
275  # just before 1950s and 2000s are blue to make them stand out.
276  for {set i 1} {$i < 10} {incr i} {
277  set vlineColor gray80
278  if {$i == 4 || $i == 9} { set vlineColor steelBlue}
279  lappend vlines [list $vlineColor 1 at $i.5]
280  }
281  }
282 
283  ::utils::graph::create filter -width $width -height $height -xtop 40 -ytop 35 \
284  -ytick 1 -xtick 1 -font font_Small -canvas $w.c -textcolor black \
285  -vline $vlines -background lightYellow -tickcolor black -xmin 0 -xmax 1
287  busyCursor .
288  update
289 
290  set count 0
291  set dlist {}
292  set xlabels {}
293  set max 0.0
294 
295  # Generate plot values and labels:
296  if {$::tools::graphs::filter::type == "decade"} {
297  set ftype date
298  set typeName $::tr(Decade)
299  set rlist [list 0000 1919 -1919 1920 1929 20-29 \
300  1930 1939 30-39 1940 1949 40-49 1950 1959 50-59 \
301  1960 1969 60-69 1970 1979 70-79 1980 1989 80-89 \
302  1990 1999 90-99 2000 2009 2000+]
303  } elseif {$::tools::graphs::filter::type == "year"} {
304  set ftype date
305  set typeName $::tr(Year)
306  set endYear $FilterMaxYear
307  set startYear $FilterMinYear
308  set rlist {}
309  for {set i $startYear} {$i <= $endYear} {set i [expr {$i + $FilterStepYear}]} {
310  lappend rlist $i
311  lappend rlist [expr {$i+$FilterStepYear-1}]
312  lappend rlist [expr {$i+$FilterStepYear/2}]
313  }
314  } elseif {$::tools::graphs::filter::type == "elo"} {
315  set ftype elo
316  set typeName $::tr(Rating)
317  # set rlist [list 0 1999 0-1999 2000 2099 20xx 2100 2199 21xx \
318  2200 2299 22xx 2300 2399 23xx 2400 2499 24xx \
319  2500 2599 25xx 2600 2699 26xx 2700 3999 2700+]
320  set endElo $FilterMaxElo
321  set startElo $FilterMinElo
322  set rlist {}
323  for {set i $startElo} {$i <= $endElo} {set i [expr {$i + $FilterStepElo}]} {
324  lappend rlist $i
325  lappend rlist [expr {$i+$FilterStepElo-1}]
326  # shorten gap between 0 and "useful" ratings 1800
327  set j $i
328  if { $i < 100 } { set i [expr { 1800 - $FilterStepElo}]}
329  lappend rlist [concat $j-[expr {$i+$FilterStepElo-1}]]
330  }
331  } else {
332  set ftype move
333  set typeName $::tr(moves)
334  set startMove $FilterMinMoves
335  set endMove $FilterMaxMoves
336  set rlist {}
337  for {set i $startMove} {$i <= $endMove} {set i [expr {$i + $FilterStepMoves}]} {
338  lappend rlist [expr {2*$i}]
339  lappend rlist [expr {2*($i+$FilterStepMoves)-1}]
340  if { $i % 5 == 0 } {
341  lappend rlist $i
342  } else {
343  lappend rlist ""
344  }
345  }
346  }
347 
348  foreach {start end label} $rlist {
349  if {$ftype == "date"} { append end ".12.31"}
350  set r [sc_filter freq [sc_base current] dbfilter $ftype $start $end $FilterGuessELO]
351  set filter [lindex $r 0]
352  set all [lindex $r 1]
353  if {$all == 0} {
354  set freq 0.0
355  } else {
356  set freq [expr {double($filter) * 1000.0 / double($all)}]
357  }
358  if {$freq >= 1000.0} { set freq 999.9}
359  incr count
360  lappend dlist $count
361  lappend dlist $freq
362  if {$freq > $max} { set max $freq}
363  lappend xlabels [list $count $label]
364  }
365 
366  # Find a suitable spacing of y-axis labels:
367  set ytick 0.1
368  if {$max > 1.0} { set ytick 0.2}
369  if {$max > 2.5} { set ytick 0.5}
370  if {$max > 5} { set ytick 1}
371  if {$max > 10} { set ytick 2}
372  if {$max > 25} { set ytick 5}
373  if {$max > 50} { set ytick 10}
374  if {$max > 100} { set ytick 20}
375  if {$max > 250} { set ytick 50}
376  if {$max > 500} { set ytick 100}
377  set hlines [list [list gray80 1 each $ytick]]
378  # Add mean horizontal line:
379  set filter [sc_filter count]
380  set all [sc_base numGames $::curr_db]
381  if {$all > 0} {
382  set mean [expr {double($filter) * 1000.0 / double($all)}]
383  if {$mean >= 1000.0} { set mean 999.9}
384  lappend hlines [list red 1 at $mean]
385  }
386 
387  # Create fake dataset with bounds so we see 0.0::
388  #::utils::graph::data decade bounds -points 0 -lines 0 -bars 0 -coords {1 0.0 1 0.0}
389 
390  ::utils::graph::data filter data -color darkBlue -points 1 -lines 1 -bars 0 \
391  -linewidth 2 -radius 4 -outline darkBlue -coords $dlist
392  ::utils::graph::configure filter -xlabels $xlabels -ytick $ytick \
393  -hline $hlines -ymin 0 -xmin 0.5 -xmax [expr {$count + 0.5}]
395  $w.c itemconfigure title -text $::tr(GraphFilterTitle)
396  $w.c itemconfigure type -text $typeName
397  $w.b.status configure -text " $::tr(Filter): [::windows::gamelist::filterText]"
398  unbusyCursor .
399  update
400 }
401 
402 #Invert white/black Score in Score graph, switches for display move time and adding time
403 set ::tools::graphs::score::White 0
404 set ::tools::graphs::score::Black 0
405 set ::tools::graphs::score::ThinkTime 0
406 set ::tools::graphs::score::Both 1
407 set ::tools::graphs::score::TimeSum 1
408 
409 ###########################
410 # Game score and time graph
411 
412 # MoveTimeList
413 # Returns a Tcl list of the numeric times of each move, as found
414 # in the commment for each move.
415 # A time is a number with the format
416 # "%clk 00:00:00" or
417 # "%clkms 12345" (used by BabaChess) or
418 # "%emt 00:00:00" (used by pychess)
419 # "%emt 1.23" (used by Raptor)
420 # found somewhere in the comment of the move.
421 proc MoveTimeList {color add} {
422  set movetimes { }
423  set mainline { }
424  set base [sc_base current]
425  set gnum [sc_game number]
426  set game [sc_base getGame $base $gnum live]
427  set n [llength $game]
428  set movenr 0
429  for {set i 0} { $i < $n} { incr i} {
430  set RAVd [lindex [lindex $game $i] 0]
431  set RAVn [lindex [lindex $game $i] 1]
432  # only search in the mainline
433  if { $RAVd == 0 && $RAVn == 0} {
434  # append comments for white
435  if { $color == "w" && [expr $movenr % 2] == 1 } {
436  lappend mainline [lindex [lindex $game $i] 4]}
437  # append comments for black
438  if { $color == "b" && [expr $movenr % 2] == 0 } {
439  lappend mainline [lindex [lindex $game $i] 4]}
440  incr movenr
441  }
442  }
443  set movenr 0
444  set offset 0.0
445  if { $color == "w" } { set offset 0.5}
446  set sum 0.0
447  for {set i 0} { $i < $n} { incr i} {
448  # only look for the first match, because normaly only one of these types should used in game
449  set comment [lindex $mainline $i]
450  set clkmsExp {.*?\[%clkms\s*(.*?)\s*\].*}
451  set clkms ""
452  regexp $clkmsExp $comment -> clkms
453  if { $clkms != "" } {
454  scan $clkms "%f" sec
455  if { [scan $clkms "%f" sec] == 1 } {
456  # scale millisec to minutes
457  lappend movetimes [expr $movenr+$offset] [expr { $sec / 60000.0 }]}
458  } else {
459  set clkExp {.*?\[%clk\s*(.*?)\s*\].*}
460  set clock ""
461  regexp $clkExp $comment -> clock
462  if { $clock != "" } {
463  if { [scan $clock "%f:%f:%f" ho mi sec] == 3 } {
464  lappend movetimes [expr $movenr+$offset] [expr { $ho*60.0 + $mi + $sec/60}]}
465  } else {
466  set emtExp {.*?\[%emt\s*(.*?)\s*\].*}
467  set emt ""
468  regexp $emtExp $comment -> emt
469  if { $emt != "" } {
470  # emt could have 2 formats: 00:12:34 or 1.23
471  set ok 0
472  if { [regexp ":" $emt] } {
473  if { [scan $emt "%f:%f:%f" ho mi sec] == 3 } { incr ok}
474  } else {
475  set ho 0.0
476  set mi 0.0
477  if { [scan $emt "%f" sec] == 1 } { incr ok}
478  }
479  if { $ok == 1 } {
480  set f [expr { $ho*3600.0 + $mi*60 + $sec}]
481  if { $add == 1 } {
482  # add move times and scale to minutes
483  set f [expr { $f/60.0 + $sum }]
484  set sum $f
485  }
486  lappend movetimes [expr $movenr+$offset] $f
487  }
488  }
489  }
490  }
491  incr movenr
492  }
493  return $movetimes
494 }
495 
496 # MoveScoreList
497 # Returns a Tcl list of the numeric move scores, as found
498 # in the commment for each move.
499 # A score is a number with the format
500 # "+0.23" or
501 # "-2.3" or
502 # ":M4", ":M-4", "+M4", "-M4" for announce Mate
503 # found somewhere in the comment of the move.
504 # The list returned should be read in pairs of values: the first is the
505 # move (0.0 = start, 0.5 after White's first move, 1.0 after Black's
506 # first move, etc) and the second is the value found.
507 proc MoveScoreList { invw invb } {
508  set moveScores { }
509  set mainline { }
510  set base [sc_base current]
511  set gnum [sc_game number]
512  set game [sc_base getGame $base $gnum live]
513  set n [llength $game]
514  set movenr 0
515  for {set i 0} { $i < $n} { incr i} {
516  set RAVd [lindex [lindex $game $i] 0]
517  set RAVn [lindex [lindex $game $i] 1]
518  # only search in the mainline
519  if { $RAVd == 0 && $RAVn == 0} {
520  lappend mainline [lindex [lindex $game $i] 4]
521  }
522  }
523  set movenr 0.0
524  set side 0
525  for {set i 1} { $i < $n} { incr i} {
526  set comment [lindex $mainline $i]
527  set evalExp {.*?\[%eval\s*(.*?)\s*\].*}
528  set eval ""
529  #little trick to check for valid score
530  set score -20.0
531  regexp $evalExp $comment -> eval
532  if { $eval != "" } { # check for [%eval 1.23]
533  scan $eval "%f" score
534  if { [scan $eval "%f" score] == 1 } {
535  if { $score > 10 } { set score 9.9}
536  if { $score < -10 } { set score -9.9}
537  } else {
538  # Mate found in %eval #N oder #-N
539  if { [string first "#" $eval] != -1 } {
540  set score 9.9
541  if { [string first "-" $eval] > 0 } { set score -9.9}
542  }
543  }
544  }
545  set foundIndex [string first ":M" $comment]
546  # check for Mate :M5 or :M-3
547  if { $foundIndex >= 0 } {
548  if { [scan [string range $comment [expr $foundIndex+2] end] "%f" score] == 1 } {
549  # change Mate in x to +/-9.9
550  if { $score >= 1 } { set score 9.9}
551  if { $score <= -1 } { set score -9.9}
552  }
553  } else {
554  set f 1
555  set foundIndex [string first "+M" $comment]
556  if { $foundIndex < 0 } { set foundIndex [string first "-M" $comment]; set f -1}
557  # check for Mate +M5 or -M3 (Annotation from Arena GUI)
558  if { $foundIndex >= 0 } {
559  if { [scan [string range $comment [expr $foundIndex+2] end] "%f" score] == 1 } {
560  # change Mate in x to +/-9.9
561  set score [expr $f * $score]
562  if { $score >= 1 } { set score 9.9}
563  if { $score <= -1 } { set score -9.9}
564  }
565  } else {
566  # check for scores +1.23 or -1.23, find the first apperance in the comment
567  set foundIndex [string first "+" $comment]
568  if { $foundIndex < 0 } { set foundIndex [string first "-" $comment]}
569  if { $foundIndex >= 0 } {
570  if { [scan [string range $comment $foundIndex end] "%f" score] == 1 } {
571  if { $score > 10 } { set score 9.9}
572  if { $score < -10 } { set score -9.9}
573  }
574  }
575  }
576  }
577  if { $score != -20.0 } {
578  # we have found something valid, check if the score should be inverted
579  if { $invw == 1 && $side == 1 } { set score [expr 0.0 - $score]}
580  if { $invb == 1 && $side == 0 } { set score [expr 0.0 - $score]}
581  lappend moveScores $movenr $score
582  }
583  set movenr [expr $movenr + 0.5]
584  if { $side == 0 } { set side 1} else { set side 0}
585  }
586  return $moveScores
587 }
588 
589 proc ::tools::graphs::score::Refresh { {docreate 1 }} {
590  set linecolor red
591  set firstColor darkgreen
592  set secondColor blue
593  set linewidth 2
594  set psize 2
595 
596  set w .sgraph
597  # Game has changed, but window is not open: do nothing
598  if {! [winfo exists $w] && $docreate == 0 } { return}
599 
600  if {! [winfo exists $w] } {
602  menu $w.menu
603  ::setMenu $w $w.menu
604  $w.menu add cascade -label GraphFile -menu $w.menu.file
605  menu $w.menu.file
606  $w.menu.file add command -label GraphFileColor \
607  -command "::tools::graphs::Save color $w.c"
608  $w.menu.file add command -label GraphFileGrey \
609  -command "::tools::graphs::Save gray $w.c"
610  $w.menu.file add separator
611  $w.menu.file add command -label GraphFileClose -command "destroy $w"
612  $w.menu add cascade -label GraphOptions -menu $w.menu.options
613  $w.menu add command -label Help -accelerator F1 -command {helpWindow Graphs Score}
614  #Checkbuttons for Invert white/black Score in Score graph
615  menu $w.menu.options
616  foreach i {White Black Both ThinkTime TimeSum } {
617  $w.menu.options add checkbutton -label GraphOptions$i \
618  -variable ::tools::graphs::score::$i -offvalue "0" -onvalue "1" \
619  -command "::tools::graphs::score::Refresh"
620  }
621  canvas $w.c -width 500 -height 300 -selectforeground [ttk::style lookup . -foreground] -background [ttk::style lookup . -background]
622 
623  $w.c create text 25 5 -tag text -justify center -width 1 \
624  -font font_Regular -anchor n
625  pack $w.c -side top -expand yes -fill both
626  bind $w <F1> {helpWindow Graphs Score}
627  bind $w <Configure> {
628  .sgraph.c itemconfigure text -width [expr {[winfo width .sgraph.c] - 20}]
629  .sgraph.c coords text [expr {[winfo width .sgraph.c] / 2}] 10
630  ::utils::graph::configure score -height [expr {[winfo height .sgraph.c] - 50}]
631  ::utils::graph::configure score -width [expr {[winfo width .sgraph.c] - 40}]
632  ::utils::graph::redraw score
633  }
634  bind $w.c <1> {::tools::graphs::score::Move %x}
635  wm title $w "Scid: [tr ToolsScore]"
638  }
639  ::setTitle $w "Scid: [tr ToolsScore]"
640 
641  $w.c itemconfigure text -width [expr {[winfo width $w.c] - 20}]
642  $w.c coords text [expr {[winfo width $w.c] / 2}] 10
643  set height [expr {[winfo height $w.c] - 50}]
644  set width [expr {[winfo width $w.c] - 40}]
645  set yticks 1
646  if { $::tools::graphs::score::Both == 1 || $::tools::graphs::score::ThinkTime == 1} {
647  ::setTitle $w "Scid: [tr ToolsScore] & [tr Time]"
648  set max 0
649  # Find max Value of time, then set the tick value vor horizontal lines
650  foreach j { "w" "b"} {
651  set coords [MoveTimeList $j $::tools::graphs::score::TimeSum]
652  set coords$j $coords
653  set ncoords [expr {[llength $coords] - 1}]
654  for {set i 0} {$i < $ncoords} {incr i 2} {
655  set y [lindex $coords [expr {$i + 1}]]
656  if { $y > $max } { set max $y}
657  }
658  }
659  if {$max > 20} { set yticks 5}
660  if {$max > 50} { set yticks 10}
661  if {$max > 100} { set yticks 20}
662  }
663  if { $::tools::graphs::score::ThinkTime == 1 && $::tools::graphs::score::Both == 0 } {
664  ::setTitle $w "Scid: [tr Time]"}
665 
666  ::utils::graph::create score -width $width -height $height -xtop 25 -ytop 25 \
667  -ytick $yticks -xtick 5 -font font_Small -canvas $w.c -textcolor black \
668  -hline [list [list gray80 1 each $yticks]] \
669  -vline {{gray80 1 each 1} {steelBlue 1 each 5}}
670 
671  # Create fake dataset with bounds so we see at least -1.0 to 1.0:
672  ::utils::graph::data score bounds -points 0 -lines 0 -bars 0 -coords {1 0 1 0.9}
673 
674  # Update the graph:
675  set whiteelo [sc_game tag get WhiteElo]
676  set blackelo [sc_game tag get BlackElo]
677  if {$whiteelo == 0} {set whiteelo ""} else {set whiteelo "($whiteelo)"}
678  if {$blackelo == 0} {set blackelo ""} else {set blackelo "($blackelo)"}
679  $w.c itemconfigure text -text "[sc_game info white]$whiteelo - [sc_game info black]$blackelo [sc_game info site] [sc_game info date]"
680  busyCursor $w
681  update
682 
683  if { $::tools::graphs::score::Both || $::tools::graphs::score::ThinkTime } {
684  # draw move time
685  catch {::utils::graph::data score data1 -color $firstColor -points 0 -lines 1\
686  -key [sc_game info white] -linewidth $linewidth -radius $psize -outline $firstColor -coords $coordsw}
687  catch {::utils::graph::data score data2 -color $secondColor -points 0 -lines 1 \
688  -linewidth $linewidth -radius $psize -outline $secondColor -coords $coordsb}
689  }
690  if { $::tools::graphs::score::Both || $::tools::graphs::score::ThinkTime == 0 } {
691  # draw score bars
692  catch {::utils::graph::data score data -color $linecolor -points 0 -lines 0 -bars 2 \
693  -linewidth $linewidth -radius $psize -outline $linecolor \
694  -coords [MoveScoreList $::tools::graphs::score::White $::tools::graphs::score::Black]}
695  }
696 
698  unbusyCursor $w
699  update
700 }
701 
702 proc ::tools::graphs::score::ConfigMenus {{lang ""}} {
703  if {! [winfo exists .sgraph]} { return}
704  if {$lang == ""} { set lang $::language}
705  set m .sgraph.menu
706  foreach idx {0 1} tag {File Options} {
707  configMenuText $m $idx Graph$tag $lang
708  }
709  foreach idx {0 1 3} tag {Color Grey Close} {
710  configMenuText $m.file $idx GraphFile$tag $lang
711  }
712  foreach idx {0 1 2} tag {White Black Both} {
713  configMenuText $m.options $idx GraphOptions$tag $lang
714  }
715  #add option to show used Time and toggle between "Sum of time" (in min) and "Time per move" (in sec)
716  $m entryconfig 2 -label $::tr(Help)
717  $m.options entryconfig 3 -label $::tr(Time)
718  $m.options entryconfig 4 -label $::tr(Total)
719 
720 }
721 
722 proc ::tools::graphs::score::Move {xc} {
723  set x [expr {round([::utils::graph::xunmap score $xc] * 2 + 0.5)}]
724  sc_move start
725  sc_move forward $x
727 }
728 
729 
730 ####################
731 # Rating graph
732 
733 set ::tools::graphs::rating::year 1900
734 set ::tools::graphs::rating::type both
735 set ::tools::graphs::rating::elo info
736 set ::tools::graphs::rating::player ""
737 
738 proc ::tools::graphs::rating::GetElo { player } {
739  if {$::tools::graphs::rating::elo == "elo"} {
740  set eloList [sc_name elo $::tools::graphs::rating::year $player]
741  } else {
742  set filter [sc_filter new $::curr_db]
743  sc_filter search $::curr_db $filter header -date "$::tools::graphs::rating::year 2047"
744  set eloList [sc_base player_elo $::curr_db $filter $player]
745  sc_filter release $::curr_db $filter
746  }
747  return $eloList
748 }
749 
750 proc ::tools::graphs::rating::Refresh {{type ""} {player ""}} {
751  set white [sc_game info white]
752  set black [sc_game info black]
753  set whiteColor red
754  set blackColor blue
755  set lwidth 2
756  set psize 2
757 
758  if {$type == ""} { set type $::tools::graphs::rating::type}
759  if {$player == ""} { set player $::tools::graphs::rating::player}
760  set ::tools::graphs::rating::type $type
761  set ::tools::graphs::rating::player $player
762 
763  set w .rgraph
764 
765  if {! [winfo exists $w]} {
766  toplevel $w
767  menu $w.menu
768  ::setMenu $w $w.menu
769  $w.menu add cascade -label GraphFile -menu $w.menu.file
770  menu $w.menu.file
771  $w.menu.file add command -label GraphFileColor \
772  -command "::tools::graphs::Save color $w.c"
773  $w.menu.file add command -label GraphFileGrey \
774  -command "::tools::graphs::Save gray $w.c"
775  $w.menu.file add separator
776  $w.menu.file add command -label GraphFileClose -command "destroy $w"
777  $w.menu add cascade -label GraphOptions -menu $w.menu.options
778  menu $w.menu.options
779  foreach i {White Black Both PInfo} j {white black both player} {
780  $w.menu.options add radiobutton -label GraphOptions$i \
781  -variable ::tools::graphs::rating::type -value $j \
782  -command "::tools::graphs::rating::Refresh"
783  }
784  $w.menu.options add separator
785  foreach i { EloDB EloFile } j {info elo} {
786  $w.menu.options add radiobutton -label GraphOptions$i \
787  -variable ::tools::graphs::rating::elo -value $j \
788  -command "::tools::graphs::rating::Refresh"
789  }
790  $w.menu.options add separator
791  foreach i {1900 1980 1985 1990 1995 2000 2005 2010 2015 } {
792  $w.menu.options add radiobutton -label "Since $i" \
793  -variable ::tools::graphs::rating::year -value $i \
794  -command "::tools::graphs::rating::Refresh"
795  }
796 
797  canvas $w.c -width 500 -height 300 -selectforeground [ttk::style lookup . -foreground] -background [ttk::style lookup . -background]
798  $w.c create text 25 10 -tag text -justify center -width 1 \
799  -font font_Regular -anchor n
800  pack $w.c -side top -expand yes -fill both
801  bind $w <F1> {helpWindow Graphs Rating}
802  bind $w <Configure> {
803  .rgraph.c itemconfigure text -width [expr {[winfo width .rgraph.c] - 50} ]
804  .rgraph.c coords text [expr {[winfo width .rgraph.c] / 2} ] 10
805  ::utils::graph::configure ratings -height [expr {[winfo height .rgraph.c] - 70} ]
806  ::utils::graph::configure ratings -width [expr {[winfo width .rgraph.c] - 100} ]
807  ::utils::graph::configure ratings -logy 10
808  ::utils::graph::redraw ratings
809  }
810  bind $w.c <Button-1> "::tools::graphs::rating::Refresh"
811  bind $w.c <Button-$::MB3> "::tools::graphs::rating::Refresh"
812  wm title $w "Scid: [tr ToolsRating]"
814  }
815 
816  $w.c itemconfigure text -width [expr {[winfo width $w.c] - 50}]
817  $w.c coords text [expr {[winfo width $w.c] / 2}] 10
818  set height [expr {[winfo height $w.c] - 70}]
819  set width [expr {[winfo width $w.c] - 100}]
820  ::utils::graph::create ratings -width $width -height $height -xtop 50 -ytop 35 \
821  -ytick 50 -xtick 1 -font font_Small -canvas $w.c -textcolor black \
822  -hline {{gray80 1 each 25} {steelBlue 1 each 100}} \
823  -vline {{gray80 1 each 1} {steelBlue 1 each 5}}
824  ::utils::graph::redraw ratings
825  busyCursor $w
826  update
827 
828  set title "[tr ToolsRating]: "
829  if {$type == "player"} {
830  append title $player
831  catch {::utils::graph::data ratings d -color $whiteColor -points 1 -lines 1 \
832  -linewidth $lwidth -radius $psize -outline $whiteColor \
833  -coords [GetElo $player]}
834  }
835  if {$type == "white" || $type == "both"} {
836  set key ""
837  if {$type == "both"} { set key [::utils::string::Surname $white]}
838  append title $white
839  catch {::utils::graph::data ratings d -color $whiteColor -points 1 -lines 1 \
840  -linewidth $lwidth -radius $psize -outline $whiteColor \
841  -key $key -coords [GetElo $white]}
842  }
843  if {$type == "both"} { append title " - "}
844  if {$type == "black" || $type == "both"} {
845  set key ""
846  if {$type == "both"} { set key [::utils::string::Surname $black]}
847  append title $black
848  catch {::utils::graph::data ratings d2 -color $blackColor -points 1 -lines 1 \
849  -linewidth $lwidth -radius $psize -outline $blackColor \
850  -key $key -coords [GetElo $black]}
851  }
852  set minYear [expr {int([::utils::graph::cget ratings axmin])}]
853  set maxYear [expr {int([::utils::graph::cget ratings axmax])}]
854  ::utils::graph::configure ratings -xtick 1
855  if {[expr {$maxYear - $minYear}] > 10} {::utils::graph::configure ratings -xtick 5}
856  ::utils::graph::redraw ratings
857  $w.c itemconfigure text -text $title
858  unbusyCursor $w
859 }
860 
861 proc ::tools::graphs::rating::ConfigMenus {{lang ""}} {
862  if {! [winfo exists .rgraph]} { return}
863  if {$lang == ""} { set lang $::language}
864  set m .rgraph.menu
865  foreach idx {0 1} tag {File Options} {
866  configMenuText $m $idx Graph$tag $lang
867  }
868  foreach idx {0 1 3} tag {Color Grey Close} {
869  configMenuText $m.file $idx GraphFile$tag $lang
870  }
871  foreach idx {0 1 2 3 5 6} tag {White Black Both PInfo EloDB EloFile} {
872  configMenuText $m.options $idx GraphOptions$tag $lang
873  }
874 }
875 
876 
877 ########################################
878 # Filter graph window for absolut values
879 
880 # ::tools::graphs::absfilter::type
881 # can be "decade", "year" or "elo", "move"
882 #
883 set ::tools::graphs::absfilter::type year
884 
885 proc tools::graphs::absfilter::Open {} {
886  global absfilterGraph
887  set w .afgraph
888  if {[winfo exists $w]} {
889  focus .
890  destroy $w
891  set absfilterGraph 0
892  return
893  }
894  win::createDialog $w 0
895  menu $w.menu
896  ::setMenu $w $w.menu
897  $w.menu add cascade -label GraphFile -menu $w.menu.file
898  configMenuText $w.menu 0 GraphFile $::language
899  menu $w.menu.file
900  $w.menu.file add command -label GraphFileColor -command "::tools::graphs::Save color $w.c"
901  configMenuText $w.menu.file 0 GraphFileColor $::language
902  $w.menu.file add command -label GraphFileGrey -command "::tools::graphs::Save gray $w.c"
903  configMenuText $w.menu.file 1 GraphFileGrey $::language
904  $w.menu.file add separator
905  $w.menu.file add command -label GraphFileClose -command "destroy $w"
906  configMenuText $w.menu.file 3 GraphFileClose $::language
907  wm title $w $::tr(TitleFilterGraph)
908  set absfilterGraph 1
909  bind $w <Destroy> {set absfilterGraph 0}
910 
911  ttk::frame $w.b
912  pack $w.b -side top -fill x
913  ttk::label $w.b.status -width 1 -font font_Small -anchor w
914 
915  canvas $w.c -width 600 -height 400 -selectforeground [ttk::style lookup . -foreground] -background [ttk::style lookup . -background]
916  $w.c create text 25 5 -tag title -justify center -width 1 \
917  -font font_Small -anchor n
918  $w.c create text 250 295 -tag type -justify center -width 1 \
919  -font font_Small -anchor s
920  pack $w.c -side top -expand yes -fill both
921  ::utils::graph::create absfilter
922 
923  bind $w <F1> {helpWindow Graphs Filter}
924  bind $w <Configure> {
925  .afgraph.c itemconfigure title -width [expr {[winfo width .afgraph.c] - 50}]
926  .afgraph.c coords title [expr {[winfo width .afgraph.c] / 2}] 10
927  .afgraph.c itemconfigure type -width [expr {[winfo width .afgraph.c] - 50}]
928  .afgraph.c coords type [expr {[winfo width .afgraph.c] / 2}] \
929  [expr {[winfo height .afgraph.c] - 10}]
930  ::utils::graph::configure absfilter -height [expr {[winfo height .afgraph.c] - 80}]
931  ::utils::graph::configure absfilter -width [expr {[winfo width .afgraph.c] - 60}]
932  ::utils::graph::redraw absfilter
933  }
934  bind $w.c <1> tools::graphs::absfilter::Switch
935  bind $w.c <$::MB3> ::tools::graphs::absfilter::Refresh
936  foreach {name text} {decade Decade year Year elo Rating move moves} {
937  ttk::radiobutton $w.b.$name -text $::tr($text) \
938  -variable ::tools::graphs::absfilter::type -value $name \
939  -command ::tools::graphs::absfilter::Refresh
940  pack $w.b.$name -side left -padx 1 -pady 2
941  }
942  ttk::button $w.b.setup -image tb_config -command configureFilterGraph
943  pack $w.b.decade $w.b.elo -side left -padx 1 -pady 2
944  pack $w.b.setup -side right -pady 2
945  pack $w.b.status -side left -padx 2 -pady 2 -fill x -expand yes
946 
948 }
949 
950 proc tools::graphs::absfilter::Switch {} {
951  variable type
952  switch $type {
953  "decade" { set type "year"}
954  "year" { set type "elo"}
955  "elo" { set type "move"}
956  "move" { set type "decade"}
957  }
959 }
960 
961 proc ::tools::graphs::absfilter::Refresh {} {
962  global FilterMaxMoves FilterMinMoves FilterStepMoves FilterMaxElo FilterMinElo FilterStepElo FilterMaxYear FilterMinYear FilterStepYear FilterGuessELO
963 
964  set w .afgraph
965  if {! [winfo exists $w]} { return}
966 
967  $w.c itemconfigure title -width [expr {[winfo width $w.c] - 50}]
968  $w.c coords title [expr {[winfo width $w.c] / 2}] 10
969  $w.c itemconfigure type -width [expr {[winfo width $w.c] - 50}]
970  $w.c coords type [expr {[winfo width $w.c] / 2}] \
971  [expr {[winfo height $w.c] - 10}]
972  set height [expr {[winfo height $w.c] - 80}]
973  set width [expr {[winfo width $w.c] - 60}]
974  set vlines {}
975  if {$::tools::graphs::absfilter::type == "elo"} {
976  # Vertical lines for Elo-range graph:
977  for {set i 1} {$i <= $FilterMaxElo- $FilterMinElo} { incr i} {
978  lappend vlines [list gray80 1 at $i.5]
979  }
980  } elseif {$::tools::graphs::absfilter::type == "year"} {
981  # Vertical lines for Year-range graph:
982  for {set i 1} {$i <= $FilterMaxYear- $FilterMinYear} {incr i} {
983  lappend vlines [list gray80 1 at $i.5]
984  }
985  } elseif {$::tools::graphs::absfilter::type == "decade"} {
986  # Vertical lines for Decade graph: most are gray, but those
987  # just before 1950s and 2000s are blue to make them stand out.
988  for {set i 1} {$i < 10} {incr i} {
989  set vlineColor gray80
990  if {$i == 4 || $i == 9} { set vlineColor steelBlue}
991  lappend vlines [list $vlineColor 1 at $i.5]
992  }
993  }
994 
995  ::utils::graph::create absfilter -width $width -height $height -xtop 40 -ytop 35 \
996  -ytick 1 -xtick 1 -font font_Small -canvas $w.c -textcolor black \
997  -vline $vlines -background lightYellow -tickcolor black -xmin 0 -xmax 1
998  ::utils::graph::redraw absfilter
999  busyCursor .
1000  update
1001 
1002  set count 0
1003  set dlist {}
1004  set xlabels {}
1005  set max 0.0
1006 
1007  # Generate plot values and labels:
1008  if {$::tools::graphs::absfilter::type == "decade"} {
1009  set ftype date
1010  set typeName $::tr(Decade)
1011  set rlist [list 0000 1919 -1919 1920 1929 20-29 \
1012  1930 1939 30-39 1940 1949 40-49 1950 1959 50-59 \
1013  1960 1969 60-69 1970 1979 70-79 1980 1989 80-89 \
1014  1990 1999 90-99 2000 2009 2000+]
1015  } elseif {$::tools::graphs::absfilter::type == "year"} {
1016  set ftype date
1017  set typeName $::tr(Year)
1018  set endYear $FilterMaxYear
1019  set startYear $FilterMinYear
1020  set rlist {}
1021  for {set i $startYear} {$i <= $endYear} {set i [expr {$i + $FilterStepYear}]} {
1022  lappend rlist $i
1023  lappend rlist [expr {$i+$FilterStepYear-1}]
1024  lappend rlist [expr {$i+$FilterStepYear/2}]
1025  }
1026  } elseif {$::tools::graphs::absfilter::type == "elo"} {
1027  set ftype elo
1028  set typeName $::tr(Rating)
1029  # set rlist [list 0 1999 0-1999 2000 2099 20xx 2100 2199 21xx \
1030  2200 2299 22xx 2300 2399 23xx 2400 2499 24xx \
1031  2500 2599 25xx 2600 2699 26xx 2700 3999 2700+]
1032  set endElo $FilterMaxElo
1033  set startElo $FilterMinElo
1034  set rlist {}
1035  for {set i $startElo} {$i <= $endElo} {set i [expr {$i + $FilterStepElo}]} {
1036  lappend rlist $i
1037  lappend rlist [expr {$i+$FilterStepElo-1}]
1038  # shorten gap between 0 and "useful" ratings 1800
1039  set j $i
1040  if { $i < 100 } { set i [expr { 1800 - $FilterStepElo}]}
1041  lappend rlist [concat $j-[expr {$i+$FilterStepElo-1}]]
1042  }
1043  } else {
1044  set ftype move
1045  set typeName $::tr(moves)
1046  set startMove $FilterMinMoves
1047  set endMove $FilterMaxMoves
1048  set rlist {}
1049  for {set i $startMove} {$i <= $endMove} {set i [expr {$i + $FilterStepMoves}]} {
1050  lappend rlist [expr {2*$i}]
1051  lappend rlist [expr {2*($i+$FilterStepMoves)-1}]
1052  if { $i % 5 == 0 } {
1053  lappend rlist $i
1054  } else {
1055  lappend rlist ""
1056  }
1057  }
1058  }
1059 
1060  set mean 0
1061  foreach {start end label} $rlist {
1062  if {$ftype == "date"} { append end ".12.31"}
1063  set r [sc_filter freq [sc_base current] dbfilter $ftype $start $end $FilterGuessELO]
1064  set absfilter [lindex $r 0]
1065  set all [lindex $r 1]
1066  set freq $absfilter
1067  incr count
1068  set mean [expr { $mean + $absfilter }]
1069  lappend dlist $count
1070  lappend dlist $freq
1071  if {$freq > $max} { set max $freq}
1072  lappend xlabels [list $count $label]
1073  }
1074 
1075  # Find a suitable spacing of y-axis labels:
1076  set ytick 1
1077  if {$max >= 10} { set ytick 1}
1078  if {$max >= 25} { set ytick 5}
1079  # if {$max >= 50} { set ytick 5 }
1080  if {$max >= 100} { set ytick 10}
1081  if {$max >= 250} { set ytick 25}
1082  if {$max >= 500} { set ytick 50}
1083  if {$max >= 1000} { set ytick 100}
1084  if {$max >= 2500} { set ytick 250}
1085  if {$max >= 5000} { set ytick 500}
1086  if {$max >= 10000} { set ytick 1000}
1087  if {$max >= 25000} { set ytick 2500}
1088  if {$max >= 50000} { set ytick 5000}
1089  if {$max >= 100000} { set ytick 10000}
1090  if {$max >= 250000} { set ytick 25000}
1091  if {$max >= 500000} { set ytick 50000}
1092  if {$max >= 1000000} { set ytick 100000}
1093  set hlines [list [list gray80 1 each $ytick]]
1094  # Add mean horizontal line:
1095  set absfilter [sc_filter count]
1096  set all [sc_base numGames $::curr_db]
1097  if { $count != 0 } {set mean [expr { $mean / $count }]}
1098  if {$all > 0} {
1099  if {$mean > $max} { set max $mean}
1100  lappend hlines [list red 1 at $mean]
1101  }
1102 
1103  # Create fake dataset with bounds so we see 0.0::
1104  #::utils::graph::data decade bounds -points 0 -lines 0 -bars 0 -coords {1 0.0 1 0.0}
1105 
1106  ::utils::graph::data absfilter data -color darkBlue -points 1 -lines 1 -bars 0 \
1107  -linewidth 2 -radius 4 -outline darkBlue -coords $dlist
1108  ::utils::graph::configure absfilter -xlabels $xlabels -ytick $ytick \
1109  -hline $hlines -ymin 0 -xmin 0.5 -xmax [expr {$count + 0.5}]
1110  ::utils::graph::redraw absfilter
1111  $w.c itemconfigure title -text $::tr(GraphAbsFilterTitle)
1112  $w.c itemconfigure type -text $typeName
1113  $w.b.status configure -text " $::tr(Filter): [::windows::gamelist::filterText]"
1114  unbusyCursor .
1115  update
1116 }
1117 ### End of file: graphs.tcl