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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147 | export const CONSENT_CATEGORIES = {
necessary: {
label: 'Necessary',
description: 'Required to run the game, remember this session, and keep controls working.',
required: true,
},
analytics: {
label: 'Analytics',
description: 'Allows browser and play-style measurements for the end-of-game receipt.',
required: false,
},
personalization: {
label: 'Personalization',
description: 'Allows the game to adapt visuals, dialogue, ads, and difficulty to detected signals.',
required: false,
},
marketing: {
label: 'Marketing',
description: 'Allows simulated targeted ads and a mock advertising profile. Nothing is sent to advertisers.',
required: false,
},
};
export const ZONE_DEFINITIONS = [
{
key: 'Zone1Scene',
zone: 1,
title: 'The Homepage',
duration: 34,
orientation: 'horizontal',
palette: { sky: 0xf7f3ff, ground: 0xffffff, accent: 0x7c5cff, danger: 0xff7a90 },
guide: 'Welcome! I am here to make your experience amazing. Just be yourself!',
},
{
key: 'Zone2Scene',
zone: 2,
title: 'The Social Feed',
duration: 48,
orientation: 'vertical',
palette: { sky: 0x201339, ground: 0xff7cc8, accent: 0x7c5cff, danger: 0x47e5bc },
guide: 'Great engagement! Your friends are going to love this.',
},
{
key: 'Zone3Scene',
zone: 3,
title: 'The Marketplace',
duration: 58,
orientation: 'horizontal',
palette: { sky: 0x2b1300, ground: 0xffb000, accent: 0xff3d00, danger: 0xff004d },
guide: 'Based on your activity, I found some things you will love.',
},
{
key: 'Zone4Scene',
zone: 4,
title: 'The Algorithm',
duration: 48,
orientation: 'horizontal',
palette: { sky: 0x06080e, ground: 0xd9e3ff, accent: 0x61f3ff, danger: 0xffffff },
guide: 'I know what you want before you do. Convenient, right?',
},
{
key: 'Zone5Scene',
zone: 5,
title: 'Terms of Service',
duration: 36,
orientation: 'vertical',
palette: { sky: 0x050505, ground: 0x111111, accent: 0xffffff, danger: 0xff3535 },
guide: 'You agreed to this in Section 14.3(b). Would you like to review?',
},
];
export function createSession() {
const now = Date.now();
return {
id: randomHex(12),
startedAt: now,
endedAt: null,
replayPrivacyMode: new URLSearchParams(window.location.search).get('privacy') === '1',
consent: {
necessary: true,
analytics: false,
personalization: false,
marketing: false,
},
consentTelemetry: {
choice: 'not submitted',
decisionMs: 0,
scrolled: false,
maxScrollDepth: 0,
clickPath: [],
},
device: {},
geo: {},
adblock: { detected: null, tested: false },
incognito: { detected: null, reason: 'Not tested' },
behavioral: {
jumps: 0,
leftMoves: 0,
rightMoves: 0,
reactionSamples: [],
deaths: 0,
rageTaps: 0,
idleMs: 0,
longestIdleMs: 0,
posts: 0,
lurks: 0,
purchases: [],
promptDecisions: [],
termsRead: false,
optOutFound: false,
},
currencies: {
cookies: 0,
convenience: 0,
dataShadow: 0,
},
flags: {
notificationBadges: false,
sharedLocation: false,
syncedContacts: false,
personalized: false,
agreedTerms: false,
},
doppelgangers: [],
zoneHistory: [],
profile: null,
};
}
export function formatDuration(ms) {
const total = Math.max(0, Math.round(ms / 1000));
const minutes = Math.floor(total / 60);
const seconds = String(total % 60).padStart(2, '0');
return `${minutes}:${seconds}`;
}
export function randomHex(bytes) {
const values = new Uint8Array(bytes);
crypto.getRandomValues(values);
return Array.from(values, (value) => value.toString(16).padStart(2, '0')).join('');
}
export function boolText(value) {
if (value === true) return 'Yes';
if (value === false) return 'No';
return 'Unknown';
}
|