Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
414f989
:construction: Duplicated shortanswer as base for horizontal Parsons
zihan21206 Feb 10, 2022
81015a2
Merge branch 'RunestoneInteractive:master' into master
zihan21206 Feb 13, 2022
b160087
:construction: Adding horizontal parsons
zihan21206 Feb 15, 2022
5ac48b5
:tada: A working version of the tool!
zihan21206 Feb 16, 2022
e4a3e7c
:sparkles: A working version with multiple instances of hparsons
zihan21206 Feb 17, 2022
9777048
:sparkles: Specifying arguments for hparsons
zihan21206 Feb 18, 2022
b7cfe16
:sparkles: Fix hiding test cases
zihan21206 Feb 18, 2022
df7beb3
:bug: Fix unittest
zihan21206 Feb 18, 2022
5ae7af9
:sparkles: Allow saving previous student answer
zihan21206 Feb 20, 2022
99a60c7
:mute: Removing logs
zihan21206 Feb 22, 2022
88d03c2
:alembic: Experimenting to switch to SQL
zihan21206 Mar 2, 2022
8353958
:alembic: Migrating activecode-sql fully to hparsons
zihan21206 Mar 3, 2022
fa6d7d2
:fire: Removing code that is not useful for horizontal parsons + sql
zihan21206 Mar 4, 2022
68e3db1
:beers: Oh GOD now it is truly migrated
zihan21206 Mar 5, 2022
2138981
:construction: Merge with remote
zihan21206 Mar 7, 2022
243a528
:fire: Initial cleanup of unused attributes
zihan21206 Mar 7, 2022
60145ef
:sparkles: Initial demo version for hparsons - sql. -messy code warning-
zihan21206 Mar 7, 2022
9b939b3
:fire: Removing unused code for horizontal parsons sql.
zihan21206 Mar 9, 2022
0bdd7d2
:lipstick: Final fix for css
zihan21206 Mar 9, 2022
62a6adc
:sparkles: Allow adding blocks from ReST
zihan21206 Mar 9, 2022
b58cd79
:bulb: Adding todo for fixing text entry
zihan21206 Mar 9, 2022
41a951d
:sparkles: Finishing horizontal parsons problems with sql
zihan21206 Mar 19, 2022
cd1600c
Merge branch 'master' of https://github.com/RunestoneInteractive/Rune…
zihan21206 Mar 19, 2022
86e529c
Merge branch 'RunestoneInteractive-master' into hparsons-sql
zihan21206 Mar 19, 2022
eef9d87
Update package.json according to upstream
zihan21206 Mar 19, 2022
f82e939
:loud_sound: Add logs for moving horizontal parsons blocks.
zihan21206 Mar 19, 2022
34e653f
:sparkles: Allow reusing blocks in horizontal parsons
zihan21206 Mar 19, 2022
45ecaa5
Merge branch 'master' of github.com:RunestoneInteractive/RunestoneCom…
zihan21206 Mar 19, 2022
21c9090
:ok_hand: Update node according to new pr
zihan21206 Mar 19, 2022
22492d2
:sparkles: Allow radomizing blocks
zihan21206 Mar 20, 2022
97e8ddb
:sparkles: Allow click to add to a new block
zihan21206 Mar 21, 2022
9211c6e
:sparkles: Allow click to remove blocks
zihan21206 Mar 21, 2022
c7dda64
:sparkles: Allow resetting the input
zihan21206 Mar 21, 2022
ace7909
:sparkles: Allow checking for no data in unittest.
zihan21206 Mar 23, 2022
7496e7a
Merge branch 'RunestoneInteractive:master' into master
zihan21206 Mar 23, 2022
09c837d
Merge branch 'master' of github.com:amy21206/RunestoneComponents
zihan21206 Mar 24, 2022
d192101
Merge branch 'RunestoneInteractive:master' into master
zihan21206 Mar 24, 2022
37975b9
:white_check_mark: Adding unittest for horizontal parsons problems
zihan21206 Mar 25, 2022
519f86f
:white_check_mark: Adding tests to hparsons directive
zihan21206 Mar 28, 2022
8991af6
Merge branch 'RunestoneInteractive:master' into master
zihan21206 Mar 31, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,706 changes: 3,497 additions & 209 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@
"vega-embed": "3.14.0",
"wavedrom": "^2.0.0"
}
}
}
2 changes: 2 additions & 0 deletions runestone/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .dragndrop import DragNDrop
from .fitb import FillInTheBlank
from .groupsub import GroupSubmission
from .hparsons import HParsonsNode
from .khanex import Khanex
from .selectquestion import SelectQuestion
from .matrixeq import MatrixEq
Expand Down Expand Up @@ -246,6 +247,7 @@ def build(options):
"disqus": DisqusDirective,
"dragndrop": DragNDrop,
"groupsub": GroupSubmission,
"hparsons": HParsonsNode,
"parsonsprob": ParsonsProblem,
"poll": Poll,
"quizly": Quizly,
Expand Down
17 changes: 17 additions & 0 deletions runestone/hparsons/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<h2>Short Answer</h2>

```html
<p data-component="shortanswer" data-optional id="example1">What is the best thing about the color blue?</p>
```

The <code>p</code> tag represents the entire Short Answer component to be rendered.
(more info about the use)


Option spec:

<ul>
<li><code>data-component="shortanswer"</code> Identifies this as a Short Answer component</li>
<li><code>id</code> Must be unique in the document</li>
<li><code>data-optional</code> Makes this component optional for the student to answer--it isn't required.</li>
</ul>
1 change: 1 addition & 0 deletions runestone/hparsons/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .hparsons import *
59 changes: 59 additions & 0 deletions runestone/hparsons/css/hparsons.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
.hparsons_section {
position: relative;
margin-right: auto;
margin-left: auto;
max-width: 800px;
clear: both;
}

.hparsons_section > *:not(.hparsons_section) {
max-width: 500pt;
margin-left: auto;
margin-right: auto;
}

.hp_question {
padding-left: 10px;
padding-top: 10px;
margin: 5px;
}

.hp_actions {
text-align: center;
}

.hp_output {
display: none;
max-width: 450px;
background-color: inherit;
}
.hp_output pre {
background-color: lightgray;
}

.hp_sql_result {
background-color: lightgrey;
padding: 10px;
border-radius: 6px;
margin-bottom: 10px;
}

.hp_sql_result_success {
background-color: transparent;
color: green;
border: 0px;
padding: 0px;
margin-top: 10px;
margin-bottom: 10px;
min-height: 0px !important;
}

.hp_sql_result_failure {
background-color: transparent;
color: red;
border: 0px;
padding: 0px;
margin-top: 10px;
margin-bottom: 10px;
min-height: 0px !important;
}
226 changes: 226 additions & 0 deletions runestone/hparsons/hparsons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
# *********
# |docname|
# *********
# Copyright (C) 2011 Bradley N. Miller
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
__author__ = "bmiller"

from docutils import nodes
from docutils.parsers.rst import directives
from sqlalchemy import Table
from runestone.server.componentdb import (
addQuestionToDB,
addHTMLToDB,
get_engine_meta,
maybeAddToAssignment,
)
from runestone.common.runestonedirective import (
RunestoneIdDirective,
RunestoneIdNode,
)

def setup(app):
app.add_directive("hparsons", HParsonsDirective)
app.add_node(HParsonsNode, html=(visit_hp_html, depart_hp_html))


TEMPLATE_START = """
<div>
<div data-component="hparsons" id=%(divid)s data-question_label="%(question_label)s" class="alert alert-warning hparsons_section">
<div class="hp_question col-md-12">
"""

TEMPLATE_END = """
</div>
<div class='hparsons'></div>
<textarea data-lang="%(language)s"
%(optional)s
%(dburl)s
%(textentry)s
%(reuse)s
%(randomize)s
style="visibility: hidden;">
%(initialsetting)s
</textarea>
</div>
</div>
"""


class HParsonsNode(nodes.General, nodes.Element, RunestoneIdNode):
pass


# self for these functions is an instance of the writer class. For example
# in html, self is sphinx.writers.html.SmartyPantsHTMLTranslator
# The node that is passed as a parameter is an instance of our node class.
def visit_hp_html(self, node):

node["delimiter"] = "_start__{}_".format(node["runestone_options"]["divid"])

self.body.append(node["delimiter"])

res = TEMPLATE_START % node["runestone_options"]
self.body.append(res)


def depart_hp_html(self, node):
res = TEMPLATE_END % node["runestone_options"]
self.body.append(res)

addHTMLToDB(
node["runestone_options"]["divid"],
node["runestone_options"]["basecourse"],
"".join(self.body[self.body.index(node["delimiter"]) + 1 :]),
)

self.body.remove(node["delimiter"])


class HParsonsDirective(RunestoneIdDirective):
# only keep: language, autograde, dburl
"""
.. hparsons:: uniqueid
:language: sql, regex
:dburl: only for sql -- url to load database
:randomize: randomize the order of horizontal parsons
TODO: fix textentry
:reuse: only for parsons -- make the blocks reusable
:textentry: if you will use text entry instead of horizontal parsons

Here is the problem description. It must ends with the tildes.
Make sure you use the correct delimitier for each section below.
~~~~
--blocks--
block 1
block 2
--explanations--
explanations for block 1
explanations for block 2
--unittest--
assert 1,1 == world
assert 0,1 == hello
assert 2,1 == 42
"""

required_arguments = 1
optional_arguments = 1
has_content = True
option_spec = RunestoneIdDirective.option_spec.copy()
option_spec.update(
{
"dburl": directives.unchanged,
"language": directives.unchanged,
"textentry": directives.flag,
"reuse": directives.flag,
"randomize": directives.flag,
}
)

def run(self):
super(HParsonsDirective, self).run()

env = self.state.document.settings.env

if "textentry" in self.options:
self.options['textentry'] = ' data-textentry="true"'
else:
self.options['textentry'] = ''

if "reuse" in self.options:
self.options['reuse'] = ' data-reuse="true"'
else:
self.options['reuse'] = ''

if "randomize" in self.options:
self.options['randomize'] = ' data-randomize="true"'
else:
self.options['randomize'] = ''

explain_text = None
if self.content:
if "~~~~" in self.content:
idx = self.content.index("~~~~")
explain_text = self.content[:idx]
self.content = self.content[idx + 1 :]
source = "\n".join(self.content)
else:
source = "\n"

self.explain_text = explain_text or ["Not an Exercise"]
addQuestionToDB(self)

self.options["initialsetting"] = source

# TODO: change this
if "language" not in self.options:
self.options["language"] = "python"

# SQL Options
if "dburl" in self.options:
self.options["dburl"] = "data-dburl='{}'".format(self.options["dburl"])
else:
self.options["dburl"] = ""

course_name = env.config.html_context["course_id"]
divid = self.options["divid"]

engine, meta, sess = get_engine_meta()

if engine:
Source_code = Table(
"source_code", meta, autoload=True, autoload_with=engine
)
engine.execute(
Source_code.delete()
.where(Source_code.c.acid == divid)
.where(Source_code.c.course_id == course_name)
)
engine.execute(
Source_code.insert().values(
acid=divid,
course_id=course_name,
main_code=source,
suffix_code=suffix,
)
)
else:
if (
not hasattr(env, "dberr_activecode_reported")
or not env.dberr_activecode_reported
):
env.dberr_activecode_reported = True
print(
"Unable to save to source_code table in activecode.py. Possible problems:"
)
print(" 1. dburl or course_id are not set in conf.py for your book")
print(" 2. unable to connect to the database using dburl")
print("")
print(
"This should only affect the grading interface. Everything else should be fine."
)

hpnode = HParsonsNode()
hpnode["runestone_options"] = self.options
hpnode["source"], hpnode["line"] = self.state_machine.get_source_and_line(self.lineno)
self.add_name(hpnode) # make this divid available as a target for :ref:

maybeAddToAssignment(self)
if explain_text:
self.updateContent()
self.state.nested_parse(explain_text, self.content_offset, hpnode)

return [hpnode]
Loading