277 lines
9.9 KiB
Python
277 lines
9.9 KiB
Python
from collections import defaultdict
|
|
from django.db import models
|
|
from django.contrib.auth.models import User
|
|
|
|
# these things are independent of the game
|
|
|
|
OUTCOMES = (('no contest', 'no contest'),
|
|
('normal', 'normal'),
|
|
('DQ', 'DQ'),
|
|
('submission', 'submission'),
|
|
('appearance', 'appearance'),
|
|
('brawl', 'brawl'),
|
|
)
|
|
|
|
TITLES = (('wwe', 'WWE'),
|
|
('heavyweight', 'Heavyweight'),
|
|
('ic', 'Intercontinental'),
|
|
('us', 'United States'),
|
|
('tag', 'Tag Team'),
|
|
('diva', 'Divas'),
|
|
)
|
|
|
|
class Star(models.Model):
|
|
id = models.CharField(max_length=100, primary_key=True)
|
|
name = models.CharField(max_length=200)
|
|
photo_url = models.URLField()
|
|
division = models.CharField(max_length=100)
|
|
title = models.CharField(max_length=20, choices=TITLES, null=True)
|
|
|
|
@property
|
|
def active(self):
|
|
return self.division != 'other'
|
|
|
|
def win_title(self, title, tag_partner=None):
|
|
Star.objects.filter(title=title).update(title=None)
|
|
self.title = title
|
|
self.save()
|
|
if tag_partner:
|
|
if title != 'tag':
|
|
raise ValueError("can't have tag partner w/ non-tag belt")
|
|
tag_partner.title = title
|
|
tag_partner.save()
|
|
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
|
|
class Event(models.Model):
|
|
name = models.CharField(max_length=100)
|
|
date = models.DateField()
|
|
|
|
def add_match(self, *teams, **kwargs):
|
|
winner = kwargs.get('winner', None)
|
|
outcome = kwargs.get('outcome', '')
|
|
title_at_stake = kwargs.get('title_at_stake', None)
|
|
notes = kwargs.get('notes', '')
|
|
|
|
match = Match.objects.create(event=self,
|
|
title_at_stake=title_at_stake,
|
|
notes=notes
|
|
)
|
|
for team in teams:
|
|
mt = MatchTeam.objects.create(match=match)
|
|
if not isinstance(team, (list, tuple)):
|
|
team = [team]
|
|
for member in team:
|
|
try:
|
|
member = Star.objects.get(pk=member)
|
|
except Star.DoesNotExist:
|
|
raise ValueError('invalid star pk {0}'.format(member))
|
|
if not mt.title and member.title:
|
|
# multiple titles?
|
|
mt.title = member.title
|
|
mt.save()
|
|
mt.members.add(member)
|
|
if winner:
|
|
match.record_win(winner, outcome)
|
|
else:
|
|
match.outcome = outcome
|
|
match.save()
|
|
return match
|
|
|
|
def __unicode__(self):
|
|
return '{0} {1}'.format(self.name, self.date)
|
|
|
|
|
|
class Match(models.Model):
|
|
event = models.ForeignKey(Event, related_name='matches')
|
|
winner = models.ForeignKey(Star, null=True)
|
|
outcome = models.CharField(max_length=10, choices=OUTCOMES)
|
|
title_at_stake = models.CharField(max_length=50, choices=TITLES, null=True)
|
|
notes = models.TextField(blank=True, default='')
|
|
|
|
def record_win(self, star, outcome):
|
|
team = self.teams.get(members__pk=star)
|
|
team.victorious = True
|
|
team.save()
|
|
self.winner_id = star
|
|
self.outcome = outcome
|
|
self.save()
|
|
|
|
def do_title_change(self):
|
|
if self.title_at_stake:
|
|
victors = list(self.teams.get(victorious=True).members.all())
|
|
if len(victors) == 1:
|
|
victor[0].win_title(self.title_at_stake)
|
|
elif len(victors) == 2 and self.title_at_stake == 'tag':
|
|
victor[0].win_title(self.title_at_stake, victor[1])
|
|
else:
|
|
raise ValueError('invalid number of victors for title change')
|
|
|
|
def points(self):
|
|
points = {}
|
|
winners = None
|
|
losers = []
|
|
title_teams = {}
|
|
team_count = 0
|
|
for team in self.teams.all():
|
|
for star in team.members.all():
|
|
points[star.id] = 0
|
|
if self.outcome == 'appearance' and not star.active:
|
|
points[star.id] += 10
|
|
if self.outcome == 'brawl':
|
|
points[star.id] += 2
|
|
if team.title:
|
|
title_teams[team.title] = team
|
|
if team.victorious:
|
|
winners = team
|
|
else:
|
|
losers.append(team.members.count())
|
|
team_count += 1
|
|
|
|
# don't worry about winners of appearances or brawls
|
|
if self.outcome in ('appearance', 'brawl'):
|
|
return points
|
|
|
|
if winners:
|
|
winner_count = winners.members.count()
|
|
loser_count = sum(losers)
|
|
|
|
# figure out base points for winning
|
|
# DQ wins are worth 1 point no matter what
|
|
if self.outcome == 'DQ':
|
|
base_points = 1
|
|
allies = 0 # allies don't matter in a DQ
|
|
# rumble is worth participants/2
|
|
elif team_count > 6:
|
|
base_points = team_count / 2
|
|
allies = 0 # no allies in a rumble
|
|
else:
|
|
# normal wins are worth 2
|
|
allies = winner_count - 1
|
|
base_points = max((loser_count - allies) * 2, 1)
|
|
|
|
# award points to winners
|
|
for w in winners.members.all():
|
|
points[w.id] = base_points
|
|
|
|
if self.title_at_stake:
|
|
if winners.title == self.title_at_stake:
|
|
# title defense
|
|
if winners.title in ('heavyweight', 'wwe'):
|
|
points[w.id] += 5
|
|
else:
|
|
points[w.id] += 3
|
|
elif self.outcome in ('normal', 'submission'):
|
|
# title win!
|
|
if self.title_at_stake in ('heavyweight', 'wwe'):
|
|
points[w.id] += 20
|
|
else:
|
|
points[w.id] += 10
|
|
else:
|
|
# defense by DQ
|
|
for star in title_teams[self.title_at_stake].members.all():
|
|
points[star.id] += 1
|
|
else:
|
|
# look over titles in match, to score a title-nondefense
|
|
for title, title_team in title_teams.iteritems():
|
|
# beat someone w/ title in a non-defense
|
|
if winners.title != title:
|
|
# beat tag champs in tag match w/o tag belt on line
|
|
if title == 'tag' and all(c == 2 for c in losers):
|
|
points[w.id] += 2
|
|
# beat champ in non-handicap match w/o belt on line
|
|
elif all(c == 1 for c in losers):
|
|
points[w.id] += 2
|
|
|
|
# if multiple people in this match and this person was credited
|
|
# w/ win, give them the bonus points
|
|
if allies:
|
|
points[self.winner_id] += 1
|
|
if self.outcome == 'submission':
|
|
points[self.winner_id] += 1
|
|
return points
|
|
|
|
def __unicode__(self):
|
|
ret = ' vs. '.join(str(t) for t in
|
|
self.teams.all().prefetch_related('members'))
|
|
if not self.winner_id:
|
|
ret += ' (no contest)'
|
|
return ret
|
|
|
|
class MatchTeam(models.Model):
|
|
members = models.ManyToManyField(Star)
|
|
match = models.ForeignKey(Match, related_name='teams')
|
|
victorious = models.BooleanField(default=False)
|
|
title = models.CharField(max_length=50, choices=TITLES, null=True)
|
|
|
|
def __unicode__(self):
|
|
ret = ' & '.join([str(m) for m in self.members.all()])
|
|
if self.title:
|
|
ret += ' (c)'
|
|
if self.victorious:
|
|
ret += ' (v)'
|
|
return ret
|
|
|
|
|
|
# fantasy stuff
|
|
|
|
class League(models.Model):
|
|
name = models.CharField(max_length=100)
|
|
active = models.BooleanField(default=True)
|
|
raw_picks = models.IntegerField(default=3)
|
|
smackdown_picks = models.IntegerField(default=3)
|
|
diva_picks = models.IntegerField(default=2)
|
|
wildcard_picks = models.IntegerField(default=1)
|
|
oldtimer_picks = models.IntegerField(default=2)
|
|
|
|
def score_event(self, event):
|
|
ppv_bonus = 1 if event.name.lower() not in ('raw', 'smackdown') else 0
|
|
TeamPoints.objects.filter(match__event=event).delete()
|
|
for match in event.matches.all():
|
|
for star, points in match.points().iteritems():
|
|
try:
|
|
team = self.teams.get(stars=star)
|
|
TeamPoints.objects.create(points=points + ppv_bonus,
|
|
team=team,
|
|
star_id=star,
|
|
match=match)
|
|
except Team.DoesNotExist:
|
|
pass
|
|
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
|
|
class Team(models.Model):
|
|
name = models.CharField(max_length=100)
|
|
login = models.OneToOneField(User, related_name='team')
|
|
league = models.ForeignKey(League, related_name='teams')
|
|
stars = models.ManyToManyField(Star, related_name='teams')
|
|
|
|
def add_star(self, pk):
|
|
star = Star.objects.get(pk=pk)
|
|
if self.league.teams.filter(stars=star).count() >= 1:
|
|
raise ValueError('cannot add {0}, already drafted in {1}'.format(
|
|
star, self.league))
|
|
self.stars.add(star)
|
|
|
|
def drop_star(self, pk):
|
|
member = Star.objects.get(pk=pk)
|
|
self.stars.remove(member)
|
|
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
|
|
class TeamPoints(models.Model):
|
|
points = models.IntegerField()
|
|
team = models.ForeignKey(Team, related_name='points')
|
|
star = models.ForeignKey(Star)
|
|
match = models.ForeignKey(Match)
|
|
|
|
def __unicode__(self):
|
|
return "{0} received {1} points for {2}'s performance in {3}".format(
|
|
self.team, self.points, self.star, self.match)
|