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>
