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

Commit 22492d2

Browse files
committed
✨ Allow radomizing blocks
1 parent 21c9090 commit 22492d2

File tree

6 files changed

+94
-374
lines changed

6 files changed

+94
-374
lines changed

runestone/hparsons/css/hparsons.css

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,43 @@
1717
padding-top: 10px;
1818
margin: 5px;
1919
}
20+
21+
.hp_actions {
22+
text-align: center;
23+
}
24+
25+
.hp_output {
26+
display: none;
27+
max-width: 450px;
28+
background-color: inherit;
29+
}
30+
.hp_output pre {
31+
background-color: lightgray;
32+
}
33+
34+
.hp_sql_result {
35+
background-color: lightgrey;
36+
padding: 10px;
37+
border-radius: 6px;
38+
margin-bottom: 10px;
39+
}
40+
41+
.hp_sql_result_success {
42+
background-color: transparent;
43+
color: green;
44+
border: 0px;
45+
padding: 0px;
46+
margin-top: 10px;
47+
margin-bottom: 10px;
48+
min-height: 0px !important;
49+
}
50+
51+
.hp_sql_result_failure {
52+
background-color: transparent;
53+
color: red;
54+
border: 0px;
55+
padding: 0px;
56+
margin-top: 10px;
57+
margin-bottom: 10px;
58+
min-height: 0px !important;
59+
}

runestone/hparsons/hparsons.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def setup(app):
5151
%(dburl)s
5252
%(textentry)s
5353
%(reuse)s
54+
%(randomize)s
5455
style="visibility: hidden;">
5556
%(initialsetting)s
5657
</textarea>
@@ -95,6 +96,7 @@ class HParsonsDirective(RunestoneIdDirective):
9596
.. hparsons:: uniqueid
9697
:language: sql, regex
9798
:dburl: only for sql -- url to load database
99+
:randomize: randomize the order of horizontal parsons
98100
TODO: fix textentry
99101
:reuse: only for parsons -- make the blocks reusable
100102
:textentry: if you will use text entry instead of horizontal parsons
@@ -124,6 +126,7 @@ class HParsonsDirective(RunestoneIdDirective):
124126
"language": directives.unchanged,
125127
"textentry": directives.flag,
126128
"reuse": directives.flag,
129+
"randomize": directives.flag,
127130
}
128131
)
129132

@@ -142,6 +145,11 @@ def run(self):
142145
else:
143146
self.options['reuse'] = ''
144147

148+
if "randomize" in self.options:
149+
self.options['randomize'] = ' data-randomize="true"'
150+
else:
151+
self.options['randomize'] = ''
152+
145153
explain_text = None
146154
if self.content:
147155
if "~~~~" in self.content:

runestone/hparsons/js/horizontal-parsons.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,7 +3044,8 @@ class ParsonsInput {
30443044
parentElement;
30453045
_prevPosition;
30463046
reusable;
3047-
constructor(parentElement, reusable) {
3047+
randomize;
3048+
constructor(parentElement, reusable, randomize) {
30483049
this.el = document.createElement('div');
30493050
this.parentElement = parentElement;
30503051
this.el.id = 'regextool-' + this.parentElement.toolNumber + '-parsons-input';
@@ -3066,6 +3067,7 @@ class ParsonsInput {
30663067
this.expandableBlocks = [];
30673068
this.expandableBlockTooltips = null;
30683069
this.reusable = reusable;
3070+
this.randomize = randomize;
30693071
this._dragSortable = new Sortable(this._dragArea, {
30703072
group: 'shared',
30713073
direction: 'horizontal',
@@ -3093,6 +3095,15 @@ class ParsonsInput {
30933095
return ret;
30943096
}
30953097
};
3098+
// Durstenfeld shuffle
3099+
shuffleArray(array) {
3100+
for (let i = array.length - 1; i > 0; i--) {
3101+
let j = Math.floor(Math.random() * (i + 1));
3102+
let temp = array[i];
3103+
array[i] = array[j];
3104+
array[j] = temp;
3105+
}
3106+
}
30963107
setSourceBlocks = (data, tooltips) => {
30973108
// reset
30983109
// this._dragSortable.destroy();
@@ -3101,6 +3112,13 @@ class ParsonsInput {
31013112
this._dragArea.innerHTML = '';
31023113
this._dropArea.innerHTML = '';
31033114
// adding normal blocks
3115+
if (this.randomize) {
3116+
let originalData = JSON.stringify(data);
3117+
this.shuffleArray(data);
3118+
while (JSON.stringify(data) == originalData) {
3119+
this.shuffleArray(data);
3120+
}
3121+
}
31043122
for (let i = 0; i < data.length; ++i) {
31053123
const newBlock = document.createElement('div');
31063124
this._dragArea.appendChild(newBlock);
@@ -15414,7 +15432,8 @@ class HParsonsElement extends HTMLElement {
1541415432
this.inputDiv.classList.add('hparsons-input');
1541515433
this.root.append(this.inputDiv);
1541615434
const reusable = this.getAttribute('reuse-blocks') ? true : false;
15417-
this.hparsonsInput = new ParsonsInput(this, reusable);
15435+
const randomize = this.getAttribute('randomize') ? true : false;
15436+
this.hparsonsInput = new ParsonsInput(this, reusable, randomize);
1541815437
// console.log(reusable)
1541915438
// a div wrapping the input and the test case status
1542015439
// init regex input based on the input type
@@ -15500,7 +15519,8 @@ class HParsonsElement extends HTMLElement {
1550015519
if (this.inputType == 'parsons') {
1550115520
// init elements: parsons regex input
1550215521
const reusable = this.getAttribute('reuse-blocks') != null ? true : false;
15503-
this.hparsonsInput = new ParsonsInput(this, reusable);
15522+
const randomize = this.getAttribute('randomize') != null ? true : false;
15523+
this.hparsonsInput = new ParsonsInput(this, reusable, randomize);
1550415524
this.inputDiv.appendChild(this.hparsonsInput.el);
1550515525
}
1550615526
else {

runestone/hparsons/js/hparsons-sql.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Handsontable from "handsontable";
33
import initSqlJs from "sql.js/dist/sql-wasm.js";
44
import RunestoneBase from "../../common/js/runestonebase.js";
55
import "../css/hparsons.css";
6+
import 'handsontable/dist/handsontable.full.css';
67

78
var allDburls = {};
89

@@ -21,6 +22,7 @@ export default class SQLHParons extends RunestoneBase {
2122
var orig = $(opts.orig).find("textarea")[0];
2223
this.textentry = $(orig).data('textentry') ? true : false;
2324
this.reuse = $(orig).data('reuse') ? true : false;
25+
this.randomize = $(orig).data('randomize') ? true : false;
2426
this.divid = opts.orig.id;
2527
this.containerDiv = opts.orig;
2628
this.useRunestoneServices = opts.useRunestoneServices;
@@ -51,7 +53,7 @@ export default class SQLHParons extends RunestoneBase {
5153
if ($(orig).data("caption")) {
5254
this.caption = $(orig).data("caption");
5355
} else {
54-
this.caption = "ActiveCode";
56+
this.caption = "HorizontalParsons";
5557
}
5658
this.addCaption("runestone");
5759
this.indicate_component_ready();
@@ -151,6 +153,9 @@ export default class SQLHParons extends RunestoneBase {
151153
if (this.reuse) {
152154
parsonsHTML += ` reuse-blocks="true"`;
153155
}
156+
if (this.randomize) {
157+
parsonsHTML += ` randomize="true"`;
158+
}
154159
parsonsHTML += `>`
155160
this.outerDiv.innerHTML = parsonsHTML;
156161
this.outerDiv.addEventListener('horizontal-parsons', (ev) => {this.logHorizontalParsonsEvent(ev.detail)})
@@ -172,7 +177,7 @@ export default class SQLHParons extends RunestoneBase {
172177
// Create a parent div with two elements: pre for standard output and a div
173178
// to hold turtle graphics output. We use a div in case the turtle changes from
174179
var outDiv = document.createElement("div");
175-
$(outDiv).addClass("ac_output col-md-12");
180+
$(outDiv).addClass("hp_output col-md-12");
176181
this.outDiv = outDiv;
177182
this.output = document.createElement("pre");
178183
this.output.id = this.divid + "_stdout";
@@ -191,11 +196,11 @@ export default class SQLHParons extends RunestoneBase {
191196
createControls() {
192197
var ctrlDiv = document.createElement("div");
193198
var butt;
194-
$(ctrlDiv).addClass("ac_actions");
199+
$(ctrlDiv).addClass("hp_actions");
195200
$(ctrlDiv).addClass("col-md-12");
196201
// Run
197202
butt = document.createElement("button");
198-
$(butt).text($.i18n("msg_activecode_run_code"));
203+
$(butt).text("Run");
199204
$(butt).addClass("btn btn-success run-button");
200205
ctrlDiv.appendChild(butt);
201206
this.runButton = butt;
@@ -300,7 +305,7 @@ export default class SQLHParons extends RunestoneBase {
300305
let resultArray = this.results;
301306
for (let r of resultArray) {
302307
let section = document.createElement("div");
303-
section.setAttribute("class", "ac_sql_result");
308+
section.setAttribute("class", "hp_sql_result");
304309
respDiv.appendChild(section);
305310
if (r.status === "success") {
306311
if (r.columns) {
@@ -317,26 +322,26 @@ export default class SQLHParons extends RunestoneBase {
317322
}
318323
msg = msg + ".";
319324
messageBox.textContent = msg;
320-
messageBox.setAttribute("class", "ac_sql_result_success");
325+
messageBox.setAttribute("class", "hp_sql_result_success");
321326
section.appendChild(messageBox);
322327
} else if (r.rowcount) {
323328
let messageBox = document.createElement("pre");
324329
let op = r.operation;
325330
op = op + (op.charAt(op.length - 1) === "e" ? "d." : "ed.");
326331
let rmsg = r.rowcount !== 1 ? " rows " : " row ";
327332
messageBox.textContent = "" + r.rowcount + rmsg + op;
328-
messageBox.setAttribute("class", "ac_sql_result_success");
333+
messageBox.setAttribute("class", "hp_sql_result_success");
329334
section.appendChild(messageBox);
330335
} else {
331336
let messageBox = document.createElement("pre");
332337
messageBox.textContent = "Operation succeeded.";
333-
messageBox.setAttribute("class", "ac_sql_result_success");
338+
messageBox.setAttribute("class", "hp_sql_result_success");
334339
section.appendChild(messageBox);
335340
}
336341
} else {
337342
let messageBox = document.createElement("pre");
338343
messageBox.textContent = r.message;
339-
messageBox.setAttribute("class", "ac_sql_result_failure");
344+
messageBox.setAttribute("class", "hp_sql_result_failure");
340345
section.appendChild(messageBox);
341346
}
342347
}

0 commit comments

Comments
 (0)