
* Updated tests, banned type decls and toplevel letvals * Properly ban nested contracts * Fix including by path * Fix error message test * Fix prettpr attr display. Make dialyzer happy * More tests * Fixed type printing * Updated docs
85 lines
2.5 KiB
Plaintext
85 lines
2.5 KiB
Plaintext
contract Voting =
|
|
|
|
// Types
|
|
record proposal =
|
|
{ name : string
|
|
, voteCount : uint
|
|
}
|
|
|
|
datatype vote = NotVoted | Voted(int) | Delegated(address)
|
|
|
|
record voter =
|
|
{ weight : int
|
|
, vote : vote
|
|
}
|
|
|
|
record state =
|
|
{ chairPerson : address
|
|
, voters : map(address, voter)
|
|
, proposals : list(proposal)
|
|
}
|
|
|
|
// Initialization
|
|
function init(proposalNames: list(string)): state =
|
|
{ chairPerson = caller(),
|
|
voters = Map.empty,
|
|
proposals = MyList.map((name) => {name = name, voteCount = 0}, proposalNames) }
|
|
|
|
function initVoter() = { weight = 1, vote = NotVoted}
|
|
|
|
function giveRightToVote(voter: address) =
|
|
require(caller() == state.chairPerson)
|
|
require(!Map.mem(voter, state.voters))
|
|
put(state{ voters = Map.add(voter, initVoter(), state.voters) })
|
|
|
|
function delegateChain(delegate: address) =
|
|
require(delegate != caller()) /* Delegation loop! */
|
|
let voter = Map.find(delegate, state.voters)
|
|
switch(voter.vote)
|
|
Delegated(d) => delegateChain(d)
|
|
_ => delegate
|
|
|
|
function addVote(candidate, weight) =
|
|
let proposal = MyList.nth(state.proposals, candidate)
|
|
proposal{ voteCount = proposal.voteCount + weight }
|
|
|
|
function delegateVote(delegateTo: address, weight: uint) =
|
|
let voter = Map.find(delegateTo, state.voters)
|
|
switch(voter.vote)
|
|
Voted(vote) => addVote(vote, weight)
|
|
Delegated(_) => abort("impossible") // impossible
|
|
NotVoted => voter{ weight = voter.weight + weight }
|
|
|
|
function delegate(delegateTo: address) =
|
|
require(delegateTo != caller())
|
|
let voter = Map.find(caller(), state.voters)
|
|
require(voter.vote == NotVoted)
|
|
let finalDelegate = delegateChain(delegateTo)
|
|
let voter' = voter{ vote = Delegated(finalDelegate) }
|
|
delegateVote(finalDelegate, voter.weight)
|
|
|
|
function vote(candidate: uint) =
|
|
let voter = Map.find(caller(), state.voters)
|
|
require(voter.vote == NotVoted)
|
|
let voter' = voter{ vote = Voted(candidate) }
|
|
addVote(candidate, voter.weight)
|
|
|
|
function winningProposal'(current, rest) =
|
|
switch(rest)
|
|
[] => current
|
|
p :: ps => winningProposal'(if (p.voteCount > current.voteCount) p else current, ps)
|
|
|
|
// const
|
|
function winningProposal() : proposal =
|
|
switch(state.proposals)
|
|
[] => abort("none")
|
|
p :: ps => winningProposal'(p, ps)
|
|
|
|
// const
|
|
function winnerName() = winningProposal().name
|
|
|
|
// const
|
|
function currentTally() =
|
|
MyList.map((p) => (p.name, p.voteCount), state.proposals)
|
|
|