feat(curriculum): add voting system lab (#57208)

Co-authored-by: Dario-DC <105294544+Dario-DC@users.noreply.github.com>
Co-authored-by: Tom <20648924+moT01@users.noreply.github.com>
This commit is contained in:
Zaira 2024-12-10 05:50:39 +05:00 committed by GitHub
parent 75f480c948
commit 7260918523
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 379 additions and 1 deletions

View File

@ -3101,7 +3101,12 @@
]
},
"cvsw": { "title": "226", "intro": [] },
"cvs1": { "title": "227", "intro": [] },
"lab-voting-system": {
"title": "Build a Voting System",
"intro": [
"In this lab, you will build a voting system using Maps and Sets."
]
},
"review-javascript-maps-and-sets": {
"title": "JavaScript Maps and Sets Review",
"intro": [

View File

@ -0,0 +1,9 @@
---
title: Introduction to the Build a Voting System
block: lab-voting-system
superBlock: full-stack-developer
---
## Introduction to the Build a Voting System
In this lab, you will build a voting system using Maps and Sets.

View File

@ -0,0 +1,11 @@
{
"name": "Build a Voting System",
"isUpcomingChange": true,
"usesMultifileEditor": true,
"dashedName": "lab-voting-system",
"superBlock": "full-stack-developer",
"challengeOrder": [{ "id": "673b567e3ba535dda140d278", "title": "Build a Voting System" }],
"helpCategory": "JavaScript",
"blockType": "lab",
"blockLayout": "link"
}

View File

@ -0,0 +1,352 @@
---
id: 673b567e3ba535dda140d278
title: Build a Voting System
challengeType: 14
dashedName: build-a-voting-system
---
# --description--
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:**
1. You should initialize a `poll` variable to a new `Map` object.
2. You should have a function `addOption` that accepts a parameter `option`.
3. 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.`.
4. You should have a function `vote` that accepts two parameters, `option` (the option to vote for) and `voterId` (a unique ID for the voter).
5. 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 display 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>".`
6. You should have at least three options in your `poll`.
7. Your `poll` should have at least three votes.
8. You should have a function `displayResults` that returns the poll results in the following format:
```js
Poll Results:
OptionA: N votes
OptionB: N votes
.
.
/*
sample output
Poll Results:
Turkey: 2 votes
Morocco: 1 votes
*/
```
# --hints--
You should have a `poll` variable initialized to a new `Map` object.
```js
assert.exists(poll);
assert.instanceOf(poll, Map);
```
You should define a function `addOption` that accepts a parameter `option`.
```js
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`.
```js
assert.isFunction(vote);
assert.match(vote.toString(), /\(\s*option\s*,\s*voterId\s*\)/);
```
You should define a function `displayResults` to display the poll results.
```js
assert.isFunction(displayResults);
```
You should have at least three options in your `poll`.
```js
assert.lengthOf(poll, 3);
```
Your `poll` should have at least three votes.
```js
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.
```js
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.`
```js
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."`
```js
assert.equal(addOption(""), 'Option cannot be empty.');
```
When `Turkey` is already added, `addOption("Turkey")` should return `Option "Turkey" already exists.`
```js
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 `Malysia` exists in the voting options, `vote("Malysia", "traveler1")` should return `Voter traveler1 voted for "Malysia".`
```js
const pollCopy = new Map(poll);
try {
poll.clear();
addOption("Malysia");
assert.equal(vote("Malysia", "traveler1"), 'Voter traveler1 voted for "Malysia".');
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
});
}
```
`vote` should update the `Set` of voters for an option.
```js
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".`
```js
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`.
```js
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.`
```js
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.
```js
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);
});
}
```
`displayResults()` should return the results in the correct format.
```js
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);
});
}
```
# --seed--
## --seed-contents--
```js
```
# --solutions--
```js
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");
```

View File

@ -468,6 +468,7 @@
"dashedName": "maps-and-sets",
"blocks": [
{ "dashedName": "lecture-working-with-maps-and-sets" },
{ "dashedName": "lab-voting-system" },
{ "dashedName": "review-javascript-maps-and-sets" },
{ "dashedName": "quiz-javascript-maps-and-sets" }
]