Compare commits

..

5 Commits

Author SHA1 Message Date
Tiago Collot 058ffe56d6 docs(revconcatalternate): fix instructions 2 years ago
Tiago Collot 9685f3b098 docs(revconcatalternate): fix subject 2 years ago
Hamza elkhatri 5d68fa5c4a
docs(revconcatalternate): change title 2 years ago
Hamza elkhatri b64e0eecb2
docs(RevConcatAlternate): remove space and Dash 2 years ago
hamza 6f4e32b1b5 DEV-3187 add(docs):add subject of revconcAlter 2 years ago
  1. 57
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 21
      .github/ISSUE_TEMPLATE/feature_request.md
  3. 46
      .github/workflows/docker-images.yml
  4. 278
      docs/addition_of_exercise_draft.md
  5. 92
      docs/audits-at-home/README.md
  6. 83
      docs/audits-at-home/README_ru.md
  7. 190
      docs/event-management.md
  8. 330
      docs/grand-prix-go-curriculum.md
  9. 65
      docs/metrics.md
  10. 244
      docs/modular-steps-management.md
  11. 165
      docs/object-attribute-system.md
  12. 40
      docs/object-child-creation.md
  13. 58
      docs/object-creation.md
  14. 34
      docs/object-edit.md
  15. 29
      docs/objects.md
  16. 28
      docs/pc-requirements.md
  17. 330
      docs/piscine-go-curriculum.md
  18. 150
      docs/piscine-rust-curriculum.md
  19. 2
      docs/reviews.md
  20. 62
      docs/server-installation.md
  21. 25
      docs/server-requirements.md
  22. 140
      docs/setup_of_external_repo.md
  23. 67
      docs/ubuntu-installation.md
  24. 61
      docs/ubuntu-persistent-installation.md
  25. 39
      docs/unreal-engine-setup.md
  26. 2
      js/tests/Dockerfile
  27. 18
      js/tests/bloody-sunday_test.js
  28. 12
      js/tests/declarations_test.js
  29. 135
      js/tests/friend-support_test.mjs
  30. 147
      js/tests/gatecrashers_test.mjs
  31. 21
      js/tests/keycodes-symphony-dom_test.mjs
  32. 13
      js/tests/primitives_test.js
  33. 1
      js/tests/race_test.js
  34. 18
      js/tests/sunny-sunday_test.js
  35. 3
      js/tests/test.mjs
  36. 197
      js/tests/uninvited_test.mjs
  37. 37
      js/tests/veterinary_test.js
  38. 373
      sh/debian/configure.sh
  39. 2
      sh/debian/preseed.cfg
  40. 2
      sh/tests/Dockerfile
  41. 99
      sh/tests/append-output_test.sh
  42. 30
      sh/tests/array-selector_test.sh
  43. 54
      sh/tests/auto-exec-bin_test.sh
  44. 20
      sh/tests/auto-jobs_test.sh
  45. 34
      sh/tests/bin-status_test.sh
  46. 28
      sh/tests/burial_test.sh
  47. 86
      sh/tests/calculator_test.sh
  48. 16
      sh/tests/change-struct_test.sh
  49. 28
      sh/tests/check-user_test.sh
  50. 27
      sh/tests/comparator_test.sh
  51. 18
      sh/tests/count-files_test.sh
  52. 11
      sh/tests/custom-ls/folder1/.hidden
  53. 1
      sh/tests/custom-ls/folder1/asd
  54. 199
      sh/tests/custom-ls/folder1/hello
  55. 1
      sh/tests/custom-ls/folder1/ls-test
  56. 42
      sh/tests/custom-ls_test.sh
  57. 18
      sh/tests/details_test.sh
  58. 44
      sh/tests/dir-info_test.sh
  59. 37
      sh/tests/division_test.sh
  60. 15
      sh/tests/easy-conditions_test.sh
  61. 12
      sh/tests/easy-perm/example.txt
  62. 16
      sh/tests/easy-perm/example2.txt
  63. 17
      sh/tests/easy-perm_test.sh
  64. 28
      sh/tests/env-format_test.sh
  65. 38
      sh/tests/file-checker_test.sh
  66. 17
      sh/tests/file-details_test.sh
  67. 127
      sh/tests/file-researcher/facts.txt
  68. 28
      sh/tests/file-researcher_test.sh
  69. 16
      sh/tests/file-struct_test.sh
  70. 0
      sh/tests/find-files-extension/folder1/file1.txt
  71. 0
      sh/tests/find-files-extension/folder1/file2.txt
  72. 0
      sh/tests/find-files-extension/folder1/file3.txt
  73. 0
      sh/tests/find-files-extension/folder1/test4.sh
  74. 0
      sh/tests/find-files-extension/folder2/fileInsideAfolder4.txt
  75. 0
      sh/tests/find-files-extension/folder2/test.sh
  76. 0
      sh/tests/find-files-extension/folder2/testtxt/fileInsideAfolder5.txt
  77. 0
      sh/tests/find-files-extension/folder2/testtxt/test/fileInsideAfolder6.txt
  78. 0
      sh/tests/find-files-extension/folder2/testtxt/test/lol.sh
  79. 35
      sh/tests/find-files-extension_test.sh
  80. 0
      sh/tests/find-files/folder1/ab
  81. 0
      sh/tests/find-files/folder1/ac
  82. 0
      sh/tests/find-files/folder1/az
  83. 0
      sh/tests/find-files/folder1/bz
  84. 0
      sh/tests/find-files/folder1/cz
  85. 0
      sh/tests/find-files/folder1/za!
  86. 0
      sh/tests/find-files/folder2/aa/aa
  87. 0
      sh/tests/find-files/folder2/aa/az
  88. 0
      sh/tests/find-files/folder2/aa/ba/ab
  89. 0
      sh/tests/find-files/folder2/aa/ba/bz
  90. 0
      sh/tests/find-files/folder2/ab
  91. 0
      sh/tests/find-files/folder2/ac
  92. 0
      sh/tests/find-files/folder2/alphabet
  93. 0
      sh/tests/find-files/folder2/az
  94. 0
      sh/tests/find-files/folder2/ba/aa/alphabetz!
  95. 0
      sh/tests/find-files/folder2/ba/aa/cz
  96. 0
      sh/tests/find-files/folder2/ba/aa/za!
  97. 0
      sh/tests/find-files/folder2/ba/ac
  98. 0
      sh/tests/find-files/folder2/ba/alphabetz
  99. 0
      sh/tests/find-files/folder2/bz
  100. 0
      sh/tests/find-files/folder2/cz
  101. Some files were not shown because too many files changed in this diff diff.show_more

57
.github/ISSUE_TEMPLATE/bug_report.md

@ -1,53 +1,32 @@
---
name: 🐛 Bug report
about: Create a report to help us improve
title: "[BUG] "
labels: "🐛 bug"
assignees: ""
---
### Environment
**Describe the bug**
A clear and concise description of what the bug/error is.
Device (web, mobile):
**Users**
Usernames of students/admin that are affected by the issue:
Operating system (Windows, macOS, Linux):
**Severity**
Choose the severity label (❗minor), (‼ major), or (⚠ critical).
Browser (Chrome, Firefox, Safari, Brave):
**Type**
Choose the label (🖌 ui), (⚙ functionality), (🗂 documentation), or (🔐 security)
### Steps to reproduce the issue = what action results in the issue
**To Reproduce**
Steps to reproduce the behavior:
URL of the page:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
Steps to follow:
**Workarounds**
Any known workarounds for the issue:
1.
2.
**Expected behavior**
A clear and concise description of what you expected to happen.
Usernames of students that are affected by the issue:
**Attachments**
If applicable, add screenshots/videos/logs to help explain your problem.
<sub>Using tools like [Loom](https://chrome.google.com/webstore/detail/loom-for-chrome/liecbddmkiiihnedobmlmillhodjkdmb)</sub>
### Expected Result = How the software should have performed
**Desktop (please complete the following information):**
What was the expected outcome of the action taken in `step 3` ?
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
### Actual Result = How the software actually performed
**Smartphone (please complete the following information):**
Actual outcome of the action taken in `step 3`
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
Error message that appears (if applicable)
**Additional context**
Add any other context about the problem here.
### Visual Proof
Screenshots & Videos (using [Loom](https://chrome.google.com/webstore/detail/loom-for-chrome/liecbddmkiiihnedobmlmillhodjkdmb))

21
.github/ISSUE_TEMPLATE/feature_request.md

@ -1,28 +1,11 @@
---
name: 🪄 Feature request
about: Suggest a feature or an enhancement for this project
title: "[FEATURE] "
labels: "🪄 feature"
assignees: ""
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Type**
Choose the label (🖌 ui), (⚙ functionality), (🗂 documentation), or (🔐 security)
**Expected benefit**
A clear and concise description of the expected benefit of the feature, including any relevant metrics or data to support its value:
**Target audience**
Who will benefit from this feature (e.g. users, developers, administrators):
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context & attachments**
Add any other context, screenshots, or additional attachments, such as mockups or prototypes, to provide more context for the feature.
**Additional context**
Add any other context or screenshots about the feature request here.

46
.github/workflows/docker-images.yml

@ -1,46 +0,0 @@
name: Docker Image CI
on:
push:
branches: ['master']
pull_request:
branches: ['master']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to docker.01-edu.org Registry
uses: docker/login-action@v2.1.0
with:
registry: docker.01-edu.org
username: ${{ secrets.USER_DOCKER_01EDU_ORG }}
password: ${{ secrets.SECRET_DOCKER_01EDU_ORG }}
- name: Build the Sh Docker image
if: always()
run: |
docker build sh/tests/ --file sh/tests/Dockerfile --tag ghcr.io/01-edu/test-sh:latest
docker push ghcr.io/01-edu/test-sh:latest
- name: Build the JS Docker image
if: always()
run: |
docker build js/tests/ --file js/tests/Dockerfile --tag ghcr.io/01-edu/test-js:latest
docker push ghcr.io/01-edu/test-js:latest
- name: Build the DOM Docker image
if: always()
run: |
docker build . --file dom/Dockerfile --tag ghcr.io/01-edu/test-dom:latest
docker push ghcr.io/01-edu/test-dom:latest

278
docs/addition_of_exercise_draft.md

@ -0,0 +1,278 @@
# THE ADDITION OF EXERCISE PROCEDURE
**Needs to be updated since the refactor**
##### This is for a go exercise in the piscine-go
## **1. Writing the subject and / or writing the solution**
Always address each exceptional cases.
Example: [fprime](https://github.com/01-edu/public/blob/master/subjects/fprime.en.md).
The exceptional cases in the `usage` part.
```console
$ go run . 225225
3*3*5*5*7*11*13
$ go run . 8333325
3*3*5*5*7*11*13*37
...
$ go run . 0
$ go run . 1
1
$
```
The subject states that only **positive integer** will be tested, however, 0 and 1 are not primes.
The subject writer made a mistake because of forgetting that fact.
During the exam, the test was testing the `1` case and expecting a `1\n` to be printed. The real result should only have been a `\n`.
Some students found this mistake. An update of the subject during the exam treating that special case was immediately necessary.
1. Try to avoid the “you” and contracted “language”
2. Always check the formating md
---
### fprime <span style="color:#ff3234">(Title of the exercise)</span>
#### Instructions <span style="color:#ff3234">(Instructions of the exercise)</span>
Write a program that takes a positive `int` and displays its prime factors, followed by a newline (`'\n'`). <span style="color:#ff3234">(general guidelines, notice the imperative style tense and the avoidance of “you”. “You” is authorized in the case of a presence of a back story where the player is immersed)</span>
- Factors must be displayed in ascending order and separated by `*`. <span style="color:#ff3234">(formating requirement) </span>
- If the number of arguments is different from 1, the program displays a newline. <span style="color:#ff3234">(special case requirement, this case will need to be tested)</span>
- The input, when there is one, will always be valid. <span style="color:#ff3234">(Clarification on what the tester will do, hence giving the student guidelines on the cases to be handled, the tests have to reflect this instruction as well)</span>
- In this exercise the primes factor of 1 is considered as 1. <span style="color:#ff3234">(Handling of exceptional case: THIS Happens to be a mistake, we will see uses this example for the “UPDATING A SUBJECT/TEST PROCEDURE”)</sapn>
### Usage
```console
$ go run . 225225
3*3*5*5*7*11*13
$ go run . 8333325
3*3*5*5*7*11*13*37
$ go run . 9539
9539
$ go run . 804577
804577
$ go run . 42
2*3*7
$ go run . a
$ go run . 0
$ go run . 1
1
$
```
---
## **2. Creating the files for tests (4 main cases)**
### always in -> _all/tests/go/_
### **Folder organization**
- Function exercise in a Quest `(strlen)`
- 2 files:
- strlen_test.go
- solutions/strlen.goz
```console
go
| strlen_test.go
|
| __ solutions
| |-strlen.go (package solutions)
|
| __ student (the same thing as the solutions, just run "cp -aT solutions/ student/")
```
- Program exercise in a Quest `(doop)`
- 2 files
- doop_test.go
- solutions/doop/main.go
```console
go
| doop_test.go
|
|
| __ solutions
| |__doop
| |-main.go (package main)
|
| __ student (the same thing as the solutions, just run "cp -aT solutions/ student/")
```
- Program exercise in the exam `(dooprog)`
- 2 files
- solutions/doopprog/main.go
- solutions/doopprog/doopprog_test.go
```console
go
|
| __ solutions
| | __ doopprog
| |-main.go (package main)
| |-doopprog_test.go
|
| __ student (the same thing as the solutions, just run "cp -aT solutions/ student/")
```
- Function exercise in the exam `(atoiprog)`
- 3 files
- solutions/atoi.go
- solutions/atoiprog/main.go
- solutions/atoiprog/atoiprog_test.go
```console
go
|
| __ solutions
| |
| |-atoi.go (package solutions)
| |__atoiprog
| |-main.go (package main)(func main(){} stays empty)
| |-atoiprog_test.go
|
| __ student (the same thing as the solutions, just run "cp -aT solutions/ student/")
```
---
## **3. Writing a file_test.go (test file for go)**
### <span style="color:#00bae6">**RULE 1**</span>
- Make the test as independent as possible (no self-made functions imported)
- **If** the source is not in the import section, copy and paste the function, with **lowercase** for the first letter of its name.
- Example: addprimesum_test.go
![isaprime](isaprime.png)
The func isAPrime is fully copied to the file.
### <span style="color:#00bae6">**RULE 2**</span>
Every special case in the subject should be tested. Preferably first. Before the randoms tests
### <span style="color:#00bae6">**RULE 3**</span>
Whenever possible do at least 1 random test! This is to avoid cheating by predictability of the tests. If the tests are fixed, then the student may create a forest of ifs program to bypass the tester.
### z01.functions to be used by tester
- Function exercise in a Quest (strlen) ![z01sl](strlenz01.png)
```go
z01.Challenge(t, studentSol, studentStu) // if the program doesn’t have arguments
z01.Challenge(t, studentSol, studentStu, args...) //if the program has arguments
```
- Program exercise in a Quest (doop) ![z01doop](doopz01.png)<- Screenshots to be added.
```go
z01.ChallengeMain(t) // if the program doesn’t have arguments
z01.ChallengeMain(t, args...) // if the program has arguments
```
- Program exercise in the exam (dooprog) Screenshots to be added.
```go
z01.ChallengeMainExam(t) // if the program doesn’t have arguments
z01.ChallengeMainExam (t, args...) // if the program has arguments
```
- Function exercise in the exam (Atoiprog) Screenshots to be added.
```go
z01.Challenge(t, studentSol, studentStu) // if the program doesn’t have arguments
z01.Challenge(t, studentSol, studentStu, args...) //if the program has arguments
```
---
## **4. Testing locally (`go test` or `go test -run=Test\<nameOfTheFunction\>`)**
### you do -run=... because you have many test files, so you need to run just one
### Before every PR : a go test has to be executed (in several situations) in the folder(s) of the exercise(s) worked on
**First thing first**
```console
rm -r student
cp -aT solutions/ student
```
### Execute a go test in the appropriate folder
- Function exercise in a Quest `(strlen)` ![](image.png)
`all/test/go`
```console
go test -run=TestStrlen
```
- Program exercise in a Quest `(doop)` ![](image.png)<- Screenshots to be added.
`all/test/go/`
```console
go test -run=TestDoop
```
- Program exercise in the exam `(dooprog)` Screenshots to be added.
Here you can do just _go test_, because there's only one test file
`all/test/go/student/dooprog`
```console
go test
```
- Function exercise in the exam `(atoiprog)` Screenshots to be added.
`all/test/go/student/atoiprog`
```console
go test
```
### **NOTE:** If a go test gives a (cached) result, use this type of command (example with raid3):
`go test count=1 raid3_test.go`
The result should be an OK message:
- This means that the test is running correctly when the correct solution is given. If this does not work, the test file is likely to have errors inside.
- Time should be under 5-6 seconds. If longer, remove some of the iteration of the random tests (for example, less random tests)
- Be watchful of exercises with challenge function: Always test a copy of the variable and not the same variable for both the student and the solution function.
- Introduce errors in the student solution.go file in order to see the errors message and compare them to the subject examples.
- Error messages for structures exercises (linked lists, binary trees) need to be tailored accordingly.

92
docs/audits-at-home/README.md

@ -0,0 +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!

83
docs/audits-at-home/README_ru.md

@ -0,0 +1,83 @@
## Как проводить аудиты удаленно
Сначала небольшое напоминание,
Аудиты, как мы неоднократно говорили, являются неотъемлемой частью вашего обучения и получения реальных навыков.
Обычно они должны проводиться оффлайн.
Идея состоит в том, что это способствует обмену знаний между аудиторами и членами группы.
Если проект провалится, вся группа будет знать точную причину. И после того, как все ваши проверки будут выполнены, вы попытаетесь сдать еще раз, с новообретенными знаниями.
Во время всех этих дополнительных проверок вы, как группа, будете обсуждать с аудиторами ваши недочеты.
Если проект будет успешным, вы будете вдохновлять аудиторов.
В любом случае вы будете либо учиться или либо учить кого-то. Роли учителя/ученика меняются почти каждый раз.
Это, в конечном счете, те взаимодействия, которые необходимы для реального обучения;
Давать и получать отзывы, а также видеть то, что ты действительно знаешь, а что нет.
Это улучшит вашу способность решать проблемы, вашу способность адаптироваться, что является одним из наиболее важных навыков хорошего программиста.
Сегодня мы снова должны адаптироваться ...
Иметь знания конечно хорошо, но здоровье важнее.
Мы действительно желаем всем вам оставаться дома в безопасности.
Поэтому мы разработали небольшое руководство по проведению аудита из дома.
Ссылка на видео: [youtube.com/watch?v=J8g8P-IJLJw](https://www.youtube.com/watch?v=J8g8P-IJLJw)
Также, можете прочесть:
### Необходимые вещи для коммуникации аудитора и капитана команды
- Программы для коммуникации и стрима (Discord подойдет)
- teamViewer или что-то похожее чтобы дать аудитору доступ к вашему компьютеру
### Что нужно сделать капитану:
- Собрать команду перед аудитом.
- Дать аудитору доступ к git, либо сделав репу публичной, либо сделав аудитора коллаборатором
- Залогиниться в платформе чтобы аудитор начал проверку
### Что нужно сделать аудитору:
- Договориться с командой на счет времени проверки
- Скачать репу проекта
- Стримить процесс проверки команде
### Инструкции
1. Аудитор договаривается на счет времени проверки с командой
2. Как только все будет готово, начинает проверку
3. Если возможно, аудитор запускает стрим, чтобы команда видела саму проверку.
4. Капитан, зайдя на платформу, разрешает аудитору взять под контроль свой компьютер (TeamViewer)
5. Теперь аудитор может запустить проверку на компьютере капитана.
Организация окон со стороны аудитора может быть сложной частью. Мы предлагаем
посмотреть видео, и узнать как мы это сделали.
6. Аудитор проводит проверку, если аудитор не может в прямом эфире транслировать свою проверку, он или она
затем объяснит голосом (или в чате), что он или она делает и как проверяет.
7. Аудит проводится до тех пор, пока все вопросы не верны или пока не будет допущена ошибка.
8. Если проект сломался на каком-либо тесте, аудитор может показать команде при каком тесте произошла ошибка.
9. Группа обсуждает потенциальное место ошибки столько, сколько необходимо, до завершения аудита.
10. После завершения аудита все программы могут быть закрыты. Скажите пока и спасибо за ваше время и сделайте
необходимые выводы среди членов группы.
### Conclusion
Спасибо, что дочитали до конца. Оставайтесь в безопасности.
### Bonus
Знаете ли вы, что есть хорошее расширение `Live Share` в` vscode`?
Это позволяет легко выполнять дистанционное групповое программирование. Это может быть альтернативным решением
для прямого эфира, если это необходимо.
Попробуйте!
Будьте в безопасности! Удачного кодинга!

190
docs/event-management.md

@ -0,0 +1,190 @@
# Events management
## Usage
An event is associated to an object when the usage of this object implies:
- a limited capacity of people
- a limited time
Event management require:
- Edition of the attributes of the object on which the event is based
- Creation and settings of the event associated to the reference object
> Events are used for: `piscines`, `check-in`, `exams`, `rushes`, `hackatons`, `conferences`.
## Settings for the reference object
Important indications:
- Objects that doesn't have required attributes for event creation will not be open to event creation.
| name | fullfillment |
| -------------------- | ------------ |
| capacity | **required** |
| eventDuration | **required** |
| registrationDuration | **required** |
| description | optionnal |
| eventStartDelay | optionnal |
- All the attributes filled in the object are used as values by default for event's creation; it can be overloaded for each event related to the reference object.
- If the reference object has a child or children which are events itself, settings are also required for each event child.
#### Edit the object attributes:
> in _Object attributes_
<img width="1073" alt="Capture d’écran 2019-08-22 à 11 40 34" src="img/63525316-64e0da80-c4f5-11e9-9e61-57d5a73da9b1.png">
- Add a new key **capacity** of type `Number` with the maximum number of persons you want for events related to the object by default
- Add a new key **eventDuration** of type `Number` with the duration in minutes you want for events related to the object by default
- Add a new key **registrationDuration** of type `Number` with the duration in minutes you want to allow to people to register to the event by default
- Add a new key **eventStartDelay** of type `Number`, if you want a default delay between the end of registration and the beginning of the event. This duration is expressed in minutes.
- Add a new key **description** of type `String`, if you need to associate some informations to your event (description, location, access, documents to provide, etc.)
#### Edit the children
> in _Children_
<img width="609" alt="Capture d’écran 2019-08-22 à 15 43 43" src="img/63525543-c86b0800-c4f5-11e9-8820-60d9ff33994f.png">
- Add a new key **startAfter** of type `Number`, with the default delay you want between the beginning of the event and the beginning of the child event. This duration is expressed in minutes.
##### Example
Here is an example of the `Piscine Go` settings. It presents the settings of the object attributes `Piscine Go`, the settings of one of its child which is an event and the settings of the child object attributes itself.
> NB : this object settings are provided in the admin, in the curses section: 'Piscine Go' and in the exams section 'Exam 01'.
**Piscine Go**
_Object attributes_
```json
{
"capacity": 400,
"eventDuration": 37440,
"registrationDuration": 43200,
"eventStartDelay": 240
}
```
This piscine object attributes look like this:
![piscine-object-attributes](img/piscine-object-attributes.png)
_Children_
> In the `Piscine Go`, children of type _exam_ and _rush_ have events itself.
> A **startAfter** key has to be defined for each of them, in their parent object `Piscine Go`. For example, the exam-01 gets this key:
```json
{
"startAfter": 8160
}
```
This child attributes look like this:
![piscine children attributes](img/63525543-c86b0800-c4f5-11e9-8820-60d9ff33994f.png)
**Exam 01**
> The object `Exam 01`, which is a child of `Piscine Go`, has its own _Object Attributes_ filled in the child object.
_Object attributes_
```json
{
"eventDuration": 240,
"registrationDuration": 2160,
"eventStartDelay": 60
}
```
> NB: the **capacity** attribute is herited from the parent object `Piscine Go` here.
This exam object attributes look like this:
![exam-object-attributes](img/exam-object-attributes.png)
## Create the event
### Create a new event for your object
> (in _Admin_ > _Manage events_ > _Add new event_)
<img width="788" alt="Capture d’écran 2019-08-22 à 11 37 13" src="img/63532891-9d87b080-c503-11e9-8ff2-46c7a5b19c12.png">
<img width="789" alt="Capture d’écran 2019-08-22 à 11 37 35" src="img/63533088-02430b00-c504-11e9-9675-bcab7bec825c.png">
<img width="787" alt="Capture d’écran 2019-08-22 à 11 38 07" src="img/63533145-21419d00-c504-11e9-8e80-fb4f53d93b00.png">
- The **reference object** of your event is the object for which you need to create an event: `Check`, `Piscine Go`, etc.
- The **registration starts at** indicates when registration of the event begins.
- The **registration ends at** indicates when registration of the event ends.
- The **event starts at** indicates when the event begins.
> NB:
>
> - End of registration can't be before its beginning.
> - Start of event can't be before end of registration.
> - Date and Time input is not yet working in firefox but should be added soon by mozilla. In the mean while use chrome for adding events
### Settings for you event
> In the event you have created, 3 categories must be checked:
>
> 1. General settings
> 2. Registration's settings
> 3. Event's settings
#### General settings
<img width="785" alt="Capture d’écran 2019-08-22 à 11 39 26" src="img/63533589-015ea900-c505-11e9-8b77-b45b620cd171.png">
General settings of your event can be set after creation of the event. By default, it is the values indicated in the **reference object**.
- **Capacity**
- During the regitration, the capacity doesn't apply. When registration ends, we register the amount defined by the **capacity** to the event _(ordered by registration date)_.
- If someone unregister to the event during a registration, it release one place.
- During a registration, users can see if their place is guaranteed or if they are in waiting list.
- If the event has children which are event themselves, they will use by default the capacity of the parent event
if no capacity was defined on this child.
- **Description** (facultative)
- It can be used to describe the topic of the event, or to add some practical informations: location, documents to provide, accessibility, etc.
#### Registration
<img width="761" alt="Capture d’écran 2019-08-22 à 11 39 37" src="img/63533613-0facc500-c505-11e9-90e8-94254cef5ce3.png">
- End of registration can't be after start of registration.
- Dates can't be updated after it's passed.
- The **registration duration** indicated in the **reference object** is reminded under the inputs to help you fill the informations.
- Same for the **event start delay**.
- The list of users in the registration, pending or accepeted, is accessible by clicking on the link 'N users registered', at the left bottom of this categrory.
#### Event
<img width="740" alt="Capture d’écran 2019-08-22 à 11 39 49" src="img/63533641-1d624a80-c505-11e9-9cd1-e1d156dd7fc4.png">
- End of event can't be after start of event.
- Dates can't be updated after it's passed.
- The **end of event** is calculated by default by adding the **event duration** indicated in the **reference object** to the **start of event** date.
- If the event contains other events, the **end of event** can't be before the end of the last child event.
- The **event duration** indicated in the **reference object** is reminded under the inputs to help you fill the informations.
- If the event contains other events, the **minimum end of event** is indicated under the inputs to help you fill the informations.
- The list of users selected for the event at its creation is accessible by clicking on the link 'N users registered', at the left bottom of this categrory.
#### Children (facultative)
<img width="1009" alt="Capture d’écran 2019-08-22 à 18 24 49" src="img/63535788-29044000-c50a-11e9-835c-f8378558962c.png">
This category appears only if the event has children which are events itself.
- Children settings can't be overloaded.
- Each event child presents:
- Its **Start** and **end** (according to the children settings of the **reference object**)
- Its **capacity**
- Its **groups size**
- Reminder: in `hackatons` or `rushes`, candidates or students registered to the are divided in groups of N persons.

330
docs/grand-prix-go-curriculum.md

@ -0,0 +1,330 @@
# Grand Prix Go curriculum
---
## Week One (Lundi 02/12/19 au DImanche 08/12/19)
### Sprint 1
#### Introduction to shell
Notions: basic usage and interaction with a command line terminal.
Videos:
- 1-2 `curl` with the GitHub api and Example of shell file | https://www.youtube.com/watch?v=A0Mqc215igw
- 1-3 `touch`, `chmod` and `echo` | https://www.youtube.com/watch?v=21h-vsuXgDU
- 1-4 `find` and `grep` | https://www.youtube.com/watch?v=7a1JSWHhJlM
- 1-5 `cut`, `sed` and `tr` | https://www.youtube.com/watch?v=Nil7rVP3eMI
- 1-6 `jq` and `wc` | https://www.youtube.com/watch?v=cQmcaOseuiA&
Exercices:
- introduction | https://public.01-edu.org/subjects/introduction.en
- make-it-better | https://public.01-edu.org/subjects/make-it-better.en
- to-git-or-not-to-git | https://public.01-edu.org/subjects/to-git-or-not-to-git.en
- who-are-you | https://public.01-edu.org/subjects/who-are-you.en
- cl-camp1 | https://public.01-edu.org/subjects/cl-camp1.en
- cl-camp2 | https://public.01-edu.org/subjects/cl-camp2.en
- cl-camp3 | https://public.01-edu.org/subjects/cl-camp3.en
- cl-camp4 | https://public.01-edu.org/subjects/cl-camp4.en
- cl-camp5 | https://public.01-edu.org/subjects/cl-camp5.en
- cl-camp6 | https://public.01-edu.org/subjects/cl-camp6.en
- cl-camp7 | https://public.01-edu.org/subjects/cl-camp7.en
- cl-camp8 | https://public.01-edu.org/subjects/cl-camp8.en
- now-get-to-work | https://public.01-edu.org/subjects/now-get-to-work.en
### Sprint 2
#### Introduction to Go Lang and basic programmation concepts
Notions: Variables declaration, Loops, if and else statement, usage of z01.PrintRune function.
Videos:
- 02-01-If and Else Statements in Go | https://www.youtube.com/watch?v=rnF1_SfeGE4
- 02-02-ForLoops | https://www.youtube.com/watch?v=Bt47lx6q2-4
- 02-03-PrintRune function | https://www.youtube.com/watch?v=o8JrvI3jqoM
- 02-04-Variables Declaration and ascii | https://www.youtube.com/watch?v=RCNOV8m0hJQ
Exercices:
- printalphabet | https://public.01-edu.org/subjects/printalphabet.en
- printreversealphabet | https://public.01-edu.org/subjects/printreversealphabet.en
- prindigits | https://public.01-edu.org/subjects/printdigits.en
- isnegative | https://public.01-edu.org/subjects/isnegative.en
- printcomb | https://public.01-edu.org/subjects/printcomb.en
- printcomb2 | https://public.01-edu.org/subjects/printcomb2.en
- printnbr | https://public.01-edu.org/subjects/printnbr.en
- printcombn | https://public.01-edu.org/subjects/printcombn.en
### Sprint 3
#### Introduction to Go Lang and basic programmation concepts II
Notions: String Manupulation, Range Loops, Pointers, Modulo and Division relative to computer science.
Videos:
- 03-01-StringsManipulation | https://www.youtube.com/watch?v=8LplJN_8iOU
- 03-02-RangeLoop | https://www.youtube.com/watch?v=i89N4cjh1-g
- 03-03-Pointers on variables | https://www.youtube.com/watch?v=owVPa5b1BMc
- 03-04-Modulo and Division | https://www.youtube.com/watch?v=NVan-9-Ioec
Exercices:
- pointone | https://public.01-edu.org/subjects/pointone.en
- ultimatepointone | https://public.01-edu.org/subjects/ultimatepointone.en
- divmod | https://public.01-edu.org/subjects/divmod.en
- ultimatedivmod | https://public.01-edu.org/subjects/ultimatedivmod.en
- printstr | https://public.01-edu.org/subjects/printstr.en
- strlen | https://public.01-edu.org/subjects/strlen.en
- swap | https://public.01-edu.org/subjects/swap.en
- strrev | https://public.01-edu.org/subjects/strrev.en
- basicatoi | https://public.01-edu.org/subjects/basicatoi.en
- basicatoi2 | https://public.01-edu.org/subjects/basicatoi2.en
- atoi | https://public.01-edu.org/subjects/atoi.en
- sortintegerable | https://public.01-edu.org/subjects/sortintegertable.en
### Checkpoint 1 (4hours)
#### Basic functions and programs skills evaluation, based on Sprint 2 and Sprint 3
### CLM (Contre La Montre) 1 - Rectangle Drawing
#### First Group project. Problem resolution. Usage of first knowledge (loop and if/else)
---
## Week Two (Lundi 09/12/2019 à Dimanche 15/12/2019)
### Sprint 4
#### Algorithm concepts
Notions: Iterative and recursive programmation
Videos:
- 04-01-Iterativity and Recursivity | https://www.youtube.com/watch?v=oCZDdAID5Ik
Exercices:
- iterativefactorial | https://public.01-edu.org/subjects/iterativefactorial.en
- recursivefactorial | https://public.01-edu.org/subjects/recursivefactorial.en
- iterativepower | https://public.01-edu.org/subjects/iterativepower.en
- recursivepower | https://public.01-edu.org/subjects/recursivepower.en
- fibonacci | https://public.01-edu.org/subjects/fibonacci.en
- sqrt | https://public.01-edu.org/subjects/sqrt.en
- isprime | https://public.01-edu.org/subjects/isprime.en
- findnextprime | https://public.01-edu.org/subjects/findnextprime.en
- eightqueens | https://public.01-edu.org/subjects/eightqueens.en
### Sprint 5
#### Application of previously viewed concepts.
Notions: String Manipulation and medium-advanced algorithms
Videos:
- 05-01-Runes, Bytes and Strings | https://www.youtube.com/watch?v=-eIU5ISID64
Exercices:
- firstrune | https://public.01-edu.org/subjects/firstrune.en
- nrune | https://public.01-edu.org/subjects/nrune.en
- lastrune | https://public.01-edu.org/subjects/lastrune.en
- index | https://public.01-edu.org/subjects/index.en
- compare | https://public.01-edu.org/subjects/compare.en
- toupper | https://public.01-edu.org/subjects/toupper.en
- tolower | https://public.01-edu.org/subjects/tolower.en
- capitalize | https://public.01-edu.org/subjects/capitalize.en
- isalpha | https://public.01-edu.org/subjects/isalpha.en
- isnumeric | https://public.01-edu.org/subjects/isnumeric.en
- islower | https://public.01-edu.org/subjects/islower.en
- isupper | https://public.01-edu.org/subjects/isupper.en
- isprintable | https://public.01-edu.org/subjects/isprintable.en
- concat | https://public.01-edu.org/subjects/concat.en
- basicjoin | https://public.01-edu.org/subjects/basicjoin.en
- join | https://public.01-edu.org/subjects/join.en
- printnbrbase | https://public.01-edu.org/subjects/printnbrbase.en
- atoibase | https://public.01-edu.org/subjects/atoibase.en
### Sprint 6
#### Usage of OS.Args
Notions: Arguments manipulation in programs
Videos:
- 06-01-Os.Args | https://www.youtube.com/watch?v=I1xt_TLRhF0
Exercices:
- printprogramname | https://public.01-edu.org/subjects/printprogramname.en
- printparams | https://public.01-edu.org/subjects/printparams.en
- revparams | https://public.01-edu.org/subjects/revparams.en
- sortparams | https://public.01-edu.org/subjects/sortparams.en
### Sprint 7
#### The Memory Allocation in GoLang
Notions: Usage of Make and Append
Videos:
- 07-01-Make and Append methods | https://www.youtube.com/watch?v=2HHVUM0YQuI
Exercices:
- appendrange | https://public.01-edu.org/subjects/apprendrange.en
- makerange | https://public.01-edu.org/subjects/makerange.en
- concatparams | https://public.01-edu.org/subjects/concatparams.en
- splitwhitespaces | https://public.01-edu.org/subjects/splitwhitespaces.en
- printwordstables | https://public.01-edu.org/subjects/printwordstables.en
- convertbase | https://public.01-edu.org/subjects/converbase.en
- split | https://public.01-edu.org/subjects/split.en
### Checkpoint 2 (4hours)
#### Basic functions and programs skills evaluation, based on Sprint 2 and Sprint 6
### CLM (Contre La Montre) 2 - Sudoku
#### Second Group project. Problem resolution. Usage of Memory manipulation tools
---
## Week Three + Holiday project (Lundi 16/12/2019 à dimache 05/01/2020 )
### Sprint 8
#### Introduction to Structures and advanced types in GoLang
Notions: Creation of struct types and file manipulation (Open, Read, Close methods)
Videos:
- 08-01-Structures in Go | https://www.youtube.com/watch?v=-24M7r7VuLY
- 08-02-File Manipulation in go | https://www.youtube.com/watch?v=8vUgchQGhcQ
Exercices:
- bool | https://public.01-edu.org/subjects/bool.en
- point | https://public.01-edu.org/subjects/point.en
- displayfile | https://public.01-edu.org/subjects/displayfile.en
- cat | https://public.01-edu.org/subjects/cat.en
- ztail | https://public.01-edu.org/subjects/ztail.en
### Sprint 9
#### Functions as argument
Notions: Advance function prototyping
Videos:
- 09-01-Functions as Arguments | https://www.youtube.com/watch?v=lw8jUwsluAE
Exercices:
- foreach | https://public.01-edu.org/subjects/foreach.en
- map | https://public.01-edu.org/subjects/map.en
- any | https://public.01-edu.org/subjects/any.en
- countif | https://public.01-edu.org/subjects/countif.en
- issorted | https://public.01-edu.org/subjects/issorted.en
- doop | https://public.01-edu.org/subjects/doop.en
- sortwordarr | https://public.01-edu.org/subjects/sortwordarr.en
- advancedsortwordarr | https://public.01-edu.org/subjects/advancedsortwordarr.en
### Sprint 10
#### Hackathon
Notions: All previously viewed concepts in team work
Exercices:
- rot14 | https://public.01-edu.org/subjects/rot14.en
- abort | https://public.01-edu.org/subjects/abort.en
- collatzcountdown | https://public.01-edu.org/subjects/collatzcountdown.en
- comcheck | https://public.01-edu.org/subjects/comcheck.en
- enigma | https://public.01-edu.org/subjects/enigma.en
- pilot | https://public.01-edu.org/subjects/pilot.en
- fixthemain | https://public.01-edu.org/subjects/fixthemain.en
- compact | https://public.01-edu.org/subjects/compact.en
- activebits | https://public.01-edu.org/subjects/activebits.en
- max | https://public.01-edu.org/subjects/max.en
- join | https://public.01-edu.org/subjects/join.en
- unmatch | https://public.01-edu.org/subjects/unmatch.en
### Checkpoint 3 (4hours)
#### Basic functions and programs skills evaluation, based on Sprint 2 and Sprint 8
### CLM (Contre La Montre) 3 - File Reader ( Projet pour les 2 semaines de vacances)
#### Second Group project. Problem resolution. File manipulation based on CLM (Contre La Montre) 1
---
## Week Four (lundi 06/01/2020 à vendredi 10/01/2020)
### Sprint 11
#### Linked lists in GoLang
Notions: Pointers manipulation and data structure
Videos:
- 11-01-Linked Lists Introduction | https://www.youtube.com/watch?v=EPICVEbylU0
Exercices:
- listpushback | https://public.01-edu.org/subjects/listpushback.en
- listpushfront | https://public.01-edu.org/subjects/listpushfront.en
- listsize | https://public.01-edu.org/subjects/listsize.en
- listlast | https://public.01-edu.org/subjects/listlast.en
- listclear | https://public.01-edu.org/subjects/listclear.en
- listat | https://public.01-edu.org/subjects/listat.en
- listreverse | https://public.01-edu.org/subjects/listreverse.en
- listforeach | https://public.01-edu.org/subjects/listforeach.en
- listforeachif | https://public.01-edu.org/subjects/listforeachif.en
- listfind | https://public.01-edu.org/subjects/listfind.en
- listremoveif | https://public.01-edu.org/subjects/listremoveif.en
- listmerge | https://public.01-edu.org/subjects/listmerge.en
- listsort | https://public.01-edu.org/subjects/listsort.en
- sortlistinsert | https://public.01-edu.org/subjects/sortlistinsert.en
- sortedlistmerge | https://public.01-edu.org/subjects/sortedlistmerge.en
### Sprint 12
#### Binary Trees
Notions: Advanced Data Structure using binary trees
Videos:
- 12-01-Introduction to Binary Trees | https://www.youtube.com/watch?v=3g2WCqWNIVs
Exercices:
- btreeinsertdata | https://public.01-edu.org/subjects/btreeinsertdata.en
- btreeapplyinorder | https://public.01-edu.org/subjects/btreeapplyinorder.en
- btreeapplypreorder | https://public.01-edu.org/subjects/btreeapplypreorder.en
- btreesearchitem | https://public.01-edu.org/subjects/btreesearchitem.en
- btreelevelcount | https://public.01-edu.org/subjects/btreelevelcount.en
- btreeisbinary | https://public.01-edu.org/subjects/btreeisbinary.en
- btreeapplylevel | https://public.01-edu.org/subjects/btreeapplylevel.en
- btreemax | https://public.01-edu.org/subjects/btreemax.en
- btreemin | https://public.01-edu.org/subjects/btreemin.en
- btreetransplant | https://public.01-edu.org/subjects/btreetransplant.en
- btreedeletenode | https://public.01-edu.org/subjects/btreedeletenode.en
### Checkpoint 4 - Final Checkpoint (8hours)
#### Functions and programs skills evaluation, based on Sprint 2 and Sprint 11

65
docs/metrics.md

@ -0,0 +1,65 @@
## Metrics card - Export of students' results
### Where to find the data
Metrics for students from a given campus can be found in the Metrics card in the Admin dashboard.
### Important information
- Data can be exported in csv and json formats
- Data is filtered by campus, exports include all historical data for that campus.
- We will later develop a feature that enables filtering information before downloading it
- Data is updated every hour
- The download link is valid for 24 hours
- We recommend sharing the downloaded document itself instead of the download link as the link contains the admin’s authorisation token
### Description of the data included in the exports
| Field | Example | Description |
| --------------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **user** | MarieMalarme | Student’s github username |
| **first_name** | Marie | Student’s first name |
| **last_name** | Malarme | Student’s last name |
| **object** | who-are-you | Name of the object for which a result is given |
| **type** | exercise | There are 3 object types: <br/> - exercise (for quests and exams) <br/> - raid <br/> - project |
| **parent** | Quest 01 | The object’s hierarchical parent: <br/> - If the object is an exercise, the parent will be either a quest or an exam. <br/> - If the object is a raid or a project, the parent will be the module (piscine or div) |
| **module** | piscine-go | The part of the curriculum in which the object is included, either a piscine (piscine Go, piscine JS, piscine Rust) or the main curriculum (Div01) |
| **path** | /madere/piscine-go/quest-01/who-are-you | The url to that object, which outlines the path and hence the hierarchical structure to that object |
| **attempts** | 2 | Number of submission attempts made by the student |
| **status** | succeeded | Current status of the student's work on the object: <br/> - "available" indicates that the student has started working on the object but either hasn't submitted it yet to be corrected, or is waiting for the auditing process to be completed <br/> - "succeeded" and "failed" are attributed once the object has been corrected |
| **xp** | 325 | Number of XPs gained by the student for succeeding |
| **base_xp** | 325 | Maximum number of XPs the student can get for succeeding for that object |
| **grade** | 1 | The student’s score for that object is a number between 0 (failed) and 1 (succeeded). If the object is a project, the grade can be superior to 1 when the student successfully passes bonus questions |
| **last_update** | 2020-07-27T15:39:46.368Z | Date and time of the student’s latest activity for that object |
### Explanation of the XP and Grade calculation
#### Exercises within quests
- _Test mode_: automatic tester
- _XPs_: fixed value. Students get all the points when succeeding at the exercise, no matter how many attempts they made.
- _Grade_: 0 (failure) or 1 (success)
#### Exercises within exams
- _Contextual information_:
- Exams consist of many exercises which are grouped by difficulty levels. The student is randomly assigned an exercise from each level and has to succeed in order to move on to the next exercise level.
- Each exercise level has a maximum amount of XPs which grows according to the level’s difficulty.
- Exams are limited in time so students have to successfully complete as many exams as they can as fast as they can with the least amount of errors.
- _Test mode_: automatic tester
- _XPs_: variable value. Students get the maximum amount of points when they succeed at the first attempt. Each failed submission reduces the amount of XPs the student can get for that level.
- _Grade_: 0 (failure) or 1 (success)
#### Raids
- _Test mode_: projects are evaluated by a jury panel in 2 steps:
- First the jury evaluates the code through an audit, a series of pass / fail questions to be answered by the auditor. Succeeding the audit gives students a certain amount of XPs.
- The jury then interviews students and can decide to give them bonus / malus XPs based on their evaluation of the code and the students’ answers to their questions.
- _XPs_: variable value calculated as a fixed value for succeeding the project plus / minus XPs attributed by the jury at their discretion
- _Grade_: 0 (failure) or 1 (success)
#### Projects
- _Test mode_: audits, which are peer-to-peer evaluations based on a series of pass/fail questions to be answered by the auditor
- _XPs_: variable value. Students can get more than the maximum value of XPs if they complete bonus exercises. They get no XPs at all if they fail at least one of the questions in the audit
- _Grade_: number between 0 and 1, proportionate to the number of questions successfully passed in the audit. The grade can be higher than 1 if the student completed bonus exercises.

244
docs/modular-steps-management.md

@ -0,0 +1,244 @@
# Sign up & onboarding's Administration section - Modular steps management
## Usage
After their first authentication in the app, every candidate has to do his **sign up** and his **onboarding**. The steps that compose the **sign up** and the **administration** section of the onboarding are either:
- Forms (identification, medical information, etc.)
- Documents to sign (general conditions, charts, regulations, etc.)
All the sections are modular: you can add, update, delete and order them as you wish.
This documentation explains how to manage these steps.
## Create your step child object
### Create a new object for your step in the admin
> Information is available for object's creation: [Object creation](object-creation.md)
- This object must have the same type as its future parent object (_signup_ or _onboarding_).
> Your step is then available in the _Admin_. You can find it in the section of its type (_SignUp_ or _Onboarding_) or thanks to the search bar of the cursus object's page.
### Add this new object as a child of your parent's object
- Edit the parent object: _Sign up_ or _Administration_
> Information is available for object's creation: [Child object creation](object-child-creation.md)
## Settings for a `form` step
In the step object you have created, 2 attributes must be filled:
1. Subtype
2. Form
### Description
#### Edit the step object you have created :
> in _Object attributes_
<img width="1073" alt="Capture d’écran 2019-04-22 à 15 59 33" src="img/56507445-3936ef00-6519-11e9-90c8-d85056e9330b.png">
- Add a new key **subtype** of type `String` with the exact value 'form-step'
- Add a new key **form** of type `Object`
- Form can have several sections. Each section is displayed with a title, and its inputs.
> NB: The submission of the form will check the required inputs of all the sections created for the form.
- To create a section, add a new key to the form object, of type `Object`, that contains:
- A **title** key of type `String`. The value of this property will be the title displayed in the top of the form section.
> If there is only one section in the form step, and no section title is needed, this property can be ignored.
- An **inputs** key of type `Object`, which will contain all the inputs of the section. For each wanted input, add a new `Object` element in the "inputs" object.
> The key of this object will be used as the "name" attribute of your input.
> The values will be considered as the properties of your input.
#### Defining an input:
- A **type** key of type `String` must be declared. It defines the type of the input : `tel`, `text`, `date`, `select`, `radio`, `switch`, `checkbox`, `textarea`, `countries`.
- All other attributes needed for the input can be added to the object, according to the input type: `placeholder`, `id`, `required`, `label`, `items`, `emptyItems`, `index`, etc...
#### Important indication:
- The **index** property is used to order the inputs. It will not be passed onto the input. Be mindful not to set the same index twice.
- The **type** property is required. It will be used to determine the kind of input should be generated. It is passed onto the input only if the input type attribute is required (type 'tel' or 'text' for example, but not for type 'select' - in this case, we will generate a select element)
- A special type 'countries' has been added to the classicals. It generate a `Select` (containing all the countries) with a search bar. 'Items' property is handled by the app.
- It's recommended to add 'min' and 'max' properties to input type 'date' (no default value are set).
- `onChange` prop are ignored as the event is handled by the app.
- For `switch` and `checkbox` input types, the default value has to be set as a boolean property named **value**.
- More information for each inputs is available in the design documentation:
- [textInput documentation](<https://((DOMAIN))/docs/Components/FormInputs/TextInput>) - used for inputs type 'text', 'tel', and 'date'
- [textArea documentation](<https://((DOMAIN))/docs/Components/FormInputs/TextArea>)
- [select documentation](<https://((DOMAIN))/docs/Components/FormControls/Select>)
- [radio button documentation](<https://((DOMAIN))/docs/Components/FormControls/Radio>)
- [switch documentation](<https://((DOMAIN))/docs/Components/FormControls/Switch>)
- [checkbox documentation](<https://((DOMAIN))/docs/Components/FormControls/Checkbox>)
### Examples
Here is an example of the form step's attributes. It presents a form with two sections, and an example of each kind of input type.
> NB : this example object is provided in the admin, in the onboarding section: 'Form step example'.
```json
{
"subtype": "form-step",
"form": {
"identification": {
"title": "Identification",
"inputs": {
"firstName": {
"index": 0,
"placeholder": "First name",
"maxLength": 50,
"type": "text",
"required": true
},
"tel": {
"index": 1,
"required": true,
"type": "tel",
"label": "Phone number",
"placeholder": "+333 33 33 33 33",
"pattern": "[+][3][0-9]{2}[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{2}"
},
"medicalInfo": {
"label": "Medical informations",
"placeholder": "Your medical Informations",
"index": 7,
"maxLength": 250,
"type": "textarea"
},
"dateOfBirth": {
"index": 2,
"required": true,
"type": "date",
"label": "Date of birth",
"min": "1621-07-08",
"max": "1900-01-01",
"value": "2000-01-01"
},
"country": {
"index": 4,
"id": "countries",
"type": "countries",
"required": true,
"emptyItem": { "label": "Select your country label" }
},
"gender": {
"index": 3,
"type": "select",
"id": "genders",
"required": true,
"emptyItem": { "label": "Select your gender" },
"items": [
{ "label": "Male", "data": "male" },
{ "label": "Female", "data": "female" }
]
},
"environment": {
"index": 5,
"type": "radio",
"required": true,
"label": "Which environment do you live in ?",
"inlineBlock": true,
"items": [
{ "label": "City", "data": "city" },
{ "label": "Countryside", "data": "countryside" }
]
},
"programmingAbilities": {
"index": 6,
"type": "switch",
"label": "I am new in programming",
"value": true
},
"generalConditions": {
"index": 8,
"type": "checkbox",
"label": "I have read and I accept the general conditions",
"value": false
}
}
},
"moreAboutYou": {
"title": "More about you",
"inputs": {
"favoriteColor": {
"index": 0,
"placeholder": "Your favorite color",
"type": "text",
"required": true
}
}
}
}
}
```
This 'form' step would look like this:
![form-step-example](img/form-step-example.png)
## Settings for a `document to sign` step
The newly created child can be customized with these attributes :
| name | fullfillment |
| ---------- | ------------ |
| subtype | **required** |
| text | **required** |
| buttonText | optionnal |
| checkbox | optionnal |
### Description
#### To set up the child object you have created with these elements:
1. Edit you step object
2. Go to _Object attributes_
3. Add the following attributes:
- Add a new key **subtype** of type `String` with the exact value 'sign-step'
- Add a new key **text** of type `String` with the text of your document to sign as value
- Add a new key **buttonText** of type `String` with the text that you want to display in the submit button of your step. Default value for this attribute is 'Sign'.
- Add a new key **checkbox** of type `Object`, if the user has to be forced to click on a checkbox before validating his document (ex: 'I have read and accepted the conditions'). In the checkbox object, the following attributes should be defined:
- A **label** key of type `String`, for the text associated to the checkbox
- A **required** key of type `Boolean`, set at true if the user has to check it
- A **name** key of type `String`
- All other attributes wanted for the checkbox.
- Add a new key **link** of type `Object`, if a link must be added to the step (ex: download of a .pdf version of the document to sign). In the link object, the following attributes should be defined:
- A **href** key of type `String`, with the link you want to add to the step
- A **label** key of type `String`, for the text displayed for the link (by default, '> Link to the document' is displayed)
- All other attributes wanted for the link.
### Examples
Here is an example of the structure a 'document to sign' step could have:
```json
{
"subtype": "sign-step",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ornare non sem eu pretium. Integer porttitor risus eget nibh iaculis, ac lacinia orci dictum. Nunc ullamcorper consequat enim in posuere. Aliquam volutpat est odio, vel maximus arcu maximus sit amet. Donec ultricies faucibus magna id luctus. Duis et dapibus elit. In vestibulum ipsum erat, at commodo tortor convallis vel. Nunc ut ultrices nulla. Etiam lorem justo, consequat a consectetur a, porttitor non turpis. Mauris eu mollis nisl, id dignissim quam. Curabitur condimentum sollicitudin rutrum. Aenean blandit, arcu nec ullamcorper rhoncus, lectus sem lacinia lorem, venenatis dignissim velit mi et sapien. Nullam posuere augue ut magna ullamcorper dignissim. Ut rhoncus sapien vel nulla commodo finibus. Cras non leo vel urna finibus volutpat. Praesent et ex eget diam tincidunt suscipit. Phasellus bibendum neque vel placerat iaculis. Vestibulum bibendum ultrices ipsum, non sodales lectus. Cras eget orci eget elit blandit scelerisque at ut nulla. Integer ligula eros, eleifend quis sodales a, porttitor sit amet neque. Fusce mollis magna at lectus varius, quis suscipit mi cursus. Etiam id imperdiet metus, in malesuada quam. Aliquam facilisis nunc non sapien condimentum, quis iaculis nisl auctor. Nunc lorem sapien, interdum vel efficitur ac, dapibus a diam. Ut ante urna, sodales in bibendum vel, lacinia ut mauris. In vel placerat leo. In libero dui, tincidunt at sem id, faucibus sollicitudin elit.",
"buttonText": "Sign chart",
"checkbox": {
"name": "acceptChart",
"label": "I have read and accepted the Chart 01",
"required": true
},
"link": {
"label": "Download Chart 01",
"href": "https://help.github.com/en/articles/creating-an-issue",
"download": true,
"target": "_blank"
}
}
```
NB : `target` & `download` are forwarded to the a html element as they are valid html properties
This 'document to sign' step would look like this:
![document-to-sign-step-example](img/document-to-sign-step-example.png)

165
docs/object-attribute-system.md

@ -0,0 +1,165 @@
# Object Attributes System
> This document cover two notions, the edition of attributes and the impact it has relatively to the others Objects.
## Edition of Attributes
> There is no limit to how many attributes can be defined to an Object.
In the "Object Attributes" section of the "Object Edit" Page, the first row is a form to create and append a new attribute. It requires two elements, the name of the attribute and its type (`String`, `Number`, `Boolean`, `Array`, `Object`, `Function`, `Null`). Click 'Add' to create the attribute.
> Within a same Object, each attribute's name must be unique.
Once created, the new attributes appears right below and the ability to associate a value to it is now available. Depending on the type of the attribute, the interface will vary.
- String value input is type String.
- Number value input is type Number.
- Booleans value input appears as a switch, true by default.
- Arrays and Objects content are hidable / showable via the "Show/Hide content" button on the right of the attribute. There is no limit on the depth of Object/Array, however, after a certain level, the interface will start to feel narrow.
- String value input is type String.
- Null will not display any input.
- Function will offer to select from all available functions, save on select.
Any attribute can be delete by clicking on the 'trash' icon on the right hand of it.
Here an example of how the section looks like.
![object-attributes](img/object-attributes.png)
## Attributes and RelationShips
When an attributes is set to an Object, other Objects, associated to this particular Object, will have access to it. Which means that, if an Object A is added as a child of an Object B, A will embed its attributes within the instance of B.
Object's attributes follow a hierarchy when associated to an other Object.
The **defaults attributes** of a child, the ones defined in the original Object are the weakest ones. A **children attribute** is applied to all the children and override the default attributes. Finally, **relation attribute** is the strongest one, it override Default Attributes and Children Attributes.
When an object and its relationship are resolved, the three structures (`attrs`, `childrenAttrs`, `childAttrs`) are merged.
The following json shows how the object would be represented:
```json
{
"children": {
"printalphabet": {
"duration": 3600,
"xp": 800,
"isBonus": true
}
}
}
```
Children
![children](img/children.png)
Child
![child-capture](img/child-capture.png)
## Detailed example
Let's create a few `exercises` objects
> swap
```js
{
"id": 12344,
"title": "swap",
"attrs": {
"language": "go",
"duration": 7200
}
}
```
> printalphabet
```js
{
"id": 12345,
"title": "printalphabet-v2",
"attrs": {
"language": "go",
"duration": 3600
}
}
```
We can now create a parent object that will reference them and link them.
This allow you to specify the structuration of your pedagogical content.
I'll make a quest that regroup those 2 exercises:
> quest-03
```js
{
"id": 12346,
"title": "quest-03",
"attrs": {},
"childrenAttrs": {
"xp": 800,
"duration": 4800,
},
"children": {
"printalphabet": {
"ref": 12345,
"index": 0,
"attrs": {
"duration": 7200
}
},
"swap": {
"ref": 12344,
"index": 1,
"attrs": {}
}
}
}
```
All done, now when rendering an object, attributes are merged like so:
> rendered quest object
```js
{
"id": 12346,
"title": "quest-03",
"attrs": {},
"children": {
"printalphabet": {
"ref": 12345,
"index": 0,
"attrs": {
"language": "go",
"xp": 800,
"duration": 7200
}
},
"swap": {
"ref": 12344,
"index": 1,
"attrs": {
"language": "go",
"xp": 800,
"duration": 4800
}
}
}
}
```
First we apply the **default attributes** from the referenced object.
> Here `duration` and `language` are applied.
Then we apply the **children attributes** to every child.
> In this case we override every `duration` to 4800 and add the new `xp` attribute.
After that we apply the **relation attributes**, that are the most specific and as such,
override all others attributes.
> In this case only the `printalphabet` relation had attributes and so we apply
> the given `duration` to the final merged object.

40
docs/object-child-creation.md

@ -0,0 +1,40 @@
# Admin object's management - create a child object
## Usage
Objects of the Admin can be configured :
- By setting particular **attributes** to the object
- By associating **children** to the object
Children can be added, deleted, reordered in the list. Also, it's possible to configure it in a special way for the parent object, by setting children attributes for all the children.
This documentation explains how to associate a child to a parent object.
### Create a new object for your child in the admin
> Information is available for object's creation: [Object Creation](object-creation.md)
### Add this new object as a child of your parent's object
#### 1. Edit the parent object
<img width="640" alt="Capture d’écran 2019-04-22 à 19 24 23" src="img/56517407-cb98bc00-6534-11e9-98d6-a2b1c0193a38.png">
<img width="640" alt="Capture d’écran 2019-04-22 à 19 24 10" src="img/56517421-d0f60680-6534-11e9-86ef-97fb9e59786e.png">
#### 2. Go to _Children_ > _Add a child_
![add-child-to-parent-object](img/add-child-to-parent-object.png)
#### 3. Set up the new child:
- Enter its name in the input "Add a child name"
- Select your step object in the select input
- Click on "ADD"
Your step is then related to its parent. You can see it in the _Children_ section of the parent's object. There, you can now:
- Delete the child from its parent (the actual object of your child will not be deleted).
- Reorder it in the children's list, by dragging it to the place you want.
- Update its original settings by clicking on the eye icon of its reference (redirection to object edit page of the child).
<img width="1229" alt="Capture d’écran 2019-04-22 à 19 51 12" src="img/56518936-a1e19400-6538-11e9-81c7-520ffd365cff.png">

58
docs/object-creation.md

@ -0,0 +1,58 @@
# Admin object's management - create an object
## Usage
Elements of the app are managed through objects in _Admin_.
Objects of the Admin are first created and defined:
- By their **title**,
- By their **type**.
Then it can be configured through:
- Attributes,
- Children.
> This documentation explains how to create an object.
### Create a new object in the admin
> (in _Admin_ > _Add new object_)
<img width="664" alt="Capture d’écran 2019-04-22 à 15 57 37" src="img/56507169-6505a500-6518-11e9-89bb-04c7fd9b41ca.png">
<img width="450" alt="Capture d’écran 2019-04-22 à 15 58 21" src="img/56507180-6afb8600-6518-11e9-97a5-4dcff8f0a069.png">
- The **title** of your object will be the title displayed to your candidates. Use an intellegible title for your user.
> NB: you can always edit it in the _Admin_
- The **type** depends on the nature of your object:
- **Campus** is used to declare a school.
- Examples: _Alem_, _Madeira_, etc.
- Campus can contains cursus: _Alem_ contains for example _01-classical_ and _Piscine Go_.
- **Cursus** is used to declare a course.
- Examples: _01-classical_, _Piscine Go_, etc.
- Cursuses can contains cursuses: the main cursus _01-classical_, for example, contains cursuses like _Piscine Go_, but also all the branches that the student have access to, as _Web_, _Security_, _Algorythm_, _Design_, etc.
- Cursuses can contains quests: _Piscine Go_ of _01-classical_ contains quests like _Quest 1_ or _Quest 2_.
- **Quest** is used to declare a project.
- Examples: _Quest 1_, _Quest 2_, etc.
- Quest contains exercises: _Quest 1_ of _Piscine Go_ contains exercises like _printalphabet_ or _printcomb_.
- Exercise is used to declare exercises
- Examples: _printalphabet_, _printcomb_, _atoi_, etc.
- Exercises doesn't contains any children.
- Signup is used to declare steps of the registration.
- Examples: _Using our services_, _Tell us more about you_, etc.
- One major object _Sign up_ contains all the sign up's modular steps : _Using our services_, _Tell us more about you_, etc.
- Onbaording is used to declare steps of the onbaording.
- Examples: _Toad_, _Administration_, _Additional Informations_, _Chart 01_, etc.
- Three main objects define the major steps of the onboarding : _Toad_, _Administration_, _Piscine_.
- _Administration_ contains modular steps: _Additional Informations_, _Chart 01_, etc.
The child object is then available in the _Admin_. It can be found in the section of its type or thanks to the search bar of the cursus object's page.
More information is available:
- for setting attributes of an object: (soon available)
- for setting children of an object: [Child object creation](object-child-creation.md)
- for creation of modular steps in Sign up and onboarding's Administration object: [Modular step management](modular-steps-management.md)

34
docs/object-edit.md

@ -0,0 +1,34 @@
# Objects Edition
> Allow you to edit an object, see and manage its relations.
## Page Composition
![object-edit-overview](img/object-edit-overview.png)
### Pin 1
- Link back to the "Objects" page ;
- Editable name field, hit 'enter' or 'cmd + s' or click on the floppy-disk icon to save ;
- Major dependencies visualisation, (where my object is used as a child), click the label to navigate to the dependence ;
- External URL, this is an optional parameter, it's use to point at an other source of content or information needed by the object. We generaly use to point at a Git repository ;
### Pin 2
- Delete Button, Warning there, it will destroy your object! ;
- Type of your Object (`organisation`, `campus`, `onboarding`, `cursus`, `quest`, `exercise`), save on select ;
- Status of your Object (`draft`, `online`, `offline`), save on select ;
- The first and last name of the original author ;
### Pin 3
- Object Attribute edition area, manage all the attributes relative to this Object. These attributes will be exposed to its relationship ;
### Pin 4
- Object Children edition area ;
- Children Attributes edition area, these attributes impact and overload all the following children. Works the same way as standard attributes ;
- Add a child, allows to add a child to the children list, more information here -> [Object Child creation](object-child-creation.md) ;
- Children List, allows you to reorganise, delete and edit child. Each child can be overload with its own attributes, the edition works the same way as the original attributes ;
More informations about attribute overload system [here](object-attribute-system.md)

29
docs/objects.md

@ -0,0 +1,29 @@
# Objects
> Allow you to create, manage and organize your pedagical and onboarding content.
## Definition
An Object is an highly customizable element, which can be use in many situations. We use it to compose cursuses and onboarding processes.
Objects can be associated together and then share a vertical or horizontal relationship, which allows to build complex structure of multiple objects.
It structure can be visualized in two parts. The first one is the definition of the object itself and attributes, called `attrs`. The second part is the definition of minor relationships, called `children` and attributes applied to them, called `childrenAttrs`.
This is the minimal structure of an object:
- name
- type (`organisation`, `campus`, `onboarding`, `cursus`, `quest`, `exercise`)
- status (`draft`, `online`, `offline`)
- attrs {}
- childrenAttrs {}
- children {}
## Browse Objects:
To access your Objects, go to the admin dashboard and then click on the _manage object_ link within the "Object" card.
![go-to-objects](img/go-to-objects.png)
Objects are sorted by type in different sections. This page offer a search bar that allow you query the objects by name. In the top-right corner, click the _add a new object_ button to create a new object. Fill a name, select a type and click _create_ to validate your creation. You will be redirected to the Object Edition page (document is here).
![all-object-page](img/all-object-page.png)

28
docs/pc-requirements.md

@ -0,0 +1,28 @@
# PC requirements (Minimum)
Features required:
- **Compatibility with Linux (Ubuntu/Debian x64)**
| Component | Specifications |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Processor | 4 threads x86-64 (64 bits), [2200 single thread performance](https://www.cpubenchmark.net/singleThread.html) / [1000 single-core score](https://browser.geekbench.com/processor-benchmarks) |
| Memory | 8 GB DDR4 |
| Storage | 120 GB SSD |
| Display | 14" Full HD (flicker-free) |
# PC requirements (Recommended)
Features required:
- **Compatibility with Linux (Ubuntu/Debian x64)**
| Component | Specifications |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Processor | 6 threads x86-64 (64 bits), [2600 single thread performance](https://www.cpubenchmark.net/singleThread.html) / [1200 single-core score](https://browser.geekbench.com/processor-benchmarks) |
| Memory | 16 GB DDR4 |
| Storage | 120 GB SSD |
| Display | 17" Full HD (flicker-free) |
|**For comfort:**| An additional display : 24" Full HD (flicker-free). Pivotable to 90 degrees.|
**Important**: Please note that the above requirements do not cover the Game Engine specific branches.

330
docs/piscine-go-curriculum.md

@ -0,0 +1,330 @@
# Piscine Go curriculum
---
## Week One
### Quest 1
#### Introduction to shell
Notions: basic usage and interaction with a command line terminal.
Videos:
- [1-2](https://www.youtube.com/watch?v=A0Mqc215igw) `curl` with the GitHub api and Example of shell file
- [1-3](https://www.youtube.com/watch?v=21h-vsuXgDU) `touch`, `chmod` and `echo`
- [1-4](https://www.youtube.com/watch?v=7a1JSWHhJlM) `find` and `grep`
- [1-5](https://www.youtube.com/watch?v=Nil7rVP3eMI) `cut`, `sed` and `tr`
- [1-6](https://www.youtube.com/watch?v=cQmcaOseuiA&) `jq` and `wc`
Exercices:
- [introduction](https://github.com/01-edu/public/tree/master/subjects/introduction/README.md)
- [make-it-better](https://github.com/01-edu/public/tree/master/subjects/make-it-better/README.md)
- [to-git-or-not-to-git](https://github.com/01-edu/public/tree/master/subjects/to-git-or-not-to-git/README.md)
- [who-are-you](https://github.com/01-edu/public/tree/master/subjects/who-are-you/README.md)
- [cl-camp1](https://github.com/01-edu/public/tree/master/subjects/cl-camp1/README.md)
- [cl-camp2](https://github.com/01-edu/public/tree/master/subjects/cl-camp2/README.md)
- [cl-camp3](https://github.com/01-edu/public/tree/master/subjects/cl-camp3/README.md)
- [cl-camp4](https://github.com/01-edu/public/tree/master/subjects/cl-camp4/README.md)
- [cl-camp5](https://github.com/01-edu/public/tree/master/subjects/cl-camp5/README.md)
- [cl-camp6](https://github.com/01-edu/public/tree/master/subjects/cl-camp6/README.md)
- [cl-camp7](https://github.com/01-edu/public/tree/master/subjects/cl-camp7/README.md)
- [cl-camp8](https://github.com/01-edu/public/tree/master/subjects/cl-camp8/README.md)
- [now-get-to-work](https://github.com/01-edu/public/tree/master/subjects/now-get-to-work/README.md)
### Quest 2
#### Introduction to Go Lang and basic programmation concepts
Notions: Variables declaration, Loops, if and else statement, usage of z01.PrintRune function.
Videos:
- [02-01-If](https://www.youtube.com/watch?v=rnF1_SfeGE4) and Else Statements in Go
- [02-02-ForLoops](https://www.youtube.com/watch?v=Bt47lx6q2-4)
- [02-03-PrintRune](https://www.youtube.com/watch?v=o8JrvI3jqoM) function
- [02-04-Variables](https://www.youtube.com/watch?v=RCNOV8m0hJQ) Declaration and ascii
Exercices:
- [printalphabet](https://github.com/01-edu/public/tree/master/subjects/printalphabet/README.md)
- [printreversealphabet](https://github.com/01-edu/public/tree/master/subjects/printreversealphabet/README.md)
- [prindigits](https://github.com/01-edu/public/tree/master/subjects/printdigits/README.md)
- [isnegative](https://github.com/01-edu/public/tree/master/subjects/isnegative/README.md)
- [printcomb](https://github.com/01-edu/public/tree/master/subjects/printcomb/README.md)
- [printcomb2](https://github.com/01-edu/public/tree/master/subjects/printcomb2/README.md)
- [printnbr](https://github.com/01-edu/public/tree/master/subjects/printnbr/README.md)
- [printcombn](https://github.com/01-edu/public/tree/master/subjects/printcombn/README.md)
### Quest 3
#### Introduction to Go Lang and basic programmation concepts II
Notions: String Manupulation, Range Loops, Pointers, Modulo and Division relative to computer science.
Videos:
- [03-01-StringsManipulation](https://www.youtube.com/watch?v=8LplJN_8iOU)
- [03-02-RangeLoop](https://www.youtube.com/watch?v=i89N4cjh1-g)
- [03-03-Pointers](https://www.youtube.com/watch?v=owVPa5b1BMc) on variables
- [03-04-Modulo](https://www.youtube.com/watch?v=NVan-9-Ioec) and Division
Exercices:
- [pointone](https://github.com/01-edu/public/tree/master/subjects/pointone/README.md)
- [ultimatepointone](https://github.com/01-edu/public/tree/master/subjects/ultimatepointone/README.md)
- [divmod](https://github.com/01-edu/public/tree/master/subjects/divmod/README.md)
- [ultimatedivmod](https://github.com/01-edu/public/tree/master/subjects/ultimatedivmod/README.md)
- [printstr](https://github.com/01-edu/public/tree/master/subjects/printstr/README.md)
- [strlen](https://github.com/01-edu/public/tree/master/subjects/strlen/README.md)
- [swap](https://github.com/01-edu/public/tree/master/subjects/swap/README.md)
- [strrev](https://github.com/01-edu/public/tree/master/subjects/strrev/README.md)
- [basicatoi](https://github.com/01-edu/public/tree/master/subjects/basicatoi/README.md)
- [basicatoi2](https://github.com/01-edu/public/tree/master/subjects/basicatoi2/README.md)
- [atoi](https://github.com/01-edu/public/tree/master/subjects/atoi/README.md)
- [sortintegerable](https://github.com/01-edu/public/tree/master/subjects/sortintegertable/README.md)
### Exam 1 (4hours)
#### Basic functions and programs skills evaluation, based on Quest 2 and Quest 3
### Raid 1 - Square Drawing
#### First Group project. Problem resolution. Usage of first knowledge (loop and if/else)
---
## Week Two
### Quest 4
#### Algorithm concepts
Notions: Iterative and recursive programmation
Videos:
- [04-01-Iterativity and Recursivity](https://www.youtube.com/watch?v=oCZDdAID5Ik)
Exercices:
- [iterativefactorial](https://github.com/01-edu/public/tree/master/subjects/iterativefactorial/README.md)
- [recursivefactorial](https://github.com/01-edu/public/tree/master/subjects/recursivefactorial/README.md)
- [iterativepower](https://github.com/01-edu/public/tree/master/subjects/iterativepower/README.md)
- [recursivepower](https://github.com/01-edu/public/tree/master/subjects/recursivepower/README.md)
- [fibonacci](https://github.com/01-edu/public/tree/master/subjects/fibonacci/README.md)
- [sqrt](https://github.com/01-edu/public/tree/master/subjects/sqrt/README.md)
- [isprime](https://github.com/01-edu/public/tree/master/subjects/isprime/README.md)
- [findnextprime](https://github.com/01-edu/public/tree/master/subjects/findnextprime/README.md)
- [eightqueens](https://github.com/01-edu/public/tree/master/subjects/eightqueens/README.md)
### Quest 5
#### Application of previously viewed concepts.
Notions: String Manipulation and medium-advanced algorithms
Videos:
- [05-01-Runes](https://www.youtube.com/watch?v=-eIU5ISID64), Bytes and Strings
Exercices:
- [firstrune](https://github.com/01-edu/public/tree/master/subjects/firstrune/README.md)
- [nrune](https://github.com/01-edu/public/tree/master/subjects/nrune/README.md)
- [lastrune](https://github.com/01-edu/public/tree/master/subjects/lastrune/README.md)
- [index](https://github.com/01-edu/public/tree/master/subjects/index/README.md)
- [compare](https://github.com/01-edu/public/tree/master/subjects/compare/README.md)
- [toupper](https://github.com/01-edu/public/tree/master/subjects/toupper/README.md)
- [tolower](https://github.com/01-edu/public/tree/master/subjects/tolower/README.md)
- [capitalize](https://github.com/01-edu/public/tree/master/subjects/capitalize/README.md)
- [isalpha](https://github.com/01-edu/public/tree/master/subjects/isalpha/README.md)
- [isnumeric](https://github.com/01-edu/public/tree/master/subjects/isnumeric/README.md)
- [islower](https://github.com/01-edu/public/tree/master/subjects/islower/README.md)
- [isupper](https://github.com/01-edu/public/tree/master/subjects/isupper/README.md)
- [isprintable](https://github.com/01-edu/public/tree/master/subjects/isprintable/README.md)
- [concat](https://github.com/01-edu/public/tree/master/subjects/concat/README.md)
- [basicjoin](https://github.com/01-edu/public/tree/master/subjects/basicjoin/README.md)
- [join](https://github.com/01-edu/public/tree/master/subjects/join/README.md)
- [printnbrbase](https://github.com/01-edu/public/tree/master/subjects/printnbrbase/README.md)
- [atoibase](https://github.com/01-edu/public/tree/master/subjects/atoibase/README.md)
### Quest 6
#### Usage of OS.Args
Notions: Arguments manipulation in programs
Videos:
- [06-01-Os.Args](https://www.youtube.com/watch?v=I1xt_TLRhF0)
Exercices:
- [printprogramname](https://github.com/01-edu/public/tree/master/subjects/printprogramname/README.md)
- [printparams](https://github.com/01-edu/public/tree/master/subjects/printparams/README.md)
- [revparams](https://github.com/01-edu/public/tree/master/subjects/revparams/README.md)
- [sortparams](https://github.com/01-edu/public/tree/master/subjects/sortparams/README.md)
### Quest 7
#### The Memory Allocation in GoLang
Notions: Usage of Make and Append
Videos:
- [07-01-Make](https://www.youtube.com/watch?v=2HHVUM0YQuI) and Append methods
Exercices:
- [appendrange](https://github.com/01-edu/public/tree/master/subjects/apprendrange/README.md)
- [makerange](https://github.com/01-edu/public/tree/master/subjects/makerange/README.md)
- [concatparams](https://github.com/01-edu/public/tree/master/subjects/concatparams/README.md)
- [splitwhitespaces](https://github.com/01-edu/public/tree/master/subjects/splitwhitespaces/README.md)
- [printwordstables](https://github.com/01-edu/public/tree/master/subjects/printwordstables/README.md)
- [convertbase](https://github.com/01-edu/public/tree/master/subjects/converbase/README.md)
- [split](https://github.com/01-edu/public/tree/master/subjects/split/README.md)
### Exam 2 (4hours)
#### Basic functions and programs skills evaluation, based on all the quests from 2 to 6
### Raid 2 - Sudoku
#### Second Group project. Problem resolution. Usage of Memory manipulation tools
---
## Week Three
### Quest 8
#### Introduction to Structures and advanced types in GoLang
Notions: Creation of struct types and file manipulation (Open, Read, Close methods)
Videos:
- [08-01-Structures](https://www.youtube.com/watch?v=-24M7r7VuLY) in Go
- [08-02-File](https://www.youtube.com/watch?v=8vUgchQGhcQ) Manipulation in go
Exercices:
- [bool](https://github.com/01-edu/public/tree/master/subjects/bool/README.md)
- [point](https://github.com/01-edu/public/tree/master/subjects/point/README.md)
- [displayfile](https://github.com/01-edu/public/tree/master/subjects/displayfile/README.md)
- [cat](https://github.com/01-edu/public/tree/master/subjects/cat/README.md)
- [ztail](https://github.com/01-edu/public/tree/master/subjects/ztail/README.md)
### Quest 9
#### Functions as argument
Notions: Advance function prototyping
Videos:
- [09-01-Functions](https://www.youtube.com/watch?v=lw8jUwsluAE) as Arguments
Exercices:
- [foreach](https://github.com/01-edu/public/tree/master/subjects/foreach/README.md)
- [map](https://github.com/01-edu/public/tree/master/subjects/map/README.md)
- [any](https://github.com/01-edu/public/tree/master/subjects/any/README.md)
- [countif](https://github.com/01-edu/public/tree/master/subjects/countif/README.md)
- [issorted](https://github.com/01-edu/public/tree/master/subjects/issorted/README.md)
- [doop](https://github.com/01-edu/public/tree/master/subjects/doop/README.md)
- [sortwordarr](https://github.com/01-edu/public/tree/master/subjects/sortwordarr/README.md)
- [advancedsortwordarr](https://github.com/01-edu/public/tree/master/subjects/advancedsortwordarr/README.md)
### Quest 10
#### Hackathon
Notions: All previously viewed concepts in team work
Exercices:
- [rot14](https://github.com/01-edu/public/tree/master/subjects/rot14/README.md)
- [abort](https://github.com/01-edu/public/tree/master/subjects/abort/README.md)
- [collatzcountdown](https://github.com/01-edu/public/tree/master/subjects/collatzcountdown/README.md)
- [comcheck](https://github.com/01-edu/public/tree/master/subjects/comcheck/README.md)
- [enigma](https://github.com/01-edu/public/tree/master/subjects/enigma/README.md)
- [pilot](https://github.com/01-edu/public/tree/master/subjects/pilot/README.md)
- [fixthemain](https://github.com/01-edu/public/tree/master/subjects/fixthemain/README.md)
- [compact](https://github.com/01-edu/public/tree/master/subjects/compact/README.md)
- [activebits](https://github.com/01-edu/public/tree/master/subjects/activebits/README.md)
- [max](https://github.com/01-edu/public/tree/master/subjects/max/README.md)
- [join](https://github.com/01-edu/public/tree/master/subjects/join/README.md)
- [unmatch](https://github.com/01-edu/public/tree/master/subjects/unmatch/README.md)
### Exam 3 (4hours)
#### Basic functions and programs skills evaluation, based on all the quests from 2 to 8
### Raid 3 - File Reader
#### Second Group project. Problem resolution. File manipulation based on Raid 1
---
## Week Four
### Quest 11
#### Linked lists in GoLang
Notions: Pointers manipulation and data structure
Videos:
- [11-01-Linked](https://www.youtube.com/watch?v=EPICVEbylU0) Lists Introduction
Exercices:
- [listpushback](https://github.com/01-edu/public/tree/master/subjects/listpushback/README.md)
- [listpushfront](https://github.com/01-edu/public/tree/master/subjects/listpushfront/README.md)
- [listsize](https://github.com/01-edu/public/tree/master/subjects/listsize/README.md)
- [listlast](https://github.com/01-edu/public/tree/master/subjects/listlast/README.md)
- [listclear](https://github.com/01-edu/public/tree/master/subjects/listclear/README.md)
- [listat](https://github.com/01-edu/public/tree/master/subjects/listat/README.md)
- [listreverse](https://github.com/01-edu/public/tree/master/subjects/listreverse/README.md)
- [listforeach](https://github.com/01-edu/public/tree/master/subjects/listforeach/README.md)
- [listforeachif](https://github.com/01-edu/public/tree/master/subjects/listforeachif/README.md)
- [listfind](https://github.com/01-edu/public/tree/master/subjects/listfind/README.md)
- [listremoveif](https://github.com/01-edu/public/tree/master/subjects/listremoveif/README.md)
- [listmerge](https://github.com/01-edu/public/tree/master/subjects/listmerge/README.md)
- [listsort](https://github.com/01-edu/public/tree/master/subjects/listsort/README.md)
- [sortlistinsert](https://github.com/01-edu/public/tree/master/subjects/sortlistinsert/README.md)
- [sortedlistmerge](https://github.com/01-edu/public/tree/master/subjects/sortedlistmerge/README.md)
### Quest 12
#### Binary Trees
Notions: Advanced Data Structure using binary trees
Videos:
- [12-01-Introduction](https://www.youtube.com/watch?v=3g2WCqWNIVs) to Binary Trees
Exercices:
- [btreeinsertdata](https://github.com/01-edu/public/tree/master/subjects/btreeinsertdata/README.md)
- [btreeapplyinorder](https://github.com/01-edu/public/tree/master/subjects/btreeapplyinorder/README.md)
- [btreeapplypreorder](https://github.com/01-edu/public/tree/master/subjects/btreeapplypreorder/README.md)
- [btreesearchitem](https://github.com/01-edu/public/tree/master/subjects/btreesearchitem/README.md)
- [btreelevelcount](https://github.com/01-edu/public/tree/master/subjects/btreelevelcount/README.md)
- [btreeisbinary](https://github.com/01-edu/public/tree/master/subjects/btreeisbinary/README.md)
- [btreeapplylevel](https://github.com/01-edu/public/tree/master/subjects/btreeapplylevel/README.md)
- [btreemax](https://github.com/01-edu/public/tree/master/subjects/btreemax/README.md)
- [btreemin](https://github.com/01-edu/public/tree/master/subjects/btreemin/README.md)
- [btreetransplant](https://github.com/01-edu/public/tree/master/subjects/btreetransplant/README.md)
- [btreedeletenode](https://github.com/01-edu/public/tree/master/subjects/btreedeletenode/README.md)
### Exam 4 - Final Exam (8hours)
#### Functions and programs skills evaluation, based on all the quests from 2 to 11

150
docs/piscine-rust-curriculum.md

@ -0,0 +1,150 @@
# Piscine Rust curriculum
---
## Week One
### Quest 01-rust
Exercises:
- fibonacci2 | https://github.com/01-edu/public/tree/master/subjects/fibonacci2
- scalar | https://github.com/01-edu/public/tree/master/subjects/scalar
- temperature_conv | https://github.com/01-edu/public/tree/master/subjects/temperature_conv
- looping | https://github.com/01-edu/public/tree/master/subjects/looping
- speed_transformation | https://github.com/01-edu/public/tree/master/subjects/speed_transformation
- groceries | https://github.com/01-edu/public/tree/master/subjects/groceries
- reverse_string | https://github.com/01-edu/public/tree/master/subjects/reverse_string
- find_factorial | https://github.com/01-edu/public/tree/master/subjects/find_factorial
- matrix_transposition | https://github.com/01-edu/public/tree/master/subjects/matrix_transposition
- division_and_remainder | https://github.com/01-edu/public/tree/master/subjects/division_and_remainder
- tuples | https://github.com/01-edu/public/tree/master/subjects/tuples
### Quest 02-rust
Exercices:
- ownership | https://github.com/01-edu/public/tree/master/subjects/ownership
- copy | https://github.com/01-edu/public/tree/master/subjects/copy
- borrow | https://github.com/01-edu/public/tree/master/subjects/borrow
- doubtful | https://github.com/01-edu/public/tree/master/subjects/doubtful
- borrow_me_the_reference | https://github.com/01-edu/public/tree/master/subjects/borrow_me_the_reference
- changes | https://github.com/01-edu/public/tree/master/subjects/changes
- string_literals | https://github.com/01-edu/public/tree/master/subjects/string_literals
- name_initials | https://github.com/01-edu/public/tree/master/subjects/name_initials
- arrange_it | https://github.com/01-edu/public/tree/master/subjects/arrange_it
- tic_tac_toe | https://github.com/01-edu/public/tree/master/subjects/tic_tac_toe
### Quest 03-rust
Exercices:
- circle | https://github.com/01-edu/public/tree/master/subjects/circle
- card_deck | https://github.com/01-edu/public/tree/master/subjects/card_deck
- arrays | https://github.com/01-edu/public/tree/master/subjects/arrays
- strings | https://github.com/01-edu/public/tree/master/subjects/strings
- edit_distance | https://github.com/01-edu/public/tree/master/subjects/edit_distance
- to_url | https://github.com/01-edu/public/tree/master/subjects/to_url
- capitalizing | https://github.com/01-edu/public/tree/master/subjects/capitalizing
- hashing | https://github.com/01-edu/public/tree/master/subjects/hashing
- string_permutation | https://github.com/01-edu/public/tree/master/subjects/string_permutation
- bigger | https://github.com/01-edu/public/tree/master/subjects/bigger
- simple_hash | https://github.com/01-edu/public/tree/master/subjects/simple_hash
- collect | https://github.com/01-edu/public/tree/master/subjects/collect
---
## Week Two
## Quest 04-rust
Exercices:
- unwrap_or_expect | https://github.com/01-edu/public/tree/master/subjects/unwrap_or_expect
- panic | https://github.com/01-edu/public/tree/master/subjects/panic
- handling | https://github.com/01-edu/public/tree/master/subjects/handling
- profanity_filter | https://github.com/01-edu/public/tree/master/subjects/profanity_filter
- question_mark | https://github.com/01-edu/public/tree/master/subjects/question_mark
- banner | https://github.com/01-edu/public/tree/master/subjects/banner
- cipher | https://github.com/01-edu/public/tree/master/subjects/cipher
- error_types | https://github.com/01-edu/public/tree/master/subjects/error_types
- boxing_todo | https://github.com/01-edu/public/tree/master/subjects/boxing_todo
## Quest 05-rust
Exercices:
- middle_day | https://github.com/01-edu/public/tree/master/subjects/middle_day
- does_it_fit | https://github.com/01-edu/public/tree/master/subjects/does_it_fit
- macro_calculator | https://github.com/01-edu/public/tree/master/subjects/macro_calculator
- shopping_mall | https://github.com/01-edu/public/tree/master/subjects/shopping_mall
- expected_variable | https://github.com/01-edu/public/tree/master/subjects/expected_variable
- mobs | https://github.com/01-edu/public/tree/master/subjects/mobs
## Quest 06-rust
Exercices:
- traits | https://github.com/01-edu/public/tree/master/subjects/traits
- lifetimes | https://github.com/01-edu/public/tree/master/subjects/lifetimes
- lalgebra_scalar | https://github.com/01-edu/public/tree/master/subjects/lalgebra_scalar
- matrix | https://github.com/01-edu/public/tree/master/subjects/matrix
- matrix_ops | https://github.com/01-edu/public/tree/master/subjects/matrix_ops
- matrix_mult | https://github.com/01-edu/public/tree/master/subjects/matrix_mult
- lalgebra_vector | https://github.com/01-edu/public/tree/master/subjects/lalgebra_vector
- blood_types | https://github.com/01-edu/public/tree/master/subjects/blood_types
- border_cross | https://github.com/01-edu/public/tree/master/subjects/border_cross
- roman_numbers | https://github.com/01-edu/public/tree/master/subjects/roman_numbers
- generics | https://github.com/01-edu/public/tree/master/subjects/generics
- roman_numbers_iter | https://github.com/01-edu/public/tree/master/subjects/roman_numbers_iter
- vectors_operations | https://github.com/01-edu/public/tree/master/subjects/vector_operations
- events | https://github.com/01-edu/public/tree/master/subjects/events
- delete_prefix | https://github.com/01-edu/public/tree/master/subjects/delete_prefix
- commits_stats | https://github.com/01-edu/public/tree/master/subjects/commits_stats
---
## Week Three
## Quest 07-rust
Exercices:
- box_it | https://github.com/01-edu/public/tree/master/subjects/box_it
- borrow_box | https://github.com/01-edu/public/tree/master/subjects/borrow_box
- box_recursion | https://github.com/01-edu/public/tree/master/subjects/box_recursion
- how_many_references | https://github.com/01-edu/public/tree/master/subjects/how_many_references
- ref_cell | https://github.com/01-edu/public/tree/master/subjects/ref_cell
- drop_the_thread | https://github.com/01-edu/public/tree/master/subjects/drop_the_thread
## Quest 08-rust
Exercices:
- closures | https://github.com/01-edu/public/tree/master/subjects/closures
- sales | https://github.com/01-edu/public/tree/master/subjects/sales
- adding | https://github.com/01-edu/public/tree/master/subjects/adding
- adding_twice | https://github.com/01-edu/public/tree/master/subjects/adding_twice
- get_products | https://github.com/01-edu/public/tree/master/subjects/get_products
- highest | https://github.com/01-edu/public/tree/master/subjects/highest
- iterators | https://github.com/01-edu/public/tree/master/subjects/iterators
- slices_to_map | https://github.com/01-edu/public/tree/master/subjects/slices_to_map
- step_iterator | https://github.com/01-edu/public/tree/master/subjects/step_iterator
- project_motion | https://github.com/01-edu/public/tree/master/subjects/project_motion
## Quest 09-rust
Exercices:
- stars | https://github.com/01-edu/public/tree/master/subjects/stars
- ordinal | https://github.com/01-edu/public/tree/master/subjects/ordinal
- pangram | https://github.com/01-edu/public/tree/master/subjects/pangram
- diamond_creation | https://github.com/01-edu/public/tree/master/subjects/diamond_creation
- scores | https://github.com/01-edu/public/tree/master/subjects/scores
- talking | https://github.com/01-edu/public/tree/master/subjects/talking
- searching | https://github.com/01-edu/public/tree/master/subjects/searching
- logic_number | https://github.com/01-edu/public/tree/master/subjects/logic_number
- rot | https://github.com/01-edu/public/tree/master/subjects/rot
- pig_latin | https://github.com/01-edu/public/tree/master/subjects/pig_latin
- spelling | https://github.com/01-edu/public/tree/master/subjects/spelling
- rgb_match | https://github.com/01-edu/public/tree/master/subjects/rgb_match

2
docs/reviews.md

@ -47,4 +47,4 @@ You can have those 4 cases :
| fail | failed | **succeeded** |
| fail | succeeded | **failed** |
| succeed | succeeded | **succeeded** |
| succeed | failed | **failed** |
| succeed | failed | **failed** |

62
docs/server-installation.md

@ -0,0 +1,62 @@
# Server installation
## 🌐 DNS Configuration
The following DNS records should be configured in your domain's [zone file](https://en.wikipedia.org/wiki/Zone_file) or through the web interface of your dns provider/domain registrar.
- A _domain/subdomain_ pointing to the public IP address (using `A Record`) of your [dedicated server](server-requirements.md).
- A _subdomain_ called `git` pointing to the above mentioned *domain/subdomain* (using `CNAME Record`) or it's IP address (using `A Record`).
Your newly configured DNS records should look like this:
| FQDN | Record type | Target |
| -------------- | ----------- | ------------- |
| ((DOMAIN)) | A | X.X.X.X |
| git.((DOMAIN)) | CNAME | ((DOMAIN)) |
Here is an _example_ of the DNS records for the domain `example.org` with the public IP address of `93.184.216.34`:
| FQDN | Record type | Target |
| -------------- | ----------- | ------------- |
| example.org | A | 93.184.216.34 |
| git.example.org | CNAME | example.org |
## 🛠 Network Configuration
### ➡ Inbound
| Port | Protocol(s) | Service/Application |
| ----------- | ----------- | ------------------- |
| 80 | TCP | HTTP/(1.1, 2, 3) |
| 443 | TCP | HTTP(S)/(1.1, 2, 3) |
| 521 | TCP | SSH |
| 8080 - 8090 | TCP | HTTP/(1.1, 2, 3) |
### ⬅ Outbound
| Port | Protocol(s) | Service/Application |
| ----------- | ----------- | -------------------- |
| 587 | TCP | SMTP |
| 8080 - 8090 | TCP | HTTP/(1.1, 2, 3) |
## 💿 OS installation
1. Download and boot the `amd64` variant of the [Debian](https://www.debian.org/distrib/netinst) ISO image.
2. Select :
- "**Advanced options ...**"
- "**... Automated install**"
3. The network is automatically configured using your DHCP server. Additionally, you can also configure it manually to suit your preference.
4. At the prompt "Location of initial preconfiguration file:", please enter the following URL :
```console
raw.githubusercontent.com/01-edu/public/master/sh/debian/preseed.cfg
```
5. Then select "**Continue**" and follow the on-screen instructions.
## 🏁 Finishing up
Once the server is ready to be accessed remotely, please let us know via approriate communication channels and we will proceed with configuring the server.

25
docs/server-requirements.md

@ -0,0 +1,25 @@
# Server requirements (Minimum)
Features required:
- Dedicated hardware components (kept in **data centre** conditions)
- Compatibility with **Linux (Debian x64)**
| Component | Specification |
| --------- | ---------------------------------------------------------------------------------- |
| Processor | 8 threads x86-64 (64 bits), [2200 single thread performance](https://www.cpubenchmark.net/singleThread.html) / [1000 single-core score](https://browser.geekbench.com/processor-benchmarks) |
| Memory | 16 GB DDR4 |
| Storage | 2 x 500 GB SSD (`RAID 1` for _redundancy_ or `RAID 0` for _performance/capacity_) |
# Server requirements (Recommended)
Features required:
- Dedicated hardware components (kept in **data centre** environment)
- Compatibility with **Linux (Debian x64)**
| Component | Specification |
| --------- | ---------------------------------------------------------------------------------- |
| Processor | 10 threads x86-64 (64 bits), [2600 single thread performance](https://www.cpubenchmark.net/singleThread.html) / [1200 single-core score](https://browser.geekbench.com/processor-benchmarks) |
| Memory | 32 GB ECC DDR4 |
| Storage | 2 x 500 GB SSD (`RAID 1` for _redundancy_ or `RAID 0` for _performance/capacity_) |

140
docs/setup_of_external_repo.md

@ -0,0 +1,140 @@
# Addition of repository procedure
## Introduction
This document is a guide on how to add your own repository to store your projects and exercises.
This guide assumes that you have understood the files structures of the repository [public](https://github.com/01-edu/public).
It will only address the settings part of this task.
The addition of projects will be treated first as it does not require the knowledge of Docker.
However being familiar with Docker is **mandatory** for adding your own exercises with your own tests.
## Prerequisites
- A GitHub account where your exercises repository will be stored [https://github.com](https://github.com)
- A Docker Hub account [https://hub.docker.com](https://hub.docker.com)
## Setup of GitHub repository
### Create your own public repository
Once logged into your GitHub account, click on the creation of new repository:
It is the button `New` (the button is on the top corner right side).
### Git clone your repository and prepare an example for the folder structure for projects
- Create a folder called `subjects`.
- Inside this folder create a folder called what you wish (example: `firstproject`).
- Inside the folder `firstproject` create a `README.md` file which you will use as the subject content of your first project.
- After the subject content `README.md` is created, create a folder `audit` inside the `firstproject` directory.
- Inside the `audit` folder create a `README.md` that respect the audit type of file. We advise you to take an example such as the
ascii-art audit `README.md` file. Here is the [link](https://raw.githubusercontent.com/01-edu/public/master/subjects/ascii-art/audit/README.md) to the raw file.
- Once all those files are done, git push them to your new repository.
### Publish the repository on GitHub pages
- Go to the settings tab of your projects repository.
- On the option page find the GitHub Pages section.
- Please see below the settings to follow.
(Please not that it might take up to 10 mins for your page to be published)
![screenshot 1](img/adding-exercises-repository/1.png)
- You will notice that a message says Your site is published at “https://yourgithublogin.github.io/nameofyourrepo”
### Configuration of Docker image (if exercises tests need to be added)
The container runs with the following settings (options of `docker run`) :
- `--read-only`
- Mount the container's root filesystem as read only
- `--network none`
- Connect a container to a network without Internet
- `--memory 500M`
- Memory limit
- `--cpus 2.0`
- Number of CPUs
- `--user 1000:1000`
- Username or UID (format: <name|uid>[:<group|gid>])
- `--env EXERCISE=hello-world`
- Exercise name
- `--env USERNAME=aeinstein`
- Student's login
- `--env HOME=/jail`
- Home directory of the container
- `--env TMPDIR=/jail`
- Temporary directory of the container
- `--workdir /jail`
- Working directory inside the container
- `--tmpfs /jail:size=100M,noatime,exec,nodev,nosuid,uid=1000,gid=1000,nr_inodes=5k,mode=1700`
- Mount a tmpfs directory on `/jail`, 100 MB writable.
- `--volume volume_containing_student_repository:/jail/student:ro`
- Bind mount a volume containing the student repository.
Example of a [Dockerfile](https://github.com/01-edu/public/blob/master/js/tests/Dockerfile) and its [entrypoint](https://github.com/01-edu/public/blob/master/js/tests/entrypoint.sh).
## The addition of a custom project
**Take note of the paths of a project subject you added and add them to the attributes**
Example:
If user Frenchris, added an exercise to the nameofyourrepo called `firstproject`
This is the path where the README.md subject would be.
https://frenchris.github.io/nameofyourrepo/subjects/firstproject/
Note that you do not keep the README.md at the end of the path but you do keep the `/`.
This path should be added to the attribute “subject” of type string in the object attribute of the new exercise.
Additionally the README.md audit path would be.
https://frenchris.github.io/nameofyourrepo/subjects/firstproject/audit/
This path should be added to the attribute “subject” of type string in the object attribute of the new exercise.
- Once both those path are noted, create your project on your server.
- Add the regular attributes (`groupMin`, `groupMax`, `language`, `exerciseType`).
- Add the optional attributes to test if your wish (`auditsRatio`, `auditsRequired`) both set to 1.
- And add the `audit` and `subject` attributes (of type `string`) with the previously noted paths.
Now that the attributes are filled.
- Create a module, called `Div-custom` for example. Add its standard attributes.
- Add `firstproject` as a child to `Div-custom`.
**Note**: If you do not wish students from other events to be selected for matches in this new event.
in the children attributes of the module,
- Add `matchWhere` as a `FUNCTION`.
- Set its value to `USERINEVENT`.
This attribute will isole the event during matches to the user of the event.
- Add this `Div-custom` as a child in your campus object.
- Go to event, and launch the event `yourcampus/Div-custom`.
- Add yourself and other testing accounts to the newly launched event.
- Test your subject by creating a group and launching an audit
If the paths are correctly inputed and your repository is correctly publicly published on GitHub pages, you will see your subject and your audit in the platform.
## Setup of your Docker repository
1. Sign in your Docker Hub account and link it to your repository.
2. In your account, go to your settings and link your GitHub account.
3. Create a repository named “test” and make sure that your GitHub account is linked.
If you see this image,
![screenshot 2](img/adding-exercises-repository/2.png)
It means your GitHub account is correctly linked.
4. In the Builds tab configure the automated build settings as below (for the go tests).
![screenshot 3](img/adding-exercises-repository/3.png)
5. Once the build is complete (it can take 5 to 15 mins). Go back to the attributes of the exercise:
- Add the attribute **testImage (type string)**.
The `testImage` attribute is the name of the [Docker](https://docs.docker.com/get-started) image used to run the container responsible for testing the student's code.
- Fill it with the name of the repository,
**in this example: frenchris/test**
6. Once your exercise has both the attributes completed correctly, the exercise is viable and can be tested on the server which was selected for its addition.
7. As a reminder to test the exercise it is suggested to follow these steps:
- `Create` a custom `Quest-test` object
- `Adding` the new `exercise` object as a child to the newly created `Quest-test` object
- `Create` a `Piscine-test` object
- `Adding` the new `Quest-test` as a child to the newly created `Piscine-test` object
- `Adding` the `Piscine-test` to the `campus` object as **first child**
- Go to the event page and launch the newly created `Piscine-test`. (You may need to refresh the page 2-3 times before the `campus/Piscine-test` option appears)
- Once the event is launched, use the event page to add yourself as a student in the launched event `Piscine-test`
- You can now try the exercise. If everything is well set, the subject should be loaded and, when you submit a correct solution, the exercise should pass.

67
docs/ubuntu-installation.md

@ -0,0 +1,67 @@
# Ubuntu
## OS Installation
Download and boot the [latest Ubuntu release](https://releases.ubuntu.com/21.04/ubuntu-21.04-desktop-amd64.iso).
Follow the steps with these customizations:
![img1](img/ubuntu-installation/1.png)
![img2](img/ubuntu-installation/2.png)
![img3](img/ubuntu-installation/3.png)
The partitioning is:
1. 256 MB : EFI partition
2. 20 GB : system partition
![img4](img/ubuntu-installation/4.png)
![img5](img/ubuntu-installation/5.png)
Remove the installation disk and then reboot.
Skip the welcoming window.
Don't install updates if Ubuntu asks to. The scripts will.
## Admin access
You can add your public SSH key to access the administrator account later:
```shell
unset HISTFILE
sudo mkdir /root/.ssh
sudo wget github.com/xpetit.keys --output-document !$/authorized_keys
sudo chmod 400 !$
```
## OS configuration
Run a terminal and type these commands:
```shell
unset HISTFILE
sudo apt -y install git
git clone https://github.com/01-edu/public.git
public/sh/debian/ubuntu/setup.sh
```
The script will ask for student user password (which will be deleted after) and then after a long configuration process it will restart the computer.
The system is now read-only, every data is written to a temporary partition.
The session is password-less.
To gain a superuser terminal, use SSH:
```console
user@remote:~$ ssh -p512 root@IP_ADDRESS
```
To gain access with read/write access to the filesystem, use this command:
```console
root@ubuntu:~# overlayroot-chroot
INFO: Chrooting into [/media/root-ro]
root@ubuntu:/#
```

61
docs/ubuntu-persistent-installation.md

@ -0,0 +1,61 @@
# Ubuntu
## OS Installation
Install the latest version of [Virtual Box](https://www.virtualbox.org/wiki/Downloads).
> The text instructions are more important than the screenshots
Screenshots of the installation of Ubuntu in Virtual Box are [here](https://github.com/xpetit/vbox-ubuntu-install/blob/master/README.md).
Download and boot the [last Ubuntu release](http://releases.ubuntu.com/19.10/ubuntu-19.10-desktop-amd64.iso).
- Create a new virtual machine named "Ubuntu" with at least 4096 MB of RAM
- Use the fixed size storage allocation (to have more performance)
- In the settings of the VM
- System -> Motherboard : check "Enable EFI"
- System -> Processor : Select at least 2 processors
- Display -> Screen : Put "Video Memory" to the maximum
- Enable 3D acceleration
- Storage
- Remove IDE controller
- Add Optical Drive to the SATA controller
- Choose your Ubuntu ISO image
- Close the settings (click OK)
- Run the VM
Follow the screenshots (some settings can be personalized, such as keyboard layout, location, password, login automatically, but **do not change the username**)
Skip the welcoming window.
Don't install updates if Ubuntu asks to. The scripts will.
## OS customization
You can overwrite the files of the folder `system` by setting an environment variable named `OVERWRITE` with the format : `Destination folder;Git URL`.
For example to write the content of the repository [github.com/xpetit/custom](https://github.com/xpetit/custom) in the system folder :
```shell
export OVERWRITE='.;https://github.com/xpetit/custom.git'
```
## OS configuration
Run a terminal and type these commands :
```shell
unset HISTFILE
sudo apt-get -y install git
export PERSISTENT=
git clone https://github.com/01-edu/public.git
public/scripts/setup.sh
```
After reboot you should install Virtual Box additions (and reboot again) :
```shell
sudo apt -y install virtualbox-guest-x11
```
Then it is advised to use the virtual machine in full screen mode (Host key - F)

39
docs/unreal-engine-setup.md

@ -0,0 +1,39 @@
## Setup Guide
This is a guide with all steps to install the Epic Games Launcher and Unreal Engine to get ready to work.
First up you will need to register on [Epic Games](https://www.epicgames.com/id/register?redirect_uri=https%3A%2F%2Fwww.epicgames.com%2Fstore%2Fen-US%2F&client_id=875a3b57d3a640a6b7f9b4e883463ab4).
Then depending on your operating system, you will need the following steps:
### Windows
- On the [Epic Games main page](https://www.epicgames.com/store/en-US/) click on the top right corner button (`Get Epic Games`).
- A download pop up box should appear, then proceed to download the installer.
- After going through all the steps to install the Epic Games Launcher, open it and sign in using your account.
### Linux
- First of all, install `wine` to run Windows programs on Linux systems.
- If you have a 64-bit Linux system use: `sudo apt install wine64`
- If you have a 32-bit Linux system use: `sudo apt install wine32`
- Check if it is installed correctly with: `wine --version`
- Then, install `Lutris` in order to download Epic Games with the following commands:
```sh
sudo add-apt-repository ppa:lutris-team/lutris
sudo apt update
sudo apt install lutris
```
- After `Lutris` is installed, open it and on the top bar, search for `Epic Games` and you will see the result `Epic Games Store`. Go ahead and click on `install`.
- After installing it, open it and sign in with your account.
### Unreal Engine
- Once the Epic Games Launcher is opened, go to the `Unreal Engine` tab and select the Library tab.
- Click on the plus icon to add `Unreal Engine 4` and choose the version to install by clicking on the dropdown list. Then click on install.
- After installing the Unreal Engine, you can click on `Launch` and prepare for the next adventure.

2
js/tests/Dockerfile

@ -1,4 +1,4 @@
FROM docker.01-edu.org/alpine:3.17.0
FROM alpine:3.16.0
# Installs latest Chromium package.
RUN apk add --no-cache \

18
js/tests/bloody-sunday_test.js

@ -0,0 +1,18 @@
export const tests = []
const t = (f) => tests.push(f)
t(() => bloodySunday(new Date('0001-01-01')) === 'Monday')
t(() => bloodySunday(new Date('0001-01-02')) === 'Tuesday')
t(() => bloodySunday(new Date('0001-01-03')) === 'Wednesday')
t(() => bloodySunday(new Date('0001-01-04')) === 'Thursday')
t(() => bloodySunday(new Date('0001-01-05')) === 'Friday')
t(() => bloodySunday(new Date('0001-01-06')) === 'Saturday')
t(() => bloodySunday(new Date('0001-01-07')) === 'Monday')
t(() => bloodySunday(new Date('0001-12-01')) === 'Friday')
t(() => bloodySunday(new Date('1664-08-09')) === 'Saturday')
t(() => bloodySunday(new Date('2020-01-01')) === 'Monday')
t(() => bloodySunday(new Date('2048-12-08')) === 'Thursday')
Object.freeze(tests)

12
js/tests/declarations_test.js

@ -1,13 +1,5 @@
export const tests = []
const t = (f) => tests.push(f)
const isConst = (name) => {
try {
eval(`${name} = 'm'`)
return false
} catch (err) {
return true
}
}
// escapeStr
// is declared and of type string
@ -80,8 +72,4 @@ t(() => nested.obj.update === undefined)
t(() => cantEdit(() => nested.arr.push('hot stuff')))
t(() => nested.arr.length === 3)
// check if all variable are const
t(() => ['escapeStr', 'arr', 'obj', 'nested']
.every(isConst))
Object.freeze(tests)

135
js/tests/friend-support_test.mjs

@ -1,135 +0,0 @@
import { once } from 'node:events'
import { spawn } from 'node:child_process'
import { mkdir, writeFile, chmod } from 'fs/promises'
import { join } from 'path'
export const tests = []
const fetch = _fetch // to redefine the real fetch
const port = 5000
export const setup = async ({ randStr }) => {
const dir = '.'
await mkdir(`${dir}/guests`, { recursive: true })
const randLastName = randStr()
const createFilesIn = ({ files, dirPath }) => {
Promise.all(
files.map(([fileName, content]) =>
writeFile(`${dirPath}/${fileName}`, JSON.stringify(content)),
),
)
}
const sendRequest = async (path, options) => {
const response = await fetch(`http://localhost:${port}${path}`, options)
const { status } = response
const headers = Object.fromEntries(response.headers)
let body = ''
try {
body = await response.json()
} catch (err) {
body = err
}
return { status, body, headers }
}
const startServer = async path => {
const server = spawn('node', [`${path}`])
const message = await Promise.race([
once(server.stdout, 'data'),
Promise.race([
once(server.stderr, 'data').then(String).then(Error),
once(server, 'error'),
]).then(result => Promise.reject(result)),
])
return { server, message }
}
return { tmpPath: dir, createFilesIn, randLastName, sendRequest, startServer }
}
const isServerRunningWell = async ({ path, ctx }) => {
const { server, message } = await ctx.startServer(path)
server.kill()
return message[0].toString().includes(port)
}
const testOneGuest = async ({ path, eq, ctx, randStr }) => {
const { server } = await ctx.startServer(path)
const randMsg = randStr()
const expBody = { message: randMsg }
const files = [[`mario_${ctx.randLastName}.json`, expBody]]
const dirName = 'guests'
const dirPath = join(ctx.tmpPath, dirName)
await ctx.createFilesIn({ dirPath, files })
const { status, body, headers } = await ctx.sendRequest(
`/mario_${ctx.randLastName}`,
{
method: 'GET',
},
)
server.kill()
return eq(
{
status: status,
body: body,
contentType: headers['content-type'],
},
{
status: 200,
body: expBody,
contentType: 'application/json',
},
)
}
const testServerFail = async ({ path, eq, ctx }) => {
const { server } = await ctx.startServer(path)
await chmod(`${ctx.tmpPath}/guests/mario_${ctx.randLastName}.json`, 0)
const { status, body, headers } = await ctx.sendRequest(
`/mario_${ctx.randLastName}`,
{
method: 'GET',
},
)
server.kill()
return eq(
{
status: status,
body: body,
contentType: headers['content-type'],
},
{
status: 500,
body: { error: 'server failed' },
contentType: 'application/json',
},
)
}
const testGuestNotThere = async ({ path, eq, ctx }) => {
const { server } = await ctx.startServer(path)
const { status, body, headers } = await ctx.sendRequest('/andrea_bianchi', {
method: 'GET',
})
server.kill()
return eq(
{
status: status,
body: body,
contentType: headers['content-type'],
},
{
status: 404,
body: { error: 'guest not found' },
contentType: 'application/json',
},
)
}
tests.push(isServerRunningWell, testOneGuest, testServerFail, testGuestNotThere)
Object.freeze(tests)

147
js/tests/gatecrashers_test.mjs

@ -1,147 +0,0 @@
import { once } from 'node:events'
import { spawn } from 'node:child_process'
import { mkdir, writeFile, access } from 'fs/promises'
import { join } from 'path'
export const tests = []
const fetch = _fetch // to redefine the real fetch
const port = 5000
export const setup = async ({}) => {
const dir = '.'
await mkdir(`${dir}/guests`, { recursive: true })
const createFilesIn = ({ files, dirPath }) =>
Promise.all(
files.map(([fileName, content]) =>
writeFile(`${dirPath}/${fileName}`, JSON.stringify(content)),
),
)
const sendRequest = async (path, options) => {
const response = await fetch(`http://localhost:${port}${path}`, options)
const { status } = response
const headers = Object.fromEntries(response.headers)
let body = ''
try {
body = await response.json()
} catch (err) {
body = err
}
return { status, body, headers }
}
const sendRequestWithAuth = async (guestName, auth, body) => {
let options = {
method: 'POST',
headers: {
body: JSON.stringify(body),
},
}
if (auth.len !== 0) {
options.headers.authorization =
'Basic ' + Buffer.from(auth).toString('base64')
}
return sendRequest(guestName, options)
}
const startServer = async path => {
const server = spawn('node', [`${path}`])
const message = await Promise.race([
once(server.stdout, 'data'),
Promise.race([
once(server.stderr, 'data').then(String).then(Error),
once(server, 'error'),
]).then(result => Promise.reject(result)),
])
return { server, message }
}
return {
tmpPath: dir,
createFilesIn,
sendRequest,
sendRequestWithAuth,
startServer,
}
}
const isServerRunningWell = async ({ path, ctx }) => {
const { server, message } = await ctx.startServer(path)
server.kill()
return message[0].toString().includes(port)
}
const testGoodRequests = async ({ path, eq, fail, ctx }) => {
const expectedBody = {
answer: 'yes',
drink: 'juice',
food: 'pizza',
}
const dirName = 'guests'
const dirPath = join(ctx.tmpPath, dirName)
const { server } = await ctx.startServer(path)
const newGuestNames = ['Ana_Riber', 'Rob_Frie', 'George_Harl']
const auths = [
'Caleb_Squires:abracadabra',
'Tyrique_Dalton:abracadabra',
'Rahima_Young:abracadabra',
]
for (var i = 0; i < 3; i++) {
const { status, body, headers } = await ctx.sendRequestWithAuth(
`/${newGuestNames[i]}`,
`${auths[i]}`,
expectedBody,
)
fail(await access(`${dirPath}/${newGuestNames[i]}.json`))
eq(
{ status: status, contentType: headers['content-type'], body: body },
{ status: 200, contentType: 'application/json', body: expectedBody },
)
}
server.kill()
return true
}
const testUnauthorizedRequests = async ({ path, eq, ctx }) => {
const body = {
answer: 'yes',
drink: 'juice',
food: 'pizza',
}
const { server } = await ctx.startServer(path)
const newGuestNames = [
'Super_Mario',
'Super_Mario',
'Super_Mario',
'Super_Mario',
]
const auths = [
'',
'LetMePass',
'Rahima_Young:wrongpass',
'Anonymus:abracadabra',
]
for (var i = 0; i < 3; i++) {
const { status } = await ctx.sendRequestWithAuth(
`/${newGuestNames[i]}`,
`${auths[i]}`,
body,
)
eq({ status: status }, { status: 401 })
}
server.kill()
return true
}
tests.push(isServerRunningWell, testGoodRequests, testUnauthorizedRequests)
Object.freeze(tests)

21
js/tests/keycodes-symphony-dom_test.mjs

@ -1,12 +1,11 @@
export const tests = []
export const setup = async () => {
const getNotes = async (page) =>
await page.$$eval('.note', (nodes) => {
return nodes.map((note) => note.textContent)
})
return { getNotes }
}
export const setup = async ({ page }) => ({
getNotes: async () =>
await page.$$eval('.note', (nodes) => {
return nodes.map((note) => note.textContent)
}),
})
const characters = `didyouhandlethekeydowneventcorrectly`
@ -15,7 +14,7 @@ tests.push(async ({ page, eq, ctx }) => {
for (const [i, character] of characters.split('').entries()) {
await page.keyboard.down(character)
const typed = characters.slice(0, i + 1).split('')
eq(await ctx.getNotes(page), typed)
eq(await ctx.getNotes(), typed)
}
})
@ -25,7 +24,7 @@ tests.push(async ({ page, eq, ctx }) => {
while (step < 10) {
await page.keyboard.down('Backspace')
const typed = characters.slice(0, characters.length - step).split('')
eq(await ctx.getNotes(page), typed)
eq(await ctx.getNotes(), typed)
step++
}
})
@ -33,8 +32,8 @@ tests.push(async ({ page, eq, ctx }) => {
tests.push(async ({ page, eq, ctx }) => {
// check that all the notes are cleared when Escape key is pressed
await page.keyboard.down('Escape')
const cleared = (await ctx.getNotes(page)).length === 0
eq(cleared, true)
const cleared = (await ctx.getNotes()).length === 0
eq(await cleared, true)
})
tests.push(async ({ page, eq }) => {

13
js/tests/primitives_test.js

@ -1,14 +1,5 @@
export const tests = []
const isConst = (name) => {
try {
eval(`${name} = 'm'`)
return false
} catch (err) {
return true
}
}
const t = (f) => tests.push(f)
// str is declared and of type string
t(() => typeof str === 'string')
@ -21,8 +12,4 @@ t(() => typeof bool === 'boolean')
// undef is declared and of type undefined
t(() => undef === undefined)
// check if all variables are const
t(() => ['str', 'num', 'bool', 'undef']
.every(isConst))
Object.freeze(tests)

1
js/tests/race_test.js

@ -1,3 +1,4 @@
Promise.race = undefined
// /*/ // ⚡
export const tests = []
const t = (f) => tests.push(f)

18
js/tests/sunny-sunday_test.js

@ -1,18 +0,0 @@
export const tests = []
const t = (f) => tests.push(f)
t(() => sunnySunday(new Date('0001-01-01')) === 'Monday')
t(() => sunnySunday(new Date('0001-01-02')) === 'Tuesday')
t(() => sunnySunday(new Date('0001-01-03')) === 'Wednesday')
t(() => sunnySunday(new Date('0001-01-04')) === 'Thursday')
t(() => sunnySunday(new Date('0001-01-05')) === 'Friday')
t(() => sunnySunday(new Date('0001-01-06')) === 'Saturday')
t(() => sunnySunday(new Date('0001-01-07')) === 'Monday')
t(() => sunnySunday(new Date('0001-12-01')) === 'Friday')
t(() => sunnySunday(new Date('1664-08-09')) === 'Saturday')
t(() => sunnySunday(new Date('2020-01-01')) === 'Monday')
t(() => sunnySunday(new Date('2048-12-08')) === 'Thursday')
Object.freeze(tests)

3
js/tests/test.mjs

@ -8,7 +8,6 @@ import http from 'http'
import fs from 'fs'
global.window = global
global._fetch = fetch
global.fetch = url => {
// this is a fake implementation of fetch for the tester
// -> refer to https://devdocs.io/javascript/global_objects/fetch
@ -180,7 +179,7 @@ const runTests = async ({ url, path, code }) => {
new Promise((s, f) => {
timeout = setTimeout(f, 60000, Error('Time limit reached (1min)'))
}),
])
])
if (!(await waitWithTimeout) && !isDOM) {
throw Error('Test failed')
}

197
js/tests/uninvited_test.mjs

@ -1,197 +0,0 @@
import { once } from 'node:events'
import { spawn } from 'node:child_process'
import { mkdir, writeFile, chmod } from 'fs/promises'
import { join } from 'path'
import fs from 'node:fs/promises'
export const tests = []
const fetch = _fetch // to redefine the real fetch
const port = 5000
export const setup = async ({ randStr }) => {
const dir = '.'
await mkdir(`${dir}/guests`, { recursive: true })
const randomName = randStr()
const createFilesIn = ({ files, dirPath }) => {
Promise.all(
files.map(([fileName, content]) =>
writeFile(`${dirPath}/${fileName}`, JSON.stringify(content), {
flag: 'wx',
}),
),
).catch(reason => console.log(reason))
return true
}
const sendRequest = async (path, options) => {
const response = await fetch(`http://localhost:${port}${path}`, options)
const { status } = response
const headers = Object.fromEntries(response.headers)
let body = ''
try {
body = await response.json()
} catch (err) {
body = err
}
return { status, body, headers }
}
const startServer = async path => {
const server = spawn('node', [`${path}`])
const message = await Promise.race([
once(server.stdout, 'data'),
Promise.race([
once(server.stderr, 'data').then(String).then(Error),
once(server, 'error'),
]).then(result => Promise.reject(result)),
])
return { server, message }
}
return { tmpPath: dir, createFilesIn, randomName, sendRequest, startServer }
}
const testServerRunning = async ({ path, ctx }) => {
const { server, message } = await ctx.startServer(path)
server.kill()
return message[0].toString().includes(port)
}
const testRightStatusCode = async ({ path, ctx, randStr }) => {
const { server } = await ctx.startServer(path)
const { status } = await ctx.sendRequest(`/${ctx.randomName}`, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: randStr(),
})
server.kill()
if (status != 201) return false
return true
}
const testRightContentType = async ({ path, ctx, randStr }) => {
const { server } = await ctx.startServer(path)
const { headers } = await ctx.sendRequest(`/${ctx.randomName}`, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: randStr(),
})
server.kill()
if (headers['content-type'] != 'application/json') return false
return true
}
const testServerFail = async ({ path, eq, ctx, randStr }) => {
const { server } = await ctx.startServer(path)
await chmod(`${ctx.tmpPath}/guests`, 0).catch(reason => console.log(reason))
const { status, body, headers } = await ctx.sendRequest(
`/${ctx.randomName}`,
{
method: 'POST',
body: randStr(),
},
)
await chmod(`${ctx.tmpPath}/guests`, 0o777)
server.kill()
return eq(
{
status: status,
body: body,
'content-type': headers['content-type'],
},
{
status: 500,
body: { error: 'server failed' },
'content-type': 'application/json',
},
)
}
const testFileCreated = async ({ path, ctx, randStr }) => {
const { server } = await ctx.startServer(path)
const randomName = randStr()
await ctx.sendRequest(`/${randomName}`, {
body: randStr(),
method: 'POST',
})
const dirName = 'guests'
const dirPath = join(ctx.tmpPath, dirName)
let accessWorked = true
server.kill()
await fs
.access(`${dirPath}/${randomName}.json`, fs.constants.F_OK)
.catch(reason => {
accessWorked = false
console.log(reason)
})
return accessWorked
}
const testFileContent = async ({ path, ctx, randStr }) => {
const { server } = await ctx.startServer(path)
const randomName = randStr()
const body = randStr()
await ctx.sendRequest(`/${randomName}`, {
body: body,
method: 'POST',
})
const dirName = 'guests'
const dirPath = join(ctx.tmpPath, dirName)
server.kill()
let content = ''
await fs
.readFile(`./${dirPath}/${randomName}.json`, 'utf8', (err, data) => {
if (err) {
console.error(err)
return 'error when reading file'
}
return data
})
.then(data => {
if (data === 'error when reading file') return
content = data
})
return body === content
}
const testBodyOnSuccess = async ({ path, ctx, eq, randStr }) => {
const { server } = await ctx.startServer(path)
const randomBody = { message: randStr() }
const { body } = await ctx.sendRequest(`/${ctx.randomName}`, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify(randomBody),
})
server.kill()
return eq(
{
body: body,
},
{
body: randomBody,
},
)
}
tests.push(
testServerRunning,
testRightStatusCode,
testRightContentType,
testBodyOnSuccess,
testFileCreated,
testFileContent,
testServerFail,
)
Object.freeze(tests)

37
js/tests/veterinary_test.js

@ -1,37 +0,0 @@
export const tests = []
const testProperties = () => {
return (
Array.isArray(veterinary.animalKnowledge) &&
typeof veterinary.canTreat === 'function' &&
typeof veterinary.respondClient === 'function'
)
}
const testCanTreat = () => {
veterinary.animalKnowledge.push('dog', 'cat', 'elephant')
return (
veterinary.canTreat('dog') &&
veterinary.canTreat('cat') &&
veterinary.canTreat('elephant') &&
!veterinary.canTreat('') &&
!veterinary.canTreat('goldfish')
)
}
const testRespondClient = () => {
veterinary.animalKnowledge.push('parrot')
const vetResponse1 = veterinary.respondClient('Jack', 'parrot')
const vetResponse2 = veterinary.respondClient('Matias', 'cobra')
return (
vetResponse1.includes('Jack') &&
vetResponse1.toLowerCase().includes('yes') &&
vetResponse2.includes('Matias') &&
vetResponse2.toLowerCase().includes('no')
)
}
tests.push(testProperties, testCanTreat, testRespondClient)
Object.freeze(tests)

373
sh/debian/configure.sh diff.vendored

@ -1,11 +1,9 @@
#!/usr/bin/env bash
# Bash Strict Mode
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
cd -P "$(dirname "$0")"
PS4='-\D{%F %T} '
export DEBIAN_FRONTEND=noninteractive
export DEBIAN_PRIORITY=critical
@ -13,32 +11,20 @@ export DEBIAN_PRIORITY=critical
# Fix Debian 10 bug (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=905409)
PATH=/sbin:/usr/sbin:$PATH
function sysConfig() {
echo "Enter the server FQDN $(tput setaf 2)[System: $(hostname)]$(tput sgr0):"
read serverFQDN
hostnamectl set-hostname $serverFQDN
# Debian stable OS
apt-get update
apt-get -y -o "Dpkg::Options::=--force-confdef" -o "Dpkg::Options::=--force-confold" upgrade
apt-get -y dist-upgrade
echo "Enter the server Time Zone $(tput setaf 2)[System: $(cat /etc/timezone)]$(tput sgr0): "
read serverTZ
timedatectl set-timezone $serverTZ
# Disable OpenStack SSH malware
mv /home/debian/.ssh/authorized_keys /root/.ssh/authorized_keys ||:
sed -i '/Generated-by-Nova/d' /root/.ssh/authorized_keys ||:
chown root:root /root/.ssh/authorized_keys ||:
# Navigate to tmp
cd /tmp
# Terminal goodies
touch .hushlogin
# Debian stable OS
apt-get update
apt-get -y -o "Dpkg::Options::=--force-confdef" -o "Dpkg::Options::=--force-confold" upgrade
apt-get -y dist-upgrade
# Disable OpenStack SSH malware
mv /home/debian/.ssh/authorized_keys /root/.ssh/authorized_keys || :
sed -i '/Generated-by-Nova/d' /root/.ssh/authorized_keys || :
chown root:root /root/.ssh/authorized_keys || :
# Terminal goodies
touch .hushlogin
cat <<'EOF' >>/root/.bashrc
cat <<'EOF'>> /root/.bashrc
export LS_OPTIONS="--color=auto"
eval "`dircolors`"
@ -58,13 +44,13 @@ export HISTTIMEFORMAT="%F %T "
export DOCKER_BUILDKIT=1 COMPOSE_DOCKER_CLI_BUILD=1
EOF
cat <<'EOF' >>/etc/inputrc
cat <<'EOF'>> /etc/inputrc
set completion-ignore-case
set show-all-if-ambiguous On
set show-all-if-unmodified On
EOF
cat <<'EOF' >>/etc/bash.bashrc
cat <<'EOF'>> /etc/bash.bashrc
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
@ -74,274 +60,89 @@ if ! shopt -oq posix; then
fi
EOF
# Basic packages
apt-get -y install man bash-completion git ufw jq curl build-essential netcat wget psmisc lz4 file net-tools brotli unzip zip moreutils dnsutils fail2ban xauth sysfsutils rsync iperf pv tree mc screen ssh iotop htop awscli whois sudo
# Basic packages
apt-get -y install man bash-completion git ufw jq curl build-essential netcat wget psmisc lz4 file net-tools brotli unzip zip moreutils xauth sysfsutils rsync iperf pv tree mc screen ssh iotop whois sudo
# Enable time synchronization
timedatectl set-ntp true
# Enable time synchronization
timedatectl set-ntp true
# Configure screen
cat <<'EOF' >>/etc/screenrc
# Configure screen
cat <<'EOF'>> /etc/screenrc
startup_message off
shell -$SHELL
defscrollback 100000
bind l eval clear "scrollback 0" "scrollback 100000"
EOF
# Configure SSH
cat <<'EOF' >>/etc/ssh/sshd_config
# Configure SSH
cat <<'EOF'>> /etc/ssh/sshd_config
Port 521
PasswordAuthentication no
AllowUsers root
X11UseLocalhost no
EOF
systemctl restart ssh
touch /root/.Xauthority
# Firewall
ufw allow in 80/tcp
ufw allow in 443/tcp
ufw allow in 521/tcp
ufw allow in 8080/tcp
ufw allow in 8082/tcp
ufw logging off
ufw --force enable
ufw --force delete 6
ufw --force delete 6
ufw --force delete 6
ufw --force delete 6
ufw --force delete 6
# Optimize
systemctl disable unattended-upgrades.service apt-daily.timer apt-daily-upgrade.timer console-setup.service keyboard-setup.service remote-fs.target man-db.timer systemd-timesyncd.service
sed -i 's/MODULES=most/MODULES=dep/g' /etc/initramfs-tools/initramfs.conf
sed -i 's/COMPRESS=gzip/COMPRESS=lz4/g' /etc/initramfs-tools/initramfs.conf
echo 'RESUME=none' >>/etc/initramfs-tools/conf.d/resume
update-initramfs -u
echo 'GRUB_TIMEOUT=0' >>/etc/default/grub
update-grub
apt-get -y purge apparmor exim\*
for i in $(seq 0 "$(nproc --ignore 1)"); do
echo "devices/system/cpu/cpu${i}/cpufreq/scaling_governor = performance" >>/etc/sysfs.conf
done
# Disable sleep when closing laptop screen
echo HandleLidSwitch=ignore >>/etc/systemd/logind.conf
# noatime
sed -i 's| / ext4 | / ext4 noatime,|g' /etc/fstab
# Disable swap
swapoff -a
sed -i '/swap/d' /etc/fstab
# Docker
apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
apt-get update
apt-get -y install docker-ce docker-ce-cli containerd.io
# Docker compose
curl -L "https://github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
# NodeJS
curl -fsSL https://deb.nodesource.com/setup_18.x | bash && apt-get install -y nodejs
# Git
echo deb http://deb.debian.org/debian buster-backports main | tee /etc/apt/sources.list.d/buster-backports.list
apt-get update && apt-get -y install -t buster-backports git
# Generate SSH key
ssh-keygen -ted25519 -f ~/.ssh/id_ed25519 -N ''
# Use Cloudflare DNS server
echo 'supersede domain-name-servers 1.1.1.1;' >>/etc/dhcp/dhclient.conf
# Cleanup
sed -i '/^deb-src/d' /etc/apt/sources.list
apt-get update
apt-get -y purge unattended-upgrades
apt-get -y autoremove --purge
apt-get clean
# SSH Keys Infra Team
curl https://github.com/{harryvasanth,frenchris,kigiri}.keys >>~/.ssh/authorized_keys
# Create Core directories
mkdir -p /root/core/scripts/misc
}
# Check Config
function checkConfig() {
test "$(command -v "${1:-}")" && echo -n ✅ || echo -n ❌
echo " $@"
}
# Check configs in the List
function checkList() {
checkConfig docker-compose
checkConfig docker
checkConfig node
checkConfig git
checkConfig man
checkConfig ufw
checkConfig jq
checkConfig curl
checkConfig netcat
checkConfig wget
checkConfig lz4
checkConfig file
checkConfig brotli
checkConfig unzip
checkConfig zip
checkConfig fail2ban-server
checkConfig xauth
checkConfig rsync
checkConfig iperf
checkConfig pv
checkConfig tree
checkConfig mc
checkConfig screen
checkConfig ssh
checkConfig iotop
checkConfig htop
checkConfig aws
checkConfig whois
checkConfig sudo
test "$(ls ~/.ssh/*.pub 2>/dev/null)" && echo -n ✅ || echo -n ❌
echo " SSH private/public key pair generated"
}
function runHTTPS() {
echo -e "Deploying HTTPS service: \n"
echo "Enter the server FQDN $(tput setaf 2)[System: $(hostname)]$(tput sgr0):"
read httpsFQDN
# Check if the FQDN is valid
if ping -c1 -W1 $httpsFQDN 2>/dev/null; then
cd /root/core/https
DOMAIN=$httpsFQDN ./run.sh
echo -e "HTTPS service is up! \n"
else
echo "$(tput setaf 1)$(tput bold)The FQDN: $httpsFQDN is not reachable$(tput sgr0)"
echo "$(tput setaf 1)Please check your DNS configuration$(tput sgr0)"
runHTTPS
fi
}
# Deploy core repositories
function deployCore() {
# Check for the presence of configurations
test "$(ls ~/.ssh/*.pub 2>/dev/null)" && echo -n "$(tput setaf 2)$(tput bold)Config check passed!$(tput sgr0)" || exit 1
echo -e "$(tput setaf 6)$(tput bold)\nThe core components will be deployed to the server: $(tput sgr0)\n"
# Clone core repositories
git clone git@github.com:01-edu/runner.git /root/core/runner
git clone git@github.com:01-edu/https.git /root/core/https
# Docker login
echo -e "Enter the docker username: "
read dockerUsername
echo -e "Enter the docker password: "
read dockerPassword
docker login docker.01-edu.org -u $dockerUsername -p $dockerPassword
# Deploy HTTPS
runHTTPS
# Deploy Runner
echo -e "Deploying Runner service: \n "
cd /root/core/runner
# Get the latest release version tag and create latest branch
tag=$(git describe --tags $(git rev-list --tags --max-count=1))
git checkout $tag -b latest
git describe --tags
# Set upstream to latest
git branch --set-upstream-to=origin/latest latest
# Get user auth infor for the runner
echo -e "Enter the runner Registry password: "
read registryPassword
echo -e "Enter the runner GitHub username: "
read githubUsername
echo -e "Enter the runner GitHub token: "
read githubToken
REGISTRY_PASSWORD=$registryPassword GITHUB_USERNAME=$githubUsername GITHUB_TOKEN=$githubToken ./run.sh
echo -e "Runner service is up! \n"
}
function deployPlatform() {
# Check for the presence of configurations
test "$(ls ~/.ssh/*.pub 2>/dev/null)" && echo -n "$(tput setaf 2)$(tput bold)Config check passed!$(tput sgr0)" || exit 1
echo -e "$(tput setaf 6)$(tput bold)\nThe platform components will be deployed to the server: $(tput sgr0)\n"
# Clone platform repository
echo "Enter the server FQDN $(tput setaf 2)[System: $(hostname)]$(tput sgr0):"
read serverFQDN
git clone git@github.com:01-edu/all.git /root/$serverFQDN
cd /root/$serverFQDN
# Generate platform environment file automatically
./generate_env.sh --auto
docker-compose up --build --detach
./redeploy.sh --latest
}
function clonePlatform() {
# Check for the presence of configurations
test "$(ls ~/.ssh/*.pub 2>/dev/null)" && echo -n "$(tput setaf 2)$(tput bold)Config check passed!$(tput sgr0)" || exit 1
echo -e "$(tput setaf 6)$(tput bold)\nThe platform components will be deployed to the server: $(tput sgr0)\n"
# Clone platform repository
echo "Enter the target directory for the platform $(tput setaf 2)[System: $(pwd)/$(hostname)]$(tput sgr0):"
read serverDir
git clone git@github.com:01-edu/all.git $serverDir
cd $serverDir
# Generate platform environment file automatically
./generate_env.sh --gen
}
if [[ ! -n ${1:-} ]] || [[ "--check" = $1 ]]; then
echo -e "$(tput setaf 2)$(tput bold)Commencing configuration check: $(tput sgr0)"
checkList
echo -e "$(tput setaf 2)\nSystem configuration check complete! $(tput sgr0)\n"
exit 0
elif [[ "--help" = $1 ]]; then
echo "$(tput setaf 2) --check : to check the current configuration. $(tput sgr0)"
echo "$(tput setaf 3) --run : to configure the system. $(tput sgr0)"
echo "$(tput setaf 1) --reboot : to configure the system and reboot. $(tput sgr0)"
echo "$(tput setaf 6) --deploy : to deploy and spin-up platform components. $(tput sgr0)"
echo "$(tput setaf 5) --platform : to clone platform. $(tput sgr0)"
echo "$(tput setaf 7) --help : to display this message. $(tput sgr0)"
elif [[ "--reboot" = $1 ]]; then
echo -e "$(tput setaf 1)$(tput bold)\nSystem will be configured and rebooted. $(tput sgr0)"
sysConfig
echo -e "$(tput setaf 1)\nSystem configuration complete. Rebooting now... $(tput sgr0)"
reboot
elif [[ "--run" = $1 ]]; then
echo -e "$(tput setaf 3)$(tput bold)\nSystem will be configured without rebooting. $(tput sgr0)"
sysConfig
echo -e "$(tput setaf 3)\nSystem configuration complete! $(tput sgr0)"
exit 0
elif [[ "--deploy" = $1 ]]; then
deployCore
deployPlatform
echo -e "$(tput setaf 6)\nRepositories cloned and platform has been deployed successfully! $(tput sgr0)"
exit 0
elif [[ "--platform" = $1 ]]; then
clonePlatform
echo -e "$(tput setaf 5)\nPlatform has been cloned successfully! $(tput sgr0)"
exit 0
else
echo "$(tput setaf 1)$(tput bold) Unknown configuration option: $1 $(tput sgr0)"
echo "$(tput setaf 1)Please use --help for all available options. $(tput sgr0)"
echo "$(tput setaf 1)No changes are made $(tput sgr0)"
exit 0
fi
systemctl restart ssh
touch /root/.Xauthority
# Firewall
ufw allow in 80/tcp
ufw allow in 443/tcp
ufw allow in 521/tcp
ufw logging off
ufw --force enable
ufw --force delete 4
ufw --force delete 4
ufw --force delete 4
# Optimize
systemctl disable unattended-upgrades.service apt-daily.timer apt-daily-upgrade.timer console-setup.service keyboard-setup.service remote-fs.target man-db.timer systemd-timesyncd.service
sed -i 's/MODULES=most/MODULES=dep/g' /etc/initramfs-tools/initramfs.conf
sed -i 's/COMPRESS=gzip/COMPRESS=lz4/g' /etc/initramfs-tools/initramfs.conf
echo 'RESUME=none' >> /etc/initramfs-tools/conf.d/resume
update-initramfs -u
echo 'GRUB_TIMEOUT=0' >> /etc/default/grub
update-grub
apt-get -y purge apparmor exim\*
for i in $(seq 0 "$(nproc --ignore 1)"); do
echo "devices/system/cpu/cpu${i}/cpufreq/scaling_governor = performance" >> /etc/sysfs.conf
done
# Disable sleep when closing laptop screen
echo HandleLidSwitch=ignore >> /etc/systemd/logind.conf
# noatime
sed -i 's| / ext4 | / ext4 noatime,|g' /etc/fstab
# Disable swap
swapoff -a
sed -i '/swap/d' /etc/fstab
# Docker
apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
apt-get update
apt-get -y install docker-ce docker-ce-cli containerd.io
# Docker compose
curl -L "https://github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
# Generate SSH key
ssh-keygen -ted25519 -f ~/.ssh/id_ed25519 -N ''
# Use Cloudflare DNS server
echo 'supersede domain-name-servers 1.1.1.1;' >> /etc/dhcp/dhclient.conf
# Cleanup
sed -i '/^deb-src/d' /etc/apt/sources.list
apt-get update
apt-get -y purge unattended-upgrades
apt-get -y autoremove --purge
apt-get clean
# The end
reboot

2
sh/debian/preseed.cfg diff.vendored

@ -2,7 +2,7 @@
d-i anna/choose_modules string network-console
d-i preseed/early_command string anna-install network-console
d-i network-console/authorized_keys_url string https://github.com/frenchris.keys
d-i network-console/authorized_keys_url string https://github.com/xpetit.keys
d-i network-console/password-disabled boolean true
d-i debian-installer/locale string en_US

2
sh/tests/Dockerfile

@ -1,7 +1,7 @@
FROM docker.01-edu.org/debian:10.9-slim
RUN apt-get update
RUN apt-get -y install jq curl tree apt-utils
RUN apt-get -y install jq curl
WORKDIR /app/assets/superhero
RUN curl --remote-name --location https://demo.01-edu.org/assets/superhero/all.json

99
sh/tests/append-output_test.sh

@ -1,99 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
FILENAME="student/append-output.sh"
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
if test ! -e append-output; then
mkdir append-output
cat <<EOF >append-output/results.txt
"In the End" - Linkin Park
"Crawling" - Linkin Park
"Elevation" - U2
"Get the Party Started" - Pink
"Lady Marmalade" - Christina Aguilera, Lil' Kim, Mya, Pink
EOF
cat <<EOF >append-output/songs.txt
"Breathe" - Faith Hill
"It Wasn't Me" - Shaggy featuring Ricardo "RikRok" Ducent
"Hanging by a Moment" - Lifehouse
"Shape of My Heart" - Backstreet Boys
"Thank You" - Dido
"I'm Like a Bird" - Nelly Furtado
"Family Affair" - Mary J. Blige
"Fallin'" - Alicia Keys
"All for You" - Janet Jackson
"I Wanna Know" - Joe
"U Remind Me" - Usher
"U Got It Bad" - Usher
"I'm a Believer" - Smash Mouth
"Get the Party Started" - Pink
"Wherever You Will Go" - The Calling
"In the End" - Linkin Park
"Loser" - Beck
"Get Ur Freak On" - Missy Elliott
"I'm Real" - Jennifer Lopez
"Butterfly" - Crazy Town
"Crawling" - Linkin Park
"I'm a Slave 4 U" - Britney Spears
"Elevation" - U2
"Lady Marmalade" - Christina Aguilera, Lil' Kim, Mya, Pink
"Play" - Jennifer Lopez
"I'm Just a Kid" - Simple Plan
"Imitation of Life" - R.E.M.
"Big Pimpin'" - Jay-Z
"Stutter" - Joe featuring Mystikal
"I Wish" - R. Kelly
"This Is the Night" - Clay Aiken
"Hella Good" - No Doubt
"I Know" - Dionne Farris
"I'll Be Missing You" - Puff Daddy and Faith Evans featuring 112
"I Try" - Macy Gray
"Thong Song" - Sisqo
"Survivor" - Destiny's Child
"I Want It That Way" - Backstreet Boys
"Bad Day" - Daniel Powter
"I'm Like a Bird" - Nelly Furtado
"I Need to Know" - Marc Anthony
"Follow Me" - Uncle Kracker
"Hemorrhage (In My Hands)" - Fuel
"Soak Up the Sun" - Sheryl Crow
"I Hope You Dance" - Lee Ann Womack
"Can't Get You Out of My Head" - Kylie Minogue
"I Just Wanna Love U (Give It 2 Me)" - Jay-Z
"My Love Is Your Love" - Whitney Houston
"Bounce with Me" - Lil' Bow Wow
"Where the Party At" - Jagged Edge
"I'm Already There" - Lonestar
"I Don't Want to Miss a Thing" - Aerosmith
"If You Could Read My Mind" - Stars on 54
"My Way" - Usher
"Always on Time" - Ja Rule featuring Ashanti
EOF
fi
challenge() {
$(cd "$1" && bash "$script_dirS"/$FILENAME)
submitted=$(cat $1/results.txt)
rm $1"/results.txt"
$(cd "$1" && bash "$script_dirS"/solutions/append-output.sh)
expected=$(cat $1/results.txt)
diff <(echo "$submitted") <(echo "$expected")
}
if [ -s ${FILENAME} ]; then
if [[ $(cat $FILENAME | grep "cat <<EOF >results.txt" | wc -l) -ne 0 ]]; then
echo "cheating is not allowed in this exercise!"
exit 1
elif
[[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]
then
echo "cheating is not allowed in this exercise!"
exit 1
fi
fi
challenge append-output
rm -r append-output

30
sh/tests/array-selector_test.sh

@ -1,30 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
submitted=$(bash "$script_dirS"/student/array-selector.sh "$@")
expected=$(bash "$script_dirS"/solutions/array-selector.sh "$@")
diff <(echo "$submitted") <(echo "$expected")
}
# Test with numbers - out of range included
for num in {0..6}
do
challenge $num
done
# Test with a value that is not a digit
challenge "abc"
# Test with wrong number of arguments
challenge

54
sh/tests/auto-exec-bin_test.sh

@ -1,54 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
FILENAME="student/auto-exec-bin.sh"
BINFILE="~/myBins/01exec"
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
setupbin() {
if [ -f ${BINFILE} ]; then
echo "bin already exists!"
else
mkdir -p ~/myBins
echo "echo Hello 01 Scripting Pool" > $HOME/myBins/01exec
fi
chmod +x $HOME/myBins/01exec
}
challenge() {
OLD_PATH=$PATH
# run soultion script
source "$script_dirS"/$FILENAME
submitted=$(cd / && 01exec)
PATH=$OLD_PATH
# run student script
source "$script_dirS"/solutions/auto-exec-bin.sh
expected=$(cd / && 01exec)
# diff
diff <(echo "$submitted") <(echo "$expected")
}
# True if FILE exists and is a regular file
if [ -f ${FILENAME} ]; then
# FILE exists and it's not empty
if [ -s ${FILENAME} ]; then
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then
echo "echo is not allowed in this exercise!"
exit 1
fi
setupbin
challenge
else
echo "The file exist but is empty"
exit 1
fi
else
echo "File does not exist"
exit 1
fi

20
sh/tests/auto-jobs_test.sh

@ -1,20 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
print_content() {
mkdir -p uncompressed
tar -xpf auto-jobs.tar -C uncompressed
cat -e uncompressed/$1
}
for i in 1 2 3 4
do
submitted=$(cd student && print_content task$i)
expected=$(cd solutions && print_content task$i)
diff <(echo "$submitted") <(echo "$expected")
done

34
sh/tests/bin-status_test.sh

@ -1,34 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
FILENAME="student/bin-status.sh"
challenge() {
submitted=$(eval "$@" >/dev/null 2>&1 ; source $FILENAME)
expected=$(eval "$@" >/dev/null 2>&1 ; source solutions/bin-status.sh)
diff <(echo "$submitted") <(echo "$expected")
}
# True if FILE exists and is a regular file
if [ -f ${FILENAME} ]; then
# FILE exists and it's not empty
if [ -s ${FILENAME} ]; then
challenge true
challenge false
challenge ls -l
challenge ls asdasdasdasdad
else
echo "The file exist but is empty"
exit 1
fi
else
echo "File does not exist"
exit 1
fi

28
sh/tests/burial_test.sh

@ -1,28 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
FILENAME="student/burial.sh"
# True if FILE exists and is a regular file
if [ -f ${FILENAME} ]; then
# FILE exists and it's not empty
if [ -s ${FILENAME} ]; then
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then
echo "echo is not allowed in this exercise!"
exit 1
fi
submitted=$(bash $FILENAME)
expected=$(bash solutions/burial.sh)
diff <(echo "$submitted") <(echo "$expected")
else
echo "The file exist but is empty"
exit 1
fi
else
echo "File does not exist"
exit 1
fi

86
sh/tests/calculator_test.sh

@ -1,86 +0,0 @@
#!/usr/bin/env bash
# set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
submitted="./calculator.sh $@
"
expected="./calculator.sh $@
"
submitted+=$(2>&1 bash "$script_dirS"/student/calculator.sh "$@")
submitted+="
exit status: $?"
expected+=$(2>&1 bash "$script_dirS"/solutions/calculator.sh "$@")
expected+="
exit status: $?"
diff -U 1 <(echo "$submitted") <(echo "$expected")
if [ $? != 0 ]
then
exit 1
fi
}
# Check if student uses case statement
if [[ $(cat "$script_dirS"/student/calculator.sh | grep case | wc -l) -eq 0 ]]
then
echo "Error: the use of case statement is mandatory"
exit 1
fi
# Valid inputs
challenge "15" "+" "10"
challenge "15" "-" "10"
challenge "15" "/" "10"
challenge "15" "*" "10"
challenge "3491" "+" "-67"
challenge "3491" "-" "-67"
challenge "3491" "/" "-67"
challenge "3491" "*" "-67"
challenge "-3491" "+" "-67"
challenge "-3491" "-" "-67"
challenge "-3491" "/" "-67"
challenge "-3491" "*" "-67"
# Invalid inputs
challenge
challenge "-3491" "*" "-67" "10" "12"
challenge "20" "/" "0"
challenge "20" "@" "10"
challenge "10" "*" "67invalid"
# Test operators functions
source $script_dirS"/student/calculator.sh" 10 + 10 >/dev/null 2>&1
if [ $(do_add 11 14) != 25 ]
then
echo "error in function do_add"
exit 1
fi
if [ $(do_sub 11 14) != -3 ]
then
echo "error in function do_sub"
exit 1
fi
if [ $(do_mult 3 5) != 15 ]
then
echo "error in function do_mult"
exit 1
fi
if [ $(do_divide 50 5) != 10 ]
then
echo "error in function do_divide"
exit 1
fi

16
sh/tests/change-struct_test.sh

@ -1,16 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
print_content() {
mkdir -p uncompressed
tar -xpf change-struct.tar -C uncompressed
tree uncompressed
}
submitted=$(cd student && print_content)
expected=$(cd solutions && print_content)
diff <(echo "$submitted") <(echo "$expected")

28
sh/tests/check-user_test.sh

@ -1,28 +0,0 @@
#!/usr/bin/env bash
# set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
submitted="./check-user.sh $@
"
expected="./check-user.sh $@
"
submitted+=$(bash 2>&1 "$script_dirS"/student/check-user.sh "$@")
expected+=$(bash 2>&1 "$script_dirS"/solutions/check-user.sh "$@")
diff -U 1 <(echo "$submitted") <(echo "$expected")
}
challenge "-i" "root"
challenge "-e" "root"
challenge "-i" "unknown_not_found"
challenge "-e" "unknown_not_found"
challenge
challenge "-i" "root" "too" "many" "args"
challenge "-t" "root"

27
sh/tests/comparator_test.sh

@ -1,27 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
submitted=$(bash $script_dirS/student/comparator.sh "$@")
expected=$(bash $script_dirS/solutions/comparator.sh "$@")
diff <(echo "$submitted") <(echo "$expected")
}
for i in $(seq 1 10); do
n1=$(shuf -i 1-20 -n 1)
n2=$(shuf -i 1-30 -n 1)
challenge $n1 $n2
done
challenge "0" "0"
challenge "10" "10"
challenge "-11" "-11"
challenge "14"
challenge "-11" "-11" "4"
challenge "as" "str"

18
sh/tests/count-files_test.sh

@ -1,18 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
submitted=$(cd "$1" && bash "$script_dirS"/student/count-files.sh)
expected=$(cd "$1" && bash "$script_dirS"/solutions/count-files.sh)
diff <(echo "$submitted") <(echo "$expected")
}
challenge cl-camp5/folder1
challenge cl-camp5/folder2

11
sh/tests/custom-ls/folder1/.hidden

@ -1,11 +0,0 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum venenatis rutrum vehicula. Phasellus vehicula sagittis nibh, sed congue turpis suscipit a. Etiam sed nibh risus. Aenean aliquet urna ornare nisi bibendum, nec vehicula quam sagittis. Quisque varius vel tortor et rhoncus. Aliquam erat volutpat. Quisque sit amet cursus tortor.
Aenean egestas dui est, eu vehicula mi vehicula vitae. Nunc rhoncus sit amet libero id tempus. Fusce mollis at urna sit amet iaculis. Ut dapibus sed enim eu fringilla. Proin pretium, orci eget mollis viverra, nibh nunc feugiat purus, vel consequat felis magna ac felis. Nam gravida imperdiet arcu. Aliquam est felis, iaculis non felis id, cursus convallis metus. Phasellus ac varius arcu. Aenean congue nisi ut urna tempor tempor. Mauris sit amet purus non risus auctor ultricies imperdiet vitae ex. Vestibulum maximus eros quam, a luctus massa condimentum ac. In commodo consequat diam, at rutrum massa interdum non. In sed rutrum dolor.
Ut auctor porta felis, luctus ullamcorper ipsum pulvinar ac. Curabitur non pharetra purus. Nulla euismod leo nec massa convallis, ac facilisis orci lacinia. Maecenas eget magna tristique, eleifend est vehicula, mattis lectus. Etiam lectus sem, rutrum in nisl vitae, congue tincidunt urna. Praesent luctus auctor arcu, quis tristique ex suscipit eleifend. Phasellus congue tempus nisi vitae suscipit. Quisque ut luctus ipsum. Duis eget consequat massa. Vestibulum aliquam ligula quis felis imperdiet luctus. Phasellus efficitur gravida elementum. Sed quis mi tortor.
Pellentesque luctus porttitor est ac tristique. Nulla facilisi. Duis eu tellus ac lectus vehicula tristique. Quisque magna ex, tristique at sollicitudin sed, blandit consequat erat. In hac habitasse platea dictumst. Mauris sodales, enim in scelerisque ullamcorper, leo lectus pharetra justo, eget dignissim eros libero vitae sapien. Donec elementum varius feugiat. Donec porta eu tellus non suscipit. Integer eu diam ultricies, sodales dolor a, ornare odio. Nulla congue commodo libero, facilisis aliquam nulla pellentesque nec. Aliquam et nisi facilisis, mollis est eu, ultricies metus. Praesent rutrum eros eu neque dapibus gravida. Nam et tortor congue, egestas leo et, euismod erat. Pellentesque ut efficitur risus. Integer sodales convallis arcu, eget mattis purus condimentum eu. Mauris urna neque, ornare in convallis eget, viverra varius lectus.
Sed dapibus nibh neque, eget consequat odio placerat ac. Duis vel nunc erat. Suspendisse vel ornare leo. Sed ut augue turpis. Maecenas ullamcorper a est non pretium. Nulla venenatis interdum pretium. Nulla ut velit vel magna blandit lacinia. Etiam dictum vestibulum nulla non gravida. Pellentesque cursus enim euismod massa congue, vitae ullamcorper urna bibendum. Phasellus in tempus ex. Etiam quis ante a erat bibendum auctor.

1
sh/tests/custom-ls/folder1/asd

@ -1 +0,0 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eget nisl leo. Donec gravida tristique velit sit amet vulputate. In bibendum nisi tortor. Cras ullamcorper velit non mauris dapibus blandit. Maecenas rutrum semper mauris sed hendrerit. Morbi pellentesque est at enim suscipit semper. Donec tincidunt sem velit, sit amet cursus quam tincidunt eu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vivamus non libero vel est posuere ullamcorper sit amet nec lectus. Quisque sagittis augue euismod nulla ultricies elementum sit amet eu leo.

199
sh/tests/custom-ls/folder1/hello

@ -1,199 +0,0 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce accumsan nisi vel mi sodales varius. Morbi in maximus ipsum. Maecenas pulvinar mi efficitur nulla luctus, quis tempus neque finibus. Curabitur ut tristique lacus. Donec a arcu vel mi hendrerit fermentum vitae ut urna. Nulla dapibus lacus in tellus tincidunt aliquam. Nullam tortor lorem, posuere sed nibh sed, fringilla mollis justo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec ultricies ac magna sed hendrerit. Donec nec venenatis sapien. Vivamus maximus diam at lorem interdum ullamcorper at eu mauris. Pellentesque ante tortor, sagittis in euismod non, mollis at arcu. Vestibulum vitae eleifend nisl, cursus accumsan felis. Integer a rhoncus sem, at aliquam lectus.
Vivamus molestie hendrerit efficitur. Vestibulum ut hendrerit mi, sed semper arcu. Suspendisse ullamcorper lobortis ante a tristique. Curabitur a placerat erat. Phasellus dapibus vitae ante vitae sollicitudin. Cras porta sit amet ante sed viverra. Curabitur ut elit tincidunt, facilisis ligula id, condimentum erat. Integer sit amet congue elit.
Praesent laoreet suscipit libero finibus convallis. Integer dapibus, sapien ut porta mollis, tortor sapien pellentesque ligula, at consequat mi metus sed nisi. Nulla lacinia nisi vel velit gravida, eu gravida metus faucibus. Phasellus blandit cursus metus quis volutpat. Pellentesque tempus aliquet lorem id varius. Phasellus placerat iaculis porta. Nulla nunc libero, lacinia sit amet odio pretium, malesuada molestie dui. In hac habitasse platea dictumst. Nulla congue consectetur nulla, vitae euismod urna. Aliquam massa risus, elementum ut fringilla mollis, elementum ut neque. Donec odio justo, tempor sit amet commodo nec, malesuada ultricies magna. Vivamus congue ullamcorper velit, nec pulvinar nisi fermentum eu. Morbi sit amet mi egestas, pulvinar augue ut, euismod leo. Ut auctor condimentum elementum.
Sed rhoncus facilisis sem, a congue ex congue ac. Sed dictum est lorem, eget fermentum enim molestie ut. Aenean sed sagittis nunc, in dapibus justo. Sed faucibus hendrerit felis. Duis aliquam tempor erat at porta. Morbi bibendum bibendum risus, non mattis nisl venenatis quis. Aliquam erat volutpat. Nunc ac neque arcu. Vivamus et ipsum maximus, porttitor ante in, pretium mauris. Suspendisse molestie tempus ante ut interdum. Nulla sed ex vehicula nisl fermentum viverra eget a sapien. Aliquam tempus scelerisque dignissim.
Pellentesque massa lorem, rutrum a lorem et, vehicula fermentum orci. Mauris quis viverra eros. Donec lobortis iaculis justo non sollicitudin. Nullam scelerisque volutpat ultrices. Etiam fermentum congue tortor nec molestie. Sed laoreet nisi nec aliquam condimentum. Sed hendrerit tempor lobortis. Sed tempor magna at euismod semper. Donec nec felis orci. Donec sollicitudin placerat lorem, quis semper elit mollis ac. Morbi semper eu odio ac gravida.
Aliquam sollicitudin nisi nec nibh hendrerit fermentum. Quisque laoreet, enim sit amet finibus lobortis, nulla nibh laoreet leo, quis elementum nulla nulla in dolor. Sed id porta enim. Donec eu porttitor purus. Nunc ac augue sagittis, pretium sapien ut, aliquam purus. Curabitur lacus velit, hendrerit nec sagittis sit amet, vulputate sit amet magna. Sed ut molestie magna, sit amet dapibus felis. Proin aliquet nec neque vel molestie. Mauris dictum risus nec tincidunt maximus. Proin sagittis nisi lorem, vel vestibulum purus tincidunt id. Donec pharetra nisi lacus, quis ornare odio vestibulum non. Nunc ut condimentum purus, eget porta libero. In urna nulla, aliquam nec hendrerit a, sodales vel purus.
Suspendisse non semper enim. Nunc varius est ac arcu cursus, accumsan varius lorem porttitor. Morbi viverra diam tortor, ut sodales eros aliquam id. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec blandit sit amet metus sit amet cursus. In faucibus sapien ut dolor blandit, a sollicitudin urna viverra. Vivamus posuere tellus ac elit lobortis, vel dignissim felis sodales. Aliquam ut arcu ligula. Proin nec magna semper, condimentum sem at, fermentum est. Morbi sit amet suscipit lectus. Nam porttitor libero ipsum, in sagittis est efficitur sagittis. Quisque eleifend neque id eros dapibus commodo. Nam in diam vel felis bibendum cursus non ac quam. Sed id sapien mollis, ultricies nisi sed, maximus sapien. Nulla ullamcorper at ante et gravida. Duis quis tortor libero.
Cras vitae mi eget metus scelerisque malesuada. Nulla tempor ipsum enim. Phasellus congue, eros nec dictum dignissim, elit lacus bibendum augue, et pharetra lacus nisi vitae arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer condimentum lacinia nulla in pretium. Vestibulum ipsum ante, rhoncus vitae quam id, faucibus porttitor odio. Donec vulputate, nunc vel bibendum faucibus, mauris metus rutrum lacus, eget pretium ex lacus eu ante. Duis nec nulla cursus, lacinia ipsum ut, placerat nulla. Nulla facilisi. Praesent efficitur nunc a odio pretium fringilla. Nullam viverra ornare mi a feugiat. Proin at posuere orci. Nulla placerat turpis at sem aliquet consequat. Pellentesque in velit id turpis aliquet tempor.
Fusce ullamcorper ultrices mauris, vitae convallis purus consectetur in. Mauris ac nibh arcu. Pellentesque blandit rutrum pretium. Quisque auctor ipsum blandit ante scelerisque, nec hendrerit enim eleifend. Aliquam eros enim, finibus vitae semper a, lobortis ut lorem. Maecenas eget nunc rutrum, vulputate arcu a, suscipit felis. Proin ac nisi neque. Phasellus placerat vestibulum tortor sed tincidunt. Praesent suscipit felis nec purus molestie bibendum. Aenean ornare tincidunt eros fermentum lobortis. Nunc quis augue in ante sodales consectetur id a nisi.
Etiam elit mi, iaculis id urna et, blandit euismod lectus. Proin pharetra, massa vel cursus placerat, dui sapien ullamcorper felis, sed placerat enim risus in neque. Ut metus tellus, bibendum condimentum urna ut, egestas malesuada mauris. Maecenas vel efficitur lacus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Vestibulum dictum a quam quis consequat. Sed nec libero iaculis, mollis enim non, commodo libero. Nunc laoreet interdum purus at tincidunt. Proin rutrum diam ex, nec fringilla ante consequat id. Suspendisse potenti. Vivamus in justo libero. Sed sodales iaculis tellus et ornare. Fusce fermentum interdum libero ut pharetra. Sed eget venenatis mauris.
Suspendisse commodo posuere augue, vitae rutrum massa fermentum vel. Nunc dignissim lobortis convallis. Nam hendrerit egestas aliquam. Ut efficitur sem vitae libero iaculis condimentum. Nam ac dui et ante posuere interdum pulvinar ut ipsum. Integer dictum, tortor in blandit vestibulum, tortor quam mollis diam, et dictum felis tellus quis felis. Mauris sed ex aliquet, sollicitudin enim quis, semper enim. Nam feugiat ut diam ut pulvinar.
Cras eleifend sollicitudin mi vitae molestie. Vivamus facilisis maximus nulla, et vehicula dui sagittis at. Mauris eget augue orci. Sed vitae magna et velit elementum blandit. Curabitur aliquet rutrum mi, finibus aliquet eros egestas a. Ut vestibulum, purus vel lobortis tempus, odio neque lobortis enim, quis pellentesque neque justo eget velit. Aliquam erat volutpat. Aenean vel cursus turpis. Integer vel justo eu nunc dignissim aliquam. Nam vitae diam id lorem interdum vehicula. Donec ut erat molestie sem lacinia efficitur.
Duis vestibulum, ipsum vitae blandit ullamcorper, erat ex sagittis elit, ut elementum dui metus non velit. Praesent semper magna non magna vestibulum, et tempus tortor mattis. Nam ut risus bibendum, consequat mi non, congue arcu. Duis aliquam facilisis massa, et aliquet massa gravida a. Donec et ex orci. Cras mollis mi elit, nec auctor justo semper ut. Curabitur euismod interdum erat. Ut egestas turpis vel magna dictum sagittis. Quisque eu scelerisque ante, pellentesque gravida orci. Vivamus in fermentum ipsum. Vestibulum eu commodo sem. Suspendisse in lectus vel massa tincidunt pharetra sed eget eros. Sed sollicitudin egestas nisl. Aliquam consequat erat in imperdiet pharetra. Vestibulum fermentum dolor tortor, id faucibus lacus blandit mattis. Sed laoreet leo vitae lacinia pretium.
In non lorem sem. Aliquam in finibus ipsum. Nunc et interdum elit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin posuere bibendum turpis, mattis dignissim dolor convallis vel. Maecenas ac erat quis magna mattis consectetur interdum ornare risus. Curabitur quis neque mauris.
Cras vitae mollis nibh, malesuada vehicula velit. Pellentesque euismod, lacus sed sodales mattis, ipsum ex egestas mauris, non sagittis elit dui nec sem. In vitae fermentum erat. Pellentesque velit diam, pellentesque sit amet dolor ac, dictum vestibulum felis. Nulla hendrerit ex vitae molestie semper. Nam vestibulum accumsan odio, sit amet suscipit ex lacinia a. Quisque rutrum dignissim nunc, ut vehicula nulla scelerisque vel. Integer sollicitudin tempus nibh in vestibulum. Donec non posuere leo. Pellentesque malesuada ullamcorper vulputate. Nam iaculis lectus vel feugiat dictum. In pellentesque purus lorem, ut auctor urna vestibulum sed. Nulla facilisi. In id metus vitae ligula sollicitudin dignissim. Ut commodo vehicula odio, at aliquam arcu volutpat id.
Nunc sed risus molestie, tincidunt tortor ac, ornare mauris. Maecenas vel nisi ac sem malesuada volutpat. Suspendisse finibus, elit in semper sagittis, sapien nisi bibendum nisi, non porta est nulla at eros. Phasellus tristique ex lectus, et aliquet ante vehicula vitae. Duis a tempus enim, vel porttitor velit. Aliquam lacinia augue nec justo ultricies pharetra. Fusce eros dolor, suscipit ut sapien sit amet, sodales vestibulum mauris. Aenean eget sem justo. Quisque consectetur tempor nibh a pellentesque. Nulla fermentum nibh ac tristique mollis.
Sed eget arcu ac purus consequat tincidunt. Fusce auctor rhoncus magna eget bibendum. Cras tempor imperdiet lacus id vehicula. Pellentesque ornare augue nec eros dictum, at ultrices justo suscipit. Aliquam consequat, ex sit amet gravida ultrices, arcu odio finibus tellus, vitae iaculis purus est a est. Fusce vulputate nisi at neque facilisis rutrum. Curabitur sed consectetur sapien, et dapibus mi.
Nunc arcu lorem, pharetra quis mattis non, iaculis vel magna. Phasellus consectetur elit nec iaculis pellentesque. Phasellus lobortis ex ex, sed imperdiet ante posuere a. Phasellus volutpat dui ut orci placerat, id laoreet libero sagittis. Nulla dignissim accumsan arcu, a pellentesque mauris ultricies ut. Ut in metus dolor. Vivamus blandit odio urna, sed euismod ex scelerisque elementum. Nunc lobortis efficitur nunc eget suscipit. Nunc at nisi diam. Fusce blandit, est a condimentum placerat, elit nisl malesuada tellus, sit amet aliquet quam enim sed eros. Morbi eget placerat lorem. Nunc ultrices odio nisl, suscipit porttitor est congue eu. Nunc rhoncus risus eleifend, ultrices nisi nec, laoreet felis.
Phasellus consectetur odio id pellentesque sollicitudin. Pellentesque volutpat sem quis malesuada pretium. Vestibulum a felis sit amet nulla lobortis efficitur consectetur at justo. Sed ut arcu vitae nibh eleifend pulvinar nec vulputate est. Donec pretium, elit sed commodo commodo, metus elit volutpat tortor, eleifend bibendum metus augue vel elit. Fusce placerat justo luctus purus condimentum sollicitudin. Donec magna erat, vehicula eget lectus a, dapibus fringilla enim. Donec varius felis at libero ultricies tempus. Donec ligula lacus, fringilla non metus sed, pellentesque malesuada eros. Aliquam vel libero vitae turpis gravida condimentum sed tristique nunc. Maecenas aliquam urna nec dolor vulputate congue. Morbi mattis purus quis nisi dictum, eu ultricies risus euismod. Pellentesque mi velit, imperdiet a cursus nec, consequat ac dui. Suspendisse ullamcorper elit quis turpis porta, non blandit dui auctor. Nullam et diam facilisis, consequat augue pulvinar, molestie orci.
Etiam ac scelerisque nulla. Cras at justo vel enim lacinia sagittis sit amet nec tellus. Nunc convallis commodo pretium. Maecenas condimentum nulla suscipit, commodo neque sit amet, fermentum enim. Curabitur dui diam, gravida in tellus vitae, luctus feugiat nibh. Vestibulum in aliquam tellus. Nunc tempus odio vel lectus vehicula, sit amet lobortis libero condimentum.
Nam dictum, erat at hendrerit tincidunt, nulla lectus convallis sem, a pretium lectus nunc non nulla. Nulla gravida vulputate justo, eu viverra felis laoreet vel. Suspendisse arcu eros, rutrum sit amet molestie vitae, cursus sed lorem. Fusce orci metus, aliquam vel ex sed, rhoncus commodo augue. Donec a eros a nibh feugiat blandit. Proin venenatis pretium pretium. Praesent nec arcu leo. Fusce lacus turpis, porttitor vitae commodo id, hendrerit eget sem. Etiam cursus tincidunt eros ut venenatis. Vestibulum ultricies consectetur leo, eu imperdiet leo ultricies quis. Donec in enim sit amet mi imperdiet dignissim. In egestas interdum risus, sit amet egestas orci lobortis eu. Cras cursus euismod nisi sit amet euismod. Curabitur malesuada venenatis sem ac maximus. Donec mattis viverra euismod. Curabitur aliquet enim tempus dapibus porttitor.
Nulla sit amet volutpat enim. Nam gravida mauris erat, at sagittis odio iaculis quis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse dapibus id velit ac viverra. Nullam diam massa, condimentum in velit at, eleifend finibus nisi. Aliquam ut tellus non massa semper blandit. Maecenas condimentum venenatis sagittis. Sed quis ante a orci mollis dictum. Etiam interdum tempus purus at aliquam. Vestibulum cursus pulvinar est vitae lacinia. Quisque nibh risus, cursus id scelerisque vitae, elementum quis diam. Aliquam pharetra massa a ex ultrices maximus. Morbi laoreet iaculis leo, vitae maximus odio.
Fusce volutpat, lacus non porttitor venenatis, nulla enim consectetur lorem, vel fermentum leo tellus non ex. Quisque pellentesque magna nec nibh blandit tincidunt. Nulla facilisi. Etiam at vulputate metus. Etiam posuere imperdiet urna, non dictum dui finibus laoreet. Vivamus vitae fringilla velit. Suspendisse tortor odio, malesuada eget nibh in, lacinia placerat felis. Fusce id lobortis ipsum, eu posuere erat. Donec vel justo erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris molestie gravida tellus, vel suscipit neque accumsan sed. Duis ac felis in mi venenatis rutrum non ac massa. Vivamus orci velit, efficitur non arcu quis, cursus gravida quam. Curabitur elementum felis luctus lobortis laoreet.
Donec pellentesque, lorem a imperdiet faucibus, leo lectus porttitor nulla, eget consequat neque ex ut est. Aenean massa tortor, iaculis id libero in, gravida sagittis justo. Duis sit amet placerat sapien, vel dictum quam. Proin maximus quam libero, a dictum mi tincidunt ultrices. Duis lobortis nisi tempor mauris egestas, in condimentum augue rutrum. Vivamus eget libero eu lorem malesuada tincidunt eu vitae nunc. Nam justo diam, eleifend id enim sit amet, eleifend facilisis purus. Phasellus convallis quam vitae augue auctor pretium. Vivamus et tristique arcu. Maecenas et urna porta, varius dui a, scelerisque mi. Fusce eget ex aliquam, commodo augue sed, ornare lacus. Quisque congue dapibus nisl.
Morbi pretium ac arcu nec accumsan. Nullam non cursus neque. Etiam eget mauris congue, faucibus felis sed, bibendum sapien. In efficitur ipsum eget bibendum pharetra. Aliquam gravida, leo ac dapibus feugiat, turpis ante ornare dui, sit amet consequat metus nunc sed nibh. Morbi pellentesque magna a justo vulputate, sed convallis turpis volutpat. Nulla accumsan odio sed nibh vulputate vulputate in quis tellus. Ut quis dolor cursus, accumsan tellus sed, condimentum mauris. Nam ullamcorper nulla in pellentesque aliquet.
Morbi vulputate finibus odio vitae vulputate. Quisque et imperdiet magna. Suspendisse sem nunc, pulvinar ac cursus sed, finibus vitae est. Suspendisse convallis, erat ornare tincidunt eleifend, turpis orci dapibus dolor, vitae mattis massa lectus ac lacus. Nunc id sem tincidunt, dapibus enim eget, tristique ex. In eu dictum enim. Curabitur ut efficitur enim. Integer ac eros mi. Pellentesque tempus hendrerit nunc, quis placerat quam lobortis at. Ut euismod ornare urna efficitur rhoncus. Duis in lorem enim.
In hac habitasse platea dictumst. Curabitur tincidunt sollicitudin lacus, id interdum velit auctor at. Proin eget risus est. Nunc enim mi, vestibulum ac risus sit amet, tristique rutrum tortor. Fusce quis nulla mattis, fermentum dolor in, semper nulla. Pellentesque vel lectus magna. Nam eget arcu suscipit, varius justo a, ornare quam. Donec vitae sollicitudin nibh, eget iaculis felis. Nullam commodo purus et magna finibus, vitae finibus ipsum aliquam. Vestibulum condimentum dui dolor, ut dictum mi maximus eu. Nunc et pretium sem. Etiam accumsan eu felis in convallis. Nullam pulvinar vestibulum tellus nec rutrum. Suspendisse semper, velit vitae vulputate posuere, nunc dolor egestas neque, at efficitur turpis metus nec leo. Etiam bibendum massa condimentum iaculis vestibulum. Morbi ipsum purus, efficitur eget maximus ac, mattis id massa.
Nam volutpat velit sed nulla ullamcorper facilisis. Sed commodo non turpis sed imperdiet. Pellentesque malesuada nibh eget commodo accumsan. Curabitur iaculis eget sapien ac aliquam. Etiam sed ex lectus. Vivamus et urna erat. Nunc quis efficitur felis. Nulla sagittis lacus a ex tristique, vehicula vulputate enim suscipit. Pellentesque pulvinar vitae leo pellentesque gravida. Sed efficitur pretium interdum. Aenean non rutrum ligula. Etiam ultrices nisl nec tempor efficitur.
Nulla eget nulla dictum, elementum lacus vitae, congue tellus. Proin sit amet pellentesque mauris, sit amet aliquet dolor. Etiam eget nulla ligula. Vestibulum imperdiet pretium mauris, ac tempus erat eleifend at. Ut condimentum fringilla ex ut faucibus. Cras eros nunc, iaculis et maximus vitae, auctor sed sapien. Fusce eu odio non ipsum posuere sagittis. Praesent nunc arcu, vestibulum ut condimentum eu, aliquam eu orci. Fusce in arcu ultricies, dictum enim consequat, facilisis turpis. Pellentesque nunc nisi, ultrices et leo et, consequat tincidunt lorem.
Pellentesque sed faucibus ex. Suspendisse ultrices vulputate dolor. Nam eu dolor suscipit, vehicula sapien non, tempus orci. Quisque eget porta nisi, id tincidunt tellus. Fusce sodales purus et ligula consequat, quis sodales metus tempor. Sed dictum libero placerat nibh tincidunt, eget aliquam orci feugiat. Suspendisse ullamcorper sapien quis porttitor sagittis. Integer vel laoreet elit. Mauris convallis viverra sapien eget accumsan. In hac habitasse platea dictumst. Sed et arcu nibh. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Curabitur quis dictum tortor, at imperdiet lorem.
Sed pulvinar nisi eu ante condimentum rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed malesuada mauris nec dui rhoncus lacinia. Curabitur tincidunt ullamcorper felis ac ullamcorper. Suspendisse dolor est, suscipit ac ligula a, molestie dapibus lectus. Morbi semper, tortor nec tincidunt elementum, nisl tortor consectetur massa, in sodales urna leo sit amet justo. Fusce eu sem eget diam blandit venenatis vel in odio. Vivamus volutpat feugiat sem, sit amet pellentesque orci molestie sed. Proin tincidunt hendrerit nibh, in blandit lacus. Maecenas mattis finibus odio, nec scelerisque ligula aliquam id. Quisque viverra velit eget sem suscipit dapibus. Integer pretium, turpis non commodo condimentum, est felis gravida arcu, vitae elementum lorem erat sed sapien.
Mauris sed urna eu lacus sagittis rhoncus. Sed eleifend id erat quis vestibulum. Suspendisse mattis tempor neque, in vestibulum nisl molestie sit amet. Nulla blandit lectus semper dui accumsan molestie. Ut in dui non augue laoreet imperdiet vitae a orci. Quisque a leo hendrerit, ultrices sem vel, rhoncus augue. Donec quis facilisis enim, ut efficitur enim. Donec finibus libero vitae sem fringilla, at pharetra arcu volutpat. Duis ut mollis dolor. Vestibulum maximus justo nisi, id euismod risus sodales vel.
Sed ut interdum quam, quis mollis lorem. Quisque eget arcu nec justo porta malesuada quis sed odio. Proin tempus enim ac neque efficitur sollicitudin. Fusce a venenatis dui, eget tincidunt sapien. Aliquam sodales hendrerit turpis sit amet commodo. Donec id dui in enim dignissim dignissim a ut lacus. Donec varius bibendum urna sollicitudin aliquet. In hac habitasse platea dictumst.
Donec suscipit cursus porta. Integer interdum ante eget suscipit egestas. Donec ultricies dignissim lectus, a aliquet diam auctor nec. Curabitur sapien turpis, facilisis eleifend metus id, euismod ultricies leo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus rutrum nisi vel leo vulputate dapibus. Fusce sit amet massa sed velit fermentum maximus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ante ligula, sollicitudin sit amet facilisis quis, consequat id ex. Sed imperdiet venenatis tellus, vel gravida metus tempor molestie. Phasellus eleifend, neque eu fringilla fermentum, diam odio luctus lacus, ullamcorper viverra urna elit euismod metus.
Vestibulum sed arcu purus. Quisque sed tellus mattis, convallis ipsum eget, finibus turpis. Nulla quis accumsan sapien. Nam risus felis, finibus at sapien ac, commodo pharetra turpis. Vestibulum vel arcu dictum, gravida purus in, volutpat nisi. Vivamus risus felis, faucibus et erat in, tristique mollis nisi. Morbi sollicitudin ipsum vel diam placerat vestibulum. Morbi dictum velit et posuere tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque risus eu hendrerit pharetra.
Fusce accumsan tempor est, nec fermentum augue posuere et. Etiam aliquam ullamcorper tortor iaculis condimentum. Aenean vel ullamcorper leo. Quisque consequat sit amet sapien id sodales. Vestibulum pretium dui a eros mollis volutpat. Quisque ac sodales felis. In hac habitasse platea dictumst.
Nullam placerat vestibulum ex sed porta. Pellentesque vel est iaculis, pretium neque eu, condimentum elit. Mauris vitae congue sem. Praesent molestie commodo orci a viverra. Donec consectetur tempus imperdiet. Aenean sed elit at turpis consequat ultricies. Curabitur consequat a orci sit amet feugiat. Donec fringilla, risus sed lobortis efficitur, arcu arcu elementum lorem, eu pulvinar elit eros at massa.
Mauris nec molestie turpis. Sed porttitor, orci vel rutrum accumsan, risus arcu pellentesque ante, a pretium libero sem sed lectus. Quisque ornare ipsum id libero sagittis scelerisque in nec lorem. Nunc sagittis eros diam, in elementum enim mattis vel. Duis rhoncus volutpat aliquam. Mauris hendrerit ex aliquam faucibus vestibulum. In viverra lobortis magna. Nullam tincidunt nunc id neque efficitur, et commodo dolor bibendum.
Duis fermentum massa vitae nisi accumsan, et volutpat libero porttitor. Quisque a nibh et mauris lobortis pharetra nec ac diam. Donec ultricies, tellus nec feugiat porta, felis quam accumsan ipsum, vitae laoreet sapien sem id ligula. Mauris vel erat at sapien consectetur dignissim. Aenean placerat tellus in leo fringilla, non condimentum magna placerat. Ut at justo maximus, tristique quam id, euismod orci. Morbi eget metus erat. Donec ultrices odio eget velit accumsan, vitae blandit leo dignissim. Vivamus quis auctor ipsum. Etiam placerat auctor rhoncus. Curabitur lacus justo, rutrum vitae placerat in, hendrerit ultricies augue. Integer vestibulum bibendum magna vehicula hendrerit. Nulla vehicula leo ut est feugiat imperdiet et id lorem. Maecenas quis lacus lobortis, viverra dui et, dapibus eros.
Fusce ac sapien ut odio blandit pellentesque vitae nec mauris. Aliquam a ipsum id urna condimentum dictum. Proin vehicula bibendum ligula vitae consectetur. Nullam id erat mattis, vehicula velit eu, finibus nisl. Fusce lorem neque, vehicula sed diam non, viverra venenatis ligula. Fusce fermentum turpis at volutpat mollis. Praesent nec lobortis ligula. Nulla magna nulla, consectetur vitae tincidunt ut, eleifend eu nulla. Pellentesque mollis erat et interdum vulputate.
Sed tincidunt pretium dui, et pellentesque ex interdum vitae. Mauris non pretium lectus. Etiam in aliquam dui, nec porttitor turpis. Quisque sagittis, tellus in tincidunt pellentesque, arcu urna fringilla sem, a dictum libero metus ac enim. Mauris mollis nibh quis dui finibus, eu porta arcu efficitur. Vivamus neque ipsum, vulputate a efficitur ut, laoreet eu dui. Sed in nisl mattis, tincidunt orci nec, finibus dui. Donec lobortis vitae nibh eget lobortis. Integer at fringilla dui, consectetur fringilla libero. Pellentesque magna augue, dignissim non sodales nec, convallis quis tellus. Proin tristique, mi et malesuada bibendum, tortor diam consequat felis, et rhoncus quam ante a tellus. Aenean gravida, justo eu fermentum ultricies, elit turpis vehicula felis, nec viverra lorem velit id lorem.
Aenean luctus scelerisque odio at mattis. Suspendisse sit amet malesuada leo. Nunc nec condimentum enim. Maecenas finibus massa diam. Morbi blandit scelerisque enim, id lobortis odio pellentesque in. In quis mi dui. In dignissim, leo et aliquam placerat, erat urna placerat purus, venenatis convallis ligula nibh euismod urna. Ut interdum eget turpis vel tincidunt. Nulla facilisi. Integer scelerisque augue nunc, nec pharetra purus volutpat id. Aliquam bibendum ac enim et tempor. Vivamus sit amet nisi vel lacus tristique euismod at eu eros. Fusce sed nisi ipsum. Aenean felis magna, condimentum non sapien in, pharetra maximus dui. Sed neque felis, sodales sed nisi sollicitudin, congue congue nulla.
Mauris consectetur dolor ac leo luctus venenatis. Proin blandit commodo lacus sed mollis. Nam vel est at justo laoreet finibus vitae vel turpis. Donec at augue libero. Sed accumsan justo sed est tempus blandit. Cras eros diam, pellentesque fermentum tempor in, malesuada non velit. Cras volutpat ante diam. Vivamus luctus tempus nisi, sit amet elementum massa tincidunt vitae. Suspendisse hendrerit, tortor sit amet venenatis interdum, tortor neque dictum nibh, sit amet interdum dui lacus quis lectus. Sed nisi sem, rhoncus sed aliquet sed, finibus et ante. Nulla blandit orci eu nibh ullamcorper porta. Praesent id magna id neque cursus facilisis.
Proin convallis, ligula eu fringilla tempus, risus felis sagittis quam, in tempor nisi magna ac risus. Sed imperdiet accumsan magna. Mauris maximus diam eget tincidunt luctus. Duis libero risus, molestie vitae orci consectetur, elementum tristique nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Duis quis diam nunc. Praesent iaculis lacus ut diam tristique consectetur. Vivamus dui ante, mattis eget eros a, tincidunt lacinia risus. Ut ultrices porttitor odio, ac scelerisque enim efficitur id. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam vehicula accumsan erat, id mollis nisl accumsan eu. Nunc ipsum sapien, egestas et sem congue, consequat consectetur nunc. Vivamus pretium est ipsum, eget condimentum est bibendum sed. Donec lobortis blandit est, sit amet consectetur arcu. Vivamus sapien est, convallis sed laoreet eget, ornare eget tellus.
Sed condimentum, magna gravida dignissim hendrerit, nisl nunc vehicula justo, ut vehicula ipsum purus non dolor. Curabitur quis tellus porttitor, venenatis tortor eu, interdum justo. Suspendisse bibendum orci sit amet malesuada tincidunt. Sed maximus feugiat tempus. Nullam in ante ante. Nullam convallis arcu quis sapien facilisis, id dignissim sapien malesuada. Cras tempor, enim in consequat vestibulum, dui nisi maximus nulla, et dignissim justo odio non orci.
Suspendisse fringilla turpis sed tortor efficitur, a placerat nisi vestibulum. Etiam convallis lacus vitae dignissim tempor. Suspendisse id mauris a risus bibendum maximus. Nullam dignissim sit amet ligula ac lobortis. Nullam feugiat est quis tortor fermentum lobortis eget eget libero. Donec non suscipit nulla. Sed ac lacus neque. Nunc imperdiet mi ut metus sagittis mollis. Sed varius sodales accumsan. Donec auctor elementum sagittis. Donec odio mauris, faucibus quis mollis nec, efficitur at eros. Maecenas massa ligula, fringilla eget mi quis, placerat vehicula lacus. Maecenas leo nibh, bibendum ac sem sed, dignissim iaculis nibh.
Donec in tincidunt arcu. Quisque commodo rutrum ornare. Aenean eu purus pretium, faucibus justo eget, pharetra urna. Fusce pharetra facilisis sapien sed luctus. Cras non elit vestibulum, rutrum lectus ut, bibendum erat. Duis vitae est eu libero vehicula viverra at vitae ipsum. Nunc justo ligula, tempor vitae ex sit amet, consectetur placerat ex. Aenean ligula dui, fermentum vel semper sed, semper eu orci. Etiam gravida sagittis eros, et pellentesque justo. Curabitur et pulvinar velit. In semper odio leo, ut pharetra nunc accumsan nec. Sed velit augue, ultrices in ante blandit, feugiat pretium massa. Maecenas bibendum, nibh eget suscipit ultrices, elit felis auctor risus, nec dictum nibh neque ac diam. Sed consequat arcu id nibh tristique sodales. Phasellus vulputate placerat velit sed condimentum.
Nulla facilisis leo nec efficitur venenatis. Phasellus ac interdum ligula. Curabitur pharetra laoreet ipsum, ac porta nunc tristique eu. Morbi mollis varius massa ac egestas. Vivamus sed nibh tellus. Pellentesque auctor sapien aliquet nunc semper venenatis. Aenean dignissim venenatis feugiat.
Donec ut tincidunt sapien, ut consequat felis. Morbi luctus orci in elit luctus blandit. Proin fringilla odio vel elit tristique tincidunt. Integer tellus metus, vestibulum eu eleifend eu, finibus id velit. Curabitur nec turpis accumsan, aliquam nibh nec, luctus velit. Curabitur id velit eget quam scelerisque pretium et a mauris. Suspendisse vel felis lectus. Maecenas a augue lectus. Sed viverra maximus nisl, at tempor lectus ornare ut. Donec ac semper velit. Nunc hendrerit sapien et tellus fermentum sagittis.
Sed malesuada enim et est tincidunt, a tristique mi porttitor. Sed interdum, orci non sagittis sagittis, ipsum enim aliquet erat, quis pharetra sapien lacus vel tellus. Nunc dictum nunc sed suscipit tempus. In hac habitasse platea dictumst. Maecenas gravida vestibulum faucibus. Nam eget tempus odio. Maecenas a eleifend massa, ut efficitur odio.
Integer fermentum lacus turpis, at aliquet diam convallis non. Ut ac arcu vitae felis dapibus porttitor a sit amet orci. Suspendisse nisl libero, fringilla non posuere vel, pharetra nec nisl. Pellentesque et euismod nibh, eget ornare urna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In viverra faucibus purus, a congue felis interdum ut. Aliquam vitae tellus sed felis mattis elementum. Fusce eleifend lorem ut ex euismod euismod. Donec ac consectetur augue. Cras posuere neque massa, sed euismod urna mattis ac. Mauris nec sollicitudin lacus. Sed eu massa et lorem viverra bibendum sed sit amet arcu. Vivamus gravida hendrerit mi, cursus iaculis nunc imperdiet a. Quisque purus mauris, viverra sit amet euismod sit amet, rutrum id nibh. Donec dignissim diam nibh, quis rhoncus nulla suscipit at. Mauris dapibus, tellus et efficitur aliquet, tellus diam vehicula enim, ac fermentum ante justo nec turpis.
Nullam sapien orci, pharetra a elit eu, interdum interdum libero. Ut eu pulvinar ipsum. Aliquam hendrerit elit arcu, vel volutpat nisl convallis id. In maximus justo sed magna euismod sagittis. Morbi fermentum ante nisi, id volutpat nisl congue a. Praesent sed efficitur turpis. Pellentesque eu turpis nec massa semper semper. Donec tincidunt ac lacus eget maximus. Quisque vel tortor eros. Nam vitae urna a mi maximus vestibulum.
Phasellus et eros lectus. Mauris luctus diam a dolor sagittis, quis lacinia odio euismod. Ut sed porttitor sem. Mauris faucibus vitae ex et malesuada. Nullam quis tincidunt diam, et lobortis ipsum. Pellentesque scelerisque metus vel luctus porttitor. Donec eu vehicula erat, ornare efficitur elit. Praesent ullamcorper est sit amet odio finibus malesuada. Nulla molestie id odio quis semper. In ultrices, massa quis consequat placerat, mi magna porttitor enim, sed blandit nulla nunc nec nunc. Duis suscipit, mauris sit amet aliquet sodales, arcu massa efficitur enim, et sollicitudin urna nisi sed mi.
Nunc tempus dolor lorem, consectetur semper dolor feugiat in. In imperdiet ullamcorper erat id accumsan. Sed at molestie sem. Phasellus sagittis consequat orci, in feugiat odio imperdiet ac. Aliquam auctor eros vulputate dolor rhoncus, ac hendrerit enim lacinia. Morbi augue orci, sollicitudin sed consequat fermentum, hendrerit sed velit. Sed a turpis aliquet, fringilla elit eu, dictum libero. Donec aliquam urna mauris, vel interdum urna congue vel. Sed ex tellus, consectetur sed imperdiet at, finibus efficitur nisl. Phasellus aliquam semper libero finibus rhoncus. Pellentesque dolor augue, porta eu urna eu, ultricies lacinia metus. Praesent cursus ante dapibus, volutpat nunc id, pharetra diam. Nam iaculis enim non faucibus dapibus. Vivamus est augue, aliquam ac ipsum eget, vestibulum commodo lorem. Proin porttitor nibh vitae est fermentum, id suscipit dolor elementum.
Praesent tempor fermentum tellus, vitae tincidunt turpis mattis a. Etiam eu magna et eros iaculis ullamcorper. Pellentesque pharetra turpis metus, nec bibendum leo fermentum et. Sed arcu nulla, gravida nec leo quis, efficitur suscipit libero. Quisque purus mi, auctor vitae quam quis, tincidunt porta sapien. Proin eu facilisis orci, at eleifend lectus. Aenean blandit viverra nulla non tempor. Duis venenatis tortor nec finibus interdum.
Duis sed tortor nulla. Donec scelerisque sem purus, id varius risus lobortis ut. Proin velit ipsum, vulputate vitae viverra ac, viverra quis ante. Maecenas eget sapien non sem volutpat elementum finibus eu nunc. Pellentesque non ex quis leo gravida malesuada quis mollis eros. Fusce mollis nunc eget risus vehicula eleifend in sed lorem. In hac habitasse platea dictumst. Nulla quis pretium nisl. Vivamus dignissim, nibh in luctus ornare, nunc risus commodo enim, et aliquet libero neque ut orci. Suspendisse sed quam eget urna viverra porta. Aenean ligula ligula, congue vel ullamcorper et, vehicula quis tortor. Sed dictum nec nulla eget sollicitudin. Aliquam molestie ligula justo, sit amet faucibus dolor ultricies eget.
Aliquam et risus posuere, malesuada nibh id, malesuada sapien. Curabitur lacus ex, ullamcorper id pharetra at, maximus vel augue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec varius felis quis tortor laoreet volutpat. Quisque iaculis posuere enim, tincidunt rhoncus erat sodales vel. Etiam sit amet purus suscipit, tempus lacus non, semper tellus. Pellentesque in aliquet urna. Vivamus a justo bibendum, tristique tellus pretium, fringilla eros.
Cras eget arcu condimentum, varius eros vel, fermentum quam. Duis ut turpis ut erat laoreet pulvinar et non lectus. Nam mattis libero quis congue pharetra. In vulputate quis massa quis eleifend. Donec eu velit ac urna tempor blandit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam sed lobortis mi. Etiam porttitor, leo sed dictum rutrum, justo massa semper tortor, vel lobortis urna elit a felis. Aliquam odio augue, pellentesque sed ex sed, bibendum pellentesque turpis. Morbi viverra nulla ac ipsum mattis, non auctor tortor condimentum. Vestibulum pretium nec nulla vitae sollicitudin. Integer scelerisque libero id blandit pharetra.
Ut aliquet libero id commodo mattis. Nulla ut ex malesuada, tincidunt nisl in, lacinia nisl. Pellentesque scelerisque semper mauris, nec tincidunt urna bibendum id. Nulla facilisi. Nulla facilisi. Sed id fringilla odio. Fusce tempus egestas mauris nec accumsan. Integer dictum, elit vehicula molestie ultrices, purus sapien luctus enim, nec suscipit felis neque sit amet mi. Nulla sed fermentum orci.
Donec id lorem euismod, posuere leo in, pharetra velit. Nullam sed blandit mauris. Proin vitae congue neque, quis tristique ante. Donec consectetur a velit sed congue. Sed finibus dui luctus, maximus metus et, tempor sapien. Quisque vulputate molestie arcu eu malesuada. Ut consectetur rutrum diam eu viverra. Suspendisse interdum ipsum mattis neque pulvinar posuere. Donec dolor erat, bibendum vitae malesuada ac, hendrerit quis metus. Duis vitae urna orci. Sed lobortis nisl ut tortor eleifend malesuada. Curabitur dapibus ex vitae ante ornare, et aliquet orci bibendum.
Quisque sollicitudin metus turpis, vitae condimentum metus semper id. Duis pharetra facilisis leo vel egestas. Vivamus ut magna justo. Sed quis vehicula turpis, sed dictum augue. Praesent erat tellus, fermentum non vestibulum vitae, commodo in lectus. Integer eu rutrum nibh. Sed pellentesque lacinia mauris, et varius orci laoreet ut. Nulla condimentum ante eros, sed aliquam augue gravida nec. Integer auctor nisl nec mauris vulputate laoreet eget nec lorem. Suspendisse convallis dui a nisi dapibus egestas sit amet non quam. Cras vulputate sapien sit amet lacinia scelerisque. Quisque justo ante, tincidunt in risus ut, dapibus maximus mauris. Vivamus eget lectus nec mi eleifend viverra. Fusce efficitur turpis vel erat auctor aliquam. Nunc volutpat felis massa, sit amet egestas libero mollis non.
In in tempus sapien, sit amet lacinia lacus. Phasellus vehicula sodales cursus. Pellentesque at mollis sapien. Quisque sollicitudin, lorem nec condimentum fringilla, velit arcu vehicula dui, at porttitor turpis leo nec nunc. Mauris elementum eros purus, malesuada consectetur orci sodales eu. Fusce suscipit, turpis vel mattis finibus, leo lacus maximus nibh, ac aliquet nunc enim et lectus. Donec nec nulla est. Duis porta id dolor a vehicula. Mauris accumsan arcu eget metus scelerisque, eget consequat mi rutrum. Aenean placerat tristique feugiat.
Mauris in odio neque. In pretium libero condimentum urna fermentum cursus. Vivamus tincidunt tincidunt volutpat. Aenean sed faucibus dui, tincidunt egestas eros. Nunc velit velit, aliquam eget purus eu, dictum ullamcorper eros. Vestibulum molestie interdum pulvinar. In ac mauris non metus consectetur luctus sed in risus. Sed eget consequat augue. Nulla posuere ligula augue, eu pretium ipsum placerat a. Mauris quis ullamcorper metus, at egestas tellus.
Ut consectetur placerat mauris vel placerat. Nam volutpat sapien ut ornare congue. Vestibulum cursus magna at scelerisque venenatis. Nullam ac lacus quis sapien lobortis ullamcorper eu in libero. Quisque semper vitae urna vitae dictum. Mauris pretium elementum turpis, vel varius odio ullamcorper in. Vestibulum efficitur malesuada est, eu venenatis mauris iaculis sed. Sed suscipit egestas lacus, at porta risus cursus et. Aenean nec augue tempor est elementum bibendum vitae non nisl. Proin molestie porttitor dolor vitae laoreet. Ut sagittis, dui quis pulvinar ultrices, neque tortor auctor nibh, sed ornare mauris mauris vel lacus. Nunc sed ullamcorper lorem. Maecenas facilisis arcu non diam feugiat rhoncus.
Mauris dictum iaculis molestie. Duis viverra pellentesque volutpat. Proin id felis velit. Morbi sed tellus sed ligula molestie ultricies. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque at lobortis ex. Integer pharetra nibh diam, vehicula scelerisque mi vehicula sit amet. Proin lobortis at augue non bibendum. Morbi porttitor varius tortor, et tristique nibh cursus vitae. Maecenas cursus facilisis tortor, aliquet volutpat ante convallis eget. Nunc odio turpis, pellentesque sed enim sit amet, posuere eleifend magna. Duis ultrices felis ipsum, eu ornare ex iaculis et. Curabitur metus diam, rutrum sit amet rhoncus et, imperdiet sit amet neque. Cras nec dui laoreet magna condimentum fringilla vel quis orci. Morbi sit amet nisi luctus, commodo lacus et, aliquam felis.
Integer pharetra lacinia metus, ut gravida enim varius nec. Proin in risus augue. Aenean vel urna elit. Cras sed erat molestie enim fringilla posuere sed vel lorem. Suspendisse mauris massa, tempus quis tortor ut, placerat egestas ligula. Nam eu massa dictum, fermentum est nec, lacinia felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Pellentesque tellus quam, placerat commodo tincidunt id, tincidunt ut lectus. Integer ut blandit diam. Duis quis rutrum augue. Nulla ex elit, malesuada vel interdum in, commodo a turpis. Quisque pharetra neque at imperdiet ornare. Cras tincidunt arcu tellus, sit amet ultricies nisi congue nec. Curabitur vel est sed dolor euismod tempus. Praesent at sagittis risus, id viverra neque.
Donec augue leo, pellentesque eu volutpat quis, suscipit in mi. Aenean placerat libero id ornare vestibulum. Maecenas nec faucibus nisi. Curabitur elementum aliquam congue. Maecenas nec lobortis purus. Nam aliquam justo erat, in placerat magna rutrum suscipit. Vestibulum non sem et ipsum lobortis consectetur. Sed sed commodo dui, in feugiat ipsum. Proin mattis gravida lectus, non placerat magna fringilla sit amet.
Integer erat sem, hendrerit id venenatis quis, vestibulum in orci. Praesent sed nisl in sem euismod suscipit. Vivamus in lectus est. Nulla sed neque ut dui posuere interdum sed in mi. Maecenas tincidunt porta ornare. Quisque id sapien aliquet eros consectetur ultrices. In dui turpis, tincidunt ac consectetur vel, scelerisque id arcu. Curabitur sed auctor tellus, sit amet congue ex. Vestibulum accumsan, diam id interdum feugiat, ex turpis fermentum enim, nec tristique ante lacus in sem. Fusce vel ante luctus, mollis ante quis, porttitor leo.
Morbi luctus cursus sapien, accumsan pulvinar urna euismod id. Duis fermentum mi a sapien sollicitudin, ac laoreet magna vestibulum. Integer faucibus diam id dui lacinia, et egestas felis faucibus. Vestibulum efficitur quam at condimentum vulputate. Donec et orci mauris. Cras sit amet dictum nulla, eu vestibulum lacus. Suspendisse rhoncus nibh neque, sit amet semper leo eleifend vel. In tortor tellus, ornare a risus at, malesuada porttitor massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nam urna nunc, ultrices at nulla sit amet, cursus malesuada lacus. Integer nec sem faucibus, placerat sapien ac, placerat sapien. Cras molestie arcu imperdiet nisi accumsan luctus. In in interdum turpis. Aliquam posuere volutpat pharetra. Aenean pharetra volutpat tempor. Aenean quis turpis ut libero interdum gravida. Maecenas ac scelerisque velit. Morbi non nulla dignissim, maximus lacus sit amet, vestibulum metus. Nunc convallis elit non tincidunt ultricies. Suspendisse aliquet vel lectus a facilisis. Nulla sit amet venenatis odio.
Suspendisse magna nisi, varius luctus ipsum et, imperdiet consequat lacus. Nulla quis congue augue. Proin vehicula mi leo, suscipit dignissim ex egestas eu. Quisque interdum erat quis quam facilisis, in feugiat felis tincidunt. Donec orci odio, porttitor vitae pellentesque eu, rhoncus ac risus. Aliquam faucibus commodo orci. Sed eu arcu sed diam venenatis vulputate a ut sem. Integer nec dapibus dolor. Aenean fringilla malesuada quam, non sagittis libero venenatis ac. Integer blandit neque eget leo auctor lobortis. Donec at tincidunt nunc, a efficitur purus. Vestibulum et orci lobortis, cursus lorem dapibus, malesuada nisi. Nunc in ipsum quis ipsum malesuada lacinia eu non tortor. Mauris ac vehicula tellus.
Nullam ut aliquet ipsum, vitae porttitor sapien. Curabitur eleifend sem id venenatis elementum. Nullam non augue eu arcu posuere finibus sit amet eget lorem. Sed vehicula lectus a justo ultrices, eget pharetra augue eleifend. Pellentesque tempor turpis sed leo viverra tempus. Duis volutpat non urna sit amet dictum. Mauris eu orci pellentesque, rhoncus purus a, fermentum dui. Cras accumsan commodo euismod. In suscipit aliquet ex, a scelerisque tortor ultrices ac. Donec ipsum dui, vulputate non gravida et, vulputate ac dolor. Curabitur et hendrerit arcu, et hendrerit erat. Vivamus suscipit risus eu orci sollicitudin, vel convallis enim ultricies. Cras vehicula consequat risus ac gravida. Duis venenatis nisi vel leo pulvinar bibendum. Mauris elementum et quam eu elementum.
Aliquam erat volutpat. Sed a dapibus diam. Quisque laoreet sit amet tortor sodales interdum. Duis congue venenatis odio, suscipit dignissim justo pretium non. Nunc eu arcu ullamcorper, placerat nisl a, euismod libero. Phasellus molestie mi quis est egestas, ac venenatis justo malesuada. Fusce et nisi ullamcorper, pharetra risus non, venenatis libero. In et sodales ante. Ut quis odio at diam interdum laoreet non nec odio. Morbi rutrum metus nisl, sit amet finibus ipsum accumsan vitae. Praesent fringilla rhoncus erat id ultrices. Aenean ut erat non nisl blandit bibendum ac sit amet lectus. Pellentesque scelerisque dui nec fermentum eleifend. Nulla rhoncus magna non orci sollicitudin fermentum. Nullam consequat orci vitae ullamcorper laoreet. Nam congue tincidunt ligula condimentum ultricies.
Donec nec eros vitae ante commodo scelerisque. Donec felis ex, ornare ut neque a, volutpat blandit enim. Fusce a mi a nunc facilisis semper. Fusce mollis justo eu mi tempor eleifend. Sed ultrices urna quis ipsum cursus, et elementum ante posuere. Praesent viverra vestibulum iaculis. Praesent vel faucibus erat. Integer et diam dapibus, convallis arcu quis, pharetra nulla. Mauris enim arcu, fringilla in tincidunt non, suscipit eu erat. Etiam quis ante euismod, gravida nisl vel, tincidunt libero. Vivamus ac eleifend arcu. Mauris egestas, eros ut porttitor vehicula, erat ligula faucibus elit, ut suscipit massa augue ut est. Aliquam dapibus efficitur purus eu pretium. Donec pulvinar turpis orci. Mauris nisl velit, pharetra sed nisl at, pellentesque convallis felis. Etiam vitae lectus lectus.
Aenean eu ligula interdum, feugiat lacus quis, feugiat tortor. Etiam mattis massa vel augue ullamcorper egestas. Vivamus in orci magna. Vivamus a dictum nisl, vitae ornare justo. Sed libero tellus, dapibus in auctor et, porta vel augue. Nullam scelerisque tellus pretium nibh varius vestibulum. Sed et neque turpis. Proin malesuada nisl ut felis iaculis, ac aliquam lorem euismod. Vestibulum pretium sapien sit amet enim egestas elementum. Cras eget est luctus, mollis sapien ac, porta ex. Praesent venenatis dapibus lacus, ut efficitur lacus fringilla non. Integer eu rutrum magna. Integer iaculis venenatis blandit. Vestibulum euismod vitae leo tincidunt dignissim. Interdum et malesuada fames ac ante ipsum primis in faucibus.
Proin sodales neque dui, at sagittis magna fermentum vel. Cras id metus id sapien cursus rhoncus. In hendrerit augue dictum, gravida augue vel, consectetur lorem. Vivamus sollicitudin pellentesque pulvinar. Donec consectetur sem quis odio scelerisque elementum. Ut luctus enim nec nunc venenatis mattis vitae ac lorem. Nullam aliquam nulla et ornare interdum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam sollicitudin lacinia tellus et suscipit.
Ut eget orci non est luctus mattis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vel magna ligula. Donec eu sem ut odio ullamcorper ornare. Sed blandit, felis pellentesque laoreet cursus, diam sem viverra nunc, in auctor orci diam sit amet enim. Maecenas sit amet commodo turpis, nec tristique lectus. Maecenas dictum leo nec rhoncus faucibus. Vestibulum augue quam, varius ac facilisis vitae, commodo in quam. Aenean suscipit tellus non tincidunt viverra. Integer eu ipsum non nibh bibendum euismod id at erat.
Mauris non malesuada sapien. Pellentesque vitae mi nulla. Curabitur laoreet, sapien et facilisis varius, est est dapibus leo, dapibus auctor erat urna vel enim. In vehicula, nisl ac pharetra finibus, tellus ipsum vestibulum mi, venenatis pulvinar ante sem nec risus. Phasellus porta porttitor lectus, id consectetur justo commodo a. Donec in dui ut tellus ultricies aliquet. Praesent ac mi metus. Integer lobortis purus eu justo lobortis, vel imperdiet ex hendrerit. Aliquam erat volutpat. Proin ut ligula nisl. Sed pretium porttitor varius. Nam iaculis ac orci sed pulvinar. Donec mattis orci non dui vehicula, at lobortis nibh efficitur. Vestibulum varius erat ornare posuere convallis.
Vivamus gravida massa feugiat scelerisque maximus. Nam bibendum facilisis vehicula. Vivamus id lacinia nisl. Sed tempus, orci in tincidunt dignissim, nulla nibh fringilla magna, et rutrum erat sapien ac turpis. Curabitur laoreet id mi in luctus. Vestibulum nec erat et nunc bibendum feugiat vitae nec eros. Morbi vitae convallis neque, vitae faucibus leo. Suspendisse sem justo, vestibulum eget nulla varius, molestie vestibulum nibh. Nullam eleifend arcu enim, et porta felis pretium id. Cras eu sapien quis lacus feugiat venenatis.
Sed diam turpis, interdum vel felis imperdiet, posuere venenatis augue. Maecenas sapien nulla, consectetur vitae mattis in, finibus id lorem. Quisque consequat euismod vestibulum. Maecenas congue velit lorem, tincidunt tristique lorem consectetur quis. Proin vulputate porta convallis. Cras id tincidunt nulla. Proin sit amet turpis imperdiet turpis aliquet feugiat sit amet eu augue. Donec ut consequat neque. Morbi laoreet leo eu augue ullamcorper, ut porttitor lectus pulvinar.
Vivamus vitae nisi eu libero vestibulum sollicitudin vitae in metus. Ut nec massa justo. Phasellus euismod consequat massa id tempor. Vestibulum et imperdiet quam. In ipsum nibh, consectetur quis posuere vitae, laoreet et ante. Maecenas cursus eros vel ante tempor, vel tristique neque tincidunt. Ut eget erat vitae sapien posuere luctus. Donec a finibus erat.
Quisque at ligula sit amet arcu molestie feugiat commodo sit amet nisi. Aenean aliquet hendrerit metus vitae lacinia. Pellentesque pulvinar luctus ipsum non condimentum. In fringilla ac dui a fermentum. Nulla sollicitudin, nisl a fermentum rutrum, eros diam posuere nunc, eget luctus risus eros nec ligula. Suspendisse sit amet ante porta, semper est tempor, pulvinar odio. Cras dictum elit sed orci lacinia aliquet. Ut consectetur, nisl sit amet lacinia finibus, leo eros tempus risus, at lacinia nulla nisi vel tellus. Aliquam at nisl egestas, auctor est a, congue diam. Proin fringilla pellentesque arcu sit amet aliquet.
Morbi a lectus ultricies nibh efficitur scelerisque ac ac urna. Nunc molestie risus vitae ipsum ornare vestibulum. Vivamus molestie tincidunt tempus. Maecenas tristique luctus augue ut lobortis. In risus turpis, condimentum mattis posuere eget, sodales ut lorem. Sed vulputate tempor diam in ullamcorper. Aenean aliquet lectus vitae massa laoreet, nec vehicula odio porta.
Aliquam tristique ut nisi sit amet luctus. Quisque nulla mi, vulputate at lobortis vitae, fermentum at lacus. Curabitur non massa in nunc tempus dignissim. Suspendisse erat velit, molestie non vulputate in, lobortis quis purus. Pellentesque quis placerat nisl. In posuere vestibulum nisl eget egestas. Sed non dui posuere, pharetra est eu, ullamcorper mauris. Pellentesque dictum varius erat at condimentum. Sed nisi enim, pellentesque quis enim molestie, imperdiet volutpat arcu. Aenean commodo finibus vulputate. Fusce ornare scelerisque urna, vitae tempus neque vehicula eu.
Fusce lacinia augue id tristique rutrum. Aenean ut elementum augue. Nulla ut lectus tellus. Pellentesque et libero et mauris facilisis rutrum a pharetra dolor. Vivamus lobortis lacus eu ante suscipit, vel commodo nisi venenatis. Sed gravida gravida congue. Aliquam rutrum dictum orci ac condimentum. Aenean ac ex eu diam dapibus venenatis id ut lacus.
Maecenas non porttitor orci. Donec dapibus rhoncus consectetur. Cras porta sagittis magna, at convallis eros consequat non. Quisque consectetur sem in sagittis sollicitudin. Maecenas id eros porta, tristique sem mollis, sagittis enim. Praesent mollis dapibus commodo. Etiam bibendum lacus nec iaculis eleifend. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam vitae finibus erat. Fusce sollicitudin eleifend elit in hendrerit. Quisque fermentum rhoncus pulvinar. In lobortis libero ac nisi euismod venenatis sit amet sed ipsum. Nam id molestie quam, eu bibendum diam.
Etiam non augue volutpat, fermentum nunc non, sodales lectus. Curabitur elementum euismod ex, quis porttitor erat tempus accumsan. Morbi fringilla nisl nec hendrerit cursus. Suspendisse egestas massa in nisl gravida sollicitudin. Maecenas maximus, tortor sed lacinia consectetur, nisi magna tincidunt lorem, vel maximus dolor sem in eros. Sed a vulputate nunc. Integer egestas, tortor vitae imperdiet cursus, massa enim pellentesque felis, sit amet sollicitudin velit arcu id lorem.
Nullam nec diam convallis, fermentum quam id, pulvinar velit. Pellentesque ultricies semper metus, cursus pulvinar tortor consectetur vel. Fusce suscipit urna sem, vitae ultrices lacus aliquet vel. Pellentesque tempor tristique mi, quis rhoncus lacus fringilla a. Interdum et malesuada fames ac ante ipsum primis in faucibus. Morbi neque risus, malesuada at lacinia non, posuere elementum mauris. Pellentesque eget egestas est, nec congue leo. Nunc faucibus mi id vulputate sodales. Cras ornare eget justo eu blandit. Fusce id magna lorem. Nunc sit amet dolor placerat, ornare metus non, ultricies augue.
Ut sed auctor dui, ullamcorper pretium sapien. Sed ut felis id nunc mollis consectetur et in nunc. Nunc volutpat nec urna nec facilisis. Ut sagittis ipsum nec aliquam interdum. Donec rutrum dolor eget neque euismod vestibulum. Nulla condimentum neque neque, eget ullamcorper risus cursus scelerisque. Sed bibendum luctus dolor eget dignissim. Etiam non nulla enim. Vestibulum eget semper odio. Sed semper vulputate ipsum ac maximus. Nullam sed libero pellentesque quam rhoncus sagittis vitae sed ipsum.
Sed vitae ex vulputate, scelerisque sapien quis, mattis massa. Duis rutrum neque ante, a vestibulum massa congue at. Nam tincidunt ex luctus ultricies laoreet. Duis cursus magna eu diam malesuada ultricies. Cras porttitor sagittis tellus, eget mollis enim molestie eu. Nunc tristique semper massa. Nullam varius velit sit amet velit suscipit, a bibendum odio facilisis. Nunc et arcu bibendum, fermentum odio id, congue lectus. Phasellus malesuada volutpat justo ut sodales. Integer interdum et nibh non blandit. Nam a vulputate tellus.
Quisque auctor commodo nisl, ut semper lectus tincidunt sed. Integer cursus finibus est. Vivamus dui dui, feugiat nec leo eu, vestibulum interdum nunc. Nam massa dolor, tempor sit amet congue et, maximus at elit. In blandit at nibh et porta. Curabitur elementum efficitur elit, vel sagittis tellus eleifend lacinia. Sed tincidunt elit eu purus fermentum finibus. Aenean egestas dignissim tellus vel semper.
Nulla id condimentum lorem. Donec vitae dui quam. Maecenas sapien dui, facilisis sed tellus sit amet, pharetra iaculis ligula. Fusce sagittis, odio sed aliquam feugiat, nunc ipsum ultrices lorem, vel pellentesque nibh orci finibus leo. Proin a urna tincidunt, porttitor sapien ac, fringilla velit. Suspendisse in vehicula risus. Morbi mattis cursus cursus. Nam vel varius nisi, blandit malesuada lacus.
Nullam laoreet nibh quis erat dictum fringilla. Quisque a tortor dolor. Curabitur pulvinar molestie lectus, eget dapibus nisl tristique id. Nullam pulvinar accumsan arcu, euismod auctor nunc dignissim ac. Vivamus pulvinar massa at metus sollicitudin, dictum convallis arcu vestibulum. Suspendisse at leo nec sem sollicitudin luctus sit amet vitae nisi. Duis lobortis risus id odio luctus, sit amet feugiat mauris ullamcorper. Donec iaculis suscipit nunc eu dictum. Quisque ut lobortis elit. Cras eget auctor lacus. Donec mattis vitae nisi a porta. Morbi quis eros sed ante pharetra euismod. Nullam varius bibendum magna a cursus.
Aenean vestibulum leo magna, sit amet varius eros eleifend mollis. Aenean tempor ullamcorper velit vel sagittis. Aenean maximus enim nulla, nec pellentesque elit ullamcorper eget. Duis tincidunt, dolor id euismod rhoncus, orci dolor auctor augue, eu molestie odio tellus nec sem. Donec gravida arcu ac ex ultrices rhoncus. Nulla tincidunt gravida neque id dictum. Sed lectus lectus, rhoncus ac odio vitae, porttitor elementum nunc. Morbi gravida, leo id sollicitudin iaculis, mi elit volutpat eros, quis venenatis massa dui pharetra neque. Cras sit amet dignissim mi. Donec in lectus sed risus congue consequat. Duis ut malesuada metus. Praesent maximus ac tortor eget feugiat. Nulla in nunc eget quam sodales sagittis.
Nam eu porta enim. Fusce pretium elit sapien, a feugiat nibh tempor a. Etiam feugiat dui nec neque malesuada, quis tristique sapien vestibulum. Sed volutpat eget nulla id imperdiet. Morbi sodales tortor ac ligula vulputate tincidunt. Aliquam placerat orci sem, id fringilla orci facilisis eu. Nullam aliquet odio eget ante placerat blandit. Morbi ut justo cursus, ullamcorper purus id, scelerisque neque. Donec a nisi pellentesque, commodo magna efficitur, feugiat neque. Maecenas at quam eleifend, ornare sem non, pretium ante. Pellentesque eget fringilla ligula. Donec massa arcu, viverra auctor sem at, ultricies blandit odio. Proin sed leo quam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce elementum efficitur blandit. Morbi tincidunt porttitor odio nec placerat.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec vel libero pharetra, euismod nulla sit amet, volutpat lorem. Maecenas blandit magna ornare mi imperdiet luctus. Fusce congue risus et enim placerat ornare. Aenean ac magna eget risus rhoncus molestie at et leo. Cras mattis erat lectus, sed dignissim enim pulvinar vel. Donec turpis libero, condimentum sit amet rutrum id, blandit in diam. Praesent tincidunt malesuada lorem, at posuere nisi. Ut rutrum turpis vel mi blandit congue. Aenean viverra metus quis erat hendrerit, nec egestas diam placerat. Praesent vel ipsum enim. Praesent eget sollicitudin dui. Donec semper turpis id magna molestie, sit amet interdum odio lacinia. Curabitur ut mollis metus. Duis luctus leo velit, id accumsan risus sodales non.
Nullam ut arcu sed justo tempus consequat. Donec nisl ante, lacinia ac convallis ac, bibendum sed diam. Duis viverra dolor sed ex convallis, vel facilisis ligula maximus. Pellentesque eu pulvinar nulla. In ante risus, viverra a euismod et, laoreet a dui. In hac habitasse platea dictumst. Nunc ullamcorper tellus non viverra pharetra. Aenean dapibus dolor sit amet dui facilisis placerat. In hac habitasse platea dictumst. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec ac efficitur enim, ac placerat dui. Donec vitae vestibulum leo.
Aliquam vestibulum dictum metus, eget commodo ipsum sollicitudin et. Nam volutpat efficitur magna eu vestibulum. Donec dolor purus, aliquet quis orci ut, finibus molestie sapien. Mauris in libero in lorem pretium commodo eu sit amet justo. Integer eu elit sit amet orci cursus sagittis ac a ligula. Curabitur ac eleifend ante. Nulla placerat lacus eu molestie hendrerit.
Proin eu dignissim ante. Fusce lobortis eu ante sed finibus. Vivamus sed dictum turpis. Ut tristique vitae nibh at laoreet. Nullam eget interdum metus, sit amet porttitor nibh. Maecenas dignissim, lacus ac facilisis volutpat, ante nibh vehicula dui, nec facilisis enim turpis vel turpis. Proin risus tortor, vehicula sit amet congue eget, accumsan a magna. Suspendisse potenti. Praesent lacinia mollis feugiat. Donec a nunc ac nibh tincidunt volutpat. Proin nec urna eros. Sed vitae elit fringilla, congue sem non, mattis arcu. Maecenas euismod neque metus, consectetur vestibulum neque rutrum non.
Morbi magna metus, congue nec lacus id, semper mattis augue. Pellentesque vel dolor eu turpis luctus volutpat. Donec consectetur maximus commodo. Quisque erat elit, iaculis vel leo quis, volutpat mollis quam. Sed dui lectus, pretiu

1
sh/tests/custom-ls/folder1/ls-test

@ -1 +0,0 @@
hello

42
sh/tests/custom-ls_test.sh

@ -1,42 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
shopt -s expand_aliases
FILENAME="student/custom-ls.sh"
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
source "$script_dirS"/$FILENAME
submitted=$(cd "$1" && custom-ls)
unalias custom-ls
source "$script_dirS"/solutions/custom-ls.sh
expected=$(cd "$1" && custom-ls)
unalias custom-ls
diff <(echo "$submitted") <(echo "$expected")
}
# True if FILE exists and is a regular file
if [ -f ${FILENAME} ]; then
# FILE exists and it's not empty
if [ -s ${FILENAME} ]; then
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then
echo "echo is not allowed in this exercise!"
exit 1
fi
challenge custom-ls/folder1
else
echo "The file exist but is empty"
exit 1
fi
else
echo "File does not exist"
exit 1
fi

18
sh/tests/details_test.sh

@ -1,18 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
touch file1.txt
submitted=$(bash "$script_dirS"/student/details.sh && ls -l file1.txt | awk '{print $1, $2, $5, $6, $7, $8, $9}')
expected=$(bash "$script_dirS"/solutions/details.sh && ls -l file1.txt | awk '{print $1, $2, $5, $6, $7, $8, $9}')
diff <(echo "$submitted") <(echo "$expected")
stat file1.txt
}
challenge
rm file1.txt

44
sh/tests/dir-info_test.sh

@ -1,44 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
IFS='
'
FILENAME="student/dir-info.sh"
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
rm -rf student/dir-info-files
mkdir student/dir-info-files
cd student/dir-info-files
directories=(folder1 folder2/aa folder2/ba/aa folder2/aa/ba)
for dir in "${directories[@]}"; do
mkdir -p "$dir"
done
files=(.abc 34 folder1/ab 4 folder1/ac 2 folder1/az 3 folder1/bz 3 \
folder1/cz 9 folder1/.hello 21 folder1/za! 3 folder2/ab 7 folder2/ac 0 \
folder2/alphabet 0 folder2/az 0 folder2/bz 4 folder2/cz 0 folder2/za! 28 \
folder2/aa/aa 3 folder2/aa/az 4 folder2/aa/.salut 7 folder2/aa/ba/ab 0 \
folder2/aa/ba/bz 0 folder2/ba/ac 0 folder2/ba/alphabetz 0 folder2/ba/.ola 17 \
folder2/ba/aa/alphabetz! 0 folder2/ba/aa/.ciao 7 folder2/ba/aa/cz 0 \
folder2/ba/aa/za! 0)
for ((i=0; i<${#files[@]}; i+=2)) do
dd if=/dev/zero of="${files[i]}" bs=1 count="${files[i + 1]}" 2> /dev/null
done
cd ../
challenge () {
submitted=$(bash "$script_dirS"/"$FILENAME" < <(echo "$1"))
expected=$(bash "$script_dirS"/solutions/dir-info.sh < <(echo "$1"))
diff <(echo "$submitted") <(echo "$expected")
}
challenge "dir-info-files/folder1"
challenge "dir-info-files/folder2"
challenge "dir-info-files"
rm -rf dir-info-files

37
sh/tests/division_test.sh

@ -1,37 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
# Test if test command was used
if grep -q "test" "$script_dirS"/student/division.sh
then
echo "Error: the test command cannot be used in the student script"
return
fi
# Test with one or two arguments
if [ $# -eq 1 ]
then
submitted=$(bash "$script_dirS"/student/division.sh $1)
expected=$(bash "$script_dirS"/solutions/division.sh $1)
else
submitted=$(bash "$script_dirS"/student/division.sh $1 $2)
expected=$(bash "$script_dirS"/solutions/division.sh $1 $2)
fi
diff <(echo "$submitted") <(echo "$expected")
}
challenge "10" "2"
challenge "4" "2"
challenge "0.5" "0.5"
challenge "5" "2"
challenge "0.5"
challenge "foo" "bar"
challenge "1" "0"
challenge "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" "2"

15
sh/tests/easy-conditions_test.sh

@ -1,15 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
for i in $(seq 1 5); do
export X=$(shuf -i 1-20 -n 1)
export Y=$(shuf -i 1-30 -n 1)
submitted=$(bash "$script_dirS"/student/easy-conditions.sh)
expected=$(bash "$script_dirS"/solutions/easy-conditions.sh)
diff <(echo "$submitted") <(echo "$expected")
done

12
sh/tests/easy-perm/example.txt

@ -1,12 +0,0 @@
Q. How did the programmer die in the shower?
A. He read the shampoo bottle instructions: Lather. Rinse. Repeat.
~~~~~~~~~~~~~~~~~~~~~~~~~
How many programmers does it take to change a light bulb?
None – It’s a hardware problem
~~~~~~~~~~~~~~~~~~~~~~~~~
Why do programmers always mix up Halloween and Christmas?
Because Oct 31 equals Dec 25.

16
sh/tests/easy-perm/example2.txt

@ -1,16 +0,0 @@
“The best TDD can do, is assure that code does what the programmer thinks it should do. That is pretty good BTW.”
“Simply put, things always had to be in a production-ready state: if you wrote it, you darn well had to be there to get it running!”
“If you think it’s expensive to hire a professional, wait until you hire an amateur.”
“Programming is not a zero-sum game. Teaching something to a fellow programmer doesn’t take it away from you.”
“A phased approach to continuous delivery is not only preferable, it’s infinitely more manageable.”
“So, what do you do?”
“I’m lean”
“What?”
“I’m agile”
“What?”
“Fine. I make websites.”

17
sh/tests/easy-perm_test.sh

@ -1,17 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
chmod 303 easy-perm/*
challenge() {
submitted=$(bash "$script_dirS"/student/easy-perm.sh && ls -l "$1" | awk '{print $1}')
expected=$(bash "$script_dirS"/solutions/easy-perm.sh && ls -l "$1" | awk '{print $1}')
diff <(echo "$submitted") <(echo "$expected")
}
challenge easy-perm/

28
sh/tests/env-format_test.sh

@ -1,28 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
FILENAME="student/env-format.sh"
# True if FILE exists and is a regular file
if [ -f ${FILENAME} ]; then
# FILE exists and it's not empty
if [ -s ${FILENAME} ]; then
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then
echo "echo is not allowed in this exercise!"
exit 1
fi
submitted=$(bash $FILENAME)
expected=$(bash solutions/env-format.sh)
diff <(echo "$submitted") <(echo "$expected")
else
echo "The file exist but is empty"
exit 1
fi
else
echo "File does not exist"
exit 1
fi

38
sh/tests/file-checker_test.sh

@ -1,38 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
# check that test command was not used
if grep -q "test" "$script_dirS"/student/file-checker.sh
then
echo "The 'test' command is not allowed in this exercise"
exit 1
fi
if test ! -e file-checker; then
mkdir file-checker
cd file-checker
touch readable-and-writable readable-only readable-and-executable readable-writable-executable
chmod -x "$script_dirS/file-checker/readable-and-writable"
chmod -xw "$script_dirS/file-checker/readable-only"
chmod -w "$script_dirS/file-checker/readable-and-executable"
chmod +x "$script_dirS/file-checker/readable-and-executable"
chmod +x "$script_dirS/file-checker/readable-writable-executable"
cd ..
fi
challenge() {
submitted=$(bash "$script_dirS"/student/file-checker.sh "$1")
expected=$(bash "$script_dirS"/solutions/file-checker.sh "$1")
diff <(echo "$submitted") <(echo "$expected")
}
challenge "$script_dirS/file-checker/readable-only"
challenge "$script_dirS/file-checker/readable-and-writable"
challenge "$script_dirS/file-checker/readable-and-executable"
challenge "$script_dirS/file-checker/readable-writable-executable"
rm -rf file-checker

17
sh/tests/file-details_test.sh

@ -1,17 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
submitted=$(cd "$1" && bash "$script_dirS"/student/file-details.sh)
expected=$(cd "$1" && bash "$script_dirS"/solutions/file-details.sh)
diff <(echo "$submitted") <(echo "$expected")
}
challenge hard-perm

127
sh/tests/file-researcher/facts.txt

@ -1,127 +0,0 @@
Indonesia consists only of islands - 13,667 total
During World War II, the very first bomb dropped on Berlin by the Allies killed the only elephant in the Berlin Zoo
People who ride on roller coasters have a higher chance of having a blood clot in the brain
The tallest freestanding sculpture in the world is Chief Crazy Horse in South Dakota, USA
Marie Curie, the Nobel prize winning scientist who discovered radium, died of radiation poisoning
898 tornadoes were recorded to have occurred in the United States in the year 2000.
The word Popcorn is derived from the middle English word "poppe," which means "explosive sound"
The food that is digested in your stomach is called "chyme."
Alcohol beverages have all 13 minerals necessary for human life
The sentence "The quick brown fox jumps over the lazy dog." uses every letter in the alphabet. (Developed by Western Union to Test telex/twxcommunications)
The word housekeeping was invented by Shakespeare
The only two days of the year in which there are no professional sports games (MLB, NBA, NHL, or NFL) are the day before and the day after theMajorLeague All-Star Game.
In the great fire of London in 1666 half of London was burnt down but only 6 people were injured
Lack of sleep can affect your immune system and reduce your ability to fight infections
All dogs are the descendant of the wolf. These wolves lived in eastern Asia about 15,000 years ago
It is not possible to tickle yourself. The cerebellum, a part of the brain, warns the rest of the brain that you are about to tickle yourself. Since your brain knows this, it ignores the resulting sensation
Parma ham is only Parma ham if it is made in the Parma region of Italy. The British chain supermarket Asda, made and packaged its own "Parma ham" and was successfully sued by the real Parma ham people (Parma Ham Trade Association)
With winds of 50 miles per hour, The Statue of Liberty sways three inches and the torch sways five inches
A famous bullfighter, Lagarijo, killed 4,867 bulls in the 19th century.
Police detectives have used snapping turtles to help them locate dead bodies
In most advertisements, including newspapers, the time displayed on a watch is 10:10
The national sport of Japan is sumo wrestling
The early occurrence of a fetus yawning is at eleven weeks after conception
In a month, a fingernail grows an eighth of an inch
Edward VIII did not officially become the King of England as he abdicated the throne to marry an American divorcee
The book "Little Red Riding Hood" was banned in 1990 by two school districts in California. They did this because in the book there was a picture of a basket that had a bottle of wine in it
The reason why golf balls have dimples on them is because it helps in the ball to move a farther distance by reducing drag
Americans consume the most peanut butter in the world
Celtic warriors sometimes fought their battles naked, their bodies dyed blue from head to toe
To make butter more attractive in color, carrot juice was used by people in the Middle Ages
Early hockey games allowed as many as 30 players a side on the ice
Most fleas do not live past a year old
It takes seven to ten days to make a jelly belly jellybean
Some asteroids have other asteroids orbiting them
Maine is the only state whose name is just one syllable
The male praying mantis cannot copulate while its head is attached to its body. The female initiates sex by ripping the males head off
There is enough concrete in the Hoover Dam to pave a two lane highway from San Francisco to New York
Americans on the average eat 18 acres of pizza every day
Every 238 years, the orbits of Neptune and Pluto change making Neptune at times the farthest planet from the sun
There is a certain species of kangaroo that is only 2.5 centimeters long when it is born
In a lifetime, the average house cat spends approximately 10,950 hours purring
The real name of Toto the dog in "The Wizard Of Oz" was Terry
Stannous fluoride, which is the cavity fighter found in toothpaste is made from recycled tin
It takes 12 honeybees to make one teaspoon of honey
Thomas Watson, who was the chairman of IBM in 1943 predicted that their would probably only be a world market for five computers.
The largest hamburger cooked in the world weighed in at 6,040 pounds
The first lighthouse was in Alexandria in 290 B.C
Heinz first started making ketchup in 1876 and the recipe has remained the same ever since
The largest wedding chapel in Las Vegas is the Viva Las Vegas Chapel, which can seat 100 people
The most popular name for a pet in the United States is Max
Spiral staircases in medieval castles are running clockwise. This is because all knights used to be right-handed. When the intruding army would climb the stairs they would not be able to use their right hand which was holding the sword because of the difficulties of climbing the stairs. Left-handed knights would have had no troubles, except left-handed people could never become knights because it was assumed that they were descendants of the devil
The largest shopping mall in the world is the West Edmonton Mall located in Edmonton, Alberta, Canada
The CN Tower located in Toronto, Ontario Canada took a total construction time of 40 months to complete at an original cost of $63 million
The 20th president of the United States, James Garfield, was able to write Greek with one hand and Latin with the other at the same time
The country of Andorra has a zero percent unemployment rate
In Los Angeles, there are fewer people than there are automobiles
A woman has approximately 4.5 litres of blood in her body, while men have 5.6 litres
In India, pickled ginger, minced mutton and a cottage cheese like substance are popular pizza toppings
Oral-B were the first toothbrushes to go to the moon when they were aboard the Apollo 11 mission
A maple tree is usually tapped when the tree is at least 45 years old and has a diameter of 12 inches
In 1998, a law passed in the U.S. state of Virginia allows drivers to keep their road kill, as long as they report it within 12 hours. updated
A language becomes extinct in this world every two weeks
An acre of trees can remove about 13 tons of dust and gases every year from the surrounding environment
The decomposition point of Olive Oil is 220 degrees Celsius
Ten radishes only contain eight calories
Annually a thousand people are killed by scorpions in Mexico
Every year, 100 million sharks are killed by people
Tug of war was an Olympic event from 1900-1920
Of all the countries, Brazil has the most plant species, with over 56,000
One female mouse can produce up to 100 babies a year
Impotence is grounds for divorce in 26 U.S. states
Women who are romance novel readers are reported to make love 74% more often with their partners than women who do not read romance novels.
The average lifespan of a human taste bud is ten days
The monogram "RR" for Rolls-Royce has never been altered, except for when Sir Henry Royce passed away in 1933. Then it was changed from red to black.
People with darker skin will not wrinkle as fast as people with lighter skin
Fido means faithful in Latin
Pebbles cereal was actually named after the shape of the cereal and not the Pebbles Flintstone character
A group of kangaroos is called a mob
Cat's urine glows under a blacklight.
Every three seconds, a new baby is born
More than 260,000 people have been killed by volcanic activity since 1700 AD.
The only predator that polar bears have are humans
Many insects can carry 50 times their own body weight
The last land battle of the U.S. Civil War was fought in Texas
Annually 7 million tons of textiles and clothing is thrown out. Out of this, only 12% is used again or recycled
A scorpion can have up to 12 eyes
A snake charmer in Bangladesh once found 3,500 poisonous cobras and their eggs hidden underneath the floors of two suburban homes
The IRS employees tax manual has instructions for collecting taxes after a nuclear war
There are approximately fifty Bibles sold each minute across the world
The pectin that is found in apples aids in lowering cholesterol levels
Post-It Notes, which are adhesive notes, were invented while looking for a way to improve the acrylate adhesive found in tapes
Crayola Crayons currently has over 120 different crayon colors
Odontophobia is the fear of teeth
The width of a tornado can range from less than ten yards to more than a mile.
In Johannesburg, the average car will be involved in an accident once every four years.
The youngest actress to be nominated as best actress is Keisha Castle-Hughes who was nominated at just 13 years old
The Taj Mahal was actually built for use as a tomb
According to studies, an average roll of toilet paper lasts about five days in the bathroom
Almonds are members of the peach family
The oldest known disease in the world is leprosy
A fall of 30 feet can be survived my most cats
The largest member of the dolphin family are orcas
In 1477, the first diamond engagement ring was given to Mary of Burgundy by Archduke Maximillian of Austria
The hormone replacement drug "Premarin" is made from the urine of pregnant horses
TWIX Caramel Cookie Bars were first introduced in 1979
Nintendo was first establish in 1889 and they started out making special playing cards
People over the age of fifty will start to lose their dislike for foods that taste bitter
In Kentucky, 50 percent of the people who get married for the first time are teenagers
Elephants have been known to learn up to 60 commands
On average 1,668 gallons of water are used by each person in the United States daily
Copper is the second most used metal in the world.
Milton Bradley originally wanted to name the game Twister, Pretzel; but he could not since the name was copyrighted
According to studies, men prefer to have white bedrooms and women prefer to have blue bedrooms
If someone was to fly once around the surface of the moon, it would be equal to a round trip from New York to London
St. Patrick never really drove out any snakes from Ireland. This story was an analogy of how he drove paganism out of Ireland
Fat is important for the development of children and normal growth
The most common seasonings found in American homes are chili powder, cinnamon, and seasoned salts
People who have eaten beetles say that it tastes like apples
Montreal was named after a local mountain "Mont Royal."
Millie the White House dog earned more than 4 times as much as President Bush in 1991. And, rightfully so
In an average lifetime, a person will spend 4 years traveling in an automobile and six months waiting at a red light.
A small drip from a faucet can waste up to 50 gallons of water daily, which is enough water to run a dishwasher twice on a full cycle
Kotex was first manufactured as bandages, during W.W.I
The longest Monopoly game ever played was 1,680 hours long, which is seventy straight days
The first known contraceptive was crocodile dung, used by Egyptians in 2000 B.C
Over 1,600 people in North America have been victims of trunk entrapment (being locked inside of a car trunk)
A rhinoceros horn is made of compacted hair

28
sh/tests/file-researcher_test.sh

@ -1,28 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
FILENAME="student/file-researcher.sh"
# True if FILE exists and is a regular file
if [ -f ${FILENAME} ]; then
# FILE exists and it's not empty
if [ -s ${FILENAME} ]; then
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then
echo "echo is not allowed in this exercise!"
exit 1
fi
submitted=$(bash $FILENAME)
expected=$(bash solutions/file-researcher.sh)
diff <(echo "$submitted") <(echo "$expected")
else
echo "The file exist but is empty"
exit 1
fi
else
echo "File does not exist"
exit 1
fi

16
sh/tests/file-struct_test.sh

@ -1,16 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
print_content() {
mkdir -p uncompressed
tar -xpf file-struct.tar -C uncompressed
tree uncompressed
}
submitted=$(cd student && print_content)
expected=$(cd solutions && print_content)
diff <(echo "$submitted") <(echo "$expected")

0
sh/tests/find-files-extension/folder1/file1.txt

0
sh/tests/find-files-extension/folder1/file2.txt

0
sh/tests/find-files-extension/folder1/file3.txt

0
sh/tests/find-files-extension/folder1/test4.sh

0
sh/tests/find-files-extension/folder2/fileInsideAfolder4.txt

0
sh/tests/find-files-extension/folder2/test.sh

0
sh/tests/find-files-extension/folder2/testtxt/fileInsideAfolder5.txt

0
sh/tests/find-files-extension/folder2/testtxt/test/fileInsideAfolder6.txt

0
sh/tests/find-files-extension/folder2/testtxt/test/lol.sh

35
sh/tests/find-files-extension_test.sh

@ -1,35 +0,0 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
FILENAME="student/find-files-extension.sh"
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
submitted=$(cd "$1" && bash "$script_dirS"/$FILENAME)
expected=$(cd "$1" && bash "$script_dirS"/solutions/find-files-extension.sh)
diff <(echo "$submitted") <(echo "$expected")
}
# True if FILE exists and is a regular file
if [ -f ${FILENAME} ]; then
# FILE exists and it's not empty
if [ -s ${FILENAME} ]; then
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then
echo "echo is not allowed in this exercise!";
exit 1
fi
challenge find-files-extension/folder1
challenge find-files-extension/folder2
else
echo "The file exist but is empty"
exit 1
fi
else
echo "File does not exist"
exit 1
fi

0
sh/tests/find-files/folder2/aa/ba/ab

0
sh/tests/find-files/folder2/aa/ba/bz

0
sh/tests/find-files/folder2/alphabet

0
sh/tests/find-files/folder2/ba/aa/alphabetz!

0
sh/tests/find-files/folder2/ba/aa/cz

0
sh/tests/find-files/folder2/ba/aa/za!

0
sh/tests/find-files/folder2/ba/alphabetz

Some files were not shown because too many files changed in this diff diff.show_more

Loading…
Cancel
Save