diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..61679f2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,2 @@ +{"editor.minimap.enabled": false +} \ No newline at end of file diff --git a/election-part2.js b/election-part2.js index 464babb..9a26fe6 100644 --- a/election-part2.js +++ b/election-part2.js @@ -1,43 +1,169 @@ // Importing the functions from what you did in part 1. -const { - candidatesObjToArray, - filterInvalidVoters, - runElection, - getWinner, - winnerMessage, -} = require('./election'); +// const { +// candidatesObjToArray, +// filterInvalidVoters, +// runElection, +// getWinner, +// winnerMessage, +// } = require('./election'); +function candidatesObjToArray(candidates) { + var arrOfKeys = Object.keys(candidates); + var arrOfCandidates = arrOfKeys.map(function (key) { return candidates[key] }); + return arrOfCandidates; +} /** - * 1 - Write a Voter class modelling a member of the population who votes in the election. + * 2 - Remove any voters who have voted for more than 2 people, or have voted for the same person twice. +*/ +function filterInvalidVoters(allVoters) { + const filteredByLength = allVoters.filter(item => item.votingCard.length < 3); + const filteredByClash = filteredByLength.filter(item => item.votingCard[0] !== item.votingCard[1]) + return filteredByClash; +} +/** + * 3 - Add up all the votes cast by the voting population. Note that for two adjacent votes in the vote array, + * the right vote counts for half of the left vote. */ - - +//refactored Version of runElection +function runElection(validVoters, candidates) { + for (let i = 0; i < candidates.length; i++) { + validVoters.forEach(function (item) { + //console.log(can); + if (item.votingCard[0] === i) { + candidates[i].numVotes += 1 + } + if (item.votingCard[1] === i) + candidates[i].numVotes += 0.5; + }) + } + return candidates; +} +/** + * 4 - After an election has been run, return the winner + * + * Desired return value: {name: "Tamara Faiza", age: 46, party: "Pizza Party", numVotes: 3} + */ +function getWinner(candidates) { + candidates.sort(function(a,b) {return b.numVotes-a.numVotes}) + //check if two candidates have the same numVotes we have to return null-draw + if (candidates[0].numVotes===candidates[1].numVotes) {return null;} + return candidates[0]; //Hila Waraich won with 26.5 votes +} +/** + * 5 - Return a message including the name of the winner, and how many votes + * he/she received + */ +function winnerMessage(winner) { + var winner = getWinner(candidates) + if (winner !== null) { + var mes = winner.name + " has won the election with " + winner.numVotes + " votes!"; + return mes; + } + else return "The election was a draw"; +} + +/* 1 - Write a Voter class modelling a member of the population who votes in the election. +*/ +class Voter { + constructor(name, age, votingCard) { + this.name = name; + this.age = age; + this.votingCard = votingCard; + } +} +let votingPopulation = [ + new Voter('Jane Finnegan', 19, [1, 3]), + new Voter('Norman Beracha', 35, [3, 4]), + new Voter('Salome Kadek', 22, [2, 1, 3]), + new Voter('Wei Li', 19, [1, 2]), + new Voter('Sam MacKinnon', 59, [1, 4]) +] /** * 2 - Write a Candidate class modelling a candidate in the election. Candidates are also voters (they can vote for themselves, or anyone else). * However they have some extra properties. */ - - +class Candidate extends Voter { + constructor(name, age, party, votingCard) { + super(name, age, votingCard); + this.party = party; + this.numVotes = 0; + } +} +let candidates = { + 1: new Candidate('Tamara Faiza', 46, 'Pizza Party', [1, 1]), + 2: new Candidate('Aylin Duke', 39, 'Foam Party', [2, 2]), + 3: new Candidate('Clay Roderick', 54, 'Flat Earth Party', [3, 4]), + 4: new Candidate('Nour al-Din', 32, 'Pizza Party', [4, 1]) +} /** * 3 - Write an Election class which models the election. */ +class Election { + constructor(validVoters, candidates) { + this.validVoters = validVoters; + //console.log(validVoters, "validVoters in class"); + this.candidates = candidates; + this.winner = 'winner has not been chosen yet'; + } + runElection() { + + this.candidates = runElection(this.validVoters, this.candidates) + + + } getWinner() { + //console.log("getwinner is getting called") + this.winner = getWinner(this.candidates); + + } printWinnerMessage() { + //console.log("this is bug message",this.winner) + if (this.winner === null) { return "The election was a draw"; } + return this.winner.name + " has won the election with " + this.winner.numVotes + " votes!"; + } +} +// Example of how the winner message can be printed. + +/* +fetch('http://www.mocky.io/v2/5a55224b2d000088425b1ed8') + .then(function (response) { return response.json() }) + .then(function (json) { console.log(json); }) */ + +//list of Candidates +let listCan = document.querySelectorAll(".candidates li"); +// listCan[0].textContent=candidates["1"].name; +// listCan[1].textContent=candidates["2"].name; +// listCan[2].textContent=candidates["3"].name; +// listCan[3].textContent=candidates["4"].name; + +//listCan.forEach((item,i,candidates)=>item[i].textContent=candidates[i+1].name); //?????solved +listCan.forEach((item, i, listCan) => item.textContent = candidates[i + 1].name) +// for (let i = 0; i < listCan.length; i++) { +// listCan[i].textContent = candidates[i + 1].name; +// } +//list of Voters +let listVote = document.querySelectorAll(".voters li"); +listVote.forEach((item, i, listVote) => item.textContent = votingPopulation[i].name); + +//run Election Buttun +let runButt = document.getElementById("runBut"); +runButt.addEventListener("click", () => fetchElectionData().then(message=>alert(message))); + +function fetchElectionData() { + var data; + //return 2; + return fetch('https://s3-eu-west-1.amazonaws.com/lorenzomixedstuff/electionList.json').then(res => res.json()).then(function (jsonData) { + data = jsonData; + candidates = data.candidates.map(function (item) { return new Candidate(item.name, item.age, item.party, item.votingCard) }); + voters = data.voters; + let allVoters = voters.concat(candidates); + let validVoters = filterInvalidVoters(allVoters); + + let election = new Election(validVoters, candidates); + election.runElection(); // Example of how runElection() can be called. + election.getWinner(); //need to modify it so it becomes a sort only selects max numVotes + var message = election.printWinnerMessage(); + return message; + } + ) +} - -// Include your votingPopulation array here. -let votingPopulation = []; - - -// Include your candidates object here. -let candidates = {}; - - -let allVoters = votingPopulation.concat(candidatesObjToArray(candidates)); - -let validVoters = filterInvalidVoters(allVoters); - -let election = new Election(validVoters, candidates); - -election.runElection(); // Example of how runElection() can be called. - -console.log(election.printWinnerMessage()); // Example of how the winner message can be printed. diff --git a/election.js b/election.js index 776f3a1..c3862b8 100644 --- a/election.js +++ b/election.js @@ -6,72 +6,110 @@ * 1 - Convert candidates object to array */ function candidatesObjToArray(candidates) { - + var arrOfKeys = Object.keys(candidates); + var arrOfCandidates = arrOfKeys.map(function (key) { return candidates[key]; }); + return arrOfCandidates; } /** * 2 - Remove any voters who have voted for more than 2 people, or have voted for the same person twice. */ -function filterInvalidVoters(voters) { +function filterInvalidVoters(allVoters) { + return allVoters.filter(item => item.votingCard.length < 3 && item.votingCard[0] !== item.votingCard[1] + ) } - /** * 3 - Add up all the votes cast by the voting population. Note that for two adjacent votes in the vote array, * the right vote counts for half of the left vote. */ -function runElection(voters, candidates) { - +//refactored Version of runElection +function runElection(validVoters, candidates) { + for (let i = 1; i < Object.values(candidates).length; i++) { + validVoters.forEach(function (item) { + if (item.votingCard[0] === i) { + candidates[i].numVotes += 1 + } + if (item.votingCard[1] === i) + candidates[i].numVotes += 0.5; + }) + } + return candidates; } - /** * 4 - After an election has been run, return the winner * * Desired return value: {name: "Tamara Faiza", age: 46, party: "Pizza Party", numVotes: 3} */ function getWinner(candidates) { - + let winner = { numVotes: 0.0 }; + try { + Object.values(candidates).forEach(function (item) { + /* console.log(item.name,item.numVotes); + console.log(winner.name,winner.numVotes); + console.log(); */ + if (item.numVotes == winner.numVotes) { + throw "Duplicate"; + } + else if (item.numVotes > winner.numVotes) { + winner = item; + } + }) + } catch (error) { + return null; + } + return winner; } - /** * 5 - Return a message including the name of the winner, and how many votes * he/she received */ function winnerMessage(winner) { - + var winner = getWinner(candidates) + if (winner !== null) { + var mes = winner.name + " has won the election with " + winner.numVotes + " votes!"; + return mes; + } + else return "The election was a draw"; } // A sample population of a small number of voters, stored as an array let votingPopulation = [ - {name: 'Jane Finnegan', age: 19, votingCard: [1,3]}, - {name: 'Norman Beracha', age: 35, votingCard: [3,4]}, - {name: 'Salome Kadek', age: 22, votingCard: [2,1,3]}, - {name: 'Wei Li', age: 19, votingCard: [1,2]}, - {name: 'Sam MacKinnon', age: 59, votingCard: [1,4]} + { name: 'Jane Finnegan', age: 19, votingCard: [1, 3] }, + { name: 'Norman Beracha', age: 35, votingCard: [3, 4] }, + { name: 'Salome Kadek', age: 22, votingCard: [2, 1, 3] }, + { name: 'Wei Li', age: 19, votingCard: [1, 2] }, + { name: 'Sam MacKinnon', age: 59, votingCard: [1, 4] } ]; // The election candidates, stored as an object where each object key is the candidate ID, and the object // value is the candidate object itself. let candidates = { - 1: {name: 'Tamara Faiza', age: 46, votingCard: [1,1], party: 'Pizza Party', numVotes: 0}, - 2: {name: 'Aylin Duke', age: 39, votingCard: [2,2], party: 'Foam Party', numVotes: 0}, - 3: {name: 'Clay Roderick', age: 54, votingCard: [3,4], party: 'Flat Earth Party', numVotes: 0}, - 4: {name: 'Nour al-Din', age: 32, votingCard: [4,1], party: 'Pizza Party', numVotes: 0} -}; + 1: { name: 'Tamara Faiza', age: 46, votingCard: [1, 1], party: 'Pizza Party', numVotes: 0 }, + 2: { name: 'Aylin Duke', age: 39, votingCard: [2, 2], party: 'Foam Party', numVotes: 0 }, + 3: { name: 'Clay Roderick', age: 54, votingCard: [3, 4], party: 'Flat Earth Party', numVotes: 0 }, + 4: { name: 'Nour al-Din', age: 32, votingCard: [4, 1], party: 'Pizza Party', numVotes: 0 } +} //4,3 is draw let allVoters = votingPopulation.concat(candidatesObjToArray(candidates)); +//console.log(allVoters); let validVoters = filterInvalidVoters(allVoters); +//console.log(validVoters,"validdddddddddd") //--> array of Objects candidates = runElection(validVoters, candidates); +//console.log(candidates); let winner = getWinner(candidates); +//console.log("and the winner is: ",winner) + +console.log(winnerMessage()); module.exports = { - candidatesObjToArray, - filterInvalidVoters, - runElection, - getWinner, - winnerMessage + candidatesObjToArray, + filterInvalidVoters, + runElection, + getWinner, + winnerMessage } diff --git a/election.test.js b/election.test.js index 75efd0b..f1f3864 100644 --- a/election.test.js +++ b/election.test.js @@ -56,6 +56,16 @@ test('getWinner should return the winning candidate', () => { numVotes: 3.5, }) }) +test('getWinner should return the winning candidate', () => { + const candidatesAfterElection = { + 1: {name:"Tamara Faiza",age:46,votingCard:[1,1],party:"Pizza Party",numVotes:3.0}, + 2: {name:"Aylin Duke",age:39,votingCard:[2,2],party:"Foam Party",numVotes:0.5}, + 3: {name:"Clay Roderick",age:54,votingCard:[3,4],party:"Flat Earth Party",numVotes:3.0}, + 4: {name:"Nour al-Din",age:32,votingCard:[4,1],party:"Pizza Party",numVotes:2.5} + }; + + expect(getWinner(candidatesAfterElection)).toEqual(null) +}) test('winnerMessage should return a message with the name of the winner and number of votes received', () => { const winner = { diff --git a/electionclass.js b/electionclass.js new file mode 100644 index 0000000..bed1df8 --- /dev/null +++ b/electionclass.js @@ -0,0 +1,20 @@ +class Election { + constructor(validVoters, candidates) { + this.validVoters = validVoters; + this.candidates = candidates; + this.winner = 'winner has not been chosen yet'; + } + runElection() { + this.candidates = runElection(this.validVoters, this.candidates) + + } getWinner() { + this.winner = getWinner(this.candidates); + + } printWinnerMessage() { + if (this.winner === null) { return "The election was a draw"; } + return this.winner.name + " has won the election with " + this.winner.numVotes + " votes!"; + } +} +module.exports = { + Election +} \ No newline at end of file diff --git a/electionclass.test.js b/electionclass.test.js new file mode 100644 index 0000000..12ffa94 --- /dev/null +++ b/electionclass.test.js @@ -0,0 +1,55 @@ +function runElection(validVoters, candidates) { + return candidates.map(item=>item.runElection()); //?map????? +} + +function getWinner(candidates) { + let winner = { numVotes: 0.0 }; + try { + Object.values(candidates).forEach(function (item) { + if (item.numVotes == winner.numVotes) { + throw "Duplicate"; + } + else if (item.numVotes > winner.numVotes) { + winner = item; + } + }) + } catch (error) { + return null; + } + return winner; +} +const { Election } = require("./electionclass.js") +test('running the election should add votes to the candidates', () => { + const validVoters = [ + {name: 'Jane Finnegan', age: 19, votingCard: [1,3]}, + {name: 'Norman Beracha', age: 35, votingCard: [3,4]}, + {name: 'Wei Li', age: 19, votingCard: [1,2]}, + {name: 'Sam MacKinnon', age: 59, votingCard: [1,4]}, + {name: 'Clay Roderick', age: 54, votingCard: [3,4], party: 'Flat Earth Party', numVotes: 0}, + {name: 'Nour al-Din', age: 32, votingCard: [4,1], party: 'Pizza Party', numVotes: 0} + ] + + expect(runElection(validVoters, candidates)).toEqual({ + 1: {name:"Tamara Faiza",age:46,votingCard:[1,1],party:"Pizza Party",numVotes:3.5}, + 2: {name:"Aylin Duke",age:39,votingCard:[2,2],party:"Foam Party",numVotes:0.5}, + 3: {name:"Clay Roderick",age:54,votingCard:[3,4],party:"Flat Earth Party",numVotes:2.5}, + 4: {name:"Nour al-Din",age:32,votingCard:[4,1],party:"Pizza Party",numVotes:2.5} + }) +}) + +test('getWinner should return the winning candidate', () => { + const candidatesAfterElection = { + 1: {name:"Tamara Faiza",age:46,votingCard:[1,1],party:"Pizza Party",numVotes:3.5}, + 2: {name:"Aylin Duke",age:39,votingCard:[2,2],party:"Foam Party",numVotes:0.5}, + 3: {name:"Clay Roderick",age:54,votingCard:[3,4],party:"Flat Earth Party",numVotes:2.5}, + 4: {name:"Nour al-Din",age:32,votingCard:[4,1],party:"Pizza Party",numVotes:2.5} + }; + + expect(getWinner(candidatesAfterElection)).toEqual({ + name: 'Tamara Faiza', + age: 46, + votingCard: [1, 1], + party: 'Pizza Party', + numVotes: 3.5, + }) +}) \ No newline at end of file diff --git a/index.html b/index.html index 90b9358..10ca65d 100644 --- a/index.html +++ b/index.html @@ -1,7 +1,38 @@ +
- + - +