BARRAUX Arthur
2 years ago
5 changed files with 1091 additions and 1085 deletions
@ -1,7 +1,7 @@ |
|||||
# test si custom tkinter fonction sur le pc |
# test si custom tkinter fonction sur le pc |
||||
try: |
try: |
||||
from package.ctk_app import App |
from package.ctk_app import App |
||||
except ImportError: |
except ImportError: |
||||
from package.tk_app import App |
from package.tk_app import App |
||||
|
|
||||
App().mainloop() |
App().mainloop() |
||||
|
@ -1,343 +1,346 @@ |
|||||
"""Classe d'application tk et ctk""" |
"""Classe d'application tk et ctk""" |
||||
|
|
||||
import math |
import math |
||||
import customtkinter as ctk |
import customtkinter as ctk |
||||
from package.data_structure import Pile_chaine |
from package.data_structure import Pile_chaine |
||||
from package.expression import Expression |
from package.expression import Expression |
||||
|
|
||||
|
|
||||
def change_appearance_mode_event(new_appearance_mode: str) -> None: |
def change_appearance_mode_event(new_appearance_mode: str) -> None: |
||||
"""Change le thème de sombre à Claire""" |
"""Change le thème de sombre à Claire""" |
||||
ctk.set_appearance_mode(new_appearance_mode) |
ctk.set_appearance_mode(new_appearance_mode) |
||||
|
|
||||
def parse_string_to_list(text: str) -> list: |
def parse_string_to_list(text: str) -> list: |
||||
""" Transforme le text en liste d'éléments intelligible par le programme """ |
""" Transforme le text en liste d'éléments intelligible par le programme """ |
||||
text = list(text) |
text = list(text) |
||||
result = [] |
result = [] |
||||
buffer_function = "" |
buffer_function = "" |
||||
buffer_number = "" |
buffer_number = "" |
||||
number_first = False # Savoir dans quel ordre sont les chiffres et les lettres |
number_first = False # Savoir dans quel ordre sont les chiffres et les lettres |
||||
for char in text: |
for char in text: |
||||
if char == 'e': |
if char == 'e': |
||||
result.append(math.e) |
result.append(math.e) |
||||
elif char == '𝜋': |
elif char == '𝜋': |
||||
result.append(math.pi) |
result.append(math.pi) |
||||
elif char.isdigit() or char == ".": |
elif char.isdigit() or char == ".": |
||||
buffer_number += char |
buffer_number += char |
||||
if len(buffer_function) == 0: |
if len(buffer_function) == 0: |
||||
number_first = True |
number_first = True |
||||
elif char.isalpha(): |
elif char.isalpha(): |
||||
buffer_function += char |
buffer_function += char |
||||
else: |
else: |
||||
if number_first: |
if number_first: |
||||
result.append(float(buffer_number)) |
result.append(float(buffer_number)) |
||||
buffer_number = "" |
buffer_number = "" |
||||
number_first = False |
number_first = False |
||||
if len(buffer_function) != 0: |
if len(buffer_function) != 0: |
||||
result.append('*') |
result.append('*') |
||||
result.append(buffer_function) |
result.append(buffer_function) |
||||
buffer_function = "" |
buffer_function = "" |
||||
elif char == '(': |
elif char == '(': |
||||
result.append('*') |
result.append('*') |
||||
|
|
||||
else: |
else: |
||||
if len(buffer_function) != 0: |
if len(buffer_function) != 0: |
||||
result.append(buffer_function) |
result.append(buffer_function) |
||||
buffer_function = "" |
buffer_function = "" |
||||
if len(buffer_number) != 0: |
if len(buffer_number) != 0: |
||||
result.append(float(buffer_number)) |
result.append(float(buffer_number)) |
||||
buffer_number = "" |
buffer_number = "" |
||||
number_first = False |
number_first = False |
||||
result.append(char) |
result.append(char) |
||||
if len(buffer_number) != 0: |
if len(buffer_number) != 0: |
||||
result.append(float(buffer_number)) |
result.append(float(buffer_number)) |
||||
if len(buffer_function) != 0: |
if len(buffer_function) != 0: |
||||
result.append('*') |
result.append('*') |
||||
result.append(buffer_function) |
result.append(buffer_function) |
||||
elif len(buffer_function) != 0: |
elif len(buffer_function) != 0: |
||||
result.append(buffer_function) |
result.append(buffer_function) |
||||
return result |
return result |
||||
|
|
||||
def npi2tree(expr: list) -> Expression: |
def npi2tree(expr: list) -> Expression: |
||||
""" Renvoie l'arbre formé à partir de l'expression donnée""" |
""" Renvoie l'arbre formé à partir de l'expression donnée""" |
||||
pile = Pile_chaine() |
pile = Pile_chaine() |
||||
for val in expr: |
for val in expr: |
||||
if not type(val) is float and val != "x": |
if not type(val) is float and val != "x": |
||||
# on inverse pour avoir les nombres dans le bon ordre |
# on inverse pour avoir les nombres dans le bon ordre |
||||
nombre2 = pile.depiler() |
nombre2 = pile.depiler() |
||||
if not pile.est_vide(): |
if not pile.est_vide(): |
||||
pile.empiler(Expression(val, pile.depiler(), nombre2)) |
pile.empiler(Expression(val, pile.depiler(), nombre2)) |
||||
else: |
else: |
||||
pile.empiler(Expression(val, nombre2)) |
pile.empiler(Expression(val, nombre2)) |
||||
else: |
else: |
||||
pile.empiler(Expression(val)) |
pile.empiler(Expression(val)) |
||||
return pile.sommet() |
return pile.sommet() |
||||
|
|
||||
def inf2npi(expr: list) -> list: |
def inf2npi(expr: list) -> list: |
||||
"""Transforme une expression infixé en notation polonaise inversée""" |
"""Transforme une expression infixé en notation polonaise inversée""" |
||||
operator_stack = Pile_chaine() |
operator_stack = Pile_chaine() |
||||
operator_priority = { |
operator_priority = { |
||||
'+': 1, |
'+': 1, |
||||
'-': 1, |
'-': 1, |
||||
'*': 2, |
'*': 2, |
||||
'^': 3, |
'^': 3, |
||||
'/': 2, |
'/': 2, |
||||
'(': 0, |
'(': 0, |
||||
')': 0 |
')': 0 |
||||
} |
} |
||||
output = [] |
output = [] |
||||
for val in expr: |
for val in expr: |
||||
if type(val) is float or val == 'x': |
if type(val) is float or val == 'x': |
||||
output.append(val) |
output.append(val) |
||||
else: |
else: |
||||
if operator_stack.est_vide() or ( val == '(' or operator_priority[val] > operator_priority[operator_stack.sommet()]): |
if operator_stack.est_vide() or ( val == '(' or operator_priority[val] > operator_priority[operator_stack.sommet()]): |
||||
operator_stack.empiler(val) |
operator_stack.empiler(val) |
||||
else: |
else: |
||||
while not operator_stack.est_vide(): |
while not operator_stack.est_vide(): |
||||
if operator_stack.sommet() == '(': |
if operator_stack.sommet() == '(': |
||||
operator_stack.depiler() |
operator_stack.depiler() |
||||
else: |
else: |
||||
output.append(operator_stack.depiler()) |
output.append(operator_stack.depiler()) |
||||
if val != ')': |
if val != ')': |
||||
operator_stack.empiler(val) |
operator_stack.empiler(val) |
||||
while not operator_stack.est_vide(): |
while not operator_stack.est_vide(): |
||||
output.append(operator_stack.depiler()) |
output.append(operator_stack.depiler()) |
||||
return output |
return output |
||||
|
|
||||
|
|
||||
class App(ctk.CTk): |
class App(ctk.CTk): |
||||
"""Classe pour l'interface graphique avec custom tkinter""" |
"""Classe pour l'interface graphique avec custom tkinter""" |
||||
def __init__(self) -> None: |
def __init__(self) -> None: |
||||
super().__init__() |
super().__init__() |
||||
|
|
||||
change_appearance_mode_event('dark') |
change_appearance_mode_event('dark') |
||||
|
|
||||
self.fonction_screen_height = None |
self.fonction_screen_height = None |
||||
self.fonction_screen_width = None |
self.fonction_screen_width = None |
||||
self.grid_columnconfigure(0, weight=0) |
self.grid_columnconfigure(0, weight=0) |
||||
self.grid_columnconfigure((1,2,3,4,5), weight=1) |
self.grid_columnconfigure((1,2,3,4,5), weight=1) |
||||
self.grid_rowconfigure(0, weight=0) |
self.grid_rowconfigure(0, weight=0) |
||||
self.grid_rowconfigure((1,2,3,4,5), weight=1) |
self.grid_rowconfigure((1,2,3,4,5), weight=1) |
||||
|
|
||||
# touches de la calculette |
# touches de la calculette |
||||
|
|
||||
self.keys = [] |
self.keys = [] |
||||
for i, val in enumerate(["←", "cos", "sin", "tan", "→", "x", "e", "√", "^", "𝜋", 7, 8, 9, "(", ")", 4, 5, 6, "*", "/", 1, 2, 3, "+", "-", |
for i, val in enumerate(["←", "cos", "sin", "tan", "→", "x", "e", "√", "^", "𝜋", 7, 8, 9, "(", ")", 4, 5, 6, "*", "/", 1, 2, 3, "+", "-", |
||||
"clear", 0, ".", "ln", "exe"]): # add numbers button |
"clear", 0, ".", "ln", "exe"]): # add numbers button |
||||
if type(val) == int: |
if type(val) == int: |
||||
self.keys.append(ctk.CTkButton(self, text=val, command=lambda x=val: self.add_value(x), fg_color=("gray50","gray20"), text_color="gray90", hover_color=("gray40", "gray30"))) |
self.keys.append(ctk.CTkButton(self, text=val, command=lambda x=val: self.add_value(x), fg_color=("gray50","gray20"), text_color="gray90", hover_color=("gray40", "gray30"))) |
||||
elif val == "clear": |
elif val == "clear": |
||||
self.keys.append(ctk.CTkButton(self, text=val, command=self.clear_screen)) |
self.keys.append(ctk.CTkButton(self, text=val, command=self.clear_screen)) |
||||
elif val == "←": |
elif val == "←": |
||||
self.keys.append(ctk.CTkButton(self, text=val, command=self.move_cursor_left)) |
self.keys.append(ctk.CTkButton(self, text=val, command=self.move_cursor_left)) |
||||
elif val == "→": |
elif val == "→": |
||||
self.keys.append(ctk.CTkButton(self, text=val, command=self.move_cursor_right)) |
self.keys.append(ctk.CTkButton(self, text=val, command=self.move_cursor_right)) |
||||
else: |
else: |
||||
self.keys.append(ctk.CTkButton(self, text=val, command=lambda x=val: self.add_value(x))) |
self.keys.append(ctk.CTkButton(self, text=val, command=lambda x=val: self.add_value(x))) |
||||
self.keys[i].grid(row=i//5+1, column=i % 5+1, sticky="NSEW", padx=5, pady=5) |
self.keys[i].grid(row=i//5+1, column=i % 5+1, sticky="NSEW", padx=5, pady=5) |
||||
|
|
||||
# Calcul Frame |
# Calcul Frame |
||||
|
|
||||
self.calcul_frame = ctk.CTkFrame(self, corner_radius=0, fg_color="transparent") |
self.calcul_frame = ctk.CTkFrame(self, corner_radius=0, fg_color="transparent") |
||||
|
|
||||
self.calcul_screen = ctk.CTkLabel(self.calcul_frame, text="hello") |
self.calcul_screen = ctk.CTkLabel(self.calcul_frame, text="hello") |
||||
self.calcul_screen.pack(fill="both", expand=True) |
self.calcul_screen.pack(fill="both", expand=True) |
||||
self.calcul_entry = ctk.CTkEntry(self.calcul_frame) |
self.calcul_entry = ctk.CTkEntry(self.calcul_frame) |
||||
self.calcul_entry.pack(fill="both", expand=True) |
self.calcul_entry.pack(fill="both", expand=True) |
||||
|
|
||||
# Fonction Frame |
# Fonction Frame |
||||
|
|
||||
self.fonction_frame = ctk.CTkFrame(self, fg_color="transparent") |
self.fonction_frame = ctk.CTkFrame(self, fg_color="transparent") |
||||
|
|
||||
self.fonction_bornes_frame = ctk.CTkFrame(self.fonction_frame, corner_radius=None) |
self.fonction_bornes_frame = ctk.CTkFrame(self.fonction_frame, corner_radius=None) |
||||
|
|
||||
self.fonction_bornes_entry = ctk.CTkEntry(self.fonction_bornes_frame) |
self.fonction_bornes_entry = ctk.CTkEntry(self.fonction_bornes_frame) |
||||
self.fonction_bornes_entry.insert(0, "-100,100") |
self.fonction_bornes_entry.insert(0, "-100,100") |
||||
self.fonction_bornes_entry.grid(sticky="ew", row=1, padx=10) |
self.fonction_bornes_entry.grid(sticky="ew", row=1, padx=10) |
||||
|
|
||||
self.fonction_bornes_text = ctk.CTkLabel(self.fonction_bornes_frame, text="Entrez les bornes de tracé: (min, max)") |
self.fonction_bornes_text = ctk.CTkLabel(self.fonction_bornes_frame, text="Entrez les bornes de tracé: (min, max)") |
||||
self.fonction_bornes_text.grid(sticky="ew", row=0) |
self.fonction_bornes_text.grid(sticky="ew", row=0) |
||||
|
|
||||
self.fonction_bornes_frame.grid(sticky="ns", column=0, rowspan=2) |
self.fonction_bornes_frame.grid(sticky="ns", column=0, rowspan=2) |
||||
|
|
||||
|
|
||||
self.fonction_screen = ctk.CTkCanvas(self.fonction_frame) |
self.fonction_screen = ctk.CTkCanvas(self.fonction_frame) |
||||
self.fonction_screen.grid(sticky="nsew", column=1, row=0) |
self.fonction_screen.grid(sticky="nsew", column=1, row=0) |
||||
self.fonction_entry = ctk.CTkEntry(self.fonction_frame) |
self.fonction_entry = ctk.CTkEntry(self.fonction_frame) |
||||
self.fonction_entry.grid(sticky='ew', column=1, row=1) |
self.fonction_entry.grid(sticky='ew', column=1, row=1) |
||||
|
|
||||
# navigation menu |
# navigation menu |
||||
self.navigation_frame = ctk.CTkFrame(self, corner_radius=0) |
self.navigation_frame = ctk.CTkFrame(self, corner_radius=0) |
||||
self.navigation_frame.grid_rowconfigure(4, weight=1) |
self.navigation_frame.grid_rowconfigure(4, weight=1) |
||||
self.navigation_frame.grid(row=0, rowspan=10, column=0, sticky="nsew") |
self.navigation_frame.grid(row=0, rowspan=10, column=0, sticky="nsew") |
||||
|
|
||||
self.titre = ctk.CTkLabel(self.navigation_frame, text="Wx Calculator", compound="left" |
self.titre = ctk.CTkLabel(self.navigation_frame, text="Wx Calculator", compound="left" |
||||
, font=ctk.CTkFont(size=15, weight="bold")) |
, font=ctk.CTkFont(size=15, weight="bold")) |
||||
self.titre.grid(row=0, column=0, padx=20, pady=20) |
self.titre.grid(row=0, column=0, padx=20, pady=20) |
||||
|
|
||||
self.home_button = ctk.CTkButton(self.navigation_frame, corner_radius=0, height=40, border_spacing=10 |
self.home_button = ctk.CTkButton(self.navigation_frame, corner_radius=0, height=40, border_spacing=10 |
||||
, text="Calcul", fg_color="transparent", text_color=("gray10", "gray90") |
, text="Calcul", fg_color="transparent", text_color=("gray10", "gray90") |
||||
, hover_color=("gray70", "gray30"), anchor="w" |
, hover_color=("gray70", "gray30"), anchor="w" |
||||
, command=lambda: self.select_frame_by_name("Calcul")) |
, command=lambda: self.select_frame_by_name("Calcul")) |
||||
self.home_button.grid(row=1, column=0, sticky="ew") |
self.home_button.grid(row=1, column=0, sticky="ew") |
||||
|
|
||||
self.function_button = ctk.CTkButton(self.navigation_frame, corner_radius=0, height=40, border_spacing=10 |
self.function_button = ctk.CTkButton(self.navigation_frame, corner_radius=0, height=40, border_spacing=10 |
||||
, text="Fonction", fg_color="transparent", text_color=("gray10", "gray90") |
, text="Fonction", fg_color="transparent", text_color=("gray10", "gray90") |
||||
, hover_color=("gray70", "gray30"), anchor="w" |
, hover_color=("gray70", "gray30"), anchor="w" |
||||
, command=lambda: self.select_frame_by_name("Fonction")) |
, command=lambda: self.select_frame_by_name("Fonction")) |
||||
self.function_button.grid(row=2, column=0, sticky="ew") |
self.function_button.grid(row=2, column=0, sticky="ew") |
||||
|
|
||||
self.appearance_mode_menu = ctk.CTkOptionMenu(self.navigation_frame, values=["Light", "Dark", "System"] |
self.appearance_mode_menu = ctk.CTkOptionMenu(self.navigation_frame, values=["Light", "Dark", "System"] |
||||
, command=change_appearance_mode_event) |
, command=change_appearance_mode_event) |
||||
self.appearance_mode_menu.grid(row=4, column=0, padx=20, pady=20, sticky="s") |
self.appearance_mode_menu.grid(row=4, column=0, padx=20, pady=20, sticky="s") |
||||
self.mode = 'Calcul' |
self.mode = 'Calcul' |
||||
|
|
||||
# select default frame |
# select default frame |
||||
|
|
||||
self.select_frame_by_name("Calcul") |
self.select_frame_by_name("Calcul") |
||||
|
|
||||
def select_frame_by_name(self, name): |
def select_frame_by_name(self, name): |
||||
"""Change de mode : passe de calcul à fonction""" |
"""Change de mode : passe de calcul à fonction""" |
||||
# set button color for selected button |
# set button color for selected button |
||||
self.home_button.configure(fg_color=("gray75", "gray25") if name == "Calcul" else "transparent") |
self.home_button.configure(fg_color=("gray75", "gray25") if name == "Calcul" else "transparent") |
||||
self.function_button.configure(fg_color=("gray75", "gray25") if name == "Fonction" else "transparent") |
self.function_button.configure(fg_color=("gray75", "gray25") if name == "Fonction" else "transparent") |
||||
|
|
||||
# show selected frame |
# show selected frame |
||||
if name == "Calcul": |
if name == "Calcul": |
||||
self.mode = "Calcul" |
self.mode = "Calcul" |
||||
self.calcul_frame.grid(padx=20, pady=20, columnspan=5, column=1, row=0, sticky="nsew") |
self.calcul_frame.grid(padx=20, pady=20, columnspan=5, column=1, row=0, sticky="nsew") |
||||
self.keys[-1]._command = self.calculate |
self.keys[-1]._command = self.calculate |
||||
|
|
||||
else: |
else: |
||||
self.calcul_frame.grid_forget() |
self.calcul_frame.grid_forget() |
||||
if name == "Fonction": |
if name == "Fonction": |
||||
self.mode = "Fonction" |
self.mode = "Fonction" |
||||
self.fonction_frame.grid(columnspan=5, column=1, row=0, padx=20, pady=20, sticky="ns") |
self.fonction_frame.grid(columnspan=5, column=1, row=0, padx=20, pady=20, sticky="ns") |
||||
self.fonction_frame.update() |
self.fonction_frame.update() |
||||
self.fonction_screen_width = self.fonction_screen.winfo_width() |
self.fonction_screen_width = self.fonction_screen.winfo_width() |
||||
self.keys[-1]._command = self.draw_graph |
self.keys[-1]._command = self.draw_graph |
||||
self.fonction_screen_height = self.fonction_screen.winfo_height() |
self.fonction_screen_height = self.fonction_screen.winfo_height() |
||||
else: |
else: |
||||
self.fonction_frame.grid_forget() |
self.fonction_frame.grid_forget() |
||||
|
|
||||
def add_value(self, value) -> None: |
def add_value(self, value) -> None: |
||||
"""Ajoute le charactère à la suite de l'expression""" |
"""Ajoute le charactère à la suite de l'expression""" |
||||
parenthesis = False |
parenthesis = False |
||||
if value == "e": |
if value == "e": |
||||
value += "^" |
value += "^" |
||||
if value == "(": |
if value == "(": |
||||
value += ")" |
value += ")" |
||||
parenthesis = True |
parenthesis = True |
||||
elif value in ["ln", "cos", "sin", "tan", "√"]: |
elif value in ["ln", "cos", "sin", "tan", "√"]: |
||||
value += "()" |
value += "()" |
||||
parenthesis = True |
parenthesis = True |
||||
if self.mode == 'Fonction': |
if self.mode == 'Fonction': |
||||
self.fonction_entry.insert(ctk.INSERT, value) |
self.fonction_entry.insert(ctk.INSERT, value) |
||||
else: |
else: |
||||
self.calcul_entry.insert(ctk.INSERT, value) |
self.calcul_entry.insert(ctk.INSERT, value) |
||||
if parenthesis: |
if parenthesis: |
||||
self.move_cursor_left() |
self.move_cursor_left() |
||||
|
|
||||
def clear_screen(self) -> None: |
def clear_screen(self) -> None: |
||||
"""Enlève l'affichage actuel""" |
"""Enlève l'affichage actuel""" |
||||
if self.mode == "Calcul": |
if self.mode == "Calcul": |
||||
self.calcul_screen.configure(text="") |
self.calcul_screen.configure(text="") |
||||
self.calcul_entry.delete('0', 'end') |
self.calcul_entry.delete('0', 'end') |
||||
else: |
else: |
||||
self.fonction_screen.delete('all') |
self.fonction_screen.delete('all') |
||||
self.fonction_entry.delete(0, 'end') |
self.fonction_entry.delete(0, 'end') |
||||
|
|
||||
def move_cursor_left(self): |
def move_cursor_left(self): |
||||
"""Déplace le curseur à gauche""" |
"""Déplace le curseur à gauche""" |
||||
if self.mode == "Calcul": |
if self.mode == "Calcul": |
||||
pos = self.calcul_entry.index(ctk.INSERT) |
pos = self.calcul_entry.index(ctk.INSERT) |
||||
if pos > 0: |
if pos > 0: |
||||
self.calcul_entry.icursor(pos -1) |
self.calcul_entry.icursor(pos -1) |
||||
else: |
else: |
||||
pos = self.fonction_entry.index(ctk.INSERT) |
pos = self.fonction_entry.index(ctk.INSERT) |
||||
if pos > 0: |
if pos > 0: |
||||
self.fonction_entry.icursor(pos-1) |
self.fonction_entry.icursor(pos-1) |
||||
|
|
||||
def move_cursor_right(self): |
def move_cursor_right(self): |
||||
"""Déplace le curseur à droite""" |
"""Déplace le curseur à droite""" |
||||
if self.mode == "Calcul": |
if self.mode == "Calcul": |
||||
pos = self.calcul_entry.index(ctk.INSERT) |
pos = self.calcul_entry.index(ctk.INSERT) |
||||
if pos < len(self.calcul_entry.get()): |
if pos < len(self.calcul_entry.get()): |
||||
self.calcul_entry.icursor(pos + 1) |
self.calcul_entry.icursor(pos + 1) |
||||
else: |
else: |
||||
pos = self.fonction_entry.index(ctk.INSERT) |
pos = self.fonction_entry.index(ctk.INSERT) |
||||
if pos < len(self.fonction_entry.get()): |
if pos < len(self.fonction_entry.get()): |
||||
self.fonction_entry.icursor(pos + 1) |
self.fonction_entry.icursor(pos + 1) |
||||
|
|
||||
def draw_framing(self, min_x, max_x, min_y, max_y): |
def draw_framing(self, min_x, max_x, min_y, max_y): |
||||
"""Dessine le cadrillage du graphique""" |
"""Dessine le cadrillage du graphique""" |
||||
ratio = self.fonction_screen_height / self.fonction_screen_width # longueur par largeur du canvas |
ratio = self.fonction_screen_height / self.fonction_screen_width # longueur par largeur du canvas |
||||
|
|
||||
# position du max dans l'interval |
# position du max dans l'interval |
||||
abscisse = max_y / (abs(min_y)+abs(max_y)) |
abscisse = max_y / (abs(min_y)+abs(max_y)) |
||||
ordonnee = max_x / (abs(min_x)+abs(max_x)) |
ordonnee = max_x / (abs(min_x)+abs(max_x)) |
||||
|
|
||||
for i in range(20): # dessin des lignes verticales |
for i in range(20): # dessin des lignes verticales |
||||
if i == int(20 - 20*ordonnee): |
if i == int(20 - 20*ordonnee): |
||||
self.fonction_screen.create_line(0 + i * self.fonction_screen_width/20, 0 |
self.fonction_screen.create_line(0 + i * self.fonction_screen_width/20, 0 |
||||
, 0 + i * self.fonction_screen_width/20, self.fonction_screen_height |
, 0 + i * self.fonction_screen_width/20, self.fonction_screen_height |
||||
, fill='red', width=4) |
, fill='red', width=4) |
||||
text = self.fonction_screen.create_text(0 + i * self.fonction_screen_width/20, 10, text=max_y) |
text = self.fonction_screen.create_text(0 + i * self.fonction_screen_width/20, 10, text=max_y) |
||||
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
||||
self.fonction_screen.tag_lower(rect, text) |
self.fonction_screen.tag_lower(rect, text) |
||||
|
|
||||
text = self.fonction_screen.create_text(0 + i * self.fonction_screen_width/20, |
text = self.fonction_screen.create_text(0 + i * self.fonction_screen_width/20, |
||||
self.fonction_screen_height - 10, text=min_y) |
self.fonction_screen_height - 10, text=min_y) |
||||
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
||||
self.fonction_screen.tag_lower(rect, text) |
self.fonction_screen.tag_lower(rect, text) |
||||
else: |
else: |
||||
self.fonction_screen.create_line(0 + i * self.fonction_screen_width/20, 0 |
self.fonction_screen.create_line(0 + i * self.fonction_screen_width/20, 0 |
||||
, 0 + i * self.fonction_screen_width/20, self.fonction_screen_height |
, 0 + i * self.fonction_screen_width/20, self.fonction_screen_height |
||||
, fill='red') |
, fill='red') |
||||
nb_abscisse_lines = int(20*ratio) # nombre de lignes horizontales à tracer |
nb_abscisse_lines = int(20*ratio) # nombre de lignes horizontales à tracer |
||||
|
|
||||
for i in range(nb_abscisse_lines): # dessin des lignes horizontales |
for i in range(nb_abscisse_lines): # dessin des lignes horizontales |
||||
if i == math.ceil(nb_abscisse_lines * abscisse): # tracer de l'axe des abscisses |
if i == math.ceil(nb_abscisse_lines * abscisse): # tracer de l'axe des abscisses |
||||
self.fonction_screen.create_line(0, 0 + i * self.fonction_screen_width/20 |
self.fonction_screen.create_line(0, 0 + i * self.fonction_screen_width/20 |
||||
, self.fonction_screen_width |
, self.fonction_screen_width |
||||
, 0 + i * self.fonction_screen_width/20, fill='red' |
, 0 + i * self.fonction_screen_width/20, fill='red' |
||||
, width=4) |
, width=4) |
||||
text = self.fonction_screen.create_text(15, 0 + i * self.fonction_screen_width/20 |
text = self.fonction_screen.create_text(15, 0 + i * self.fonction_screen_width/20 |
||||
, text=min_x) |
, text=min_x) |
||||
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text) |
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text) |
||||
, fill="white") |
, fill="white") |
||||
self.fonction_screen.tag_lower(rect, text) |
self.fonction_screen.tag_lower(rect, text) |
||||
|
|
||||
text = self.fonction_screen.create_text(self.fonction_screen_width - 15 |
text = self.fonction_screen.create_text(self.fonction_screen_width - 15 |
||||
, 0 + i * self.fonction_screen_width/20 |
, 0 + i * self.fonction_screen_width/20 |
||||
, text=max_x) |
, text=max_x) |
||||
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
||||
self.fonction_screen.tag_lower(rect, text) |
self.fonction_screen.tag_lower(rect, text) |
||||
else: |
else: |
||||
self.fonction_screen.create_line(0, 0 + i * self.fonction_screen_width/20 |
self.fonction_screen.create_line(0, 0 + i * self.fonction_screen_width/20 |
||||
, self.fonction_screen_width |
, self.fonction_screen_width |
||||
, 0 + i * self.fonction_screen_width/20, fill='red') |
, 0 + i * self.fonction_screen_width/20, fill='red') |
||||
|
|
||||
def calculate(self) -> None: |
def calculate(self) -> None: |
||||
"""Calcule dans la partie graphique""" |
"""Calcule dans la partie graphique""" |
||||
exp = parse_string_to_list(self.calcul_entry.get()) |
exp = parse_string_to_list(self.calcul_entry.get()) |
||||
exp = npi2tree(inf2npi(exp)) |
exp = npi2tree(inf2npi(exp)) |
||||
exp.print_tree() |
exp.print_tree() |
||||
try: |
try: |
||||
result = exp.evalue() |
result = exp.evalue() |
||||
except ZeroDivisionError: |
except ZeroDivisionError: |
||||
result = "ERREUR" |
result = "ERREUR" |
||||
self.calcul_screen.configure(text=result) |
self.calcul_screen.configure(text=result) |
||||
|
|
||||
def draw_graph(self): |
def draw_graph(self): |
||||
"""Dessine les points du graphique""" |
"""Dessine les points du graphique""" |
||||
self.fonction_screen.delete('all') |
self.fonction_screen.delete('all') |
||||
min_x, max_x = map(int, self.fonction_bornes_entry.get().split(',')) |
min_x, max_x = map(int, self.fonction_bornes_entry.get().split(',')) # bornes du graphique |
||||
fonction_points = npi2tree(inf2npi(parse_string_to_list(self.fonction_entry.get()))).valeurs_de_fonction(min_x, max_x) |
fonction_points = npi2tree(inf2npi(parse_string_to_list(self.fonction_entry.get()))).valeurs_de_fonction(min_x, max_x) |
||||
max_y = max(fonction_points, key=lambda item: item[1])[1] |
max_y = max(fonction_points, key=lambda item: item[1])[1] |
||||
min_y = min(fonction_points, key=lambda item: item[1])[1] |
min_y = min(fonction_points, key=lambda item: item[1])[1] |
||||
self.draw_framing(min_x, max_x, min_y, max_y) |
self.draw_framing(min_x, max_x, min_y, max_y) |
||||
for i, (x, y) in enumerate(fonction_points): |
ratio = (fonction_points[0][0] - min_x) / (abs(max_x)+abs(min_x)) |
||||
image_x = i * (self.fonction_screen_width/len(fonction_points)) |
i = len(fonction_points) * ratio |
||||
image_y = self.fonction_screen_height - (y - min_y) * self.fonction_screen_height / (abs(max_y)+abs(min_y)) |
for (x, y) in fonction_points: |
||||
self.fonction_screen.create_rectangle(image_x, image_y, image_x, image_y) |
image_x = i * (self.fonction_screen_width/len(fonction_points)) |
||||
|
image_y = self.fonction_screen_height - (y - min_y) * self.fonction_screen_height / (abs(max_y)+abs(min_y)) |
||||
|
self.fonction_screen.create_rectangle(image_x, image_y, image_x, image_y) |
||||
|
i += 1 |
||||
|
@ -1,335 +1,335 @@ |
|||||
#!/usr/bin/env python3 |
#!/usr/bin/env python3 |
||||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||||
""" |
""" |
||||
Created on Tue Sep 22 20:44:35 2020 |
Created on Tue Sep 22 20:44:35 2020 |
||||
|
|
||||
@author: manu |
@author: manu |
||||
""" |
""" |
||||
|
|
||||
|
|
||||
class Maillon: |
class Maillon: |
||||
"""Un maillon d'une liste chaînée.""" |
"""Un maillon d'une liste chaînée.""" |
||||
def __init__(self, valeur, suivant): |
def __init__(self, valeur, suivant): |
||||
self.valeur = valeur |
self.valeur = valeur |
||||
self.suivant = suivant |
self.suivant = suivant |
||||
|
|
||||
def __str__(self): |
def __str__(self): |
||||
"""Renvoie une chane de caractères représentant le maillon.""" |
"""Renvoie une chane de caractères représentant le maillon.""" |
||||
return str(self.valeur) |
return str(self.valeur) |
||||
|
|
||||
|
|
||||
class ListeChaine: |
class ListeChaine: |
||||
"""Une liste chaînée.""" |
"""Une liste chaînée.""" |
||||
def __init__(self, tete=None): |
def __init__(self, tete=None): |
||||
"""Crée une liste vide, ou une liste dont la tete (un maillon) |
"""Crée une liste vide, ou une liste dont la tete (un maillon) |
||||
est donnée.""" |
est donnée.""" |
||||
self.__tete = tete |
self.__tete = tete |
||||
|
|
||||
def est_vide(self): |
def est_vide(self): |
||||
"""Indique si la liste est vide.""" |
"""Indique si la liste est vide.""" |
||||
return self.__tete is None |
return self.__tete is None |
||||
|
|
||||
def tete(self): |
def tete(self): |
||||
"""Renvoie la valeur du premier élément de la liste.""" |
"""Renvoie la valeur du premier élément de la liste.""" |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
raise IndexError("La liste vide n'a pas de tête") |
raise IndexError("La liste vide n'a pas de tête") |
||||
return self.__tete.valeur |
return self.__tete.valeur |
||||
|
|
||||
def queue(self): |
def queue(self): |
||||
"""Renvoie la queue de la liste.""" |
"""Renvoie la queue de la liste.""" |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
raise IndexError("La liste vide n'a pas de queue") |
raise IndexError("La liste vide n'a pas de queue") |
||||
return ListeChaine(self.__tete.suivant) |
return ListeChaine(self.__tete.suivant) |
||||
|
|
||||
def ajoute(self, valeur): |
def ajoute(self, valeur): |
||||
"""ajoute `valeur` en tête de la liste.""" |
"""ajoute `valeur` en tête de la liste.""" |
||||
self.__tete = Maillon(valeur, self.__tete) |
self.__tete = Maillon(valeur, self.__tete) |
||||
|
|
||||
def __str__(self): |
def __str__(self): |
||||
"""Renvoie une chaîne de caractères représentant la liste.""" |
"""Renvoie une chaîne de caractères représentant la liste.""" |
||||
maillon = self.__tete |
maillon = self.__tete |
||||
s = '' |
s = '' |
||||
while maillon is not None: |
while maillon is not None: |
||||
s = s + str(maillon.valeur) |
s = s + str(maillon.valeur) |
||||
maillon = maillon.suivant |
maillon = maillon.suivant |
||||
if maillon is not None: |
if maillon is not None: |
||||
s += '->' |
s += '->' |
||||
return s |
return s |
||||
|
|
||||
def __len__(self): |
def __len__(self): |
||||
"""Renvoie la longueur de la liste.""" |
"""Renvoie la longueur de la liste.""" |
||||
maillon = self.__tete |
maillon = self.__tete |
||||
long = 0 |
long = 0 |
||||
while maillon is not None: |
while maillon is not None: |
||||
long = long + 1 |
long = long + 1 |
||||
maillon = maillon.suivant |
maillon = maillon.suivant |
||||
return long |
return long |
||||
|
|
||||
def __getitem__(self, n): |
def __getitem__(self, n): |
||||
"""Renvoie l'élément d'indice n de la liste.""" |
"""Renvoie l'élément d'indice n de la liste.""" |
||||
maillon = self.__tete |
maillon = self.__tete |
||||
i = 0 |
i = 0 |
||||
while i < n and maillon is not None: |
while i < n and maillon is not None: |
||||
i = i + 1 |
i = i + 1 |
||||
maillon = maillon.suivant |
maillon = maillon.suivant |
||||
if maillon is None or n < 0: |
if maillon is None or n < 0: |
||||
raise IndexError("Indice non valide") |
raise IndexError("Indice non valide") |
||||
return maillon.valeur |
return maillon.valeur |
||||
|
|
||||
def __add__(self, other): |
def __add__(self, other): |
||||
"""Renvoie la liste correspondant à la concaténation des 2 listes.""" |
"""Renvoie la liste correspondant à la concaténation des 2 listes.""" |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
return other |
return other |
||||
v = self.tete() |
v = self.tete() |
||||
q = self.queue() |
q = self.queue() |
||||
return ListeChaine(Maillon(v, (q + other).__tete)) |
return ListeChaine(Maillon(v, (q + other).__tete)) |
||||
|
|
||||
def reverse(self): |
def reverse(self): |
||||
"""Renvoie une liste correspondant à la liste renversée.""" |
"""Renvoie une liste correspondant à la liste renversée.""" |
||||
res = ListeChaine() |
res = ListeChaine() |
||||
maillon = self.__tete |
maillon = self.__tete |
||||
while maillon is not None: |
while maillon is not None: |
||||
res.ajoute(maillon.valeur) |
res.ajoute(maillon.valeur) |
||||
maillon = maillon.suivant |
maillon = maillon.suivant |
||||
return res |
return res |
||||
|
|
||||
|
|
||||
class Pile_lst: |
class Pile_lst: |
||||
"""Implémentation d'une pile par une liste.""" |
"""Implémentation d'une pile par une liste.""" |
||||
def __init__(self): |
def __init__(self): |
||||
"""Crée une pile vide.""" |
"""Crée une pile vide.""" |
||||
self.__pile = [] |
self.__pile = [] |
||||
|
|
||||
def est_vide(self): |
def est_vide(self): |
||||
"""Indique si la pile est vide.""" |
"""Indique si la pile est vide.""" |
||||
return self.__pile == [] |
return self.__pile == [] |
||||
|
|
||||
def empiler(self, valeur): |
def empiler(self, valeur): |
||||
"""Empile la valeur.""" |
"""Empile la valeur.""" |
||||
self.__pile.append(valeur) |
self.__pile.append(valeur) |
||||
|
|
||||
def depiler(self): |
def depiler(self): |
||||
"""Dépile le sommet de la pile et le renvoie.""" |
"""Dépile le sommet de la pile et le renvoie.""" |
||||
return self.__pile.pop() |
return self.__pile.pop() |
||||
|
|
||||
def taille(self): |
def taille(self): |
||||
"""Renvoie la taille de la pile.""" |
"""Renvoie la taille de la pile.""" |
||||
return len(self.__pile) |
return len(self.__pile) |
||||
|
|
||||
def sommet(self): |
def sommet(self): |
||||
"""Renvoie le sommet de la pile (sans le dépiler).""" |
"""Renvoie le sommet de la pile (sans le dépiler).""" |
||||
return self.__pile[-1] |
return self.__pile[-1] |
||||
|
|
||||
def __str__(self): |
def __str__(self): |
||||
s = "|" |
s = "|" |
||||
for val in self.__pile: |
for val in self.__pile: |
||||
s = str(val) + "->" + s |
s = str(val) + "->" + s |
||||
return s |
return s |
||||
|
|
||||
|
|
||||
class Pile_chaine: |
class Pile_chaine: |
||||
"""Implémentation d'une pile par une liste chaînée.""" |
"""Implémentation d'une pile par une liste chaînée.""" |
||||
def __init__(self): |
def __init__(self): |
||||
"""Crée une pile vide.""" |
"""Crée une pile vide.""" |
||||
self.__pile = ListeChaine() |
self.__pile = ListeChaine() |
||||
self.__taille = 0 |
self.__taille = 0 |
||||
|
|
||||
def est_vide(self): |
def est_vide(self): |
||||
"""Indique si la pile est vide.""" |
"""Indique si la pile est vide.""" |
||||
return self.__taille == 0 |
return self.__taille == 0 |
||||
|
|
||||
def empiler(self, valeur): |
def empiler(self, valeur): |
||||
"""Empile la valeur.""" |
"""Empile la valeur.""" |
||||
self.__pile.ajoute(valeur) |
self.__pile.ajoute(valeur) |
||||
self.__taille += 1 |
self.__taille += 1 |
||||
|
|
||||
def depiler(self): |
def depiler(self): |
||||
"""Dépile le sommet de la pile et le renvoie.""" |
"""Dépile le sommet de la pile et le renvoie.""" |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
raise IndexError("Impossible de dépiler une pile vide.") |
raise IndexError("Impossible de dépiler une pile vide.") |
||||
valeur = self.__pile.tete() |
valeur = self.__pile.tete() |
||||
self.__pile = self.__pile.queue() |
self.__pile = self.__pile.queue() |
||||
self.__taille -= 1 |
self.__taille -= 1 |
||||
return valeur |
return valeur |
||||
|
|
||||
def taille(self): |
def taille(self): |
||||
"""Renvoie la taille de la pile.""" |
"""Renvoie la taille de la pile.""" |
||||
return self.__taille |
return self.__taille |
||||
|
|
||||
def sommet(self): |
def sommet(self): |
||||
"""Renvoie le sommet de la pile (sans le dépiler).""" |
"""Renvoie le sommet de la pile (sans le dépiler).""" |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
raise IndexError("Une pile vide n'a pas de sommet.") |
raise IndexError("Une pile vide n'a pas de sommet.") |
||||
return self.__pile.tete() |
return self.__pile.tete() |
||||
|
|
||||
def __str__(self): |
def __str__(self): |
||||
return str(self.__pile) + "->|" |
return str(self.__pile) + "->|" |
||||
|
|
||||
|
|
||||
class File_lst: |
class File_lst: |
||||
"""Implémentation d'une file par une liste.""" |
"""Implémentation d'une file par une liste.""" |
||||
def __init__(self): |
def __init__(self): |
||||
"""Crée une file vide.""" |
"""Crée une file vide.""" |
||||
self.__file = [] |
self.__file = [] |
||||
|
|
||||
def est_vide(self): |
def est_vide(self): |
||||
"""Indique si la file est vide.""" |
"""Indique si la file est vide.""" |
||||
return self.__file == [] |
return self.__file == [] |
||||
|
|
||||
def enfiler(self, valeur): |
def enfiler(self, valeur): |
||||
"""Enfile l'élément valeur.""" |
"""Enfile l'élément valeur.""" |
||||
self.__file.append(valeur) |
self.__file.append(valeur) |
||||
|
|
||||
def defiler(self): |
def defiler(self): |
||||
"""Défile la tête de la file et la renvoie.""" |
"""Défile la tête de la file et la renvoie.""" |
||||
return self.__file.pop(0) |
return self.__file.pop(0) |
||||
|
|
||||
def taille(self): |
def taille(self): |
||||
"""Renvoie la taille de la file.""" |
"""Renvoie la taille de la file.""" |
||||
return len(self.__file) |
return len(self.__file) |
||||
|
|
||||
def tete(self): |
def tete(self): |
||||
"""Renvoie la tête de la file (sans la défiler).""" |
"""Renvoie la tête de la file (sans la défiler).""" |
||||
return self.__file[0] |
return self.__file[0] |
||||
|
|
||||
def __str__(self): |
def __str__(self): |
||||
s = "tete->" |
s = "tete->" |
||||
for val in self.__file: |
for val in self.__file: |
||||
s += str(val) + "->" |
s += str(val) + "->" |
||||
return s + "queue" |
return s + "queue" |
||||
|
|
||||
|
|
||||
class Maillon_db: |
class Maillon_db: |
||||
"""Un maillon d'une liste doublement chaînée.""" |
"""Un maillon d'une liste doublement chaînée.""" |
||||
def __init__(self, precedent, valeur, suivant): |
def __init__(self, precedent, valeur, suivant): |
||||
self.valeur = valeur |
self.valeur = valeur |
||||
self.precedent = precedent |
self.precedent = precedent |
||||
self.suivant = suivant |
self.suivant = suivant |
||||
|
|
||||
def __str__(self): |
def __str__(self): |
||||
return str(self.valeur) |
return str(self.valeur) |
||||
|
|
||||
|
|
||||
class File_chaine: |
class File_chaine: |
||||
"""Implémentation d'une file par une liste doublement chaînée.""" |
"""Implémentation d'une file par une liste doublement chaînée.""" |
||||
def __init__(self): |
def __init__(self): |
||||
"""Crée une file vide.""" |
"""Crée une file vide.""" |
||||
self.__debut = self.__fin = None |
self.__debut = self.__fin = None |
||||
self.__taille = 0 |
self.__taille = 0 |
||||
|
|
||||
def __iter__(self): |
def __iter__(self): |
||||
return self |
return self |
||||
|
|
||||
def __next__(self): |
def __next__(self): |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
raise StopIteration |
raise StopIteration |
||||
return self.defiler() |
return self.defiler() |
||||
|
|
||||
def est_vide(self): |
def est_vide(self): |
||||
"""Indique si la file est vide.""" |
"""Indique si la file est vide.""" |
||||
return self.__taille == 0 |
return self.__taille == 0 |
||||
|
|
||||
def enfiler(self, valeur): |
def enfiler(self, valeur): |
||||
"""Enfile l'élément valeur.""" |
"""Enfile l'élément valeur.""" |
||||
maillon = Maillon_db(self.__fin, valeur, None) |
maillon = Maillon_db(self.__fin, valeur, None) |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
self.__debut = self.__fin = maillon |
self.__debut = self.__fin = maillon |
||||
else: |
else: |
||||
self.__fin.suivant = maillon |
self.__fin.suivant = maillon |
||||
self.__fin = maillon |
self.__fin = maillon |
||||
self.__taille += 1 |
self.__taille += 1 |
||||
|
|
||||
def defiler(self): |
def defiler(self): |
||||
"""Défile la tête de la file et la renvoie.""" |
"""Défile la tête de la file et la renvoie.""" |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
raise IndexError("Impossible de défiler une file vide.") |
raise IndexError("Impossible de défiler une file vide.") |
||||
valeur = self.__debut.valeur |
valeur = self.__debut.valeur |
||||
self.__taille -= 1 |
self.__taille -= 1 |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
self.__debut = self.__fin = None |
self.__debut = self.__fin = None |
||||
else: |
else: |
||||
self.__debut = self.__debut.suivant |
self.__debut = self.__debut.suivant |
||||
self.__debut.precedent = None |
self.__debut.precedent = None |
||||
return valeur |
return valeur |
||||
|
|
||||
def taille(self): |
def taille(self): |
||||
"""Renvoie la taille de la file.""" |
"""Renvoie la taille de la file.""" |
||||
return self.__taille |
return self.__taille |
||||
|
|
||||
def tete(self): |
def tete(self): |
||||
"""Renvoie la tête de la file (sans la défiler).""" |
"""Renvoie la tête de la file (sans la défiler).""" |
||||
if self.est_vide(): |
if self.est_vide(): |
||||
raise IndexError("Une file vide n'a pas de tête.") |
raise IndexError("Une file vide n'a pas de tête.") |
||||
return self.__debut.valeur |
return self.__debut.valeur |
||||
|
|
||||
def __str__(self): |
def __str__(self): |
||||
s = "tete->" |
s = "tete->" |
||||
maillon = self.__debut |
maillon = self.__debut |
||||
while maillon is not None: |
while maillon is not None: |
||||
s += str(maillon) + "->" |
s += str(maillon) + "->" |
||||
maillon = maillon.suivant |
maillon = maillon.suivant |
||||
return s + "queue" |
return s + "queue" |
||||
|
|
||||
|
|
||||
class Arbre: |
class Arbre: |
||||
def __init__(self, val) -> None: |
def __init__(self, val) -> None: |
||||
self.val = val |
self.val = val |
||||
self.gauche = None |
self.gauche = None |
||||
self.droit = None |
self.droit = None |
||||
|
|
||||
def insere_gauche(self, val) -> object: |
def insere_gauche(self, val) -> object: |
||||
"""insere un arbre gauche a la racine de l'arbre""" |
"""insere un arbre gauche a la racine de l'arbre""" |
||||
nouvel_arbre = Arbre(val) |
nouvel_arbre = Arbre(val) |
||||
nouvel_arbre.gauche = self.gauche |
nouvel_arbre.gauche = self.gauche |
||||
self.gauche = nouvel_arbre |
self.gauche = nouvel_arbre |
||||
return nouvel_arbre |
return nouvel_arbre |
||||
|
|
||||
def insere_droit(self, val) -> object: |
def insere_droit(self, val) -> object: |
||||
"""insere un arbre gauche a la racine de l'arbre""" |
"""insere un arbre gauche a la racine de l'arbre""" |
||||
nouvel_arbre = Arbre(val) |
nouvel_arbre = Arbre(val) |
||||
nouvel_arbre.gauche = self.droit |
nouvel_arbre.gauche = self.droit |
||||
self.droit = nouvel_arbre |
self.droit = nouvel_arbre |
||||
return nouvel_arbre |
return nouvel_arbre |
||||
|
|
||||
|
|
||||
if __name__ == "__main__": |
if __name__ == "__main__": |
||||
f = File_lst() |
f = File_lst() |
||||
print(f.est_vide()) |
print(f.est_vide()) |
||||
f.enfiler('A') |
f.enfiler('A') |
||||
f.enfiler('B') |
f.enfiler('B') |
||||
f.enfiler('C') |
f.enfiler('C') |
||||
print(f.est_vide()) |
print(f.est_vide()) |
||||
print(f.tete()) |
print(f.tete()) |
||||
print(f) |
print(f) |
||||
print(f.taille()) |
print(f.taille()) |
||||
print(f.defiler()) |
print(f.defiler()) |
||||
print(f.defiler()) |
print(f.defiler()) |
||||
print(f.defiler()) |
print(f.defiler()) |
||||
print(f.est_vide()) |
print(f.est_vide()) |
||||
lst = ListeChaine() |
lst = ListeChaine() |
||||
print(lst.est_vide()) |
print(lst.est_vide()) |
||||
lst.ajoute(306) |
lst.ajoute(306) |
||||
lst.ajoute(42) |
lst.ajoute(42) |
||||
lst.ajoute(205) |
lst.ajoute(205) |
||||
print(lst) |
print(lst) |
||||
print(lst.est_vide()) |
print(lst.est_vide()) |
||||
print(lst[0]) |
print(lst[0]) |
||||
print(lst[1]) |
print(lst[1]) |
||||
print(len(lst)) |
print(len(lst)) |
||||
lst2 = ListeChaine() |
lst2 = ListeChaine() |
||||
lst2.ajoute(18) |
lst2.ajoute(18) |
||||
lst2.ajoute(45) |
lst2.ajoute(45) |
||||
print(lst + lst2) |
print(lst + lst2) |
||||
p = Pile_lst() |
p = Pile_lst() |
||||
print(p.est_vide()) |
print(p.est_vide()) |
||||
p.empiler('A') |
p.empiler('A') |
||||
p.empiler('B') |
p.empiler('B') |
||||
p.empiler('C') |
p.empiler('C') |
||||
print(p.est_vide()) |
print(p.est_vide()) |
||||
print(p.sommet()) |
print(p.sommet()) |
||||
print(p) |
print(p) |
||||
print(p.taille()) |
print(p.taille()) |
||||
print(p.depiler()) |
print(p.depiler()) |
||||
print(p.depiler()) |
print(p.depiler()) |
||||
print(p.depiler()) |
print(p.depiler()) |
||||
print(p.est_vide()) |
print(p.est_vide()) |
@ -1,73 +1,73 @@ |
|||||
"""Fichier de classe pour les expressions""" |
"""Fichier de classe pour les expressions""" |
||||
import math |
import math |
||||
|
|
||||
class Expression: |
class Expression: |
||||
"""manipule les expression sous forme d'arbre""" |
"""manipule les expression sous forme d'arbre""" |
||||
def __init__(self, val, fils_gauche=None, fils_droit=None) -> None: |
def __init__(self, val, fils_gauche=None, fils_droit=None) -> None: |
||||
self.val = val |
self.val = val |
||||
self.fils_gauche = fils_gauche |
self.fils_gauche = fils_gauche |
||||
self.fils_droit = fils_droit |
self.fils_droit = fils_droit |
||||
|
|
||||
def __str__(self) -> str: |
def __str__(self) -> str: |
||||
"""renvoie l'expression sous forme infixé""" |
"""renvoie l'expression sous forme infixé""" |
||||
if self.est_feuille(): |
if self.est_feuille(): |
||||
return str(self.val) |
return str(self.val) |
||||
return '('+self.fils_gauche.__str__()+str(self.val)+self.fils_droit.__str__()+')' |
return '('+self.fils_gauche.__str__()+str(self.val)+self.fils_droit.__str__()+')' |
||||
|
|
||||
def print_tree(self, level=0): |
def print_tree(self, level=0): |
||||
""" Affiche le noeud joliment""" |
""" Affiche le noeud joliment""" |
||||
if self.fils_gauche is not None: |
if self.fils_gauche is not None: |
||||
self.fils_gauche.print_tree(level + 1) |
self.fils_gauche.print_tree(level + 1) |
||||
print(' ' * 4 * level + '-> ' + str(self.val)) |
print(' ' * 4 * level + '-> ' + str(self.val)) |
||||
if self.fils_droit is not None: |
if self.fils_droit is not None: |
||||
self.fils_droit.print_tree(level + 1) |
self.fils_droit.print_tree(level + 1) |
||||
|
|
||||
def est_feuille(self) -> bool: |
def est_feuille(self) -> bool: |
||||
""" Renvoie true si le noeud est une feuille""" |
""" Renvoie true si le noeud est une feuille""" |
||||
if self.fils_droit is None and self.fils_gauche is None: |
if self.fils_droit is None and self.fils_gauche is None: |
||||
return True |
return True |
||||
return False |
return False |
||||
|
|
||||
def evalue(self, x=0) -> float: |
def evalue(self, x=0) -> float: |
||||
""" Renvoie le résultat de l'expression""" |
""" Renvoie le résultat de l'expression""" |
||||
try: |
try: |
||||
if self.est_feuille(): |
if self.est_feuille(): |
||||
if self.val == 'x': |
if self.val == 'x': |
||||
return x |
return x |
||||
return float(self.val) |
return float(self.val) |
||||
elif self.val == '+': |
elif self.val == '+': |
||||
return self.fils_gauche.evalue(x) + self.fils_droit.evalue(x) |
return self.fils_gauche.evalue(x) + self.fils_droit.evalue(x) |
||||
elif self.val == '*': |
elif self.val == '*': |
||||
return self.fils_gauche.evalue(x) * self.fils_droit.evalue(x) |
return self.fils_gauche.evalue(x) * self.fils_droit.evalue(x) |
||||
elif self.val == '/': |
elif self.val == '/': |
||||
return self.fils_gauche.evalue(x) / self.fils_droit.evalue(x) |
return self.fils_gauche.evalue(x) / self.fils_droit.evalue(x) |
||||
elif self.val == '^': |
elif self.val == '^': |
||||
return self.fils_gauche.evalue(x) ** self.fils_droit.evalue(x) |
return self.fils_gauche.evalue(x) ** self.fils_droit.evalue(x) |
||||
elif self.val == '-': |
elif self.val == '-': |
||||
return self.fils_gauche.evalue(x) - self.fils_droit.evalue(x) |
return self.fils_gauche.evalue(x) - self.fils_droit.evalue(x) |
||||
elif self.val == 'ln': |
elif self.val == 'ln': |
||||
return math.log(self.fils_gauche.evalue(x)) |
return math.log(self.fils_gauche.evalue(x)) |
||||
elif self.val == '√': |
elif self.val == '√': |
||||
return math.sqrt(self.fils_gauche.evalue(x)) |
return math.sqrt(self.fils_gauche.evalue(x)) |
||||
elif self.val == "cos": |
elif self.val == "cos": |
||||
return math.cos(self.fils_gauche.evalue(x)) |
return math.cos(self.fils_gauche.evalue(x)) |
||||
elif self.val == "sin": |
elif self.val == "sin": |
||||
return math.sin(self.fils_gauche.evalue(x)) |
return math.sin(self.fils_gauche.evalue(x)) |
||||
elif self.val == "tan": |
elif self.val == "tan": |
||||
return math.tan(self.fils_gauche.evalue(x)) |
return math.tan(self.fils_gauche.evalue(x)) |
||||
|
|
||||
except ZeroDivisionError: |
except ZeroDivisionError: |
||||
raise ZeroDivisionError |
raise ZeroDivisionError |
||||
|
|
||||
def valeurs_de_fonction(self, start, end): |
def valeurs_de_fonction(self, start, end): |
||||
""" Calcul les valeurs entre start et end""" |
""" Calcul les valeurs entre start et end""" |
||||
result = [] |
result = [] |
||||
pas = (end - start) / 1000 |
pas = (end - start) / 1000 |
||||
while start <= end: |
while start <= end: |
||||
try: |
try: |
||||
result.append((start, self.evalue(start))) |
result.append((start, self.evalue(start))) |
||||
except: |
except: |
||||
pass |
pass |
||||
start += pas |
start += pas |
||||
return result |
return result |
||||
|
|
||||
|
@ -1,328 +1,331 @@ |
|||||
"""Classe d'application tk""" |
"""Classe d'application tk""" |
||||
|
|
||||
import math |
import math |
||||
import tkinter as tk |
import tkinter as tk |
||||
import tkinter.font |
import tkinter.font |
||||
from package.data_structure import Pile_chaine |
from package.data_structure import Pile_chaine |
||||
from package.expression import Expression |
from package.expression import Expression |
||||
|
|
||||
|
|
||||
def parse_string_to_list(text: str) -> list: |
def parse_string_to_list(text: str) -> list: |
||||
""" Transforme le text en liste d'éléments intelligible par le programme """ |
""" Transforme le text en liste d'éléments intelligible par le programme """ |
||||
text = list(text) |
text = list(text) |
||||
result = [] |
result = [] |
||||
buffer_function = "" |
buffer_function = "" |
||||
buffer_number = "" |
buffer_number = "" |
||||
number_first = False # Savoir dans quel ordre sont les chiffres et les lettres |
number_first = False # Savoir dans quel ordre sont les chiffres et les lettres |
||||
for char in text: |
for char in text: |
||||
if char == 'e': |
if char == 'e': |
||||
result.append(math.e) |
result.append(math.e) |
||||
elif char == '𝜋': |
elif char == '𝜋': |
||||
result.append(math.pi) |
result.append(math.pi) |
||||
elif char.isdigit() or char == ".": |
elif char.isdigit() or char == ".": |
||||
buffer_number += char |
buffer_number += char |
||||
if len(buffer_function) == 0: |
if len(buffer_function) == 0: |
||||
number_first = True |
number_first = True |
||||
elif char.isalpha(): |
elif char.isalpha(): |
||||
buffer_function += char |
buffer_function += char |
||||
else: |
else: |
||||
if number_first: |
if number_first: |
||||
result.append(float(buffer_number)) |
result.append(float(buffer_number)) |
||||
buffer_number = "" |
buffer_number = "" |
||||
number_first = False |
number_first = False |
||||
if len(buffer_function) != 0: |
if len(buffer_function) != 0: |
||||
result.append('*') |
result.append('*') |
||||
result.append(buffer_function) |
result.append(buffer_function) |
||||
buffer_function = "" |
buffer_function = "" |
||||
elif char == '(': |
elif char == '(': |
||||
result.append('*') |
result.append('*') |
||||
|
|
||||
else: |
else: |
||||
if len(buffer_function) != 0: |
if len(buffer_function) != 0: |
||||
result.append(buffer_function) |
result.append(buffer_function) |
||||
buffer_function = "" |
buffer_function = "" |
||||
if len(buffer_number) != 0: |
if len(buffer_number) != 0: |
||||
result.append(float(buffer_number)) |
result.append(float(buffer_number)) |
||||
buffer_number = "" |
buffer_number = "" |
||||
number_first = False |
number_first = False |
||||
result.append(char) |
result.append(char) |
||||
if len(buffer_number) != 0: |
if len(buffer_number) != 0: |
||||
result.append(float(buffer_number)) |
result.append(float(buffer_number)) |
||||
if len(buffer_function) != 0: |
if len(buffer_function) != 0: |
||||
result.append('*') |
result.append('*') |
||||
result.append(buffer_function) |
result.append(buffer_function) |
||||
elif len(buffer_function) != 0: |
elif len(buffer_function) != 0: |
||||
result.append(buffer_function) |
result.append(buffer_function) |
||||
return result |
return result |
||||
|
|
||||
def npi2tree(expr: list) -> Expression: |
def npi2tree(expr: list) -> Expression: |
||||
""" Renvoie l'arbre formé à partir de l'expression donnée""" |
""" Renvoie l'arbre formé à partir de l'expression donnée""" |
||||
pile = Pile_chaine() |
pile = Pile_chaine() |
||||
for val in expr: |
for val in expr: |
||||
if not type(val) is float and val != "x": |
if not type(val) is float and val != "x": |
||||
# on inverse pour avoir les nombres dans le bon ordre |
# on inverse pour avoir les nombres dans le bon ordre |
||||
nombre2 = pile.depiler() |
nombre2 = pile.depiler() |
||||
if not pile.est_vide(): |
if not pile.est_vide(): |
||||
pile.empiler(Expression(val, pile.depiler(), nombre2)) |
pile.empiler(Expression(val, pile.depiler(), nombre2)) |
||||
else: |
else: |
||||
pile.empiler(Expression(val, nombre2)) |
pile.empiler(Expression(val, nombre2)) |
||||
else: |
else: |
||||
pile.empiler(Expression(val)) |
pile.empiler(Expression(val)) |
||||
return pile.sommet() |
return pile.sommet() |
||||
|
|
||||
def inf2npi(expr: list) -> list: |
def inf2npi(expr: list) -> list: |
||||
"""Transforme une expression infixé en notation polonaise inversée""" |
"""Transforme une expression infixé en notation polonaise inversée""" |
||||
operator_stack = Pile_chaine() |
operator_stack = Pile_chaine() |
||||
operator_priority = { |
operator_priority = { |
||||
'+': 1, |
'+': 1, |
||||
'-': 1, |
'-': 1, |
||||
'*': 2, |
'*': 2, |
||||
'^': 3, |
'^': 3, |
||||
'/': 2, |
'/': 2, |
||||
'(': 0, |
'(': 0, |
||||
')': 0 |
')': 0 |
||||
} |
} |
||||
output = [] |
output = [] |
||||
for val in expr: |
for val in expr: |
||||
if type(val) is float or val == 'x': |
if type(val) is float or val == 'x': |
||||
output.append(val) |
output.append(val) |
||||
else: |
else: |
||||
if operator_stack.est_vide() or ( val == '(' or operator_priority[val] > operator_priority[operator_stack.sommet()]): |
if operator_stack.est_vide() or ( val == '(' or operator_priority[val] > operator_priority[operator_stack.sommet()]): |
||||
operator_stack.empiler(val) |
operator_stack.empiler(val) |
||||
else: |
else: |
||||
while not operator_stack.est_vide(): |
while not operator_stack.est_vide(): |
||||
if operator_stack.sommet() == '(': |
if operator_stack.sommet() == '(': |
||||
operator_stack.depiler() |
operator_stack.depiler() |
||||
else: |
else: |
||||
output.append(operator_stack.depiler()) |
output.append(operator_stack.depiler()) |
||||
if val != ')': |
if val != ')': |
||||
operator_stack.empiler(val) |
operator_stack.empiler(val) |
||||
while not operator_stack.est_vide(): |
while not operator_stack.est_vide(): |
||||
output.append(operator_stack.depiler()) |
output.append(operator_stack.depiler()) |
||||
return output |
return output |
||||
|
|
||||
|
|
||||
class App(tk.Tk): |
class App(tk.Tk): |
||||
"""Classe d'application graphique si python < 3.7""" |
"""Classe d'application graphique si python < 3.7""" |
||||
def __init__(self) -> None: |
def __init__(self) -> None: |
||||
super().__init__() |
super().__init__() |
||||
|
|
||||
self.fonction_screen_height = None |
self.fonction_screen_height = None |
||||
self.fonction_screen_width = None |
self.fonction_screen_width = None |
||||
|
|
||||
# touches de la calculette |
# touches de la calculette |
||||
|
|
||||
self.keys = [] |
self.keys = [] |
||||
for i, val in enumerate(["←", "cos", "sin", "tan", "→", "x", "e", "√", "^", "𝜋", 7, 8, 9, "(", ")", 4, 5, 6, "*", "/", 1, 2, 3, "+", "-", |
for i, val in enumerate(["←", "cos", "sin", "tan", "→", "x", "e", "√", "^", "𝜋", 7, 8, 9, "(", ")", 4, 5, 6, "*", "/", 1, 2, 3, "+", "-", |
||||
"clear", 0, ".", "ln", "exe"]): # add numbers button |
"clear", 0, ".", "ln", "exe"]): # add numbers button |
||||
if type(val) == int: |
if type(val) == int: |
||||
self.keys.append(tk.Button(self, text=val, command=lambda x=val: self.add_value(x), background="blue", fg="gray90")) |
self.keys.append(tk.Button(self, text=val, command=lambda x=val: self.add_value(x), background="blue", fg="gray90")) |
||||
elif val == "clear": |
elif val == "clear": |
||||
self.keys.append(tk.Button(self, text=val, command=self.clear_screen)) |
self.keys.append(tk.Button(self, text=val, command=self.clear_screen)) |
||||
elif val == "←": |
elif val == "←": |
||||
self.keys.append(tk.Button(self, text=val, command=self.move_cursor_left)) |
self.keys.append(tk.Button(self, text=val, command=self.move_cursor_left)) |
||||
elif val == "→": |
elif val == "→": |
||||
self.keys.append(tk.Button(self, text=val, command=self.move_cursor_right)) |
self.keys.append(tk.Button(self, text=val, command=self.move_cursor_right)) |
||||
else: |
else: |
||||
self.keys.append(tk.Button(self, text=val, command=lambda x=val: self.add_value(x))) |
self.keys.append(tk.Button(self, text=val, command=lambda x=val: self.add_value(x))) |
||||
self.keys[i].grid(row=i//5+1, column=i % 5+1, sticky="NSEW", padx=5, pady=5) |
self.keys[i].grid(row=i//5+1, column=i % 5+1, sticky="NSEW", padx=5, pady=5) |
||||
|
|
||||
# Calcul Frame |
# Calcul Frame |
||||
|
|
||||
self.calcul_frame = tk.Frame(self, bg="gray30") |
self.calcul_frame = tk.Frame(self, bg="gray30") |
||||
|
|
||||
self.calcul_screen = tk.Label(self.calcul_frame, text="hello") |
self.calcul_screen = tk.Label(self.calcul_frame, text="hello") |
||||
self.calcul_screen.pack(fill="both", expand=True) |
self.calcul_screen.pack(fill="both", expand=True) |
||||
self.calcul_entry = tk.Entry(self.calcul_frame, width=50) |
self.calcul_entry = tk.Entry(self.calcul_frame, width=50) |
||||
self.calcul_entry.pack(fill="both", expand=True) |
self.calcul_entry.pack(fill="both", expand=True) |
||||
|
|
||||
# Fonction Frame |
# Fonction Frame |
||||
|
|
||||
self.fonction_frame = tk.Frame(self, bg="gray30") |
self.fonction_frame = tk.Frame(self, bg="gray30") |
||||
|
|
||||
self.fonction_bornes_frame = tk.Frame(self.fonction_frame) |
self.fonction_bornes_frame = tk.Frame(self.fonction_frame) |
||||
|
|
||||
self.fonction_bornes_entry = tk.Entry(self.fonction_bornes_frame) |
self.fonction_bornes_entry = tk.Entry(self.fonction_bornes_frame) |
||||
self.fonction_bornes_entry.insert(0, "-100,100") |
self.fonction_bornes_entry.insert(0, "-100,100") |
||||
self.fonction_bornes_entry.grid(sticky="ew", row=1, padx=10) |
self.fonction_bornes_entry.grid(sticky="ew", row=1, padx=10) |
||||
|
|
||||
self.fonction_bornes_text = tk.Label(self.fonction_bornes_frame, text="Entrez les bornes de tracé: (min, max)") |
self.fonction_bornes_text = tk.Label(self.fonction_bornes_frame, text="Entrez les bornes de tracé: (min, max)") |
||||
self.fonction_bornes_text.grid(sticky="ew", row=0) |
self.fonction_bornes_text.grid(sticky="ew", row=0) |
||||
|
|
||||
self.fonction_bornes_frame.grid(sticky="ns", column=0, rowspan=2) |
self.fonction_bornes_frame.grid(sticky="ns", column=0, rowspan=2) |
||||
|
|
||||
|
|
||||
self.fonction_screen = tk.Canvas(self.fonction_frame) |
self.fonction_screen = tk.Canvas(self.fonction_frame) |
||||
self.fonction_screen.grid(sticky="nsew", column=1, row=0) |
self.fonction_screen.grid(sticky="nsew", column=1, row=0) |
||||
self.fonction_entry = tk.Entry(self.fonction_frame) |
self.fonction_entry = tk.Entry(self.fonction_frame) |
||||
self.fonction_entry.grid(sticky='ew', column=1, row=1) |
self.fonction_entry.grid(sticky='ew', column=1, row=1) |
||||
|
|
||||
# navigation menu |
# navigation menu |
||||
self.navigation_frame = tk.Frame(self, bg="gray50") |
self.navigation_frame = tk.Frame(self, bg="gray50") |
||||
self.navigation_frame.grid(row=0, rowspan=10, column=0, sticky="nsew") |
self.navigation_frame.grid(row=0, rowspan=10, column=0, sticky="nsew") |
||||
|
|
||||
self.titre = tk.Label(self.navigation_frame, text="Wx Calculator", compound="left" |
self.titre = tk.Label(self.navigation_frame, text="Wx Calculator", compound="left" |
||||
, font=tk.font.Font(size=15, weight="bold")) |
, font=tk.font.Font(size=15, weight="bold")) |
||||
self.titre.grid(row=0, column=0, padx=20, pady=20) |
self.titre.grid(row=0, column=0, padx=20, pady=20) |
||||
|
|
||||
self.home_button = tk.Button(self.navigation_frame, height=3 |
self.home_button = tk.Button(self.navigation_frame, height=3 |
||||
, text="Calcul", bg="gray30", fg="gray10", anchor="w" |
, text="Calcul", bg="gray30", fg="gray10", anchor="w" |
||||
, command=lambda: self.select_frame_by_name("Calcul")) |
, command=lambda: self.select_frame_by_name("Calcul")) |
||||
self.home_button.grid(row=1, column=0, sticky="ew") |
self.home_button.grid(row=1, column=0, sticky="ew") |
||||
|
|
||||
self.function_button = tk.Button(self.navigation_frame, height=3 |
self.function_button = tk.Button(self.navigation_frame, height=3 |
||||
, text="Fonction", bg="gray30", fg="gray10", anchor="w" |
, text="Fonction", bg="gray30", fg="gray10", anchor="w" |
||||
, command=lambda: self.select_frame_by_name("Fonction")) |
, command=lambda: self.select_frame_by_name("Fonction")) |
||||
self.function_button.grid(row=2, column=0, sticky="ew") |
self.function_button.grid(row=2, column=0, sticky="ew") |
||||
|
|
||||
self.mode = 'Calcul' |
self.mode = 'Calcul' |
||||
|
|
||||
# select default frame |
# select default frame |
||||
|
|
||||
self.select_frame_by_name("Calcul") |
self.select_frame_by_name("Calcul") |
||||
|
|
||||
def select_frame_by_name(self, name): |
def select_frame_by_name(self, name): |
||||
"""Change de mode : passe de calcul à fonction""" |
"""Change de mode : passe de calcul à fonction""" |
||||
# set button color for selected button |
# set button color for selected button |
||||
self.home_button.configure(bg="gray75" if name == "Calcul" else "gray30") |
self.home_button.configure(bg="gray75" if name == "Calcul" else "gray30") |
||||
self.function_button.configure(bg="gray75" if name == "Fonction" else "gray30") |
self.function_button.configure(bg="gray75" if name == "Fonction" else "gray30") |
||||
|
|
||||
# show selected frame |
# show selected frame |
||||
if name == "Calcul": |
if name == "Calcul": |
||||
self.mode = "Calcul" |
self.mode = "Calcul" |
||||
self.calcul_frame.grid(padx=20, pady=20, columnspan=5, column=1, row=0, sticky="nsew") |
self.calcul_frame.grid(padx=20, pady=20, columnspan=5, column=1, row=0, sticky="nsew") |
||||
self.keys[-1].configure(command=self.calculate) |
self.keys[-1].configure(command=self.calculate) |
||||
|
|
||||
else: |
else: |
||||
self.calcul_frame.grid_forget() |
self.calcul_frame.grid_forget() |
||||
if name == "Fonction": |
if name == "Fonction": |
||||
self.mode = "Fonction" |
self.mode = "Fonction" |
||||
self.fonction_frame.grid(columnspan=5, column=1, row=0, padx=20, pady=20, sticky="ns") |
self.fonction_frame.grid(columnspan=5, column=1, row=0, padx=20, pady=20, sticky="ns") |
||||
self.fonction_frame.update() |
self.fonction_frame.update() |
||||
self.fonction_screen_width = self.fonction_screen.winfo_width() |
self.fonction_screen_width = self.fonction_screen.winfo_width() |
||||
self.keys[-1].configure(command=self.draw_graph) |
self.keys[-1].configure(command=self.draw_graph) |
||||
self.fonction_screen_height = self.fonction_screen.winfo_height() |
self.fonction_screen_height = self.fonction_screen.winfo_height() |
||||
else: |
else: |
||||
self.fonction_frame.grid_forget() |
self.fonction_frame.grid_forget() |
||||
|
|
||||
def add_value(self, value) -> None: |
def add_value(self, value) -> None: |
||||
"""Ajoute le charactère à la suite de l'expression""" |
"""Ajoute le charactère à la suite de l'expression""" |
||||
parenthesis = False |
parenthesis = False |
||||
if value == "e": |
if value == "e": |
||||
value += "^" |
value += "^" |
||||
if value == "(": |
if value == "(": |
||||
value += ")" |
value += ")" |
||||
parenthesis = True |
parenthesis = True |
||||
elif value in ["ln", "cos", "sin", "tan", "√"]: |
elif value in ["ln", "cos", "sin", "tan", "√"]: |
||||
value += "()" |
value += "()" |
||||
parenthesis = True |
parenthesis = True |
||||
if self.mode == 'Fonction': |
if self.mode == 'Fonction': |
||||
self.fonction_entry.insert(tk.INSERT, value) |
self.fonction_entry.insert(tk.INSERT, value) |
||||
else: |
else: |
||||
self.calcul_entry.insert(tk.INSERT, value) |
self.calcul_entry.insert(tk.INSERT, value) |
||||
if parenthesis: |
if parenthesis: |
||||
self.move_cursor_left() |
self.move_cursor_left() |
||||
|
|
||||
def clear_screen(self) -> None: |
def clear_screen(self) -> None: |
||||
"""Enlève l'affichage actuel""" |
"""Enlève l'affichage actuel""" |
||||
if self.mode == "Calcul": |
if self.mode == "Calcul": |
||||
self.calcul_screen.configure(text="") |
self.calcul_screen.configure(text="") |
||||
self.calcul_entry.delete('0', 'end') |
self.calcul_entry.delete('0', 'end') |
||||
else: |
else: |
||||
self.fonction_screen.delete('all') |
self.fonction_screen.delete('all') |
||||
self.fonction_entry.delete(0, 'end') |
self.fonction_entry.delete(0, 'end') |
||||
|
|
||||
def move_cursor_left(self): |
def move_cursor_left(self): |
||||
"""Déplace le curseur à gauche""" |
"""Déplace le curseur à gauche""" |
||||
if self.mode == "Calcul": |
if self.mode == "Calcul": |
||||
pos = self.calcul_entry.index(tk.INSERT) |
pos = self.calcul_entry.index(tk.INSERT) |
||||
if pos > 0: |
if pos > 0: |
||||
self.calcul_entry.icursor(pos -1) |
self.calcul_entry.icursor(pos -1) |
||||
else: |
else: |
||||
pos = self.fonction_entry.index(tk.INSERT) |
pos = self.fonction_entry.index(tk.INSERT) |
||||
if pos > 0: |
if pos > 0: |
||||
self.fonction_entry.icursor(pos-1) |
self.fonction_entry.icursor(pos-1) |
||||
|
|
||||
def move_cursor_right(self): |
def move_cursor_right(self): |
||||
"""Déplace le curseur à droite""" |
"""Déplace le curseur à droite""" |
||||
if self.mode == "Calcul": |
if self.mode == "Calcul": |
||||
pos = self.calcul_entry.index(tk.INSERT) |
pos = self.calcul_entry.index(tk.INSERT) |
||||
if pos < len(self.calcul_entry.get()): |
if pos < len(self.calcul_entry.get()): |
||||
self.calcul_entry.icursor(pos + 1) |
self.calcul_entry.icursor(pos + 1) |
||||
else: |
else: |
||||
pos = self.fonction_entry.index(tk.INSERT) |
pos = self.fonction_entry.index(tk.INSERT) |
||||
if pos < len(self.fonction_entry.get()): |
if pos < len(self.fonction_entry.get()): |
||||
self.fonction_entry.icursor(pos + 1) |
self.fonction_entry.icursor(pos + 1) |
||||
|
|
||||
def draw_framing(self, min_x, max_x, min_y, max_y): |
def draw_framing(self, min_x, max_x, min_y, max_y): |
||||
"""Dessine le cadrillage du graphique""" |
"""Dessine le cadrillage du graphique""" |
||||
ratio = self.fonction_screen_height / self.fonction_screen_width # longueur par largeur du canvas |
ratio = self.fonction_screen_height / self.fonction_screen_width # longueur par largeur du canvas |
||||
|
|
||||
# position du max dans l'interval |
# position du max dans l'interval |
||||
abscisse = max_y / (abs(min_y)+abs(max_y)) |
abscisse = max_y / (abs(min_y)+abs(max_y)) |
||||
ordonnee = max_x / (abs(min_x)+abs(max_x)) |
ordonnee = max_x / (abs(min_x)+abs(max_x)) |
||||
|
|
||||
for i in range(20): # dessin des lignes verticales |
for i in range(20): # dessin des lignes verticales |
||||
if i == int(20 - 20*ordonnee): |
if i == int(20 - 20*ordonnee): |
||||
self.fonction_screen.create_line(0 + i * self.fonction_screen_width/20, 0 |
self.fonction_screen.create_line(0 + i * self.fonction_screen_width/20, 0 |
||||
, 0 + i * self.fonction_screen_width/20, self.fonction_screen_height |
, 0 + i * self.fonction_screen_width/20, self.fonction_screen_height |
||||
, fill='red', width=4) |
, fill='red', width=4) |
||||
text = self.fonction_screen.create_text(0 + i * self.fonction_screen_width/20, 10, text=max_y) |
text = self.fonction_screen.create_text(0 + i * self.fonction_screen_width/20, 10, text=max_y) |
||||
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
||||
self.fonction_screen.tag_lower(rect, text) |
self.fonction_screen.tag_lower(rect, text) |
||||
|
|
||||
text = self.fonction_screen.create_text(0 + i * self.fonction_screen_width/20, |
text = self.fonction_screen.create_text(0 + i * self.fonction_screen_width/20, |
||||
self.fonction_screen_height - 10, text=min_y) |
self.fonction_screen_height - 10, text=min_y) |
||||
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
||||
self.fonction_screen.tag_lower(rect, text) |
self.fonction_screen.tag_lower(rect, text) |
||||
else: |
else: |
||||
self.fonction_screen.create_line(0 + i * self.fonction_screen_width/20, 0 |
self.fonction_screen.create_line(0 + i * self.fonction_screen_width/20, 0 |
||||
, 0 + i * self.fonction_screen_width/20, self.fonction_screen_height |
, 0 + i * self.fonction_screen_width/20, self.fonction_screen_height |
||||
, fill='red') |
, fill='red') |
||||
nb_abscisse_lines = int(20*ratio) # nombre de lignes horizontales à tracer |
nb_abscisse_lines = int(20*ratio) # nombre de lignes horizontales à tracer |
||||
|
|
||||
for i in range(nb_abscisse_lines): # dessin des lignes horizontales |
for i in range(nb_abscisse_lines): # dessin des lignes horizontales |
||||
if i == math.ceil(nb_abscisse_lines * abscisse): # tracer de l'axe des abscisses |
if i == math.ceil(nb_abscisse_lines * abscisse): # tracer de l'axe des abscisses |
||||
self.fonction_screen.create_line(0, 0 + i * self.fonction_screen_width/20 |
self.fonction_screen.create_line(0, 0 + i * self.fonction_screen_width/20 |
||||
, self.fonction_screen_width |
, self.fonction_screen_width |
||||
, 0 + i * self.fonction_screen_width/20, fill='red' |
, 0 + i * self.fonction_screen_width/20, fill='red' |
||||
, width=4) |
, width=4) |
||||
text = self.fonction_screen.create_text(15, 0 + i * self.fonction_screen_width/20 |
text = self.fonction_screen.create_text(15, 0 + i * self.fonction_screen_width/20 |
||||
, text=min_x) |
, text=min_x) |
||||
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text) |
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text) |
||||
, fill="white") |
, fill="white") |
||||
self.fonction_screen.tag_lower(rect, text) |
self.fonction_screen.tag_lower(rect, text) |
||||
|
|
||||
text = self.fonction_screen.create_text(self.fonction_screen_width - 15 |
text = self.fonction_screen.create_text(self.fonction_screen_width - 15 |
||||
, 0 + i * self.fonction_screen_width/20 |
, 0 + i * self.fonction_screen_width/20 |
||||
, text=max_x) |
, text=max_x) |
||||
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
rect = self.fonction_screen.create_rectangle(self.fonction_screen.bbox(text), fill="white") |
||||
self.fonction_screen.tag_lower(rect, text) |
self.fonction_screen.tag_lower(rect, text) |
||||
else: |
else: |
||||
self.fonction_screen.create_line(0, 0 + i * self.fonction_screen_width/20 |
self.fonction_screen.create_line(0, 0 + i * self.fonction_screen_width/20 |
||||
, self.fonction_screen_width |
, self.fonction_screen_width |
||||
, 0 + i * self.fonction_screen_width/20, fill='red') |
, 0 + i * self.fonction_screen_width/20, fill='red') |
||||
|
|
||||
def calculate(self) -> None: |
def calculate(self) -> None: |
||||
"""Calcule dans la partie graphique""" |
"""Calcule dans la partie graphique""" |
||||
exp = parse_string_to_list(self.calcul_entry.get()) |
exp = parse_string_to_list(self.calcul_entry.get()) |
||||
exp = npi2tree(inf2npi(exp)) |
exp = npi2tree(inf2npi(exp)) |
||||
exp.print_tree() |
exp.print_tree() |
||||
try: |
try: |
||||
result = exp.evalue() |
result = exp.evalue() |
||||
except ZeroDivisionError: |
except ZeroDivisionError: |
||||
result = "ERREUR" |
result = "ERREUR" |
||||
self.calcul_screen.configure(text=result) |
self.calcul_screen.configure(text=result) |
||||
|
|
||||
def draw_graph(self): |
def draw_graph(self): |
||||
"""Dessine les points du graphique""" |
"""Dessine les points du graphique""" |
||||
self.fonction_screen.delete('all') |
self.fonction_screen.delete('all') |
||||
min_x, max_x = map(int, self.fonction_bornes_entry.get().split(',')) |
min_x, max_x = map(int, self.fonction_bornes_entry.get().split(',')) |
||||
fonction_points = npi2tree(inf2npi(parse_string_to_list(self.fonction_entry.get()))).valeurs_de_fonction(min_x, max_x) |
fonction_points = npi2tree(inf2npi(parse_string_to_list(self.fonction_entry.get()))).valeurs_de_fonction(min_x, max_x) |
||||
max_y = max(fonction_points, key=lambda item: item[1])[1] |
max_y = max(fonction_points, key=lambda item: item[1])[1] |
||||
min_y = min(fonction_points, key=lambda item: item[1])[1] |
min_y = min(fonction_points, key=lambda item: item[1])[1] |
||||
self.draw_framing(min_x, max_x, min_y, max_y) |
self.draw_framing(min_x, max_x, min_y, max_y) |
||||
for i, (x, y) in enumerate(fonction_points): |
ratio = (fonction_points[0][0] - min_x) / (abs(max_x)+abs(min_x)) |
||||
image_x = i * (self.fonction_screen_width/len(fonction_points)) |
i = len(fonction_points) * ratio |
||||
image_y = self.fonction_screen_height - (y - min_y) * self.fonction_screen_height / (abs(max_y)+abs(min_y)) |
for (x, y) in fonction_points: |
||||
self.fonction_screen.create_rectangle(image_x, image_y, image_x, image_y) |
image_x = i * (self.fonction_screen_width/len(fonction_points)) |
||||
|
image_y = self.fonction_screen_height - (y - min_y) * self.fonction_screen_height / (abs(max_y)+abs(min_y)) |
||||
|
self.fonction_screen.create_rectangle(image_x, image_y, image_x, image_y) |
||||
|
i += 1 |
Loading…
Reference in new issue