@m2c2kit/cli 0.1.9 → 0.1.10
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/dist/.env
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
CLI_VERSION=0.1.
|
|
1
|
+
CLI_VERSION=0.1.10
|
package/dist/cli.js
CHANGED
|
@@ -146,6 +146,10 @@ await yarg
|
|
|
146
146
|
sourceFilePath: path.join(packageHomeFolderPath, "fonts", "roboto", "Roboto-Regular.ttf"),
|
|
147
147
|
destinationFilePath: path.join(newFolderPath, "fonts", "roboto", "Roboto-Regular.ttf"),
|
|
148
148
|
},
|
|
149
|
+
{
|
|
150
|
+
sourceFilePath: path.join(packageHomeFolderPath, "scripts", "post-install.mjs"),
|
|
151
|
+
destinationFilePath: path.join(newFolderPath, "post-install.mjs"),
|
|
152
|
+
},
|
|
149
153
|
];
|
|
150
154
|
let errorCopyingFiles = false;
|
|
151
155
|
copyFiles.forEach((c) => {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import { resolve, basename } from "path";
|
|
4
|
+
|
|
5
|
+
const { dependencies } = JSON.parse(fs.readFileSync("./package.json"));
|
|
6
|
+
|
|
7
|
+
/** If this m2c2kit app uses surveys, then copy the required css
|
|
8
|
+
* files from node_modules so they can be bundled */
|
|
9
|
+
if (Object.keys(dependencies).includes("@m2c2kit/survey")) {
|
|
10
|
+
// does ./css folder exist? if not, create
|
|
11
|
+
if (!fs.existsSync("./css")) {
|
|
12
|
+
fs.mkdirSync("./css");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const cssDistDir = "./node_modules/@m2c2kit/survey/dist/css/";
|
|
16
|
+
const cssFiles = fs
|
|
17
|
+
.readdirSync(cssDistDir, {
|
|
18
|
+
withFileTypes: true,
|
|
19
|
+
})
|
|
20
|
+
.filter((dirent) => !dirent.isDirectory())
|
|
21
|
+
.map((dirent) => resolve(cssDistDir, dirent.name));
|
|
22
|
+
|
|
23
|
+
cssFiles.forEach((file) => {
|
|
24
|
+
const sourceContents = fs.readFileSync(file);
|
|
25
|
+
fs.writeFileSync(`./css/${basename(file)}`, sourceContents);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"serve": "rollup -c --watch --configServe",
|
|
6
|
-
"build": "rollup -c --configProd"
|
|
6
|
+
"build": "rollup -c --configProd",
|
|
7
|
+
"postinstall": "node ./post-install.mjs"
|
|
7
8
|
},
|
|
8
9
|
"private": true,
|
|
9
10
|
"dependencies": {
|
|
10
|
-
"@m2c2kit/core": "0.1.
|
|
11
|
-
"@m2c2kit/addons": "0.1.
|
|
11
|
+
"@m2c2kit/core": "0.1.8",
|
|
12
|
+
"@m2c2kit/addons": "0.1.8"
|
|
12
13
|
},
|
|
13
14
|
"devDependencies": {
|
|
14
15
|
"rollup": "2.63.0",
|
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
|
-
WebColors,
|
|
3
|
-
Action,
|
|
4
2
|
Game,
|
|
3
|
+
Action,
|
|
5
4
|
Scene,
|
|
6
|
-
|
|
5
|
+
Shape,
|
|
7
6
|
Point,
|
|
8
7
|
Label,
|
|
9
|
-
|
|
10
|
-
Shape,
|
|
8
|
+
WebColors,
|
|
11
9
|
Rect,
|
|
12
|
-
|
|
10
|
+
LabelHorizontalAlignmentMode,
|
|
13
11
|
GameParameters,
|
|
12
|
+
GameOptions,
|
|
14
13
|
TrialSchema,
|
|
15
14
|
Session,
|
|
16
|
-
GameTrialEvent,
|
|
17
|
-
GameLifecycleEvent,
|
|
18
15
|
SessionLifecycleEvent,
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
ActivityDataEvent,
|
|
17
|
+
ActivityLifecycleEvent,
|
|
18
|
+
Sprite,
|
|
21
19
|
} from "@m2c2kit/core";
|
|
22
20
|
import { Button, Instructions } from "@m2c2kit/addons";
|
|
23
21
|
|
|
24
22
|
class {{className}} extends Game {
|
|
25
23
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
24
|
constructor() {
|
|
25
|
+
/**
|
|
26
|
+
* These are configurable game parameters and their defaults.
|
|
27
|
+
* At run time, they can be changed with the setParameters() method.
|
|
28
|
+
*/
|
|
27
29
|
const defaultParameters: GameParameters = {
|
|
28
30
|
ReadyTime: {
|
|
29
31
|
value: 1000,
|
|
@@ -33,6 +35,12 @@ class {{className}} extends Game {
|
|
|
33
35
|
TrialNum: { value: 3, description: "How many trials to run" },
|
|
34
36
|
};
|
|
35
37
|
|
|
38
|
+
/**
|
|
39
|
+
* This describes all the data that will be generated by the assessment.
|
|
40
|
+
* At runtime, when a trial completes, the data will be returned to the
|
|
41
|
+
* session with a callback, along with this schema transformed into
|
|
42
|
+
* JSON Schema Draft-07 format.
|
|
43
|
+
*/
|
|
36
44
|
const demoTrialSchema: TrialSchema = {
|
|
37
45
|
colorChosen: { type: "string", description: "the color that was picked" },
|
|
38
46
|
correct: { type: "boolean", description: "was the answer correct?" },
|
|
@@ -47,9 +55,9 @@ class {{className}} extends Game {
|
|
|
47
55
|
showFps: true,
|
|
48
56
|
trialSchema: demoTrialSchema,
|
|
49
57
|
parameters: defaultParameters,
|
|
50
|
-
// set this color so we can see the boundaries of the game during development,
|
|
51
|
-
// but typically we would not set this
|
|
52
|
-
bodyBackgroundColor: WebColors.Wheat,
|
|
58
|
+
// You can set this color so we can see the boundaries of the game during development,
|
|
59
|
+
// but typically we would not set this, so it is commented out
|
|
60
|
+
// bodyBackgroundColor: WebColors.Wheat,
|
|
53
61
|
// note: using 2:1 aspect ratio, because that is closer to modern phones
|
|
54
62
|
width: 400,
|
|
55
63
|
height: 800,
|
|
@@ -97,6 +105,7 @@ class {{className}} extends Game {
|
|
|
97
105
|
textFontSize: 24,
|
|
98
106
|
titleFontSize: 30,
|
|
99
107
|
image: "smiley",
|
|
108
|
+
imageMarginBottom: 24
|
|
100
109
|
},
|
|
101
110
|
{
|
|
102
111
|
title: "{{appName}} Demo",
|
|
@@ -301,11 +310,6 @@ class {{className}} extends Game {
|
|
|
301
310
|
});
|
|
302
311
|
startOverButton.isUserInteractionEnabled = true;
|
|
303
312
|
startOverButton.onTapDown(() => {
|
|
304
|
-
// in the setup() for the end scene, we animate the smiley sprite with
|
|
305
|
-
// a move action. if the user taps the start over button before the
|
|
306
|
-
// animation is completed, we should remove it by calling
|
|
307
|
-
// removeAllActions()
|
|
308
|
-
smileySprite.removeAllActions();
|
|
309
313
|
game.initData();
|
|
310
314
|
game.presentScene(getReadyScene);
|
|
311
315
|
});
|
|
@@ -325,69 +329,14 @@ class {{className}} extends Game {
|
|
|
325
329
|
});
|
|
326
330
|
endScene.addChild(exitButton);
|
|
327
331
|
|
|
328
|
-
const smileySprite = new Sprite({ imageName: "smiley" });
|
|
329
|
-
endScene.addChild(smileySprite);
|
|
330
|
-
|
|
331
332
|
endScene.setup(() => {
|
|
332
333
|
doneLabel.text = `You did ${game.trialIndex} trials. You're done!`;
|
|
333
|
-
|
|
334
|
-
// example of how to position a sprite and create an action to move it
|
|
335
|
-
smileySprite.position = new Point(200, 500);
|
|
336
|
-
smileySprite.run(
|
|
337
|
-
Action.Move({ point: new Point(200, 100), duration: 3000 })
|
|
338
|
-
);
|
|
339
334
|
});
|
|
340
335
|
|
|
341
336
|
game.entryScene = "instructions-01";
|
|
342
337
|
}
|
|
343
338
|
}
|
|
344
339
|
|
|
345
|
-
// ===========================================================================
|
|
346
|
-
|
|
347
|
-
//#region to support m2c2kit in Android WebView
|
|
348
|
-
/** When running within an Android WebView, the below defines how the session
|
|
349
|
-
* can communicate events back to the Android app. Note: names of this Android
|
|
350
|
-
* namespace and its functions must match the corresponding Android code
|
|
351
|
-
* in addJavascriptInterface() and @JavascriptInterface */
|
|
352
|
-
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
353
|
-
declare namespace Android {
|
|
354
|
-
function onGameTrialComplete(gameTrialEventAsString: string): void;
|
|
355
|
-
function onGameLifecycleChange(gameLifecycleEventAsString: string): void;
|
|
356
|
-
function onSessionLifecycleChange(
|
|
357
|
-
sessionLifecycleEventAsString: string
|
|
358
|
-
): void;
|
|
359
|
-
/** if the Android native app will control the session execution and be
|
|
360
|
-
* able to set custom game paraemters (which is probably what you want),
|
|
361
|
-
* be sure that sessionManualStart() in the native code returns true */
|
|
362
|
-
function sessionManualStart(): boolean;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function contextIsAndroidWebView(): boolean {
|
|
366
|
-
return typeof Android !== "undefined";
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function sendEventToAndroid(event: EventBase) {
|
|
370
|
-
switch (event.eventType) {
|
|
371
|
-
case EventType.sessionLifecycle: {
|
|
372
|
-
Android.onSessionLifecycleChange(JSON.stringify(event));
|
|
373
|
-
break;
|
|
374
|
-
}
|
|
375
|
-
case EventType.gameTrial: {
|
|
376
|
-
Android.onGameTrialComplete(JSON.stringify(event));
|
|
377
|
-
break;
|
|
378
|
-
}
|
|
379
|
-
case EventType.gameLifecycle: {
|
|
380
|
-
Android.onGameLifecycleChange(JSON.stringify(event));
|
|
381
|
-
break;
|
|
382
|
-
}
|
|
383
|
-
default:
|
|
384
|
-
throw new Error(
|
|
385
|
-
`attempt to send unknown event ${event.eventType} to Android`
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
//#endregion
|
|
390
|
-
|
|
391
340
|
const game1 = new {{className}}();
|
|
392
341
|
// default was 3 trials; this is how we can specify a different value
|
|
393
342
|
game1.setParameters({ TrialNum: 2 });
|
|
@@ -395,68 +344,71 @@ game1.setParameters({ TrialNum: 2 });
|
|
|
395
344
|
const session = new Session({
|
|
396
345
|
activities: [game1],
|
|
397
346
|
sessionCallbacks: {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
//#endregion
|
|
347
|
+
/**
|
|
348
|
+
* onSessionLifecycleChange() will be called on events such
|
|
349
|
+
* as when the session initialization is complete or when it
|
|
350
|
+
* ends.
|
|
351
|
+
*
|
|
352
|
+
* Once initialized, the session will automatically start,
|
|
353
|
+
* unless we're running in an Android WebView AND a manual start
|
|
354
|
+
* is desired.
|
|
355
|
+
*/
|
|
356
|
+
onSessionLifecycleChange: (ev: SessionLifecycleEvent) => {
|
|
357
|
+
if (ev.initialized) {
|
|
412
358
|
session.start();
|
|
413
359
|
}
|
|
414
|
-
if (
|
|
360
|
+
if (ev.ended) {
|
|
415
361
|
console.log("session ended");
|
|
416
|
-
//#region to support m2c2kit in Android WebView
|
|
417
|
-
if (contextIsAndroidWebView()) {
|
|
418
|
-
sendEventToAndroid(event);
|
|
419
|
-
}
|
|
420
|
-
//#endregion
|
|
421
362
|
}
|
|
422
363
|
},
|
|
423
364
|
},
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
365
|
+
activityCallbacks: {
|
|
366
|
+
/**
|
|
367
|
+
* onActivityDataCreate() is where you insert code to post data to an API
|
|
368
|
+
* or interop with a native function in the host app.
|
|
369
|
+
*
|
|
370
|
+
* newData is the data that was just generated by the completed trial
|
|
371
|
+
* data is all the data, cumulative of all trials, that have been generated.
|
|
372
|
+
*
|
|
373
|
+
* We separate out newData from data in case you want to alter the execution
|
|
374
|
+
* based on the most recent trial, e.g., maybe you want to stop after
|
|
375
|
+
* a certain user behavior or performance threshold in the just completed
|
|
376
|
+
* trial.
|
|
377
|
+
*/
|
|
378
|
+
onActivityDataCreate: (ev: ActivityDataEvent) => {
|
|
379
|
+
console.log(`********** trial complete`);
|
|
380
|
+
console.log("newData: " + JSON.stringify(ev.newData));
|
|
381
|
+
console.log("newData schema: " + JSON.stringify(ev.newDataSchema));
|
|
382
|
+
console.log("data: " + JSON.stringify(ev.data));
|
|
383
|
+
console.log("data schema: " + JSON.stringify(ev.dataSchema));
|
|
384
|
+
console.log(
|
|
385
|
+
"activity parameters: " + JSON.stringify(ev.activityConfiguration)
|
|
386
|
+
);
|
|
438
387
|
},
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
388
|
+
/**
|
|
389
|
+
* onActivityLifecycleChange() notifies us when an activity, such
|
|
390
|
+
* as an assessment or a survey, has completed. Usually, however,
|
|
391
|
+
* we want to know when all the activities are done, so we'll
|
|
392
|
+
* look for the session ending via onSessionLifecycleChange
|
|
393
|
+
*/
|
|
394
|
+
onActivityLifecycleChange: (ev: ActivityLifecycleEvent) => {
|
|
395
|
+
if (ev.ended) {
|
|
396
|
+
console.log(`ended activity ${ev.name}`);
|
|
442
397
|
if (session.nextActivity) {
|
|
443
398
|
session.advanceToNextActivity();
|
|
444
399
|
} else {
|
|
445
400
|
session.end();
|
|
446
401
|
}
|
|
447
|
-
//#region to support m2c2kit in Android WebView
|
|
448
|
-
if (contextIsAndroidWebView()) {
|
|
449
|
-
sendEventToAndroid(event);
|
|
450
|
-
}
|
|
451
|
-
//#endregion
|
|
452
402
|
}
|
|
453
403
|
},
|
|
454
404
|
},
|
|
455
405
|
});
|
|
456
406
|
|
|
457
|
-
/**
|
|
407
|
+
/**
|
|
408
|
+
* Make session also available on window in case we want to control
|
|
458
409
|
* the session through another means, such as other javascript or
|
|
459
|
-
* browser code, or the Android WebView loadUrl() method
|
|
410
|
+
* browser code, or the Android WebView loadUrl() method
|
|
411
|
+
* */
|
|
460
412
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
461
413
|
(window as unknown as any).session = session;
|
|
462
414
|
session.init();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m2c2kit/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "m2c2kit command line interface",
|
|
5
5
|
"module": "dist/cli.js",
|
|
6
6
|
"files": [
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"build": "npm run clean && npm run compile && npm run copy-files && npm run write-dotenv",
|
|
18
18
|
"compile": "tsc",
|
|
19
19
|
"clean": "rimraf dist/ && rimraf build/",
|
|
20
|
-
"copy-files": "copyfiles -f build/src/cli.js dist && copyfiles templates/* fonts/**/* dist/",
|
|
20
|
+
"copy-files": "copyfiles -f build/src/cli.js dist && copyfiles scripts/* templates/* fonts/**/* dist/",
|
|
21
21
|
"write-dotenv": "node write-dotenv.js"
|
|
22
22
|
},
|
|
23
23
|
"author": "",
|