skillprint-js-sdk 1.1.0-beta.6 โ 1.1.0-beta.8
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/README.md +83 -1
- package/dist/index.cjs +426 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +314 -13
- package/dist/index.d.ts +314 -13
- package/dist/index.global.js +419 -89
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +419 -89
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ A professional JavaScript & TypeScript SDK for integrating Skillprint's real-tim
|
|
|
14
14
|
- ๐ธ **Automated Screenshot Capture**: Asynchronous, throttled gameplay screenshot captures for Canvas and WebGL contexts without dropping game frame rates.
|
|
15
15
|
- ๐ **Real-Time Dynamic Parameters**: Receive, convert, clamp, and apply AI-driven parameter modifications seamlessly during active sessions.
|
|
16
16
|
- ๐ฎ **Built-In Engine Adapters**: Ready-to-use adapter wrappers for Phaser.js, Three.js, PixiJS, and Generic Canvas.
|
|
17
|
+
- ๐ **Discrete Telemetry Events**: `logEvent()` for universal and game-specific gameplay events, sent with the screenshots and timestamped from session start. See [Discrete Telemetry Events](#discrete-telemetry-events).
|
|
17
18
|
- ๐ **WebGL & URL Extraction**: Automatic query parameter extraction for web deployments (`mood`, `playerId`).
|
|
18
19
|
- ๐งช **100% Test Coverage Ready**: Fully tested with Vitest and jsdom.
|
|
19
20
|
|
|
@@ -188,6 +189,71 @@ manager.startGameSessionWithOverrides(
|
|
|
188
189
|
|
|
189
190
|
---
|
|
190
191
|
|
|
192
|
+
## Discrete Telemetry Events
|
|
193
|
+
|
|
194
|
+
Screenshots are the SDK's main telemetry and cover every game automatically. `logEvent()` adds discrete events: what the player did and when. Events and screenshots are both stamped with the **milliseconds since the session started**, so Skillprint can line each event up with the frames around it.
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import { GameEvent } from 'skillprint-js-sdk';
|
|
198
|
+
|
|
199
|
+
manager.logEvent(GameEvent.LEVEL_START, { level: 3 });
|
|
200
|
+
manager.logEvent('ROTATE_CLOCKWISE');
|
|
201
|
+
manager.logEvent(GameEvent.LEVEL_COMPLETE, { level: 3, score: 1200 });
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Events are queued and sent with the next screenshot upload, or on their own when there is no screenshot to send. `stopGameSession()` sends the rest with the closing upload, so they arrive before the session closes. `logEvent` never throws, and with no active session it only logs a warning.
|
|
205
|
+
|
|
206
|
+
### Universal and game-specific events
|
|
207
|
+
|
|
208
|
+
**Universal events** (`GameEvent`) mean the same thing in every game. Send the ones that apply to yours:
|
|
209
|
+
|
|
210
|
+
| Event | When | Scoring signal |
|
|
211
|
+
|---|---|---|
|
|
212
|
+
| `GAME_START`, `GAME_END` | The game begins or ends | |
|
|
213
|
+
| `GAME_PAUSE`, `GAME_RESUME` | Play is paused or resumed | |
|
|
214
|
+
| `LEVEL_START`, `LEVEL_COMPLETE` | A level begins or is completed | Positive |
|
|
215
|
+
| `LEVEL_QUIT`, `LEVEL_FAILED`, `LEVEL_RESTART` | A level is abandoned, lost or restarted | Negative |
|
|
216
|
+
| `MATCH`, `UNMATCH` | A match is made or undone, in games built on matching | |
|
|
217
|
+
| `HINT` | The player asks for a hint | Negative |
|
|
218
|
+
| `GENERIC_POSITIVE`, `GENERIC_NEGATIVE` | Anything else clearly good or bad for the player | Positive / Negative |
|
|
219
|
+
|
|
220
|
+
**Game-specific events** are any other name, for actions only your game has. For Hextris, for example:
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
manager.logEvent('ROTATE_CLOCKWISE');
|
|
224
|
+
manager.logEvent('ROTATE_ANTICLOCKWISE');
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
They don't need registering; send what your game already tracks, in `UPPER_SNAKE_CASE`. `isUniversalEvent(name)` tells the two kinds apart.
|
|
228
|
+
|
|
229
|
+
Each event can carry data (`{ level: 3, score: 1200 }`). `event` and `timestamp` are set by the SDK and can't be overridden.
|
|
230
|
+
|
|
231
|
+
### What is sent
|
|
232
|
+
|
|
233
|
+
Each screenshot upload can carry, beside the images:
|
|
234
|
+
- `offset_ms<n>`: when the n-th screenshot was captured, in ms from session start
|
|
235
|
+
- `events`: a JSON array of the events since the last upload (at most 1000), e.g. `[{"event": "ROTATE_CLOCKWISE", "timestamp": 1250}]`, where `timestamp` is ms from session start
|
|
236
|
+
|
|
237
|
+
### Pages that upload their own frames
|
|
238
|
+
|
|
239
|
+
A page that captures its own screenshots and calls `SkillprintAPIClient` directly (see [Host mode](#skillprintapiclient)) keeps a `SessionTimeline` itself:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import { SessionTimeline, SkillprintAPIClient } from 'skillprint-js-sdk';
|
|
243
|
+
|
|
244
|
+
const timeline = new SessionTimeline();
|
|
245
|
+
await client.startSession(sessionId, 'focus', null, 'hextris');
|
|
246
|
+
timeline.start();
|
|
247
|
+
|
|
248
|
+
const offset = timeline.offsetMs(); // when a frame is captured
|
|
249
|
+
timeline.record('ROTATE_CLOCKWISE'); // when the player acts
|
|
250
|
+
|
|
251
|
+
await client.postScreenshots(sessionId, [frame], false, {
|
|
252
|
+
offsetsMs: [offset],
|
|
253
|
+
events: timeline.takeEvents()
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
191
257
|
## API Reference
|
|
192
258
|
|
|
193
259
|
### Core Classes
|
|
@@ -202,7 +268,8 @@ manager.startGameSessionWithOverrides(
|
|
|
202
268
|
- `static getInstance(): SkillprintManager | null`
|
|
203
269
|
- `registerParameterModifier(parameterName: string, updateAction: ParameterModifierAction, expectedType?: string | null): void`
|
|
204
270
|
- `startGameSession(targetMood: Mood | string, customPlayerId?: string | null): Promise<void>`
|
|
205
|
-
- `stopGameSession(): void`
|
|
271
|
+
- `stopGameSession(): Promise<void>` โ stops capture, uploads any queued screenshots with the final batch marked `is_last_chunk` so the backend scores it and closes the session; never rejects
|
|
272
|
+
- `logEvent(event: GameEvent | string, data?: Record<string, unknown>): Promise<void>` โ see [Discrete Telemetry Events](#discrete-telemetry-events) below
|
|
206
273
|
- `getCurrentSessionId(): string | null`
|
|
207
274
|
- `getConfig(): SkillprintConfig`
|
|
208
275
|
|
|
@@ -211,6 +278,21 @@ manager.startGameSessionWithOverrides(
|
|
|
211
278
|
- `isValid(value: unknown): boolean`
|
|
212
279
|
- `convertValue(rawValue: unknown): number | boolean | string | null`
|
|
213
280
|
|
|
281
|
+
#### `SkillprintAPIClient`
|
|
282
|
+
The HTTP client `SkillprintManager` uses. Use it directly when your page already captures its own frames, or when you need session scores.
|
|
283
|
+
- `constructor(baseUrl: string, partnerApiKey?: string, logger?: SDKLogger)`
|
|
284
|
+
- `startSession(sessionId, targetMood, customPlayerId?, gameName?, gameParameters?: ParameterInfo[], options?: { deviceContext? })`
|
|
285
|
+
- `postScreenshots(sessionId, screenshots: Blob[], isLastChunk?, options?: { gameStates?, inputCount?, offsetsMs?, events? })`: `offsetsMs[n]` is when the n-th screenshot was captured and `events` are the events since the last upload, both in ms from session start (see [Discrete Telemetry Events](#discrete-telemetry-events)). `gameStates[n]` (for example `{ score: 1200 }`) is sent with the n-th screenshot, and the latest `score` becomes the session's score. `inputCount` is how many player inputs the batch covers; a batch with 0 is left out of skill scores. `isLastChunk: true` scores the batch and closes the session.
|
|
286
|
+
- `getSession(sessionId): Promise<SessionResult>`: the session's `state` (`OPEN`, then `CLOSED` once scored), `skillScores`, `moodScores`, `score`, `telemetry` (adjustments and logged events) and `parameterUpdates`
|
|
287
|
+
- `pollParameterResults(sessionId)`: only the parameter updates
|
|
288
|
+
- `getUserProfile()`: the player's skill profile; needs a player token
|
|
289
|
+
- `setPlayerToken(token: string | null)`: the token of a player your page has already signed in, used when `startSession` gets no `customPlayerId`
|
|
290
|
+
- `createOrGetUserToken(customPlayerId)`, `createUser(internalId)`, `getUserToken(internalId)`: need a partner key
|
|
291
|
+
|
|
292
|
+
A failed call throws `SkillprintApiError`, which carries the HTTP `status` and response `body`.
|
|
293
|
+
|
|
294
|
+
**Host mode.** A page on an origin the Skillprint API allows, such as the Skillprint portal, can sign its own players in and skip the partner key: pass `''` as `partnerApiKey` and call `setPlayerToken()`. The client then sends no `Api-Key`, and sends the player token on every session call. Sessions started this way belong to the player, not to a partner organization. When the token expires (a `401`), get a new one, call `setPlayerToken()` and retry.
|
|
295
|
+
|
|
214
296
|
---
|
|
215
297
|
|
|
216
298
|
## Development & Testing
|