git-watchtower 2.3.6 → 2.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/casino/index.js +29 -0
- package/src/server/web-ui/js.js +27 -3
- package/src/server/web.js +6 -2
package/package.json
CHANGED
package/src/casino/index.js
CHANGED
|
@@ -283,6 +283,16 @@ function startSlotReels(renderCallback) {
|
|
|
283
283
|
* @param {Object|null} winLevel - The win level object from getWinLevel()
|
|
284
284
|
*/
|
|
285
285
|
function stopSlotReels(hadUpdates = false, renderCallback = null, winLevel = null) {
|
|
286
|
+
// No-op when casino mode is off. The bin's polling path captures
|
|
287
|
+
// `casinoOn` once at the top of pollGitChanges and continues to use that
|
|
288
|
+
// snapshot for the rest of the cycle, so a poll completing AFTER the
|
|
289
|
+
// user toggled casino off would otherwise install a fresh
|
|
290
|
+
// slotResultInterval that fires render() ~20× over the next 3s. The
|
|
291
|
+
// display getters are already guarded by `casinoEnabled`, so the user
|
|
292
|
+
// sees nothing — but render() still burns full-screen redraws and the
|
|
293
|
+
// interval keeps a closure alive. Drop the call cleanly here instead.
|
|
294
|
+
if (!casinoEnabled) return;
|
|
295
|
+
|
|
286
296
|
if (slotReelInterval) {
|
|
287
297
|
clearInterval(slotReelInterval);
|
|
288
298
|
slotReelInterval = null;
|
|
@@ -689,6 +699,24 @@ function getStats() {
|
|
|
689
699
|
};
|
|
690
700
|
}
|
|
691
701
|
|
|
702
|
+
/**
|
|
703
|
+
* Stats payload safe for SSE serialization. Excludes the random/clock-driven
|
|
704
|
+
* decorative fields (luckMeter, houseEdge, vibesQuality, timeSinceLastHit)
|
|
705
|
+
* because they tick on every call — leaving them in the payload defeats
|
|
706
|
+
* web.js's `lastPushedJson` dedup, so the full ~100 KB state is shipped to
|
|
707
|
+
* every connected client every 500 ms even when nothing has actually
|
|
708
|
+
* changed. The dashboard recomputes these client-side at render time.
|
|
709
|
+
*
|
|
710
|
+
* Stable but slow-ticking fields (sessionDuration, which changes once per
|
|
711
|
+
* minute) are kept — the cost is at most one extra push per minute.
|
|
712
|
+
*
|
|
713
|
+
* @returns {Object}
|
|
714
|
+
*/
|
|
715
|
+
function getSerializableStats() {
|
|
716
|
+
const { luckMeter, houseEdge, vibesQuality, timeSinceLastHit, ...stable } = getStats();
|
|
717
|
+
return stable;
|
|
718
|
+
}
|
|
719
|
+
|
|
692
720
|
/**
|
|
693
721
|
* Reset session stats
|
|
694
722
|
*/
|
|
@@ -778,6 +806,7 @@ module.exports = {
|
|
|
778
806
|
// Stats
|
|
779
807
|
recordPoll,
|
|
780
808
|
getStats,
|
|
809
|
+
getSerializableStats,
|
|
781
810
|
resetStats,
|
|
782
811
|
getStatsDisplay,
|
|
783
812
|
};
|
package/src/server/web-ui/js.js
CHANGED
|
@@ -1241,7 +1241,31 @@ ${pureFnBlock}
|
|
|
1241
1241
|
return left + right;
|
|
1242
1242
|
}
|
|
1243
1243
|
|
|
1244
|
+
// Decorative casino fields the server intentionally does NOT include in
|
|
1245
|
+
// the SSE payload because they're random/clock-driven and would defeat
|
|
1246
|
+
// the lastPushedJson dedup. Recompute them locally at render time so the
|
|
1247
|
+
// dashboard stays visually identical to the TUI.
|
|
1248
|
+
const CASINO_VIBES = ['\u{1f60e}','\u{1f525}','✨','\u{1f4ab}','\u{1f31f}','⚡','\u{1f3af}','\u{1f4aa}','\u{1f680}','\u{1f4af}'];
|
|
1249
|
+
function computeCasinoDecorations(cs) {
|
|
1250
|
+
const baseLuck = 50 + Math.random() * 30;
|
|
1251
|
+
const streakBonus = Math.min((cs.consecutivePolls || 0) * 5, 20);
|
|
1252
|
+
return {
|
|
1253
|
+
luckMeter: Math.min(Math.round(baseLuck + streakBonus), 99),
|
|
1254
|
+
houseEdge: Math.round(55 + Math.random() * 45),
|
|
1255
|
+
vibesQuality: CASINO_VIBES[Math.floor(Date.now() / 3000) % CASINO_VIBES.length],
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1244
1259
|
function renderCasinoStatsRow(cs) {
|
|
1260
|
+
// Server-supplied (preferred) OR locally computed (default). The
|
|
1261
|
+
// fallback covers older servers that still ship the decorative fields,
|
|
1262
|
+
// plus tests that stub them in explicitly. != null treats undefined and
|
|
1263
|
+
// null as "missing" so legitimate zero values from the server survive.
|
|
1264
|
+
const local = computeCasinoDecorations(cs);
|
|
1265
|
+
const houseEdge = (cs.houseEdge != null) ? cs.houseEdge : local.houseEdge;
|
|
1266
|
+
const luckMeter = (cs.luckMeter != null) ? cs.luckMeter : local.luckMeter;
|
|
1267
|
+
const vibesQuality = cs.vibesQuality || local.vibesQuality;
|
|
1268
|
+
|
|
1245
1269
|
const netClass = cs.netWinnings >= 0 ? 'pos' : 'neg';
|
|
1246
1270
|
const netSign = cs.netWinnings >= 0 ? '+' : '';
|
|
1247
1271
|
const stat = (k, v) => '<span class="stat"><span class="stat-k">' + k + '</span><span class="stat-v">' + v + '</span></span>';
|
|
@@ -1256,9 +1280,9 @@ ${pureFnBlock}
|
|
|
1256
1280
|
let right = '<div class="stats-group">';
|
|
1257
1281
|
right += stat('\u{1f4b8} Cost', '<span class="neg">' + dollar + (cs.totalPolls || 0) + '</span>');
|
|
1258
1282
|
right += stat('\u{1f4b0} Net', '<span class="' + netClass + '">' + netSign + dollar + (cs.netWinnings || 0) + '</span>');
|
|
1259
|
-
right += stat('\u{1f3b0} Edge', '<span class="neon">' +
|
|
1260
|
-
right += stat('\u{1f3b2} Luck', '<span class="gold">' +
|
|
1261
|
-
right += stat('\u{1f60e} Vibes', escHtml(
|
|
1283
|
+
right += stat('\u{1f3b0} Edge', '<span class="neon">' + houseEdge + '%</span>');
|
|
1284
|
+
right += stat('\u{1f3b2} Luck', '<span class="gold">' + luckMeter + '%</span>');
|
|
1285
|
+
right += stat('\u{1f60e} Vibes', escHtml(vibesQuality));
|
|
1262
1286
|
right += stat('\u{1f9e0} Hits', '<span class="pos">' + (cs.dopamineHits || 0) + '</span>');
|
|
1263
1287
|
if (cs.consecutivePolls > 1) right += stat('\u{1f525} Streak', '<span class="gold">' + cs.consecutivePolls + 'x</span>');
|
|
1264
1288
|
right += '</div>';
|
package/src/server/web.js
CHANGED
|
@@ -147,8 +147,12 @@ class WebDashboardServer {
|
|
|
147
147
|
// the mode on, so the web dashboard can render the same winnings box
|
|
148
148
|
// the terminal does. Null when disabled — keeps payload small and
|
|
149
149
|
// avoids ticking Math.random()/Date.now() into every SSE push when
|
|
150
|
-
// nobody's asked for the effect.
|
|
151
|
-
|
|
150
|
+
// nobody's asked for the effect. We use `getSerializableStats` (not
|
|
151
|
+
// the full getStats) so the random/clock-driven decorative fields
|
|
152
|
+
// (luckMeter, houseEdge, vibesQuality, timeSinceLastHit) don't
|
|
153
|
+
// defeat the lastPushedJson dedup — the dashboard recomputes them
|
|
154
|
+
// client-side from the stable counters that ARE in the payload.
|
|
155
|
+
casinoStats: s.casinoModeEnabled ? casino.getSerializableStats() : null,
|
|
152
156
|
projectName: s.projectName,
|
|
153
157
|
|
|
154
158
|
// Activity
|