Skip to content
Snippets Groups Projects
Commit 33eb15de authored by Eliott Sammier's avatar Eliott Sammier
Browse files

Parse QCU correct answers with Xpath and Regex

parent 25f3425a
Branches
No related tags found
No related merge requests found
...@@ -50,14 +50,12 @@ class RegexParser: ...@@ -50,14 +50,12 @@ class RegexParser:
raise ParseError("Failed to find function 'entrerDonnees'") raise ParseError("Failed to find function 'entrerDonnees'")
body = func_split[1] body = func_split[1]
activity_type, activity_var_name = self.parse_activity_constructor(body) activity_type, activity_var_name = self._parse_activity_constructor(body)
print(activity_type, file=output) print(activity_type, end="", file=output)
if activity_type == "ExerciceQC_QCU":
print(" ", self._parse_qcu_answers(body), end="", file=output)
for line in body.splitlines(): def _parse_activity_constructor(self, code: str) -> tuple[str, str]:
line = line.strip()
pass
def parse_activity_constructor(self, code: str) -> tuple[str, str]:
""" """
Find activity constructor call, return the activity type Find activity constructor call, return the activity type
and resulting variable name. and resulting variable name.
...@@ -80,6 +78,24 @@ class RegexParser: ...@@ -80,6 +78,24 @@ class RegexParser:
act_type += "_" + args.replace('"', "") act_type += "_" + args.replace('"', "")
return act_type, var_name return act_type, var_name
def _parse_qcu_answers(self, code: str) -> list[bool]:
"""Parse the correct answers for a QCU activity, as a list of booleans"""
correct_choices = []
index = 0
for line in code.splitlines():
line = line.strip()
m = re.match(r"var nr = (\d+);", line)
if m is not None:
# "index" line
index = int(m.group(1))
elif line == "exo.tabStylesR[nr] = CODE_F;":
# "incorrect answer" line
insert_grow(correct_choices, index, False, fill_value=False)
elif line == "exo.tabStylesR[nr] = CODE_V;":
# "correct answer" line
insert_grow(correct_choices, index, True, fill_value=False)
return correct_choices
def __str__(self) -> str: def __str__(self) -> str:
return "RegexParser" return "RegexParser"
...@@ -108,8 +124,10 @@ class XpathParser: ...@@ -108,8 +124,10 @@ class XpathParser:
xml = self.to_xml(jstree.toDict(), "jstree") xml = self.to_xml(jstree.toDict(), "jstree")
try: try:
self.fun = self.request_function(xml)[0] self.fun = self.request_function(xml)[0]
print(self._parse_activity_type(), file=output) act_type = self._parse_activity_type()
# self._parse_qcu_choices() print(act_type, end="", file=output)
if act_type == "ExerciceQC_QCU":
print(" ", self._parse_qcu_answers(), end="", file=output)
except Exception as e: except Exception as e:
raise ParseError(e) raise ParseError(e)
...@@ -124,18 +142,20 @@ class XpathParser: ...@@ -124,18 +142,20 @@ class XpathParser:
case other: case other:
return other return other
def _parse_qcu_choices(self): def _parse_qcu_answers(self) -> list[bool]:
"""Parse the correct answers for a QCU activity, as a list of booleans"""
indexes_and_values = self.request_index_and_values(self.fun) indexes_and_values = self.request_index_and_values(self.fun)
correct_choices = [] correct_choices = []
index = 0
for e in indexes_and_values: for e in indexes_and_values:
value = e.xpath("@value") value = e.xpath("@value")
if len(value) != 0: if len(value) != 0:
# "index line" # "index line"
index = value[0] index = int(value[0])
else: else:
# "true line" # "true line"
insert_grow(correct_choices, index, True, fill_value=False) insert_grow(correct_choices, index, True, fill_value=False)
print(correct_choices) return correct_choices
def to_xml(self, obj, tag_name: Optional[str] = None): def to_xml(self, obj, tag_name: Optional[str] = None):
"""Recursively convert an object structure to an XML `ElementTree`. """Recursively convert an object structure to an XML `ElementTree`.
...@@ -242,7 +262,7 @@ class MatchParser: ...@@ -242,7 +262,7 @@ class MatchParser:
pass pass
def print(self, s: str): def print(self, s: str):
print(s, file=self.output) print(s, end="", file=self.output)
def match_function(self, func: dict): def match_function(self, func: dict):
"""Checks if `func` matches a function declaration named `entrerDonnees`, """Checks if `func` matches a function declaration named `entrerDonnees`,
...@@ -301,7 +321,7 @@ def parse_page(graph: Graph, filepath: str, id: str): ...@@ -301,7 +321,7 @@ def parse_page(graph: Graph, filepath: str, id: str):
# Try different parsers, each writing to a different file to compare their results # Try different parsers, each writing to a different file to compare their results
for parser in [XpathParser(), MatchParser(graph, id), RegexParser()]: for parser in [XpathParser(), MatchParser(graph, id), RegexParser()]:
with open(f"/tmp/{str(parser)}.txt", "a") as f: with open(f"/tmp/{str(parser)}.txt", "a") as f:
print(f"{id:8}", end="", file=f) print(f"\n{id:8}", end="", file=f)
try: try:
parser.parse(js, output=f) parser.parse(js, output=f)
except ParseError as e: except ParseError as e:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment