Add skin value and back-nine doubling to skins games

Players can now set a monetary value per skin when starting a skins game.
For 18-hole games, an option to double the value on holes 10–18 is available.
The value is stored at game creation and displayed throughout the live game
and summary (leaderboard, scorecard, and totals).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Rolf
2026-03-23 20:56:13 +01:00
parent 8601584099
commit 6317422316
5 changed files with 118 additions and 38 deletions
+20 -8
View File
@@ -241,12 +241,12 @@
</tbody>
<tfoot>
<tr class="totals-row">
<td>Skins</td>
<td x-text="SKIN_VALUE ? 'Value' : 'Skins'"></td>
{% if hole_pars %}<td></td>{% endif %}
{% for p in players %}
<td x-text="calcSkins().skins['{{ p.id }}'] || 0"></td>
<td x-text="SKIN_VALUE ? (parseFloat(calcSkins().money['{{ p.id }}'].toPrecision(4)) || 0) : (calcSkins().skins['{{ p.id }}'] || 0)"></td>
{% endfor %}
<td x-text="calcSkins().unclaimed ? '(' + calcSkins().unclaimed + ')' : ''"></td>
<td x-text="SKIN_VALUE ? (calcSkins().unclaimedMoney ? '(' + parseFloat(calcSkins().unclaimedMoney.toPrecision(4)) + ')' : '') : (calcSkins().unclaimed ? '(' + calcSkins().unclaimed + ')' : '')"></td>
</tr>
</tfoot>
</table>
@@ -278,6 +278,8 @@ const GAME_ID = "{{ game.id }}";
const GAME_HOLES = {{ game.holes_count }};
const GAME_FORMAT = "{{ game.format }}";
const SKINS_CARRYOVER = {{ carryover | tojson }};
const SKIN_VALUE = {{ skin_value | tojson }};
const SKIN_DOUBLE_BACK9 = {{ skin_double_back9 | tojson }};
const HOLE_PARS = {{ hole_pars | tojson }};
const HOLE_SIS = {{ hole_stroke_indices | tojson }};
const STROKES_PER_HOLE = {{ strokes_per_hole | tojson }};
@@ -483,9 +485,11 @@ function gameApp() {
calcSkins() {
const skins = {};
PLAYERS_DATA.forEach(p => skins[p.id] = 0);
const money = {};
PLAYERS_DATA.forEach(p => { skins[p.id] = 0; money[p.id] = 0; });
const holes = {};
let pot = 0;
let moneyPot = 0;
for (let hole = 1; hole <= GAME_HOLES; hole++) {
if (this.isSkipped(hole)) continue;
const holeScores = this.scores[hole] || {};
@@ -494,18 +498,21 @@ function gameApp() {
.filter(x => x.strokes > 0);
if (scored.length === 0) continue;
pot += 1;
if (SKIN_VALUE) moneyPot += SKIN_VALUE * (SKIN_DOUBLE_BACK9 && hole >= 10 ? 2 : 1);
const min = Math.min(...scored.map(x => x.strokes));
const winners = scored.filter(x => x.strokes === min);
if (winners.length === 1) {
skins[winners[0].id] += pot;
holes[hole] = { winner: winners[0].id, pot };
money[winners[0].id] += moneyPot;
holes[hole] = { winner: winners[0].id, pot, moneyPot };
pot = 0;
moneyPot = 0;
} else {
holes[hole] = { winner: null, pot };
if (!SKINS_CARRYOVER) pot = 0;
holes[hole] = { winner: null, pot, moneyPot };
if (!SKINS_CARRYOVER) { pot = 0; moneyPot = 0; }
}
}
return { skins, holes, unclaimed: pot };
return { skins, money, holes, unclaimed: pot, unclaimedMoney: moneyPot };
},
isSkinWinner(hole, uid) {
@@ -515,6 +522,11 @@ function gameApp() {
skinHoleLabel(hole) {
const h = this.calcSkins().holes[hole];
if (!h) return '';
if (SKIN_VALUE) {
const v = parseFloat(h.moneyPot.toPrecision(4));
if (h.winner) return '' + v;
return '→ ' + v;
}
if (h.winner) return h.pot > 1 ? '✓ ' + h.pot : '✓';
return '→ ' + h.pot;
},