djangofantalega: model Lineup
9 – Models: Lineup
Creare il Model Lineup.
Lineup (formazione) è in relazione many-to-one con Team,
ma è anche in relazione con Player.
Una formazione (Lineup) contiene molti giocatori (Player), ma un
giocatore, può far parte di più formazioni;
la relazione Player-Lineup è quindi di tipo many-to-many.
Come già fatto in precedenza, si utilizzerà una association-table per la relazione ManytoMany
in modo da poter sfruttare l’attributo ‘position’, poichè la posizione di un giocatore
in panchina, è determinante quando si usa il cambio modulo.
Aggiungere quindi nel file fantalega/models.py i models necessari:
... class Lineup (models.Model): league = models.ForeignKey(League, related_name='league_lineups') team = models.ForeignKey(Team, related_name='team_lineups') players = models.ManyToManyField(Player, through='LineupsPlayers', related_name='player_lineups') timestamp = models.DateTimeField() day = models.IntegerField() pts = models.FloatField(null=True) won = models.IntegerField(null=True) matched = models.IntegerField(null=True) lost = models.IntegerField(null=True) goals_made = models.IntegerField(null=True) goals_conceded = models.IntegerField(null=True) def get_players_by_position(self): lineup_players = LineupsPlayers.query.filter(lineup=self.id).order_by( LineupsPlayers.position).all() if lineup_players: return [rec.player for rec in lineup_players] def __unicode__(self): return "[%s] %s" % (self.day, self.team.name) # M2M secondary Association object class LineupsPlayers(models.Model): player = models.ForeignKey(Player, on_delete=models.CASCADE) lineup = models.ForeignKey(Lineup, on_delete=models.CASCADE) position = models.IntegerField() class Meta: verbose_name_plural = 'Lineup-Player Associations' @staticmethod def get_sorted_lineup(lineup): return LineupsPlayers.objects.filter( lineup=lineup).order_by('position').all()
Aggiornare il database inserendo le nuove tabelle.
(venv) >python manage.py makemigrations Migrations for 'fantalega': fantalega\migrations\0006_auto_20161111_1103.py: - Create model Lineup - Create model LineupsPlayers - Add field players to lineup - Add field team to lineup
confermare con:
(venv) C:\tmp\djangosite>python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, fantalega, log, sessions Running migrations: Applying fantalega.0006_auto_20161111_1103... OK
Sistemare l’interfaccia di admin per i nuovi modelli:
file fantalega/admin.py:
# noinspection PyUnresolvedReferences ... from .models import Lineup, LineupsPlayers # Register your models here. class LineupPlayersInline(admin.TabularInline): model = Lineup.players.through extra = 0 classes = ('collapse',) class LineupAdmin(admin.ModelAdmin): inlines = [LineupPlayersInline, ] ordering = ('day', ) list_display = ('day', 'team', 'pts') list_filter = ('day', 'team') list_per_page = 20 class LineupsPlayersAdmin(admin.ModelAdmin): ordering = ('position', ) list_display = ('position', 'colored_player', 'get_team_name', ) list_filter = ('lineup__day', 'lineup__team__name') list_per_page = 21 @staticmethod def get_team_name(obj): return obj.lineup.team.name @staticmethod def colored_player(obj): colour = '013ADF' if obj.position <= 11 else 'FF0080' return format_html('<span style="color: #{};">{}</span>', colour, obj.player.name) ... admin.site.register(Lineup, LineupAdmin) admin.site.register(LineupsPlayers, LineupsPlayersAdmin)
Ora aggiungere gli urls inerenti Lineup nel file fantalega\urls.py:
... # lineup urls url(r'^leagues/(?P<league_id>[0-9]+)/teams/' r'(?P<team_id>[0-9]+)/lineup/upload$', views.upload_lineup, name='upload_lineup'), url(r'^leagues/(?P<league_id>[0-9]+)/teams/(?P<team_id>[0-9]+)' r'/lineup/(?P<day>[0-9]+)/$', views.lineup_details, name='lineup_details'), url(r'^leagues/(?P<league_id>[0-9]+)/teams/(?P<team_id>[0-9]+)' r'/lineup/(?P<day>[0-9]+)/edit$', views.lineup_edit, name='lineup_edit'), ]
Aggiungere nel file fantalega\views.py le nuove viste ‘upload_lineup’,
‘lineup_details’ e ‘lineup_edit’:
... from .models import Lineup, LineupsPlayers from django.utils import timezone # this is important! ... @login_required def upload_lineup(request, league_id, team_id, day=None): league = get_object_or_404(League, pk=int(league_id)) modules = [(1, '343'), (2, '352'), (3, '442'), (4, '433'), (5, '451'), (6, '532'), (7, '541')] team = get_object_or_404(Team, pk=int(team_id)) if request.GET.get('back_to_team_details'): return redirect('team_details', league.id, team.id) team_players = [(p.code, "%s [%s]" % (p.name, p.role)) for p in team.player_set.all()] if request.method == "POST": form = UploadLineupForm(request.POST, initial={'players': team_players, 'team': team, 'modules': modules, 'day': day, 'league': league}) if form.is_valid(): day = form.cleaned_data['day'] lineup = Lineup.objects.filter(team=team, day=day, league=league).first() if lineup: messages.error(request, 'Lineup already exists!') return redirect('team_details', league_id, team_id) holders = [Player.get_by_code(int(code), season=league.season) for code in form.cleaned_data['holders']] substitutes = [Player.get_by_code(int(code), season=league.season) for code in [form.cleaned_data['substitute_%s' % n] for n in range(1, 11)]] error = form.check_holders() if error: messages.error(request, error) else: dead_line = Match.objects.filter( league=league, day=day).first().dead_line now = timezone.now() if now > dead_line: messages.error(request, "You are out of time!") messages.info(request, "Getting the previous Lineup") lineup = Lineup.objects.filter( team=team, day=(day - 1), league=league).first() holders = [p for p in lineup.players.all()[:11]] substitutes = [p for p in lineup.players.all()[11:]] lineup = Lineup.objects.create(team=team, day=day, league=league, timestamp=now) for pos, player in enumerate((holders + substitutes), 1): LineupsPlayers.objects.create(position=pos, lineup=lineup, player=player) messages.success(request, 'Lineup uploaded!') return redirect('team_details', league_id, team_id) else: form = UploadLineupForm(initial={'players': team_players, 'team': team, 'modules': modules, 'day': day, 'league': league}) return render(request, 'fantalega/upload_lineup.html', {'form': form, 'players': team_players, 'team': team, 'league': league}) @login_required def lineup_edit(request, league_id, team_id, day): league = get_object_or_404(League, pk=int(league_id)) modules = [(1, '343'), (2, '352'), (3, '442'), (4, '433'), (5, '451'), (6, '532'), (7, '541')] team = get_object_or_404(Team, pk=int(team_id)) if request.GET.get('back_to_team_details'): return redirect('team_details', league.id, team.id) lineup = Lineup.objects.filter(team=team, league=league, day=day).first() team_players = [(p.code, "%s [%s]" % (p.name, p.role)) for p in team.player_set.all()] if request.method == "POST": form = UploadLineupForm(request.POST, initial={'players': team_players, 'team': team, 'modules': modules, 'day': day, 'league': league}) if form.is_valid(): day = form.cleaned_data['day'] # module_id = form.cleaned_data['module'] # module = dict(form.fields['module'].choices)[int(module_id)] holders = [Player.get_by_code(int(code), season=league.season) for code in form.cleaned_data['holders']] substitutes = [Player.get_by_code(int(code), season=league.season) for code in [form.cleaned_data['substitute_%s' % n] for n in range(1, 11)]] error = form.check_holders() if error: messages.error(request, error) else: now = timezone.now() dead_line = Match.objects.filter( league=league, day=day).first().dead_line if now > dead_line: messages.error(request, "You are out of time!") messages.info(request, "No change saved") else: messages.success(request, "Lineup correct!") lineup.timestamp = now lineup.save() for pos, player in enumerate((holders + substitutes), 1): lu = LineupsPlayers.objects.filter( lineup=lineup, position=int(pos)).first() lu.player = player lu.save() print "[INFO] Lineup %s (%s) -> Player %s " \ "pos %s upgraded!" % (team.name, day, player.name, pos) messages.success(request, 'Lineup upgraded!') return redirect('team_details', league_id, team_id) else: form = UploadLineupForm(initial={'players': team_players, 'team': team, 'modules': modules, 'day': day, 'league': league}) for n, player in enumerate(lineup.players.all()[11:], 1): form.fields['substitute_%s' % n].initial = player.code form.fields['holders'].initial = [p.code for p in lineup.players.all()[:11]] return render(request, 'fantalega/upload_lineup.html', {'form': form, 'players': team_players, 'team': team, 'league': league}) @login_required def lineup_details(request, league_id, team_id, day): league = get_object_or_404(League, pk=int(league_id)) total = 0.0 mod = 0.0 team = get_object_or_404(Team, pk=int(team_id)) if request.GET.get('back_to_team_details'): return redirect('team_details', league.id, team.id) offset = team.leagues.all()[0].offset fantaday = int(day) + int(offset) lineup = team.team_lineups.filter(day=int(day)).first() lineup_players = LineupsPlayers.get_sorted_lineup(lineup) holders = [l_p.player for l_p in lineup_players[:11]] substitutes = [s_p.player for s_p in lineup_players[11:]] d_votes = {code: (fv, v) for code, fv, v in [Evaluation.get_evaluations(day=(int(day) + offset), code=p.code, season=league.season) for p in holders]} if request.GET.get('modify lineup'): return redirect('lineup_edit', league.id, team.id, day) if request.GET.get('calculate'): try: handler = LineupHandler(lineup, int(day), league) total = handler.get_pts() mod = handler.mod except AttributeError: messages.error(request, 'No pts available: ' 'lineups or evaluations are missing, ' 'check in calendar...') total = '' context = {'team': team, 'holders': holders, 'substitutes': substitutes, 'lineup': lineup, 'day': day, 'd_votes': d_votes, 'mod': mod, 'fantaday': fantaday, 'total': total, 'league': league} return render(request, 'fantalega/lineup.html', context)
Sia la vista ‘upload_lineup’ che lineup_edit, fanno utilizzo dello stesso form:
fantalega/forms.py
... from .models import Player ... class UploadLineupForm(forms.Form): def __init__(self, *args, **kwargs): self.dict_values = kwargs.pop('initial') super(UploadLineupForm, self).__init__(*args, **kwargs) self.fields['module'] = forms.ChoiceField( label=u'module', choices=self.dict_values['modules'], widget=forms.Select()) self.fields['day'] = forms.IntegerField(initial=self.dict_values['day']) self.fields['holders'] = forms.MultipleChoiceField( choices=self.dict_values['players'], widget=forms.CheckboxSelectMultiple()) for n in range(1, 11): self.fields['substitute_%s' % n] = forms.ChoiceField( label=u'substitute %s' % n, choices=self.dict_values['players'], widget=forms.Select(), required=False) def check_holders(self): error = '' data = self.cleaned_data['holders'] substitutes = [self.cleaned_data.get('substitute_%s' % n) for n in range(1, 11)] if len(data) != 11: return "holder players number is wrong!" module = dict(self.fields['module'].choices)[ int(self.cleaned_data['module'])] mod_defs, mod_mids, mod_forws = module goalkeepers = len() defenders = len() midfielders = len() forwarders = len() if goalkeepers > 1: return "To many goalkeepers!" if defenders != int(mod_defs): return "number of defenders doesn't match module!" if midfielders != int(mod_mids): return "number of midfielders doesn't match module!" if forwarders != int(mod_forws): return "number of forwarders doesn't match module!" for code in substitutes: player = Player.get_by_code(int(code), self.dict_values['league'].season) if code in data: return "substitute %s is in holders!" % player.name if substitutes.count(code) > 1: return "Duplicate substitute %s in list!" % player.name return error
Nota:
I campi (field) substitute, essendo 10, sono stati creati dinamicamente con un ciclo for.
che inseriremo negli import delle views
fantalega/views.py
... from .forms import UploadLineupForm ...
Le templates coinvolte nell'operazione di salvataggio delle formazioni saranno:
fantalega/upload_lineup.html
{% extends 'fantalega/base.html' %} {% load bootstrap3 %} {% block content %} <b>Upload lineup for <font color="green">{{ team.name }}</font></b> <br><br> <form action="#" method="get"> <input type="submit" class="btn" value="back to {{ team.name }} team" name="back_to_team_details"> </form> <form method="POST" class="form"> {% csrf_token %} <div id="container" style="width:100%;"> <div id="left" style="float:left; width:50%;"> {% bootstrap_field form.module %} {% bootstrap_field form.holders %} </div> <div id="right" style="float:right; width:50%;"> {% bootstrap_field form.day %} {% bootstrap_field form.substitute_1 %} {% bootstrap_field form.substitute_2 %} {% bootstrap_field form.substitute_3 %} {% bootstrap_field form.substitute_4 %} {% bootstrap_field form.substitute_5 %} {% bootstrap_field form.substitute_6 %} {% bootstrap_field form.substitute_7 %} {% bootstrap_field form.substitute_8 %} {% bootstrap_field form.substitute_9 %} {% bootstrap_field form.substitute_10 %} </div> </div> <div> {% buttons %} <button type="submit" class="btn btn-primary"> {% bootstrap_icon "save" %} upload</button> {% endbuttons %} </div> </form> {% endblock %}
Nota:
siccome il form per l'upload e la modifica della formazione è lo stesso,
unica sarà anche la template. Per visualizzare i dettagli della formazione invece:
fantalega/lineup.html
{% extends 'fantalega/base.html' %} {% load app_filters %} {% block content %} <h1>Lineup <font color="green">{{ team.name }}</font> day: <font color="red">{{ day }}</font><br></h1> <div id="container" style="width:100%;"> <div id="left" style="float:left; width:30%;"> <b><font color="orange">holders:</font></b><br> <table class="table table-striped"> <tr> <th>code</th> <th>player name</th> <th>real team</th> <th>role</th> <th>fv</th> <th>v</th> </tr> {% for player in holders %} <tr> <td>{{ player.code }}</td> <td><a href="{% url 'player_details' player.id %}"> {{ player.name }}</a></td> <td>{{ player.real_team }}</td> <td>{{ player.role }}</td> <td>{{ player|get_fvote:fantaday }}</td> <td>{{ player|get_vote:fantaday }}</td> </tr> {% endfor %} </table> <form action="#" method="get"> <input type="submit" class="btn" value="modify lineup" name="modify lineup"> </form> <form action="#" method="get"> <input type="submit" class="btn" value="calculate" name="calculate"> </form> <b><font color="orange">pts:</font></b> {{ total|pts_filter }} <br> <b><font color="orange">defense mod:</font></b> {{ mod }} <br> <br> <form action="#" method="get"> <input type="submit" class="btn" value="back to {{ team.name }} team" name="back_to_team_details"> </form> </div> <div id="right" style="float:right; width:30%;"> <b><font color="orange">substitutes:</font></b><br> <table class="table table-striped"> <tr> <th>code</th> <th>player name</th> <th>real team</th> <th>role</th> <th>fv</th> <th>v</th> </tr> {% for player in substitutes %} <tr> <td>{{ player.code }}</td> <td><a href="{% url 'player_details' player.id %}"> {{ player.name }}</a></td> <td>{{ player.real_team }}</td> <td>{{ player.role }}</td> <td>{{ player|get_fvote:fantaday }}</td> <td>{{ player|get_vote:fantaday }}</td> </tr> {% endfor %} </table> </div> </div> {% endblock %}
Per inserire una formazione, ogni User dovrà recarsi all'interno
della lega e cliccare sulla propria squadra.
Nella pagina relativa ai dettagli di squadra c'è un pulsante 'new lineup', che
va come sempre, abilitato nella view di competenza: 'team_details'.
Se vogliamo che le formazioni già inserite vengano visualizzate,
dobbiamo passare alla template, tramite il dizionario 'context', la lista
delle formazioni.
... @login_required def team_details(request, league_id, team_id): league = get_object_or_404(League, pk=int(league_id)) team = get_object_or_404(Team, pk=int(team_id)) lineups = Lineup.objects.filter(team=team, league=league).order_by('day') context = {'team': team, 'user': request.user, 'league': league, 'lineups': lineups} if request.GET.get('back_to_teams'): return redirect('league_details', league.id) if request.GET.get('new lineup'): return redirect('upload_lineup', league.id, team.id) return render(request, 'fantalega/team.html', context) ...
Ora cliccando sul bottone 'New Lineup', si verrà redirezionati al form
di inserimento. Scegliere il modulo, i titolari le riserve e salvare.
I dati inseriti verranno controllati:
- correttezza del modulo
- giocatori non duplicati
- deadline rispettata
E' possibile cliccare sulla singola formazione elencata per entrare nel
dettagli della stessa. Utilizzando un custom_filter, aggiungerlo al
file fantalega/templatetags/app_filters.py
... @register.filter(name='get_vote') def get_vote(player, day): evaluation = player.player_votes.filter(day=int(day)).first() if evaluation: return '%s' % float(evaluation.net_value) else: return '0.0'
All'interno della pagina formazione, ci sono due pulsanti oltre quello
di ritorno ai dettagli squadra: 'modify lineup' e 'calculate'.
Con il primo è possibile modificare la formazione, con il secondo,
si richiama uno script che esegue i calcoli.
Attenzione!!
Ricordarsi che la giornata da calcolare tiene presente dell'offset di lega.
Se si vogliono calcolare i punteggi della giornata di fantalega 1 ma l'offset di
lega è 2, vuol dire che nella realtà si è alla giornata 3, quindi è necessario
prima importare la valutazioni della giornata reale 3, poi effettuare i calcoli.
Siccome i voti già inseriti dovrebbero apparire nella template dei dettagli
di lega, aggiungiamo al dizionario passato alla template, anche le giornate
inserite:
def league_details(request, league_id): league = get_object_or_404(League, pk=int(league_id)) league_teams = league.team_set.all() days = [d['day'] for d in Evaluation.objects.filter( season=league.season).order_by('day').values('day').distinct()] ... context = {'league': league, 'teams': league_teams, 'days': days, 'user': request.user} ...
Il tasto 'calculate' è legato alla view 'lineup_details':
... if request.GET.get('calculate'): try: handler = LineupHandler(lineup, int(day), league) total = handler.get_pts() mod = handler.mod except AttributeError: messages.error(request, 'No pts available: ' 'lineups or evaluations are missing, ' 'check in calendar...') total = '' ...
LineupHandler viene importato nel file views.py
... from fantalega.scripts.calc import LineupHandler, get_final, lineups_data ...
il file fantalega/scripts/calc.py conterrà quindi:
from fantalega.models import Evaluation class BadInputError(Exception): pass def convert_pts_to_goals(pts): """ convert_pts_to_goals(pts) -> int Calculate number of goals by total pts, e.g.: convert_pts_to_goals(60) -> 0 convert_pts_to_goals(66) -> 1 convert_pts_to_goals(72) -> 2 """ if isinstance(pts, float): if pts < 60.0: return 0 return (float(pts) - 60) // 6 else: raise BadInputError("Need a Float as input, %s in input" % pts) def get_final(pts_a, pts_b): """ get_final(pts_a, pts_b) -> tuple Convert pts to goals between 2 teams, e.g.: get_final(66, 62) -> (1, 0) """ if isinstance(pts_a, float) and isinstance(pts_b, float): goal_a = convert_pts_to_goals(pts_a) goal_b = convert_pts_to_goals(pts_b) if goal_a == goal_b: if pts_a - pts_b >= 4: # +4 in the same level results in +1 goal goal_a += 1 elif pts_b - pts_a >= 4: # +4 in the same level for team_b goal_b += 1 if pts_a < 60: # og for team_a goal_b += 1 if pts_b < 60: # og for team_b goal_a += 1 if pts_a - pts_b > 9.5: # +10 in the same level results in +1 goal goal_a += 1 elif pts_b - pts_a > 9.5: # +10 for team_b goal_b += 1 return int(goal_a), int(goal_b) else: raise BadInputError("Need a Float as input, %s and %s in input" %\ (pts_a, pts_b)) def lineups_data(goals_a, goals_b): """ lineups_data(goals_a, goals_b) -> dict Convert to goals team data as: won, lost, matched, goals_made etc, i.e.: lineups_data(3, 2) -> {'hw': 1, 'vw': 0, 'hl': 0, ...} hw: home_won vw: visit_won hm: home_matched vm: visit_matched hl: home_lost ...and so on hgm: home goals made hgc: home goals conceded :param goals_a: int goals of team A :param goals_b: int goals of team B """ data = {'hw': 0, 'hm': 0, 'hl': 0, 'hgm': goals_a, 'hgc': goals_b, 'vw': 0, 'vm': 0, 'vl': 0, 'vgm': goals_b, 'vgc': goals_a} if goals_a > goals_b: data['hw'] = 1 data['hl'] = 0 data['hm'] = 0 data['vw'] = 0 data['vl'] = 1 data['vm'] = 0 elif goals_a < goals_b: data['hw'] = 0 data['hl'] = 1 data['hm'] = 0 data['vw'] = 1 data['vl'] = 0 data['vm'] = 0 else: data['hw'] = 0 data['hl'] = 0 data['hm'] = 1 data['vw'] = 0 data['vl'] = 0 data['vm'] = 1 return data class LineupHandler(object): def __init__(self, lineup, day, league): self.league = league self.day = day + league.offset self.mod = 0.0 self.lineup = lineup self.holders = [p for p in self.lineup.players.all()[:11]] self.substitutes = [p for p in self.lineup.players.all()[11:]] self.not_evaluated = [] self.available_by_role = [] self.added_player = [] self.new_list = [] self.substitutions = 0 self.candidate = None self.available = [p for p in self.substitutes if Evaluation.objects.filter(player=p, day=self.day, season=league.season ).first().fanta_value > 0.0 and p.role != 'goalkeeper'] def get_goalkeeper_substitute(self): gks = [p for p in self.substitutes if Evaluation.objects.filter( player=p, day=self.day, season=self.league.season ).first().fanta_value > 0.0 and p.role == 'goalkeeper'] if gks: return gks[0] else: return None def get_evaluation(self, player): evaluation = Evaluation.objects.filter(player=player, season=self.league.season, day=self.day).first() return evaluation.fanta_value def need_substitutions(self): evaluated = [p for p in self.holders if self.get_evaluation(p) > 0.0] return len(evaluated) != 11 def get_same_role_substitute(self, player): self.available_by_role = [p for p in self.substitutes if p.role == player.role and Evaluation.objects.filter( season=self.league.season, player=p, day=self.day ).first().fanta_value > 0.0] self.candidate = self.available_by_role[0] return self.candidate def get_substitute(self, player): if player.role == 'goalkeeper': self.candidate = self.get_goalkeeper_substitute() else: # print self.available if self.available: return self.available[0] def is_same_role_available(self, player): self.available_by_role = [p for p in self.substitutes if p.role == player.role and Evaluation.objects.filter( season=self.league.season, player=p, day=self.day ).first().fanta_value > 0.0] return len(self.available_by_role) > 0 def is_substitute_available(self): self.available = [p for p in self.substitutes if Evaluation.objects.filter( season=self.league.season, player=p, day=self.day ).first().fanta_value > 0.0 and p.role != 'goalkeeper'] return len(self.available) > 0 def get_pts(self): if not self.need_substitutions(): return self.def_mod(self.holders) else: self.not_evaluated = \ [p for p in self.holders if Evaluation.objects.filter( player=p, day=self.day, season=self.league.season ).first().fanta_value == 0.0] for player in self.not_evaluated: if self.is_same_role_available(player): self.candidate = self.get_same_role_substitute(player) self.substitutes.pop(self.substitutes.index(self.candidate)) elif self.is_substitute_available(): self.candidate = self.get_substitute(player) # check module if self.is_module_accepted(player): self.substitutes.pop(self.substitutes.index(self.candidate)) else: print "\n[WARNING] module doesn't exist!" self.candidate = None else: self.candidate = None if self.candidate and self.substitutions < 3: self.added_player.append(self.candidate) self.substitutions += 1 self.new_list = [p for p in self.holders if Evaluation.objects.filter( player=p, day=self.day, season=self.league.season ).first().fanta_value > 0.0] +\ self.added_player return self.def_mod(self.new_list) def is_module_accepted(self, player): d, m, f = 0, 0, 0 lineup = self.holders[:] lineup.pop(lineup.index(player)) lineup.append(self.candidate) for role in [p.role for p in lineup]: if role == 'defender': d += 1 elif role == 'midfielder': m += 1 elif role == 'forward': f += 1 else: pass module = '%s%s%s' % (d, m, f) print "\n[INFO] module changes in %s" % module return module in ('343', '352', '442', '433', '451', '532', '541') def def_mod(self, player_list): total = sum([Evaluation.objects.filter( player=p, day=self.day, season=self.league.season ).first().fanta_value for p in player_list]) defenders = [p for p in player_list if p.role == 'defender'] goalkeepers = [p for p in player_list if p.role == 'goalkeeper'] gk = goalkeepers[0] if goalkeepers else None vgk = Evaluation.objects.filter(player=gk, day=self.day, season=self.league.season ).first().net_value def_votes = [Evaluation.objects.filter(season=self.league.season, player=d, day=self.day).first().net_value for d in defenders] if len(defenders) >= 4 and gk: if vgk == 0.0: vgk = 6.0 for v in def_votes: if v == 0.0: def_votes[def_votes.index(v)] = 6.0 values = sorted(def_votes, reverse=True)[:3] + [vgk] avg_def = sum(values)/4.0 if avg_def == 6: self.mod = 1 elif 6 < avg_def <= 6.25: self.mod = 2 elif 6.25 < avg_def <= 6.5: self.mod = 3 elif 6.5 < avg_def <= 6.75: self.mod = 4 elif 6.75 < avg_def <= 7: self.mod = 5 elif avg_def > 7: self.mod = 6 return total + self.mod else: return total
Salvare ora gli avanzamenti su github:
git add --all
git commit -m "Lineup added"
git push -u origin master
articoli precedenti
0 - indice
1 - Virtualenv e Git
2 - Models: Season
3 - Admin: Login e Logout
4 - Models: League
5 - Models: Team
6 - Models: Match
7 - Models: Player
8 - Asta
articoli successivi
10 - Models: Trade
11 - Asta di riparazione
12 - Classifica
Commenti recenti