update dengan info process di status bar dan support moodle quiz XML
parent
eb1fe990cf
commit
b47fa6b20e
|
@ -23,6 +23,9 @@ class gquiz:
|
||||||
self.form_service = None
|
self.form_service = None
|
||||||
self.drive_service = None
|
self.drive_service = None
|
||||||
self.main_form = None
|
self.main_form = None
|
||||||
|
self.infoPrint = self._defaultPrint
|
||||||
|
self.progress = -1
|
||||||
|
self.resultUri = ""
|
||||||
|
|
||||||
self.submition["requests"].append({
|
self.submition["requests"].append({
|
||||||
"updateSettings": {
|
"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):
|
def generateService(self):
|
||||||
''' Start Tokenizing
|
''' Start Tokenizing
|
||||||
here is the way to get token
|
here is the way to get token
|
||||||
|
@ -52,19 +63,23 @@ class gquiz:
|
||||||
# time.
|
# time.
|
||||||
if os.path.exists('token.json'):
|
if os.path.exists('token.json'):
|
||||||
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
|
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 there are no (valid) credentials available, let the user log in.
|
||||||
if not creds or not creds.valid:
|
if not creds or not creds.valid:
|
||||||
if creds and creds.expired and creds.refresh_token:
|
if creds and creds.expired and creds.refresh_token:
|
||||||
creds.refresh(Request())
|
creds.refresh(Request())
|
||||||
|
self.infoPrint("refresh token",self.progress)
|
||||||
else:
|
else:
|
||||||
flow = InstalledAppFlow.from_client_secrets_file(
|
flow = InstalledAppFlow.from_client_secrets_file(
|
||||||
'./secret/client_secrets.json', SCOPES)
|
'./secret/client_secrets.json', SCOPES)
|
||||||
creds = flow.run_local_server(port=0)
|
creds = flow.run_local_server(port=0)
|
||||||
|
self.infoPrint("generate token",self.progress)
|
||||||
# Save the credentials for the next run
|
# Save the credentials for the next run
|
||||||
with open('token.json', 'w') as token:
|
with open('token.json', 'w') as token:
|
||||||
token.write(creds.to_json())
|
token.write(creds.to_json())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
self.infoPrint("creating service",self.progress)
|
||||||
service = build('docs', 'v1', credentials=creds)
|
service = build('docs', 'v1', credentials=creds)
|
||||||
self.form_service, self.drive_service = \
|
self.form_service, self.drive_service = \
|
||||||
build('forms', 'v1', credentials=creds, discoveryServiceUrl=DISCOVERY_DOC, static_discovery=False),\
|
build('forms', 'v1', credentials=creds, discoveryServiceUrl=DISCOVERY_DOC, static_discovery=False),\
|
||||||
|
@ -81,6 +96,7 @@ class gquiz:
|
||||||
name : name form
|
name : name form
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
self.infoPrint("creating form",self.progress)
|
||||||
self.main_form = self.form_service.forms().create(body={"info":{"title":name}}).execute()
|
self.main_form = self.form_service.forms().create(body={"info":{"title":name}}).execute()
|
||||||
except HttpError as error:
|
except HttpError as error:
|
||||||
print('An error occurred: %s' % error)
|
print('An error occurred: %s' % error)
|
||||||
|
@ -120,13 +136,15 @@ class gquiz:
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
'''
|
'''
|
||||||
|
self.infoPrint("creating option",self.progress)
|
||||||
opt = {"value" : "{}".format(value)}
|
opt = {"value" : "{}".format(value)}
|
||||||
if(image != None):
|
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')})
|
req = requests.post(self.image_temp_service_url,files={"file": open(image,'rb')})
|
||||||
if(req.json()['status'] == 'error'):
|
if(req.json()['status'] == 'error'):
|
||||||
raise Exception("upload failed : {}".format(req.json()))
|
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'])
|
u = urlparse(req.json()['data']['url'])
|
||||||
opt.update({"image" : {
|
opt.update({"image" : {
|
||||||
"sourceUri": u._replace(path="/dl"+u.path).geturl(),
|
"sourceUri": u._replace(path="/dl"+u.path).geturl(),
|
||||||
|
@ -168,12 +186,14 @@ class gquiz:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.infoPrint("create question...",self.progress)
|
||||||
if (itemImage != None):
|
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')})
|
req = requests.post(self.image_temp_service_url,files={"file": open(itemImage,'rb')})
|
||||||
if(req.json()['status'] == 'error'):
|
if(req.json()['status'] == 'error'):
|
||||||
raise Exception("upload failed : {}".format(req.json()))
|
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'])
|
u = urlparse(req.json()['data']['url'])
|
||||||
item['questionItem'].update(\
|
item['questionItem'].update(\
|
||||||
{"image": {
|
{"image": {
|
||||||
|
@ -183,7 +203,6 @@ class gquiz:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
time.sleep(3)
|
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def submitQuestion(self, index, item):
|
def submitQuestion(self, index, item):
|
||||||
|
@ -198,14 +217,18 @@ class gquiz:
|
||||||
"item": item
|
"item": item
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
self.infoPrint("submit question",self.progress)
|
||||||
print(self.submition)
|
print(self.submition)
|
||||||
|
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
self.infoPrint("Updating Form...",self.progress)
|
||||||
# Adds the question to the form
|
# Adds the question to the form
|
||||||
question_setting = self.form_service.forms().batchUpdate(formId=self.main_form["formId"], body=self.submition).execute()
|
question_setting = self.form_service.forms().batchUpdate(formId=self.main_form["formId"], body=self.submition).execute()
|
||||||
print(question_setting)
|
print(question_setting)
|
||||||
|
|
||||||
# Prints the result to show the question has been added
|
# Prints the result to show the question has been added
|
||||||
get_result = self.form_service.forms().get(formId=self.main_form["formId"]).execute()
|
get_result = self.form_service.forms().get(formId=self.main_form["formId"]).execute()
|
||||||
|
self.resultUri = get_result['responderUri']
|
||||||
print(get_result)
|
print(get_result)
|
||||||
|
self.infoPrint("Updating Form... Done",self.progress)
|
||||||
|
|
|
@ -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 = "<p dir=\"ltr\" style=\"text-align: left;\">{}</p>".format(value)
|
||||||
|
else :
|
||||||
|
f = open(image,"rb")
|
||||||
|
ET.SubElement(ans, 'text').text = "<p dir=\"ltr\" style=\"text-align: left;\">" + \
|
||||||
|
"<img src=\"@@PLUGINFILE@@/{}\" alt=\"{}\" class=\"img-fluid atto_image_button_text-bottom\"></p>"\
|
||||||
|
.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 = "<p dir=\"ltr\" style=\"text-align: left;\">{}</p>".format(description)
|
||||||
|
|
||||||
|
if (itemImage != None):
|
||||||
|
f = open(itemImage,"rb")
|
||||||
|
descText.text = descText.text + "<p dir=\"ltr\" style=\"text-align: left;\">" + \
|
||||||
|
"<img src=\"@@PLUGINFILE@@/{}\" alt=\"{}\" class=\"img-fluid atto_image_button_text-bottom\"></p>"\
|
||||||
|
.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")
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,41 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import sys, os
|
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
|
# uncomemnt for run separatly from soffice
|
||||||
#sys.path.append("/lib64/libreoffice/program/")
|
# sys.path.append("/lib64/libreoffice/program/")
|
||||||
|
|
||||||
from scriptforge import ScriptForge, CreateScriptService
|
from scriptforge import ScriptForge, CreateScriptService
|
||||||
from unohelper import fileUrlToSystemPath
|
from unohelper import fileUrlToSystemPath
|
||||||
|
|
||||||
# uncomemnt for run separatly from soffice
|
#[start] comment for run separatly from soffice
|
||||||
#ScriptForge(hostname='localhost', port=2021)
|
if (not 'gquiz' in sys.modules) or (not 'moodleQuiz' in sys.modules):
|
||||||
def generateTemplate():
|
doc = XSCRIPTCONTEXT.getDocument()
|
||||||
doc = CreateScriptService("Calc")
|
url = fileUrlToSystemPath('{}/{}'.format(doc.URL,'Scripts/python/Library'))
|
||||||
basic = CreateScriptService("Basic")
|
sys.path.insert(0, url)
|
||||||
|
else:
|
||||||
|
importlib.reload(gquiz)
|
||||||
|
importlib.reload(moodleQuiz)
|
||||||
|
|
||||||
|
#[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, \
|
doc.SetArray(doc.CurrentSelection, \
|
||||||
(("<Text question>","<IMG question image>", \
|
(("<Text question>","<IMG question image>", \
|
||||||
"<isAnswerA>", "<IMG option1>", "<Text Option1>", \
|
"<isAnswerA>", "<IMG option1>", "<Text Option1>", \
|
||||||
|
@ -20,29 +44,19 @@ def generateTemplate():
|
||||||
"<isAnswerD>", "<IMG option4>", "<Text Option4>", \
|
"<isAnswerD>", "<IMG option4>", "<Text Option4>", \
|
||||||
"<isAnswerE>", "<IMG option5>", "<Text Option5>", ),))
|
"<isAnswerE>", "<IMG option5>", "<Text Option5>", ),))
|
||||||
|
|
||||||
def updateQuestion():
|
def _statusBarInfoUpdate(text : str, progress : int):
|
||||||
# strat comment for run separatly from soffice
|
ui.SetStatusbar("{}% {}".format(progress,text), progress)
|
||||||
if not 'gquiz' 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")
|
def _updateQuestion(q):
|
||||||
selctedCell = doc.CurrentSelection
|
selctedCell = doc.CurrentSelection
|
||||||
|
|
||||||
q = gquiz()
|
|
||||||
q.generateService()
|
|
||||||
q.createForm("Demo Soal")
|
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
for nrow in range(0, doc.LastRow(selctedCell)+1-doc.FirstRow(selctedCell)):
|
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))
|
item = doc.getValue(doc.Offset(doc.FirstCell(selctedCell),nrow,0,1,17))
|
||||||
opt = []
|
opt = []
|
||||||
theAnswer = -1
|
theAnswer = -1
|
||||||
c = 1
|
c = 1
|
||||||
|
|
||||||
for o in range(2,17,3):
|
for o in range(2,17,3):
|
||||||
if (item[o] == 1):
|
if (item[o] == 1):
|
||||||
theAnswer = c
|
theAnswer = c
|
||||||
|
@ -67,4 +81,22 @@ def updateQuestion():
|
||||||
q.submitQuestion(nrow,qq)
|
q.submitQuestion(nrow,qq)
|
||||||
q.update()
|
q.update()
|
||||||
|
|
||||||
g_exportedScripts = (generateTemplate, updateQuestion, )
|
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)
|
||||||
|
|
|
@ -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()
|
|
|
@ -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)
|
Loading…
Reference in New Issue