骰子和猜拳

This commit is contained in:
zhx 2026-06-11 19:47:33 +08:00
parent a23e2a1007
commit bb133314cd
3 changed files with 254 additions and 4 deletions

View File

@ -785,9 +785,38 @@ var default_api = 'https://api.global-interaction.com/';
}, },
}; };
function analyticsEventID(prefix) {
var random = '';
if (window.crypto && window.crypto.getRandomValues) {
var bytes = new Uint32Array(2);
window.crypto.getRandomValues(bytes);
random = bytes[0].toString(36) + bytes[1].toString(36);
} else {
random = Math.random().toString(36).slice(2);
}
return (
String(prefix || 'self_game') +
'_' +
Date.now().toString(36) +
'_' +
random
);
}
function reportSelfGameEvent(payload) {
var body = Object.assign({}, payload || {});
body.event_id = body.event_id || analyticsEventID(body.event_name);
body.occurred_at_ms = body.occurred_at_ms || Date.now();
return request('/api/v1/games/self/report-events', {
method: 'POST',
body: body,
});
}
var gameAPI = { var gameAPI = {
dice: diceGameAPI, dice: diceGameAPI,
rps: rpsGameAPI, rps: rpsGameAPI,
reportEvent: reportSelfGameEvent,
}; };
window.HyAppAPI = { window.HyAppAPI = {

View File

@ -1556,6 +1556,7 @@
var frame = document.querySelector('.rps-frame'); var frame = document.querySelector('.rps-frame');
var timers = []; var timers = [];
var pollTimer = 0; var pollTimer = 0;
var pageStartedAt = performance.now();
var transparentPixel = var transparentPixel =
'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%221%22 height=%221%22%2F%3E'; 'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%221%22 height=%221%22%2F%3E';
var gestures = { var gestures = {
@ -1595,6 +1596,26 @@
serverTimeMS: 0, serverTimeMS: 0,
}; };
function trackSelfGameEvent(name, extra) {
var api =
window.HyAppAPI &&
window.HyAppAPI.game &&
window.HyAppAPI.game.reportEvent;
if (typeof api !== 'function') return;
var payload = Object.assign(
{
event_name: name,
game_id: GAME_ID,
page: 'game/rock',
h5_version: 'rock-h5-20260611',
entry_source: currentRoomID() ? 'room' : 'direct',
success: true,
},
extra || {}
);
api(payload).catch(function () {});
}
function updateScale() { function updateScale() {
var scale = Math.min( var scale = Math.min(
window.innerWidth / DESIGN_WIDTH, window.innerWidth / DESIGN_WIDTH,
@ -2263,12 +2284,24 @@
resetToLobby(); resetToLobby();
return; return;
} }
trackSelfGameEvent('reveal_enter', {
match_id: matchID,
gesture: state.selectedGesture,
});
var rollStartedAt = performance.now();
rpsAPI() rpsAPI()
.roll(matchID, { .roll(matchID, {
game_id: GAME_ID, game_id: GAME_ID,
gesture: state.selectedGesture, gesture: state.selectedGesture,
}) })
.then(function (data) { .then(function (data) {
trackSelfGameEvent('roll_api', {
match_id: matchID,
gesture: state.selectedGesture,
duration_ms: Math.round(
performance.now() - rollStartedAt
),
});
var nextMatch = matchFromData(data); var nextMatch = matchFromData(data);
if (roundID !== state.roundID) return; if (roundID !== state.roundID) return;
state.match = nextMatch || match; state.match = nextMatch || match;
@ -2276,6 +2309,15 @@
showBattle(roundID, state.match); showBattle(roundID, state.match);
}) })
.catch(function (error) { .catch(function (error) {
trackSelfGameEvent('roll_api', {
match_id: matchID,
gesture: state.selectedGesture,
duration_ms: Math.round(
performance.now() - rollStartedAt
),
success: false,
error_code: error && error.message,
});
showMessage(error.message); showMessage(error.message);
resetToLobby(); resetToLobby();
}); });
@ -2329,6 +2371,11 @@
stake_coin: state.selectedStake, stake_coin: state.selectedStake,
gesture: state.selectedGesture, gesture: state.selectedGesture,
}); });
trackSelfGameEvent('match_click', {
stake_coin: state.selectedStake,
gesture: state.selectedGesture,
mode: matchRequestMode(),
});
var payload = { var payload = {
game_id: GAME_ID, game_id: GAME_ID,
room_id: currentRoomID(), room_id: currentRoomID(),
@ -2348,7 +2395,30 @@
} else { } else {
request = rpsAPI().match(payload); request = rpsAPI().match(payload);
} }
request.then(handleMatchData).catch(function (error) { var matchStartedAt = performance.now();
request
.then(function (data) {
var match = matchFromData(data);
trackSelfGameEvent('match_success', {
match_id: match && (match.match_id || match.matchId),
stake_coin: state.selectedStake,
gesture: state.selectedGesture,
duration_ms: Math.round(
performance.now() - matchStartedAt
),
});
handleMatchData(data);
})
.catch(function (error) {
trackSelfGameEvent('match_api', {
stake_coin: state.selectedStake,
gesture: state.selectedGesture,
duration_ms: Math.round(
performance.now() - matchStartedAt
),
success: false,
error_code: error && error.message,
});
state.busy = false; state.busy = false;
showMessage(error.message); showMessage(error.message);
setScreen('lobby'); setScreen('lobby');
@ -2440,6 +2510,12 @@
if (match) renderMatch(match); if (match) renderMatch(match);
renderVictory(result, match); renderVictory(result, match);
setScreen('victory'); setScreen('victory');
trackSelfGameEvent('settlement_show', {
match_id: match && (match.match_id || match.matchId),
result: result,
gesture: state.selectedGesture,
stake_coin: state.selectedStake,
});
postBridge('gameRPSSettled', { postBridge('gameRPSSettled', {
game_code: GAME_CODE, game_code: GAME_CODE,
game_id: GAME_ID, game_id: GAME_ID,
@ -2471,7 +2547,18 @@
} }
return rpsAPI() return rpsAPI()
.cancel(matchID) .cancel(matchID)
.catch(function () {}); .then(function () {
trackSelfGameEvent('match_cancel', {
match_id: matchID,
});
})
.catch(function () {
trackSelfGameEvent('cancel_api', {
match_id: matchID,
success: false,
error_code: 'cancel_failed',
});
});
} }
function openRecharge() { function openRecharge() {
@ -2544,9 +2631,15 @@
renderStakeOptions(state.config); renderStakeOptions(state.config);
return Promise.resolve(); return Promise.resolve();
} }
var configStartedAt = performance.now();
return rpsAPI() return rpsAPI()
.config(GAME_ID) .config(GAME_ID)
.then(function (data) { .then(function (data) {
trackSelfGameEvent('config_load_success', {
duration_ms: Math.round(
performance.now() - configStartedAt
),
});
state.config = state.config =
(data && (data.config || data.rps_config)) || (data && (data.config || data.rps_config)) ||
data || data ||
@ -2554,6 +2647,13 @@
renderStakeOptions(state.config); renderStakeOptions(state.config);
}) })
.catch(function () { .catch(function () {
trackSelfGameEvent('config_load_fail', {
duration_ms: Math.round(
performance.now() - configStartedAt
),
success: false,
error_code: 'config_failed',
});
renderStakeOptions(state.config); renderStakeOptions(state.config);
}); });
} }
@ -2591,6 +2691,9 @@
state.selectedGesture = state.selectedGesture =
target.getAttribute('data-gesture') || 'rock'; target.getAttribute('data-gesture') || 'rock';
renderSelection(); renderSelection();
trackSelfGameEvent('gesture_select', {
gesture: state.selectedGesture,
});
return; return;
} }
if (action === 'stake') { if (action === 'stake') {
@ -2609,6 +2712,9 @@
); );
} }
); );
trackSelfGameEvent('stake_select', {
stake_coin: state.selectedStake,
});
return; return;
} }
if (action === 'start') { if (action === 'start') {
@ -2627,11 +2733,21 @@
if (action === 'rematch') { if (action === 'rematch') {
cancelMatch().then(function () { cancelMatch().then(function () {
resetToLobby(); resetToLobby();
trackSelfGameEvent('play_again', {
source: 'rematch',
stake_coin: state.selectedStake,
gesture: state.selectedGesture,
});
startMatch(); startMatch();
}); });
return; return;
} }
if (action === 'play-again') { if (action === 'play-again') {
trackSelfGameEvent('play_again', {
source: 'settlement',
stake_coin: state.selectedStake,
gesture: state.selectedGesture,
});
resetToLobby(); resetToLobby();
} }
}); });
@ -2669,6 +2785,9 @@
updateScale(); updateScale();
initActions(); initActions();
trackSelfGameEvent('page_open', {
duration_ms: Math.round(performance.now() - pageStartedAt),
});
window.addEventListener('beforeunload', function () { window.addEventListener('beforeunload', function () {
cancelMatch(); cancelMatch();
}); });

View File

@ -2434,6 +2434,7 @@
var timers = []; var timers = [];
var pollTimer = 0; var pollTimer = 0;
var roundSequence = 0; var roundSequence = 0;
var pageStartedAt = performance.now();
var rollEffectPlayers = { var rollEffectPlayers = {
self: null, self: null,
opponent: null, opponent: null,
@ -2450,6 +2451,26 @@
serverTimeMS: 0, serverTimeMS: 0,
}; };
function trackSelfGameEvent(name, extra) {
var api =
window.HyAppAPI &&
window.HyAppAPI.game &&
window.HyAppAPI.game.reportEvent;
if (typeof api !== 'function') return;
var payload = Object.assign(
{
event_name: name,
game_id: 'dice',
page: 'game/touzi',
h5_version: 'dice-h5-20260611',
entry_source: currentRoomID() ? 'room' : 'direct',
success: true,
},
extra || {}
);
api(payload).catch(function () {});
}
function updateScale() { function updateScale() {
var scale = Math.min( var scale = Math.min(
window.innerWidth / DESIGN_WIDTH, window.innerWidth / DESIGN_WIDTH,
@ -3266,6 +3287,9 @@
setPhaseText(i18nText('diceMatch.rolling', 'Rolling...')); setPhaseText(i18nText('diceMatch.rolling', 'Rolling...'));
frame.classList.remove('has-scores'); frame.classList.remove('has-scores');
playRollEffects(); playRollEffects();
trackSelfGameEvent('reveal_enter', {
match_id: matchID,
});
postBridge('gameDiceRolling', { postBridge('gameDiceRolling', {
game_code: 'touzi', game_code: 'touzi',
match_id: matchID, match_id: matchID,
@ -3273,9 +3297,18 @@
var rollPromise = game var rollPromise = game
.roll(matchID) .roll(matchID)
.then(function (data) { .then(function (data) {
trackSelfGameEvent('roll_api', {
match_id: matchID,
success: true,
});
return matchFromData(data); return matchFromData(data);
}) })
.catch(function () { .catch(function () {
trackSelfGameEvent('roll_api', {
match_id: matchID,
success: false,
error_code: 'roll_failed',
});
return game.getMatch(matchID).then(function (data) { return game.getMatch(matchID).then(function (data) {
return matchFromData(data); return matchFromData(data);
}); });
@ -3370,6 +3403,10 @@
frame.classList.add('is-victory'); frame.classList.add('is-victory');
renderVictory(match); renderVictory(match);
refreshBalance(); refreshBalance();
trackSelfGameEvent('settlement_show', {
match_id: match.match_id,
result: match.result,
});
postBridge('gameDiceSettled', { postBridge('gameDiceSettled', {
game_code: 'touzi', game_code: 'touzi',
match_id: match.match_id, match_id: match.match_id,
@ -3450,13 +3487,35 @@
game_code: 'touzi', game_code: 'touzi',
stake: stake, stake: stake,
}); });
trackSelfGameEvent('match_click', {
stake_coin: stake,
});
var matchStartedAt = performance.now();
game.match({ game.match({
game_id: 'dice', game_id: 'dice',
room_id: currentRoomID(), room_id: currentRoomID(),
stake_coin: stake, stake_coin: stake,
}) })
.then(handleMatchData) .then(function (data) {
var match = matchFromData(data);
trackSelfGameEvent('match_success', {
match_id: match && match.match_id,
stake_coin: stake,
duration_ms: Math.round(
performance.now() - matchStartedAt
),
});
handleMatchData(data);
})
.catch(function (error) { .catch(function (error) {
trackSelfGameEvent('match_api', {
stake_coin: stake,
duration_ms: Math.round(
performance.now() - matchStartedAt
),
success: false,
error_code: error && error.message,
});
showMessage(error.message); showMessage(error.message);
resetToLobby(true); resetToLobby(true);
}); });
@ -3473,7 +3532,20 @@
) { ) {
return Promise.resolve(); return Promise.resolve();
} }
return game.cancel(match.match_id).catch(function () {}); return game
.cancel(match.match_id)
.then(function () {
trackSelfGameEvent('match_cancel', {
match_id: match.match_id,
});
})
.catch(function () {
trackSelfGameEvent('cancel_api', {
match_id: match.match_id,
success: false,
error_code: 'cancel_failed',
});
});
} }
function resetToLobby(keepStake) { function resetToLobby(keepStake) {
@ -3537,6 +3609,7 @@
true, true,
i18nText('diceMatch.loading', 'Loading') i18nText('diceMatch.loading', 'Loading')
); );
var configStartedAt = performance.now();
Promise.all([ Promise.all([
api() api()
.user.me() .user.me()
@ -3555,7 +3628,22 @@
}), }),
diceAPI() diceAPI()
.config('dice') .config('dice')
.then(function (data) {
trackSelfGameEvent('config_load_success', {
duration_ms: Math.round(
performance.now() - configStartedAt
),
});
return data;
})
.catch(function () { .catch(function () {
trackSelfGameEvent('config_load_fail', {
duration_ms: Math.round(
performance.now() - configStartedAt
),
success: false,
error_code: 'config_failed',
});
return null; return null;
}), }),
]).then(function (results) { ]).then(function (results) {
@ -3589,6 +3677,9 @@
if (action === 'stake') { if (action === 'stake') {
if (state.busy) return; if (state.busy) return;
selectStake(target); selectStake(target);
trackSelfGameEvent('stake_select', {
stake_coin: state.selectedStake,
});
return; return;
} }
if (action === 'match') { if (action === 'match') {
@ -3601,6 +3692,10 @@
postBridge('gameRematch', { postBridge('gameRematch', {
game_code: 'touzi', game_code: 'touzi',
}); });
trackSelfGameEvent('play_again', {
source: 'rematch',
stake_coin: state.selectedStake,
});
startMatch(); startMatch();
}); });
return; return;
@ -3611,6 +3706,10 @@
postBridge('gamePlayAgain', { postBridge('gamePlayAgain', {
game_code: 'touzi', game_code: 'touzi',
}); });
trackSelfGameEvent('play_again', {
source: 'settlement',
stake_coin: state.selectedStake,
});
}); });
} }
}); });
@ -3621,6 +3720,9 @@
updateScale(); updateScale();
initActions(); initActions();
trackSelfGameEvent('page_open', {
duration_ms: Math.round(performance.now() - pageStartedAt),
});
window.addEventListener( window.addEventListener(
'hyapp:i18n-ready', 'hyapp:i18n-ready',
refreshLocalizedRuntimeText refreshLocalizedRuntimeText