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