Created
March 3, 2017 13:08
-
-
Save eiriklv/30ed442ef3f0705cf84bce485bfafd79 to your computer and use it in GitHub Desktop.
Modeling an election in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Dependencies | |
*/ | |
const sortBy = require('sort-by'); | |
/** | |
* Representing an election as a data structure | |
*/ | |
const votes = [ | |
{ id: 0, voterId: 'a', zone: 'Oslo', party: 'Miljøpartiet De Grønne' }, | |
{ id: 1, voterId: 'b', zone: 'Oslo', party: 'Fremskrittspartiet' }, | |
{ id: 2, voterId: 'c', zone: 'Oslo', party: 'Arbeiderpartiet' }, | |
{ id: 3, voterId: 'd', zone: 'Oslo', party: 'Piratpartiet' }, | |
{ id: 4, voterId: 'e', zone: 'Oslo', party: 'Liberalistene' }, | |
{ id: 5, voterId: 'f', zone: 'Oslo', party: 'Høyre' }, | |
{ id: 6, voterId: 'g', zone: 'Oslo', party: 'Sosialistisk Venstreparti' }, | |
{ id: 7, voterId: 'h', zone: 'Oslo', party: 'Venstre' }, | |
{ id: 8, voterId: 'i', zone: 'Oslo', party: 'Piratpartiet' }, | |
{ id: 9, voterId: 'j', zone: 'Oslo', party: 'Høyre' }, | |
{ id: 10, voterId: 'k', zone: 'Oslo', party: 'Høyre' }, | |
{ id: 11, voterId: 'l', zone: 'Trondheim', party: 'Miljøpartiet De Grønne' }, | |
{ id: 12, voterId: 'm', zone: 'Trondheim', party: 'Fremskrittspartiet' }, | |
{ id: 13, voterId: 'n', zone: 'Trondheim', party: 'Arbeiderpartiet' }, | |
{ id: 14, voterId: 'o', zone: 'Trondheim', party: 'Piratpartiet' }, | |
{ id: 14, voterId: 'o', zone: 'Trondheim', party: 'Piratpartiet' }, | |
{ id: 15, voterId: 'p', zone: 'Trondheim', party: 'Piratpartiet' }, | |
{ id: 16, voterId: 'q', zone: 'Bergen', party: 'Liberalistene' }, | |
{ id: 17, voterId: 'r', zone: 'Bergen', party: 'Høyre' }, | |
{ id: 18, voterId: 's', zone: 'Bergen', party: 'Sosialistisk Venstreparti' }, | |
{ id: 19, voterId: 't', zone: 'Bergen', party: 'Sosialistisk Venstreparti' }, | |
{ id: 20, voterId: 'u', zone: 'Bergen', party: 'Venstre' }, | |
{ id: 21, voterId: 'v', zone: 'Bergen', party: 'Piratpartiet' }, | |
{ id: 22, voterId: 'x', zone: 'Stavanger', party: 'Piratpartiet' }, | |
{ id: 23, voterId: 'y', zone: 'Stavanger', party: 'Piratpartiet' }, | |
{ id: 24, voterId: 'z', zone: 'Stavanger', party: 'Piratpartiet' }, | |
{ id: 25, voterId: 'æ', zone: 'Stavanger', party: 'Piratpartiet' }, | |
{ id: 26, voterId: 'ø', zone: 'Stavanger', party: 'Piratpartiet' }, | |
{ id: 27, voterId: 'å', zone: 'Stavanger', party: 'Piratpartiet' }, | |
]; | |
/** | |
* Selection of fields (mapping) | |
*/ | |
const voteIds = votes.map((vote) => vote.id); | |
const voterIds = votes.map((vote) => vote.voterId); | |
const zones = votes.map((vote) => vote.zone); | |
const parties = votes.map((vote) => vote.party); | |
/** | |
* Counting the amount of votes | |
*/ | |
const amountOfVotes = votes.length; | |
/** | |
* Getting the sum for a specific party | |
*/ | |
const amountOfVotesForPiratpartiet = votes | |
.filter((vote) => vote.party === 'Piratpartiet') | |
.length; | |
/** | |
* Function that takes a list and an element | |
* and returns a new list of unique elements | |
*/ | |
function uniqueReducer(uniqueList, element) { | |
return uniqueList.includes(element) ? | |
uniqueList : | |
[...uniqueList, element]; | |
} | |
/** | |
* Getting all the unique parties that are represented | |
*/ | |
const partiesRepresented = votes | |
.map((vote) => vote.party) | |
.reduce(uniqueReducer, []); | |
/** | |
* Getting all the unique zones that are represented | |
*/ | |
const zonesRepresented = votes | |
.map((vote) => vote.zone) | |
.reduce(uniqueReducer, []); | |
/** | |
* Group all the votes by party | |
*/ | |
const votesGroupedByParty = votes | |
.reduce((votesByParty, vote) => { | |
return Object.assign({}, votesByParty, { | |
[vote.party]: [ | |
...(votesByParty[vote.party] || []), | |
vote, | |
], | |
}); | |
}, {}); | |
/** | |
* Group all the votes by zone | |
*/ | |
const votesGroupedByZone = votes | |
.reduce((votesByZone, vote) => { | |
return Object.assign({}, votesByZone, { | |
[vote.zone]: [ | |
...(votesByZone[vote.zone] || []), | |
vote, | |
], | |
}); | |
}, {}); | |
/** | |
* Find the national winner party by counting all the votes per party | |
*/ | |
const nationalWinner = partiesRepresented | |
.map((party) => ({ party, sum: votesGroupedByParty[party].length })) | |
.sort(sortBy('-sum')) | |
.map((result) => result.party)[0] | |
/** | |
* Find a summary of each zone | |
*/ | |
const summaryByZone = zonesRepresented | |
.map((zone) => { | |
return { | |
zone: zone, | |
sums: partiesRepresented | |
.map((party) => ({ | |
party, | |
sum: votesGroupedByZone[zone] | |
.filter((vote) => vote.party === party) | |
.length | |
})) | |
}; | |
}); | |
/** | |
* Find the winner for each zone | |
*/ | |
const winnerByZone = summaryByZone | |
.map((summary) => ({ | |
zone: summary.zone, | |
winner: summary.sums | |
.sort(sortBy('-sum')) | |
.map((result) => result.party)[0] | |
})); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment