@skillprint/cocos-sdk 0.0.1

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,112 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { _decorator, Component, Enum } from 'cc';
8
+ import { ApiEnvironment } from './SkillprintTypes';
9
+ const { ccclass, property } = _decorator;
10
+ Enum(ApiEnvironment);
11
+ let SkillprintConfigComponent = class SkillprintConfigComponent extends Component {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.gameName = 'cocos-demo-game';
15
+ this.targetEnvironment = ApiEnvironment.Staging;
16
+ this.stagingPartnerApiKey = '';
17
+ this.stagingApiBaseUrl = 'https://api.staging.skillprint.co';
18
+ this.productionPartnerApiKey = '';
19
+ this.productionApiBaseUrl = 'https://api.skillprint.co';
20
+ this.screenshotMaxWidth = 960;
21
+ this.screenshotJpegQuality = 60;
22
+ this.screenshotIntervalSeconds = 2.0;
23
+ this.screenshotPostIntervalSeconds = 5.0;
24
+ this.pollResultsIntervalSeconds = 5.0;
25
+ this.enableDebugLogging = false;
26
+ }
27
+ getConfig() {
28
+ return {
29
+ gameName: this.gameName,
30
+ targetEnvironment: this.targetEnvironment,
31
+ productionPartnerApiKey: this.productionPartnerApiKey,
32
+ productionApiBaseUrl: this.productionApiBaseUrl,
33
+ stagingPartnerApiKey: this.stagingPartnerApiKey,
34
+ stagingApiBaseUrl: this.stagingApiBaseUrl,
35
+ screenshotMaxWidth: this.screenshotMaxWidth,
36
+ screenshotJpegQuality: this.screenshotJpegQuality,
37
+ screenshotIntervalSeconds: this.screenshotIntervalSeconds,
38
+ screenshotPostIntervalSeconds: this.screenshotPostIntervalSeconds,
39
+ pollResultsIntervalSeconds: this.pollResultsIntervalSeconds,
40
+ enableDebugLogging: this.enableDebugLogging,
41
+ gameParameters: []
42
+ };
43
+ }
44
+ };
45
+ __decorate([
46
+ property({
47
+ displayName: 'Game Name (Slug)',
48
+ tooltip: 'The unique slug registered for your game, e.g. fruit-boom'
49
+ })
50
+ ], SkillprintConfigComponent.prototype, "gameName", void 0);
51
+ __decorate([
52
+ property({
53
+ type: Enum(ApiEnvironment),
54
+ displayName: 'Target Environment'
55
+ })
56
+ ], SkillprintConfigComponent.prototype, "targetEnvironment", void 0);
57
+ __decorate([
58
+ property({
59
+ displayName: 'Staging API Key',
60
+ })
61
+ ], SkillprintConfigComponent.prototype, "stagingPartnerApiKey", void 0);
62
+ __decorate([
63
+ property({
64
+ displayName: 'Staging API Base URL'
65
+ })
66
+ ], SkillprintConfigComponent.prototype, "stagingApiBaseUrl", void 0);
67
+ __decorate([
68
+ property({
69
+ displayName: 'Production API Key',
70
+ })
71
+ ], SkillprintConfigComponent.prototype, "productionPartnerApiKey", void 0);
72
+ __decorate([
73
+ property({
74
+ displayName: 'Production API Base URL'
75
+ })
76
+ ], SkillprintConfigComponent.prototype, "productionApiBaseUrl", void 0);
77
+ __decorate([
78
+ property({
79
+ displayName: 'Screenshot Max Width',
80
+ tooltip: 'Maximum width for screenshots. Images wider than this are downscaled. 0 = no limit.'
81
+ })
82
+ ], SkillprintConfigComponent.prototype, "screenshotMaxWidth", void 0);
83
+ __decorate([
84
+ property({
85
+ displayName: 'Screenshot JPEG Quality',
86
+ tooltip: 'Compression quality (1-100). Lower values are smaller files.'
87
+ })
88
+ ], SkillprintConfigComponent.prototype, "screenshotJpegQuality", void 0);
89
+ __decorate([
90
+ property({
91
+ displayName: 'Screenshot Interval (s)'
92
+ })
93
+ ], SkillprintConfigComponent.prototype, "screenshotIntervalSeconds", void 0);
94
+ __decorate([
95
+ property({
96
+ displayName: 'Screenshot Post Interval (s)'
97
+ })
98
+ ], SkillprintConfigComponent.prototype, "screenshotPostIntervalSeconds", void 0);
99
+ __decorate([
100
+ property({
101
+ displayName: 'Poll Results Interval (s)'
102
+ })
103
+ ], SkillprintConfigComponent.prototype, "pollResultsIntervalSeconds", void 0);
104
+ __decorate([
105
+ property({
106
+ displayName: 'Enable Debug Logging'
107
+ })
108
+ ], SkillprintConfigComponent.prototype, "enableDebugLogging", void 0);
109
+ SkillprintConfigComponent = __decorate([
110
+ ccclass('SkillprintConfigComponent')
111
+ ], SkillprintConfigComponent);
112
+ export { SkillprintConfigComponent };
@@ -0,0 +1,35 @@
1
+ import { Component } from 'cc';
2
+ import { SkillprintConfig } from './SkillprintTypes';
3
+ export declare class SkillprintManager extends Component {
4
+ private static _instance;
5
+ static get instance(): SkillprintManager;
6
+ private config;
7
+ private currentSessionId;
8
+ private isSessionActive;
9
+ private apiClient;
10
+ private screenshotUtility;
11
+ private screenshotQueue;
12
+ private registeredParameters;
13
+ private captureCallback;
14
+ private postCallback;
15
+ private pollCallback;
16
+ onLoad(): void;
17
+ init(config: SkillprintConfig): void;
18
+ registerParameterModifier<T>(parameterName: string, updateAction: (value: T) => void, description?: string, howItWorks?: string): void;
19
+ startGameSession(targetMood: string, customPlayerId?: string | null): Promise<void>;
20
+ stopGameSession(): Promise<void>;
21
+ private startLoops;
22
+ private stopLoops;
23
+ private applyParameterUpdates;
24
+ private convertValue;
25
+ private isValidValue;
26
+ private findActiveCamera;
27
+ startGameSessionFromUrl(fallbackMood?: string, fallbackPlayerId?: string | null): void;
28
+ startGameSessionWithOverrides(fallbackMood?: string, fallbackPlayerId?: string | null, overrideMood?: string | null, overridePlayerId?: string | null): void;
29
+ getUrlParametersInfo(): string;
30
+ private getSkillprintUrlParameters;
31
+ private generateUUID;
32
+ log(msg: string, level?: 'Info' | 'Warning' | 'Error'): void;
33
+ getConfig(): SkillprintConfig | null;
34
+ onDestroy(): void;
35
+ }
@@ -0,0 +1,418 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var SkillprintManager_1;
8
+ import { _decorator, Component, director, Camera, sys, Enum } from 'cc';
9
+ import { ParameterType, ApiEnvironment } from './SkillprintTypes';
10
+ import { SkillprintAPIClient } from './SkillprintAPIClient';
11
+ import { ScreenshotUtility } from './ScreenshotUtility';
12
+ const { ccclass, property } = _decorator;
13
+ Enum(ApiEnvironment);
14
+ let SkillprintManager = SkillprintManager_1 = class SkillprintManager extends Component {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.config = null;
18
+ this.currentSessionId = null;
19
+ this.isSessionActive = false;
20
+ this.apiClient = null;
21
+ this.screenshotUtility = null;
22
+ this.screenshotQueue = [];
23
+ this.registeredParameters = new Map();
24
+ // References to the scheduler callbacks
25
+ this.captureCallback = null;
26
+ this.postCallback = null;
27
+ this.pollCallback = null;
28
+ }
29
+ static get instance() {
30
+ if (!this._instance) {
31
+ // Log warning, developers should ensure a node has the manager component,
32
+ // or we will instantiate it programmatically
33
+ console.warn('[SkillprintSDK] SkillprintManager instance is requested but not initialized yet.');
34
+ }
35
+ return this._instance;
36
+ }
37
+ onLoad() {
38
+ if (SkillprintManager_1._instance === null) {
39
+ SkillprintManager_1._instance = this;
40
+ director.addPersistRootNode(this.node); // Keep SDK persistent across scenes
41
+ }
42
+ else if (SkillprintManager_1._instance !== this) {
43
+ this.log('Another instance of SkillprintManager already exists. Destroying this one.', 'Warning');
44
+ this.node.destroy();
45
+ }
46
+ }
47
+ init(config) {
48
+ this.config = config;
49
+ const activeApiKey = this.config.targetEnvironment === 'Production'
50
+ ? this.config.productionPartnerApiKey
51
+ : (this.config.stagingPartnerApiKey || this.config.productionPartnerApiKey);
52
+ const activeBaseUrl = this.config.targetEnvironment === 'Production'
53
+ ? (this.config.productionApiBaseUrl || 'https://api.skillprint.co')
54
+ : (this.config.stagingApiBaseUrl || 'https://api.staging.skillprint.co');
55
+ if (!activeApiKey) {
56
+ this.log(`Partner API Key for ${this.config.targetEnvironment} environment is not set in config. SDK will not function.`, 'Error');
57
+ this.enabled = false;
58
+ return;
59
+ }
60
+ this.apiClient = new SkillprintAPIClient(activeBaseUrl, activeApiKey, (msg, lvl) => this.log(msg, lvl));
61
+ this.screenshotUtility = new ScreenshotUtility((msg, lvl) => this.log(msg, lvl));
62
+ // Pre-register parameters defined in config
63
+ if (this.config.gameParameters) {
64
+ this.config.gameParameters.forEach((param) => {
65
+ if (!this.registeredParameters.has(param.parameterName)) {
66
+ this.registeredParameters.set(param.parameterName, param);
67
+ }
68
+ else {
69
+ this.log(`Duplicate parameter name found in config: ${param.parameterName}. Using first occurrence.`, 'Warning');
70
+ }
71
+ });
72
+ }
73
+ this.log(`Skillprint SDK Initialized for ${this.config.targetEnvironment} environment (URL: ${activeBaseUrl}).`);
74
+ }
75
+ registerParameterModifier(parameterName, updateAction, description, howItWorks) {
76
+ let paramDef = this.registeredParameters.get(parameterName);
77
+ if (!paramDef) {
78
+ // Auto-create definition if it doesn't exist yet
79
+ let inferredType = ParameterType.Float;
80
+ let defaultMin = 0;
81
+ let defaultMax = 1;
82
+ paramDef = {
83
+ parameterName: parameterName,
84
+ description: description || `Game parameter '${parameterName}' (auto-detected)`,
85
+ howSDKChangesIt: howItWorks || '',
86
+ type: inferredType,
87
+ minValue: defaultMin,
88
+ maxValue: defaultMax
89
+ };
90
+ this.registeredParameters.set(parameterName, paramDef);
91
+ this.log(`Parameter '${parameterName}' was not in config. Auto-created definition. Consider defining it in the config file.`, 'Warning');
92
+ }
93
+ paramDef.UpdateAction = (value) => {
94
+ updateAction(value);
95
+ };
96
+ this.log(`Parameter '${parameterName}' modifier registered successfully.`);
97
+ }
98
+ async startGameSession(targetMood, customPlayerId = null) {
99
+ if (this.isSessionActive) {
100
+ this.log('Session already active. Call stopGameSession first.', 'Warning');
101
+ return;
102
+ }
103
+ if (!this.config || !this.apiClient) {
104
+ this.log('SDK not configured properly. Cannot start session.', 'Error');
105
+ return;
106
+ }
107
+ // Validate mood parameter
108
+ const validMoods = ['relax', 'focus', 'creativity', 'collaborate', 'grit', 'joy', 'curiosity', 'empathy', 'awe'];
109
+ if (validMoods.indexOf(targetMood) === -1) {
110
+ this.log(`Invalid targetMood: '${targetMood}'. Valid moods are: ${validMoods.join(', ')}`, 'Error');
111
+ return;
112
+ }
113
+ this.currentSessionId = this.generateUUID();
114
+ this.isSessionActive = true;
115
+ this.log(`Starting game session for ${this.config.targetEnvironment} environment.`);
116
+ // Map registered parameters to API format
117
+ const parameterInfos = Array.from(this.registeredParameters.values()).map((p) => {
118
+ return {
119
+ name: p.parameterName,
120
+ type: p.type.toString(),
121
+ description: p.description || '',
122
+ adjustmentGuide: p.howSDKChangesIt || null,
123
+ minValue: (p.type === ParameterType.Float || p.type === ParameterType.Integer) && p.minValue !== undefined ? p.minValue.toString() : null,
124
+ maxValue: (p.type === ParameterType.Float || p.type === ParameterType.Integer) && p.maxValue !== undefined ? p.maxValue.toString() : null
125
+ };
126
+ });
127
+ this.log(`Sending ${parameterInfos.length} game parameter(s) to API: ` + parameterInfos.map(p => p.name).join(', '), 'Warning');
128
+ const success = await this.apiClient.startSession(this.currentSessionId, targetMood, customPlayerId, this.config.gameName, parameterInfos);
129
+ if (success) {
130
+ this.log(`Skillprint session started: ${this.currentSessionId}`);
131
+ this.startLoops();
132
+ }
133
+ else {
134
+ this.log('Failed to start Skillprint session', 'Error');
135
+ this.isSessionActive = false;
136
+ this.currentSessionId = null;
137
+ }
138
+ }
139
+ async stopGameSession() {
140
+ if (!this.isSessionActive || !this.currentSessionId || !this.apiClient) {
141
+ this.log('No active session to stop.', 'Warning');
142
+ return;
143
+ }
144
+ const closingSessionId = this.currentSessionId;
145
+ this.log(`Stopping Skillprint session: ${closingSessionId}`);
146
+ this.isSessionActive = false;
147
+ this.stopLoops();
148
+ // Copy remaining screenshots and upload with isLastChunk = true
149
+ const finalBatch = [...this.screenshotQueue];
150
+ this.screenshotQueue = [];
151
+ try {
152
+ await this.apiClient.postScreenshots(closingSessionId, finalBatch, true);
153
+ this.log('Session close signal sent successfully.');
154
+ }
155
+ catch (err) {
156
+ this.log(`Failed to send session close signal: ${err.message || err}`, 'Error');
157
+ }
158
+ this.currentSessionId = null;
159
+ this.log('Skillprint session stopped.');
160
+ }
161
+ startLoops() {
162
+ var _a, _b, _c;
163
+ const intervalCapture = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.screenshotIntervalSeconds) || 2.0;
164
+ const intervalPost = ((_b = this.config) === null || _b === void 0 ? void 0 : _b.screenshotPostIntervalSeconds) || 5.0;
165
+ const intervalPoll = ((_c = this.config) === null || _c === void 0 ? void 0 : _c.pollResultsIntervalSeconds) || 5.0;
166
+ // Capture loop
167
+ this.captureCallback = async () => {
168
+ var _a, _b;
169
+ if (!this.isSessionActive || !this.screenshotUtility)
170
+ return;
171
+ const camera = this.findActiveCamera();
172
+ if (!camera) {
173
+ this.log('Active camera not found in scene for screenshot capture', 'Warning');
174
+ return;
175
+ }
176
+ const imgData = await this.screenshotUtility.captureScreenshot(camera, ((_a = this.config) === null || _a === void 0 ? void 0 : _a.screenshotMaxWidth) || 960, ((_b = this.config) === null || _b === void 0 ? void 0 : _b.screenshotJpegQuality) || 60);
177
+ if (imgData) {
178
+ if (this.screenshotQueue.length < 50) {
179
+ this.screenshotQueue.push(imgData);
180
+ this.log(`Screenshot captured. Queue size: ${this.screenshotQueue.length}`);
181
+ }
182
+ else {
183
+ this.log('Screenshot queue full. Discarding new screenshot.', 'Warning');
184
+ }
185
+ }
186
+ };
187
+ this.schedule(this.captureCallback, intervalCapture);
188
+ // Post loop
189
+ this.postCallback = async () => {
190
+ if (!this.isSessionActive || !this.apiClient || this.screenshotQueue.length === 0)
191
+ return;
192
+ // Determine batch size (based on cadence ratio)
193
+ const batchSize = Math.max(1, Math.ceil(intervalPost / intervalCapture));
194
+ const batchToPost = this.screenshotQueue.splice(0, batchSize * 2);
195
+ this.log(`Posting ${batchToPost.length} screenshots...`);
196
+ const ok = await this.apiClient.postScreenshots(this.currentSessionId, batchToPost, false);
197
+ if (ok) {
198
+ this.log(`Successfully posted ${batchToPost.length} screenshots.`);
199
+ }
200
+ else {
201
+ this.log('Failed to post screenshots batch.', 'Error');
202
+ }
203
+ };
204
+ this.schedule(this.postCallback, intervalPost);
205
+ // Poll loop
206
+ this.pollCallback = async () => {
207
+ if (!this.isSessionActive || !this.apiClient)
208
+ return;
209
+ const updates = await this.apiClient.pollParameterResults(this.currentSessionId);
210
+ if (updates && updates.length > 0) {
211
+ this.log(`Received ${updates.length} parameter updates from API.`);
212
+ this.applyParameterUpdates(updates);
213
+ }
214
+ };
215
+ this.schedule(this.pollCallback, intervalPoll);
216
+ }
217
+ stopLoops() {
218
+ if (this.captureCallback) {
219
+ this.unschedule(this.captureCallback);
220
+ this.captureCallback = null;
221
+ }
222
+ if (this.postCallback) {
223
+ this.unschedule(this.postCallback);
224
+ this.postCallback = null;
225
+ }
226
+ if (this.pollCallback) {
227
+ this.unschedule(this.pollCallback);
228
+ this.pollCallback = null;
229
+ }
230
+ }
231
+ applyParameterUpdates(updates) {
232
+ if (!this.apiClient)
233
+ return;
234
+ updates.forEach((update) => {
235
+ const rawValue = this.apiClient.getParsedValue(update);
236
+ this.log(`[DEBUG] Received update - Name: ${update.parameterName}, RawValue: '${rawValue}'`);
237
+ if (rawValue === null || rawValue === undefined) {
238
+ this.log(`Parameter '${update.parameterName}' received null/undefined value from API. Skipping.`, 'Warning');
239
+ return;
240
+ }
241
+ const paramDef = this.registeredParameters.get(update.parameterName);
242
+ if (!paramDef) {
243
+ this.log(`Received update for unknown parameter: ${update.parameterName}. Skipping.`, 'Warning');
244
+ return;
245
+ }
246
+ if (!paramDef.UpdateAction) {
247
+ this.log(`Parameter '${update.parameterName}' received from API but has no registered modifier callback. Skipping.`, 'Warning');
248
+ return;
249
+ }
250
+ const convertedValue = this.convertValue(rawValue, paramDef);
251
+ if (convertedValue !== null && this.isValidValue(convertedValue, paramDef)) {
252
+ try {
253
+ this.log(`Applying update: ${paramDef.parameterName} = ${convertedValue} (Type: ${paramDef.type})`);
254
+ paramDef.UpdateAction(convertedValue);
255
+ }
256
+ catch (e) {
257
+ this.log(`Error applying update for ${paramDef.parameterName}: ${e.message || e}`, 'Error');
258
+ }
259
+ }
260
+ else {
261
+ this.log(`Invalid value or type conversion failed for parameter ${paramDef.parameterName}: '${rawValue}'`, 'Warning');
262
+ }
263
+ });
264
+ }
265
+ convertValue(rawValue, paramDef) {
266
+ try {
267
+ switch (paramDef.type) {
268
+ case ParameterType.Float:
269
+ const fVal = parseFloat(rawValue);
270
+ return isNaN(fVal) ? null : fVal;
271
+ case ParameterType.Integer:
272
+ const iVal = parseInt(rawValue, 10);
273
+ return isNaN(iVal) ? null : iVal;
274
+ case ParameterType.Boolean:
275
+ if (typeof rawValue === 'boolean')
276
+ return rawValue;
277
+ if (typeof rawValue === 'string') {
278
+ return rawValue.toLowerCase() === 'true' || rawValue === '1';
279
+ }
280
+ if (typeof rawValue === 'number') {
281
+ return rawValue !== 0;
282
+ }
283
+ return null;
284
+ default:
285
+ return rawValue;
286
+ }
287
+ }
288
+ catch (err) {
289
+ this.log(`Conversion failed: ${err.message || err}`, 'Error');
290
+ return null;
291
+ }
292
+ }
293
+ isValidValue(value, paramDef) {
294
+ switch (paramDef.type) {
295
+ case ParameterType.Float:
296
+ case ParameterType.Integer:
297
+ const num = value;
298
+ if (paramDef.minValue !== undefined && num < paramDef.minValue)
299
+ return false;
300
+ if (paramDef.maxValue !== undefined && num > paramDef.maxValue)
301
+ return false;
302
+ return true;
303
+ case ParameterType.Boolean:
304
+ return typeof value === 'boolean';
305
+ }
306
+ return false;
307
+ }
308
+ findActiveCamera() {
309
+ var _a;
310
+ // Query scene for active camera components
311
+ const rootNodes = (_a = director.getScene()) === null || _a === void 0 ? void 0 : _a.children;
312
+ if (!rootNodes)
313
+ return null;
314
+ for (let i = 0; i < rootNodes.length; i++) {
315
+ const camera = rootNodes[i].getComponentInChildren(Camera);
316
+ if (camera && camera.node.active && camera.enabled) {
317
+ return camera;
318
+ }
319
+ }
320
+ return null;
321
+ }
322
+ // Web URL parameters methods
323
+ startGameSessionFromUrl(fallbackMood = 'relax', fallbackPlayerId = null) {
324
+ this.startGameSessionWithOverrides(fallbackMood, fallbackPlayerId);
325
+ }
326
+ startGameSessionWithOverrides(fallbackMood = 'relax', fallbackPlayerId = null, overrideMood = null, overridePlayerId = null) {
327
+ let targetMood = overrideMood;
328
+ let playerId = overridePlayerId;
329
+ // If not forced, try browser query string
330
+ if (!targetMood || !playerId) {
331
+ const urlParams = this.getSkillprintUrlParameters();
332
+ if (!targetMood) {
333
+ targetMood = urlParams.targetMood || fallbackMood;
334
+ }
335
+ if (!playerId) {
336
+ playerId = urlParams.playerId || fallbackPlayerId;
337
+ }
338
+ }
339
+ // Validate target mood
340
+ if (!targetMood) {
341
+ this.log("No target mood specified and no fallback provided. Using 'focus' as default.", 'Warning');
342
+ targetMood = 'focus';
343
+ }
344
+ const validMoods = ['relax', 'focus', 'creativity', 'collaborate', 'grit', 'joy', 'curiosity', 'empathy', 'awe'];
345
+ if (validMoods.indexOf(targetMood) === -1) {
346
+ this.log(`Invalid mood '${targetMood}'. Valid moods: ${validMoods.join(', ')}. Using 'focus' as fallback.`, 'Warning');
347
+ targetMood = 'focus';
348
+ }
349
+ this.log(`Starting Skillprint session with Mood: '${targetMood}', Player ID: '${playerId || 'none'}'`);
350
+ this.startGameSession(targetMood, playerId);
351
+ }
352
+ getUrlParametersInfo() {
353
+ if (!sys.isBrowser) {
354
+ return 'URL parameters not supported on this platform (not Browser)';
355
+ }
356
+ const urlParams = this.getSkillprintUrlParameters();
357
+ return `Current URL: ${window.location.href}\nMood Parameter: '${urlParams.targetMood || 'not found'}'\nPlayer ID Parameter: '${urlParams.playerId || 'not found'}'`;
358
+ }
359
+ getSkillprintUrlParameters() {
360
+ if (!sys.isBrowser) {
361
+ return { targetMood: null, playerId: null };
362
+ }
363
+ const searchParams = new URLSearchParams(window.location.search);
364
+ const mood = searchParams.get('mood') || searchParams.get('targetMood');
365
+ const playerId = searchParams.get('playerId') || searchParams.get('player_id') || searchParams.get('userId');
366
+ // Store persistent storage updates
367
+ if (mood)
368
+ sys.localStorage.setItem('SkillprintMood', mood);
369
+ if (playerId)
370
+ sys.localStorage.setItem('SkillprintPlayerId', playerId);
371
+ return {
372
+ targetMood: mood || sys.localStorage.getItem('SkillprintMood'),
373
+ playerId: playerId || sys.localStorage.getItem('SkillprintPlayerId')
374
+ };
375
+ }
376
+ // UUID Generator helper
377
+ generateUUID() {
378
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
379
+ const r = Math.random() * 16 | 0;
380
+ const v = c === 'x' ? r : (r & 0x3 | 0x8);
381
+ return v.toString(16);
382
+ });
383
+ }
384
+ // Centralized Logging
385
+ log(msg, level = 'Info') {
386
+ if (this.config && !this.config.enableDebugLogging && level === 'Info') {
387
+ return;
388
+ }
389
+ const formatted = `[SkillprintSDK] ${msg}`;
390
+ switch (level) {
391
+ case 'Info':
392
+ console.log(formatted);
393
+ break;
394
+ case 'Warning':
395
+ console.warn(formatted);
396
+ break;
397
+ case 'Error':
398
+ console.error(formatted);
399
+ break;
400
+ }
401
+ }
402
+ getConfig() {
403
+ return this.config;
404
+ }
405
+ onDestroy() {
406
+ if (this.isSessionActive) {
407
+ this.stopGameSession();
408
+ }
409
+ if (SkillprintManager_1._instance === this) {
410
+ SkillprintManager_1._instance = null;
411
+ }
412
+ }
413
+ };
414
+ SkillprintManager._instance = null;
415
+ SkillprintManager = SkillprintManager_1 = __decorate([
416
+ ccclass('SkillprintManager')
417
+ ], SkillprintManager);
418
+ export { SkillprintManager };
@@ -0,0 +1,69 @@
1
+ export declare enum ApiEnvironment {
2
+ Production = "Production",
3
+ Staging = "Staging"
4
+ }
5
+ export declare enum ParameterType {
6
+ Float = "Float",
7
+ Integer = "Integer",
8
+ Boolean = "Boolean"
9
+ }
10
+ export declare enum Mood {
11
+ relax = "relax",
12
+ focus = "focus",
13
+ creativity = "creativity",
14
+ collaborate = "collaborate",
15
+ grit = "grit",
16
+ joy = "joy",
17
+ curiosity = "curiosity",
18
+ empathy = "empathy",
19
+ awe = "awe"
20
+ }
21
+ export interface ParameterDefinition {
22
+ parameterName: string;
23
+ description?: string;
24
+ howSDKChangesIt?: string;
25
+ type: ParameterType;
26
+ minValue?: number;
27
+ maxValue?: number;
28
+ defaultValue?: string;
29
+ UpdateAction?: (value: any) => void;
30
+ }
31
+ export interface SkillprintConfig {
32
+ gameName: string;
33
+ targetEnvironment: ApiEnvironment;
34
+ productionPartnerApiKey: string;
35
+ productionApiBaseUrl?: string;
36
+ stagingPartnerApiKey?: string;
37
+ stagingApiBaseUrl?: string;
38
+ screenshotMaxWidth?: number;
39
+ screenshotJpegQuality?: number;
40
+ screenshotIntervalSeconds?: number;
41
+ screenshotPostIntervalSeconds?: number;
42
+ pollResultsIntervalSeconds?: number;
43
+ enableDebugLogging?: boolean;
44
+ gameParameters?: ParameterDefinition[];
45
+ }
46
+ export interface ParameterInfo {
47
+ name: string;
48
+ type: string;
49
+ description: string;
50
+ adjustmentGuide: string | null;
51
+ minValue: string | null;
52
+ maxValue: string | null;
53
+ }
54
+ export interface StartSessionRequest {
55
+ sessionId: string;
56
+ game: string;
57
+ targetMood: string;
58
+ gameParameters: ParameterInfo[];
59
+ }
60
+ export interface ParameterUpdateResult {
61
+ parameterName: string;
62
+ newValue: any;
63
+ [key: string]: any;
64
+ }
65
+ export interface PollResultsResponse {
66
+ gameplayTips?: string;
67
+ state?: string;
68
+ parameterUpdates?: ParameterUpdateResult[];
69
+ }
@@ -0,0 +1,23 @@
1
+ export var ApiEnvironment;
2
+ (function (ApiEnvironment) {
3
+ ApiEnvironment["Production"] = "Production";
4
+ ApiEnvironment["Staging"] = "Staging";
5
+ })(ApiEnvironment || (ApiEnvironment = {}));
6
+ export var ParameterType;
7
+ (function (ParameterType) {
8
+ ParameterType["Float"] = "Float";
9
+ ParameterType["Integer"] = "Integer";
10
+ ParameterType["Boolean"] = "Boolean";
11
+ })(ParameterType || (ParameterType = {}));
12
+ export var Mood;
13
+ (function (Mood) {
14
+ Mood["relax"] = "relax";
15
+ Mood["focus"] = "focus";
16
+ Mood["creativity"] = "creativity";
17
+ Mood["collaborate"] = "collaborate";
18
+ Mood["grit"] = "grit";
19
+ Mood["joy"] = "joy";
20
+ Mood["curiosity"] = "curiosity";
21
+ Mood["empathy"] = "empathy";
22
+ Mood["awe"] = "awe";
23
+ })(Mood || (Mood = {}));
@@ -0,0 +1,5 @@
1
+ export * from './SkillprintTypes';
2
+ export * from './SkillprintAPIClient';
3
+ export * from './ScreenshotUtility';
4
+ export * from './SkillprintManager';
5
+ export * from './SkillprintConfigComponent';
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './SkillprintTypes';
2
+ export * from './SkillprintAPIClient';
3
+ export * from './ScreenshotUtility';
4
+ export * from './SkillprintManager';
5
+ export * from './SkillprintConfigComponent';