playe-developer-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/README.md +341 -0
- package/dist/index.cjs.js +759 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +458 -0
- package/dist/index.esm.js +748 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/playe-sdk.umd.js +765 -0
- package/dist/playe-sdk.umd.js.map +1 -0
- package/dist/playe-sdk.umd.min.js +2 -0
- package/dist/playe-sdk.umd.min.js.map +1 -0
- package/examples/basic-usage.ts +170 -0
- package/examples/browser-example.html +520 -0
- package/examples/cdn-usage.html +425 -0
- package/package.json +90 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Playe Developer SDK - Browser Example</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: Arial, sans-serif;
|
|
10
|
+
max-width: 800px;
|
|
11
|
+
margin: 0 auto;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
background-color: #f5f5f5;
|
|
14
|
+
}
|
|
15
|
+
.container {
|
|
16
|
+
background: white;
|
|
17
|
+
padding: 20px;
|
|
18
|
+
border-radius: 8px;
|
|
19
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
20
|
+
}
|
|
21
|
+
button {
|
|
22
|
+
background: #007bff;
|
|
23
|
+
color: white;
|
|
24
|
+
border: none;
|
|
25
|
+
padding: 10px 20px;
|
|
26
|
+
border-radius: 4px;
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
margin: 5px;
|
|
29
|
+
}
|
|
30
|
+
button:hover {
|
|
31
|
+
background: #0056b3;
|
|
32
|
+
}
|
|
33
|
+
button:disabled {
|
|
34
|
+
background: #ccc;
|
|
35
|
+
cursor: not-allowed;
|
|
36
|
+
}
|
|
37
|
+
.log {
|
|
38
|
+
background: #f8f9fa;
|
|
39
|
+
border: 1px solid #dee2e6;
|
|
40
|
+
border-radius: 4px;
|
|
41
|
+
padding: 10px;
|
|
42
|
+
margin: 10px 0;
|
|
43
|
+
height: 300px;
|
|
44
|
+
overflow-y: auto;
|
|
45
|
+
font-family: monospace;
|
|
46
|
+
font-size: 12px;
|
|
47
|
+
}
|
|
48
|
+
.status {
|
|
49
|
+
padding: 10px;
|
|
50
|
+
margin: 10px 0;
|
|
51
|
+
border-radius: 4px;
|
|
52
|
+
}
|
|
53
|
+
.status.info { background: #d1ecf1; border: 1px solid #bee5eb; }
|
|
54
|
+
.status.success { background: #d4edda; border: 1px solid #c3e6cb; }
|
|
55
|
+
.status.error { background: #f8d7da; border: 1px solid #f5c6cb; }
|
|
56
|
+
.game-area {
|
|
57
|
+
border: 2px solid #007bff;
|
|
58
|
+
border-radius: 8px;
|
|
59
|
+
padding: 20px;
|
|
60
|
+
margin: 20px 0;
|
|
61
|
+
text-align: center;
|
|
62
|
+
min-height: 200px;
|
|
63
|
+
background: linear-gradient(45deg, #f0f8ff, #e6f3ff);
|
|
64
|
+
}
|
|
65
|
+
.score {
|
|
66
|
+
font-size: 24px;
|
|
67
|
+
font-weight: bold;
|
|
68
|
+
color: #007bff;
|
|
69
|
+
}
|
|
70
|
+
.progress-bar {
|
|
71
|
+
width: 100%;
|
|
72
|
+
height: 20px;
|
|
73
|
+
background: #e9ecef;
|
|
74
|
+
border-radius: 10px;
|
|
75
|
+
overflow: hidden;
|
|
76
|
+
margin: 10px 0;
|
|
77
|
+
}
|
|
78
|
+
.progress-fill {
|
|
79
|
+
height: 100%;
|
|
80
|
+
background: #28a745;
|
|
81
|
+
transition: width 0.3s ease;
|
|
82
|
+
}
|
|
83
|
+
</style>
|
|
84
|
+
</head>
|
|
85
|
+
<body>
|
|
86
|
+
<div class="container">
|
|
87
|
+
<h1>🎮 Playe Developer SDK - Browser Example</h1>
|
|
88
|
+
|
|
89
|
+
<div class="status info">
|
|
90
|
+
<strong>Status:</strong> <span id="status">Ready to initialize</span>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div>
|
|
94
|
+
<button id="initBtn">Initialize SDK</button>
|
|
95
|
+
<button id="testBtn" disabled>Test SDK</button>
|
|
96
|
+
<button id="startGameBtn" disabled>Start Game</button>
|
|
97
|
+
<button id="simulateGameBtn" disabled>Simulate Game</button>
|
|
98
|
+
<button id="leaderboardBtn" disabled>Get Leaderboard</button>
|
|
99
|
+
<button id="clearLogBtn">Clear Log</button>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div class="game-area" id="gameArea" style="display: none;">
|
|
103
|
+
<h3>🎯 Game Simulation</h3>
|
|
104
|
+
<div class="score">Score: <span id="currentScore">0</span></div>
|
|
105
|
+
<div class="progress-bar">
|
|
106
|
+
<div class="progress-fill" id="progressFill" style="width: 0%;"></div>
|
|
107
|
+
</div>
|
|
108
|
+
<p>Level: <span id="currentLevel">1</span> | Lives: <span id="currentLives">3</span></p>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div class="log" id="logArea"></div>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<script type="module">
|
|
115
|
+
// Note: In a real implementation, you would import the SDK from a built bundle
|
|
116
|
+
// import { createPlayeSDK, DeviceUtils } from '@workspace/playe-developer-sdk';
|
|
117
|
+
|
|
118
|
+
// For this example, we'll simulate the SDK interface
|
|
119
|
+
class MockPlayeSDK {
|
|
120
|
+
constructor(config) {
|
|
121
|
+
this.config = config;
|
|
122
|
+
this.sessionId = null;
|
|
123
|
+
this.isInitialized = false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
test(message) {
|
|
127
|
+
log('info', `[SDK Test] ${message || 'SDK is working!'}`);
|
|
128
|
+
log('info', `[SDK Test] Config: ${JSON.stringify(this.config, null, 2)}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async initializeGameSession(params) {
|
|
132
|
+
log('info', 'Initializing game session...');
|
|
133
|
+
await delay(1000);
|
|
134
|
+
|
|
135
|
+
const sessionId = 'session_' + Math.random().toString(36).substr(2, 9);
|
|
136
|
+
this.sessionId = sessionId;
|
|
137
|
+
|
|
138
|
+
const response = {
|
|
139
|
+
sessionId,
|
|
140
|
+
campaignId: params.campaignId,
|
|
141
|
+
gameId: params.gameId,
|
|
142
|
+
status: 'initialized',
|
|
143
|
+
campaign: {
|
|
144
|
+
id: params.campaignId,
|
|
145
|
+
name: 'Example Campaign',
|
|
146
|
+
style: 'Leaderboard',
|
|
147
|
+
status: 'active',
|
|
148
|
+
totalPrizePool: 1000,
|
|
149
|
+
maxAttempts: 3,
|
|
150
|
+
requiresGPS: false,
|
|
151
|
+
requiresFingerprint: true,
|
|
152
|
+
requiresOCR: false,
|
|
153
|
+
},
|
|
154
|
+
player: {
|
|
155
|
+
id: 'player_123',
|
|
156
|
+
email: params.playerEmail,
|
|
157
|
+
fingerprint: params.playerFingerprint,
|
|
158
|
+
attemptsUsed: 1,
|
|
159
|
+
attemptsRemaining: 2,
|
|
160
|
+
completedSessions: [],
|
|
161
|
+
},
|
|
162
|
+
createdAt: new Date().toISOString(),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
log('success', `Game session initialized: ${sessionId}`);
|
|
166
|
+
return response;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async startGameSession(sessionId, config) {
|
|
170
|
+
log('info', `Starting game session: ${sessionId}`);
|
|
171
|
+
await delay(500);
|
|
172
|
+
|
|
173
|
+
log('success', 'Game session started successfully');
|
|
174
|
+
return { status: 'started', sessionId, config };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async updateGameProgress(sessionId, progressData) {
|
|
178
|
+
log('info', `Updating progress - Score: ${progressData.currentScore}`);
|
|
179
|
+
await delay(200);
|
|
180
|
+
|
|
181
|
+
const response = {
|
|
182
|
+
isValid: true,
|
|
183
|
+
currentRank: Math.floor(Math.random() * 10) + 1,
|
|
184
|
+
isLeading: progressData.currentScore > 2000,
|
|
185
|
+
campaignStatus: {
|
|
186
|
+
remainingPrizes: 5,
|
|
187
|
+
totalWinners: 3,
|
|
188
|
+
acceptingNewPlayers: true,
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
log('info', `Current rank: ${response.currentRank}`);
|
|
193
|
+
return response;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async completeGame(sessionId, completionData) {
|
|
197
|
+
log('info', `Completing game - Final Score: ${completionData.finalScore}`);
|
|
198
|
+
await delay(1000);
|
|
199
|
+
|
|
200
|
+
const isWinner = completionData.finalScore > 2000;
|
|
201
|
+
const response = {
|
|
202
|
+
isWinner,
|
|
203
|
+
prizeAmount: isWinner ? 100 : 0,
|
|
204
|
+
prizeType: isWinner ? 'cash' : null,
|
|
205
|
+
finalRank: Math.floor(Math.random() * 10) + 1,
|
|
206
|
+
totalParticipants: 50,
|
|
207
|
+
winnerDetails: isWinner ? {
|
|
208
|
+
position: 1,
|
|
209
|
+
wonAt: new Date().toISOString(),
|
|
210
|
+
isInstantWin: false,
|
|
211
|
+
} : null,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
if (isWinner) {
|
|
215
|
+
log('success', `🎉 Congratulations! You won $${response.prizeAmount}!`);
|
|
216
|
+
} else {
|
|
217
|
+
log('info', `Good try! Final rank: ${response.finalRank}`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return response;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async getLeaderboard(campaignId, limit) {
|
|
224
|
+
log('info', 'Fetching leaderboard...');
|
|
225
|
+
await delay(500);
|
|
226
|
+
|
|
227
|
+
const entries = Array.from({ length: limit || 10 }, (_, i) => ({
|
|
228
|
+
rank: i + 1,
|
|
229
|
+
playerId: `player_${i + 1}`,
|
|
230
|
+
displayName: `Player ${i + 1}`,
|
|
231
|
+
score: Math.floor(Math.random() * 3000) + 1000,
|
|
232
|
+
achievedAt: new Date(Date.now() - Math.random() * 86400000).toISOString(),
|
|
233
|
+
isCurrentPlayer: i === 2, // Make 3rd place the current player
|
|
234
|
+
prizeAmount: i < 3 ? [100, 50, 25][i] : 0,
|
|
235
|
+
}));
|
|
236
|
+
|
|
237
|
+
const response = {
|
|
238
|
+
campaignId,
|
|
239
|
+
entries,
|
|
240
|
+
playerRank: {
|
|
241
|
+
currentRank: 3,
|
|
242
|
+
score: entries[2].score,
|
|
243
|
+
ranksFromTop: 2,
|
|
244
|
+
ranksFromPrize: 0,
|
|
245
|
+
isInPrizePosition: true,
|
|
246
|
+
},
|
|
247
|
+
lastUpdated: new Date().toISOString(),
|
|
248
|
+
isLive: true,
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
log('success', 'Leaderboard fetched successfully');
|
|
252
|
+
log('info', `Your rank: ${response.playerRank.currentRank}`);
|
|
253
|
+
return response;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
destroy() {
|
|
257
|
+
log('info', 'SDK destroyed');
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Mock DeviceUtils
|
|
262
|
+
const DeviceUtils = {
|
|
263
|
+
getDeviceInfo() {
|
|
264
|
+
return {
|
|
265
|
+
userAgent: navigator.userAgent,
|
|
266
|
+
platform: navigator.platform,
|
|
267
|
+
language: navigator.language,
|
|
268
|
+
touchSupported: 'ontouchstart' in window,
|
|
269
|
+
screenResolution: `${screen.width}x${screen.height}`,
|
|
270
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
271
|
+
};
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
generateFingerprint() {
|
|
275
|
+
const components = [
|
|
276
|
+
navigator.userAgent,
|
|
277
|
+
navigator.language,
|
|
278
|
+
navigator.platform,
|
|
279
|
+
`${screen.width}x${screen.height}`,
|
|
280
|
+
new Date().getTimezoneOffset().toString(),
|
|
281
|
+
];
|
|
282
|
+
|
|
283
|
+
const str = components.join('|');
|
|
284
|
+
let hash = 0;
|
|
285
|
+
for (let i = 0; i < str.length; i++) {
|
|
286
|
+
const char = str.charCodeAt(i);
|
|
287
|
+
hash = ((hash << 5) - hash) + char;
|
|
288
|
+
hash = hash & hash;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return Math.abs(hash).toString(36);
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// Helper functions
|
|
296
|
+
function delay(ms) {
|
|
297
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function log(type, message) {
|
|
301
|
+
const logArea = document.getElementById('logArea');
|
|
302
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
303
|
+
const logEntry = document.createElement('div');
|
|
304
|
+
logEntry.innerHTML = `<span style="color: #666;">[${timestamp}]</span> ${message}`;
|
|
305
|
+
logArea.appendChild(logEntry);
|
|
306
|
+
logArea.scrollTop = logArea.scrollHeight;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function updateStatus(message, type = 'info') {
|
|
310
|
+
const statusEl = document.getElementById('status');
|
|
311
|
+
const statusContainer = statusEl.parentElement;
|
|
312
|
+
statusEl.textContent = message;
|
|
313
|
+
statusContainer.className = `status ${type}`;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Game simulation
|
|
317
|
+
let gameInterval;
|
|
318
|
+
let currentScore = 0;
|
|
319
|
+
let currentLevel = 1;
|
|
320
|
+
let currentLives = 3;
|
|
321
|
+
|
|
322
|
+
function updateGameDisplay() {
|
|
323
|
+
document.getElementById('currentScore').textContent = currentScore;
|
|
324
|
+
document.getElementById('currentLevel').textContent = currentLevel;
|
|
325
|
+
document.getElementById('currentLives').textContent = currentLives;
|
|
326
|
+
|
|
327
|
+
const progress = Math.min((currentScore / 3000) * 100, 100);
|
|
328
|
+
document.getElementById('progressFill').style.width = `${progress}%`;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Main application
|
|
332
|
+
let sdk = null;
|
|
333
|
+
let currentSession = null;
|
|
334
|
+
|
|
335
|
+
// Event listeners
|
|
336
|
+
document.getElementById('initBtn').addEventListener('click', async () => {
|
|
337
|
+
try {
|
|
338
|
+
updateStatus('Initializing SDK...', 'info');
|
|
339
|
+
|
|
340
|
+
// Initialize SDK
|
|
341
|
+
sdk = new MockPlayeSDK({
|
|
342
|
+
apiBaseUrl: 'https://api.playe.com',
|
|
343
|
+
apiKey: 'demo-key-12345',
|
|
344
|
+
enableDebugMode: true,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
log('success', 'SDK initialized successfully');
|
|
348
|
+
updateStatus('SDK initialized', 'success');
|
|
349
|
+
|
|
350
|
+
document.getElementById('initBtn').disabled = true;
|
|
351
|
+
document.getElementById('testBtn').disabled = false;
|
|
352
|
+
document.getElementById('startGameBtn').disabled = false;
|
|
353
|
+
document.getElementById('leaderboardBtn').disabled = false;
|
|
354
|
+
|
|
355
|
+
} catch (error) {
|
|
356
|
+
log('error', `Failed to initialize SDK: ${error.message}`);
|
|
357
|
+
updateStatus('Initialization failed', 'error');
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
document.getElementById('testBtn').addEventListener('click', () => {
|
|
362
|
+
if (sdk) {
|
|
363
|
+
sdk.test('Browser SDK test successful!');
|
|
364
|
+
|
|
365
|
+
const deviceInfo = DeviceUtils.getDeviceInfo();
|
|
366
|
+
log('info', `Device Info: ${JSON.stringify(deviceInfo, null, 2)}`);
|
|
367
|
+
|
|
368
|
+
const fingerprint = DeviceUtils.generateFingerprint();
|
|
369
|
+
log('info', `Device Fingerprint: ${fingerprint}`);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
document.getElementById('startGameBtn').addEventListener('click', async () => {
|
|
374
|
+
if (!sdk) return;
|
|
375
|
+
|
|
376
|
+
try {
|
|
377
|
+
updateStatus('Starting game session...', 'info');
|
|
378
|
+
|
|
379
|
+
const fingerprint = DeviceUtils.generateFingerprint();
|
|
380
|
+
const deviceInfo = DeviceUtils.getDeviceInfo();
|
|
381
|
+
|
|
382
|
+
// Initialize game session
|
|
383
|
+
const session = await sdk.initializeGameSession({
|
|
384
|
+
campaignId: 'demo-campaign-123',
|
|
385
|
+
gameId: 'demo-game-456',
|
|
386
|
+
playerFingerprint: fingerprint,
|
|
387
|
+
playerEmail: 'demo@example.com',
|
|
388
|
+
deviceInfo,
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
currentSession = session;
|
|
392
|
+
|
|
393
|
+
// Start the session
|
|
394
|
+
await sdk.startGameSession(session.sessionId, {
|
|
395
|
+
difficulty: 'normal',
|
|
396
|
+
mode: 'demo',
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
updateStatus('Game session active', 'success');
|
|
400
|
+
document.getElementById('simulateGameBtn').disabled = false;
|
|
401
|
+
document.getElementById('gameArea').style.display = 'block';
|
|
402
|
+
|
|
403
|
+
// Reset game state
|
|
404
|
+
currentScore = 0;
|
|
405
|
+
currentLevel = 1;
|
|
406
|
+
currentLives = 3;
|
|
407
|
+
updateGameDisplay();
|
|
408
|
+
|
|
409
|
+
} catch (error) {
|
|
410
|
+
log('error', `Failed to start game: ${error.message}`);
|
|
411
|
+
updateStatus('Failed to start game', 'error');
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
document.getElementById('simulateGameBtn').addEventListener('click', async () => {
|
|
416
|
+
if (!sdk || !currentSession) return;
|
|
417
|
+
|
|
418
|
+
updateStatus('Simulating gameplay...', 'info');
|
|
419
|
+
document.getElementById('simulateGameBtn').disabled = true;
|
|
420
|
+
|
|
421
|
+
// Simulate 30 seconds of gameplay
|
|
422
|
+
gameInterval = setInterval(async () => {
|
|
423
|
+
// Increase score randomly
|
|
424
|
+
const scoreIncrease = Math.floor(Math.random() * 100) + 50;
|
|
425
|
+
currentScore += scoreIncrease;
|
|
426
|
+
|
|
427
|
+
// Occasionally level up
|
|
428
|
+
if (currentScore > currentLevel * 1000) {
|
|
429
|
+
currentLevel++;
|
|
430
|
+
log('info', `Level up! Now at level ${currentLevel}`);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
updateGameDisplay();
|
|
434
|
+
|
|
435
|
+
// Send progress update
|
|
436
|
+
try {
|
|
437
|
+
const progressUpdate = await sdk.updateGameProgress(currentSession.sessionId, {
|
|
438
|
+
currentScore,
|
|
439
|
+
elapsedTime: Date.now() - new Date(currentSession.createdAt).getTime(),
|
|
440
|
+
gameState: {
|
|
441
|
+
level: currentLevel,
|
|
442
|
+
lives: currentLives,
|
|
443
|
+
},
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
if (progressUpdate.isLeading) {
|
|
447
|
+
log('success', '🏆 You are in the lead!');
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
} catch (error) {
|
|
451
|
+
log('error', `Progress update failed: ${error.message}`);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
}, 2000);
|
|
455
|
+
|
|
456
|
+
// End game after 30 seconds
|
|
457
|
+
setTimeout(async () => {
|
|
458
|
+
clearInterval(gameInterval);
|
|
459
|
+
|
|
460
|
+
try {
|
|
461
|
+
const completion = await sdk.completeGame(currentSession.sessionId, {
|
|
462
|
+
finalScore: currentScore,
|
|
463
|
+
gameMetrics: {
|
|
464
|
+
totalPlayTime: 30,
|
|
465
|
+
actionsPerformed: Math.floor(currentScore / 50),
|
|
466
|
+
powerUpsUsed: Math.floor(Math.random() * 5),
|
|
467
|
+
levelsCompleted: currentLevel,
|
|
468
|
+
},
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
updateStatus(`Game completed! Final rank: ${completion.finalRank}`,
|
|
472
|
+
completion.isWinner ? 'success' : 'info');
|
|
473
|
+
|
|
474
|
+
} catch (error) {
|
|
475
|
+
log('error', `Failed to complete game: ${error.message}`);
|
|
476
|
+
updateStatus('Failed to complete game', 'error');
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
document.getElementById('simulateGameBtn').disabled = false;
|
|
480
|
+
}, 30000);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
document.getElementById('leaderboardBtn').addEventListener('click', async () => {
|
|
484
|
+
if (!sdk) return;
|
|
485
|
+
|
|
486
|
+
try {
|
|
487
|
+
const leaderboard = await sdk.getLeaderboard('demo-campaign-123', 10);
|
|
488
|
+
|
|
489
|
+
log('info', '📊 Leaderboard:');
|
|
490
|
+
leaderboard.entries.forEach((entry, index) => {
|
|
491
|
+
const medal = index < 3 ? ['🥇', '🥈', '🥉'][index] : ' ';
|
|
492
|
+
const current = entry.isCurrentPlayer ? ' (You)' : '';
|
|
493
|
+
log('info', `${medal} ${entry.rank}. ${entry.displayName}${current} - ${entry.score} pts`);
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
} catch (error) {
|
|
497
|
+
log('error', `Failed to get leaderboard: ${error.message}`);
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
document.getElementById('clearLogBtn').addEventListener('click', () => {
|
|
502
|
+
document.getElementById('logArea').innerHTML = '';
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// Initialize the page
|
|
506
|
+
log('info', '🎮 Playe Developer SDK Browser Example loaded');
|
|
507
|
+
log('info', 'Click "Initialize SDK" to get started');
|
|
508
|
+
|
|
509
|
+
// Handle page unload
|
|
510
|
+
window.addEventListener('beforeunload', () => {
|
|
511
|
+
if (gameInterval) {
|
|
512
|
+
clearInterval(gameInterval);
|
|
513
|
+
}
|
|
514
|
+
if (sdk) {
|
|
515
|
+
sdk.destroy();
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
</script>
|
|
519
|
+
</body>
|
|
520
|
+
</html>
|