骰子和猜拳

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 = {
dice: diceGameAPI,
rps: rpsGameAPI,
reportEvent: reportSelfGameEvent,
};
window.HyAppAPI = {

View File

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

View File

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