Scid  4.6.5
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 
63  toplevel $w
64  wm title $w $::tr(ConfigureFilter)
66  bind $w <F1> {helpWindow Graphs Filter}
67  frame $w.filter
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  label $w.filter.label$i -text $::tr($n): -font font_Bold
73  grid $w.filter.label$i -row $row -column $col -sticky w
74  incr col
75  foreach {j k} { FilterMin " " FilterMax " - " FilterStep " Interval:"} {
76  label $w.filter.label$j$i -text $k
77  entry $w.filter.i$j$i -textvariable $j$i -justify right -width 5 -validate all -vcmd { regexp {^[0-9]{0,4}$} %P }
78  grid $w.filter.label$j$i -row $row -column $col -sticky w
79  incr col
80  grid $w.filter.i$j$i -row $row -column $col -sticky w
81  incr col
82  }
83  if { $i == "Elo" } {
84  checkbutton $w.filter.iEloGuess -text $::tr(FilterEstimate) -onvalue 1 -offvalue 0 -variable FilterGuessELO
85  grid $w.filter.iEloGuess -row $row -column $col -sticky w
86  # incr col
87  }
88  incr row
89  set col 0
90  }
91 
92  button $w.close -textvar ::tr(Close) -command {
93  checkConfigFilterGraph; ::tools::graphs::filter::Refresh
94  ::tools::graphs::absfilter::Refresh; destroy .configFilterGraph }
95  button $w.standard -textvar ::tr(Defaults) -command {
96  set FilterMinElo 2100
97  set FilterMaxElo 2800
98  set FilterStepElo 100
99  set FilterMaxYear [clock format [clock seconds] -format {%Y}]
100  set FilterMinYear [expr {$FilterMaxYear - 12}]
101  set FilterStepYear 1
102  set FilterMinMoves 5
103  set FilterMaxMoves 80
104  set FilterStepMoves 1
105  set FilterGuessELO 1
106  }
107  button $w.update -textvar ::tr(Update) -command { checkConfigFilterGraph
108  ::tools::graphs::absfilter::Refresh;
109  ::tools::graphs::filter::Refresh
110  }
111 
112  pack $w.filter
113  pack $w.close $w.update $w.standard -side right -padx 2 -pady 2
114  focus $w.filter.iFilterMinYear
115  bind $w <Configure> "recordWinSize $w"
116 }
117 
118 #####################
119 # Filter graph window
120 
121 # ::tools::graphs::filter::type
122 # can be "decade", "year" or "elo" , "move"
123 #
124 set ::tools::graphs::filter::type year
125 
126 proc tools::graphs::filter::Open {} {
127  global filterGraph
128  set w .fgraph
129  if {[winfo exists $w]} {
130  focus .
131  destroy $w
132  set filterGraph 0
133  return
134  }
135  toplevel $w
136  menu $w.menu
137  $w configure -menu $w.menu
138  $w.menu add cascade -label GraphFile -menu $w.menu.file
139  configMenuText $w.menu 0 GraphFile $::language
140  menu $w.menu.file
141  $w.menu.file add command -label GraphFileColor -command "::tools::graphs::Save color $w.c"
142  configMenuText $w.menu.file 0 GraphFileColor $::language
143  $w.menu.file add command -label GraphFileGrey -command "::tools::graphs::Save gray $w.c"
144  configMenuText $w.menu.file 1 GraphFileGrey $::language
145  $w.menu.file add separator
146  $w.menu.file add command -label GraphFileClose -command "destroy $w"
147  configMenuText $w.menu.file 3 GraphFileClose $::language
148  wm title $w $::tr(TitleFilterGraph)
149  set filterGraph 1
150  bind $w <Destroy> {set filterGraph 0}
151 
152  frame $w.b
153  pack $w.b -side bottom -fill x
154  label $w.b.status -width 1 -font font_Small -anchor w
155  frame $w.sep -height 2 -borderwidth 2 -relief sunken -background white
156  pack $w.sep -side bottom -fill x -pady 4
157 
158  canvas $w.c -width 600 -height 400
159  $w.c create text 25 5 -tag title -justify center -width 1 \
160  -font font_Small -anchor n
161  $w.c create text 250 295 -tag type -justify center -width 1 \
162  -font font_Small -anchor s
163  pack $w.c -side top -expand yes -fill both
165 
166  bind $w <F1> {helpWindow Graphs Filter}
167  bind $w <Configure> {
168  .fgraph.c itemconfigure title -width [expr {[winfo width .fgraph.c] - 50}]
169  .fgraph.c coords title [expr {[winfo width .fgraph.c] / 2}] 10
170  .fgraph.c itemconfigure type -width [expr {[winfo width .fgraph.c] - 50}]
171  .fgraph.c coords type [expr {[winfo width .fgraph.c] / 2}] \
172  [expr {[winfo height .fgraph.c] - 10}]
173  ::utils::graph::configure filter -height [expr {[winfo height .fgraph.c] - 80}]
174  ::utils::graph::configure filter -width [expr {[winfo width .fgraph.c] - 60}]
175  ::utils::graph::redraw filter
176  }
177  bind $w.c <1> tools::graphs::filter::Switch
178  bind $w.c <$::MB3> ::tools::graphs::filter::Refresh
179 
180  foreach {name text} {decade Decade year Year elo Rating move moves} {
181  radiobutton $w.b.$name -padx 4 -pady 3 -text $::tr($text) \
182  -variable ::tools::graphs::filter::type -value $name \
183  -command ::tools::graphs::filter::Refresh
184  pack $w.b.$name -side left -padx 1 -pady 2
185  }
186  button $w.b.setup -image tb_graph -command configureFilterGraph
187  dialogbutton $w.b.close -text $::tr(Close) -command "destroy $w"
188  pack $w.b.decade $w.b.elo -side left -padx 1 -pady 2
189  pack $w.b.close $w.b.setup -side right -padx 2 -pady 2
190  pack $w.b.status -side left -padx 2 -pady 2 -fill x -expand yes
191 
193 }
194 
195 proc tools::graphs::filter::Switch {} {
196  variable type
197  switch $type {
198  "decade" { set type "year"}
199  "year" { set type "elo"}
200  "elo" { set type "move"}
201  "move" { set type "decade"}
202  }
204 }
205 
206 proc ::tools::graphs::filter::Refresh {} {
207  global FilterMaxMoves FilterMinMoves FilterStepMoves FilterMaxElo FilterMinElo FilterStepElo FilterMaxYear FilterMinYear FilterStepYear FilterGuessELO
208 
209  set w .fgraph
210  if {! [winfo exists $w]} { return}
211 
212  $w.c itemconfigure title -width [expr {[winfo width $w.c] - 50}]
213  $w.c coords title [expr {[winfo width $w.c] / 2}] 10
214  $w.c itemconfigure type -width [expr {[winfo width $w.c] - 50}]
215  $w.c coords type [expr {[winfo width $w.c] / 2}] \
216  [expr {[winfo height $w.c] - 10}]
217  set height [expr {[winfo height $w.c] - 80}]
218  set width [expr {[winfo width $w.c] - 60}]
219  set vlines {}
220  if {$::tools::graphs::filter::type == "elo"} {
221  # Vertical lines for Elo-range graph:
222  for {set i 1} {$i <= $FilterMaxElo- $FilterMinElo} { incr i} {
223  lappend vlines [list gray80 1 at $i.5]
224  }
225  } elseif {$::tools::graphs::filter::type == "year"} {
226  # Vertical lines for Year-range graph:
227  for {set i 1} {$i <= $FilterMaxYear- $FilterMinYear} {incr i} {
228  lappend vlines [list gray80 1 at $i.5]
229  }
230  } elseif {$::tools::graphs::filter::type == "decade"} {
231  # Vertical lines for Decade graph: most are gray, but those
232  # just before 1950s and 2000s are blue to make them stand out.
233  for {set i 1} {$i < 10} {incr i} {
234  set vlineColor gray80
235  if {$i == 4 || $i == 9} { set vlineColor steelBlue}
236  lappend vlines [list $vlineColor 1 at $i.5]
237  }
238  }
239 
240  ::utils::graph::create filter -width $width -height $height -xtop 40 -ytop 35 \
241  -ytick 1 -xtick 1 -font font_Small -canvas $w.c -textcolor black \
242  -vline $vlines -background lightYellow -tickcolor black -xmin 0 -xmax 1
244  busyCursor .
245  update
246 
247  set count 0
248  set dlist {}
249  set xlabels {}
250  set max 0.0
251 
252  # Generate plot values and labels:
253  if {$::tools::graphs::filter::type == "decade"} {
254  set ftype date
255  set typeName $::tr(Decade)
256  set rlist [list 0000 1919 -1919 1920 1929 20-29 \
257  1930 1939 30-39 1940 1949 40-49 1950 1959 50-59 \
258  1960 1969 60-69 1970 1979 70-79 1980 1989 80-89 \
259  1990 1999 90-99 2000 2009 2000+]
260  } elseif {$::tools::graphs::filter::type == "year"} {
261  set ftype date
262  set typeName $::tr(Year)
263  set endYear $FilterMaxYear
264  set startYear $FilterMinYear
265  set rlist {}
266  for {set i $startYear} {$i <= $endYear} {set i [expr {$i + $FilterStepYear}]} {
267  lappend rlist $i
268  lappend rlist [expr {$i+$FilterStepYear-1}]
269  lappend rlist [expr {$i+$FilterStepYear/2}]
270  }
271  } elseif {$::tools::graphs::filter::type == "elo"} {
272  set ftype elo
273  set typeName $::tr(Rating)
274  # set rlist [list 0 1999 0-1999 2000 2099 20xx 2100 2199 21xx \
275  2200 2299 22xx 2300 2399 23xx 2400 2499 24xx \
276  2500 2599 25xx 2600 2699 26xx 2700 3999 2700+]
277  set endElo $FilterMaxElo
278  set startElo $FilterMinElo
279  set rlist {}
280  for {set i $startElo} {$i <= $endElo} {set i [expr {$i + $FilterStepElo}]} {
281  lappend rlist $i
282  lappend rlist [expr {$i+$FilterStepElo-1}]
283  # shorten gap between 0 and "useful" ratings 1800
284  set j $i
285  if { $i < 100 } { set i [expr { 1800 - $FilterStepElo}]}
286  lappend rlist [concat $j-[expr {$i+$FilterStepElo-1}]]
287  }
288  } else {
289  set ftype move
290  set typeName $::tr(moves)
291  set startMove $FilterMinMoves
292  set endMove $FilterMaxMoves
293  set rlist {}
294  for {set i $startMove} {$i <= $endMove} {set i [expr {$i + $FilterStepMoves}]} {
295  lappend rlist [expr {2*$i}]
296  lappend rlist [expr {2*($i+$FilterStepMoves)-1}]
297  if { $i % 5 == 0 } {
298  lappend rlist $i
299  } else {
300  lappend rlist ""
301  }
302  }
303  }
304 
305  foreach {start end label} $rlist {
306  if {$ftype == "date"} { append end ".12.31"}
307  set r [sc_filter freq [sc_base current] dbfilter $ftype $start $end $FilterGuessELO]
308  set filter [lindex $r 0]
309  set all [lindex $r 1]
310  if {$all == 0} {
311  set freq 0.0
312  } else {
313  set freq [expr {double($filter) * 1000.0 / double($all)}]
314  }
315  if {$freq >= 1000.0} { set freq 999.9}
316  incr count
317  lappend dlist $count
318  lappend dlist $freq
319  if {$freq > $max} { set max $freq}
320  lappend xlabels [list $count $label]
321  }
322 
323  # Find a suitable spacing of y-axis labels:
324  set ytick 0.1
325  if {$max > 1.0} { set ytick 0.2}
326  if {$max > 2.5} { set ytick 0.5}
327  if {$max > 5} { set ytick 1}
328  if {$max > 10} { set ytick 2}
329  if {$max > 25} { set ytick 5}
330  if {$max > 50} { set ytick 10}
331  if {$max > 100} { set ytick 20}
332  if {$max > 250} { set ytick 50}
333  if {$max > 500} { set ytick 100}
334  set hlines [list [list gray80 1 each $ytick]]
335  # Add mean horizontal line:
336  set filter [sc_filter count]
337  set all [sc_base numGames $::curr_db]
338  if {$all > 0} {
339  set mean [expr {double($filter) * 1000.0 / double($all)}]
340  if {$mean >= 1000.0} { set mean 999.9}
341  lappend hlines [list red 1 at $mean]
342  }
343 
344  # Create fake dataset with bounds so we see 0.0::
345  #::utils::graph::data decade bounds -points 0 -lines 0 -bars 0 -coords {1 0.0 1 0.0}
346 
347  ::utils::graph::data filter data -color darkBlue -points 1 -lines 1 -bars 0 \
348  -linewidth 2 -radius 4 -outline darkBlue -coords $dlist
349  ::utils::graph::configure filter -xlabels $xlabels -ytick $ytick \
350  -hline $hlines -ymin 0 -xmin 0.5 -xmax [expr {$count + 0.5}]
352  $w.c itemconfigure title -text $::tr(GraphFilterTitle)
353  $w.c itemconfigure type -text $typeName
354  $w.b.status configure -text " $::tr(Filter): [::windows::gamelist::filterText]"
355  unbusyCursor .
356  update
357 }
358 
359 #Klimmek: Invert white/black Score in Score graph
360 set ::tools::graphs::score::White 0
361 set ::tools::graphs::score::Black 0
362 
363 ####################
364 # Game score graph
365 
366 proc ::tools::graphs::score::Refresh {} {
367  set linecolor red
368  set linewidth 2
369  set psize 2
370 
371  set w .sgraph
372 
373  if {! [winfo exists $w]} {
374  toplevel $w
375  menu $w.menu
376  $w configure -menu $w.menu
377  $w.menu add cascade -label GraphFile -menu $w.menu.file
378  menu $w.menu.file
379  $w.menu.file add command -label GraphFileColor \
380  -command "::tools::graphs::Save color $w.c"
381  $w.menu.file add command -label GraphFileGrey \
382  -command "::tools::graphs::Save gray $w.c"
383  $w.menu.file add separator
384  $w.menu.file add command -label GraphFileClose -command "destroy $w"
385  $w.menu add cascade -label GraphOptions -menu $w.menu.options
386  #Checkbuttons for Invert white/black Score in Score graph
387  menu $w.menu.options
388  foreach i {White Black} {
389  $w.menu.options add checkbutton -label GraphOptions$i \
390  -variable ::tools::graphs::score::$i -offvalue "0" -onvalue "1" \
391  -command "::tools::graphs::score::Refresh"
392  }
393 
394  canvas $w.c -width 500 -height 300
395  $w.c create text 25 5 -tag text -justify center -width 1 \
396  -font font_Regular -anchor n
397  pack $w.c -side top -expand yes -fill both
398  bind $w <F1> {helpWindow Graphs Score}
399  bind $w <Configure> {
400  .sgraph.c itemconfigure text -width [expr {[winfo width .sgraph.c] - 50}]
401  .sgraph.c coords text [expr {[winfo width .sgraph.c] / 2}] 10
402  ::utils::graph::configure score -height [expr {[winfo height .sgraph.c] - 90}]
403  ::utils::graph::configure score -width [expr {[winfo width .sgraph.c] - 100}]
404  ::utils::graph::redraw score
405  }
406  bind $w.c <$::MB3> ::tools::graphs::score::Refresh
407  bind $w.c <1> {::tools::graphs::score::Move %x}
408  bind $w <Control-Z> ::tools::graphs::score::Refresh
409  wm title $w "Scid: [tr ToolsScore]"
411  }
412 
413  $w.c itemconfigure text -width [expr {[winfo width $w.c] - 50}]
414  $w.c coords text [expr {[winfo width $w.c] / 2}] 10
415  set height [expr {[winfo height $w.c] - 90}]
416  set width [expr {[winfo width $w.c] - 100}]
417  ::utils::graph::create score -width $width -height $height -xtop 50 -ytop 45 \
418  -ytick 1 -xtick 5 -font font_Small -canvas $w.c -textcolor black \
419  -hline {{gray80 1 each 1} {black 1 at 0}} \
420  -vline {{gray80 1 each 1} {steelBlue 1 each 5}}
421 
422  # Create fake dataset with bounds so we see at least -1.0 to 1.0:
423  ::utils::graph::data score bounds -points 0 -lines 0 -bars 0 -coords {1 -0.9 1 0.9}
424 
425  # Update the graph:
426  set whiteelo [sc_game tag get WhiteElo]
427  set blackelo [sc_game tag get BlackElo]
428  if {$whiteelo == 0} {set whiteelo ""} else {set whiteelo "($whiteelo)"}
429  if {$blackelo == 0} {set blackelo ""} else {set blackelo "($blackelo)"}
430  $w.c itemconfigure text -text "[sc_game info white]$whiteelo - [sc_game info black]$blackelo\n[sc_game info site] [sc_game info date]"
431  busyCursor $w
432  update
433  #Klimmek: Invert white/black Score in Score graph
434  catch {::utils::graph::data score data -color $linecolor -points 1 -lines 1 \
435  -linewidth $linewidth -radius $psize -outline $linecolor \
436  -coords [sc_game scores $::tools::graphs::score::White $::tools::graphs::score::Black]}
438  unbusyCursor $w
439  update
440 }
441 
442 proc ::tools::graphs::score::ConfigMenus {{lang ""}} {
443  if {! [winfo exists .sgraph]} { return}
444  if {$lang == ""} { set lang $::language}
445  set m .sgraph.menu
446  foreach idx {0 1} tag {File Options} {
447  configMenuText $m $idx Graph$tag $lang
448  }
449  foreach idx {0 1 3} tag {Color Grey Close} {
450  configMenuText $m.file $idx GraphFile$tag $lang
451  }
452  #Klimmek: translate optionsmenu
453  foreach idx {0 1} tag {White Black} {
454  configMenuText $m.options $idx GraphOptions$tag $lang
455  }
456 }
457 
458 proc ::tools::graphs::score::Move {xc} {
459  set x [expr {round([::utils::graph::xunmap score $xc] * 2)}]
460  sc_move start
461  sc_move forward $x
463 }
464 
465 
466 ####################
467 # Rating graph
468 
469 set ::tools::graphs::rating::year 1900
470 set ::tools::graphs::rating::type both
471 set ::tools::graphs::rating::player ""
472 
473 proc ::tools::graphs::rating::Refresh {{type ""} {player ""}} {
474  set white [sc_game info white]
475  set black [sc_game info black]
476  set whiteColor red
477  set blackColor blue
478  set lwidth 2
479  set psize 2
480 
481  if {$type == ""} { set type $::tools::graphs::rating::type}
482  if {$player == ""} { set player $::tools::graphs::rating::player}
483  set ::tools::graphs::rating::type $type
484  set ::tools::graphs::rating::player $player
485 
486  set w .rgraph
487 
488  if {! [winfo exists $w]} {
489  toplevel $w
490  menu $w.menu
491  $w configure -menu $w.menu
492  $w.menu add cascade -label GraphFile -menu $w.menu.file
493  menu $w.menu.file
494  $w.menu.file add command -label GraphFileColor \
495  -command "::tools::graphs::Save color $w.c"
496  $w.menu.file add command -label GraphFileGrey \
497  -command "::tools::graphs::Save gray $w.c"
498  $w.menu.file add separator
499  $w.menu.file add command -label GraphFileClose -command "destroy $w"
500  $w.menu add cascade -label GraphOptions -menu $w.menu.options
501  menu $w.menu.options
502  foreach i {White Black Both PInfo} j {white black both player} {
503  $w.menu.options add radiobutton -label GraphOptions$i \
504  -variable ::tools::graphs::rating::type -value $j \
505  -command "::tools::graphs::rating::Refresh"
506  }
507  $w.menu.options add separator
508  foreach i {1900 1980 1985 1990 1995 2000 2005 2010 2015 } {
509  $w.menu.options add radiobutton -label "Since $i" \
510  -variable ::tools::graphs::rating::year -value $i \
511  -command "::tools::graphs::rating::Refresh"
512  }
513 
514  canvas $w.c -width 500 -height 300
515  $w.c create text 25 10 -tag text -justify center -width 1 \
516  -font font_Regular -anchor n
517  pack $w.c -side top -expand yes -fill both
518  bind $w <F1> {helpWindow Graphs Rating}
519  bind $w <Configure> {
520  .rgraph.c itemconfigure text -width [expr {[winfo width .rgraph.c] - 50} ]
521  .rgraph.c coords text [expr {[winfo width .rgraph.c] / 2} ] 10
522  ::utils::graph::configure ratings -height [expr {[winfo height .rgraph.c] - 70} ]
523  ::utils::graph::configure ratings -width [expr {[winfo width .rgraph.c] - 100} ]
524  ::utils::graph::configure ratings -logy 10
525  ::utils::graph::redraw ratings
526  }
527  bind $w.c <Button-1> "::tools::graphs::rating::Refresh"
528  bind $w.c <Button-$::MB3> "::tools::graphs::rating::Refresh"
529  wm title $w "Scid: [tr ToolsRating]"
531  }
532 
533  $w.c itemconfigure text -width [expr {[winfo width $w.c] - 50}]
534  $w.c coords text [expr {[winfo width $w.c] / 2}] 10
535  set height [expr {[winfo height $w.c] - 70}]
536  set width [expr {[winfo width $w.c] - 100}]
537  ::utils::graph::create ratings -width $width -height $height -xtop 50 -ytop 35 \
538  -ytick 50 -xtick 1 -font font_Small -canvas $w.c -textcolor black \
539  -hline {{gray80 1 each 25} {steelBlue 1 each 100}} \
540  -vline {{gray80 1 each 1} {steelBlue 1 each 5}}
541  ::utils::graph::redraw ratings
542  busyCursor $w
543  update
544 
545  set title "[tr ToolsRating]: "
546  set year $::tools::graphs::rating::year
547  if {$type == "player"} {
548  append title $player
549  catch {::utils::graph::data ratings d -color $whiteColor -points 1 -lines 1 \
550  -linewidth $lwidth -radius $psize -outline $whiteColor \
551  -coords [sc_name info -ratings:$year $player]}
552  }
553  if {$type == "white" || $type == "both"} {
554  set key ""
555  if {$type == "both"} { set key [::utils::string::Surname $white]}
556  append title $white
557  catch {::utils::graph::data ratings d -color $whiteColor -points 1 -lines 1 \
558  -linewidth $lwidth -radius $psize -outline $whiteColor \
559  -key $key -coords [sc_name info -ratings:$year $white]}
560  }
561  if {$type == "both"} { append title " - "}
562  if {$type == "black" || $type == "both"} {
563  set key ""
564  if {$type == "both"} { set key [::utils::string::Surname $black]}
565  append title $black
566  catch {::utils::graph::data ratings d2 -color $blackColor -points 1 -lines 1 \
567  -linewidth $lwidth -radius $psize -outline $blackColor \
568  -key $key -coords [sc_name info -ratings:$year $black]}
569  }
570  set minYear [expr {int([::utils::graph::cget ratings axmin])}]
571  set maxYear [expr {int([::utils::graph::cget ratings axmax])}]
572  ::utils::graph::configure ratings -xtick 1
573  if {[expr {$maxYear - $minYear}] > 10} {::utils::graph::configure ratings -xtick 5}
574  ::utils::graph::redraw ratings
575  $w.c itemconfigure text -text $title
576  unbusyCursor $w
577 }
578 
579 proc ::tools::graphs::rating::ConfigMenus {{lang ""}} {
580  if {! [winfo exists .rgraph]} { return}
581  if {$lang == ""} { set lang $::language}
582  set m .rgraph.menu
583  foreach idx {0 1} tag {File Options} {
584  configMenuText $m $idx Graph$tag $lang
585  }
586  foreach idx {0 1 3} tag {Color Grey Close} {
587  configMenuText $m.file $idx GraphFile$tag $lang
588  }
589  foreach idx {0 1 2 3} tag {White Black Both PInfo} {
590  configMenuText $m.options $idx GraphOptions$tag $lang
591  }
592 }
593 
594 
595 ########################################
596 # Filter graph window for absolut values
597 
598 # ::tools::graphs::absfilter::type
599 # can be "decade", "year" or "elo", "move"
600 #
601 set ::tools::graphs::absfilter::type year
602 
603 proc tools::graphs::absfilter::Open {} {
604  global absfilterGraph
605  set w .afgraph
606  if {[winfo exists $w]} {
607  focus .
608  destroy $w
609  set absfilterGraph 0
610  return
611  }
612  toplevel $w
613  menu $w.menu
614  $w configure -menu $w.menu
615  $w.menu add cascade -label GraphFile -menu $w.menu.file
616  configMenuText $w.menu 0 GraphFile $::language
617  menu $w.menu.file
618  $w.menu.file add command -label GraphFileColor -command "::tools::graphs::Save color $w.c"
619  configMenuText $w.menu.file 0 GraphFileColor $::language
620  $w.menu.file add command -label GraphFileGrey -command "::tools::graphs::Save gray $w.c"
621  configMenuText $w.menu.file 1 GraphFileGrey $::language
622  $w.menu.file add separator
623  $w.menu.file add command -label GraphFileClose -command "destroy $w"
624  configMenuText $w.menu.file 3 GraphFileClose $::language
625  wm title $w $::tr(TitleFilterGraph)
626  set absfilterGraph 1
627  bind $w <Destroy> {set absfilterGraph 0}
628 
629  frame $w.b
630  pack $w.b -side bottom -fill x
631  label $w.b.status -width 1 -font font_Small -anchor w
632  frame $w.sep -height 2 -borderwidth 2 -relief sunken -background white
633  pack $w.sep -side bottom -fill x -pady 4
634 
635  canvas $w.c -width 600 -height 400
636  $w.c create text 25 5 -tag title -justify center -width 1 \
637  -font font_Small -anchor n
638  $w.c create text 250 295 -tag type -justify center -width 1 \
639  -font font_Small -anchor s
640  pack $w.c -side top -expand yes -fill both
641  ::utils::graph::create absfilter
642 
643  bind $w <F1> {helpWindow Graphs Filter}
644  bind $w <Configure> {
645  .afgraph.c itemconfigure title -width [expr {[winfo width .afgraph.c] - 50}]
646  .afgraph.c coords title [expr {[winfo width .afgraph.c] / 2}] 10
647  .afgraph.c itemconfigure type -width [expr {[winfo width .afgraph.c] - 50}]
648  .afgraph.c coords type [expr {[winfo width .afgraph.c] / 2}] \
649  [expr {[winfo height .afgraph.c] - 10}]
650  ::utils::graph::configure absfilter -height [expr {[winfo height .afgraph.c] - 80}]
651  ::utils::graph::configure absfilter -width [expr {[winfo width .afgraph.c] - 60}]
652  ::utils::graph::redraw absfilter
653  }
654  bind $w.c <1> tools::graphs::absfilter::Switch
655  bind $w.c <$::MB3> ::tools::graphs::absfilter::Refresh
656  foreach {name text} {decade Decade year Year elo Rating move moves} {
657  radiobutton $w.b.$name -padx 4 -pady 3 -text $::tr($text) \
658  -variable ::tools::graphs::absfilter::type -value $name \
659  -command ::tools::graphs::absfilter::Refresh
660  pack $w.b.$name -side left -padx 1 -pady 2
661  }
662  button $w.b.setup -image tb_graph -command configureFilterGraph
663  dialogbutton $w.b.close -text $::tr(Close) -command "destroy $w"
664  pack $w.b.decade $w.b.elo -side left -padx 1 -pady 2
665  pack $w.b.close $w.b.setup -side right -padx 2 -pady 2
666  pack $w.b.status -side left -padx 2 -pady 2 -fill x -expand yes
667 
669 }
670 
671 proc tools::graphs::absfilter::Switch {} {
672  variable type
673  switch $type {
674  "decade" { set type "year"}
675  "year" { set type "elo"}
676  "elo" { set type "move"}
677  "move" { set type "decade"}
678  }
680 }
681 
682 proc ::tools::graphs::absfilter::Refresh {} {
683  global FilterMaxMoves FilterMinMoves FilterStepMoves FilterMaxElo FilterMinElo FilterStepElo FilterMaxYear FilterMinYear FilterStepYear FilterGuessELO
684 
685  set w .afgraph
686  if {! [winfo exists $w]} { return}
687 
688  $w.c itemconfigure title -width [expr {[winfo width $w.c] - 50}]
689  $w.c coords title [expr {[winfo width $w.c] / 2}] 10
690  $w.c itemconfigure type -width [expr {[winfo width $w.c] - 50}]
691  $w.c coords type [expr {[winfo width $w.c] / 2}] \
692  [expr {[winfo height $w.c] - 10}]
693  set height [expr {[winfo height $w.c] - 80}]
694  set width [expr {[winfo width $w.c] - 60}]
695  set vlines {}
696  if {$::tools::graphs::absfilter::type == "elo"} {
697  # Vertical lines for Elo-range graph:
698  for {set i 1} {$i <= $FilterMaxElo- $FilterMinElo} { incr i} {
699  lappend vlines [list gray80 1 at $i.5]
700  }
701  } elseif {$::tools::graphs::absfilter::type == "year"} {
702  # Vertical lines for Year-range graph:
703  for {set i 1} {$i <= $FilterMaxYear- $FilterMinYear} {incr i} {
704  lappend vlines [list gray80 1 at $i.5]
705  }
706  } elseif {$::tools::graphs::absfilter::type == "decade"} {
707  # Vertical lines for Decade graph: most are gray, but those
708  # just before 1950s and 2000s are blue to make them stand out.
709  for {set i 1} {$i < 10} {incr i} {
710  set vlineColor gray80
711  if {$i == 4 || $i == 9} { set vlineColor steelBlue}
712  lappend vlines [list $vlineColor 1 at $i.5]
713  }
714  }
715 
716  ::utils::graph::create absfilter -width $width -height $height -xtop 40 -ytop 35 \
717  -ytick 1 -xtick 1 -font font_Small -canvas $w.c -textcolor black \
718  -vline $vlines -background lightYellow -tickcolor black -xmin 0 -xmax 1
719  ::utils::graph::redraw absfilter
720  busyCursor .
721  update
722 
723  set count 0
724  set dlist {}
725  set xlabels {}
726  set max 0.0
727 
728  # Generate plot values and labels:
729  if {$::tools::graphs::absfilter::type == "decade"} {
730  set ftype date
731  set typeName $::tr(Decade)
732  set rlist [list 0000 1919 -1919 1920 1929 20-29 \
733  1930 1939 30-39 1940 1949 40-49 1950 1959 50-59 \
734  1960 1969 60-69 1970 1979 70-79 1980 1989 80-89 \
735  1990 1999 90-99 2000 2009 2000+]
736  } elseif {$::tools::graphs::absfilter::type == "year"} {
737  set ftype date
738  set typeName $::tr(Year)
739  set endYear $FilterMaxYear
740  set startYear $FilterMinYear
741  set rlist {}
742  for {set i $startYear} {$i <= $endYear} {set i [expr {$i + $FilterStepYear}]} {
743  lappend rlist $i
744  lappend rlist [expr {$i+$FilterStepYear-1}]
745  lappend rlist [expr {$i+$FilterStepYear/2}]
746  }
747  } elseif {$::tools::graphs::absfilter::type == "elo"} {
748  set ftype elo
749  set typeName $::tr(Rating)
750  # set rlist [list 0 1999 0-1999 2000 2099 20xx 2100 2199 21xx \
751  2200 2299 22xx 2300 2399 23xx 2400 2499 24xx \
752  2500 2599 25xx 2600 2699 26xx 2700 3999 2700+]
753  set endElo $FilterMaxElo
754  set startElo $FilterMinElo
755  set rlist {}
756  for {set i $startElo} {$i <= $endElo} {set i [expr {$i + $FilterStepElo}]} {
757  lappend rlist $i
758  lappend rlist [expr {$i+$FilterStepElo-1}]
759  # shorten gap between 0 and "useful" ratings 1800
760  set j $i
761  if { $i < 100 } { set i [expr { 1800 - $FilterStepElo}]}
762  lappend rlist [concat $j-[expr {$i+$FilterStepElo-1}]]
763  }
764  } else {
765  set ftype move
766  set typeName $::tr(moves)
767  set startMove $FilterMinMoves
768  set endMove $FilterMaxMoves
769  set rlist {}
770  for {set i $startMove} {$i <= $endMove} {set i [expr {$i + $FilterStepMoves}]} {
771  lappend rlist [expr {2*$i}]
772  lappend rlist [expr {2*($i+$FilterStepMoves)-1}]
773  if { $i % 5 == 0 } {
774  lappend rlist $i
775  } else {
776  lappend rlist ""
777  }
778  }
779  }
780 
781  set mean 0
782  foreach {start end label} $rlist {
783  if {$ftype == "date"} { append end ".12.31"}
784  set r [sc_filter freq [sc_base current] dbfilter $ftype $start $end $FilterGuessELO]
785  set absfilter [lindex $r 0]
786  set all [lindex $r 1]
787  set freq $absfilter
788  incr count
789  set mean [expr { $mean + $absfilter }]
790  lappend dlist $count
791  lappend dlist $freq
792  if {$freq > $max} { set max $freq}
793  lappend xlabels [list $count $label]
794  }
795 
796  # Find a suitable spacing of y-axis labels:
797  set ytick 1
798  if {$max >= 10} { set ytick 1}
799  if {$max >= 25} { set ytick 5}
800  # if {$max >= 50} { set ytick 5 }
801  if {$max >= 100} { set ytick 10}
802  if {$max >= 250} { set ytick 25}
803  if {$max >= 500} { set ytick 50}
804  if {$max >= 1000} { set ytick 100}
805  if {$max >= 2500} { set ytick 250}
806  if {$max >= 5000} { set ytick 500}
807  if {$max >= 10000} { set ytick 1000}
808  if {$max >= 25000} { set ytick 2500}
809  if {$max >= 50000} { set ytick 5000}
810  if {$max >= 100000} { set ytick 10000}
811  if {$max >= 250000} { set ytick 25000}
812  if {$max >= 500000} { set ytick 50000}
813  if {$max >= 1000000} { set ytick 100000}
814  set hlines [list [list gray80 1 each $ytick]]
815  # Add mean horizontal line:
816  set absfilter [sc_filter count]
817  set all [sc_base numGames $::curr_db]
818  if { $count != 0 } {set mean [expr { $mean / $count }]}
819  if {$all > 0} {
820  if {$mean > $max} { set max $mean}
821  lappend hlines [list red 1 at $mean]
822  }
823 
824  # Create fake dataset with bounds so we see 0.0::
825  #::utils::graph::data decade bounds -points 0 -lines 0 -bars 0 -coords {1 0.0 1 0.0}
826 
827  ::utils::graph::data absfilter data -color darkBlue -points 1 -lines 1 -bars 0 \
828  -linewidth 2 -radius 4 -outline darkBlue -coords $dlist
829  ::utils::graph::configure absfilter -xlabels $xlabels -ytick $ytick \
830  -hline $hlines -ymin 0 -xmin 0.5 -xmax [expr {$count + 0.5}]
831  ::utils::graph::redraw absfilter
832  $w.c itemconfigure title -text $::tr(GraphAbsFilterTitle)
833  $w.c itemconfigure type -text $typeName
834  $w.b.status configure -text " $::tr(Filter): [::windows::gamelist::filterText]"
835  unbusyCursor .
836  update
837 }
838 ### End of file: graph.tcl