Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit 93ffaf4

Browse files
authored
Merge pull request #1247 from RunestoneInteractive/group_submit
group submit
2 parents 41d4430 + 0dc9127 commit 93ffaf4

21 files changed

Lines changed: 761 additions & 94 deletions

File tree

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
"author": "",
1919
"license": "ISC",
2020
"devDependencies": {
21-
"css-minimizer-webpack-plugin": "^3.0.0",
2221
"copy-webpack-plugin": "^8.0.0",
2322
"css-loader": "^5.0.0",
23+
"css-minimizer-webpack-plugin": "^3.0.0",
2424
"eslint": "^7.0.0",
2525
"html-loader": "^2.0.0",
2626
"html-webpack-plugin": "^5.0.0",
@@ -37,6 +37,7 @@
3737
"handsontable": "7.2.2",
3838
"jexcel": "^3.9.1",
3939
"jquery-ui": "1.10.4",
40+
"select2": "^4.1.0-rc.0",
4041
"sql.js": "1.5.0",
4142
"vega-embed": "3.14.0",
4243
"wavedrom": "^2.0.0"

runestone/__init__.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,22 @@
55

66
from .activecode import ActiveCode
77
from .animation import Animation
8-
from .mchoice import MChoice, QuestionNumber
98
from .blockly import Blockly
10-
from .quizly import Quizly
11-
from .khanex import Khanex
129
from .codelens import Codelens
1310
from .clickableArea import ClickableArea
1411
from .datafile import DataFile
1512
from .disqus import DisqusDirective
1613
from .dragndrop import DragNDrop
1714
from .fitb import FillInTheBlank
15+
from .groupsub import GroupSubmission
16+
from .khanex import Khanex
1817
from .selectquestion import SelectQuestion
1918
from .matrixeq import MatrixEq
19+
from .mchoice import MChoice, QuestionNumber
2020
from .meta import Meta
2121
from .parsons import ParsonsProblem
2222
from .poll import Poll
23+
from .quizly import Quizly
2324
from .reveal import RevealDirective
2425
from .shortanswer import JournalDirective
2526
from .showeval import ShowEval
@@ -146,8 +147,8 @@ def setup(app):
146147
try:
147148
for c in setup.custom_js_files:
148149
if isinstance(c, dict):
149-
#peel off filename, pass rest of key/values on as kwargs
150-
filename = c.pop("file")
150+
# peel off filename, pass rest of key/values on as kwargs
151+
filename = c.pop("file")
151152
app.add_autoversioned_javascript(filename, **c)
152153
else:
153154
app.add_autoversioned_javascript(c)
@@ -244,6 +245,7 @@ def build(options):
244245
"datafile": DataFile,
245246
"disqus": DisqusDirective,
246247
"dragndrop": DragNDrop,
248+
"groupsub": GroupSubmission,
247249
"parsonsprob": ParsonsProblem,
248250
"poll": Poll,
249251
"quizly": Quizly,

runestone/activecode/js/activecode.js

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,8 @@ export class ActiveCode extends RunestoneBase {
476476
if (!didAgree) {
477477
didAgree = confirm(
478478
"Pair Programming should only be used with the consent of your instructor." +
479-
"Your partner must be a registered member of the class and have agreed to pair with you." +
480-
"By clicking OK you certify that both of these conditions have been met."
479+
"Your partner must be a registered member of the class and have agreed to pair with you." +
480+
"By clicking OK you certify that both of these conditions have been met."
481481
);
482482
if (didAgree) {
483483
localStorage.setItem("partnerAgree", "true");
@@ -520,13 +520,13 @@ export class ActiveCode extends RunestoneBase {
520520
$(butt).attr(
521521
"href",
522522
"http://" +
523-
chatcodesServer +
524-
"/new?" +
525-
$.param({
526-
topic: window.location.host + "-" + this.divid,
527-
code: this.editor.getValue(),
528-
lang: "Python",
529-
})
523+
chatcodesServer +
524+
"/new?" +
525+
$.param({
526+
topic: window.location.host + "-" + this.divid,
527+
code: this.editor.getValue(),
528+
lang: "Python",
529+
})
530530
);
531531
this.chatButton = butt;
532532
chatBar.appendChild(butt);
@@ -913,7 +913,7 @@ export class ActiveCode extends RunestoneBase {
913913
});
914914
}
915915

916-
toggleEditorVisibility() {}
916+
toggleEditorVisibility() { }
917917

918918
addErrorMessage(err) {
919919
// Add the error message
@@ -1051,7 +1051,7 @@ Yet another is that there is an internal error. The internal error message is:
10511051
var xl = eval(x);
10521052
xl = xl.map(pyStr);
10531053
x = xl.join(" ");
1054-
} catch (err) {}
1054+
} catch (err) { }
10551055
}
10561056
}
10571057
$(this.output).css("visibility", "visible");
@@ -1155,7 +1155,7 @@ Yet another is that there is an internal error. The internal error message is:
11551155
if (
11561156
this.historyScrubber &&
11571157
this.history[$(this.historyScrubber).slider("value")] !=
1158-
this.editor.getValue()
1158+
this.editor.getValue()
11591159
) {
11601160
saveCode = "True";
11611161
this.history.push(this.editor.getValue());
@@ -1188,8 +1188,9 @@ Yet another is that there is an internal error. The internal error message is:
11881188
}
11891189
}
11901190

1191-
logCurrentAnswer() {
1192-
this.logRunEvent({
1191+
// the sid parameter is optional and is used for group submissions
1192+
async logCurrentAnswer(sid) {
1193+
let data = {
11931194
div_id: this.divid,
11941195
code: this.editor.getValue(),
11951196
lang: this.language,
@@ -1198,14 +1199,22 @@ Yet another is that there is an internal error. The internal error message is:
11981199
prefix: this.pretext,
11991200
suffix: this.suffix,
12001201
partner: this.partner,
1201-
}); // Log the run event
1202+
}; // Log the run event
1203+
if (typeof sid !== "undefined") {
1204+
data.sid = sid;
1205+
}
1206+
await this.logRunEvent(data);
12021207
// If unit tests were run there will be a unit_results
12031208
if (this.unit_results) {
1204-
this.logBookEvent({
1209+
let unitData = {
12051210
act: this.unit_results,
12061211
div_id: this.divid,
12071212
event: "unittest",
1208-
});
1213+
};
1214+
if (typeof sid !== "undefined") {
1215+
unitData.sid = sid;
1216+
}
1217+
await this.logBookEvent(unitData)
12091218
}
12101219
}
12111220

runestone/activecode/js/activecode_sql.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,8 @@ export default class SQLActiveCode extends ActiveCode {
233233
return Promise.resolve("done");
234234
}
235235

236-
logCurrentAnswer() {
237-
this.logRunEvent({
236+
async logCurrentAnswer(sid) {
237+
let data = {
238238
div_id: this.divid,
239239
code: this.editor.getValue(),
240240
lang: this.language,
@@ -243,15 +243,23 @@ export default class SQLActiveCode extends ActiveCode {
243243
prefix: this.pretext,
244244
suffix: this.suffix,
245245
partner: this.partner,
246-
}); // Log the run event
246+
}; // Log the run event
247+
if (typeof sid !== "undefined") {
248+
data.sid = sid;
249+
}
250+
await this.logRunEvent(data);
247251

248252
if (this.unit_results) {
249-
this.logBookEvent({
253+
let unitData = {
250254
event: "unittest",
251255
div_id: this.divid,
252256
course: eBookConfig.course,
253257
act: this.unit_results,
254-
});
258+
};
259+
if (typeof sid !== "undefined") {
260+
unitData.sid = sid;
261+
}
262+
await this.logBookEvent(unitData);
255263
}
256264
}
257265

@@ -291,9 +299,8 @@ export default class SQLActiveCode extends ActiveCode {
291299
}
292300
let pct = (100 * this.passed) / (this.passed + this.failed);
293301
pct = pct.toLocaleString(undefined, { maximumFractionDigits: 2 });
294-
result += `You passed ${this.passed} out of ${
295-
this.passed + this.failed
296-
} tests for ${pct}%`;
302+
result += `You passed ${this.passed} out of ${this.passed + this.failed
303+
} tests for ${pct}%`;
297304
this.unit_results = `percent:${pct}:passed:${this.passed}:failed:${this.failed}`;
298305
return result;
299306
}

runestone/clickableArea/js/clickable.js

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ export default class ClickableArea extends RunestoneBase {
276276
if (
277277
this.ccIndex < this.ccArray.length &&
278278
this.ccCounter ===
279-
Math.floor(this.ccArray[this.ccIndex].split(",")[0]) &&
279+
Math.floor(this.ccArray[this.ccIndex].split(",")[0]) &&
280280
Math.floor(this.ccArray[this.ccIndex].split(",")[1]) === 0
281281
) {
282282
this.manageNewClickable(tComponentArr[t].children[i]);
@@ -285,7 +285,7 @@ export default class ClickableArea extends RunestoneBase {
285285
} else if (
286286
this.ciIndex < this.ciArray.length &&
287287
this.ccCounter ===
288-
Math.floor(this.ciArray[this.ciIndex].split(",")[0]) &&
288+
Math.floor(this.ciArray[this.ciIndex].split(",")[0]) &&
289289
Math.floor(this.ciArray[this.ciIndex].split(",")[1]) === 0
290290
) {
291291
this.manageNewClickable(tComponentArr[t].children[i]);
@@ -302,13 +302,13 @@ export default class ClickableArea extends RunestoneBase {
302302
if (
303303
this.ccIndex < this.ccArray.length &&
304304
tmp ===
305-
Math.floor(
306-
this.ccArray[this.ccIndex].split(",")[1]
307-
) &&
305+
Math.floor(
306+
this.ccArray[this.ccIndex].split(",")[1]
307+
) &&
308308
this.ccCounter ===
309-
Math.floor(
310-
this.ccArray[this.ccIndex].split(",")[0]
311-
)
309+
Math.floor(
310+
this.ccArray[this.ccIndex].split(",")[0]
311+
)
312312
) {
313313
this.manageNewClickable(
314314
tComponentArr[t].children[i].children[j]
@@ -320,13 +320,13 @@ export default class ClickableArea extends RunestoneBase {
320320
} else if (
321321
this.ciIndex < this.ciArray.length &&
322322
tmp ===
323-
Math.floor(
324-
this.ciArray[this.ciIndex].split(",")[1]
325-
) &&
323+
Math.floor(
324+
this.ciArray[this.ciIndex].split(",")[1]
325+
) &&
326326
this.ccCounter ===
327-
Math.floor(
328-
this.ciArray[this.ciIndex].split(",")[0]
329-
)
327+
Math.floor(
328+
this.ciArray[this.ciIndex].split(",")[0]
329+
)
330330
) {
331331
this.manageNewClickable(
332332
tComponentArr[t].children[i].children[j]
@@ -399,13 +399,17 @@ export default class ClickableArea extends RunestoneBase {
399399
this.setLocalStorage({ correct: this.correct ? "T" : "F" });
400400
}
401401

402-
logCurrentAnswer() {
403-
this.logBookEvent({
402+
async logCurrentAnswer(sid) {
403+
let data = {
404404
event: "clickableArea",
405405
act: this.givenIndexArray.join(";"),
406406
div_id: this.divid,
407407
correct: this.correct ? "T" : "F",
408-
});
408+
};
409+
if (typeof sid !== "undefined") {
410+
data.sid = sid;
411+
}
412+
await this.logBookEvent(data);
409413
}
410414

411415
renderFeedback() {
@@ -424,15 +428,15 @@ export default class ClickableArea extends RunestoneBase {
424428
}
425429
$(this.feedBackDiv).html(
426430
"Incorrect. You clicked on " +
427-
this.correctNum +
428-
" of the " +
429-
this.correctArray.length.toString() +
430-
" correct elements and " +
431-
this.incorrectNum +
432-
" of the " +
433-
this.incorrectArray.length.toString() +
434-
" incorrect elements. " +
435-
this.feedback
431+
this.correctNum +
432+
" of the " +
433+
this.correctArray.length.toString() +
434+
" correct elements and " +
435+
this.incorrectNum +
436+
" of the " +
437+
this.incorrectArray.length.toString() +
438+
" incorrect elements. " +
439+
this.feedback
436440
);
437441
$(this.feedBackDiv).attr("class", "alert alert-danger");
438442
}

runestone/common/js/runestonebase.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ export default class RunestoneBase {
2222
constructor(opts) {
2323
this.component_ready_promise = new Promise(resolve => this._component_ready_resolve_fn = resolve)
2424
this.optional = false;
25+
if (typeof window.allComponents === "undefined") {
26+
window.allComponents = [];
27+
}
28+
window.allComponents.push(this);
2529
if (opts) {
2630
this.sid = opts.sid;
2731
this.graderactive = opts.graderactive;
@@ -343,6 +347,11 @@ export default class RunestoneBase {
343347
"Each component should provide an implementation of disableInteraction"
344348
);
345349
}
350+
351+
toString() {
352+
return `${this.constructor.name}: ${this.divid}`
353+
}
354+
346355
}
347356

348357
window.RunestoneBase = RunestoneBase;

0 commit comments

Comments
 (0)