pragma solidity ^0.4.24; contract Votacion { modifier onlyOwner() { require(isOwner(msg.sender)); _; } uint public voteStartTime; uint public voteEndTime; uint16 private voterCount; string public votingTitle; address public owner; uint16 public accountedVotes; uint16 public nulledVotes; uint16 public votesRemaining; event Voted (bytes24 _token); event newVoterId (uint _voterId); event voteAccounted (bytes32 _candidateName, uint _votesReceived, uint16 _totalVotesAccounted); event voteNulled (uint16 _voterId, uint16 _totalVotesAccounted); mapping (bytes32 => uint16) private votesReceived; mapping (bytes32 => bool) public votesCasted; mapping (uint8 => string) public candidateNames1; mapping (uint8 => string) public candidateNames2; mapping (uint16 => string) public voterIndex; mapping (string => bool) internal voterIds; bytes32[] private candidateList1; bytes32[] private candidateList2; struct Counter { uint16 countStart; uint16 countEnd; uint16 countLimit; uint16 accountedVotes; uint16 nulledVotes; bytes32 candidate1; bytes32 candidate2; } constructor (bytes32[] _candidateList1, bytes32[] _candidateList2, string _votingTitle, uint _startTime, uint _endTime) public { owner = msg.sender; voterCount = 0; candidateList1 = _candidateList1; candidateList2 = _candidateList2; voteStartTime = _startTime; voteEndTime = _endTime; votingTitle = _votingTitle; nulledVotes = 0; accountedVotes = 0; for (uint8 i = 0; i < _candidateList1.length; i++){ candidateNames1[i] = bytes32ToString(_candidateList1[i]); candidateNames2[i] = bytes32ToString(_candidateList2[i]); } } function allCandidates() external view returns (bytes32[] candidates1, bytes32[] candidates2) { candidates1 = candidateList1; candidates2 = candidateList2; } function isOwner(address addr) view public returns(bool) { return addr == owner; } function countVotes() external onlyOwner { require(votingEnded()); require(votesRemaining > 0); Counter memory counter = Counter((((nulledVotes + accountedVotes) / 2 ) + 1), 0, 0, accountedVotes, nulledVotes, 0x0, 0x0); if (votesRemaining < 100){ counter.countLimit = votesRemaining; }else{ counter.countLimit = 100; } counter.countEnd = (counter.nulledVotes / 2) + (counter.accountedVotes / 2) + counter.countLimit; for (uint16 i = counter.countStart; i <= counter.countEnd; i++){ counter.candidate1 = checkVote(i); counter.candidate2 = checkVote2(i); if (counter.candidate1 == 0x0000000000000000000000000000000000000000000000000000000000000000) { counter.nulledVotes += 1; emit voteNulled(i, counter.nulledVotes); }else{ votesReceived[counter.candidate1] += 1; counter.accountedVotes += 1; emit voteAccounted(counter.candidate1, votesReceived[counter.candidate1], counter.accountedVotes); } if (counter.candidate2 == 0x0000000000000000000000000000000000000000000000000000000000000000) { counter.nulledVotes += 1; emit voteNulled(i, counter.nulledVotes); }else{ votesReceived[counter.candidate2] += 1; counter.accountedVotes += 1; emit voteAccounted(counter.candidate2, votesReceived[counter.candidate2], counter.accountedVotes); } } votesRemaining -= counter.countLimit; accountedVotes = counter.accountedVotes; nulledVotes = counter.nulledVotes; } function isUniqueId(string voterId) internal view returns (bool exists){ return voterIds[voterId]; } function newVoter(string voterId) external onlyOwner { require (!isUniqueId(voterId)); voterIds[voterId] = true; voterCount += 1; voterIndex[voterCount] = voterId; votesRemaining += 1; emit newVoterId(voterCount); } function queryVote(string voterId) public view returns (string candidate1, string candidate2) { for (uint8 x = 0; x < candidateList1.length; x++){ if (votesCasted[keccak256(abi.encodePacked(voterId, candidateNames1[x]))] == true){ candidate1 = candidateNames1[x]; } } for (uint8 y = 0; y < candidateList2.length; y++){ if (votesCasted[keccak256(abi.encodePacked(voterId, candidateNames2[y]))] == true){ candidate2 = candidateNames2[y]; } } } function checkVote(uint16 voterNumber) internal view returns (bytes32) { for (uint8 x = 0; x < candidateList1.length; x++){ if (votesCasted[keccak256(abi.encodePacked(voterIndex[voterNumber], candidateNames1[x]))] == true){ return candidateList1[x]; } } } function checkVote2(uint16 voterNumber) internal view returns (bytes32) { for (uint8 x = 0; x < candidateList2.length; x++){ if (votesCasted[keccak256(abi.encodePacked(voterIndex[voterNumber], candidateNames2[x]))] == true){ return candidateList2[x]; } } } function readVoterCount() external view onlyOwner returns (uint){ return voterCount; } function bytes32ToString(bytes32 x) internal pure returns (string) { bytes memory bytesString = new bytes(32); uint charCount = 0; for (uint j = 0; j < 32; j++) { byte char = byte(bytes32(uint(x) * 2 ** (8 * j))); if (char != 0) { bytesString[charCount] = char; charCount++; } } bytes memory bytesStringTrimmed = new bytes(charCount); for (j = 0; j < charCount; j++) { bytesStringTrimmed[j] = bytesString[j]; } return string(bytesStringTrimmed); } function stringToBytes32(string memory source) internal pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(source); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(source, 32)) } } function totalVotesFor(string candidate) external view returns (uint16) { require(votingEnded()); return votesReceived[stringToBytes32(candidate)]; } function voteForOption(bytes32 hashedVote1, bytes32 hashedVote2, bytes24 votedFlag) external onlyOwner { require(now >= voteStartTime); require(now <= voteEndTime); votesCasted[hashedVote1] = true; votesCasted[hashedVote2] = true; emit Voted(votedFlag); } function votingStarted() external view returns (bool) { return now > voteStartTime; } function votingEnded() public view returns (bool) { return now > voteEndTime; } function votingStatus() external view returns (bool) { return (now > voteStartTime) != (now > voteEndTime); } }
0.4.24