Skip to content

Commit

Permalink
Merge pull request #53 from ace-lab/39-require-answers-name-property
Browse files Browse the repository at this point in the history
Required answers-name, checks attribs
  • Loading branch information
SybelBlue authored Sep 24, 2024
2 parents 6b10c1e + 86956ea commit f6d1548
Showing 1 changed file with 32 additions and 40 deletions.
72 changes: 32 additions & 40 deletions pl-faded-parsons.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,8 @@ def read_file_lines(data, filename, error_if_not_found=True):
return False


def get_answers_name(element_html):
# use answers-name to namespace multiple pl-faded-parsons elements on a page
element = xml.fragment_fromstring(element_html)
return pl.get_string_attrib(element, 'answers-name', '')


def get_student_code(element_html, data):
answers_name = get_answers_name(element_html)
def get_student_code(element, data):
answers_name = pl.get_string_attrib(element, 'answers-name')
student_code = data['submitted_answers'].get(answers_name + 'student-parsons-solution', None)
return student_code

Expand Down Expand Up @@ -122,10 +116,9 @@ def base64_encode(s):
return base64.b64encode(s.encode("ascii")).decode("ascii")


def render_question_panel(element_html, data):
def render_question_panel(element, data):
"""Render the panel that displays the question (from code_lines.txt) and interaction boxes"""
element = xml.fragment_fromstring(element_html)
answers_name = get_answers_name(element_html)
answers_name = pl.get_string_attrib(element, 'answers-name')

format = pl.get_string_attrib(element, "format", "right").replace("-", '_')
if format not in ("bottom", "right", "no_code"):
Expand Down Expand Up @@ -179,15 +172,11 @@ def get_code_lines():
raw_lines = str(element.text)


starter_lines_data_available = 'starter-lines' in data['submitted_answers'] and \
data['submitted_answers']['starter-lines'] != []
submission_lines_data_available = 'submission-lines' in data['submitted_answers'] and \
data['submitted_answers']['submission-lines'] != []
starter_lines = data['submitted_answers'].get(answers_name + 'starter-lines', [])
submission_lines = data['submitted_answers'].get(answers_name + 'submission-lines', [])

if starter_lines_data_available or submission_lines_data_available:
start_lines = data['submitted_answers']['starter-lines'] if starter_lines_data_available else []
old_submission = data['submitted_answers']['submission-lines']
scrambled_lines, solution_lines = load_previous_state(lang, start_lines, old_submission)
if starter_lines or submission_lines:
scrambled_lines, solution_lines = load_previous_state(lang, starter_lines, submission_lines)
else:
starter_lines, given_lines = load_starter_and_given(raw_lines, lang)
scrambled_lines = starter_lines.copy()
Expand Down Expand Up @@ -218,27 +207,27 @@ def get_code_lines():
"scrambled" : scrambled,
})
html_params.update({
"answers-name": answers_name,
"given" : given,
"uuid": pl.get_uuid(),
"previous_log" : data['submitted_answers'].get('log', "[]")
"previous_log" : data['submitted_answers'].get(answers_name + 'log', "[]")
})

with open('pl-faded-parsons-question.mustache', 'r') as f:
return chevron.render(f, html_params).strip()


def render_submission_panel(element_html, data):
def render_submission_panel(element, data):
"""Show student what they submitted"""
html_params = {
'code': get_student_code(element_html, data),
'code': get_student_code(element, data),
}
with open('pl-faded-parsons-submission.mustache', 'r') as f:
return chevron.render(f, html_params).strip()


def render_answer_panel(element_html, data):
def render_answer_panel(element, data):
"""Show the instructor's reference solution"""
element = xml.fragment_fromstring(element_html)
path = pl.get_string_attrib(element, 'solution-path', './solution')
path = os.path.join(data["options"]["question_path"], path)

Expand All @@ -256,43 +245,46 @@ def render_answer_panel(element_html, data):
# Main functions
#
def render(element_html, data):
element = xml.fragment_fromstring(element_html)
pl.check_attribs(
element,
required_attribs=["answers-name"],
optional_attribs=["language", "format", "solution-path", "file-name"]
)
panel_type = data['panel']
if panel_type == 'question':
return render_question_panel(element_html, data)
return render_question_panel(element, data)
elif panel_type == 'submission':
return render_submission_panel(element_html, data)
return render_submission_panel(element, data)
elif panel_type == 'answer':
return render_answer_panel(element_html, data)
return render_answer_panel(element, data)
else:
raise Exception(f'Invalid panel type: {panel_type}')


def parse(element_html, data):
"""Parse student's submitted answer (HTML form submission)"""
# make an XML fragment that can be passed around to other PL functions,
# parsed/walked, etc

element = xml.fragment_fromstring(element_html)
format = pl.get_string_attrib(element, "format", "right").replace("-", '_')
answers_name = pl.get_string_attrib(element, 'answers-name')

def load_json_if_present(key: str, default=[]):
if key in data['raw_submitted_answers']:
return json.loads(data['raw_submitted_answers'][key])
return default

if format != "no_code":
starter_lines = load_json_if_present('starter-tray-order')
submission_lines = load_json_if_present('solution-tray-order')
starter_lines = load_json_if_present(answers_name + 'starter-tray-order')
submission_lines = load_json_if_present(answers_name + 'solution-tray-order')

submission_code = "\n".join([
line.get("content", "")
for line in submission_lines
]) + "\n"
submission_code = "\n".join(
line.get("content", "") for line in submission_lines
) + "\n"

data['submitted_answers']['student-parsons-solution'] = submission_code
data['submitted_answers'][answers_name + 'student-parsons-solution'] = submission_code
if format != "no_code":
data['submitted_answers']['starter-lines'] = starter_lines
data['submitted_answers']['submission-lines'] = submission_lines
data['submitted_answers'][answers_name + 'starter-lines'] = starter_lines
data['submitted_answers'][answers_name + 'submission-lines'] = submission_lines

# `element` is now an XML data structure - see docs for LXML library at lxml.de

Expand All @@ -304,7 +296,7 @@ def load_json_if_present(key: str, default=[]):
data['submitted_answers']['_files'] = [
{
"name": file_name,
"contents": base64_encode(get_student_code(element_html, data))
"contents": base64_encode(get_student_code(element, data))
}
]

Expand Down

0 comments on commit f6d1548

Please sign in to comment.