diff --git a/Scripts/Python/Library/gquiz.py b/Scripts/Python/Library/gquiz.py index b96822d..cde4489 100644 --- a/Scripts/Python/Library/gquiz.py +++ b/Scripts/Python/Library/gquiz.py @@ -23,6 +23,9 @@ class gquiz: self.form_service = None self.drive_service = None self.main_form = None + self.infoPrint = self._defaultPrint + self.progress = -1 + self.resultUri = "" self.submition["requests"].append({ "updateSettings": { @@ -35,6 +38,14 @@ class gquiz: } }) + def setProgress(self, i : int): + self.progress = i + def AttachProcessInfo(self, callback): + self.infoPrint = callback + + def _defaultPrint(self, text : str, progress: int): + print("{}% {}".format(progress, text)) + def generateService(self): ''' Start Tokenizing here is the way to get token @@ -52,19 +63,23 @@ class gquiz: # time. if os.path.exists('token.json'): creds = Credentials.from_authorized_user_file('token.json', SCOPES) + self.infoPrint("token already exist",self.progress) # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) + self.infoPrint("refresh token",self.progress) else: flow = InstalledAppFlow.from_client_secrets_file( './secret/client_secrets.json', SCOPES) creds = flow.run_local_server(port=0) + self.infoPrint("generate token",self.progress) # Save the credentials for the next run with open('token.json', 'w') as token: token.write(creds.to_json()) try: + self.infoPrint("creating service",self.progress) service = build('docs', 'v1', credentials=creds) self.form_service, self.drive_service = \ build('forms', 'v1', credentials=creds, discoveryServiceUrl=DISCOVERY_DOC, static_discovery=False),\ @@ -81,6 +96,7 @@ class gquiz: name : name form """ try: + self.infoPrint("creating form",self.progress) self.main_form = self.form_service.forms().create(body={"info":{"title":name}}).execute() except HttpError as error: print('An error occurred: %s' % error) @@ -120,13 +136,15 @@ class gquiz: } }} ''' + self.infoPrint("creating option",self.progress) opt = {"value" : "{}".format(value)} if(image != None): - print("print with image, uploading... ") + self.infoPrint("uploading option image... ",self.progress) req = requests.post(self.image_temp_service_url,files={"file": open(image,'rb')}) if(req.json()['status'] == 'error'): raise Exception("upload failed : {}".format(req.json())) - print("success") + time.sleep(3) + self.infoPrint("uploading option image... ok",self.progress) u = urlparse(req.json()['data']['url']) opt.update({"image" : { "sourceUri": u._replace(path="/dl"+u.path).geturl(), @@ -168,12 +186,14 @@ class gquiz: } } } + self.infoPrint("create question...",self.progress) if (itemImage != None): - print("uploading image for quesiton : ") + self.infoPrint("uploading question image...",self.progress) req = requests.post(self.image_temp_service_url,files={"file": open(itemImage,'rb')}) if(req.json()['status'] == 'error'): raise Exception("upload failed : {}".format(req.json())) - print("succes") + time.sleep(3) + self.infoPrint("uploading question image... ok",self.progress) u = urlparse(req.json()['data']['url']) item['questionItem'].update(\ {"image": { @@ -183,7 +203,6 @@ class gquiz: } } }) - time.sleep(3) return item def submitQuestion(self, index, item): @@ -198,14 +217,18 @@ class gquiz: "item": item } }) + self.infoPrint("submit question",self.progress) print(self.submition) def update(self): + self.infoPrint("Updating Form...",self.progress) # Adds the question to the form question_setting = self.form_service.forms().batchUpdate(formId=self.main_form["formId"], body=self.submition).execute() print(question_setting) # Prints the result to show the question has been added get_result = self.form_service.forms().get(formId=self.main_form["formId"]).execute() + self.resultUri = get_result['responderUri'] print(get_result) + self.infoPrint("Updating Form... Done",self.progress) diff --git a/Scripts/Python/Library/moodleQuiz.py b/Scripts/Python/Library/moodleQuiz.py new file mode 100644 index 0000000..850821c --- /dev/null +++ b/Scripts/Python/Library/moodleQuiz.py @@ -0,0 +1,87 @@ +# coding: utf-8 +from __future__ import unicode_literals +import base64 +import xml.etree.ElementTree as ET + +class moodleQuiz: + def __init__(self): + self.infoPrint = self._defaultPrint + self.progress = -1 + self.resultUri = "" + self.data = ET.Element('quiz') + + def setProgress(self, i : int): + self.progress = i + self.infoPrint("generating...", self.progress) + + def AttachProcessInfo(self, callback): + self.infoPrint = callback + + def _defaultPrint(self, text : str, progress: int): + print("{}% {}".format(progress, text)) + + def _subElementFile(self, parent, file): + Efile = ET.SubElement(parent, "file") + Efile.set('name',file.name.split("/").pop()) + Efile.set('path','/') + Efile.set('encoding','base64') + Efile.text = base64.b64encode(file.read()).decode('utf-8') + + def createOption(self, value, image=None): + ans = ET.Element('answer') + ans.set('fraction', '0') + ans.set('format', 'html') + if(image == None): + ET.SubElement(ans, 'text').text = "

{}

".format(value) + else : + f = open(image,"rb") + ET.SubElement(ans, 'text').text = "

" + \ + "\"{}\"

"\ + .format(f.name.split("/").pop(), f.name.split("/").pop().split(".")[0]) + self._subElementFile(ans, f) + ET.SubElement(ET.SubElement(ans,'feedback'), 'text').text = "Ooopss!" + return ans + + + def createQuestion(self, title, description, options, indexAnswer, itemImage=None): + question = ET.Element('question') + question.set('type','multichoice') + + ET.SubElement(ET.SubElement(question, 'name'), 'text')\ + .text = title + + descQuestion = ET.SubElement(question, 'questiontext') + descQuestion.set('format', 'html') + descText = ET.SubElement(descQuestion, 'text') + descText.text = "

{}

".format(description) + + if (itemImage != None): + f = open(itemImage,"rb") + descText.text = descText.text + "

" + \ + "\"{}\"

"\ + .format(f.name.split("/").pop(), f.name.split("/").pop().split(".")[0]) + self._subElementFile(descQuestion, f) + + for i in range(0, len(options)): + ans = options[i] + if i == (indexAnswer-1) : + ans.set('fraction', '100') + ans.find('feedback').find('text').text = "YES!" + question.append(ET.fromstring(ET.tostring(ans))) + + ET.SubElement(question, 'shuffleanswers').text = '0' + ET.SubElement(question, 'answernumbering').text = 'abc' + return question + + def submitQuestion(self, index, item): + self.data.append(ET.fromstring(ET.tostring(item))) + + def copyFile(self,origin_file_id, copy_title): + print("noting to copy, it for moodle") + + def update(self): + ET.indent(self.data) + print(ET.tostring(self.data)) + ET.ElementTree(self.data).write("./moodleXMLMultichoiceQuestion.xml") + + diff --git a/Scripts/Python/quiz_generator.py b/Scripts/Python/quiz_generator.py index ecf51e8..99ae0d2 100644 --- a/Scripts/Python/quiz_generator.py +++ b/Scripts/Python/quiz_generator.py @@ -1,70 +1,102 @@ # coding: utf-8 from __future__ import unicode_literals import sys, os +import requests +import importlib + +# to run separatly from soffice +# $ soffice --calc --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager" # uncomemnt for run separatly from soffice -#sys.path.append("/lib64/libreoffice/program/") +# sys.path.append("/lib64/libreoffice/program/") + from scriptforge import ScriptForge, CreateScriptService from unohelper import fileUrlToSystemPath -# uncomemnt for run separatly from soffice -#ScriptForge(hostname='localhost', port=2021) -def generateTemplate(): - doc = CreateScriptService("Calc") - basic = CreateScriptService("Basic") - doc.SetArray(doc.CurrentSelection, \ - (("","", \ - "", "", "", \ - "", "", "", \ - "", "", "", \ - "", "", "", \ - "", "", "", ),)) - -def updateQuestion(): -# strat comment for run separatly from soffice - if not 'gquiz' in sys.modules: +#[start] comment for run separatly from soffice +if (not 'gquiz' in sys.modules) or (not 'moodleQuiz' in sys.modules): doc = XSCRIPTCONTEXT.getDocument() url = fileUrlToSystemPath('{}/{}'.format(doc.URL,'Scripts/python/Library')) sys.path.insert(0, url) -# end - from gquiz import gquiz - import requests - - doc = CreateScriptService("Calc") - selctedCell = doc.CurrentSelection - - q = gquiz() - q.generateService() - q.createForm("Demo Soal") - cwd = os.getcwd() - for nrow in range(0, doc.LastRow(selctedCell)+1-doc.FirstRow(selctedCell)): - item = doc.getValue(doc.Offset(doc.FirstCell(selctedCell),nrow,0,1,17)) - opt = [] - theAnswer = -1 - c = 1 - - for o in range(2,17,3): - if (item[o] == 1): - theAnswer = c - if (item[o+1] != ""): - opt.append(q.createOption("{}. {}".format(chr(64+c),item[o+2]),cwd+item[o+1])) - else: - opt.append(q.createOption("{}. {}".format(chr(64+c),item[o+2]))) - c = c+1 - - if (theAnswer == -1): - raise Exception("Chose the correct answer") +else: + importlib.reload(gquiz) + importlib.reload(moodleQuiz) - if( item[1] != ""): - img = cwd+item[1] - else: - img = None - - qq = q.createQuestion(title = "Soal No {}".format(nrow+1),\ - description = item[0],\ - indexAnswer = theAnswer, \ - options = opt, itemImage=img) - q.submitQuestion(nrow,qq) - q.update() - -g_exportedScripts = (generateTemplate, updateQuestion, ) +#[end] +#[start] uncomemnt for run separatly from soffice +#sys.path.insert(0, '{}/{}'.format(os.getcwd(),'Library')) +#[end] + +from gquiz import gquiz +from moodleQuiz import moodleQuiz + +ScriptForge(hostname='localhost', port=2002) +ui = CreateScriptService("UI") +doc = CreateScriptService("Calc") +bas = CreateScriptService("Basic") + +def MakeTemplate(): + doc.SetArray(doc.CurrentSelection, \ + (("","", \ + "", "", "", \ + "", "", "", \ + "", "", "", \ + "", "", "", \ + "", "", "", ),)) + +def _statusBarInfoUpdate(text : str, progress : int): + ui.SetStatusbar("{}% {}".format(progress,text), progress) + +def _updateQuestion(q): + selctedCell = doc.CurrentSelection + cwd = os.getcwd() + maxRow = doc.LastRow(selctedCell)+1-doc.FirstRow(selctedCell) + for nrow in range(0, maxRow): + q.setProgress(int(((nrow+1)/maxRow)*100)) + item = doc.getValue(doc.Offset(doc.FirstCell(selctedCell),nrow,0,1,17)) + opt = [] + theAnswer = -1 + c = 1 + for o in range(2,17,3): + if (item[o] == 1): + theAnswer = c + if (item[o+1] != ""): + opt.append(q.createOption("{}. {}".format(chr(64+c),item[o+2]),cwd+item[o+1])) + else: + opt.append(q.createOption("{}. {}".format(chr(64+c),item[o+2]))) + c = c+1 + + if (theAnswer == -1): + raise Exception("Chose the correct answer") + + if( item[1] != ""): + img = cwd+item[1] + else: + img = None + + qq = q.createQuestion(title = "Soal No {}".format(nrow+1),\ + description = item[0],\ + indexAnswer = theAnswer, \ + options = opt, itemImage=img) + q.submitQuestion(nrow,qq) + q.update() + +def GoogleQuiz(): + q = gquiz() + q.AttachProcessInfo(_statusBarInfoUpdate) + q.setProgress(0) + q.generateService() + q.createForm("Demo Soal") + _updateQuestion(q) + ui.SetStatusbar("creating google form quiz done!") + bas.InputBox("Open link to edit your form:","Your Google Form Quiz, done!", "{}".format(q.resultUri)) + +def MoodleQuiz(): + q = moodleQuiz() + q.AttachProcessInfo(_statusBarInfoUpdate) + q.setProgress(0) + _updateQuestion(q) + ui.SetStatusbar("Done!") + bas.MsgBox("Check *.xml file in curent folder!") + +g_exportedScripts = (MakeTemplate, GoogleQuiz, MoodleQuiz) diff --git a/Scripts/Python/test_gquiz.py b/Scripts/Python/test_gquiz.py deleted file mode 100644 index c36fdc9..0000000 --- a/Scripts/Python/test_gquiz.py +++ /dev/null @@ -1,29 +0,0 @@ -# coding: utf-8 -from __future__ import unicode_literals - -import sys, requests -from unohelper import fileUrlToSystemPath - -def gquiz_test(): - if not 'gquiz' in sys.modules: - doc = XSCRIPTCONTEXT.getDocument() - url = fileUrlToSystemPath('{}/{}'.format(doc.URL,'Scripts/python/Library')) - sys.path.insert(0, url) - from gquiz import gquiz - - q = gquiz() - - q.generateService() - - q.copyFile("16-rh3W-NwYzdKVBZJmi574sTWe_rMIdE-FQSw_33qXI", "Soal Masuk Penjara") - opt = [ q.createOption("A.","./asset/option1.png"), - q.createOption("B.","./asset/option2.png"), - q.createOption("C.","./asset/option3.png"), - q.createOption("D.","./asset/option4.png"), - q.createOption("E.","./asset/option5.png") ] - - qq = q.createQuestion(title = "Soal No 1",\ - description = "Dari gambar dibawah ini, ada bagian gambar yang hilang. Dari pilihan dibawah, manakah gambar yang benar?",\ - indexAnswer = 4, options = opt, itemImage='./asset/test_image.png') - q.submitQuestion(0,qq) - q.update() diff --git a/Scripts/Python/test_quiz.py b/Scripts/Python/test_quiz.py new file mode 100644 index 0000000..6db6933 --- /dev/null +++ b/Scripts/Python/test_quiz.py @@ -0,0 +1,33 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import sys, requests, os +from unohelper import fileUrlToSystemPath + +sys.path.insert(0, "{}/{}".format(os.getcwd(),"Library")) +from gquiz import gquiz +from moodleQuiz import moodleQuiz + +def test(q): + opt = [ q.createOption("A.","./asset/option1.png"), + q.createOption("B.","./asset/option2.png"), + q.createOption("C.","./asset/option3.png"), + q.createOption("D.","./asset/option4.png"), + q.createOption("E.","./asset/option5.png") ] + qq = q.createQuestion(title = "Soal No 1",\ + description = "Dari gambar dibawah ini, ada bagian gambar yang hilang. Dari pilihan dibawah, manakah gambar yang benar?",\ + indexAnswer = 4, options = opt, itemImage='./asset/test_image.png') + q.submitQuestion(0,qq) + q.update() + +os.system("mkdir asset && mkdir secret") +os.system("cp ../../asset/* ./asset") +os.system("cp ../../secret/client_secrets.json ./secret") + +q = moodleQuiz() +test(q) + +q = gquiz() +q.generateService() +q.createForm("test") +test(q) diff --git a/myedu.ods b/myedu.ods index 34919bf..eea9789 100644 Binary files a/myedu.ods and b/myedu.ods differ