Statistiche sui calendari del Fantacalcio con Python

python-fantacalcio

Come allenamento nell'uso di Python, ho deciso di riprendere in mano un mio vecchio progetto MATLAB e reimplementarlo dopo 4 anni di distanza dal suo ultimo utilizzo. Si tratta di un "semplice" script per il calcolo di tutte le classifiche generate da ogni possibile calendario estratto per un campionato di Fantacalcio a gironi. Tale script aveva lo scopo di determinare quante volte una squadra sarebbe stata prima in classifica rispetto a tutti i possibili calendari.

Se non avete capito nulla delle ultime due frasi lette, i casi sono due:
1) non giocate al Fantacalcio, e quindi avete già chiuso questa tab del browser
2) giocate al Fantacalcio, ma non sono stato granchè chiaro nella spiegazione

Per quelli di voi che ricadono nella seconda categoria, credo non sia necessario spiegarvi cosa sia il Fantacalcio e perchè sia così popolare tra i gruppi di amici in tutta Italia. Potrebbe però essere necessario che vi spieghi meglio cosa intendevo con la frase "determinare quante volte una squadra sarebbe stata prima in classifica rispetto a tutti i possibili calendari".

PRIMO DISCLAIMER: il file excel utilizzato dallo script per caricare tutte le informazioni sulle partite giocate è ottenibile solo se la vostra lega è iscritta al servizio Leghe di Fantagazzetta. Questo perchè:
1) è un servizio piuttosto diffuso per la gesione delle leghe
2) dà la possibilità di scaricare il calendario completo e compilato in un file excel
3) per non perdere troppo tempo nell'importazione del file excel, ho preferito scegliere un servizio che mantenesse uno standard fissato per il template del calendario ed adattarmi su quello

SECONDO DISCLAIMER: ho deciso di utilizzare il progettino come esempio per altri tutorial di Python. Il codice presentato nel seguente articolo risulta perciò la prima versione del programma. La versione più aggiornata è direttamente disponibile sul nostro repository, ma, se interessati, vi consiglio di continuare a leggere l'articolo per capire i punti principali del progetto.

Fantacampionato a Calendario

Esistono tante versioni con le quali giocare un campionato di Fantacalcio tra amici. Una delle più diffuse è sicuramente quella a Calendario, in cui ogni giornata coppie di squadre si confrontano sul numero di punti fatti dai loro giocatori, senza che questi influenzino i punti fatti dal proprio avversario. A seconda del numero di punti, alle squadre saranno attribuiti dei gol, i quali determineranno il risultato finale della partita.
Generalmente, queste fasce sono: da 66 punti a 71,5 è attribuito 1 gol, da 72 punti a 77,5 sono attribuiti 2 gol, da 78 punti a 83,5 sono attribuiti 3 gol, e via così a gruppi di 6 punti.

Sebbene sia una delle modalità più divertenti, soprattutto per gli sfottò generati tra i Fantapresidenti delle squadre che si sfidano durante la giornata, è anche la modalità che più dipende dal calendario estratto ad inizio campionato.
Ho definito questa categoria di campionato "Fantacalcio a gironi", intendendo per girone un blocco di giornate in cui ogni squadra incontra una volta tutte le squadre avversarie. Un Calendario è perciò formato da un numero stabilito di gironi, dipendente dal numero di squadre, di partite di Serie A, ecc...


Esempio
Secondo il calendario estratto per il Fantacalcio di Paperopoli, alla prima giornata si sfidano Paperino contro Ciccio e Gastone contro Paperoga.
Paperino riesce ad arrivare a 83,5 punti contro Ciccio che arriva a 79; nell'altro match, Gastone arriva a 66,5 punti con un solo assist per un gol in chiaro fuorigioco, mentre Paperoga si scorda di cambiare la formazione, gioca con 4 infortunati, 2 squalificati e arriva a 43 punti.
Risultati:
Paperino - Ciccio 3-3
Gastone - Paperoga 1-0
Avremmo così Gastone a comandare la classifica in solitaria, seguito da Ciccio e da un incavolatissimo Paperino al secondo posto.
In questo campionato a 4 squadre, sia Paperino che Ciccio sarebbero stati in vetta alla classifica dopo la prima giornata in ben 2 occasioni su 3; d'altra parte Gastone ha beccato quell'unica possibilità su 3 per conquistare la vittoria; lasciamo perdere Paperoga...

Estrazione del Calendario

Per l'estrazione del Calendario, il metodo forse più diffuso è quello di utilizzare un "girone template", in cui ogni squadra è sostiuita da un "alias" (solitamente una lettera), e poi attribuire a sorte gli alias alle squadre. Riprendendo l'esempio precedente, avremmo un template girone del tipo:
Giorn. 1: A - B; C - D
Giorn. 2: A - C; B - D
Giorn. 3: D - A; C - B
Per il quale sono stati estratti: A per Paperino, B per Ciccio, C per Gastone e D per Paperoga.
Visti i risultati della prima giornata, se per esempio Paperino fosse stato estratto con la lettera C e Ciccio con la A, adesso sarebbero primi in classifica.


Il template si ripete poi fino a formare l'intero Calendario. Questa modalità non prevede differenze se una squadra gioca in "casa" o "fuori casa".
Solitamente, per un campionato a 4 squadre avremo gironi da 3 giornate, per un campionato da 6 avremo gironi da 5 giornate, e così via.
Nell'esempio scelto, avremo un calendario da 12 giornate, suddivise in 4 gironi.

Tutti i possibili Calendari

Ma quanti sono i possibili calendari? Il ragionamento è il seguente: se fissiamo il template della prima giornata ad A vs B e C vs D, i possibili calendari sono tutte le possibili associazioni delle lettere alle squadre partecipanti. Quindi è il numero di tutte le permutazioni delle squadre partecipanti. Per un campionato a 4 squadre, sono 24; per un campionato a 6 squadre sono 720; per un campionato a 8 squadre sono 40320; per un campionato a 10 squadre sono 3628800.
Ognuno di questi calendari avrà una classifica finale differente. E qui arriviamo perciò allo scopo dello script:
calcolare in quante differenti (ed ipotetiche) classifiche una squadra sarebbe stata prima e scrivere i risultati in file .csv.
Questo anche per dirvi prima di tutto che il codice che andrò a presentare non è ancora ottimizzato, quindi per un campionato giocattolo come quello dell'esempio impiegherà un tempo ragionevole ad arrivare a fine esecuzione, ma per un Fantacampionato reale con 8 squadre e 5 gironi da 7 giornate, i tempi saranno decisamente dilatati.

Come ottenere il file Excel del Calendario

Prima di partire con il codice, vediamo come ottenere il calendario del fantacampionato dalla pagina della vostra competizione su Leghe Fantagazzetta. Vi basterà semplicemente andare nella sezione "Calendario" e cliccare sul bottone "SCARICA IL CALENDARIO IN EXCEL". Aprendolo, si dovrebbe presentare un file con lo stesso schema riportato nell'immagine seguente:
calendario_paperopoli

Moduli usati e Costanti

Veniamo ora al codice Python e vediamo prima di tutto i moduli necessari per il suo funzionamento.

import itertools
import openpyxl as xl
import bisect
from collections import Counter

Il modulo itertools sarà utilizzato per creare la lista di tutte le possibili permutazioni delle squadre; openpyxl è un modulo per l'elaborazione dei file Excel con python; bisect sarà utilizzato come trucchetto per calcolare velocemente il numero di gol fatti rispetto al numero di punti della squadra; infine la classe Counter di collections sarà utilizzata per fondere insieme e sommare differenti dictionary.

E' stata utilizzata una classe Costanti per raccogliere tutte quelle variabili che devono rimanere costanti per tutta l'esecuzione dello script, in modo che queste non debbano essere cablate all'interno del codice.

class Costanti:
    """Classe di utility con tutte le costanti per il progetto"""
    
    """costanti dipendenti dal fantacampionato"""
    NUM_SQUADRE = 4
    NUM_GIRONI = 4
    NUM_GIORNATE = (NUM_SQUADRE - 1) * NUM_GIRONI
    ULTIMA_GIORNATA = NUM_GIORNATE
    
    """costanti per leggere il file excel"""
    FIRST_LETTER_ODD = 'A'
    LAST_LETTER_ODD = 'D'
    FIRST_LETTER_EVN = 'G'
    LAST_LETTER_EVN = 'J'    
    STARTING_NUMBER = 5
    OFFSET_VERT_GIORNATE = (NUM_SQUADRE / 2) + 1
    
    """calendario con segnaposto per un girone"""
    SEGNAPOSTI = ['A', 'B', 'C', 'D']
    CALENDARIO_SEGNAPOSTI = [SEGNAPOSTI
                            ,['A', 'C', 'B', 'D']
                            ,['D', 'A', 'C', 'B']
                             ]
    CALENDARIO_SEGNAPOSTI_COMPLETO = CALENDARIO_SEGNAPOSTI * NUM_GIRONI
    
    """soglie punti-gol"""
    SOGLIE_PUNTI_GOL = range(66,186,6)
    
    """costanti per la classifica"""
    PTI_V = 3
    PTI_P = 1
    PTI_S = 0
    PARIMERITO = True

    """nome del file .csv di output"""
    FILENAME_OUTPUT = "ClassificaCalendari.csv"

Ho cercato di dare nomi piuttosto esplicativi alle costanti, mantenendo parole italiane per le entità peculiari del Fantacalcio ("squadra", "calendario", "classifica", ecc...).

Passandole in rassegna per gruppi, vediamo che il primo gruppo di variabili dipende esclusivamente dal tipo di competizione (numero di squadre, numero di gironi, ecc...), mentre il secondo gruppo dipende dal file Excel utilizzato. Dall'immagine inserita in precedenza si nota come:
- le giornate sono tutte raggruppate in blocchi di celle di grandezza fissa, dipendenti dal numero di squadre partecipanti alla competizione
- nella macrocolonna di sinistra abbiamo tutte le giornate dispari, mentre nella macrocolonna di destra abbiamo tute le giornate pari

La costante ULTIMA_GIORNATA serve a specificare l'ultima giornata da considerare per il calcolo delle classifiche se si vuole fare una analisi parziale dei calendari.

Poichè il modulo openpyxl permette l'estrazione delle celle in blocchi rettangolari, ho deciso di trovare una regola fissa per raccogliere le informazioni sulle giornate, blocco per blocco. Si parte perciò con l'assunzione che il blocco della prima giornata sia quello definito dalla cella 'A5' alla cella 'D#' con # pari alla metà del numero di squadre partecipanti alla lega. Allo stesso modo, per la seconda giornata, il blocco di interesse sarà dalla cella 'G5' alla cella 'J#'. Per scorrere da una giornata all'altra verticalmente, si somma il valore rappresentato dalla costante OFFSET_VERT_GIORNATE.

Il terzo gruppo di variabili è fondamentale invece per la creazione del calendario. Rappresenta il template del girone di cui parlavamo nei paragrafi precedenti. Gli ultimi due gruppi di variabili dipendono invece dalle regole sulle assegnazioni di punti e gol alle squadre. PARIMERITO è un flag booleano che sarà utilizzato in seguito per considerare nella classifica dei calendari anche i casi in cui più squadre arrivano prime a parimerito.

L'ultima costante serve per definire il file di output con la classifica dei calendari vinti.

Classi e funzioni di Utility

Oltre alla classe Costanti il programmino è formato una classe per rappresentare una giornata di Fantacalcio, una per rappresentare il calendario e più funzioni di utility.

Giornata

Ciò che varia a seconda dell'estrazione è solamente l'ordine con cui le squadre si affrontano nel campionato. I punteggi raggiunti dalle squadre rimangono sempre gli stessi per ogni giornata al variare del calendario (almeno nell'ambiente in cui ci stiamo ponendo).
Per questo motivo, ho deciso di gestire le giornate con una classe apposita (Giornata) come mostrato nel codice seguente:

class Giornata:
    """Classe per gestire le giornate"""
    
    def __init__(self, n_giornata):
        self._squadre = []
        self._squadre_pti = {}
        self._squadre_pti_classifica = {}
        self._n_giornata = n_giornata
        self._giocata = False        
        self._nome_giornata = "Giornata " + str(self._n_giornata)
    
    def print_giornata(self):
        """Stampa la giornata"""
        print self._nome_giornata
        for (squadra, pti) in zip(self._squadre_pti.keys(), self._squadre_pti.values()):
            print squadra + ' ' + str(pti)  

L'attributo _squadre serve solo per mantenere sempre l'elenco delle squadre partecipanti. Viceversa i dizionari _squadre_pti e _squadre_pti_classifica servono effettivamente per calcolare le classifiche: _squadre_pti ha come chiave i nomi delle squadre e come valore i punti ottenuti in quella giornata dalla squadra; _squadre_pti_classifica invece mantiene i punti in classifica fino a quella giornata per uno specifico calendario.
I valori di _squadre_pti_classifica varieranno ogni volta che si calcolerà un calendario differente, ma invece di creare un numero fattoriale di riferimenti a oggetti Giornata ho preferito, per ora, non mantenere memoria di ogni singola classifica di giornata al variare del calendario in esame.
Infine, l'attributo _giocata sarà True solo se quella giornata sarà stata effettivamente giocata e quindi sarà valida per il calcolo delle classifiche. In questo modo sarà possibile utilizzare lo script anche se il campionato non è ancora finito.

Funzioni di Utility

Vediamo adesso la funzione di utility per individuare le squadre partecipanti dal file Excel:

def get_squadre_calendario(sheet):
    """Metodo per la ricerca dei nomi delle squadre partecipanti
    all'interno del blocco della prima giornata di campionato"""
    squadre = []
    for i in range(Costanti.NUM_SQUADRE/2):
        squadre.append(sheet[Costanti.FIRST_LETTER_EVN + str(Costanti.STARTING_NUMBER + i)].value)
        squadre.append(sheet[Costanti.LAST_LETTER_EVN + str(Costanti.STARTING_NUMBER + i)].value)
    return squadre  

L'oggetto sheet rappresenta il foglio di lavoro di Excel sul quale andremo ad estrarre le informazioni. Dalla documentazione di openpyxl si vede che per accedere al contenuto di una cella di un foglio di lavoro, per esempio alla cella 'A5', si utilizza il codice sheet['A5'].value, come se il foglio fosse un array bidimensionale, con le coordinate rimappate come quelle di Excel. Il metodo get_squadre_calendario parte dalla prima riga del blocco della prima giornata e aggiunge nella lista squadre le coppie di sfidanti, prese singolarmente.

Una volta ottenuti i nomi delle squadre, abbiamo le chiavi dei dizionari degli oggetti Giornata. Dobbiamo quindi inizializzare la nostra lista di oggetti Giornata con i punteggi letti dal file Excel.

def set_giornate_calendario(sheet, giornate, squadre):
    """Metodo per la completa inizializzazione delle giornate del calendario
    Legge dal foglio Excel 'sheet' nei blocchi delle giornate
    La posizione dei blocchi delle giornate nel calendario è da verificare negli attributi della classe 'Costanti'"""
    offset_giornata = 0
    for g in giornate:
        g._squadre = squadre
        if g._n_giornata % 2 == 1:
            tl = Costanti.FIRST_LETTER_ODD + str(Costanti.STARTING_NUMBER + offset_giornata)
            br = Costanti.LAST_LETTER_ODD + str(Costanti.STARTING_NUMBER + Costanti.NUM_SQUADRE/2 + offset_giornata - 1)
        else:
            tl = Costanti.FIRST_LETTER_EVN + str(Costanti.STARTING_NUMBER + offset_giornata)
            br = Costanti.LAST_LETTER_EVN + str(Costanti.STARTING_NUMBER + Costanti.NUM_SQUADRE/2 + offset_giornata - 1)
            offset_giornata += Costanti.OFFSET_VERT_GIORNATE
        blocco_giornata = list(sheet[tl:br])
        if blocco_giornata[0][1].value > 0 and blocco_giornata[0][2].value > 0:
            g._giocata=True
            for row in blocco_giornata[0:]:
                g._squadre_pti[row[0].value] = row[1].value
                g._squadre_pti[row[3].value] = row[2].value

Il metodo set_giornate_calendario scorre il file Excel per "blocco giornata" ed inserisce le informazioni negli oggetti g della classe Giornata, appartenenti alla lista giornate. Se questa è stata giocata (quindi ha punteggi maggiori di zero), ad ogni squadra viene attribuito il punteggio di giornata.

Calendario

Ora che per ogni giornata sappiamo quanti punti sono stati fatti dalle squadre, dobbiamo calcolarci le singole classifiche per ogni calendario. Ho deciso di creare una classe apposita Calendario per la gestione di calcoli e classifiche. Il numero di oggetti della classe Calendario dipenderà dal numero di squadre, numero che come già detto andrà ad esplodere molto velocemente (come il fattoriale) all'aumentare dei partecipanti.

class Calendario:
    """Classe per gestire un calendario
    Comprende il calcolo della classifica per tutte le partite giocate"""
    
    
    def __init__(self, permutation, giornate):
        self._permutation = permutation
        self._giornate = giornate
        self._classifica = dict(zip(self._permutation, [0]*Costanti.NUM_SQUADRE))
        self._diz_segnaposti = dict(zip(Costanti.SEGNAPOSTI, self._permutation))
        self._calendario_custom = []
        self._pti_primo = 0
        self._squadre_campioni = []
        for segnaposti_giornata in Costanti.CALENDARIO_SEGNAPOSTI_COMPLETO:
            segnaposti_giornata_custom = ['SEGNAPOSTO']*Costanti.NUM_SQUADRE
            for ind, segnaposto in enumerate(segnaposti_giornata):
                segnaposti_giornata_custom[ind] = self._diz_segnaposti[segnaposto]
            self._calendario_custom.append(segnaposti_giornata_custom)
    
    
    def get_squadra_campione(self):
        """Restituisce la lista delle squadre campioni
        Se Costanti.PARIMETRO = True restituisce una lista di un elemento (concatenazione delle squadre campioni)
        Altrimenti restituisce una lista con tutte le squadre alla prima posizione"""
        if Costanti.PARIMERITO:
            return [" / ".join(self._squadre_campioni) + "@" + str(self._pti_primo)]
        else:
            return [sc + "@" + str(self._pti_primo) for sc in self._squadre_campioni]

        
    def calcola_classifica(self, ultima_giornata=Costanti.ULTIMA_GIORNATA):
        """Calcola la classifica fino alla giornata numero 'ultima_giornata'
        per tutte le giornate con flag 'giocata'=True"""
        for g in self._giornate[:ultima_giornata]:
            if g._giocata:
                self.calcola_giornata(g)
                self._classifica = dict(Counter(g._squadre_pti_classifica) + Counter(self._classifica))
        self._pti_primo = max(self._classifica.values())
        self._squadre_campioni = [k for k,v in self._classifica.iteritems() if v==self._pti_primo]
        self._squadre_campioni.sort()
        

    def calcola_giornata(self, giornata):
        """Calcola tutte le partite della giornata
        attribuendo i punti vittoria, pareggio o sconfitta alle squadre"""
        scontri_giornata = self._calendario_custom[giornata._n_giornata-1]
        for indx in range(0, len(scontri_giornata), 2):
            [pti_casa, pti_fuori] = self.calcola_partita(giornata._squadre_pti[scontri_giornata[indx]], giornata._squadre_pti[scontri_giornata[indx+1]])
            giornata._squadre_pti_classifica[scontri_giornata[indx]] = pti_casa
            giornata._squadre_pti_classifica[scontri_giornata[indx+1]] = pti_fuori     
          
        
    def calcola_partita(self, pti_casa, pti_fuori):
        """Calcola i gol di una partita confrontando pti_casa e pti_fuori"""
        gol_casa = self.converti_punti_gol(pti_casa)
        gol_fuori = self.converti_punti_gol(pti_fuori)
        if gol_casa > gol_fuori:
            return [Costanti.PTI_V, Costanti.PTI_S]
        elif gol_casa < gol_fuori:
            return [Costanti.PTI_S, Costanti.PTI_V]
        else:
            return [Costanti.PTI_P, Costanti.PTI_P]
            
            
    def converti_punti_gol(self, pti):
        """Restituisce il numero di gol a seconda dei punti e delle soglie gol stabilite"""
        if pti < Costanti.SOGLIE_PUNTI_GOL[0]:
            return 0
        else:
            return bisect.bisect_right(Costanti.SOGLIE_PUNTI_GOL,pti)

        
    def print_calendario(self):
        """Stampa il calendario"""
        n_giornata = 1
        for giornata_custom in self._calendario_custom:
            print "Giornata " + str(n_giornata)
            for i in range(0, Costanti.NUM_SQUADRE, 2):
                print str(giornata_custom[i][:3]) + ' - ' + str(giornata_custom[i+1][:3])
            print
            n_giornata += 1
            
            
    def print_classifica(self):
        """Stampa la classifica"""
        for squadra, punti in sorted(self._classifica.iteritems(), key=lambda (k,v): (v,k), reverse=True):
            print squadra + '\t\t' + str(punti)

Questa è la classe più complessa del programmino. Tra gli attributi abbiamo _permutation che è banalmente la permutazione delle squadre per questo specifico calendario (in una lista di stringhe), _giornate che mantiene la lista degli oggetti Giornata, il dizionario _classifica con chiave i nomi delle squadre e valori i punti in classifica, il dizionario _diz_segnaposti con chiave i segnaposti (A, B, C, ecc...) e valori i nomi delle squadre, _calendario_custom una lista di liste rappresentante il calendario per questa realtà. Ogni lista elemento è ordinata come spiegato:

_calendario_custom = [
['A', 'B', 'C', 'D'], # per la giornata in cui A vs B e C vs D
['A', 'C', 'B', 'D'], # per la giornata in cui A vs C e B vs D
['D', 'A', 'C', 'B']] # per la giornata in cui D vs A e C vs B

I metodi chiamati sono calcola_classifica, che per ogni giornata chiama calcola_giornata, che per ogni giornata chiama calcola_partita, che utilizza il metodo converti_punti_gol per assegnare i gol fatti alle singole squadre.

Una volta calcolata la classifica, grazie al metodo get_squadra_campione è restituita la lista delle squadre con più punti, se Costanti.PARIMERITO=False, o una stringa con la concatenazione di queste, altrimenti.


Il Main

Vediamo infine la funzione main dalla quale parte l'esecuzione dello script:

def main(filename="Calendario.xlsx"):
    """A partire dal nome del file excel scaricato:
    crea una lista di oggetti Giornata, inizializzati con i punti delle squadre nelle singole giornate;
    utilizza queste informazioni per calcolare la classifica di tutti i fattoriale(Costanti.NUM_SQUADRE) calendari;
    stampa la classifica dei calendari vinti dalle singole squadre, al variare dei punti in classifica"""
    
    squadre = []
    giornate = [Giornata(n) for n in range(1, Costanti.NUM_GIORNATE+1)]

    calendario_xl = xl.load_workbook(filename)
    calendario_sheet = calendario_xl.get_active_sheet()
    squadre = get_squadre_calendario(calendario_sheet)

    set_giornate_calendario(calendario_sheet, giornate, squadre)
    
    all_permutations = list(itertools.permutations(squadre))

    classifica_calendari = dict(zip(squadre, [0]*Costanti.NUM_SQUADRE))

    for perm in all_permutations:
        calendario = Calendario(perm, giornate)
        calendario.calcola_classifica()
        squadre_campioni = calendario.get_squadra_campione()
        classifica_attuale = dict(zip(squadre, [0]*Costanti.NUM_SQUADRE))
        for sc in squadre_campioni:
            classifica_attuale[sc] = 1 
        classifica_calendari = dict(Counter(classifica_calendari) + Counter(classifica_attuale))

    import pandas as pd
    classifica_list = []
    location = 0
    df = pd.DataFrame(columns=['SQUADRA', 'PUNTI IN CLASSIFICA', 'CALENDARI VINTI'])
    for squadra, vittorie in classifica_calendari.iteritems():
        row = squadra + '@' + str(vittorie)
        df.loc[location] = row.split('@')
        location = location + 1
    df = df.sort(columns=['CALENDARI VINTI'], ascending=False)
    df.to_csv(Costanti.FILENAME_OUTPUT, sep=';', index=False)

Per prima cosa sono inizializzate le liste squadre e giornate; poi con le funzioni del modulo openpyxl viene letto il file Excel passato come parametro alla funzione; dopo la valorizzazione delle liste squadre e giornate, è creata la lista di tutte le permutazioni di squadre con la funzione permutations del modulo itertools.
Per ogni permutazione, è creato un oggetto Calendario per il quale sarà calcolata la classifica e restituito l'elenco delle squadre vincitricei. Queste popoleranno il dizionario classifica_calendari che sarà infine scritto all'interno di un file .csv con il modulo pandas (per il quale avevamo scritto una piccola introduzione).

Mettiamo infine a disposizione lo script completo ed il calendario di Paperopoli per le vostre sperimentazioni su github tramite quest link https://github.com/allafinedelpalo/FantacalcioPython

Non esitate a segnalare malfunzionamenti, migliorie o dubbi sul codice. Il programma ha funzionato per esempi piccoli, ma non è "testato" per tutte le evenienze. In un prossimo articolo vedremo come mostrare alcune delle statistiche calcolate (più altre più complesse) con il modulo matplotlib di python.

EDIT: dopo aver letto il commento di Luca, abbiamo aggiunto una descrizione per la costante ULTIMA_GIORNATA per fermare il calcolo delle classifiche ad una determinata giornata e abbiamo automatizzato la costruzione del calendario con i segnaposti utilizzando un'implementazione python dell'algoritmo Round-robin tournament trovata su stackoverflow.

Alessio Antonielli

Ingegnere informatico, appassionato di cinema, musica, videogiochi e serie tv. Insomma, le solite cose che vi aspettereste da un ex studente di Ingegneria Informatica, giusto per rafforzare lo stereotipo…

Statistiche sui calendari del Fantacalcio con Python ultima modifica: 2016-10-11T11:36:14+01:00 da Alessio Antonielli


Advertisment ad adsense adlogger