assessml
v0.14.0
Published
AssessML (Assessment Markup Language) is a concise and flexible declarative language for educational assessments. This repository contains the language specification and JavaScript implementations of various language tools (AST generator, compilers, etc).
Downloads
27
Readme
AssessML (Assessment Markup Language)
AssessML (Assessment Markup Language) is a concise and flexible declarative language for educational assessments. It is meant to be used with assessment editors such as assess-elements to create a fully featured assessment experience. This repository contains the language specification and JavaScript implementations of various language tools (AST generator, compilers, etc).
Installation
npm install assessml
Use
The elements are written in TypeScript, and there is no built-in build process. You will have to provide your own build process to consume them. We use Zwitterion.
import {
generateAST,
compileToHTML,
compileToAssessML
} from 'assessml';
// generate AST
const ast = generateAST(`
What time is it?
[radio1]1:00pm[radio1]
[radio2]2:00pm[radio2]
[radio3]3:00pm[radio3]
[radio4]4:00pm[radio4]
`);
// compile to HTML from source code
const html = compileToHTML(`
What time is it?
[radio1]1:00pm[radio1]
[radio2]2:00pm[radio2]
[radio3]3:00pm[radio3]
[radio4]4:00pm[radio4]
`);
// compile to HTML from AST
const html = compileToHTML(ast);
// compile to AssessML from source code
const assessML = compileToAssessML(`
What time is it?
[radio1]1:00pm[radio1]
[radio2]2:00pm[radio2]
[radio3]3:00pm[radio3]
[radio4]4:00pm[radio4]
`);
// compile to AssessML from AST
const assessML = compileToAssessML(ast);
If you use TypeScript, you can import the typings:
import {
AST,
Check,
Content,
Drag,
Drop,
Essay,
Input,
Radio,
Variable
} from 'assessml';
Development
Clone the repository:
SSH:
git clone [email protected]:Prendus/assessml.git
HTTPS:
git clone https://github.com/Prendus/assessml.git
Install all dependencies:
cd assessml
npm install
Run test cases in terminal:
npm run test
Run test cases manually in browser:
npm run test-manual
Language specification
Syntax examples
AssessML is meant to be used with an assessment editor to provide functionality such as answer checking. We will use assess-elements for our examples. Exercises created with assess-elements have two components, which can be described as the exercise text and the answer code. The exercise text describes what the user will see, and is written with AssessML. The answer code gives the exercise its functionality, is where the final answer will need to be calculated, and is written in JavaScript. The following are examples of currently available AssessML tags, along with sample JavaScript functionality.
Variable
AssessML (exercise text)
[var1] + [var2] = [input1]
JavaScript (answer code)
// randInt has been defined elsewhere
var1 = randInt(0, 25);
var2 = randInt(26, 50);
answer = input1 == var1 + var2;
Variable tags present variable strings or numbers to the user. The compileToHTML
function takes a function as a parameter that will generate default initial values for variables. Variable names must start with var
and end with any non-empty string. In the assess-elements assessment editor, variable tags declared in the exercise text will create variables with equivalent names in the answer code. These variables will contain the string or number value of the variable. Minimum and maximum values, as well as decimal precision, can be set using JavaScript functions defined elsewhere.
Fill in the blank
AssessML (exercise text)
Fill in the blanks:
Sally was [input1] across the field when she realized that she [input2] into a stream of [input3] water.
JavaScript (answer code)
answer = (
input1 === 'running' &&
input2 === 'ran' &&
input3 === 'running'
);
Input tags create small inputs for users to enter short responses. Input names must start with input
and end with any non-empty string. In the assess-elements assessment editor, input tags declared in the exercise text will create variables with equivalent names in the answer code. These variables will contain the string entered by the user into the input.
Essay
AssessML (exercise text)
Tell me about your feelings:
[essay1]
JavaScript (answer code)
answer = essay1.includes('happy');
Essay tags provide a large textarea for users to write essay responses. Any JavaScript functionality can be used in the answer code to determine if the question is answered correctly. In this example, we use a simple string function to check if the user has mentioned the word happy
anywhere in the response. Essay names must start with essay
and end with any non-empty string. In the assess-elements assessment editor, essay tags declared in the exercise text will create variables with equivalent names in the answer code. These variables will contain the string entered by the user into the essay input.
Multiple choice (radio buttons)
AssessML (exercise text)
What color is the sky?
[radio1]Red[radio1]
[radio2]Blue[radio2]
[radio3]Green[radio3]
[radio4]Yellow[radio4]
JavaScript (answer code)
answer = radio2 === true;
Radio tags create radio buttons to the left of whatever is declared within the tags. Any text, including other AssessML tags, can go between radio tags. Radio names must start with radio
and end with any non-empty string. In the assess-elements assessment editor, radio tags declared in the exercise text will create variables with equivalent names in the answer code. These variables will contain boolean values representing the checked state of the radio buttons.
Multiple select (checkboxes)
AssessML (exercise text)
Who were presidents of the United States of America?
[check1]Bing Crosby[check1]
[check2]Bill Cosby[check2]
[check3]Thomas Jefferson[check3]
[check4]George Washington[check4]
JavaScript (answer code)
answer = (
check1 === false &&
check2 === false &&
check3 === true &&
check4 === true
);
Check tags create checkboxes to the left of whatever is declared within the tags. Any text, including other AssessML tags, can go between check tags. Check names must start with check
and end with any non-empty string. In the assess-elements assessment editor, check tags declared in the exercise text will create variables with equivalent names in the answer code. These variables will contain boolean values representing the checked state of the checkboxes.
Image
AssessML (exercise text)
What type of bird is this?
[img1]
[input1]
JavaScript (answer code)
img1.src = 'https://images.pexels.com/photos/48894/galah-rose-breasted-cockatoo-parrot-bird-48894.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260';
answer = input1 === 'cockatoo';
Image tags create images. Image names must start with image
and end with any non-empty string. In the assess-elements assessment editor, image tags declared in the exercise text will create variables with equivalent names in the answer code. These variables have one property, src
, that must be set to some kind of image URI, such as the URL to a remotely hosted image, or a data URI for an inline image.
Code
AssessML (exercise text)
Create a function named hello that returns the string 'world!';
[code1]
JavaScript (answer code)
if (code1) {
eval(code1);
answer = hello() === 'world!';
}
else {
answer = false;
}
Code tags create an interactive code editor. Code names must start with code
and end with any non-empty string. In the assess-elements assessment editor, code tags declared in the exercise text will create variables with equivalent names in the answer code. These variables will contain the string entered by the user into the code editor. The answer code can then eval
the user code or perform static analysis to interact with and verify it. Be aware that eval
can be a security vulnerability when executing untrusted code. assess-elements will and secure-eval currently does provide means of mitigating eval
risks.
Shuffle
AssessML (exercise text)
Which of the following is a number?
[shuffle1]
[radio1]1[radio1]
[radio2]Monkey[radio2]
[radio3]Fish[radio3]
[shuffle1]
JavaScript (answer code)
answer = radio1 === true;
Shuffle tags allow shuffling of their contents. For example, this makes it unnecessary to worry about order of options when creating multiple choice or multiple select exercises for which you want an unpredictable order. Shuffle tags can have any valid combination of AssessML tags between them. Shuffle names must start with shuffle
and end with any non-empty string.
Solution
AssessML (exercise text)
What is the 5 + 5? [input1]
[solution1]
First take 5, then take another 5, then add them together. Boom, you have 10.
[solution1]
JavaScript (answer code)
answer = input1 == 10;
Solution tags allow a solution to be delivered with the exercise text. The solution is stored in an HTML template, thus not initially rendered. An assessment editor can display the contents of the template as desired. Any text, including other AssessML tags, can go between solution tags. Solution names must start with solution
and end with any non-empty string.
BNF (Backus-Naur form) Grammar
<Document> := <Document><Content><Document> | <Document><Variable><Document> | <Document><Input><Document> | <Document><Essay><Document> | <Document><Radio><Document> | <Document><Check><Document> | <Document><Image><Document>| <Document><Code><Document> | <Document><Shuffle><Document> | <Document><Solution><Document> | <Empty>
<Content> := string
<Variable> := [var<Content>]
<Input> := [input<Content>]
<Essay> := [essay<Content>]
<Radio> := [radio<Content>]<Document>[radio<Content>]
<Check> := [check<Content>]<Document>[check<Content>]
<Image> := [img<Content>]
<Code> := [code<Content>]
<Shuffle> := [shuffle<Content>]<Document>[shuffle<Content>]
<Solution> := [solution<Content>]<Document>[solution<Content>]
<Empty> := '' (the empty string)
AST (Abstract Syntax Tree)
AST
interface AST {
readonly type: 'AST';
readonly ast: ASTObject[];
}
type ASTObject = Content | Variable | Input | Essay | Radio | Check | Image | Code | Shuffle | Solution;
Content
interface Content {
readonly type: 'CONTENT';
readonly varName: string;
readonly content: string;
}
Variable
interface Variable {
readonly type: 'VARIABLE';
readonly varName: string;
readonly value: number | string;
}
Input
interface Input {
readonly type: 'INPUT';
readonly varName: string;
}
Essay
interface Essay {
readonly type: 'ESSAY';
readonly varName: string;
}
Radio
interface Radio {
readonly type: 'RADIO';
readonly varName: string;
readonly content: ASTObject[];
}
Check
interface Check {
readonly type: 'CHECK';
readonly varName: string;
readonly content: ASTObject[];
}
Image
interface Image {
readonly type: 'IMAGE';
readonly varName: string;
readonly src: string;
}
Code
interface Code {
readonly type: 'CODE';
readonly varName: string;
}
Shuffle
interface Shuffle {
readonly type: 'SHUFFLE';
readonly varName: string;
readonly content: ASTObject[];
readonly shuffledIndeces: number[];
}
Solution
interface Solution {
readonly type: 'SOLUTION';
readonly varName: string;
readonly content: ASTObject[];
}