Skip to content

Commit 321c934

Browse files
committed
Add time analysis graphs and time input; add base corruption safeguard
1 parent a4b9ce3 commit 321c934

6 files changed

Lines changed: 365 additions & 12 deletions

File tree

tcl/file/maint.tcl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,34 @@ proc baseIsCompactable {} {
822822

823823
proc compactDB {{base -1}} {
824824
if {$base < 0} { set base [sc_base current] }
825+
826+
# Safeguard: check for open engine windows or active engine pipes
827+
set enginesOpen 0
828+
foreach w [winfo children .] {
829+
if {[string match ".analysisWin*" $w] || [string match ".engineWin*" $w] || \
830+
[string match ".coachWin" $w] || [string match ".tacticsWin" $w] || \
831+
[string match ".reviewgame" $w] || [string match ".calvarWin" $w] || \
832+
[string match ".inputengineconsole" $w]} {
833+
set enginesOpen 1 ; break
834+
}
835+
}
836+
if {!$enginesOpen} {
837+
foreach n {1 2 3 4} {
838+
if {[info exists ::analysis(pipe$n)] && $::analysis(pipe$n) != ""} {
839+
set enginesOpen 1 ; break
840+
}
841+
}
842+
}
843+
if {!$enginesOpen && [info exists ::enginewin::engState]} {
844+
if {[array size ::enginewin::engState] > 0} { set enginesOpen 1 }
845+
}
846+
847+
if {$enginesOpen} {
848+
tk_messageBox -type ok -icon warning -title "Scid: $::tr(CompactDatabase)" \
849+
-message "Cannot proceed while chess engines are open.\nPlease close all engine windows and try again."
850+
return
851+
}
852+
825853
if {[::game::Clear] == "cancel"} { return }
826854
if {[catch {sc_base compact $base stats} stats]} {
827855
return [ERROR::MessageBox "$::tr(CompactDatabase)\n"]

tcl/help/help.tcl

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3164,14 +3164,7 @@ set helpText(Maintenance) {<h1>Database maintenance</h1>
31643164
9999999.
31653165
</p>
31663166

3167-
<h3>Repair a base</h3>
3168-
<p>
3169-
In the rare cases that a scidCommunity database is corrupted one might try to
3170-
repair it using Database / Maintenance / Repair base. For this to work,
3171-
the base in question must not be opened (which is not possible in
3172-
most cases anyway). scidCommunity will then try its best to get the database
3173-
back in a consistent and usable state.
3174-
</p>
3167+
31753168

31763169
<p><footer>(Updated: scidCommunity, February 2026)</footer></p>
31773170
}

tcl/lang/english.tcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ menuText E ToolsTrainCalvar "Calculation of variations" 0 {Calculation of varia
205205
menuText E ToolsTrainFindBestMove "Find best move" 0 {Find best move}
206206
menuText E ToolsTrainFics "Play on FICS" 0 {Play on freechess.org}
207207
menuText E ToolsEngineTournament "Engine tournament" 0 {Start a tournament between chess engines}
208+
menuText E ToolsTimeAnalysis "Time Analysis" 0 {Show clock time graph for the current game}
208209
menuText E ToolsBookTuning "Book tuning" 0 {Book tuning}
209210
menuText E ToolsDownloadTWIC "Download TWIC Games" 0 {Download the latest The Week In Chess (TWIC) games}
210211
menuText E ToolsConnectHardware "Connect Hardware" 8 {Connect external hardware}

tcl/menus.tcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ $m add command -label ToolsOpReport \
260260
-accelerator "Ctrl+Shift+O" -command ::optable::makeReportWin
261261
$m add command -label ToolsTracker \
262262
-accelerator "Ctrl+Shift+K" -command ::ptrack::make
263+
$m add command -label ToolsTimeAnalysis -command ::tools::graphs::time::Open
263264
$m add command -label ToolsBookTuning -command ::book::tuning
264265
$m add command -label ToolsDownloadTWIC -command "::twic::downloadWeek latest"
265266
menu $m.hardware

tcl/tools/graphs.tcl

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,4 +1144,228 @@ proc ::tools::graphs::absfilter::Refresh {} {
11441144
unbusyCursor .
11451145
update
11461146
}
1147+
1148+
########################################
1149+
# Time Analysis graph window
1150+
1151+
namespace eval ::tools::graphs::time {}
1152+
1153+
# ElapsedList:
1154+
# From a MoveTimeList result {x0 t0 x1 t1 ...} (remaining clock times),
1155+
# compute elapsed time per move as the delta between consecutive entries.
1156+
# Returns {moveNum elapsedMins ...} starting from the 2nd clock entry.
1157+
# The first entry is skipped because the starting time is unknown.
1158+
# For bar-chart side-by-side layout, White bars are offset -0.2 and
1159+
# Black bars are offset +0.2 from integer move numbers.
1160+
proc ::tools::graphs::time::ElapsedList {coordsList offset} {
1161+
set result {}
1162+
set n [llength $coordsList]
1163+
# Need at least two entries to compute a delta
1164+
if {$n < 4} { return $result }
1165+
set moveNum 1
1166+
for {set i 2} {$i < $n} {incr i 2} {
1167+
set prevTime [lindex $coordsList [expr {$i - 1}]]
1168+
set currTime [lindex $coordsList [expr {$i + 1}]]
1169+
set elapsed [expr {$prevTime - $currTime}]
1170+
if {$elapsed < 0} { set elapsed 0 }
1171+
lappend result [expr {$moveNum + $offset}] $elapsed
1172+
incr moveNum
1173+
}
1174+
return $result
1175+
}
1176+
1177+
proc ::tools::graphs::time::Open {} {
1178+
set w .tgraph
1179+
if {[winfo exists $w]} {
1180+
focus $w
1181+
::tools::graphs::time::Refresh
1182+
return
1183+
}
1184+
1185+
toplevel $w
1186+
wm title $w "scidCommunity: Time Analysis"
1187+
1188+
# ---- Line graph canvas (top) ----
1189+
canvas $w.c -width 600 -height 280 \
1190+
-selectforeground [ttk::style lookup . -foreground] \
1191+
-background [ttk::style lookup . -background]
1192+
$w.c create text 25 5 -tag title -justify center -width 1 \
1193+
-font font_Regular -anchor n
1194+
1195+
# ---- Bar chart canvas (bottom) ----
1196+
canvas $w.c2 -width 600 -height 200 \
1197+
-selectforeground [ttk::style lookup . -foreground] \
1198+
-background [ttk::style lookup . -background]
1199+
$w.c2 create text 25 5 -tag bartitle -justify center -width 1 \
1200+
-font font_Regular -anchor n
1201+
1202+
# ---- Button bar ----
1203+
ttk::frame $w.btns
1204+
ttk::button $w.btns.refresh -text "Refresh" \
1205+
-command ::tools::graphs::time::Refresh
1206+
ttk::button $w.btns.close -text "Close" -command "destroy $w"
1207+
pack $w.btns.refresh -side left -padx 4 -pady 2
1208+
pack $w.btns.close -side right -padx 4 -pady 2
1209+
1210+
pack $w.btns -side bottom -fill x
1211+
pack $w.c -side top -expand yes -fill both
1212+
pack $w.c2 -side top -fill both
1213+
1214+
bind $w <Configure> {
1215+
# Resize line graph (top canvas)
1216+
.tgraph.c itemconfigure title -width [expr {[winfo width .tgraph.c] - 20}]
1217+
.tgraph.c coords title [expr {[winfo width .tgraph.c] / 2}] 8
1218+
if {[::utils::graph::isgraph tgraph]} {
1219+
::utils::graph::configure tgraph \
1220+
-height [expr {[winfo height .tgraph.c] - 50}] \
1221+
-width [expr {[winfo width .tgraph.c] - 60}]
1222+
::utils::graph::redraw tgraph
1223+
}
1224+
# Resize bar chart (bottom canvas)
1225+
.tgraph.c2 itemconfigure bartitle -width [expr {[winfo width .tgraph.c2] - 20}]
1226+
.tgraph.c2 coords bartitle [expr {[winfo width .tgraph.c2] / 2}] 8
1227+
if {[::utils::graph::isgraph tgraph2]} {
1228+
::utils::graph::configure tgraph2 \
1229+
-height [expr {[winfo height .tgraph.c2] - 50}] \
1230+
-width [expr {[winfo width .tgraph.c2] - 60}]
1231+
::utils::graph::redraw tgraph2
1232+
}
1233+
}
1234+
bind $w <F1> {helpWindow Index}
1235+
1236+
::tools::graphs::time::Refresh
1237+
}
1238+
1239+
proc ::tools::graphs::time::Refresh {} {
1240+
set w .tgraph
1241+
if {![winfo exists $w]} { return }
1242+
1243+
# Fetch remaining clock data for both colours (add=0 => remaining time)
1244+
set coordsW [MoveTimeList "w" 0]
1245+
set coordsB [MoveTimeList "b" 0]
1246+
1247+
if {[llength $coordsW] == 0 && [llength $coordsB] == 0} {
1248+
# Clear any previous graph drawings from both canvases
1249+
$w.c delete -withtag gtgraph
1250+
$w.c2 delete -withtag gtgraph2
1251+
tk_messageBox -parent $w -icon info -title "Time Analysis" \
1252+
-message "No \[%clk\] clock comments were found in this game.\n\nAdd clock times via the Comments Window (Ctrl+E) to use this feature."
1253+
return
1254+
}
1255+
1256+
set white [sc_game info white]
1257+
set black [sc_game info black]
1258+
set date [sc_game info date]
1259+
1260+
# ---- Line graph (remaining clock time) ----
1261+
1262+
set maxMins 0
1263+
foreach lst [list $coordsW $coordsB] {
1264+
foreach {xv yv} $lst {
1265+
if {$yv > $maxMins} { set maxMins $yv }
1266+
}
1267+
}
1268+
set ytick 1
1269+
if {$maxMins > 10} { set ytick 2 }
1270+
if {$maxMins > 30} { set ytick 5 }
1271+
if {$maxMins > 60} { set ytick 10 }
1272+
if {$maxMins > 120} { set ytick 20 }
1273+
1274+
set height [expr {[winfo height $w.c] - 50}]
1275+
set width [expr {[winfo width $w.c] - 60}]
1276+
if {$height < 50} { set height 230 }
1277+
if {$width < 50} { set width 540 }
1278+
1279+
::utils::graph::create tgraph \
1280+
-width $width -height $height \
1281+
-xtop 40 -ytop 30 \
1282+
-font font_Small -canvas $w.c \
1283+
-textcolor black -tickcolor black \
1284+
-background white \
1285+
-xtick 1 -ytick $ytick \
1286+
-ymin 0 \
1287+
-hline [list [list gray80 1 each $ytick]] \
1288+
-vline {{gray80 1 each 1} {steelBlue 1 each 5}}
1289+
1290+
::utils::graph::data tgraph bounds -points 0 -lines 0 -bars 0 \
1291+
-coords {0 0 1 0}
1292+
1293+
if {[llength $coordsW] > 0} {
1294+
::utils::graph::data tgraph white \
1295+
-color darkgreen -outline darkgreen \
1296+
-points 1 -lines 1 -linewidth 2 -radius 3 \
1297+
-key $white -coords $coordsW
1298+
}
1299+
if {[llength $coordsB] > 0} {
1300+
::utils::graph::data tgraph black \
1301+
-color steelBlue -outline steelBlue \
1302+
-points 1 -lines 1 -linewidth 2 -radius 3 \
1303+
-key $black -coords $coordsB
1304+
}
1305+
1306+
::utils::graph::redraw tgraph
1307+
$w.c itemconfigure title -text "Remaining Clock Time: $white vs $black ($date)"
1308+
$w.c itemconfigure title -width [expr {[winfo width $w.c] - 20}]
1309+
$w.c coords title [expr {[winfo width $w.c] / 2}] 8
1310+
1311+
# ---- Bar chart (time spent per move) ----
1312+
1313+
# Compute elapsed (time spent) per move for each player:
1314+
# White bars offset -0.2, Black bars offset +0.2 for side-by-side display
1315+
set elapsedW [::tools::graphs::time::ElapsedList $coordsW -0.2]
1316+
set elapsedB [::tools::graphs::time::ElapsedList $coordsB 0.2]
1317+
1318+
set maxElapsed 0
1319+
foreach lst [list $elapsedW $elapsedB] {
1320+
foreach {xv yv} $lst {
1321+
if {$yv > $maxElapsed} { set maxElapsed $yv }
1322+
}
1323+
}
1324+
set ytick2 0.5
1325+
if {$maxElapsed > 2} { set ytick2 1 }
1326+
if {$maxElapsed > 5} { set ytick2 2 }
1327+
if {$maxElapsed > 10} { set ytick2 5 }
1328+
if {$maxElapsed > 30} { set ytick2 10}
1329+
1330+
set height2 [expr {[winfo height $w.c2] - 50}]
1331+
set width2 [expr {[winfo width $w.c2] - 60}]
1332+
if {$height2 < 50} { set height2 150 }
1333+
if {$width2 < 50} { set width2 540 }
1334+
1335+
::utils::graph::create tgraph2 \
1336+
-width $width2 -height $height2 \
1337+
-xtop 40 -ytop 30 \
1338+
-font font_Small -canvas $w.c2 \
1339+
-textcolor black -tickcolor black \
1340+
-background white \
1341+
-xtick 1 -ytick $ytick2 \
1342+
-ymin 0 \
1343+
-hline [list [list gray80 1 each $ytick2]] \
1344+
-vline {{gray80 1 each 1} {steelBlue 1 each 5}}
1345+
1346+
::utils::graph::data tgraph2 bounds -points 0 -lines 0 -bars 0 \
1347+
-coords {0 0 1 0}
1348+
1349+
if {[llength $elapsedW] > 0} {
1350+
::utils::graph::data tgraph2 wbars \
1351+
-color darkgreen -outline black \
1352+
-points 0 -lines 0 -bars 1 \
1353+
-barwidth 0.35 \
1354+
-coords $elapsedW
1355+
}
1356+
if {[llength $elapsedB] > 0} {
1357+
::utils::graph::data tgraph2 bbars \
1358+
-color steelBlue -outline black \
1359+
-points 0 -lines 0 -bars 1 \
1360+
-barwidth 0.35 \
1361+
-coords $elapsedB
1362+
}
1363+
1364+
::utils::graph::redraw tgraph2
1365+
$w.c2 itemconfigure bartitle \
1366+
-text "Time Spent Per Move (minutes) — White (green) Black (blue)"
1367+
$w.c2 itemconfigure bartitle -width [expr {[winfo width $w.c2] - 20}]
1368+
$w.c2 coords bartitle [expr {[winfo width $w.c2] / 2}] 8
1369+
}
1370+
11471371
### End of file: graphs.tcl

0 commit comments

Comments
 (0)