@m2c2kit/core 0.1.6 → 0.1.9

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/index.d.ts CHANGED
@@ -27,12 +27,11 @@ interface EntityEventListener {
27
27
  /**
28
28
  * Position in two-dimensional space.
29
29
  */
30
- declare class Point {
30
+ interface Point {
31
31
  /** Horizonal coordinate */
32
32
  x: number;
33
33
  /** Vertical coordinate */
34
34
  y: number;
35
- constructor(x?: number, y?: number);
36
35
  }
37
36
 
38
37
  interface TapEvent extends EntityEvent {
@@ -40,6 +39,11 @@ interface TapEvent extends EntityEvent {
40
39
  point: Point;
41
40
  }
42
41
 
42
+ interface DrawableOptions {
43
+ anchorPoint?: Point;
44
+ zPosition?: number;
45
+ }
46
+
43
47
  interface Constraints {
44
48
  /** Constrain the top (vertical axis) of this entity to the top of the specified entity. The tops of both will appear at the same vertical location */
45
49
  topToTopOf?: Entity | string;
@@ -79,13 +83,30 @@ interface Layout {
79
83
  constraints?: Constraints;
80
84
  }
81
85
 
86
+ /**
87
+ * Color in red (0-255), green (0-255), blue (0-255), alpha (0-1) format. Must be numeric array of length 4.
88
+ */
89
+ declare type RgbaColor = [number, number, number, number];
90
+
91
+ interface TextOptions {
92
+ /** Text to be displayed */
93
+ text?: string;
94
+ /** Name of font to use for text. Must have been previously loaded */
95
+ fontName?: string;
96
+ /** Color of text. Default is Constants.DEFAULT_FONT_COLOR (WebColors.Black) */
97
+ fontColor?: RgbaColor;
98
+ /** Size of text. Default is Constants.DEFAULT_FONT_SIZE (16) */
99
+ fontSize?: number;
100
+ }
101
+
82
102
  /**
83
103
  * Width and height on two-dimensional space
84
104
  */
85
- declare class Size {
105
+ interface Size {
106
+ /** Horizonal width, x-axis */
86
107
  width: number;
108
+ /** Vertical height, y-axis */
87
109
  height: number;
88
- constructor(width?: number, height?: number);
89
110
  }
90
111
 
91
112
  interface EntityOptions {
@@ -134,7 +155,7 @@ declare abstract class Entity implements EntityOptions {
134
155
  queuedAction?: Action;
135
156
  originalActions: Action[];
136
157
  eventListeners: EntityEventListener[];
137
- uuid: string;
158
+ readonly uuid: string;
138
159
  needsInitialization: boolean;
139
160
  userData: any;
140
161
  loopMessages: Set<string>;
@@ -209,9 +230,20 @@ declare abstract class Entity implements EntityOptions {
209
230
  * Remove all actions from this entity. If actions are running, they will be stopped.
210
231
  */
211
232
  removeAllActions(): void;
212
- private static getEntityOptions;
213
- private static getDrawableOptions;
214
- private static getTextOptions;
233
+ /**
234
+ * Duplicates an entity using deep copy.
235
+ *
236
+ * @remarks This is a deep recursive clone (entity and children).
237
+ * The uuid property of all duplicated entities will be newly created,
238
+ * because uuid must be unique.
239
+ *
240
+ * @param newName - optional name of the new, duplicated entity. If not
241
+ * provided, name will be the new uuid
242
+ */
243
+ abstract duplicate(newName?: string): Entity;
244
+ protected getEntityOptions(): EntityOptions;
245
+ protected getDrawableOptions(): DrawableOptions;
246
+ protected getTextOptions(): TextOptions;
215
247
  /**
216
248
  * Gets the scene that contains this entity by searching up the ancestor tree recursively. Throws exception if entity is not part of a scene.
217
249
  *
@@ -375,6 +407,11 @@ declare class ScaleAction extends Action {
375
407
  constructor(scale: number, duration: number, runDuringTransition?: boolean);
376
408
  }
377
409
 
410
+ declare enum ActivityType {
411
+ game = "Game",
412
+ survey = "Survey"
413
+ }
414
+
378
415
  declare class LoadedImage {
379
416
  name: string;
380
417
  image: Image;
@@ -384,18 +421,21 @@ declare class LoadedImage {
384
421
  }
385
422
 
386
423
  /**
387
- * Image that can be rendered by a browser and loaded from a URL or HTML svg tag in string form.
424
+ * Image that can be rendered by a browser from a URL or from a
425
+ * HTML svg tag in string form. Provide either url or svgString, not both.
388
426
  */
389
427
  interface BrowserImage {
390
- /** Name that will be used to refer to the SVG image. Must be unique among all images */
428
+ /** Name that will be used to refer to the image. Must be unique among all
429
+ * images within a game */
391
430
  name: string;
392
- /** Width to scale SVG image to */
431
+ /** Width to scale image to */
393
432
  width: number;
394
- /** Height to scale SVG image to */
433
+ /** Height to scale image to */
395
434
  height: number;
396
- /** The HTML SVG tag, in string form, that will be rendered and loaded. Must begin with &#60;svg> and end with &#60;/svg> */
435
+ /** The HTML SVG tag, in string form, that will be rendered and loaded.
436
+ * Must begin with &#60;svg> and end with &#60;/svg> */
397
437
  svgString?: string;
398
- /** URL of SVG asset to render and load */
438
+ /** URL of image asset (svg, png, jpg) to render and load */
399
439
  url?: string;
400
440
  }
401
441
 
@@ -411,24 +451,71 @@ declare class ImageManager {
411
451
  private _scratchCanvas?;
412
452
  private ctx?;
413
453
  private scale?;
454
+ /**
455
+ * Returns a CanvasKit Image that was previously rendered by the ImageManager.
456
+ *
457
+ * @remarks Typically, this won't be called directly because a programmer
458
+ * will use a higher-level abstraction (m2c2kit Sprite).
459
+ *
460
+ * @param gameUuid - The game that the image resource is part of
461
+ * @param imageName - The name given to the rendered image
462
+ * @returns A CanvasKit Image
463
+ */
414
464
  getLoadedImage(gameUuid: string, imageName: string): LoadedImage;
415
465
  /**
416
- * Adds a CanvasKit image to the images available to a given game.
417
- * Typically, this won't be called directly because images will be
466
+ * Adds a CanvasKit Image to the images available to a given game.
467
+ *
468
+ * @remarks Typically, a programmer won't call this because images will be
418
469
  * automatically rendered and loaded in the Activity async init.
419
- * The only time this function is called in-game is to add
420
- * screenshot images needed for transitions
470
+ * The only time this function is called in-game is when our internal
471
+ * methods add screenshot images needed for transitions.
421
472
  *
422
- * @param loadedImage
423
- * @param gameUuid
473
+ * @param loadedImage - An image that has been converted to a CanvasKit Image
474
+ * @param gameUuid - The game that the Image is part of
424
475
  */
425
476
  addLoadedImage(loadedImage: LoadedImage, gameUuid: string): void;
477
+ /**
478
+ * Renders game images from their original format (png, jpg, svg) to
479
+ * CanvasKit Image.
480
+ *
481
+ * @remarks Typically, a programmer won't call this because the Session
482
+ * object will manage this. Rendering is an async activity, and thus
483
+ * this method returns a promise. Rendering of all images is done in
484
+ * parallel.
485
+ *
486
+ * @param allGamesImages - An array of GameImages data structures that
487
+ * specify the image's desired size, it's name, and where the image to be
488
+ * rendered is located (e.g., embedded svgString or url)
489
+ * @returns A promise that completes when all game images have rendered
490
+ */
426
491
  renderImages(allGamesImages: Array<GameImages>): Promise<void[]>;
492
+ /**
493
+ * Adds all rendered CanvasKit Images to the images available to m2c2kit.
494
+ *
495
+ * @remarks Typically, a programmer won't call this because the Session
496
+ * object will manage this.
497
+ */
427
498
  loadAllGamesRenderedImages(): void;
499
+ /**
500
+ * Our private method rendering an image to a CanvasKit Image
501
+ *
502
+ * @remarks This is complex because there is a separate flow to render
503
+ * svg images versus other (e.g., jpg, png). Svg images may be provided
504
+ * in a url or inline. In addition, there is a Firefox svg rendering issue,
505
+ * see below, that must be handled.
506
+ * Additional complexity comes from the potentially multiple async steps and
507
+ * the multiple errors that can happen throughout.
508
+ *
509
+ * @param gameUuid
510
+ * @param browserImage
511
+ * @returns A promise of type void
512
+ */
428
513
  private renderBrowserImage;
429
514
  private convertRenderedDataUrlImageToCanvasKitImage;
430
515
  /**
431
- * scratchCanvas is an extra, non-visible canvas in the DOM we use so the native browser can render images
516
+ * Returns the scratchCanvas, which is an extra, non-visible canvas in the
517
+ * DOM we use so the native browser can render images like svg, png, jpg,
518
+ * that we later will convert to CanvasKit Image.
432
519
  */
433
520
  private get scratchCanvas();
434
521
  private dataURLtoArrayBuffer;
@@ -484,22 +571,143 @@ declare class FontManager {
484
571
  private loadGameFonts;
485
572
  }
486
573
 
487
- interface GameEvent {
488
- gameUuid: string;
489
- gameName: string;
574
+ interface EventBase {
575
+ eventType: EventType;
576
+ }
577
+ /** Note: I would have named it Event, but that would collide with
578
+ * the existing, and much more well-known, Web API Event */
579
+ declare enum EventType {
580
+ activityData = "ActivityData",
581
+ activityLifecycle = "ActivityLifecycle",
582
+ sessionLifecycle = "SessionLifecycle"
490
583
  }
491
584
 
492
- interface GameLifecycleEvent extends GameEvent {
493
- ended: boolean;
585
+ interface ActivityEvent extends EventBase {
586
+ uuid: string;
587
+ name: string;
494
588
  }
495
589
 
496
- interface GameParameters {
497
- [key: string]: DefaultParameter;
498
- }
499
- interface DefaultParameter {
500
- value: any;
501
- type?: "number" | "string" | "boolean" | "object";
502
- description?: string;
590
+ interface ActivityData {
591
+ [key: string]: string | number | boolean | object | undefined | null;
592
+ }
593
+
594
+ interface ActivityDataEvent extends ActivityEvent {
595
+ newData: ActivityData;
596
+ newDataSchema: any;
597
+ data: ActivityData;
598
+ dataSchema: any;
599
+ activityConfiguration: any;
600
+ }
601
+
602
+ interface ActivityLifecycleEvent extends ActivityEvent {
603
+ /** the activity started. */
604
+ started?: boolean;
605
+ /** the activity ended. the user fully completed the activity and */
606
+ ended?: boolean;
607
+ /** the activity ended. the user canceled without fully completing the activity */
608
+ userCanceled?: boolean;
609
+ }
610
+
611
+ interface ActivityCallbacks {
612
+ /** Callback executed when the activity lifecycle changes, such as when it ends. */
613
+ onActivityLifecycleChange?: (event: ActivityLifecycleEvent) => void;
614
+ /** Callback executed when an activity creates some data. */
615
+ onActivityDataCreate?: (event: ActivityDataEvent) => void;
616
+ }
617
+
618
+ interface SessionEvent extends EventBase {
619
+ }
620
+
621
+ interface SessionLifecycleEvent extends SessionEvent {
622
+ initialized?: boolean;
623
+ ended?: boolean;
624
+ started?: boolean;
625
+ }
626
+
627
+ interface SessionCallbacks {
628
+ /** Callback executed when the session lifecycle changes, such as when it is initialized. */
629
+ onSessionLifecycleChange?: (event: SessionLifecycleEvent) => void;
630
+ }
631
+
632
+ interface SessionOptions {
633
+ /** The activities that compose this session */
634
+ activities: Array<Activity>;
635
+ /** Callbacks executed when activity events occurs, such as when activity creates data or ends */
636
+ activityCallbacks?: ActivityCallbacks;
637
+ /** Callbacks executed when session events occur */
638
+ sessionCallbacks?: SessionCallbacks;
639
+ }
640
+
641
+ declare class Session {
642
+ options: SessionOptions;
643
+ fontManager: FontManager;
644
+ imageManager: ImageManager;
645
+ currentActivity?: Activity;
646
+ uuid: string;
647
+ private canvasKit?;
648
+ /**
649
+ * A Session contains one or more activities; currently, the only
650
+ * class that implements Activity is Game, but Survey is planned.
651
+ * The session manages the start and stop of activities, and
652
+ * advancement to next activity
653
+ *
654
+ * @param options
655
+ */
656
+ constructor(options: SessionOptions);
657
+ /**
658
+ * Asynchronously initializes the m2c2kit engine and loads assets
659
+ */
660
+ init(): Promise<void>;
661
+ /**
662
+ * Starts the session and starts the first activity.
663
+ */
664
+ start(): void;
665
+ /**
666
+ * Declares the session ended and sends callback.
667
+ */
668
+ end(): void;
669
+ /**
670
+ * Stops the current activity and advances to next activity in the session.
671
+ * If there is no activity after the current activity, throws error
672
+ */
673
+ advanceToNextActivity(): void;
674
+ /**
675
+ * Gets the next activity after the current one, or undefined if
676
+ * this is the last activity.
677
+ */
678
+ get nextActivity(): Activity | undefined;
679
+ private logStartingActivity;
680
+ /**
681
+ * Gets asynchronous assets, including initialization of canvaskit wasm,
682
+ * fetching of fonts from specified urls, and rendering and fetching
683
+ * of images
684
+ * @returns
685
+ */
686
+ private getAsynchronousAssets;
687
+ private loadCanvasKit;
688
+ private loadAssets;
689
+ private assignCanvasKit;
690
+ private getFontsConfigurationFromGames;
691
+ private getImagesConfigurationFromGames;
692
+ }
693
+
694
+ interface Activity {
695
+ /** The type of activity: Game or Survey */
696
+ type: ActivityType;
697
+ /** Initializes the activity. */
698
+ init(): void;
699
+ /** Starts the activity */
700
+ start(): void;
701
+ /** Stops the activity */
702
+ stop(): void;
703
+ /** The activity's parent session */
704
+ session: Session;
705
+ /** The activity's unique identifier. NOTE: This is newly generated each session. The uuid for an activity will vary across sessions. */
706
+ uuid: string;
707
+ /** The activity's human friendly name */
708
+ name: string;
709
+ /** Set activity parameters if defaults are not desired*/
710
+ setParameters(newParameters: any): void;
503
711
  }
504
712
 
505
713
  interface IDrawable {
@@ -508,14 +716,63 @@ interface IDrawable {
508
716
  zPosition: number;
509
717
  }
510
718
 
719
+ interface CompositeOptions extends EntityOptions, DrawableOptions {
720
+ }
721
+
722
+ declare abstract class Composite extends Entity implements IDrawable {
723
+ readonly type = EntityType.composite;
724
+ compositeType: string;
725
+ isDrawable: boolean;
726
+ anchorPoint: Point;
727
+ zPosition: number;
728
+ /**
729
+ * Base Drawable object for creating custom entities ("composites") composed of primitive entities.
730
+ *
731
+ * @param options
732
+ */
733
+ constructor(options?: CompositeOptions);
734
+ initialize(): void;
735
+ update(): void;
736
+ draw(canvas: Canvas): void;
737
+ }
738
+
511
739
  /**
512
- * Color in red (0-255), green (0-255), blue (0-255), alpha (0-1) format. Must be numeric array of length 4.
740
+ * Reasonable defaults to use if values are not specified.
513
741
  */
514
- declare type RgbaColor = [number, number, number, number];
742
+ declare class Constants {
743
+ static readonly FPS_DISPLAY_TEXT_FONT_SIZE = 12;
744
+ static readonly FPS_DISPLAY_TEXT_COLOR: RgbaColor;
745
+ static readonly FPS_DISPLAY_UPDATE_INTERVAL = 500;
746
+ static readonly DEFAULT_SCENE_BACKGROUND_COLOR: RgbaColor;
747
+ static readonly DEFAULT_SHAPE_FILL_COLOR: RgbaColor;
748
+ static readonly DEFAULT_FONT_COLOR: RgbaColor;
749
+ static readonly DEFAULT_FONT_SIZE = 16;
750
+ static readonly LIMITED_FPS_RATE = 5;
751
+ }
515
752
 
516
- interface DrawableOptions {
517
- anchorPoint?: Point;
518
- zPosition?: number;
753
+ /**
754
+ * This enum is used interally for processing the layout constraints. We use
755
+ * an enum to avoid magic strings.
756
+ */
757
+ declare enum ConstraintType {
758
+ topToTopOf = "topToTopOf",
759
+ topToBottomOf = "topToBottomOf",
760
+ bottomToTopOf = "bottomToTopOf",
761
+ bottomToBottomOf = "bottomToBottomOf",
762
+ startToStartOf = "startToStartOf",
763
+ startToEndOf = "startToEndOf",
764
+ endToEndOf = "endToEndOf",
765
+ endToStartOf = "endToStartOf"
766
+ }
767
+
768
+ declare enum Dimensions {
769
+ MATCH_CONSTRAINT = 0
770
+ }
771
+
772
+ interface FontData {
773
+ gameUuid: string;
774
+ fontUrl: string;
775
+ fontArrayBuffer: ArrayBuffer;
519
776
  }
520
777
 
521
778
  interface SceneOptions extends EntityOptions, DrawableOptions {
@@ -526,12 +783,16 @@ interface SceneOptions extends EntityOptions, DrawableOptions {
526
783
  declare class Scene extends Entity implements IDrawable, SceneOptions {
527
784
  readonly type = EntityType.scene;
528
785
  isDrawable: boolean;
529
- anchorPoint: Point;
786
+ anchorPoint: {
787
+ x: number;
788
+ y: number;
789
+ };
530
790
  zPosition: number;
531
791
  private _backgroundColor;
532
792
  _active: boolean;
533
793
  _transitioning: boolean;
534
794
  _setupCallback?: (scene: Scene) => void;
795
+ _appearCallback?: (scene: Scene) => void;
535
796
  private _game?;
536
797
  private backgroundPaint?;
537
798
  /**
@@ -548,13 +809,31 @@ declare class Scene extends Entity implements IDrawable, SceneOptions {
548
809
  get backgroundColor(): RgbaColor;
549
810
  set backgroundColor(backgroundColor: RgbaColor);
550
811
  /**
551
- * Code that will be called every time the screen is first presented.
812
+ * Duplicates an entity using deep copy.
813
+ *
814
+ * @remarks This is a deep recursive clone (entity and children).
815
+ * The uuid property of all duplicated entities will be newly created,
816
+ * because uuid must be unique.
817
+ *
818
+ * @param newName - optional name of the new, duplicated entity. If not
819
+ * provided, name will be the new uuid
820
+ */
821
+ duplicate(newName?: string): Scene;
822
+ /**
823
+ * Code that will be called every time the screen is presented.
552
824
  *
553
825
  * @remarks Use this callback to set entities to their initial state, if that state might be changed later. For example, if a scene allows players to place dots on a grid, the setup() method should ensure the grid is clear of any prior dots from previous times this scene may have been displayed. In addition, if entities should vary in each iteration, that should be done here.
554
826
  *
555
827
  * @param callback
556
828
  */
557
- setup(callback: (scene: Scene) => void): void;
829
+ onSetup(callback: (scene: Scene) => void): void;
830
+ /**
831
+ *
832
+ * Code that will be called after the scene has finished any transitions and has fully appeared on the screen.
833
+ *
834
+ * @param callback
835
+ */
836
+ onAppear(callback: (scene: Scene) => void): void;
558
837
  draw(canvas: Canvas): void;
559
838
  }
560
839
 
@@ -594,7 +873,16 @@ interface TrialSchema {
594
873
  [key: string]: PropertySchema;
595
874
  }
596
875
  interface PropertySchema {
597
- type: "number" | "string" | "boolean" | "object";
876
+ type: "number" | "string" | "boolean" | "object" | "array";
877
+ description?: string;
878
+ }
879
+
880
+ interface GameParameters {
881
+ [key: string]: DefaultParameter;
882
+ }
883
+ interface DefaultParameter {
884
+ value: any;
885
+ type?: "number" | "string" | "boolean" | "object";
598
886
  description?: string;
599
887
  }
600
888
 
@@ -636,18 +924,46 @@ interface GameOptions {
636
924
  _unitTesting?: boolean;
637
925
  }
638
926
 
927
+ interface GameData extends ActivityData {
928
+ trials: Array<TrialData>;
929
+ metadata: Metadata;
930
+ }
931
+
639
932
  interface TrialData {
640
933
  [key: string]: string | number | boolean | undefined | null;
641
934
  }
642
935
  interface Metadata {
643
936
  userAgent?: string;
937
+ devicePixelRatio?: number;
938
+ screen?: screenMetadata;
939
+ }
940
+ /**
941
+ * screenMetadata is similar to window.Screen, except we don't want the
942
+ * methods on the window.Screen.ScreenOrientation
943
+ */
944
+ interface screenMetadata {
945
+ readonly availHeight: number;
946
+ readonly availWidth: number;
947
+ readonly colorDepth: number;
948
+ readonly height: number;
949
+ /** ScreenOrientation has some methods on it; we only want these two properties
950
+ * However, when unit testing, orientation is not available to us. Thus, make this
951
+ * property optional
952
+ */
953
+ readonly orientation?: Pick<ScreenOrientation, "type" | "angle">;
954
+ readonly pixelDepth: number;
955
+ readonly width: number;
644
956
  }
645
957
  declare class Game implements Activity {
958
+ readonly type = ActivityType.game;
646
959
  _canvasKit?: CanvasKit;
647
960
  _session?: Session;
648
961
  uuid: string;
962
+ name: string;
649
963
  options: GameOptions;
650
- constructor(options: GameOptions, specifiedParameters?: any);
964
+ constructor(options: GameOptions);
965
+ init(): void;
966
+ setParameters(newParameters: any): void;
651
967
  get canvasKit(): CanvasKit;
652
968
  set canvasKit(canvasKit: CanvasKit);
653
969
  get session(): Session;
@@ -676,6 +992,7 @@ declare class Game implements Activity {
676
992
  private scenes;
677
993
  private incomingSceneTransitions;
678
994
  private currentSceneSnapshot?;
995
+ private pendingScreenshot?;
679
996
  /**
680
997
  * Adds a scene to the game.
681
998
  *
@@ -712,6 +1029,7 @@ declare class Game implements Activity {
712
1029
  start(entryScene?: Scene | string): void;
713
1030
  stop(): void;
714
1031
  initData(): void;
1032
+ private getScreenMetadata;
715
1033
  /**
716
1034
  * Adds data to the game's TrialData object.
717
1035
  *
@@ -724,7 +1042,7 @@ declare class Game implements Activity {
724
1042
  /**
725
1043
  * Should be called when the current trial has completed. It will
726
1044
  * also increment the trial index.
727
- * Calling this will trigger the onGameTrialComplete callback function,
1045
+ * Calling this will trigger the onActivityDataCreate callback function,
728
1046
  * if one was provided in SessionOptions. This is how the game communicates
729
1047
  * trial data to the parent session, which can then save or process the data.
730
1048
  * It is the responsibility of the the game programmer to call this at
@@ -733,7 +1051,7 @@ declare class Game implements Activity {
733
1051
  trialComplete(): void;
734
1052
  /**
735
1053
  * Should be called when the current game has ended. This will trigger
736
- * the onGameLifecycleChange callback function, if one was provided in
1054
+ * the onActivityLifecycleChange callback function, if one was provided in
737
1055
  * SessionOptions. This is how the game can communicate its ended or
738
1056
  * "finished" state to the parent session.
739
1057
  * It is the responsibility of the the game programmer to call this at
@@ -750,6 +1068,23 @@ declare class Game implements Activity {
750
1068
  private update;
751
1069
  private draw;
752
1070
  private takeCurrentSceneSnapshot;
1071
+ private handlePendingScreenshot;
1072
+ /**
1073
+ * Takes screenshot of canvas
1074
+ *
1075
+ * @remarks Coordinates should be provided unscaled; that is, the method
1076
+ * will handle any scaling that happened due to device pixel ratios
1077
+ * not equal to 1. This returns a promise because the screenshot request
1078
+ * must be queued and completed once a draw cycle has completed. See
1079
+ * the loop() method.
1080
+ *
1081
+ * @param sx - Upper left coordinate of screenshot
1082
+ * @param sy - Upper right coordinate of screenshot
1083
+ * @param sw - width of area to screenshot
1084
+ * @param sh - hegith of area to screenshot
1085
+ * @returns Promise of Uint8Array of image data
1086
+ */
1087
+ takeScreenshot(sx?: number, sy?: number, sw?: number, sh?: number): Promise<Uint8Array | null>;
753
1088
  private animateSceneTransition;
754
1089
  private drawFps;
755
1090
  /**
@@ -776,151 +1111,6 @@ declare class Game implements Activity {
776
1111
  private calculateEntityAbsoluteBoundingBox;
777
1112
  }
778
1113
 
779
- interface GameData {
780
- trials: Array<TrialData>;
781
- metadata: Metadata;
782
- }
783
-
784
- interface GameTrialEvent extends GameEvent {
785
- trialIndex: number;
786
- trialSchema: TrialSchema;
787
- gameData: GameData;
788
- gameParameters: GameParameters;
789
- }
790
-
791
- interface GameCallbacks {
792
- /** Callback executed when the game lifecycle changes, such as when it ends. */
793
- onGameLifecycleChange?: (event: GameLifecycleEvent) => void;
794
- /** Callback executed when a game trial completes. */
795
- onGameTrialComplete?: (event: GameTrialEvent) => void;
796
- }
797
-
798
- interface SessionOptions {
799
- /** The activities that compose this session */
800
- activities: Array<Activity>;
801
- /** Callbacks executed when trials are completed and when game ends */
802
- gameCallbacks?: GameCallbacks;
803
- }
804
-
805
- declare class Session {
806
- options: SessionOptions;
807
- fontManager: FontManager;
808
- imageManager: ImageManager;
809
- currentActivity?: Activity;
810
- uuid: string;
811
- private canvasKit?;
812
- /**
813
- * A Session contains one or more activities; currently, the only
814
- * class that implements Activity is Game, but Survey is planned.
815
- * The session manages the start and stop of activities, and
816
- * advancement to next activity
817
- *
818
- * @param options
819
- */
820
- constructor(options: SessionOptions);
821
- /**
822
- * Asynchronously initializes the m2c2kit engine and loads assets
823
- */
824
- init(): Promise<void>;
825
- /**
826
- * Starts the session and starts the first activity.
827
- */
828
- start(): void;
829
- /**
830
- * Stops the current activity and advances to next activity in the session.
831
- * If there is no activity after the current activity, throws error
832
- */
833
- advanceToNextActivity(): void;
834
- /**
835
- * Gets the next activity after the current one, or undefined if
836
- * this is the last activity.
837
- */
838
- get nextActivity(): Activity | undefined;
839
- private logStartingActivity;
840
- /**
841
- * Gets asynchronous assets, including initialization of canvaskit wasm,
842
- * fetching of fonts from specified urls, and rendering and fetching
843
- * of images
844
- * @returns
845
- */
846
- private getAsynchronousAssets;
847
- private loadCanvasKit;
848
- private loadAssets;
849
- private assignCanvasKit;
850
- private getFontsConfigurationFromGames;
851
- private getImagesConfigurationFromGames;
852
- }
853
-
854
- interface Activity {
855
- /** Starts the activity */
856
- start(): void;
857
- /** Stops the activity */
858
- stop(): void;
859
- /** The activity's parent session */
860
- session: Session;
861
- /** The activity's unique identifier. NOTE: This is newly generated each session. The uuid for an activity will vary across sessions. */
862
- uuid: string;
863
- }
864
-
865
- interface CompositeOptions extends EntityOptions, DrawableOptions {
866
- }
867
-
868
- declare abstract class Composite extends Entity implements IDrawable {
869
- readonly type = EntityType.composite;
870
- compositeType: string;
871
- isDrawable: boolean;
872
- anchorPoint: Point;
873
- zPosition: number;
874
- /**
875
- * Base Drawable object for creating custom entities ("composites") composed of primitive entities.
876
- *
877
- * @param options
878
- */
879
- constructor(options?: CompositeOptions);
880
- initialize(): void;
881
- update(): void;
882
- draw(canvas: Canvas): void;
883
- }
884
-
885
- /**
886
- * Reasonable defaults to use if values are not specified.
887
- */
888
- declare class Constants {
889
- static readonly FPS_DISPLAY_TEXT_FONT_SIZE = 12;
890
- static readonly FPS_DISPLAY_TEXT_COLOR: RgbaColor;
891
- static readonly FPS_DISPLAY_UPDATE_INTERVAL = 500;
892
- static readonly DEFAULT_SCENE_BACKGROUND_COLOR: RgbaColor;
893
- static readonly DEFAULT_SHAPE_FILL_COLOR: RgbaColor;
894
- static readonly DEFAULT_FONT_COLOR: RgbaColor;
895
- static readonly DEFAULT_FONT_SIZE = 16;
896
- static readonly LIMITED_FPS_RATE = 5;
897
- }
898
-
899
- /**
900
- * This enum is used interally for processing the layout constraints. We use
901
- * an enum to avoid magic strings.
902
- */
903
- declare enum ConstraintType {
904
- topToTopOf = "topToTopOf",
905
- topToBottomOf = "topToBottomOf",
906
- bottomToTopOf = "bottomToTopOf",
907
- bottomToBottomOf = "bottomToBottomOf",
908
- startToStartOf = "startToStartOf",
909
- startToEndOf = "startToEndOf",
910
- endToEndOf = "endToEndOf",
911
- endToStartOf = "endToStartOf"
912
- }
913
-
914
- declare enum Dimensions {
915
- MATCH_CONSTRAINT = 0
916
- }
917
-
918
- interface FontData {
919
- gameUuid: string;
920
- fontUrl: string;
921
- fontArrayBuffer: ArrayBuffer;
922
- }
923
-
924
1114
  interface IText {
925
1115
  text?: string;
926
1116
  fontName?: string;
@@ -928,17 +1118,6 @@ interface IText {
928
1118
  fontSize?: number;
929
1119
  }
930
1120
 
931
- interface TextOptions {
932
- /** Text to be displayed */
933
- text?: string;
934
- /** Name of font to use for text. Must have been previously loaded */
935
- fontName?: string;
936
- /** Color of text. Default is Constants.DEFAULT_FONT_COLOR (WebColors.Black) */
937
- fontColor?: RgbaColor;
938
- /** Size of text. Default is Constants.DEFAULT_FONT_SIZE (16) */
939
- fontSize?: number;
940
- }
941
-
942
1121
  declare enum LabelHorizontalAlignmentMode {
943
1122
  center = 0,
944
1123
  left = 1,
@@ -958,7 +1137,10 @@ declare class Label extends Entity implements IDrawable, IText, LabelOptions {
958
1137
  readonly type = EntityType.label;
959
1138
  isDrawable: boolean;
960
1139
  isText: boolean;
961
- anchorPoint: Point;
1140
+ anchorPoint: {
1141
+ x: number;
1142
+ y: number;
1143
+ };
962
1144
  zPosition: number;
963
1145
  private _text;
964
1146
  private _fontName;
@@ -992,6 +1174,17 @@ declare class Label extends Entity implements IDrawable, IText, LabelOptions {
992
1174
  set preferredMaxLayoutWidth(preferredMaxLayoutWidth: number | undefined);
993
1175
  get backgroundColor(): RgbaColor | undefined;
994
1176
  set backgroundColor(backgroundColor: RgbaColor | undefined);
1177
+ /**
1178
+ * Duplicates an entity using deep copy.
1179
+ *
1180
+ * @remarks This is a deep recursive clone (entity and children).
1181
+ * The uuid property of all duplicated entities will be newly created,
1182
+ * because uuid must be unique.
1183
+ *
1184
+ * @param newName - optional name of the new, duplicated entity. If not
1185
+ * provided, name will be the new uuid
1186
+ */
1187
+ duplicate(newName?: string): Label;
995
1188
  update(): void;
996
1189
  draw(canvas: Canvas): void;
997
1190
  }
@@ -1021,22 +1214,39 @@ declare class LayoutConstraint {
1021
1214
 
1022
1215
  declare class RandomDraws {
1023
1216
  /**
1024
- * Draw random integers, without replacement, from a uniform distribution.
1217
+ * Draws a single random integer from a uniform distribution of integers in
1218
+ * the specified range.
1025
1219
  *
1026
- * @param n
1027
- * @param minimumInclusive
1028
- * @param maximumInclusive
1029
- * @returns array of integers
1220
+ * @param minimumInclusive - Lower bound of range
1221
+ * @param maximumInclusive - Upper bound of range
1222
+ * @returns A sampled integer
1223
+ */
1224
+ static SingleFromRange(minimumInclusive: number, maximumInclusive: number): number;
1225
+ /**
1226
+ * Draws random integers, without replacement, from a uniform distribution
1227
+ * of integers in the specified range.
1228
+ *
1229
+ * @param n - Number of draws
1230
+ * @param minimumInclusive - Lower bound of range
1231
+ * @param maximumInclusive - Upper bound of range
1232
+ * @returns An array of integers
1030
1233
  */
1031
1234
  static FromRangeWithoutReplacement(n: number, minimumInclusive: number, maximumInclusive: number): Array<number>;
1032
1235
  /**
1033
- * Draw random grid cell locations, without replacement, from a uniform distribution of all grid cells. Grid cell locations are zero-based, i.e., upper-left is (0,0).
1236
+ * Draw random grid cell locations, without replacement, from a uniform
1237
+ * distribution of all grid cells. Grid cell locations are zero-based,
1238
+ * i.e., upper-left is (0,0).
1034
1239
  *
1035
1240
  * @param n - Number of draws
1036
1241
  * @param rows - Number of rows in grid; must be at least 1
1037
1242
  * @param columns - Number of columns in grid; must be at least 1
1038
- * @param predicate - Optional lambda function that takes a grid row number and grid column number pair and returns a boolean to indicate if the pair should be allowed. For example, if one wanted to constrain the random grid location to be along the diagonal, the predicate would be: (row, column) => row === column
1039
- * @returns array of grid cells. Each cell is object in form of { row: number, column: number }). Grid cell locations are zero-based
1243
+ * @param predicate - Optional lambda function that takes a grid row number
1244
+ * and grid column number pair and returns a boolean to indicate if the pair
1245
+ * should be allowed. For example, if one wanted to constrain the random
1246
+ * grid location to be along the diagonal, the predicate would be:
1247
+ * (row, column) => row === column
1248
+ * @returns Array of grid cells. Each cell is object in form of:
1249
+ * {row: number, column: number}. Grid cell locations are zero-based
1040
1250
  */
1041
1251
  static FromGridWithoutReplacement(n: number, rows: number, columns: number, predicate?: (row: number, column: number) => boolean): Array<{
1042
1252
  row: number;
@@ -1059,21 +1269,18 @@ interface RectOptions {
1059
1269
  height?: number;
1060
1270
  }
1061
1271
 
1062
- declare class Rect implements RectOptions {
1063
- origin?: Point;
1064
- size?: Size;
1065
- x?: number;
1066
- y?: number;
1067
- width?: number;
1068
- height?: number;
1069
- constructor(options: RectOptions);
1272
+ declare enum ShapeType {
1273
+ undefined = "Undefined",
1274
+ rectangle = "Rectangle",
1275
+ circle = "Circle"
1070
1276
  }
1071
1277
 
1072
1278
  interface ShapeOptions extends EntityOptions, DrawableOptions {
1279
+ shapeType?: ShapeType;
1073
1280
  /** If provided, shape will be a circle with given radius */
1074
1281
  circleOfRadius?: number;
1075
1282
  /** If provided, shape will be a rectangle as specified in {@link Rect} */
1076
- rect?: Rect;
1283
+ rect?: RectOptions;
1077
1284
  /** Radius of rectangle's corners */
1078
1285
  cornerRadius?: number;
1079
1286
  /** Color with which to fill shape. Default is Constants.DEFAULT_SHAPE_FILL_COLOR (WebColors.Red) */
@@ -1084,21 +1291,18 @@ interface ShapeOptions extends EntityOptions, DrawableOptions {
1084
1291
  lineWidth?: number;
1085
1292
  }
1086
1293
 
1087
- declare enum ShapeType {
1088
- undefined = "Undefined",
1089
- rectangle = "Rectangle",
1090
- circle = "Circle"
1091
- }
1092
-
1093
1294
  declare class Shape extends Entity implements IDrawable, ShapeOptions {
1094
1295
  readonly type = EntityType.shape;
1095
1296
  isDrawable: boolean;
1096
1297
  isShape: boolean;
1097
- anchorPoint: Point;
1298
+ anchorPoint: {
1299
+ x: number;
1300
+ y: number;
1301
+ };
1098
1302
  zPosition: number;
1099
1303
  shapeType: ShapeType;
1100
1304
  circleOfRadius?: number;
1101
- rect?: Rect;
1305
+ rect?: RectOptions;
1102
1306
  cornerRadius: number;
1103
1307
  private _fillColor;
1104
1308
  private _strokeColor?;
@@ -1116,6 +1320,17 @@ declare class Shape extends Entity implements IDrawable, ShapeOptions {
1116
1320
  set fillColor(fillColor: RgbaColor);
1117
1321
  get strokeColor(): RgbaColor | undefined;
1118
1322
  set strokeColor(strokeColor: RgbaColor | undefined);
1323
+ /**
1324
+ * Duplicates an entity using deep copy.
1325
+ *
1326
+ * @remarks This is a deep recursive clone (entity and children).
1327
+ * The uuid property of all duplicated entities will be newly created,
1328
+ * because uuid must be unique.
1329
+ *
1330
+ * @param newName - optional name of the new, duplicated entity. If not
1331
+ * provided, name will be the new uuid
1332
+ */
1333
+ duplicate(newName?: string): Shape;
1119
1334
  update(): void;
1120
1335
  draw(canvas: Canvas): void;
1121
1336
  }
@@ -1128,7 +1343,10 @@ interface SpriteOptions extends EntityOptions, DrawableOptions {
1128
1343
  declare class Sprite extends Entity implements IDrawable, SpriteOptions {
1129
1344
  readonly type = EntityType.sprite;
1130
1345
  isDrawable: boolean;
1131
- anchorPoint: Point;
1346
+ anchorPoint: {
1347
+ x: number;
1348
+ y: number;
1349
+ };
1132
1350
  zPosition: number;
1133
1351
  private _imageName;
1134
1352
  private loadedImage?;
@@ -1143,6 +1361,17 @@ declare class Sprite extends Entity implements IDrawable, SpriteOptions {
1143
1361
  initialize(): void;
1144
1362
  set imageName(imageName: string);
1145
1363
  get imageName(): string;
1364
+ /**
1365
+ * Duplicates an entity using deep copy.
1366
+ *
1367
+ * @remarks This is a deep recursive clone (entity and children).
1368
+ * The uuid property of all duplicated entities will be newly created,
1369
+ * because uuid must be unique.
1370
+ *
1371
+ * @param newName - optional name of the new, duplicated entity. If not
1372
+ * provided, name will be the new uuid
1373
+ */
1374
+ duplicate(newName?: string): Sprite;
1146
1375
  update(): void;
1147
1376
  draw(canvas: Canvas): void;
1148
1377
  }
@@ -1164,7 +1393,10 @@ declare class TextLine extends Entity implements IDrawable, IText, TextLineOptio
1164
1393
  isDrawable: boolean;
1165
1394
  isText: boolean;
1166
1395
  zPosition: number;
1167
- anchorPoint: Point;
1396
+ anchorPoint: {
1397
+ x: number;
1398
+ y: number;
1399
+ };
1168
1400
  private _text;
1169
1401
  private _fontName;
1170
1402
  private _fontColor;
@@ -1189,25 +1421,116 @@ declare class TextLine extends Entity implements IDrawable, IText, TextLineOptio
1189
1421
  set fontSize(fontSize: number);
1190
1422
  update(): void;
1191
1423
  initialize(): void;
1424
+ /**
1425
+ * Duplicates an entity using deep copy.
1426
+ *
1427
+ * @remarks This is a deep recursive clone (entity and children).
1428
+ * The uuid property of all duplicated entities will be newly created,
1429
+ * because uuid must be unique.
1430
+ *
1431
+ * @param newName - optional name of the new, duplicated entity. If not
1432
+ * provided, name will be the new uuid
1433
+ */
1434
+ duplicate(newName?: string): TextLine;
1192
1435
  draw(canvas: Canvas): void;
1193
1436
  }
1194
1437
 
1195
1438
  declare class Timer {
1196
- private originTime;
1197
1439
  private startTime;
1198
1440
  private stopTime;
1199
1441
  private stopped;
1200
- private _elapsed;
1442
+ /**
1443
+ * cumulativeElapsed is a cumulative total of elapsed time while the timer
1444
+ * was in previous started (running) states, NOT INCLUDING the possibily
1445
+ * active run's duration
1446
+ */
1447
+ private cumulativeElapsed;
1201
1448
  private name;
1202
1449
  private static _timers;
1203
1450
  constructor(name: string);
1204
- static Start(name: string): void;
1205
- static Stop(name: string): void;
1206
- static Restart(name: string): void;
1207
- static Elapsed(name: string): number;
1208
- static Remove(name: string): void;
1209
- static Exists(name: string): boolean;
1210
- static RemoveAll(): void;
1451
+ /**
1452
+ * Aliases performance.now()
1453
+ *
1454
+ * @remarks The m2c2kit Timer class is designed to measure elapsed durations
1455
+ * after a designated start point for a uniquely named timer. However, if a
1456
+ * timestamp based on the
1457
+ * [time origin](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#the_time_origin)
1458
+ * is needed, this method can be used.
1459
+ *
1460
+ * @returns a [DOMHighResTimeStamp](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp)
1461
+ */
1462
+ static now(): number;
1463
+ /**
1464
+ * Starts a millisecond-resolution timer based on
1465
+ * [performance.now()](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now).
1466
+ *
1467
+ * @remarks The method throws an error if a timer with the given
1468
+ * name is already in a started state.
1469
+ *
1470
+ * @param name - The name of the timer to be started
1471
+ */
1472
+ static start(name: string): void;
1473
+ /**
1474
+ * Stops a timer.
1475
+ *
1476
+ * @remarks The method throws an error if a timer with the given
1477
+ * name is already in a stopped state, or if a timer with the
1478
+ * given name has not been started.
1479
+ *
1480
+ * @param name - The name of the timer to be stopped
1481
+ */
1482
+ static stop(name: string): void;
1483
+ /**
1484
+ * Restarts a timer.
1485
+ *
1486
+ * @remarks The timer elapsed duration is set to 0 and it starts anew.
1487
+ * The method throws an error if a timer with the given
1488
+ * name does not exist (if there is not a started or stopped timer
1489
+ * with the given name).
1490
+ *
1491
+ * @param name - The name of the timer to be restarted
1492
+ */
1493
+ static restart(name: string): void;
1494
+ /**
1495
+ * Returns the total time elapsed, in milliseconds, of the timer.
1496
+ *
1497
+ * @remarks The total time elapsed will include all durations from multiple
1498
+ * starts and stops of the timer, if applicable. A timer's elapsed duration
1499
+ * can be read while it is in started or stopped state. The method throws
1500
+ * an error if a timer with the given name does not exist.
1501
+ *
1502
+ * @param name - The name of the timer whose elapsed duration is requested
1503
+ */
1504
+ static elapsed(name: string): number;
1505
+ /**
1506
+ * Removes a timer.
1507
+ *
1508
+ * @remarks After removal, no additional methods can be used with a timer
1509
+ * of the given name, other than to start a new timer with the given name,
1510
+ * whose duration will begin at 0 again. The method throws an error if
1511
+ * a timer with the given name does not exist.
1512
+ *
1513
+ * @param name - The name of the timer to be removed
1514
+ */
1515
+ static remove(name: string): void;
1516
+ /**
1517
+ * Remove all timers.
1518
+ *
1519
+ * @remarks This method will {@link remove} any timers in a started or
1520
+ * stopped state. This method is idempotent; method is safe to call even
1521
+ * if there are no timers to remove; no errors are thrown if there are
1522
+ * not any timers that can be removed.
1523
+ */
1524
+ static removeAll(): void;
1525
+ /**
1526
+ * Checks if a timer of the given name exists.
1527
+ *
1528
+ * @remarks The method checks if there is a timer with the given name.
1529
+ *
1530
+ * @param name - The name of the timer to check for existence
1531
+ * @returns boolean
1532
+ */
1533
+ static exists(name: string): boolean;
1211
1534
  }
1212
1535
 
1213
1536
  declare class Uuid {
@@ -1359,4 +1682,4 @@ declare class WebColors {
1359
1682
  static RebeccaPurple: RgbaColor;
1360
1683
  }
1361
1684
 
1362
- export { Action, Activity, BrowserImage, Composite, CompositeOptions, Constants, ConstraintType, Constraints, CustomAction, CustomActionOptions, DefaultParameter, Dimensions, DrawableOptions, Entity, EntityEventListener, EntityOptions, EntityType, FontData, FontManager, Game, GameCallbacks, GameData, GameLifecycleEvent, GameOptions, GameParameters, GameTrialEvent, GlobalVariables, GroupAction, IDrawable, IText, ImageManager, Label, LabelHorizontalAlignmentMode, LabelOptions, Layout, LayoutConstraint, LoadedImage, Metadata, MoveAction, MoveActionOptions, Point, PropertySchema, PushTransition, RandomDraws, Rect, RectOptions, RgbaColor, ScaleAction, ScaleActionOptions, Scene, SceneOptions, SceneTransition, SequenceAction, Session, SessionOptions, Shape, ShapeOptions, ShapeType, Size, Sprite, SpriteOptions, Story, StoryOptions, TextLine, TextLineOptions, TextOptions, Timer, Transition, TransitionDirection, TransitionType, TrialData, TrialSchema, Uuid, WaitAction, WaitActionOptions, WebColors, handleInterfaceOptions };
1685
+ export { Action, Activity, ActivityDataEvent, ActivityLifecycleEvent, ActivityType, BrowserImage, Composite, CompositeOptions, Constants, ConstraintType, Constraints, CustomAction, CustomActionOptions, DefaultParameter, Dimensions, DrawableOptions, Entity, EntityEventListener, EntityOptions, EntityType, EventBase, EventType, FontData, FontManager, Game, GameData, GameOptions, GameParameters, GlobalVariables, GroupAction, IDrawable, IText, ImageManager, Label, LabelHorizontalAlignmentMode, LabelOptions, Layout, LayoutConstraint, LoadedImage, Metadata, MoveAction, MoveActionOptions, Point, PropertySchema, PushTransition, RandomDraws, RectOptions, RgbaColor, ScaleAction, ScaleActionOptions, Scene, SceneOptions, SceneTransition, SequenceAction, Session, SessionLifecycleEvent, SessionOptions, Shape, ShapeOptions, ShapeType, Size, Sprite, SpriteOptions, Story, StoryOptions, TextLine, TextLineOptions, TextOptions, Timer, Transition, TransitionDirection, TransitionType, TrialData, TrialSchema, Uuid, WaitAction, WaitActionOptions, WebColors, handleInterfaceOptions };