ajout du TP de rentrée Z-Event
This commit is contained in:
@@ -0,0 +1,568 @@
|
|||||||
|
# Corrigé du TP Z-Event
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 1 : Le compteur (variables et types)
|
||||||
|
|
||||||
|
### 1.1. État de la cagnotte
|
||||||
|
|
||||||
|
**Question 1.1** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
pourcentage = round(collecte / objectif * 100, 2)
|
||||||
|
|
||||||
|
print(f"Objectif atteint à {pourcentage} %") # Objectif atteint à 73.5 %
|
||||||
|
```
|
||||||
|
|
||||||
|
**Question 1.2** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
reste = objectif - collecte
|
||||||
|
|
||||||
|
print(f"Il manque {reste} euros") # Il manque 662549.25 euros
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2. Le piège du compteur
|
||||||
|
|
||||||
|
**Question 1.3** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
don_1 = "25"
|
||||||
|
don_2 = "40"
|
||||||
|
|
||||||
|
total = don_1 + don_2
|
||||||
|
print(total) # affiche 2540 : sur deux chaînes, + est une concaténation
|
||||||
|
|
||||||
|
# Correction : convertir les chaînes en nombres avant d'additionner
|
||||||
|
total = int(don_1) + int(don_2)
|
||||||
|
print(total) # 65
|
||||||
|
```
|
||||||
|
|
||||||
|
## Partie 2 : L'annonce des dons (fonctions)
|
||||||
|
|
||||||
|
### 2.1. Formater un don
|
||||||
|
|
||||||
|
**Question 2.1** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def formater_don(pseudo, montant):
|
||||||
|
return f"{pseudo} vient de donner {montant} euros"
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(formater_don("Nyx_42", 5.0)) # Nyx_42 vient de donner 5.0 euros
|
||||||
|
print(formater_don("Marion_NSI", 100.0)) # Marion_NSI vient de donner 100.0 euros
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2. Repérer les gros dons
|
||||||
|
|
||||||
|
**Question 2.2** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def est_gros_don(montant, seuil=50):
|
||||||
|
return montant >= seuil
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(est_gros_don(120.0)) # True
|
||||||
|
print(est_gros_don(50.0)) # True
|
||||||
|
print(est_gros_don(20.0)) # False
|
||||||
|
print(est_gros_don(20.0, 10)) # True
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3. Les paliers
|
||||||
|
|
||||||
|
**Question 2.3** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def palier(total):
|
||||||
|
if total < 500000:
|
||||||
|
return "Départ"
|
||||||
|
elif total < 1000000:
|
||||||
|
return "Palier 1"
|
||||||
|
elif total < 2000000:
|
||||||
|
return "Palier 2"
|
||||||
|
else:
|
||||||
|
return "Objectif"
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(palier(120000)) # Départ
|
||||||
|
print(palier(750000)) # Palier 1
|
||||||
|
print(palier(1837450.75)) # Palier 2
|
||||||
|
print(palier(2500000)) # Objectif
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4. Le message complet
|
||||||
|
|
||||||
|
**Question 2.4** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def annonce_regie(pseudo, montant):
|
||||||
|
message = formater_don(pseudo, montant)
|
||||||
|
if est_gros_don(montant):
|
||||||
|
message = message + " [GROS DON]"
|
||||||
|
return message
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(annonce_regie("Poulpe3000", 2.0)) # Poulpe3000 vient de donner 2.0 euros
|
||||||
|
print(annonce_regie("Anonyme", 250.0)) # Anonyme vient de donner 250.0 euros [GROS DON]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Partie 3 : L'historique des dons (boucles et listes)
|
||||||
|
|
||||||
|
### 3.1. Le total collecté
|
||||||
|
|
||||||
|
**Question 3.1** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def total_dons(liste_dons):
|
||||||
|
total = 0
|
||||||
|
for don in liste_dons:
|
||||||
|
total = total + don["montant"]
|
||||||
|
return total
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(total_dons(dons)) # 1449.5
|
||||||
|
print(total_dons([])) # 0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2. Le don le plus élevé
|
||||||
|
|
||||||
|
**Question 3.2** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def plus_gros_don(liste_dons):
|
||||||
|
record = liste_dons[0] # on part du premier don, surtout pas de 0
|
||||||
|
for don in liste_dons:
|
||||||
|
if don["montant"] > record["montant"]:
|
||||||
|
record = don
|
||||||
|
return record
|
||||||
|
|
||||||
|
# Test
|
||||||
|
record = plus_gros_don(dons)
|
||||||
|
print(record["pseudo"], record["montant"]) # Anonyme 500.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3. Compter et filtrer
|
||||||
|
|
||||||
|
**Question 3.3** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def compter_gros_dons(liste_dons, seuil=50):
|
||||||
|
compteur = 0
|
||||||
|
for don in liste_dons:
|
||||||
|
if est_gros_don(don["montant"], seuil):
|
||||||
|
compteur = compteur + 1
|
||||||
|
return compteur
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(compter_gros_dons(dons)) # 7
|
||||||
|
print(compter_gros_dons(dons, 100)) # 4
|
||||||
|
```
|
||||||
|
|
||||||
|
**Question 3.4** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def donateurs(liste_dons):
|
||||||
|
pseudos = []
|
||||||
|
for don in liste_dons:
|
||||||
|
if don["pseudo"] not in pseudos:
|
||||||
|
pseudos.append(don["pseudo"])
|
||||||
|
return pseudos
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(donateurs(dons))
|
||||||
|
# ['Nyx_42', 'TitiLeBg', 'Camille_R', 'Poulpe3000', 'Anonyme', 'Sam_du_59', 'Lulu_2007', 'Marion_NSI', 'Kevin_B']
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4. Le bandeau des derniers dons
|
||||||
|
|
||||||
|
**Question 3.5** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def derniers_dons(liste_dons, n):
|
||||||
|
return liste_dons[-n:]
|
||||||
|
|
||||||
|
# Test
|
||||||
|
for don in derniers_dons(dons, 3):
|
||||||
|
print(don["heure"], don["pseudo"])
|
||||||
|
# 21:39 Anonyme
|
||||||
|
# 21:48 Poulpe3000
|
||||||
|
# 21:59 Marion_NSI
|
||||||
|
```
|
||||||
|
|
||||||
|
## Partie 4 : Le classement des chaînes (dictionnaires)
|
||||||
|
|
||||||
|
### 4.1. La cagnotte de chaque chaîne
|
||||||
|
|
||||||
|
**Question 4.1** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def cagnottes(liste_dons):
|
||||||
|
totaux = {}
|
||||||
|
for don in liste_dons:
|
||||||
|
streamer = don["streamer"]
|
||||||
|
if streamer in totaux:
|
||||||
|
totaux[streamer] = totaux[streamer] + don["montant"]
|
||||||
|
else:
|
||||||
|
totaux[streamer] = don["montant"]
|
||||||
|
return totaux
|
||||||
|
|
||||||
|
# Test
|
||||||
|
totaux = cagnottes(dons)
|
||||||
|
print(totaux["Antoine Daniel"]) # 115.0
|
||||||
|
print(totaux["Joueur du Grenier"]) # 140.0
|
||||||
|
print(len(totaux)) # 13
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2. La chaîne en tête
|
||||||
|
|
||||||
|
**Question 4.2** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def meilleure_chaine(totaux):
|
||||||
|
meilleur = None
|
||||||
|
for streamer in totaux:
|
||||||
|
if meilleur is None or totaux[streamer] > totaux[meilleur]:
|
||||||
|
meilleur = streamer
|
||||||
|
return meilleur
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(meilleure_chaine(cagnottes(dons))) # MisterMV
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3. Le détail des dons
|
||||||
|
|
||||||
|
**Question 4.3** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def dons_par_chaine(liste_dons):
|
||||||
|
detail = {}
|
||||||
|
for don in liste_dons:
|
||||||
|
streamer = don["streamer"]
|
||||||
|
if streamer not in detail:
|
||||||
|
detail[streamer] = []
|
||||||
|
detail[streamer].append(don["montant"])
|
||||||
|
return detail
|
||||||
|
|
||||||
|
# Test
|
||||||
|
detail = dons_par_chaine(dons)
|
||||||
|
print(detail["MisterMV"]) # [20.0, 12.0, 500.0]
|
||||||
|
print(detail["Baghera Jones"]) # [15.5, 5.0, 35.0]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4. Le podium
|
||||||
|
|
||||||
|
**Question 4.4** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def podium(totaux):
|
||||||
|
classement = sorted(totaux, key=lambda streamer: totaux[streamer], reverse=True)
|
||||||
|
return classement[:3]
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(podium(cagnottes(dons)))
|
||||||
|
# ['MisterMV', 'Domingo', 'Ultia']
|
||||||
|
```
|
||||||
|
|
||||||
|
## Partie 5 : Le planning et les raids (synthèse)
|
||||||
|
|
||||||
|
### 5.1. Qui est à l'antenne
|
||||||
|
|
||||||
|
**Question 5.1** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def a_l_antenne(planning, heure):
|
||||||
|
for streamer, debut, fin in planning:
|
||||||
|
if debut < fin:
|
||||||
|
if debut <= heure < fin:
|
||||||
|
return streamer
|
||||||
|
else:
|
||||||
|
# créneau à cheval sur minuit
|
||||||
|
if heure >= debut or heure < fin:
|
||||||
|
return streamer
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(a_l_antenne(planning, 19)) # Antoine Daniel
|
||||||
|
print(a_l_antenne(planning, 22)) # Joueur du Grenier
|
||||||
|
print(a_l_antenne(planning, 1)) # Baghera Jones
|
||||||
|
print(a_l_antenne(planning, 10)) # None
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2. Suivre la chaîne des raids
|
||||||
|
|
||||||
|
**Question 5.2** :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def suivre_raids(raids, depart):
|
||||||
|
parcours = [depart]
|
||||||
|
courant = depart
|
||||||
|
while raids.get(courant): # .get évite l'erreur si la clé est absente
|
||||||
|
courant = raids[courant][0]
|
||||||
|
parcours.append(courant)
|
||||||
|
return parcours
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(suivre_raids(raids, "Antoine Daniel"))
|
||||||
|
# ['Antoine Daniel', 'MisterMV', 'Joueur du Grenier', 'Baghera Jones', 'Ultia']
|
||||||
|
print(suivre_raids(raids, "Horty"))
|
||||||
|
# ['Horty', 'Sylvain Levy']
|
||||||
|
print(suivre_raids(raids, "Ultia"))
|
||||||
|
# ['Ultia']
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code complet fonctionnel
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Toutes ces données sont inventées pour l'exercice.
|
||||||
|
objectif = 2500000
|
||||||
|
collecte = 1837450.75
|
||||||
|
|
||||||
|
dons = [
|
||||||
|
{"pseudo": "Nyx_42", "streamer": "Antoine Daniel", "montant": 5.0, "heure": "18:04"},
|
||||||
|
{"pseudo": "TitiLeBg", "streamer": "MisterMV", "montant": 20.0, "heure": "18:11"},
|
||||||
|
{"pseudo": "Camille_R", "streamer": "Joueur du Grenier", "montant": 50.0, "heure": "18:23"},
|
||||||
|
{"pseudo": "Nyx_42", "streamer": "Baghera Jones", "montant": 15.5, "heure": "18:37"},
|
||||||
|
{"pseudo": "Poulpe3000", "streamer": "Horty", "montant": 2.0, "heure": "18:41"},
|
||||||
|
{"pseudo": "Anonyme", "streamer": "Ultia", "montant": 120.0, "heure": "18:52"},
|
||||||
|
{"pseudo": "Sam_du_59", "streamer": "Antoine Daniel", "montant": 10.0, "heure": "19:03"},
|
||||||
|
{"pseudo": "Camille_R", "streamer": "Sylvain Levy", "montant": 30.0, "heure": "19:14"},
|
||||||
|
{"pseudo": "Lulu_2007", "streamer": "ZeratoR", "montant": 8.5, "heure": "19:20"},
|
||||||
|
{"pseudo": "TitiLeBg", "streamer": "Etoiles", "montant": 45.0, "heure": "19:33"},
|
||||||
|
{"pseudo": "Marion_NSI", "streamer": "Joueur du Grenier", "montant": 75.0, "heure": "19:47"},
|
||||||
|
{"pseudo": "Poulpe3000", "streamer": "MisterMV", "montant": 12.0, "heure": "19:55"},
|
||||||
|
{"pseudo": "Anonyme", "streamer": "Domingo", "montant": 250.0, "heure": "20:08"},
|
||||||
|
{"pseudo": "Kevin_B", "streamer": "Baghera Jones", "montant": 5.0, "heure": "20:16"},
|
||||||
|
{"pseudo": "Nyx_42", "streamer": "Maghla", "montant": 60.0, "heure": "20:29"},
|
||||||
|
{"pseudo": "Sam_du_59", "streamer": "Horty", "montant": 3.5, "heure": "20:38"},
|
||||||
|
{"pseudo": "Marion_NSI", "streamer": "Antoine Daniel", "montant": 100.0, "heure": "20:44"},
|
||||||
|
{"pseudo": "Lulu_2007", "streamer": "Alphacast", "montant": 18.0, "heure": "20:57"},
|
||||||
|
{"pseudo": "Camille_R", "streamer": "Ultia", "montant": 40.0, "heure": "21:05"},
|
||||||
|
{"pseudo": "Kevin_B", "streamer": "Ponce", "montant": 22.5, "heure": "21:12"},
|
||||||
|
{"pseudo": "TitiLeBg", "streamer": "Joueur du Grenier", "montant": 15.0, "heure": "21:26"},
|
||||||
|
{"pseudo": "Anonyme", "streamer": "MisterMV", "montant": 500.0, "heure": "21:39"},
|
||||||
|
{"pseudo": "Poulpe3000", "streamer": "Sylvain Levy", "montant": 7.5, "heure": "21:48"},
|
||||||
|
{"pseudo": "Marion_NSI", "streamer": "Baghera Jones", "montant": 35.0, "heure": "21:59"},
|
||||||
|
]
|
||||||
|
|
||||||
|
planning = [
|
||||||
|
("Antoine Daniel", 18, 20),
|
||||||
|
("MisterMV", 20, 22),
|
||||||
|
("Joueur du Grenier", 22, 24),
|
||||||
|
("Baghera Jones", 0, 3),
|
||||||
|
("Ultia", 3, 6),
|
||||||
|
]
|
||||||
|
|
||||||
|
raids = {
|
||||||
|
"Antoine Daniel": ["MisterMV"],
|
||||||
|
"MisterMV": ["Joueur du Grenier", "Horty"],
|
||||||
|
"Joueur du Grenier": ["Baghera Jones"],
|
||||||
|
"Baghera Jones": ["Ultia"],
|
||||||
|
"Ultia": [],
|
||||||
|
"Horty": ["Sylvain Levy"],
|
||||||
|
"Sylvain Levy": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
pourcentage = round(collecte / objectif * 100, 2)
|
||||||
|
|
||||||
|
print(f"Objectif atteint à {pourcentage} %") # Objectif atteint à 73.5 %
|
||||||
|
|
||||||
|
reste = objectif - collecte
|
||||||
|
|
||||||
|
print(f"Il manque {reste} euros") # Il manque 662549.25 euros
|
||||||
|
|
||||||
|
don_1 = "25"
|
||||||
|
don_2 = "40"
|
||||||
|
|
||||||
|
total = don_1 + don_2
|
||||||
|
print(total) # affiche 2540 : sur deux chaînes, + est une concaténation
|
||||||
|
|
||||||
|
# Correction : convertir les chaînes en nombres avant d'additionner
|
||||||
|
total = int(don_1) + int(don_2)
|
||||||
|
print(total) # 65
|
||||||
|
|
||||||
|
def formater_don(pseudo, montant):
|
||||||
|
return f"{pseudo} vient de donner {montant} euros"
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(formater_don("Nyx_42", 5.0)) # Nyx_42 vient de donner 5.0 euros
|
||||||
|
print(formater_don("Marion_NSI", 100.0)) # Marion_NSI vient de donner 100.0 euros
|
||||||
|
|
||||||
|
def est_gros_don(montant, seuil=50):
|
||||||
|
return montant >= seuil
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(est_gros_don(120.0)) # True
|
||||||
|
print(est_gros_don(50.0)) # True
|
||||||
|
print(est_gros_don(20.0)) # False
|
||||||
|
print(est_gros_don(20.0, 10)) # True
|
||||||
|
|
||||||
|
def palier(total):
|
||||||
|
if total < 500000:
|
||||||
|
return "Départ"
|
||||||
|
elif total < 1000000:
|
||||||
|
return "Palier 1"
|
||||||
|
elif total < 2000000:
|
||||||
|
return "Palier 2"
|
||||||
|
else:
|
||||||
|
return "Objectif"
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(palier(120000)) # Départ
|
||||||
|
print(palier(750000)) # Palier 1
|
||||||
|
print(palier(1837450.75)) # Palier 2
|
||||||
|
print(palier(2500000)) # Objectif
|
||||||
|
|
||||||
|
def annonce_regie(pseudo, montant):
|
||||||
|
message = formater_don(pseudo, montant)
|
||||||
|
if est_gros_don(montant):
|
||||||
|
message = message + " [GROS DON]"
|
||||||
|
return message
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(annonce_regie("Poulpe3000", 2.0)) # Poulpe3000 vient de donner 2.0 euros
|
||||||
|
print(annonce_regie("Anonyme", 250.0)) # Anonyme vient de donner 250.0 euros [GROS DON]
|
||||||
|
|
||||||
|
def total_dons(liste_dons):
|
||||||
|
total = 0
|
||||||
|
for don in liste_dons:
|
||||||
|
total = total + don["montant"]
|
||||||
|
return total
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(total_dons(dons)) # 1449.5
|
||||||
|
print(total_dons([])) # 0
|
||||||
|
|
||||||
|
def plus_gros_don(liste_dons):
|
||||||
|
record = liste_dons[0] # on part du premier don, surtout pas de 0
|
||||||
|
for don in liste_dons:
|
||||||
|
if don["montant"] > record["montant"]:
|
||||||
|
record = don
|
||||||
|
return record
|
||||||
|
|
||||||
|
# Test
|
||||||
|
record = plus_gros_don(dons)
|
||||||
|
print(record["pseudo"], record["montant"]) # Anonyme 500.0
|
||||||
|
|
||||||
|
def compter_gros_dons(liste_dons, seuil=50):
|
||||||
|
compteur = 0
|
||||||
|
for don in liste_dons:
|
||||||
|
if est_gros_don(don["montant"], seuil):
|
||||||
|
compteur = compteur + 1
|
||||||
|
return compteur
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(compter_gros_dons(dons)) # 7
|
||||||
|
print(compter_gros_dons(dons, 100)) # 4
|
||||||
|
|
||||||
|
def donateurs(liste_dons):
|
||||||
|
pseudos = []
|
||||||
|
for don in liste_dons:
|
||||||
|
if don["pseudo"] not in pseudos:
|
||||||
|
pseudos.append(don["pseudo"])
|
||||||
|
return pseudos
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(donateurs(dons))
|
||||||
|
# ['Nyx_42', 'TitiLeBg', 'Camille_R', 'Poulpe3000', 'Anonyme', 'Sam_du_59', 'Lulu_2007', 'Marion_NSI', 'Kevin_B']
|
||||||
|
|
||||||
|
def derniers_dons(liste_dons, n):
|
||||||
|
return liste_dons[-n:]
|
||||||
|
|
||||||
|
# Test
|
||||||
|
for don in derniers_dons(dons, 3):
|
||||||
|
print(don["heure"], don["pseudo"])
|
||||||
|
# 21:39 Anonyme
|
||||||
|
# 21:48 Poulpe3000
|
||||||
|
# 21:59 Marion_NSI
|
||||||
|
|
||||||
|
def cagnottes(liste_dons):
|
||||||
|
totaux = {}
|
||||||
|
for don in liste_dons:
|
||||||
|
streamer = don["streamer"]
|
||||||
|
if streamer in totaux:
|
||||||
|
totaux[streamer] = totaux[streamer] + don["montant"]
|
||||||
|
else:
|
||||||
|
totaux[streamer] = don["montant"]
|
||||||
|
return totaux
|
||||||
|
|
||||||
|
# Test
|
||||||
|
totaux = cagnottes(dons)
|
||||||
|
print(totaux["Antoine Daniel"]) # 115.0
|
||||||
|
print(totaux["Joueur du Grenier"]) # 140.0
|
||||||
|
print(len(totaux)) # 13
|
||||||
|
|
||||||
|
def meilleure_chaine(totaux):
|
||||||
|
meilleur = None
|
||||||
|
for streamer in totaux:
|
||||||
|
if meilleur is None or totaux[streamer] > totaux[meilleur]:
|
||||||
|
meilleur = streamer
|
||||||
|
return meilleur
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(meilleure_chaine(cagnottes(dons))) # MisterMV
|
||||||
|
|
||||||
|
def dons_par_chaine(liste_dons):
|
||||||
|
detail = {}
|
||||||
|
for don in liste_dons:
|
||||||
|
streamer = don["streamer"]
|
||||||
|
if streamer not in detail:
|
||||||
|
detail[streamer] = []
|
||||||
|
detail[streamer].append(don["montant"])
|
||||||
|
return detail
|
||||||
|
|
||||||
|
# Test
|
||||||
|
detail = dons_par_chaine(dons)
|
||||||
|
print(detail["MisterMV"]) # [20.0, 12.0, 500.0]
|
||||||
|
print(detail["Baghera Jones"]) # [15.5, 5.0, 35.0]
|
||||||
|
|
||||||
|
def podium(totaux):
|
||||||
|
classement = sorted(totaux, key=lambda streamer: totaux[streamer], reverse=True)
|
||||||
|
return classement[:3]
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(podium(cagnottes(dons)))
|
||||||
|
# ['MisterMV', 'Domingo', 'Ultia']
|
||||||
|
|
||||||
|
def a_l_antenne(planning, heure):
|
||||||
|
for streamer, debut, fin in planning:
|
||||||
|
if debut < fin:
|
||||||
|
if debut <= heure < fin:
|
||||||
|
return streamer
|
||||||
|
else:
|
||||||
|
# créneau à cheval sur minuit
|
||||||
|
if heure >= debut or heure < fin:
|
||||||
|
return streamer
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(a_l_antenne(planning, 19)) # Antoine Daniel
|
||||||
|
print(a_l_antenne(planning, 22)) # Joueur du Grenier
|
||||||
|
print(a_l_antenne(planning, 1)) # Baghera Jones
|
||||||
|
print(a_l_antenne(planning, 10)) # None
|
||||||
|
|
||||||
|
def suivre_raids(raids, depart):
|
||||||
|
parcours = [depart]
|
||||||
|
courant = depart
|
||||||
|
while raids.get(courant): # .get évite l'erreur si la clé est absente
|
||||||
|
courant = raids[courant][0]
|
||||||
|
parcours.append(courant)
|
||||||
|
return parcours
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(suivre_raids(raids, "Antoine Daniel"))
|
||||||
|
# ['Antoine Daniel', 'MisterMV', 'Joueur du Grenier', 'Baghera Jones', 'Ultia']
|
||||||
|
print(suivre_raids(raids, "Horty"))
|
||||||
|
# ['Horty', 'Sylvain Levy']
|
||||||
|
print(suivre_raids(raids, "Ultia"))
|
||||||
|
# ['Ultia']
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Auteur : Florian Mathieu
|
||||||
|
|
||||||
|
Licence CC BY-SA
|
||||||
|
|
||||||
|
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||||
@@ -1,7 +1,55 @@
|
|||||||
# Révisions de rentrée : PERRIAND-7
|
# Révisions de rentrée : notes de séance
|
||||||
|
|
||||||
Activités de reprise pour la rentrée de Terminale, après la coupure estivale.
|
Deux activités de reprise pour la rentrée de Terminale, après la coupure estivale.
|
||||||
Fil rouge unique : le réveil d'une station orbitale après deux mois d'hibernation.
|
Elles couvrent les mêmes notions et sont interchangeables : Z-Event (marathon caritatif de
|
||||||
|
streaming) et PERRIAND-7 (station orbitale en avarie).
|
||||||
|
|
||||||
|
## Z-Event
|
||||||
|
|
||||||
|
| Fichier | Pour qui | Publié sur hub-docs |
|
||||||
|
|---|---|---|
|
||||||
|
| `TP_ZEvent.md` | Élèves | oui |
|
||||||
|
| `TP_ZEvent.ipynb` | Élèves | seulement si ajouté à `NOTEBOOK_ALLOWLIST` |
|
||||||
|
| `Corrige_TP_ZEvent.md` | Professeur | **oui par défaut** (c'est un `.md`), voir ci-dessous |
|
||||||
|
| `_generateur_zevent.py` | Professeur | non (`EXCLUDE_FILES`) |
|
||||||
|
|
||||||
|
Écrit au gabarit de tes TP : `## Contexte`, `## Objectifs pédagogiques`, `## Partie N`,
|
||||||
|
`**Question N.M**`, sorties attendues en commentaire à droite des `print`, `## Barème
|
||||||
|
indicatif` sur 20, auteur et licence. Cinq parties, dix-huit questions, environ deux heures.
|
||||||
|
|
||||||
|
**Le contexte factuel est volontairement prudent.** Le TP ne dit rien de l'édition en cours :
|
||||||
|
ni montant, ni association, ni participants réels. Seuls figurent des éléments stables
|
||||||
|
(l'événement existe depuis 2016, créé par ZeratoR et Dach). Toutes les données manipulées
|
||||||
|
sont inventées, et un encadré le dit explicitement aux élèves dès le contexte. Les streamers
|
||||||
|
cités ne servent que de noms dans un jeu de données fictif.
|
||||||
|
|
||||||
|
**Deux décisions de publication à prendre** avant de pousser :
|
||||||
|
- `Corrige_TP_ZEvent.md` sera publié automatiquement sur hub-docs, comme tous tes autres
|
||||||
|
`Corrige_TP_*.md`. Le `robots.txt` le désindexe des moteurs de recherche, mais il reste
|
||||||
|
accessible depuis la navigation du site. Si tu ne veux pas ça pour demain, il faut soit
|
||||||
|
l'ajouter temporairement à `EXCLUDE_FILES`, soit ne pas le pousser tout de suite.
|
||||||
|
- `TP_ZEvent.ipynb` ne sera **pas** publié tant qu'il n'est pas dans
|
||||||
|
`NOTEBOOK_ALLOWLIST["terminale"]`. Sans ça, les élèves n'auront que la version Markdown
|
||||||
|
en ligne, et le choix de format annoncé dans le README n'existera pas.
|
||||||
|
|
||||||
|
### Points de vigilance
|
||||||
|
|
||||||
|
- **Question 1.3** : `"25" + "40"` donne `"2540"`. Leur faire exécuter avant d'expliquer.
|
||||||
|
- **Question 3.2** : l'initialisation de l'accumulateur avec `liste[0]` et non `0` est le
|
||||||
|
point qui coince le plus. C'est la question 2 de la synthèse.
|
||||||
|
- **Question 5.1** : le créneau de Baghera Jones est à cheval sur minuit, donc `debut > fin`.
|
||||||
|
C'est volontaire, et c'est le seul endroit du TP qui demande de distinguer deux cas.
|
||||||
|
- **Question 5.2** : parcours d'une liste d'adjacence. La question 4 de la synthèse pose le
|
||||||
|
problème du cycle sans demander de le résoudre, c'est le pont vers le chapitre Graphes.
|
||||||
|
|
||||||
|
### Barème
|
||||||
|
|
||||||
|
Réparti sur 20 dans l'énoncé. Les parties 1 à 3 pèsent 13 points : un élève qui a décroché
|
||||||
|
pendant l'été peut valider la moitié du TP sans toucher aux dictionnaires.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PERRIAND-7
|
||||||
|
|
||||||
| Fichier | Pour qui | Publié sur hub-docs |
|
| Fichier | Pour qui | Publié sur hub-docs |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -93,9 +141,14 @@ Les deux notebooks sont produits par un script unique (énoncé et corrigé part
|
|||||||
même source, ce qui évite qu'ils divergent) :
|
même source, ce qui évite qu'ils divergent) :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 _generateur.py
|
python3 _generateur.py # PERRIAND-7
|
||||||
|
python3 _generateur_zevent.py # Z-Event
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Pour Z-Event, les sorties attendues affichées en commentaire ne sont pas écrites à la main :
|
||||||
|
le générateur exécute les solutions de référence et injecte les valeurs obtenues. Modifier
|
||||||
|
un montant dans le jeu de données met donc à jour tous les résultats de l'énoncé.
|
||||||
|
|
||||||
Modifier un exercice dans `_generateur.py` puis relancer met à jour les deux notebooks.
|
Modifier un exercice dans `_generateur.py` puis relancer met à jour les deux notebooks.
|
||||||
|
|
||||||
Attention : `_generateur.py` contient le corrigé en clair, et `build_docs.py` publie les
|
Attention : `_generateur.py` contient le corrigé en clair, et `build_docs.py` publie les
|
||||||
|
|||||||
+23
-22
@@ -1,34 +1,35 @@
|
|||||||
# Révisions de rentrée : PERRIAND-7
|
# Révisions de rentrée
|
||||||
|
|
||||||
Activité de reprise, à faire en début d'année de Terminale.
|
Deux activités de reprise, à faire en début d'année de Terminale. Elles couvrent les mêmes
|
||||||
|
notions de Première : variables, fonctions, boucles, listes, dictionnaires. Prenez celle
|
||||||
|
que vous voulez, elles sont indépendantes.
|
||||||
|
|
||||||
La station orbitale PERRIAND-7 sort de deux mois d'hibernation et ses programmes de bord
|
Rien de nouveau là-dedans : tout a été vu l'an dernier. L'objectif est de remettre le pied
|
||||||
ne répondent plus correctement. À vous de les réveiller, un module à la fois.
|
à l'étrier avant d'attaquer les chapitres de Terminale.
|
||||||
|
|
||||||
## Ce qu'on révise
|
## Z-Event : la régie de données d'un marathon caritatif
|
||||||
|
|
||||||
| Module | Notion |
|
Vous êtes bénévole à la régie d'un marathon caritatif de streaming. Vous écrivez les outils
|
||||||
|---|---|
|
Python qui alimentent le compteur de dons, les classements par chaîne et le planning.
|
||||||
| 1. Le réacteur | variables, affectation, mutabilité |
|
|
||||||
| 2. Les protocoles | fonctions, paramètres, `return` |
|
|
||||||
| 3. Le balayage | boucles `for` et `while` |
|
|
||||||
| 4. La soute | listes, listes de listes |
|
|
||||||
| 5. L'équipage | dictionnaires |
|
|
||||||
| 6. Sortie d'orbite | synthèse |
|
|
||||||
|
|
||||||
Rien de nouveau : tout a été vu en Première. Mais chaque notion révisée ici resservira
|
- [Énoncé au format Markdown](TP_ZEvent.md)
|
||||||
directement cette année, en récursivité, en POO, sur les arbres et sur les graphes.
|
- [Énoncé au format notebook](TP_ZEvent.ipynb)
|
||||||
|
|
||||||
## Le notebook
|
Le TP existe dans les deux formats, au choix. Le contenu est identique.
|
||||||
|
|
||||||
[PERRIAND-7_Reveil_des_systemes.ipynb](PERRIAND-7_Reveil_des_systemes.ipynb)
|
## PERRIAND-7 : le réveil d'une station orbitale
|
||||||
|
|
||||||
Ouvrable sur [Basthon](https://basthon.fr), Jupyter ou VS Code. Aucune installation,
|
Une station spatiale sort de deux mois d'hibernation et ses programmes de bord ne répondent
|
||||||
aucun fichier annexe. Chaque exercice est accompagné de ses tests : si `OK` s'affiche,
|
plus. Vous les réparez, module par module.
|
||||||
c'est gagné.
|
|
||||||
|
|
||||||
Les modules sont indépendants. Chaque module commence par une cellule SECOURS qui remet
|
- [Notebook](PERRIAND-7_Reveil_des_systemes.ipynb)
|
||||||
en place ses données : vous pouvez passer au suivant sans avoir fini le précédent.
|
|
||||||
|
Chaque exercice est accompagné de ses tests : si `OK` s'affiche, c'est gagné. Les modules
|
||||||
|
sont indépendants, chacun commence par une cellule SECOURS qui remet en place ses données.
|
||||||
|
|
||||||
|
## Comment ouvrir un notebook
|
||||||
|
|
||||||
|
[Basthon](https://basthon.fr), Jupyter ou VS Code. Aucune installation, aucun fichier annexe.
|
||||||
|
|
||||||
---
|
---
|
||||||
*Lycée Charlotte Perriand, NSI Terminale, Licence CC BY-SA 4.0*
|
*Lycée Charlotte Perriand, NSI Terminale, Licence CC BY-SA 4.0*
|
||||||
|
|||||||
@@ -0,0 +1,857 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "bf05817a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# TP : Z-Event - La régie de données d'un marathon caritatif\n",
|
||||||
|
"\n",
|
||||||
|
"> **Thème** : Révisions Python - variables, fonctions, boucles, listes, dictionnaires\n",
|
||||||
|
"\n",
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Contexte\n",
|
||||||
|
"\n",
|
||||||
|
"Depuis 2016, le **Z-Event** réunit chaque année des dizaines de streamers francophones\n",
|
||||||
|
"pendant plusieurs jours d'affilée, dans un même lieu, pour récolter des dons au profit\n",
|
||||||
|
"d'une association. L'événement a été créé par **ZeratoR** et **Dach**. Le principe est\n",
|
||||||
|
"simple : les spectateurs donnent, les streamers relèvent des défis, et un compteur géant\n",
|
||||||
|
"affiche la cagnotte en direct.\n",
|
||||||
|
"\n",
|
||||||
|
"Derrière ce compteur, il y a du code. Chaque don qui tombe doit être enregistré, additionné,\n",
|
||||||
|
"attribué à la chaîne sur laquelle il a été fait, comparé aux paliers annoncés, puis réaffiché\n",
|
||||||
|
"en moins d'une seconde sur tous les écrans. C'est ce travail que vous allez faire ici.\n",
|
||||||
|
"\n",
|
||||||
|
"Vous êtes bénévole à la **régie de données** de l'événement. Votre mission : écrire les\n",
|
||||||
|
"outils Python qui alimentent le compteur et les classements.\n",
|
||||||
|
"\n",
|
||||||
|
"> Les données de ce TP (montants, pseudos, horaires, cagnottes) sont **entièrement inventées**\n",
|
||||||
|
"> pour l'exercice. Elles ne correspondent à aucune édition réelle du Z-Event.\n",
|
||||||
|
"\n",
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Objectifs pédagogiques\n",
|
||||||
|
"\n",
|
||||||
|
"- Manipuler des variables et reconnaître une erreur de type\n",
|
||||||
|
"- Écrire des fonctions qui **renvoient** une valeur au lieu de l'afficher\n",
|
||||||
|
"- Parcourir une liste avec une boucle et accumuler un résultat\n",
|
||||||
|
"- Construire et exploiter des dictionnaires, y compris des dictionnaires de listes\n",
|
||||||
|
"- Réinvestir ces notions dans les chapitres de Terminale : POO, structures linéaires, graphes\n",
|
||||||
|
"\n",
|
||||||
|
"Aucune de ces notions n'est nouvelle : tout a été vu en Première. L'objectif est de les\n",
|
||||||
|
"remettre en service après la coupure estivale.\n",
|
||||||
|
"\n",
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Les données\n",
|
||||||
|
"\n",
|
||||||
|
"Copiez ce bloc en tête de votre fichier. Toutes les parties du TP s'appuient dessus."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "62c3fbf5",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Toutes ces données sont inventées pour l'exercice.\n",
|
||||||
|
"objectif = 2500000\n",
|
||||||
|
"collecte = 1837450.75\n",
|
||||||
|
"\n",
|
||||||
|
"dons = [\n",
|
||||||
|
" {\"pseudo\": \"Nyx_42\", \"streamer\": \"Antoine Daniel\", \"montant\": 5.0, \"heure\": \"18:04\"},\n",
|
||||||
|
" {\"pseudo\": \"TitiLeBg\", \"streamer\": \"MisterMV\", \"montant\": 20.0, \"heure\": \"18:11\"},\n",
|
||||||
|
" {\"pseudo\": \"Camille_R\", \"streamer\": \"Joueur du Grenier\", \"montant\": 50.0, \"heure\": \"18:23\"},\n",
|
||||||
|
" {\"pseudo\": \"Nyx_42\", \"streamer\": \"Baghera Jones\", \"montant\": 15.5, \"heure\": \"18:37\"},\n",
|
||||||
|
" {\"pseudo\": \"Poulpe3000\", \"streamer\": \"Horty\", \"montant\": 2.0, \"heure\": \"18:41\"},\n",
|
||||||
|
" {\"pseudo\": \"Anonyme\", \"streamer\": \"Ultia\", \"montant\": 120.0, \"heure\": \"18:52\"},\n",
|
||||||
|
" {\"pseudo\": \"Sam_du_59\", \"streamer\": \"Antoine Daniel\", \"montant\": 10.0, \"heure\": \"19:03\"},\n",
|
||||||
|
" {\"pseudo\": \"Camille_R\", \"streamer\": \"Sylvain Levy\", \"montant\": 30.0, \"heure\": \"19:14\"},\n",
|
||||||
|
" {\"pseudo\": \"Lulu_2007\", \"streamer\": \"ZeratoR\", \"montant\": 8.5, \"heure\": \"19:20\"},\n",
|
||||||
|
" {\"pseudo\": \"TitiLeBg\", \"streamer\": \"Etoiles\", \"montant\": 45.0, \"heure\": \"19:33\"},\n",
|
||||||
|
" {\"pseudo\": \"Marion_NSI\", \"streamer\": \"Joueur du Grenier\", \"montant\": 75.0, \"heure\": \"19:47\"},\n",
|
||||||
|
" {\"pseudo\": \"Poulpe3000\", \"streamer\": \"MisterMV\", \"montant\": 12.0, \"heure\": \"19:55\"},\n",
|
||||||
|
" {\"pseudo\": \"Anonyme\", \"streamer\": \"Domingo\", \"montant\": 250.0, \"heure\": \"20:08\"},\n",
|
||||||
|
" {\"pseudo\": \"Kevin_B\", \"streamer\": \"Baghera Jones\", \"montant\": 5.0, \"heure\": \"20:16\"},\n",
|
||||||
|
" {\"pseudo\": \"Nyx_42\", \"streamer\": \"Maghla\", \"montant\": 60.0, \"heure\": \"20:29\"},\n",
|
||||||
|
" {\"pseudo\": \"Sam_du_59\", \"streamer\": \"Horty\", \"montant\": 3.5, \"heure\": \"20:38\"},\n",
|
||||||
|
" {\"pseudo\": \"Marion_NSI\", \"streamer\": \"Antoine Daniel\", \"montant\": 100.0, \"heure\": \"20:44\"},\n",
|
||||||
|
" {\"pseudo\": \"Lulu_2007\", \"streamer\": \"Alphacast\", \"montant\": 18.0, \"heure\": \"20:57\"},\n",
|
||||||
|
" {\"pseudo\": \"Camille_R\", \"streamer\": \"Ultia\", \"montant\": 40.0, \"heure\": \"21:05\"},\n",
|
||||||
|
" {\"pseudo\": \"Kevin_B\", \"streamer\": \"Ponce\", \"montant\": 22.5, \"heure\": \"21:12\"},\n",
|
||||||
|
" {\"pseudo\": \"TitiLeBg\", \"streamer\": \"Joueur du Grenier\", \"montant\": 15.0, \"heure\": \"21:26\"},\n",
|
||||||
|
" {\"pseudo\": \"Anonyme\", \"streamer\": \"MisterMV\", \"montant\": 500.0, \"heure\": \"21:39\"},\n",
|
||||||
|
" {\"pseudo\": \"Poulpe3000\", \"streamer\": \"Sylvain Levy\", \"montant\": 7.5, \"heure\": \"21:48\"},\n",
|
||||||
|
" {\"pseudo\": \"Marion_NSI\", \"streamer\": \"Baghera Jones\", \"montant\": 35.0, \"heure\": \"21:59\"},\n",
|
||||||
|
"]"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "bc90ce2a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Partie 1 : Le compteur (variables et types)\n",
|
||||||
|
"\n",
|
||||||
|
"### 1.1. État de la cagnotte"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "245368be",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 1.1** : Calculez dans une variable `pourcentage` la part de l'objectif déjà\n",
|
||||||
|
"atteinte, arrondie à deux décimales."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "2052888a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"pourcentage = # À compléter\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Objectif atteint à {pourcentage} %\") # Objectif atteint à 73.5 %"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "b97c5eaf",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 1.2** : Calculez dans une variable `reste` la somme qu'il manque encore pour\n",
|
||||||
|
"atteindre l'objectif."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "00b6e536",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"reste = # À compléter\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Il manque {reste} euros\") # Il manque 662549.25 euros"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "35235678",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 1.2. Le piège du compteur\n",
|
||||||
|
"\n",
|
||||||
|
"Le compteur du site reçoit les montants sous forme de **chaînes de caractères**, parce qu'ils\n",
|
||||||
|
"arrivent d'un formulaire web. Le code ci-dessous ne fait donc pas ce qu'on croit."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "729d870a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 1.3** : Exécutez ce code, observez le résultat, puis corrigez-le pour que\n",
|
||||||
|
"`total` contienne bien la somme des deux dons."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "0ba70c50",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"don_1 = \"25\"\n",
|
||||||
|
"don_2 = \"40\"\n",
|
||||||
|
"\n",
|
||||||
|
"total = don_1 + don_2\n",
|
||||||
|
"print(total) # affiche 2540 au lieu de 65\n",
|
||||||
|
"\n",
|
||||||
|
"# Correction :\n",
|
||||||
|
"total = # À compléter\n",
|
||||||
|
"print(total) # 65"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "ca07a1b6",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Partie 2 : L'annonce des dons (fonctions)\n",
|
||||||
|
"\n",
|
||||||
|
"Un don qui tombe doit être annoncé à l'écran. Ces fonctions produisent les messages.\n",
|
||||||
|
"\n",
|
||||||
|
"### 2.1. Formater un don"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2d6d0204",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 2.1** : Écrivez la fonction `formater_don(pseudo, montant)` qui **renvoie** la\n",
|
||||||
|
"chaîne d'annonce. Attention : elle doit la renvoyer, pas l'afficher."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "91af8ea0",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def formater_don(pseudo, montant):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(formater_don(\"Nyx_42\", 5.0)) # Nyx_42 vient de donner 5.0 euros\n",
|
||||||
|
"print(formater_don(\"Marion_NSI\", 100.0)) # Marion_NSI vient de donner 100.0 euros"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "dbccc201",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 2.2. Repérer les gros dons\n",
|
||||||
|
"\n",
|
||||||
|
"La régie déclenche une animation spéciale au-delà d'un certain montant."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "e5808117",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 2.2** : Écrivez `est_gros_don(montant, seuil)` qui renvoie `True` si le montant\n",
|
||||||
|
"est **supérieur ou égal** au seuil, `False` sinon. Le seuil vaut 50 par défaut."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "927dd827",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def est_gros_don(montant, seuil=50):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(est_gros_don(120.0)) # True\n",
|
||||||
|
"print(est_gros_don(50.0)) # True\n",
|
||||||
|
"print(est_gros_don(20.0)) # False\n",
|
||||||
|
"print(est_gros_don(20.0, 10)) # True"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "88a5c245",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 2.3. Les paliers\n",
|
||||||
|
"\n",
|
||||||
|
"Les organisateurs annoncent des paliers au fil de la collecte.\n",
|
||||||
|
"\n",
|
||||||
|
"| Cagnotte | Palier |\n",
|
||||||
|
"|----------|--------|\n",
|
||||||
|
"| moins de 500 000 | `\"Départ\"` |\n",
|
||||||
|
"| de 500 000 à 999 999 | `\"Palier 1\"` |\n",
|
||||||
|
"| de 1 000 000 à 1 999 999 | `\"Palier 2\"` |\n",
|
||||||
|
"| 2 000 000 et plus | `\"Objectif\"` |"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "c0f285d0",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 2.3** : Écrivez `palier(total)` qui renvoie le nom du palier atteint."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "5a353ce4",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def palier(total):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(palier(120000)) # Départ\n",
|
||||||
|
"print(palier(750000)) # Palier 1\n",
|
||||||
|
"print(palier(1837450.75)) # Palier 2\n",
|
||||||
|
"print(palier(2500000)) # Objectif"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "fd1db284",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 2.4. Le message complet"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "0eda16ce",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 2.4** : Écrivez `annonce_regie(pseudo, montant)` qui renvoie le message affiché\n",
|
||||||
|
"en régie. Votre fonction **doit appeler** `formater_don` et `est_gros_don` : ne recopiez pas\n",
|
||||||
|
"leur contenu.\n",
|
||||||
|
"\n",
|
||||||
|
"Le message se termine par `\" [GROS DON]\"` lorsque le montant déclenche l'animation."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "63490a01",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def annonce_regie(pseudo, montant):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(annonce_regie(\"Poulpe3000\", 2.0)) # Poulpe3000 vient de donner 2.0 euros\n",
|
||||||
|
"print(annonce_regie(\"Anonyme\", 250.0)) # Anonyme vient de donner 250.0 euros [GROS DON]"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2e4c7e7f",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Partie 3 : L'historique des dons (boucles et listes)\n",
|
||||||
|
"\n",
|
||||||
|
"La liste `dons` contient les vingt-quatre derniers dons enregistrés. Chaque don est un\n",
|
||||||
|
"dictionnaire à quatre clés : `pseudo`, `streamer`, `montant`, `heure`.\n",
|
||||||
|
"\n",
|
||||||
|
"### 3.1. Le total collecté"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "3c9df8f3",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 3.1** : Écrivez `total_dons(liste_dons)` qui renvoie la somme de tous les\n",
|
||||||
|
"montants. Utilisez une boucle et un accumulateur, pas la fonction `sum`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "b2e587a4",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def total_dons(liste_dons):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(total_dons(dons)) # 1449.5\n",
|
||||||
|
"print(total_dons([])) # 0"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "c65fb763",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.2. Le don le plus élevé"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "3d3882b8",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 3.2** : Écrivez `plus_gros_don(liste_dons)` qui renvoie le **dictionnaire** du\n",
|
||||||
|
"don le plus élevé. L'usage de `max` est interdit. On suppose la liste non vide."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "9eaac029",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def plus_gros_don(liste_dons):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"record = plus_gros_don(dons)\n",
|
||||||
|
"print(record[\"pseudo\"], record[\"montant\"]) # Anonyme 500.0"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "aa89e941",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.3. Compter et filtrer"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d357b858",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 3.3** : Écrivez `compter_gros_dons(liste_dons, seuil)` qui renvoie le nombre de\n",
|
||||||
|
"dons supérieurs ou égaux au seuil. Réutilisez `est_gros_don`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "4c02a2b9",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def compter_gros_dons(liste_dons, seuil=50):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(compter_gros_dons(dons)) # 7\n",
|
||||||
|
"print(compter_gros_dons(dons, 100)) # 4"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "fae9409f",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 3.4** : Écrivez `donateurs(liste_dons)` qui renvoie la liste des pseudos **sans\n",
|
||||||
|
"doublon**, dans l'ordre de leur premier don."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "b98464c0",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def donateurs(liste_dons):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(donateurs(dons))\n",
|
||||||
|
"# ['Nyx_42', 'TitiLeBg', 'Camille_R', 'Poulpe3000', 'Anonyme', 'Sam_du_59', 'Lulu_2007', 'Marion_NSI', 'Kevin_B']"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "87fd84e5",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.4. Le bandeau des derniers dons\n",
|
||||||
|
"\n",
|
||||||
|
"Le site n'affiche que les tout derniers dons reçus."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "a57d2849",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 3.5** : Écrivez `derniers_dons(liste_dons, n)` qui renvoie les `n` derniers dons\n",
|
||||||
|
"de la liste, en utilisant une **tranche**."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "769c9428",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def derniers_dons(liste_dons, n):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"for don in derniers_dons(dons, 3):\n",
|
||||||
|
" print(don[\"heure\"], don[\"pseudo\"])\n",
|
||||||
|
"# 21:39 Anonyme\n",
|
||||||
|
"# 21:48 Poulpe3000\n",
|
||||||
|
"# 21:59 Marion_NSI"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "9e3fe8d8",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Partie 4 : Le classement des chaînes (dictionnaires)\n",
|
||||||
|
"\n",
|
||||||
|
"Chaque don est attribué à la chaîne sur laquelle il a été fait. La régie tient à jour la\n",
|
||||||
|
"cagnotte de chaque streamer.\n",
|
||||||
|
"\n",
|
||||||
|
"### 4.1. La cagnotte de chaque chaîne"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "166e98fd",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 4.1** : Écrivez `cagnottes(liste_dons)` qui renvoie un dictionnaire associant à\n",
|
||||||
|
"chaque streamer le total des dons reçus sur sa chaîne."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "1c270111",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def cagnottes(liste_dons):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"totaux = cagnottes(dons)\n",
|
||||||
|
"print(totaux[\"Antoine Daniel\"]) # 115.0\n",
|
||||||
|
"print(totaux[\"Joueur du Grenier\"]) # 140.0\n",
|
||||||
|
"print(len(totaux)) # 13"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "9f6b6bf5",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 4.2. La chaîne en tête"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "a759ae20",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 4.2** : Écrivez `meilleure_chaine(totaux)` qui renvoie le nom du streamer dont\n",
|
||||||
|
"la cagnotte est la plus élevée.\n",
|
||||||
|
"\n",
|
||||||
|
"Rappel : `for cle in dictionnaire` parcourt les clés."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "0a6ce0d9",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def meilleure_chaine(totaux):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(meilleure_chaine(cagnottes(dons))) # MisterMV"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "a2ee2282",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 4.3. Le détail des dons\n",
|
||||||
|
"\n",
|
||||||
|
"On veut maintenant, pour chaque streamer, la **liste** des montants reçus et plus seulement\n",
|
||||||
|
"leur somme : un dictionnaire dont les valeurs sont des listes."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "b9eac959",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 4.3** : Écrivez `dons_par_chaine(liste_dons)` qui renvoie un dictionnaire\n",
|
||||||
|
"associant à chaque streamer la liste des montants reçus, dans l'ordre chronologique."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "d47e5375",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def dons_par_chaine(liste_dons):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"detail = dons_par_chaine(dons)\n",
|
||||||
|
"print(detail[\"MisterMV\"]) # [20.0, 12.0, 500.0]\n",
|
||||||
|
"print(detail[\"Baghera Jones\"]) # [15.5, 5.0, 35.0]"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "f5a46137",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 4.4. Le podium"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "ea80de46",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 4.4** : Écrivez `podium(totaux)` qui renvoie la liste des trois premiers\n",
|
||||||
|
"streamers, du plus gros total au plus petit.\n",
|
||||||
|
"\n",
|
||||||
|
"Indication : `sorted(totaux, key=..., reverse=True)` trie les clés selon un critère."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "262c0672",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def podium(totaux):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(podium(cagnottes(dons)))\n",
|
||||||
|
"# ['MisterMV', 'Domingo', 'Ultia']"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "4ebedc4c",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Partie 5 : Le planning et les raids (synthèse)\n",
|
||||||
|
"\n",
|
||||||
|
"Un **raid**, c'est lorsqu'un streamer envoie son public sur une autre chaîne à la fin de son\n",
|
||||||
|
"passage. Cette partie combine tout ce qui précède.\n",
|
||||||
|
"\n",
|
||||||
|
"Copiez ce second bloc de données à la suite du premier."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "2ed28b19",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"planning = [\n",
|
||||||
|
" (\"Antoine Daniel\", 18, 20),\n",
|
||||||
|
" (\"MisterMV\", 20, 22),\n",
|
||||||
|
" (\"Joueur du Grenier\", 22, 24),\n",
|
||||||
|
" (\"Baghera Jones\", 0, 3),\n",
|
||||||
|
" (\"Ultia\", 3, 6),\n",
|
||||||
|
"]\n",
|
||||||
|
"\n",
|
||||||
|
"raids = {\n",
|
||||||
|
" \"Antoine Daniel\": [\"MisterMV\"],\n",
|
||||||
|
" \"MisterMV\": [\"Joueur du Grenier\", \"Horty\"],\n",
|
||||||
|
" \"Joueur du Grenier\": [\"Baghera Jones\"],\n",
|
||||||
|
" \"Baghera Jones\": [\"Ultia\"],\n",
|
||||||
|
" \"Ultia\": [],\n",
|
||||||
|
" \"Horty\": [\"Sylvain Levy\"],\n",
|
||||||
|
" \"Sylvain Levy\": [],\n",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d741bfa1",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 5.1. Qui est à l'antenne\n",
|
||||||
|
"\n",
|
||||||
|
"Le planning est une liste de triplets `(streamer, heure_de_debut, heure_de_fin)`, en heures\n",
|
||||||
|
"entières sur vingt-quatre heures. Attention au créneau de Baghera Jones : il commence à\n",
|
||||||
|
"minuit, donc son heure de début est plus petite que celle de la personne qui la précède."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "18718573",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 5.1** : Écrivez `a_l_antenne(planning, heure)` qui renvoie le nom du streamer en\n",
|
||||||
|
"direct à cette heure, ou `None` si personne ne l'est.\n",
|
||||||
|
"\n",
|
||||||
|
"L'heure de début est incluse, l'heure de fin est exclue."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "9f1639da",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def a_l_antenne(planning, heure):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(a_l_antenne(planning, 19)) # Antoine Daniel\n",
|
||||||
|
"print(a_l_antenne(planning, 22)) # Joueur du Grenier\n",
|
||||||
|
"print(a_l_antenne(planning, 1)) # Baghera Jones\n",
|
||||||
|
"print(a_l_antenne(planning, 10)) # None"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "0dbf8608",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 5.2. Suivre la chaîne des raids\n",
|
||||||
|
"\n",
|
||||||
|
"Le dictionnaire `raids` associe à chaque streamer la liste de ceux vers qui il envoie son\n",
|
||||||
|
"public. Certains n'envoient personne : leur liste est vide."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "342c85a1",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Question 5.2** : Écrivez `suivre_raids(raids, depart)` qui renvoie la liste des chaînes\n",
|
||||||
|
"traversées en partant de `depart` et en suivant à chaque fois le **premier** raid, jusqu'à\n",
|
||||||
|
"tomber sur un streamer qui n'en fait aucun.\n",
|
||||||
|
"\n",
|
||||||
|
"Le point de départ fait partie du résultat."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"id": "67ef757e",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"def suivre_raids(raids, depart):\n",
|
||||||
|
" # À compléter\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"# Test\n",
|
||||||
|
"print(suivre_raids(raids, \"Antoine Daniel\"))\n",
|
||||||
|
"# ['Antoine Daniel', 'MisterMV', 'Joueur du Grenier', 'Baghera Jones', 'Ultia']\n",
|
||||||
|
"print(suivre_raids(raids, \"Horty\"))\n",
|
||||||
|
"# ['Horty', 'Sylvain Levy']\n",
|
||||||
|
"print(suivre_raids(raids, \"Ultia\"))\n",
|
||||||
|
"# ['Ultia']"
|
||||||
|
],
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "f66fcb63",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Questions de synthèse\n",
|
||||||
|
"\n",
|
||||||
|
"Répondez en quelques lignes, sans machine.\n",
|
||||||
|
"\n",
|
||||||
|
"1. À la question 1.3, `\"25\" + \"40\"` donne `\"2540\"`. Expliquez pourquoi Python ne signale\n",
|
||||||
|
" aucune erreur alors que le résultat est faux du point de vue de la régie.\n",
|
||||||
|
"\n",
|
||||||
|
"2. À la question 3.2, pourquoi initialise-t-on `record` avec le premier don de la liste\n",
|
||||||
|
" plutôt qu'avec un montant de 0 ?\n",
|
||||||
|
"\n",
|
||||||
|
"3. Aux questions 4.1 et 4.3, on parcourt la même liste de dons mais on ne construit pas la\n",
|
||||||
|
" même structure. Dans quel cas le dictionnaire de listes est-il préférable au dictionnaire\n",
|
||||||
|
" de totaux ?\n",
|
||||||
|
"\n",
|
||||||
|
"4. La question 5.2 s'arrête lorsqu'un streamer ne fait aucun raid. Que se passerait-il si\n",
|
||||||
|
" deux streamers se renvoyaient mutuellement leur public ? Comment modifieriez-vous la\n",
|
||||||
|
" fonction pour l'éviter ?\n",
|
||||||
|
"\n",
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Ce que vous venez de réviser\n",
|
||||||
|
"\n",
|
||||||
|
"| Partie | Notion | Chapitre de Terminale concerné |\n",
|
||||||
|
"|--------|--------|--------------------------------|\n",
|
||||||
|
"| 1 | Variables, types, conversions | POO, structures linéaires |\n",
|
||||||
|
"| 2 | Fonctions, `return`, paramètre par défaut | Récursivité, Modularité |\n",
|
||||||
|
"| 3 | Boucles, accumulateur, listes, tranches | Parcours d'arbres et de graphes, tri fusion |\n",
|
||||||
|
"| 4 | Dictionnaires, dictionnaires de listes | Graphes, programmation dynamique |\n",
|
||||||
|
"| 5 | Synthèse, parcours d'un enchaînement | Graphes, Pile et File |\n",
|
||||||
|
"\n",
|
||||||
|
"La question 5.2 est un parcours de graphe : `raids` est une **liste d'adjacence**, exactement\n",
|
||||||
|
"la structure que vous utiliserez au chapitre Graphes.\n",
|
||||||
|
"\n",
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"## Barème indicatif\n",
|
||||||
|
"\n",
|
||||||
|
"| Partie | Points |\n",
|
||||||
|
"|--------|--------|\n",
|
||||||
|
"| Partie 1 : Le compteur | 3 |\n",
|
||||||
|
"| Partie 2 : L'annonce des dons | 5 |\n",
|
||||||
|
"| Partie 3 : L'historique des dons | 5 |\n",
|
||||||
|
"| Partie 4 : Le classement des chaînes | 4 |\n",
|
||||||
|
"| Partie 5 : Le planning et les raids | 2 |\n",
|
||||||
|
"| Questions de synthèse | 1 |\n",
|
||||||
|
"| **Total** | **20** |\n",
|
||||||
|
"\n",
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"Auteur : Florian Mathieu\n",
|
||||||
|
"\n",
|
||||||
|
"Licence CC BY-SA\n",
|
||||||
|
"\n",
|
||||||
|
"<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\"><img alt=\"Licence Creative Commons\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-sa/4.0/88x31.png\" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\">Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 4.0 International</a>."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"name": "python",
|
||||||
|
"version": "3.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
@@ -0,0 +1,497 @@
|
|||||||
|
# TP : Z-Event - La régie de données d'un marathon caritatif
|
||||||
|
|
||||||
|
> **Thème** : Révisions Python - variables, fonctions, boucles, listes, dictionnaires
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contexte
|
||||||
|
|
||||||
|
Depuis 2016, le **Z-Event** réunit chaque année des dizaines de streamers francophones
|
||||||
|
pendant plusieurs jours d'affilée, dans un même lieu, pour récolter des dons au profit
|
||||||
|
d'une association. L'événement a été créé par **ZeratoR** et **Dach**. Le principe est
|
||||||
|
simple : les spectateurs donnent, les streamers relèvent des défis, et un compteur géant
|
||||||
|
affiche la cagnotte en direct.
|
||||||
|
|
||||||
|
Derrière ce compteur, il y a du code. Chaque don qui tombe doit être enregistré, additionné,
|
||||||
|
attribué à la chaîne sur laquelle il a été fait, comparé aux paliers annoncés, puis réaffiché
|
||||||
|
en moins d'une seconde sur tous les écrans. C'est ce travail que vous allez faire ici.
|
||||||
|
|
||||||
|
Vous êtes bénévole à la **régie de données** de l'événement. Votre mission : écrire les
|
||||||
|
outils Python qui alimentent le compteur et les classements.
|
||||||
|
|
||||||
|
> Les données de ce TP (montants, pseudos, horaires, cagnottes) sont **entièrement inventées**
|
||||||
|
> pour l'exercice. Elles ne correspondent à aucune édition réelle du Z-Event.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Objectifs pédagogiques
|
||||||
|
|
||||||
|
- Manipuler des variables et reconnaître une erreur de type
|
||||||
|
- Écrire des fonctions qui **renvoient** une valeur au lieu de l'afficher
|
||||||
|
- Parcourir une liste avec une boucle et accumuler un résultat
|
||||||
|
- Construire et exploiter des dictionnaires, y compris des dictionnaires de listes
|
||||||
|
- Réinvestir ces notions dans les chapitres de Terminale : POO, structures linéaires, graphes
|
||||||
|
|
||||||
|
Aucune de ces notions n'est nouvelle : tout a été vu en Première. L'objectif est de les
|
||||||
|
remettre en service après la coupure estivale.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Les données
|
||||||
|
|
||||||
|
Copiez ce bloc en tête de votre fichier. Toutes les parties du TP s'appuient dessus.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Toutes ces données sont inventées pour l'exercice.
|
||||||
|
objectif = 2500000
|
||||||
|
collecte = 1837450.75
|
||||||
|
|
||||||
|
dons = [
|
||||||
|
{"pseudo": "Nyx_42", "streamer": "Antoine Daniel", "montant": 5.0, "heure": "18:04"},
|
||||||
|
{"pseudo": "TitiLeBg", "streamer": "MisterMV", "montant": 20.0, "heure": "18:11"},
|
||||||
|
{"pseudo": "Camille_R", "streamer": "Joueur du Grenier", "montant": 50.0, "heure": "18:23"},
|
||||||
|
{"pseudo": "Nyx_42", "streamer": "Baghera Jones", "montant": 15.5, "heure": "18:37"},
|
||||||
|
{"pseudo": "Poulpe3000", "streamer": "Horty", "montant": 2.0, "heure": "18:41"},
|
||||||
|
{"pseudo": "Anonyme", "streamer": "Ultia", "montant": 120.0, "heure": "18:52"},
|
||||||
|
{"pseudo": "Sam_du_59", "streamer": "Antoine Daniel", "montant": 10.0, "heure": "19:03"},
|
||||||
|
{"pseudo": "Camille_R", "streamer": "Sylvain Levy", "montant": 30.0, "heure": "19:14"},
|
||||||
|
{"pseudo": "Lulu_2007", "streamer": "ZeratoR", "montant": 8.5, "heure": "19:20"},
|
||||||
|
{"pseudo": "TitiLeBg", "streamer": "Etoiles", "montant": 45.0, "heure": "19:33"},
|
||||||
|
{"pseudo": "Marion_NSI", "streamer": "Joueur du Grenier", "montant": 75.0, "heure": "19:47"},
|
||||||
|
{"pseudo": "Poulpe3000", "streamer": "MisterMV", "montant": 12.0, "heure": "19:55"},
|
||||||
|
{"pseudo": "Anonyme", "streamer": "Domingo", "montant": 250.0, "heure": "20:08"},
|
||||||
|
{"pseudo": "Kevin_B", "streamer": "Baghera Jones", "montant": 5.0, "heure": "20:16"},
|
||||||
|
{"pseudo": "Nyx_42", "streamer": "Maghla", "montant": 60.0, "heure": "20:29"},
|
||||||
|
{"pseudo": "Sam_du_59", "streamer": "Horty", "montant": 3.5, "heure": "20:38"},
|
||||||
|
{"pseudo": "Marion_NSI", "streamer": "Antoine Daniel", "montant": 100.0, "heure": "20:44"},
|
||||||
|
{"pseudo": "Lulu_2007", "streamer": "Alphacast", "montant": 18.0, "heure": "20:57"},
|
||||||
|
{"pseudo": "Camille_R", "streamer": "Ultia", "montant": 40.0, "heure": "21:05"},
|
||||||
|
{"pseudo": "Kevin_B", "streamer": "Ponce", "montant": 22.5, "heure": "21:12"},
|
||||||
|
{"pseudo": "TitiLeBg", "streamer": "Joueur du Grenier", "montant": 15.0, "heure": "21:26"},
|
||||||
|
{"pseudo": "Anonyme", "streamer": "MisterMV", "montant": 500.0, "heure": "21:39"},
|
||||||
|
{"pseudo": "Poulpe3000", "streamer": "Sylvain Levy", "montant": 7.5, "heure": "21:48"},
|
||||||
|
{"pseudo": "Marion_NSI", "streamer": "Baghera Jones", "montant": 35.0, "heure": "21:59"},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 1 : Le compteur (variables et types)
|
||||||
|
|
||||||
|
### 1.1. État de la cagnotte
|
||||||
|
|
||||||
|
**Question 1.1** : Calculez dans une variable `pourcentage` la part de l'objectif déjà
|
||||||
|
atteinte, arrondie à deux décimales.
|
||||||
|
|
||||||
|
```python
|
||||||
|
pourcentage = # À compléter
|
||||||
|
|
||||||
|
print(f"Objectif atteint à {pourcentage} %") # Objectif atteint à 73.5 %
|
||||||
|
```
|
||||||
|
|
||||||
|
**Question 1.2** : Calculez dans une variable `reste` la somme qu'il manque encore pour
|
||||||
|
atteindre l'objectif.
|
||||||
|
|
||||||
|
```python
|
||||||
|
reste = # À compléter
|
||||||
|
|
||||||
|
print(f"Il manque {reste} euros") # Il manque 662549.25 euros
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2. Le piège du compteur
|
||||||
|
|
||||||
|
Le compteur du site reçoit les montants sous forme de **chaînes de caractères**, parce qu'ils
|
||||||
|
arrivent d'un formulaire web. Le code ci-dessous ne fait donc pas ce qu'on croit.
|
||||||
|
|
||||||
|
**Question 1.3** : Exécutez ce code, observez le résultat, puis corrigez-le pour que
|
||||||
|
`total` contienne bien la somme des deux dons.
|
||||||
|
|
||||||
|
```python
|
||||||
|
don_1 = "25"
|
||||||
|
don_2 = "40"
|
||||||
|
|
||||||
|
total = don_1 + don_2
|
||||||
|
print(total) # affiche 2540 au lieu de 65
|
||||||
|
|
||||||
|
# Correction :
|
||||||
|
total = # À compléter
|
||||||
|
print(total) # 65
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 2 : L'annonce des dons (fonctions)
|
||||||
|
|
||||||
|
Un don qui tombe doit être annoncé à l'écran. Ces fonctions produisent les messages.
|
||||||
|
|
||||||
|
### 2.1. Formater un don
|
||||||
|
|
||||||
|
**Question 2.1** : Écrivez la fonction `formater_don(pseudo, montant)` qui **renvoie** la
|
||||||
|
chaîne d'annonce. Attention : elle doit la renvoyer, pas l'afficher.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def formater_don(pseudo, montant):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(formater_don("Nyx_42", 5.0)) # Nyx_42 vient de donner 5.0 euros
|
||||||
|
print(formater_don("Marion_NSI", 100.0)) # Marion_NSI vient de donner 100.0 euros
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2. Repérer les gros dons
|
||||||
|
|
||||||
|
La régie déclenche une animation spéciale au-delà d'un certain montant.
|
||||||
|
|
||||||
|
**Question 2.2** : Écrivez `est_gros_don(montant, seuil)` qui renvoie `True` si le montant
|
||||||
|
est **supérieur ou égal** au seuil, `False` sinon. Le seuil vaut 50 par défaut.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def est_gros_don(montant, seuil=50):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(est_gros_don(120.0)) # True
|
||||||
|
print(est_gros_don(50.0)) # True
|
||||||
|
print(est_gros_don(20.0)) # False
|
||||||
|
print(est_gros_don(20.0, 10)) # True
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3. Les paliers
|
||||||
|
|
||||||
|
Les organisateurs annoncent des paliers au fil de la collecte.
|
||||||
|
|
||||||
|
| Cagnotte | Palier |
|
||||||
|
|----------|--------|
|
||||||
|
| moins de 500 000 | `"Départ"` |
|
||||||
|
| de 500 000 à 999 999 | `"Palier 1"` |
|
||||||
|
| de 1 000 000 à 1 999 999 | `"Palier 2"` |
|
||||||
|
| 2 000 000 et plus | `"Objectif"` |
|
||||||
|
|
||||||
|
**Question 2.3** : Écrivez `palier(total)` qui renvoie le nom du palier atteint.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def palier(total):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(palier(120000)) # Départ
|
||||||
|
print(palier(750000)) # Palier 1
|
||||||
|
print(palier(1837450.75)) # Palier 2
|
||||||
|
print(palier(2500000)) # Objectif
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4. Le message complet
|
||||||
|
|
||||||
|
**Question 2.4** : Écrivez `annonce_regie(pseudo, montant)` qui renvoie le message affiché
|
||||||
|
en régie. Votre fonction **doit appeler** `formater_don` et `est_gros_don` : ne recopiez pas
|
||||||
|
leur contenu.
|
||||||
|
|
||||||
|
Le message se termine par `" [GROS DON]"` lorsque le montant déclenche l'animation.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def annonce_regie(pseudo, montant):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(annonce_regie("Poulpe3000", 2.0)) # Poulpe3000 vient de donner 2.0 euros
|
||||||
|
print(annonce_regie("Anonyme", 250.0)) # Anonyme vient de donner 250.0 euros [GROS DON]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 3 : L'historique des dons (boucles et listes)
|
||||||
|
|
||||||
|
La liste `dons` contient les vingt-quatre derniers dons enregistrés. Chaque don est un
|
||||||
|
dictionnaire à quatre clés : `pseudo`, `streamer`, `montant`, `heure`.
|
||||||
|
|
||||||
|
### 3.1. Le total collecté
|
||||||
|
|
||||||
|
**Question 3.1** : Écrivez `total_dons(liste_dons)` qui renvoie la somme de tous les
|
||||||
|
montants. Utilisez une boucle et un accumulateur, pas la fonction `sum`.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def total_dons(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(total_dons(dons)) # 1449.5
|
||||||
|
print(total_dons([])) # 0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2. Le don le plus élevé
|
||||||
|
|
||||||
|
**Question 3.2** : Écrivez `plus_gros_don(liste_dons)` qui renvoie le **dictionnaire** du
|
||||||
|
don le plus élevé. L'usage de `max` est interdit. On suppose la liste non vide.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def plus_gros_don(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
record = plus_gros_don(dons)
|
||||||
|
print(record["pseudo"], record["montant"]) # Anonyme 500.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3. Compter et filtrer
|
||||||
|
|
||||||
|
**Question 3.3** : Écrivez `compter_gros_dons(liste_dons, seuil)` qui renvoie le nombre de
|
||||||
|
dons supérieurs ou égaux au seuil. Réutilisez `est_gros_don`.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def compter_gros_dons(liste_dons, seuil=50):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(compter_gros_dons(dons)) # 7
|
||||||
|
print(compter_gros_dons(dons, 100)) # 4
|
||||||
|
```
|
||||||
|
|
||||||
|
**Question 3.4** : Écrivez `donateurs(liste_dons)` qui renvoie la liste des pseudos **sans
|
||||||
|
doublon**, dans l'ordre de leur premier don.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def donateurs(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(donateurs(dons))
|
||||||
|
# ['Nyx_42', 'TitiLeBg', 'Camille_R', 'Poulpe3000', 'Anonyme', 'Sam_du_59', 'Lulu_2007', 'Marion_NSI', 'Kevin_B']
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4. Le bandeau des derniers dons
|
||||||
|
|
||||||
|
Le site n'affiche que les tout derniers dons reçus.
|
||||||
|
|
||||||
|
**Question 3.5** : Écrivez `derniers_dons(liste_dons, n)` qui renvoie les `n` derniers dons
|
||||||
|
de la liste, en utilisant une **tranche**.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def derniers_dons(liste_dons, n):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
for don in derniers_dons(dons, 3):
|
||||||
|
print(don["heure"], don["pseudo"])
|
||||||
|
# 21:39 Anonyme
|
||||||
|
# 21:48 Poulpe3000
|
||||||
|
# 21:59 Marion_NSI
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 4 : Le classement des chaînes (dictionnaires)
|
||||||
|
|
||||||
|
Chaque don est attribué à la chaîne sur laquelle il a été fait. La régie tient à jour la
|
||||||
|
cagnotte de chaque streamer.
|
||||||
|
|
||||||
|
### 4.1. La cagnotte de chaque chaîne
|
||||||
|
|
||||||
|
**Question 4.1** : Écrivez `cagnottes(liste_dons)` qui renvoie un dictionnaire associant à
|
||||||
|
chaque streamer le total des dons reçus sur sa chaîne.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def cagnottes(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
totaux = cagnottes(dons)
|
||||||
|
print(totaux["Antoine Daniel"]) # 115.0
|
||||||
|
print(totaux["Joueur du Grenier"]) # 140.0
|
||||||
|
print(len(totaux)) # 13
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2. La chaîne en tête
|
||||||
|
|
||||||
|
**Question 4.2** : Écrivez `meilleure_chaine(totaux)` qui renvoie le nom du streamer dont
|
||||||
|
la cagnotte est la plus élevée.
|
||||||
|
|
||||||
|
Rappel : `for cle in dictionnaire` parcourt les clés.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def meilleure_chaine(totaux):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(meilleure_chaine(cagnottes(dons))) # MisterMV
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3. Le détail des dons
|
||||||
|
|
||||||
|
On veut maintenant, pour chaque streamer, la **liste** des montants reçus et plus seulement
|
||||||
|
leur somme : un dictionnaire dont les valeurs sont des listes.
|
||||||
|
|
||||||
|
**Question 4.3** : Écrivez `dons_par_chaine(liste_dons)` qui renvoie un dictionnaire
|
||||||
|
associant à chaque streamer la liste des montants reçus, dans l'ordre chronologique.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def dons_par_chaine(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
detail = dons_par_chaine(dons)
|
||||||
|
print(detail["MisterMV"]) # [20.0, 12.0, 500.0]
|
||||||
|
print(detail["Baghera Jones"]) # [15.5, 5.0, 35.0]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4. Le podium
|
||||||
|
|
||||||
|
**Question 4.4** : Écrivez `podium(totaux)` qui renvoie la liste des trois premiers
|
||||||
|
streamers, du plus gros total au plus petit.
|
||||||
|
|
||||||
|
Indication : `sorted(totaux, key=..., reverse=True)` trie les clés selon un critère.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def podium(totaux):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(podium(cagnottes(dons)))
|
||||||
|
# ['MisterMV', 'Domingo', 'Ultia']
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 5 : Le planning et les raids (synthèse)
|
||||||
|
|
||||||
|
Un **raid**, c'est lorsqu'un streamer envoie son public sur une autre chaîne à la fin de son
|
||||||
|
passage. Cette partie combine tout ce qui précède.
|
||||||
|
|
||||||
|
Copiez ce second bloc de données à la suite du premier.
|
||||||
|
|
||||||
|
```python
|
||||||
|
planning = [
|
||||||
|
("Antoine Daniel", 18, 20),
|
||||||
|
("MisterMV", 20, 22),
|
||||||
|
("Joueur du Grenier", 22, 24),
|
||||||
|
("Baghera Jones", 0, 3),
|
||||||
|
("Ultia", 3, 6),
|
||||||
|
]
|
||||||
|
|
||||||
|
raids = {
|
||||||
|
"Antoine Daniel": ["MisterMV"],
|
||||||
|
"MisterMV": ["Joueur du Grenier", "Horty"],
|
||||||
|
"Joueur du Grenier": ["Baghera Jones"],
|
||||||
|
"Baghera Jones": ["Ultia"],
|
||||||
|
"Ultia": [],
|
||||||
|
"Horty": ["Sylvain Levy"],
|
||||||
|
"Sylvain Levy": [],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.1. Qui est à l'antenne
|
||||||
|
|
||||||
|
Le planning est une liste de triplets `(streamer, heure_de_debut, heure_de_fin)`, en heures
|
||||||
|
entières sur vingt-quatre heures. Attention au créneau de Baghera Jones : il commence à
|
||||||
|
minuit, donc son heure de début est plus petite que celle de la personne qui la précède.
|
||||||
|
|
||||||
|
**Question 5.1** : Écrivez `a_l_antenne(planning, heure)` qui renvoie le nom du streamer en
|
||||||
|
direct à cette heure, ou `None` si personne ne l'est.
|
||||||
|
|
||||||
|
L'heure de début est incluse, l'heure de fin est exclue.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def a_l_antenne(planning, heure):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(a_l_antenne(planning, 19)) # Antoine Daniel
|
||||||
|
print(a_l_antenne(planning, 22)) # Joueur du Grenier
|
||||||
|
print(a_l_antenne(planning, 1)) # Baghera Jones
|
||||||
|
print(a_l_antenne(planning, 10)) # None
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2. Suivre la chaîne des raids
|
||||||
|
|
||||||
|
Le dictionnaire `raids` associe à chaque streamer la liste de ceux vers qui il envoie son
|
||||||
|
public. Certains n'envoient personne : leur liste est vide.
|
||||||
|
|
||||||
|
**Question 5.2** : Écrivez `suivre_raids(raids, depart)` qui renvoie la liste des chaînes
|
||||||
|
traversées en partant de `depart` et en suivant à chaque fois le **premier** raid, jusqu'à
|
||||||
|
tomber sur un streamer qui n'en fait aucun.
|
||||||
|
|
||||||
|
Le point de départ fait partie du résultat.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def suivre_raids(raids, depart):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(suivre_raids(raids, "Antoine Daniel"))
|
||||||
|
# ['Antoine Daniel', 'MisterMV', 'Joueur du Grenier', 'Baghera Jones', 'Ultia']
|
||||||
|
print(suivre_raids(raids, "Horty"))
|
||||||
|
# ['Horty', 'Sylvain Levy']
|
||||||
|
print(suivre_raids(raids, "Ultia"))
|
||||||
|
# ['Ultia']
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions de synthèse
|
||||||
|
|
||||||
|
Répondez en quelques lignes, sans machine.
|
||||||
|
|
||||||
|
1. À la question 1.3, `"25" + "40"` donne `"2540"`. Expliquez pourquoi Python ne signale
|
||||||
|
aucune erreur alors que le résultat est faux du point de vue de la régie.
|
||||||
|
|
||||||
|
2. À la question 3.2, pourquoi initialise-t-on `record` avec le premier don de la liste
|
||||||
|
plutôt qu'avec un montant de 0 ?
|
||||||
|
|
||||||
|
3. Aux questions 4.1 et 4.3, on parcourt la même liste de dons mais on ne construit pas la
|
||||||
|
même structure. Dans quel cas le dictionnaire de listes est-il préférable au dictionnaire
|
||||||
|
de totaux ?
|
||||||
|
|
||||||
|
4. La question 5.2 s'arrête lorsqu'un streamer ne fait aucun raid. Que se passerait-il si
|
||||||
|
deux streamers se renvoyaient mutuellement leur public ? Comment modifieriez-vous la
|
||||||
|
fonction pour l'éviter ?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ce que vous venez de réviser
|
||||||
|
|
||||||
|
| Partie | Notion | Chapitre de Terminale concerné |
|
||||||
|
|--------|--------|--------------------------------|
|
||||||
|
| 1 | Variables, types, conversions | POO, structures linéaires |
|
||||||
|
| 2 | Fonctions, `return`, paramètre par défaut | Récursivité, Modularité |
|
||||||
|
| 3 | Boucles, accumulateur, listes, tranches | Parcours d'arbres et de graphes, tri fusion |
|
||||||
|
| 4 | Dictionnaires, dictionnaires de listes | Graphes, programmation dynamique |
|
||||||
|
| 5 | Synthèse, parcours d'un enchaînement | Graphes, Pile et File |
|
||||||
|
|
||||||
|
La question 5.2 est un parcours de graphe : `raids` est une **liste d'adjacence**, exactement
|
||||||
|
la structure que vous utiliserez au chapitre Graphes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Barème indicatif
|
||||||
|
|
||||||
|
| Partie | Points |
|
||||||
|
|--------|--------|
|
||||||
|
| Partie 1 : Le compteur | 3 |
|
||||||
|
| Partie 2 : L'annonce des dons | 5 |
|
||||||
|
| Partie 3 : L'historique des dons | 5 |
|
||||||
|
| Partie 4 : Le classement des chaînes | 4 |
|
||||||
|
| Partie 5 : Le planning et les raids | 2 |
|
||||||
|
| Questions de synthèse | 1 |
|
||||||
|
| **Total** | **20** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Auteur : Florian Mathieu
|
||||||
|
|
||||||
|
Licence CC BY-SA
|
||||||
|
|
||||||
|
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||||
@@ -0,0 +1,862 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Génère le TP Z-Event : énoncé Markdown, corrigé Markdown et notebook élève.
|
||||||
|
|
||||||
|
Source unique : les trois fichiers sortent d'ici, ils ne peuvent pas diverger.
|
||||||
|
Les sorties attendues affichées dans les commentaires (# Test) ne sont PAS écrites
|
||||||
|
à la main : elles sont calculées en exécutant les solutions de référence au moment
|
||||||
|
de la génération.
|
||||||
|
"""
|
||||||
|
import io, json, os, uuid
|
||||||
|
|
||||||
|
DEST = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
LICENCE = """Auteur : Florian Mathieu
|
||||||
|
|
||||||
|
Licence CC BY-SA
|
||||||
|
|
||||||
|
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 4.0 International</a>."""
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- LES DONNÉES
|
||||||
|
|
||||||
|
DONNEES_SRC = '''# Toutes ces données sont inventées pour l'exercice.
|
||||||
|
objectif = 2500000
|
||||||
|
collecte = 1837450.75
|
||||||
|
|
||||||
|
dons = [
|
||||||
|
{"pseudo": "Nyx_42", "streamer": "Antoine Daniel", "montant": 5.0, "heure": "18:04"},
|
||||||
|
{"pseudo": "TitiLeBg", "streamer": "MisterMV", "montant": 20.0, "heure": "18:11"},
|
||||||
|
{"pseudo": "Camille_R", "streamer": "Joueur du Grenier", "montant": 50.0, "heure": "18:23"},
|
||||||
|
{"pseudo": "Nyx_42", "streamer": "Baghera Jones", "montant": 15.5, "heure": "18:37"},
|
||||||
|
{"pseudo": "Poulpe3000", "streamer": "Horty", "montant": 2.0, "heure": "18:41"},
|
||||||
|
{"pseudo": "Anonyme", "streamer": "Ultia", "montant": 120.0, "heure": "18:52"},
|
||||||
|
{"pseudo": "Sam_du_59", "streamer": "Antoine Daniel", "montant": 10.0, "heure": "19:03"},
|
||||||
|
{"pseudo": "Camille_R", "streamer": "Sylvain Levy", "montant": 30.0, "heure": "19:14"},
|
||||||
|
{"pseudo": "Lulu_2007", "streamer": "ZeratoR", "montant": 8.5, "heure": "19:20"},
|
||||||
|
{"pseudo": "TitiLeBg", "streamer": "Etoiles", "montant": 45.0, "heure": "19:33"},
|
||||||
|
{"pseudo": "Marion_NSI", "streamer": "Joueur du Grenier", "montant": 75.0, "heure": "19:47"},
|
||||||
|
{"pseudo": "Poulpe3000", "streamer": "MisterMV", "montant": 12.0, "heure": "19:55"},
|
||||||
|
{"pseudo": "Anonyme", "streamer": "Domingo", "montant": 250.0, "heure": "20:08"},
|
||||||
|
{"pseudo": "Kevin_B", "streamer": "Baghera Jones", "montant": 5.0, "heure": "20:16"},
|
||||||
|
{"pseudo": "Nyx_42", "streamer": "Maghla", "montant": 60.0, "heure": "20:29"},
|
||||||
|
{"pseudo": "Sam_du_59", "streamer": "Horty", "montant": 3.5, "heure": "20:38"},
|
||||||
|
{"pseudo": "Marion_NSI", "streamer": "Antoine Daniel", "montant": 100.0, "heure": "20:44"},
|
||||||
|
{"pseudo": "Lulu_2007", "streamer": "Alphacast", "montant": 18.0, "heure": "20:57"},
|
||||||
|
{"pseudo": "Camille_R", "streamer": "Ultia", "montant": 40.0, "heure": "21:05"},
|
||||||
|
{"pseudo": "Kevin_B", "streamer": "Ponce", "montant": 22.5, "heure": "21:12"},
|
||||||
|
{"pseudo": "TitiLeBg", "streamer": "Joueur du Grenier", "montant": 15.0, "heure": "21:26"},
|
||||||
|
{"pseudo": "Anonyme", "streamer": "MisterMV", "montant": 500.0, "heure": "21:39"},
|
||||||
|
{"pseudo": "Poulpe3000", "streamer": "Sylvain Levy", "montant": 7.5, "heure": "21:48"},
|
||||||
|
{"pseudo": "Marion_NSI", "streamer": "Baghera Jones", "montant": 35.0, "heure": "21:59"},
|
||||||
|
]'''
|
||||||
|
|
||||||
|
PLANNING_SRC = '''planning = [
|
||||||
|
("Antoine Daniel", 18, 20),
|
||||||
|
("MisterMV", 20, 22),
|
||||||
|
("Joueur du Grenier", 22, 24),
|
||||||
|
("Baghera Jones", 0, 3),
|
||||||
|
("Ultia", 3, 6),
|
||||||
|
]
|
||||||
|
|
||||||
|
raids = {
|
||||||
|
"Antoine Daniel": ["MisterMV"],
|
||||||
|
"MisterMV": ["Joueur du Grenier", "Horty"],
|
||||||
|
"Joueur du Grenier": ["Baghera Jones"],
|
||||||
|
"Baghera Jones": ["Ultia"],
|
||||||
|
"Ultia": [],
|
||||||
|
"Horty": ["Sylvain Levy"],
|
||||||
|
"Sylvain Levy": [],
|
||||||
|
}'''
|
||||||
|
|
||||||
|
# Exécution des données pour calculer les sorties attendues.
|
||||||
|
ENV = {}
|
||||||
|
exec(DONNEES_SRC, ENV)
|
||||||
|
exec(PLANNING_SRC, ENV)
|
||||||
|
dons, planning, raids = ENV["dons"], ENV["planning"], ENV["raids"]
|
||||||
|
objectif, collecte = ENV["objectif"], ENV["collecte"]
|
||||||
|
|
||||||
|
pourcentage_att = round(collecte / objectif * 100, 2)
|
||||||
|
reste_att = objectif - collecte
|
||||||
|
total_att = 0
|
||||||
|
for d in dons:
|
||||||
|
total_att += d["montant"]
|
||||||
|
record_att = dons[0]
|
||||||
|
for d in dons:
|
||||||
|
if d["montant"] > record_att["montant"]:
|
||||||
|
record_att = d
|
||||||
|
gros50_att = len([d for d in dons if d["montant"] >= 50])
|
||||||
|
gros100_att = len([d for d in dons if d["montant"] >= 100])
|
||||||
|
donateurs_att = []
|
||||||
|
for d in dons:
|
||||||
|
if d["pseudo"] not in donateurs_att:
|
||||||
|
donateurs_att.append(d["pseudo"])
|
||||||
|
trois_derniers = dons[-3:]
|
||||||
|
|
||||||
|
cagnottes_att = {}
|
||||||
|
for d in dons:
|
||||||
|
cagnottes_att[d["streamer"]] = cagnottes_att.get(d["streamer"], 0) + d["montant"]
|
||||||
|
meilleure_att = max(cagnottes_att, key=lambda s: cagnottes_att[s])
|
||||||
|
podium_att = sorted(cagnottes_att, key=lambda s: cagnottes_att[s], reverse=True)[:3]
|
||||||
|
detail_att = {}
|
||||||
|
for d in dons:
|
||||||
|
detail_att.setdefault(d["streamer"], []).append(d["montant"])
|
||||||
|
|
||||||
|
|
||||||
|
def antenne_att(h):
|
||||||
|
for nom, debut, fin in planning:
|
||||||
|
if debut < fin:
|
||||||
|
if debut <= h < fin:
|
||||||
|
return nom
|
||||||
|
else:
|
||||||
|
if h >= debut or h < fin:
|
||||||
|
return nom
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def raids_att(depart):
|
||||||
|
parcours = [depart]
|
||||||
|
courant = depart
|
||||||
|
while raids.get(courant):
|
||||||
|
courant = raids[courant][0]
|
||||||
|
parcours.append(courant)
|
||||||
|
return parcours
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- LES BLOCS
|
||||||
|
|
||||||
|
BLOCS = []
|
||||||
|
|
||||||
|
|
||||||
|
def md(texte, dans_corrige=False):
|
||||||
|
BLOCS.append(("md", texte, dans_corrige))
|
||||||
|
|
||||||
|
|
||||||
|
def code(source):
|
||||||
|
BLOCS.append(("code", source, source))
|
||||||
|
|
||||||
|
|
||||||
|
def question(num, enonce, eleve, solution):
|
||||||
|
BLOCS.append(("question", num, enonce, eleve, solution))
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- EN-TÊTE
|
||||||
|
|
||||||
|
md("""# TP : Z-Event - La régie de données d'un marathon caritatif
|
||||||
|
|
||||||
|
> **Thème** : Révisions Python - variables, fonctions, boucles, listes, dictionnaires
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contexte
|
||||||
|
|
||||||
|
Depuis 2016, le **Z-Event** réunit chaque année des dizaines de streamers francophones
|
||||||
|
pendant plusieurs jours d'affilée, dans un même lieu, pour récolter des dons au profit
|
||||||
|
d'une association. L'événement a été créé par **ZeratoR** et **Dach**. Le principe est
|
||||||
|
simple : les spectateurs donnent, les streamers relèvent des défis, et un compteur géant
|
||||||
|
affiche la cagnotte en direct.
|
||||||
|
|
||||||
|
Derrière ce compteur, il y a du code. Chaque don qui tombe doit être enregistré, additionné,
|
||||||
|
attribué à la chaîne sur laquelle il a été fait, comparé aux paliers annoncés, puis réaffiché
|
||||||
|
en moins d'une seconde sur tous les écrans. C'est ce travail que vous allez faire ici.
|
||||||
|
|
||||||
|
Vous êtes bénévole à la **régie de données** de l'événement. Votre mission : écrire les
|
||||||
|
outils Python qui alimentent le compteur et les classements.
|
||||||
|
|
||||||
|
> Les données de ce TP (montants, pseudos, horaires, cagnottes) sont **entièrement inventées**
|
||||||
|
> pour l'exercice. Elles ne correspondent à aucune édition réelle du Z-Event.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Objectifs pédagogiques
|
||||||
|
|
||||||
|
- Manipuler des variables et reconnaître une erreur de type
|
||||||
|
- Écrire des fonctions qui **renvoient** une valeur au lieu de l'afficher
|
||||||
|
- Parcourir une liste avec une boucle et accumuler un résultat
|
||||||
|
- Construire et exploiter des dictionnaires, y compris des dictionnaires de listes
|
||||||
|
- Réinvestir ces notions dans les chapitres de Terminale : POO, structures linéaires, graphes
|
||||||
|
|
||||||
|
Aucune de ces notions n'est nouvelle : tout a été vu en Première. L'objectif est de les
|
||||||
|
remettre en service après la coupure estivale.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Les données
|
||||||
|
|
||||||
|
Copiez ce bloc en tête de votre fichier. Toutes les parties du TP s'appuient dessus.
|
||||||
|
""")
|
||||||
|
|
||||||
|
code(DONNEES_SRC)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- PARTIE 1
|
||||||
|
|
||||||
|
md("""---
|
||||||
|
|
||||||
|
## Partie 1 : Le compteur (variables et types)
|
||||||
|
|
||||||
|
### 1.1. État de la cagnotte
|
||||||
|
""", dans_corrige=True)
|
||||||
|
|
||||||
|
question(
|
||||||
|
"1.1",
|
||||||
|
"""**Question 1.1** : Calculez dans une variable `pourcentage` la part de l'objectif déjà
|
||||||
|
atteinte, arrondie à deux décimales.""",
|
||||||
|
'''pourcentage = # À compléter
|
||||||
|
|
||||||
|
print(f"Objectif atteint à {pourcentage} %") # Objectif atteint à ''' + str(pourcentage_att) + " %",
|
||||||
|
'''pourcentage = round(collecte / objectif * 100, 2)
|
||||||
|
|
||||||
|
print(f"Objectif atteint à {pourcentage} %") # Objectif atteint à ''' + str(pourcentage_att) + " %",
|
||||||
|
)
|
||||||
|
|
||||||
|
question(
|
||||||
|
"1.2",
|
||||||
|
"""**Question 1.2** : Calculez dans une variable `reste` la somme qu'il manque encore pour
|
||||||
|
atteindre l'objectif.""",
|
||||||
|
'''reste = # À compléter
|
||||||
|
|
||||||
|
print(f"Il manque {reste} euros") # Il manque ''' + str(reste_att) + " euros",
|
||||||
|
'''reste = objectif - collecte
|
||||||
|
|
||||||
|
print(f"Il manque {reste} euros") # Il manque ''' + str(reste_att) + " euros",
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 1.2. Le piège du compteur
|
||||||
|
|
||||||
|
Le compteur du site reçoit les montants sous forme de **chaînes de caractères**, parce qu'ils
|
||||||
|
arrivent d'un formulaire web. Le code ci-dessous ne fait donc pas ce qu'on croit.
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"1.3",
|
||||||
|
"""**Question 1.3** : Exécutez ce code, observez le résultat, puis corrigez-le pour que
|
||||||
|
`total` contienne bien la somme des deux dons.""",
|
||||||
|
'''don_1 = "25"
|
||||||
|
don_2 = "40"
|
||||||
|
|
||||||
|
total = don_1 + don_2
|
||||||
|
print(total) # affiche 2540 au lieu de 65
|
||||||
|
|
||||||
|
# Correction :
|
||||||
|
total = # À compléter
|
||||||
|
print(total) # 65''',
|
||||||
|
'''don_1 = "25"
|
||||||
|
don_2 = "40"
|
||||||
|
|
||||||
|
total = don_1 + don_2
|
||||||
|
print(total) # affiche 2540 : sur deux chaînes, + est une concaténation
|
||||||
|
|
||||||
|
# Correction : convertir les chaînes en nombres avant d'additionner
|
||||||
|
total = int(don_1) + int(don_2)
|
||||||
|
print(total) # 65''',
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- PARTIE 2
|
||||||
|
|
||||||
|
md("""---
|
||||||
|
|
||||||
|
## Partie 2 : L'annonce des dons (fonctions)
|
||||||
|
|
||||||
|
Un don qui tombe doit être annoncé à l'écran. Ces fonctions produisent les messages.
|
||||||
|
|
||||||
|
### 2.1. Formater un don
|
||||||
|
""", dans_corrige=True)
|
||||||
|
|
||||||
|
question(
|
||||||
|
"2.1",
|
||||||
|
"""**Question 2.1** : Écrivez la fonction `formater_don(pseudo, montant)` qui **renvoie** la
|
||||||
|
chaîne d'annonce. Attention : elle doit la renvoyer, pas l'afficher.""",
|
||||||
|
'''def formater_don(pseudo, montant):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(formater_don("Nyx_42", 5.0)) # Nyx_42 vient de donner 5.0 euros
|
||||||
|
print(formater_don("Marion_NSI", 100.0)) # Marion_NSI vient de donner 100.0 euros''',
|
||||||
|
'''def formater_don(pseudo, montant):
|
||||||
|
return f"{pseudo} vient de donner {montant} euros"
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(formater_don("Nyx_42", 5.0)) # Nyx_42 vient de donner 5.0 euros
|
||||||
|
print(formater_don("Marion_NSI", 100.0)) # Marion_NSI vient de donner 100.0 euros''',
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 2.2. Repérer les gros dons
|
||||||
|
|
||||||
|
La régie déclenche une animation spéciale au-delà d'un certain montant.
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"2.2",
|
||||||
|
"""**Question 2.2** : Écrivez `est_gros_don(montant, seuil)` qui renvoie `True` si le montant
|
||||||
|
est **supérieur ou égal** au seuil, `False` sinon. Le seuil vaut 50 par défaut.""",
|
||||||
|
'''def est_gros_don(montant, seuil=50):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(est_gros_don(120.0)) # True
|
||||||
|
print(est_gros_don(50.0)) # True
|
||||||
|
print(est_gros_don(20.0)) # False
|
||||||
|
print(est_gros_don(20.0, 10)) # True''',
|
||||||
|
'''def est_gros_don(montant, seuil=50):
|
||||||
|
return montant >= seuil
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(est_gros_don(120.0)) # True
|
||||||
|
print(est_gros_don(50.0)) # True
|
||||||
|
print(est_gros_don(20.0)) # False
|
||||||
|
print(est_gros_don(20.0, 10)) # True''',
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 2.3. Les paliers
|
||||||
|
|
||||||
|
Les organisateurs annoncent des paliers au fil de la collecte.
|
||||||
|
|
||||||
|
| Cagnotte | Palier |
|
||||||
|
|----------|--------|
|
||||||
|
| moins de 500 000 | `"Départ"` |
|
||||||
|
| de 500 000 à 999 999 | `"Palier 1"` |
|
||||||
|
| de 1 000 000 à 1 999 999 | `"Palier 2"` |
|
||||||
|
| 2 000 000 et plus | `"Objectif"` |
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"2.3",
|
||||||
|
"""**Question 2.3** : Écrivez `palier(total)` qui renvoie le nom du palier atteint.""",
|
||||||
|
'''def palier(total):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(palier(120000)) # Départ
|
||||||
|
print(palier(750000)) # Palier 1
|
||||||
|
print(palier(1837450.75)) # Palier 2
|
||||||
|
print(palier(2500000)) # Objectif''',
|
||||||
|
'''def palier(total):
|
||||||
|
if total < 500000:
|
||||||
|
return "Départ"
|
||||||
|
elif total < 1000000:
|
||||||
|
return "Palier 1"
|
||||||
|
elif total < 2000000:
|
||||||
|
return "Palier 2"
|
||||||
|
else:
|
||||||
|
return "Objectif"
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(palier(120000)) # Départ
|
||||||
|
print(palier(750000)) # Palier 1
|
||||||
|
print(palier(1837450.75)) # Palier 2
|
||||||
|
print(palier(2500000)) # Objectif''',
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 2.4. Le message complet
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"2.4",
|
||||||
|
"""**Question 2.4** : Écrivez `annonce_regie(pseudo, montant)` qui renvoie le message affiché
|
||||||
|
en régie. Votre fonction **doit appeler** `formater_don` et `est_gros_don` : ne recopiez pas
|
||||||
|
leur contenu.
|
||||||
|
|
||||||
|
Le message se termine par `" [GROS DON]"` lorsque le montant déclenche l'animation.""",
|
||||||
|
'''def annonce_regie(pseudo, montant):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(annonce_regie("Poulpe3000", 2.0)) # Poulpe3000 vient de donner 2.0 euros
|
||||||
|
print(annonce_regie("Anonyme", 250.0)) # Anonyme vient de donner 250.0 euros [GROS DON]''',
|
||||||
|
'''def annonce_regie(pseudo, montant):
|
||||||
|
message = formater_don(pseudo, montant)
|
||||||
|
if est_gros_don(montant):
|
||||||
|
message = message + " [GROS DON]"
|
||||||
|
return message
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(annonce_regie("Poulpe3000", 2.0)) # Poulpe3000 vient de donner 2.0 euros
|
||||||
|
print(annonce_regie("Anonyme", 250.0)) # Anonyme vient de donner 250.0 euros [GROS DON]''',
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- PARTIE 3
|
||||||
|
|
||||||
|
md("""---
|
||||||
|
|
||||||
|
## Partie 3 : L'historique des dons (boucles et listes)
|
||||||
|
|
||||||
|
La liste `dons` contient les vingt-quatre derniers dons enregistrés. Chaque don est un
|
||||||
|
dictionnaire à quatre clés : `pseudo`, `streamer`, `montant`, `heure`.
|
||||||
|
|
||||||
|
### 3.1. Le total collecté
|
||||||
|
""", dans_corrige=True)
|
||||||
|
|
||||||
|
question(
|
||||||
|
"3.1",
|
||||||
|
"""**Question 3.1** : Écrivez `total_dons(liste_dons)` qui renvoie la somme de tous les
|
||||||
|
montants. Utilisez une boucle et un accumulateur, pas la fonction `sum`.""",
|
||||||
|
'''def total_dons(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(total_dons(dons)) # ''' + str(total_att) + '''
|
||||||
|
print(total_dons([])) # 0''',
|
||||||
|
'''def total_dons(liste_dons):
|
||||||
|
total = 0
|
||||||
|
for don in liste_dons:
|
||||||
|
total = total + don["montant"]
|
||||||
|
return total
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(total_dons(dons)) # ''' + str(total_att) + '''
|
||||||
|
print(total_dons([])) # 0''',
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 3.2. Le don le plus élevé
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"3.2",
|
||||||
|
"""**Question 3.2** : Écrivez `plus_gros_don(liste_dons)` qui renvoie le **dictionnaire** du
|
||||||
|
don le plus élevé. L'usage de `max` est interdit. On suppose la liste non vide.""",
|
||||||
|
'''def plus_gros_don(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
record = plus_gros_don(dons)
|
||||||
|
print(record["pseudo"], record["montant"]) # ''' + record_att["pseudo"] + " " + str(record_att["montant"]),
|
||||||
|
'''def plus_gros_don(liste_dons):
|
||||||
|
record = liste_dons[0] # on part du premier don, surtout pas de 0
|
||||||
|
for don in liste_dons:
|
||||||
|
if don["montant"] > record["montant"]:
|
||||||
|
record = don
|
||||||
|
return record
|
||||||
|
|
||||||
|
# Test
|
||||||
|
record = plus_gros_don(dons)
|
||||||
|
print(record["pseudo"], record["montant"]) # ''' + record_att["pseudo"] + " " + str(record_att["montant"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 3.3. Compter et filtrer
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"3.3",
|
||||||
|
"""**Question 3.3** : Écrivez `compter_gros_dons(liste_dons, seuil)` qui renvoie le nombre de
|
||||||
|
dons supérieurs ou égaux au seuil. Réutilisez `est_gros_don`.""",
|
||||||
|
'''def compter_gros_dons(liste_dons, seuil=50):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(compter_gros_dons(dons)) # ''' + str(gros50_att) + '''
|
||||||
|
print(compter_gros_dons(dons, 100)) # ''' + str(gros100_att),
|
||||||
|
'''def compter_gros_dons(liste_dons, seuil=50):
|
||||||
|
compteur = 0
|
||||||
|
for don in liste_dons:
|
||||||
|
if est_gros_don(don["montant"], seuil):
|
||||||
|
compteur = compteur + 1
|
||||||
|
return compteur
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(compter_gros_dons(dons)) # ''' + str(gros50_att) + '''
|
||||||
|
print(compter_gros_dons(dons, 100)) # ''' + str(gros100_att),
|
||||||
|
)
|
||||||
|
|
||||||
|
question(
|
||||||
|
"3.4",
|
||||||
|
"""**Question 3.4** : Écrivez `donateurs(liste_dons)` qui renvoie la liste des pseudos **sans
|
||||||
|
doublon**, dans l'ordre de leur premier don.""",
|
||||||
|
'''def donateurs(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(donateurs(dons))
|
||||||
|
# ''' + str(donateurs_att),
|
||||||
|
'''def donateurs(liste_dons):
|
||||||
|
pseudos = []
|
||||||
|
for don in liste_dons:
|
||||||
|
if don["pseudo"] not in pseudos:
|
||||||
|
pseudos.append(don["pseudo"])
|
||||||
|
return pseudos
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(donateurs(dons))
|
||||||
|
# ''' + str(donateurs_att),
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 3.4. Le bandeau des derniers dons
|
||||||
|
|
||||||
|
Le site n'affiche que les tout derniers dons reçus.
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"3.5",
|
||||||
|
"""**Question 3.5** : Écrivez `derniers_dons(liste_dons, n)` qui renvoie les `n` derniers dons
|
||||||
|
de la liste, en utilisant une **tranche**.""",
|
||||||
|
'''def derniers_dons(liste_dons, n):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
for don in derniers_dons(dons, 3):
|
||||||
|
print(don["heure"], don["pseudo"])
|
||||||
|
# ''' + "\n# ".join("%s %s" % (d["heure"], d["pseudo"]) for d in trois_derniers),
|
||||||
|
'''def derniers_dons(liste_dons, n):
|
||||||
|
return liste_dons[-n:]
|
||||||
|
|
||||||
|
# Test
|
||||||
|
for don in derniers_dons(dons, 3):
|
||||||
|
print(don["heure"], don["pseudo"])
|
||||||
|
# ''' + "\n# ".join("%s %s" % (d["heure"], d["pseudo"]) for d in trois_derniers),
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- PARTIE 4
|
||||||
|
|
||||||
|
md("""---
|
||||||
|
|
||||||
|
## Partie 4 : Le classement des chaînes (dictionnaires)
|
||||||
|
|
||||||
|
Chaque don est attribué à la chaîne sur laquelle il a été fait. La régie tient à jour la
|
||||||
|
cagnotte de chaque streamer.
|
||||||
|
|
||||||
|
### 4.1. La cagnotte de chaque chaîne
|
||||||
|
""", dans_corrige=True)
|
||||||
|
|
||||||
|
question(
|
||||||
|
"4.1",
|
||||||
|
"""**Question 4.1** : Écrivez `cagnottes(liste_dons)` qui renvoie un dictionnaire associant à
|
||||||
|
chaque streamer le total des dons reçus sur sa chaîne.""",
|
||||||
|
'''def cagnottes(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
totaux = cagnottes(dons)
|
||||||
|
print(totaux["Antoine Daniel"]) # ''' + str(cagnottes_att["Antoine Daniel"]) + '''
|
||||||
|
print(totaux["Joueur du Grenier"]) # ''' + str(cagnottes_att["Joueur du Grenier"]) + '''
|
||||||
|
print(len(totaux)) # ''' + str(len(cagnottes_att)),
|
||||||
|
'''def cagnottes(liste_dons):
|
||||||
|
totaux = {}
|
||||||
|
for don in liste_dons:
|
||||||
|
streamer = don["streamer"]
|
||||||
|
if streamer in totaux:
|
||||||
|
totaux[streamer] = totaux[streamer] + don["montant"]
|
||||||
|
else:
|
||||||
|
totaux[streamer] = don["montant"]
|
||||||
|
return totaux
|
||||||
|
|
||||||
|
# Test
|
||||||
|
totaux = cagnottes(dons)
|
||||||
|
print(totaux["Antoine Daniel"]) # ''' + str(cagnottes_att["Antoine Daniel"]) + '''
|
||||||
|
print(totaux["Joueur du Grenier"]) # ''' + str(cagnottes_att["Joueur du Grenier"]) + '''
|
||||||
|
print(len(totaux)) # ''' + str(len(cagnottes_att)),
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 4.2. La chaîne en tête
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"4.2",
|
||||||
|
"""**Question 4.2** : Écrivez `meilleure_chaine(totaux)` qui renvoie le nom du streamer dont
|
||||||
|
la cagnotte est la plus élevée.
|
||||||
|
|
||||||
|
Rappel : `for cle in dictionnaire` parcourt les clés.""",
|
||||||
|
'''def meilleure_chaine(totaux):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(meilleure_chaine(cagnottes(dons))) # ''' + meilleure_att,
|
||||||
|
'''def meilleure_chaine(totaux):
|
||||||
|
meilleur = None
|
||||||
|
for streamer in totaux:
|
||||||
|
if meilleur is None or totaux[streamer] > totaux[meilleur]:
|
||||||
|
meilleur = streamer
|
||||||
|
return meilleur
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(meilleure_chaine(cagnottes(dons))) # ''' + meilleure_att,
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 4.3. Le détail des dons
|
||||||
|
|
||||||
|
On veut maintenant, pour chaque streamer, la **liste** des montants reçus et plus seulement
|
||||||
|
leur somme : un dictionnaire dont les valeurs sont des listes.
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"4.3",
|
||||||
|
"""**Question 4.3** : Écrivez `dons_par_chaine(liste_dons)` qui renvoie un dictionnaire
|
||||||
|
associant à chaque streamer la liste des montants reçus, dans l'ordre chronologique.""",
|
||||||
|
'''def dons_par_chaine(liste_dons):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
detail = dons_par_chaine(dons)
|
||||||
|
print(detail["MisterMV"]) # ''' + str(detail_att["MisterMV"]) + '''
|
||||||
|
print(detail["Baghera Jones"]) # ''' + str(detail_att["Baghera Jones"]),
|
||||||
|
'''def dons_par_chaine(liste_dons):
|
||||||
|
detail = {}
|
||||||
|
for don in liste_dons:
|
||||||
|
streamer = don["streamer"]
|
||||||
|
if streamer not in detail:
|
||||||
|
detail[streamer] = []
|
||||||
|
detail[streamer].append(don["montant"])
|
||||||
|
return detail
|
||||||
|
|
||||||
|
# Test
|
||||||
|
detail = dons_par_chaine(dons)
|
||||||
|
print(detail["MisterMV"]) # ''' + str(detail_att["MisterMV"]) + '''
|
||||||
|
print(detail["Baghera Jones"]) # ''' + str(detail_att["Baghera Jones"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 4.4. Le podium
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"4.4",
|
||||||
|
"""**Question 4.4** : Écrivez `podium(totaux)` qui renvoie la liste des trois premiers
|
||||||
|
streamers, du plus gros total au plus petit.
|
||||||
|
|
||||||
|
Indication : `sorted(totaux, key=..., reverse=True)` trie les clés selon un critère.""",
|
||||||
|
'''def podium(totaux):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(podium(cagnottes(dons)))
|
||||||
|
# ''' + str(podium_att),
|
||||||
|
'''def podium(totaux):
|
||||||
|
classement = sorted(totaux, key=lambda streamer: totaux[streamer], reverse=True)
|
||||||
|
return classement[:3]
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(podium(cagnottes(dons)))
|
||||||
|
# ''' + str(podium_att),
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- PARTIE 5
|
||||||
|
|
||||||
|
md("""---
|
||||||
|
|
||||||
|
## Partie 5 : Le planning et les raids (synthèse)
|
||||||
|
|
||||||
|
Un **raid**, c'est lorsqu'un streamer envoie son public sur une autre chaîne à la fin de son
|
||||||
|
passage. Cette partie combine tout ce qui précède.
|
||||||
|
|
||||||
|
Copiez ce second bloc de données à la suite du premier.
|
||||||
|
""", dans_corrige=True)
|
||||||
|
|
||||||
|
code(PLANNING_SRC)
|
||||||
|
|
||||||
|
md("""### 5.1. Qui est à l'antenne
|
||||||
|
|
||||||
|
Le planning est une liste de triplets `(streamer, heure_de_debut, heure_de_fin)`, en heures
|
||||||
|
entières sur vingt-quatre heures. Attention au créneau de Baghera Jones : il commence à
|
||||||
|
minuit, donc son heure de début est plus petite que celle de la personne qui la précède.
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"5.1",
|
||||||
|
"""**Question 5.1** : Écrivez `a_l_antenne(planning, heure)` qui renvoie le nom du streamer en
|
||||||
|
direct à cette heure, ou `None` si personne ne l'est.
|
||||||
|
|
||||||
|
L'heure de début est incluse, l'heure de fin est exclue.""",
|
||||||
|
'''def a_l_antenne(planning, heure):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(a_l_antenne(planning, 19)) # ''' + str(antenne_att(19)) + '''
|
||||||
|
print(a_l_antenne(planning, 22)) # ''' + str(antenne_att(22)) + '''
|
||||||
|
print(a_l_antenne(planning, 1)) # ''' + str(antenne_att(1)) + '''
|
||||||
|
print(a_l_antenne(planning, 10)) # ''' + str(antenne_att(10)),
|
||||||
|
'''def a_l_antenne(planning, heure):
|
||||||
|
for streamer, debut, fin in planning:
|
||||||
|
if debut < fin:
|
||||||
|
if debut <= heure < fin:
|
||||||
|
return streamer
|
||||||
|
else:
|
||||||
|
# créneau à cheval sur minuit
|
||||||
|
if heure >= debut or heure < fin:
|
||||||
|
return streamer
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(a_l_antenne(planning, 19)) # ''' + str(antenne_att(19)) + '''
|
||||||
|
print(a_l_antenne(planning, 22)) # ''' + str(antenne_att(22)) + '''
|
||||||
|
print(a_l_antenne(planning, 1)) # ''' + str(antenne_att(1)) + '''
|
||||||
|
print(a_l_antenne(planning, 10)) # ''' + str(antenne_att(10)),
|
||||||
|
)
|
||||||
|
|
||||||
|
md("""### 5.2. Suivre la chaîne des raids
|
||||||
|
|
||||||
|
Le dictionnaire `raids` associe à chaque streamer la liste de ceux vers qui il envoie son
|
||||||
|
public. Certains n'envoient personne : leur liste est vide.
|
||||||
|
""")
|
||||||
|
|
||||||
|
question(
|
||||||
|
"5.2",
|
||||||
|
"""**Question 5.2** : Écrivez `suivre_raids(raids, depart)` qui renvoie la liste des chaînes
|
||||||
|
traversées en partant de `depart` et en suivant à chaque fois le **premier** raid, jusqu'à
|
||||||
|
tomber sur un streamer qui n'en fait aucun.
|
||||||
|
|
||||||
|
Le point de départ fait partie du résultat.""",
|
||||||
|
'''def suivre_raids(raids, depart):
|
||||||
|
# À compléter
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(suivre_raids(raids, "Antoine Daniel"))
|
||||||
|
# ''' + str(raids_att("Antoine Daniel")) + '''
|
||||||
|
print(suivre_raids(raids, "Horty"))
|
||||||
|
# ''' + str(raids_att("Horty")) + '''
|
||||||
|
print(suivre_raids(raids, "Ultia"))
|
||||||
|
# ''' + str(raids_att("Ultia")),
|
||||||
|
'''def suivre_raids(raids, depart):
|
||||||
|
parcours = [depart]
|
||||||
|
courant = depart
|
||||||
|
while raids.get(courant): # .get évite l'erreur si la clé est absente
|
||||||
|
courant = raids[courant][0]
|
||||||
|
parcours.append(courant)
|
||||||
|
return parcours
|
||||||
|
|
||||||
|
# Test
|
||||||
|
print(suivre_raids(raids, "Antoine Daniel"))
|
||||||
|
# ''' + str(raids_att("Antoine Daniel")) + '''
|
||||||
|
print(suivre_raids(raids, "Horty"))
|
||||||
|
# ''' + str(raids_att("Horty")) + '''
|
||||||
|
print(suivre_raids(raids, "Ultia"))
|
||||||
|
# ''' + str(raids_att("Ultia")),
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- FIN
|
||||||
|
|
||||||
|
md("""---
|
||||||
|
|
||||||
|
## Questions de synthèse
|
||||||
|
|
||||||
|
Répondez en quelques lignes, sans machine.
|
||||||
|
|
||||||
|
1. À la question 1.3, `"25" + "40"` donne `"2540"`. Expliquez pourquoi Python ne signale
|
||||||
|
aucune erreur alors que le résultat est faux du point de vue de la régie.
|
||||||
|
|
||||||
|
2. À la question 3.2, pourquoi initialise-t-on `record` avec le premier don de la liste
|
||||||
|
plutôt qu'avec un montant de 0 ?
|
||||||
|
|
||||||
|
3. Aux questions 4.1 et 4.3, on parcourt la même liste de dons mais on ne construit pas la
|
||||||
|
même structure. Dans quel cas le dictionnaire de listes est-il préférable au dictionnaire
|
||||||
|
de totaux ?
|
||||||
|
|
||||||
|
4. La question 5.2 s'arrête lorsqu'un streamer ne fait aucun raid. Que se passerait-il si
|
||||||
|
deux streamers se renvoyaient mutuellement leur public ? Comment modifieriez-vous la
|
||||||
|
fonction pour l'éviter ?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ce que vous venez de réviser
|
||||||
|
|
||||||
|
| Partie | Notion | Chapitre de Terminale concerné |
|
||||||
|
|--------|--------|--------------------------------|
|
||||||
|
| 1 | Variables, types, conversions | POO, structures linéaires |
|
||||||
|
| 2 | Fonctions, `return`, paramètre par défaut | Récursivité, Modularité |
|
||||||
|
| 3 | Boucles, accumulateur, listes, tranches | Parcours d'arbres et de graphes, tri fusion |
|
||||||
|
| 4 | Dictionnaires, dictionnaires de listes | Graphes, programmation dynamique |
|
||||||
|
| 5 | Synthèse, parcours d'un enchaînement | Graphes, Pile et File |
|
||||||
|
|
||||||
|
La question 5.2 est un parcours de graphe : `raids` est une **liste d'adjacence**, exactement
|
||||||
|
la structure que vous utiliserez au chapitre Graphes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Barème indicatif
|
||||||
|
|
||||||
|
| Partie | Points |
|
||||||
|
|--------|--------|
|
||||||
|
| Partie 1 : Le compteur | 3 |
|
||||||
|
| Partie 2 : L'annonce des dons | 5 |
|
||||||
|
| Partie 3 : L'historique des dons | 5 |
|
||||||
|
| Partie 4 : Le classement des chaînes | 4 |
|
||||||
|
| Partie 5 : Le planning et les raids | 2 |
|
||||||
|
| Questions de synthèse | 1 |
|
||||||
|
| **Total** | **20** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
""" + LICENCE)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- SORTIES
|
||||||
|
|
||||||
|
def enonce_md():
|
||||||
|
parts = []
|
||||||
|
for b in BLOCS:
|
||||||
|
if b[0] == "md":
|
||||||
|
parts.append(b[1].strip("\n"))
|
||||||
|
elif b[0] == "code":
|
||||||
|
parts.append("```python\n" + b[1] + "\n```")
|
||||||
|
else:
|
||||||
|
parts.append(b[2].strip("\n") + "\n\n```python\n" + b[3] + "\n```")
|
||||||
|
return "\n\n".join(parts) + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def corrige_md():
|
||||||
|
parts = ["# Corrigé du TP Z-Event", "---"]
|
||||||
|
exclus = ("## Contexte", "## Objectifs pédagogiques", "## Les données",
|
||||||
|
"## Questions de synthèse", "## Ce que vous venez de réviser",
|
||||||
|
"## Barème indicatif")
|
||||||
|
for b in BLOCS:
|
||||||
|
if b[0] == "md":
|
||||||
|
# On reprend toute la hiérarchie de titres de l'énoncé (parties et
|
||||||
|
# sous-parties), sauf le titre du TP et les sections de clôture.
|
||||||
|
titres = [l for l in b[1].split("\n")
|
||||||
|
if l.startswith("## ") or l.startswith("### ")]
|
||||||
|
titres = [l for l in titres if l not in exclus]
|
||||||
|
if titres:
|
||||||
|
parts.append("\n\n".join(titres))
|
||||||
|
elif b[0] == "question":
|
||||||
|
parts.append("**Question %s** :\n\n```python\n%s\n```" % (b[1], b[4]))
|
||||||
|
complet = [DONNEES_SRC, PLANNING_SRC] + [b[4] for b in BLOCS if b[0] == "question"]
|
||||||
|
parts.append("---")
|
||||||
|
parts.append("## Code complet fonctionnel")
|
||||||
|
parts.append("```python\n" + "\n\n".join(complet) + "\n```")
|
||||||
|
parts.append("---")
|
||||||
|
parts.append(LICENCE)
|
||||||
|
return "\n\n".join(parts) + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def notebook():
|
||||||
|
cells = []
|
||||||
|
|
||||||
|
def add(kind, src):
|
||||||
|
c = {"cell_type": kind, "id": uuid.uuid4().hex[:8], "metadata": {},
|
||||||
|
"source": src.splitlines(keepends=True)}
|
||||||
|
if kind == "code":
|
||||||
|
c["execution_count"] = None
|
||||||
|
c["outputs"] = []
|
||||||
|
cells.append(c)
|
||||||
|
|
||||||
|
for b in BLOCS:
|
||||||
|
if b[0] == "md":
|
||||||
|
add("markdown", b[1].strip("\n"))
|
||||||
|
elif b[0] == "code":
|
||||||
|
add("code", b[1])
|
||||||
|
else:
|
||||||
|
add("markdown", b[2].strip("\n"))
|
||||||
|
add("code", b[3])
|
||||||
|
return {"cells": cells,
|
||||||
|
"metadata": {"kernelspec": {"display_name": "Python 3", "language": "python",
|
||||||
|
"name": "python3"},
|
||||||
|
"language_info": {"name": "python", "version": "3.11"}},
|
||||||
|
"nbformat": 4, "nbformat_minor": 5}
|
||||||
|
|
||||||
|
|
||||||
|
io.open(os.path.join(DEST, "TP_ZEvent.md"), "w", encoding="utf-8").write(enonce_md())
|
||||||
|
io.open(os.path.join(DEST, "Corrige_TP_ZEvent.md"), "w", encoding="utf-8").write(corrige_md())
|
||||||
|
with io.open(os.path.join(DEST, "TP_ZEvent.ipynb"), "w", encoding="utf-8") as f:
|
||||||
|
json.dump(notebook(), f, ensure_ascii=False, indent=1)
|
||||||
|
|
||||||
|
print("écrits : TP_ZEvent.md, Corrige_TP_ZEvent.md, TP_ZEvent.ipynb (%d questions)"
|
||||||
|
% sum(1 for b in BLOCS if b[0] == "question"))
|
||||||
Reference in New Issue
Block a user