Skip to content
Snippets Groups Projects
Commit 63f3e96b authored by Mathieu Loiseau's avatar Mathieu Loiseau
Browse files

images

parent d3ab3ecf
No related branches found
No related tags found
No related merge requests found
quiz-*.xml quiz-*.xml
__pycache__ __pycache__
data
#!/usr/bin/env python3 #!/usr/bin/env python3
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from utils import strip_tags, mlang_2_multiling, score_2_str from utils import strip_tags, mlang_2_multiling, score_2_str
import base64
from PIL import Image
from io import BytesIO
class Quizz: class Quizz:
def __init__(self, file_name): def __init__(self, file_name, target_folder):
self.file_name = file_name self.file_name = file_name
self.tree = ET.parse(self.file_name) self.tree = ET.parse(self.file_name)
self.questions = {} self.questions = {}
self.folder = target_folder
self.parse() self.parse()
def get_tree(self): def get_tree(self):
...@@ -15,15 +20,15 @@ class Quizz: ...@@ -15,15 +20,15 @@ class Quizz:
if c not in self.questions.keys(): if c not in self.questions.keys():
self.questions[c] = [] self.questions[c] = []
if q.attrib['type'] == "multichoice": if q.attrib['type'] == "multichoice":
newQ = MCQ(q,c,len(self.questions[c])) newQ = MCQ(q,c,len(self.questions[c]),self.folder)
elif q.attrib['type'] == "shortanswer": elif q.attrib['type'] == "shortanswer":
newQ = Question(q,c,len(self.questions[c])) newQ = Question(q,c,len(self.questions[c]),self.folder)
elif q.attrib['type'] == "truefalse": elif q.attrib['type'] == "truefalse":
newQ = TF(q,c,len(self.questions[c])) newQ = TF(q,c,len(self.questions[c]),self.folder)
elif q.attrib['type'] == "matching": elif q.attrib['type'] == "matching":
newQ = Question(q,c,len(self.questions[c])) newQ = Question(q,c,len(self.questions[c]),self.folder)
elif q.attrib['type'] == "ddimageortext": elif q.attrib['type'] == "ddimageortext":
newQ = Question(q,c,len(self.questions[c])) newQ = Question(q,c,len(self.questions[c]),self.folder)
else: else:
raise f"{q.attrib['type']} is not expected" raise f"{q.attrib['type']} is not expected"
self.questions[c].append(newQ) self.questions[c].append(newQ)
...@@ -43,17 +48,33 @@ class Quizz: ...@@ -43,17 +48,33 @@ class Quizz:
res += str(q) res += str(q)
return res return res
def save(self):
name = self.file_name[self.file_name.rfind('/')+1:self.file_name.rfind('.')]
output = open(self.folder+"/"+name+".tex", "w")
output.write(self.__str__())
class Question: class Question:
def __init__(self,xmlQ,c,n): def __init__(self,xmlQ,c,n,f):
self.q = mlang_2_multiling(strip_tags(xmlQ.find("questiontext/text").text)) self.folder = f
self.q = mlang_2_multiling(strip_tags(xmlQ.find("questiontext/text").text, self.folder))
self.category = c self.category = c
self.id = f"{c[c.rfind(':')+1:]}_{n}" self.id = f"{c[c.rfind(':')+1:]}_{n}"
self.env = "questionmult" self.env = "todo:"+xmlQ.attrib["type"]
self.max = float(xmlQ.find("defaultgrade").text) self.max = float(xmlQ.find("defaultgrade").text)
self.parseImages(xmlQ.findall(".//file"))
def parseImages(self, file_elements):
for i in file_elements:
name = i.attrib["name"]
print(name)
im = Image.open(BytesIO(base64.b64decode(i.text)))
ext = name[name.rfind('.')+1:].upper()
im.save(self.folder+"/"+name, ext)
def __str__(self): def __str__(self):
return """\\element{"""+self.category+"""}{ return """\\element{"""+self.category+"""}{
\\begin{"""+self.env+"""}{"""+self.id+"""}\\nbpoints{"""+score_2_str(self.max)+"""} \\begin{"""+self.env+"""}{"""+self.id+"""}\\nbpoints{"""+score_2_str(self.max)+"""}
"""+self.q+"\\end{"+self.env+"}" """+self.q+"\\end{"+self.env+"}\n"
class Answer: class Answer:
def __init__(self,t,b,max,fb): def __init__(self,t,b,max,fb):
...@@ -80,9 +101,10 @@ class Answer: ...@@ -80,9 +101,10 @@ class Answer:
class MCQ(Question): class MCQ(Question):
def __init__(self, xmlQ,c,n): def __init__(self, xmlQ,c,n,f):
super().__init__(xmlQ,c,n) super().__init__(xmlQ,c,n,f)
self.choices = [] self.choices = []
self.env = "questionmult"
self.__parseAnswers(xmlQ) self.__parseAnswers(xmlQ)
def __parseAnswers(self, xmlQ): def __parseAnswers(self, xmlQ):
...@@ -90,8 +112,8 @@ class MCQ(Question): ...@@ -90,8 +112,8 @@ class MCQ(Question):
for a in xmlQ.findall("answer"): for a in xmlQ.findall("answer"):
fb = a.find("feedback/text").text fb = a.find("feedback/text").text
if fb != None: if fb != None:
fb = mlang_2_multiling(strip_tags(fb)) fb = mlang_2_multiling(strip_tags(fb, self.folder))
self.choices.append(Answer(mlang_2_multiling(strip_tags(a.find("text").text)), a.attrib['fraction'], self.max, fb)) self.choices.append(Answer(mlang_2_multiling(strip_tags(a.find("text").text, self.folder)), a.attrib['fraction'], self.max, fb))
def __str__(self): def __str__(self):
res = """\\element{"""+self.category+"""}{ res = """\\element{"""+self.category+"""}{
...@@ -106,25 +128,25 @@ class MCQ(Question): ...@@ -106,25 +128,25 @@ class MCQ(Question):
return res return res
class TF(MCQ): class TF(MCQ):
def __init__(self, xmlQ,c,n): def __init__(self, xmlQ,c,n,f):
super(MCQ, self).__init__(xmlQ,c,n) super(MCQ, self).__init__(xmlQ,c,n,f)
self.choices = [] self.choices = []
self.env = "question" self.env = "question"
self.shuffle = False self.shuffle = False
self.__parseAnswers(xmlQ) self.__parseAnswers(xmlQ)
def __parseAnswers(self, xmlQ): def __parseAnswers(self, xmlQ):
print("ok")
for a in xmlQ.findall("answer"): for a in xmlQ.findall("answer"):
fb = a.find("feedback/text").text fb = a.find("feedback/text").text
if fb != None: if fb != None:
fb = mlang_2_multiling(strip_tags(fb)) fb = mlang_2_multiling(strip_tags(fb, self.folder))
if a.find("text").text == "true": if a.find("text").text == "true":
self.choices.append(Answer("\\multi{vrai}{true}", a.attrib['fraction'], self.max, fb)) self.choices.append(Answer("\\multiling{vrai}{true}", a.attrib['fraction'], self.max, fb))
else: else:
self.choices.append(Answer("\\multi{faux}{false}", a.attrib['fraction'], self.max, fb)) self.choices.append(Answer("\\multiling{faux}{false}", a.attrib['fraction'], self.max, fb))
if __name__ == "__main__": if __name__ == "__main__":
quizz = Quizz("quiz-GI-4-SID-S1-top-20201204-1620.xml") quizz = Quizz("data/quiz-GI-4-SID-S1-top-20201204-1620.xml", "data")
#quizz = Quizz("quiz-GI-4.xml") #quizz = Quizz("data/quiz-GI-4.xml" , "data")
print(quizz) #print(quizz)
quizz.save()
#!/usr/bin/env python3 #!/usr/bin/env python3
from re import compile,sub,escape from re import compile,sub,escape
from html import unescape
from urllib.parse import unquote
def html_2_tex(text): def html_2_tex(text):
#https://code.activestate.com/recipes/81330-single-pass-multiple-replace/ #https://code.activestate.com/recipes/81330-single-pass-multiple-replace/
dict = {'&nbsp;': '~', '&gt;':'>', '&lt;': '<'} # dict = {'&nbsp;': '~', '&gt;':'>', '&lt;': '<'}
""" Replace in 'text' all occurences of any key in the given # """ Replace in 'text' all occurences of any key in the given
dictionary by its corresponding value. Returns the new tring.""" # dictionary by its corresponding value. Returns the new tring."""
# Create a regular expression from the dictionary keys # # Create a regular expression from the dictionary keys
regex = compile("(%s)" % "|".join(map(escape, dict.keys()))) # regex = compile("(%s)" % "|".join(map(escape, dict.keys())))
#
# # For each match, look-up corresponding value in dictionary
# return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
return unescape(text)
# For each match, look-up corresponding value in dictionary
return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
def remove_moodle_cdata(txt): def remove_moodle_cdata(txt, folder):
return txt.replace("<![CDATA[","").replace("]]>","") return sub(r'<img src="[^/]*/([^"]*)" (alt="([^"]*)")?[^>]*>', r"""\\begin{figure}[h!]
\\begin{center}
\\includegraphics[width=0.8\\linewidth]{$$$$folder$$$$/\1}
\\end{center}
\\caption{\3}
\\end{figure}
""",txt).replace("<![CDATA[","").replace("]]>","").replace("$$$$folder$$$$", folder)
def strip_tags(txt): def strip_tags(txt, folder):
return html_2_tex(sub(compile('<.*?>'), '',remove_moodle_cdata(txt))) return html_2_tex(sub(compile('<.*?>'), '',remove_moodle_cdata(unquote(txt), folder)))
def mlang_2_multiling(txt): def mlang_2_multiling(txt):
return sub(r"\{mlang en\}(.*?)\{mlang\}((\{mlang other\})|(\{mlang fr\}))(.*?)\{mlang\}", r"\\multiling{\5}{\1}",txt) return sub(r"\{mlang en\}(.*?)\{mlang\}((\{mlang other\})|(\{mlang fr\}))(.*?)\{mlang\}", r"\\multiling{\5}{\1}",txt)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment