-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgameState.js
More file actions
128 lines (121 loc) · 3.68 KB
/
Copy pathgameState.js
File metadata and controls
128 lines (121 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// gameState.js — game state helpers and data structures
/** @returns {object} Fresh GameState for a new session */
export function createGameState() {
return {
wins: 0,
losses: 0,
unresolved: 0,
totalWagered: 0,
netResult: 0,
receipts: [],
currentRound: null, // ActiveRound | null
};
}
/**
* Build a Receipt object for a completed round.
* @param {object} question
* @param {'win'|'loss'|'unresolved'} outcome
* @param {number} hbarAmount
* @param {string} transactionId
* @returns {object}
*/
export function buildReceipt(question, outcome, hbarAmount, transactionId) {
return {
question: question.text,
correctAnswer: `${question.answer}) ${question.choices[question.answer]}`,
outcome,
hbarAmount,
transactionId,
timestamp: new Date(),
};
}
/**
* Update session stats after a round completes.
* Mutates gameState in place.
* @param {object} gameState
* @param {'win'|'loss'|'unresolved'} outcome
* @param {number} entryFeeHbar
* @param {number} payoutHbar
*/
export function updateStats(gameState, outcome, entryFeeHbar, payoutHbar) {
gameState.totalWagered += entryFeeHbar;
if (outcome === 'win') {
gameState.wins += 1;
gameState.netResult += payoutHbar - entryFeeHbar;
} else if (outcome === 'loss') {
gameState.losses += 1;
gameState.netResult -= entryFeeHbar;
} else {
gameState.unresolved += 1;
}
}
/**
* Check if the player can afford the entry fee.
* @param {number} balance
* @param {number} entryFee
* @returns {boolean}
*/
export function canAfford(balance, entryFee) {
return balance >= entryFee;
}
/**
* Format session stats for display.
* @param {object} gameState
* @returns {string}
*/
export function formatStats(gameState) {
const total = gameState.wins + gameState.losses + gameState.unresolved;
if (total === 0) {
return '📊 No rounds played yet this session. Type "play" to start!';
}
const sign = gameState.netResult >= 0 ? '+' : '';
return [
'📊 SESSION STATS',
` 🏆 Wins: ${gameState.wins}`,
` 💸 Losses: ${gameState.losses}`,
` ❓ Unresolved: ${gameState.unresolved}`,
` 💰 Total wagered: ${gameState.totalWagered} HBAR`,
` 📈 Net result: ${sign}${gameState.netResult.toFixed(2)} HBAR`,
].join('\n');
}
/**
* Format receipt history for display.
* @param {object} gameState
* @returns {string}
*/
export function formatReceipts(gameState) {
if (gameState.receipts.length === 0) {
return '📜 No rounds completed yet this session.';
}
return gameState.receipts
.map((r, i) => {
const icon = r.outcome === 'win' ? '🏆' : r.outcome === 'loss' ? '💸' : '❓';
return [
`\n--- Round ${i + 1} ${icon} ---`,
`Q: ${r.question}`,
`Answer: ${r.correctAnswer}`,
`Result: ${r.outcome.toUpperCase()} | ${r.hbarAmount} HBAR`,
`Tx ID: ${r.transactionId}`,
`Time: ${r.timestamp.toLocaleTimeString()}`,
].join('\n');
})
.join('\n');
}
/**
* Build the closing message shown on exit.
* @param {object} gameState
* @returns {string}
*/
export function buildClosingMessage(gameState) {
const total = gameState.wins + gameState.losses + gameState.unresolved;
if (total === 0) {
return "👋 Thanks for stopping by our Trivia! Come back again. Stay hashed out there!";
}
const sign = gameState.netResult >= 0 ? '+' : '';
return [
"🎬 That's a wrap on today's episode of Hash Gordon's Blockchain Bonanza!",
` Final score: ${gameState.wins} wins, ${gameState.losses} losses`,
` Net result: ${sign}${gameState.netResult.toFixed(2)} HBAR`,
" Until next time — stay decentralized! 🔗✨",
].join('\n');
}