Archivio

Posts Tagged ‘wxpython’

wxpython: statusbar + gauge

22 novembre 2017 Commenti chiusi
import wx
import time


class View(wx.Frame):
    def __init__(self, parent):
        self.parent = parent
        super(View, self).__init__(parent=self.parent)
        self.panel = wx.Panel(parent=self)
        self.SetSize((350, 100))
        self.status_bar = self.CreateStatusBar(2)
        self.status_bar.SetStatusText('0/0')
        self.status_bar.SetStatusWidths([100, -1])
        gauge_pos, gauge_size = self.get_gauge_dimensions()
        self.gauge = wx.Gauge (self.status_bar, -1, 100, gauge_pos, gauge_size)
        # bindings
        self.Bind(wx.EVT_SIZE, self.on_size)
        self.Show()

    def get_gauge_dimensions(self):
        """Get gauge position and dimensions"""
        pos_x, pos_y, dim_x, dim_y = self.status_bar.GetFieldRect(1)
        return (pos_x, pos_y), (dim_x, dim_y)
       
    def on_quit(self, event):
        self.Destroy()

    def on_size(self, event):
        """Resize gauge when the main frame is resized"""
        size = self.GetSize()
        self.SetSize(size)
        gauge_pos, gauge_size = self.get_gauge_dimensions()
        self.gauge.SetSize(gauge_size)
        event.Skip ()       
        self.Update()

    def set_range(self, value):
        """Set the range of gauge"""
        self.gauge.SetRange(value)

    def get_range(self):
        """Get the range of gauge"""
        return self.gauge.GetRange()

    def set_progress(self, value):
        """Set the indicator gauges progress"""
        self.gauge.SetValue(value)

    def set_status_text(self, value):
        """Set the indicator text gauges progress"""
        self.status_bar.SetStatusText(value)


if __name__ == "__main__":
    app = wx.App(False)
    tot = 300  # maximum value for gauge
    v = View(parent=None)
    v.set_range(tot)
    for n in range(1, tot + 1):
        v.set_progress(n)
        time.sleep(.001)
        v.set_status_text('%s/%s' % (n, tot))
    v.set_progress(0)
    app.MainLoop()

Categorie:python, wxPython Tag: ,

FantaStat 2.0

22 novembre 2017 Commenti chiusi

Introduzione

Fstat 2.0 è una semplice applicazione per visualizzare le statistiche
dei giocatori di fantacalcio.
La precedente versione serviva a visualizzare i file.txt veccio formato, quelli che indicavano anche i goal segnati, gli assist ecc.
I file più recenti indicano solo il fanta voto, voto senza bonus malus e la quotazione:

code|NAME|TEAM|fanta voto|voto|quotazione

Link utili

Il codice dell’applicazione è reperibile nel repo corrispondente di github.
I binari win con database players.db qui.
I file txt delle giornate di fantacampionato sono reperibili sul blog.

Moduli utilizzati
Python 2.7.8
grafica: wx 3.0.2.0
ORM: Django 1.10.1

L’utilizzo è molto semplice e di seguito viene descritto:

Creazione database

Qualora ci si dimenticasse di creare il database per primo, al lancio dell’applicazione si verrà avvisati da un messaggio.

Ogni baco segnalato sarà ben gradito.

Creare quindi il database con il seguente comando:

python manage.py makemigrations players

Le migrations iniziali dovrebbero già essere presenti nel repo di github, quindi potrebbero non risultare modifiche, procedere quindi con il secondo comando:

python manage.py migrate

Avviare Fstat2.0

Per avviare l’applicazione eseguire lo script main.py con il comando:

python main.py

Non avendo ancora importato nessun giocatore, verremo avvisati da un messaggio che è necessario importare il primo file:

Le prime giornata disputate sono già fornite con il repo in posizione players/days, oppure sono sempre reperibili qui.
Dal menu Import-> Import players importare il file desiderato, solitamente la giornata 1 (MCC1.txt)

Il file dei giocatori va importato solo la prima volta, dopodichè il menu non sarà più attivo.
Da qui in avanti si importeranno solo i file dei voti.
Il primo sarà nuovamente MCC1.txt. Dal menu Import -> Import Evaluations, procedere con l’importazione.

Finita un’importazione eseguire un refresh dall’apposito pulsante.
L’interfaccia si presenta come in figura:

I radio-buttons permettono di filtrare i giocatori per ruolo, mentre cliccando sulle colonne della lista,
l’ordinamento avverrà in base alla colonna cliccata. Ad esempio cliccando su real_team, i giocatori
saranno ordinati per ruolo e per squadra di appartenenza.

Cliccando invece sulla “riga” di un determinato giocatore, sarà possibile modificarlo.

Dal menu Player -> Summary si accede alla lista riassuntiva del giocatori, poichè la visualizzazione della schermata del frame principale, mostra le medie dei giocatori e non i valori iniziali.
Da qui cliccando sui giocatori si possono modificare come in precedenza.

Qualora nei file non risultasse un giocatore, sarà possibile crearlo dal menu Players -> New Player

Stesso discorso vale per le valutazioni; esiste un sommario accessibile dal menu Evaluations -> Summary

dove cliccando sulla riga di una valutazione, sarà possibile modificarla

Come per i giocatori, sarà possibile aggiungere una valutazione ad hoc, dal menu
Evaluations -> New Evaluation

Come ultima operazione, è possibile cancellare tutti i dati, dal menu Reset.

Fantamanager 2.2

20 settembre 2017 Commenti chiusi

Diversamente dalla versione precedente FantaLega 2.1 e dalla versione Light, qui è possibile gestire un campionato di n.squadre, a scontri diretti (con più di 8/10 squadre).
Il giocatore non potrà più appartenere a più squadre ma è prevista un’asta.

Opzioni:
Asta
Costruzione Squadre
Generazione calendario
Modifica Squadre
Consegna formazioni
Modifica Formazioni
Importazione Giocatori e Voti Gazzetta
Modifica Giocatori
Mercato tra squadre
Calcolo punteggio formazioni
Classifica Squadre

Grafica: WX
Django per l’ORM

Utilizzare virtualenv ed installare i requirements:

pip install -r requirements.txt

Creare il database:

python manage.py makemigrations fantalega
python manage.py migrate

lanciare l’applicazione con il comando:

python main.py

Il link di github:
repo su github

Fantalega: gestore Asta

1 settembre 2017 Commenti chiusi

Ieri è terminata ufficialmente la sessione di calciomercato.
Molti fanta-allenatori hanno rischiosamente già effettuato le loro aste,
molti altri (noi), NO.

Ecco un tool parecchio spartano che velocizzerà le annotazioni
squadra-giocatore durante l’asta.

Auction1.0 è un gestore di aste di fantacalcio scritto in python.
Per la grafica sono state utilizzate le librerie wx, mentre per la
gestione del database e l’ORM, è stato utilizzato django.

Requisiti: installare django e wxpython

Su github è presente una prima bozza di repo.

Per prima cosa creare i database con i due comandi:

python manage.py makemigrations auction
python manage.py migrate

dopo queste operazioni che creeranno il database con le relative tabelle, è
possibile avviare la app:

python main.py

per prima cosa importiamo i giocatori utilizzando i soliti file txt in
formato Gazzetta, reperibili qui:

E’ possibile importare i giocatori più e più volte in modo da aggiornare
la lista dei calciatori.
Importati i giocatori, è necessario creare le squadre.

Dopo aver creato le squadre, si comincia l’asta.

Si seleziona il giocatore per squadra reale di appartenenza,
si utilizzano i filtri di ruolo e si assegna un costo d’asta e la squadra
che si aggiudica il giocatore. Durante l’asta è possibile avere un resoconto
delle squadre, con budget rimanente e giocatori ancora da comprare

Dai menu Teams e Players è possibile editare le squadre e i giocatori
per apportare delle modifiche. E’ anche possibile aggiungere giocatori che,
in fase d’asta, non sono ancora stati ufficializzati da Gazzetta e quindi
non presenti nei file.

Terminata l’asta è possibile effettuare scambi tra fanta-allenatori con il menu
“Trades”.

Nota: la casella max trades del pannello edit-team indica le massime operazioni
di mercato concesse durante la fantalega, mutuate dall’applicazione completa.
Queste operazioni (Trades) in fase di asta, sono invece illimitate.

Come ultima operazione, è possibile esportare un file in formato csv (menu Auction).

Python: creazione calendario Fantalega

28 aprile 2010 Commenti chiusi

Il modulo che regola la creazione del calendario secondo il metodo del cingolo a scorrimento è:

# calendar.py


class Calendar(object):
    def __init__(self, teams, rounds=2):
        self.teams = teams
        self.max_rounds = rounds
        self.team1_home = True
        self.team2_home = True
        self.matrix = []
        self.first_round_calendar = []
        self.season = []

    def generate_matrix(self):
        """
        generate_matrix() -> list

        create a matrix to fill with teams
        First init matrix with all None fields.
        The matrix first row is a copy of input iterable (i.e. teams).
        The matrix second row is the reversed one except the last iterable value
        that is excluded.
        """
        # init matrix
        self.matrix = [[None]*len(self.teams) for team in self.teams]
        # first matrix row with all teams (header) i.e. [1, 2, 3, 4]
        self.matrix[0] = self.teams
        # reversed header without the last team i.e. [3, 2, 1, None]
        row2 = self.teams[:][:-1]
        row2.reverse()
        self.matrix[1][0:(len(self.teams) - 1)] = row2[0:(len(self.teams) - 1)]

    def matrix_rotation(self):
        """
        matrix_rotation() -> list

        This is the first step of matrix composition.
        if the first row is [3, 2, 1, None], the second one will be the last value
        except None of the first row at postion 1 and then the other values rotated:
        [1, 3, 2, None]
        The last row will be [2, 1, 3, None]
        """
        i = 1
        while i < len(self.teams):
            k = 1
            for item in self.matrix[i]:
                try:
                    self.matrix[i + 1][k] = item
                    self.matrix[i + 1][0] = self.matrix[i + 1][(
                        len(self.teams) - 1)]
                    self.matrix[i + 1][(len(self.teams) - 1)] = None
                    k += 1
                except IndexError:
                    break
            i += 1

    def matrix_substitution(self):
        """
        matrix_substitution() -> list

        This is the second step of matrix composition.
        If the matrix header and a matrix row for the same index, have the same value
        the row index moves his value in place of 'None' and gets the excluded value
        of the previous matrix generation (4):
        [1, 2, 3, 4]
        [3, 2, 1, None] --> 2 has same index of header
        [3, 4, 1, 2]  4 take place of 2 and 2 substitutes None
        """
        row_m = 1
        while row_m < len(self.teams):
            for item_a in self.matrix[0]:
                for item_b in self.matrix[row_m]:
                    if self.matrix[0].index(item_a) == \
                       self.matrix[row_m].index(item_b):
                        # when a value has the same index than header 
                        if item_a == item_b:
                            # the value is substituted by the excluded one (e.g. 4)
                            self.matrix[row_m][self.matrix[row_m].index(item_b)] = \
                                self.teams[-1]  
                            self.matrix[row_m][(len(self.teams) - 1)] = item_b
            row_m += 1

    def match_composition(self):
        """
        match_composition() -> list

        Match composition: third step
        coupling the first team of header with the matrix first-row team
        with same index. The second team of header is coupled with the
        second team of the matrix first row.
        We get teams only if the team are not chosen yet, to avoid duplicated match
        if header team or n-row one is duplicate, we pass to the other column
        I.e. At day 1 we couple header team with same index first-row team,
        at day 2 we couple header team with same index second-row team and so on.
        """
        cal = []
        day = 1
        while day < len(self.teams):
            first_round = []
            for team1 in self.matrix[0]:
                index = self.matrix[0].index(team1)
                team2 = self.matrix[day][index]
                if team2 not in first_round or team1 not in first_round:
                    if self.team1_home is True:
                        first_round.append(team1)
                        first_round.append(team2)
                        cal.append((day, team1, team2))
                        self.team1_home = False
                        self.team2_home = True
                    else:
                        first_round.append(team2)
                        first_round.append(team1)
                        cal.append((day, team2, team1))
                        self.team1_home = True
                        self.team2_home = False
            day += 1
        return cal


    def generate_2nd_round(self):
        """
        generate_2nd_round() -> list

        Create the second round for half calendar
        Tuples have "day, team_a, team_b" format
        """
        return [(int(n) + len(self.teams) - 1, team2, team1)
                for n, team1, team2 in self.first_round_calendar]


    def build_season(self):
        """
        build_season() -> list

        generate a match calendar iterable.
        Tuples have "day, team_a, team_b" format
        """
        n_round = 1
        self.generate_matrix()
        self.matrix_rotation()
        self.matrix_substitution()
       
        self.first_round_calendar = self.match_composition()
        while n_round < self.max_rounds:
            second_round = self.generate_2nd_round()
            self.season = self.first_round_calendar + second_round
            n_round += 1
        return self.season

Una piccola interfaccia per l’inserimento delle squadre:

# main.py

import wx
from random import shuffle
from calendar import Calendar


def get_teams():
    app = wx.App()
    app.MainLoop()
    teams = []
    dlg = wx.TextEntryDialog(None, "number of teams?", 'INFO', '')
    if dlg.ShowModal() == wx.ID_OK:
        try:
            nteams  = int(dlg.GetValue())
        except ValueError:
            print "ERROR: Need a number!"
        else:
            # exit if number of teams is < 2
            if nteams < 2:
                print "ERROR: number of teams must be >= 2"
            else:
                
                team_no = 1
                while team_no <= nteams:
                    dlgt = wx.TextEntryDialog(None, "team name n. %d?"  % (team_no),
                                              'INFO', '')
                    if dlgt.ShowModal() == wx.ID_OK:
                        name = dlgt.GetValue()
                        if name in teams:
                            print "ERROR: team <%s> already exists" % name
                            dlgt.SetValue('')
                        else:
                            teams.append(name)
                            dlgt.SetValue('')
                            team_no += 1
                # Add fake team if number of teams is odd
                if nteams % 2 != 0: 
                    teams.append('Fake Team')
        return teams


if __name__ == '__main__':
    teams = get_teams()
    # shuffle(teams)
    if teams:
        cal = Calendar(teams=teams)
        season = cal.build_season()
        for match in season:
            print match
    else:
        print "WARNING: no teams saved"

Un piccolo abbozzo di tests:

import unittest
from calendar import Calendar


class CalendarInitTestCase(unittest.TestCase):
    def setUp(self):
        self.teams = ['Inter', 'Milan', 'Juve', 'Napoli']
        self.cal = Calendar(self.teams)

    def tearDown(self):
        self.teams = []

    def test_default_rounds(self):
        self.assertEqual(self.cal.max_rounds, 2)

    def test_default_teams(self):
        self.assertEqual(self.cal.teams, self.teams)


class CalendarMatrixTestCase(unittest.TestCase):
    def setUp(self):
        self.teams = ['Inter', 'Milan', 'Juve', 'Napoli']
        self.cal = Calendar(self.teams)
        self.cal.generate_matrix()

    def tearDown(self):
        self.cal.teams = []
        self.cal.matrix = []

    def test_matrix_header(self):
        self.assertEqual(self.cal.matrix[0], self.teams)

    def test_matrix_first_row_before_rotation(self):
        self.assertEqual(self.cal.matrix[1], ['Juve', 'Milan', 'Inter', None])

    def test_matrix_second_row_before_rotation(self):
        self.assertEqual(self.cal.matrix[2], [None, None, None, None])

    def test_matrix_third_row_before_rotation(self):
        self.assertEqual(self.cal.matrix[3], [None, None, None, None])

    def test_matrix_second_row_after_rotation(self):
        self.cal.matrix_rotation()
        self.assertEqual(self.cal.matrix[2], ['Inter', 'Juve', 'Milan', None])

    def test_matrix_third_row_after_rotation(self):
        self.cal.matrix_rotation()
        self.assertEqual(self.cal.matrix[3], ['Milan', 'Inter', 'Juve', None])

    def test_matrix_first_row_after_substitution(self):
        self.cal.matrix_rotation()
        self.cal.matrix_substitution()
        self.assertEqual(self.cal.matrix[1], ['Juve', 'Napoli', 'Inter', 'Milan'])

    def test_matrix_second_row_after_substitution(self):
        self.cal.matrix_rotation()
        self.cal.matrix_substitution()
        self.assertEqual(self.cal.matrix[2], ['Napoli', 'Juve', 'Milan', 'Inter'])

    def test_matrix_third_row_after_substitution(self):
        self.cal.matrix_rotation()
        self.cal.matrix_substitution()
        self.assertEqual(self.cal.matrix[3], ['Milan', 'Inter', 'Napoli', 'Juve'])


class CalendarSeasonTestCase(unittest.TestCase):
    def setUp(self):
        self.teams = ['Inter', 'Milan', 'Juve', 'Napoli']
        self.cal = Calendar(self.teams)
        self.cal.generate_matrix()
        self.cal.matrix_rotation()
        self.cal.matrix_substitution()
        self.season = [(1, 'Inter', 'Juve'), (1, 'Napoli', 'Milan'),
                       (2, 'Inter', 'Napoli'), (2, 'Juve', 'Milan'),
                       (3, 'Inter', 'Milan'), (3, 'Napoli', 'Juve'),
                       (4, u'Juve', u'Inter'), (4, u'Milan', u'Napoli'),
                       (5, u'Napoli', u'Inter'), (5, u'Milan', u'Juve'),
                       (6, u'Milan', u'Inter'), (6, u'Juve', u'Napoli')]
    def tearDown(self):
        self.cal.teams = []
        self.cal.matrix = []

    def test_1st_round_season(self):
        self.cal.build_season()
        self.assertEqual(self.cal.first_round_calendar,
                         self.season[:len(self.season)/2])

    def test_complete_season(self):
        self.cal.build_season()
        self.assertEqual(self.cal.season, self.season)
        
        
    


if __name__ == '__main__':
    suite1 = unittest.TestLoader().loadTestsFromTestCase(CalendarInitTestCase)
    suite2 = unittest.TestLoader().loadTestsFromTestCase(CalendarMatrixTestCase)
    suite3 = unittest.TestLoader().loadTestsFromTestCase(CalendarSeasonTestCase)
    alltests = unittest.TestSuite([suite1, suite2, suite3])
    unittest.TextTestRunner(verbosity=2).run(alltests)
Categorie:python, wxpython Tag: ,