Commit 538ce78e 538ce78e9497d4c2654fc45ac40340ec1156b913 by Vincent Peybernes

Specify and implement election structure.

1 parent 0a873941
...@@ -10,12 +10,14 @@ ...@@ -10,12 +10,14 @@
10 * 10 *
11 * @constructor 11 * @constructor
12 * @property {Candidate[]} candidateList 12 * @property {Candidate[]} candidateList
13 * @property {String[]} votes
13 * @property {Number} numberOfCandidates 14 * @property {Number} numberOfCandidates
14 * 15 *
15 */ 16 */
16 function RelativePlacement() { 17 function RelativePlacement() {
17 Object.defineProperties(this, { 18 Object.defineProperties(this, {
18 candidateList: {value: {}}, 19 candidateList: {value: {}},
20 votes: {value: []},
19 numberOfCandidates: {get: () => Object.keys(this.candidateList).length} 21 numberOfCandidates: {get: () => Object.keys(this.candidateList).length}
20 }); 22 });
21 } 23 }
...@@ -43,15 +45,50 @@ ...@@ -43,15 +45,50 @@
43 } 45 }
44 }; 46 };
45 47
46 RelativePlacement.prototype.addVote = function () {}; 48 /**
49 * @name addVote
50 * @param {String[]} vote
51 * @methodOf RelativePlacement
52 * @this RelativePlacement
53 */
54 RelativePlacement.prototype.addVote = function (vote) {
55 if(vote.length != this.numberOfCandidates)
56 throw new Error('The vote and the candidate list have not the same size.');
57
58 var candidates = Object.keys(this.candidateList);
59 var controlMask = Math.pow(2,candidates.length)-1;
60 var checkMask = 0;
61
62 for(let i = 0; i < vote.length; i++){
63 var index = candidates.indexOf(vote[i]);
64 if(index == -1) throw new Error('The candidate "'+vote[i]+"' is not present in candidate list.");
65 checkMask |= Math.pow(2, index);
66 }
67
68 if(checkMask != controlMask) throw new Error('Candidate must be unique in each vote.');
69
70 this.votes.push(vote);
71 for(let i = 0; i < vote.length; i++){
72 let candidate = this.candidateList[vote[i]];
73 candidate.votes.push(i);
74 }
75 };
47 RelativePlacement.prototype.addVotes = function () {}; 76 RelativePlacement.prototype.addVotes = function () {};
48 RelativePlacement.prototype.getResult = function () {}; 77 RelativePlacement.prototype.getResult = function () {};
49 78
79 /**
80 *
81 * @param name
82 * @constructor
83 * @property {String} name
84 * @property {Number[]} votes
85 * @property {Number[]} placements
86 */
50 function Candidate(name) { 87 function Candidate(name) {
51 Object.defineProperties(this, { 88 Object.defineProperties(this, {
52 name: {value: name, enumerable: true}, 89 name: {value: name, enumerable: true},
53 votes: {value:[], enumerable: true}, 90 votes: {value:[], enumerable: true},
54 placement: {value:[], enumerable: false} 91 placements: {value:[], enumerable: true, writable: true}
55 }); 92 });
56 } 93 }
57 94
......
...@@ -32,9 +32,9 @@ describe('RelativePlacement', () => { ...@@ -32,9 +32,9 @@ describe('RelativePlacement', () => {
32 assert.equal(1, election.numberOfCandidates); 32 assert.equal(1, election.numberOfCandidates);
33 assert.deepEqual({ 33 assert.deepEqual({
34 name: 'foo', 34 name: 'foo',
35 votes:[] 35 votes:[],
36 placements: []
36 }, election.candidateList['foo']); 37 }, election.candidateList['foo']);
37 assert.deepEqual([], election.candidateList['foo'].placement);
38 }); 38 });
39 39
40 it('should add some candidates', () => { 40 it('should add some candidates', () => {
...@@ -44,16 +44,86 @@ describe('RelativePlacement', () => { ...@@ -44,16 +44,86 @@ describe('RelativePlacement', () => {
44 44
45 assert.deepEqual({ 45 assert.deepEqual({
46 name: 'foo', 46 name: 'foo',
47 votes:[] 47 votes:[],
48 placements: []
48 }, election.candidateList['foo']); 49 }, election.candidateList['foo']);
49 assert.deepEqual({ 50 assert.deepEqual({
50 name: 'bar', 51 name: 'bar',
51 votes:[] 52 votes:[],
53 placements: []
52 }, election.candidateList['bar']); 54 }, election.candidateList['bar']);
53 }); 55 });
54 56
55 it('should not add a same candidate multiple time', () => { 57 it('should not add a same candidate multiple time', () => {
58 assert.equal(0, election.numberOfCandidates);
59 election.addCandidate('foo');
60 assert.equal(1, election.numberOfCandidates);
61 assert.throws(()=>{
62 election.addCandidate('foo');
63 }, (err) => {
64 return err instanceof Error && /already exist/.test(err.message);
65 },
66 'unexpected error'
67 );
68 assert.equal(1, election.numberOfCandidates);
69 });
70 });
71
72 describe('Add votes', () => {
73 var election;
74
75 beforeEach(()=> {
76 election = new RelativePlacement();
77 election.addCandidates(['A','B','C']);
78 });
79
80 it('should add a vote to each candidates', () => {
81 var vote = ['A','B','C'];
82 election.addVote(['A','B','C']);
83 for(let i = 0; i < vote.length; i++){
84 let candidate = election.candidateList[vote[i]];
85 assert.equal(candidate.votes.length, 1, 'number of candidates vote');
86 assert.equal(candidate.votes[0], i, 'value of candidates vote');
87 }
88 });
89
90 it('should has same sizes between candidate list and vote', () => {
91 assert.throws(() => {
92 election.addVote(['A','B']);
93 },
94 err => err instanceof Error && /same size/.test(err.message),
95 'smaller vote'
96 );
97 assert.equal(election.votes.length, 0, 'no vote registered');
98 assert.equal(election.candidateList['A'].votes.length, 0, 'no vote registered in candidate');
99
100 assert.throws(() => {
101 election.addVote(['A','B','C','D']);
102 },
103 err => err instanceof Error && /same size/.test(err.message),
104 'bigger vote'
105 );
106 assert.equal(election.votes.length, 0, 'no vote registered');
107 assert.equal(election.candidateList['A'].votes.length, 0, 'no vote registered in candidate');
108 });
109
110 it('should not has unknown candidate in vote', () => {
111 assert.throws(() => {
112 election.addVote(['A','B','D']);
113 },
114 err => err instanceof Error && /not present/.test(err.message));
115
116 assert.equal(election.votes.length, 0, 'no vote registered');
117 assert.equal(election.candidateList['A'].votes.length, 0, 'no vote registered in candidate');
118 });
56 119
120 it('should has an unique vote by candidate', () => {
121 assert.throws(() => {
122 election.addVote(['A','B','A']);
123 },
124 err => err instanceof Error && /unique/.test(err.message));
125 assert.equal(election.votes.length, 0, 'no vote registered');
126 assert.equal(election.candidateList['A'].votes.length, 0, 'no vote registered in candidate');
57 }); 127 });
58 }); 128 });
59 }); 129 });
...\ No newline at end of file ...\ No newline at end of file
......
1 [ 1 [
2 { 2 {
3 "comment": "The most fundamentally",
4 "votes":{
5 "A": [1,1,1],
6 "B": [2,2,2],
7 "C": [3,3,3]
8 },
9 "result": ["A","B","C"]
10 },
11 {
3 "votes":{ 12 "votes":{
4 "320": [1,1,1,1,1], 13 "320": [1,1,1,1,1],
5 "284": [2,4,2,4,3], 14 "284": [2,4,2,4,3],
......