|
Post by Pleonast on Dec 16, 2013 8:42:16 GMT -8
# -- VoteCount.py -- 18 Dec 2013
""" Copyright 2013 Pleonast on boards.straightdope.com
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. """
class Day_t: def __init__(Self,Name,Num,LastPost): Self._Name=Name Self._Num=Num Self._LastPost=LastPost
class Player_t: def __init__(Self,Name,Alias,Align=None): Self._Name=Name Self._Alias=Alias Self._Align=Align Self._VotesAsSource=[] Self._UnvotesAsSource=[] Self._NetVotesAsSource=[] Self._VotesAsTarget=[] Self._UnvotesAsTarget=[] Self._NetVotesAsTarget=[] Self._SortValue=(-float('inf'),) def AddVoteAsSource(Self,Vote): if Vote._Source!=Self._Alias: return # prevent voting if already have vote on target for v in Self._NetVotesAsSource: if v._Target==Vote._Target: return Self._VotesAsSource+=[Vote] Self._VotesAsSource.sort(key=lambda vote:(vote._Post,vote._Target)) Self._NetVotesAsSource+=[Vote] def AddVoteAsTarget(Self,Vote): if Vote._Target!=Self._Alias: return # prevent voting if already have vote from source for v in Self._NetVotesAsTarget: if v._Source==Vote._Source: return Self._VotesAsTarget+=[Vote] Self._VotesAsTarget.sort(key=lambda vote:(vote._Post,vote._Source)) Self._NetVotesAsTarget+=[Vote] def AddUnvoteAsSource(Self,Unvote): if Unvote._Source!=Self._Alias: return # only unvote if vote is present for v in Self._NetVotesAsSource[:]: if v._Target==Unvote._Target: Self._UnvotesAsSource+=[Unvote] Self._NetVotesAsSource.remove(v) return def AddUnvoteAsTarget(Self,Unvote): if Unvote._Target!=Self._Alias: return # only unvote if vote is present for v in Self._NetVotesAsTarget[:]: if v._Source==Unvote._Source: Self._UnvotesAsTarget+=[Unvote] Self._NetVotesAsTarget.remove(v) return def CheckAlign(Self,Aligns): if Self._Align and Self._Align not in Aligns: raise ValueError(Self._Name+' has unknown alignment '+Self._Align) def StrVotesAsSource(Self,Players,StrikeCode,Aligns): output='' if Self._Align: output+='[color='+Aligns[Self._Align]._Color+']' output+='[b]'+Self._Name+'[/b]' if Self._Align: output+='[/color]' output+=' has ' numVotes=len(Self._NetVotesAsSource) if len(Self._VotesAsSource)==0: output+='not voted.\n' return output output+='voted for' isFirst=True unvotes=Self._UnvotesAsSource[:] for vote in Self._VotesAsSource: unvote=None for u in unvotes: if u._Target==vote._Target: unvote=u unvotes.remove(u) break if isFirst: isFirst=False else: output+=',' output+=' ' if unvote: output+='['+StrikeCode+']' if Players[vote._Target]._Align: output+=('[color='+ Aligns[Players[vote._Target]._Align]._Color+']') output+=Players[vote._Target]._Name if Players[vote._Target]._Align: output+='[/color]' output+=' ('+str(vote._Post) if unvote: output+='-'+str(unvote._Post) output+=')' if unvote: output+='[/'+StrikeCode+']' if isFirst: output+=' not voted' output+='.\n' return output def StrVotesAsTarget(Self,Players,StrikeCode,Aligns): output='' if Self._Align: output+='[color='+Aligns[Self._Align]._Color+']' output+='[b]'+Self._Name+'[/b]' if Self._Align: output+='[/color]' output+=' has ' numVotes=len(Self._NetVotesAsTarget) if len(Self._VotesAsTarget)==0: output+='no votes.\n' return output output+=str(numVotes)+' vote' if numVotes!=1: output+='s' if Self._Alias=='ham' or Self._Alias=='fil': output+=' [of '+str((len(Players)-3+1)//2)+' needed]' output+=' from' isFirst=True unvotes=Self._UnvotesAsTarget[:] for vote in Self._VotesAsTarget: unvote=None for u in unvotes: if u._Source==vote._Source: unvote=u unvotes.remove(u) break if isFirst: isFirst=False else: output+=',' output+=' ' if unvote: output+='['+StrikeCode+']' if Players[vote._Source]._Align: output+=('[color='+ Aligns[Players[vote._Source]._Align]._Color+']') output+=Players[vote._Source]._Name if Players[vote._Source]._Align: output+='[/color]' output+=' ('+str(vote._Post) if unvote: output+='-'+str(unvote._Post) output+=')' if unvote: output+='[/'+StrikeCode+']' if isFirst: output+=' no votes' output+='.\n' return output
class Align_t: def __init__(Self,Name,Alias,Color): Self._Name=Name Self._Alias=Alias Self._Color=Color def StrLegend(Self): return '[color='+Self._Color+']'+Self._Name+'[/color]\n'
class Vote_t: def __init__(Self,Source,Target,Post): Self._Source=Source Self._Target=Target Self._Post=Post
def CheckAlias(Players,Alias): if not Alias in Players: raise ValueError('unknown alias '+Alias)
def ApplyVote(Players,Source,Target,Post): CheckAlias(Players,Source) CheckAlias(Players,Target) vote=Vote_t(Source,Target,Post) Players[Source].AddVoteAsSource(vote) Players[Target].AddVoteAsTarget(vote)
def ApplyUnvote(Players,Source,Target,Post): CheckAlias(Players,Source) CheckAlias(Players,Target) vote=Vote_t(Source,Target,Post) Players[Source].AddUnvoteAsSource(vote) Players[Target].AddUnvoteAsTarget(vote)
def ApplyUnvoteAll(Players,Source,Post): CheckAlias(Players,Source) for player in Players: ApplyUnvote(Players,Source,player,Post)
def GetDayNightStr(Day): dayInt=round(Day) dayDiff=Day-dayInt if abs(dayDiff)<0.1: return 'D'+str(dayInt) else: return 'N'+str(int(Day))
def GetLynchOrder(Players): lynchOrder=[] for alias in Players: if alias=='ham' or alias=='fil': continue if alias=='no': Players[alias]._SortValue=(-len(Players[alias]._NetVotesAsTarget), '~') else: Players[alias]._SortValue=(-len(Players[alias]._NetVotesAsTarget), Players[alias]._Name.lower()) lynchOrder+=[Players[alias]] lynchOrder.sort(key=lambda Player:Player._SortValue) return lynchOrder
def GetLynchPlayer(LynchOrder): numVotes=len(LynchOrder[0]._NetVotesAsTarget) for idx in range(1,len(LynchOrder)): player=LynchOrder[idx] if player._Alias=='no': continue if len(player._NetVotesAsTarget)==numVotes: return 'no' else: return LynchOrder[0]
def GetNameOrder(Players): nameOrder=[] for alias in Players: if alias=='ham' or alias=='fil' or alias=='no': continue nameOrder+=[Players[alias]] nameOrder.sort(key=lambda Player:Player._Name.lower()) return nameOrder
def Main(): # initialize day=None players={} players['no']=Player_t('No Lynch','no') players['ham']=Player_t('Hammer','ham') players['fil']=Player_t('Filibuster','fil') postMax=0 strikeCode='del' aligns={} # read input try: lineCount=0 while True: line=input() lineCount+=1 if not line: continue words=line.split(',') try: if words[0].startswith('d'): # d,DayName,DayNum,LastPost # add day info dayName=words[1] dayNum=int(words[2]) lastPost=int(words[3]) day=Day_t(dayName,dayNum,lastPost) elif words[0].startswith('p'): # p,Name,Alias[,Align] # add player to list, with align if known name=words[1] alias=words[2] if len(words)>=4: align=words[3] else: align=None players[alias]=Player_t(name,alias,align) elif words[0].startswith('v'): # v,Post,SourceAlias,TargetAlias(es),... # record vote post=int(words[1]) source=words[2] if len(words)<4: raise ValueError('Missing target') for idx in range(3,len(words)): target=words[idx] ApplyVote(players,source,target,post) if post>postMax: postMax=post elif words[0].startswith('u'): # u,Post,SourceAlias,TargetAlias(es),... # record unvote post=int(words[1]) source=words[2] if len(words)<4: raise ValueError('Missing target') for idx in range(3,len(words)): target=words[idx] if target=='all': ApplyUnvoteAll(players,source,post) else: ApplyUnvote(players,source,target,post) if post>postMax: postMax=post elif words[0].startswith('s'): # s,StrikethroughCode # set strike-through bb code, default is del strikeCode=words[1] elif words[0].startswith('a'): # a,Name,Alias,Color # set up alignment name=words[1] alias=words[2] color=words[3] aligns[alias]=Align_t(name,alias,color) else: raise ValueError('Unknown command '+words[0]) except (ValueError,IndexError): print('Error on line',lineCount,':',line) except EOFError: pass if not day: raise ValueError('Day not defined') if day._LastPost and postMax>day._LastPost: day._LastPost=postMax # check alignments are defined for player in players: players[player].CheckAlign(aligns) # do output output='' output+='[u]' if day._LastPost: output+='Current' else: output+='Final' output+=' Day '+day._Name+' Vote Count[/u]\n' # get lynch output+='\n' lynchOrder=GetLynchOrder(players) lynchPlayer=GetLynchPlayer(lynchOrder) if lynchPlayer=='no': lynchName='no one' else: lynchName='[b]'+lynchPlayer._Name+'[/b]' if day._LastPost: if players['ham']._NetVotesAsTarget: output+=players['ham'].StrVotesAsTarget(players,strikeCode,aligns) if players['fil']._NetVotesAsTarget: output+=players['fil'].StrVotesAsTarget(players,strikeCode,aligns) if (players['ham']._NetVotesAsTarget or players['fil']._NetVotesAsTarget): output+='\n' output+=('Given these votes as of Post '+str(day._LastPost)+', ' +lynchName+' will be lynched.\n') else: output+='With these votes, '+lynchName+' was lynched.\n' # votes on players output+='\n' for player in lynchOrder: output+=player.StrVotesAsTarget(players,strikeCode,aligns) # votes by players output+='\n' nameOrder=GetNameOrder(players) for player in nameOrder: output+=player.StrVotesAsSource(players,strikeCode,aligns) # alignment legend output+='\n' for align in aligns: output+=aligns[align].StrLegend() print(output)
if __name__=='__main__': # multiprocessing.freeze_support() Main()
# -- VoteCount.py
|
|
|
Post by Pleonast on Dec 16, 2013 8:42:46 GMT -8
d,One,1,108 s,s
p,Meeko,meek p,Sister Coyote,sis p,swammerdami,swam p,gnarlycharlie,gnarl p,silverjan,jan p,Captain Klutz,capt p,guiri,gui p,texcat,tex p,patricia,pat p,Chameleon,cham p,Colby11,colb p,storyteller0910,story p,Mahaloth,mah p,BillMc,bill
v,5,tex,mah v,17,gui,bill v,20,swam,no v,21,mah,swam v,22,gnarl,capt v,23,pat,swam u,26,capt,all v,26,capt,story v,27,cham,tex,gui,gnarl v,28,meek,cham v,30,jan,capt v,33,swam,mah,pat v,37,swam,jan u,38,gnarl,capt v,38,gnarl,jan v,39,colb,jan u,40,cham,gnarl u,42,jan,capt v,42,jan,gnarl v,49,tex,cham v,62,sis,no u,64,capt,story v,64,capt,cham u,69,swam,jan v,69,swam,cham v,75,capt,pat,meek u,75,capt,cham v,81,bill,no u,84,cham,all v,84,cham,no v,86,story,sis u,90,story,sis v,101,mah,bill,sis,cham v,102,mah,gui u,106,gui,bill v,106,gui,pat
|
|
|
Post by Pleonast on Dec 23, 2013 7:40:25 GMT -8
d,Two,2,0 s,s
p,Meeko,meek p,Sister Coyote,sis p,swammerdami,swam p,gnarlycharlie,gnarl p,silverjan,jan p,Captain Klutz,capt p,guiri,gui p,texcat,tex p,storyteller0910,story p,Mahaloth,mah p,BillMc,bill
v,8,capt,mah v,20,jan,gnarl u,23,jan,gnarl v,23,jan,sis v,25,swam,gnarl,mah u,39,swam,mah v,42,gui,mah v,47,swam,tex v,51,mah,bill v,55,bill,story v,56,gui,story v,58,swam,story u,58,swam,tex v,59,meek,story v,60,tex,story u,66,capt,mah v,66,capt,story v,68,story,bill u,70,jan,sis v,70,jan,story v,75,gnarl,story v,77,sis,story v,79,capt,meek
|
|
|
Post by Pleonast on Dec 31, 2013 16:35:48 GMT -8
d,Three,3,0 s,s
p,Meeko,meek p,Sister Coyote,sis p,silverjan,jan p,Captain Klutz,capt p,guiri,gui p,texcat,tex p,Mahaloth,mah p,BillMc,bill
v,23,gui,sis v,25,jan,sis v,40,mah,meek v,41,meek,mah v,47,capt,sis v,53,sis,capt u,67,capt,sis v,67,capt,meek v,69,meek,capt u,69,meek,mah v,79,tex,sis u,86,capt,meek v,89,bill,tex u,95,sis,all u,98,gui,sis
|
|