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