// ------------------------------------------------------------------------------
// This file is part of netvote.
//
// netvote 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.
//
// netvote 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.
//
// You should have received a copy of the GNU General Public License
// along with solidity. If not, see
//
// (c) 2017 netvote contributors.
//------------------------------------------------------------------------------
pragma solidity ^0.4.17;
import "../../lib/Bytes32Set.sol";
import "../links/PoolRegistry.sol";
import "./TieredElection.sol";
import "./TieredPool.sol";
import "../BaseBallot.sol";
/**
* @title TieredBallot
* @dev A tiered ballot represents one instance of a ballot in a tiered eleciton.
* This allows one to partition pools into groups for the purposes of separating votes.
*/
contract TieredBallot is BaseBallot, PoolRegistry {
using Bytes32Set for Bytes32Set.SetData;
// events for subscribing to this ballot
event BallotVote(address pool, bytes32 voteId);
// default group (popular vote)
bytes32 constant GROUP_ALL = "ALL";
// configuration
Bytes32Set.SetData groupSet;
mapping (bytes32 => AddressSet.SetData) groupPoolSet;
mapping (address => Bytes32Set.SetData) poolGroupSet;
address public election;
// state
// map of voters to prevent duplicates
mapping (bytes32 => bool) voterVoted;
// pools to the list of voters
mapping (address => bytes32[]) poolVoters;
function TieredBallot(address electionAddress, address ownerAddress, string location) BaseBallot(ownerAddress, location) public {
require(electionAddress != address(0));
election = electionAddress;
groupSet.put(GROUP_ALL);
}
modifier validPool() {
require(poolSet.contains(msg.sender));
_;
}
function groupPoolCount(bytes32 group) constant public returns (uint256) {
return groupPoolSet[group].size();
}
function getGroupPool(bytes32 group, uint256 index) constant public returns (address) {
return groupPoolSet[group].getAt(index);
}
function getPoolVoterCount(address pool) constant public returns(uint256) {
return poolVoters[pool].length;
}
// gets voter address by pool and index (for iteration)
function getPoolVoter(address pool, uint256 i) constant public returns(bytes32) {
return poolVoters[pool][i];
}
// adds a pool to the ballot
function addPool(address p) public building admin {
poolSet.put(p);
addPoolToGroup(p, GROUP_ALL);
}
function checkElection() public constant returns (bool) {
return election != address(0) && TieredElection(election).ballotExists(this);
}
function checkPools() public constant returns (bool) {
// there must be at least one pool set
if (poolSet.size() == 0) {
return false;
}
for (uint256 i = 0; i