Scid  4.6.5
preport.tcl
Go to the documentation of this file.
1 # preport.tcl: Player reports.
2 # Part of Scid. Copyright 2003 Shane Hudson
3 
4 namespace eval ::preport {}
5 array set ::preport::_data {}
6 
7 set preport(MaxGames) 400
8 
9 set ::preport::_player ""
10 set ::preport::_color white
11 set ::preport::_pos start
12 set ::preport::_clipbase 0
13 
14 # preportDlg
15 # Present a dialog allowing the user to select the
16 # player and color for which to generate a player report.
17 #
18 proc ::preport::preportDlg {args} {
19  if {[sc_base numGames $::curr_db] == 0} {
20  tk_messageBox -title "Scid" -type ok -icon warning -message "No games in current base"
21  return
22  }
23  # Set default player and color if parameters are provided
24  if {[llength $args] >= 1} {
25  set ::preport::_player [lindex $args 0]
26  if {$::preport::_player == [sc_game info white]} {
27  set ::preport::_color white
28  } elseif {$::preport::_player == [sc_game info black]} {
29  set ::preport::_color black
30  }
31  }
32  if {[llength $args] >= 2} {
33  set ::preport::_color [lindex $args 1]
34  }
35 
36  set w .preportDlg
37  if {[winfo exists $w]} { return}
38  toplevel $w
39  wm title $w "Scid: [tr ToolsPlayerReport]"
40  wm resizable $w 0 0
41  pack [label $w.plabel -text "Generate Player Report"]
42  pack [frame $w.g] -side top -fill x -expand yes -padx 2
43  label $w.g.where -text "Player:"
44  grid $w.g.where -row 0 -column 0 -sticky w
45  ttk::combobox $w.g.player -width 40 -textvariable ::preport::_player
46  ::utils::history::SetCombobox ::preport::_player $w.g.player
47  grid $w.g.player -row 0 -column 1 -sticky we
48  label $w.g.has -text "Color:"
49  grid $w.g.has -row 1 -column 0 -sticky w
50  frame $w.g.color
51  radiobutton $w.g.color.white -text $::tr(White) \
52  -variable ::preport::_color -value white
53  frame $w.g.color.gap -width 5
54  radiobutton $w.g.color.black -text $::tr(Black) \
55  -variable ::preport::_color -value black
56  pack $w.g.color.white $w.g.color.gap $w.g.color.black -side left
57  grid $w.g.color -row 1 -column 1 -sticky w
58  label $w.g.pos -text "Start position:"
59  grid $w.g.pos -row 2 -column 0
60  frame $w.g.pselect
61  radiobutton $w.g.pselect.start -text "Standard start position" \
62  -variable ::preport::_pos -value start
63  radiobutton $w.g.pselect.current -text "Current board position" \
64  -variable ::preport::_pos -value current
65  pack $w.g.pselect.start $w.g.pselect.current -side left
66  grid $w.g.pselect -row 2 -column 1 -sticky w
67  checkbutton $w.g.clipbase -text $::tr(PReportClipbase) \
68  -variable ::preport::_clipbase
69  grid $w.g.clipbase -row 3 -column 1 -sticky w
71  pack [frame $w.b] -side bottom -fill x
72  pack [frame $w.b2] -side bottom -fill x
73  set whiteName [sc_game info white]
74  set blackName [sc_game info black]
75  dialogbutton $w.b2.white -text "$::tr(White) ($whiteName)" -command {
76  set ::preport::_player [sc_game info white]
77  set ::preport::_color white
78  }
79  dialogbutton $w.b2.black -text "$::tr(Black) ($blackName)" -command {
80  set ::preport::_player [sc_game info black]
81  set ::preport::_color black
82  }
83  if {$whiteName == "" || $whiteName == "?"} {
84  $w.b2.white configure -state disabled
85  }
86  if {$blackName == "" || $blackName == "?"} {
87  $w.b2.black configure -state disabled
88  }
89 
90  dialogbutton $w.b.help -text $::tr(Help) \
91  -command {helpWindow Reports Player}
92  dialogbutton $w.b.ok -text OK \
93  -command "catch {grab release $w}; destroy $w; ::preport::makeReportWin"
94  dialogbutton $w.b.cancel -text $::tr(Cancel) \
95  -command "catch {grab release $w}; destroy $w"
96  # foreach button {help ok cancel} {
97  # $w.b.$button configure -font font_Small
98  # }
99  if {$whiteName != "" && $whiteName != "?"} {
100  packbuttons left $w.b2.white
101  }
102  if {$blackName != "" && $blackName != "?"} {
103  packbuttons right $w.b2.black
104  }
105  packbuttons right $w.b.cancel $w.b.ok
106  packbuttons left $w.b.help
107  if {[sc_base current] == $::clipbase_db} {
108  $w.g.clipbase configure -state disabled
109  }
110  bind $w <Return> [list $w.b.ok invoke]
111  bind $w <Escape> [list $w.b.cancel invoke]
113  grab $w
114  focus $w.g.player
115 }
116 
117 proc ::preport::ConfigMenus {{lang ""}} {
118  if {! [winfo exists .preportWin]} { return}
119  if {$lang == ""} { set lang $::language}
120  set m .preportWin.menu
121  foreach idx {0 1} tag {File Help} {
122  configMenuText $m $idx Oprep$tag $lang
123  }
124  foreach idx {0 1 2 4 6} tag {Text Html LaTeX Options Close} {
125  configMenuText $m.file $idx OprepFile$tag $lang
126  }
127  foreach idx {0 1} tag {Report Index} {
128  configMenuText $m.helpmenu $idx OprepHelp$tag $lang
129  }
130 
131 }
132 
133 proc ::preport::makeReportWin {args} {
134  set showProgress 1
135  set args [linsert $args 0 "args"]
136  if {[lsearch -exact $args "-noprogress"] >= 0} { set showProgress 0}
137  if {$showProgress} {
138  set w .progress
139  toplevel $w
140  wm withdraw $w
141  wm title $w "Scid: [tr ToolsPlayerReport]"
142  bind $w <Visibility> "raiseWin $w"
143 
144  pack [frame $w.b] -side bottom -fill x
145  set ::preport::_interrupt 0
146  button $w.b.cancel -text $::tr(Cancel) -command {
147  set ::preport::_interrupt 1
148  progressBarCancel
149  }
150  pack $w.b.cancel -side right -pady 5 -padx 2
151 
152  foreach i {1 2 3} name {"Searching database for report games"
153  "Searching current board" "Generating report information"} {
154  label $w.text$i -text "$i. $name"
155  pack $w.text$i -side top
156  canvas $w.c$i -width 400 -height 20 -bg white -relief solid -border 1
157  $w.c$i create rectangle 0 0 0 0 -fill blue -outline blue -tags bar
158  $w.c$i create text 395 10 -anchor e -font font_Regular -tags time \
159  -fill black -text "0:00 / 0:00"
160  pack $w.c$i -side top -pady 10
161  }
162  wm resizable $w 0 0
163  # Set up geometry for middle of screen:
164  set x [winfo screenwidth $w]; set x [expr $x - 400]; set x [expr $x / 2]
165  set y [winfo screenheight $w]; set y [expr $y - 20]; set y [expr $y / 2]
166  wm geometry $w +$x+$y
167  wm deiconify $w
168  grab $w.b.cancel
169  progressBarSet $w.c1 401 21
170  }
171 
172  set searchArgs {}
173  lappend searchArgs -filter RESET
174  lappend searchArgs "-$::preport::_color"
175  lappend searchArgs "\"$::preport::_player\""
176  eval sc_search header $searchArgs
177  if {$showProgress} {
178  if {$::preport::_interrupt} {
179  catch {grab release $w.b.cancel}
180  destroy $w
181  return
182  }
183  progressBarSet $w.c2 401 21
184  }
185 
186  ::utils::history::AddEntry ::preport::_player $::preport::_player
187 
188  if {$::preport::_pos == "start"} { sc_game push}
189  sc_search board AND Exact false 0
190  if {$showProgress} {
191  if {$::preport::_interrupt} {
192  unbusyCursor .
193  catch {grab release $w.b.cancel}
194  destroy $w
195  return
196  }
197  progressBarSet $w.c3 401 21
198  }
199  sc_report player create $::preport(ExtraMoves) $::preport(MaxGames)
200  if {$::preport::_pos == "start"} { sc_game pop}
201  if {$::preport::_clipbase} {
202  if {[sc_base current] != $::clipbase_db} {
203  sc_clipbase clear
204  ::windows::gamelist::CopyGames "" [sc_base current] $::clipbase_db
205  }
206  }
207  if {$showProgress} {
208  catch {grab release $w.b.cancel}
209  destroy $w
210  if {$::preport::_interrupt} { return}
211  }
212  set report [::preport::report ctext 1]
213 
214  if {[lsearch -exact $args "-nodisplay"] >= 0} { return}
215 
216  set w .preportWin
217  if {![winfo exists $w]} {
218  toplevel $w
219  wm title $w "Scid: $::tr(PReportTitle)"
220  menu $w.menu
221  $w configure -menu $w.menu
222  $w.menu add cascade -label OprepFile -menu $w.menu.file
223  $w.menu add cascade -label OprepHelp -menu $w.menu.helpmenu
224  foreach i {file helpmenu} {
225  menu $w.menu.$i -tearoff 0
226  }
227  $w.menu.file add command -label OprepFileText \
228  -command {::preport::saveReport text}
229  $w.menu.file add command -label OprepFileHtml \
230  -command {::preport::saveReport html}
231  $w.menu.file add command -label OprepFileLaTeX \
232  -command {::preport::saveReport latex}
233  $w.menu.file add separator
234  $w.menu.file add command -label OprepFileOptions \
235  -command ::preport::setOptions
236  $w.menu.file add separator
237  $w.menu.file add command -label Close \
238  -command "$w.b.close invoke"
239  $w.menu.helpmenu add command -label "Player Report Help" \
240  -accelerator F1 -command {helpWindow Reports Player}
241  $w.menu.helpmenu add command -label "Index" \
242  -command {helpWindow Index}
243 
244  bind $w <F1> {helpWindow Reports Player}
245  bind $w <Escape> "$w.b.close invoke"
246  bind $w <Up> "$w.text yview scroll -1 units"
247  bind $w <Down> "$w.text yview scroll 1 units"
248  bind $w <Prior> "$w.text yview scroll -1 pages"
249  bind $w <Next> "$w.text yview scroll 1 pages"
250  bind $w <Key-Home> "$w.text yview moveto 0"
251  bind $w <Key-End> "$w.text yview moveto 0.99"
252 
253  autoscrollframe -bars y $w.scroll text $w.text \
254  -height 30 -width 85 -font font_Small -setgrid 1 -wrap word \
255  -background white -foreground black -cursor top_left_arrow
256  ::htext::init $w.text
257  frame $w.b
258  button $w.b.opts -text [tr OprepFileOptions] -command ::preport::setOptions
259  button $w.b.help -textvar ::tr(Help) -command {helpWindow Reports Player}
260  button $w.b.viewHTML -text $::tr(OprepViewHTML) \
261  -command ::preport::previewHTML
262  button $w.b.update -textvar ::tr(Update...) -command {
263  ::preport::preportDlg
264  }
265  button $w.b.close -textvar ::tr(Close) -command "focus .; destroy $w"
266  pack $w.b -side bottom -fill x
267  pack $w.scroll -side top -fill both -expand yes
268  pack $w.b.close $w.b.update -side right -padx 2 -pady 2
269  if {$::windowsOS} {
270  pack $w.b.viewHTML -side left -padx 2 -pady 2
271  }
272  pack $w.b.opts -side left -padx 2 -pady 2
275  }
276 
277  busyCursor .
278  $w.text configure -state normal
279  $w.text delete 1.0 end
280  regsub -all "\n" $report "<br>" report
281  ::htext::display $w.text $report
282  $w.text configure -state disabled
283  unbusyCursor .
286 }
287 
288 
289 proc ::preport::setOptions {} {
290  set w .preportOptions
291  if {[winfo exists $w]} { return}
292  toplevel $w
293  pack [frame $w.f] -side top -fill x -padx 5 -pady 5
294  set row 0
295  foreach i {Stats AvgPerf Results MovesFrom Themes Endgames} {
296  set yesno($i) 1
297  }
298  foreach i {Stats Oldest Newest MostFrequentOpponents Results sep \
299  AvgPerf HighRating sep \
300  MostFrequentEcoCodes Themes Endgames sep \
301  MaxGames ExtraMoves} {
302  set from 0; set to 10; set tick 1; set res 1
303  if {$i == "MaxGames"} {
304  set from 0; set to 500; set tick 100; set res 50
305  }
306  if {$i == "sep"} {
307  frame $w.f.fsep$row -height 2 -borderwidth 2 -relief sunken -bg white
308  frame $w.f.tsep$row -height 2 -borderwidth 2 -relief sunken -bg white
309  grid $w.f.fsep$row -row $row -column 0 -sticky we -columnspan 4
310  #grid $w.f.tsep$row -row $row -column 1 -sticky we -columnspan 2
311  } elseif {[info exists yesno($i)]} {
312  frame $w.f.f$i
313  radiobutton $w.f.f$i.yes -variable ::preport($i) -value 1 \
314  -text "$::tr(Yes) " -font font_Small
315  radiobutton $w.f.f$i.no -variable ::preport($i) -value 0 \
316  -text "$::tr(No) " -font font_Small
317  pack $w.f.f$i.yes -side left
318  pack $w.f.f$i.no -side right
319  label $w.f.t$i -textvar ::tr(Oprep$i) -font font_Small
320  grid $w.f.f$i -row $row -column 0 -sticky n
321  grid $w.f.t$i -row $row -column 1 -sticky w -columnspan 3
322  } else {
323  scale $w.f.s$i -variable ::preport($i) -from $from -to $to \
324  -width 8 -length 200 -tickinterval $tick -orient horizontal \
325  -font font_Small -resolution $res -showvalue 0
326  label $w.f.t$i -textvar ::tr(Oprep$i) -font font_Small
327  grid $w.f.s$i -row $row -column 0 -sticky we
328  grid $w.f.t$i -row $row -column 1 -sticky w -columnspan 3
329  }
330  grid rowconfigure $w.f $row -pad 2
331  incr row
332  }
334  pack [frame $w.b] -side bottom -fill x
335  button $w.b.defaults -textvar ::tr(Defaults) -command {
336  array set ::preport [array get ::preportDefaults]
337  }
338  button $w.b.ok -text "OK" -command {
339  destroy .preportOptions
340  catch {set ::preport::_data(yview) [lindex [.preportWin.text yview] 0]}
341  ::preport::makeReportWin
342  catch {.preportWin.text yview moveto $::preport::_data(yview)}
343  }
344  button $w.b.cancel -textvar ::tr(Cancel) -command {
345  array set ::preport [array get ::preport::backup]
346  destroy .preportOptions
347  }
348  pack $w.b.defaults -side left -padx 5 -pady 5
349  pack $w.b.cancel $w.b.ok -side right -padx 5 -pady 5
350  array set ::preport::backup [array get ::preport]
351  wm resizable $w 0 0
352  wm title $w "Scid: [tr ToolsPlayerReport]: [tr OprepFileOptions]"
353  bind $w <Escape> "$w.b.cancel invoke"
354 }
355 
356 
357 # previewHTML:
358 # Saves the report to a temporary file, and invokes the user's web
359 # browser to display it.
360 #
361 proc ::preport::previewHTML {} {
362  busyCursor .
363  set tmpdir $::scidLogDir
364  set tmpfile "TempPlayerReport"
365  set fname [file join $tmpdir $tmpfile]
366  if {[catch {set tempfile [open $fname.html w]}]} {
367  tk_messageBox -title "Scid: Error writing report" -type ok -icon warning \
368  -message "Unable to write the file: $fname.html"
369  }
370  puts $tempfile [::preport::report html 1]
371  close $tempfile
372  if {[string match $::tcl_platform(os) "Windows NT"]} {
373  catch {exec $::env(COMSPEC) /c start $fname.html &}
374  } else {
375  catch {exec start $fname.html &}
376  }
377  unbusyCursor .
378 }
379 
380 proc ::preport::saveReport {fmt} {
381  set default ".txt"
382  set ftype {
383  { "Text files" {".txt"} }
384  { "All files" {"*"} }
385  }
386  if {$fmt == "latex"} {
387  set default ".tex"
388  set ftype {
389  { "LaTeX files" {".tex" ".ltx"} }
390  { "All files" {"*"} }
391  }
392  } elseif {$fmt == "html"} {
393  set default ".html"
394  set ftype {
395  { "HTML files" {".html" ".htm"} }
396  { "All files" {"*"} }
397  }
398  }
399 
400  set fname [tk_getSaveFile -initialdir [pwd] -filetypes $ftype \
401  -defaultextension $default -title "Scid: Save opening report"]
402  if {$fname == ""} { return}
403 
404  busyCursor .
405  if {[catch {set tempfile [open $fname w]}]} {
406  tk_messageBox -title "Scid: Error writing report" -type ok -icon warning \
407  -message "Unable to write the file: $fname\n\n"
408  } else {
409  set report [::preport::report $fmt 1]
410  if {$::hasEncoding && $::langEncoding($::language) != ""} {
411  catch {set report [encoding convertto $::langEncoding($::language) $report]}
412  }
413  puts $tempfile $report
414  close $tempfile
415  }
416  unbusyCursor .
417 }
418 
419 proc ::preport::_reset {} {
420  set ::preport::_data(sec) 0
421  set ::preport::_data(subsec) 0
422 }
423 
424 proc ::preport::_title {} {
425  set fmt $::preport::_data(fmt)
426  set title $::tr(PReportTitle)
427  if {$fmt == "latex"} {
428  return "\\begin{center}{\\LARGE \\bf $title}\\end{center}\n\n"
429  } elseif {$fmt == "html"} {
430  return "<h1><center>$title</center></h1>\n\n"
431  } elseif {$fmt == "ctext"} {
432  return "<h1><center>$title</center></h1>\n\n"
433  }
434  set r "--------------------------------------------------------------"
435  append r "\n [string toupper $title]\n"
436  append r "--------------------------------------------------------------"
437  append r "\n\n"
438  return $r
439 }
440 
441 proc ::preport::_sec {text} {
442  set fmt $::preport::_data(fmt)
443  incr ::preport::_data(sec)
444  set ::preport::_data(subsec) 0
445  if {$fmt == "latex"} {
446  return "\n\n\\section{$text}\n"
447  } elseif {$fmt == "html"} {
448  return "\n<h2>$::preport::_data(sec). $text</h2>\n"
449  } elseif {$fmt == "ctext"} {
450  return "<h4>$::preport::_data(sec). $text</h4>"
451  }
452  set line "$::preport::_data(sec). [string toupper $text]"
453  set underline "-----------------------------------------------------"
454  return "\n\n$line\n[string range $underline 1 [string length $line]]\n"
455 }
456 
457 proc ::preport::_subsec {text} {
458  set fmt $::preport::_data(fmt)
459  incr ::preport::_data(subsec)
460  if {$fmt == "latex"} {
461  return "\n\\subsection{$text}\n\n"
462  } elseif {$fmt == "html"} {
463  return "\n<h3>$::preport::_data(sec).$::preport::_data(subsec) $text</h3>\n\n"
464  } elseif {$fmt == "ctext"} {
465  return "\n<maroon><b>$::preport::_data(sec).$::preport::_data(subsec) $text</b></maroon>\n\n"
466  }
467  return "\n$::preport::_data(sec).$::preport::_data(subsec) $text\n\n"
468 }
469 
470 
471 proc ::preport::report {fmt {withTable 1}} {
472  global tr preport
473  sc_report player format $fmt
474  set fmt [string tolower $fmt]
475  set ::preport::_data(fmt) $fmt
477 
478  # numRows: the number of rows to show in the theory table.
479  # If it is zero, the number of rows if decided according to the
480  # number of games in the report.
481  set numRows 0
482 
483  # Specify whether a theory table is to be printed, so note numbers
484  # can be generated and displayed if necessary:
485  sc_report player notes $withTable $numRows
486 
487  set n "\n"; set p "\n\n"; set preText ""; set postText ""
488  set percent "%"; set bullet " * "
489  if {$fmt == "latex"} {
490  set n "\\\\\n"; set p "\n\n"
491  #set preText "{\\samepage\\begin{verbatim}\n"
492  #set postText "\\end{verbatim}\n}\n"
493  set percent "\\%"; set bullet "\\hspace{0.5cm}\$\\bullet\$"
494  } elseif {$fmt == "html"} {
495  set n "<br>\n"; set p "<p>\n\n"
496  set preText "<pre>\n"; set postText "</pre>\n"
497  } elseif {$fmt == "ctext"} {
498  set preText "<tt>"; set postText "</tt>"
499  }
500 
501  # Generate the report:
502  set games $tr(games)
503  set moves $tr(moves)
504  set counts [sc_report player count]
505  set rgames [lindex $counts 0]
506  set tgames [lindex $counts 1]
507 
508  set r {}
509  append r $::optable::_docStart($fmt)
510  set r [string map [list "\[OprepTitle\]" $tr(PReportTitle)] $r]
511  append r [::preport::_title]
512  append r "$tr(Player): \"$::preport::_player\""
513  if {$::preport::_color == "white"} {
514  append r " $tr(PReportColorWhite)"
515  } else {
516  append r " $tr(PReportColorBlack)"
517  }
518  set eco ""
519  if {$::preport::_pos == "current" && ![sc_pos isAt start]} {
520  append r " [format $tr(PReportMoves) [sc_report player line]]"
521  set eco [sc_report player eco]
522  }
523  append r " ("
524  if {$fmt == "ctext"} {
525  append r "<darkblue><run sc_report player select all 0; ::windows::stats::Refresh>"
526  }
527  append r "$rgames"
528  if {$fmt == "ctext"} { append r "</run></darkblue>"; }
529  append r " $games)$n"
530  append r "$tr(Database): [file tail [sc_base filename $::curr_db]] "
531  append r "([::utils::thousands [sc_base numGames $::curr_db]] $games)$n"
532  if {$eco != ""} {
533  append r "$tr(ECO): $eco$n"
534  }
535  append r "$::tr(OprepGenerated) Scid $::scidVersion, [::utils::date::today]$n"
536 
537  if {$preport(Stats) || $preport(Oldest) > 0 || $preport(Newest) > 0 ||
538  $preport(MostFrequentOpponents) > 0 || $preport(Results)} {
539  append r [::preport::_sec $tr(OprepStatsHist)]
540  }
541  if {$preport(Stats)} {
542  append r [::preport::_subsec $tr(OprepStats)]
543  append r [::optable::stats $fmt]
544  }
545  if {$preport(Oldest) > 0} {
546  append r [::preport::_subsec $tr(OprepOldest)]
547  append r [sc_report player best o $preport(Oldest)]
548  }
549  if {$preport(Newest) > 0} {
550  append r [::preport::_subsec $tr(OprepNewest)]
551  append r [sc_report player best n $preport(Newest)]
552  }
553  if {$preport(MostFrequentOpponents) > 0} {
554  append r [::preport::_subsec "$tr(OprepMostFrequentOpponents)"]
555  if {$::preport::_color == "white"} {
556  append r [sc_report player players black $preport(MostFrequentOpponents)]
557  } else {
558  append r [sc_report player players white $preport(MostFrequentOpponents)]
559  }
560  }
561  if {$preport(Results)} {
562  append r [::preport::_subsec $::tr(OprepResults)]
563  append r [::optable::results player $fmt]
564  }
565 
566  if {$preport(AvgPerf) || $preport(HighRating)} {
567  append r [::preport::_sec $tr(OprepRatingsPerf)]
568  }
569  if {$preport(AvgPerf)} {
570  append r [::preport::_subsec $tr(OprepAvgPerf)]
571  set e [sc_report player elo white]
572  set welo [lindex $e 0]; set wng [lindex $e 1]
573  set bpct [lindex $e 2]; set bperf [lindex $e 3]
574  set e [sc_report player elo black]
575  set belo [lindex $e 0]; set bng [lindex $e 1]
576  set wpct [lindex $e 2]; set wperf [lindex $e 3]
577  append r "$tr(OprepWRating): $welo ($wng $games); "
578  append r "$tr(OprepWPerf): $wperf ($wpct$percent vs $belo)$n"
579  append r "$tr(OprepBRating): $belo ($bng $games); "
580  append r "$tr(OprepBPerf): $bperf ($bpct$percent vs $welo)$n"
581  }
582  if {$preport(HighRating) > 0} {
583  append r [::preport::_subsec $tr(OprepHighRating)]
584  append r [sc_report player best a $preport(HighRating)]
585  }
586 
587  if {$preport(Themes) || $preport(MostFrequentEcoCodes) > 0 ||
588  $preport(Endgames)} {
589  append r [::preport::_sec $tr(OprepMovesThemes)]
590  }
591  if {$preport(MostFrequentEcoCodes) > 0} {
592  append r [::preport::_subsec $tr(PReportOpenings)]
593  append r [sc_report player eco $preport(MostFrequentEcoCodes)]
594  }
595  if {$preport(Themes)} {
596  append r [::preport::_subsec $tr(OprepThemes)]
597  append r [sc_report player themes $tr(OprepThemeDescription:) \
598  $tr(OprepThemeSameCastling:) $tr(OprepThemeOppCastling:) \
599  $tr(OprepThemeKPawnStorm:) $tr(OprepThemeQueenswap:) \
600  $tr(OprepTheme1BishopPair:) \
601  $tr(OprepThemeWIQP:) $tr(OprepThemeBIQP:) \
602  $tr(OprepThemeWP567:) $tr(OprepThemeBP234:) \
603  $tr(OprepThemeOpenCDE:)]
604  }
605  if {$preport(Endgames)} {
606  append r [::preport::_subsec $tr(OprepEndgames)]
607  append r "$tr(OprepEndClass:)$n"
608  append r [sc_report player endmat]
609  }
610 
611  if {$withTable && $::preport(MaxGames) > 0} {
612  set sec [::preport::_sec $tr(OprepTheoryTable)]
613  set comment ""
614  if {$tgames > $::preport(MaxGames)} {
615  set comment [format $tr(OprepTableComment) $::preport(MaxGames)]
616  }
617  append r [sc_report player print $numRows $sec $comment]
618  }
619  append r $::optable::_docEnd($fmt)
620 
621  # Eszet (ss) characters seem to be mishandled by LaTeX, even with
622  # the font encoding package, so convert them explicitly:
623  if {$fmt == "latex"} { regsub -all ß $r {{\\ss}} r}
624 
625  return $r
626 }