Standard-rules-only leaderboard with client unranked indicators
Only standard-rules games now count toward leaderboard stats. Games with any house rule variant are marked "Unranked" in the active rules bar, and a notice appears in the lobby when house rules are selected. Also fixes game_logger duplicate options dicts (now uses dataclasses.asdict, capturing all options including previously missing ones) and refactors duplicated achievement-checking logic into shared helpers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -417,6 +417,7 @@ class GolfGame {
|
||||
this.oneEyedJacksCheckbox = document.getElementById('one-eyed-jacks');
|
||||
this.knockEarlyCheckbox = document.getElementById('knock-early');
|
||||
this.wolfpackComboNote = document.getElementById('wolfpack-combo-note');
|
||||
this.unrankedNotice = document.getElementById('unranked-notice');
|
||||
this.startGameBtn = document.getElementById('start-game-btn');
|
||||
this.leaveRoomBtn = document.getElementById('leave-room-btn');
|
||||
this.addCpuBtn = document.getElementById('add-cpu-btn');
|
||||
@@ -545,6 +546,34 @@ class GolfGame {
|
||||
this.wolfpackCheckbox.addEventListener('change', updateWolfpackCombo);
|
||||
this.fourOfAKindCheckbox.addEventListener('change', updateWolfpackCombo);
|
||||
|
||||
// Show/hide unranked notice when house rules change
|
||||
const houseRuleInputs = [
|
||||
this.flipModeSelect, this.knockPenaltyCheckbox,
|
||||
this.superKingsCheckbox, this.tenPennyCheckbox,
|
||||
this.knockBonusCheckbox, this.underdogBonusCheckbox,
|
||||
this.tiedShameCheckbox, this.blackjackCheckbox,
|
||||
this.wolfpackCheckbox, this.flipAsActionCheckbox,
|
||||
this.fourOfAKindCheckbox, this.negativePairsCheckbox,
|
||||
this.oneEyedJacksCheckbox, this.knockEarlyCheckbox,
|
||||
];
|
||||
const jokerRadios = document.querySelectorAll('input[name="joker-mode"]');
|
||||
const updateUnrankedNotice = () => {
|
||||
const hasHouseRules = (
|
||||
(this.flipModeSelect?.value && this.flipModeSelect.value !== 'never') ||
|
||||
this.knockPenaltyCheckbox?.checked ||
|
||||
(document.querySelector('input[name="joker-mode"]:checked')?.value !== 'none') ||
|
||||
this.superKingsCheckbox?.checked || this.tenPennyCheckbox?.checked ||
|
||||
this.knockBonusCheckbox?.checked || this.underdogBonusCheckbox?.checked ||
|
||||
this.tiedShameCheckbox?.checked || this.blackjackCheckbox?.checked ||
|
||||
this.wolfpackCheckbox?.checked || this.flipAsActionCheckbox?.checked ||
|
||||
this.fourOfAKindCheckbox?.checked || this.negativePairsCheckbox?.checked ||
|
||||
this.oneEyedJacksCheckbox?.checked || this.knockEarlyCheckbox?.checked
|
||||
);
|
||||
this.unrankedNotice?.classList.toggle('hidden', !hasHouseRules);
|
||||
};
|
||||
houseRuleInputs.forEach(el => el?.addEventListener('change', updateUnrankedNotice));
|
||||
jokerRadios.forEach(el => el.addEventListener('change', updateUnrankedNotice));
|
||||
|
||||
// Toggle scoreboard collapse on mobile
|
||||
const scoreboardTitle = this.scoreboard.querySelector('h4');
|
||||
if (scoreboardTitle) {
|
||||
@@ -2637,17 +2666,20 @@ class GolfGame {
|
||||
return `<span class="rule-tag" data-rule="${key}">${rule}</span>`;
|
||||
};
|
||||
|
||||
const unrankedTag = this.gameState.is_standard_rules === false
|
||||
? '<span class="rule-tag unranked">Unranked</span>' : '';
|
||||
|
||||
if (rules.length === 0) {
|
||||
this.activeRulesList.innerHTML = '<span class="rule-tag standard">Standard</span>';
|
||||
} else if (rules.length <= 2) {
|
||||
this.activeRulesList.innerHTML = rules.map(renderTag).join('');
|
||||
this.activeRulesList.innerHTML = unrankedTag + rules.map(renderTag).join('');
|
||||
} else {
|
||||
const displayed = rules.slice(0, 2);
|
||||
const hidden = rules.slice(2);
|
||||
const moreCount = hidden.length;
|
||||
const tooltip = hidden.join(', ');
|
||||
|
||||
this.activeRulesList.innerHTML = displayed.map(renderTag).join('') +
|
||||
this.activeRulesList.innerHTML = unrankedTag + displayed.map(renderTag).join('') +
|
||||
`<span class="rule-tag rule-more" title="${tooltip}">+${moreCount} more</span>`;
|
||||
}
|
||||
this.activeRulesBar.classList.remove('hidden');
|
||||
|
||||
@@ -259,6 +259,7 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div id="unranked-notice" class="unranked-notice hidden">Games with house rules are unranked and won't affect leaderboard stats.</div>
|
||||
<button id="start-game-btn" class="btn btn-primary">Start Game</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -837,6 +837,28 @@ input::placeholder {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.active-rules-bar .rule-tag.unranked {
|
||||
background: rgba(220, 80, 80, 0.3);
|
||||
color: #f08080;
|
||||
border: 1px solid rgba(220, 80, 80, 0.4);
|
||||
}
|
||||
|
||||
/* Unranked notice in waiting room */
|
||||
.unranked-notice {
|
||||
background: rgba(220, 80, 80, 0.15);
|
||||
border: 1px solid rgba(220, 80, 80, 0.3);
|
||||
color: #f0a0a0;
|
||||
font-size: 0.8rem;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
margin: 8px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.unranked-notice.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Card Styles */
|
||||
.card {
|
||||
width: clamp(65px, 5.5vw, 100px);
|
||||
|
||||
Reference in New Issue
Block a user