diff --git a/src/Ballot.sol b/src/Ballot.sol
index 637b4d982d21b4b2c01bec74188d5c6d11e93937..14cb9c0f0404daefc1dd6362685afe3f688fe423 100644
--- a/src/Ballot.sol
+++ b/src/Ballot.sol
@@ -1,139 +1,138 @@
-pragma solidity ^0.4.11;
+// Basado en https://soliditycookbook.com/voting
+// vim:syntax:filetype=javascript:ai:sm
+// vim:expandtab:backspace=indent,eol,start:softtabstop=4
+pragma solidity ^0.4.25;
 
 /// @title Voting with delegation.
-contract Ballot {
+contract            Ballot      {
     // This declares a new complex type which will
     // be used for variables later.
     // It will represent a single voter.
-    struct Voter {
-        uint weight; // weight is accumulated by delegation
-        bool voted;  // if true, that person already voted
-        address delegate; // person delegated to
-        uint vote;   // index of the voted proposal
+    struct          Voter       {
+        address     voter;
+        int         vote;       // index of the voted proposal or -1 if not voted
     }
-
     // This is a type for a single proposal.
-    struct Proposal {
-        bytes32 name;   // short name (up to 32 bytes)
-        uint voteCount; // number of accumulated votes
+    struct          Proposal    {
+        bytes32     name;       // short name (up to 32 bytes)
+        uint        voteCount;  // number of accumulated votes
+    }
+    struct          Votingrules  {
+        string      title;
+        address     chairman;
+        uint        voteAtOrAfter;
+        uint        voteAtOrBefore;
+        // Which percentage of the registered voters must
+        // vote in order for the vote to be considered valid.
+        // e.g. 0.0
+        float       percentOfRegisteredVotersReqToBeValid;
+        // Which percentage of the cast votes are required
+        // for the motion/title to pass?
+        // MAJORITY VOTE:
+        //   specify 50.00000000001
+        // TWO-THIRDS:
+        //   specify 67.77777777777
+        float       percentOfVotesCastToWin;
+        // Counting registered voters who do not vote as blank
+        // votes, has the effect that it is more difficult
+        // to acquire the desired votes.
+        bool        countNonvotesAsBlanks;
     }
 
-    address public chairperson;
-
-    // This declares a state variable that
-    // stores a `Voter` struct for each possible address.
-    mapping(address => Voter) public voters;
-
-    // A dynamically-sized array of `Proposal` structs.
-    Proposal[] public proposals;
+    Votingrules                     public  rules;
+    mapping( address => int )       public  voterMap;
+    Voter[]                         public  voterList;
+    uint                            public  numvoters;
+    Proposal[]                      public  proposalList;
+    uint                            public  numproposals;
 
     /// Create a new ballot to choose one of `proposalNames`.
-    function Ballot(bytes32[] proposalNames) {
-        chairperson = msg.sender;
-        voters[chairperson].weight = 1;
+    constructor(
+        string      ballotTitle,
+        uint        voteAtOrAfter,
+        uint        voteAtOrBefore,
+        float       percentOfRegisteredVotersReqToBeValid,
+        float       percentOfVotesCastToWin,
+        bool        countNonvotesAsBlanks,
+        bytes32[]   proposalNames
+    ) {
+        require( voteAtOrBefore > now );
+        // chairman can not automatically vote. Chairman must
+        // giveRightToVote to himself if he wants to vote.
+        rules.chairman                                  =   msg.sender;
+        rules.title                                     =   ballotTitle;
+        rules.voteAtOrAfter                             =   voteAtOrAfter;
+        rules.voteAtOrBefore                            =   voteAtOrBefore;
+        rules.percentOfRegisteredVotersReqToBeValid     =   percentOfRegisteredVotersReqToBeValid,
+        rules.percentOfVotesCastToWin                   =   percentOfVotesCastToWin,
+        rules.countNonvotesAsBlanks                     =   countNonvotesAsBlanks,
 
         // For each of the provided proposal names,
         // create a new proposal object and add it
         // to the end of the array.
-        for (uint i = 0; i < proposalNames.length; i++) {
-            // `Proposal({...})` creates a temporary
-            // Proposal object and `proposals.push(...)`
-            // appends it to the end of `proposals`.
-            proposals.push(Proposal({
-                name: proposalNames[i],
-                voteCount: 0
-            }));
+        numproposals                        =   proposalNames.length;
+        int         i                       =   0;
+        while ( i < numproposals )
+        {
+            Proposal    newprop;
+            newprop.name                    =   proposalNames[i];
+            newprop.voteCount               =   0;
+            proposalList.push( newprop );
+            i++;
         }
     }
 
     // Give `voter` the right to vote on this ballot.
-    // May only be called by `chairperson`.
-    function giveRightToVote(address voter) {
-        // If the argument of `require` evaluates to `false`,
-        // it terminates and reverts all changes to
-        // the state and to Ether balances. It is often
-        // a good idea to use this if functions are
-        // called incorrectly. But watch out, this
-        // will currently also consume all provided gas
-        // (this is planned to change in the future).
-        require((msg.sender == chairperson) && !voters[voter].voted && (voters[voter].weight == 0));
-        voters[voter].weight = 1;
-    }
-
-    /// Delegate your vote to the voter `to`.
-    function delegate(address to) {
-        // assigns reference
-        Voter storage sender = voters[msg.sender];
-        require(!sender.voted);
-
-        // Self-delegation is not allowed.
-        require(to != msg.sender);
-
-        // Forward the delegation as long as
-        // `to` also delegated.
-        // In general, such loops are very dangerous,
-        // because if they run too long, they might
-        // need more gas than is available in a block.
-        // In this case, the delegation will not be executed,
-        // but in other situations, such loops might
-        // cause a contract to get "stuck" completely.
-        while (voters[to].delegate != address(0)) {
-            to = voters[to].delegate;
-
-            // We found a loop in the delegation, not allowed.
-            require(to != msg.sender);
-        }
-
-        // Since `sender` is a reference, this
-        // modifies `voters[msg.sender].voted`
-        sender.voted = true;
-        sender.delegate = to;
-        Voter storage delegate = voters[to];
-        if (delegate.voted) {
-            // If the delegate already voted,
-            // directly add to the number of votes
-            proposals[delegate.vote].voteCount += sender.weight;
-        } else {
-            // If the delegate did not vote yet,
-            // add to her weight.
-            delegate.weight += sender.weight;
-        }
-    }
-
-    /// Give your vote (including votes delegated to you)
-    /// to proposal `proposals[proposal].name`.
-    function vote(uint proposal) {
-        Voter storage sender = voters[msg.sender];
-        require(!sender.voted);
-        sender.voted = true;
-        sender.vote = proposal;
-
-        // If `proposal` is out of the range of the array,
-        // this will throw automatically and revert all
-        // changes.
-        proposals[proposal].voteCount += sender.weight;
+    function giveRightToVote( address voter )
+    {
+        // May only be called by chairman.
+        require( msg.sender == chairman );
+        require( voteAtOrBefore <= now  );
+        uint        idx                     =   voterMap[voter];
+        // Can't add voters more than once.
+        require( idx == 0 );
+        // Not even the voter listed in [0].
+        if ( voterList.length > 0 )
+            require( voterList[0].voter != voter );
+        // If the voter's address doesn't match, it is because
+        // he doesn't exist (and then we always have idx=0).
+        // So we push him onto the voterList.
+        Voter       newvoter;
+        newvoter.voter                      =   voter;
+        newvoter.vote                       =   -1;
+        idx                                 =   voterList.push( newvoter ) - 1;
+        voterMap[voter]                     =   idx;
+        numvoters++;
     }
 
-    /// @dev Computes the winning proposal taking all
-    /// previous votes into account.
-    function winningProposal() constant
-            returns (uint winningProposal)
+    function getVoterIdx( address voter )
+        readonly
+        returns int
     {
-        uint winningVoteCount = 0;
-        for (uint p = 0; p < proposals.length; p++) {
-            if (proposals[p].voteCount > winningVoteCount) {
-                winningVoteCount = proposals[p].voteCount;
-                winningProposal = p;
-            }
-        }
+        int         idx                     =   voterMap[voter];
+        if ( idx > 0 )
+            return idx;
+        if ( voterList[0].voter == voter )
+            return 0;
+        return -1;
     }
 
-    // Calls winningProposal() function to get the index
-    // of the winner contained in the proposals array and then
-    // returns the name of the winner
-    function winnerName() constant
-            returns (bytes32 winnerName)
+    /// Give your vote to proposal `proposals[proposal].name`.
+    function vote( uint proposal )
     {
-        winnerName = proposals[winningProposal()].name;
+        require( proposal < numproposals        );
+        require( rules.voteAtOrAfter  >= now    );
+        require( rules.voteAtOrBefore <= now    );
+        int         idx                     =   getVoterIdx( msg.sender );
+        require( idx > -1 );
+        int         formervote              =   voterList[idx].vote;
+        require( formervote != int(proposal) );
+        if ( formervote > -1 )
+        {
+            // He changed his vote - this is normal for politicians, too.
+            proposals[ uint(formervote) ].voteCount--;
+        }
+        proposals[ proposal  ].voteCount++;
+        voterList[ uint(idx) ].vote         =   uint(proposal);
     }
 }