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.
@@ -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>