diff --git a/flake.nix b/flake.nix
index b17a0f5..9185c96 100644
--- a/flake.nix
+++ b/flake.nix
@@ -15,8 +15,6 @@
url = "github:ipetkov/crane";
inputs = {
nixpkgs.follows = "nixpkgs";
- flake-utils.follows = "flake-utils";
- rust-overlay.follows = "rust-overlay";
};
};
};
@@ -42,6 +40,7 @@
(pkgs.lib.hasSuffix "\.md" path) ||
(pkgs.lib.hasSuffix "\.stpl" path) ||
(pkgs.lib.hasInfix "static" path) ||
+ (pkgs.lib.hasInfix "zettoit-style" path) ||
(craneLib.filterCargoSources path type)
;
};
diff --git a/src/question/single_choice.rs b/src/question/single_choice.rs
index f60c945..4a06f9a 100644
--- a/src/question/single_choice.rs
+++ b/src/question/single_choice.rs
@@ -96,6 +96,24 @@ impl Question for SingleChoiceQuestion {
acc
},
),
+ submissions_correct: &self.submissions.iter().fold(
+ vec![0; self.inner.answers.len()],
+ |mut acc, (_, v)| {
+ if *v == self.inner.correct {
+ acc[*v as usize] += 1;
+ }
+ acc
+ },
+ ),
+ submissions_wrong: &self.submissions.iter().fold(
+ vec![0; self.inner.answers.len()],
+ |mut acc, (_, v)| {
+ if *v != self.inner.correct {
+ acc[*v as usize] += 1;
+ }
+ acc
+ },
+ ),
correct_answer: &self.inner.answers[self.inner.correct as usize],
answers: &self.inner.answers,
}
@@ -126,6 +144,8 @@ struct ViewerTemplate<'a> {
name: &'a str,
total_submissions: u32,
submissions: &'a [u32],
+ submissions_correct: &'a [u32],
+ submissions_wrong: &'a [u32],
correct_answer: &'a str,
answers: &'a [String],
}
diff --git a/static/check.svg b/static/check.svg
deleted file mode 100644
index 96d0c15..0000000
--- a/static/check.svg
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
diff --git a/static/patternomaly.js b/static/patternomaly.js
new file mode 100644
index 0000000..466a17f
--- /dev/null
+++ b/static/patternomaly.js
@@ -0,0 +1,1106 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global.pattern = factory());
+}(this, (function () { 'use strict';
+
+var BACKGROUND_COLOR = 'rgba(100, 100, 100, 0.7)';
+var PATTERN_COLOR = 'rgba(255, 255, 255, 0.8)';
+var POINT_STYLE = 'round';
+
+var asyncGenerator = function () {
+ function AwaitValue(value) {
+ this.value = value;
+ }
+
+ function AsyncGenerator(gen) {
+ var front, back;
+
+ function send(key, arg) {
+ return new Promise(function (resolve, reject) {
+ var request = {
+ key: key,
+ arg: arg,
+ resolve: resolve,
+ reject: reject,
+ next: null
+ };
+
+ if (back) {
+ back = back.next = request;
+ } else {
+ front = back = request;
+ resume(key, arg);
+ }
+ });
+ }
+
+ function resume(key, arg) {
+ try {
+ var result = gen[key](arg);
+ var value = result.value;
+
+ if (value instanceof AwaitValue) {
+ Promise.resolve(value.value).then(function (arg) {
+ resume("next", arg);
+ }, function (arg) {
+ resume("throw", arg);
+ });
+ } else {
+ settle(result.done ? "return" : "normal", result.value);
+ }
+ } catch (err) {
+ settle("throw", err);
+ }
+ }
+
+ function settle(type, value) {
+ switch (type) {
+ case "return":
+ front.resolve({
+ value: value,
+ done: true
+ });
+ break;
+
+ case "throw":
+ front.reject(value);
+ break;
+
+ default:
+ front.resolve({
+ value: value,
+ done: false
+ });
+ break;
+ }
+
+ front = front.next;
+
+ if (front) {
+ resume(front.key, front.arg);
+ } else {
+ back = null;
+ }
+ }
+
+ this._invoke = send;
+
+ if (typeof gen.return !== "function") {
+ this.return = undefined;
+ }
+ }
+
+ if (typeof Symbol === "function" && Symbol.asyncIterator) {
+ AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
+ return this;
+ };
+ }
+
+ AsyncGenerator.prototype.next = function (arg) {
+ return this._invoke("next", arg);
+ };
+
+ AsyncGenerator.prototype.throw = function (arg) {
+ return this._invoke("throw", arg);
+ };
+
+ AsyncGenerator.prototype.return = function (arg) {
+ return this._invoke("return", arg);
+ };
+
+ return {
+ wrap: function (fn) {
+ return function () {
+ return new AsyncGenerator(fn.apply(this, arguments));
+ };
+ },
+ await: function (value) {
+ return new AwaitValue(value);
+ }
+ };
+}();
+
+var classCallCheck = function (instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+};
+
+var createClass = function () {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+ }
+
+ return function (Constructor, protoProps, staticProps) {
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) defineProperties(Constructor, staticProps);
+ return Constructor;
+ };
+}();
+
+var _extends = Object.assign || function (target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+
+ for (var key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+ }
+
+ return target;
+};
+
+var inherits = function (subClass, superClass) {
+ if (typeof superClass !== "function" && superClass !== null) {
+ throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
+ }
+
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
+ constructor: {
+ value: subClass,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
+};
+
+var possibleConstructorReturn = function (self, call) {
+ if (!self) {
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+ }
+
+ return call && (typeof call === "object" || typeof call === "function") ? call : self;
+};
+
+var Shape = function () {
+ function Shape() {
+ var size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 20;
+ var backgroundColor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : BACKGROUND_COLOR;
+ var patternColor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : PATTERN_COLOR;
+ classCallCheck(this, Shape);
+
+ this._canvas = document.createElement('canvas');
+ this._context = this._canvas.getContext('2d');
+
+ this._canvas.width = size;
+ this._canvas.height = size;
+
+ this._context.fillStyle = backgroundColor;
+ this._context.fillRect(0, 0, this._canvas.width, this._canvas.height);
+
+ this._size = size;
+ this._patternColor = patternColor;
+
+ return this;
+ }
+
+ createClass(Shape, [{
+ key: 'setStrokeProps',
+ value: function setStrokeProps() {
+ this._context.strokeStyle = this._patternColor;
+ this._context.lineWidth = this._size / 10;
+ this._context.lineJoin = POINT_STYLE;
+ this._context.lineCap = POINT_STYLE;
+ }
+ }, {
+ key: 'setFillProps',
+ value: function setFillProps() {
+ this._context.fillStyle = this._patternColor;
+ }
+ }]);
+ return Shape;
+}();
+
+var Plus = function (_Shape) {
+ inherits(Plus, _Shape);
+
+ function Plus() {
+ classCallCheck(this, Plus);
+ return possibleConstructorReturn(this, (Plus.__proto__ || Object.getPrototypeOf(Plus)).apply(this, arguments));
+ }
+
+ createClass(Plus, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawPlus();
+ this.drawPlus(halfSize, halfSize);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawPlus',
+ value: function drawPlus() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var halfSize = size / 2;
+ var quarterSize = size / 4;
+
+ this._context.moveTo(quarterSize + offsetX, 0 + offsetY);
+ this._context.lineTo(quarterSize + offsetX, halfSize + offsetY);
+ this._context.moveTo(0 + offsetX, quarterSize + offsetY);
+ this._context.lineTo(halfSize + offsetX, quarterSize + offsetY);
+
+ this._context.closePath();
+ }
+ }]);
+ return Plus;
+}(Shape);
+
+var Cross = function (_Shape) {
+ inherits(Cross, _Shape);
+
+ function Cross() {
+ classCallCheck(this, Cross);
+ return possibleConstructorReturn(this, (Cross.__proto__ || Object.getPrototypeOf(Cross)).apply(this, arguments));
+ }
+
+ createClass(Cross, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawCross();
+ this.drawCross(halfSize, halfSize);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawCross',
+ value: function drawCross() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var halfSize = size / 2;
+ var gap = 2;
+
+ this._context.moveTo(offsetX + gap, offsetY + gap);
+ this._context.lineTo(halfSize - gap + offsetX, halfSize - gap + offsetY);
+ this._context.moveTo(offsetX + gap, halfSize - gap + offsetY);
+ this._context.lineTo(halfSize - gap + offsetX, offsetY + gap);
+
+ this._context.closePath();
+ }
+ }]);
+ return Cross;
+}(Shape);
+
+var Dash = function (_Shape) {
+ inherits(Dash, _Shape);
+
+ function Dash() {
+ classCallCheck(this, Dash);
+ return possibleConstructorReturn(this, (Dash.__proto__ || Object.getPrototypeOf(Dash)).apply(this, arguments));
+ }
+
+ createClass(Dash, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawDash();
+ this.drawDash(halfSize, halfSize);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawDash',
+ value: function drawDash() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var halfSize = size / 2;
+ var gap = 2;
+
+ this._context.moveTo(offsetX + gap, offsetY + gap);
+ this._context.lineTo(halfSize - gap + offsetX, halfSize - gap + offsetY);
+
+ this._context.closePath();
+ }
+ }]);
+ return Dash;
+}(Shape);
+
+var CrossDash = function (_Shape) {
+ inherits(CrossDash, _Shape);
+
+ function CrossDash() {
+ classCallCheck(this, CrossDash);
+ return possibleConstructorReturn(this, (CrossDash.__proto__ || Object.getPrototypeOf(CrossDash)).apply(this, arguments));
+ }
+
+ createClass(CrossDash, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ var cross = new Cross();
+ cross.drawCross.call(this);
+
+ var dash = new Dash();
+ dash.drawDash.call(this, halfSize, halfSize);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }]);
+ return CrossDash;
+}(Shape);
+
+var Dot = function (_Shape) {
+ inherits(Dot, _Shape);
+
+ function Dot() {
+ classCallCheck(this, Dot);
+ return possibleConstructorReturn(this, (Dot.__proto__ || Object.getPrototypeOf(Dot)).apply(this, arguments));
+ }
+
+ createClass(Dot, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setFillProps();
+
+ this.drawDot();
+ this.drawDot(halfSize, halfSize);
+
+ this._context.fill();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawDot',
+ value: function drawDot() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+ var diameter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this._size / 10;
+
+ var size = this._size;
+ var quarterSize = size / 4;
+ var x = quarterSize + offsetX;
+ var y = quarterSize + offsetY;
+
+ this._context.moveTo(x + quarterSize, y);
+ this._context.arc(x, y, diameter, 0, 2 * Math.PI);
+
+ this._context.closePath();
+ }
+ }]);
+ return Dot;
+}(Shape);
+
+var DotDash = function (_Shape) {
+ inherits(DotDash, _Shape);
+
+ function DotDash() {
+ classCallCheck(this, DotDash);
+ return possibleConstructorReturn(this, (DotDash.__proto__ || Object.getPrototypeOf(DotDash)).apply(this, arguments));
+ }
+
+ createClass(DotDash, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ var dash = new Dash();
+ dash.drawDash.call(this, halfSize, halfSize);
+
+ this._context.closePath();
+ this._context.stroke();
+
+ this.setFillProps();
+
+ var dot = new Dot();
+ dot.drawDot.call(this);
+
+ this._context.fill();
+
+ return this._canvas;
+ }
+ }]);
+ return DotDash;
+}(Shape);
+
+var Disc = function (_Dot) {
+ inherits(Disc, _Dot);
+
+ function Disc() {
+ classCallCheck(this, Disc);
+ return possibleConstructorReturn(this, (Disc.__proto__ || Object.getPrototypeOf(Disc)).apply(this, arguments));
+ }
+
+ createClass(Disc, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+ var diameter = this._size / 5;
+
+ this._context.beginPath();
+
+ this.setFillProps();
+
+ this.drawDot(0, 0, diameter);
+ this.drawDot(halfSize, halfSize, diameter);
+
+ this._context.fill();
+
+ return this._canvas;
+ }
+ }]);
+ return Disc;
+}(Dot);
+
+var Ring = function (_Dot) {
+ inherits(Ring, _Dot);
+
+ function Ring() {
+ classCallCheck(this, Ring);
+ return possibleConstructorReturn(this, (Ring.__proto__ || Object.getPrototypeOf(Ring)).apply(this, arguments));
+ }
+
+ createClass(Ring, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+ var diameter = this._size / 5;
+
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawDot(0, 0, diameter);
+ this.drawDot(halfSize, halfSize, diameter);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }]);
+ return Ring;
+}(Dot);
+
+var Line = function (_Shape) {
+ inherits(Line, _Shape);
+
+ function Line() {
+ classCallCheck(this, Line);
+ return possibleConstructorReturn(this, (Line.__proto__ || Object.getPrototypeOf(Line)).apply(this, arguments));
+ }
+
+ createClass(Line, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawLine();
+ this.drawLine(halfSize, halfSize);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawLine',
+ value: function drawLine() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var quarterSize = size / 4;
+
+ this._context.moveTo(0, quarterSize + offsetY);
+ this._context.lineTo(this._size, quarterSize + offsetY);
+
+ this._context.closePath();
+ }
+ }]);
+ return Line;
+}(Shape);
+
+var VerticalLine = function (_Line) {
+ inherits(VerticalLine, _Line);
+
+ function VerticalLine() {
+ classCallCheck(this, VerticalLine);
+ return possibleConstructorReturn(this, (VerticalLine.__proto__ || Object.getPrototypeOf(VerticalLine)).apply(this, arguments));
+ }
+
+ createClass(VerticalLine, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ this._context.translate(this._size, 0);
+ this._context.rotate(90 * Math.PI / 180);
+
+ Line.prototype.drawTile.call(this);
+
+ return this._canvas;
+ }
+ }]);
+ return VerticalLine;
+}(Line);
+
+var Weave = function (_Shape) {
+ inherits(Weave, _Shape);
+
+ function Weave() {
+ classCallCheck(this, Weave);
+ return possibleConstructorReturn(this, (Weave.__proto__ || Object.getPrototypeOf(Weave)).apply(this, arguments));
+ }
+
+ createClass(Weave, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawWeave(0, 0);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawWeave',
+ value: function drawWeave(offsetX, offsetY) {
+ var size = this._size;
+ var halfSize = size / 2;
+
+ this._context.moveTo(offsetX + 1, offsetY + 1);
+ this._context.lineTo(halfSize - 1, halfSize - 1);
+
+ this._context.moveTo(halfSize + 1, size - 1);
+ this._context.lineTo(size - 1, halfSize + 1);
+
+ this._context.closePath();
+ }
+ }]);
+ return Weave;
+}(Shape);
+
+var Zigzag = function (_Shape) {
+ inherits(Zigzag, _Shape);
+
+ function Zigzag() {
+ classCallCheck(this, Zigzag);
+ return possibleConstructorReturn(this, (Zigzag.__proto__ || Object.getPrototypeOf(Zigzag)).apply(this, arguments));
+ }
+
+ createClass(Zigzag, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawZigzag();
+ this.drawZigzag(this._size / 2);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawZigzag',
+ value: function drawZigzag() {
+ var offsetY = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+
+ var size = this._size;
+ var quarterSize = size / 4;
+ var halfSize = size / 2;
+ var tenthSize = size / 10;
+
+ this._context.moveTo(0, tenthSize + offsetY);
+ this._context.lineTo(quarterSize, halfSize - tenthSize + offsetY);
+ this._context.lineTo(halfSize, tenthSize + offsetY);
+ this._context.lineTo(size - quarterSize, halfSize - tenthSize + offsetY);
+ this._context.lineTo(size, tenthSize + offsetY);
+ }
+ }]);
+ return Zigzag;
+}(Shape);
+
+var ZigzagVertical = function (_Zigzag) {
+ inherits(ZigzagVertical, _Zigzag);
+
+ function ZigzagVertical() {
+ classCallCheck(this, ZigzagVertical);
+ return possibleConstructorReturn(this, (ZigzagVertical.__proto__ || Object.getPrototypeOf(ZigzagVertical)).apply(this, arguments));
+ }
+
+ createClass(ZigzagVertical, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ this._context.translate(this._size, 0);
+ this._context.rotate(90 * Math.PI / 180);
+
+ Zigzag.prototype.drawTile.call(this);
+
+ return this._canvas;
+ }
+ }]);
+ return ZigzagVertical;
+}(Zigzag);
+
+var Diagonal = function (_Shape) {
+ inherits(Diagonal, _Shape);
+
+ function Diagonal() {
+ classCallCheck(this, Diagonal);
+ return possibleConstructorReturn(this, (Diagonal.__proto__ || Object.getPrototypeOf(Diagonal)).apply(this, arguments));
+ }
+
+ createClass(Diagonal, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawDiagonalLine();
+ this.drawDiagonalLine(halfSize, halfSize);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawDiagonalLine',
+ value: function drawDiagonalLine() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var halfSize = size / 2;
+ var gap = 1;
+
+ this._context.moveTo(halfSize - gap - offsetX, gap * -1 + offsetY);
+ this._context.lineTo(size + 1 - offsetX, halfSize + 1 + offsetY);
+
+ this._context.closePath();
+ }
+ }]);
+ return Diagonal;
+}(Shape);
+
+var DiagonalRightLeft = function (_Diagonal) {
+ inherits(DiagonalRightLeft, _Diagonal);
+
+ function DiagonalRightLeft() {
+ classCallCheck(this, DiagonalRightLeft);
+ return possibleConstructorReturn(this, (DiagonalRightLeft.__proto__ || Object.getPrototypeOf(DiagonalRightLeft)).apply(this, arguments));
+ }
+
+ createClass(DiagonalRightLeft, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ this._context.translate(this._size, 0);
+ this._context.rotate(90 * Math.PI / 180);
+
+ Diagonal.prototype.drawTile.call(this);
+
+ return this._canvas;
+ }
+ }]);
+ return DiagonalRightLeft;
+}(Diagonal);
+
+var Square = function (_Shape) {
+ inherits(Square, _Shape);
+
+ function Square() {
+ classCallCheck(this, Square);
+ return possibleConstructorReturn(this, (Square.__proto__ || Object.getPrototypeOf(Square)).apply(this, arguments));
+ }
+
+ createClass(Square, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setFillProps();
+
+ this.drawSquare();
+ this.drawSquare(halfSize, halfSize);
+
+ this._context.fill();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawSquare',
+ value: function drawSquare() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var halfSize = size / 2;
+ var gap = size / 20;
+
+ this._context.fillRect(offsetX + gap, offsetY + gap, halfSize - gap * 2, halfSize - gap * 2);
+
+ this._context.closePath();
+ }
+ }]);
+ return Square;
+}(Shape);
+
+var Box = function (_Shape) {
+ inherits(Box, _Shape);
+
+ function Box() {
+ classCallCheck(this, Box);
+ return possibleConstructorReturn(this, (Box.__proto__ || Object.getPrototypeOf(Box)).apply(this, arguments));
+ }
+
+ createClass(Box, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawBox();
+ this.drawBox(halfSize, halfSize);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawBox',
+ value: function drawBox() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var halfSize = size / 2;
+ var gap = size / 20;
+
+ this._context.strokeRect(offsetX + gap, offsetY + gap, halfSize - gap * 4, halfSize - gap * 4);
+
+ this._context.closePath();
+ }
+ }]);
+ return Box;
+}(Shape);
+
+var Triangle = function (_Shape) {
+ inherits(Triangle, _Shape);
+
+ function Triangle() {
+ classCallCheck(this, Triangle);
+ return possibleConstructorReturn(this, (Triangle.__proto__ || Object.getPrototypeOf(Triangle)).apply(this, arguments));
+ }
+
+ createClass(Triangle, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setFillProps();
+
+ this.drawTriangle();
+ this.drawTriangle(halfSize, halfSize);
+
+ this._context.fill();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawTriangle',
+ value: function drawTriangle() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var halfSize = size / 2;
+ var quarterSize = size / 4;
+
+ this._context.moveTo(quarterSize + offsetX, offsetY);
+ this._context.lineTo(halfSize + offsetX, halfSize + offsetY);
+ this._context.lineTo(offsetX, halfSize + offsetY);
+
+ this._context.closePath();
+ }
+ }]);
+ return Triangle;
+}(Shape);
+
+var TriangleVertical = function (_Triangle) {
+ inherits(TriangleVertical, _Triangle);
+
+ function TriangleVertical() {
+ classCallCheck(this, TriangleVertical);
+ return possibleConstructorReturn(this, (TriangleVertical.__proto__ || Object.getPrototypeOf(TriangleVertical)).apply(this, arguments));
+ }
+
+ createClass(TriangleVertical, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var size = this._size;
+
+ this._context.translate(size, size);
+ this._context.rotate(180 * Math.PI / 180);
+
+ Triangle.prototype.drawTile.call(this);
+
+ return this._canvas;
+ }
+ }]);
+ return TriangleVertical;
+}(Triangle);
+
+var Diamond = function (_Shape) {
+ inherits(Diamond, _Shape);
+
+ function Diamond() {
+ classCallCheck(this, Diamond);
+ return possibleConstructorReturn(this, (Diamond.__proto__ || Object.getPrototypeOf(Diamond)).apply(this, arguments));
+ }
+
+ createClass(Diamond, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setFillProps();
+
+ this.drawDiamond();
+ this.drawDiamond(halfSize, halfSize);
+
+ this._context.fill();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawDiamond',
+ value: function drawDiamond() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var halfSize = size / 2;
+ var quarterSize = size / 4;
+
+ this._context.moveTo(quarterSize + offsetX, offsetY);
+ this._context.lineTo(halfSize + offsetX, quarterSize + offsetY);
+ this._context.lineTo(quarterSize + offsetX, halfSize + offsetY);
+ this._context.lineTo(offsetX, quarterSize + offsetY);
+
+ this._context.closePath();
+ }
+ }]);
+ return Diamond;
+}(Shape);
+
+var DiamondBox = function (_Diamond) {
+ inherits(DiamondBox, _Diamond);
+
+ function DiamondBox() {
+ classCallCheck(this, DiamondBox);
+ return possibleConstructorReturn(this, (DiamondBox.__proto__ || Object.getPrototypeOf(DiamondBox)).apply(this, arguments));
+ }
+
+ createClass(DiamondBox, [{
+ key: 'drawTile',
+ value: function drawTile() {
+ var halfSize = this._size / 2;
+
+ this._context.beginPath();
+
+ this.setStrokeProps();
+
+ this.drawDiamond();
+ this.drawDiamond(halfSize, halfSize);
+
+ this._context.stroke();
+
+ return this._canvas;
+ }
+ }, {
+ key: 'drawDiamond',
+ value: function drawDiamond() {
+ var offsetX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+ var size = this._size;
+ var halfSize = size / 2 - 1;
+ var quarterSize = size / 4;
+
+ this._context.moveTo(quarterSize + offsetX, offsetY + 1);
+ this._context.lineTo(halfSize + offsetX, quarterSize + offsetY);
+ this._context.lineTo(quarterSize + offsetX, halfSize + offsetY);
+ this._context.lineTo(offsetX + 1, quarterSize + offsetY);
+
+ this._context.closePath();
+ }
+ }]);
+ return DiamondBox;
+}(Diamond);
+
+var shapes = {
+ 'plus': Plus,
+ 'cross': Cross,
+ 'dash': Dash,
+ 'cross-dash': CrossDash,
+ 'dot': Dot,
+ 'dot-dash': DotDash,
+ 'disc': Disc,
+ 'ring': Ring,
+ 'line': Line,
+ 'line-vertical': VerticalLine,
+ 'weave': Weave,
+ 'zigzag': Zigzag,
+ 'zigzag-vertical': ZigzagVertical,
+ 'diagonal': Diagonal,
+ 'diagonal-right-left': DiagonalRightLeft,
+ 'square': Square,
+ 'box': Box,
+ 'triangle': Triangle,
+ 'triangle-inverted': TriangleVertical,
+ 'diamond': Diamond,
+ 'diamond-box': DiamondBox
+};
+
+var deprecatedShapes = {
+ 'circle': shapes['disc'],
+ 'triangle-vertical': shapes['triangle-inverted'],
+ 'line-horizontal': shapes['line'],
+ 'line-diagonal-lr': shapes['diagonal'],
+ 'line-diagonal-rl': shapes['diagonal-right-left'],
+ 'zigzag-horizontal': shapes['zigzag'],
+ 'diamond-outline': shapes['diamond-box']
+};
+
+var completeShapesList = [];
+
+function getRandomShape() {
+ var excludedShapeTypes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
+
+ var shapesList = Object.keys(shapes);
+
+ excludedShapeTypes.forEach(function (shapeType) {
+ shapesList.splice(shapesList.indexOf(shapeType), 1);
+ });
+
+ var randomIndex = Math.floor(Math.random() * shapesList.length);
+
+ return shapesList[randomIndex];
+}
+
+_extends(completeShapesList, shapes, deprecatedShapes);
+
+function draw() {
+ var shapeType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'square';
+ var backgroundColor = arguments[1];
+ var patternColor = arguments[2];
+ var size = arguments[3];
+
+ var patternCanvas = document.createElement('canvas');
+ var patternContext = patternCanvas.getContext('2d');
+ var outerSize = size * 2;
+
+ var Shape = completeShapesList[shapeType];
+ var shape = new Shape(size, backgroundColor, patternColor);
+
+ var pattern = patternContext.createPattern(shape.drawTile(), 'repeat');
+
+ patternCanvas.width = outerSize;
+ patternCanvas.height = outerSize;
+
+ pattern.shapeType = shapeType;
+
+ return pattern;
+}
+
+function generate(colorList) {
+ var firstShapeType = void 0;
+ var previousShapeType = void 0;
+
+ return colorList.map(function (color, index, list) {
+ var shapeType = void 0;
+
+ if (index === 0) {
+ shapeType = getRandomShape();
+ previousShapeType = shapeType;
+ firstShapeType = previousShapeType;
+ } else if (index === list.length - 1) {
+ shapeType = getRandomShape([previousShapeType, firstShapeType]);
+ } else {
+ shapeType = getRandomShape([previousShapeType]);
+ previousShapeType = shapeType;
+ }
+
+ return draw(shapeType, color);
+ });
+}
+
+var pattern = {
+ draw: draw,
+ generate: generate
+};
+
+return pattern;
+
+})));
+//# sourceMappingURL=patternomaly.js.map
diff --git a/static/xmark.svg b/static/xmark.svg
deleted file mode 100644
index 1770be5..0000000
--- a/static/xmark.svg
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
diff --git a/templates/index.stpl b/templates/index.stpl
index c77fa8f..2258164 100644
--- a/templates/index.stpl
+++ b/templates/index.stpl
@@ -31,10 +31,12 @@ answers = [ "A", "B", "C", "D"]
correct = 0
-
diff --git a/templates/play.stpl b/templates/play.stpl
index 2ee0d1b..77ee3ef 100644
--- a/templates/play.stpl
+++ b/templates/play.stpl
@@ -11,21 +11,15 @@
<% } %>
<% if let PlayerState::NotStarted = state { %>
-
- The Quiz hasn't started yet. Please wait for the first question.
-
+ The Quiz hasn't started yet. Please wait for the first question.
<% } else if let PlayerState::Answering{ inner_body } = state { %>
<%- inner_body %>
<% } else if let PlayerState::Waiting(_) = state{ %>
-
- You answered the current question. Please wait for the results.
-
+ You answered the current question. Please wait for the results.
<% } else if let PlayerState::Result{ inner_body } = state{ %>
<%- inner_body %>
<% } else if let PlayerState::Completed(correct) = state { %>
-
- The Quiz finished. You can close this tab now. You answered <%= correct*100.0 %>% correctly.
-
+ The Quiz finished. You can close this tab now. You answered <%= correct*100.0 %>% correctly.
<% } %>
<% if !htmx { %>
diff --git a/templates/single_choice/player.stpl b/templates/single_choice/player.stpl
index 063751a..bfa6b8b 100644
--- a/templates/single_choice/player.stpl
+++ b/templates/single_choice/player.stpl
@@ -1,10 +1,8 @@
-
- <%= name %>
- <% for (index, answer) in answers.iter().enumerate() { %>
-
- <% } %>
-
+<%= name %>
+<% for (index, answer) in answers.iter().enumerate() { %>
+
+<% } %>
diff --git a/templates/single_choice/result.stpl b/templates/single_choice/result.stpl
index 988741f..1399b52 100644
--- a/templates/single_choice/result.stpl
+++ b/templates/single_choice/result.stpl
@@ -1,18 +1,14 @@
<% if is_correct { %>
-
- Correct
- Your answer is correct. The correct answer is <%= correct_answer %> .
-
+ Correct
+ Your answer is correct. The correct answer is <%= correct_answer %> .
<% } else { %>
-
- Wrong
-
- Your answer is incorrect. The correct answer is <%= correct_answer %> .
- <% if let Some(player_answer) = player_answer { %>
- You answered <%= player_answer %> .
- <% } else { %>
- You didn't answer the question.
- <% } %>
-
-
+ Wrong
+
+ Your answer is incorrect. The correct answer is <%= correct_answer %> .
+ <% if let Some(player_answer) = player_answer { %>
+ You answered <%= player_answer %> .
+ <% } else { %>
+ You didn't answer the question.
+ <% } %>
+
<% } %>
diff --git a/templates/single_choice/viewer.stpl b/templates/single_choice/viewer.stpl
index 92ab402..d715013 100644
--- a/templates/single_choice/viewer.stpl
+++ b/templates/single_choice/viewer.stpl
@@ -1,7 +1,6 @@
<%= name %>
Total Participants: <%= total_submissions %>
<% if show_result { %>
-
The correct answer is: <%= correct_answer %>
<% } %>
@@ -18,34 +17,72 @@
"<%= answer %>",
<% } %>
],
+<% if show_result { %>
+ datasets: [
+ {
+ label: "correct answers",
+ data: [
+ <% for submissions in submissions_correct.iter() { %>
+ <%= submissions %>,
+ <% } %>
+ ],
+ borderWidth: 1,
+ borderColor: '#fff',
+ backgroundColor: '#fff',
+ },
+ {
+ label: "wrong answers",
+ data: [
+ <% for submissions in submissions_wrong.iter() { %>
+ <%= submissions %>,
+ <% } %>
+ ],
+ borderWidth: 2,
+ borderColor: '#fff',
+ backgroundColor: [ pattern.draw('diagonal-right-left', '#000000') ],
+ }
+ ]
+<% } else { %>
datasets: [{
- label: "# der Stimmen",
data: [
<% for submissions in submissions.iter() { %>
<%= submissions %>,
<% } %>
],
- borderWidth: 1
+
+ borderWidth: 2,
+ borderColor: '#FFF',
+ backgroundColor: [ pattern.draw('diagonal-right-left', '#000000') ]
+
}]
+<% } %>
},
options: {
- legend: {
- display: false
+ plugins: {
+ legend: {
+ display: false
+ }
},
scales: {
x: {
+ stacked: true,
ticks: {
font: {
- size: 64
- }
+ size: 64,
+ family: 'monospace'
+ },
+ color: '#FFF'
}
},
y: {
beginAtZero: true,
+ stacked: true,
ticks: {
font: {
- size:24
- }
+ size: 16,
+ family: 'monospace'
+ },
+ color: '#FFF'
}
}
}
diff --git a/templates/view.stpl b/templates/view.stpl
index 5ce02db..df1add9 100644
--- a/templates/view.stpl
+++ b/templates/view.stpl
@@ -11,11 +11,14 @@
filter: invert();
width: 100%;
height: auto;
+ max-height: 90vh;
+ max-width: 90wh;
}
+
<% } %>
<% if let ViewerState::Answering{ inner_body } = state { %>
@@ -34,15 +37,11 @@
<% } %>
<% } else if let ViewerState::NotStarted((player, qrcode, url)) = state { %>
-
- <%- qrcode %>
- or visit <%= url %>
- Start Quiz with <%= player %> Players
-
+ <%- qrcode %>
+ or visit <%= url %>
+ Start Quiz with <%= player %> Players
<% } else {%>
-
- The Quiz finished. You can close this tab now.
-
+ The Quiz finished. You can close this tab now.
<% } %>
<% if !htmx { %>