Projet : créer un programme Python faisant intervenir les classes.
Consignes :
On souhaite avoir un code avec de "bonnes pratiques" donc :
Nous avons créer la classeArbreBinaire
. Toutefois, une
fois un arbre créé, il était difficile de le visualiser.
Nous allons donc créer un outil pour visualiser les arbres binaires à l'aide de la bibliothèque PIL
. Le but est
de créer une image au format png représentant l'arbre implémenté.
Quelques indications :
ImageDraw
.Voici un morceau de code pour vous aider à démarrer.
#Nom prenom
from PIL import Image,ImageDraw, ImageFont
img=Image.new("RGB",(800,900))
draw=ImageDraw.Draw(img)
class ArbreBinaire:
def __init__(self,valeur):
self.valeur=valeur
self.gauche=None
self.droit=None
def ajout_gauche(self,valeur):
self.gauche=Arbre_binaire(valeur)
def ajout_droit(self,valeur):
self.droit=Arbre_binaire(valeur)
def suppr_gauche(self):
self.gauche=None
def suppr_droit(self):
self.droit=None
#fond blanc
# for x in range(800):
# for y in range(900):
# img.putpixel((x,y),(255,255,255))
#un texte en (20,20) écrit en rouge
#font = ImageFont.truetype("arial.ttf", 30)
#draw.text((20,20),"coucou",(255,0,0), font=font)
#une ligne :
#draw.line([(30,40),(50,60)],fill="black",width=6)
#un point :
#img.putpixel((400,450),(0,0,255))
img.show()
Nous souhaitons avoir accès à un LLM (Large Language Model) dans notre projet.
Faire tourner un LLM sur sa machine requiert une machine assez puissante pour le faire fonctionner.
En effet, des LLM performants requièrent des cartes graphiques de plusieurs milliers d'euros et plus d'une centaine de Go de mémoire vive. Des modèles plus petits peuvent tourner sur des machines plus raisonnables mais cela reste au delà de la puissance des machines du lycée.
Nous allons donc utiliser un module nommé ia.py
qui utilise une API vers le site de votre professeur qui fait lui aussi appel à une API vers un LLM.
Prérequis :
requests
ia.py
un fichier nommé noms_des_eleves.py
contenant au début les trois premières lignes suivantes:
import os
#se déplacer dans le répertoire où se situe ia.py
#os.chdir(os.path.dirname(os.path.abspath(__file__))) # pour des logiciels comme VScode par Exemple
os.chdir("u:\\NSI") # a modifier
import ia
'''
Exemple d'utilisation du module ia :
messages = [
{"role": "system", "content": "Tu es un assistant pédagogique."},
{"role": "user", "content": "Explique-moi les bases de Python."},
{"role": "assistant", "content": "Python est un langage de programmation facile à apprendre..."},
{"role": "user", "content": "Comment déclarer une liste ?"}
]
ia.reponse(messages)
print(messages)
'''
Vous pouvez bien entendu regarder ce que contient le module ia.py
mais vous ne le modifierez pas.
Tout votre code sera dans le second fichier que vous avez créé.
Exemples non exhaustifs des projets possibles :
Certains projets ci-dessus sont (trop?) simples. On attendra alors une interface graphique (pyxel, tkinter, flask...).
import tkinter as tk
# Fonction pour mettre à jour le texte du label avec le texte saisi par l'utilisateur
def update_text():
# Récupère le texte entré dans le champ de saisie
new_text = entry.get()
# Met à jour le texte affiché dans le label
label.config(text=new_text)
# Création de la fenêtre principale de l'application
root = tk.Tk()
# Définition du titre de la fenêtre
root.title("Interface simple")
# Création d'un label qui affiche un texte initial "coucou"
label = tk.Label(root, text="coucou", font=("Arial", 16))
# Ajout du label à la fenêtre principale avec un espacement vertical
label.pack(pady=10)
# Création d'un champ de saisie pour permettre à l'utilisateur d'entrer du texte
entry = tk.Entry(root, width=30)
# Ajout du champ de saisie à la fenêtre principale avec un espacement vertical
entry.pack(pady=5)
# Création d'un bouton qui, lorsqu'il est cliqué, appelle la fonction update_text
button = tk.Button(root, text="Valider", command=update_text)
# Ajout du bouton à la fenêtre principale avec un espacement vertical
button.pack(pady=5)
# Lancement de la boucle principale de l'application Tkinter
# Cette boucle écoute les événements et met à jour l'interface utilisateur
root.mainloop()
import pyxel # Importation de la bibliothèque Pyxel pour créer des interfaces graphiques simples
class InterfacePyxel:
def __init__(self):
# Initialisation de la fenêtre Pyxel
pyxel.init(360, 320, title="Interface Pyxel") # Crée une fenêtre de 360x320 pixels avec un titre
self.message = "Bienvenue !" # Message affiché dans la zone de message
# Définition des boutons avec leurs propriétés : position, taille, label, et action associée
self.buttons = [
{"x": 10, "y": 300, "width": 60, "height": 20, "label": "Bouton A", "action": self.bouton1_action},
{"x": 90, "y": 300, "width": 60, "height": 20, "label": "Bouton B", "action": self.bouton2_action}
]
# Démarrage de la boucle principale Pyxel
pyxel.run(self.update, self.draw)
def bouton1_action(self):
"""Action associée au premier bouton."""
self.message = "Bouton 1 clique" # Mise à jour du message affiché
def bouton2_action(self):
"""Action associée au second bouton."""
self.message = "Bouton 2 clique" # Mise à jour du message affiché
def draw_message_area(self):
"""Affiche la zone de messages."""
pyxel.rect(10, 10, 300, 200, 1) # Dessine un rectangle de 300x200 pixels à la position (10, 10) avec la couleur 1
pyxel.text(15, 20, self.message, 7) # Affiche le message en blanc (7) à la position (15, 20)
def draw_buttons(self):
"""Dessine les boutons définis."""
for button in self.buttons:
# Récupère les coordonnées, la taille et le label de chaque bouton
x, y, w, h = button["x"], button["y"], button["width"], button["height"]
pyxel.rect(x, y, w, h, 5) # Dessine le rectangle du bouton en couleur 5
pyxel.text(x + 5, y + 7, button["label"], 0) # Affiche le texte du bouton en noir (0) avec un décalage
def is_inside(self, mouse_x, mouse_y, button):
"""Vérifie si la souris est dans les limites d'un bouton."""
x, y, w, h = button["x"], button["y"], button["width"], button["height"]
# Vérifie si les coordonnées de la souris se trouvent dans la zone du bouton
return x <= mouse_x <= x + w and y <= mouse_y <= y + h
def update(self):
"""Gestion des événements utilisateur."""
# Vérifie si le bouton gauche de la souris est pressé
if pyxel.btn(pyxel.MOUSE_BUTTON_LEFT):
mouse_x = pyxel.mouse_x # Récupère la position X de la souris
mouse_y = pyxel.mouse_y # Récupère la position Y de la souris
for button in self.buttons:
# Si la souris est à l'intérieur d'un bouton, exécute l'action associée
if self.is_inside(mouse_x, mouse_y, button):
button["action"]()
def draw(self):
"""Dessin de l'interface graphique."""
pyxel.cls(0) # Efface l'écran en remplissant avec la couleur noire (0)
self.draw_message_area() # Dessine la zone de message
self.draw_buttons() # Dessine les boutons
# Dessine un petit rectangle blanc (7) représentant la position actuelle de la souris
pyxel.rect(pyxel.mouse_x, pyxel.mouse_y, 5, 5, 7)
# Lancement de l'application
if __name__ == "__main__":
InterfacePyxel() # Instancie la classe et lance l'application
from flask import Flask, session, redirect, url_for, request, render_template
from flask_session import Session
# Création de l'application Flask
app = Flask(__name__)
# Configuration de Flask-Session
app.config["SESSION_TYPE"] = "filesystem" # Les sessions sont stockées dans des fichiers locaux (utilisé pour conserver les données de session)
app.config["SECRET_KEY"] = "45465145615614654654165454544" # Clé secrète pour signer les données de session
Session(app) # Initialisation de l'extension Flask-Session pour gérer les sessions
@app.route("/", methods=["GET","POST"]) # Route principale, accepte les méthodes GET et POST
def index():
# Vérifie si une liste "personnes" existe déjà dans la session
if "personnes" not in session:
# Si elle n'existe pas, initialise la session avec une liste contenant une personne par défaut
session['personnes'] = [
{"nom": "Duranton", "prenom": "Olivier"}
]
# Récupère les données envoyées via le formulaire (si elles existent)
nom = request.form.get("nom") # Récupère le champ "nom" du formulaire
prenom = request.form.get("prenom") # Récupère le champ "prenom" du formulaire
# Si le nom et le prénom ont été soumis via le formulaire
if nom is not None and prenom is not None:
# Ajoute une nouvelle personne (dictionnaire avec nom et prénom) à la liste dans la session
session["personnes"].append({"nom": nom, "prenom": prenom})
# Rend le template HTML "index.html" en passant la liste des personnes à afficher
return render_template("index.html", personnes=session['personnes'])
# Lancement de l'application
if __name__ == "__main__":
app.run(debug=False) # Lance le serveur Flask en mode debug (désactivé sur les ordinateurs du lycée car debug=True n'y marche pas)
Et dans le même dossier, avoir un dossier nommé templates
avec à l'intérieur le fichier index.html
qui contient :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
{% for personne in personnes %}
<div class="personnes">
<strong>{{ personne.nom.capitalize() }}:</strong>
{{ personne.prenom }}
</div>
{% endfor %}
<form method="POST" action="/">
<input type="text" name="nom" placeholder="Votre nom de famille..." required>
<input type="text" name="prenom" placeholder="Votre prénom..." required>
<button type="submit">Envoyer</button>
</form>
</body>
</html>
Le but de ce projet est d'appréhender les bases de données de la conception jusqu'à l'implémentation.
Voici les exigences :
Il y a trois fichiers à fournir :
Un fichier .pdf
comportant :
Un fichier .db
Un fichier .sql
comportant :
INSERT INTO
;UPDATE
;DELETE FROM
;SELECT
simples ;SELECT
associée avec la commande ORDER BY
;SELECT
associée avec la commande WHERE
;SELECT
associée avec les commandes WHERE
et
ORDER BY
;SELECT
associée avec les commandes WHERE
et
JOIN
;SELECT
comportant 2 commandes JOIN
;SELECT
avec la fonction COUNT()
SELECT
avec la fonction MAX()
SELECT
avec la fonction MIN()
SELECT
avec la fonction SUM()
SELECT
avec la fonction AVG()
Voici une première image :
Voici une deuxième image :
Il y a une différence entre ces deux images. La voyez-vous?
Un message a été caché dans la deuxième image, mais invisible pour votre oeil.
Le principe pour masquer le message a été le suivant :
(0,0,0)
) sur fond blanc ((255,255,255)
)
dans une image privée .
original.jpeg
Pour chaque pixel aux coordonnées (x,y)
de la nouvelle image , on récupère le tuple
(r,g,b)
de l'image publique aux coordonnées (x,y)
puis :
r
et g
de la nouvelle image sont identiquesb
:
D'abord, si b
est impair, on lui enlève 1. Ainsi la valeur de b
est paire à cette étape.
b
s'il existe un pixel blanc à ces coordonnées de l'image privée ou si ce pixel est en dehors de l'image privée.
Quelques lignes de codes pour vous aider :
# importation des bibliothèques nécessaires :
from PIL import Image
from PIL import ImageDraw
import os
repertoire_actuel="U:\\" #à modifier
# Se déplacer dans le répertoire du fichier actuel
os.chdir(repertoire_actuel)
#Pour ouvrir une image :
#nom_de_variable_image=Image.open(nom_du_fichier_de_type_str)
#Pour créer une nouvelle image :
#nom_de_variable_image=Image.new("RGB",(largeur,hauteur))
#Pour connaitre la taille d'une image :
#largeur,hauteur = nom_de_variable_image.size
'''
for x in range(largeur):
for y in range(hauteur):
r,g,b=nom_de_variable_image.getpixel((x,y))[:3] # connaitre les pixels r,g,b
nom_de_variable_image.putpixel((x,y),(r,g,b)) #mettre un pixel d'une certaine couleur
'''
#pour faire apparaitre une image :
#nom_de_variable_image.show()
#pour enregistrer une image :
#nom_de_variable_image.save(nom_du_fichier_de_type_str)
Télécharger la deuxième image puis faire apparaitre l'image privée à l'aide
d'une fonction separation(fichier_entree :str,fichier_sortie :str)
. fichier_entree
correspond au nom du fichier qu'il faut ouvrir. fichier_sortie
correspond au nom du fichier que vous allez créer. Il correspond à l'image privée.
Vous pouvez aussi tester votre code sur l'image originale, pour voir la différence.
Creer une fonction cache(image_publique :str, image_privee :str, fichier_sortie :str)
qui permet de cacher une image en noir et blanc dans une autre et la tester.
Attention : le fichier de sortie doit être au format png
pour ne pas avoir de compressions de l'image et modifier les valeurs des pixels.
Une fois fini, approfondissement au choix :