/usr/local/lib/python2.4/site-packages/dataplot/soccer/models.py

Go to the documentation of this file.
00001 from django.template.loader import render_to_string
00002 from dataplot import R,GenericPlot
00003 from dataplot import plotmodels as models
00004 #from django.db import models
00005 import pdb,os
00006 #GenericPlot.enable_caching=True
00007 
00008 R.SquareScatter.default_kwargs={'marginal':False}
00009 
00010 PLAYER_STATS=(
00011     'games',
00012     'wins',
00013     'win_percent',
00014     'goals_per_game',
00015     'team_goals_per_game',
00016     'goals_allowed_per_game',
00017     'differential',
00018     )
00019 
00020 class PlayerManager(models.Manager):
00021     """Adds plotting methods.
00022 
00023     """
00024 
00025     def get_ts_data(self):
00026         """Plot args for making multiple time series of win%
00027 
00028         We should replace this data filtering method with some
00029         database-backed method, so statistics can be looked up and
00030         plotted faster/easier.
00031 
00032         """
00033         data=[
00034             dict(P.win_percent_plot_args(),name=P.name)
00035             for P in self.plotable()]
00036         for D in data:
00037             v=D['y'][0]
00038             while v==0 or v==1:
00039                 D['y'].pop(0)
00040                 D['d'].pop(0)
00041                 v=D['y'][0]
00042         return data
00043 
00044     def plotable(self):
00045         return self.frequent_players()
00046 
00047     def frequent_players(self):
00048         return self.filter(games__gte=5)
00049 
00050     def get_goals_and_victories_args(self):
00051         qs=self.plotable()
00052         return {
00053             'x':[x.goals_per_game for x in qs],
00054             'xlab':"Goals per game",
00055             'y':[x.win_percent for x in qs],
00056             'ylab':"Win percent",
00057             'main':"Goals = victories?",
00058             'ann':['%s\n%s'%(x.name,x.games) for x in qs],
00059             }
00060     
00061     def wins_diff_args(self):
00062         qs=self.plotable()
00063         return {
00064             'y':[x.win_percent for x in qs],
00065             'ylab':"Win percent",
00066             'x':[x.differential for x in qs],
00067             'xlab':"Differential (average number of points your team wins/loses by)",
00068             'main':"Win percent versus differential",
00069             'ann':[x.name for x in qs],
00070             }
00071 
00072     def SquareScatter_args(self):
00073         qs=self.plotable()
00074         return {
00075             'y':[x.team_goals_per_game for x in qs],
00076             'ylab':"Team goals per game",
00077             'x':[x.goals_per_game for x in qs],
00078             'xlab':"Goals per game",
00079             'main':"Your contribution to your team's goals",
00080             'ann':[x.name for x in qs],
00081             }
00082     
00083 class Player(models.Model):
00084     name=models.CharField(
00085         max_length=100,null=False,blank=True,default='',unique=True)
00086     goals_per_game=models.FloatField(blank=True,null=True)
00087     team_goals_per_game=models.FloatField(blank=True,null=True)
00088     goals_allowed_per_game=models.FloatField(blank=True,null=True)
00089     differential=models.FloatField(blank=True,null=True)
00090     games=models.IntegerField(blank=True,null=True)
00091     wins=models.IntegerField(blank=True,null=True)
00092     win_percent=models.FloatField(blank=True,null=True)
00093 
00094     objects=PlayerManager()
00095 
00096     URLID='name'
00097 
00098     class Admin:
00099         fields=(
00100             (None,{'fields':['name']}),
00101             )
00102         list_display=tuple(['name']+list(PLAYER_STATS))
00103 
00104     class Meta:
00105         ordering=[('name')]
00106 
00107     MANAGER_DATAPLOTS=[
00108         (R.SquareScatter,{'attribute':'offense_defense','get_plot_args':{
00109         'x':'team_goals_per_game',
00110         'y':'inverse_goals_allowed',
00111         'ann':'name',
00112         'main':"Defense v. offense"
00113         }}),
00114         R.SquareScatter,
00115         (R.SquareScatter,{'attribute':'wins_diff'}),
00116         (R.multi_time_series,{'get_plot_args':{
00117         'x':'get_ts_data',
00118         'main':"Win percent over time",
00119         'ylab':"Win percent",
00120         'xlab':"Game date",
00121         },'init_args':{'h':9,'w':6.5}}),
00122         ]
00123 
00124     DATAPLOTS=[
00125         (R.TimeSeries,{'qs':'scores_ordered','get_plot_args':{
00126         'd':'game_seconds',
00127         'y':'goals',
00128         }}),
00129         (R.TimeSeries,{'qs':'scores_by_date','attribute':'win_percent_plot',
00130                        'get_plot_args':{
00131         'd':'game_seconds',
00132         'y':'win_percent_until_now',
00133         'ylab':'Win percent',
00134         'xlab':'Game date',
00135         'main':'Win percent change over time'
00136         }}),
00137         ]
00138 
00139     def get_absolute_url(self):
00140         return '/soccer/player/%s/'%self.id
00141 
00142     def inverse_goals_allowed(self):
00143         return 1/(self.goals_allowed_per_game+1)
00144 
00145     def get_stats(self):
00146         return [self.get_stat(at) for at in PLAYER_STATS]
00147 
00148     def get_stat(self,at):
00149         v=getattr(self,at)
00150         if v==None:
00151             return
00152         stat={
00153             'name':at.replace("_"," ").capitalize(),
00154             'value':v,
00155             }
00156         for side in 'gt','lt','exact':
00157             di={'%s__%s'%(at,side):v}
00158             stat[side]=qs=Player.objects.filter(**di)
00159         return stat
00160 
00161     def scores_ordered(self):
00162         return order_scores(self.score_set.all())
00163 
00164     def scores_by_date(self):
00165         return self.score_set.select_related().order_by('soccer_game.date')
00166 
00167     def __str__(self):
00168         return self.name
00169 
00170     def save(self):
00171         self.cache()
00172         super(Player,self).save()
00173 
00174     def save_plots(self): # forces remake of this players plots every save
00175         self.make_model_plots()
00176 
00177     def cache(self):
00178         scores=self.score_set.all()
00179         N=self.games=scores.count()
00180         if not N:
00181             return
00182         self.goals_per_game=float(sum([
00183             sc.goals for sc in scores]))/N
00184         # need to make sure cached values are updated first!
00185         self.goals_allowed_per_game=float(sum([
00186             sc.points_allowed() for sc in scores]))/N
00187         self.team_goals_per_game=float(sum([
00188             sc.team.points for sc in scores]))/N
00189         diffs=[sc.differential() for sc in scores]
00190         self.differential=float(sum(diffs))/N
00191         # maybe use team.won to calc instead?
00192         self.wins=sum([1 for d in diffs if d > 0])
00193         self.win_percent=float(self.wins)/N
00194 
00195     def get_absolute_url(self):
00196         return '/soccer/player/%s/'%self.name
00197 
00198 GAME_STATS=(
00199     'hi_score',
00200     'lo_score',
00201     'differential',
00202     )
00203 
00204 class GameManager(models.Manager):
00205     
00206     DEFAULT_DATAFILE=os.path.join(os.path.dirname(__file__),'games.txt')
00207     TUPKEYS=('name','goals','own_goals')
00208     
00209     def get_latest(self):
00210         try:
00211             return self.order_by('-date')[0]
00212         except IndexError: # no data yet
00213             self.create_from_file()
00214             return self.order_by('-date')[0]
00215 
00216     def create_from_file(self,filename=None):
00217         """Create new bike rides based on records in a text file.
00218 
00219         """
00220         filename=filename or self.DEFAULT_DATAFILE
00221         print "Loading data from %s"%filename
00222         lines=open(filename).readlines()
00223         for line in lines: # assume no header line
00224             print line
00225             self.create_from_line(line)
00226 
00227     def create_from_line(self,line):
00228         """Create one game based on line of text datafile.
00229 
00230         """
00231         from dataplot import GenericPlot
00232         oldcache=GenericPlot.enable_caching
00233         GenericPlot.enable_caching=False #
00234         teamlists=[i.split() for i in line.split(',')]
00235         G=Game.objects.create(date=teamlists[0].pop(0))
00236         for L in teamlists:
00237             T=G.team_set.create(name=L.pop(0))
00238             like=[L[i::len(self.TUPKEYS)] for i in range(len(self.TUPKEYS))]
00239             dictlist=[dict(zip(self.TUPKEYS,tup)) for tup in zip(*like)]
00240             for D in dictlist:
00241                 D['player'],cr=Player.objects.get_or_create(name=D.pop('name'))
00242                 sc=T.score_set.create(**D)
00243             T.save()
00244         GenericPlot.enable_caching=oldcache
00245         return G
00246 
00247     def get_export_text(self):
00248         """Text for exported data file.
00249 
00250         """
00251         return '\n'.join([g.export() for g in self.all()])
00252 
00253     def export_games_to_file(self,filename=None):
00254         """Export data to a text file.
00255 
00256         """
00257         filename=filename or self.DEFAULT_DATAFILE
00258         text=self.get_export_text()
00259         f=open(filename,'w')
00260         f.write(text)
00261         f.close()
00262 
00263 class Game(models.Model):
00264     date=models.DateField(blank=False,null=False)
00265     hi_score=models.IntegerField(blank=True,null=True)
00266     lo_score=models.IntegerField(blank=True,null=True)
00267     differential=models.IntegerField(blank=True,null=True)
00268 
00269     objects=GameManager()
00270 
00271     URLID='date'
00272 
00273     class Admin:
00274         list_display=[
00275             'date',
00276             'hi_score',
00277             'lo_score',
00278             'differential',
00279             ]
00280         fields=(
00281             (None,{
00282             'fields':['date']}),
00283             )
00284 
00285     class Meta:
00286         ordering=[('date')]
00287 
00288     def export(self):
00289         teams=self.teams_ordered()
00290         teamtext=','.join([T.export() for T in teams])
00291         return '%s %s'%(self.date,teamtext)
00292 
00293     def teams_ordered(self):
00294         return self.team_set.order_by('-points')
00295 
00296     def cache(self):
00297         try:
00298             teams=self.teams_ordered()
00299             self.hi_score,self.lo_score=[getattr(t,'points') for t in teams]
00300         except:
00301             pass
00302         try:
00303             self.differential=self.hi_score-self.lo_score
00304         except:
00305             pass
00306     
00307     def __str__(self):
00308         return '%s'%self.date
00309 
00310     def get_absolute_url(self):
00311         return '/soccer/game/%s/'%self.date
00312 
00313     def save(self):
00314         self.cache()
00315         super(Game,self).save()
00316         
00317 def order_scores(qs):
00318     return qs.select_related().order_by(
00319         '-goals','own_goals','soccer_player.name')
00320 
00321 class Team(models.Model):
00322     name=models.CharField(max_length=100)
00323     game=models.ForeignKey(Game)
00324     goals=models.IntegerField(blank=True,null=True)
00325     own_goals=models.IntegerField(blank=True,null=True)
00326     points=models.IntegerField(blank=True,null=True)
00327     won=models.BooleanField(blank=True,null=False,default=False)
00328     tied=models.BooleanField(blank=True,null=False,default=False)
00329     players=models.IntegerField(blank=True,null=True)
00330 
00331     def export(self):
00332         scores=self.scores_ordered()
00333         sctext=' '.join([
00334             '%s %s %s'%(sc.player.name,sc.goals,sc.own_goals)
00335             for sc in scores])
00336         return '%s %s'%(self.name,sctext)
00337         
00338     def summary(self):
00339         return render_to_string(
00340             'soccer/team_summary.html',{'t':self})
00341 
00342     def scores_ordered(self):
00343         p=getattr(self,'HILITE',None)
00344         qs=order_scores(self.score_set.all())
00345         if p:
00346             for sc in qs:
00347                 sc.is_player=sc.player==self.HILITE
00348         return qs
00349             
00350     def cache(self):
00351         """Save both teams relevant to this game.
00352 
00353         """
00354         self.other=self.other_team()
00355         self.other.other=self
00356         teams=(self,self.other)
00357         for t in teams: # totals for each team
00358             qs=t.score_set.all()
00359             t.goals=sum([sc.goals for sc in qs])
00360             t.own_goals=sum([sc.own_goals for sc in qs])
00361             t.players=qs.count()
00362         for t in teams: # points based on other teams totals
00363             t.points=t.goals+sum([
00364                 sc.own_goals for sc in t.other.score_set.all()])
00365         for t in teams:
00366             t.won=t.points>t.other.points
00367             t.tied=t.points==t.other.points
00368             super(Team,t).save()
00369         for p in Player.objects.filter(
00370             score__team__game__id__exact=self.game.id).distinct():
00371             p.save() # will remake player plots
00372         Player.make_manager_plots()
00373         self.game.save()
00374 
00375     def other_team(self):
00376         try:
00377             return self.game.team_set.exclude(id=self.id)[0]
00378         except:
00379             pass
00380 
00381     def save(self):
00382         if self.game.team_set.count()==2:
00383             self.cache()
00384         else:
00385             super(Team,self).save()
00386 
00387     def __str__(self):
00388         return '%s'%self.name
00389 
00390     class Admin:
00391         list_display=[
00392             'name',
00393             'game',
00394             'players',
00395             'points',
00396             'goals',
00397             'own_goals',
00398             ]
00399         fields=[
00400             (None,{
00401             'fields':['name','game']}),
00402             ]
00403              
00404 
00405 class Score(models.Model):
00406     player=models.ForeignKey(Player,blank=True,null=False,core=True)
00407     team=models.ForeignKey(Team,edit_inline=True,num_in_admin=10)
00408     goals=models.IntegerField(null=False,blank=False,default=0,core=True)
00409     own_goals=models.IntegerField(null=False,blank=False,default=0,core=True)
00410 
00411     def __str__(self):
00412         return '%s: %s'%(self.player,self.goals)
00413 
00414     def game_seconds(self):
00415         return self.team.game.date.strftime("%s")
00416 
00417     def win_percent_until_now(self):
00418         qs=self.player.score_set.filter(
00419             team__game__date__lte=self.team.game.date)
00420         wins=qs.filter(team__won__exact=True).count()
00421         ties=qs.filter(team__tied__exact=True).count()
00422         games=qs.count()
00423         pct=(wins*1.0+ties*0.5)/games
00424         return pct
00425     
00426     def points_allowed(self):
00427         return self.team.other_team().points
00428 
00429     def differential(self):
00430         return self.team.points-self.team.other_team().points
00431 
00432     def player_summary(self):
00433         self.team.HILITE=self.player
00434         return self.team.summary()
00435     

Generated on Tue Apr 22 23:16:22 2008 for django-dataplot by  doxygen 1.4.6