stats sur un match de basket
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
15 KiB

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='#bbb')
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=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("<Control-o>", self.browse_open)
self.root.bind("<Control-n>", self.new)
self.root.bind("<Control-s>", self.save)
self.canvas.bind("<Button-1>", 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", 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 = "<Button-1>"
self.bind_ctrl_s = "<Control-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()