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

Commit e26c923

Browse files
authored
Merge pull request #1381 from amy21206/grading
Add grading logs for horizontal Parsons (micro Parsons) problems.
2 parents f5d45dc + 330f54e commit e26c923

File tree

10 files changed

+97
-67
lines changed

10 files changed

+97
-67
lines changed

package-lock.json

Lines changed: 42 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,8 +18,8 @@
1818
"author": "",
1919
"license": "ISC",
2020
"devDependencies": {
21-
"copy-webpack-plugin": "^9.0.0",
2221
"compression-webpack-plugin": "^9.0.0",
22+
"copy-webpack-plugin": "^9.0.0",
2323
"css-loader": "^6.0.0",
2424
"css-minimizer-webpack-plugin": "^3.0.0",
2525
"html-loader": "^3.0.0",
@@ -36,6 +36,7 @@
3636
"handsontable": "7.2.2",
3737
"jexcel": "^3.9.1",
3838
"jquery-ui": "1.10.4",
39+
"micro-parsons": "https://github.com/amy21206/micro-parsons-element/releases/download/v0.1.3/micro-parsons-0.1.3.tgz",
3940
"select2": "^4.1.0-rc.0",
4041
"sql.js": "1.5.0",
4142
"vega-embed": "3.14.0",

runestone/hparsons/js/BlockFeedback.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,25 @@ export default class BlockFeedback extends HParsonsFeedback {
3030
// Called when check button clicked (block-based Feedback)
3131
async runButtonHandler() {
3232
this.checkCurrentAnswer();
33+
this.logCurrentAnswer();
3334
this.renderFeedback();
3435
}
3536

37+
async logCurrentAnswer() {
38+
let act = {
39+
scheme: "block",
40+
correct: this.grader.graderState == 'correct' ? "T" : "F",
41+
answer: this.hparsons.hparsonsInput.getParsonsTextArray(),
42+
percent: this.grader.percent
43+
}
44+
let logData = {
45+
event: "hparsonsAnswer",
46+
div_id: this.hparsons.divid,
47+
act: act
48+
}
49+
await this.hparsons.logBookEvent(logData);
50+
}
51+
3652
// Used for block-based feedback
3753
checkCurrentAnswer() {
3854
if (!this.solved) {

runestone/hparsons/js/SQLFeedback.js

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -272,34 +272,20 @@ export default class SQLFeedback extends HParsonsFeedback {
272272
}
273273

274274
// copied from activecode-sql
275-
async logCurrentAnswer(sid) {
276-
// commenting these out for now
277-
// Not sure if we need to log run event in horizontal parsons
278-
// let data = {
279-
// div_id: this.hparsons.divid,
280-
// code: this.hparsons.hparsonsInput.getParsonsTextArray(),
281-
// language: "sql",
282-
// // errinfo: this.results[this.results.length - 1].status,
283-
// to_save: this.hparsons.saveCode,
284-
// prefix: this.hparsons.pretext,
285-
// suffix: this.hparsons.suffix,
286-
// }; // Log the run event
287-
// if (typeof sid !== "undefined") {
288-
// data.sid = sid;
289-
// }
290-
// await this.hparsons.logRunEvent(data);
291-
275+
async logCurrentAnswer() {
292276
if (this.unit_results) {
293-
let unitData = {
294-
event: "unittest",
277+
let act = {
278+
scheme: "execution",
279+
correct: (this.failed === 0 && this.percent != null) ? "T" : "F",
280+
answer: this.hparsons.hparsonsInput.getParsonsTextArray(),
281+
percent: this.percent // percent is null if there is execution error
282+
}
283+
let logData = {
284+
event: "hparsonsAnswer",
295285
div_id: this.hparsons.divid,
296-
course: eBookConfig.course,
297-
act: this.unit_results,
298-
};
299-
if (typeof sid !== "undefined") {
300-
unitData.sid = sid;
286+
act: act
301287
}
302-
await this.hparsons.logBookEvent(unitData);
288+
await this.hparsons.logBookEvent(logData);
303289
}
304290
}
305291

@@ -332,6 +318,7 @@ export default class SQLFeedback extends HParsonsFeedback {
332318
result += "\n";
333319
}
334320
let pct = (100 * this.passed) / (this.passed + this.failed);
321+
this.percent = pct;
335322
pct = pct.toLocaleString(undefined, { maximumFractionDigits: 2 });
336323
result += `You passed ${this.passed} out of ${this.passed + this.failed
337324
} tests for ${pct}%`;

runestone/hparsons/js/blockGrader.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
export default class BlockBasedGrader {
77
constructor(problem) {
88
this.problem = problem;
9+
this.percent = 0;
910
}
1011
// Use a LIS (Longest Increasing Subsequence) algorithm to return the indexes
1112
// that are not part of that subsequence.
Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
// import 'handsontable/dist/handsontable.full.css';
21
import RunestoneBase from "../../common/js/runestonebase.js";
32
import "../css/hparsons.css";
43
import "../css/hljs-xcode.css";
54
import BlockFeedback from "./BlockFeedback.js";
65
import SQLFeedback from "./SQLFeedback.js";
6+
import {InitMicroParsons} from 'micro-parsons/micro-parsons/micro-parsons.js';
7+
import 'micro-parsons/micro-parsons/micro-parsons.css';
78

89
export var hpList;
910
// Dictionary that contains all instances of horizontal Parsons problem objects
1011
if (hpList === undefined) hpList = {};
1112

12-
// The following js library is a custom element for micro parsons (horizontal parsons) input.
13-
// Currently it is not published as an npm package yet, and edits should be made through: https://github.com/amy21206/micro-parsons-element.
14-
// It will be replaced by importing the corresponding package in the future.
15-
import "./micro-parsons.js";
1613

17-
export default class SQLHParsons extends RunestoneBase {
14+
export default class HParsons extends RunestoneBase {
1815
constructor(opts) {
1916
super(opts);
2017
// copied from activecode
@@ -67,7 +64,7 @@ export default class SQLHParsons extends RunestoneBase {
6764
if ($(orig).data("caption")) {
6865
this.caption = $(orig).data("caption");
6966
} else {
70-
this.caption = "HorizontalParsons";
67+
this.caption = "MicroParsons";
7168
}
7269
this.addCaption("runestone");
7370
this.indicate_component_ready();
@@ -78,22 +75,9 @@ export default class SQLHParsons extends RunestoneBase {
7875

7976
// copied from activecode, already modified to add parsons
8077
createEditor() {
81-
// console.log('test create editor hparsons')
8278
this.outerDiv = document.createElement("div");
8379
$(this.origElem).replaceWith(this.outerDiv);
84-
let parsonsHTML = `<micro-parsons id='${this.divid}-hparsons'`;
85-
parsonsHTML += ` input-type='parsons' `;
86-
if (this.reuse) {
87-
parsonsHTML += ` reuse-blocks="true"`;
88-
}
89-
if (this.randomize) {
90-
parsonsHTML += ` randomize="true"`;
91-
}
92-
if (this.language) {
93-
parsonsHTML += ` language="` + this.language + `"`;
94-
}
95-
parsonsHTML += `>`;
96-
this.outerDiv.innerHTML = parsonsHTML;
80+
this.outerDiv.id = `${this.divid}-container`;
9781
this.outerDiv.addEventListener("micro-parsons", (ev) => {
9882
this.logHorizontalParsonsEvent(ev.detail);
9983
this.feedbackController.clearFeedback();
@@ -109,9 +93,17 @@ export default class SQLHParsons extends RunestoneBase {
10993
: blocksString;
11094
blocks = blocksString.split("\n");
11195
}
112-
this.hparsonsInput = $(this.outerDiv).find("micro-parsons")[0];
11396
this.originalBlocks = blocks.slice(1, -1);
114-
this.hparsonsInput.parsonsData = blocks.slice(1, -1);
97+
const props = {
98+
selector: `#${this.divid}-container`,
99+
id: `${this.divid}-hparsons`,
100+
reuse: this.reuse,
101+
randomize: this.randomize,
102+
parsonsBlocks: blocks.slice(1, -1),
103+
language: this.language
104+
}
105+
InitMicroParsons(props);
106+
this.hparsonsInput = $(this.outerDiv).find("micro-parsons")[0];
115107
}
116108

117109
createOutput() {
@@ -152,8 +144,6 @@ export default class SQLHParsons extends RunestoneBase {
152144
}
153145

154146
logHorizontalParsonsEvent(hparsonsEvent) {
155-
// TODO: might need to find another way to change "act".
156-
// The event string is probably too long.
157147
let ev = {
158148
event: "hparsons",
159149
div_id: this.divid,
@@ -173,7 +163,7 @@ $(document).on("runestone:login-complete", function () {
173163
if ($(this).closest("[data-component=timedAssessment]").length == 0) {
174164
// If this element exists within a timed component, don't render it here
175165
// try {
176-
hpList[this.id] = new SQLHParsons({
166+
hpList[this.id] = new HParsons({
177167
orig: this,
178168
useRunestoneServices: eBookConfig.useRunestoneServices,
179169
});
@@ -189,5 +179,5 @@ if (typeof window.component_factory === "undefined") {
189179
window.component_factory = {};
190180
}
191181
window.component_factory["hparsons"] = function (opts) {
192-
return new SQLHParsons(opts);
182+
return new HParsons(opts);
193183
};

runestone/hparsons/js/hparsonsFeedback.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export default class HParsonsFeedback {
22
constructor(hparsons) {
33
this.hparsons = hparsons;
4+
this.percent = 0;
45
}
56
createOutput() {
67
console.log('createOutput method not implemented in feedback!');

runestone/hparsons/js/micro-parsons.js

Lines changed: 0 additions & 8 deletions
This file was deleted.

runestone/hparsons/test/test_hparsons.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def click_control(hp_question, button_name):
3838
def test_run_block(selenium_utils_get):
3939
div_id = "test_hparsons_block_1"
4040
hp_question = find_hp_question(selenium_utils_get, div_id)
41-
hp = hp_question.find_element(By.CSS_SELECTOR, 'horizontal-parsons')
41+
hp = hp_question.find_element(By.CSS_SELECTOR, 'micro-parsons')
4242
drag_area = hp.find_element(By.CSS_SELECTOR, '.drag-area')
4343
drop_area = hp.find_element(By.CSS_SELECTOR, '.drop-area')
4444
run_btn = hp_question.find_elements(By.TAG_NAME, 'button')[0]
@@ -106,7 +106,7 @@ def test_run_block(selenium_utils_get):
106106
def test_randomize_block(selenium_utils_get):
107107
div_id = "test_hparsons_sql_1"
108108
hp = find_hp_question(selenium_utils_get, div_id).find_element(
109-
By.CSS_SELECTOR, 'horizontal-parsons')
109+
By.CSS_SELECTOR, 'micro-parsons')
110110
original_sequence = ['SELECT', '*', 'FROM', 'test']
111111
randomized_sequence = []
112112
for block in hp.find_element(By.CSS_SELECTOR, '.drag-area').find_elements(By.CSS_SELECTOR, '.parsons-block'):
@@ -134,7 +134,7 @@ def test_randomize_block(selenium_utils_get):
134134
def test_add_and_remove_blocks(selenium_utils_get):
135135
div_id = "test_hparsons_sql_1"
136136
hp = find_hp_question(selenium_utils_get, div_id).find_element(
137-
By.CSS_SELECTOR, 'horizontal-parsons')
137+
By.CSS_SELECTOR, 'micro-parsons')
138138
drag_area = hp.find_element(By.CSS_SELECTOR, '.drag-area')
139139
drop_area = hp.find_element(By.CSS_SELECTOR, '.drop-area')
140140

@@ -154,7 +154,7 @@ def test_add_and_remove_blocks(selenium_utils_get):
154154
# For reusable blocks
155155
div_id = "test_hparsons_sql_2"
156156
hp = find_hp_question(selenium_utils_get, div_id).find_element(
157-
By.CSS_SELECTOR, 'horizontal-parsons')
157+
By.CSS_SELECTOR, 'micro-parsons')
158158
drag_area = hp.find_element(By.CSS_SELECTOR, '.drag-area')
159159
drop_area = hp.find_element(By.CSS_SELECTOR, '.drop-area')
160160

@@ -184,7 +184,7 @@ def test_run_SQL(selenium_utils_get):
184184
div_id = "test_hparsons_sql_2"
185185
hp_question = find_hp_question(selenium_utils_get, div_id)
186186
time.sleep(2)
187-
hp = hp_question.find_element(By.CSS_SELECTOR, 'horizontal-parsons')
187+
hp = hp_question.find_element(By.CSS_SELECTOR, 'micro-parsons')
188188
drag_area = hp.find_element(By.CSS_SELECTOR, '.drag-area')
189189
drop_area = hp.find_element(By.CSS_SELECTOR, '.drop-area')
190190

webpack.index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ const module_map = {
7070
khanex: () => import("./runestone/khanex/js/khanex.js"),
7171
lp_build: () => import("./runestone/lp/js/lp.js"),
7272
multiplechoice: () => import("./runestone/mchoice/js/timedmc.js"),
73-
hparsons: () => import("./runestone/hparsons/js/hparsons-sql.js"),
73+
hparsons: () => import("./runestone/hparsons/js/hparsons.js"),
7474
parsons: () => import("./runestone/parsons/js/timedparsons.js"),
7575
poll: () => import("./runestone/poll/js/poll.js"),
7676
quizly: () => import("./runestone/quizly/js/quizly.js"),

0 commit comments

Comments
 (0)