PyScore

001: # -*- python -*-
002: #### racesheet.py #### python package PyScore.tabulate module racesheet ####
003: 
004: # PyScore
005: # a race scoring programme
006: # written by Matt Draisey
007: # 2004 April 6
008: 
009: reloadables=[]
010: 
011: #### racesheet.py #### python package PyScore.tabulate module racesheet ####
012: 
013: import re
014: from relational import base
015: from standing import boatconf,confbase,enumstat,eventstat
016: from tabulate import enumcond
017: 
018: ######## ######## some base classes ######## ########
019: 
020: class SheetEntry(confbase.ConfValueEntry):
021:     """The base of a working class to tabulate results."""
022:     
023: class SheetList(base.ValueListable,list,base.Joint):
024:     """A nice relation of SheetEntries."""
025: 
026: def apply_to_race_named(func,racename,handicapsheet,*p,**pp):
027:     def hasracename(race):
028:         if race.racename==racename: return race
029:         else: raise AttributeError
030:     for (race,handicapentries) in handicapsheet.adjoin_hierarchy([(
031:         "start",
032:         lambda entry,start: hasracename(start.race),
033:         lambda entry: hasracename(entry.race)
034:     )]):
035:         handicaprace=SheetList(handicapentries)
036:         func(race,handicaprace,*p,**pp)
037: 
038: def apply_to_all_races(func,handicapsheet,*p,**pp):
039:     for (race,handicapentries) in handicapsheet.adjoin_hierarchy([(
040:         "start",lambda entry,start: start.race,lambda entry: entry.race
041:     )]):
042:         handicaprace=SheetList(handicapentries)
043:         func(race,handicaprace,*p,**pp)
044: 
045: class SheetDict(dict):
046:     """A nice keyed relation of SheetEntries."""
047: 
048:     def values(self):
049:         return SheetList(dict.values(self))
050: 
051:     def items(self):
052:         return SheetList(dict.items(self))
053: 
054: ######## ######## some concrete classes ######## ########
055: 
056: class RaceSheetEntry(SheetEntry):
057:     """
058:     A working class to tabulate per race results.
059:     Racesheet race sheet entries are referred to simply as a race
060:     or a raceentry.
061:     """
062: 
063:     def __init__(self,racename):
064: 
065:         assert isinstance(racename,eventstat.RaceName)
066:         self.racename=racename
067: 
068:         # for comparison # for print # for saving to file
069:         self.entuple=(racename,)
070:         
071: class StartSheetEntry(SheetEntry):
072:     """
073:     A working class to tabulate per start/division results.
074:     Racesheet division sheet entries are referred to simply as a start
075:     or as a startentry.
076:     """
077: 
078:     def __init__(self,race,divisionname):
079: 
080:         assert isinstance(race,RaceSheetEntry)
081:         self.race=race
082: 
083:         assert isinstance(divisionname,eventstat.DivisionName)
084:         self.divisionname=divisionname
085: 
086:         try:
087:             self.levelracing=divisionname.levelracing
088:         except AttributeError:
089:             pass
090:         
091:         try:
092:             self.levelrating=divisionname.levelrating
093:         except AttributeError:
094:             pass
095:         
096:         # for comparison # for print # for saving to file
097:         self.entuple=(race,divisionname,)
098:         #self.entuple=(race.racename,divisionname,)
099: 
100: class HandicapSheetEntry(SheetEntry):
101:     """
102:     A working class to tabulate per boat results.
103:     Racesheet handicap sheet entries are referred to simply as a handicap
104:     or a handicapentry or even more simply as an entry.
105:     """
106: 
107:     HMSre=re.compile(r"""^(\d{2}):(\d{2}):(\d{2})$""")
108: 
109:     def __init__(self,race,startnew,en,bs,bn,fc,ft,cd,cf,cr,ps):
110: 
111:         # race: the current RaceSheetEntry
112:         # startnew: a startsheet factory for this race
113: 
114:         ### pk: Persistent key (primary key in boat conf data)
115: 
116:         # en: Entry number
117:         # bs: Sail number
118:         # bn: Boat name
119:         # fc: Finish condition
120:         # ft: Finish time
121:         # cd: Division
122:         # cf: Fleet series/casual configuration
123:         # cr: Effective rating
124:         # ps: Comment
125: 
126:         assert isinstance(race,RaceSheetEntry)
127: 
128:         try:
129:             zdivisionname=eventstat.DivisionName(cd,strict=True)
130:         except ValueError:
131:             zdivisionname=eventstat.DivisionName.UNKNOWN
132:             self.race=race
133:         else:
134:             self.start=startnew(zdivisionname)
135: 
136:         self.boat=boatconf.BoatIdentificationEntry(bs,bn)
137:         self.fleet=enumstat.FleetEnum(cf)
138:         try:
139:             zrating=int(cr)
140:             self.rating=zrating
141:             self.ziprating=(0,zrating)
142:         except ValueError:
143:             try:
144:                 zrating=zdivisionname.levelrating
145:                 self.rating=zrating
146:                 self.ziprating=(1,zrating)
147:             except AttributeError:
148:                 zrating="?"
149:                 self.ziprating=(2,)
150:         self.finishcondition=enumcond.FinishCondEnum(fc)
151:         tmatch=self.HMSre.match(ft)
152:         if tmatch:
153:             zfinishhms=tuple([int(dd) for dd in tmatch.groups()])
154:             self.finishhms=zfinishhms
155:             self.zipfinishhms=(0,zfinishhms)
156:         else:
157:             zfinishhms=()
158:             self.zipfinishhms=(1,)
159:         self.entrynumber=en
160:         self.comment=ps
161: 
162:         # for comparison # for print # for saving to file
163:         self.entuple=(race,zdivisionname,self.boat,)
164:         #self.entuple=(race.racename,zdivisionname,self.boat,)
165: 
166: class OverrideSheetEntry(SheetEntry):
167:     """
168:     A specialized variety of HandicapSheetEntry to allow
169:     explicit manual scores to override calculated scores.
170:     """
171: 
172:     def __init__(self,race,startnew,en,bs,bn,cd,cf,sf,ss,sc,sw,ps):
173: 
174:         # race: the current RaceSheetEntry
175:         # startnew: a startsheet factory for this race
176: 
177:         # en: Entry number
178:         # bs: Sail number
179:         # bn: Boat name
180:         # cd: Division
181:         # cf: Fleet series/casual configuration
182:         # sf: Score condition
183:         # ss: Series score
184:         # sc: Casual score
185:         # sw: Casual weight
186:         # ps: Comment
187: 
188:         assert isinstance(race,RaceSheetEntry)
189: 
190:         try:
191:             zdivisionname=eventstat.DivisionName(cd,strict=True)
192:         except ValueError:
193:             zdivisionname=eventstat.DivisionName.UNKNOWN
194:             self.race=race
195:         else:
196:             self.start=startnew(zdivisionname)
197: 
198:         self.boat=boatconf.BoatIdentificationEntry(bs,bn)
199:         self.fleet=enumstat.FleetEnum(cf)
200:         self.entrynumber=en
201:         self.scorecondition=enumcond.ScoreCondEnum(sf)
202:         try:
203:             self.finishcondition=enumcond.FinishCondEnum(
204:                 sf,strict=True
205:             )
206:         except ValueError:
207:             self.finishcondition=enumcond.FinishCondEnum.DNC
208:         try:
209:             self.seriespoints=round(float(ss),1)
210:         except ValueError:
211:             pass
212:         else:
213:             self.starter=False
214:         try:
215:             self.casualpoints=int(sc)
216:             self.casualweight=int(sw)
217:         except ValueError:
218:             pass
219:         else:
220:             self.starter=False
221:         self.comment=ps
222: 
223:         # for comparison # for print # for saving to file
224:         self.entuple=(race,zdivisionname,self.boat,)
225:         #self.entuple=(race.racename,zdivisionname,self.boat,)
226: 
227: class RCSheetEntry(SheetEntry):
228:     """
229:     A specialized variety of HandicapSheetEntry to allow for an
230:     automatic series redress of average series points to boats that
231:     miss their start to fulfill RC duties.
232:     RC sheet entries are referred to simply as an RC entry.
233:     RC entries are associated with a race and not with a particular
234:     start.  Such information is dependent on series registration
235:     which may not be available at the race level.
236:     """
237: 
238:     def __init__(self,race,bs,bn,ps):
239: 
240:         # bs: Sail number
241:         # bn: Boat name
242:         # ps: Comment
243: 
244:         # unlike handicapsheet entries, RCSheetEntries do not
245:         # automatically create race and start entries for
246:         # obvious reasons.
247: 
248:         assert isinstance(race,RaceSheetEntry)
249: 
250:         self.race=race
251:         self.boat=boatconf.BoatIdentificationEntry(bs,bn)
252:         self.comment=ps
253: 
254:         # for comparison # for print # for saving to file
255:         self.entuple=(race,self.boat,)
256:         #self.entuple=(race.racename,self.boat,)
257: 
258: #### racesheet.py #### python package PyScore.tabulate module racesheet ####