Cycle Vitesse/Relais
Professeurs référents :
M FAURY (ISN)
M VERDIER (EPS)
Présentation de l’équipe projet
NOM Prénom | Classe | Année Scolaire |
PELGER Pierre | TS5 | 2017-2018 |
MERESSE Marc | TS5 | 2017-2018 |
Présentation du projet
Dans le cadre du cycle de course, plus particulièrement les épreuves de relai, dans les cours d’EPS, on souhaite avoir accès à un outil facile d’utilisation permettant la saisie des performances des élèves et de certaines statistiques qui y sont liées. L’application doit pouvoir être utilisée facilement par le professeur comme les élèves, qui pourront modifier de nombreux paramètres, ajouter des groupes, des élèves,… Elle doit aussi permettre à l’utilisateur de rechercher les performances des élèves selon différents critères (classe, groupe,…).
Cahier des charges
Description détaillée :
Étapes | Avancement |
Squelette graphique (pages/boutons/zones d’entrée de texte) [Méresse] | Terminé |
Design [Méresse] | En cours |
Ergonomie [Méresse] | Terminé |
Textes de l’app [Méresse] | Terminé |
Fonction de calcul des performances [Pelger] | En cours |
Création des objets [Pelger] | Terminé |
Recherche des élèves (optionnel) | Non commencé |
Fichier XML [Pelger] | Terminé |
Manipulation de la base de données | En cours |
Mot de passe administrateur (optionnel) | Non commencé |
Répartition des tâches
PELGER Pierre | Statistiques, données, fichiers |
MERESSE Marc | Interface graphique, textes |
Suivi collectif du projet
Date | Tâche | Remarques |
07/02/2018 | Début de réflexion sur le projet | Cahier des charges précisé après entretien avec M.Verdier. |
28/02/2018 | Découverte des modules et des outils de programmation
Début des manipulations sur différents petits projets de test |
|
04/04/2018 | Création des objets classes, groupes et élèves (programmation orientée objet)
Après apprentissage de Tkinter, début de la création du squelette de l’app. |
|
25/04/2018 | Squelette de l’application terminé. Nous relevons un ensemble de problèmes d’ergonomie à régler.
Choix d’un fichier XML pour stocker les données. |
Pour le design nécessité d’implémenter un système de frames ou canvas. |
02/05/2018 | Amélioration du design. L’app est lisible -grâce aux frames– et le design satisfaisant. | Remplacement intégral des méthodes .pack() par des .grid() pour afficher correctement les barres de défilement des diverses listes de la base de données. |
Ressources documentaires et documentation du projet
Liste des références consultées pour le projet :
Marc Méresse :
http://apprendre-python.com/page-tkinter-interface-graphique-python-tutoriel
http://effbot.org/tkinterbook/
http://tkinter.fdex.eu/index.html
Pierre Pelger :
Objectif
Proposer un logiciel renseignant et calculant pour chaque élève ses performances individuelles et collectives dans les épreuves de Vitesse et Relai en EPS.
Cahier des charges
Exemples :
- Sur une course de 30m, Jean met 6″ et Paul 5″.
- Le temps additionné de ces 2 coureurs est 5+6=11″
- Ensuite, ils réalisent un relais sur 60m. Leur temps est alors de 10″78c
Le logiciel doit permettre :
La saisie des noms des « athlètes »
- La saisie des différentes performances réalisées par chacun d’entre eux, pour différents types d’épreuves.
- Les calculs pertinents pour évaluer leurs performances « globales », leur évolution, leurs points faibles, …
- additions de temps (par exemple sur 30 m pour Paul et Jean 5″ + 6″ = 11″)
- comparaison de leurs performances individuelles avec leur performance collective (individuel : 11″ / 60m ; collectif 10″78c)
- …
- Le réglage de nombreux paramètres : nombre d’élèves par groupe de relais, …
- Des analyse statistiques, sur la classe, d’autres classe, dans le temps, …
- …
[reveal heading= »%image% Programme »]
### textes #page1 texteTuto= """Cycle Vitesse et Relai ! Les règles sont simples : -Formez vos groupes de trois élèves. -Chronométrez-vous individuellement sur la distance prévue. -En groupe, courrez en relai sur la somme des distances individuelles comme vous l'indique votre professeur. -Utilisez l'onglet "Renseigner mes performances" pour sauvegarder vos résultats individuels et collectifs. Pour tout problème, renseignez-vous auprès de votre professeur ou consultez la page "Infos" dans la barre de menu.""" texteCredits="""Ce logiciel est Open-Source. Développé dans le cadre de la spécialité ISN du lycée Blaise Pascal de Clermont-Ferrand, 2017-2018. Interface graphique : Marc Méresse Cœur : Pierre Pelger Professeurs référents : M. Faury (ISN) ; M.Verdier(EPS) """ ###imports, fenêtre, génération aléatoire des effectifs print('hello world') from tkinter import * from tkinter import ttk from random import * nombre_de_classes=randint(1,5) liste_nombre_groupes=[0]*nombre_de_classes for i in range(nombre_de_classes): liste_nombre_groupes[i]=randint(1,13) groupes_total=0 for i in range(nombre_de_classes): groupes_total+=liste_nombre_groupes[i] eleves_total=randint(1,250) accueil = Tk() accueil.title('Cycle Vitesse et Relai') accueil.minsize(width=700, height=300) ### # messages pop-up from tkinter.messagebox import * def pierre(): showwarning('Partie de Pierre Pelger','!!à implémenter!!') def marc(): showwarning('Partie de Marc Méresse','!!à implémenter!!') def fenetreCredits(): showwarning('Crédits',texteCredits) # gérer classe def gerer_classes(): gestion_classes = Toplevel() gestion_classes.title("Gestion des Classes") gestion_classes.geometry('400x370') cadreTexte1 = Frame(gestion_classes, background = 'PeachPuff', bd = 10) cadreTexte1.pack(side=TOP) separateur1 = Frame(gestion_classes, height=3, bd=1, relief=SUNKEN) separateur1.pack(fill=X, padx=5, pady=5) cadreAjouter1 = Frame(gestion_classes, background = 'PeachPuff', bd=10) cadreAjouter1.pack(side=LEFT) cadreSupprimer1 = Frame(gestion_classes, background = 'PeachPuff', bd=10) cadreSupprimer1.pack(side = RIGHT) #texte texte1 = Label(cadreTexte1, text='Ajouter ou supprimer des classes.\nAvant d\'enregistrer une nouvelle classe, assurez-vous d\'avoir créé la fiche de chaque groupe de cette classe dans la rubrique "Gérer groupes".', height=5, width=150) texte1.pack(fill=BOTH, expand = 1) listeClasses = Listbox(cadreSupprimer1) for i in range(nombre_de_classes): nomclasseexemple='classe'+str(i) listeClasses.insert(i, nomclasseexemple) listeClasses.grid(row=0,column=0) boutonSupprimerClasse=Button(cadreSupprimer1, text="Supprimer la classe selectionnée", command=pierre) boutonSupprimerClasse.grid(row=1,column=0) classe = StringVar() inviteClasse=Label(cadreAjouter1, text='Nom de la classe') inviteClasse.grid(row=0,column=0) entreeClasse = Entry(cadreAjouter1, textvariable=classe, width=20) entreeClasse.grid(row=1,column=0) listeGroupes = Listbox(cadreAjouter1, selectmode = MULTIPLE) for i in range(groupes_total): nomgroupeexemple='groupe'+str(i) listeGroupes.insert(i,nomgroupeexemple) listeGroupes.grid(row=2,column=0) #barre ajouter barre1=Scrollbar(cadreAjouter1) barre1.grid(row=2,column=1) barre1.config(command = listeGroupes.yview) listeGroupes.config(yscrollcommand=barre1.set) #barre supprimer barre2=Scrollbar(cadreSupprimer1) barre2.grid(row=0,column=1) barre2.config(command = listeClasses.yview) listeClasses.config(yscrollcommand=barre1.set) ajouterClasse=Button(cadreAjouter1, text="Créer la classe", cursor='plus',command=pierre) ajouterClasse.grid(row=3,column=0) # gérer groupes def gerer_groupes(): gestion_groupes = Toplevel() gestion_groupes.title("Gestion des Groupes d'élèves") gestion_groupes.geometry('400x375') cadreTexte12 = Frame(gestion_groupes, background = 'PeachPuff', bd = 10) cadreTexte12.pack(side=TOP) separateur2 = Frame(gestion_groupes, height=3, bd=1, relief=SUNKEN) separateur2.pack(fill=X, padx=5, pady=5) cadreAjouter12 = Frame(gestion_groupes, background = 'PeachPuff', bd=10) cadreAjouter12.pack(side=LEFT) cadreSupprimer12 = Frame(gestion_groupes, background = 'PeachPuff', bd=10) cadreSupprimer12.pack(side = RIGHT) texte1 = Label(cadreTexte12, text='Formez vos groupes de trois.\nAvant de créer un nouveau groupe, assurez-vous d\'avoir créé chaque profil d\'élève de ce groupe dans la rubrique "Gérer élèves".', height=5, width=150) texte1.pack() listeGroupes = Listbox(cadreSupprimer12) for i in range(groupes_total): nomgroupeexemple='Groupe '+str(i) listeGroupes.insert(i,nomgroupeexemple) listeGroupes.pack() supprimerGroupe=Button(cadreSupprimer12, text="Supprimer le groupe sélectionné", command=pierre) supprimerGroupe.pack() groupe = StringVar() inviteGroupe=Label(cadreAjouter12, text='Nom du groupe') inviteGroupe.pack() entreeGroupe = Entry(cadreAjouter12, textvariable=groupe, width=20) entreeGroupe.pack() check=StringVar() listeEleves=Listbox(cadreAjouter12, selectmode=MULTIPLE) for i in range(eleves_total): nomeleveexemple='Eleve '+str(i) listeEleves.insert(i, nomeleveexemple) listeEleves.pack() ajouterGroupe=Button(cadreAjouter12, text="Créer Groupe", cursor='plus', command=pierre) ajouterGroupe.pack() # gérer élèves def gerer_eleves(): gestion_eleves = Toplevel() gestion_eleves.title("Gestion des Groupes d'élèves") gestion_eleves.geometry('400x400') cadreTexte3 = Frame(gestion_eleves, background = 'PeachPuff', bd = 10) cadreTexte3.pack(side=TOP) separateur3 = Frame(gestion_eleves, height=3, bd=1, relief=SUNKEN) separateur3.pack(fill=X, padx=5, pady=5) cadreAjouter3 = Frame(gestion_eleves, background = 'PeachPuff', bd=10) cadreAjouter3.pack(side=LEFT) cadreSupprimer3 = Frame(gestion_eleves, background = 'PeachPuff', bd=10) cadreSupprimer3.pack(side = RIGHT) texte1 = Label(cadreTexte3, text='Créez un nouveau profil d\'élève à partir de son nom.', height=5, width=60) texte1.pack() texte2 = Label(cadreTexte3, text='Ou supprimez un profil d\'élève.', height=5, width=60) texte2.pack() prenom = StringVar() textePrenom=Label(cadreAjouter3, text='Prénom de l\'élève :') textePrenom.pack() entreePrenom = Entry(cadreAjouter3, textvariable=prenom, width=20) entreePrenom.pack() nom = StringVar() texteNom=Label(cadreAjouter3, text='Nom de l\'élève :') texteNom.pack() entreeNom = Entry(cadreAjouter3, textvariable=nom, width=20) entreeNom.pack() listeEleves=Listbox(cadreSupprimer3) for i in range(eleves_total): nomeleveexemple='Eleve '+str(i) listeEleves.insert(i, nomeleveexemple) listeEleves.pack() ajouterEleve=Button(cadreAjouter3, text="Ajouter",cursor='plus', command=pierre) ajouterEleve.pack() supprimerEleve=Button(cadreSupprimer3, text="Supprimer un élève", command=pierre) supprimerEleve.pack() #cascade de choix de classe / groupe & entrée perfs def choisir_classe(): #cascade groupe def maclasse_sesgroupes(): try: indiceClasse=int(listeClasses.get(ACTIVE)[-2]+listeClasses.get(ACTIVE)[-1]) except: indiceClasse=int(listeClasses.get(ACTIVE)[-1]) def mongroupe_seseleves(): try: indiceGroupe=int(listeGroupes.get(ACTIVE)[-2]+listeGroupes.get(ACTIVE)[-1]) except: indiceGroupe=int(listeGroupes.get(ACTIVE)[-1]) titreajuste2=titreajuste+'Groupe '+str(indiceGroupe) perfs = Toplevel() perfs.title(titreajuste2) perfs.geometry('400x370') ###ici compléter la fenetre avec perf eleve1,2,3 et perf groupe choix_groupe.destroy() titreajuste='Classe '+str(indiceClasse)+' ' choix_groupe = Toplevel() choix_groupe.title(titreajuste) choix_groupe.geometry('400x370') cadreTexteGroupe = Frame(choix_groupe, background = 'PeachPuff', bd = 10) cadreTexteGroupe.pack(side=TOP) separateur1bis = Frame(choix_groupe, height=3, bd=1, relief=SUNKEN) separateur1bis.pack(fill=X, padx=5, pady=5) cadrelisteGroupes = Frame(choix_groupe, background = 'PeachPuff', bd=10) cadrelisteGroupes.pack() #texte texte1bis = Label(cadreTexteGroupe, text='Sélectionnez votre groupe.', height=5, width=150) texte1bis.pack(fill=BOTH, expand = 1) listeGroupes = Listbox(cadrelisteGroupes) for i in range(liste_nombre_groupes[indiceClasse]): nomclasseexemple=titreajuste+'Groupe '+str(i) listeGroupes.insert(i, nomclasseexemple) listeGroupes.grid(row=0,column=0) boutonSelectionGroupe=Button(cadrelisteGroupes, text="OK", command=mongroupe_seseleves) boutonSelectionGroupe.grid(row=1,column=0) #barre choix barre=Scrollbar(cadrelisteGroupes) barre.grid(row=0,column=1) barre.config(command = listeGroupes.yview) listeGroupes.config(yscrollcommand=barre.set) choix_classe.destroy() choix_classe = Toplevel() choix_classe.title("Sélection de la Classe") choix_classe.geometry('400x370') cadreTexte = Frame(choix_classe, background = 'PeachPuff', bd = 10) cadreTexte.pack(side=TOP) separateur1 = Frame(choix_classe, height=3, bd=1, relief=SUNKEN) separateur1.pack(fill=X, padx=5, pady=5) cadrelisteClasses = Frame(choix_classe, background = 'PeachPuff', bd=10) cadrelisteClasses.pack() #texte texte1 = Label(cadreTexte, text='Sélectionnez votre classe.', height=5, width=150) texte1.pack(fill=BOTH, expand = 1) listeClasses = Listbox(cadrelisteClasses) for i in range(nombre_de_classes): nomclasseexemple='Classe '+str(i) listeClasses.insert(i, nomclasseexemple) listeClasses.grid(row=0,column=0) boutonSelectionClasse=Button(cadrelisteClasses, text="OK", command=maclasse_sesgroupes) boutonSelectionClasse.grid(row=1,column=0) #barre choix barre=Scrollbar(cadrelisteClasses) barre.grid(row=0,column=1) barre.config(command = listeClasses.yview) listeClasses.config(yscrollcommand=barre.set) #cascade de choix de classe / groupe & consultation resultats def choisir_classe2(): #cascade groupe def maclasse_sesgroupes2(): try: indiceClasse=int(listeClasses.get(ACTIVE)[-2]+listeClasses.get(ACTIVE)[-1]) except: indiceClasse=int(listeClasses.get(ACTIVE)[-1]) def mongroupe_seseleves2(): try: indiceGroupe=int(listeGroupes.get(ACTIVE)[-2]+listeGroupes.get(ACTIVE)[-1]) except: indiceGroupe=int(listeGroupes.get(ACTIVE)[-1]) titreajustebis2=titreajustebis+'Groupe test '+str(indiceGroupe) resultats = Toplevel() resultats.title(titreajustebis2) resultats.geometry('400x370') cadreEleve1=Label(resultats, text='Eleve 1') cadreEleve1.grid(row=0,column=0) entreeEleve1 = Entry(resultats, textvariable='1', width=20) entreeEleve1.grid(row=0,column=1) cadreEleve2=Label(resultats, text='Eleve 2') cadreEleve2.grid(row=1,column=0) entreeEleve2 = Entry(resultats, textvariable='2', width=20) entreeEleve2.grid(row=1,column=1) cadreEleve3=Label(resultats, text='Eleve 3') cadreEleve3.grid(row=2,column=0) entreeEleve2 = Entry(resultats, textvariable='3', width=20) entreeEleve2.grid(row=2,column=1) choix_groupe2.destroy() titreajustebis='Classe '+str(indiceClasse)+' ' choix_groupe2 = Toplevel() choix_groupe2.title(titreajustebis) choix_groupe2.geometry('400x370') cadreTexteGroupe = Frame(choix_groupe2, background = 'PeachPuff', bd = 10) cadreTexteGroupe.pack(side=TOP) separateur1bis = Frame(choix_groupe2, height=3, bd=1, relief=SUNKEN) separateur1bis.pack(fill=X, padx=5, pady=5) cadrelisteGroupes = Frame(choix_groupe2, background = 'PeachPuff', bd=10) cadrelisteGroupes.pack() #texte texte1bis = Label(cadreTexteGroupe, text='Sélectionnez votre groupe.', height=5, width=150) texte1bis.pack(fill=BOTH, expand = 1) listeGroupes = Listbox(cadrelisteGroupes) for i in range(liste_nombre_groupes[indiceClasse]): nomclasseexemple=titreajustebis+'Groupe '+str(i) listeGroupes.insert(i, nomclasseexemple) listeGroupes.grid(row=0,column=0) boutonSelectionGroupe=Button(cadrelisteGroupes, text="OK", command=mongroupe_seseleves2) boutonSelectionGroupe.grid(row=1,column=0) #barre choix barre=Scrollbar(cadrelisteGroupes) barre.grid(row=0,column=1) barre.config(command = listeGroupes.yview) listeGroupes.config(yscrollcommand=barre.set) choix_classe2.destroy() choix_classe2 = Toplevel() choix_classe2.title("Sélection de la Classe") choix_classe2.geometry('400x370') cadreTexte = Frame(choix_classe2, background = 'PeachPuff', bd = 10) cadreTexte.pack(side=TOP) separateur1 = Frame(choix_classe2, height=3, bd=1, relief=SUNKEN) separateur1.pack(fill=X, padx=5, pady=5) cadrelisteClasses = Frame(choix_classe2, background = 'PeachPuff', bd=10) cadrelisteClasses.pack() #texte texte1 = Label(cadreTexte, text='Sélectionnez votre classe.', height=5, width=150) texte1.pack(fill=BOTH, expand = 1) listeClasses = Listbox(cadrelisteClasses) for i in range(nombre_de_classes): nomclasseexemple='Classe '+str(i) listeClasses.insert(i, nomclasseexemple) listeClasses.grid(row=0,column=0) boutonSelectionClasse=Button(cadrelisteClasses, text="OK", command=maclasse_sesgroupes2) boutonSelectionClasse.grid(row=1,column=0) #barre choix barre=Scrollbar(cadrelisteClasses) barre.grid(row=0,column=1) barre.config(command = listeClasses.yview) listeClasses.config(yscrollcommand=barre.set) ###pages # grille pour les onglets et positionnement en haut à gauche onglets = ttk.Notebook(accueil) onglets.grid(row = 1, column = 0, columnspan = 3, sticky = W) # pages page1 = ttk.Frame(onglets) onglets.add(page1, text='Le cycle Course et Relai') page2 = ttk.Frame(onglets) onglets.add(page2, text='Renseigner mes performances') page3 = ttk.Frame(onglets) onglets.add(page3, text='Résultats') ###page 1 # texte page 1 #page1.grid_columnconfigure(0, weight=1) #page1.grid_rowconfigure(0, weight=1) #texte = Label(page1,text=texteTuto) #texte.pack(expand=1, fill=Y) #texte.configure(font=("Times New Roman", 18, "italic")) texteaccueil = Label(page1, text=texteTuto) texteaccueil.pack(fill=BOTH) ### page 2 cadreTexte = Frame(page2, background = 'PeachPuff', bd = 10) cadreTexte.pack(side=TOP) separateur = Frame(page2, height=3, bd=1, relief=SUNKEN) separateur.pack(fill=X, padx=5, pady=5) cadre = Frame(page2, background = 'PeachPuff', bd=10) cadre.pack() texte = Label(cadreTexte, text='Une fois vos performances effectuées et chronométrées, cliquez ci-dessous et suivez les instructions.', height=5, width=60) texte.pack() boutonPerfClasse=Button(cadre, text="Renseigner mes performances individuelles et de groupe",cursor='plus', command=choisir_classe) boutonPerfClasse.pack() ###page 3 cadreTexte = Frame(page3, background = 'PeachPuff', bd = 10) cadreTexte.pack(side=TOP) separateur = Frame(page3, height=3, bd=1, relief=SUNKEN) separateur.pack(fill=X, padx=5, pady=5) cadre = Frame(page3, background = 'PeachPuff', bd=10) cadre.pack() texte = Label(cadreTexte, text='Ici consultez vos performances archivées.', height=5, width=60) texte.pack() boutonRechercheClasse=Button(cadre, text="Renseigner mes performances individuelles et de groupe",cursor='man', command=choisir_classe2) boutonRechercheClasse.pack() ###barre de menu # barre de menu barremenu = Menu(accueil) menu1 = Menu(barremenu, tearoff=0) menu1.add_command(label="Gérer classes", command=gerer_classes) menu1.add_command(label="Gérer groupes", command=gerer_groupes) menu1.add_command(label="Gérer élèves", command=gerer_eleves) barremenu.add_cascade(label="Gestion", menu=menu1) menu2 = Menu(barremenu, tearoff=0) menu2.add_command(label="Aide", command=marc) menu2.add_separator() menu2.add_command(label="Crédits", command=fenetreCredits) barremenu.add_cascade(label="Infos", menu=menu2) accueil.config(menu=barremenu) ### mainloop accueil.mainloop()
[/reveal]
<?xml version="1.0" encoding="UTF-8"> <classe> <groupe id="1"> <name>...</name> <collectif>...</collectif> <eleve id="54"/> <eleve id="2"> <id>54</id> </eleve> <eleve id="3"> <nom>...</nom> <prenom>...</prenom> <individuel>...</individuel> </eleve> </groupe> </classe>