forked from root/public
Augusto
3 years ago
122 changed files with 1937 additions and 518 deletions
@ -1,29 +0,0 @@
|
||||
# BIOS Configuration |
||||
|
||||
## Steps |
||||
|
||||
<kbd>F10</kbd> (Open Setup) |
||||
|
||||
- _Security_ |
||||
- _Create BIOS Administrator Password_ → Set password |
||||
- _Advanced_ |
||||
- _Boot Options_ |
||||
- _USB Storage Boot_ → Disabled |
||||
- _Fast Boot_ → Disabled (disturbs network boot) |
||||
- _Audio Alerts During Boot_ → Disabled (very noisy) |
||||
- _HP Sure Recover_ |
||||
- _HP Sure Recover_ → Disabled (tries to restore Windows) |
||||
- _Secure Boot Configuration_ |
||||
- _Configure Legacy Support and Secure Boot_ → «Legacy Support Disable and Secure Boot Disable» (**TODO**: use Secure Boot) |
||||
|
||||
<kbd>F10</kbd> → Yes (Save changes & Reboot) |
||||
|
||||
> Enter the code that the BIOS asks to disable the secure boot |
||||
|
||||
## Automation |
||||
|
||||
- Can be automated using Intel vPro/AMT (**TODO**) |
||||
- Can be partially automated with a USB programmable keyboard such as : |
||||
- [USB Rubber Ducky](https://shop.hak5.org/products/usb-rubber-ducky-deluxe) |
||||
- [XK-24 USB Programmable Keypad for Windows or Mac](https://www.amazon.com/gp/product/B003MB780E) |
||||
- [Cactus WHID: WiFi HID Injector USB Rubberducky](https://www.tindie.com/products/aprbrother/cactus-whid-wifi-hid-injector-usb-rubberducky/) |
@ -0,0 +1,299 @@
|
||||
# Schema Public |
||||
|
||||
## Tables |
||||
|
||||
### audit |
||||
|
||||
Some exercises require reviews from other students or any other member of the school. The reviewer checks that some conditions are met by the code of the student being reviewed. This process is called an `audit` and it's kept in this table. |
||||
|
||||
Columns: |
||||
- id. |
||||
- groupId: The group that the audit refers to. |
||||
- auditorId: The user who's making the audit. |
||||
- attrs: The attributes of the audits keep the feedback of the auditor for each question failed. |
||||
- grade: A floating point number with the ratio between questions required to pass and questions approved. (Less than 1 means failed. More or equal than 1 means passed. More than 1 means that the student had bonus questions correct). |
||||
- createdAt: The timestamp of the time and date of creation. |
||||
- updatedAt: The timestamp of the last update. |
||||
- code: The code that must be used by the auditor to start the audit. This code is set to null after the audit is expired. |
||||
- resultId: The result of the audit. `resultId` is filled when the group has enough audits to validate or fail a project - that means that while it's not filled, audits are still "doable" (if no grade, so not done), and then after they are not needed anymore |
||||
- version: A sha of the commit that the audit refers to. |
||||
- endAt: It is used for expiration date (after this date the audit is expired). |
||||
- private: Used to access the code by the auditor. |
||||
|
||||
### discordToken (TODO: remove) |
||||
|
||||
Columns: |
||||
- id |
||||
- accessToken |
||||
- refreshToken |
||||
- expiresAt |
||||
|
||||
### event |
||||
|
||||
An event anchors an objects into time. |
||||
> Note: Some [object attributes](attributes.md) are related to time, but they express time only in relative terms to the beginning of the event. |
||||
> Also, live edits (i.e., editing an event while is ongoing) it's not supported. The changes will only take effect after reloading the page. |
||||
|
||||
Columns: |
||||
- id |
||||
- createdAt: The timestamp of the creation of the event. |
||||
- endAt: The timestamp for the end of the event. |
||||
- registrationId: The registration to the event. |
||||
- objectId: The object that is used to generate the event. |
||||
- parentId: The immediate event ancestor. The parent event. |
||||
- status: Confirmation that the event finished correctly (NULL or done for now). |
||||
- path: The path of the event (the relative url of the event). |
||||
- campus: The campus that contains the event. |
||||
- code: Used to unlock the exams. |
||||
|
||||
### event_user |
||||
|
||||
This table links users and events. A user can be in many events and an events have many users. |
||||
|
||||
Columns: |
||||
- id |
||||
- createdAt |
||||
- userId |
||||
- eventId |
||||
|
||||
### group |
||||
|
||||
Some projects are required to be made by groups. Those groups are kept in this table. |
||||
|
||||
Columns: |
||||
- id |
||||
- objectId: The object that is being "done" by the group. Usually projects or raids. |
||||
- eventId : The groups only exist in relation to an event |
||||
- captainId: The captain of the group. |
||||
- createdAt. |
||||
- updatedAt. |
||||
- status: See [group_status](#group_status) for possible values. |
||||
- path. |
||||
- campus. |
||||
|
||||
### group_status |
||||
|
||||
Columns: |
||||
- status |
||||
Possible values (for now) |
||||
- `setup` |
||||
- `working` |
||||
- `audit` |
||||
- `finished` |
||||
|
||||
### group_user |
||||
|
||||
This table links users to groups. A user can be in many groups and a group contains many users. |
||||
|
||||
Columns: |
||||
- id |
||||
- userId |
||||
- groupId |
||||
- confirmed: Boolean. False by default. True after the user represented by the user id confirms the group. |
||||
- createdAt |
||||
- updatedAt |
||||
|
||||
### match |
||||
|
||||
It is used for the `bet` system in the bonus exercises. Specifically to keep a record of the matches between students who will review and make a bet about each others code. |
||||
|
||||
Columns: |
||||
- id |
||||
- createdAt |
||||
- updatedAt |
||||
- objectId: The object that requires the match. |
||||
- userId: The user that is matched. |
||||
- matchId: The matched that is made to another user. |
||||
- confirmed: The same as in group_user it's a way to keep track of invitations that had not been confirmed. |
||||
- bet: boolean; For the optional exercises that require a bet. A bet can be true if the exercises is expected to pass and false otherwise. |
||||
- result: boolean; True for correct bet. |
||||
- path |
||||
- campus |
||||
- eventId: The event the object in inserted in. (Piscine, Raid, etc). |
||||
|
||||
### object |
||||
|
||||
Objects are generic representations of elements in the structure of the curriculum (Onboarding, campus, piscine, raids, etc). They are arranged in a hierarchical structure to allow unlimited nesting (see [object_child](#object_child)). They also keep the timeline of the events relaying in durations (ex. `duration`, `eventDuration`, etc) specified by [attributes](attributes.md) (`attrs`). |
||||
|
||||
Columns: |
||||
- id |
||||
- name |
||||
- type: |
||||
- `onboarding` |
||||
- `campus` |
||||
- `exercise` |
||||
- `quest` |
||||
- `signup` |
||||
- `exam` |
||||
- `raid` |
||||
- `project` |
||||
- `piscine` |
||||
- status: (Currently not in used, but it should always be `online` to avoid errors TODO: remove at some point). |
||||
- `online` |
||||
- `offline` |
||||
- `draft` |
||||
- attrs: See [object attributes](attributes.md). |
||||
- childrenAttrs: Attributes that are applied to all the children objects. |
||||
- createdAt |
||||
- updatedAt |
||||
- externalRelationUrl (Maybe not needed). |
||||
- authorId (Maybe not needed). |
||||
- campus: The campus the object is related to. |
||||
- referenceId: If the object is a duplication this field points to the reference object. |
||||
- referencedAt: The timestamp of the creation of the copy object. |
||||
|
||||
### object_child |
||||
|
||||
It keeps a child-parent relationship between two objects. It's used to encapsulate objects inside each other. |
||||
|
||||
Columns: |
||||
- id |
||||
- parentId |
||||
- childId |
||||
- attrs |
||||
- key: When generating the JS object this field will be the `key` of the child. It is also used in the url. |
||||
- index: Defines the position of the child object inside the parent object. |
||||
|
||||
### progress |
||||
|
||||
It is a register of the steps in the progression of students doing the exercises and projects. |
||||
|
||||
Columns: |
||||
- id |
||||
- createdAt |
||||
- updateAt |
||||
- userId |
||||
- groupId |
||||
- eventId |
||||
- version: the sha of the last commit |
||||
- grade: is the average of the grades of the results related to this progress if several exist. |
||||
- isDone: set to trure as soon as a user fails a validation or when all validations required are done. |
||||
- path |
||||
- campus |
||||
- objectId |
||||
|
||||
### record |
||||
|
||||
Keeps a register for the bans. It can also keep the record of other situations, this is done by setting the banEndAt to a date already passed and the reason for the record. |
||||
|
||||
Columns: |
||||
- id |
||||
- userId |
||||
- authorId |
||||
- message |
||||
- banEndAt |
||||
- createdAt |
||||
|
||||
### registration |
||||
|
||||
Registrations to events (For example, an exam). |
||||
|
||||
Columns: |
||||
- id |
||||
- createdAt, When the registration was created. |
||||
- startAt, When users can start registering to an event. |
||||
- endAt, When the registration ends. |
||||
- eventStartAt, Event at which the event will be started (and as such created). Event don't exist only when they start |
||||
- objectId, The object the registration refers to. |
||||
- parentId, The parent object of the object the registration refers to. |
||||
- attrs |
||||
- path |
||||
- campus |
||||
|
||||
### registration_user |
||||
|
||||
The user registered to events. A user can register to many events and and event can have many users. |
||||
|
||||
Columns: |
||||
- id |
||||
- registrationId |
||||
- userId |
||||
- createdAt |
||||
|
||||
### result |
||||
|
||||
The result for each exercise and project made in the platform. |
||||
|
||||
Columns: |
||||
- id |
||||
- createdAt |
||||
- updatedAt |
||||
- grade |
||||
- attrs |
||||
- type: |
||||
- `tester` |
||||
- `user_audit` |
||||
- `admit_audit` |
||||
- `admin_selection` |
||||
- `status` |
||||
- userId |
||||
- groupId |
||||
- objectId |
||||
- path |
||||
- version, The version of the code the result refers to. |
||||
- eventId |
||||
- isLast, Used to represent transitory states. A progress is only considered finished when `isLast` is `true`. |
||||
- campus |
||||
|
||||
### role |
||||
|
||||
Columns: |
||||
- id |
||||
- slug |
||||
- name |
||||
- description |
||||
- createdAt |
||||
- updatedAt |
||||
|
||||
### token |
||||
|
||||
Columns: |
||||
- id |
||||
- status |
||||
- `active` |
||||
- `expired` |
||||
- createdAt |
||||
- updatedAt |
||||
|
||||
### transaction |
||||
|
||||
It's a register of the rewards given to students. |
||||
|
||||
Columns: |
||||
- id |
||||
- type: |
||||
- `xp`: transaction giving xp |
||||
- `up`: transaction correspondent to reviewing someone |
||||
- `down`: transaction correspondent to reviewing you |
||||
- amount: |
||||
- type = xp; The amount of Xp that an object rewards. |
||||
- type = up || down; a percentage of the change (10%); |
||||
- userId |
||||
- attrs |
||||
- createdAt |
||||
- path |
||||
- objectId |
||||
- eventId |
||||
- campus |
||||
|
||||
### user |
||||
|
||||
Columns: |
||||
- id |
||||
- githubId: (deprecated). |
||||
- githubLogin: alias -> login. |
||||
- discordId: depracated (TODO: remove) |
||||
- discordLogin: depracated (TODO: remove) |
||||
- profile |
||||
- attrs: Extra information about the users (email, address, etc). |
||||
- createdAt |
||||
- updateAt |
||||
- discordDMChannelld: depracated (TODO: remove) |
||||
- campus |
||||
|
||||
### user_role |
||||
|
||||
Columns: |
||||
- id |
||||
- userId |
||||
- roleId |
@ -0,0 +1,225 @@
|
||||
# DB authorization |
||||
|
||||
Every request to Hasura executes against a set of session variables. Normally there are some main variables for the authorization context: |
||||
|
||||
- `X-Hasura-User-Id`: this variable usually denotes the user executing the request. |
||||
|
||||
- `X-Hasura-Role`: This variable denotes the role with which the user is executing the current request. Hasura has a built-in notion of a role, and will explicitly look for this variable to infer the role. |
||||
|
||||
- `X-Hasura-campuses`: this variable contains the campus that the user currently is on. |
||||
|
||||
In our database we have several roles which are simple arbitrary names. |
||||
Each role can be given a set of permissions and actions (`select`, `insert`, `update`, `delete`). That will execute against each table of the database. |
||||
|
||||
Example: |
||||
|
||||
To give the user with a certain role a permission to make a request, we must set a permission rule that would look something like this: |
||||
|
||||
```json |
||||
{ "user_id": { "_eq": "X-Hasura-User-Id" } } |
||||
``` |
||||
|
||||
This is the same as saying : if the value of the `user_id` column equals the value of the session variable `X-Hasura-User-Id`, it allows this request to execute on the current row and get information on that user id. |
||||
|
||||
## Roles |
||||
|
||||
These are the roles presented in the database: |
||||
|
||||
- `anonymous`: this role allows non logged in users to query tables (only using the `select` action): |
||||
|
||||
- `users` : columns `id`, `login` |
||||
- `object` : columns `id`, `childAttr`, `campus`, `name`, `type` |
||||
- `result` : columns `groupId`, `objectId`, `progressId`, `userId`, `grade`, `campus` |
||||
- `transactions` : columns `objectId`, `userId`, `amount`, `type` |
||||
- `progress` : columns `isDone`, `objectId`, `userId`, `id`, `grade`, `campus` |
||||
|
||||
--- |
||||
|
||||
- `user` : this role allows the following queries: |
||||
|
||||
- `selects` action: |
||||
|
||||
- without permission rules: |
||||
|
||||
- `event_user` |
||||
- `group` |
||||
- `group_user` |
||||
- `match` |
||||
- `registration_user` |
||||
- `event` |
||||
- `object` |
||||
- `object_child` |
||||
- `object_status` |
||||
- `object_type` |
||||
- `registration` |
||||
- `role` |
||||
- `transaction_type` |
||||
- _`event_user_view`_ |
||||
- _`object_children_view`_ |
||||
- _`registration_user_view`_ |
||||
- _`user_public_view`_ |
||||
|
||||
- with permission rules: |
||||
- `audit`, the user only can query this table if the user id from the `X-Hasura-User-Id` variable is equal to one of the `members`, or the `auditorId`. |
||||
- `result`, the user only can query this table if the `X-Hasura-User-Id` is equal to the `userId` or one of the members from their group. |
||||
- `transaction`, this table can be queried by users if the `X-Hasura-User-Id` is equal to the `userId`. |
||||
- `record`, the same applies to this table and the tables below. |
||||
- `progress` |
||||
- `user_role` |
||||
- `user`, the same applies to this table but with the `id`. |
||||
- _`user_role_view`_ |
||||
- _`audit_private`_ |
||||
- _`progress_by_path_view`_ |
||||
- _`progress_view`_ |
||||
- _`xp`_ |
||||
- _`xp_by_event`_ |
||||
- _`xp_by_path`_ |
||||
|
||||
--- |
||||
|
||||
- `campus-admin` : this role allows users to query every table, but with the variables `X-Hasura-campus` checked (campus check). This means that users with this role will only be able to query information from their own campus. Example: a user in campus `madere` can only query the content associated to that campus. The following tables can be queried: |
||||
|
||||
- `select` action: |
||||
- without permission rules: |
||||
- `group_status` |
||||
- `object_status` |
||||
- `object_type` |
||||
- `result_type` |
||||
- `role` |
||||
- `transaction_type` |
||||
- `user_role` |
||||
- _`user_public_view`_ |
||||
- _`user_role_view`_ |
||||
- with permission rules: |
||||
- `event_user` |
||||
- `audit` |
||||
- `group` |
||||
- `group_user` |
||||
- `match` |
||||
- `object` |
||||
- `event` |
||||
- `progress` |
||||
- `record` |
||||
- `registration` |
||||
- `registration_user` |
||||
- `result` |
||||
- `transaction` |
||||
- `user` |
||||
- _`progress_by_path_view`_ |
||||
- _`audit_private`_ |
||||
- _`event_user_view`_ |
||||
- _`event_with_results_ready_view`_ |
||||
- _`progress_view`_ |
||||
- _`registration_user_view`_ |
||||
- _`registration_with_event_ready_view`_ |
||||
- _`toad_result_view`_ |
||||
- _`xp_by_event`_ |
||||
- _`xp_by_path`_ |
||||
|
||||
--- |
||||
|
||||
- `campus-admin-read-only` : this role allows users to query almost all tables (only using the `select` action). But with the same permission rule in the `campus-admin`. The following tables can be queried: |
||||
|
||||
- without permission rules: |
||||
- `group_status` |
||||
- `object_status` |
||||
- `object_type` |
||||
- `result_type` |
||||
- `role` |
||||
- `transaction_type` |
||||
- `user_role` |
||||
- _`user_public_view`_ |
||||
- _`user_role_view`_ |
||||
- with permission rules: |
||||
- `event_user` |
||||
- `audit` |
||||
- `group` |
||||
- `group_user` |
||||
- `match` |
||||
- `object` |
||||
- `event` |
||||
- `progress` |
||||
- `record` |
||||
- `registration` |
||||
- `registration_user` |
||||
- `result` |
||||
- `transaction` |
||||
- `user` |
||||
- _`progress_by_path_view`_ |
||||
- _`audit_private`_ |
||||
- _`event_user_view`_ |
||||
- _`event_with_results_ready_view`_ |
||||
- _`progress_view`_ |
||||
- _`registration_user_view`_ |
||||
- _`registration_with_event_ready_view`_ |
||||
- _`toad_result_view`_ |
||||
- _`xp_by_event`_ |
||||
- _`xp_by_path`_ |
||||
|
||||
--- |
||||
|
||||
- `admin-read-only` : this role allows users to query all tables only using the `select` action. |
||||
|
||||
--- |
||||
|
||||
- `admin` : this role allows users to query using any action in any table on the database. |
||||
|
||||
> You can see more about each role by going to the [graphiql](https://((DOMAIN))/graphiql) in the docs section. Note that you must be logged in with the user role you desire to see. For the role `anonymous` you do not need to be logged in. If you want to see the possible tables that can be queried by an admin, you must login with an admin, and so on... |
||||
|
||||
A role is given by default to every user, if an user has more roles, the highest would be taken by default when login. |
||||
|
||||
This table can describe the permissions for each table of the database and each user role. |
||||
|
||||
✅ : with permission rules\ |
||||
🟩 : without permission rules\ |
||||
❌ : not allowed\ |
||||
S : select\ |
||||
U : update\ |
||||
I : insert\ |
||||
D : delete |
||||
|
||||
| tables | `anonymous` | `user` | `campus-admin` | `campus-admin-read-only` | `admin` | `admin-read-only` | |
||||
| :--------------------------------- | :------------------------------ | :------------------------------ | :------------------------------ | :------------------------------ | :------------------------------ | ------------------------------- | |
||||
| | S  U  I  D  | S  U  I  D  | S  U  I  D  | S  U  I  D  | S  U  I  D  | S  U  I  D  | |
||||
| event_user | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| audit | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| group | ❌ ❌ ❌ ❌ | 🟩 ✅ ✅ ✅ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| group_user | ❌ ❌ ❌ ❌ | 🟩 ✅ ✅ ✅ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| match | ❌ ❌ ❌ ❌ | 🟩 ✅ ✅ ✅ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| progress | 🟩 ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| record | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| registration_user | ❌ ❌ ❌ ❌ | 🟩 ❌ ✅ ✅ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| result | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| transaction | 🟩 ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| user | 🟩 ❌ ❌ ❌ | ✅ 🟩 ❌ ❌ | ✅ ✅ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| audit_expired_view | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| audit_private | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| discordToken | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| event | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| event_user_view | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| object | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| event_with_results_ready_view | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| group_status | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| job | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| match_to_remove_view | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ✅ ✅ ✅ | ❌ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| object_child | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ❌ ✅ ✅ ✅ | ❌ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| object_children_view | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| object_status | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| object_type | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| progress_by_path_view | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| progress_view | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| registration | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| registration_user_view | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| registration_with_event_ready_view | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| result_type | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| role | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| toad_result_view | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| token | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| token_status | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| transaction_type | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| user_public_view | ❌ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| user_role | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| user_roles_view | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | 🟩 ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| xp | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ❌ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| xp_by_event | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
||||
| xp_by_path | ❌ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ❌ ❌ ❌ | ✅ ✅ ✅ ✅ | ✅ ❌ ❌ ❌ | |
@ -0,0 +1,192 @@
|
||||
# Database Relations |
||||
|
||||
## Entity Relationship Diagram ERD |
||||
|
||||
An entity relationship diagram (ERD) shows the relationships of entity and sets stored in a database. |
||||
|
||||
An entity in this context is a table, this table contains a set of attributes, they can be of any data structure (INT, TEXT, ...). |
||||
|
||||
An entity can have several relations to other entities. Those relations are represented with "crow foots" |
||||
|
||||
### Relationships cardinality |
||||
|
||||
Relationships have a cardinality, normally they have two indicators that are shown on both sides of the line. |
||||
|
||||
1. One end of the line, refers to the **max** number of times that an instance of one entity can be associated with instances in the related entity. It can be **one**, **many** or **none** |
||||
|
||||
2. The second, describes the **min** number of times one instance can be related to others. |
||||
It can be **zero** or **mandatory** |
||||
|
||||
The combination of those two indicators create relations, you can get more information [here](https://community.mis.temple.edu/mis3506digitaldesignfall2018/files/2018/10/Adam-Alalouf_Cardinality.pdf) |
||||
|
||||
![alt text](../img/db/db-relations.jpg "hierarchical roles") |
||||
|
||||
## Relations |
||||
|
||||
### Events |
||||
|
||||
Events will be the accumulation of the following tables : |
||||
|
||||
- `event` |
||||
- `registration` |
||||
- `registration_user` |
||||
- `event_user` |
||||
|
||||
This part of the database takes care of schools activities with time. |
||||
|
||||
The `event` table contains the following relations: |
||||
|
||||
- `parentId` that is associated to himself. This association can be better explained if we take a look at the `path` column. An event can be based on a parent event (ex: the event `/madere/div-01/piscine-rust` is associated to this parent event `/madere/div-01`). |
||||
|
||||
- `registrationId` that is associated to the `registration` table. This is a one to one relations, meaning that an event must always have a registration associated to it. |
||||
|
||||
- `objectId` that is associated to the `object` table, this column will identify which object is associated to which event. An object can have multiple events, but an event must always be associated to an object. (it will never exist an event where the `objectId` is `null`) |
||||
|
||||
--- |
||||
|
||||
The `event_user` contains the associations between events and users. This will contain information on which users are registered to which event. An event can have multiple users and a user can have multiple events, this way being a many to many relationship. |
||||
|
||||
--- |
||||
|
||||
The `registration` table contains all objects/activities that need registration. Having the following relations: |
||||
|
||||
- `parentId` that is associated to himself. As said above (in the events), it has the same use. |
||||
- `objectId` that is associated to the object table, this is the object reference to the registrations. |
||||
|
||||
--- |
||||
|
||||
The `registration_user` table is a relationship many to many between `registration` and `user`. This table contains all users that are registered to an event. |
||||
|
||||
- `registrationId` a registration can have multiple users. |
||||
- `userId` a user can have multiple registrations. |
||||
|
||||
--- |
||||
|
||||
### Objects |
||||
|
||||
Object will be the accumulation of the following tables : |
||||
|
||||
- `object` |
||||
- `object_child` |
||||
- `object_status` |
||||
- `object_type` |
||||
|
||||
This part of the database defines the structure of the content. |
||||
|
||||
The `object` table contains the following relations: |
||||
|
||||
- `referenceId` that is associated to himself, this attribute allows the duplication of reference objects (given by **01-edu**), that are used to set up campuses |
||||
- `authorId` that is associated to the user table and this is the author of that object/content. |
||||
|
||||
--- |
||||
|
||||
The `object_child` table contains the encapsulation of objects. An object can have multiple children and a child must have one object parent. Note that one parent can't be associated two times to children with the same key. This table contains the following relationships to the object table: |
||||
|
||||
- `parentId` that associates the parent object to the child object. |
||||
- `childId` that belongs to the parent object. |
||||
|
||||
Both child and parent must have at least one association to the `object` table, and the `object` table can have multiple relations with the `object_child` table. |
||||
|
||||
Example: |
||||
|
||||
Campus `madeira` is a **parent object** of `piscine-go`, therefore the later one is the **child**. |
||||
|
||||
But `piscine-go` can be the **parent object** of all the quest, exams and raids (those being the **child objects**). And so on... creating a finite cycle. |
||||
|
||||
--- |
||||
|
||||
### Users |
||||
|
||||
Users will be the accumulation of the following tables: |
||||
|
||||
- `role` |
||||
- `user_role` |
||||
- `user` |
||||
- `group` |
||||
- `group_user` |
||||
- `token` |
||||
- `record` |
||||
- `transaction` |
||||
|
||||
--- |
||||
|
||||
The `role` table contains permission roles for each user. |
||||
|
||||
--- |
||||
|
||||
The `user_role` contains information on which users are associated to which role. A user can have multiple roles and a role can be associated to multiple users. |
||||
|
||||
--- |
||||
|
||||
The `group` table is the link between projects or raids and a group of users. This table contains the following relations: |
||||
|
||||
- `eventId` that associates which group is related to which event. |
||||
- `captainId` that associates the captain's user. |
||||
- `objectId` that associates which group is related to which object. |
||||
|
||||
--- |
||||
|
||||
The `group_user` table contains the relation between groups and users. A group can have several users and so do the users. |
||||
|
||||
--- |
||||
|
||||
The `token` table stores the tokens ids from the hasura authorization variables for each user. This table has no relation between other tables. |
||||
|
||||
--- |
||||
|
||||
The `record` table takes care of students records (bans). All relations in this table are with the table user. |
||||
|
||||
--- |
||||
|
||||
The `transaction` table takes care of rewarding the user, by accumulating the user's **xp** , **up** and **down** (you can see more information about those types in the `database-structure.md`). This table contains the following relations: |
||||
|
||||
- `userId` that represents the user rewarded |
||||
- `eventId` that associates the event in which the user was rewarded. Example: the user can be rewarded for an exercise `/madere/piscine-go/quest-01/make-it-better` and the parent event of that exercise will be `/madere/piscine-go`. |
||||
- `objectId` that associates the object in which the user was rewarded. Example: if a user passes an exercise (object), the reward will be associated to that object. |
||||
|
||||
--- |
||||
|
||||
#### Results |
||||
|
||||
Results will be the accumulation of the following tables: |
||||
|
||||
- `audit` |
||||
- `match` |
||||
- `progress` |
||||
- `result` |
||||
|
||||
This part of the database defines the users/students progress in the school. |
||||
|
||||
The `audit` table contains all information related to the audit system and it is one of the ways of obtaining results. This table contains the following relations: |
||||
|
||||
- `groupId` that associates the group being audited. |
||||
- `auditorId` as the name says, it is linked to the user table and has a relation of many to one. This column will be the auditor. |
||||
- `resultId` that associates the audit to the result. An audit can have one or no results (pending on the auditor review). While the results must have at least one audit. |
||||
|
||||
--- |
||||
|
||||
The `match` table is another way of obtaining a result. This table is used in bonus exercises to match two students. The following relations are established: |
||||
|
||||
- `userId` this will be the user wanting the match to happen. |
||||
- `matchId` this is a self related id, a match can be made by matching other students or it can be none. If the latter is none it means that the student is waiting for the match, otherwise it is a match. |
||||
- `eventId` that associates the event to the current match. Example: a user can be waiting for the exercise `/madere/piscine-go/quest-01/teacher` that is located in the `/madere/piscine-go` event. |
||||
- `objectId` that associates the object to the current match, this being the bonus exercise that the user is doing. |
||||
|
||||
--- |
||||
|
||||
The `progress` table is the reflection of user's activity on specific path: registration to an event related, commitment to a group associated to this path, generation of result expected to validate a progress on this path. |
||||
|
||||
- `userId` that associates an user with a progress. A progress must always have a user associate to it and a user can or cannot have multiple progresses. |
||||
- `groupId` this association allows each user form a group to have progress. This is a many to none or one connection, meaning that a progress can have none or one group and a group can have multiple progresses. |
||||
- `eventId` that associates which event the user has progressed on. |
||||
- `objectId` that associates which object the user has progressed on. |
||||
- `version` is the association between the `progress` and the `result` table |
||||
|
||||
--- |
||||
|
||||
The `result` table keeps the track of students result. The following relations are established: |
||||
|
||||
- `userId` that associates an user with a result. An user can have multiple results but a result is associated to just one user. |
||||
- `groupId` that associates a group with a result. The same logic as in the `userId` |
||||
- `objectId` that associates an object with a result. A result must have always a object associated to it and an object can have multiple results |
||||
- `eventId` that associates an event with a result. The same logic as in the `objectId` |
@ -0,0 +1,257 @@
|
||||
# Examples of graphql (queries) |
||||
|
||||
> Note: that all queries present here can be ran in your own school. For this you must login with an admin role and access the following route <https://((DOMAIN))/graphiql>. Depending on our role the tables permissions may differ. |
||||
|
||||
## Simple queries to get info |
||||
|
||||
- The following query returns the basic information of a given user : |
||||
|
||||
```graphql |
||||
query getUserInfo($name: String!) { |
||||
user(where: {login: {_eq: $name}}) { |
||||
profile |
||||
login |
||||
attrs |
||||
auditRatio |
||||
campus |
||||
createdAt |
||||
totalDown |
||||
totalUp |
||||
updatedAt |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Query variable: |
||||
|
||||
```graphql |
||||
{"name": "Joao"} |
||||
``` |
||||
|
||||
--- |
||||
|
||||
- The following query returns the list of all records of a given user (including the finished ones), the output would be : |
||||
- author of the record |
||||
- the time that the record was created and will end |
||||
- message/reason for the ban |
||||
|
||||
```graphql |
||||
query bannedUsers($name: String!) { |
||||
record(where: {user: {login: {_eq: $name}}}) { |
||||
authorLogin |
||||
banEndAt |
||||
createdAt |
||||
message |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Query variable: |
||||
|
||||
```graphql |
||||
{"name": "Joao"} |
||||
``` |
||||
|
||||
--- |
||||
|
||||
- The following query returns a list of groups given the path `name`. The output will be the `captainLogin` and the `userLogin` from all the members of that group. |
||||
|
||||
```graphql |
||||
query getGroupInfo($object: String!) { |
||||
group(where: {object: {name: {_eq: $object}}}) { |
||||
captainLogin |
||||
path |
||||
status |
||||
members { |
||||
userLogin |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Query variable: |
||||
|
||||
```graphql |
||||
{"path": "/madere/div-01/go-reloaded"} |
||||
``` |
||||
|
||||
--- |
||||
|
||||
- The following query returns all events in a given campus, the output for this query will be the: |
||||
- object name |
||||
- path of the event |
||||
- parent event (this will be the parent event of the given child event) |
||||
|
||||
```graphql |
||||
query eventsByCampus($campus: String!) { |
||||
event(where: {campus: {_eq: $campus}}) { |
||||
object { |
||||
name |
||||
} |
||||
parent { |
||||
path |
||||
object { |
||||
name |
||||
} |
||||
createdAt |
||||
endAt |
||||
path |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Query variable: |
||||
|
||||
```graphql |
||||
{ "campus": "madere" } |
||||
``` |
||||
|
||||
--- |
||||
|
||||
- The following query returns information of users that are associated to an event. For the query to work it should be given two arguments : `campus` and the `path`. The output will be the user name/login, audit ratio and the event info. |
||||
|
||||
```graphql |
||||
query usersEvent($campus: String!, $path: String!) { |
||||
event_user(where: {event: {path: {_eq: $path}, _and: {campus: {_eq: $campus}}}}) { |
||||
userAuditRatio |
||||
userLogin |
||||
event { |
||||
path |
||||
object { |
||||
name |
||||
} |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Query variable: |
||||
|
||||
```graphql |
||||
{"campus": "madera", "path": "/madere/div-01/piscine-js"} |
||||
``` |
||||
|
||||
- If we wanted to filter the users that were registered to a type of object in the event, we would just need to filter the object by `type` instead of filtering using the `path`. Should look something like this: |
||||
|
||||
```graphql |
||||
query usersEvent($campus: String!, $objectType: String!) { |
||||
event_user(where: {event: {object: {type: {_eq: $objectType}}, _and: {campus: {_eq: $campus}}}}) { |
||||
userAuditRatio |
||||
userLogin |
||||
event { |
||||
path |
||||
object { |
||||
name |
||||
} |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Query variable: |
||||
|
||||
```graphql |
||||
{"campus": "pyc", "objectType": "raid"} |
||||
``` |
||||
|
||||
--- |
||||
|
||||
- The following query returns the current `XP` of a given user, the output should be the `amount` that this user should have |
||||
|
||||
```graphql |
||||
query xp($name: String!) { |
||||
xp(where: {user: {login: {_eq: $name}}}) { |
||||
user { |
||||
login |
||||
} |
||||
amount |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Query variable: |
||||
|
||||
```graphql |
||||
{"name": "Joao"} |
||||
``` |
||||
|
||||
- If we wanted to filter all `XP` gain from an user from a given object, it would look something like this: |
||||
|
||||
```graphql |
||||
query eventXp($userName: String!, $objectName: String!) { |
||||
xp_by_path(where: {user: {login: {_eq: $userName}}, _and: {object: {name: {_eq: $objectName}}}}) { |
||||
path |
||||
user { |
||||
login |
||||
} |
||||
event { |
||||
path |
||||
} |
||||
object { |
||||
name |
||||
} |
||||
amount |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Query variable: |
||||
|
||||
```graphql |
||||
{"userName": "Joao", "objectName": "ascii-art"} |
||||
``` |
||||
|
||||
--- |
||||
|
||||
- The following query gives information relevant to the onboarding games, This view will. |
||||
|
||||
```graphql |
||||
query getGameInfo($name: String!) { |
||||
toad_result_view(where: {user: {login: {_eq: $name}}}) { |
||||
user { |
||||
login |
||||
} |
||||
attempts |
||||
allowedAttempts |
||||
score |
||||
path |
||||
games |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Query variables: |
||||
|
||||
```graphql |
||||
{"name": "Joao"} |
||||
``` |
||||
|
||||
--- |
||||
|
||||
- The following query returns information about the progress of a given user in a specific path. |
||||
|
||||
```graphql |
||||
query getProgress($name: String!, $path: String!) { |
||||
progress(where: {user: {login: {_eq: $name}}, _and: {path: {_eq: $path}}}) { |
||||
path |
||||
grade |
||||
isDone |
||||
campus |
||||
group { |
||||
captainLogin |
||||
members { |
||||
user { |
||||
login |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
query variable: |
||||
|
||||
```graphql |
||||
{"name": "Joao", "path": "/madere/piscine-go/exam-01" } |
||||
``` |
After Width: | Height: | Size: 666 KiB |
@ -1,21 +0,0 @@
|
||||
# Object Attribute Reference |
||||
|
||||
## List all **USABLE** preset object attributes |
||||
|
||||
| Attribute | Type | Value | Description | |
||||
| ----------------- | -------- | ---------------------------------------------------------------------- | ------------------------------------------------------- | |
||||
| `xp` | function | `exerciceExpCalculation`, `examExpCalculation` or `raidExpCalculation` | Amount of experience points that an object will give. | |
||||
| `correctionPrice` | function | `correctionPrice` | Amount of correction points needed to test an exercise. | |
||||
| `duration` | number | | | |
||||
| `time` | string | | | |
||||
| `info` | object | | | |
||||
|
||||
## List all **RESERVED** preset object attributes |
||||
|
||||
| Attribute | Type | Value | Description | |
||||
| ------------ | -------- | ----- | ----------- | |
||||
| `scopeStart` | function | | | |
||||
| `scopeEnd` | function | | | |
||||
| `startDay` | function | | | |
||||
| `status` | function | | | |
||||
| `week` | function | | | |
@ -1,30 +0,0 @@
|
||||
# OS Deployment |
||||
|
||||
## Image creation steps |
||||
|
||||
- [Installation of Ubuntu](ubuntu-installation.md) |
||||
- minimal OS installation (downloads ~200 MB) |
||||
- Software installation (downloads ~900 MB) |
||||
- Optimization |
||||
- improve speed |
||||
- reduce image size |
||||
- reduce power (CPU) & memory usage |
||||
- reduce surface of attack |
||||
- reduce bandwidth usage |
||||
- Customization |
||||
- machine-dependent (drivers, bug workarounds...) |
||||
- time zone of the school |
||||
- school scripts |
||||
- Cleaning |
||||
- logs |
||||
- temporary files |
||||
- histories |
||||
- caches |
||||
- auto-generated IDs |
||||
- Preparation of the disk image |
||||
- zero unallocated space of filesystem (~7 GB of data remains) |
||||
- (optional) create compressed image with [lz4](https://lz4.github.io/lz4) (the resulting image is ~3.2 GB) |
||||
|
||||
## Network installation |
||||
|
||||
- Boot through PXE [UDPcast](http://udpcast.linux.lu) which allows an efficient transfer of the disk image (using multicast or broadcast) |
@ -1,37 +0,0 @@
|
||||
# Principles |
||||
|
||||
## Make a simple system (less complexity) |
||||
|
||||
Rationale : |
||||
|
||||
- Reduce the number of potential bugs and problems |
||||
- The remaining bugs will be easier to identify/isolate & fix |
||||
- Easier maintenance |
||||
- Lower human capital required |
||||
|
||||
## Limit security & filtering mechanisms |
||||
|
||||
Especially during the launch, rationale : |
||||
|
||||
- Reduce complexity (see above) |
||||
- Alem is a school, not a bank, so the security requirements are lower |
||||
- Some students will be able to bypass security systems in all cases |
||||
- And they will spread the word quickly |
||||
- The only reliable way to identify students will be security cameras and staff attention |
||||
- Students will share accounts and USB drives |
||||
- They will open connections to the outside and there is no definitive way to prevent this |
||||
- We will "hire" the students who have found vulnerabilities using technical skills and creativity |
||||
- We cannot anticipate every breach hundreds of students will find & exploit |
||||
- Focus on endpoint security rather than network security (firewall on each node) |
||||
- Reduce complexity of the network and make it more flexible |
||||
|
||||
## Promote open, neutral network & technologies |
||||
|
||||
Rationale : |
||||
|
||||
- Students will spend more time learning things and exchanging ideas than bypassing censorship |
||||
- Students will have more extensive knowledge and skills |
||||
- It is better to make them aware of their situation than to try to stop them |
||||
- A student's motivation is very much influenced by his or her environment |
||||
- An environment with limitations will limit the spectrum of things that stimulate the student's curiosity |
||||
- A focus will made on increasing student's empowerement in order to make them feel accountable for their own actions. If the student cheats, he has to understand that he is only hindering his own progress. |
@ -1,31 +0,0 @@
|
||||
# Responsibilities |
||||
|
||||
## Alem |
||||
|
||||
- Hardware |
||||
- Maintenance & replacement of parts |
||||
- HP machines |
||||
- Inventory (associates MAC address or other ID to the physical location of the machine) |
||||
- [BIOS configuration](bios-configuration.md) |
||||
- Connected on Ethernet network |
||||
- Audio & USB extension cables (to protect the PC ports) |
||||
- Computers & cables are physically attached to the table (to prevent stealing or damage) |
||||
- Monitor brightness (the default might be too high and it cannot be controlled by software) |
||||
- Server (virtualized with at least these dedicated resources) |
||||
- CPU : 8 threads |
||||
- RAM : 64 GB |
||||
- SSD : 512 GB |
||||
- NIC : pass-through or bridged ? (see with Vitalii) |
||||
- Software |
||||
- DHCP |
||||
- DNS |
||||
- PXE |
||||
- Image creation & deployment (with the help of team 01) |
||||
|
||||
## 01 |
||||
|
||||
- Software maintenance |
||||
- Implement the features requested or identified at the Alem School |
||||
- Bug fix |
||||
- Technical advice |
||||
- Pedagogical support |
@ -1,35 +0,0 @@
|
||||
US based, it must be adapted to other countries (in order to avoid voltage problems). |
||||
|
||||
- UPS ([APC Smart-UPS Li-Ion, Short Depth 1000VA](https://www.apc.com/shop/us/en/products/APC-Smart-UPS-Li-Ion-Short-Depth-1000VA-120V-with-SmartConnect-Not-for-sale-in-Vermont-/P-SMTL1000RM2UC)) ≈ \$1,400.00 |
||||
- Router/Firewall ([Netgate XG-7100 1U](https://www.netgate.com/solutions/pfsense/xg-7100-1u.html)) ≈ \$1,000.00 |
||||
- Switch ([TP-Link 48-Port Gigabit Switch TL-SG1048](https://www.amazon.com/dp/B004UBUJZG)) ≈ \$220.00 |
||||
- Quantity : round(_number of students_ / 48 + 1) |
||||
- Server ([Dell EMC PowerEdge R340](https://www.dell.com/en-us/work/shop/servers-storage-and-networking/poweredge-r340-rack-server/spd/poweredge-r340/pe_r340_13158_vi_vp)) ≈ \$3,000.00 |
||||
- Trusted Platform Module (TPM) |
||||
- Trusted Platform Module 2.0 |
||||
- Chassis |
||||
- 2.5" Chassis with up to 8 Hot Plug Hard Drives |
||||
- Processor |
||||
- Intel® Xeon® E-2246G 3.6GHz, 12M cache, 6C/12T, turbo (80W) |
||||
- Memory |
||||
- 16GB 2666MT/s DDR4 ECC UDIMM |
||||
- Quantity : 2 |
||||
- RAID |
||||
- No RAID |
||||
- RAID/Internal Storage Controllers |
||||
- PERC H330 RAID Controller, Adapter |
||||
- Hard Drive |
||||
- 480GB SSD SATA Mix Use 6Gbps 512 2.5in Hot-plug AG Drive, 3 DWPD, 2628 TBW |
||||
- Quantity : 2 |
||||
- Power Supply |
||||
- Dual, Hot Plug, Redundant Power Supply (1+1), 550W |
||||
- Bezel |
||||
- PowerEdge 1U Standard Bezel |
||||
- ProSupport and Next Business Day Onsite Service, 60 Month(s) |
||||
- etc |
||||
- Rack Enclosure ≈ \$500.00 |
||||
- PDU |
||||
- Cable Manager |
||||
- Cable Organizer |
||||
- Cable Pass-Through Panel |
||||
- Roof Fan Tray |
@ -0,0 +1,5 @@
|
||||
module main |
||||
|
||||
go 1.16 |
||||
|
||||
require github.com/olekukonko/tablewriter v0.0.5 |
@ -0,0 +1,4 @@
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= |
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= |
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= |
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= |
@ -0,0 +1,231 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"bufio" |
||||
"encoding/json" |
||||
"errors" |
||||
"fmt" |
||||
"math" |
||||
"os" |
||||
"os/exec" |
||||
"strconv" |
||||
"strings" |
||||
|
||||
"github.com/olekukonko/tablewriter" |
||||
) |
||||
|
||||
func fatalln(a ...interface{}) { |
||||
fmt.Println(a...) |
||||
os.Exit(1) |
||||
} |
||||
|
||||
func expect(target, err error, action string) { |
||||
if err != nil && err != target && !errors.Is(err, target) { |
||||
fatalln("Failed to", action, ":", err) |
||||
} |
||||
} |
||||
|
||||
func renderTable(data [][]string) { |
||||
table := tablewriter.NewWriter(os.Stdout) |
||||
table.SetColumnSeparator(" ") |
||||
table.SetCenterSeparator(" ") |
||||
table.SetRowSeparator(" ") |
||||
table.SetAlignment(tablewriter.ALIGN_CENTER) |
||||
table.SetHeader(data[0]) |
||||
for _, row := range data[1:] { |
||||
table.Append(row) |
||||
} |
||||
table.Render() |
||||
} |
||||
|
||||
// run returns the output of the command
|
||||
// In case of error, display the description, the command and the error
|
||||
func run(description, name string, arg ...string) []byte { |
||||
b, err := exec.Command(name, arg...).CombinedOutput() |
||||
if err != nil { |
||||
fmt.Println("Failed to", description) |
||||
fmt.Printf("%s %#v\n", name, arg) |
||||
if _, ok := err.(*exec.ExitError); ok { |
||||
fatalln(string(b)) |
||||
} |
||||
fatalln(err) |
||||
} |
||||
return b |
||||
} |
||||
|
||||
type ( |
||||
size int |
||||
stringTrim string |
||||
|
||||
device struct { |
||||
Path string // path to the device node
|
||||
RO bool // read-only device
|
||||
RM bool // removable device
|
||||
Hotplug bool // removable or hotplug device (usb, pcmcia, ...)
|
||||
Model stringTrim // device identifier
|
||||
Size size // size of the device
|
||||
Type string // device type
|
||||
Tran string // device transport type
|
||||
Vendor stringTrim // device vendor
|
||||
} |
||||
) |
||||
|
||||
func (s stringTrim) String() string { |
||||
return strings.TrimSpace(string(s)) |
||||
} |
||||
|
||||
// format size with SI prefix
|
||||
func (s size) String() string { |
||||
f := float64(s) |
||||
if f < 0 { |
||||
f = 0 |
||||
} |
||||
unit := " kMGTPEZY" |
||||
for f >= 1000 { |
||||
unit = unit[1:] |
||||
f /= 1000 |
||||
} |
||||
var prec int |
||||
if unit[0] != ' ' && math.Round(f) < 10 { |
||||
prec = 1 |
||||
} |
||||
return fmt.Sprintf("%.*f %cB", prec, f, unit[0]) |
||||
} |
||||
|
||||
func main() { |
||||
// Usage
|
||||
fmt.Println("While using this formatting tool:") |
||||
fmt.Println(" - do not plug/unplug any drive") |
||||
fmt.Println(" - make sure the drive is not in use") |
||||
fmt.Print("Press ENTER to continue") |
||||
bufio.NewScanner(os.Stdin).Scan() |
||||
|
||||
// Get a list of the block devices
|
||||
var data struct { |
||||
Blockdevices []device |
||||
} |
||||
b := run("list the block devices", |
||||
"lsblk", |
||||
"--all", |
||||
"--bytes", |
||||
"--nodeps", |
||||
"--json", |
||||
"--output", "path,ro,rm,hotplug,model,size,type,tran,vendor", |
||||
) |
||||
expect(nil, json.Unmarshal(b, &data), "list the block devices") |
||||
|
||||
// Filter the block devices to get only the USB flash drives
|
||||
var devices []device |
||||
for _, device := range data.Blockdevices { |
||||
if !device.RO && device.RM && device.Hotplug && device.Type == "disk" && device.Tran == "usb" { |
||||
devices = append(devices, device) |
||||
} |
||||
} |
||||
|
||||
// If no USB flash drive is found, exit the program with an explanation
|
||||
if len(devices) == 0 { |
||||
fmt.Println("No available USB devices were found.") |
||||
if len(data.Blockdevices) > 0 { |
||||
fmt.Println("Here is a list of the block devices found:") |
||||
table := [][]string{{"Path", "RO", "RM", "Hotplug", "Model", "Size", "Type", "Tran", "Vendor"}} |
||||
for _, device := range data.Blockdevices { |
||||
table = append(table, []string{ |
||||
device.Path, |
||||
strconv.FormatBool(device.RO), |
||||
strconv.FormatBool(device.RM), |
||||
strconv.FormatBool(device.Hotplug), |
||||
device.Model.String(), |
||||
device.Size.String(), |
||||
device.Type, |
||||
device.Tran, |
||||
device.Vendor.String(), |
||||
}) |
||||
} |
||||
renderTable(table) |
||||
} |
||||
return |
||||
} |
||||
|
||||
// Display the found USB flash drives
|
||||
table := [][]string{{"Number", "Vendor", "Model", "Size"}} |
||||
for i, device := range devices { |
||||
table = append(table, []string{ |
||||
strconv.Itoa(i), |
||||
device.Vendor.String(), |
||||
device.Model.String(), |
||||
device.Size.String(), |
||||
}) |
||||
} |
||||
renderTable(table) |
||||
|
||||
// Select the USB flash drive to format
|
||||
fmt.Println(`Enter the number of the disk you want to format (or "exit"):`) |
||||
var choice string |
||||
fmt.Scanln(&choice) |
||||
if strings.ToLower(choice) == "exit" { |
||||
return |
||||
} |
||||
var nb int |
||||
nb, err := strconv.Atoi(choice) |
||||
if err != nil || nb < 0 || nb >= len(devices) { |
||||
fatalln("Wrong disk number:", choice) |
||||
} |
||||
device := devices[nb] |
||||
|
||||
// Get a list of the USB flash drive mount points
|
||||
b, err = os.ReadFile("/proc/mounts") |
||||
expect(nil, err, "list the mount points") |
||||
lines := strings.Split(string(b), "\n") |
||||
var mountPoints []string |
||||
for _, line := range lines { |
||||
fields := strings.Fields(line) |
||||
if len(fields) < 2 { |
||||
continue |
||||
} |
||||
deviceName := fields[0] |
||||
mountPoint := fields[1] |
||||
if strings.Contains(deviceName, device.Path) { |
||||
mountPoints = append(mountPoints, mountPoint) |
||||
} |
||||
} |
||||
|
||||
// Unmount the USB flash drive
|
||||
if len(mountPoints) > 0 { |
||||
mountPointOccurrences := map[string]int{} |
||||
for _, mountPoint := range mountPoints { |
||||
mountPoint = mountPoint[1:] // remove leading '/'
|
||||
parts := strings.Split(mountPoint, "/") |
||||
for i := 1; i <= len(parts); i++ { |
||||
mountPointOccurrences[strings.Join(parts[:i], "/")]++ |
||||
} |
||||
} |
||||
for mountPoint, occurrences := range mountPointOccurrences { |
||||
parts := strings.Split(mountPoint, "/") |
||||
for i := len(parts) - 1; i > 0; i-- { |
||||
parent := strings.Join(parts[:i], "/") |
||||
if occurrences < mountPointOccurrences[parent] { |
||||
delete(mountPointOccurrences, mountPoint) |
||||
} else { |
||||
delete(mountPointOccurrences, parent) |
||||
} |
||||
} |
||||
} |
||||
for mountPoint := range mountPointOccurrences { |
||||
mountPoint = "/" + mountPoint // put back leading '/'
|
||||
fmt.Print("The selected device is mounted on ", mountPoint, ". Trying to unmount it... ") |
||||
run("umount the selected device", "umount", "--recursive", mountPoint) |
||||
fmt.Println("done") |
||||
} |
||||
} |
||||
|
||||
// Format USB flash drive
|
||||
fmt.Print("Formatting... ") |
||||
run("erase disk data", "wipefs", "--all", device.Path) |
||||
run("erase disk data", "sgdisk", "--zap-all", device.Path) |
||||
run("create partition table", "sgdisk", "--largest-new", "0", device.Path) |
||||
run("create partition table", "sgdisk", "--change-name", "1:01-home", device.Path) |
||||
run("inform the OS of partition table changes", "partx", "--update", device.Path) |
||||
run("format partition", "mkfs.f2fs", "-f", device.Path+"1") |
||||
fmt.Println("done") |
||||
fmt.Println(device.Vendor, device.Model, device.Size, "has been formatted, logout and login to use it") |
||||
} |
@ -1,3 +1,3 @@
|
||||
#!/usr/bin/env bash |
||||
|
||||
curl -s "https://$DOMAIN/api/graphql-engine/v1/graphql" --data '{"query":"{user(where:{githubLogin:{_eq:\"'$USERNAME'\"}}){id}}"}' | jq '.data.user[0].id' |
||||
curl -s "https://$DOMAIN/api/graphql-engine/v1/graphql" --data '{"query":"{user(where:{login:{_eq:\"'$USERNAME'\"}}){id}}"}' | jq '.data.user[0].id' |
||||
|
@ -1,36 +0,0 @@
|
||||
<html> |
||||
<head> |
||||
<title>GraphiQL</title> |
||||
<link href="https://unpkg.com/graphiql/graphiql.min.css" rel="stylesheet" /> |
||||
</head> |
||||
<body style="margin: 0;"> |
||||
<div id="graphiql" style="height: 100vh;"></div> |
||||
|
||||
<script |
||||
crossorigin |
||||
src="https://unpkg.com/react/umd/react.production.min.js" |
||||
></script> |
||||
<script |
||||
crossorigin |
||||
src="https://unpkg.com/react-dom/umd/react-dom.production.min.js" |
||||
></script> |
||||
<script |
||||
crossorigin |
||||
src="https://unpkg.com/graphiql/graphiql.min.js" |
||||
></script> |
||||
|
||||
<script> |
||||
const graphQLFetcher = graphQLParams => |
||||
fetch(`https://${location.hostname}/api/graphql-engine/v1/graphql`, { |
||||
method: 'post', |
||||
headers: { 'Content-Type': 'application/json' }, |
||||
body: JSON.stringify(graphQLParams), |
||||
}) |
||||
.then(response => response.json().catch(() => response.text())) |
||||
ReactDOM.render( |
||||
React.createElement(GraphiQL, { fetcher: graphQLFetcher }), |
||||
document.getElementById('graphiql'), |
||||
) |
||||
</script> |
||||
</body> |
||||
</html> |
@ -0,0 +1,76 @@
|
||||
## guess-it-1 |
||||
|
||||
### Objectives |
||||
|
||||
Now that you have the math skills up and running , it is time for you to guess numbers. Find a way to implement the `math-skills` exercise into this one. |
||||
|
||||
### Instructions |
||||
|
||||
That is right, you must build a program that given a number as standard input, prints out a range in which the next number provided should be. |
||||
|
||||
The data received by the program, as always, will be presented as the following example: |
||||
|
||||
```console |
||||
189 |
||||
113 |
||||
121 |
||||
114 |
||||
145 |
||||
110 |
||||
... |
||||
``` |
||||
|
||||
This data represents a graph in which the values of the x axis are the number of the lines (0, 1, 2, 3, 4, 5 ...) and the values of the y axis are the actual numbers (189, 113, 121, 114, 145, 110...). |
||||
|
||||
Each of the numbers will be your standard input and the purpose of your program is for you to find the range in which the next number will be in. |
||||
This range should have a space separating the lower limit from the upper one like in the example: |
||||
|
||||
```console |
||||
>$ ./your_program |
||||
189 --> the standard input |
||||
120 200 --> the range for the next input, in this case for the number 113 |
||||
113 --> the standard input |
||||
160 230 --> the range for the next input, in this case for the number 121 |
||||
121 --> the standard input |
||||
110 140 --> the range for the next input, in this case for the number 114 |
||||
114 --> the standard input |
||||
100 200 --> the range for the next input, in this case for the number 145 |
||||
145 --> the standard input |
||||
1 99 --> the range for the next input, in this case for the number 110 |
||||
110 --> the standard input |
||||
100 150 --> the range for the next input, in this case for the number |
||||
145 |
||||
... |
||||
``` |
||||
|
||||
As seen above, some of the ranges are not correct and some are bigger than others. As this is just an example, if you so wish, a specific range in your program can be given. That is fully up to you to decide. The intent of this exercise is to use the calculations you did in the `math-skills` exercise to guess the numbers. |
||||
|
||||
### Testing |
||||
|
||||
Your program will be extensively tested, so performance should be prioritized. Testing will work as follow: |
||||
|
||||
If you guess correctly the range for the next given number, your score will be incremented based on the size of your range. In other words, the bigger your range is, the smaller your score will be. So we advise you to find the perfect balance between a small range and a good guess. |
||||
|
||||
In order for auditors to test your program, you will have to follow the next steps: |
||||
|
||||
- create a folder called **`student`** |
||||
- copy the files that are needed to run your program into this folder |
||||
- write an **executable** shell script named `script.sh` containing the command(s) to run your program, **from the root folder of the provided tester** (see below where to find it) |
||||
|
||||
Here is a following example of the script, assuming that the program is called `solution` and was written in JS(Javascript): |
||||
|
||||
```sh |
||||
#!/bin/sh |
||||
# We assume that we are on the root folder, so we have to enter the |
||||
# student folder in order to run the `solution.js` file |
||||
node ./student/solution.js |
||||
``` |
||||
|
||||
You can choose in which language you want to build your program. |
||||
|
||||
If you fail one of these steps, the test will not work. So we advise you to run the test by downloading [this zip file](https://assets.01-edu.org/guess-the-number.zip) containing the tester. You should place the `student/` folder in the root directory of the items provided and read its instructions. The data sets used to test this exercise will be `Data 1`, `Data 2` and `Data 3`. |
||||
|
||||
This project will help you learn about: |
||||
|
||||
- Statistical and Probabilities Calculation |
||||
- Scripting |
@ -0,0 +1,23 @@
|
||||
#### Functional |
||||
|
||||
##### After downloading [this zip file](https://assets.01-edu.org/guess-the-number.zip) containing a tester, follow its instructions (present in the README) in order to test the student program against the `big-range` program 3 times using the `Data 1`. |
||||
|
||||
###### Did the student won against `big-range` most of the times (at least 2 out of 3 times)? |
||||
|
||||
##### Try running the student program against the `big-range` program, using `Data 2` and then `Data 3` 3 times each. |
||||
|
||||
###### Did the student won against `big-range` most of the times (at least 2 out of 3 times for each)? |
||||
|
||||
##### Try running the student program against the `average` program, using `Data 1`, `Data 2` and `Data 3` 3 times each. |
||||
|
||||
###### Did the student won against `average` most of the times (at least 2 out of 3 times for each)? |
||||
|
||||
##### Try running the student program against the `median` program, using `Data 1`, `Data 2` and `Data 3` 3 times each. |
||||
|
||||
###### Did the student won against `median` most of the times (at least 2 out of 3 times for each)? |
||||
|
||||
#### Bonus |
||||
|
||||
##### Try running the student program against the `nic` program, using `Data 1`, `Data 2` and `Data 3` 3 times each. |
||||
|
||||
###### +Did the student won against `nic` most of the times (at least 2 out of 3 times for each)? |
@ -0,0 +1,76 @@
|
||||
## guess-it-2 |
||||
|
||||
### Objectives |
||||
|
||||
Now that you have even more statistical knowledge, you will guess even more numbers. This time it will be a bit harder. |
||||
|
||||
### Instructions |
||||
|
||||
That is right, you must build a program that given a number as standard input, prints out a range in which the next number provided should be. Just like last time. |
||||
|
||||
The data received by the program, as always, will be presented as below: |
||||
|
||||
```console |
||||
189 |
||||
113 |
||||
121 |
||||
114 |
||||
145 |
||||
110 |
||||
... |
||||
``` |
||||
|
||||
This data represents a graph in which the values of the x axis are the number of the lines (0, 1, 2, 3, 4, 5 ...) and the values of the y axis are the actual numbers (189, 113, 121, 114, 145, 110...). |
||||
|
||||
Each of the numbers will be your standard input and the purpose of your program is for you to find the range in which the next number will be in. |
||||
This range should have a space separating the lower limit from the upper one like in the example: |
||||
|
||||
```console |
||||
>$ ./your_program |
||||
189 --> standard input |
||||
120 200 --> range for the next input, in this case for the number 113 |
||||
113 --> standard input |
||||
160 230 --> range for the next input, in this case for the number 121 |
||||
121 --> standard input |
||||
110 140 --> range for the next input, in this case for the number 114 |
||||
114 --> standard input |
||||
100 200 --> range for the next input, in this case for the number 145 |
||||
145 --> standard input |
||||
1 99 --> range for the next input, in this case for the number 110 |
||||
110 --> standard input |
||||
100 150 --> range for the next input, in this case for the number 145 |
||||
145 --> standard input |
||||
... |
||||
``` |
||||
|
||||
As you can see, some of the ranges are not correct and some are bigger than others. This is just an example. If you wish, you can give a specific range in your program, that is fully up to you to decide. The intent of this exercise is for you to use the calculations you did in the previous exercise (`linear_stats`) to guess the numbers. |
||||
|
||||
### Testing |
||||
|
||||
Your program will be extensively tested, so performance should be prioritized. Testing will work as follow: |
||||
|
||||
If you correctly guess the range for the next given number, your score will be incremented based on the size of your range. In other words, the bigger your range is, the smaller your score will be. So we advise you to find the perfect balance between a small range and a good guess. |
||||
|
||||
In order for auditors to test your program, you will have to follow the next steps: |
||||
|
||||
- create a folder called **`student`** |
||||
- copy the files that are needed to run your program into this folder |
||||
- write an **executable** shell script named `script.sh` containing the command(s) to run your program, **from the root folder of the provided tester** (see below where to find it) |
||||
|
||||
Here is a following example of the script, assuming that the program is called `solution` and was written in JS(Javascript): |
||||
|
||||
```sh |
||||
#!/bin/sh |
||||
# We assume that we are on the root folder, so we have to enter the |
||||
# student folder in order to run the `solution.js` file |
||||
node ./student/solution.js |
||||
``` |
||||
|
||||
You can choose in which language you want to build your program. |
||||
|
||||
If you fail one of these steps, the test will not work. So we advise you to run the test by downloading [this zip file](https://assets.01-edu.org/guess-the-number.zip) containing the tester. You should place the `student/` folder in the root directory of the items provided and read its instructions. The data sets used to test this exercise will be `Data 5` and `Data 6`. |
||||
|
||||
This project will help you learn about: |
||||
|
||||
- Statistical and Probabilities Calculations |
||||
- Scripting |
@ -0,0 +1,27 @@
|
||||
#### Functional |
||||
|
||||
##### After downloading [this zip file](https://assets.01-edu.org/guess-the-number.zip) containing a tester, follow its instructions (present in the README) in order to test the student program against the `big-range` program 3 times using the `Data 4`. |
||||
|
||||
###### Did the student won against `big-range` most of the times (at least 2 out of 3 times)? |
||||
|
||||
##### Try running the student program against the `big-range` program, using `Data 5` 3 times. |
||||
|
||||
###### Did the student won against `big-range` most of the times (at least 2 out of 3 times for each)? |
||||
|
||||
##### Try running the student program against the `linear-regr` program, using `Data 4` and `Data 5` 3 times each. |
||||
|
||||
###### Did the student won against `linear-regr` most of the times (at least 2 out of 3 times for each)? |
||||
|
||||
##### Try running the student program against the `correlation-coef` program, using `Data 4` and `Data 5` 3 times each. |
||||
|
||||
###### Did the student won against `correlation-coef` most of the times (at least 2 out of 3 times for each)? |
||||
|
||||
#### Bonus |
||||
|
||||
##### +Try running the student program against the `mse` program, using `Data 4` and `Data 5` 3 times each. |
||||
|
||||
###### +Did the student won against `mse` most of the times (at least 2 out of 3 times for each)? |
||||
|
||||
##### +Try running the student program against the `nic` program, using `Data 4` and `Data 5` 3 times each. |
||||
|
||||
###### +Did the student won against `nic` most of the times (at least 2 out of 3 times for each)? |
@ -0,0 +1,46 @@
|
||||
## linear-stats |
||||
|
||||
This time, like in the first exercise, you will have to build a program that prints various statistical calculations. Now, you will focus on the `Linear Regression Line` and the `Pearson Correlation Coefficent`. |
||||
|
||||
### Instructions |
||||
|
||||
Your program must be able to read from a file and print the result of each statistic mentioned above. In other words, your program must be able to read the data present in the path passed as argument. The data in the file will be presented as below: |
||||
|
||||
```console |
||||
189 |
||||
113 |
||||
121 |
||||
114 |
||||
145 |
||||
110 |
||||
... |
||||
``` |
||||
|
||||
This data represents a graph in which the values of the x axis are the number of the lines (0, 1, 2, 3, 4, 5 ...) and the values of the y axis are the actual numbers (189, 113, 121, 114, 145, 110...). |
||||
|
||||
To run your program, a command similar to this one will be used if your project is made in Go: |
||||
|
||||
```sh |
||||
>$ go run your-program.go data.txt |
||||
``` |
||||
|
||||
After reading the file, your program should print the `Linear Regression Line` and the `Pearson Correlation Coefficient` in the following format: |
||||
|
||||
```console |
||||
Linear Regression Line: y = <value>x + <value> |
||||
Pearson Correlation Coefficient: <value> |
||||
``` |
||||
|
||||
The values in between the single angle quotation marks (`< >`) should be a decimal number. The values for the `Linear Regression Line` should have 6 decimal places, while the `Pearson Correlation Coefficient` value should have 10 decimal places. |
||||
|
||||
#### Testing |
||||
|
||||
Your program will be tested by an auditor who will run a program provided by us, that creates a random data set of numbers and prints the result. The auditor task is to compare how your program performed. |
||||
|
||||
You can choose the language in which you want to build your program. |
||||
|
||||
This program will help you learn about: |
||||
|
||||
- Statistical and Probabilities Calculations |
||||
- [Linear Regression Line](https://en.wikipedia.org/wiki/Linear_regression) |
||||
- [Pearson Correlation Coefficient](https://en.wikipedia.org/wiki/Pearson_correlation_coefficient) |
@ -0,0 +1,19 @@
|
||||
#### Functional |
||||
|
||||
##### After downloading the [file](https://assets.01-edu.org/stats-projects/linear-stats) and giving executable permissions, run the script with `./linear-stats` and then run the program of the student with the created `data.txt` by the previous command. |
||||
|
||||
###### Are the outputs of both programs (the one provided and the student one) in the same format? |
||||
|
||||
###### In the output of the student program, did the values on the Linear Regression Line contain 6 decimal places? |
||||
|
||||
###### In the output of the student program, did the values on the Pearson Correlation Coefficient contain 10 decimal places? |
||||
|
||||
###### Did the values of both programs match? |
||||
|
||||
##### Do the same procedure (running the script provided and the student program) 3 more times in order to test new data sets. |
||||
|
||||
###### Did the values of both programs match in all tries? |
||||
|
||||
#### Bonus |
||||
|
||||
###### +Did the student provided a README with an explanation on how to test his/her program? |
@ -0,0 +1,57 @@
|
||||
## math-skills |
||||
|
||||
### Objectives |
||||
|
||||
The purpose of this project is for you to calculate the following: |
||||
|
||||
- Average |
||||
- Standard Deviation |
||||
- Variance |
||||
- Median |
||||
|
||||
### Instructions |
||||
|
||||
Your program must be able to read from a file and print the result of each statistic mentioned above. In other words, your program must be able to read the data present in the path passed as argument. The data in the file will be presented as the following example: |
||||
|
||||
```console |
||||
189 |
||||
113 |
||||
121 |
||||
114 |
||||
145 |
||||
110 |
||||
... |
||||
``` |
||||
|
||||
This data represents a graph in which the values of the x axis are the number of the lines (0, 1, 2, 3, 4, 5 ...) and the values of the y axis are the actual numbers (189, 113, 121, 114, 145, 110...). |
||||
|
||||
To run your program a command similar to this one will be used if your project is made in Go: |
||||
|
||||
```sh |
||||
>$ go run your-program.go data.txt |
||||
``` |
||||
|
||||
After reading the file, your program must execute each of the calculations asked above and print the results in the following manner (the following numbers are only examples): |
||||
|
||||
```console |
||||
Average: 35 |
||||
Standard Deviation: 65 |
||||
Variance: 5 |
||||
Median: 4 |
||||
``` |
||||
|
||||
Please note that the values are rounded integers. |
||||
|
||||
### Testing |
||||
|
||||
Your program will be tested by an auditor who will run a program provided by us. This program creates a random data set of numbers and prints the result. The auditor job is to compare how your program performed. |
||||
|
||||
You can choose the language in which you want to build your program. |
||||
|
||||
This project will help you learn about: |
||||
|
||||
- Statistics and Mathematics |
||||
- [Average](https://en.wikipedia.org/wiki/Average) |
||||
- [Standard Deviation](https://en.wikipedia.org/wiki/Standard_deviation) |
||||
- [Variance](https://en.wikipedia.org/wiki/Variance) |
||||
- [Median](https://en.wikipedia.org/wiki/Median) |
@ -0,0 +1,17 @@
|
||||
#### Functional |
||||
|
||||
##### After downloading the [file](https://assets.01-edu.org/stats-projects/math-skills) and giving executable permissions, run the script with `./math-skills` and then run the program of the student with the created `data.txt` by the previous command. |
||||
|
||||
###### Are the outputs of both programs (the one provided and the student one) in the same format? |
||||
|
||||
###### In the output of the student program, are the data types of the values rounded integers? |
||||
|
||||
###### Did the values of both programs match? |
||||
|
||||
##### Do the same procedure (running the script provided and the student program) 3 more times in order to test new data sets. |
||||
|
||||
###### Did the values of both programs match in all tries? |
||||
|
||||
#### Bonus |
||||
|
||||
###### +Did the student provided a README with an explanation on how to test his/her program? |
Some files were not shown because too many files changed in this diff diff.show_more
Loading…
Reference in new issue