import tkinter from tkinter import filedialog import os import math class Terrain: def __init__(self): self.height = 15000//25 self.width = 28000//25 self.three_points = 6250//25 # rayon self.middle_circle = 1800//25 # rayon class Team: def __init__(self, players): self.players = players self.posx, self.posy = 0,0 # coo de la dernière action self.ac_player = 0 # dernier joueur class File: def __init__(self, name='untitled.bbm'): self.name = name self.temp_data = '' self.content = [] def write_data(self): with open(self.name, 'a') as f: f.write(self.temp_data) self.temp_data = '' self.read_file() def read_file(self): with open(self.name, 'r') as f: self.content = f.readlines() class Gui: def __init__(self): self.terrain = Terrain() self.team = None self.mode = None self.root = tkinter.Tk() self.root.title('BasketBall Analitycs®') self.canvas = tkinter.Canvas(self.root, width=self.terrain.width, height=self.terrain.height, background='#bbb') self.start_frame = tkinter.Frame(self.root, width=self.terrain.width, height=self.terrain.height, bg='red') self.start_button_new = tkinter.Button(self.start_frame, text='new', command=self.new) self.start_button_open = tkinter.Button(self.start_frame, text='open', command=self.browse_open) self.start_frame.pack() self.start_button_new.place(x=self.terrain.width//2-45, y=self.terrain.height//2-30, width=90, height=30) self.start_button_open.place(x=self.terrain.width//2-45, y=self.terrain.height//2, width=90, height=30) # file menu self.menubar = tkinter.Menu(self.root) self.filemenu = tkinter.Menu(self.menubar, tearoff=0) self.filemenu.add_command(label="new", command=self.new) self.filemenu.add_command(label="open", command=self.browse_open) self.filemenu.add_separator() self.filemenu.add_command(label="exit", command=self.root.quit) self.menubar.add_cascade(label="file", menu=self.filemenu) self.action_to_show = [] # topbar self.root.config(menu=self.menubar) # image des actions self.tir_reussi = tkinter.PhotoImage(file='img/tir_reussi.png') self.tir_rate = tkinter.PhotoImage(file='img/tir_rate.png') self.lance_reussi = tkinter.PhotoImage(file='img/lance_reussi.png') self.lance_rate = tkinter.PhotoImage(file='img/lance_rate.png') self.rebond_def = tkinter.PhotoImage(file='img/rebond_def.png') self.rebond_off = tkinter.PhotoImage(file='img/rebond_off.png') self.faute = tkinter.PhotoImage(file='img/faute.png') self.passe_dec = tkinter.PhotoImage(file='img/passe_dec.png') self.root.bind("", self.browse_open) self.root.bind("", self.new) self.root.bind("", self.save) self.canvas.bind("", self.context_menu) self.root.mainloop() def get_names(self): self.team = Team(self.players_entry.get().split(',')) print(self.team.players) self.w_player.destroy() self.w_player.quit() def new(self, *event): # créer un fichier vierge self.file = File() self.root.title(self.file.name) self.w_player = tkinter.Toplevel() frame = tkinter.Frame(self.w_player, width=600, height=200) self.players_entry = tkinter.Entry(frame) text = tkinter.Label(frame, text="Entrez les joueurs séparés par virgules") ok_button = tkinter.Button(frame, text='OK', command=self.get_names) frame.pack() self.players_entry.place(x=200, y=80, width=200, height=20) text.place(x=150, y=40, width=300, height=40) ok_button.place(x=280, y=120, width=40, height=20) self.w_player.mainloop() self.setup() def save(self, *event): # sauvegarde du fichier if self.menu != None: if self.file.name == 'untitled.bbm': path = tkinter.filedialog.asksaveasfilename(initialdir = "~", title = "Select a File", filetypes = (("BasketBall Match", "*.bbm"), ("all files", "*.*"))) if len(path) != 0: self.file.name = path self.file.write_data() self.root.title(self.file.name) def browse_open(self, *event): # ouvre un fichier path = tkinter.filedialog.askopenfilename(initialdir = "~/Documents/python/basket", title = "Select a File", filetypes = (("BasketBall Match", "*.bbm"), ("all files", "*.*"))) if len(path) != 0: self.file = File(path) self.file.read_file() self.team = Team(self.file.content[0].strip().split(' ')) self.root.title(self.file.name) self.setup() def setup(self): self.start_frame.pack_forget() self.canvas.pack() self.mode = 'match' self.draw_terrain() self.filemenu.insert_command(2, label="save", command=self.save) # mode menu self.modemenu = tkinter.Menu(self.menubar, tearoff=0) self.modemenu.add_command(label="stat", command=lambda: self.changemode('stat')) self.modemenu.add_command(label="match", command=lambda: self.changemode('match')) self.menubar.add_cascade(label="mode", menu=self.modemenu) # stat menu self.statmenu = tkinter.Menu(self.menubar, tearoff=0) self.statsubmenu = tkinter.Menu(self.statmenu, tearoff=0) self.statsubmenu.add_command(label=self.team.players[0], command=lambda: self.draw_player(self.team.players[0])) self.statsubmenu.add_command(label=self.team.players[1], command=lambda: self.draw_player(self.team.players[1])) self.statsubmenu.add_command(label=self.team.players[2], command=lambda: self.draw_player(self.team.players[2])) self.statsubmenu.add_command(label=self.team.players[3], command=lambda: self.draw_player(self.team.players[3])) self.statsubmenu.add_command(label=self.team.players[4], command=lambda: self.draw_player(self.team.players[4])) self.statmenu.add_cascade(label="player", menu=self.statsubmenu) self.statmenu.add_command(label='team', command=lambda: self.draw_player('*')) # actions menubar self.actionmenu = tkinter.Menu(self.menubar, tearoff=0) self.actionmenu.add_checkbutton(0, label='tirs', command=lambda: self.check_action('tirs')) self.actionmenu.add_checkbutton(0, label='lance', command=lambda: self.check_action('lance')) self.actionmenu.add_checkbutton(0, label='rebonds', command=lambda: self.check_action('rebond')) self.actionmenu.add_checkbutton(0, label='passe', command=lambda: self.check_action('passe')) self.actionmenu.add_checkbutton(0, label='faute', command=lambda: self.check_action('faute')) for i in range(5): self.actionmenu.invoke(i) # menu contextuel des actions self.action = tkinter.Menu(self.root, tearoff=0) self.action.add_command(label='tir réussi', command=lambda: self.action_menu('tm')) self.action.add_command(label='tir raté', command=lambda: self.action_menu('tr')) self.action.add_command(label='lancé franc réussi', command=lambda: self.action_menu('lfm')) self.action.add_command(label='lancé franc raté', command=lambda: self.action_menu('lfr')) self.action.add_command(label='faute', command=lambda: self.action_menu('f')) self.action.add_command(label='rebond offensif', command=lambda: self.action_menu('ro')) self.action.add_command(label='rebond défensif', command=lambda: self.action_menu('rd')) self.action.add_command(label='passe décisive', command=lambda: self.action_menu('pd')) # Menu contextuel des joueurs self.menu = tkinter.Menu(self.root, tearoff = 0) self.menu.add_command(label=self.team.players[0], command=lambda: self.show_sub_menu(self.team.players[0])) self.menu.add_command(label=self.team.players[1], command=lambda: self.show_sub_menu(self.team.players[1])) self.menu.add_command(label=self.team.players[2], command=lambda: self.show_sub_menu(self.team.players[2])) self.menu.add_command(label=self.team.players[3], command=lambda: self.show_sub_menu(self.team.players[3])) self.menu.add_command(label=self.team.players[4], command=lambda: self.show_sub_menu(self.team.players[4])) self.bind_click = "" self.bind_ctrl_s = "" def check_action(self, action): if action in self.action_to_show: self.action_to_show.remove(action) else: self.action_to_show.append(action) def changemode(self, newmode): if self.mode != newmode: if newmode == 'stat': self.menubar.add_cascade(label='stat', menu=self.statmenu) self.menubar.add_cascade(label='actions', menu=self.actionmenu) else: for i in range(2): self.menubar.delete(3) self.mode = newmode items = self.canvas.find_all() while len(items) > 4: self.canvas.delete(items[-1]) items = self.canvas.find_all() def context_menu(self, event): if self.mode == "match": self.team.posx, self.team.posy = event.x, event.y self.coo = [event.x_root, event.y_root] self.menu.tk_popup(event.x_root, event.y_root) self.menu.grab_release() def show_sub_menu(self, player): self.team.ac_player = player self.action.tk_popup(self.coo[0], self.coo[1]) self.action.grab_release() def action_menu(self, action): """enregistre temporairement l'action""" self.clean_terrain() # test si l'action est dans la liste des 3 points if action == 'tm': self.canvas.create_image(self.team.posx-20, self.team.posy-20, image=self.tir_reussi, anchor='nw') if ((self.team.posx-0)**2) + ((self.team.posy-self.terrain.height/2)**2) <= self.terrain.three_points**2 or ((self.team.posx-self.terrain.width)**2) + ((self.team.posy-self.terrain.height/2)**2) <= self.terrain.three_points**2: score = 2 else: score = 3 if action == 'tr': self.canvas.create_image(self.team.posx-20, self.team.posy-20, image=self.tir_rate, anchor='nw') score = 0 if action == 'lfm': self.canvas.create_image(self.team.posx-20, self.team.posy-20, image=self.lance_reussi, anchor='nw') score = 1 if action == 'lfr': self.canvas.create_image(self.team.posx-20, self.team.posy-20, image=self.lance_rate, anchor='nw') score = 0 if action == 'ro': self.canvas.create_image(self.team.posx-20, self.team.posy-20, image=self.rebond_off, anchor='nw') score = 0 if action == 'rd': self.canvas.create_image(self.team.posx-20, self.team.posy-20, image=self.rebond_def, anchor='nw') score = 0 if action == 'f': self.canvas.create_image(self.team.posx-20, self.team.posy-20, image=self.faute, anchor='nw') score = 0 if action == 'pd': self.canvas.create_image(self.team.posx-20, self.team.posy-20, image=self.passe_dec, anchor='nw') score = 0 if self.file.temp_data == '': self.root.title(self.file.name+' *') self.file.temp_data += self.team.ac_player+' '+action+' '+str(score)+' '+str(self.team.posx)+' '+str(self.team.posy)+'\n' def clean_terrain(self): """Nettoie le terrain""" items = self.canvas.find_all() while len(items) > 4: self.canvas.delete(items[-1]) items = self.canvas.find_all() def draw_player(self, player, *event): """dessine les actions de toute l'équipe""" self.clean_terrain() for line in self.file.content[2:]: # forme type: joueur action points x y params = line.strip().split(' ') if params[0] == player or player == '*': # nom du joueur if 'tirs' in self.action_to_show: if params[1] == 'tm': self.canvas.create_image(int(params[3]), int(params[4]), image=self.tir_reussi, anchor='nw') if params[1] == 'tr': self.canvas.create_image(int(params[3]), int(params[4]), image=self.tir_rate, anchor='nw') if 'lance' in self.action_to_show: if params[1] == 'lfm': self.canvas.create_image(int(params[3]), int(params[4]), image=self.lance_reussi, anchor='nw') if params[1] == 'lfr': self.canvas.create_image(int(params[3]), int(params[4]), image=self.lance_rate, anchor='nw') if 'faute' in self.action_to_show and params[1] == 'f': self.canvas.create_image(int(params[3]), int(params[4]), image=self.faute, anchor='nw') if 'rebond' in self.action_to_show: if params[1] == 'ro': self.canvas.create_image(int(params[3]), int(params[4]), image=self.rebond_off, anchor='nw') if params[1] == 'rd': self.canvas.create_image(int(params[3]), int(params[4]), image=self.rebond_def, anchor='nw') if 'passe' in self.action_to_show and params[1] == 'pd': self.canvas.create_image(int(params[3]), int(params[4]), image=self.passe_dec, anchor='nw') def draw_terrain(self): """dessinne les lignes du terrain""" # ligne des 3 points self.canvas.create_arc(-self.terrain.three_points, self.terrain.height//2 - self.terrain.three_points, self.terrain.three_points, self.terrain.height - (self.terrain.height//2 - self.terrain.three_points),width=3, start=90, extent=-180) self.canvas.create_arc(self.terrain.width-self.terrain.three_points, self.terrain.height//2 - self.terrain.three_points, self.terrain.width+self.terrain.three_points, self.terrain.height - (self.terrain.height//2 - self.terrain.three_points),width=3, start=90, extent=180) # ligne centrale self.canvas.create_line(self.terrain.width//2, 0, self.terrain.width//2, self.terrain.height, width=3) # cercle du milieu self.canvas.create_oval(self.terrain.width//2 - self.terrain.middle_circle, self.terrain.height//2 - self.terrain.middle_circle, self.terrain.width//2 + self.terrain.middle_circle, self.terrain.height//2 + self.terrain.middle_circle, width=3) gui = Gui()