Commit 5d28a7b3 by Will Daly

Merge branch 'master' into ai-grading

Conflicts:
	.gitignore
	apps/openassessment/xblock/static/js/openassessment.min.js
	openassessment/assessment/test/test_models.py
parents 60cbce58 041e5e43
......@@ -2,7 +2,7 @@
branch = True
[report]
include = apps/*
include = openassessment/*
omit =
**/__init__.py
**/tests/*
......
......@@ -54,8 +54,8 @@ coverage
# tim-specific
ora2db
apps/openassessment/xblock/static/js/fixtures/*.html
storage/*
openassessment/xblock/static/js/fixtures/*.html
# logging
logs/*/*.log*
......
......@@ -7,6 +7,7 @@ before_script:
- "pip install coveralls"
script:
- "./scripts/test.sh"
- "./scripts/i18n.sh"
- "python setup.py install"
after_success:
coveralls
......@@ -164,15 +164,7 @@ To extract strings and compile messages:
.. code:: bash
python manage.py makemessages -l en
python manage.py makemessages -d djangojs -l en
python manage.py compilemessages
Generate dummy strings for testing:
.. code:: bash
i18n_tool dummy
./scripts/i18n.sh
License
......
# edX translation file.
# Copyright (C) 2014 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
# EdX Team <info@edx.org>, 2014.
#
msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-06-05 06:32-0400\n"
"PO-Revision-Date: 2014-06-04 15:41-0400\n"
"Last-Translator: \n"
"Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n"
"Language: fake2\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_base.js:151
msgid "Unable to Load"
msgstr "Ʉnɐblǝ ʇø Łøɐd"
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_edit.js:81
msgid ""
"This problem has already been released. Any changes will apply only to "
"future assessments."
msgstr ""
"Ŧɥᴉs dɹøblǝɯ ɥɐs ɐlɹǝɐdʎ bǝǝn ɹǝlǝɐsǝd. Ⱥnʎ ɔɥɐnƃǝs ʍᴉll ɐddlʎ ønlʎ ʇø "
"ɟnʇnɹǝ ɐssǝssɯǝnʇs."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_response.js:174
msgid "Status of Your Response"
msgstr "Sʇɐʇns øɟ Ɏønɹ Ɍǝsdønsǝ"
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_response.js:277
msgid "This response has not been saved."
msgstr "Ŧɥᴉs ɹǝsdønsǝ ɥɐs nøʇ bǝǝn sɐʌǝd."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_response.js:295
msgid "Saving..."
msgstr "Sɐʌᴉnƃ..."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_response.js:313
msgid "This response has been saved but not submitted."
msgstr "Ŧɥᴉs ɹǝsdønsǝ ɥɐs bǝǝn sɐʌǝd bnʇ nøʇ snbɯᴉʇʇǝd."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_response.js:316
msgid "Error"
msgstr "Ɇɹɹøɹ"
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_server.js:59
#: apps/openassessment/xblock/static/js/src/oa_server.js:90
#: apps/openassessment/xblock/static/js/src/oa_server.js:109
msgid "This section could not be loaded."
msgstr "Ŧɥᴉs sǝɔʇᴉøn ɔønld nøʇ bǝ løɐdǝd."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_server.js:144
msgid "This response could not be submitted."
msgstr "Ŧɥᴉs ɹǝsdønsǝ ɔønld nøʇ bǝ snbɯᴉʇʇǝd."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_server.js:170
msgid "This response could not be saved."
msgstr "Ŧɥᴉs ɹǝsdønsǝ ɔønld nøʇ bǝ sɐʌǝd."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_server.js:207
msgid "This feedback could not be submitted."
msgstr "Ŧɥᴉs ɟǝǝdbɐɔʞ ɔønld nøʇ bǝ snbɯᴉʇʇǝd."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_server.js:253
#: apps/openassessment/xblock/static/js/src/oa_server.js:293
#: apps/openassessment/xblock/static/js/src/oa_server.js:334
msgid "This assessment could not be submitted."
msgstr "Ŧɥᴉs ɐssǝssɯǝnʇ ɔønld nøʇ bǝ snbɯᴉʇʇǝd."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_server.js:362
msgid "This problem could not be loaded."
msgstr "Ŧɥᴉs dɹøblǝɯ ɔønld nøʇ bǝ løɐdǝd."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_server.js:391
msgid "This problem could not be saved."
msgstr "Ŧɥᴉs dɹøblǝɯ ɔønld nøʇ bǝ sɐʌǝd."
#: apps/openassessment/xblock/static/js/openassessment.min.js:1
#: apps/openassessment/xblock/static/js/src/oa_server.js:421
msgid "The server could not be contacted."
msgstr "Ŧɥǝ sǝɹʌǝɹ ɔønld nøʇ bǝ ɔønʇɐɔʇǝd."
// openassessment: elements - footer
// ====================
// NOTES:
// * The grade/status portion of the openassessment UI
@mixin hide-text {
color: transparent;
font: 0/0 a;
text-shadow: none;
}
@mixin appearance ($value) {
@include prefixer(appearance, $value, webkit moz ms o spec);
}
//************************************************************************//
// Background-image property for adding multiple background images with
// gradients, or for stringing multiple gradients together.
//************************************************************************//
@mixin background-image($images...) {
background-image: _add-prefix($images, webkit);
background-image: _add-prefix($images);
}
@function _add-prefix($images, $vendor: false) {
$images-prefixed: ();
$gradient-positions: false;
@for $i from 1 through length($images) {
$type: type-of(nth($images, $i)); // Get type of variable - List or String
// If variable is a list - Gradient
@if $type == list {
$gradient-type: nth(nth($images, $i), 1); // linear or radial
$gradient-pos: null;
$gradient-args: null;
@if ($gradient-type == linear) or ($gradient-type == radial) {
$gradient-pos: nth(nth($images, $i), 2); // Get gradient position
$gradient-args: nth(nth($images, $i), 3); // Get actual gradient (red, blue)
}
@else {
$gradient-args: nth(nth($images, $i), 2); // Get actual gradient (red, blue)
}
$gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos);
$gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor);
$images-prefixed: append($images-prefixed, $gradient, comma);
}
// If variable is a string - Image
@else if $type == string {
$images-prefixed: join($images-prefixed, nth($images, $i), comma);
}
}
@return $images-prefixed;
}
//Examples:
//@include background-image(linear-gradient(top, orange, red));
//@include background-image(radial-gradient(50% 50%, cover circle, orange, red));
//@include background-image(url("/images/a.png"), linear-gradient(orange, red));
//@include background-image(url("image.png"), linear-gradient(orange, red), url("image.png"));
//@include background-image(linear-gradient(hsla(0, 100%, 100%, 0.25) 0%, hsla(0, 100%, 100%, 0.08) 50%, transparent 50%), linear-gradient(orange, red));
//************************************************************************//
// Background property for adding multiple backgrounds using shorthand
// notation.
//************************************************************************//
@mixin background(
$background-1 , $background-2: false,
$background-3: false, $background-4: false,
$background-5: false, $background-6: false,
$background-7: false, $background-8: false,
$background-9: false, $background-10: false,
$fallback: false
) {
$backgrounds: compact($background-1, $background-2,
$background-3, $background-4,
$background-5, $background-6,
$background-7, $background-8,
$background-9, $background-10);
$fallback-color: false;
@if (type-of($fallback) == color) or ($fallback == "transparent") {
$fallback-color: $fallback;
}
@else {
$fallback-color: _extract-background-color($backgrounds);
}
@if $fallback-color {
background-color: $fallback-color;
}
background: _background-add-prefix($backgrounds, webkit);
background: _background-add-prefix($backgrounds);
}
@function _extract-background-color($backgrounds) {
$final-bg-layer: nth($backgrounds, length($backgrounds));
@if type-of($final-bg-layer) == list {
@for $i from 1 through length($final-bg-layer) {
$value: nth($final-bg-layer, $i);
@if type-of($value) == color {
@return $value;
}
}
}
@return false;
}
@function _background-add-prefix($backgrounds, $vendor: false) {
$backgrounds-prefixed: ();
@for $i from 1 through length($backgrounds) {
$shorthand: nth($backgrounds, $i); // Get member for current index
$type: type-of($shorthand); // Get type of variable - List (gradient) or String (image)
// If shorthand is a list (gradient)
@if $type == list {
$first-member: nth($shorthand, 1); // Get first member of shorthand
// Linear Gradient
@if index(linear radial, nth($first-member, 1)) {
$gradient-type: nth($first-member, 1); // linear || radial
$gradient-args: false;
$gradient-positions: false;
$shorthand-start: false;
@if type-of($first-member) == list { // Linear gradient plus additional shorthand values - lg(red,orange)repeat,...
$gradient-positions: nth($first-member, 2);
$gradient-args: nth($first-member, 3);
$shorthand-start: 2;
}
@else { // Linear gradient only - lg(red,orange),...
$gradient-positions: nth($shorthand, 2);
$gradient-args: nth($shorthand, 3); // Get gradient (red, blue)
}
$gradient-positions: _gradient-positions-parser($gradient-type, $gradient-positions);
$gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor);
// Append any additional shorthand args to gradient
@if $shorthand-start {
@for $j from $shorthand-start through length($shorthand) {
$gradient: join($gradient, nth($shorthand, $j), space);
}
}
$backgrounds-prefixed: append($backgrounds-prefixed, $gradient, comma);
}
// Image with additional properties
@else {
$backgrounds-prefixed: append($backgrounds-prefixed, $shorthand, comma);
}
}
// If shorthand is a simple string (color or image)
@else if $type == string {
$backgrounds-prefixed: join($backgrounds-prefixed, $shorthand, comma);
}
}
@return $backgrounds-prefixed;
}
//Examples:
//@include background(linear-gradient(top, orange, red));
//@include background(radial-gradient(circle at 40% 40%, orange, red));
//@include background(url("/images/a.png") no-repeat, linear-gradient(orange, red));
//@include background(url("image.png") center center, linear-gradient(orange, red), url("image.png"));
@mixin border-image($images) {
-webkit-border-image: _border-add-prefix($images, webkit);
-moz-border-image: _border-add-prefix($images, moz);
-o-border-image: _border-add-prefix($images, o);
border-image: _border-add-prefix($images);
}
@function _border-add-prefix($images, $vendor: false) {
$border-image: null;
$images-type: type-of(nth($images, 1));
$first-var: nth(nth($images, 1), 1); // Get type of Gradient (Linear || radial)
// If input is a gradient
@if $images-type == string {
@if ($first-var == "linear") or ($first-var == "radial") {
$gradient-type: nth($images, 1); // Get type of gradient (linear || radial)
$gradient-pos: nth($images, 2); // Get gradient position
$gradient-args: nth($images, 3); // Get actual gradient (red, blue)
$gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos);
$border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor);
}
// If input is a URL
@else {
$border-image: $images;
}
}
// If input is gradient or url + additional args
@else if $images-type == list {
$type: type-of(nth($images, 1)); // Get type of variable - List or String
// If variable is a list - Gradient
@if $type == list {
$gradient: nth($images, 1);
$gradient-type: nth($gradient, 1); // Get type of gradient (linear || radial)
$gradient-pos: nth($gradient, 2); // Get gradient position
$gradient-args: nth($gradient, 3); // Get actual gradient (red, blue)
$gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos);
$border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor);
@for $i from 2 through length($images) {
$border-image: append($border-image, nth($images, $i));
}
}
}
@return $border-image;
}
//Examples:
// @include border-image(url("image.png"));
// @include border-image(url("image.png") 20 stretch);
// @include border-image(linear-gradient(45deg, orange, yellow));
// @include border-image(linear-gradient(45deg, orange, yellow) stretch);
// @include border-image(linear-gradient(45deg, orange, yellow) 20 30 40 50 stretch round);
// @include border-image(radial-gradient(top, cover, orange, yellow, orange));
@mixin box-sizing ($box) {
// content-box | border-box | inherit
@include prefixer(box-sizing, $box, webkit moz spec);
}
// Requires Sass 3.1+
@mixin radial-gradient($G1, $G2,
$G3: false, $G4: false,
$G5: false, $G6: false,
$G7: false, $G8: false,
$G9: false, $G10: false,
$pos: null,
$shape-size: null,
$deprecated-pos1: center center,
$deprecated-pos2: center center,
$deprecated-radius1: 0,
$deprecated-radius2: 460,
$fallback: false) {
$data: _radial-arg-parser($G1, $G2, $pos, $shape-size);
$G1: nth($data, 1);
$G2: nth($data, 2);
$pos: nth($data, 3);
$shape-size: nth($data, 4);
$full: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10);
// Strip deprecated cover/contain for spec
$shape-size-spec: _shape-size-stripper($shape-size);
// Set $G1 as the default fallback color
$first-color: nth($full, 1);
$fallback-color: nth($first-color, 1);
@if (type-of($fallback) == color) or ($fallback == "transparent") {
$fallback-color: $fallback;
}
// Add Commas and spaces
$shape-size: if($shape-size, '#{$shape-size}, ', null);
$pos: if($pos, '#{$pos}, ', null);
$pos-spec: if($pos, 'at #{$pos}', null);
$shape-size-spec: if(($shape-size-spec != ' ') and ($pos == null), '#{$shape-size-spec}, ', '#{$shape-size-spec} ');
background-color: $fallback-color;
background-image: _deprecated-webkit-gradient(radial, $deprecated-pos1, $deprecated-pos2, $full, $deprecated-radius1, $deprecated-radius2); // Safari <= 5.0 && IOS 4
background-image: -webkit-radial-gradient(unquote(#{$pos}#{$shape-size}#{$full}));
background-image: unquote("radial-gradient(#{$shape-size-spec}#{$pos-spec}#{$full})");
}
@mixin user-select($arg: none) {
@include prefixer(user-select, $arg, webkit moz ms spec);
}
// Flexible grid
@function flex-grid($columns, $container-columns: $fg-max-columns) {
$width: $columns * $fg-column + ($columns - 1) * $fg-gutter;
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
@return percentage($width / $container-width);
}
// Flexible gutter
@function flex-gutter($container-columns: $fg-max-columns, $gutter: $fg-gutter) {
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
@return percentage($gutter / $container-width);
}
// The $fg-column, $fg-gutter and $fg-max-columns variables must be defined in your base stylesheet to properly use the flex-grid function.
// This function takes the fluid grid equation (target / context = result) and uses columns to help define each.
//
// The calculation presumes that your column structure will be missing the last gutter:
//
// -- column -- gutter -- column -- gutter -- column
//
// $fg-column: 60px; // Column Width
// $fg-gutter: 25px; // Gutter Width
// $fg-max-columns: 12; // Total Columns For Main Container
//
// div {
// width: flex-grid(4); // returns (315px / 995px) = 31.65829%;
// margin-left: flex-gutter(); // returns (25px / 995px) = 2.51256%;
//
// p {
// width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%;
// float: left;
// margin: flex-gutter(4); // returns (25px / 315px) = 7.936508%;
// }
//
// blockquote {
// float: left;
// width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%;
// }
// }
// Render Deprecated Webkit Gradient - Linear || Radial
//************************************************************************//
@function _deprecated-webkit-gradient($type,
$deprecated-pos1, $deprecated-pos2,
$full,
$deprecated-radius1: false, $deprecated-radius2: false) {
$gradient-list: ();
$gradient: false;
$full-length: length($full);
$percentage: false;
$gradient-type: $type;
@for $i from 1 through $full-length {
$gradient: nth($full, $i);
@if length($gradient) == 2 {
$color-stop: color-stop(nth($gradient, 2), nth($gradient, 1));
$gradient-list: join($gradient-list, $color-stop, comma);
}
@else if $gradient != null {
@if $i == $full-length {
$percentage: 100%;
}
@else {
$percentage: ($i - 1) * (100 / ($full-length - 1)) + "%";
}
$color-stop: color-stop(unquote($percentage), $gradient);
$gradient-list: join($gradient-list, $color-stop, comma);
}
}
@if $type == radial {
$gradient: -webkit-gradient(radial, $deprecated-pos1, $deprecated-radius1, $deprecated-pos2, $deprecated-radius2, $gradient-list);
}
@else if $type == linear {
$gradient: -webkit-gradient(linear, $deprecated-pos1, $deprecated-pos2, $gradient-list);
}
@return $gradient;
}
@function _linear-positions-parser($pos) {
$type: type-of(nth($pos, 1));
$spec: null;
$degree: null;
$side: null;
$corner: null;
$length: length($pos);
// Parse Side and corner positions
@if ($length > 1) {
@if nth($pos, 1) == "to" { // Newer syntax
$side: nth($pos, 2);
@if $length == 2 { // eg. to top
// Swap for backwards compatability
$degree: _position-flipper(nth($pos, 2));
}
@else if $length == 3 { // eg. to top left
$corner: nth($pos, 3);
}
}
@else if $length == 2 { // Older syntax ("top left")
$side: _position-flipper(nth($pos, 1));
$corner: _position-flipper(nth($pos, 2));
}
@if ("#{$side} #{$corner}" == "left top") or ("#{$side} #{$corner}" == "top left") {
$degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
}
@else if ("#{$side} #{$corner}" == "right top") or ("#{$side} #{$corner}" == "top right") {
$degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
}
@else if ("#{$side} #{$corner}" == "right bottom") or ("#{$side} #{$corner}" == "bottom right") {
$degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
}
@else if ("#{$side} #{$corner}" == "left bottom") or ("#{$side} #{$corner}" == "bottom left") {
$degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
}
$spec: to $side $corner;
}
@else if $length == 1 {
// Swap for backwards compatability
@if $type == string {
$degree: $pos;
$spec: to _position-flipper($pos);
}
@else {
$degree: -270 - $pos; //rotate the gradient opposite from spec
$spec: $pos;
}
}
$degree: unquote($degree + ",");
$spec: unquote($spec + ",");
@return $degree $spec;
}
@function _position-flipper($pos) {
@return if($pos == left, right, null)
if($pos == right, left, null)
if($pos == top, bottom, null)
if($pos == bottom, top, null);
}
@function _radial-arg-parser($G1, $G2, $pos, $shape-size) {
@each $value in $G1, $G2 {
$first-val: nth($value, 1);
$pos-type: type-of($first-val);
$spec-at-index: null;
// Determine if spec was passed to mixin
@if type-of($value) == list {
$spec-at-index: if(index($value, at), index($value, at), false);
}
@if $spec-at-index {
@if $spec-at-index > 1 {
@for $i from 1 through ($spec-at-index - 1) {
$shape-size: $shape-size nth($value, $i);
}
@for $i from ($spec-at-index + 1) through length($value) {
$pos: $pos nth($value, $i);
}
}
@else if $spec-at-index == 1 {
@for $i from ($spec-at-index + 1) through length($value) {
$pos: $pos nth($value, $i);
}
}
$G1: false;
}
// If not spec calculate correct values
@else {
@if ($pos-type != color) or ($first-val != "transparent") {
@if ($pos-type == number)
or ($first-val == "center")
or ($first-val == "top")
or ($first-val == "right")
or ($first-val == "bottom")
or ($first-val == "left") {
$pos: $value;
@if $pos == $G1 {
$G1: false;
}
}
@else if
($first-val == "ellipse")
or ($first-val == "circle")
or ($first-val == "closest-side")
or ($first-val == "closest-corner")
or ($first-val == "farthest-side")
or ($first-val == "farthest-corner")
or ($first-val == "contain")
or ($first-val == "cover") {
$shape-size: $value;
@if $value == $G1 {
$G1: false;
}
@else if $value == $G2 {
$G2: false;
}
}
}
}
}
@return $G1, $G2, $pos, $shape-size;
}
// Checks if a number is even
@function is-even($int) {
@if $int%2 == 0 {
@return true;
}
@return false;
}
// Checks if an element belongs to a list
@function belongs-to($tested-item, $list) {
@each $item in $list {
@if $item == $tested-item {
@return true;
}
}
@return false;
}
// Contains display value
@function contains-display-value($query) {
@if belongs-to(table, $query) or belongs-to(block, $query) or belongs-to(inline-block, $query) or belongs-to(inline, $query) {
@return true;
}
@return false;
}
// Parses the first argument of span-columns()
@function container-span($span: $span) {
@if length($span) == 3 {
$container-columns: nth($span, 3);
@return $container-columns;
}
@else if length($span) == 2 {
$container-columns: nth($span, 2);
@return $container-columns;
}
@else {
@return $grid-columns;
}
}
@function container-shift($shift: $shift) {
$parent-columns: $grid-columns !default;
@if length($shift) == 3 {
$container-columns: nth($shift, 3);
@return $container-columns;
}
@else if length($shift) == 2 {
$container-columns: nth($shift, 2);
@return $container-columns;
}
@else {
@return $parent-columns;
}
}
// Generates a striped background
@function gradient-stops($grid-columns, $color: $visual-grid-color) {
$transparent: rgba(0,0,0,0);
$column-width: flex-grid(1, $grid-columns);
$gutter-width: flex-gutter($grid-columns);
$column-offset: $column-width;
$values: ($transparent 0, $color 0);
@for $i from 1 to $grid-columns*2 {
@if is-even($i) {
$values: append($values, $transparent $column-offset, comma);
$values: append($values, $color $column-offset, comma);
$column-offset: $column-offset + $column-width;
}
@else {
$values: append($values, $color $column-offset, comma);
$values: append($values, $transparent $column-offset, comma);
$column-offset: $column-offset + $gutter-width;
}
}
@return $values;
}
// Layout direction
@function get-direction($layout, $default) {
$direction: nil;
@if $layout == LTR or $layout == RTL {
$direction: direction-from-layout($layout);
} @else {
$direction: direction-from-layout($default);
}
@return $direction;
}
@function direction-from-layout($layout) {
$direction: nil;
@if $layout == LTR {
$direction: right;
} @else {
$direction: left;
}
@return $direction;
}
@function get-opposite-direction($direction) {
$opposite-direction: left;
@if $direction == left {
$opposite-direction: right;
}
@return $opposite-direction;
}
@mixin fill-parent() {
width: 100%;
@if $border-box-sizing == false {
@include box-sizing(border-box);
}
}
@if $border-box-sizing == true {
* {
@include box-sizing(border-box);
}
}
@mixin media($query:$feature $value $columns, $total-columns: $grid-columns) {
@if length($query) == 1 {
@media screen and ($default-feature: nth($query, 1)) {
$default-grid-columns: $grid-columns;
$grid-columns: $total-columns;
@content;
$grid-columns: $default-grid-columns;
}
}
@else if length($query) == 2 {
@media screen and (nth($query, 1): nth($query, 2)) {
$default-grid-columns: $grid-columns;
$grid-columns: $total-columns;
@content;
$grid-columns: $default-grid-columns;
}
}
@else if length($query) == 3 {
@media screen and (nth($query, 1): nth($query, 2)) {
$default-grid-columns: $grid-columns;
$grid-columns: nth($query, 3);
@content;
$grid-columns: $default-grid-columns;
}
}
@else if length($query) == 4 {
@media screen and (nth($query, 1): nth($query, 2)) and (nth($query, 3): nth($query, 4)) {
$default-grid-columns: $grid-columns;
$grid-columns: $total-columns;
@content;
$grid-columns: $default-grid-columns;
}
}
@else if length($query) == 5 {
@media screen and (nth($query, 1): nth($query, 2)) and (nth($query, 3): nth($query, 4)) {
$default-grid-columns: $grid-columns;
$grid-columns: nth($query, 5);
@content;
$grid-columns: $default-grid-columns;
}
}
@else {
@warn "Wrong number of arguments for breakpoint(). Read the documentation for more details.";
}
}
// Remove last element gutter
@mixin omega($query: block, $direction: default) {
$table: if(belongs-to(table, $query), true, false);
$auto: if(belongs-to(auto, $query), true, false);
@if $direction != default {
@warn "The omega mixin will no longer take a $direction argument. To change the layout direction, use row($direction) or set $default-layout-direction instead."
} @else {
$direction: get-direction($layout-direction, $default-layout-direction);
}
@if length($query) == 1 {
@if $auto {
&:last-child {
margin-#{$direction}: 0;
}
}
@else if contains-display-value($query) {
@if $table {
padding-#{$direction}: 0;
}
@else {
margin-#{$direction}: 0;
}
}
@else {
@include nth-child($query, $direction);
}
}
@else if length($query) == 2 {
@if $table {
@if $auto {
&:last-child {
padding-#{$direction}: 0;
}
}
@else {
&:nth-child(#{nth($query, 1)}) {
padding-#{$direction}: 0;
}
}
}
@else {
@if $auto {
&:last-child {
margin-#{$direction}: 0;
}
}
@else {
@include nth-child(nth($query, 1), $direction);
}
}
}
@else {
@warn "Too many arguments passed to the omega() mixin."
}
}
@mixin nth-child($query, $direction) {
$opposite-direction: get-opposite-direction($direction);
&:nth-child(#{$query}) {
margin-#{$direction}: 0;
}
@if type-of($query) == number {
&:nth-child(#{$query}+1) {
clear: $opposite-direction;
}
}
}
@mixin outer-container {
@include clearfix;
max-width: $max-width;
margin: {
left: auto;
right: auto;
}
}
$parent-columns: $grid-columns !default;
$fg-column: $column;
$fg-gutter: $gutter;
$fg-max-columns: $grid-columns;
$container-display-table: false !default;
$layout-direction: nil !default;
@function flex-grid($columns, $container-columns: $fg-max-columns) {
$width: $columns * $fg-column + ($columns - 1) * $fg-gutter;
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
@return percentage($width / $container-width);
}
@function flex-gutter($container-columns: $fg-max-columns, $gutter: $fg-gutter) {
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
@return percentage($gutter / $container-width);
}
@function grid-width($n) {
@return $n * $gw-column + ($n - 1) * $gw-gutter;
}
@function get-parent-columns($columns) {
@if $columns != $grid-columns {
$parent-columns: $columns;
} @else {
$parent-columns: $grid-columns;
}
@return $parent-columns;
}
@function is-display-table($container-is-display-table, $display) {
$display-table: false;
@if $container-is-display-table == true {
$display-table: true;
} @else if $display == table {
$display-table: true;
}
@return $display-table;
}
@function get-padding-for-table-layout($columns, $total-columns) {
$total-padding: flex-gutter($total-columns) * ($columns - 1);
$padding: $total-padding / $columns;
@return $padding;
}
@mixin span-columns($span: $columns of $container-columns, $display: block) {
$columns: nth($span, 1);
$container-columns: container-span($span);
// Set nesting context (used by shift())
$parent-columns: get-parent-columns($container-columns);
$direction: get-direction($layout-direction, $default-layout-direction);
$opposite-direction: get-opposite-direction($direction);
$display-table: is-display-table($container-display-table, $display);
@if $display-table {
$padding: get-padding-for-table-layout($columns, $container-columns);
display: table-cell;
padding-#{$direction}: $padding;
width: flex-grid($columns, $container-columns) + $padding;
} @else {
float: #{$opposite-direction};
@if $display != no-display {
display: block;
}
@if $display == collapse {
@warn "The 'collapse' argument will be deprecated. Use 'block-collapse' instead."
}
@if $display == collapse or $display == block-collapse {
width: flex-grid($columns, $container-columns) + flex-gutter($container-columns);
&:last-child {
width: flex-grid($columns, $container-columns);
}
} @else {
margin-#{$direction}: flex-gutter($container-columns);
width: flex-grid($columns, $container-columns);
&:last-child {
margin-#{$direction}: 0;
}
}
}
}
@mixin breakpoint($query:$feature $value $columns, $total-columns: $grid-columns) {
@warn "The breakpoint() mixin was renamed to media() in Neat 1.0. Please update your project with the new syntax before the next version bump.";
@if length($query) == 1 {
@media screen and ($default-feature: nth($query, 1)) {
$default-grid-columns: $grid-columns;
$grid-columns: $total-columns;
@content;
$grid-columns: $default-grid-columns;
}
}
@else if length($query) == 2 {
@media screen and (nth($query, 1): nth($query, 2)) {
$default-grid-columns: $grid-columns;
$grid-columns: $total-columns;
@content;
$grid-columns: $default-grid-columns;
}
}
@else if length($query) == 3 {
@media screen and (nth($query, 1): nth($query, 2)) {
$default-grid-columns: $grid-columns;
$grid-columns: nth($query, 3);
@content;
$grid-columns: $default-grid-columns;
}
}
@else if length($query) == 4 {
@media screen and (nth($query, 1): nth($query, 2)) and (nth($query, 3): nth($query, 4)) {
$default-grid-columns: $grid-columns;
$grid-columns: $total-columns;
@content;
$grid-columns: $default-grid-columns;
}
}
@else if length($query) == 5 {
@media screen and (nth($query, 1): nth($query, 2)) and (nth($query, 3): nth($query, 4)) {
$default-grid-columns: $grid-columns;
$grid-columns: nth($query, 5);
@content;
$grid-columns: $default-grid-columns;
}
}
@else {
@warn "Wrong number of arguments for breakpoint(). Read the documentation for more details.";
}
}
@mixin nth-omega($nth, $display: block, $direction: default) {
@warn "The nth-omega() mixin is deprecated. Please use omega() instead.";
@include omega($nth $display, $direction);
}
@mixin grid-column-gradient($values...) {
background-image: deprecated-webkit-gradient(linear, left top, left bottom, $values);
background-image: -webkit-linear-gradient(left, $values);
background-image: -moz-linear-gradient(left, $values);
background-image: -ms-linear-gradient(left, $values);
background-image: -o-linear-gradient(left, $values);
background-image: unquote("linear-gradient(left, #{$values})");
}
@if $visual-grid == true or $visual-grid == yes {
body:before {
content: '';
display: inline-block;
@include grid-column-gradient(gradient-stops($grid-columns));
height: 100%;
left: 0;
margin: 0 auto;
max-width: $max-width;
opacity: $visual-grid-opacity;
position: fixed;
right: 0;
width: 100%;
pointer-events: none;
@if $visual-grid-index == back {
z-index: -1;
}
@else if $visual-grid-index == front {
z-index: 9999;
}
@each $breakpoint in $visual-grid-breakpoints {
@if $breakpoint != nil {
@include media($breakpoint) {
@include grid-column-gradient(gradient-stops($grid-columns));
}
}
}
}
}
// xblock: utilities - Sass extends
// ====================
// NOTES:
// * these are Sass-placeholders (http://sass-lang.com/documentation/file.SASS_REFERENCE.html#placeholder_selectors_) that can be applied to any xblock
// --------------------
// utility: nth-type style clearing
// --------------------
%wipe-first-child {
&:first-child {
margin-top: 0;
border-top: none;
padding-top: 0;
margin-left: 0;
border-left: none;
padding-left: 0;
}
}
%wipe-last-child {
&:last-child {
margin-bottom: 0;
border-bottom: none;
padding-bottom: 0;
margin-right: 0;
border-right: none;
padding-right: 0;
}
}
// --------------------
// utility: wrapper elements
// --------------------
%wrapper {
@include clearfix();
@include box-sizing(border-box);
width: 100%;
}
// --------------------
// utility: list resets
// --------------------
// lists
%no-list {
list-style: none;
margin: 0;
padding: 0;
text-indent: 0;
}
// --------------------
// utility: image-replacement hidden text
// --------------------
%text-hide {
text-indent: 200%;
white-space: nowrap;
overflow: hidden;
}
// --------------------
// utility: hidden elements for screenreaders
// --------------------
%text-sr {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
// --------------------
// utility: text-wrapping
// --------------------
%text-wrap {
text-wrap: wrap;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
word-wrap: break-word;
}
// --------------------
// utility: visual text overflow
// --------------------
%text-truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// --------------------
// UI: controls
// --------------------
%fake-link {
cursor: pointer;
}
%state-disabled {
pointer-events: none;
outline: none;
}
%state-enabled {
pointer-events: auto;
outline: invert none medium;
}
// --------------------
// UI: element rendering/visibility
// --------------------
%state-hidden {
@extend %state-disabled;
display: none;
visibility: hidden;
}
// --------------------
// UI: element depth
// --------------------
%depth0 { z-index: 0; }
%depth1 { z-index: 10; }
%depth2 { z-index: 100; }
%depth3 { z-index: 1000; }
%depth4 { z-index: 10000; }
%depth5 { z-index: 100000; }
// --------------------
// UI: transitions
// --------------------
%trans-size {
@include transition(width $tmg-f1 ease-in-out, height $tmg-f1 ease-in-out);
}
%trans-opacity {
@include transition(opacity $tmg-f1 ease-in-out);
}
%trans-color {
@include transition(color $tmg-f1 ease-in-out);
}
// --------------------
// Decorative: shadows
// --------------------
%deco-shadow-up {
box-shadow: 0 -1px 2px 0 $shadow-d1;
}
%deco-shadow-down {
box-shadow: 0 1px 2px 0 $shadow-d1;
}
%deco-shadow-subtle-up {
box-shadow: 0 -1px 2px 0 $shadow-l1;
}
%deco-shadow-subtle-down {
box-shadow: 0 1px 2px 0 $shadow-l1;
}
// --------------------
// Decorative: round/circular elements
// --------------------
%deco-circle {
border-radius: 99999em;
}
// xblock: utilities - Sass mixins
// ====================
// NOTES:
// * these are Sass-based mixins (http://sass-lang.com/documentation/file.SASS_REFERENCE.html#mixins) that can be applied to any xblock
// --------------------
// shorthand - absolute position
// --------------------
@mixin posAbs ($top: auto, $right: auto, $bottom: auto, $left: auto) {
position: absolute;
top: $top;
right: $right;
bottom: $bottom;
left: $left;
}
// --------------------
// shorthand - vertically align something
// --------------------
@mixin alignVertically {
position: relative;
top: 50%;
@include transform(translateY(-50%));
}
// --------------------
// fontSize (rems)
// --------------------
@mixin fontSize($sizeValue: 16){
font-size: $sizeValue + px;
// font-size: ($sizeValue/10) + rem; // since we don't control the root element of the DOM, we can't accurately get this fluid unit of measurement to render consistently
}
// --------------------
// line-height (rems)
// --------------------
@mixin lh($fontSize: auto){
line-height: ($fontSize*1.50) + px;
// line-height: (($fontSize/10)*1.50) + rem; // since we don't control the root element of the DOM, we can't accurately get this fluid unit of measurement to render consistently
}
// --------------------
// type setting
// --------------------
@mixin typeSet($size) {
@if $size == "xsmall" {
@include fontSize($f-size-xsmall);
@include lh($f-size-xsmall);
}
@if $size == "small" {
@include fontSize($f-size-small);
@include lh($f-size-small);
}
@if $size == "base" {
@include fontSize($f-size-base);
@include lh($f-size-base);
}
@if $size == "medium" {
@include fontSize($f-size-medium);
@include lh($f-size-medium);
}
@if $size == "large" {
@include fontSize($f-size-large);
@include lh($f-size-large);
}
@if $size == "xlarge" {
@include fontSize($f-size-xlarge);
@include lh($f-size-xlarge);
}
}
// xblock: utilities - reset
// ====================
// NOTES:
// * this reset is scoped to just the xblock's markup/elements. The app/system should never be touched.
// * this reset is heavily based on the good work of normalize (http://necolas.github.io/normalize.css/)
// contains all resets inside of the main xblock wrapper
.wrapper--xblock {
// --------------------
// porting of normalize.css v3.0.0 | MIT License | git.io/normalize
// --------------------
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
/* HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined in IE 8/9.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
summary {
display: block;
}
/**
* 1. Correct `inline-block` display not defined in IE 8/9.
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
*/
audio,
canvas,
progress,
video {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address `[hidden]` styling not present in IE 8/9.
* Hide the `template` element in IE, Safari, and Firefox < 22.
*/
[hidden],
template {
display: none;
}
/* Links
========================================================================== */
/**
* Remove the gray background color from active links in IE 10.
*/
a {
background: transparent;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* Text-level semantics
========================================================================== */
/**
* Address styling not present in IE 8/9, Safari 5, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/**
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/**
* Address styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address variable `h1` font-size and margin within `section` and `article`
* contexts in Firefox 4+, Safari 5, and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/**
* Address styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* Embedded content
========================================================================== */
/**
* Remove border when inside `a` element in IE 8/9.
*/
img {
border: 0;
}
/**
* Correct overflow displayed oddly in IE 9.
*/
svg:not(:root) {
overflow: hidden;
}
/* Grouping content
========================================================================== */
/**
* Address margin not present in IE 8/9 and Safari 5.
*/
figure {
margin: 1em 40px;
}
/**
* Address differences between Firefox and other browsers.
*/
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0;
}
/**
* Contain overflow in all browsers.
*/
pre {
overflow: auto;
}
/**
* Address odd `em`-unit font size rendering in all browsers.
*/
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
/* Forms
========================================================================== */
/**
* Known limitation: by default, Chrome and Safari on OS X allow very limited
* styling of `select`, unless a `border` property is set.
*/
/**
* 1. Correct color not being inherited.
* Known issue: affects color of disabled elements.
* 2. Correct font properties not being inherited.
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
*/
button,
input,
optgroup,
select,
textarea {
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
}
/**
* Address `overflow` set to `hidden` in IE 8/9/10.
*/
button {
overflow: visible;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Firefox, IE 8+, and Opera
* Correct `select` style inheritance in Firefox.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* Remove inner padding and border in Firefox 4+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
input {
line-height: normal;
}
/**
* It's recommended that you don't attempt to style these elements.
* Firefox's implementation doesn't respect box-sizing, padding, or width.
*
* 1. Address box sizing set to `content-box` in IE 8/9/10.
* 2. Remove excess padding in IE 8/9/10.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
* `font-size` values of the `input`, it causes the cursor style of the
* decrement button to change from `default` to `text`.
*/
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
* Safari (but not Chrome) clips the cancel button when the search input has
* padding (and `textfield` appearance).
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct `color` not being inherited in IE 8/9.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
* Remove default vertical scrollbar in IE 8/9.
*/
textarea {
overflow: auto;
}
/**
* Don't inherit the `font-weight` (applied by a rule above).
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
*/
optgroup {
font-weight: bold;
}
/* Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}
// --------------------
// custom reset
// --------------------
* {
@include box-sizing(border-box);
}
div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin: 0;
vertical-align: baseline;
border: 0;
padding: 0;
outline: 0;
font-weight: 400;
}
abbr[title] {
border-bottom: none;
text-decoration: none;
cursor: help;
}
strong, .emphasis {
@extend %t-strong;
}
// --------------------
// context base reset: edX LMS
// --------------------
// TODO: fill this in when xblock is rendered in edX LMS
// --------------------
// context base reset: LTI
// --------------------
// TODO: fill this in when xblock is rendered in LTI contexts
}
// xblock: utilities - Sass variables
// ====================
// NOTES:
// * these are general variables to be set and overriden later by theming and particular xblock _variables.scss files
// --------------------
// units
// --------------------
$baseline-v: 20px; // vertical baseline
$baseline-h: 40px; // horizontal baseline
// --------------------
// layout - grid (neat-based - http://neat.bourbon.io/)
// --------------------
// grid
$max-width: 100%; // http://gridcalculator.dk/#/1040/12/20/20
$grid-columns: 12; // make grid 12 columns
$column: $baseline-v;
$gutter: $baseline-v; // gutter b/t columns
// $visual-grid: true;
// $visual-grid-index: front;
// --------------------
// colors - basic
// --------------------
// grays
$gray: rgb(55, 59, 68);
$gray-l1: tint($gray,20%);
$gray-l2: tint($gray,40%);
$gray-l3: tint($gray,60%);
$gray-l4: tint($gray,80%);
$gray-l5: tint($gray,90%);
$gray-l6: tint($gray,95%);
$gray-l7: tint($gray,99.50%);
$gray-d1: shade($gray,20%);
$gray-d2: shade($gray,40%);
$gray-d3: shade($gray,60%);
$gray-d4: shade($gray,80%);
$gray-d5: shade($gray,90%);
$gray-d6: shade($gray,95%);
$gray-d7: shade($gray,99%);
$gray-t0: rgba($gray,0.125);
$gray-t1: rgba($gray,0.25);
$gray-t2: rgba($gray,0.50);
$gray-t3: rgba($gray,0.75);
// blacks
$black: $gray-d6; // system black
$black-t: $gray-d7;
$black-t0: rgba($black,0.125);
$black-t1: rgba($black,0.25);
$black-t2: rgba($black,0.50);
$black-t3: rgba($black,0.75);
// whites
$white: $gray-l6; // system white
$white-t: $gray-l7;
$white-t0: rgba($white,0.125);
$white-t1: rgba($white,0.25);
$white-t2: rgba($white,0.50);
$white-t3: rgba($white,0.75);
// shadows
$shadow: rgba($black,0.2);
$shadow-l1: rgba($black,0.1);
$shadow-l2: rgba($black,0.05);
$shadow-d1: rgba($black,0.4);
$shadow-d2: rgba($black,0.6);
// blue
$blue: rgb(128, 169, 204);
$blue-l1: tint($blue,20%);
$blue-l2: tint($blue,40%);
$blue-l3: tint($blue,60%);
$blue-l4: tint($blue,80%);
$blue-l5: tint($blue,90%);
$blue-d1: shade($blue,20%);
$blue-d2: shade($blue,40%);
$blue-d3: shade($blue,60%);
$blue-d4: shade($blue,80%);
$blue-d5: shade($blue,90%);
$blue-s1: saturate($blue,15%);
$blue-s2: saturate($blue,30%);
$blue-s3: saturate($blue,45%);
$blue-u1: desaturate($blue,15%);
$blue-u2: desaturate($blue,30%);
$blue-u3: desaturate($blue,45%);
$blue-t0: rgba($blue,0.125);
$blue-t1: rgba($blue,0.25);
$blue-t2: rgba($blue,0.50);
$blue-t3: rgba($blue,0.75);
// --------------------
// fonts
// --------------------
$f-serif: 'Poly', Cambria, Georgia, 'Times New Roman', Times, serif;
$f-sans-serif: 'Lato', 'Helvetica Neue', Helvetica, Arial, sans-serif;
$f-monospace: 'Bitstream Vera Sans Mono', Consolas, Courier, monospace;
// --------------------
// animation/transitions
// --------------------
// timing - used for animation/transition mixin syncing
$tmg-s3: 3.0s;
$tmg-s2: 2.0s;
$tmg-s1: 1.0s;
$tmg-avg: 0.75s;
$tmg-f1: 0.50s;
$tmg-f2: 0.25s;
$tmg-f3: 0.125s;
// animation-based settings
$anim-distance-offviewport: ($baseline-h*100); // for larger/page-level animations
// --------------------
// application - fonts
// --------------------
$f-title: $f-sans-serif;
$f-copy: $f-serif;
$f-action: $f-sans-serif;
$f-base-color: $gray-l2;
// type sizes
$f-size-xsmall: 10;
$f-size-small: 12;
$f-size-base: 14;
$f-size-medium: 16;
$f-size-large: 18;
$f-size-xlarge: 22;
// --------------------
// application - colors
// --------------------
// application - colors: basic
$color-primary: $blue;
$color-secondary: $blue-u1;
$color-teritary: $blue-u2;
// application - colors: decorative
$color-decorative-primary: $blue-u2;
$color-decorative-secondary: tint($color-decorative-primary, 30%);
$color-decorative-tertiary: tint($color-decorative-primary, 60%);
$color-decorative-quaternary: tint($color-decorative-primary, 90%);
$color-decorative-quinternary: tint($color-decorative-primary, 98%);
// application - colors: states
$color-disabled: $gray-l4;
$color-unfocused: $gray-l2;
$color-focused: $blue-u2;
// application - colors: actions
$action-primary-color: tint($color-primary,10%);
$action-primary-color-focus: saturate($color-primary,25%);
$action-primary-color-active: $color-primary;
$action-primary-color-visited: shade($color-primary,20%);
$action-secondary-color: $color-secondary;
$action-secondary-color-focus: saturate($color-secondary,25%);
$action-secondary-color-active: $color-secondary;
$action-secondary-color-visited: shade($color-secondary,20%);
$action-tertiary-color: tint($color-teritary,10%);
$action-tertiary-color-focus: saturate($color-teritary,25%);
$action-tertiary-color-active: $color-teritary;
$action-tertiary-color-visited: shade($color-teritary,20%);
// application - colors: copy and headings
$heading-color: shade($f-base-color, 50%);
$heading-primary-color: shade($f-base-color, 66%);
$heading-secondary-color: tint($f-base-color, 33%);
$copy-color: $f-base-color;
$copy-secondary-color: tint($copy-color, 25%);
// application - colors: states
$selected-bg: $blue-t1;
$selected-color: $blue-s1;
// application - colors: view-based elements
$bg-view: $gray-l7;
$bg-content: $white;
$bg-message: $black;
// --------------------
// // application - colors: states
// --------------------
$color-error: rgb(188, 85, 71);
$color-warning: rgb(229, 166, 53);
$color-complete: rgb(98, 194, 74);
$color-incomplete: $color-warning;
$color-confirm: $heading-primary-color;
$color-unavailable: tint($copy-color, 85%);
// --------------------
// // application - colors: staff UI
// --------------------
$color-decorative-staff: $color-decorative-primary;
$copy-staff-color: $gray-l3;
$heading-staff-color: $white;
$staff-bg: $gray-d1;
<openassessment>
<title>
Censorship in Public Libraries
</title>
<rubric>
<prompt>
What do you think about censorship in libraries?
Read for conciseness, clarity of thought, and form.
</prompt>
<criterion>
<name>concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>The Bible</name>
<explanation></explanation>
</option>
<option points="1">
<name>Earnest Hemingway</name>
<explanation></explanation>
</option>
<option points="3">
<name>Matsuo Basho</name>
<explanation></explanation>
</option>
</criterion>
<criterion>
<name>clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Eric</name>
<explanation></explanation>
</option>
<option points="1">
<name>John</name>
<explanation></explanation>
</option>
<option points="2">
<name>Ian</name>
<explanation></explanation>
</option>
</criterion>
<criterion>
<name>form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>IRC</name>
<explanation></explanation>
</option>
<option points="1">
<name>Real Email</name>
<explanation></explanation>
</option>
<option points="2">
<name>Old-timey letters</name>
<explanation></explanation>
</option>
</criterion>
<feedbackprompt>
Please provide additional free-form feedback on this submission.
This feedback is completely optional.
</feedbackprompt>
</rubric>
<assessments>
<assessment name="student-training">
<example>
<answer>Censorship is terrible. I don't like it at all.</answer>
<select criterion="concise" option="Matsuo Basho" />
<select criterion="clear-headed" option="Eric" />
<select criterion="form" option="IRC"/>
</example>
<example>
<answer>I love censorship.</answer>
<select criterion="concise" option="Matsuo Basho" />
<select criterion="clear-headed" option="Ian" />
<select criterion="form" option="Old-timey letters"/>
</example>
</assessment>
<assessment name="peer-assessment"
start="2013-12-20T19:00-7:00"
due="2014-12-21T22:22-7:00"
must_grade="1"
must_be_graded_by="1" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>Example Based Example</title>
<assessments>
<assessment name="example-based-assessment" algorithm_id="fake">
<example>
<answer>Born in northern New South Wales, Dowling entered the Royal Australian Naval College in 1915. After graduating in 1919 he went to sea aboard various Royal Navy and RAN vessels, and later specialised in gunnery. In 1937, he was given command of the sloop HMAS Swan. Following the outbreak of World War II, he saw action in the Mediterranean theatre as executive officer of the Royal Navy cruiser HMS Naiad, and survived her sinking by a German U-boat in March 1942. Returning to Australia, he served as Director of Plans and later Deputy Chief of Naval Staff before taking command of the light cruiser HMAS Hobart in November 1944. His achievements in the South West Pacific earned him the Distinguished Service Order.
Dowling took command of the RAN's first aircraft carrier, HMAS Sydney, in 1948. He became Chief of Naval Personnel in 1950, and Flag Officer Commanding HM Australian Fleet in 1953. Soon after taking up the position of CNS in February 1955, he was promoted to vice admiral and appointed a Companion of the Order of the Bath. As CNS he had to deal with shortages of money, manpower and equipment, and with the increasing role of the United States in Australia's defence planning, at the expense of traditional ties with Britain. Knighted in 1957, Dowling was Chairman of COSC from March 1959 until May 1961, when he retired from the military. In 1963 he was appointed a Knight Commander of the Royal Victorian Order and became Australian Secretary to HM Queen Elizabeth II, serving until his death in 1969.
</answer>
<select criterion="Ideas" option="Bad" />
<select criterion="Content" option="Bad" />
</example>
<example>
<answer>Roy Russell Dowling was born on 28 May 1901 in Condong, a township on the Tweed River in northern New South Wales. His parents were sugar cane inspector Russell Dowling and his wife Lily. The youth entered the Royal Australian Naval College (RANC) at Jervis Bay, Federal Capital Territory, in 1915. An underachiever academically, he excelled at sports, and became chief cadet captain before graduating in 1918 with the King's Medal, awarded for "gentlemanly bearing, character, good influence among his fellows and officer-like qualities".[1][2] The following year he was posted to Britain as a midshipman, undergoing training with the Royal Navy and seeing service on HMS Ramillies and HMS Venturous.[3] By January 1923 he was back in Australia, serving aboard the cruiser HMAS Adelaide. He was promoted to lieutenant in March.[4] In April 1924, Adelaide joined the Royal Navy's Special Service Squadron on its worldwide cruise, taking in New Zealand, Canada, the United States, Panama, and the West Indies, before docking in September at Portsmouth, England. There Dowling left the ship for his next appointment, training as a gunnery officer and serving in that capacity at HMS Excellent.
</answer>
<select criterion="Ideas" option="Good" />
<select criterion="Content" option="Bad" />
</example>
<example>
<answer>After his return to Australia in December 1926, Dowling spent eighteen months on HMAS Platypus and HMAS Anzac, where he continued to specialise in gunnery. In July 1928, he took on an instructional role at the gunnery school in Flinders Naval Depot on Western Port Bay, Victoria. He married Jessie Blanch in Melbourne on 8 May 1930; the couple had two sons and three daughters.[1][6] Jessie accompanied him on his next posting to Britain commencing in January 1931.</answer>
<select criterion="Ideas" option="Bad" />
<select criterion="Content" option="Good" />
</example>
<example>
<answer>He was promoted to lieutenant commander on 15 March, and was appointed gunnery officer on the light cruiser HMS Colombo in May. Dowling returned to Australia in January 1933, and was appointed squadron gunnery officer aboard the heavy cruiser HMAS Canberra that April.[1][4] The ship operated mainly within Australian waters over the next two years.[7] In July 1935, Dowling took charge of the gunnery school at Flinders Naval Depot. He was promoted to commander on 31 December 1936.[1][4] The following month, he assumed command of the newly commissioned Grimsby-class sloop HMAS Swan, carrying out duties in the South West Pacific.[8] Completing his tenure on Swan in January 1939, he was briefly assigned to the Navy Office, Melbourne, before returning to Britain in March for duty at HMS Pembroke, where he awaited posting aboard the yet-to-be-commissioned anti-aircraft cruiser, HMS Naiad.</answer>
<select criterion="Ideas" option="Good" />
<select criterion="Content" option="Good" />
</example>
</assessment>
</assessments>
<rubric>
<prompt>
Censorship in the Libraries
'All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.' --Katherine Paterson, Author
Write a persuasive essay to a newspaper reflecting your views on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading.
Read for conciseness, clarity of thought, and form.
</prompt>
<criterion feedback="optional">
<name>Ideas</name>
<prompt>Determine if there is a unifying theme or main idea.</prompt>
<option points="0">
<name>Bad</name>
<explanation>Difficult for the reader to discern the main idea. Too brief or too repetitive to establish or maintain a focus.</explanation>
</option>
<option points="3">
<name>Good</name>
<explanation>Presents a unifying theme or main idea, but may include minor tangents. Stays somewhat focused on topic and task.</explanation>
</option>
</criterion>
<criterion>
<name>Content</name>
<prompt>Assess the content of the submission</prompt>
<option points="0">
<name>Bad</name>
<explanation>Includes little information with few or no details or unrelated details. Unsuccessful in attempts to explore any facets of the topic.</explanation>
</option>
<option points="1">
<name>Good</name>
<explanation>Includes little information and few or no details. Explores only one or two facets of the topic.</explanation>
</option>
</criterion>
<feedbackprompt>
(Optional) What aspects of this response stood out to you? What did it do well? How could it improve?
</feedbackprompt>
</rubric>
</openassessment>
\ No newline at end of file
<openassessment submission_due="2030-03-11T18:20">
<title>
Global Poverty
</title>
<rubric>
<prompt>
Given the state of the world today, what do you think should be done to combat poverty?
Read for conciseness, clarity of thought, and form.
</prompt>
<criterion feedback='optional'>
<name>concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>
In "Cryptonomicon", Stephenson spent multiple pages talking about breakfast cereal.
While hilarious, in recent years his work has been anything but 'concise'.
</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>
If the author wrote something cyclopean that staggers the mind, score it thus.
</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>
Tight prose that conveys a wealth of information about the world in relatively
few words. Example, "The door irised open and he stepped inside."
</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>
When Stephenson still had an editor, his prose was dense, with anecdotes about
nitrox abuse implying main characters' whole life stories.
</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>
Score the work this way if it makes you weep, and the removal of a single
word would make you sneer.
</explanation>
</option>
</criterion>
<criterion>
<name>clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation></explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation></explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation></explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation></explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>
Coolly rational, with a firm grasp of the main topics, a crystal-clear train of thought,
and unemotional examination of the facts. This is the only item explained in this category,
to show that explained and unexplained items can be mixed.
</explanation>
</option>
</criterion>
<criterion feedback='optional'>
<name>form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation></explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation></explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation></explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation></explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation></explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation></explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment"
start="2014-03-11T10:00-18:10"
due="2030-12-21T22:22-7:00"
must_grade="1"
must_be_graded_by="1" />
</assessments>
</openassessment>
<openassessment submission_due="2015-03-11T18:20">
<title>
Global Poverty
</title>
<rubric>
<prompt>
Given the state of the world today, what do you think should be done to combat poverty?
Read for conciseness, clarity of thought, and form.
</prompt>
<criterion feedback='optional'>
<name>concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>
In "Cryptonomicon", Stephenson spent multiple pages talking about breakfast cereal.
While hilarious, in recent years his work has been anything but 'concise'.
</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>
If the author wrote something cyclopean that staggers the mind, score it thus.
</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>
Tight prose that conveys a wealth of information about the world in relatively
few words. Example, "The door irised open and he stepped inside."
</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>
When Stephenson still had an editor, his prose was dense, with anecdotes about
nitrox abuse implying main characters' whole life stories.
</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>
Score the work this way if it makes you weep, and the removal of a single
word would make you sneer.
</explanation>
</option>
</criterion>
<criterion>
<name>clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation></explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation></explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation></explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation></explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>
Coolly rational, with a firm grasp of the main topics, a crystal-clear train of thought,
and unemotional examination of the facts. This is the only item explained in this category,
to show that explained and unexplained items can be mixed.
</explanation>
</option>
</criterion>
<criterion feedback='optional'>
<name>form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation></explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation></explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation></explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation></explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation></explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation></explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment"
start="2014-03-11T10:00-18:10"
due="2015-12-21T22:22-7:00"
must_grade="1"
must_be_graded_by="1" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment submission_due="2015-03-11T18:20">
<title>
Global Poverty
</title>
<rubric>
<prompt>
Given the state of the world today, what do you think should be done to combat poverty?
Read for conciseness, clarity of thought, and form.
</prompt>
<criterion>
<name>concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>
In "Cryptonomicon", Stephenson spent multiple pages talking about breakfast cereal.
While hilarious, in recent years his work has been anything but 'concise'.
</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>
If the author wrote something cyclopean that staggers the mind, score it thus.
</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>
Tight prose that conveys a wealth of information about the world in relatively
few words. Example, "The door irised open and he stepped inside."
</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>
When Stephenson still had an editor, his prose was dense, with anecdotes about
nitrox abuse implying main characters' whole life stories.
</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>
Score the work this way if it makes you weep, and the removal of a single
word would make you sneer.
</explanation>
</option>
</criterion>
<criterion>
<name>clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation></explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation></explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation></explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation></explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>
Coolly rational, with a firm grasp of the main topics, a crystal-clear train of thought,
and unemotional examination of the facts. This is the only item explained in this category,
to show that explained and unexplained items can be mixed.
</explanation>
</option>
</criterion>
<criterion>
<name>form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation></explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation></explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation></explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation></explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation></explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation></explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>
Promptless rubric
</title>
<rubric>
<criterion>
<name>concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>The Bible</name>
<explanation></explanation>
</option>
<option points="1">
<name>Earnest Hemingway</name>
<explanation></explanation>
</option>
<option points="3">
<name>Matsuo Basho</name>
<explanation></explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment"
start="2014-12-20T19:00-7:00"
due="2014-12-21T22:22-7:00"
must_grade="2"
must_be_graded_by="1" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>υηι¢σ∂є тєѕт</title>
<rubric>
<prompt>Uᴎiↄobɘ qᴙomqT</prompt>
<criterion feedback='optional'>
<name>ȼønȼɨsɇ</name>
<prompt>Нош соисіѕэ іѕ іт?</prompt>
<option points="0">
<name>アoo尺</name>
<explanation>ʇɥǝ ʍɹıʇǝɹ pıp ɐ dooɹ ɾoq.</explanation>
</option>
<option points="1">
<name>ꟻAiᴙ</name>
<explanation>Ṫḧë ẅṛïẗëṛ ḋïḋ ä ḟäïṛ jöḅ.</explanation>
</option>
<option points="3">
<name>Ǥøøđ</name>
<explanation>ᴛʜᴇ ᴡʀɪᴛᴇʀ ᴅɪᴅ ᴀ ɢᴏᴏᴅ ᴊᴏʙ.</explanation>
</option>
</criterion>
<criterion>
<name>őń-tőṕíć</name>
<prompt>ωαѕ тнє ωяιтєя ση тσρι¢?</prompt>
<option points="0">
<name>アoo尺</name>
<explanation>ʇɥǝ ʍɹıʇǝɹ pıp ɐ dooɹ ɾoq.</explanation>
</option>
<option points="1">
<name>ꟻAiᴙ</name>
<explanation>Ṫḧë ẅṛïẗëṛ ḋïḋ ä ḟäïṛ jöḅ.</explanation>
</option>
<option points="3">
<name>Ǥøøđ</name>
<explanation>ᴛʜᴇ ᴡʀɪᴛᴇʀ ᴅɪᴅ ᴀ ɢᴏᴏᴅ ᴊᴏʙ.</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="1" must_be_graded_by="1" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
"""
Student training step in the OpenAssessment XBlock.
"""
import logging
from django.utils.translation import ugettext as _
from webob import Response
from xblock.core import XBlock
from openassessment.assessment.api import student_training
import openassessment.workflow.api as workflow_api
from openassessment.xblock.data_conversion import convert_training_examples_list_to_dict
from .resolve_dates import DISTANT_FUTURE
logger = logging.getLogger(__name__)
class StudentTrainingMixin(object):
"""
Student training is a step that allows students to practice
assessing example essays provided by the course author.
1) A student is shown an example essay.
2) The student scores the example essay.
a) If the student's scores match the instructor's scores,
the student is shown the next example. If there are no
more examples, the step is marked complete.
b) If the student's scores do NOT match the instructor's scores,
the student is prompted to retry.
"""
@XBlock.handler
def render_student_training(self, data, suffix=''): # pylint:disable=W0613
"""
Render the student training step.
Args:
data: Not used.
Kwargs:
suffix: Not used.
Returns:
unicode: HTML content of the grade step
"""
if "student-training" not in self.assessment_steps:
return Response(u"")
try:
path, context = self.training_path_and_context()
except: # pylint:disable=W0702
msg = u"Could not render student training step for submission {}".format(self.submission_uuid)
logger.exception(msg)
return self.render_error(_(u"An unexpected error occurred."))
else:
return self.render_assessment(path, context)
def training_path_and_context(self):
"""
Return the template path and context used to render the student training step.
Returns:
tuple of `(path, context)` where `path` is the path to the template and
`context` is a dict.
"""
# Retrieve the status of the workflow.
# If no submissions have been created yet, the status will be None.
workflow_status = self.get_workflow_info().get('status')
problem_closed, reason, start_date, due_date = self.is_closed(step="student-training")
context = {}
template = 'openassessmentblock/student_training/student_training_unavailable.html'
if not workflow_status:
return template, context
# If the student has completed the training step, then show that the step is complete.
# We put this condition first so that if a student has completed the step, it *always*
# shows as complete.
# We're assuming here that the training step always precedes the other assessment steps
# (peer/self) -- we may need to make this more flexible later.
if workflow_status and workflow_status != "training":
template = 'openassessmentblock/student_training/student_training_complete.html'
# If the problem is closed, then do not allow students to access the training step
elif problem_closed and reason == 'start':
context['training_start'] = start_date
template = 'openassessmentblock/student_training/student_training_unavailable.html'
elif problem_closed and reason == 'due':
context['training_due'] = due_date
template = 'openassessmentblock/student_training/student_training_closed.html'
# If we're on the training step, show the student an example
# We do this last so we can avoid querying the student training API if possible.
else:
training_module = self.get_assessment_module('student-training')
if not training_module:
return template, context
if due_date < DISTANT_FUTURE:
context['training_due'] = due_date
# Report progress in the student training workflow (completed X out of Y)
context['training_num_available'] = len(training_module["examples"])
context['training_num_completed'] = student_training.get_num_completed(self.submission_uuid)
context['training_num_current'] = context['training_num_completed'] + 1
# Retrieve the example essay for the student to submit
# This will contain the essay text, the rubric, and the options the instructor selected.
examples = convert_training_examples_list_to_dict(training_module["examples"])
example = student_training.get_training_example(
self.submission_uuid,
{
'prompt': self.prompt,
'criteria': self.rubric_criteria
},
examples
)
context['training_essay'] = example['answer']
context['training_rubric'] = example['rubric']
template = 'openassessmentblock/student_training/student_training.html'
return template, context
@XBlock.json_handler
def training_assess(self, data, suffix=''): # pylint:disable=W0613
"""
Compare the scores given by the student with those given by the course author.
If they match, update the training workflow. The client can then reload this
step to view the next essay or the completed step.
Currently, we return a boolean indicating whether the student assessed correctly
or not. However, the student training API provides the exact criteria that the student
scored incorrectly, as well as the "correct" options for those criteria.
In the future, we may expose this in the UI to provide more detailed feedback.
Args:
data (dict): Must have the following keys:
options_selected (dict): Dictionary mapping criterion names to option values.
Returns:
Dict with keys:
* "success" (bool) indicating success or error
* "msg" (unicode) containing additional information if an error occurs.
* "correct" (bool) indicating whether the student scored the assessment correctly.
"""
if 'options_selected' not in data:
return {'success': False, 'msg': _(u"Missing options_selected key in request")}
if not isinstance(data['options_selected'], dict):
return {'success': False, 'msg': _(u"options_selected must be a dictionary")}
# Check the student's scores against the course author's scores.
# This implicitly updates the student training workflow (which example essay is shown)
# as well as the assessment workflow (training/peer/self steps).
try:
corrections = student_training.assess_training_example(
self.submission_uuid, data['options_selected']
)
except (student_training.StudentTrainingRequestError, student_training.StudentTrainingInternalError) as ex:
return {
'success': False,
'msg': _(u"Your scores could not be checked: {error}.").format(error=ex)
}
except:
return {
'success': False,
'msg': _(u"An unexpected error occurred.")
}
else:
try:
self.update_workflow_status()
except workflow_api.AssessmentWorkflowError:
msg = _('Could not update workflow status.')
logger.exception(msg)
return {'success': False, 'msg': msg}
return {
'success': True,
'msg': u'',
'corrections': corrections,
}
"""
Studio editing view for OpenAssessment XBlock.
"""
import pkg_resources
import logging
from django.template.context import Context
from django.template.loader import get_template
from django.utils.translation import ugettext as _
from xblock.core import XBlock
from xblock.fragment import Fragment
from openassessment.xblock.xml import serialize_content, update_from_xml_str, ValidationError, UpdateFromXmlError
from openassessment.xblock.validation import validator
logger = logging.getLogger(__name__)
class StudioMixin(object):
"""
Studio editing view for OpenAssessment XBlock.
"""
def studio_view(self, context=None):
"""
Render the OpenAssessment XBlock for editing in Studio.
Args:
context: Not actively used for this view.
Returns:
(Fragment): An HTML fragment for editing the configuration of this XBlock.
"""
rendered_template = get_template('openassessmentblock/oa_edit.html').render(Context({}))
frag = Fragment(rendered_template)
frag.add_javascript(pkg_resources.resource_string(__name__, "static/js/openassessment.min.js"))
frag.initialize_js('OpenAssessmentEditor')
return frag
@XBlock.json_handler
def update_xml(self, data, suffix=''):
"""
Update the XBlock's XML.
Args:
data (dict): Data from the request; should have a value for the key 'xml'
containing the XML for this XBlock.
Kwargs:
suffix (str): Not used
Returns:
dict with keys 'success' (bool) and 'msg' (str)
"""
if 'xml' in data:
try:
update_from_xml_str(self, data['xml'], validator=validator(self))
except ValidationError as ex:
return {'success': False, 'msg': _('Validation error: {error}').format(error=ex)}
except UpdateFromXmlError as ex:
return {'success': False, 'msg': _('An error occurred while saving: {error}').format(error=ex)}
else:
return {'success': True, 'msg': _('Successfully updated OpenAssessment XBlock')}
else:
return {'success': False, 'msg': _('Must specify "xml" in request JSON dict.')}
@XBlock.json_handler
def xml(self, data, suffix=''):
"""
Retrieve the XBlock's content definition, serialized as XML.
Args:
data (dict): Not used
Kwargs:
suffix (str): Not used
Returns:
dict with keys 'success' (bool), 'message' (unicode), and 'xml' (unicode)
"""
try:
xml = serialize_content(self)
# We do not expect `serialize_content` to raise an exception,
# but if it does, handle it gracefully.
except Exception as ex:
msg = _('An unexpected error occurred while loading the problem: {error}').format(error=ex)
logger.error(msg)
return {'success': False, 'msg': msg, 'xml': u''}
else:
return {'success': True, 'msg': '', 'xml': xml}
@XBlock.json_handler
def check_released(self, data, suffix=''):
"""
Check whether the problem has been released.
Args:
data (dict): Not used
Kwargs:
suffix (str): Not used
Returns:
dict with keys 'success' (bool), 'message' (unicode), and 'is_released' (bool)
"""
# There aren't currently any server-side error conditions we report to the client,
# but we send success/msg values anyway for consistency with other handlers.
return {
'success': True, 'msg': u'',
'is_released': self.is_released()
}
import dateutil
import logging
from django.utils.translation import ugettext as _
from xblock.core import XBlock
from submissions import api
from openassessment.workflow import api as workflow_api
from .resolve_dates import DISTANT_FUTURE
logger = logging.getLogger(__name__)
class SubmissionMixin(object):
"""Submission Mixin introducing all Submission-related functionality.
Submission Mixin contains all logic and handlers associated with rendering
the submission section of the front end, as well as making all API calls to
the middle tier for constructing new submissions, or fetching submissions.
SubmissionMixin is a Mixin for the OpenAssessmentBlock. Functions in the
SubmissionMixin call into the OpenAssessmentBlock functions and will not
work outside the scope of OpenAssessmentBlock.
"""
submit_errors = {
# Reported to user sometimes, and useful in tests
'ENODATA': _(u'API returned an empty response.'),
'EBADFORM': _(u'API Submission Request Error.'),
'EUNKNOWN': _(u'API returned unclassified exception.'),
'ENOMULTI': _(u'Multiple submissions are not allowed.'),
'ENOPREVIEW': _(u'To submit a response, view this component in Preview or Live mode.'),
}
@XBlock.json_handler
def submit(self, data, suffix=''):
"""Place the submission text into Openassessment system
Allows submission of new responses. Performs basic workflow validation
on any new submission to ensure it is acceptable to receive a new
response at this time.
Args:
data (dict): Data should contain one attribute: submission. This is
the response from the student which should be stored in the
Open Assessment system.
suffix (str): Not used in this handler.
Returns:
(tuple): Returns the status (boolean) of this request, the
associated status tag (str), and status text (unicode).
"""
status = False
status_text = None
student_sub = data['submission']
student_item_dict = self.get_student_item_dict()
# Short-circuit if no user is defined (as in Studio Preview mode)
# Since students can't submit, they will never be able to progress in the workflow
if self.in_studio_preview:
return False, 'ENOPREVIEW', self.submit_errors['ENOPREVIEW']
workflow = self.get_workflow_info()
status_tag = 'ENOMULTI' # It is an error to submit multiple times for the same item
if not workflow:
status_tag = 'ENODATA'
try:
submission = self.create_submission(student_item_dict, student_sub)
except api.SubmissionRequestError as err:
status_tag = 'EBADFORM'
status_text = unicode(err.field_errors)
except (api.SubmissionError, workflow_api.AssessmentWorkflowError):
logger.exception("This response was not submitted.")
status_tag = 'EUNKNOWN'
else:
status = True
status_tag = submission.get('student_item')
status_text = submission.get('attempt_number')
# relies on success being orthogonal to errors
status_text = status_text if status_text else self.submit_errors[status_tag]
return status, status_tag, status_text
@XBlock.json_handler
def save_submission(self, data, suffix=''):
"""
Save the current student's response submission.
If the student already has a response saved, this will overwrite it.
Args:
data (dict): Data should have a single key 'submission' that contains
the text of the student's response.
suffix (str): Not used.
Returns:
dict: Contains a bool 'success' and unicode string 'msg'.
"""
if 'submission' in data:
try:
self.saved_response = unicode(data['submission'])
self.has_saved = True
# Emit analytics event...
self.runtime.publish(
self,
"openassessmentblock.save_submission",
{"saved_response": self.saved_response}
)
except:
return {'success': False, 'msg': _(u"This response could not be saved.")}
else:
return {'success': True, 'msg': u''}
else:
return {'success': False, 'msg': _(u"This response was not submitted.")}
def create_submission(self, student_item_dict, student_sub):
# Store the student's response text in a JSON-encodable dict
# so that later we can add additional response fields.
student_sub_dict = {'text': student_sub}
submission = api.create_submission(student_item_dict, student_sub_dict)
self.create_workflow(submission["uuid"])
self.submission_uuid = submission["uuid"]
# Emit analytics event...
self.runtime.publish(
self,
"openassessmentblock.create_submission",
{
"submission_uuid": submission["uuid"],
"attempt_number": submission["attempt_number"],
"created_at": submission["created_at"],
"submitted_at": submission["submitted_at"],
"answer": submission["answer"],
}
)
return submission
@staticmethod
def get_user_submission(submission_uuid):
"""Return the most recent submission by user in workflow
Return the most recent submission. If no submission is available,
return None. All submissions are preserved, but only the most recent
will be returned in this function, since the active workflow will only
be concerned with the most recent submission.
Args:
submission_uuid (str): The uuid for the submission to retrieve.
Returns:
(dict): A dictionary representation of a submission to render to
the front end.
"""
try:
return api.get_submission(submission_uuid)
except api.SubmissionRequestError:
# This error is actually ok.
return None
@property
def save_status(self):
"""
Return a string indicating whether the response has been saved.
Returns:
unicode
"""
return _(u'This response has been saved but not submitted.') if self.has_saved else _(u'This response has not been saved.')
@XBlock.handler
def render_submission(self, data, suffix=''):
"""Renders the Submission HTML section of the XBlock
Generates the submission HTML for the first section of an Open
Assessment XBlock. See OpenAssessmentBlock.render_assessment() for
more information on rendering XBlock sections.
Needs to support the following scenarios:
Unanswered and Open
Unanswered and Closed
Saved
Saved and Closed
Submitted
Submitted and Closed
Submitted, waiting assessment
Submitted and graded
"""
path, context = self.submission_path_and_context()
return self.render_assessment(path, context_dict=context)
def submission_path_and_context(self):
"""
Determine the template path and context to use when
rendering the response (submission) step.
Returns:
tuple of `(path, context)`, where `path` (str) is the path to the template,
and `context` (dict) is the template context.
"""
workflow = self.get_workflow_info()
problem_closed, reason, start_date, due_date = self.is_closed('submission')
path = 'openassessmentblock/response/oa_response.html'
context = {}
# Due dates can default to the distant future, in which case
# there's effectively no due date.
# If we don't add the date to the context, the template won't display it.
if due_date < DISTANT_FUTURE:
context["submission_due"] = due_date
if not workflow and problem_closed:
if reason == 'due':
path = 'openassessmentblock/response/oa_response_closed.html'
elif reason == 'start':
context['submission_start'] = start_date
path = 'openassessmentblock/response/oa_response_unavailable.html'
elif not workflow:
context['saved_response'] = self.saved_response
context['save_status'] = self.save_status
context['submit_enabled'] = self.saved_response != ''
path = "openassessmentblock/response/oa_response.html"
elif workflow["status"] == "done":
student_submission = self.get_user_submission(
workflow["submission_uuid"]
)
context["student_submission"] = student_submission
path = 'openassessmentblock/response/oa_response_graded.html'
else:
context["student_submission"] = self.get_user_submission(
workflow["submission_uuid"]
)
path = 'openassessmentblock/response/oa_response_submitted.html'
return path, context
"""
Base class for handler-level testing of the XBlock.
"""
import os.path
import json
from functools import wraps
from openassessment.test_utils import CacheResetTest
from workbench.runtime import WorkbenchRuntime
import webob
def scenario(scenario_path, user_id=None):
"""
Method decorator to load a scenario for a test case.
Must be called on an `XBlockHandlerTestCase` subclass, or
else it will have no effect.
Args:
scenario_path (str): Path to the scenario XML file.
Kwargs:
user_id (str or None): User ID to log in as, or None.
Returns:
The decorated method
Example:
@scenario('data/test_scenario.xml')
def test_submit(self, xblock):
response = self.request(xblock, 'submit', 'Test submission')
self.assertTrue('Success' in response)
"""
def _decorator(func):
@wraps(func)
def _wrapped(*args, **kwargs):
# Retrieve the object (self)
# if this is a function, not a method, then do nothing.
xblock = None
if args:
self = args[0]
if isinstance(self, XBlockHandlerTestCase):
# Print a debug message
print "Loading scenario from {path}".format(path=scenario_path)
# Configure the runtime with our user id
self.set_user(user_id)
# Load the scenario
xblock = self.load_scenario(scenario_path)
# Pass the XBlock as the first argument to the decorated method (after `self`)
args = list(args)
args.insert(1, xblock)
return func(*args, **kwargs)
return _wrapped
return _decorator
class XBlockHandlerTestCase(CacheResetTest):
"""
Load the XBlock in the workbench runtime to test its handler.
"""
def setUp(self):
"""
Create the runtime.
"""
self.runtime = WorkbenchRuntime()
def set_user(self, user_id):
"""
Provide a user ID to the runtime.
Args:
user_id (str): a user ID.
Returns:
None
"""
self.runtime.user_id = user_id
def load_scenario(self, xml_path):
"""
Load an XML definition of an XBlock and return the XBlock instance.
Args:
xml (string): Path to an XML definition of the XBlock, relative
to the test module.
Returns:
XBlock
"""
block_id = self.runtime.parse_xml_string(
self.load_fixture_str(xml_path), self.runtime.id_generator
)
return self.runtime.get_block(block_id)
def request(self, xblock, handler_name, content, response_format=None):
"""
Make a request to an XBlock handler.
Args:
xblock (XBlock): The XBlock instance that should handle the request.
handler_name (str): The name of the handler.
content (unicode): Content of the request.
Kwargs:
response_format (None or str): Expected format of the response string.
If `None`, return the raw response content; if 'json', parse the
response as JSON and return the result.
Raises:
NotImplementedError: Response format not supported.
Returns:
Content of the response (mixed).
"""
# Create a fake request
request = webob.Request(dict())
request.body = content
# Send the request to the XBlock handler
response = self.runtime.handle(xblock, handler_name, request)
# Parse the response (if a format is specified)
if response_format is None:
return response.body
elif response_format == 'json':
return json.loads(response.body)
else:
raise NotImplementedError("Response format '{format}' not supported".format(response_format))
@staticmethod
def load_fixture_str(path):
"""
Load data from a fixture file.
Args:
path (str): Path to the file.
Returns:
unicode: contents of the file.
"""
base_dir = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(base_dir, path)) as file_handle:
return file_handle.read()
{
"peer_then_self": {
"valid": true,
"assessments": [
{
"name": "peer-assessment",
"must_grade": 5,
"must_be_graded_by": 3
},
{
"name": "self-assessment"
}
],
"current_assessments": null,
"is_released": false
},
"peer_only": {
"valid": true,
"assessments": [
{
"name": "peer-assessment",
"must_grade": 5,
"must_be_graded_by": 3
}
],
"current_assessments": null,
"is_released": false
},
"self_only": {
"valid": true,
"assessments": [
{
"name": "self-assessment"
}
],
"current_assessments": null,
"is_released": false
},
"self_before_peer": {
"valid": false,
"assessments": [
{
"name": "self-assessment"
},
{
"name": "peer-assessment",
"must_grade": 5,
"must_be_graded_by": 3
}
],
"current_assessments": null,
"is_released": false
},
"peer_then_peer": {
"valid": false,
"assessments": [
{
"name": "peer-assessment",
"must_grade": 5,
"must_be_graded_by": 3
},
{
"name": "peer-assessment",
"must_grade": 5,
"must_be_graded_by": 3
}
],
"current_assessments": null,
"is_released": false
}
}
<openassessment submission_due="1999-03-05">
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>𝓒𝓸𝓷𝓬𝓲𝓼𝓮</name>
<prompt>How concise is it?</prompt>
<option points="3">
<name>ﻉซƈﻉɭɭﻉกՇ</name>
<explanation>Extremely concise</explanation>
</option>
<option points="2">
<name>Ġööḋ</name>
<explanation>Concise</explanation>
</option>
<option points="1">
<name>ק๏๏г</name>
<explanation>Wordy</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>How well-formed is it?</prompt>
<option points="3">
<name>Good</name>
<explanation>Good</explanation>
</option>
<option points="2">
<name>Fair</name>
<explanation>Fair</explanation>
</option>
<option points="1">
<name>Poor</name>
<explanation>Poor</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="1" must_be_graded_by="1" due="2000-01-02"/>
<assessment name="self-assessment" due="2000-01-8"/>
</assessments>
</openassessment>
<openassessment submission_due="2014-03-05">
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>𝓒𝓸𝓷𝓬𝓲𝓼𝓮</name>
<prompt>How concise is it?</prompt>
<option points="3">
<name>ﻉซƈﻉɭɭﻉกՇ</name>
<explanation>Extremely concise</explanation>
</option>
<option points="2">
<name>Ġööḋ</name>
<explanation>Concise</explanation>
</option>
<option points="1">
<name>ק๏๏г</name>
<explanation>Wordy</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>How well-formed is it?</prompt>
<option points="3">
<name>Good</name>
<explanation>Good</explanation>
</option>
<option points="2">
<name>Fair</name>
<explanation>Fair</explanation>
</option>
<option points="1">
<name>Poor</name>
<explanation>Poor</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="1" must_be_graded_by="1" start="4014-03-02"/>
<assessment name="self-assessment" start="4014-03-8"/>
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>HP Lovecraft explanation</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>Neal Stephenson (early) explanation</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>Earnest Hemingway</explanation>
</option>
</criterion>
<criterion>
<name>Clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation>Yogi Berra explanation</explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation>Hunter S. Thompson explanation</explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation>Isaac Asimov explanation</explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>Spock explanation</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation>lolcats explanation</explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation>Facebook explanation</explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation>Reddit explanation</explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation>metafilter explanation</explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation>Usenet, 1996 explanation</explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation>The Elements of Style explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="5" must_be_graded_by="3" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment submission_due="2014-04-01">
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>HP Lovecraft explanation</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>Neal Stephenson (early) explanation</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>Earnest Hemingway</explanation>
</option>
</criterion>
<criterion>
<name>Clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation>Yogi Berra explanation</explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation>Hunter S. Thompson explanation</explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation>Isaac Asimov explanation</explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>Spock explanation</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation>lolcats explanation</explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation>Facebook explanation</explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation>Reddit explanation</explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation>metafilter explanation</explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation>Usenet, 1996 explanation</explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation>The Elements of Style explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="5" must_be_graded_by="3" start="2015-01-02" due="2015-04-01"/>
<assessment name="self-assessment" start="2016-01-02" due="2016-04-01"/>
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<rubric>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>HP Lovecraft explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="2" must_be_graded_by="1" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>Example-based assessment</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>Ideas</name>
<prompt>How good are the ideas?</prompt>
<option points="0">
<name>Poor</name>
<explanation>Poor job!</explanation>
</option>
<option points="1">
<name>Fair</name>
<explanation>Fair job</explanation>
</option>
<option points="3">
<name>Good</name>
<explanation>Good job</explanation>
</option>
</criterion>
<criterion>
<name>Content</name>
<prompt>How good is the content?</prompt>
<option points="0">
<name>Poor</name>
<explanation>Poor job!</explanation>
</option>
<option points="1">
<name>Fair</name>
<explanation>Fair job</explanation>
</option>
<option points="3">
<name>Good</name>
<explanation>Good job</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="example-based-assessment" algorithm_id="fake">
<example>
<answer>Example Answer One</answer>
<select criterion="Ideas" option="Poor" />
<select criterion="Content" option="Poor" />
</example>
<example>
<answer>Example Answer Two</answer>
<select criterion="Ideas" option="Fair" />
<select criterion="Content" option="Fair" />
</example>
<example>
<answer>Example Answer Three</answer>
<select criterion="Ideas" option="Fair" />
<select criterion="Content" option="Good" />
</example>
<example>
<answer>Example Answer Four</answer>
<select criterion="Ideas" option="Poor" />
<select criterion="Content" option="Good" />
</example>
</assessment>
<assessment name="peer-assessment" must_grade="5" must_be_graded_by="3" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion feedback="optional">
<name>𝓒𝓸𝓷𝓬𝓲𝓼𝓮</name>
<prompt>How concise is it?</prompt>
<option points="3">
<name>ﻉซƈﻉɭɭﻉกՇ</name>
<explanation>Extremely concise</explanation>
</option>
<option points="2">
<name>Ġööḋ</name>
<explanation>Concise</explanation>
</option>
<option points="1">
<name>ק๏๏г</name>
<explanation>Wordy</explanation>
</option>
</criterion>
<criterion feedback="optional">
<name>Form</name>
<prompt>How well-formed is it?</prompt>
<option points="3">
<name>Good</name>
<explanation>Good</explanation>
</option>
<option points="2">
<name>Fair</name>
<explanation>Fair</explanation>
</option>
<option points="1">
<name>Poor</name>
<explanation>Poor</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="2" must_be_graded_by="2" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>𝓒𝓸𝓷𝓬𝓲𝓼𝓮</name>
<prompt>How concise is it?</prompt>
<option points="3">
<name>ﻉซƈﻉɭɭﻉกՇ</name>
<explanation>Extremely concise</explanation>
</option>
<option points="2">
<name>Ġööḋ</name>
<explanation>Concise</explanation>
</option>
<option points="1">
<name>ק๏๏г</name>
<explanation>Wordy</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>How well-formed is it?</prompt>
<option points="3">
<name>Good</name>
<explanation>Good</explanation>
</option>
<option points="2">
<name>Fair</name>
<explanation>Fair</explanation>
</option>
<option points="1">
<name>Poor</name>
<explanation>Poor</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="1" must_be_graded_by="1" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>𝓒𝓸𝓷𝓬𝓲𝓼𝓮</name>
<prompt>How concise is it?</prompt>
<option points="3">
<name>ﻉซƈﻉɭɭﻉกՇ</name>
<explanation>Extremely concise</explanation>
</option>
<option points="2">
<name>Ġööḋ</name>
<explanation>Concise</explanation>
</option>
<option points="1">
<name>ק๏๏г</name>
<explanation>Wordy</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>How well-formed is it?</prompt>
<option points="3">
<name>Good</name>
<explanation>Good</explanation>
</option>
<option points="2">
<name>Fair</name>
<explanation>Fair</explanation>
</option>
<option points="1">
<name>Poor</name>
<explanation>Poor</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="example-based-assessment" algorithm_id="fake">
<example>
<answer>Example Answer One</answer>
<select criterion="𝓒𝓸𝓷𝓬𝓲𝓼𝓮" option="Ġööḋ" />
<select criterion="Form" option="Poor" />
</example>
<example>
<answer>Example Answer Two</answer>
<select criterion="𝓒𝓸𝓷𝓬𝓲𝓼𝓮" option="ﻉซƈﻉɭɭﻉกՇ" />
<select criterion="Form" option="Fair" />
</example>
<example>
<answer>Example Answer Three</answer>
<select criterion="𝓒𝓸𝓷𝓬𝓲𝓼𝓮" option="Ġööḋ" />
<select criterion="Form" option="Good" />
</example>
<example>
<answer>Example Answer Four</answer>
<select criterion="𝓒𝓸𝓷𝓬𝓲𝓼𝓮" option="ﻉซƈﻉɭɭﻉกՇ" />
<select criterion="Form" option="Good" />
</example>
</assessment>
<assessment name="peer-assessment" must_grade="2" must_be_graded_by="2" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>𝓒𝓸𝓷𝓬𝓲𝓼𝓮</name>
<prompt>How concise is it?</prompt>
<option points="3">
<name>ﻉซƈﻉɭɭﻉกՇ</name>
<explanation>Extremely concise</explanation>
</option>
<option points="2">
<name>Ġööḋ</name>
<explanation>Concise</explanation>
</option>
<option points="1">
<name>ק๏๏г</name>
<explanation>Wordy</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>How well-formed is it?</prompt>
<option points="3">
<name>Good</name>
<explanation>Good</explanation>
</option>
<option points="2">
<name>Fair</name>
<explanation>Fair</explanation>
</option>
<option points="1">
<name>Poor</name>
<explanation>Poor</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="example-based-assessment" algorithm_id="fake">
<example>
<answer>Example Answer One</answer>
<select criterion="𝓒𝓸𝓷𝓬𝓲𝓼𝓮" option="Ġööḋ" />
<select criterion="Form" option="Poor" />
</example>
<example>
<answer>Example Answer Two</answer>
<select criterion="𝓒𝓸𝓷𝓬𝓲𝓼𝓮" option="ﻉซƈﻉɭɭﻉกՇ" />
<select criterion="Form" option="Fair" />
</example>
<example>
<answer>Example Answer Three</answer>
<select criterion="𝓒𝓸𝓷𝓬𝓲𝓼𝓮" option="Ġööḋ" />
<select criterion="Form" option="Good" />
</example>
<example>
<answer>Example Answer Four</answer>
<select criterion="𝓒𝓸𝓷𝓬𝓲𝓼𝓮" option="ﻉซƈﻉɭɭﻉกՇ" />
<select criterion="Form" option="Good" />
</example>
</assessment>
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>𝓒𝓸𝓷𝓬𝓲𝓼𝓮</name>
<prompt>How concise is it?</prompt>
<option points="3">
<name>ﻉซƈﻉɭɭﻉกՇ</name>
<explanation>Extremely concise</explanation>
</option>
<option points="2">
<name>Ġööḋ</name>
<explanation>Concise</explanation>
</option>
<option points="1">
<name>ק๏๏г</name>
<explanation>Wordy</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>How well-formed is it?</prompt>
<option points="3">
<name>Good</name>
<explanation>Good</explanation>
</option>
<option points="2">
<name>Fair</name>
<explanation>Fair</explanation>
</option>
<option points="1">
<name>Poor</name>
<explanation>Poor</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>Foo</title>
<assessments>
<!-- assessment name not supported -->
<assessment name="unsupported-assessment" />
<assessment name="self-assessment" />
</assessments>
<rubric>
<prompt>Test prompt</prompt>
<criterion>
<name>Test criterion</name>
<prompt>Test criterion prompt</prompt>
<option points="0"><name>No</name><explanation>No explanation</explanation></option>
<option points="2"><name>Yes</name><explanation>Yes explanation</explanation></option>
</criterion>
</rubric>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="self-assessment" />
<assessment name="peer-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" />
</assessments>
</openassessment>
{
"student_training_examples_invalid_criterion": {
"rubric": {
"criteria": [
{
"order_num": 0,
"name": "vocabulary",
"prompt": "How good is the vocabulary?",
"options": [
{
"order_num": 0,
"points": 0,
"name": "Poor",
"explanation": "Poor job!"
},
{
"order_num": 1,
"points": 1,
"name": "Good",
"explanation": "Good job!"
}
]
},
{
"order_num": 1,
"name": "grammar",
"prompt": "How good is the grammar?",
"options": [
{
"order_num": 0,
"points": 0,
"name": "Poor",
"explanation": "Poor job!"
},
{
"order_num": 1,
"points": 1,
"name": "Good",
"explanation": "Good job!"
}
]
}
]
},
"assessments": [
{
"name": "student-training",
"start": null,
"due": null,
"examples": [
{
"answer": "ẗëṡẗ äṅṡẅëṛ",
"options_selected": [
{
"criterion": "Invalid criterion!",
"option": "Good"
},
{
"criterion": "grammar",
"option": "Poor"
}
]
}
]
},
{
"name": "peer-assessment",
"start": null,
"due": null,
"must_grade": 5,
"must_be_graded_by": 3
}
]
},
"example_based_no_training_examples": {
"rubric": {
"criteria": [
{
"order_num": 0,
"name": "vocabulary",
"prompt": "how good is the vocabulary?",
"options": [
{
"order_num": 0,
"points": 0,
"name": "poor",
"explanation": "poor job!"
},
{
"order_num": 1,
"points": 1,
"name": "good",
"explanation": "good job!"
}
]
},
{
"order_num": 1,
"name": "grammar",
"prompt": "how good is the grammar?",
"options": [
{
"order_num": 0,
"points": 0,
"name": "poor",
"explanation": "poor job!"
},
{
"order_num": 1,
"points": 1,
"name": "good",
"explanation": "good job!"
}
]
}
]
},
"assessments": [
{
"name": "example-based-assessment",
"start": null,
"due": null,
"algorithm_id": "ease",
"examples": []
}
]
}
}
{
"empty_dict": {
"assessments": [{}],
"current_assessments": null,
"is_released": false
},
"unsupported_type": {
"assessments": [
{
"name": "peer-assessment",
"must_grade": 5,
"must_be_graded_by": 3
},
{
"name": "self-assessment"
},
{
"name": "unsupported-assessment",
"must_grade": 5,
"must_be_graded_by": 3
}
],
"current_assessments": null,
"is_released": false
},
"no_type": {
"assessments": [
{
"name": "self-assessment"
},
{
"must_grade": 5,
"must_be_graded_by": 3
}
],
"current_assessments": null,
"is_released": false
},
"unsupported_unicode_type": {
"assessments": [
{
"name": "self-assessment"
},
{
"name": "𝓹𝓮𝓮𝓻-𝓪𝓼𝓼𝓮𝓼𝓼𝓶𝓮𝓷𝓽",
"must_grade": 5,
"must_be_graded_by": 3
}
],
"current_assessments": null,
"is_released": false
},
"no_must_grade": {
"assessments": [
{
"name": "peer-assessment",
"must_be_graded_by": 3
},
{
"name": "self-assessment"
}
],
"current_assessments": null,
"is_released": false
},
"no_must_be_graded_by": {
"assessments": [
{
"name": "peer-assessment",
"must_grade": 5
},
{
"name": "self-assessment"
}
],
"current_assessments": null,
"is_released": false
},
"must_grade_less_than_must_be_graded_by": {
"assessments": [
{
"name": "peer-assessment",
"must_grade": 4,
"must_be_graded_by": 5
},
{
"name": "self-assessment"
}
],
"current_assessments": null,
"is_released": false
},
"must_grade_zero": {
"assessments": [
{
"name": "peer-assessment",
"must_grade": 0,
"must_be_graded_by": 0
},
{
"name": "self-assessment"
}
],
"current_assessments": null,
"is_released": false
},
"must_be_graded_by_zero": {
"assessments": [
{
"name": "peer-assessment",
"must_grade": 1,
"must_be_graded_by": 0
},
{
"name": "self-assessment"
}
],
"current_assessments": null,
"is_released": false
},
"remove_peer_mid_flight": {
"assessments": [
{
"name": "peer-assessment",
"must_grade": 5,
"must_be_graded_by": 3
},
{
"name": "self-assessment"
}
],
"current_assessments": [
{
"name": "self-assessment"
}
],
"is_released": true
},
"swap_peer_and_self_mid_flight": {
"assessments": [
{
"name": "peer-assessment",
"must_grade": 5,
"must_be_graded_by": 3
},
{
"name": "self-assessment"
}
],
"current_assessments": [
{
"name": "self-assessment"
},
{
"name": "peer-assessment",
"must_grade": 5,
"must_be_graded_by": 3
}
],
"is_released": true
},
"example_based_algorithm_id_is_not_ease": {
"assessments": [
{
"name": "example-based-assessment",
"start": null,
"due": null,
"algorithm_id": "NOT_EASE",
"examples": [
{
"answer": "тєѕт αηѕωєя",
"options_selected": [
{
"criterion": "Test criterion",
"option": "No"
}
]
},
{
"answer": "тєѕт αηѕωєя TWO",
"options_selected": [
{
"criterion": "Test criterion",
"option": "Yes"
}
]
}
]
}
],
"current_assessments": null,
"is_released": false
}
}
{
"submission_start_past_submission_due": {
"xblock_start": 0,
"submission_start": 3,
"submission_due": 2,
"peer_start": 4,
"peer_due": 5,
"self_start": 6,
"self_due": 7,
"xblock_due": 10
},
"submission_start_equals_submission_due": {
"xblock_start": 0,
"submission_start": 2,
"submission_due": 2,
"peer_start": 3,
"peer_due": 4,
"self_start": 5,
"self_due": 6,
"xblock_due": 10
},
"peer_start_past_peer_due": {
"xblock_start": 0,
"submission_start": 1,
"submission_due": 2,
"peer_start": 5,
"peer_due": 4,
"self_start": 6,
"self_due": 7,
"xblock_due": 10
},
"peer_start_equals_peer_due": {
"xblock_start": 0,
"submission_start": 1,
"submission_due": 2,
"peer_start": 4,
"peer_due": 4,
"self_start": 5,
"self_due": 6,
"xblock_due": 10
},
"self_start_past_self_due": {
"xblock_start": 0,
"submission_start": 1,
"submission_due": 2,
"peer_start": 3,
"peer_due": 4,
"self_start": 7,
"self_due": 6,
"xblock_due": 10
},
"self_start_equals_self_due": {
"xblock_start": 0,
"submission_start": 1,
"submission_due": 2,
"peer_start": 3,
"peer_due": 4,
"self_start": 6,
"self_due": 6,
"xblock_due": 10
},
"submission_start_past_peer_start": {
"xblock_start": 0,
"submission_start": 4,
"submission_due": 2,
"peer_start": 3,
"peer_due": 5,
"self_start": 6,
"self_due": 7,
"xblock_due": 8
},
"peer_start_past_self_start": {
"xblock_start": 0,
"submission_start": 1,
"submission_due": 2,
"peer_start": 6,
"peer_due": 4,
"self_start": 5,
"self_due": 7,
"xblock_due": 10
},
"self_due_before_peer_due": {
"xblock_start": 0,
"submission_start": 1,
"submission_due": 2,
"peer_start": 3,
"peer_due": 9,
"self_start": 5,
"self_due": 6,
"xblock_due": 10
},
"peer_due_before_submission_due": {
"xblock_start": 0,
"submission_start": 1,
"submission_due": 7,
"peer_start": 2,
"peer_due": 6,
"self_start": 8,
"self_due": 9,
"xblock_due": 10
},
"xblock_start_set_but_submission_start_none": {
"xblock_start": 0,
"submission_start": null,
"submission_due": 7,
"peer_start": 2,
"peer_due": 6,
"self_start": 8,
"self_due": 9,
"xblock_due": 10
},
"xblock_due_set_but_self_due_none": {
"xblock_start": 0,
"submission_start": 1,
"submission_due": 7,
"peer_start": 2,
"peer_due": 6,
"self_start": 8,
"self_due": null,
"xblock_due": 10
}
}
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>HP Lovecraft explanation</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>Neal Stephenson (early) explanation</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>Earnest Hemingway</explanation>
</option>
</criterion>
<criterion>
<name>Clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation>Yogi Berra explanation</explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation>Hunter S. Thompson explanation</explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation>Isaac Asimov explanation</explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>Spock explanation</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation>lolcats explanation</explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation>Facebook explanation</explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation>Reddit explanation</explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation>metafilter explanation</explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation>Usenet, 1996 explanation</explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation>The Elements of Style explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<!-- start date is after due date -->
<assessment name="peer-assessment" must_grade="5" must_be_graded_by="3" />
<assessment name="self-assessment" start="2010-01-01" due="2003-01-01"/>
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<rubric>
<prompt>
Line 1
Line 2
Line 3
</prompt>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>HP Lovecraft explanation</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>Neal Stephenson (early) explanation</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>Earnest Hemingway</explanation>
</option>
</criterion>
<criterion>
<name>Clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation>Yogi Berra explanation</explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation>Hunter S. Thompson explanation</explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation>Isaac Asimov explanation</explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>Spock explanation</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation>lolcats explanation</explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation>Facebook explanation</explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation>Reddit explanation</explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation>metafilter explanation</explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation>Usenet, 1996 explanation</explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation>The Elements of Style explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="5" must_be_graded_by="3" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment submission_due="2099-01-23">
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>𝓒𝓸𝓷𝓬𝓲𝓼𝓮</name>
<prompt>How concise is it?</prompt>
<option points="3">
<name>ﻉซƈﻉɭɭﻉกՇ</name>
<explanation>Extremely concise</explanation>
</option>
<option points="2">
<name>Ġööḋ</name>
<explanation>Concise</explanation>
</option>
<option points="1">
<name>ק๏๏г</name>
<explanation>Wordy</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>How well-formed is it?</prompt>
<option points="3">
<name>Good</name>
<explanation>Good</explanation>
</option>
<option points="2">
<name>Fair</name>
<explanation>Fair</explanation>
</option>
<option points="1">
<name>Poor</name>
<explanation>Poor</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="1" must_be_graded_by="1" due="2099-05-23"/>
<assessment name="self-assessment" due="2099-05-23"/>
</assessments>
</openassessment>
<openassessment>
<title>Only Self Assessment</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>HP Lovecraft explanation</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>Neal Stephenson (early) explanation</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>Earnest Hemingway</explanation>
</option>
</criterion>
<criterion>
<name>Clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation>Yogi Berra explanation</explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation>Hunter S. Thompson explanation</explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation>Isaac Asimov explanation</explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>Spock explanation</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation>lolcats explanation</explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation>Facebook explanation</explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation>Reddit explanation</explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation>metafilter explanation</explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation>Usenet, 1996 explanation</explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation>The Elements of Style explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="self-assessment" />
</assessments>
</openassessment>
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment