Commit 935db7b4 authored by Jonathan Wiedemann's avatar Jonathan Wiedemann
Browse files

Add some new functions.

It is now easier to add new lessons.
parent fdd08f6e
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
......@@ -36,14 +36,14 @@ import FreeCAD as app
import FreeCADGui as gui
global MOOC_VERSION
MOOC_VERSION = 'V1.0.0'
MOOC_VERSION = "V1.2.0"
moocWB_path = os.path.dirname(moocwb_locator.__file__)
moocWB_medias_path = os.path.join(moocWB_path, 'medias')
moocWB_icons_path = os.path.join(moocWB_medias_path, 'icons')
moocWB_medias_path = os.path.join(moocWB_path, "medias")
moocWB_icons_path = os.path.join(moocWB_medias_path, "icons")
global main_moocWB_Icon
main_moocWB_Icon = os.path.join(moocWB_icons_path, 'mooc-workbench.svg')
main_moocWB_Icon = os.path.join(moocWB_icons_path, "mooc-workbench.svg")
class MoocWorkbench(Workbench):
......@@ -58,13 +58,14 @@ class MoocWorkbench(Workbench):
"This function is executed when FreeCAD starts"
import MoocPlayer
import MoocGrader
self.appendToolbar('MOOC', ['Mooc_Player', 'Mooc_Grader'])
self.appendMenu('MOOC', ['Mooc_Player', 'Mooc_Grader'])
print('Initialize MOOC module... done.')
self.appendToolbar("MOOC", ["Mooc_Player", "Mooc_Grader"])
self.appendMenu("MOOC", ["Mooc_Player", "Mooc_Grader"])
print("Initialize MOOC module... done.")
def Activated(self):
"This function is executed when the workbench is activated"
print('Activated MoocWorkbench... done')
print("Activated MoocWorkbench... done")
return
def Deactivated(self):
......
File mode changed from 100644 to 100755
This diff is collapsed.
# coding: utf-8
################################################
#
# MoocChecker.py
#
# Copyright 2018 Jonathan Wiedemann <contact at freecad-france dot com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
################################################
__title__ = "MOOC Workbench"
__author__ = "Jonathan Wiedemann"
__url__ = "http://www.freecadweb.org"
import FreeCAD as app
import FreeCADGui as gui
import math
# for debug purposes
DEBUG = False
if DEBUG:
print("MOOC CHECKER")
def make_result(r):
"""make_result(r) -> 0 or 1
make final result from list of result
to get 1 there must not be 0 in r
r=[1,1,1,0] => result = 0
r=[1,1,1,1] => result = 1
"""
if DEBUG:
print("Check.make_result(r = %s)" % r)
if len(r) > 0:
if 0 in r:
result = 0
else:
result = 1
else:
result = 0
# if DEBUG:print('result = ', result)
# if DEBUG:print('End check')
return result
# coding: utf-8
################################################
#
# MoocChecker.py
#
# Copyright 2018 Jonathan Wiedemann <contact at freecad-france dot com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
################################################
__title__ = "MOOC Workbench"
__author__ = "Jonathan Wiedemann"
__url__ = "http://www.freecadweb.org"
import FreeCAD as app
import FreeCADGui as gui
import math
# for debug purposes
DEBUG = False
if DEBUG:
print("MOOC CHECKER")
def make_result(r):
"""make_result(r) -> 0 or 1
make final result from list of result
to get 1 there must not be 0 in r
r=[1,1,1,0] => result = 0
r=[1,1,1,1] => result = 1
"""
if DEBUG:
print("Check.make_result(r = %s)" % r)
if len(r) > 0:
if 0 in r:
result = 0
else:
result = 1
else:
result = 0
# if DEBUG:print('result = ', result)
# if DEBUG:print('End check')
return result
def getSheet(sheetname=None):
if sheetname is None:
sheetname = "Spreadsheet"
doc = app.ActiveDocument
if doc:
return app.ActiveDocument.getObject(sheetname)
else:
return None
def checkSheet():
r = []
doc = app.ActiveDocument
if doc:
for obj in app.ActiveDocument.Objects:
if obj.TypeId == "Spreadsheet::Sheet":
r.append(1)
if len(r) < 1:
r.append(0)
else:
r.append(0)
return make_result(r)
def checkCell(sheet="Spreadsheet", index="A1", content=""):
r = []
obj = getSheet(sheet)
if obj:
if hasattr(obj, index):
r.append(1)
if content:
get = obj.get(index)
if type(get) is str:
if content == get:
r.append(1)
else:
if content == get.Value:
r.append(1)
return make_result(r)
def checkAlias(sheet="Spreadsheet", index="A1", content=""):
r = []
obj = getSheet(sheet)
if hasattr(obj, index):
r.append(1)
if content:
if content == obj.getAlias(index):
r.append(1)
else:
r.append(0)
else:
r.append(0)
return make_result(r)
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
......@@ -25,7 +25,7 @@
__title__ = "MOOC Workbench"
__author__ = "Jonathan Wiedemann"
__url__ = "http://www.freecadweb.org"
__url__ = "https://freecad-france.com"
# to make gui
from PySide import QtCore, QtGui
......@@ -39,7 +39,7 @@ import moocwb_locator
from os import listdir
from os.path import isfile, join
if (sys.version_info > (3, 0)): # py3
if sys.version_info > (3, 0): # py3
import importlib
else: # py2
import imp
......@@ -53,6 +53,8 @@ import webbrowser
# import MoocChecker
import MoocChecker
import MoocCheckerSpreadsheet
import MoocCheckerPart
# to DEBUG purpose
DEBUG = False
......@@ -61,8 +63,12 @@ DEBUG = False
if DEBUG:
try:
reload(MoocChecker)
reload(MoocCheckerSpreadsheet)
reload(MoocCheckerPart)
except NameError:
importlib.reload(MoocChecker)
importlib.reload(MoocCheckerSpreadsheet)
importlib.reload(MoocCheckerPart)
def debug():
......@@ -76,13 +82,14 @@ if DEBUG:
TIMER.timeout.connect(debug)
moocWB_path = os.path.dirname(moocwb_locator.__file__)
moocWB_medias_path = os.path.join(moocWB_path, 'medias')
moocWB_icons_path = os.path.join(moocWB_medias_path, 'icons')
moocWB_medias_path = os.path.join(moocWB_path, "medias")
moocWB_icons_path = os.path.join(moocWB_medias_path, "icons")
QtWidgets = QtGui
class Ui_MoocPlayer(QtWidgets.QDialog):
'''The FreeCAD Player interface'''
"""The FreeCAD Player interface"""
def __init__(self, parent=gui.getMainWindow()):
super(Ui_MoocPlayer, self).__init__(parent)
......@@ -91,7 +98,7 @@ class Ui_MoocPlayer(QtWidgets.QDialog):
mw_size = parent.size()
mw_pos = parent.pos()
move_x = mw_pos.x() + mw_size.width() - self.size().width()
move_y = mw_pos.y() + mw_size.height()/2 - self.size().height()/2
move_y = mw_pos.y() + mw_size.height() / 2 - self.size().height() / 2
self.move(move_x, move_y)
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
self.verticalLayout_left = QtWidgets.QVBoxLayout(self)
......@@ -107,11 +114,15 @@ class Ui_MoocPlayer(QtWidgets.QDialog):
self.horizontalLayout_play.setObjectName("horizontalLayout_play")
self.btn_play = QtWidgets.QPushButton(self)
self.btn_play.setObjectName("btn_play")
self.btn_play.setIcon(QtGui.QIcon(os.path.join(moocWB_icons_path, 'media-playback-start.svg')))
self.btn_play.setIcon(
QtGui.QIcon(os.path.join(moocWB_icons_path, "media-playback-start.svg"))
)
self.horizontalLayout_play.addWidget(self.btn_play)
self.btn_help = QtWidgets.QPushButton(self)
self.btn_help.setObjectName("btn_help")
self.btn_help.setIcon(QtGui.QIcon(os.path.join(moocWB_icons_path, 'help-contents.svg')))
self.btn_help.setIcon(
QtGui.QIcon(os.path.join(moocWB_icons_path, "help-contents.svg"))
)
self.horizontalLayout_play.addWidget(self.btn_help)
self.verticalLayout_left.addLayout(self.horizontalLayout_play)
self.label_objectifs = QtWidgets.QLabel(self)
......@@ -119,13 +130,17 @@ class Ui_MoocPlayer(QtWidgets.QDialog):
self.verticalLayout_left.addWidget(self.label_objectifs)
self.listWidget_objectifs = QtWidgets.QListWidget(self)
self.listWidget_objectifs.setObjectName("listWidget_objectifs")
self.listWidget_objectifs.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.NoSelection)
self.listWidget_objectifs.setSelectionMode(
QtWidgets.QAbstractItemView.SelectionMode.NoSelection
)
self.verticalLayout_left.addWidget(self.listWidget_objectifs)
self.horizontalLayout_change_step = QtWidgets.QHBoxLayout()
self.horizontalLayout_change_step.setObjectName("horizontalLayout_change_step")
self.btn_previous_step = QtWidgets.QPushButton(self)
self.btn_previous_step.setObjectName("btn_previous_step")
self.btn_previous_step.setIcon(QtGui.QIcon(os.path.join(moocWB_icons_path, 'go-previous.svg')))
self.btn_previous_step.setIcon(
QtGui.QIcon(os.path.join(moocWB_icons_path, "go-previous.svg"))
)
self.horizontalLayout_change_step.addWidget(self.btn_previous_step)
self.label_step = QtWidgets.QLabel(self)
self.label_step.setAlignment(QtCore.Qt.AlignCenter)
......@@ -133,7 +148,9 @@ class Ui_MoocPlayer(QtWidgets.QDialog):
self.horizontalLayout_change_step.addWidget(self.label_step)
self.btn_next_step = QtWidgets.QPushButton(self)
self.btn_next_step.setObjectName("btn_next_step")
self.btn_next_step.setIcon(QtGui.QIcon(os.path.join(moocWB_icons_path, 'go-next.svg')))
self.btn_next_step.setIcon(
QtGui.QIcon(os.path.join(moocWB_icons_path, "go-next.svg"))
)
self.horizontalLayout_change_step.addWidget(self.btn_next_step)
self.verticalLayout_left.addLayout(self.horizontalLayout_change_step)
......@@ -158,8 +175,8 @@ class Ui_MoocPlayer(QtWidgets.QDialog):
print("Closing Mooc Player")
class Manager_MoocPlayer():
'''functions to control and update the dialog'''
class Manager_MoocPlayer:
"""functions to control and update the dialog"""
def __init__(self, lesson):
self.form = Ui_MoocPlayer()
......@@ -217,7 +234,9 @@ class Manager_MoocPlayer():
self.form.listWidget_objectifs.setFixedHeight(
(self.form.listWidget_objectifs.sizeHintForRow(0) + 10)
* self.form.listWidget_objectifs.count()
+ 10 * self.form.listWidget_objectifs.frameWidth() + 8)
+ 10 * self.form.listWidget_objectifs.frameWidth()
+ 8
)
def play_video(self):
step_data = self.lesson.get_data_step(self.current_step_id)
......@@ -248,15 +267,19 @@ class Manager_MoocPlayer():
for x in results:
if x == 0:
self.form.listWidget_objectifs.item(idx).setForeground(brush_red)
self.form.listWidget_objectifs.item(idx).setIcon(QtGui.QIcon(os.path.join(moocWB_icons_path , 'window-close.svg')))
self.form.listWidget_objectifs.item(idx).setIcon(
QtGui.QIcon(os.path.join(moocWB_icons_path, "window-close.svg"))
)
elif x == 1:
self.form.listWidget_objectifs.item(idx).setForeground(brush_green)
self.form.listWidget_objectifs.item(idx).setIcon(QtGui.QIcon(os.path.join(moocWB_icons_path , 'dialog-apply.svg')))
self.form.listWidget_objectifs.item(idx).setIcon(
QtGui.QIcon(os.path.join(moocWB_icons_path, "dialog-apply.svg"))
)
idx += 1
class Ui_MoocChooser(QtWidgets.QDialog):
'''The FreeCAD Player chooser interface'''
"""The FreeCAD Player chooser interface"""
def setupUi(self, MoocPlayerChooser):
MoocPlayerChooser.setObjectName("MoocPlayerChooser")
......@@ -275,17 +298,31 @@ class Ui_MoocChooser(QtWidgets.QDialog):
self.verticalLayout.addWidget(self.label_description)
self.buttonBox = QtWidgets.QDialogButtonBox(MoocPlayerChooser)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setStandardButtons(
QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.get_lessons_title_list()
self.retranslateUi(MoocPlayerChooser)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), MoocPlayerChooser.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), MoocPlayerChooser.reject)
QtCore.QObject.connect(self.listWidget_trainings, QtCore.SIGNAL("itemDoubleClicked(QListWidgetItem *)"), MoocPlayerChooser.launch_mooc)
QtCore.QObject.connect(self.listWidget_trainings, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), MoocPlayerChooser.display_lesson_description)
QtCore.QObject.connect(
self.buttonBox, QtCore.SIGNAL("accepted()"), MoocPlayerChooser.accept
)
QtCore.QObject.connect(
self.buttonBox, QtCore.SIGNAL("rejected()"), MoocPlayerChooser.reject
)
QtCore.QObject.connect(
self.listWidget_trainings,
QtCore.SIGNAL("itemDoubleClicked(QListWidgetItem *)"),
MoocPlayerChooser.launch_mooc,
)
QtCore.QObject.connect(
self.listWidget_trainings,
QtCore.SIGNAL("itemClicked(QListWidgetItem *)"),
MoocPlayerChooser.display_lesson_description,
)
QtCore.QMetaObject.connectSlotsByName(MoocPlayerChooser)
self.show()
......@@ -293,24 +330,36 @@ class Ui_MoocChooser(QtWidgets.QDialog):
def retranslateUi(self, MoocPlayerChooser):
MoocPlayerChooser.setWindowTitle(u"Choisir la leçon")
self.label_welcome.setText(u"Quelle leçon souhaitez vous étudier aujourd'hui ?")
self.label_description.setText(u"Cliquer sur un éléments de la liste pour obtenir la description de la leçon.")
self.label_description.setText(
u"Cliquer sur un éléments de la liste pour obtenir la description de la leçon."
)
def accept(self):
self.launch_mooc(self.listWidget_trainings.currentItem())
def get_lessons_list(self):
moocWB_path = os.path.dirname(moocwb_locator.__file__)
moocWBpath_lessons = os.path.join(moocWB_path, 'lessons')
files = [f for f in listdir(moocWBpath_lessons) if isfile(join(moocWBpath_lessons, f))]
onlyfiles = [f for f in files if os.path.splitext(f)[1] == '.py']
onlyfiles.sort()
moocWB_path_lessons = os.path.join(moocWB_path, "lessons")
dirlist = [d for d in listdir(moocWB_path_lessons)]
lesson_fileslist = []
for dir in dirlist:
l = []
lesson_path = os.path.join(moocWB_path_lessons, dir)
for file in listdir(lesson_path):
if isfile(join(lesson_path, file)):
if os.path.splitext(file)[-1] == ".py":
l.append(file)
l.append(dir)
lesson_fileslist.append(l)
lesson_fileslist.sort()
if DEBUG:
print(onlyfiles)
print(dirlist)
print(lesson_fileslist)
self.lessons_list = []
for lesson in onlyfiles:
name, ext = os.path.splitext(lesson)
path = os.path.join(moocWBpath_lessons, lesson)
if (sys.version_info > (3, 0)):
for lesson in lesson_fileslist:
name, ext = os.path.splitext(lesson[0])
path = os.path.join(moocWB_path_lessons, lesson[1], lesson[0])
if sys.version_info > (3, 0):
spec = importlib.util.spec_from_file_location(name, path)
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
......@@ -338,16 +387,20 @@ class Ui_MoocChooser(QtWidgets.QDialog):
Manager_MoocPlayer(lesson)
class Command_MoocChooser():
class Command_MoocChooser:
"class to choose the lesson"
def GetResources(self):
# moocWB_path = os.path.dirname(moocwb_locator.__file__)
# moocWB_medias_path = os.path.join(moocWB_path, 'medias')
# moocWB_icons_path = os.path.join(moocWB_medias_path, 'icons')
return {'Pixmap': os.path.join(moocWB_icons_path, 'mooc-player.svg'),
'MenuText': QtCore.QT_TRANSLATE_NOOP(u"Mooc", "Voir un tutoriel."),
'ToolTip': QtCore.QT_TRANSLATE_NOOP(u"Mooc", "Permet de choisir et voir un tutoriel interactif.")}
return {
"Pixmap": os.path.join(moocWB_icons_path, "mooc-player.svg"),
"MenuText": QtCore.QT_TRANSLATE_NOOP(u"Mooc", "Voir un tutoriel."),
"ToolTip": QtCore.QT_TRANSLATE_NOOP(
u"Mooc", "Permet de choisir et voir un tutoriel interactif."
),
}
def IsActive(self):
return True
......@@ -359,4 +412,4 @@ class Command_MoocChooser():
if app.GuiUp:
gui.addCommand('Mooc_Player', Command_MoocChooser())
gui.addCommand("Mooc_Player", Command_MoocChooser())
......@@ -106,23 +106,31 @@ Choisir le document FreeCAD à évaluer.
Cliquer sur le bouton **Lancer l'évaluation**.
Dans le panneau de gauche vous verrez les différent critère d'évaluation listé. Si vert alors c'est ok si c'esst rouge c'est faux.
Dans le panneau de gauche vous verrez les différent critère d'évaluation listé. Si vert alors c'est ok si c'est rouge c'est faux.
Quand l'évaluation vous satisfait vous pouvez transmettre les résultats en cliquant sur le bouton **Envoyer les résultats**
<img src="/medias/images/EnvoieResult.png" width=45% >
Une fenêtre s'ouvre avec une chaine de caratère qu'il faut copier/coller dans votre espace MOOC. Vous pouvez cliquer sur le bouton **Copier** pour copier la chaine de caractère dans le presse papier. Il vous restera juste à le coller (clic droit coller ou avec le raccouris Ctrl+V).
Une fenêtre s'ouvre avec une chaîne de caractère qu'il faut copier/coller dans votre espace MOOC. Vous pouvez cliquer sur le bouton **Copier** pour copier la chaine de caractère dans le presse papier. Il vous restera juste à le coller (clic droit coller ou avec le raccouris Ctrl+V).
<img src="/medias/images/CopyPasteResult.png" width=45% >
## Fonctionnement:
Chaque leçon ou t
## Créer un tutoriel
Dans le dossier "lessons" de l'atelier, faites une copie du fichier "Template Lesson.py".
Il faut d'abord créer un dossier dans le dossier lessons.
Dans ce dossier il y aura :
- un fichier python pour le contenu des étapes et les appels de vérification.
- un dossier images avec les médias nécessaire au contenu du tutoriel.
Renommé le avec un nouveau nom en gardant l"extension ".py".
Ensuite il faut l'éditer :
Ensuite il faut l'éditer le fichier py :
Ligne 26 : renseigner votre nom
......
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment