diff --git a/css/chess.css b/css/chess.css index 9d0c762..df14c84 100644 --- a/css/chess.css +++ b/css/chess.css @@ -207,6 +207,33 @@ button#settings, button#cb_choose_game { color: grey; } +#cb_times { + display: flex; + flex-flow: row nowrap; + white-space: nowrap; + justify-content: stretch; + align-items: flex-end; + width: 100%; + padding-left: 3rem; + padding-right: 3rem; +} + +#cb_times.cb-hide-times { + visibility: hidden; +} + +#cb_light_time, #cb_dark_time { + width: 100%; +} + +#cb_light_time { + text-align: left; +} + +#cb_dark_time { + text-align: right; +} + #cb_names { position: relative; display: flex; diff --git a/index.html b/index.html index 7165092..350f75e 100644 --- a/index.html +++ b/index.html @@ -167,6 +167,10 @@ +
+
0:00:00
+
0:00:00
+
diff --git a/js/pacosako_ui.js b/js/pacosako_ui.js index c638c0d..d43c80a 100644 --- a/js/pacosako_ui.js +++ b/js/pacosako_ui.js @@ -25,6 +25,7 @@ ElementQueries.listen(); import {Buffer} from 'buffer'; import pako from 'pako'; +import {sprintf} from 'sprintf-js'; /* "Waterdrop" by Porphyr (freesound.org/people/Porphyr) / CC BY 3.0 (creativecommons.org/licenses/by/3.0) */ import Waterdrop from '../mp3/191678__porphyr__waterdrop.mp3'; @@ -254,6 +255,81 @@ $(function (){ return piece; } + function updatePlayerTimes() { + let lightTime = 0; + let darkTime = 0; + + let moveStartTime = undefined; + + for (const move of visibleGame.moves) { + if (!move.meta || !Number.isInteger(move.meta.timestamp)) { + lightTime = darkTime = undefined; + break; + } + + if (move.replaced) { + /* not the final move in the chain */ + continue; + } + + /* start counting when the dark player finishes their first move */ + if (moveStartTime === undefined) { + if (move.side === PS.DARK) { + moveStartTime = move.meta.timestamp; + } else { + continue; + } + } + + const moveTime = move.meta.timestamp - moveStartTime; + + if (moveTime > 0) { + if (move.side === PS.LIGHT) { + lightTime += moveTime; + } else { + darkTime += moveTime; + } + } + + moveStartTime = move.meta.timestamp; + } + + if (moveStartTime === undefined) { + $('#cb_light_time, #cb_dark_time').text('0:00:00'); + $('#cb_times').addClass('cb-hide-times'); + return; + } + + if (visibleGame.status === PS.PLAYING) { + if (!visibleGame.canRedo) { + const currentMoveTime = +new Date() - moveStartTime; + if (currentMoveTime > 0) { + if (visibleGame.player === PS.LIGHT) { + lightTime += currentMoveTime; + } else { + darkTime += currentMoveTime; + } + } + } + } + + $('#cb_times').removeClass('cb-hide-times'); + + function formatTime(milliseconds) { + let seconds = milliseconds / 1000; + const hours = seconds / 3600; + seconds %= 3600; + const minutes = seconds / 60; + seconds %= 60; + return sprintf('%d:%02d:%02d', hours, minutes, seconds); + } + + $('#cb_light_time').text(formatTime(lightTime)); + $('#cb_dark_time').text(formatTime(darkTime)); + } + + setInterval(() => { updatePlayerTimes(); }, 250); + function renderBoard(animate) { $('#cb_board').removeData('dragging_from'); $('#cb_board .cb-piece').remove(); @@ -403,6 +479,8 @@ $(function (){ } else if (game.winner === PS.DARK) { $('#cb_names').addClass('cb-dark-won'); } + + updatePlayerTimes(); } function applyTheme(theme) { @@ -1440,6 +1518,7 @@ $(function (){ $('#header').appendTo('#board_ui'); $('#cb_status').appendTo('#board_ui'); $('#cb_names').appendTo('#board_ui'); + $('#cb_times').appendTo('#board_ui'); $('#cb_navigate').appendTo('#board_ui'); $('#board_ui').appendTo('#page'); $('#page').removeClass('vertical-layout').addClass('horizontal-layout'); @@ -1448,6 +1527,7 @@ $(function (){ $('#cb_container').appendTo('#board_ui'); $('#cb_status').appendTo('#board_ui'); $('#cb_names').appendTo('#board_ui'); + $('#cb_times').appendTo('#board_ui'); $('#cb_navigate').appendTo('#board_ui'); $('#board_ui').appendTo('#page'); $('#page').removeClass('horizontal-layout').addClass('vertical-layout'); diff --git a/package-lock.json b/package-lock.json index 5ccd511..5efe446 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1585,6 +1585,14 @@ "dev": true, "requires": { "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } } }, "arr-diff": { diff --git a/package.json b/package.json index 57ce815..b6e19b5 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "mini-css-extract-plugin": "^0.9.0", "optimize-css-assets-webpack-plugin": "^5.0.3", "pako": "^1.0.11", + "sprintf-js": "^1.0.3", "svgo": "^1.3.2", "svgo-loader": "^2.2.1", "webpack": "^4.43.0",