Post by Pleonast on Jan 25, 2013 14:54:20 GMT -8
My vote code. Be sure to quote to see the proper indentations.
# -- VoteCount.py -- 8 Feb 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._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._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 not numVotes:
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 not numVotes:
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':
break
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