From 756d1e249a308c76b8524d7fe79e5dff92a66672 Mon Sep 17 00:00:00 2001 From: Clement Denis Date: Wed, 10 Jun 2020 21:18:53 +0200 Subject: [PATCH] normalize line endings (again) --- subjects/ascii-art/thinkertoy.txt | 1710 ++++++++--------- subjects/audits-at-home.en.md | 184 +- subjects/biggie-smalls.en.md | 24 +- subjects/change.en.md | 66 +- subjects/circular.en.md | 26 +- subjects/currify.en.md | 42 +- subjects/curry-entries.en.md | 96 +- subjects/cut-corners.en.md | 54 +- subjects/date-is.en.md | 38 +- subjects/debounce.en.md | 24 +- subjects/deep-copy.en.md | 18 +- subjects/filter.en.md | 56 +- subjects/find-expression.en.md | 60 +- subjects/flat.en.md | 38 +- subjects/flow.en.md | 48 +- subjects/for-each.en.md | 40 +- subjects/forum/forum-moderation.audit.en.md | 102 +- subjects/forum/forum.audit.en.md | 366 ++-- subjects/get-json.en.md | 56 +- subjects/gougle-search.en.md | 90 +- subjects/greedy-url.en.md | 32 +- .../groupie-tracker.audit.en.md | 206 +- subjects/index-of.en.md | 64 +- subjects/interpolation.en.md | 90 +- subjects/invert.en.md | 18 +- subjects/ion-out.en.md | 22 +- subjects/its-a-match.en.md | 42 +- subjects/keep-cut.en.md | 52 +- subjects/match-cron.en.md | 64 +- subjects/more-or-less.en.md | 30 +- subjects/mutability.en.md | 62 +- subjects/nasa.en.md | 30 +- subjects/primitives.en.md | 30 +- subjects/pyramid.en.md | 54 +- subjects/race.en.md | 48 +- subjects/repeat.en.md | 48 +- subjects/replica.en.md | 24 +- subjects/returns.en.md | 30 +- subjects/series.en.md | 22 +- subjects/sign.en.md | 54 +- subjects/tetris-optimizer/badexample00.md | 22 +- subjects/tetris-optimizer/badexample01.md | 22 +- subjects/tetris-optimizer/badexample02.md | 22 +- subjects/tetris-optimizer/badexample03.md | 22 +- subjects/tetris-optimizer/badexample04.md | 22 +- subjects/tetris-optimizer/goodexample00.md | 22 +- subjects/tetris-optimizer/goodexample01.md | 52 +- subjects/tetris-optimizer/goodexample02.md | 92 +- subjects/tetris-optimizer/goodexample03.md | 122 +- .../tetris-optimizer.audit.en.md | 166 +- subjects/triangle.en.md | 50 +- subjects/tron/ai/hard.js | 342 ++-- subjects/tron/ai/license-to-kill.js | 194 +- subjects/tron/ai/random.js | 114 +- subjects/tron/ai/right.js | 96 +- subjects/tron/ai/snail.js | 80 +- subjects/tron/index.html | 768 ++++---- subjects/tron/lib/display.js | 264 +-- subjects/tron/lib/state.js | 192 +- subjects/tron/tron.audit.en.md | 90 +- subjects/tron/tron.en.md | 152 +- 61 files changed, 3533 insertions(+), 3533 deletions(-) diff --git a/subjects/ascii-art/thinkertoy.txt b/subjects/ascii-art/thinkertoy.txt index 21eeea721..ed727f870 100644 --- a/subjects/ascii-art/thinkertoy.txt +++ b/subjects/ascii-art/thinkertoy.txt @@ -1,855 +1,855 @@ - - - - - - - - - - - - -o -| -o - -O - - -o o -| | - - - - - - - - - | | --O-O- - | | --O-O- - | | - - - - | | - -O-O- -o | | - -O-O- - | | o - -O-O- - | | - - - - O -o / - / - / o -O - - - - - - o - /| -o-O- - | - - - -o -| - - - - - - - - - / -o -| -o - \ - - - - -\ - o - | - o -/ - - - - -o | o - \|/ ---O-- - /|\ -o | o - - - - - - | --o- - | - - - - - - - - - -o -| - - - - - - -o-o - - - - - - - - - -O - - - - - o - / - o - / -o - - - - - o-o -o /o -| / | -o/ o - o-o - - - - - 0 - /| -o | - | -o-o-o - - - - - -- -o o - / - / -o--o - - - - -o-o - | - oo - | -o-o - - - - -o o -| | -o--O - | - o - - - - -o--o -| -o-o - | -o-o - - - - - o - / -O--o -o | - o-o - - - - -o---o - / - o - | - o - - - - - o-o -| | - o-o -| | - o-o - - - - - o-o -| o - o--O - / - o - - - - - -O - -O - - - - - - -o - -o -| - - - - - o - / -O - \ - o - - - - - - -o--o -o--o - - - - - -o - \ - O - / -o - - - - - o-o -o o - / - o - - O - - - - o - / \ -o O-o - \ - o- - - - - - O - / \ -o---o -| | -o o - - - - -o--o -| | -O--o -| | -o--o - - - - - o-o - / -O - \ - o-o - - - - -o-o -| \ -| O -| / -o-o - - - - -o--o -| -O-o -| -o--o - - - - -o--o -| -O-o -| -o - - - - - o-o -o -| -o -o | - o-o - - - - -o o -| | -O--O -| | -o o - - - - -o-O-o - | - | - | -o-O-o - - - - - o - | - | -\ o - o-o - - - - -o o -| / -OO -| \ -o o - - - - -o -| -| -| -O---o - - - - -o o -|\ /| -| O | -| | -o o - - - - -o o -|\ | -| \ | -| \| -o o - - - - - o-o -o o -| | -o o - o-o - - - - -o--o -| | -O--o -| -o - - - - - o-o -o o -| | -o O - o-O\ - - - - -o--o -| | -O-Oo -| \ -o o - - - - - o-o -| - o-o - | -o--o - - - - -o-O-o - | - | - | - o - - - - -o o -| | -| | -| | - o-o - - - - -o o -| | -o o - \ / - o - - - - -o o -| | -o o o - \ / \ / - o o - - - - -o o - \ / - O - / \ -o o - - - - -o o - \ / - O - | - o - - - - -o---o - / - -O- - / -o---o - - - - -O-o -| -| -| -O-o - - - - -o - \ - o - \ - o - - - - -o-O - | - | - | -o-O - - - - - o -/ \ - - - - - - - - - - - -o---o - - - - -0 -| - - - - - - - - - - oo -| | -o-o- - - - - -o -| -O-o -| | -o-o - - - - - - - o-o -| - o-o - - - - - o - | - o-O -| | - o-o - - - - - - -o-o -|-' -o-o - - - - - o-o - | --O- - | - o - - - - - - -o--o -| | -o--O - | -o--o - - -o -| -O--o -| | -o o - - - - - -o - -| -| - - - - - - o - - o - | -o o - o-o - - -o -| / -OO -| \ -o o - - - - -o -| -| -| -o - - - - - - -o-O-o -| | | -o o o - - - - - - -o-o -| | -o o - - - - - - -o-o -| | -o-o - - - - - - -o-o -| | -O-o -| -o - - - - - o-o -| | - o-O - | - o - - - - -o-o -| -o - - - - - - -o-o - \ -o-o - - - - - o - | --o- - | - o - - - - - - -o o -| | -o--o - - - - - - -o o - \ / - o - - - - - - -o o o - \ / \ / - o o - - - - - - -\ / - o -/ \ - - - - - - -o o -| | -o--O - | -o--o - - - - -o-o - / -o-o - - - - - o-o - | -o-O - | - o-o - - - - -o -| -o -| -o - - - - -o-o - | - O-o - | -o-o - - - - o_ / -/ o - - - - - - + + + + + + + + + + + + +o +| +o + +O + + +o o +| | + + + + + + + + + | | +-O-O- + | | +-O-O- + | | + + + + | | + -O-O- +o | | + -O-O- + | | o + -O-O- + | | + + + + O +o / + / + / o +O + + + + + + o + /| +o-O- + | + + + +o +| + + + + + + + + + / +o +| +o + \ + + + + +\ + o + | + o +/ + + + + +o | o + \|/ +--O-- + /|\ +o | o + + + + + + | +-o- + | + + + + + + + + + +o +| + + + + + + +o-o + + + + + + + + + +O + + + + + o + / + o + / +o + + + + + o-o +o /o +| / | +o/ o + o-o + + + + + 0 + /| +o | + | +o-o-o + + + + + -- +o o + / + / +o--o + + + + +o-o + | + oo + | +o-o + + + + +o o +| | +o--O + | + o + + + + +o--o +| +o-o + | +o-o + + + + + o + / +O--o +o | + o-o + + + + +o---o + / + o + | + o + + + + + o-o +| | + o-o +| | + o-o + + + + + o-o +| o + o--O + / + o + + + + + +O + +O + + + + + + +o + +o +| + + + + + o + / +O + \ + o + + + + + + +o--o +o--o + + + + + +o + \ + O + / +o + + + + + o-o +o o + / + o + + O + + + + o + / \ +o O-o + \ + o- + + + + + O + / \ +o---o +| | +o o + + + + +o--o +| | +O--o +| | +o--o + + + + + o-o + / +O + \ + o-o + + + + +o-o +| \ +| O +| / +o-o + + + + +o--o +| +O-o +| +o--o + + + + +o--o +| +O-o +| +o + + + + + o-o +o +| -o +o | + o-o + + + + +o o +| | +O--O +| | +o o + + + + +o-O-o + | + | + | +o-O-o + + + + + o + | + | +\ o + o-o + + + + +o o +| / +OO +| \ +o o + + + + +o +| +| +| +O---o + + + + +o o +|\ /| +| O | +| | +o o + + + + +o o +|\ | +| \ | +| \| +o o + + + + + o-o +o o +| | +o o + o-o + + + + +o--o +| | +O--o +| +o + + + + + o-o +o o +| | +o O + o-O\ + + + + +o--o +| | +O-Oo +| \ +o o + + + + + o-o +| + o-o + | +o--o + + + + +o-O-o + | + | + | + o + + + + +o o +| | +| | +| | + o-o + + + + +o o +| | +o o + \ / + o + + + + +o o +| | +o o o + \ / \ / + o o + + + + +o o + \ / + O + / \ +o o + + + + +o o + \ / + O + | + o + + + + +o---o + / + -O- + / +o---o + + + + +O-o +| +| +| +O-o + + + + +o + \ + o + \ + o + + + + +o-O + | + | + | +o-O + + + + + o +/ \ + + + + + + + + + + + +o---o + + + + +0 +| + + + + + + + + + + oo +| | +o-o- + + + + +o +| +O-o +| | +o-o + + + + + + + o-o +| + o-o + + + + + o + | + o-O +| | + o-o + + + + + + +o-o +|-' +o-o + + + + + o-o + | +-O- + | + o + + + + + + +o--o +| | +o--O + | +o--o + + +o +| +O--o +| | +o o + + + + + +o + +| +| + + + + + + o + + o + | +o o + o-o + + +o +| / +OO +| \ +o o + + + + +o +| +| +| +o + + + + + + +o-O-o +| | | +o o o + + + + + + +o-o +| | +o o + + + + + + +o-o +| | +o-o + + + + + + +o-o +| | +O-o +| +o + + + + + o-o +| | + o-O + | + o + + + + +o-o +| +o + + + + + + +o-o + \ +o-o + + + + + o + | +-o- + | + o + + + + + + +o o +| | +o--o + + + + + + +o o + \ / + o + + + + + + +o o o + \ / \ / + o o + + + + + + +\ / + o +/ \ + + + + + + +o o +| | +o--O + | +o--o + + + + +o-o + / +o-o + + + + + o-o + | +o-O + | + o-o + + + + +o +| +o +| +o + + + + +o-o + | + O-o + | +o-o + + + + o_ / +/ o + + + + + + diff --git a/subjects/audits-at-home.en.md b/subjects/audits-at-home.en.md index 7d8ba4cf7..f282dccf0 100644 --- a/subjects/audits-at-home.en.md +++ b/subjects/audits-at-home.en.md @@ -1,92 +1,92 @@ -## How to do an audit from home - -### Introduction - -A little reminder first, - -Audits, as we have told you many times, are an essential part of leveling up and truly acquiring your skills -and knowledge. - -Normally, they must be done with your physical presence. -The idea is that they encourage the exchange between the auditors and the members of the group. - -If the project fails, the whole group will learn why. And then after all your audits are done you will retry. -During all those extra audits, you, as a group, will discuss about your failures with the auditors. -If the project succeed, you will be an inspiration for the auditors. -In both of those cases you will learn or you will teach. The roles will keep reversing almost every time. - -It is, ultimaly, those interactions that are essential for really learning; -To give and receive feedback, but also to see what you really know as an individual and what you do not. -This will increase your capacity to solve problems and your capacity to adapt, which is one of the most important -skill of a good programmer. - -Today, once again, we must adapt... -Knowledge is important but not as essential as health. - -We really wish all of you to stay safe and healthy at home. - -This is why we created a little guideline in how to conduct your audit from home. -There is a video here : [youtube.com/watch?v=J8g8P-IJLJw](https://www.youtube.com/watch?v=J8g8P-IJLJw) - -But we are also going to summarize the process. -So here we go. - -### Prerequisites for the team captain and the auditor - -- A program to communicate and livestream installed (like Discord [discordapp.com](https://discordapp.com/) ) -- A program to allows the auditor to take charge of the computer - of the team captain installed (like teamViewer [teamviewer.com](https://www.teamviewer.com/) ) - -### Prerequisite for the team captain - -The team captain must communicate : - -- The contact of his or her teammates to the auditor -- The git repository of the project to be reviewed (the link must be public or accessible for the auditor) -- The team captain must be logged in in his or her session to allow the auditor to start its audit - -### Prerequisite for the auditor - -- The auditor will need to create the group on the communication program -- The auditor will need to download the project repository -- The auditor, if the internet bandwith allows it, will livestream the process - -### Instructions - -1. Let the auditor establish the communication with the group members and the captain. - -2. Once all prequisites are done from the team captain and the auditor let the audit begin. - -3. If possible, the auditor starts the stream. - -4. The captain, after checking that the login is done on his or her computer, allows the auditor - to take control of its computer (with teamViewer for example) - -5. The auditor now has the control to start the audit on the computer of the captain. - The organization of the windows by the auditor might be the tricky part. We suggest - to see how we did it in the video if you find it difficult. - -6. The auditor conducts the audit, if the auditor can not live stream its audits, he or she - will then explain by voice (or writing in the chat) what he or she is doing to the rest of the group. - -7. The audit is conducted until all questions are validated or until a mistake is made. - -8. If a mistake is made the auditor can copy paste the commands that detected the mistakes. - -9. The group discusses as much as needed until the audit is completed. - -10. Once the audit is completed, all programs can be closed up. Say bye and thank you for your time and make the - necessary conclusions among the members of the group. - -### Conclusion - -Thank you for reading until the end. Stay safe. - -### Bonus - -Did you know that there is a nice `Live Share` extension on `vscode`? -This allows to do remote group programming easily. It might be an alternative solution -to the livestream if necessary. -Try it out! - -Stay safe everyone! Happy coding! +## How to do an audit from home + +### Introduction + +A little reminder first, + +Audits, as we have told you many times, are an essential part of leveling up and truly acquiring your skills +and knowledge. + +Normally, they must be done with your physical presence. +The idea is that they encourage the exchange between the auditors and the members of the group. + +If the project fails, the whole group will learn why. And then after all your audits are done you will retry. +During all those extra audits, you, as a group, will discuss about your failures with the auditors. +If the project succeed, you will be an inspiration for the auditors. +In both of those cases you will learn or you will teach. The roles will keep reversing almost every time. + +It is, ultimaly, those interactions that are essential for really learning; +To give and receive feedback, but also to see what you really know as an individual and what you do not. +This will increase your capacity to solve problems and your capacity to adapt, which is one of the most important +skill of a good programmer. + +Today, once again, we must adapt... +Knowledge is important but not as essential as health. + +We really wish all of you to stay safe and healthy at home. + +This is why we created a little guideline in how to conduct your audit from home. +There is a video here : [youtube.com/watch?v=J8g8P-IJLJw](https://www.youtube.com/watch?v=J8g8P-IJLJw) + +But we are also going to summarize the process. +So here we go. + +### Prerequisites for the team captain and the auditor + +- A program to communicate and livestream installed (like Discord [discordapp.com](https://discordapp.com/) ) +- A program to allows the auditor to take charge of the computer + of the team captain installed (like teamViewer [teamviewer.com](https://www.teamviewer.com/) ) + +### Prerequisite for the team captain + +The team captain must communicate : + +- The contact of his or her teammates to the auditor +- The git repository of the project to be reviewed (the link must be public or accessible for the auditor) +- The team captain must be logged in in his or her session to allow the auditor to start its audit + +### Prerequisite for the auditor + +- The auditor will need to create the group on the communication program +- The auditor will need to download the project repository +- The auditor, if the internet bandwith allows it, will livestream the process + +### Instructions + +1. Let the auditor establish the communication with the group members and the captain. + +2. Once all prequisites are done from the team captain and the auditor let the audit begin. + +3. If possible, the auditor starts the stream. + +4. The captain, after checking that the login is done on his or her computer, allows the auditor + to take control of its computer (with teamViewer for example) + +5. The auditor now has the control to start the audit on the computer of the captain. + The organization of the windows by the auditor might be the tricky part. We suggest + to see how we did it in the video if you find it difficult. + +6. The auditor conducts the audit, if the auditor can not live stream its audits, he or she + will then explain by voice (or writing in the chat) what he or she is doing to the rest of the group. + +7. The audit is conducted until all questions are validated or until a mistake is made. + +8. If a mistake is made the auditor can copy paste the commands that detected the mistakes. + +9. The group discusses as much as needed until the audit is completed. + +10. Once the audit is completed, all programs can be closed up. Say bye and thank you for your time and make the + necessary conclusions among the members of the group. + +### Conclusion + +Thank you for reading until the end. Stay safe. + +### Bonus + +Did you know that there is a nice `Live Share` extension on `vscode`? +This allows to do remote group programming easily. It might be an alternative solution +to the livestream if necessary. +Try it out! + +Stay safe everyone! Happy coding! diff --git a/subjects/biggie-smalls.en.md b/subjects/biggie-smalls.en.md index 8d69d79af..6ec7ee218 100644 --- a/subjects/biggie-smalls.en.md +++ b/subjects/biggie-smalls.en.md @@ -1,12 +1,12 @@ -## Biggie Smalls - -### Instructions - -Create 2 variables -- `smalls` with the smallest possible `number` value -- `biggie` with the greatest possible `number` value - - -### Notions - -- [devdocs.io/javascript-number](https://devdocs.io/javascript-number/) +## Biggie Smalls + +### Instructions + +Create 2 variables +- `smalls` with the smallest possible `number` value +- `biggie` with the greatest possible `number` value + + +### Notions + +- [devdocs.io/javascript-number](https://devdocs.io/javascript-number/) diff --git a/subjects/change.en.md b/subjects/change.en.md index 0eda674e3..0924f8b88 100644 --- a/subjects/change.en.md +++ b/subjects/change.en.md @@ -1,33 +1,33 @@ -## Change - -### Instructions - -Create 2 functions: -- `get`: a function that takes a key and return the corresponding - value from the sourceObject - -- `set`: a function that takes a key and a value update the - value for the corresponding property of the sourceObject - and return the set value - - -### Notions - -- [nan-academy.github.io/js-training/examples/functions.js](https://nan-academy.github.io/js-training/examples/functions.js) -- [nan-academy.github.io/js-training/examples/data-structures.js](https://nan-academy.github.io/js-training/examples/data-structures.js) -- [nan-academy.github.io/js-training/examples/get.js](https://nan-academy.github.io/js-training/examples/get.js) -- [nan-academy.github.io/js-training/examples/set.js](https://nan-academy.github.io/js-training/examples/set.js) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -const sourceObject = { - num: 42, - bool: true, - str: 'some text', - log: console.log, -} -``` +## Change + +### Instructions + +Create 2 functions: +- `get`: a function that takes a key and return the corresponding + value from the sourceObject + +- `set`: a function that takes a key and a value update the + value for the corresponding property of the sourceObject + and return the set value + + +### Notions + +- [nan-academy.github.io/js-training/examples/functions.js](https://nan-academy.github.io/js-training/examples/functions.js) +- [nan-academy.github.io/js-training/examples/data-structures.js](https://nan-academy.github.io/js-training/examples/data-structures.js) +- [nan-academy.github.io/js-training/examples/get.js](https://nan-academy.github.io/js-training/examples/get.js) +- [nan-academy.github.io/js-training/examples/set.js](https://nan-academy.github.io/js-training/examples/set.js) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +const sourceObject = { + num: 42, + bool: true, + str: 'some text', + log: console.log, +} +``` diff --git a/subjects/circular.en.md b/subjects/circular.en.md index 3a10c9076..9c461c420 100644 --- a/subjects/circular.en.md +++ b/subjects/circular.en.md @@ -1,13 +1,13 @@ -## Circular - -### Instructions - -Create an object named `circular` that has a property named `circular` with -itself as the value - - -### Notions - -- [nan-academy.github.io/js-training/examples/data-structures.js](https://nan-academy.github.io/js-training/examples/data-structures.js) -- [nan-academy.github.io/js-training/examples/get.js](https://nan-academy.github.io/js-training/examples/get.js) -- [nan-academy.github.io/js-training/examples/set.js](https://nan-academy.github.io/js-training/examples/set.js) +## Circular + +### Instructions + +Create an object named `circular` that has a property named `circular` with +itself as the value + + +### Notions + +- [nan-academy.github.io/js-training/examples/data-structures.js](https://nan-academy.github.io/js-training/examples/data-structures.js) +- [nan-academy.github.io/js-training/examples/get.js](https://nan-academy.github.io/js-training/examples/get.js) +- [nan-academy.github.io/js-training/examples/set.js](https://nan-academy.github.io/js-training/examples/set.js) diff --git a/subjects/currify.en.md b/subjects/currify.en.md index 39eca20f6..23a9f27c3 100644 --- a/subjects/currify.en.md +++ b/subjects/currify.en.md @@ -1,21 +1,21 @@ -## Currify - -### Instructions - -Create the function `currify` that will curry any functions put as argument. - -example: -```js -const mult2 = (el1,el2) => el1 * el2 -console.log(mult2(2,2)) // result epected 4 - - -const mult2Curried = currify(mult2) - -console.log(mult2Curried(2)(2)) // result expected 4 -// (same result, with a function that has technically only one argument) -``` - -### Notions - -- [stackoverflow.com/questions/36314/what-is-currying](https://stackoverflow.com/questions/36314/what-is-currying) +## Currify + +### Instructions + +Create the function `currify` that will curry any functions put as argument. + +example: +```js +const mult2 = (el1,el2) => el1 * el2 +console.log(mult2(2,2)) // result epected 4 + + +const mult2Curried = currify(mult2) + +console.log(mult2Curried(2)(2)) // result expected 4 +// (same result, with a function that has technically only one argument) +``` + +### Notions + +- [stackoverflow.com/questions/36314/what-is-currying](https://stackoverflow.com/questions/36314/what-is-currying) diff --git a/subjects/curry-entries.en.md b/subjects/curry-entries.en.md index 8782acb1b..e329da8b9 100644 --- a/subjects/curry-entries.en.md +++ b/subjects/curry-entries.en.md @@ -1,48 +1,48 @@ -## Curry Entries - -### Instructions - -This exercise consists in creating curry functions to apply in the objects -entries. -You will have to create the following curry functions: - -- `defaultCurry` that will curry two objects in witch the second object must -be the default object and returns a new object with the modifications applied -by the first object -- `mapCurry` that replicate the function `.map` -- `reduceCurry` that replicate the function `.reduce` -- `filterCurry` that replicate the function `.filter` - -You will also have to create for each curry function the following: - -- `reduceScore` that will return the total value of the scores - of the persons who use the force -- `filterForce` that will return the force users with `shootingScores` - equal or higher than 80 -- `mapAverage` that will return a new object with the propriety `averageScore` - that is the averages of the scores for each person - - -### Notions - -- [devdocs.io/javascript/global_objects/array/filter](https://devdocs.io/javascript/global_objects/array/filter) -- [devdocs.io/javascript/global_objects/array/map](https://devdocs.io/javascript/global_objects/array/map) -- [devdocs.io/javascript/global_objects/array/reduce](https://devdocs.io/javascript/global_objects/array/reduce) -- [devdocs.io/javascript/global_objects/object/entries](https://devdocs.io/javascript/global_objects/object/entries) -- [devdocs.io/javascript/global_objects/object/fromentries](https://devdocs.io/javascript/global_objects/object/fromentries) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -// prettier-ignore -const personnel = { - lukeSkywalker: { id: 5, pilotingScore: 98, shootingScore: 56, isForceUser: true }, - sabineWren: { id: 82, pilotingScore: 73, shootingScore: 99, isForceUser: false }, - zebOrellios: { id: 22, pilotingScore: 20, shootingScore: 59, isForceUser: false }, - ezraBridger: { id: 15, pilotingScore: 43, shootingScore: 67, isForceUser: true }, - calebDume: { id: 11, pilotingScore: 71, shootingScore: 85, isForceUser: true }, -} -``` +## Curry Entries + +### Instructions + +This exercise consists in creating curry functions to apply in the objects +entries. +You will have to create the following curry functions: + +- `defaultCurry` that will curry two objects in witch the second object must +be the default object and returns a new object with the modifications applied +by the first object +- `mapCurry` that replicate the function `.map` +- `reduceCurry` that replicate the function `.reduce` +- `filterCurry` that replicate the function `.filter` + +You will also have to create for each curry function the following: + +- `reduceScore` that will return the total value of the scores + of the persons who use the force +- `filterForce` that will return the force users with `shootingScores` + equal or higher than 80 +- `mapAverage` that will return a new object with the propriety `averageScore` + that is the averages of the scores for each person + + +### Notions + +- [devdocs.io/javascript/global_objects/array/filter](https://devdocs.io/javascript/global_objects/array/filter) +- [devdocs.io/javascript/global_objects/array/map](https://devdocs.io/javascript/global_objects/array/map) +- [devdocs.io/javascript/global_objects/array/reduce](https://devdocs.io/javascript/global_objects/array/reduce) +- [devdocs.io/javascript/global_objects/object/entries](https://devdocs.io/javascript/global_objects/object/entries) +- [devdocs.io/javascript/global_objects/object/fromentries](https://devdocs.io/javascript/global_objects/object/fromentries) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +// prettier-ignore +const personnel = { + lukeSkywalker: { id: 5, pilotingScore: 98, shootingScore: 56, isForceUser: true }, + sabineWren: { id: 82, pilotingScore: 73, shootingScore: 99, isForceUser: false }, + zebOrellios: { id: 22, pilotingScore: 20, shootingScore: 59, isForceUser: false }, + ezraBridger: { id: 15, pilotingScore: 43, shootingScore: 67, isForceUser: true }, + calebDume: { id: 11, pilotingScore: 71, shootingScore: 85, isForceUser: true }, +} +``` diff --git a/subjects/cut-corners.en.md b/subjects/cut-corners.en.md index 951aec6f2..a197d3e38 100644 --- a/subjects/cut-corners.en.md +++ b/subjects/cut-corners.en.md @@ -1,27 +1,27 @@ -## Cut Corners - -### Instructions - -Create a function for each rounding math functions: -- round (like `Math.round`) -- ceil (like `Math.ceil`) -- floor (like `Math.floor`) -- trunc (like `Math.trunc`) - -Some restrictions apply: -- You may not use strings conversion to do it -- No bitwise operator - - -### Notions - -- [devdocs.io/javascript/global_objects/math](https://devdocs.io/javascript/global_objects/math) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -Math.round = Math.ceil = Math.floor = Math.trunc = undefined -``` +## Cut Corners + +### Instructions + +Create a function for each rounding math functions: +- round (like `Math.round`) +- ceil (like `Math.ceil`) +- floor (like `Math.floor`) +- trunc (like `Math.trunc`) + +Some restrictions apply: +- You may not use strings conversion to do it +- No bitwise operator + + +### Notions + +- [devdocs.io/javascript/global_objects/math](https://devdocs.io/javascript/global_objects/math) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +Math.round = Math.ceil = Math.floor = Math.trunc = undefined +``` diff --git a/subjects/date-is.en.md b/subjects/date-is.en.md index 836b97a6d..188b3e701 100644 --- a/subjects/date-is.en.md +++ b/subjects/date-is.en.md @@ -1,19 +1,19 @@ -## Date Is - -### Instructions - -Create the following functions: -- `isValid`, this function must return false if its an Invalid Date -- `isAfter`, this function will receive two dates and return true if the first date is bigger then the second date -- `isBefore`, this function will receive two dates and return true if the first date is lesser then the second date -- `isFuture`, will return true if the date given as parameter is higher then the present date -- `isPast`, will return true if the date given as parameter less then the present date - - -### Notions - -- [date-fns.org/v2.14.0/docs/isValid](https://date-fns.org/v2.14.0/docs/isValid) -- [date-fns.org/v2.14.0/docs/isAfter](https://date-fns.org/v2.14.0/docs/isAfter) -- [date-fns.org/v2.14.0/docs/isBefore](https://date-fns.org/v2.14.0/docs/isBefore) -- [date-fns.org/v2.14.0/docs/isFuture](https://date-fns.org/v2.14.0/docs/isFuture) -- [date-fns.org/v2.14.0/docs/isPast](https://date-fns.org/v2.14.0/docs/isPast) +## Date Is + +### Instructions + +Create the following functions: +- `isValid`, this function must return false if its an Invalid Date +- `isAfter`, this function will receive two dates and return true if the first date is bigger then the second date +- `isBefore`, this function will receive two dates and return true if the first date is lesser then the second date +- `isFuture`, will return true if the date given as parameter is higher then the present date +- `isPast`, will return true if the date given as parameter less then the present date + + +### Notions + +- [date-fns.org/v2.14.0/docs/isValid](https://date-fns.org/v2.14.0/docs/isValid) +- [date-fns.org/v2.14.0/docs/isAfter](https://date-fns.org/v2.14.0/docs/isAfter) +- [date-fns.org/v2.14.0/docs/isBefore](https://date-fns.org/v2.14.0/docs/isBefore) +- [date-fns.org/v2.14.0/docs/isFuture](https://date-fns.org/v2.14.0/docs/isFuture) +- [date-fns.org/v2.14.0/docs/isPast](https://date-fns.org/v2.14.0/docs/isPast) diff --git a/subjects/debounce.en.md b/subjects/debounce.en.md index c051a2299..c9db5f78b 100644 --- a/subjects/debounce.en.md +++ b/subjects/debounce.en.md @@ -1,12 +1,12 @@ -## Debounce - -### Instructions - -Create two functions that will work like `_.debounce` from lodash -- `debounce`, this function doesn't need to take care of the options -- `opDebounce`, this function will take care of the `leading` options - - -### Notions - -- [lodash.com/docs/4.17.15#debounce](https://lodash.com/docs/4.17.15#debounce) +## Debounce + +### Instructions + +Create two functions that will work like `_.debounce` from lodash +- `debounce`, this function doesn't need to take care of the options +- `opDebounce`, this function will take care of the `leading` options + + +### Notions + +- [lodash.com/docs/4.17.15#debounce](https://lodash.com/docs/4.17.15#debounce) diff --git a/subjects/deep-copy.en.md b/subjects/deep-copy.en.md index 4b1a786d7..1731dcf14 100644 --- a/subjects/deep-copy.en.md +++ b/subjects/deep-copy.en.md @@ -1,9 +1,9 @@ -## Deep Copy - -### Instructions - -Create a function called `deepCopy` that copy objects and arrays recursively. - -### Notions - -- [devdocs.io/javascript-object](https://devdocs.io/javascript-object/) +## Deep Copy + +### Instructions + +Create a function called `deepCopy` that copy objects and arrays recursively. + +### Notions + +- [devdocs.io/javascript-object](https://devdocs.io/javascript-object/) diff --git a/subjects/filter.en.md b/subjects/filter.en.md index f1a6887a2..c10401867 100644 --- a/subjects/filter.en.md +++ b/subjects/filter.en.md @@ -1,28 +1,28 @@ -## Filter - -### Instructions - -- Create a `filter` function that takes an array as first argument, a function as second, -and that works like the method [].filter - -- Create a `reject` function that takes an array as first argument, a function as second, -and that works like the reject function from lodash. - -- Create a `partition` function that takes an array as first argument, a function as second, -and that works like the partition function from lodash. - - -### Notions - -- [devdocs.io/javascript/global_objects/array/filter](https://devdocs.io/javascript/global_objects/array/filter) -- [lodash.com/docs/4.17.15#reject](https://lodash.com/docs/4.17.15#reject) -- [lodash.com/docs/4.17.15#partition](https://lodash.com/docs/4.17.15#partition) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -Array.prototype.filter = undefined -``` +## Filter + +### Instructions + +- Create a `filter` function that takes an array as first argument, a function as second, +and that works like the method [].filter + +- Create a `reject` function that takes an array as first argument, a function as second, +and that works like the reject function from lodash. + +- Create a `partition` function that takes an array as first argument, a function as second, +and that works like the partition function from lodash. + + +### Notions + +- [devdocs.io/javascript/global_objects/array/filter](https://devdocs.io/javascript/global_objects/array/filter) +- [lodash.com/docs/4.17.15#reject](https://lodash.com/docs/4.17.15#reject) +- [lodash.com/docs/4.17.15#partition](https://lodash.com/docs/4.17.15#partition) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +Array.prototype.filter = undefined +``` diff --git a/subjects/find-expression.en.md b/subjects/find-expression.en.md index 356771432..6e9a55747 100644 --- a/subjects/find-expression.en.md +++ b/subjects/find-expression.en.md @@ -1,30 +1,30 @@ -## Find Expression - -### Instructions - -Create a function called `findExpression` that takes a number as parameter and returns a string - -- It will be given two constant variable `add4` and `mul2` - -- Your goal is to try to find a sequence, starting from the number 1, and repeatedly either adding 4 or multiplying 2 - that produces the number given has parameter. -For example, the number 8 you must first multiplying by 2 twice and then add 4. -It will look something like this `1 *2 *2 +4` - -- If the number can not be reached you should return `undefined` - - -### Notions - -- [nan-academy.github.io/js-training/examples/loops.js](https://nan-academy.github.io/js-training/examples/loops.js) -- [nan-academy.github.io/js-training/examples/recursion.js](https://nan-academy.github.io/js-training/examples/recursion.js) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -const add4 = '+4' -const mul2 = '*2' -``` +## Find Expression + +### Instructions + +Create a function called `findExpression` that takes a number as parameter and returns a string + +- It will be given two constant variable `add4` and `mul2` + +- Your goal is to try to find a sequence, starting from the number 1, and repeatedly either adding 4 or multiplying 2 + that produces the number given has parameter. +For example, the number 8 you must first multiplying by 2 twice and then add 4. +It will look something like this `1 *2 *2 +4` + +- If the number can not be reached you should return `undefined` + + +### Notions + +- [nan-academy.github.io/js-training/examples/loops.js](https://nan-academy.github.io/js-training/examples/loops.js) +- [nan-academy.github.io/js-training/examples/recursion.js](https://nan-academy.github.io/js-training/examples/recursion.js) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +const add4 = '+4' +const mul2 = '*2' +``` diff --git a/subjects/flat.en.md b/subjects/flat.en.md index f48e04bcd..5de3c6eaa 100644 --- a/subjects/flat.en.md +++ b/subjects/flat.en.md @@ -1,19 +1,19 @@ -## Flat - -### Instructions - -Create the `flat` functions that works like the `.flat` array method - - -### Notions - -- [devdocs.io/javascript/global_objects/array/flat](https://devdocs.io/javascript/global_objects/array/flat) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -Array.prototype.flat = undefined -``` +## Flat + +### Instructions + +Create the `flat` functions that works like the `.flat` array method + + +### Notions + +- [devdocs.io/javascript/global_objects/array/flat](https://devdocs.io/javascript/global_objects/array/flat) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +Array.prototype.flat = undefined +``` diff --git a/subjects/flow.en.md b/subjects/flow.en.md index 608345690..0479561b4 100644 --- a/subjects/flow.en.md +++ b/subjects/flow.en.md @@ -1,24 +1,24 @@ -## Flow - -### Instructions - -Create the function `flow` that will works as the \_.flow([funcs]) -from lodash. - - -### Example - -``` js - -const square = nbr => nbr * nbr -const add2Numbers = (nbr1, nbr2) => nbr1 + nbr2 - -const flowedFunctions = flow([add2numbers, square]) -flowedFunctions(2, 3) // -> 25 - -``` - - -### Notions - -- [lodash.com/docs/4.17.15#flow](https://lodash.com/docs/4.17.15#flow) +## Flow + +### Instructions + +Create the function `flow` that will works as the \_.flow([funcs]) +from lodash. + + +### Example + +``` js + +const square = nbr => nbr * nbr +const add2Numbers = (nbr1, nbr2) => nbr1 + nbr2 + +const flowedFunctions = flow([add2numbers, square]) +flowedFunctions(2, 3) // -> 25 + +``` + + +### Notions + +- [lodash.com/docs/4.17.15#flow](https://lodash.com/docs/4.17.15#flow) diff --git a/subjects/for-each.en.md b/subjects/for-each.en.md index 90cddac0a..a62cd7aa1 100644 --- a/subjects/for-each.en.md +++ b/subjects/for-each.en.md @@ -1,20 +1,20 @@ -## For Each - -### Instructions - -Create a `forEach` function that takes an array as first argument, a function as second, -and that works like the method .forEach - - -### Notions - -- [devdocs.io/javascript/global_objects/array/foreach](https://devdocs.io/javascript/global_objects/array/foreach) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -Array.prototype.forEach = undefined -``` +## For Each + +### Instructions + +Create a `forEach` function that takes an array as first argument, a function as second, +and that works like the method .forEach + + +### Notions + +- [devdocs.io/javascript/global_objects/array/foreach](https://devdocs.io/javascript/global_objects/array/foreach) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +Array.prototype.forEach = undefined +``` diff --git a/subjects/forum/forum-moderation.audit.en.md b/subjects/forum/forum-moderation.audit.en.md index 9af52e1a3..d8cf61fa0 100644 --- a/subjects/forum/forum-moderation.audit.en.md +++ b/subjects/forum/forum-moderation.audit.en.md @@ -1,51 +1,51 @@ -#### Functional - -###### Does the forum present the 4 types of users? - -##### Try to enter the forum as a Guest - -###### Can you confirm that the content is only viewable? - -##### Try registering as a normal user. - -###### Can you create posts and comments? - -##### Try registering as a normal user. - -###### Can you like or dislike a post? - -##### Try registering as a moderator. Then login to an admin account and see if the admin user has received the request. - -###### Can you confirm that the admin received the request? - -##### Try accepting a moderator using the admin user. - -###### Has the moderator been promoted? - -##### Try using the moderator to delete a obscene post - -###### Can you confirm that it is possible? - -##### Try using the moderator to report a illegal post - -###### Did the admin user receive the report? - -##### Try using the admin user to answer the moderator request. - -###### Did the moderator receive the answer from the admin? - -##### Try using an admin user to demote a moderator. - -###### Can you confirm that it is possible? - -##### As an auditor, is this project up to every standard? If not, why are you failing the project?(Empty Work, Incomplete Work, Invalid compilation, Cheating, Crashing, Leaks) - -#### General - -###### +Does the project present more then 4 types of users? - -#### Social - -###### +Did you learn anything from this project? - -###### +Would you recommend/nominate this program as an example for the rest of the school? +#### Functional + +###### Does the forum present the 4 types of users? + +##### Try to enter the forum as a Guest + +###### Can you confirm that the content is only viewable? + +##### Try registering as a normal user. + +###### Can you create posts and comments? + +##### Try registering as a normal user. + +###### Can you like or dislike a post? + +##### Try registering as a moderator. Then login to an admin account and see if the admin user has received the request. + +###### Can you confirm that the admin received the request? + +##### Try accepting a moderator using the admin user. + +###### Has the moderator been promoted? + +##### Try using the moderator to delete a obscene post + +###### Can you confirm that it is possible? + +##### Try using the moderator to report a illegal post + +###### Did the admin user receive the report? + +##### Try using the admin user to answer the moderator request. + +###### Did the moderator receive the answer from the admin? + +##### Try using an admin user to demote a moderator. + +###### Can you confirm that it is possible? + +##### As an auditor, is this project up to every standard? If not, why are you failing the project?(Empty Work, Incomplete Work, Invalid compilation, Cheating, Crashing, Leaks) + +#### General + +###### +Does the project present more then 4 types of users? + +#### Social + +###### +Did you learn anything from this project? + +###### +Would you recommend/nominate this program as an example for the rest of the school? diff --git a/subjects/forum/forum.audit.en.md b/subjects/forum/forum.audit.en.md index 03cff8021..008bb265f 100644 --- a/subjects/forum/forum.audit.en.md +++ b/subjects/forum/forum.audit.en.md @@ -1,183 +1,183 @@ -#### Authentication - -###### Are an email and a password asked for in the resgistration? - -###### Does the project detect if the email or password are wrong? - -###### Does the project detect if the email or user name is already taken in the registration? - -##### Try to register as a new user in the forum. - -###### Is it possible to register? - -##### Try to login with the user you created. - -###### Can you login and have all the rights of a registered user? - -##### Try to login without any credentials. - -###### Does it show a warning message? - -###### Are sessions present in the project? - -##### Try opening two different browsers and login into one of them. Refresh the other browser. - -###### Can you confirm that the browser non logged remains unregistered? - -##### Try opening two different browsers and login into both of them. Refresh both browsers. - -###### Can you confirm that only one of those browsers has an active session? - -##### Try opening two different browsers and login into one of them. Then create a new post or just add a comment. Refresh both browsers. - -###### Does it present the comment/post on both browsers? - -#### SQLite - -###### Does the code contain at least one CREATE query? - -###### Does the code contain at least one INSERT query? - -###### Does the code contain at least one SELECT query? - -##### Try registering in the forum, open the database with `sqlite3 ` and perform a query to select all the users (Example: SELECT \* FROM users;). - -###### Does it present the user you created? - -##### Try creating a post in the forum, open the database with `sqlite3 ` and perform a query to select all the users (Example: SELECT \* FROM post;). - -###### Does it present the post you created? - -##### Try creating a comment in the forum, open the database with `sqlite3 ` and perform a query to select all the users (Example: SELECT \* FROM comment;). - -###### Does it present the comment you created? - -#### Docker - -###### Does the project have Dockerfiles? - -##### Try to run the command `"docker image build [OPTINS] PATH | URL | -"` to build the image using using the project Dockerfiles and run the command `"docker images"` to see images. - -``` -student$ docker images -REPOSITORY TAG IMAGE ID CREATED SIZE - latest 85a65d66ca39 7 seconds ago 795MB -``` - -###### Does all images build as above? - -##### Try running the command `"docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]"` to start the containers using the images just created and run the command `"docker ps -a"` to see containers. - -``` -student$ docker ps -a -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -cc8f5dcf760f "./server" 6 seconds ago Up 6 seconds 0.0.0.0:8080->8080/tcp ascii-art-web -``` - -###### Is the docker containers running as above? - -###### Does the project present no [unused object](https://docs.docker.com/config/pruning/)? - -#### Functional - -##### Enter the forum as a non-registered user. - -###### Are you prohibited to create a post? - -##### Enter the forum as a non-registered user. - -###### Are you prohibited to create a comment? - -##### Enter the forum as a non-registered user and try to like a comment. - -###### Are you prohibited to like a post? - -##### Enter the forum as a non-registered user and try to dislike a comment. - -###### Are you prohibited to dislike a comment? - -##### Enter the forum as a registered user, go to a post and try to create a comment for it. - -###### Were you able to create the comment? - -##### Enter the forum as a registered user, go to a post and try to create an empty comment for it. - -###### Were you prohibited to create the comment? - -##### Enter the forum as a registered user and try to create a post. - -###### Were you able to create a post? - -##### Enter the forum as a registered user and try to create an empty post. - -###### Were you prohibited to create the post? - -##### Try creating a post as a registered user and try to choose a category for that post. - -###### Were you able to choose a category for that post? - -##### Enter the forum as a registered user and try to like or dislike a post. - -###### Can you like or dislike the post? - -##### Enter the forum as a registered user and try to like or dislike a comment. - -###### Can you like or dislike the comment? - -##### Enter the forum as a registered user, try liking and disliking a post and then refresh the page. - -###### Does the number of likes/dislikes change? - -##### Enter the forum as a registered user and try to like and then dislike the same post. - -###### Can you confirm that it is not possible that the post is liked and disliked at the same time? - -##### Enter the forum as a registered user and try seeing all of your created posts. - -###### Does it present the expected posts? - -##### Enter the forum as a registered user and try seeing all of your liked posts. - -###### Does it present the expected posts? - -##### Navigate to a post of your choice and see its comments. - -###### Are all users (registered or not) able to see the number of likes and dislikes that comment has? - -##### Try seeing all posts from one category using the filter. - -###### Are all posts displayed from that category? - -###### Did the server behaved as expected?(did not crashed) - -###### Does the server use the right [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)? - -###### Are all the pages working? (Absence of 404 page?) - -###### Does the project handle [HTTP status 400 - Bad Requests](https://kinsta.com/knowledgebase/400-bad-request/#causes)? - -###### Does the project handle [HTTP status 500 - Internal Server Errors](https://www.restapitutorial.com/httpstatuscodes.html)? - -###### Are only the allowed packages being used? - -###### As an auditor, is this project up to every standard? If not, why are you failing the project?(Empty Work, Incomplete Work, Invalid compilation, Cheating, Crashing, Leaks) - -#### General - -###### +Does the project present a script to build the images and containers? (using a script to simplify the build) - -#### Basic - -###### +Does the project runs quickly and effectively? (Favoring recursive, no unnecessary data requests, etc) - -###### +Does the code obey the [good practices](https://public.01-edu.org/subjects/good-practices.en)? - -###### +Is there a test file for this code? - -#### Social - -###### +Did you learn anything from this project? - -###### +Can it be open-sourced / be used for other sources? - -###### +Would you recommend/nominate this program as an example for the rest of the school? +#### Authentication + +###### Are an email and a password asked for in the resgistration? + +###### Does the project detect if the email or password are wrong? + +###### Does the project detect if the email or user name is already taken in the registration? + +##### Try to register as a new user in the forum. + +###### Is it possible to register? + +##### Try to login with the user you created. + +###### Can you login and have all the rights of a registered user? + +##### Try to login without any credentials. + +###### Does it show a warning message? + +###### Are sessions present in the project? + +##### Try opening two different browsers and login into one of them. Refresh the other browser. + +###### Can you confirm that the browser non logged remains unregistered? + +##### Try opening two different browsers and login into both of them. Refresh both browsers. + +###### Can you confirm that only one of those browsers has an active session? + +##### Try opening two different browsers and login into one of them. Then create a new post or just add a comment. Refresh both browsers. + +###### Does it present the comment/post on both browsers? + +#### SQLite + +###### Does the code contain at least one CREATE query? + +###### Does the code contain at least one INSERT query? + +###### Does the code contain at least one SELECT query? + +##### Try registering in the forum, open the database with `sqlite3 ` and perform a query to select all the users (Example: SELECT \* FROM users;). + +###### Does it present the user you created? + +##### Try creating a post in the forum, open the database with `sqlite3 ` and perform a query to select all the users (Example: SELECT \* FROM post;). + +###### Does it present the post you created? + +##### Try creating a comment in the forum, open the database with `sqlite3 ` and perform a query to select all the users (Example: SELECT \* FROM comment;). + +###### Does it present the comment you created? + +#### Docker + +###### Does the project have Dockerfiles? + +##### Try to run the command `"docker image build [OPTINS] PATH | URL | -"` to build the image using using the project Dockerfiles and run the command `"docker images"` to see images. + +``` +student$ docker images +REPOSITORY TAG IMAGE ID CREATED SIZE + latest 85a65d66ca39 7 seconds ago 795MB +``` + +###### Does all images build as above? + +##### Try running the command `"docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]"` to start the containers using the images just created and run the command `"docker ps -a"` to see containers. + +``` +student$ docker ps -a +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +cc8f5dcf760f "./server" 6 seconds ago Up 6 seconds 0.0.0.0:8080->8080/tcp ascii-art-web +``` + +###### Is the docker containers running as above? + +###### Does the project present no [unused object](https://docs.docker.com/config/pruning/)? + +#### Functional + +##### Enter the forum as a non-registered user. + +###### Are you prohibited to create a post? + +##### Enter the forum as a non-registered user. + +###### Are you prohibited to create a comment? + +##### Enter the forum as a non-registered user and try to like a comment. + +###### Are you prohibited to like a post? + +##### Enter the forum as a non-registered user and try to dislike a comment. + +###### Are you prohibited to dislike a comment? + +##### Enter the forum as a registered user, go to a post and try to create a comment for it. + +###### Were you able to create the comment? + +##### Enter the forum as a registered user, go to a post and try to create an empty comment for it. + +###### Were you prohibited to create the comment? + +##### Enter the forum as a registered user and try to create a post. + +###### Were you able to create a post? + +##### Enter the forum as a registered user and try to create an empty post. + +###### Were you prohibited to create the post? + +##### Try creating a post as a registered user and try to choose a category for that post. + +###### Were you able to choose a category for that post? + +##### Enter the forum as a registered user and try to like or dislike a post. + +###### Can you like or dislike the post? + +##### Enter the forum as a registered user and try to like or dislike a comment. + +###### Can you like or dislike the comment? + +##### Enter the forum as a registered user, try liking and disliking a post and then refresh the page. + +###### Does the number of likes/dislikes change? + +##### Enter the forum as a registered user and try to like and then dislike the same post. + +###### Can you confirm that it is not possible that the post is liked and disliked at the same time? + +##### Enter the forum as a registered user and try seeing all of your created posts. + +###### Does it present the expected posts? + +##### Enter the forum as a registered user and try seeing all of your liked posts. + +###### Does it present the expected posts? + +##### Navigate to a post of your choice and see its comments. + +###### Are all users (registered or not) able to see the number of likes and dislikes that comment has? + +##### Try seeing all posts from one category using the filter. + +###### Are all posts displayed from that category? + +###### Did the server behaved as expected?(did not crashed) + +###### Does the server use the right [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)? + +###### Are all the pages working? (Absence of 404 page?) + +###### Does the project handle [HTTP status 400 - Bad Requests](https://kinsta.com/knowledgebase/400-bad-request/#causes)? + +###### Does the project handle [HTTP status 500 - Internal Server Errors](https://www.restapitutorial.com/httpstatuscodes.html)? + +###### Are only the allowed packages being used? + +###### As an auditor, is this project up to every standard? If not, why are you failing the project?(Empty Work, Incomplete Work, Invalid compilation, Cheating, Crashing, Leaks) + +#### General + +###### +Does the project present a script to build the images and containers? (using a script to simplify the build) + +#### Basic + +###### +Does the project runs quickly and effectively? (Favoring recursive, no unnecessary data requests, etc) + +###### +Does the code obey the [good practices](https://public.01-edu.org/subjects/good-practices.en)? + +###### +Is there a test file for this code? + +#### Social + +###### +Did you learn anything from this project? + +###### +Can it be open-sourced / be used for other sources? + +###### +Would you recommend/nominate this program as an example for the rest of the school? diff --git a/subjects/get-json.en.md b/subjects/get-json.en.md index 60c5fadd2..e7dfc583b 100644 --- a/subjects/get-json.en.md +++ b/subjects/get-json.en.md @@ -1,28 +1,28 @@ -## Get Json - -### Instructions - -In this exercise, we will focus on building complex async flows with promises. - -Create a `getJSON` function that takes 2 parameters: -- `path`, that will be the url called by your function -- `params` *optional*, that will be the search parameters appended to your url - -`getJSON` must construct a valid url with the `path` and stringified `params` -and call `fetch` with it. -If the response is not ok, your function must throw an error using -the response status message. - -The response body must then be read and parsed from json. - -The parsed object contains one of those 2 properties: -- `"data"` the actual data to return -- `"error"` the error message to throw - - -### Notions - -- [nan-academy.github.io/js-training/examples/promise.js](https://nan-academy.github.io/js-training/examples/promise.js) -- [devdocs.io/dom/fetch_api/using_fetch](https://devdocs.io/dom/fetch_api/using_fetch) -- [devdocs.io/dom/urlsearchparams](https://devdocs.io/dom/urlsearchparams) -- [devdocs.io/javascript/global_objects/json](https://devdocs.io/javascript/global_objects/json) +## Get Json + +### Instructions + +In this exercise, we will focus on building complex async flows with promises. + +Create a `getJSON` function that takes 2 parameters: +- `path`, that will be the url called by your function +- `params` *optional*, that will be the search parameters appended to your url + +`getJSON` must construct a valid url with the `path` and stringified `params` +and call `fetch` with it. +If the response is not ok, your function must throw an error using +the response status message. + +The response body must then be read and parsed from json. + +The parsed object contains one of those 2 properties: +- `"data"` the actual data to return +- `"error"` the error message to throw + + +### Notions + +- [nan-academy.github.io/js-training/examples/promise.js](https://nan-academy.github.io/js-training/examples/promise.js) +- [devdocs.io/dom/fetch_api/using_fetch](https://devdocs.io/dom/fetch_api/using_fetch) +- [devdocs.io/dom/urlsearchparams](https://devdocs.io/dom/urlsearchparams) +- [devdocs.io/javascript/global_objects/json](https://devdocs.io/javascript/global_objects/json) diff --git a/subjects/gougle-search.en.md b/subjects/gougle-search.en.md index 48b9402ef..622494e6e 100644 --- a/subjects/gougle-search.en.md +++ b/subjects/gougle-search.en.md @@ -1,45 +1,45 @@ -## Gougle Search - -### Instructions - -Create the `queryServers` function, that takes 2 arguments: -- `serverName` a string of the name of the server -- `q` a string of the query given by the user - -You have to construct 2 urls, using `q` as a search parameter, -prepending a `'/'` and for the 2nd appending `'_backup'`. - -Then return the first value of those 2 calls - -```js -queryServers('pouet', 'hello+world') - // return the fastest of those 2 calls: - // -> getJSON('/pouet?q=hello+world') - // -> getJSON('/pouet_backup?q=hello+world') -``` - - -Create a `gougleSearch` function that takes a single query argument. -It must call `queryServers` in concurrently on 3 servers: -`'web'`, `'image'` and `'video'`. - -A timeout of 80milliseconds must be set for the whole operation. - -You must return the value from each servers in an object -using a the server name as key. - - -### Notions - -- [devdocs.io/javascript/global_objects/promise/race](https://devdocs.io/javascript/global_objects/promise/race) -- [devdocs.io/javascript/global_objects/promise/all](https://devdocs.io/javascript/global_objects/promise/all) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -// fake `getJSON` function -let getJSON = async (url) => url -``` +## Gougle Search + +### Instructions + +Create the `queryServers` function, that takes 2 arguments: +- `serverName` a string of the name of the server +- `q` a string of the query given by the user + +You have to construct 2 urls, using `q` as a search parameter, +prepending a `'/'` and for the 2nd appending `'_backup'`. + +Then return the first value of those 2 calls + +```js +queryServers('pouet', 'hello+world') + // return the fastest of those 2 calls: + // -> getJSON('/pouet?q=hello+world') + // -> getJSON('/pouet_backup?q=hello+world') +``` + + +Create a `gougleSearch` function that takes a single query argument. +It must call `queryServers` in concurrently on 3 servers: +`'web'`, `'image'` and `'video'`. + +A timeout of 80milliseconds must be set for the whole operation. + +You must return the value from each servers in an object +using a the server name as key. + + +### Notions + +- [devdocs.io/javascript/global_objects/promise/race](https://devdocs.io/javascript/global_objects/promise/race) +- [devdocs.io/javascript/global_objects/promise/all](https://devdocs.io/javascript/global_objects/promise/all) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +// fake `getJSON` function +let getJSON = async (url) => url +``` diff --git a/subjects/greedy-url.en.md b/subjects/greedy-url.en.md index e8bfe634e..cbc1c0b56 100644 --- a/subjects/greedy-url.en.md +++ b/subjects/greedy-url.en.md @@ -1,16 +1,16 @@ -## Greedy Url - -### Instructions - -Write 3 functions : - -- `getURL` that returns an array with all valid URLs present in a data-set, http and https -- `greedyQuery` that returns URL with at least 3 or more parameters from all URLs that contain a query. -- `notSoGreedy` that returns URL with at least 2, but not more then 3 parameters from all URLs that contain a query. - -You can search for greedy quantifiers for help - - -### Notions - -- [github.com/ziishaned/learn-regex](https://github.com/ziishaned/learn-regex) +## Greedy Url + +### Instructions + +Write 3 functions : + +- `getURL` that returns an array with all valid URLs present in a data-set, http and https +- `greedyQuery` that returns URL with at least 3 or more parameters from all URLs that contain a query. +- `notSoGreedy` that returns URL with at least 2, but not more then 3 parameters from all URLs that contain a query. + +You can search for greedy quantifiers for help + + +### Notions + +- [github.com/ziishaned/learn-regex](https://github.com/ziishaned/learn-regex) diff --git a/subjects/groupie-tracker/groupie-tracker.audit.en.md b/subjects/groupie-tracker/groupie-tracker.audit.en.md index 0c159ccc7..95a52735a 100644 --- a/subjects/groupie-tracker/groupie-tracker.audit.en.md +++ b/subjects/groupie-tracker/groupie-tracker.audit.en.md @@ -1,103 +1,103 @@ -#### Functional - -###### Has the requirement for the allowed packages been respected? (Reminder for this project: (only [standard packages](https://golang.org/pkg/) - -###### Is the data from the artists being used? - -###### Is data from the relations being used? - -##### Try to see the "members" for the artist/band `"Queen"` - -``` - "Freddie Mercury", - "Brian May", - "John Daecon", - "Roger Meddows-Taylor", - "Mike Grose", - "Barry Mitchell", - "Doug Fogie" -``` - -###### Does it present the right "member", as above? - -##### Try to see the "firstAlbum" for the artist/band `"Gorillaz"` - -``` - "26-03-2001" -``` - -###### Does it present the right date for the "firstAlbum", as above? - -##### Try to see the "locations" for the artist/band `"Travis Scott"` - -``` - "santiago-chile" - "sao_paulo-brasil" - "los_angeles-usa" - "houston-usa" - "atlanta-usa" - "new_orleans-usa" - "philadelphia-usa" - "london-uk" - "frauenfeld-switzerland" - "turku-finland" -``` - -###### Does it present the right "locations" as above? - -##### Try to see the ""members"" for the artist/band `"Foo Fighters"`. - -``` - "Dave Grohl" - "Nate Mendel" - "Taylor Hawkins" - "Chris Shiflett" - "Pat Smear" - "Rami Jaffee" -``` - -###### Does it present the right members as above? - -##### Try to trigger an event using some kind of action (ex: Clicking the mouse over a certain element, pressing a key on the keyboard, resizing or closing the browser window, a form being submitted, an error occurring, etc). - -###### Does the event responds as expected? - -###### Did the server behaved as expected?(did not crashed) - -###### Does the server use the right [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)? - -###### Has the website runned without crashing at anytime? - -###### Are all the pages working? (Absence of 404 page?) - -###### Does the project handle [HTTP status 400 - Bad Requests](https://kinsta.com/knowledgebase/400-bad-request/#causes)? - -###### Does the project handle [HTTP status 500 - Internal Server Errors](https://www.restapitutorial.com/httpstatuscodes.html)? - -###### Is the communication between server and client well established? - -###### Does the server present all the needed handlers and patterns for the http requests? - -###### As an auditor, is this project up to every standard? If not, why are you failing the project?(Empty Work, Incomplete Work, Invalid compilation, Cheating, Crashing, Leaks) - -#### General - -###### +Does the event system run as asynchronous? (usage of go routines and channels) - -###### +Is the site hosted or deployed? Can you access the website through a DNS (Domain Name System)? - -#### Basic - -###### +Does the project runs quickly and effectively? (Favoring recursive, no unnecessary data requests, etc) - -###### +Does the code obey the [good practices](https://public.01-edu.org/subjects/good-practices.en)? - -###### +Is there a test file for this code? - -#### Social - -###### +Did you learn anything from this project? - -###### +Can it be open-sourced / be used for other sources? - -###### +Would you recommend/nominate this program as an example for the rest of the school? +#### Functional + +###### Has the requirement for the allowed packages been respected? (Reminder for this project: (only [standard packages](https://golang.org/pkg/) + +###### Is the data from the artists being used? + +###### Is data from the relations being used? + +##### Try to see the "members" for the artist/band `"Queen"` + +``` + "Freddie Mercury", + "Brian May", + "John Daecon", + "Roger Meddows-Taylor", + "Mike Grose", + "Barry Mitchell", + "Doug Fogie" +``` + +###### Does it present the right "member", as above? + +##### Try to see the "firstAlbum" for the artist/band `"Gorillaz"` + +``` + "26-03-2001" +``` + +###### Does it present the right date for the "firstAlbum", as above? + +##### Try to see the "locations" for the artist/band `"Travis Scott"` + +``` + "santiago-chile" + "sao_paulo-brasil" + "los_angeles-usa" + "houston-usa" + "atlanta-usa" + "new_orleans-usa" + "philadelphia-usa" + "london-uk" + "frauenfeld-switzerland" + "turku-finland" +``` + +###### Does it present the right "locations" as above? + +##### Try to see the ""members"" for the artist/band `"Foo Fighters"`. + +``` + "Dave Grohl" + "Nate Mendel" + "Taylor Hawkins" + "Chris Shiflett" + "Pat Smear" + "Rami Jaffee" +``` + +###### Does it present the right members as above? + +##### Try to trigger an event using some kind of action (ex: Clicking the mouse over a certain element, pressing a key on the keyboard, resizing or closing the browser window, a form being submitted, an error occurring, etc). + +###### Does the event responds as expected? + +###### Did the server behaved as expected?(did not crashed) + +###### Does the server use the right [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)? + +###### Has the website runned without crashing at anytime? + +###### Are all the pages working? (Absence of 404 page?) + +###### Does the project handle [HTTP status 400 - Bad Requests](https://kinsta.com/knowledgebase/400-bad-request/#causes)? + +###### Does the project handle [HTTP status 500 - Internal Server Errors](https://www.restapitutorial.com/httpstatuscodes.html)? + +###### Is the communication between server and client well established? + +###### Does the server present all the needed handlers and patterns for the http requests? + +###### As an auditor, is this project up to every standard? If not, why are you failing the project?(Empty Work, Incomplete Work, Invalid compilation, Cheating, Crashing, Leaks) + +#### General + +###### +Does the event system run as asynchronous? (usage of go routines and channels) + +###### +Is the site hosted or deployed? Can you access the website through a DNS (Domain Name System)? + +#### Basic + +###### +Does the project runs quickly and effectively? (Favoring recursive, no unnecessary data requests, etc) + +###### +Does the code obey the [good practices](https://public.01-edu.org/subjects/good-practices.en)? + +###### +Is there a test file for this code? + +#### Social + +###### +Did you learn anything from this project? + +###### +Can it be open-sourced / be used for other sources? + +###### +Would you recommend/nominate this program as an example for the rest of the school? diff --git a/subjects/index-of.en.md b/subjects/index-of.en.md index 8922e5a62..89c7b78a1 100644 --- a/subjects/index-of.en.md +++ b/subjects/index-of.en.md @@ -1,32 +1,32 @@ -## Index Of - -### Instructions - -Create 3 functions: -- `indexOf` that returns the index of the first occurence of a value -- `lastIndexOf` that returns the index of the last occurence of a value -- `includes` that returns true if the value was found in the array - -> If a value is not found, the returned index is -1 - -> functions should have an array element as first argument, -> both `indexOf` and `lastIndexOf` take an additional `fromIndex` argument -> that allows you to begin searching from a specific index. - - -### Notions - -- [devdocs.io/javascript/global_objects/array/indexof](https://devdocs.io/javascript/global_objects/array/indexof) -- [devdocs.io/javascript/global_objects/array/lastindexof](https://devdocs.io/javascript/global_objects/array/lastindexof) -- [devdocs.io/javascript/global_objects/array/includes](https://devdocs.io/javascript/global_objects/array/includes) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -Array.prototype.indexOf = undefined -Array.prototype.lastIndexOf = undefined -Array.prototype.includes = undefined -``` +## Index Of + +### Instructions + +Create 3 functions: +- `indexOf` that returns the index of the first occurence of a value +- `lastIndexOf` that returns the index of the last occurence of a value +- `includes` that returns true if the value was found in the array + +> If a value is not found, the returned index is -1 + +> functions should have an array element as first argument, +> both `indexOf` and `lastIndexOf` take an additional `fromIndex` argument +> that allows you to begin searching from a specific index. + + +### Notions + +- [devdocs.io/javascript/global_objects/array/indexof](https://devdocs.io/javascript/global_objects/array/indexof) +- [devdocs.io/javascript/global_objects/array/lastindexof](https://devdocs.io/javascript/global_objects/array/lastindexof) +- [devdocs.io/javascript/global_objects/array/includes](https://devdocs.io/javascript/global_objects/array/includes) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +Array.prototype.indexOf = undefined +Array.prototype.lastIndexOf = undefined +Array.prototype.includes = undefined +``` diff --git a/subjects/interpolation.en.md b/subjects/interpolation.en.md index be020834a..37f586b07 100644 --- a/subjects/interpolation.en.md +++ b/subjects/interpolation.en.md @@ -1,45 +1,45 @@ -## Interpolation - -### Instructions - -Create a function called `interpolation` that takes an object with 5 properties -`step`, `start`, `end`, `callback` and `duration`. -This function must calculate the interpolation points, (x, y), -from the `start` position to `end` position depending on the number of `steps`. -All the points must be calculated in the duration time. - -For each interpolation point you must execute and pass as parameters to the callback the interpolation point ([x, y]) - - -### Example - -``` -steps = 5 -start = 0 -end = 1 -duration = 10 - - t - | -10 |___________________. <- execute callback([1.0, 10]) - | | - | | - 8 |_______________. | - | | | - | | | - 6 |___________. | | - | | | | - | | | | - 4 |_______. | | | - | | | | | - | | | | | - 2 |___. | | | | - | | | | | | - |___|___|___|___|___|__d - 0 0.2 0.4 0.6 0.8 1 -``` - - -### Notions - -- [javascript.info/settimeout-setinterval](https://javascript.info/settimeout-setinterval) +## Interpolation + +### Instructions + +Create a function called `interpolation` that takes an object with 5 properties +`step`, `start`, `end`, `callback` and `duration`. +This function must calculate the interpolation points, (x, y), +from the `start` position to `end` position depending on the number of `steps`. +All the points must be calculated in the duration time. + +For each interpolation point you must execute and pass as parameters to the callback the interpolation point ([x, y]) + + +### Example + +``` +steps = 5 +start = 0 +end = 1 +duration = 10 + + t + | +10 |___________________. <- execute callback([1.0, 10]) + | | + | | + 8 |_______________. | + | | | + | | | + 6 |___________. | | + | | | | + | | | | + 4 |_______. | | | + | | | | | + | | | | | + 2 |___. | | | | + | | | | | | + |___|___|___|___|___|__d + 0 0.2 0.4 0.6 0.8 1 +``` + + +### Notions + +- [javascript.info/settimeout-setinterval](https://javascript.info/settimeout-setinterval) diff --git a/subjects/invert.en.md b/subjects/invert.en.md index 2f07a867e..0f691b2ed 100644 --- a/subjects/invert.en.md +++ b/subjects/invert.en.md @@ -1,9 +1,9 @@ -## Invert - -### Instructions - -Create a function called `invert` that inverts the object keys and values. - -### Notions - -- [devdocs.io/javascript/global_objects/object](https://devdocs.io/javascript/global_objects/object) +## Invert + +### Instructions + +Create a function called `invert` that inverts the object keys and values. + +### Notions + +- [devdocs.io/javascript/global_objects/object](https://devdocs.io/javascript/global_objects/object) diff --git a/subjects/ion-out.en.md b/subjects/ion-out.en.md index 15a4b1574..3780be46f 100644 --- a/subjects/ion-out.en.md +++ b/subjects/ion-out.en.md @@ -1,11 +1,11 @@ -## Ion Out - -### Instructions - -Make a function `ionOut` that receives a string and returns an array with every -word containing 'ion' following a t, without the 'ion'. - - -### Notions - -- [github.com/ziishaned/learn-regex#4-lookarounds](https://github.com/ziishaned/learn-regex#4-lookarounds) +## Ion Out + +### Instructions + +Make a function `ionOut` that receives a string and returns an array with every +word containing 'ion' following a t, without the 'ion'. + + +### Notions + +- [github.com/ziishaned/learn-regex#4-lookarounds](https://github.com/ziishaned/learn-regex#4-lookarounds) diff --git a/subjects/its-a-match.en.md b/subjects/its-a-match.en.md index a11c2c6fd..528e58247 100644 --- a/subjects/its-a-match.en.md +++ b/subjects/its-a-match.en.md @@ -1,21 +1,21 @@ -## Its A Match - -### Instructions - -Create 4 regular expression in variables: - -- `normal` matches with the expression 'hi'. - -- `begin` matches with the expression 'hi', - only when it is in the beginning. - -- `end` matches with the expression 'hi', - only when it is in the end. - -- `beginEnd` matches with the expression 'hi', - only when it is in the beginning and the end. - - -### Notions - -- [github.com/ziishaned/learn-regex#28-anchors](https://github.com/ziishaned/learn-regex#28-anchors) +## Its A Match + +### Instructions + +Create 4 regular expression in variables: + +- `normal` matches with the expression 'hi'. + +- `begin` matches with the expression 'hi', + only when it is in the beginning. + +- `end` matches with the expression 'hi', + only when it is in the end. + +- `beginEnd` matches with the expression 'hi', + only when it is in the beginning and the end. + + +### Notions + +- [github.com/ziishaned/learn-regex#28-anchors](https://github.com/ziishaned/learn-regex#28-anchors) diff --git a/subjects/keep-cut.en.md b/subjects/keep-cut.en.md index 83d6bd17d..6fbb9d0de 100644 --- a/subjects/keep-cut.en.md +++ b/subjects/keep-cut.en.md @@ -1,26 +1,26 @@ -## Keep Cut - -### Instructions - -Create the `cutFirst` function that takes a string -and remove the 2 first characters. - -Create the `cutLast` function that takes a string -and remove the 2 last characters. - -Create the `cutFirstLast` function that takes a string as parameter -and remove the 2 first characters and 2 last characters. - -Create a `keepFirst` function that takes a string as parameter -and return the string only keeping the 2 first characters. - -Create a `keepLast` function that takes a string as parameter -and return the string only keeping the 2 last characters. - -Create a `keepFirstLast` function that takes a string as parameter -and only keep 2 first characters and 2 last characters. - - -### Notions - -- [devdocs.io/javascript/global_objects/array/slice](https://devdocs.io/javascript/global_objects/array/slice) +## Keep Cut + +### Instructions + +Create the `cutFirst` function that takes a string +and remove the 2 first characters. + +Create the `cutLast` function that takes a string +and remove the 2 last characters. + +Create the `cutFirstLast` function that takes a string as parameter +and remove the 2 first characters and 2 last characters. + +Create a `keepFirst` function that takes a string as parameter +and return the string only keeping the 2 first characters. + +Create a `keepLast` function that takes a string as parameter +and return the string only keeping the 2 last characters. + +Create a `keepFirstLast` function that takes a string as parameter +and only keep 2 first characters and 2 last characters. + + +### Notions + +- [devdocs.io/javascript/global_objects/array/slice](https://devdocs.io/javascript/global_objects/array/slice) diff --git a/subjects/match-cron.en.md b/subjects/match-cron.en.md index a30606794..53d202052 100644 --- a/subjects/match-cron.en.md +++ b/subjects/match-cron.en.md @@ -1,32 +1,32 @@ -## Match Cron - -### Instructions - -Create a function called `matchCron` it takes a valid cron schedule string -and a valid date. \ -It returns true if the date match the pattern - -> You only have to implement numbers and `*`. \ -> other complex patterns are not required. - -Only valid pattern will be tested. - -### Example - -```js -matchCron('9 * * * *', new Date('2020-05-30 18:09:00')) // -> true -matchCron('9 * * * *', new Date('2020-05-30 19:09:00')) // -> true -matchCron('9 * * * *', new Date('2020-05-30 19:21:00')) // -> false -// | | | | | -// | | | | +- Day of the Week (range: 1-7, 1 standing for Monday) -// | | | +--- Month of the Year (range: 1-12) -// | | +----- Day of the Month (range: 1-31) -// | +------- Hour (range: 0-23) -// +--------- Minute (range: 0-59) -``` - - -### Notions - -- [crontab.guru](https://crontab.guru/) -- [devdocs.io/javascript/global_objects/date](https://devdocs.io/javascript/global_objects/date) +## Match Cron + +### Instructions + +Create a function called `matchCron` it takes a valid cron schedule string +and a valid date. \ +It returns true if the date match the pattern + +> You only have to implement numbers and `*`. \ +> other complex patterns are not required. + +Only valid pattern will be tested. + +### Example + +```js +matchCron('9 * * * *', new Date('2020-05-30 18:09:00')) // -> true +matchCron('9 * * * *', new Date('2020-05-30 19:09:00')) // -> true +matchCron('9 * * * *', new Date('2020-05-30 19:21:00')) // -> false +// | | | | | +// | | | | +- Day of the Week (range: 1-7, 1 standing for Monday) +// | | | +--- Month of the Year (range: 1-12) +// | | +----- Day of the Month (range: 1-31) +// | +------- Hour (range: 0-23) +// +--------- Minute (range: 0-59) +``` + + +### Notions + +- [crontab.guru](https://crontab.guru/) +- [devdocs.io/javascript/global_objects/date](https://devdocs.io/javascript/global_objects/date) diff --git a/subjects/more-or-less.en.md b/subjects/more-or-less.en.md index eae13eb53..edd0f67d6 100644 --- a/subjects/more-or-less.en.md +++ b/subjects/more-or-less.en.md @@ -1,15 +1,15 @@ -## More Or Less - -### Instructions - -Create 4 functions -- `more` that takes 1 argument and add 1 to it -- `less` that takes 1 argument and substract 1 to it -- `add` that takes 2 arguments and add them -- `sub` that takes 2 arguments and substract them - - -### Notions - -- [nan-academy.github.io/js-training/examples/functions](https://nan-academy.github.io/js-training/examples/functions.js) -- [nan-academy.github.io/js-training/examples/primitive-and-operators](https://nan-academy.github.io/js-training/examples/primitive-and-operators.js) +## More Or Less + +### Instructions + +Create 4 functions +- `more` that takes 1 argument and add 1 to it +- `less` that takes 1 argument and substract 1 to it +- `add` that takes 2 arguments and add them +- `sub` that takes 2 arguments and substract them + + +### Notions + +- [nan-academy.github.io/js-training/examples/functions](https://nan-academy.github.io/js-training/examples/functions.js) +- [nan-academy.github.io/js-training/examples/primitive-and-operators](https://nan-academy.github.io/js-training/examples/primitive-and-operators.js) diff --git a/subjects/mutability.en.md b/subjects/mutability.en.md index 5aca03597..022c29d2b 100644 --- a/subjects/mutability.en.md +++ b/subjects/mutability.en.md @@ -1,31 +1,31 @@ -## Mutability - -### Instructions - -Create a copy of the person object called clone1. -Create an other copy of the person object called clone2. - -Create a new variable `samePerson` with the same value as `person`. - -Increase by one the property age of `person` -and set his country to `'FR'`. - - -### Notions - -- [nan-academy.github.io/js-training/examples/set](https://nan-academy.github.io/js-training/examples/set.js) -- [nan-academy.github.io/js-training/examples/get](https://nan-academy.github.io/js-training/examples/get.js) -- [nan-academy.github.io/js-training/examples/data-structures](https://nan-academy.github.io/js-training/examples/data-structures.js) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -const person = { - name: 'Rick', - age: 77, - country: 'US', -} -``` +## Mutability + +### Instructions + +Create a copy of the person object called clone1. +Create an other copy of the person object called clone2. + +Create a new variable `samePerson` with the same value as `person`. + +Increase by one the property age of `person` +and set his country to `'FR'`. + + +### Notions + +- [nan-academy.github.io/js-training/examples/set](https://nan-academy.github.io/js-training/examples/set.js) +- [nan-academy.github.io/js-training/examples/get](https://nan-academy.github.io/js-training/examples/get.js) +- [nan-academy.github.io/js-training/examples/data-structures](https://nan-academy.github.io/js-training/examples/data-structures.js) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +const person = { + name: 'Rick', + age: 77, + country: 'US', +} +``` diff --git a/subjects/nasa.en.md b/subjects/nasa.en.md index 5b5e5f9fc..34acdec56 100644 --- a/subjects/nasa.en.md +++ b/subjects/nasa.en.md @@ -1,15 +1,15 @@ -## Nasa - -### Instructions - -Create a `nasa` function that takes a number `N` as a parameter and returns -a string with all numbers from 1 to the `N` separated by whitespace, with three exceptions: -- For numbers divisible by 3, add 'NA'. -- For numbers divisible by 5, add 'SA'. -- For the number that are divisible by 3 and 5 add 'NASA'. - - -### Notions - -- [nan-academy.github.io/js-training/examples/loops](https://nan-academy.github.io/js-training/examples/loops.js) -- [nan-academy.github.io/js-training/examples/recursion](https://nan-academy.github.io/js-training/examples/recursion.js) +## Nasa + +### Instructions + +Create a `nasa` function that takes a number `N` as a parameter and returns +a string with all numbers from 1 to the `N` separated by whitespace, with three exceptions: +- For numbers divisible by 3, add 'NA'. +- For numbers divisible by 5, add 'SA'. +- For the number that are divisible by 3 and 5 add 'NASA'. + + +### Notions + +- [nan-academy.github.io/js-training/examples/loops](https://nan-academy.github.io/js-training/examples/loops.js) +- [nan-academy.github.io/js-training/examples/recursion](https://nan-academy.github.io/js-training/examples/recursion.js) diff --git a/subjects/primitives.en.md b/subjects/primitives.en.md index fa4ade9bc..0e61ee6b2 100644 --- a/subjects/primitives.en.md +++ b/subjects/primitives.en.md @@ -1,15 +1,15 @@ -## Primitives - -### Instructions - -Create a constant variable for each primitives: -- `str` for `String` -- `num` for `Number` -- `bool` for `Boolean` -- `undef` for `undefined` - - -### Notions - -- [nan-academy.github.io/js-training/examples/primitive-and-operators](https://nan-academy.github.io/js-training/examples/primitive-and-operators.js) -- [nan-academy.github.io/js-training/examples/variables](https://nan-academy.github.io/js-training/examples/variables.js) +## Primitives + +### Instructions + +Create a constant variable for each primitives: +- `str` for `String` +- `num` for `Number` +- `bool` for `Boolean` +- `undef` for `undefined` + + +### Notions + +- [nan-academy.github.io/js-training/examples/primitive-and-operators](https://nan-academy.github.io/js-training/examples/primitive-and-operators.js) +- [nan-academy.github.io/js-training/examples/variables](https://nan-academy.github.io/js-training/examples/variables.js) diff --git a/subjects/pyramid.en.md b/subjects/pyramid.en.md index b43893ed2..8231d3a16 100644 --- a/subjects/pyramid.en.md +++ b/subjects/pyramid.en.md @@ -1,27 +1,27 @@ -## Pyramid - -### Instructions - -Create a `pyramid` function that takes a string and a number as parameters -and return a pyramid constructed by the string passed as argument and with the depth -of the number passed as argument. - -Just like triangle - -### Output example - -- `*` character and depth of 5 : - -``` - * - *** - ***** - ******* -********* -``` -> No new line in last line - -### Notions - -- [nan-academy.github.io/js-training/examples/loops](https://nan-academy.github.io/js-training/examples/loops.js) -- [nan-academy.github.io/js-training/examples/recursion](https://nan-academy.github.io/js-training/examples/recursion.js) +## Pyramid + +### Instructions + +Create a `pyramid` function that takes a string and a number as parameters +and return a pyramid constructed by the string passed as argument and with the depth +of the number passed as argument. + +Just like triangle + +### Output example + +- `*` character and depth of 5 : + +``` + * + *** + ***** + ******* +********* +``` +> No new line in last line + +### Notions + +- [nan-academy.github.io/js-training/examples/loops](https://nan-academy.github.io/js-training/examples/loops.js) +- [nan-academy.github.io/js-training/examples/recursion](https://nan-academy.github.io/js-training/examples/recursion.js) diff --git a/subjects/race.en.md b/subjects/race.en.md index c16ea9c32..5ceaa0b62 100644 --- a/subjects/race.en.md +++ b/subjects/race.en.md @@ -1,24 +1,24 @@ -## Race - -### Instructions - -Create a function `race` that works like `Promise.race` - -Create a function `some` that takes an array of promises or values -and a number and return the first resolved values up to the number given. -> Empty array or a count of 0 return a promise resolving to `undefined` - - -### Notions - -- [nan-academy.github.io/js-training/examples/promise](https://nan-academy.github.io/js-training/examples/promise.js) -- [devdocs.io/javascript/global_objects/promise/race](https://devdocs.io/javascript/global_objects/promise/race) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -Promise.race = undefined -``` +## Race + +### Instructions + +Create a function `race` that works like `Promise.race` + +Create a function `some` that takes an array of promises or values +and a number and return the first resolved values up to the number given. +> Empty array or a count of 0 return a promise resolving to `undefined` + + +### Notions + +- [nan-academy.github.io/js-training/examples/promise](https://nan-academy.github.io/js-training/examples/promise.js) +- [devdocs.io/javascript/global_objects/promise/race](https://devdocs.io/javascript/global_objects/promise/race) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +Promise.race = undefined +``` diff --git a/subjects/repeat.en.md b/subjects/repeat.en.md index 2d9d21385..53e30643d 100644 --- a/subjects/repeat.en.md +++ b/subjects/repeat.en.md @@ -1,24 +1,24 @@ -## Repeat - -### Instructions - -Create a `repeat` function that takes a string and a number as parameters -and return the repeated string by the given number -Like the method [developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat) -Of course you may not use the method directly - - -### Notions - -- [nan-academy.github.io/js-training/examples/loops](https://nan-academy.github.io/js-training/examples/loops.js) -- [nan-academy.github.io/js-training/examples/recursion](https://nan-academy.github.io/js-training/examples/recursion.js) -- [devdocs.io/javascript/global_objects/string/repeat](https://devdocs.io/javascript/global_objects/string/repeat) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -String.prototype.repeat = undefined -``` +## Repeat + +### Instructions + +Create a `repeat` function that takes a string and a number as parameters +and return the repeated string by the given number +Like the method [developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat) +Of course you may not use the method directly + + +### Notions + +- [nan-academy.github.io/js-training/examples/loops](https://nan-academy.github.io/js-training/examples/loops.js) +- [nan-academy.github.io/js-training/examples/recursion](https://nan-academy.github.io/js-training/examples/recursion.js) +- [devdocs.io/javascript/global_objects/string/repeat](https://devdocs.io/javascript/global_objects/string/repeat) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +String.prototype.repeat = undefined +``` diff --git a/subjects/replica.en.md b/subjects/replica.en.md index f098b5e97..5e2a51bd5 100644 --- a/subjects/replica.en.md +++ b/subjects/replica.en.md @@ -1,12 +1,12 @@ -## Replica - -### Instructions - -Create a function called `replica` that allows you to deep assign the values of all properties from one or more -objects to a target object. - -Attention with the shallow copies. - -### Notions - -- [nan-academy.github.io/js-training/examples/data-structures](https://nan-academy.github.io/js-training/examples/data-structures.js) +## Replica + +### Instructions + +Create a function called `replica` that allows you to deep assign the values of all properties from one or more +objects to a target object. + +Attention with the shallow copies. + +### Notions + +- [nan-academy.github.io/js-training/examples/data-structures](https://nan-academy.github.io/js-training/examples/data-structures.js) diff --git a/subjects/returns.en.md b/subjects/returns.en.md index f86069d73..d3950176a 100644 --- a/subjects/returns.en.md +++ b/subjects/returns.en.md @@ -1,15 +1,15 @@ -## Returns - -### Instructions - -Create the following functions: - -- `id` that takes one argument and return it -- `getLength` that takes an array or a string and return its length - - -### Notions - -- [nan-academy.github.io/js-training/examples/functions](https://nan-academy.github.io/js-training/examples/functions.js) -- [nan-academy.github.io/js-training/examples/data-structures](https://nan-academy.github.io/js-training/examples/data-structures.js) -- [nan-academy.github.io/js-training/examples/get](https://nan-academy.github.io/js-training/examples/get.js) +## Returns + +### Instructions + +Create the following functions: + +- `id` that takes one argument and return it +- `getLength` that takes an array or a string and return its length + + +### Notions + +- [nan-academy.github.io/js-training/examples/functions](https://nan-academy.github.io/js-training/examples/functions.js) +- [nan-academy.github.io/js-training/examples/data-structures](https://nan-academy.github.io/js-training/examples/data-structures.js) +- [nan-academy.github.io/js-training/examples/get](https://nan-academy.github.io/js-training/examples/get.js) diff --git a/subjects/series.en.md b/subjects/series.en.md index a0bf3873f..ec7660f98 100644 --- a/subjects/series.en.md +++ b/subjects/series.en.md @@ -1,11 +1,11 @@ -## Series - -### Instructions - -Create a function `series` that works takes an array of async functions. -It must execute them in series and return the results in order. - - -### Notions - -- [nan-academy.github.io/js-training/examples/promise](https://nan-academy.github.io/js-training/examples/promise.js) +## Series + +### Instructions + +Create a function `series` that works takes an array of async functions. +It must execute them in series and return the results in order. + + +### Notions + +- [nan-academy.github.io/js-training/examples/promise](https://nan-academy.github.io/js-training/examples/promise.js) diff --git a/subjects/sign.en.md b/subjects/sign.en.md index af68bfd02..554be8d8e 100644 --- a/subjects/sign.en.md +++ b/subjects/sign.en.md @@ -1,27 +1,27 @@ -## Sign - -### Instructions - -Create the `sign` function that takes one number argument -and return 1 if the number is positive, -1 if the number is negative -and 0 if the number is exactly 0 -You must not just use `Math.sign`, make your own. - -Create the `sameSign` function that takes 2 numbers as arguments and return true -if they both have the same sign, or false otherwise. - - -### Notions - -- [nan-academy.github.io/js-training/examples/functions](https://nan-academy.github.io/js-training/examples/functions.js) -- [nan-academy.github.io/js-training/examples/if-else](https://nan-academy.github.io/js-training/examples/if-else.js) -- [devdocs.io/javascript/global_objects/math/sign](https://devdocs.io/javascript/global_objects/math/sign) - - -### Code provided - -> all code provided will be added to your solution and doesn't need to be submited. - -```js -Math.sign = undefined -``` +## Sign + +### Instructions + +Create the `sign` function that takes one number argument +and return 1 if the number is positive, -1 if the number is negative +and 0 if the number is exactly 0 +You must not just use `Math.sign`, make your own. + +Create the `sameSign` function that takes 2 numbers as arguments and return true +if they both have the same sign, or false otherwise. + + +### Notions + +- [nan-academy.github.io/js-training/examples/functions](https://nan-academy.github.io/js-training/examples/functions.js) +- [nan-academy.github.io/js-training/examples/if-else](https://nan-academy.github.io/js-training/examples/if-else.js) +- [devdocs.io/javascript/global_objects/math/sign](https://devdocs.io/javascript/global_objects/math/sign) + + +### Code provided + +> all code provided will be added to your solution and doesn't need to be submited. + +```js +Math.sign = undefined +``` diff --git a/subjects/tetris-optimizer/badexample00.md b/subjects/tetris-optimizer/badexample00.md index df6897719..fea371898 100644 --- a/subjects/tetris-optimizer/badexample00.md +++ b/subjects/tetris-optimizer/badexample00.md @@ -1,11 +1,11 @@ -## bad example 00 - -- Create your file and copy the example into it. - -``` -#### -...# -.... -.... - -``` +## bad example 00 + +- Create your file and copy the example into it. + +``` +#### +...# +.... +.... + +``` diff --git a/subjects/tetris-optimizer/badexample01.md b/subjects/tetris-optimizer/badexample01.md index d2cc43cc1..51752b33c 100644 --- a/subjects/tetris-optimizer/badexample01.md +++ b/subjects/tetris-optimizer/badexample01.md @@ -1,11 +1,11 @@ -## bad example 01 - -- Create your file and copy the example into it. - -``` -...# -..#. -.#.. -#... - -``` +## bad example 01 + +- Create your file and copy the example into it. + +``` +...# +..#. +.#.. +#... + +``` diff --git a/subjects/tetris-optimizer/badexample02.md b/subjects/tetris-optimizer/badexample02.md index f0f583e01..68490dcfe 100644 --- a/subjects/tetris-optimizer/badexample02.md +++ b/subjects/tetris-optimizer/badexample02.md @@ -1,11 +1,11 @@ -## bad example 02 - -- Create your file and copy the example into it. - -``` -...# -...# -#... -#... - -``` +## bad example 02 + +- Create your file and copy the example into it. + +``` +...# +...# +#... +#... + +``` diff --git a/subjects/tetris-optimizer/badexample03.md b/subjects/tetris-optimizer/badexample03.md index cdf4cf274..3ed0d9fb5 100644 --- a/subjects/tetris-optimizer/badexample03.md +++ b/subjects/tetris-optimizer/badexample03.md @@ -1,11 +1,11 @@ -## bad example 03 - -- Create your file and copy the example into it. - -``` -.... -.... -.... -.... - -``` +## bad example 03 + +- Create your file and copy the example into it. + +``` +.... +.... +.... +.... + +``` diff --git a/subjects/tetris-optimizer/badexample04.md b/subjects/tetris-optimizer/badexample04.md index b5469d516..02295009e 100644 --- a/subjects/tetris-optimizer/badexample04.md +++ b/subjects/tetris-optimizer/badexample04.md @@ -1,11 +1,11 @@ -## bad example 04 - -- Create your file and copy the example into it. - -``` -..## -.... -.... -##.. - -``` +## bad example 04 + +- Create your file and copy the example into it. + +``` +..## +.... +.... +##.. + +``` diff --git a/subjects/tetris-optimizer/goodexample00.md b/subjects/tetris-optimizer/goodexample00.md index e962b6b91..0ba0c8c97 100644 --- a/subjects/tetris-optimizer/goodexample00.md +++ b/subjects/tetris-optimizer/goodexample00.md @@ -1,11 +1,11 @@ -## good example 00 - -- Create your file and copy the example into it. - -```console -.... -.##. -.##. -.... - -``` +## good example 00 + +- Create your file and copy the example into it. + +```console +.... +.##. +.##. +.... + +``` diff --git a/subjects/tetris-optimizer/goodexample01.md b/subjects/tetris-optimizer/goodexample01.md index db952e36c..36ee51682 100644 --- a/subjects/tetris-optimizer/goodexample01.md +++ b/subjects/tetris-optimizer/goodexample01.md @@ -1,26 +1,26 @@ -## good example 01 - -- Create your file and copy the example into it. - -``` -...# -...# -...# -...# - -.... -.... -.... -#### - -.### -...# -.... -.... - -.... -..## -.##. -.... - -``` +## good example 01 + +- Create your file and copy the example into it. + +``` +...# +...# +...# +...# + +.... +.... +.... +#### + +.### +...# +.... +.... + +.... +..## +.##. +.... + +``` diff --git a/subjects/tetris-optimizer/goodexample02.md b/subjects/tetris-optimizer/goodexample02.md index 1e5ffab8a..13b4db0b6 100644 --- a/subjects/tetris-optimizer/goodexample02.md +++ b/subjects/tetris-optimizer/goodexample02.md @@ -1,46 +1,46 @@ -## good example 02 - -- Create your file and copy the example into it. - -``` -...# -...# -...# -...# - -.... -.... -.... -#### - -.### -...# -.... -.... - -.... -..## -.##. -.... - -.... -.##. -.##. -.... - -.... -.... -##.. -.##. - -##.. -.#.. -.#.. -.... - -.... -###. -.#.. -.... - -``` +## good example 02 + +- Create your file and copy the example into it. + +``` +...# +...# +...# +...# + +.... +.... +.... +#### + +.### +...# +.... +.... + +.... +..## +.##. +.... + +.... +.##. +.##. +.... + +.... +.... +##.. +.##. + +##.. +.#.. +.#.. +.... + +.... +###. +.#.. +.... + +``` diff --git a/subjects/tetris-optimizer/goodexample03.md b/subjects/tetris-optimizer/goodexample03.md index de955d635..4dc77b405 100644 --- a/subjects/tetris-optimizer/goodexample03.md +++ b/subjects/tetris-optimizer/goodexample03.md @@ -1,61 +1,61 @@ -## good example 03 - -- Create your file and copy the example into it. - -``` -.... -.##. -.##. -.... - -...# -...# -...# -...# - -.... -..## -.##. -.... - -.... -.##. -.##. -.... - -.... -..#. -.##. -.#.. - -.### -...# -.... -.... - -##.. -.#.. -.#.. -.... - -.... -..## -.##. -.... - -##.. -.#.. -.#.. -.... - -.#.. -.##. -..#. -.... - -.... -###. -.#.. -.... - -``` +## good example 03 + +- Create your file and copy the example into it. + +``` +.... +.##. +.##. +.... + +...# +...# +...# +...# + +.... +..## +.##. +.... + +.... +.##. +.##. +.... + +.... +..#. +.##. +.#.. + +.### +...# +.... +.... + +##.. +.#.. +.#.. +.... + +.... +..## +.##. +.... + +##.. +.#.. +.#.. +.... + +.#.. +.##. +..#. +.... + +.... +###. +.#.. +.... + +``` diff --git a/subjects/tetris-optimizer/tetris-optimizer.audit.en.md b/subjects/tetris-optimizer/tetris-optimizer.audit.en.md index 1bec4dabd..165a4e243 100644 --- a/subjects/tetris-optimizer/tetris-optimizer.audit.en.md +++ b/subjects/tetris-optimizer/tetris-optimizer.audit.en.md @@ -1,83 +1,83 @@ -#### Functional - -###### Has the requirement for the allowed packages been respected? (Reminder for this project: (only [standard packages](https://golang.org/pkg/) - -##### Try [bad example 00](https://public.01-edu.org/subjects/tetris-optimizer/badexample00). - -`ERROR` - -###### Does the program prints the value above? - -##### Try [bad example 01](https://public.01-edu.org/subjects/tetris-optimizer/badexample01). - -`ERROR` - -###### Does the program prints the value above? - -##### Try [bad example 02](https://public.01-edu.org/subjects/tetris-optimizer/badexample02). - -`ERROR` - -###### Does the program prints the value above? - -##### Try [bad example 03](https://public.01-edu.org/subjects/tetris-optimizer/badexample03). - -`ERROR` - -###### Does the program prints the value above? - -##### Try [bad example 04](https://public.01-edu.org/subjects/tetris-optimizer/badexample04). - -`ERROR` - -###### Does the program prints the value above? - -##### Try [bad format](https://public.01-edu.org/subjects/tetris-optimizer/badformat). - -`ERROR` - -###### Does the program prints the value above? - -##### Try [good example 00](https://public.01-edu.org/subjects/tetris-optimizer/goodexample00). - -###### Does the result contain 0 empty spaces (0 '.')? - -##### Try [good example 01](https://public.01-edu.org/subjects/tetris-optimizer/goodexample01). - -###### Does the result contain 9 empty spaces (9 '.')? - -##### Try [good example 02](https://public.01-edu.org/subjects/tetris-optimizer/goodexample02). - -###### Does the result contain 4 empty spaces (4 '.') and a time limit lesser or equal to the one in the [good practices](https://public.01-edu.org/subjects/good-practices.en)? - -##### Try [good example 03](https://public.01-edu.org/subjects/tetris-optimizer/goodexample03). - -###### Does the result contain 5 empty spaces (5 '.') and a time limit lesser or equal to the one in the [good practices](https://public.01-edu.org/subjects/good-practices.en)? - -##### Try [hard example](https://public.01-edu.org/subjects/tetris-optimizer/hardexam). - -###### Does the result contain 1 empty spaces (1 '.') and a time limit lesser or equal to the one in the [good practices](https://public.01-edu.org/subjects/good-practices.en)? - -###### Are all of the Tetrominos contained in the test file, present in the output? - -###### Different characters correspond to different Tetrominos? - -###### Does one Tetromino has only one character? - -###### As an auditor, is this project up to every standard? If not, why are you failing the project?(Empty Work, Incomplete Work, Invalid compilation, Cheating, Crashing, Leaks) - -#### Basic - -###### +Does the project runs quickly and effectively (Favoring of recursive, no unnecessary data requests, etc.)? - -###### +Is there a test file for this code? - -###### +Are the tests checking each possible case? - -###### +Does the code obey the [good practices](https://public.01-edu.org/subjects/good-practices.en)? - -#### Social - -###### +Did you learn anything from this project? - -###### +Would you recommend/nominate this program as an example for the rest of the school? +#### Functional + +###### Has the requirement for the allowed packages been respected? (Reminder for this project: (only [standard packages](https://golang.org/pkg/) + +##### Try [bad example 00](https://public.01-edu.org/subjects/tetris-optimizer/badexample00). + +`ERROR` + +###### Does the program prints the value above? + +##### Try [bad example 01](https://public.01-edu.org/subjects/tetris-optimizer/badexample01). + +`ERROR` + +###### Does the program prints the value above? + +##### Try [bad example 02](https://public.01-edu.org/subjects/tetris-optimizer/badexample02). + +`ERROR` + +###### Does the program prints the value above? + +##### Try [bad example 03](https://public.01-edu.org/subjects/tetris-optimizer/badexample03). + +`ERROR` + +###### Does the program prints the value above? + +##### Try [bad example 04](https://public.01-edu.org/subjects/tetris-optimizer/badexample04). + +`ERROR` + +###### Does the program prints the value above? + +##### Try [bad format](https://public.01-edu.org/subjects/tetris-optimizer/badformat). + +`ERROR` + +###### Does the program prints the value above? + +##### Try [good example 00](https://public.01-edu.org/subjects/tetris-optimizer/goodexample00). + +###### Does the result contain 0 empty spaces (0 '.')? + +##### Try [good example 01](https://public.01-edu.org/subjects/tetris-optimizer/goodexample01). + +###### Does the result contain 9 empty spaces (9 '.')? + +##### Try [good example 02](https://public.01-edu.org/subjects/tetris-optimizer/goodexample02). + +###### Does the result contain 4 empty spaces (4 '.') and a time limit lesser or equal to the one in the [good practices](https://public.01-edu.org/subjects/good-practices.en)? + +##### Try [good example 03](https://public.01-edu.org/subjects/tetris-optimizer/goodexample03). + +###### Does the result contain 5 empty spaces (5 '.') and a time limit lesser or equal to the one in the [good practices](https://public.01-edu.org/subjects/good-practices.en)? + +##### Try [hard example](https://public.01-edu.org/subjects/tetris-optimizer/hardexam). + +###### Does the result contain 1 empty spaces (1 '.') and a time limit lesser or equal to the one in the [good practices](https://public.01-edu.org/subjects/good-practices.en)? + +###### Are all of the Tetrominos contained in the test file, present in the output? + +###### Different characters correspond to different Tetrominos? + +###### Does one Tetromino has only one character? + +###### As an auditor, is this project up to every standard? If not, why are you failing the project?(Empty Work, Incomplete Work, Invalid compilation, Cheating, Crashing, Leaks) + +#### Basic + +###### +Does the project runs quickly and effectively (Favoring of recursive, no unnecessary data requests, etc.)? + +###### +Is there a test file for this code? + +###### +Are the tests checking each possible case? + +###### +Does the code obey the [good practices](https://public.01-edu.org/subjects/good-practices.en)? + +#### Social + +###### +Did you learn anything from this project? + +###### +Would you recommend/nominate this program as an example for the rest of the school? diff --git a/subjects/triangle.en.md b/subjects/triangle.en.md index 77d945e9a..cb49c721b 100644 --- a/subjects/triangle.en.md +++ b/subjects/triangle.en.md @@ -1,25 +1,25 @@ -## Triangle - -### Instructions - -Create a `triangle` function that takes a string and a number as parameters -and return a triangle constructed by the string passed as argument and with the depth -of the number passed as argument. - -### Output example - -- `*` character and depth of 5: - -``` -* -** -*** -**** -***** -``` -> No new line in last line - -### Notions - -- [nan-academy.github.io/js-training/examples/loops](https://nan-academy.github.io/js-training/examples/loops.js) -- [nan-academy.github.io/js-training/examples/recursion](https://nan-academy.github.io/js-training/examples/recursion.js) +## Triangle + +### Instructions + +Create a `triangle` function that takes a string and a number as parameters +and return a triangle constructed by the string passed as argument and with the depth +of the number passed as argument. + +### Output example + +- `*` character and depth of 5: + +``` +* +** +*** +**** +***** +``` +> No new line in last line + +### Notions + +- [nan-academy.github.io/js-training/examples/loops](https://nan-academy.github.io/js-training/examples/loops.js) +- [nan-academy.github.io/js-training/examples/recursion](https://nan-academy.github.io/js-training/examples/recursion.js) diff --git a/subjects/tron/ai/hard.js b/subjects/tron/ai/hard.js index 03f2f0e71..f7849257e 100644 --- a/subjects/tron/ai/hard.js +++ b/subjects/tron/ai/hard.js @@ -1,171 +1,171 @@ -/******************************* - * functions given to the students - ********************************/ -const SIZE = 100 -const MAP = new Int8Array(SIZE * SIZE) -const isFree = ({ x, y }) => MAP[y * SIZE + x] === 0 -const isOccupied = ({ x, y }) => MAP[y * SIZE + x] === 1 -const inBounds = (n) => n < SIZE && n >= 0 -const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) -const pickRandom = (arr) => arr[Math.floor(Math.random() * arr.length)] - -/*********** - * My functions - ************/ -const isAlley = ({ x, y }) => !isFree({ x, y }) || !isInBounds({ x, y }) - -// this functions will find the best path, so the path that has more empty spaces -// so use `isFree`, -const findBestPath = (state) => { - let arr = [] - let car = state.player.cardinal - // if it as a block on the symmetric position it must - // simulate the symmetric position and see witch path is the best - if ( - (car === 3 || car === 0) && - !isFree({ x: state.player.x - 1, y: state.player.y - 1 }) && - isFree({ x: state.player.x, y: state.player.y - 1 }) && - isFree({ x: state.player.x - 1, y: state.player.y }) - ) { - let xad = state.player.x - 1 - let yad = state.player.y - 1 - - let choose = [ - calDistance(xad + 1, yad, 1, 0), - calDistance(state.player.x, state.player.y - 1, car, 0), - calDistance(state.player.x - 1, state.player.y, car, 0), - calDistance(xad, yad + 1, 2, 0), - ] - let index = choose.indexOf(Math.max(...choose)) - return index === 0 || index === 1 - ? state.player.coords[0] - : state.player.coords[3] - } - if ( - (car === 1 || car === 0) && - !isFree({ x: state.player.x + 1, y: state.player.y - 1 }) && - isFree({ x: state.player.x, y: state.player.y - 1 }) && - isFree({ x: state.player.x + 1, y: state.player.y }) - ) { - let xad = state.player.x + 1 - let yad = state.player.y - 1 - // choose will save the biggest path to be chosen - // [ down, line1, line0, left ] - let choose = [ - calDistance(xad, yad + 1, 2, 0), - calDistance(state.player.x + 1, state.player.y, car, 0), - calDistance(state.player.x, state.player.y - 1, car, 0), - calDistance(xad - 1, yad, 3, 0), - ] - let index = choose.indexOf(Math.max(...choose)) - return index === 0 || index === 1 - ? state.player.coords[1] - : state.player.coords[0] - } - if ( - (car === 2 || car === 1) && - !isFree({ x: state.player.x + 1, y: state.player.y + 1 }) && - isFree({ x: state.player.x, y: state.player.y + 1 }) && - isFree({ x: state.player.x + 1, y: state.player.y }) - ) { - let xad = state.player.x + 1 - let yad = state.player.y + 1 - // choose will save the biggest path to be chosen - // [ left, line2, line1, up ] - let choose = [ - calDistance(xad - 1, yad, 3, 0), - calDistance(state.player.x, state.player.y + 1, car, 0), - calDistance(state.player.x + 1, state.player.y, car, 0), - calDistance(xad, yad - 1, 0, 0), - ] - let index = choose.indexOf(Math.max(...choose)) - return index === 0 || index === 1 - ? state.player.coords[2] - : state.player.coords[1] - } - if ( - (car === 2 || car === 3) && - !isFree({ x: state.player.x - 1, y: state.player.y + 1 }) && - isFree({ x: state.player.x, y: state.player.y + 1 }) && - isFree({ x: state.player.x - 1, y: state.player.y }) - ) { - let xad = state.player.x - 1 - let yad = state.player.y + 1 - // choose will save the biggest path to be chosen - // [ right, line2, line3, up ] - let choose = [ - calDistance(xad + 1, yad, 1, 0), - calDistance(state.player.x - 1, state.player.y, car, 0), - calDistance(state.player.x, state.player.y + 1, car, 0), - calDistance(xad, yad - 1, 0, 0), - ] - let index = choose.indexOf(Math.max(...choose)) - return index === 0 || index === 1 - ? state.player.coords[3] - : state.player.coords[2] - } - - for ({ x, y, cardinal } of state.player.coords) { - // if everything is ok it must continue with the best path - arr.push(calDistance(x, y, cardinal, 0)) - } - return state.player.coords[arr.indexOf(Math.max(...arr))] -} - -// recursion -const calDistance = (x, y, car, count) => { - if (car <= 0) { - if ( - isFree({ x, y }) && - isAlley({ x: x + 1, y }) && - isAlley({ x, y: y - 1 }) && - isAlley({ x: x - 1, y }) - ) - return -1 - return !isFree({ x, y }) || !inBounds(y - 1) - ? count - : calDistance(x, y - 1, car, count + 1) - } - if (car === 1) { - if ( - isFree({ x, y }) && - isAlley({ x, y: y + 1 }) && - isAlley({ x, y: y - 1 }) && - isAlley({ x: x + 1, y }) - ) - return -1 - return !isFree({ x, y }) || !inBounds(x + 1) - ? count - : calDistance(x + 1, y, car, count + 1) - } - if (car === 2) { - if ( - isFree({ x, y }) && - isAlley({ x: x - 1, y }) && - isAlley({ x, y: y + 1 }) && - isAlley({ x: x + 1, y }) - ) - return -1 - return !isFree({ x, y }) || !inBounds(y + 1) - ? count - : calDistance(x, y + 1, car, count + 1) - } - if (car === 3) { - if ( - isFree({ x, y }) && - isAlley({ x, y: y - 1 }) && - isAlley({ x: x - 1, y }) && - isAlley({ x, y: y + 1 }) - ) - return -1 - return !isFree({ x, y }) || !inBounds(x - 1) - ? count - : calDistance(x - 1, y, car, count + 1) - } -} - -const addToMap = ({ x, y }) => MAP[y * SIZE + x] = 1 -const update = (state) => { - state.players.forEach(addToMap) - findBestPath(state) -} +/******************************* + * functions given to the students + ********************************/ +const SIZE = 100 +const MAP = new Int8Array(SIZE * SIZE) +const isFree = ({ x, y }) => MAP[y * SIZE + x] === 0 +const isOccupied = ({ x, y }) => MAP[y * SIZE + x] === 1 +const inBounds = (n) => n < SIZE && n >= 0 +const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) +const pickRandom = (arr) => arr[Math.floor(Math.random() * arr.length)] + +/*********** + * My functions + ************/ +const isAlley = ({ x, y }) => !isFree({ x, y }) || !isInBounds({ x, y }) + +// this functions will find the best path, so the path that has more empty spaces +// so use `isFree`, +const findBestPath = (state) => { + let arr = [] + let car = state.player.cardinal + // if it as a block on the symmetric position it must + // simulate the symmetric position and see witch path is the best + if ( + (car === 3 || car === 0) && + !isFree({ x: state.player.x - 1, y: state.player.y - 1 }) && + isFree({ x: state.player.x, y: state.player.y - 1 }) && + isFree({ x: state.player.x - 1, y: state.player.y }) + ) { + let xad = state.player.x - 1 + let yad = state.player.y - 1 + + let choose = [ + calDistance(xad + 1, yad, 1, 0), + calDistance(state.player.x, state.player.y - 1, car, 0), + calDistance(state.player.x - 1, state.player.y, car, 0), + calDistance(xad, yad + 1, 2, 0), + ] + let index = choose.indexOf(Math.max(...choose)) + return index === 0 || index === 1 + ? state.player.coords[0] + : state.player.coords[3] + } + if ( + (car === 1 || car === 0) && + !isFree({ x: state.player.x + 1, y: state.player.y - 1 }) && + isFree({ x: state.player.x, y: state.player.y - 1 }) && + isFree({ x: state.player.x + 1, y: state.player.y }) + ) { + let xad = state.player.x + 1 + let yad = state.player.y - 1 + // choose will save the biggest path to be chosen + // [ down, line1, line0, left ] + let choose = [ + calDistance(xad, yad + 1, 2, 0), + calDistance(state.player.x + 1, state.player.y, car, 0), + calDistance(state.player.x, state.player.y - 1, car, 0), + calDistance(xad - 1, yad, 3, 0), + ] + let index = choose.indexOf(Math.max(...choose)) + return index === 0 || index === 1 + ? state.player.coords[1] + : state.player.coords[0] + } + if ( + (car === 2 || car === 1) && + !isFree({ x: state.player.x + 1, y: state.player.y + 1 }) && + isFree({ x: state.player.x, y: state.player.y + 1 }) && + isFree({ x: state.player.x + 1, y: state.player.y }) + ) { + let xad = state.player.x + 1 + let yad = state.player.y + 1 + // choose will save the biggest path to be chosen + // [ left, line2, line1, up ] + let choose = [ + calDistance(xad - 1, yad, 3, 0), + calDistance(state.player.x, state.player.y + 1, car, 0), + calDistance(state.player.x + 1, state.player.y, car, 0), + calDistance(xad, yad - 1, 0, 0), + ] + let index = choose.indexOf(Math.max(...choose)) + return index === 0 || index === 1 + ? state.player.coords[2] + : state.player.coords[1] + } + if ( + (car === 2 || car === 3) && + !isFree({ x: state.player.x - 1, y: state.player.y + 1 }) && + isFree({ x: state.player.x, y: state.player.y + 1 }) && + isFree({ x: state.player.x - 1, y: state.player.y }) + ) { + let xad = state.player.x - 1 + let yad = state.player.y + 1 + // choose will save the biggest path to be chosen + // [ right, line2, line3, up ] + let choose = [ + calDistance(xad + 1, yad, 1, 0), + calDistance(state.player.x - 1, state.player.y, car, 0), + calDistance(state.player.x, state.player.y + 1, car, 0), + calDistance(xad, yad - 1, 0, 0), + ] + let index = choose.indexOf(Math.max(...choose)) + return index === 0 || index === 1 + ? state.player.coords[3] + : state.player.coords[2] + } + + for ({ x, y, cardinal } of state.player.coords) { + // if everything is ok it must continue with the best path + arr.push(calDistance(x, y, cardinal, 0)) + } + return state.player.coords[arr.indexOf(Math.max(...arr))] +} + +// recursion +const calDistance = (x, y, car, count) => { + if (car <= 0) { + if ( + isFree({ x, y }) && + isAlley({ x: x + 1, y }) && + isAlley({ x, y: y - 1 }) && + isAlley({ x: x - 1, y }) + ) + return -1 + return !isFree({ x, y }) || !inBounds(y - 1) + ? count + : calDistance(x, y - 1, car, count + 1) + } + if (car === 1) { + if ( + isFree({ x, y }) && + isAlley({ x, y: y + 1 }) && + isAlley({ x, y: y - 1 }) && + isAlley({ x: x + 1, y }) + ) + return -1 + return !isFree({ x, y }) || !inBounds(x + 1) + ? count + : calDistance(x + 1, y, car, count + 1) + } + if (car === 2) { + if ( + isFree({ x, y }) && + isAlley({ x: x - 1, y }) && + isAlley({ x, y: y + 1 }) && + isAlley({ x: x + 1, y }) + ) + return -1 + return !isFree({ x, y }) || !inBounds(y + 1) + ? count + : calDistance(x, y + 1, car, count + 1) + } + if (car === 3) { + if ( + isFree({ x, y }) && + isAlley({ x, y: y - 1 }) && + isAlley({ x: x - 1, y }) && + isAlley({ x, y: y + 1 }) + ) + return -1 + return !isFree({ x, y }) || !inBounds(x - 1) + ? count + : calDistance(x - 1, y, car, count + 1) + } +} + +const addToMap = ({ x, y }) => MAP[y * SIZE + x] = 1 +const update = (state) => { + state.players.forEach(addToMap) + findBestPath(state) +} diff --git a/subjects/tron/ai/license-to-kill.js b/subjects/tron/ai/license-to-kill.js index 7a50919e0..b3a8ff91a 100644 --- a/subjects/tron/ai/license-to-kill.js +++ b/subjects/tron/ai/license-to-kill.js @@ -1,97 +1,97 @@ -const SIZE = 100 -const MAP = new Int8Array(SIZE * SIZE) // State of the Map -const isFree = ({ x, y }) => MAP[y * SIZE + x] === 0 // 0 = block free -const isOccupied = ({ x, y }) => MAP[y * SIZE + x] === 1 // 1 = block occupied -const inBounds = n => n < SIZE && n >= 0 -const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) -const pickRandom = arr => arr[Math.floor(Math.random() * arr.length)] - -// ok check if we can move on this block -const ok = (x = -1, y = -1) => { - const coords = typeof x !== 'number' ? x : { x, y } - return isFree(coords) && isInBounds(coords) -} - -const isAlley = (card, x, y) => { - switch (card) { - case 0: - if (ok(x, y - 1) && !ok(x + 1, y - 1) && !ok(x - 1, y - 1)) { - while (ok(x, y - 1) && !hasLateralWalls(0, x, y)) { - y-- - if (hasLateralWalls(0, x, y)) return true - } - } - return false - case 1: - if (ok(x + 1, y) && !ok(x + 1, y + 1) && !ok(x + 1, y - 1)) { - while (ok(x + 1, y) && !hasLateralWalls(1, x, y)) { - x++ - if (hasLateralWalls(1, x, y)) return true - } - } - return false - case 2: - if (ok(x, y + 1) && !ok(x + 1, y + 1) && !ok(x - 1, y + 1)) { - while (ok(x, y + 1) && !hasLateralWalls(2, x, y)) { - y++ - if (hasLateralWalls(2, x, y)) return true - } - } - return false - case 3: - if (ok(x - 1, y) && !ok(x - 1, y + 1) && !ok(x - 1, y - 1)) { - while (ok(x - 1, y) && !hasLateralWalls(3, x, y)) { - x-- - if (hasLateralWalls(3, x, y)) return true - } - } - return false - } -} - -const hasLateralWalls = (card, x, y) => { - switch (card) { - case 0: return !(ok(x + 1, y) || ok(x - 1, y) || ok(x, y - 1)) - case 1: return !(ok(x, y - 1) || ok(x, y + 1) || ok(x + 1, y)) - case 2: return !(ok(x + 1, y) || ok(x - 1, y) || ok(x, y + 1)) - case 3: return !(ok(x, y - 1) || ok(x, y + 1) || ok(x - 1, y)) - } -} - -const goDirection = (state, card) => - ok(state.coords[card]) && - !isAlley(card, state.x, state.y) && - state.coords[card] - -const findEnemy = state => - state.players.filter(p => state.player.name !== p.name)[0] - -const seekEnemy = state => { - if (state.players.length === 1) return - const enemy = findEnemy(state) - const xPla = state.player.x - const yPla = state.player.y - const xOpo = enemy.x - const yOpo = enemy.y - const xDif = xPla - xOpo - const yDif = yPla - yOpo - - return ( - (Math.abs(xDif) > Math.abs(yDif) && - goDirection(state.player, xPla < xOpo ? 1 : 3)) || - goDirection(yPla < yOpo ? 2 : 0) - ) -} - -const walk = state => - seekEnemy(state) || - goDirection(state.player, 0) || - goDirection(state.player, 1) || - goDirection(state.player, 2) || - goDirection(state.player, 3) - -const addToMap = ({ x, y }) => (MAP[y * SIZE + x] = 1) -const update = state => { - state.players.forEach(addToMap) - return walk(state) -} +const SIZE = 100 +const MAP = new Int8Array(SIZE * SIZE) // State of the Map +const isFree = ({ x, y }) => MAP[y * SIZE + x] === 0 // 0 = block free +const isOccupied = ({ x, y }) => MAP[y * SIZE + x] === 1 // 1 = block occupied +const inBounds = n => n < SIZE && n >= 0 +const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) +const pickRandom = arr => arr[Math.floor(Math.random() * arr.length)] + +// ok check if we can move on this block +const ok = (x = -1, y = -1) => { + const coords = typeof x !== 'number' ? x : { x, y } + return isFree(coords) && isInBounds(coords) +} + +const isAlley = (card, x, y) => { + switch (card) { + case 0: + if (ok(x, y - 1) && !ok(x + 1, y - 1) && !ok(x - 1, y - 1)) { + while (ok(x, y - 1) && !hasLateralWalls(0, x, y)) { + y-- + if (hasLateralWalls(0, x, y)) return true + } + } + return false + case 1: + if (ok(x + 1, y) && !ok(x + 1, y + 1) && !ok(x + 1, y - 1)) { + while (ok(x + 1, y) && !hasLateralWalls(1, x, y)) { + x++ + if (hasLateralWalls(1, x, y)) return true + } + } + return false + case 2: + if (ok(x, y + 1) && !ok(x + 1, y + 1) && !ok(x - 1, y + 1)) { + while (ok(x, y + 1) && !hasLateralWalls(2, x, y)) { + y++ + if (hasLateralWalls(2, x, y)) return true + } + } + return false + case 3: + if (ok(x - 1, y) && !ok(x - 1, y + 1) && !ok(x - 1, y - 1)) { + while (ok(x - 1, y) && !hasLateralWalls(3, x, y)) { + x-- + if (hasLateralWalls(3, x, y)) return true + } + } + return false + } +} + +const hasLateralWalls = (card, x, y) => { + switch (card) { + case 0: return !(ok(x + 1, y) || ok(x - 1, y) || ok(x, y - 1)) + case 1: return !(ok(x, y - 1) || ok(x, y + 1) || ok(x + 1, y)) + case 2: return !(ok(x + 1, y) || ok(x - 1, y) || ok(x, y + 1)) + case 3: return !(ok(x, y - 1) || ok(x, y + 1) || ok(x - 1, y)) + } +} + +const goDirection = (state, card) => + ok(state.coords[card]) && + !isAlley(card, state.x, state.y) && + state.coords[card] + +const findEnemy = state => + state.players.filter(p => state.player.name !== p.name)[0] + +const seekEnemy = state => { + if (state.players.length === 1) return + const enemy = findEnemy(state) + const xPla = state.player.x + const yPla = state.player.y + const xOpo = enemy.x + const yOpo = enemy.y + const xDif = xPla - xOpo + const yDif = yPla - yOpo + + return ( + (Math.abs(xDif) > Math.abs(yDif) && + goDirection(state.player, xPla < xOpo ? 1 : 3)) || + goDirection(yPla < yOpo ? 2 : 0) + ) +} + +const walk = state => + seekEnemy(state) || + goDirection(state.player, 0) || + goDirection(state.player, 1) || + goDirection(state.player, 2) || + goDirection(state.player, 3) + +const addToMap = ({ x, y }) => (MAP[y * SIZE + x] = 1) +const update = state => { + state.players.forEach(addToMap) + return walk(state) +} diff --git a/subjects/tron/ai/random.js b/subjects/tron/ai/random.js index 286c54836..9412034ad 100644 --- a/subjects/tron/ai/random.js +++ b/subjects/tron/ai/random.js @@ -1,57 +1,57 @@ -const SIZE = 100 -const MAP = new Int8Array(SIZE * SIZE) // State of the Map -const isFree = ({ x, y }) => MAP[y * SIZE + x] === 0 // 0 = block free -const isOccupied = ({ x, y }) => MAP[y * SIZE + x] === 1 // 1 = block occupied - -// `inBounds` check if our coord (n) is an existing index in our MAP -const inBounds = n => n < SIZE && n >= 0 - -// `isInBounds` check that properties x and y of our argument are both in bounds -const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) - -// `pickRandom` get a random element from an array -const pickRandom = arr => arr[Math.floor(Math.random() * arr.length)] - -// `addToMap` save the new positions into the map -const addToMap = ({ x, y }) => MAP[y * SIZE + x] = 1 - -// `update` this function is called at each turn -const update = state => { - // update is called with a state argument that has 2 properties: - // players: an array of all the players - // player: the player for this AI - - // Each players contains: - // color: A number that represent the color of a player - // name: A string of the player name - // score: A number of the total block collected by this player - // x: The horizontal position of the player - // y: The vertical position of the player - // coords: An array of 4 coordinates of the nearest blocks - // [ NORTH, EAST, SOUTH, WEST ] - // N - // W + E - // S - - // Each coordinate contains: - // x: The horizontal position - // y: The vertical position - // cardinal: A number between 0 and 3 that represent the cardinal - // [ 0: NORTH, 1: EAST, 2: SOUTH, 3: WEST ] - // direction: A number between 0 and 3 that represent the direction - // [ 0: FORWARD, 1: RIGHT, 2: BACKWARD, 3: LEFT ] - - // Saving state between each updates: - // I update the MAP with the new position of each players - state.players.forEach(addToMap) - - // Actual AI logic: - // I filter my array of coords to keep only those that are in bounds - const coordsInBound = state.player.coords.filter(isInBounds) - - // I filter again to keep coords that are free - const available = coordsInBound.filter(isFree) - - // And I return a random available coord - return pickRandom(available) -} +const SIZE = 100 +const MAP = new Int8Array(SIZE * SIZE) // State of the Map +const isFree = ({ x, y }) => MAP[y * SIZE + x] === 0 // 0 = block free +const isOccupied = ({ x, y }) => MAP[y * SIZE + x] === 1 // 1 = block occupied + +// `inBounds` check if our coord (n) is an existing index in our MAP +const inBounds = n => n < SIZE && n >= 0 + +// `isInBounds` check that properties x and y of our argument are both in bounds +const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) + +// `pickRandom` get a random element from an array +const pickRandom = arr => arr[Math.floor(Math.random() * arr.length)] + +// `addToMap` save the new positions into the map +const addToMap = ({ x, y }) => MAP[y * SIZE + x] = 1 + +// `update` this function is called at each turn +const update = state => { + // update is called with a state argument that has 2 properties: + // players: an array of all the players + // player: the player for this AI + + // Each players contains: + // color: A number that represent the color of a player + // name: A string of the player name + // score: A number of the total block collected by this player + // x: The horizontal position of the player + // y: The vertical position of the player + // coords: An array of 4 coordinates of the nearest blocks + // [ NORTH, EAST, SOUTH, WEST ] + // N + // W + E + // S + + // Each coordinate contains: + // x: The horizontal position + // y: The vertical position + // cardinal: A number between 0 and 3 that represent the cardinal + // [ 0: NORTH, 1: EAST, 2: SOUTH, 3: WEST ] + // direction: A number between 0 and 3 that represent the direction + // [ 0: FORWARD, 1: RIGHT, 2: BACKWARD, 3: LEFT ] + + // Saving state between each updates: + // I update the MAP with the new position of each players + state.players.forEach(addToMap) + + // Actual AI logic: + // I filter my array of coords to keep only those that are in bounds + const coordsInBound = state.player.coords.filter(isInBounds) + + // I filter again to keep coords that are free + const available = coordsInBound.filter(isFree) + + // And I return a random available coord + return pickRandom(available) +} diff --git a/subjects/tron/ai/right.js b/subjects/tron/ai/right.js index 78f827ee0..a2fc0ac49 100644 --- a/subjects/tron/ai/right.js +++ b/subjects/tron/ai/right.js @@ -1,48 +1,48 @@ -const SIZE = 100 -const [FREE, UNSAFE, FILLED] = Array(3).keys() -const MAP = new Int8Array(SIZE * SIZE) -const isFree = ({ x, y }) => MAP[y * SIZE + x] < FILLED -const isUnsafe = ({ x, y }) => MAP[y * SIZE + x] === UNSAFE -const setUnsafe = ({ x, y }) => MAP[y * SIZE + x] = UNSAFE -const setFilled = ({ x, y }) => MAP[y * SIZE + x] = FILLED -const inBounds = n => n < SIZE && n >= 0 -const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) -const isForward = el => el.direction === 0 -const isRight = el => el.direction === 1 -const isLeft = el => el.direction === 3 -const goForward = arr => arr.find(isForward) -const goRight = arr => arr.find(isRight) -const goLeft = arr => arr.find(isLeft) -const isOtherPlayer = player => !player.isOwnPlayer - -let wallReached = false -const pickForwardOrRightOrLeft = arr => { - if (arr.length === 3 && !wallReached) { - return goForward(arr) || goRight(arr) || goLeft(arr) - } - - if (arr.length <= 2 && !wallReached) { - wallReached = true - return goRight(arr) || goLeft(arr) || goForward(arr) - } - - return goLeft(arr) || goForward(arr) || goRight(arr) -} - -const update = ({ player, players }) => { - players.forEach(setFilled) - players - .filter(isOtherPlayer) - .flatMap(({ coords }) => coords) - .filter(isInBounds) - .filter(isFree) - .forEach(setUnsafe) - - const coordsInBound = player.coords - .filter(isInBounds) - .filter(isNotBackward) - - const available = pickForwardOrRightOrLeft(coordsInBound.filter(isFree)) - const lastResort = pickForwardOrRightOrLeft(coordsInBound.filter(isUnsafe)) - return available || lastResort -} +const SIZE = 100 +const [FREE, UNSAFE, FILLED] = Array(3).keys() +const MAP = new Int8Array(SIZE * SIZE) +const isFree = ({ x, y }) => MAP[y * SIZE + x] < FILLED +const isUnsafe = ({ x, y }) => MAP[y * SIZE + x] === UNSAFE +const setUnsafe = ({ x, y }) => MAP[y * SIZE + x] = UNSAFE +const setFilled = ({ x, y }) => MAP[y * SIZE + x] = FILLED +const inBounds = n => n < SIZE && n >= 0 +const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) +const isForward = el => el.direction === 0 +const isRight = el => el.direction === 1 +const isLeft = el => el.direction === 3 +const goForward = arr => arr.find(isForward) +const goRight = arr => arr.find(isRight) +const goLeft = arr => arr.find(isLeft) +const isOtherPlayer = player => !player.isOwnPlayer + +let wallReached = false +const pickForwardOrRightOrLeft = arr => { + if (arr.length === 3 && !wallReached) { + return goForward(arr) || goRight(arr) || goLeft(arr) + } + + if (arr.length <= 2 && !wallReached) { + wallReached = true + return goRight(arr) || goLeft(arr) || goForward(arr) + } + + return goLeft(arr) || goForward(arr) || goRight(arr) +} + +const update = ({ player, players }) => { + players.forEach(setFilled) + players + .filter(isOtherPlayer) + .flatMap(({ coords }) => coords) + .filter(isInBounds) + .filter(isFree) + .forEach(setUnsafe) + + const coordsInBound = player.coords + .filter(isInBounds) + .filter(isNotBackward) + + const available = pickForwardOrRightOrLeft(coordsInBound.filter(isFree)) + const lastResort = pickForwardOrRightOrLeft(coordsInBound.filter(isUnsafe)) + return available || lastResort +} diff --git a/subjects/tron/ai/snail.js b/subjects/tron/ai/snail.js index fd22cff1d..89cd1c014 100644 --- a/subjects/tron/ai/snail.js +++ b/subjects/tron/ai/snail.js @@ -1,40 +1,40 @@ -const SIZE = 100 -const FREE = 0 -const UNSAFE = -1 -const FILLED = 1 -const MAP = new Int8Array(SIZE * SIZE) -const isFree = ({ x, y }) => MAP[y * SIZE + x] < FILLED -const isUnsafe = ({ x, y }) => MAP[y * SIZE + x] === UNSAFE -const setUnsafe = ({ x, y }) => MAP[y * SIZE + x] = UNSAFE -const setFilled = ({ x, y }) => MAP[y * SIZE + x] = FILLED -const inBounds = n => n < SIZE && n >= 0 -const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) -const isNotBackward = el => el.direction !== 2 -const isForward = el => el.direction === 0 -const isRight = el => el.direction === 1 -const isLeft = el => el.direction === 3 -const goForward = arr => arr.find(isForward) -const goRight = arr => arr.find(isRight) -const goLeft = arr => arr.find(isLeft) -const isOtherPlayer = player => !player.isOwnPlayer - -// `snailIt` goes with the form of a snail -const snailIt = arr => goRight(arr) || goForward(arr) || goLeft(arr) - -const update = ({ player, players }) => { - players.forEach(setFilled) - players - .filter(isOtherPlayer) - .flatMap(({ coords }) => coords) - .filter(isInBounds) - .filter(isFree) - .forEach(setUnsafe) - - const coordsInBound = player.coords - .filter(isInBounds) - .filter(isNotBackward) - - const available = snailIt(coordsInBound.filter(isFree)) - const lastResort = snailIt(coordsInBound.filter(isUnsafe)) - return available || lastResort -} +const SIZE = 100 +const FREE = 0 +const UNSAFE = -1 +const FILLED = 1 +const MAP = new Int8Array(SIZE * SIZE) +const isFree = ({ x, y }) => MAP[y * SIZE + x] < FILLED +const isUnsafe = ({ x, y }) => MAP[y * SIZE + x] === UNSAFE +const setUnsafe = ({ x, y }) => MAP[y * SIZE + x] = UNSAFE +const setFilled = ({ x, y }) => MAP[y * SIZE + x] = FILLED +const inBounds = n => n < SIZE && n >= 0 +const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y) +const isNotBackward = el => el.direction !== 2 +const isForward = el => el.direction === 0 +const isRight = el => el.direction === 1 +const isLeft = el => el.direction === 3 +const goForward = arr => arr.find(isForward) +const goRight = arr => arr.find(isRight) +const goLeft = arr => arr.find(isLeft) +const isOtherPlayer = player => !player.isOwnPlayer + +// `snailIt` goes with the form of a snail +const snailIt = arr => goRight(arr) || goForward(arr) || goLeft(arr) + +const update = ({ player, players }) => { + players.forEach(setFilled) + players + .filter(isOtherPlayer) + .flatMap(({ coords }) => coords) + .filter(isInBounds) + .filter(isFree) + .forEach(setUnsafe) + + const coordsInBound = player.coords + .filter(isInBounds) + .filter(isNotBackward) + + const available = snailIt(coordsInBound.filter(isFree)) + const lastResort = snailIt(coordsInBound.filter(isUnsafe)) + return available || lastResort +} diff --git a/subjects/tron/index.html b/subjects/tron/index.html index ea4144473..cafdba081 100644 --- a/subjects/tron/index.html +++ b/subjects/tron/index.html @@ -1,384 +1,384 @@ - - - - Tron - - - - - - -
- - -
-
-

AI-0

- LOADING -
- 0 -
- -
-

AI-1

- LOADING -
- 0 -
-
-
-
-
-
-
- > scroll or keys to move step by step, click to jump. (shift = fast) - -
-
- - - + + + + Tron + + + + + + +
+ + +
+
+

AI-0

+ LOADING +
+ 0 +
+ +
+

AI-1

+ LOADING +
+ 0 +
+
+
+
+
+
+
+ > scroll or keys to move step by step, click to jump. (shift = fast) + +
+
+ + + diff --git a/subjects/tron/lib/display.js b/subjects/tron/lib/display.js index 23bb461ea..69934e6ea 100644 --- a/subjects/tron/lib/display.js +++ b/subjects/tron/lib/display.js @@ -1,132 +1,132 @@ -const vertexArray = new Float32Array(100 * 100 * 12) -const colorArray = new Float32Array(100 * 100 * 6) -const state = new Float32Array(100 * 100 * 2) -const [canvas] = document.getElementsByTagName('canvas') -const gl = canvas.getContext('webgl2', { antialias: false }) -const S = 0.02 - -const applyState = (x, y, turn) => { - const index = x * 100 + y - const color = state[index * 2 + 0] > turn ? 0 : state[index * 2 + 1] - colorArray[index * 6 + 0] = color - colorArray[index * 6 + 1] = color - colorArray[index * 6 + 2] = color - colorArray[index * 6 + 3] = color - colorArray[index * 6 + 4] = color - colorArray[index * 6 + 5] = color -} - -export const colorize = (x, y, color) => state[(x * 100 + y) * 2 + 1] = color -export const move = (x, y, color, turn) => { - const index = (x * 100 + y) * 2 - if (state[index]) return state[index] - state[index] = turn - state[index + 1] = color -} - -const loop = fn => { - let x = -1, y = -1 - while (++x < 100) { - y = -1 - while (++y < 100) fn(x, y) - } -} - -const compileShader = (type, script) => { - const shader = gl.createShader(type) - gl.shaderSource(shader, script.trim()) - gl.compileShader(shader) - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - throw gl.getShaderInfoLog(shader) - } - return shader -} - -// program -const program = gl.createProgram() -gl.attachShader(program, compileShader(gl.VERTEX_SHADER, ` -#version 300 es - -in vec2 a_position; -in float a_color; -out float v_color; - -void main() { - gl_Position = vec4(a_position * vec2(1, -1), 0, 1); - v_color = a_color; -}`)) - -gl.attachShader(program, compileShader(gl.FRAGMENT_SHADER, ` -#version 300 es - -precision mediump float; -in float v_color; -out vec4 outColor; - -vec4 unpackColor(float f) { - vec4 color; - color.r = floor(f / 65536.0); - color.g = floor((f - color.r * 65536.0) / 256.0); - color.b = floor(f - color.r * 65536.0 - color.g * 256.0); - color.a = 256.0; - return color / 256.0; -} - -void main() { - outColor = unpackColor(v_color); -}`)) - -gl.linkProgram(program) -if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - throw gl.getProgramInfoLog(program) -} - -gl.useProgram(program) - -// initialize state -loop((x, y) => { - const x1 = ((x + 1) - 50) / 50 - S - const y1 = ((y + 1) - 50) / 50 - S - const x2 = x1 + S - const y2 = y1 + S - const index = (x * 100 + y) * 12 - vertexArray[index + 0x0] = x1 - vertexArray[index + 0x1] = y1 - vertexArray[index + 0x2] = x2 - vertexArray[index + 0x3] = y1 - vertexArray[index + 0x4] = x1 - vertexArray[index + 0x5] = y2 - vertexArray[index + 0x6] = x1 - vertexArray[index + 0x7] = y2 - vertexArray[index + 0x8] = x2 - vertexArray[index + 0x9] = y1 - vertexArray[index + 0xa] = x2 - vertexArray[index + 0xb] = y2 -}) - -const vertexBuffer = gl.createBuffer() -const a_position = gl.getAttribLocation(program, 'a_position') -gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer) -gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0) -gl.enableVertexAttribArray(a_position) -gl.bufferData(gl.ARRAY_BUFFER, vertexArray, gl.STATIC_DRAW) -gl.drawArrays(gl.TRIANGLES, 0, 60000) - -// color buffer -const colorBuffer = gl.createBuffer() -const a_color = gl.getAttribLocation(program, 'a_color') -gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer) -gl.vertexAttribPointer(a_color, 1, gl.FLOAT, false, 0, 0) -gl.enableVertexAttribArray(a_color) -gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer) - -export const update = (turn) => { - loop((x, y) => applyState(x, y, turn)) - gl.bufferData(gl.ARRAY_BUFFER, colorArray, gl.STATIC_DRAW) - gl.drawArrays(gl.TRIANGLES, 0, 60000) -} - -export const reset = () => { - state.fill(0) - update(0) -} +const vertexArray = new Float32Array(100 * 100 * 12) +const colorArray = new Float32Array(100 * 100 * 6) +const state = new Float32Array(100 * 100 * 2) +const [canvas] = document.getElementsByTagName('canvas') +const gl = canvas.getContext('webgl2', { antialias: false }) +const S = 0.02 + +const applyState = (x, y, turn) => { + const index = x * 100 + y + const color = state[index * 2 + 0] > turn ? 0 : state[index * 2 + 1] + colorArray[index * 6 + 0] = color + colorArray[index * 6 + 1] = color + colorArray[index * 6 + 2] = color + colorArray[index * 6 + 3] = color + colorArray[index * 6 + 4] = color + colorArray[index * 6 + 5] = color +} + +export const colorize = (x, y, color) => state[(x * 100 + y) * 2 + 1] = color +export const move = (x, y, color, turn) => { + const index = (x * 100 + y) * 2 + if (state[index]) return state[index] + state[index] = turn + state[index + 1] = color +} + +const loop = fn => { + let x = -1, y = -1 + while (++x < 100) { + y = -1 + while (++y < 100) fn(x, y) + } +} + +const compileShader = (type, script) => { + const shader = gl.createShader(type) + gl.shaderSource(shader, script.trim()) + gl.compileShader(shader) + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + throw gl.getShaderInfoLog(shader) + } + return shader +} + +// program +const program = gl.createProgram() +gl.attachShader(program, compileShader(gl.VERTEX_SHADER, ` +#version 300 es + +in vec2 a_position; +in float a_color; +out float v_color; + +void main() { + gl_Position = vec4(a_position * vec2(1, -1), 0, 1); + v_color = a_color; +}`)) + +gl.attachShader(program, compileShader(gl.FRAGMENT_SHADER, ` +#version 300 es + +precision mediump float; +in float v_color; +out vec4 outColor; + +vec4 unpackColor(float f) { + vec4 color; + color.r = floor(f / 65536.0); + color.g = floor((f - color.r * 65536.0) / 256.0); + color.b = floor(f - color.r * 65536.0 - color.g * 256.0); + color.a = 256.0; + return color / 256.0; +} + +void main() { + outColor = unpackColor(v_color); +}`)) + +gl.linkProgram(program) +if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + throw gl.getProgramInfoLog(program) +} + +gl.useProgram(program) + +// initialize state +loop((x, y) => { + const x1 = ((x + 1) - 50) / 50 - S + const y1 = ((y + 1) - 50) / 50 - S + const x2 = x1 + S + const y2 = y1 + S + const index = (x * 100 + y) * 12 + vertexArray[index + 0x0] = x1 + vertexArray[index + 0x1] = y1 + vertexArray[index + 0x2] = x2 + vertexArray[index + 0x3] = y1 + vertexArray[index + 0x4] = x1 + vertexArray[index + 0x5] = y2 + vertexArray[index + 0x6] = x1 + vertexArray[index + 0x7] = y2 + vertexArray[index + 0x8] = x2 + vertexArray[index + 0x9] = y1 + vertexArray[index + 0xa] = x2 + vertexArray[index + 0xb] = y2 +}) + +const vertexBuffer = gl.createBuffer() +const a_position = gl.getAttribLocation(program, 'a_position') +gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer) +gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0) +gl.enableVertexAttribArray(a_position) +gl.bufferData(gl.ARRAY_BUFFER, vertexArray, gl.STATIC_DRAW) +gl.drawArrays(gl.TRIANGLES, 0, 60000) + +// color buffer +const colorBuffer = gl.createBuffer() +const a_color = gl.getAttribLocation(program, 'a_color') +gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer) +gl.vertexAttribPointer(a_color, 1, gl.FLOAT, false, 0, 0) +gl.enableVertexAttribArray(a_color) +gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer) + +export const update = (turn) => { + loop((x, y) => applyState(x, y, turn)) + gl.bufferData(gl.ARRAY_BUFFER, colorArray, gl.STATIC_DRAW) + gl.drawArrays(gl.TRIANGLES, 0, 60000) +} + +export const reset = () => { + state.fill(0) + update(0) +} diff --git a/subjects/tron/lib/state.js b/subjects/tron/lib/state.js index 0ac838a0a..5a1b77540 100644 --- a/subjects/tron/lib/state.js +++ b/subjects/tron/lib/state.js @@ -1,96 +1,96 @@ -const SIZE = 100 -const h = SIZE / 2 -const m = h * 0.8 -const max = m => n => n > m ? max1(n - m) : n -const max1 = max(1) -const max2PI = max(Math.PI * 2) -const toInt = (r, g, b) => (r << 16) | (g << 8) | b -const toRange = n => Math.round(n * 0xFF) -const hue2rgb = (p, q, t) => { - if (t < 0) t += 1 - if (t > 1) t -= 1 - if (t < 1/6) return p + (q - p) * 6 * t - if (t < 1/2) return q - if (t < 2/3) return p + (q - p) * (2/3 - t) * 6 - return p -} - -const hslToRgb = (h, s, l) => { - if (!s) return toInt(toRange(l), toRange(l), toRange(l)) - - const q = l < 0.5 ? l * (1 + s) : l + s - l * s - const p = 2 * l - q - const r = hue2rgb(p, q, h + 1/3) - const g = hue2rgb(p, q, h) - const b = hue2rgb(p, q, h - 1/3) - - return toInt(toRange(r), toRange(g), toRange(b)) -} - -export const init = ({ players, seed }) => { - const rand = () => { - let t = seed += 0x6D2B79F5 - t = Math.imul(t ^ t >>> 15, t | 1) - t ^= t + Math.imul(t ^ t >>> 7, t | 61) - return ((t ^ t >>> 14) >>> 0) / 4294967296 - } - - const angle = (Math.PI * 2) / players.length - const rate = (SIZE / players.length / SIZE) - const shift = angle * rand() - - // shuffle using seeded random - players.sort((a, b) => a.name - b.name) - let i = players.length, j, tmp - while (--i > 0) { - j = Math.floor(rand() * (i + 1)) - tmp = players[j] - players[j] = players[i] - players[i] = tmp - } - - return players.map((name, i) => { - const jsonName = `"name":${JSON.stringify(name)}` - const hue = max1(i * rate + 0.25) - const p = { - hue, - name, - x: Math.round(max2PI(Math.cos(angle * i + shift)) * m + h), - y: Math.round(max2PI(Math.sin(angle * i + shift)) * m + h), - cardinal: 0, - direction: 0, - color: hslToRgb(hue, 1, 0.5), - toString: () => `{${jsonName},"dead":${!!p.dead},"cardinal":${p.cardinal},"direction":${p.direction},"color":${p.color},"x":${p.x},"y":${p.y},"coords":[{"x":${p.x},"y":${p.y - 1},"cardinal":0,"direction":${(4 - p.cardinal) % 4}},{"x":${p.x + 1},"y":${p.y},"cardinal":1,"direction":${(5 - p.cardinal) % 4}},{"x":${p.x},"y":${p.y + 1},"cardinal":2,"direction":${(6 - p.cardinal) % 4}},{"x":${p.x - 1},"y":${p.y},"cardinal":3,"direction":${(7 - p.cardinal) % 4}}]}`, - } - return p - }) -} - -export const injectedCode = ` -if (typeof update !== 'function') throw Error('Update function not defined') -addEventListener('message', self.init = initEvent => { - const { seed, id } = JSON.parse(initEvent.data) - const isOwnPlayer = p => p.name === id - - Math.random = () => { - let t = seed += 0x6D2B79F5 - t = Math.imul(t ^ t >>> 15, t | 1) - t ^= t + Math.imul(t ^ t >>> 7, t | 61) - return ((t ^ t >>> 14) >>> 0) / 4294967296 - } - - removeEventListener('message', self.init) - addEventListener('message', ({ data }) => { - const players = JSON.parse(data) - const player = players.find(isOwnPlayer) - player.isOwnPlayer = true - - try { postMessage(JSON.stringify(update({ players, player }))) } - catch (err) { - console.error(err) - throw err - } - }) - postMessage('loaded') // Signal that the loading is over -}) -` +const SIZE = 100 +const h = SIZE / 2 +const m = h * 0.8 +const max = m => n => n > m ? max1(n - m) : n +const max1 = max(1) +const max2PI = max(Math.PI * 2) +const toInt = (r, g, b) => (r << 16) | (g << 8) | b +const toRange = n => Math.round(n * 0xFF) +const hue2rgb = (p, q, t) => { + if (t < 0) t += 1 + if (t > 1) t -= 1 + if (t < 1/6) return p + (q - p) * 6 * t + if (t < 1/2) return q + if (t < 2/3) return p + (q - p) * (2/3 - t) * 6 + return p +} + +const hslToRgb = (h, s, l) => { + if (!s) return toInt(toRange(l), toRange(l), toRange(l)) + + const q = l < 0.5 ? l * (1 + s) : l + s - l * s + const p = 2 * l - q + const r = hue2rgb(p, q, h + 1/3) + const g = hue2rgb(p, q, h) + const b = hue2rgb(p, q, h - 1/3) + + return toInt(toRange(r), toRange(g), toRange(b)) +} + +export const init = ({ players, seed }) => { + const rand = () => { + let t = seed += 0x6D2B79F5 + t = Math.imul(t ^ t >>> 15, t | 1) + t ^= t + Math.imul(t ^ t >>> 7, t | 61) + return ((t ^ t >>> 14) >>> 0) / 4294967296 + } + + const angle = (Math.PI * 2) / players.length + const rate = (SIZE / players.length / SIZE) + const shift = angle * rand() + + // shuffle using seeded random + players.sort((a, b) => a.name - b.name) + let i = players.length, j, tmp + while (--i > 0) { + j = Math.floor(rand() * (i + 1)) + tmp = players[j] + players[j] = players[i] + players[i] = tmp + } + + return players.map((name, i) => { + const jsonName = `"name":${JSON.stringify(name)}` + const hue = max1(i * rate + 0.25) + const p = { + hue, + name, + x: Math.round(max2PI(Math.cos(angle * i + shift)) * m + h), + y: Math.round(max2PI(Math.sin(angle * i + shift)) * m + h), + cardinal: 0, + direction: 0, + color: hslToRgb(hue, 1, 0.5), + toString: () => `{${jsonName},"dead":${!!p.dead},"cardinal":${p.cardinal},"direction":${p.direction},"color":${p.color},"x":${p.x},"y":${p.y},"coords":[{"x":${p.x},"y":${p.y - 1},"cardinal":0,"direction":${(4 - p.cardinal) % 4}},{"x":${p.x + 1},"y":${p.y},"cardinal":1,"direction":${(5 - p.cardinal) % 4}},{"x":${p.x},"y":${p.y + 1},"cardinal":2,"direction":${(6 - p.cardinal) % 4}},{"x":${p.x - 1},"y":${p.y},"cardinal":3,"direction":${(7 - p.cardinal) % 4}}]}`, + } + return p + }) +} + +export const injectedCode = ` +if (typeof update !== 'function') throw Error('Update function not defined') +addEventListener('message', self.init = initEvent => { + const { seed, id } = JSON.parse(initEvent.data) + const isOwnPlayer = p => p.name === id + + Math.random = () => { + let t = seed += 0x6D2B79F5 + t = Math.imul(t ^ t >>> 15, t | 1) + t ^= t + Math.imul(t ^ t >>> 7, t | 61) + return ((t ^ t >>> 14) >>> 0) / 4294967296 + } + + removeEventListener('message', self.init) + addEventListener('message', ({ data }) => { + const players = JSON.parse(data) + const player = players.find(isOwnPlayer) + player.isOwnPlayer = true + + try { postMessage(JSON.stringify(update({ players, player }))) } + catch (err) { + console.error(err) + throw err + } + }) + postMessage('loaded') // Signal that the loading is over +}) +` diff --git a/subjects/tron/tron.audit.en.md b/subjects/tron/tron.audit.en.md index dc47c3fd2..748fbb8d6 100644 --- a/subjects/tron/tron.audit.en.md +++ b/subjects/tron/tron.audit.en.md @@ -1,45 +1,45 @@ -#### Functional - -###### Does the AI crash because of too much usage of CPU? - -##### Modify the link so that the users are the audited `GITHUB_LOGIN` - -##### and `/random.js`. Try three times, changing the seed each time. The best of three, wins - -###### Did the audited AI won against random AI? - -##### Modify the link so that the users are the audited `GITHUB_LOGIN` - -##### and `/right.js`. Try three times, changing the seed each time. The best of three, wins - -###### Did the audited AI won against `right` AI? - -##### Modify the link so that the users are the audited `GITHUB_LOGIN` - -##### and `/snail.js`. Try three times, changing the seed each time. The best of three, wins - -###### Did the audited AI won against `snail` AI? - -###### Does the code avoid [deep nesting](https://testing.googleblog.com/2017/06/code-health-reduce-nesting-reduce.html)? - -##### Modify the link so that the users are the audited `GITHUB_LOGIN` - -##### and `/hard.js`. Try three times, changing the seed each time. The best of three, wins - -###### Did the audited AI won against `hard` AI? - -#### Bonus - -##### Modify the link so that the users are the audited `GITHUB_LOGIN` - -##### and `/licence-to-kill.js`. Try three times, changing the seed each time. The best of three, wins - -###### +Did the audited AI won against `licence-to-kill` AI? - -##### If you have an AI - -##### Modify the link so that the users are the audited `GITHUB_LOGIN` - -##### and **your AI**. Try three times, changing the seed each time. The best of three, wins - -###### Did the audited AI won against your AI? +#### Functional + +###### Does the AI crash because of too much usage of CPU? + +##### Modify the link so that the users are the audited `GITHUB_LOGIN` + +##### and `/random.js`. Try three times, changing the seed each time. The best of three, wins + +###### Did the audited AI won against random AI? + +##### Modify the link so that the users are the audited `GITHUB_LOGIN` + +##### and `/right.js`. Try three times, changing the seed each time. The best of three, wins + +###### Did the audited AI won against `right` AI? + +##### Modify the link so that the users are the audited `GITHUB_LOGIN` + +##### and `/snail.js`. Try three times, changing the seed each time. The best of three, wins + +###### Did the audited AI won against `snail` AI? + +###### Does the code avoid [deep nesting](https://testing.googleblog.com/2017/06/code-health-reduce-nesting-reduce.html)? + +##### Modify the link so that the users are the audited `GITHUB_LOGIN` + +##### and `/hard.js`. Try three times, changing the seed each time. The best of three, wins + +###### Did the audited AI won against `hard` AI? + +#### Bonus + +##### Modify the link so that the users are the audited `GITHUB_LOGIN` + +##### and `/licence-to-kill.js`. Try three times, changing the seed each time. The best of three, wins + +###### +Did the audited AI won against `licence-to-kill` AI? + +##### If you have an AI + +##### Modify the link so that the users are the audited `GITHUB_LOGIN` + +##### and **your AI**. Try three times, changing the seed each time. The best of three, wins + +###### Did the audited AI won against your AI? diff --git a/subjects/tron/tron.en.md b/subjects/tron/tron.en.md index 7c423eb8d..dacdc8a32 100644 --- a/subjects/tron/tron.en.md +++ b/subjects/tron/tron.en.md @@ -1,76 +1,76 @@ -## Tron - -### Objectives - -In this project you will have to create your own Tron AI snake - -### Getting started - -You will need to create a public repository with the name `tron`. Next you need to create a file named `ai.js`. It must respect the instructions given - -### Controls - -- `arrows` or `scroll` to move step by stem -- `shift` will make it fast -- you can click anywhere on the progress bar to seek into the history - -### Rules - -- Your AI has to move every turn *(it can not stay still)* -- Every time the AI moves somewhere the AI leaves a color trail. -- the AI can only move to a blank tile. -- the AI can not move out of the map *(100 x 100)* -- the AI can only move to its `left`, `forward` or its `right`. - *(Moving `backward` is suicide as it would hit its own trail !)* -- If too much CPU power is required to decide where to go, the AI dies. -- If two Ais moved to the same spot, both of them die. -- **The AI has to survive as long as it can.** - -### The game ends - -- Once no players can make a move the player with the biggest score wins - -### How to write your AI - -- Copy the code on the file [random.js](https://raw.githubusercontent.com/01-edu/public/master/subjects/tron/ai/random.js) to your file, `ai.js` -- You may now edit the `update` function which is called each turn - > ⚠️ Do not rename the `update` function ⚠️ \ - > as it's the function that the worker will try to run to test your AI. - -### How to test your AI - -- You may use this link [tron](/public/subjects/tron?ai=&seed=1653547275), to test your AI -- You need to add your AI as a user in that link - > Example: if your git login is **Frenchris** and you want to test against **LEEDASILVA** the link becomes: `/public/subjects/tron?AI=Frenchris@master+LEEDASILVA@master&seed=1653547275` -- Open the inspector of the browser used and **disable the cache** -- let's change the update function so that your AI only goes forward. - -Replace this line just before the `return` of the update function: -```js - const available = coordsInBound.filter(isFree) - - // And I return a random available coord - return pickRandom(available) -``` - -...with this line: -```js - // always return the first free coordinates - return coordsInBound.filter(isFree)[0] -``` - -- save the file, push the changes and re-run the game in the browser. - If the cache was correctly disabled, - you have changed your AI behaviour from a random pick of available moves - to only going forward. - -- To understand better the way of controlling your AI, - read the comments inside the AI file and do a lot of testing. - -- When peer-corrected, you AI will be competing against other AIs. - Be aware that there will be the possibility for the peer-correcter - to use his or her own AI. - -*May the best tron win :)* - -Have fun and good luck. +## Tron + +### Objectives + +In this project you will have to create your own Tron AI snake + +### Getting started + +You will need to create a public repository with the name `tron`. Next you need to create a file named `ai.js`. It must respect the instructions given + +### Controls + +- `arrows` or `scroll` to move step by stem +- `shift` will make it fast +- you can click anywhere on the progress bar to seek into the history + +### Rules + +- Your AI has to move every turn *(it can not stay still)* +- Every time the AI moves somewhere the AI leaves a color trail. +- the AI can only move to a blank tile. +- the AI can not move out of the map *(100 x 100)* +- the AI can only move to its `left`, `forward` or its `right`. + *(Moving `backward` is suicide as it would hit its own trail !)* +- If too much CPU power is required to decide where to go, the AI dies. +- If two Ais moved to the same spot, both of them die. +- **The AI has to survive as long as it can.** + +### The game ends + +- Once no players can make a move the player with the biggest score wins + +### How to write your AI + +- Copy the code on the file [random.js](https://raw.githubusercontent.com/01-edu/public/master/subjects/tron/ai/random.js) to your file, `ai.js` +- You may now edit the `update` function which is called each turn + > ⚠️ Do not rename the `update` function ⚠️ \ + > as it's the function that the worker will try to run to test your AI. + +### How to test your AI + +- You may use this link [tron](/public/subjects/tron?ai=&seed=1653547275), to test your AI +- You need to add your AI as a user in that link + > Example: if your git login is **Frenchris** and you want to test against **LEEDASILVA** the link becomes: `/public/subjects/tron?AI=Frenchris@master+LEEDASILVA@master&seed=1653547275` +- Open the inspector of the browser used and **disable the cache** +- let's change the update function so that your AI only goes forward. + +Replace this line just before the `return` of the update function: +```js + const available = coordsInBound.filter(isFree) + + // And I return a random available coord + return pickRandom(available) +``` + +...with this line: +```js + // always return the first free coordinates + return coordsInBound.filter(isFree)[0] +``` + +- save the file, push the changes and re-run the game in the browser. + If the cache was correctly disabled, + you have changed your AI behaviour from a random pick of available moves + to only going forward. + +- To understand better the way of controlling your AI, + read the comments inside the AI file and do a lot of testing. + +- When peer-corrected, you AI will be competing against other AIs. + Be aware that there will be the possibility for the peer-correcter + to use his or her own AI. + +*May the best tron win :)* + +Have fun and good luck.