relative-placement.js 2.94 KB
/**
 * Created by Techniv on 30/11/2016.
 */
(function (define) {
    // TODO define exhaustive module platform
    module.exports = define();
})(function(){

    /**
     *
     * @constructor
     * @property {Candidate[]} candidateList
     * @property {String[]} votes
     * @property {Number} numberOfCandidates
     *
     */
    function RelativePlacement() {
        Object.defineProperties(this, {
            candidateList:      {value: {}},
            votes:              {value: []},
            numberOfCandidates: {get: () => Object.keys(this.candidateList).length}
        });
    }

    /**
     * @name addCandidate
     * @param {String} candidateName
     * @methodOf RelativePlacement
     * @this RelativePlacement
     */
    RelativePlacement.prototype.addCandidate = function addCandidate(candidateName){
        if(this.candidateList[candidateName]) throw new Error('"' +candidateName+ '" already exist in candidate list.');
        this.candidateList[candidateName] = new Candidate(candidateName);
    };

    /**
     * @name addCandidates
     * @param {String[]} candidateNames
     * @methodOf RelativePlacement
     * @this RelativePlacement
     */
    RelativePlacement.prototype.addCandidates = function (candidateNames) {
        for(let i = 0; i < candidateNames.length; i++){
            this.addCandidate(candidateNames[i]);
        }
    };

    /**
     * @name addVote
     * @param {String[]} vote
     * @methodOf RelativePlacement
     * @this RelativePlacement
     */
    RelativePlacement.prototype.addVote = function (vote) {
        if(vote.length != this.numberOfCandidates)
            throw new Error('The vote and the candidate list have not the same size.');

        var candidates = Object.keys(this.candidateList);
        var controlMask = Math.pow(2,candidates.length)-1;
        var checkMask = 0;

        for(let i = 0; i < vote.length; i++){
            var index = candidates.indexOf(vote[i]);
            if(index == -1) throw new Error('The candidate "'+vote[i]+"' is not present in candidate list.");
            checkMask |= Math.pow(2, index);
        }

        if(checkMask != controlMask) throw new Error('Candidate must be unique in each vote.');

        this.votes.push(vote);
        for(let i = 0; i < vote.length; i++){
            let candidate = this.candidateList[vote[i]];
            candidate.votes.push(i);
        }
    };
    RelativePlacement.prototype.addVotes = function () {};
    RelativePlacement.prototype.getResult = function () {};

    /**
     *
     * @param name
     * @constructor
     * @property {String} name
     * @property {Number[]} votes
     * @property {Number[]} placements
     */
    function Candidate(name) {
        Object.defineProperties(this, {
            name:       {value: name,   enumerable: true},
            votes:      {value:[],      enumerable: true},
            placements: {value:[],      enumerable: true, writable: true}
        });
    }

    return RelativePlacement;
});