curriculum/challenges/english/blocks/lab-voting-system/673b567e3ba535dda140d278.md
In this lab, you will build a voting system that uses Map to create a poll and Set to prevent duplicate voting.
Objective: Fulfill the user stories below and get all the tests to pass to complete the lab.
User Stories:
You should initialize a poll variable to a new Map object.
You should have a function addOption that accepts a parameter option.
In the addOption function:
If the option does not already exist in the poll, it should be added to the poll with an empty Set as its value to track voters. You should also return the message Option "<option>" added to the poll.
If the option already exists, it should return the message Option "<option>" already exists.
If you try to add an empty option, the function should return the message Option cannot be empty.
You should have a function vote that accepts two parameters, option (the option to vote for) and voterId (a unique ID for the voter).
In the vote function:
If the option does not exist in the poll, the function should return the message Option "<option>" does not exist.
If the option exists, the function should check if the voterId has already voted for this option.
If the voter has already voted, the function should return the message Voter <voterId> has already voted for "<option>".
If the voter has not voted, voterId should be added to the Set of voters for this option. The function should return the message Voter <voterId> voted for "<option>".
You should have at least three options in your poll.
Your poll should have at least three votes.
You should have a function displayResults that returns the poll results in the following format:
Poll Results:
OptionA: N votes
OptionB: N votes
.
.
/*
sample output
Poll Results:
Turkey: 2 votes
Morocco: 1 votes
*/
You should have a poll variable initialized to a new Map object.
assert.exists(poll);
assert.instanceOf(poll, Map);
You should define a function addOption that accepts a parameter option.
assert.isFunction(addOption);
assert.match(
addOption.toString(),
/^function\s+addOption\s*\(\s*option\s*\)\s*\{|\(?\s*option\s*\)?\s*=>/
);
You should define a function vote that accepts two parameters, option and voterId.
assert.isFunction(vote);
assert.match(vote.toString(), /\(\s*option\s*,\s*voterId\s*\)/);
You should define a function displayResults to display the poll results.
assert.isFunction(displayResults);
You should have at least three options in your poll.
assert.isAtLeast(poll.size, 3);
Your poll should have at least three votes.
let totalVotes = 0;
for (let voters of poll.values()) {
totalVotes += voters.size;
}
assert.isAtLeast(totalVotes, 3);
You should ensure each voting option maps to a Set object.
const pollCopy = new Map(poll);
try {
poll.clear();
addOption('Turkey');
assert.instanceOf(poll.get('Turkey'), Set);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
addOption("Egypt") should return Option "Egypt" added to the poll.
const pollCopy = new Map(poll);
try {
poll.clear();
assert.equal(addOption('Egypt'), 'Option "Egypt" added to the poll.');
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
Adding an empty option should return "Option cannot be empty."
assert.equal(addOption(''), 'Option cannot be empty.');
When Turkey is already added, addOption("Turkey") should return Option "Turkey" already exists.
const pollCopy = new Map(poll);
try {
poll.clear();
addOption('Turkey');
addOption('Turkey');
assert.equal(addOption('Turkey'), 'Option "Turkey" already exists.');
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
When Malaysia exists in the voting options, vote("Malaysia", "traveler1") should return Voter traveler1 voted for "Malaysia".
const pollCopy = new Map(poll);
try {
poll.clear();
addOption('Malaysia');
assert.equal(
vote('Malaysia', 'traveler1'),
'Voter traveler1 voted for "Malaysia".'
);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
vote should update the Set of voters for an option.
const pollCopy = new Map(poll);
try {
poll.clear();
addOption('Alaska');
vote('Alaska', 'seal');
assert.isTrue(poll.get('Alaska').has('seal'));
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
When traveler1 tries to vote for Algeria again, vote("Algeria", "traveler1") should return Voter traveler1 has already voted for "Algeria".
const pollCopy = new Map(poll);
try {
poll.clear();
addOption('Algeria');
vote('Algeria', 'traveler1');
assert.equal(
vote('Algeria', 'traveler1'),
'Voter traveler1 has already voted for "Algeria".'
);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
Duplicate votes should not increase the size of the Set.
const pollCopy = new Map(poll);
try {
poll.clear();
addOption('Turkey');
vote('Turkey', 'traveler1');
const voterSet = poll.get('Turkey');
const initialSize = voterSet.size;
vote('Turkey', 'traveler1');
assert.equal(voterSet.size, initialSize);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
When Nigeria is not in the voting options, vote("Nigeria", "traveler2") should return Option "Nigeria" does not exist.
const pollCopy = new Map(poll);
try {
poll.clear();
assert.equal(
vote('Nigeria', 'traveler2'),
'Option "Nigeria" does not exist.'
);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
A unique option should be able to receive multiple votes.
const pollCopy = new Map(poll);
try {
poll.clear();
addOption('Bali');
assert.equal(vote('Bali', 'traveler1'), 'Voter traveler1 voted for "Bali".');
assert.equal(vote('Bali', 'traveler2'), 'Voter traveler2 voted for "Bali".');
assert.equal(poll.get('Bali').size, 2);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
When option Turkey gets two votes, option Morocco gets one vote, and option Spain doesn't get any vote, displayResults() should return "Poll Results:\nTurkey: 2 votes\nMorocco: 1 votes\nSpain: 0 votes".
const pollCopy = new Map(poll);
try {
poll.clear();
addOption('Turkey');
addOption('Morocco');
addOption('Spain');
vote('Turkey', 'traveler1');
vote('Turkey', 'traveler2');
vote('Morocco', 'traveler3');
assert.equal(
displayResults(),
'Poll Results:\nTurkey: 2 votes\nMorocco: 1 votes\nSpain: 0 votes'
);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
displayResults() should return the results in the correct format.
const pollCopy = new Map(poll);
try {
poll.clear();
addOption('Turkey');
addOption('Morocco');
vote('Turkey', 'traveler1');
vote('Turkey', 'traveler2');
vote('Morocco', 'traveler3');
assert.equal(
displayResults(),
'Poll Results:\nTurkey: 2 votes\nMorocco: 1 votes'
);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
const poll = new Map();
function addOption(option) {
if (!option || option.trim() === '') {
return 'Option cannot be empty.';
}
if (!poll.has(option)) {
poll.set(option, new Set());
return `Option "${option}" added to the poll.`;
} else {
return `Option "${option}" already exists.`;
}
}
function vote(option, voterId) {
if (!poll.has(option)) {
return `Option "${option}" does not exist.`;
}
const voters = poll.get(option);
if (voters.has(voterId)) {
return `Voter ${voterId} has already voted for "${option}".`;
} else {
voters.add(voterId);
return `Voter ${voterId} voted for "${option}".`;
}
}
function displayResults() {
let results = 'Poll Results:\n';
for (let [option, voters] of poll.entries()) {
results += `${option}: ${voters.size} votes\n`;
}
return results.trim();
}
addOption('Turkey');
addOption('Morocco');
addOption('Spain');
vote('Turkey', 'traveler1');
vote('Turkey', 'traveler2');
vote('Morocco', 'traveler3');