m2c2kit internals
To learn how to write trial schema, we have to expose a little bit more of the inner workings of m2c2kit.
If this section is confusing, don't worry. Just think of all of this as a template for where you put your schema, options, and assessment code. You can follow the template and write sophisticated assessments without understanding all these programming concepts.
The Game
class
To write m2c2kit assessments, we build upon (extend) a class called Game
. Up to this point, the example code has hidden this detail. Think of this class as a blueprint or template that already has lots of built-in functionality for working with assessments.
There are two important methods (a group of code that can be called) on the Game
class:
constructor()
- This is where you define the options, including the trial schema, for your assessment.initialize()
- This is where you set up (or initialize) your assessment.
All the example code you've seen up to this point has simply been the code that was inside the initialize()
method. You've been coding this method all along, without even realizing it!
The Game
class in action
Let's look at an example of how the Game
class is used. A few things to point out:
- To create a new assessment, we define a new class that builds on ("extends") the
Game
class. When you write your own assessments, it doesn't matter what you name it,1 because the user will never see its name. In this example, we call itDocsDemo
:
class DocsDemo extends Game {
- Within the
constructor()
, we define a variable to contain our schema, calleddemoSchema
. The schema has a variable calledtrial_index
that is an integer; this will record in our data which trial the user is on. We also define a variable calledmobile_research_fun
that is a boolean (true or false) value of how the user answers our question.
const demoSchema = {
trial_index: {
type: "integer",
description: "Index of the trial within this assessment, 0-based.",
},
mobile_research_fun: {
type: "boolean",
description: "User response to question about mobile research being fun.",
}
}
- Within the
constructor()
, we define a variable for overall game options, calledoptions
. We will learn more about this later, but for now, just know that theid
for this simple example isdocs
and itsname
isDocumentation Example
. ThepublishUuid
is a universally unique identifier (UUID) so that if this assessment code is shared ("published") with others, it can be uniquely identified, even if someone else codes an assessment with the sameid
andname
. We define the size of our game screen as 200 wide by 400 high, we will use Roboto font for our labels, and we set the schema for all of our game's trials to be what we put in thedemoSchema
variable:
const options = {
name: "Documentation Example",
id: "docs",
publishUuid: "c9ec7b5b-a6cc-4308-9b1c-73b40ae4aa9e",
width: 200, height: 400,
fonts: [{
fontName: "roboto",
url: "fonts/roboto/Roboto-Regular.ttf"
}],
trialSchema: demoSchema
};
Universally unique identifiers
A universally unique identifier (UUID) is 128-bits of data generated with an algorithm to be unique from any other UUID. In text format, they look like 8a523876-907a-4b68-be22-cd6daa8b9566
. Whenever you create a new assessment, it must have its own unique UUID.
You can go to a website, such as https://www.uuidgenerator.net/version4, to generate a UUID. If you are using the m2c2kit CLI to scaffold a new assessment, the CLI will automatically generate a UUID and insert it into your code automatically!
In the tutorial, you will see the same publishUuid
of c9ec7b5b-a6cc-4308-9b1c-73b40ae4aa9e
repeatedly used in different code examples. That is because this is tutorial code -- actual assessments must have their own UUID!
-
The last line of the constructor has the code
super(options)
. This is how we get all the built-in functionality of theGame
class. Just always remember to include this at the end of your constructor. -
Within the
initialize()
, we write our assessment code, as we have been doing all along. The only difference is the first two lines:await super.initialize()
runs some built-in setup code.const game = this
allows us to conveniently refer to the game object (this was hidden from you in the previous examples).
async initialize() {
await super.initialize();
const game = this;
const sceneOne = new Scene({ backgroundColor: WebColors.PaleTurquoise });
game.addScene(sceneOne);
}
So far, our assessment doesn't do much, other than make the scene background a light turquoise. But, it defined a trial schema that is ready to accept data!
Footnotes
-
For the tutorials, however, do not change the class name (
DocsDemo
) or the value ofid
specified inoptions
! This tutorial website engine expect the class name to beDocsDemo
, and the value ofid
to bedocs
, and it will not work if you rename these. ↩