Scid  4.6.5
optable.tcl
Go to the documentation of this file.
1 ### optable.tcl: Opening report and theory table generation.
2 ### Part of Scid. Copyright 2001-2003 Shane Hudson.
3 
4 namespace eval ::optable {}
5 array set ::optable::_data {}
6 
7 set ::optable::_data(exclude) "---"
8 set ::optable::_docStart(text) {}
9 set ::optable::_docEnd(text) {}
10 set ::optable::_docStart(ctext) {}
11 set ::optable::_docEnd(ctext) {}
12 set ::optable::_flip 0
13 
14 set ::optable::_docStart(html) {<html>
15  <head>
16  <title>[OprepTitle]</title>
17  <style type="text/css">
18  <!--
19  h1 { color:#990000 }
20  h2 { color:#990000 }
21  h3 { color:#990000 }
22  .player {
23  color:darkblue
24  }
25  .elo {
26  color:green
27  font-style:italic
28  }
29  sup {
30  color:red
31  }
32  -->
33  </style>
34  </head>
35  <body bgcolor="#ffffff">
36 }
37 set ::optable::_docEnd(html) {</body>
38  </html>
39 }
40 
41 set ::optable::_docStart(latex) {\documentclass[10pt,a4paper]{article}
42  % This is a LaTeX file generated by Scid.
43  % You must have the "chess12" package installed to typeset this file.
44 
45  \usepackage{times}
46  \usepackage{a4wide}
47  \usepackage{chess}
48  \usepackage[T1]{fontenc}
49 
50  \setlength{\columnsep}{1cm}
51  \setlength{\parindent}{0pt}
52  \setlength{\parskip}{3pt}
53 
54  \font\F=chessf10
55  \newcommand{\B}{{\F B}}
56  \newcommand{\N}{{\F N}}
57  \newcommand{\R}{{\F R}}
58  \newcommand{\Q}{{\F Q}}
59  \newcommand{\K}{{\F K}}
60  \newcommand{\tspace}{{\vspace{0.08cm}}}
61  \newcommand{\draw}{{\small$\frac{1}{2}$:$\frac{1}{2}$}}
62  \newcommand{\loss}{\mbox{0:1}}
63  \newcommand{\win}{\mbox{1:0}}
64  \newcommand{\notenum}[1]{\hspace{-0.7cm}\makebox[0.55cm][r]{$^{ #1 }$ }\makebox[0.05cm]{}}
65 
66  %\font\Chess=chess10
67  \begin{document}
68  \raggedright
69  \nochess
70 }
71 set ::optable::_docEnd(latex) {
72  \end{document}
73 }
74 
75 proc ::optable::ConfigMenus {{lang ""}} {
76  if {! [winfo exists .oprepWin]} { return}
77  if {$lang == ""} { set lang $::language}
78  set m .oprepWin.menu
79  foreach idx {0 1 2} tag {File Favorites Help} {
80  configMenuText $m $idx Oprep$tag $lang
81  }
82  foreach idx {0 1 2 4 6} tag {Text Html LaTeX Options Close} {
83  configMenuText $m.file $idx OprepFile$tag $lang
84  }
85  foreach idx {0 1 2} tag {Add Edit Generate} {
86  configMenuText $m.favorites $idx OprepFavorites$tag $lang
87  }
88  foreach idx {0 1} tag {Report Index} {
89  configMenuText $m.helpmenu $idx OprepHelp$tag $lang
90  }
91 }
92 
93 proc ::optable::makeReportWin {args} {
94  set ::optable::opReportBase [sc_base current]
95  set showProgress 1
96  set args [linsert $args 0 "args"]
97  if {[lsearch -exact $args "-noprogress"] >= 0} { set showProgress 0}
98  if {$showProgress} {
99  set w .progress
100  toplevel $w
101  wm withdraw $w
102  wm title $w "Scid: Generating Report"
103  bind $w <Visibility> "raiseWin $w"
104 
105  pack [frame $w.b] -side bottom -fill x
106  set ::optable::_interrupt 0
107  button $w.b.cancel -text $::tr(Cancel) -command {
108  set ::optable::_interrupt 1
109  progressBarCancel
110  }
111  pack $w.b.cancel -side right -pady 5 -padx 2
112 
113  foreach i {1 2} name { "Searching database for report games" "Generating report information" } {
114  label $w.text$i -text "$i. $name"
115  pack $w.text$i -side top
116  canvas $w.c$i -width 400 -height 20 -bg white -relief solid -border 1
117  $w.c$i create rectangle 0 0 0 0 -fill blue -outline blue -tags bar
118  $w.c$i create text 395 10 -anchor e -font font_Regular -tags time \
119  -fill black -text "0:00 / 0:00"
120  pack $w.c$i -side top -pady 10
121  }
122  wm resizable $w 0 0
123  # Set up geometry for middle of screen:
124  set x [winfo screenwidth $w]; set x [expr $x - 400]; set x [expr $x / 2]
125  set y [winfo screenheight $w]; set y [expr $y - 20]; set y [expr $y / 2]
126  wm geometry $w +$x+$y
127  wm deiconify $w
128  grab $w.b.cancel
129  progressBarSet $w.c1 401 21
130  }
131 
132  sc_search board RESET Exact false 0
133  set newTreeData [sc_tree search]
134  if {$showProgress} {
135  if {$::optable::_interrupt} {
136  grab release $w.b.cancel
137  destroy $w
138  return
139  }
140  progressBarSet $w.c2 401 21
141  }
142  sc_report opening create $::optable(ExtraMoves) $::optable(MaxGames) $::optable::_data(exclude)
143  if {$showProgress} {
144  grab release $w.b.cancel
145  destroy $w
146  if {$::optable::_interrupt} { return}
147  }
148 
149  set ::optable::_data(tree) $newTreeData
151  set ::optable::_data(bdLaTeX) [sc_pos tex]
152  set ::optable::_data(bdHTML) [sc_pos html]
153  set ::optable::_data(bdLaTeX_flip) [sc_pos tex flip]
154  set ::optable::_data(bdHTML_flip) [sc_pos html -flip 1]
155 
157 
158  set report [::optable::report ctext 1]
159 
160  if {[lsearch -exact $args "-nodisplay"] >= 0} { return}
161 
162  set w .oprepWin
163  if {![winfo exists $w]} {
165  ::setTitle $w "[tr ToolsOpReport]"
166  menu $w.menu
167  ::setMenu $w $w.menu
168 
169  $w.menu add cascade -label OprepFile -menu $w.menu.file
170  $w.menu add cascade -label OprepFavorites -menu $w.menu.favorites
171  $w.menu add cascade -label OprepHelp -menu $w.menu.helpmenu
172  foreach i {file favorites helpmenu} {
173  menu $w.menu.$i -tearoff 0
174  }
175 
176  $w.menu.file add command -label OprepFileText \
177  -command {::optable::saveReport text}
178  $w.menu.file add command -label OprepFileHtml \
179  -command {::optable::saveReport html}
180  $w.menu.file add command -label OprepFileLaTeX \
181  -command {::optable::saveReport latex}
182  $w.menu.file add separator
183  $w.menu.file add command -label OprepFileOptions \
184  -command ::optable::setOptions
185  $w.menu.file add separator
186  $w.menu.file add command -label OprepFileClose \
187  -command "$w.b.close invoke"
188  $w.menu.favorites add command -label OprepFavoritesAdd \
189  -command ::optable::addFavoriteDlg
190  $w.menu.favorites add command -label OprepFavoritesEdit \
191  -command ::optable::editFavoritesDlg
192  $w.menu.favorites add command -label OprepFavoritesGenerate \
193  -command ::optable::generateFavoriteReports
194  $w.menu.favorites add separator
195  $w.menu.helpmenu add command -label OprepHelpReport \
196  -accelerator F1 -command {helpWindow Reports Opening}
197  $w.menu.helpmenu add command -label OprepHelpIndex \
198  -command {helpWindow Index}
199 
201 
202  bind $w <F1> {helpWindow Reports Opening}
203  bind $w <Escape> "$w.b.close invoke"
204  bind $w <Up> "$w.text yview scroll -1 units"
205  bind $w <Down> "$w.text yview scroll 1 units"
206  bind $w <Prior> "$w.text yview scroll -1 pages"
207  bind $w <Next> "$w.text yview scroll 1 pages"
208  bind $w <Key-Home> "$w.text yview moveto 0"
209  bind $w <Key-End> "$w.text yview moveto 0.99"
210 
211  text $w.text -height 30 -width 85 -font font_Small -setgrid 1 \
212  -wrap word -bg white -foreground black -yscrollcommand "$w.ybar set" \
213  -cursor top_left_arrow
214  ::htext::init $w.text
215  scrollbar $w.ybar -command "$w.text yview"
216  frame $w.b
217  button $w.b.previewLaTeX -textvar ::tr(OprepViewLaTeX) \
218  -command ::optable::previewLaTeX
219  button $w.b.previewHTML -textvar ::tr(OprepViewHTML) \
220  -command ::optable::previewHTML
221  button $w.b.opts -text [tr OprepFileOptions] -command ::optable::setOptions
222  label $w.b.lexclude -text "Exclude:"
223  menubutton $w.b.exclude -textvar ::optable::_data(exclude) \
224  -indicatoron 1 -relief raised -bd 2 -menu $w.b.exclude.m -padx 1
225  menu $w.b.exclude.m -tearoff 0
226  button $w.b.update -textvar ::tr(Update) -command {
227  set ::optable::_data(yview) [lindex [.oprepWin.text yview] 0]
228  ::optable::makeReportWin
229  .oprepWin.text yview moveto $::optable::_data(yview)
230  }
231 
232  button $w.b.mergeGames -textvar ::tr(MergeGames) -command ::optable::mergeGames
233  button $w.b.help -textvar ::tr(Help) -command {helpWindow Reports Opening}
234  button $w.b.close -textvar ::tr(Close) -command "focus .; destroy $w"
235  pack $w.b -side bottom -fill x
236  pack $w.ybar -side right -fill y
237  pack $w.text -side left -fill both -expand yes
238  pack $w.b.close $w.b.update -side right -padx 1 -pady 2
239  if {! $::windowsOS} {
240  pack $w.b.previewLaTeX -side left -padx 1 -pady 2
241  } else {
242  pack $w.b.previewHTML -side left -padx 1 -pady 2
243  }
244  pack $w.b.opts $w.b.lexclude $w.b.exclude $w.b.mergeGames -side left -padx 1 -pady 2
248  }
249 
250  catch {destroy $w.text.bd}
251 
252  set old_showMaterial $::gameInfo(showMaterial)
253  set ::gameInfo(showMaterial) 0
254  ::board::new $w.text.bd 30
255 
256  if {$::optable::_flip} { ::board::flip $w.text.bd}
257  $w.text.bd configure -relief solid -borderwidth 1
258  for {set i 0} {$i < 63} {incr i} {
259  ::board::bind $w.text.bd $i <ButtonPress-1> ::optable::flipBoard
260  #::board::bind $w.text.bd $i <ButtonPress-$::MB3> ::optable::resizeBoard
261  }
262  ::board::update $w.text.bd [sc_pos board]
263  $w.b.exclude.m delete 0 end
264  $w.b.exclude.m add radiobutton -label "---" -variable ::optable::_data(exclude) -command "$w.b.update invoke"
265  foreach move $::optable::_data(moves) {
266  $w.b.exclude.m add radiobutton -label $move -variable ::optable::_data(exclude) -command "$w.b.update invoke"
267  }
268  if {[lsearch $::optable::_data(moves) $::optable::_data(exclude)] < 0} {
269  set ::optable::_data(exclude) "---"
270  }
271  busyCursor .
272  $w.text configure -state normal
273  $w.text delete 1.0 end
274  regsub -all "\n" $report "<br>" report
275  ::htext::display $w.text $report
276  $w.text configure -state disabled
277  unbusyCursor .
280  set ::gameInfo(showMaterial) $old_showMaterial
281 
282 }
283 ################################################################################
284 # merges the N best games up to P plies to current game
285 ################################################################################
286 proc ::optable::mergeGames { {game_count 50} {ply 999} } {
287  set base $::optable::opReportBase
288  set games [split [sc_report opening best a $game_count] "\n"]
289  foreach g $games {
290  if {$g == "" } { continue}
291  set res [scan $g "%d: <g_%d>" d1 game_number]
292  if {$res != 2} {
293  if {[info exists game_number]} {
294  tk_messageBox -title "Scid: Error writing report" -type ok -icon warning -message "Error merging game $game_number"
295  } else {
296  tk_messageBox -title "Scid: Error writing report" -type ok -icon warning -message "Error merging game"
297  }
298  break
299  }
300  set err [ catch { sc_game merge $base $game_number $ply} result]
301  if {$err} {
302  tk_messageBox -title "Scid" -type ok -icon info -message "Unable to merge the selected game:\n$result"
303  break
304  }
305  }
306  updateBoard -pgn
307 }
308 ################################################################################
309 #
310 ################################################################################
311 
312 proc ::optable::flipBoard {} {
313  set old_showMaterial $::gameInfo(showMaterial)
314  set ::gameInfo(showMaterial) 0
315  ::board::flip .oprepWin.text.bd
316  set ::optable::_flip [::board::isFlipped .oprepWin.text.bd]
317  set ::gameInfo(showMaterial) $old_showMaterial
318 }
319 
320 proc ::optable::resizeBoard {} {
321  set bd .oprepWin.text.bd
322  set size [::board::size $bd]
323  if {$size >= 40} { set size 25} else { incr size 5}
324  ::board::resize $bd $size
325 }
326 
327 proc ::optable::setOptions {} {
328  set w .oprepOptions
329  if {[winfo exists $w]} { return}
330  toplevel $w
331  pack [frame $w.f] -side top -fill x -padx 5 -pady 5
332  set row 0
333  foreach i {Stats Popular AvgPerf Results MovesFrom Themes Endgames} {
334  set yesno($i) 1
335  }
336  set left 0
337  set right 1
338  foreach i {Stats Oldest Newest Popular MostFrequent sep \
339  AvgPerf HighRating sep \
340  Results Shortest col \
341  MoveOrders MovesFrom Themes Endgames gap sep \
342  MaxGames ExtraMoves sep} {
343  set from 0; set to 10; set tick 1; set res 1
344 
345  if {$i == "col"} {
346  incr left 4
347  frame $w.f.colsep$left -width 8
348  grid $w.f.colsep$left -row 0 -column $left
349  incr left
350  set right [expr {$left + 1}]
351  set row 0
352  } elseif {$i == "gap"} {
353  # nothing
354  } elseif {$i == "sep"} {
355  frame $w.f.fsep$row$left -height 2 -borderwidth 2 -relief sunken -bg white
356  frame $w.f.tsep$row$left -height 2 -borderwidth 2 -relief sunken -bg white
357  grid $w.f.fsep$row$left -row $row -column $left -sticky we -columnspan 4
358  } elseif {[info exists yesno($i)]} {
359  checkbutton $w.f.f$i -variable ::optable($i) -onvalue 1 -offvalue 0
360  label $w.f.t$i -textvar ::tr(Oprep$i) -font font_Small
361  grid $w.f.f$i -row $row -column $left -sticky n
362  grid $w.f.t$i -row $row -column $right -sticky w -columnspan 3
363  } else {
364 
365  # Pascal Georges : changed combobox to spinbox to widen choices
366  if {$i == "MaxGames"} {
367  spinbox $w.f.s$i -textvariable ::optable($i) -from 0 -to 5000 -increment 50 \
368  -state readonly -width 5 -justify right -font font_Small
369  } else {
370  set tmpcombo {}
371  for {set x $from} {$x <= $to} {incr x $res} {
372  lappend tmpcombo $x
373  }
374  ttk::combobox $w.f.s$i -textvariable ::optable($i) -width 2 -height 11 -values $tmpcombo
375  }
376 
377  label $w.f.t$i -textvar ::tr(Oprep$i) -font font_Small
378  grid $w.f.s$i -row $row -column $left ;# -sticky e
379  if {$i == "MostFrequent" || $i == "Shortest"} {
380  checkbutton $w.f.w$i -text $::tr(White) -font font_Small \
381  -variable ::optable(${i}White)
382  checkbutton $w.f.b$i -text $::tr(Black) -font font_Small \
383  -variable ::optable(${i}Black)
384  grid $w.f.t$i -row $row -column $right -sticky w
385  grid $w.f.w$i -row $row -column 2
386  grid $w.f.b$i -row $row -column 3
387  } else {
388  grid $w.f.t$i -row $row -column $right -sticky w -columnspan 3
389  }
390  }
391  grid rowconfigure $w.f $row -pad 2
392  if {$i != "col"} { incr row}
393  }
395  pack [frame $w.b] -side bottom -fill x
396  dialogbutton $w.b.defaults -textvar ::tr(Defaults) -command {
397  array set ::optable [array get ::optableDefaults]
398  }
399  dialogbutton $w.b.ok -text "OK" -command {
400  destroy .oprepOptions
401  catch {set ::optable::_data(yview) [lindex [.oprepWin.text yview] 0]}
402  ::optable::makeReportWin
403  catch {.oprepWin.text yview moveto $::optable::_data(yview)}
404  }
405  dialogbutton $w.b.cancel -textvar ::tr(Cancel) -command {
406  array set ::optable [array get ::optable::backup]
407  destroy .oprepOptions
408  }
409  packbuttons left $w.b.defaults
410  packbuttons right $w.b.cancel $w.b.ok
411  array set ::optable::backup [array get ::optable]
412  wm resizable $w 0 0
413  wm title $w "Scid: [tr ToolsOpReport]: [tr OprepFileOptions]"
414  bind $w <Escape> "$w.b.cancel invoke"
415 }
416 
417 # previewLaTeX:
418 # Saves the report to a temporary file, runs latex on it, then
419 # "dvips" to produce PostScript, and "ghostview" to display it.
420 #
421 proc ::optable::previewLaTeX {} {
422  busyCursor .
423  set tmpdir $::scidLogDir
424  set tmpfile "TempOpeningReport"
425  set fname [file join $tmpdir $tmpfile]
426  catch {exec /bin/sh -c "rm $fname.*"}
427  if {[catch {set tempfile [open $fname.tex w]}]} {
428  tk_messageBox -title "Scid: Error writing report" -type ok -icon warning \
429  -message "Unable to write the file: $fname.tex"
430  }
431  # Add the "batchmode" command to the top of the file to prevent latex
432  # pausing for input on errors:
433  puts $tempfile "\\batchmode"
434  puts $tempfile [::optable::report latex 1 $::optable::_flip]
435  close $tempfile
436  if {! [catch {exec /bin/sh -c "cd $tmpdir; latex '$tmpfile.tex'" >& /dev/null}]} {
437  if {[catch {exec /bin/sh -c "cd $tmpdir; dvips '$tmpfile.dvi'" >& /dev/null}]} {
438  tk_messageBox -title "Scid" -icon warning -type ok \
439  -message "Unable to run \"dvips\" to convert the report to PostScript."
440  } else {
441  if {[catch {exec /bin/sh -c "ghostview '$fname.ps'" >& /dev/null &}]} {
442  tk_messageBox -title "Scid" -icon warning -type ok \
443  -message "Unable to run \"xdvi\" to view the report."
444  }
445  }
446  } else {
447  tk_messageBox -title "Scid: Errors producing report" -type ok \
448  -icon warning \
449  -message "Errors running latex on the file: $fname.tex\n\nSee $fname.log for details."
450  }
451  unbusyCursor .
452 }
453 
454 # previewHTML:
455 # Saves the report to a temporary file, and invokes the user's web
456 # browser to display it.
457 #
458 proc ::optable::previewHTML {} {
459  busyCursor .
460  set tmpdir $::scidLogDir
461  set tmpfile "TempOpeningReport"
462  set fname [file join $tmpdir $tmpfile]
463  if {[catch {set tempfile [open $fname.html w]}]} {
464  tk_messageBox -title "Scid: Error writing report" -type ok -icon warning \
465  -message "Unable to write the file: $fname.html"
466  }
467  puts $tempfile [::optable::report html 1 $::optable::_flip]
468  close $tempfile
469  if {[string match $::tcl_platform(os) "Windows NT"]} {
470  catch {exec $::env(COMSPEC) /c start $fname.html &}
471  } else {
472  catch {exec start $fname.html &}
473  }
474  unbusyCursor .
475 }
476 
477 # saveReport:
478 # Saves the current opening report to a file.
479 # "fmt" is the format: text, html or latex.
480 # "type" is the report type: report, table, or both.
481 #
482 proc ::optable::saveReport {fmt} {
483  set t [tk_dialog .dialog "Scid: Select report type" \
484  "Select the report type. You may save a full report (which includes the theory table), a compact report (with no theory table), or just the theory table by itself." \
485  "" 0 "Full report" "Compact report" \
486  "Theory table" "Cancel"]
487  if {$t == 3} { return}
488  set default ".txt"
489  set ftype {
490  { "Text files" {".txt"} }
491  { "All files" {"*"} }
492  }
493  if {$fmt == "latex"} {
494  set default ".tex"
495  set ftype {
496  { "LaTeX files" {".tex" ".ltx"} }
497  { "All files" {"*"} }
498  }
499  } elseif {$fmt == "html"} {
500  set default ".html"
501  set ftype {
502  { "HTML files" {".html" ".htm"} }
503  { "All files" {"*"} }
504  }
505  }
506 
507  set fname [tk_getSaveFile -initialdir [pwd] -filetypes $ftype \
508  -defaultextension $default -title "Scid: Save opening report"]
509  if {$fname == ""} { return}
510 
511  busyCursor .
512  if {[catch {set tempfile [open $fname w]}]} {
513  tk_messageBox -title "Scid: Error writing report" -type ok -icon warning \
514  -message "Unable to write the file: $fname\n\n"
515  } else {
516  if {$t == 2} {
517  set report [::optable::table $fmt]
518  } elseif {$t == 1} {
519  set report [::optable::report $fmt 0 $::optable::_flip]
520  } else {
521  set report [::optable::report $fmt 1 $::optable::_flip]
522  }
523  if {$::hasEncoding && $::langEncoding($::language) != ""} {
524  catch {set report [encoding convertto $::langEncoding($::language) $report]}
525  }
526  puts $tempfile $report
527  close $tempfile
528  }
529  unbusyCursor .
530 }
531 
532 proc ::optable::create {} {
533  set ::optable::_data(tree) [sc_tree search]
535  set ::optable::_data(bdLaTeX) [sc_pos tex]
536  set ::optable::_data(bdHTML) [sc_pos html]
537  set ::optable::_data(bdLaTeX_flip) [sc_pos tex flip]
538  set ::optable::_data(bdHTML_flip) [sc_pos html -flip 1]
539  sc_report opening create $::optable(ExtraMoves) $::optable(MaxGames)
541 }
542 
543 # latexifyTree
544 # Convert the plain text tree output used for text/html reports
545 # to a table for LaTeX output.
546 #
547 proc ::optable::latexifyTree {} {
548  set ::optable::_data(moves) {}
549  if {! [info exists ::optable::_data(tree)]} { return}
550  set tree [split $::optable::_data(tree) "\n"]
551  set ltree "\\begin{tabular}{rllr@{:}rrrrrr}\n\\hline\n"
552  append ltree " & Move & ECO & \\multicolumn{2}{c}{Frequency}"
553  append ltree " & Score & \$\\mu\$Elo & Perf & \$\\mu\$Year & \\% Draws \\\\ \n"
554  append ltree "\\hline\n"
555  set len [llength $tree]
556  set done 0
557  for {set i 1} {$i < $len} {incr i} {
558  set line [lindex $tree $i]
559  if {[string index $line 0] == "_"} {
560  append ltree "\\hline\n"
561  continue
562  }
563  if {[string length $line] == 0} { continue}
564  set num [string range $line 0 1]
565  set move [string range $line 4 9]
566  set eco [string range $line 11 15]
567  set freq [string range $line 17 23]
568  set fpct [string range $line 25 29]
569  set score [string range $line 33 37]
570  set avElo [string range $line 41 44]
571  set perf [string range $line 47 50]
572  set avYear [string range $line 53 56]
573  set pctDraw [string range $line 59 61]
574  set mv [string trim $move]
575  regsub K $move {{\\K}} move
576  regsub Q $move {{\\Q}} move
577  regsub R $move {{\\R}} move
578  regsub B $move {{\\B}} move
579  regsub N $move {{\\N}} move
580  if {[string index $line 0] == "T"} {
581  append ltree "\\multicolumn{2}{l}{Total}"
582  } else {
583  append ltree " $num & $move "
584  lappend ::optable::_data(moves) $mv
585  }
586  append ltree " & $eco & $freq & $fpct\\% & $score\\%"
587  append ltree " & $avElo & $perf & $avYear & $pctDraw\\% \\\\ \n"
588  }
589  append ltree "\\hline\n"
590  append ltree "\\end{tabular}\n"
591  set ::optable::_data(latexTree) $ltree
592 }
593 
594 proc ::optable::setupRatios {} {
595  set r [sc_filter freq [sc_base current] tree date 0000.00.00]
596  if {[lindex $r 0] == 0} {
597  set ::optable::_data(ratioAll) 0
598  } else {
599  set ::optable::_data(ratioAll) \
600  [expr {int(double([lindex $r 1]) / double([lindex $r 0]))}]
601  }
602  foreach {start end} {1800 1899 1900 1949 1950 1969 1970 1979
603  1980 1989 1990 1999 2000 2009} {
604  set r [sc_filter freq [sc_base current] tree date $start.00.00 $end.12.31]
605  set filter [lindex $r 0]
606  set all [lindex $r 1]
607  if {$filter == 0} {
608  set ::optable::_data(range$start) "---"
609  } else {
610  set ::optable::_data(range$start) \
611  [expr {int(double($all) / double($filter))}]
612  }
613  }
614  foreach y {1 5 10} {
615  set year "[expr [::utils::date::today year]-$y]"
616  append year ".[::utils::date::today month].[::utils::date::today day]"
617  set r [sc_filter freq [sc_base current] tree date $year]
618  set filter [lindex $r 0]
619  set all [lindex $r 1]
620  if {$filter == 0} {
621  set ::optable::_data(ratio$y) 0
622  } else {
623  set ::optable::_data(ratio$y) \
624  [expr {int(double($all) / double($filter))}]
625  }
626  if {$::optable::_data(ratio$y) == 0} {
627  set r 1.0
628  } else {
629  set r [expr {double($::optable::_data(ratioAll))}]
630  set r [expr {$r / double($::optable::_data(ratio$y))}]
631  }
632  set ::optable::_data(delta$y) [expr {int(($r - 1.0) * 100.0 + 0.5)}]
633  }
634 }
635 
636 proc ::optable::_percent {x fmt} {
637  set p "%"
638  if {$fmt == "latex"} { set p "\\%"}
639  return "[expr $x / 10][sc_info decimal][expr $x % 10]$p"
640 }
641 
642 proc ::optable::results {reportType fmt} {
643  set s {}
644  set n "\n"; set next " "; set p "%"
645  set white "1-0"; set draw "=-="; set black "0-1"
646 
647  if {$fmt == "latex"} {
648  set next " & "; set n "\\\\\n"; set p "\\%"
649  set white "\\win"; set draw "\\draw"; set black "\\loss"
650  append s "\\begin{tabular}{lccccccc}\n"
651  }
652 
653  if {$fmt == "html"} { append s "<pre>\n"}
654  if {$fmt == "ctext"} { append s "<tt>"}
655  if {$fmt == "latex"} { append s "\\hline\n"}
656 
657  set lenReport [string length $::tr(OprepReportGames)]
658  set lenAll [string length $::tr(OprepAllGames)]
659  set len [expr {($lenReport > $lenAll) ? $lenReport : $lenAll}]
660  set score [::utils::string::Capital $::tr(score)]
661  set slen [string length $score]
662  if {$slen < 7} { set slen 7}
663 
664  append s " [::utils::string::Pad {} $len] $next"
665  append s "[::utils::string::PadRight $score $slen] $next"
666  if {$fmt == "latex"} {
667  append s "\\multicolumn{3}{c}{$::tr(OprepLength)} & "
668  append s "\\multicolumn{3}{c}{$::tr(OprepFrequency)} $n "
669  } else {
670  append s "[::utils::string::PadCenter $::tr(OprepLength) 19] $next"
671  append s "[::utils::string::PadCenter $::tr(OprepFrequency) 22] $n"
672  }
673 
674  append s " [::utils::string::Pad {} $len] $next"
675  append s "[::utils::string::PadRight {} $slen] $next"
676  append s "[::utils::string::PadRight $white 5] $next"
677  append s "[::utils::string::PadRight $draw 5] $next"
678  append s "[::utils::string::PadRight $black 5] $next"
679  append s "[::utils::string::PadRight $white 5] $next"
680  append s "[::utils::string::PadRight $draw 5] $next"
681  append s "[::utils::string::PadRight $black 5] $n"
682  if {$fmt == "latex"} { append s "\\hline\n"}
683 
684  set sc [sc_report $reportType score]
685  set wlen [sc_report $reportType avgLength 1]
686  set dlen [sc_report $reportType avgLength =]
687  set blen [sc_report $reportType avgLength 0]
688  set wf [sc_report $reportType freq 1]
689  set df [sc_report $reportType freq =]
690  set bf [sc_report $reportType freq 0]
691 
692  append s " [::utils::string::Pad $::tr(OprepReportGames) $len] $next"
693  append s "[::utils::string::PadRight [::optable::_percent [lindex $sc 0] $fmt] $slen] $next"
694  append s "[::utils::string::PadRight [lindex $wlen 0] 5] $next"
695  append s "[::utils::string::PadRight [lindex $dlen 0] 5] $next"
696  append s "[::utils::string::PadRight [lindex $blen 0] 5] $next"
697  append s "[::utils::string::PadRight [::optable::_percent [lindex $wf 0] $fmt] 6] $next"
698  append s "[::utils::string::PadRight [::optable::_percent [lindex $df 0] $fmt] 6] $next"
699  append s "[::utils::string::PadRight [::optable::_percent [lindex $bf 0] $fmt] 6] $n"
700 
701  append s " [::utils::string::Pad $::tr(OprepAllGames) $len] $next"
702  append s "[::utils::string::PadRight [::optable::_percent [lindex $sc 1] $fmt] $slen] $next"
703  append s "[::utils::string::PadRight [lindex $wlen 1] 5] $next"
704  append s "[::utils::string::PadRight [lindex $dlen 1] 5] $next"
705  append s "[::utils::string::PadRight [lindex $blen 1] 5] $next"
706  append s "[::utils::string::PadRight [::optable::_percent [lindex $wf 1] $fmt] 6] $next"
707  append s "[::utils::string::PadRight [::optable::_percent [lindex $df 1] $fmt] 6] $next"
708  append s "[::utils::string::PadRight [::optable::_percent [lindex $bf 1] $fmt] 6] $n"
709 
710  if {$fmt == "latex"} { append s "\\hline\n\\end{tabular}\n"}
711  if {$fmt == "html"} { append s "</pre>\n"}
712  if {$fmt == "ctext"} { append s "</tt>"}
713 
714  return $s
715 }
716 
717 proc ::optable::stats {fmt} {
718  global stats
719  set s {}
720  set all $::tr(OprepStatAll)
721  set both $::tr(OprepStatBoth)
722  set since $::tr(OprepStatSince)
723  set games [::utils::string::Capital $::tr(games)]
724  set score [::utils::string::Capital $::tr(score)]
725 
726  set alen [string length $all]
727  set blen [expr {[string length $both] + 6}]
728  set slen [expr {[string length $since] + 11}]
729  set len $alen
730  if {$len < $blen} { set len $blen}
731  if {$len < $slen} { set len $slen}
732 
733  set ratings 0
734  set years 0
735  set rlist [lsort -decreasing [array names stats r*]]
736  set ylist [lsort [array names stats y*]]
737  foreach i $rlist { if {$stats($i)} { set ratings 1}}
738  foreach i $ylist { if {$stats($i)} { set years 1}}
739 
740  if {$fmt == "latex"} {
741  append s "\\begin{tabular}{l r r r r r @{.} l}\n\\hline\n"
742  append s " & $games & \\win & \\draw & \\loss & "
743  append s "\\multicolumn{2}{c}{$score} \\tspace \\\\ \\hline \n"
744  scan [sc_filter stats all] "%u%u%u%u%u%\[.,\]%u" g w d l p c x
745  append s "$all & $g & $w & $d & $l & $p&$x\\% \\\\\n"
746 
747  if {$ratings} {
748  append s "\\hline\n"
749  foreach i $rlist {
750  if {$stats($i)} {
751  set elo [string range $i 1 end]
752  scan [sc_filter stats elo $elo] "%u%u%u%u%u%\[.,\]%u" g w d l p c x
753  append s "$both $elo+ & $g & $w & $d & $l & $p&$x\\% \\\\\n"
754  }
755  }
756  }
757  if {$years} {
758  append s "\\hline\n"
759  foreach i $ylist {
760  if {$stats($i)} {
761  set year [string range $i 1 end]
762  scan [sc_filter stats year $year] "%u%u%u%u%u%\[.,\]%u" g w d l p c x
763  append s "$since $year.01.01 & $g & $w & $d & $l & $p&$x\\% \\\\\n"
764  }
765  }
766  }
767  append s "\\hline\n\\end{tabular}\n"
768  return $s
769  }
770 
771  # For non-LaTeX format, just display in plain text:
772  if {$fmt == "html"} { append s "<pre>\n"}
773  if {$fmt == "ctext"} { append s "<tt>"}
774  set stat ""
775  append s " [::utils::string::Pad $stat [expr $len - 4]] [::utils::string::PadRight $games 10]"
776  append s " 1-0 =-= 0-1 [::utils::string::PadRight $score 8]\n"
777  append s "-----------------------------------------------------------"
778  append s "\n [::utils::string::Pad $all $len]" [sc_filter stats all]
779 
780  if {$ratings} {
781  append s "\n"
782  foreach i $rlist {
783  if {$stats($i)} {
784  set elo [string range $i 1 end]
785  set stat "$both $elo+"
786  append s "\n [::utils::string::Pad $stat $len]" [sc_filter stats elo $elo]
787  }
788  }
789  }
790  if {$years} {
791  append s "\n"
792  foreach i $ylist {
793  if {$stats($i)} {
794  set year [string range $i 1 end]
795  set stat "$since $year.01.01"
796  append s "\n [::utils::string::Pad $stat $len]" [sc_filter stats year $year]
797  }
798  }
799  }
800  append s "\n-----------------------------------------------------------\n"
801  if {$fmt == "html"} { append s "</pre>\n"}
802  if {$fmt == "ctext"} { append s "</tt>"}
803  return $s
804 }
805 
806 proc ::optable::_reset {} {
807  set ::optable::_data(sec) 0
808  set ::optable::_data(subsec) 0
809 }
810 
811 proc ::optable::_title {} {
812  set fmt $::optable::_data(fmt)
813  set title $::tr(OprepTitle)
814  if {$fmt == "latex"} {
815  return "\\begin{center}{\\LARGE \\bf $title}\\end{center}\n\n"
816  } elseif {$fmt == "html"} {
817  return "<h1><center>$title</center></h1>\n\n"
818  } elseif {$fmt == "ctext"} {
819  return "<h1><center>$title</center></h1>\n\n"
820  }
821  set r "--------------------------------------------------------------"
822  append r "\n [string toupper $title]\n"
823  append r "--------------------------------------------------------------"
824  append r "\n\n"
825  return $r
826 }
827 
828 proc ::optable::_sec {text} {
829  set fmt $::optable::_data(fmt)
830  incr ::optable::_data(sec)
831  set ::optable::_data(subsec) 0
832  if {$fmt == "latex"} {
833  return "\n\n\\section{$text}\n"
834  } elseif {$fmt == "html"} {
835  return "\n<h2>$::optable::_data(sec). $text</h2>\n"
836  } elseif {$fmt == "ctext"} {
837  return "<h4>$::optable::_data(sec). $text</h4>"
838  }
839  set line "$::optable::_data(sec). [string toupper $text]"
840  set underline "-----------------------------------------------------"
841  return "\n\n$line\n[string range $underline 1 [string length $line]]\n"
842 }
843 
844 proc ::optable::_subsec {text} {
845  set fmt $::optable::_data(fmt)
846  incr ::optable::_data(subsec)
847  if {$fmt == "latex"} {
848  return "\n\\subsection{$text}\n\n"
849  } elseif {$fmt == "html"} {
850  return "\n<h3>$::optable::_data(sec).$::optable::_data(subsec) $text</h3>\n\n"
851  } elseif {$fmt == "ctext"} {
852  return "\n<maroon><b>$::optable::_data(sec).$::optable::_data(subsec) $text</b></maroon>\n\n"
853  }
854  return "\n$::optable::_data(sec).$::optable::_data(subsec) $text\n\n"
855 }
856 ################################################################################
857 # report:
858 # Produces a report in the appropriate format. If "withTable" is true,
859 # the theory table is also included.
860 ################################################################################
861 proc ::optable::report {fmt withTable {flipPos 0}} {
862  global tr
863  sc_report opening format $fmt
864  set fmt [string tolower $fmt]
865  set ::optable::_data(fmt) $fmt
867 
868  # numRows: the number of rows to show in the theory table.
869  # If it is zero, the number of rows if decided according to the
870  # number of games in the report.
871  set numRows 0
872 
873  # Specify whether a theory table is to be printed, so note numbers
874  # can be generated and displayed if necessary:
875  sc_report opening notes $withTable $numRows
876 
877  set n "\n"; set p "\n\n"; set preText ""; set postText ""
878  set percent "%"; set bullet " * "
879  if {$fmt == "latex"} {
880  set n "\\\\\n"; set p "\n\n"
881  #set preText "{\\samepage\\begin{verbatim}\n"
882  #set postText "\\end{verbatim}\n}\n"
883  set percent "\\%"; set bullet "\\hspace{0.5cm}\$\\bullet\$"
884  } elseif {$fmt == "html"} {
885  set n "<br>\n"; set p "<p>\n\n"
886  set preText "<pre>\n"; set postText "</pre>\n"
887  } elseif {$fmt == "ctext"} {
888  set preText "<tt>"; set postText "</tt>"
889  }
890 
891  # Generate the report:
892  set games $tr(games)
893  set moves $tr(moves)
894  set counts [sc_report opening count]
895  set rgames [lindex $counts 0]
896  set tgames [lindex $counts 1]
897 
898  set r {}
899  append r $::optable::_docStart($fmt)
900  set title $::tr(OprepTitle)
901  set r [string map [list "\[OprepTitle\]" $title] $r]
902  append r [::optable::_title]
903  append r "$tr(Database): [file tail [sc_base filename $::curr_db]] "
904  append r "([::utils::thousands [sc_base numGames $::curr_db]] $games)$n"
905  append r "$tr(OprepReport): [::trans [sc_report opening line]] ("
906  if {$fmt == "ctext"} {
907  append r "<darkblue><run sc_report opening select all 0; ::windows::stats::Refresh>"
908  }
909  append r "$rgames"
910  if {$fmt == "ctext"} { append r "</run></darkblue>"; }
911  append r " $games)$n"
912  set eco [sc_report opening eco]
913  if {$eco != ""} {
914  append r "$tr(ECO): $eco$n"
915  }
916 
917  append r "$::tr(OprepGenerated) Scid $::scidVersion, [::utils::date::today]\n"
918  if {$fmt == "latex"} {
919  if {$flipPos} {
920  append r $::optable::_data(bdLaTeX_flip)
921  } else {
922  append r $::optable::_data(bdLaTeX)
923  }
924  append r {$$\showboard$$}
925  } elseif {$fmt == "html"} {
926  if {$flipPos} {
927  append r $::optable::_data(bdHTML_flip)
928  } else {
929  append r $::optable::_data(bdHTML)
930  }
931  } elseif {$fmt == "ctext"} {
932  append r "\n<center><window .oprepWin.text.bd></center>\n"
933  }
934  if {$rgames == 0} {
935  append r $::optable::_docEnd($fmt)
936  return $r
937  }
938 
939  if {$::optable(Stats) > 0 ||
940  $::optable(Oldest) > 0 ||
941  $::optable(Newest) > 0 ||
942  $::optable(Popular) > 0 ||
943  ($::optable(MostFrequent) > 0 &&
944  ($::optable(MostFrequentWhite) || $::optable(MostFrequentBlack)))} {
945  append r [::optable::_sec $tr(OprepStatsHist)]
946  }
947  if {$::optable(Stats)} {
948  append r [::optable::_subsec $tr(OprepStats)]
949  append r [::optable::stats $fmt]
950  }
951  if {$::optable(Oldest) > 0} {
952  append r [::optable::_subsec $tr(OprepOldest)]
953  append r [sc_report opening best o $::optable(Oldest)]
954  }
955  if {$::optable(Newest) > 0} {
956  append r [::optable::_subsec $tr(OprepNewest)]
957  append r [sc_report opening best n $::optable(Newest)]
958  }
959 
960  if {$::optable(Popular) > 0} {
961  append r [::optable::_subsec $tr(OprepPopular)]
962  set next ""
963  if {$fmt == "latex"} { set next " & "}
964 
965  # A table showing popularity by year ranges:
966  if {$fmt == "latex"} {
967  append r "\\begin{tabular}{lccccccc}\n\\hline\n"
968  } else {
969  append r $preText
970  }
971 
972  set sYear $tr(Year)
973  set sEvery [::utils::string::Capital $tr(OprepEvery)]
974  regsub "%u" $sEvery X sEvery
975  set len [string length $sYear]
976  if {[string length $sEvery] > $len} { set len [string length $sEvery]}
977  append r [::utils::string::Pad $tr(Year) $len]
978  foreach range {1800-99 1900-49 1950-69 1970-79 1980-89 1990-99 2000-09} {
979  append r $next
980  append r [::utils::string::PadCenter $range 8]
981  }
982 
983  append r $n
984  append r [::utils::string::Pad $sEvery $len]
985  foreach y {1800 1900 1950 1970 1980 1990 2000} {
986  append r $next
987  append r [::utils::string::PadCenter $::optable::_data(range$y) 8]
988  }
989  append r $n
990  if {$fmt == "latex"} {
991  append r "\\hline\n\\end{tabular}\n"
992  } else {
993  append r $postText
994  }
995 
996  append r "\n"
997 
998  # A table showing popularity in the last 1/5/10 years:
999  if {$fmt == "latex"} {
1000  append r "\\begin{tabular}{lrr}\n"
1001  }
1002 
1003  foreach y {All 10 5 1} {
1004  if {$fmt == "ctext"} { append r "<tt>"}
1005  append r $tr(OprepFreq$y)
1006  if {$fmt == "ctext"} { append r "</tt>"}
1007  append r $next
1008  append r [format $tr(OprepEvery) $::optable::_data(ratio$y)]
1009  if {$y != "All"} {
1010  append r $next
1011  set d $::optable::_data(delta$y)
1012  if {$d > 0} {
1013  append r " ([format $tr(OprepUp) $d $percent])"
1014  } elseif {$d < 0} {
1015  append r " ([format $tr(OprepDown) [expr 0- $d] $percent])"
1016  } else {
1017  append r " ($tr(OprepSame))"
1018  }
1019  }
1020  append r "$n"
1021  }
1022  if {$fmt == "latex"} {
1023  append r "\\end{tabular}\n"
1024  }
1025  }
1026 
1027  if {$::optable(MostFrequent) > 0 && $::optable(MostFrequentWhite)} {
1028  append r [::optable::_subsec "$tr(OprepMostFrequent) ($tr(White))"]
1029  append r [sc_report opening players white $::optable(MostFrequent)]
1030  }
1031  if {$::optable(MostFrequent) > 0 && $::optable(MostFrequentBlack)} {
1032  append r [::optable::_subsec "$tr(OprepMostFrequent) ($tr(Black))"]
1033  append r [sc_report opening players black $::optable(MostFrequent)]
1034  }
1035 
1036  if {$::optable(AvgPerf) || $::optable(HighRating)} {
1037  append r [::optable::_sec $tr(OprepRatingsPerf)]
1038  }
1039  if {$::optable(AvgPerf)} {
1040  append r [::optable::_subsec $tr(OprepAvgPerf)]
1041  set e [sc_report opening elo white]
1042  set welo [lindex $e 0]; set wng [lindex $e 1]
1043  set bpct [lindex $e 2]; set bperf [lindex $e 3]
1044  set e [sc_report opening elo black]
1045  set belo [lindex $e 0]; set bng [lindex $e 1]
1046  set wpct [lindex $e 2]; set wperf [lindex $e 3]
1047  append r "$tr(OprepWRating): $welo ($wng $games); "
1048  append r "$tr(OprepWPerf): $wperf ($wpct$percent vs $belo)$n"
1049  append r "$tr(OprepBRating): $belo ($bng $games); "
1050  append r "$tr(OprepBPerf): $bperf ($bpct$percent vs $welo)$n"
1051  }
1052 
1053  if {$::optable(HighRating) > 0} {
1054  append r [::optable::_subsec $tr(OprepHighRating)]
1055  append r [sc_report opening best a $::optable(HighRating)]
1056  }
1057 
1058  if {$::optable(Results) ||
1059  ($::optable(Shortest) > 0 &&
1060  ($::optable(ShortestBlack) || $::optable(ShortestBlack)))} {
1061  append r [::optable::_sec $tr(OprepTrends)]
1062  }
1063 
1064  if {$::optable(Results)} {
1065  append r [::optable::_subsec $::tr(OprepResults)]
1066  append r [::optable::results opening $fmt]
1067  }
1068 
1069  if {$::optable(Shortest) > 0 && $::optable(ShortestWhite)} {
1070  append r [::optable::_subsec "$tr(OprepShortest) ($tr(White))"]
1071  append r [sc_report opening best w $::optable(Shortest)]
1072  }
1073  if {$::optable(Shortest) > 0 && $::optable(ShortestBlack)} {
1074  append r [::optable::_subsec "$tr(OprepShortest) ($tr(Black))"]
1075  append r [sc_report opening best b $::optable(Shortest)]
1076  }
1077 
1078  if {$::optable(MoveOrders) > 0 ||
1079  $::optable(MovesFrom) > 0 ||
1080  $::optable(Themes) > 0 ||
1081  $::optable(Endgames) > 0} {
1082  append r [::optable::_sec $tr(OprepMovesThemes)]
1083  }
1084  if {$::optable(MoveOrders) > 0} {
1085  append r [::optable::_subsec $tr(OprepMoveOrders)]
1086  set nOrders [sc_report opening moveOrders 0]
1087  set maxOrders $::optable(MoveOrders)
1088  if {$nOrders == 1} {
1089  append r $tr(OprepMoveOrdersOne)
1090  } elseif {$nOrders <= $maxOrders} {
1091  append r [format $tr(OprepMoveOrdersAll) $nOrders]
1092  } else {
1093  append r [format $tr(OprepMoveOrdersMany) $nOrders $maxOrders]
1094  }
1095  append r $n
1096  append r [::trans [sc_report opening moveOrders $maxOrders]]
1097  }
1098  if {$::optable(MovesFrom)} {
1099  append r [::optable::_subsec $tr(OprepMovesFrom)]
1100  if {$fmt == "latex"} {
1101  append r $::optable::_data(latexTree)
1102  } else {
1103  append r $preText
1104  append r $::optable::_data(tree)
1105  append r $postText
1106  }
1107  }
1108 
1109  if {$::optable(Themes) > 0} {
1110  append r [::optable::_subsec $tr(OprepThemes)]
1111  append r [sc_report opening themes $tr(OprepThemeDescription:) \
1112  $tr(OprepThemeSameCastling:) $tr(OprepThemeOppCastling:) \
1113  $tr(OprepThemeKPawnStorm:) $tr(OprepThemeQueenswap:) \
1114  $tr(OprepTheme1BishopPair:) \
1115  $tr(OprepThemeWIQP:) $tr(OprepThemeBIQP:) \
1116  $tr(OprepThemeWP567:) $tr(OprepThemeBP234:) \
1117  $tr(OprepThemeOpenCDE:)]
1118  }
1119 
1120  if {$::optable(Endgames) > 0} {
1121  append r [::optable::_subsec $tr(OprepEndgames)]
1122  append r "$tr(OprepEndClass:)$n"
1123  append r [sc_report opening endmat]
1124  }
1125 
1126  if {$withTable && $::optable(MaxGames) > 0} {
1127  set sec [::optable::_sec $tr(OprepTheoryTable)]
1128  set comment ""
1129  if {$tgames > $::optable(MaxGames)} {
1130  set comment [format $tr(OprepTableComment) $::optable(MaxGames)]
1131  }
1132  append r [sc_report opening print $numRows $sec $comment]
1133  # puts [sc_report opening print $numRows $sec $comment]
1134  }
1135 
1136  append r $::optable::_docEnd($fmt)
1137 
1138  # Eszet (ss) characters seem to be mishandled by LaTeX, even with
1139  # the font encoding package, so convert them explicitly:
1140  if {$fmt == "latex"} { regsub -all ß $r {{\\ss}} r}
1141 
1142  return $r
1143 }
1144 
1145 # table:
1146 # Produces only the ECO table, not any other part of the report.
1147 #
1148 proc ::optable::table {fmt} {
1149  sc_report opening format $fmt
1150  set ::optable::_data(fmt) $fmt
1151  set r {}
1152  append r $::optable::_docStart($fmt)
1153  set r [string map [list "\[OprepTitle\]" $::tr(OprepTitle)] $r]
1154  append r [sc_report opening print]
1155  append r $::optable::_docEnd($fmt)
1156  return $r
1157 }
1158 
1159 
1160 set reportFavorites {}
1161 
1162 # updateFavoritesMenu
1163 # Update the Favorites menu in the report window, adding a
1164 # command for each favorite report position.
1165 #
1166 proc ::optable::updateFavoritesMenu {} {
1167  set m .oprepWin.menu.favorites
1168  $m delete 3 end
1169  $m add separator
1170  foreach entry $::reportFavorites {
1171  set name [lindex $entry 0]
1172  set moves [lindex $entry 1]
1173  $m add command -label $name \
1174  -command "importMoveList [list $moves]; ::optable::makeReportWin"
1175  }
1176  if {[llength $::reportFavorites] == 0} {
1177  $m entryconfigure 1 -state disabled
1178  $m entryconfigure 2 -state disabled
1179  } else {
1180  $m entryconfigure 1 -state normal
1181  $m entryconfigure 2 -state normal
1182  }
1183 }
1184 
1185 # favoriteReportNames
1186 # Return a list of the favorite report names.
1187 #
1188 proc ::optable::favoriteReportNames {} {
1189  set reportNames {}
1190  foreach entry $::reportFavorites {
1191  lappend reportNames [lindex $entry 0]
1192  }
1193  return $reportNames
1194 }
1195 
1196 # addFavoriteDlg
1197 # Adds the current position to the opening report favorites list.
1198 #
1199 proc ::optable::addFavoriteDlg {} {
1200  set w .addFavoriteDlg
1201  toplevel $w
1202  wm title $w "Scid: Add Opening Report Favorite"
1203  label $w.name -text "Enter a name for the opening report of this position:"
1204  pack $w.name -side top
1205  # label $w.name2 -text "(Use letters, digits, spaces and underscores only)"
1206  # pack $w.name2 -side top
1207  entry $w.e -width 40
1208  pack $w.e -side top -fill x -padx 2
1210  label $w.old -text "Existing favorite report names:"
1211  pack $w.old -side top
1212  pack [frame $w.existing] -side top -fill x -padx 2
1213  text $w.existing.list -width 30 -height 10 -background gray90 \
1214  -yscrollcommand [list $w.existing.ybar set]
1215  scrollbar $w.existing.ybar -command [list $w.existing.list yview]
1216  pack $w.existing.ybar -side right -fill y
1217  pack $w.existing.list -side left -fill both -expand yes
1218  foreach entry $::reportFavorites {
1219  $w.existing.list insert end "[lindex $entry 0]\n"
1220  }
1221  $w.existing.list configure -state disabled
1223  frame $w.b
1224  pack $w.b -side bottom -fill x
1225  button $w.b.ok -text OK -command ::optable::addFavoriteOK
1226  button $w.b.cancel -text $::tr(Cancel) -command "grab release $w; destroy $w"
1227  pack $w.b.cancel $w.b.ok -side right -padx 5 -pady 5
1228  focus $w.e
1229  grab $w
1230 }
1231 
1232 proc ::optable::addFavoriteOK {} {
1233  global reportFavorites
1234  set w .addFavoriteDlg
1235  set reportName [$w.e get]
1236  set err ""
1237  if {$reportName == ""} {
1238  set err "The report name must not be empty."
1239  } elseif {[lsearch -exact [::optable::favoriteReportNames] $reportName] >= 0} {
1240  set err "That name is already used for another favorite report position."
1241  } else {
1242  lappend reportFavorites [list $reportName [sc_game moves]]
1245  grab release $w
1246  destroy $w
1247  return
1248  }
1249  tk_messageBox -title Scid -icon info -type ok -message $err
1250 }
1251 
1252 set reportFavoritesName ""
1253 
1254 # editFavoritesDlg
1255 # Open the dialog box for editing the list of opening report
1256 # favorite positions.
1257 #
1258 proc ::optable::editFavoritesDlg {} {
1259  global reportFavorites reportFavoritesTemp reportFavoritesName
1260  set w .editFavoritesDlg
1261  if {[winfo exists $w]} { return}
1262 
1263  set ::reportFavoritesTemp $::reportFavorites
1264  toplevel $w
1265  wm title $w "Scid: [tr OprepFavoritesEdit]"
1266  # wm transient $w .
1267  bind $w <F1> {helpWindow Reports Opening}
1268  entry $w.e -width 60 -foreground black -background white \
1269  -textvariable reportFavoritesName -font font_Small -exportselection 0
1270  bind $w.e <FocusIn> "$w.e configure -background lightYellow"
1271  bind $w.e <FocusOut> "$w.e configure -background white"
1272 
1273  trace variable reportFavoritesName w ::optable::editFavoritesRefresh
1274  pack $w.e -side top -fill x
1275  pack [frame $w.b] -side bottom -fill x
1276  autoscrollframe $w.f listbox $w.f.list -width 50 -height 10 \
1277  -fg black -bg white -exportselection 0 -font font_Small -setgrid 1
1278  pack $w.f -side top -fill both -expand yes
1279  bind $w.f.list <<ListboxSelect>> ::optable::editFavoritesSelect
1280  foreach entry $::reportFavoritesTemp {
1281  set name [lindex $entry 0]
1282  set moves [lindex $entry 1]
1283  $w.f.list insert end "$name \[$moves\]"
1284  }
1285  button $w.b.delete -text $::tr(Delete) -command ::optable::editFavoritesDelete
1286  button $w.b.up -image tb_up -command {::optable::editFavoritesMove up}
1287  button $w.b.down -image tb_down -command {::optable::editFavoritesMove down}
1288  foreach i [list $w.b.up $w.b.down] {
1289  $i configure -padx 0 -pady 0 -borderwidth 1
1290  }
1291  button $w.b.ok -text "OK" -command ::optable::editFavoritesOK
1292  button $w.b.cancel -text "Cancel" -command {
1293  catch {grab release .editFavoritesDlg}
1294  destroy .editFavoritesDlg
1295  }
1296  pack $w.b.delete $w.b.up $w.b.down -side left -padx 2 -pady 2
1297  pack $w.b.cancel $w.b.ok -side right -padx 2 -pady 2
1298  set editFavoritesName ""
1299 
1300  wm withdraw $w
1301  update idletasks
1302  set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
1303  - [winfo vrootx .]}]
1304  set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
1305  - [winfo vrooty .]}]
1306  wm geom $w +$x+$y
1307  wm protocol $w WM_DELETE_WINDOW [list $w.b.cancel invoke]
1308  wm deiconify $w
1309  update
1310  catch {grab $w}
1311 }
1312 
1313 proc ::optable::editFavoritesRefresh {args} {
1314  global reportFavoritesTemp reportFavoritesName
1315  set list .editFavoritesDlg.f.list
1316  set sel [lindex [$list curselection] 0]
1317  if {$sel == ""} { return}
1318  set name $reportFavoritesName
1319  set e [lindex $reportFavoritesTemp $sel]
1320  set moves [lindex $e 1]
1321  set e [lreplace $e 0 0 $name]
1322  set reportFavoritesTemp [lreplace $reportFavoritesTemp $sel $sel $e]
1323  $list insert $sel "$name \[$moves\]"
1324  $list delete [expr $sel + 1]
1325  $list selection clear 0 end
1326  $list selection set $sel
1327 }
1328 
1329 proc ::optable::editFavoritesSelect {} {
1330  set list .editFavoritesDlg.f.list
1331  set sel [lindex [$list curselection] 0]
1332  if {$sel == ""} {
1333  set ::reportFavoritesName ""
1334  return
1335  }
1336  if {$sel >= [llength $::reportFavoritesTemp]} {
1337  $list selection clear 0 end
1338  set ::reportFavoritesName ""
1339  return
1340  }
1341  set e [lindex $::reportFavoritesTemp $sel]
1342  set ::reportFavoritesName [lindex $e 0]
1343 }
1344 
1345 proc ::optable::editFavoritesDelete {} {
1346  global reportFavoritesTemp
1347  set w .editFavoritesDlg
1348  set list $w.f.list
1349  set sel [lindex [$list curselection] 0]
1350  if {$sel == ""} { return}
1351  set reportFavoritesTemp [lreplace $reportFavoritesTemp $sel $sel]
1352  $list selection clear 0 end
1353  $list delete $sel
1354  set ::reportFavoritesName ""
1355 
1356 }
1357 
1358 proc ::optable::editFavoritesMove {dir} {
1359  global reportFavoritesTemp
1360  set w .editFavoritesDlg
1361  set list $w.f.list
1362  set sel [lindex [$list curselection] 0]
1363  if {$sel == ""} { return}
1364  set e [lindex $reportFavoritesTemp $sel]
1365  set name [lindex $e 0]
1366  set moves [lindex $e 1]
1367  set text "$name \[$moves\]"
1368 
1369  set newsel $sel
1370  if {$dir == "up"} {
1371  incr newsel -1
1372  if {$newsel < 0} { return}
1373  } else {
1374  incr newsel
1375  if {$newsel >= [$list index end]} { return}
1376  }
1377  set reportFavoritesTemp [lreplace $reportFavoritesTemp $sel $sel]
1378  set reportFavoritesTemp [linsert $reportFavoritesTemp $newsel $e]
1379  $list selection clear 0 end
1380  $list delete $sel
1381  $list insert $newsel $text
1382  $list selection set $newsel
1383 }
1384 
1385 proc ::optable::editFavoritesOK {} {
1386  set w .editFavoritesDlg
1387  catch {grab release $w}
1388  destroy $w
1389  set ::reportFavorites $::reportFavoritesTemp
1392 }
1393 
1394 proc ::optable::favoritesFilename {} {
1395  return [scidConfigFile reports]
1396 }
1397 
1398 proc ::optable::saveFavorites {} {
1399  set fname [::optable::favoritesFilename]
1400  if {[catch {open $fname w} f]} {
1401  # tk_messageBox ...
1402  return
1403  }
1404  puts $f "# Scid opening report favorites file"
1405  puts $f ""
1406  puts $f "set reportFavorites [list $::reportFavorites]"
1407  close $f
1408 }
1409 
1410 proc ::optable::loadFavorites {} {
1411  global reportFavorites
1412  set fname [::optable::favoritesFilename]
1413  catch {source $fname}
1414 }
1415 
1417 
1418 set reportFormat html
1419 set reportType full
1420 
1421 proc ::optable::generateFavoriteReports {} {
1422  global reportFavorites
1423  if {[llength $reportFavorites] == 0} {
1424  tk_messageBox -title "Scid" -type ok -icon info \
1425  -message "You have no favorite report positions."
1426  return
1427  }
1428  set ::reportDir $::initialDir(report)
1429 
1430  set w .reportFavoritesDlg
1431  if {[winfo exists $w]} { return}
1432  toplevel $w
1433  wm title $w "Scid: Generate Reports..."
1434  pack [label $w.typelabel -text "Select the report type:" -font font_Bold] -side top
1435  pack [frame $w.type] -side top -padx 2
1436  radiobutton $w.type.full -text "Full" -variable reportType -value full
1437  radiobutton $w.type.compact -text "Compact (no theory table)" -variable reportType -value compact
1438  radiobutton $w.type.theory -text "Theory table only" -variable reportType -value theory
1439  pack $w.type.full $w.type.compact $w.type.theory -side left -padx 4
1441  pack [label $w.fmtlabel -text "Select the report file format:" -font font_Bold] -side top
1442  pack [frame $w.fmt] -side top -padx 2
1443  radiobutton $w.fmt.text -text "Plain text (.txt)" -variable reportFormat -value text
1444  radiobutton $w.fmt.html -text "HTML" -variable reportFormat -value html
1445  radiobutton $w.fmt.latex -text "LaTeX" -variable reportFormat -value latex
1446  pack $w.fmt.text $w.fmt.html $w.fmt.latex -side left -padx 4
1448  pack [frame $w.dir] -side top -padx 2 -pady 2
1449  label $w.dir.label -text "Save reports in the folder: " -font font_Bold
1450  entry $w.dir.entry -background white -textvariable ::reportDir
1451  button $w.dir.choose -text $::tr(Browse...) -command {
1452  set tmpdir [tk_chooseDirectory -parent .reportFavoritesDlg \
1453  -title "Scid: Choose Report Folder"]
1454  if {$tmpdir != ""} {
1455  set ::reportDir [file nativename $tmpdir]
1456  }
1457  }
1458  pack $w.dir.label -side left
1459  pack $w.dir.choose -side right
1460  pack $w.dir.entry -side left -fill x
1462  pack [frame $w.b] -side bottom -fill x
1463  button $w.b.ok -text "OK"\
1464  -command "::optable::reportFavoritesOK; grab release $w; destroy $w; ::optable::makeReportWin"
1465  button $w.b.cancel -text $::tr(Cancel) -command "grab release $w; destroy $w"
1466  pack $w.b.cancel $w.b.ok -side right -padx 5 -pady 5
1467  grab $w
1468 }
1469 
1470 proc ::optable::reportFavoritesOK {} {
1471  global reportDir reportFormat reportType
1472  set ::initialDir(report) $reportDir
1473  set fmt $reportFormat
1474  switch $reportFormat {
1475  "html" { set suffix ".html"}
1476  "text" { set suffix ".txt"}
1477  "latex" { set suffix "tex"}
1478  }
1479 
1480  set w .reportsProgress
1481  toplevel $w
1482  wm withdraw $w
1483  wm title $w "Scid: Generating Reports"
1484  bind $w <Visibility> "raiseWin $w"
1485  pack [label $w.t -width 40 -text "Generating reports. Please wait..." -font font_Bold] -side top -pady 5
1486  pack [label $w.report] -side top -pady 5
1488  wm deiconify $w
1489  grab $w
1490  update
1491 
1492  set count 0
1493  set total [llength $::reportFavorites]
1494  foreach entry $::reportFavorites {
1495  set name [lindex $entry 0]
1496  set moves [lindex $entry 1]
1497  set fname [file join $reportDir "$name$suffix"]
1498  if {[catch {open $fname w} f]} {
1499  tk_messageBox -title "Scid" -icon warning -type ok \
1500  -message "Unable to write file: $fname\n$f"
1501  grab release $w
1502  destroy $w
1503  return
1504  }
1505  incr count
1506  $w.report configure -text "$count / $total: $name$suffix"
1507  update
1508  sc_game push
1509  sc_move addSan $moves
1510  ::optable::makeReportWin -nodisplay -noprogress
1511  if {$reportType == "theory"} {
1512  set report [::optable::table $fmt]
1513  } elseif {$reportType == "compact"} {
1514  set report [::optable::report $fmt 0 $::optable::_flip]
1515  } else {
1516  set report [::optable::report $fmt 1 $::optable::_flip]
1517  }
1518  if {$::hasEncoding && $::langEncoding($::language) != ""} {
1519  catch {set report [encoding convertto $::langEncoding($::language) $report]}
1520  }
1521  sc_game pop
1522  puts $f $report
1523  close $f
1524  }
1525  grab release $w
1526  destroy $w
1527 }
1528 
1529 # end of optable.tcl