From caffb3521ea9a4bb158227b0db13a450b601f921 Mon Sep 17 00:00:00 2001 From: OGordoo Date: Thu, 14 Jan 2021 11:04:10 +0000 Subject: [PATCH 01/42] Unreal Engine Projects --- subjects/armyofone/README.md | 2 + subjects/firingrange/README.md | 2 + subjects/jumpo/README.md | 83 +++++++++++++++++++++++++++ subjects/jumpo/audit/README.md | 77 +++++++++++++++++++++++++ subjects/mousevr/README.md | 2 + subjects/stealth-boom/README.md | 81 ++++++++++++++++++++++++++ subjects/stealth-boom/audit/README.md | 67 +++++++++++++++++++++ subjects/the-pages/README.md | 44 ++++++++++++++ subjects/the-pages/audit/README.md | 55 ++++++++++++++++++ subjects/vehiclephysics/README.md | 2 + subjects/widgetfactory/README.md | 5 ++ subjects/zombieai/README.md | 2 + 12 files changed, 422 insertions(+) create mode 100644 subjects/jumpo/README.md create mode 100644 subjects/jumpo/audit/README.md create mode 100644 subjects/stealth-boom/README.md create mode 100644 subjects/stealth-boom/audit/README.md create mode 100644 subjects/the-pages/README.md create mode 100644 subjects/the-pages/audit/README.md diff --git a/subjects/armyofone/README.md b/subjects/armyofone/README.md index 4e91e5d8..4429556c 100644 --- a/subjects/armyofone/README.md +++ b/subjects/armyofone/README.md @@ -36,3 +36,5 @@ After downloading and unzipping this [file](https://assets.01-edu.org/Unreal-Eng When finished, your project should look like the [“Expected Result” video](https://youtu.be/sebi5icA1MM). > Do not forget to zip up the project compile and save everything for peer correction. + +[Here](https://www.youtube.com/playlist?list=PLHyAJ_GrRtf9sxZqgfPVM06PrLk8_CWA-) you can find an instructional playlist on Unreal Engine. diff --git a/subjects/firingrange/README.md b/subjects/firingrange/README.md index 85258164..3c652b9e 100644 --- a/subjects/firingrange/README.md +++ b/subjects/firingrange/README.md @@ -34,3 +34,5 @@ Here are some ideas for improving the game: - Targets with different speeds. - Textures on the walls and ground. - Adding obstacles in front of the targets. + +[Here](https://www.youtube.com/playlist?list=PLHyAJ_GrRtf9sxZqgfPVM06PrLk8_CWA-) you can find an instructional playlist on Unreal Engine. diff --git a/subjects/jumpo/README.md b/subjects/jumpo/README.md new file mode 100644 index 00000000..c6d01a45 --- /dev/null +++ b/subjects/jumpo/README.md @@ -0,0 +1,83 @@ +## jumpo + +In this project, you will have to create a 2D sidescroller game. You will be using for the first time an external SDK to compile your game: the Android SDK Tool for Unreal Engine, that allows you to create a [.apk file](https://fileinfo.com/extension/apk) that can be installed and played on any Android devices. + +### Objectives + +In this game for Android the player will control a character in a similar game to Google Chrome Running Dinosaur but with coins or gems. So the game will have buttons on screen and that will be bound to character actions like jumping, ducking, etc... Another goal of this project is the sprite and [flipbook](https://docs.unrealengine.com/en-US/AnimatingObjects/Paper2D/Flipbooks/index.html) creation that is used to animate 2D art. + +The basic assets you will need for this project can be found in the ["Jumpo.zip"](https://assets.01-edu.org/Unreal-Engine-Projects/Jumpo/Jumpo.zip) file. + +### Instructions + +The following are the requirements for this project: + +- This game should have a main menu that must have a: + + - Start button, that loads the game. + - Stats button, that shows you how many coins you’ve collected overall, how many times you died, number of games and highest score. You can add more information if you want to. + - Leaderboard button, that shows the 5 highest scores ever made. + - Credits button, that shows the names of the developers that worked on the project. + - Character button, that shows the locked and unlocked characters. + - Quit button, that closes the app. + +#### Map + +These are the requirements regarding the game map: + +- Create a 2D map with obstacles that the player has to dodge by jumping or ducking. +- No 3D objects are allowed in any scene of the game. +- The game is meant to be played in landscape mode. + +#### Character and Gameplay + +For the character these are the requisites: + +- You are free to choose what character you want to use in your game. You can use the resource ones or you can check [this website](https://www.spriters-resource.com/) for more characters and sprites. +- The character should be "running" from left to right, so the character must be headed right. + - The character should actually be static in relation to the background and only the background is moving from right to left, giving the illusion that the character is the one moving. + - Once a part of the background is out of sight it gets destroyed or moved to the right. +- If the character does not die, the map should be infinite. +- Each action (running, jumping, ducking and dying) should play a different animation (a different flipbook). + - Use the .png or .tga files to extract and create a flipbook. +- While running, obstacles should appear on the character path. + - The character can either jump or roll under obstacles to survive. +- When the character hits an obstacle, it dies and the die flipbook animation gets played. + - When the character dies, a score screen is displayed and the player needs to enter 3 characters to save his score in the Leaderboard (a sort of nickname). +- The more time the character survives, the more points he earns. +- The character can collect coins/gems to load an invincibility bar. + - The number of coins collected during that run should appear on the screen as well as the progress of the invincibility bar. + - Once the invincibility bar is loaded up, the player can press it and the character becomes invincible for a short period of time. + - When the invincibility bar gets emptied, the character comes back to normal. +- The jump and roll button should be accessible using thumbs when holding the phone (in the lower corners). +- During the game, the highest ever score should appear on the top middle of the screen and the current score right below it. +- A pause button should appear somewhere on the screen but should not disturb the player experience. Top right is a good place for it. +- When the player presses the pause button or when the character dies, three buttons should appear: + - Retry -> Restarts the game and all progress is lost if the game is in pause. + - Menu -> Goes back to the main menu and all progress is lost if the game is in pause. + - Quit -> Quits the entire app. + +#### Other Game Features + +In addition to the requirements of the map and the character, these are other aspects that need to be taken into account: + +- When closing the app and launching it again, all the player data should remain as he leaved before. + +On the main menu: + +- On the "Character" tab, the player sees grayed-out characters. These are the locked characters. + - This characters can be unlocked by spending coins/gems collected. + - When first opening the game, there should be only one character unlocked. +- When a player dies, the Leaderboard should be updated accordingly to the score the player just made if it is on the 5 best score ever. + - Also the Stats should be updated after every game, whether it is or it is not one of the best 5 scores ever. +- On the Leaderbord and on the Stats tabs, a button to reset all the stats should be available. + +#### Android + +In order to complete this project you are going to need to run your game in Android devices. For that you will need to install an Android SDK. Here is the Unreal Engine [documentation](https://docs.unrealengine.com/en-US/SharingAndReleasing/Mobile/Android/Setup/AndroidStudio/index.html) for that and a [video](https://www.youtube.com/watch?v=q-mAEnqZb0M) that could also help you. + +- You could use your own android device or you could use an emulator to install the app on it and run the app to confirm that everything is working properly on Android devices. + +### Hints + +If you want a good example of how a 2D game is created you can try the [Tappy Chicken](https://assets.01-edu.org/Unreal-Engine-Projects/Jumpo/TappyChicken.zip) game provided. Or you can create an empty project and choose "2D Sidescroller Game" template which contains a lot of info that will be helpful for this project. diff --git a/subjects/jumpo/audit/README.md b/subjects/jumpo/audit/README.md new file mode 100644 index 00000000..c722a1c0 --- /dev/null +++ b/subjects/jumpo/audit/README.md @@ -0,0 +1,77 @@ +#### Functional + +###### A main menu is displayed at the game startup, displaying 5 options? + +###### Does the Credits button shows you the names of the developers that worked on the project? + +###### Does the Quit button makes the player quit the game? + +###### Does the Start button on the main menu starts a new game? + +###### Does the Character button shows you the unlockable characters and the price to unlock them? + +###### Does the Leaderboard button shows the 5 best scores? + +###### Does the Stats button shows the games stats (amount of coins you’ve collected overall, how many times you died, number of games and highest score)? + +###### Does the maps contain obstacles that the player has to dodge? + +###### Can you confirm that there is no 3D objects in the game? + +###### Is the game meant to be played in landscape mode? + +###### Is the player heading right? + +###### Is actually the background moving from right to left, giving the illusion that the player is the one moving? + +###### Is the map infinite if the character does not hit anything? + +###### Does each action (running, jumping, ducking and dying) play a different flipbook? + +###### When the character hits an obstacle does he dies? + +###### When the character dies does a score screen gets displayed and the player needs to enter 3 characters to save his score in the Leaderboard? + +###### If the score of the player is one of the best 5 scores ever, does the Leaderboard gets updated? + +###### Can the character collect coins/gems? + +###### Does the invincibility bar fills up when collecting coins/gems? + +###### Does the character becomes invincible for a little while once the player touches the invincibility bar? + +###### When the invincibility bar gets emptied does the character comes back to normal? + +###### Are the jump and duck/roll button accessible using thumbs when holding the phone? + +###### Can the character jump and duck/roll when touching the buttons? + +###### Are the highest score and current score displayed on the top middle of the screen while playing? + +###### Is the current score being updated as you play? + +###### Is a pause button available to the player? + +###### Does the Retry button on the pause menu starts a new game, losing the previous progress made? + +###### Does the Menu button on the pause menu takes the player to the main menu, losing the previous progress made? + +###### When pressing the pause button, the game stop on the background and the retry, menu and quit button appear on screen? + +###### Does the Quit button on the pause menu, quits the entire app? + +###### When quitting the app and turning back, does the Stats and Leaderboard menu still contains data? + +###### If in the Leaderboard or Stats menu you press the reset button, is all data reset to 0? + +###### Is the apk is built using the latest Android SDK version? + +#### Bonus + +###### Can the player buy an extra life before the start of the game using coins/gems? + +###### Are different sprites being used from the ones provided? + +###### Are there different map backgrounds? + +###### Can the coins/gems be used in an in-game store to buy skins/perks other than invincibility? diff --git a/subjects/mousevr/README.md b/subjects/mousevr/README.md index b94d786e..94025954 100644 --- a/subjects/mousevr/README.md +++ b/subjects/mousevr/README.md @@ -50,4 +50,6 @@ The following are the bonuses for this project: - Animate the interaction points. - Add looping background music during the experience. +[Here](https://www.youtube.com/playlist?list=PLHyAJ_GrRtf9sxZqgfPVM06PrLk8_CWA-) you can find an instructional playlist on Unreal Engine. + Ah! I made you look. diff --git a/subjects/stealth-boom/README.md b/subjects/stealth-boom/README.md new file mode 100644 index 00000000..f625ee6e --- /dev/null +++ b/subjects/stealth-boom/README.md @@ -0,0 +1,81 @@ +## stealth-boom + +In this project, you will have to create an entire stealth game using Unreal Engine. + +### Objectives + +The idea of this project is to create a little 10 minutes gameplay game with missions, stealth based gameplay and AI patrolling NPC. + +The basics assets you will need for this project can be found in the [Stealth-Boom.zip](https://assets.01-edu.org/Unreal-Engine-Projects/StealthBoom.zip) file. It contains the basic animations, character, enemies and props you will need for this project. + +### Instructions + +The following aspects should be fulfilled: + +- Create a map where the player can walk around. + + - This map should contain places for the player to hide from enemies by crouching, hide behind walls, and all other props you may use to help to make a stealth game. + - Buildings with at least 2 floors. + - Pickable ammunition and weapons around the map. + +- For the player you should add: + + - Walk and run animations + - Reload animation + - Aim animation + - Shoot animation + - Crouch animation + - the player should be able to do the above six actions while crouching + - Melee attack animation + - Gun sound when firing + - Bullets visual impact on walls (see decals documentation) + - Blood particles when hit + +- The game should contain a main menu where the player can: + + - Start the game + - Adjust the general sound of the game + - Change the graphics settings + - When changing the resolution, a pop-up should appear in the middle of the screen asking if the player wants to keep the graphics setting he/she just applied. If `Yes` is clicked within 10 seconds, the settings are set, otherwise, if the 10 seconds delay is over or if the player click `No`, the settings go back to the old ones. + - Change the mouse sensitivity + - Invert mouse vertical axis + +- You should have at least 3 types of enemies: `Guards` (patrol around and are look for intruders), `Drones` (same as Guards but can fly), and `Cameras` (stationary and look for intruders). More enemies can be added if you want to. + + - Guards AI: + - Guards should be able to patrol around the map; + - A Guard is able to see the player, if the player crosses his field of view; + - When the player enters the field of view of a Guard, the Guard enters into chase mode and must start running after the player, take cover and shooting at the player. + - If the player leaves the field of view for a certain time, the Guard goes back to patrol mode. + - Drones AI: + - Drones should be able to patrol around the map; + - A light color should determine the state of the drone (Blue for patrolling, Red for chasing the player); + - Once the player crosses the drone camera, the drone light turns red and the drone enters chase mode; + - When a drone is in chase mode, all the guards on the area are alerted, and should enter chase mode as well; + - When the player is out of the drone sight, the drone turns back to patrol mode; + - The sight radius should be inferior on the drones that on the guards. + - Camera AI: + - Cameras should be placed on walls; + - Cameras should have the same light sign as the drone, so when the player is in the camera sight, the camera light turns red and all Guards enter in chase mode; + - As the Drones, Cameras warn guards, whenever the player passes through the camera field of view; + - Some Cameras should lock access of certain areas of the map (for example, close doors) when the player is detected by that camera. + +- Drones, Guards and Cameras should have sounds effect whenever they change from chase to patrol mode, as wel as the other way around. + +- All AI should be implemented using Behavior Trees except for the Camera. + +- The player mission is up to you, either it can be some task to fix, kill all guards without getting caught or collect documents... Whatever you choose, the player should have enemies on his way to diver him away from his objective. + + - When the player successfully completes his mission, a pop up should appear saying that the mission is completed. + +- The player has a health bar that should go down whenever the player gets shot. When the player dies, he has the choice to either quit the game, go back to the main menu or start over. + + - If the player starts over, the level should not be reloaded. The player should spawn back to the starting point. + +- When pressing `Esc` the game is set on paused and the main menu widget pops up. + + - The player should be able to change the game graphics setting exactly like in the main menu. + +- A game should not last longer than 6 minutes. After that the same choices should appear as when the player dies. + +> Do not forget to zip up the project compile and save everything for peer correction. diff --git a/subjects/stealth-boom/audit/README.md b/subjects/stealth-boom/audit/README.md new file mode 100644 index 00000000..7e27c5a9 --- /dev/null +++ b/subjects/stealth-boom/audit/README.md @@ -0,0 +1,67 @@ +#### Functional + +###### Does the map contain places for the player to hide from enemies? + +###### Does the map contain buildings, pickable ammunition and weapons placed around the map? + +###### Does the player has all the minimal animation required (walking, running, melee attacking, aiming, reloading, shooting, crouching, crouch walking, crouch aiming, crouch reloading, crouch shooting)? + +###### Is there a sound for the player shooting? + +###### Are there bullets impact when shooting at a wall? + +###### When the player is hit are there any blood particles? + +###### A main menu with the five options is displaying on the screen? + +###### Can the general sound of the game be managed directly on the settings menu? + +###### When changing the resolution, does a pop-up get displayed on the screen to confirm the changes we just set? + +###### Does pressing “No” on the graphics confirmation pop-up, resets the settings to the old ones? + +###### Are the mouse settings (mouse sensitivity, invert mouse vertical axis) functioning according to their descriptions? + +###### Does the guards and drones wander around the map? + +###### When a player enters the field of view of a guard does he switches to chase mode, running and shooting towards the player while also taking cover? + +###### Does the drone light switches between each state? Blue for patrolling and red for chase mode (when a player crosses his sight)? + +###### Whenever a drone turns to chase mode, do all the guards on the area get alerted and switch to chase mode as well? + +###### Does the drone comes back to patrol mode when the player is out of the drone sight? + +###### Is the sight radius of the drones smaller than the guards? + +###### Are cameras attached to walls? + +###### Do cameras have similar light sign as the drones (red for alert mode and blue for patrol)? + +###### As the drones, do the cameras alert guards on the area, switching them to chase mode? + +###### Do some cameras lock access to certain areas of the map, when they detect a player? + +###### Do Guards, Drones and Cameras play an alert sound when a player gets detected? + +###### Does the camera can close some part of the map (Doors, open traps and kill the player etc…) to the player when the player is being detected? + +###### Are Behavior Trees used to implement the AI of the Guards and Drones? + +###### Does the player have a goal? + +###### When the goal of the player is successfully completed, does a pop up appear saying that the mission is completed? + +###### Does the player have a health bar? + +###### Does the player health decreases when he gets shot by the guards? + +###### When the player loses all his health (dies), does he get to choose either to quit the game, go back to the main menu or to start over? + +###### If the player starts over does he spawn back at the starting point? + +###### The lifespan of the game is at least 6 minutes long from launch to mission complete? + +#### Bonus + +###### Are there headshots implemented? diff --git a/subjects/the-pages/README.md b/subjects/the-pages/README.md new file mode 100644 index 00000000..f27f8846 --- /dev/null +++ b/subjects/the-pages/README.md @@ -0,0 +1,44 @@ +## the-pages + +In this exercise, create a mini-horror game inspired on ["Slender: The Eight Pages"](https://en.wikipedia.org/wiki/Slender:_The_Eight_Pages) game. + +### Objectives + +Just like in the Slender game, the goal of your game should be to get all the 8 pages spread around the map in different locations, while being chased by a monster/creature (a "Creep"). + +To find models of scary monsters/creatures, you can easily choose checking the [Mixamo website](https://www.mixamo.com/#/). Or you can use the models on the ["Creeps.zip"](https://assets.01-edu.org/Unreal-Engine-Projects/ThePages/Creeps.zip) file as well as the [assets](https://assets.01-edu.org/Unreal-Engine-Projects/ThePages/ThePages.zip) (basics animations, character, enemies and props) you will need for this project. + +### Instructions + +On starting the game, it should ask the player to press a button to enter the game. Once the player does that, the actual gameplay level should be loaded. + +The map for your game should be a large squared landscape terrain, scaled at 10 by 10 units. The action should be happening at night time in a forest-like environment. Your map should contain: + +- trees, some little facilities (like shelters or little buildings), monuments etc... You should use the [Foliage Tool](https://docs.unrealengine.com/en-US/BuildingWorlds/Foliage/index.html) to spread trees, rocks and grass around the landscape and to make them have different sizes, scales and rotations. + - To create buildings, you will be using the built in [BSP](https://www.worldofleveldesign.com/categories/ue4/bsp-01-what-is-bsp.php). This method will allow you to create complex meshes and apply textures to it (Useful when you have no 3D modeling skill like me). +- 8 pages spread around the map in the facilities or monuments you created, but should be placed in different spots of those locations in each game. +- at least three different kind of floor surface: dirt, grass and concrete. + +For the creature or monster that you choose to do: + +- It can only move (very slowly so it does not catch up to the player that quickly) when it is not on the player field of view. This means if the player sees it, it should stop. + - Randomly, the "Creep" should teleport to another location. +- The "Creep" never appears before the player collects at least 1 page on the map. +- While completing the task of collecting the 8 pages, the monster should randomly disturb our experience by appearing on the player screen, making that task more difficult. +- When the creep is on the player sight, a disturbing music/sound must be played and the camera should start stuttering like in the original game. + +The player should control a FPS (First Person Shooter) Character that: + +- has to collect 8 pages placed around the map. + - The player can collect the pages by left-clicking on them. + - A sound should be played when the player collects a page and a text should appear temporarily on screen showing how many pages are missing (example: 5 / 8 Pages). +- can toggle a flashlight on and off by pressing the "F" key. + - A sound should be played when toggling the flashlight on or off. +- when walking, should produce the sound of footsteps on the floor. + - The sound of player footsteps should be different on at least 3 different surfaces: concrete, dirt and grass. + - Once the player collects the 8 pages, the forest turns from night to day for a while and then the game ends and the credits show up on the screen. + - The credits should mention the names of the developers. + +If you want you could try to play the real game [Slender: The Eight Pages](https://pt.wikipedia.org/wiki/Slender:_The_Eight_Pages) to get a feel of what your game should look like. + +> Do not forget to zip up the project compile and save everything for peer correction. diff --git a/subjects/the-pages/audit/README.md b/subjects/the-pages/audit/README.md new file mode 100644 index 00000000..493e5f4d --- /dev/null +++ b/subjects/the-pages/audit/README.md @@ -0,0 +1,55 @@ +### Functional + +###### When you open the game, do you have to press a button to start playing? + +###### Is the map a large squared landscape terrain, scaled at 10 by 10 units? + +###### Is the action happening at night time in a forest-like environment? + +###### Does the map contain tress, little facilities (like shelters or little buildings), monuments, rocks and grass around the landscape? + +###### Were the buildings created using [BSP](https://www.worldofleveldesign.com/categories/ue4/bsp-01-what-is-bsp.php)? + +###### Does the map contain 8 pages spread around the map in the facilities or monuments the student created? + +###### Does the map contains at least three different types of floor surface: dirt, grass and concrete. + +###### If you exit and re-enter the game, did the pages changed spots on the locations? + +###### Does the monster stop if it enters the field of view of the player? + +###### Does the "Creep" randomly teleports to another location? + +###### Does the "Creep" only appears after the player collects one page? + +###### Does the monster makes the task of collecting the 8 pages more difficult? + +###### Does a music/sound gets played and the camera starts to stutter when the creature appears in the sight of the player? + +###### Is the player controlling a FPS (First Person Shooter) character? + +###### Can the player move around using the WASD keys and look around using mouse input? + +###### Can the player collect the pages by left-clicking on them? + +###### Is a sound played when the player collects a page? + +###### Is it displayed a text saying how many pages there are left, every time the player collects a page? + +###### Can the player toggle a flashlight on or off when pressing the "F" key? + +###### Is a sound played when toggling the flashlight on or off? + +###### Can you hear the sound of the player footsteps when he walks? + +###### Is there three different sounds to the footsteps, when on dirt, grass and concrete? + +###### Does the forest turns from night time to day time when the player collects all of the 8 pages? + +###### When finishing the game, does the credits (names of the developers) show up? + +### Bonus + +###### Does the game contain a 3D Main menu? + +###### Is the creature different from the one provided? diff --git a/subjects/vehiclephysics/README.md b/subjects/vehiclephysics/README.md index 9c223796..8a1e5822 100644 --- a/subjects/vehiclephysics/README.md +++ b/subjects/vehiclephysics/README.md @@ -47,3 +47,5 @@ As bonus objectives you can: - Create steam/flames particles going out from the car exhaust. - Animate the character entering and sitting in the car. - Add a button to open the doors while inside the car without exiting it. + +[Here](https://www.youtube.com/playlist?list=PLHyAJ_GrRtf9sxZqgfPVM06PrLk8_CWA-) you can find an instructional playlist on Unreal Engine. diff --git a/subjects/widgetfactory/README.md b/subjects/widgetfactory/README.md index a25e160a..700a1995 100644 --- a/subjects/widgetfactory/README.md +++ b/subjects/widgetfactory/README.md @@ -29,6 +29,7 @@ When the player clicks on the Graphics Settings button, another widget should ap - a slider that lets the player choose the percentage of the resolution scale. - a dropdown menu where the player can choose the resolution. + - At least three different resolutions should be displayed in the dropdown. - an apply button at the bottom of the Widget which actualizes the two above resolution settings. @@ -36,9 +37,11 @@ When the player clicks on the Graphics Settings button, another widget should ap - a checkbox, which when switched on, shows the game in full screen and in windowed mode otherwise. - four choices for PostProcessQuality, ShadowQuality, TextureQuality, EffectQuality and FoliageQuality. These four choices are LOW, MEDIUM, HIGH and EPIC. + - These settings have to be executed with the “Execute Console Command” node. - PostProcessAAQuality setting should have the following options as buttons: Off, 2x, 4x, 6x. + - You can use the “append (string)” node to switch between all four choices. - A “Back” button that bring the player back to the main Start menu. @@ -60,3 +63,5 @@ As bonuses you can: - Add a resolution confirmation button when changing resolution. - Use the “On Release” attribute of the buttons, instead of the "On Pressed". Automatically set the default screen resolution to get the best computer performance. + +[Here](https://www.youtube.com/playlist?list=PLHyAJ_GrRtf9sxZqgfPVM06PrLk8_CWA-) you can find an instructional playlist on Unreal Engine. diff --git a/subjects/zombieai/README.md b/subjects/zombieai/README.md index ffd332f4..34d94920 100644 --- a/subjects/zombieai/README.md +++ b/subjects/zombieai/README.md @@ -75,3 +75,5 @@ To make the game more interesting you could: - Implement a point system, in which every time the player kills a zombie, pass wave, etc…, the points gets higher. - Add creepy music during the game, add sound at each new wave, etc… - Make the player have to reload the weapon, in other words, make the gun go out of ammo. + +[Here](https://www.youtube.com/playlist?list=PLHyAJ_GrRtf9sxZqgfPVM06PrLk8_CWA-) you can find an instructional playlist on Unreal Engine. From 33b398254703eaedcbbefe94987879b9cda49df2 Mon Sep 17 00:00:00 2001 From: OGordoo Date: Thu, 14 Jan 2021 15:20:05 +0000 Subject: [PATCH 02/42] little correction --- subjects/jumpo/audit/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subjects/jumpo/audit/README.md b/subjects/jumpo/audit/README.md index c722a1c0..9a248703 100644 --- a/subjects/jumpo/audit/README.md +++ b/subjects/jumpo/audit/README.md @@ -74,4 +74,4 @@ ###### Are there different map backgrounds? -###### Can the coins/gems be used in an in-game store to buy skins/perks other than invincibility? +###### Can the coins/gems be used in an in-game store to buy skins or perks? From 299958c5efa601f47379db353a73d7eed1e58c3c Mon Sep 17 00:00:00 2001 From: Augusto Date: Mon, 18 Jan 2021 19:28:01 +0000 Subject: [PATCH 03/42] Add exercise subject for matrix_transposition_4by3 --- subjects/matrix_transposition/README.md | 2 +- subjects/matrix_transposition_4by3/README.md | 67 ++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 subjects/matrix_transposition_4by3/README.md diff --git a/subjects/matrix_transposition/README.md b/subjects/matrix_transposition/README.md index eaae796f..a1d479fe 100644 --- a/subjects/matrix_transposition/README.md +++ b/subjects/matrix_transposition/README.md @@ -13,7 +13,7 @@ Example: ``` -( a b ) __ transposition __> ( a d ) +( a b ) __ transposition __> ( a d ) ( c d ) ( b d ) ``` diff --git a/subjects/matrix_transposition_4by3/README.md b/subjects/matrix_transposition_4by3/README.md new file mode 100644 index 00000000..7b2ba7fe --- /dev/null +++ b/subjects/matrix_transposition_4by3/README.md @@ -0,0 +1,67 @@ +## matrix_transposition + +### Instructions + +- Define the structure matrix as a tuple of tuples of `i32`'s + +- Define a function that calculate the transpose matrix of a 4x3 matrix (4 rows by 3 columns) which is a 3x4 matrix (3 rows by 4 columns). + +- Note: + + - The transpose of a matrix `A` is the matrix `A'` where `A'`'s columns are `A`'s row and the rows are the columns: + +Example: + +``` +( a b ) __ transposition __> ( a d ) +( c d ) ( b d ) +``` + +- Matrix must implement Debug, PartialEq and Eq. You can use derive + +- Remember that you're defining a library so you have to make public the elements that are going to be called from an external crate. + +### Notions + +[Chapter 7]( https://doc.rust-lang.org/stable/book/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html ) + +### Expected Function + +```rust +pub struct Matrix4by3( + pub (i32, i32, i32), + pub (i32, i32, i32), + pub (i32, i32, i32), + pub (i32, i32, i32), +); + +pub struct Matrix3by4( + pub (i32, i32, i32, i32), + pub (i32, i32, i32, i32), + pub (i32, i32, i32, i32), +); + +pub fn transpose(m: Matrix4by3) -> Matrix3by4 { +} +``` + +### Usage + +Here is a posible program to test your function + +```rust +fn main() { + let matrix = Matrix4by3((1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)); + println!("Original matrix {:?}", matrix); + println!("Transpose matrix {:?}", transpose(matrix)); +} +``` + +And it's output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +Original matrix Matrix4by3((1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)) +Transpose matrix Matrix3by4((1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)) +student@ubuntu:~/[[ROOT]]/test$ +``` From f3eac5a510f01f9edca354b7167aa08ef5ca3e14 Mon Sep 17 00:00:00 2001 From: Augusto Date: Tue, 19 Jan 2021 17:29:11 +0000 Subject: [PATCH 04/42] Add exercise insertion_sort --- .../insertion_sort/Insertion-Sort-demo.jpg | Bin 0 -> 67860 bytes subjects/insertion_sort/README.md | 58 ++++++++++++++++++ subjects/matrix_transposition_4by3/README.md | 10 +-- 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 subjects/insertion_sort/Insertion-Sort-demo.jpg create mode 100644 subjects/insertion_sort/README.md diff --git a/subjects/insertion_sort/Insertion-Sort-demo.jpg b/subjects/insertion_sort/Insertion-Sort-demo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cbe8848ff52f75f6bd25402d8869a18ab5a1a3e6 GIT binary patch literal 67860 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 ( a d ) -( c d ) ( b d ) +( a b c ) __ transposition __> ( a d g j ) +( d e f ) ( b e h k ) +( g h i ) ( c f i l ) +( j k l ) ``` - Matrix must implement Debug, PartialEq and Eq. You can use derive @@ -25,7 +27,7 @@ Example: [Chapter 7]( https://doc.rust-lang.org/stable/book/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html ) -### Expected Function +### Expected Function and Structs ```rust pub struct Matrix4by3( From 6558e9cd9cb7f3b779adf602c4a5664cccfe028d Mon Sep 17 00:00:00 2001 From: Augusto Date: Tue, 19 Jan 2021 22:55:58 +0000 Subject: [PATCH 05/42] Add exercise `matrix_display`s subject --- subjects/insertion_sort/README.md | 2 -- subjects/matrix_display/README.md | 44 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 subjects/matrix_display/README.md diff --git a/subjects/insertion_sort/README.md b/subjects/insertion_sort/README.md index c469e148..550ec737 100644 --- a/subjects/insertion_sort/README.md +++ b/subjects/insertion_sort/README.md @@ -19,8 +19,6 @@ Here is a visual example of sorting a slice step by step using the insertion sor - Implement the algorithm insertion sort by creating a function `insertion_sort(slice, steps)` that executes the iterations of the algorithm the number of steps indicated by the parameter `steps`. See the [Usage](#usage) for more information. -### Notion - ### Expected Function ```rust diff --git a/subjects/matrix_display/README.md b/subjects/matrix_display/README.md new file mode 100644 index 00000000..d5acc795 --- /dev/null +++ b/subjects/matrix_display/README.md @@ -0,0 +1,44 @@ +## matrix_display + +### Instructions + +Use the Matrix struct given in the [expected struct](#expected-functions-and-struct) and implement the `std::fmt::Display` trait so it prints the matrix like in the [usage](#usage). + +You will also have to implement the associated function `new` that creates a matrix from a slice of slices. + +### Expected Functions and Struct + +```rust +pub struct Matrix(pub Vec>); + +pub fn new(slice: &[&[i32]]) -> Self { +} + +use std::fmt; + +impl fmt::Display for Matrix { +} +``` + +### Usage + +Here is a possible program to test your function + +```rust +use matrix_display::*; + +fn main() { + let matrix = Matrix::new(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]); + println!("{}", matrix); +} +``` + +And it's output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +(1 2 3) +(4 5 6) +(7 8 9) +student@ubuntu:~/[[ROOT]]/test$ +``` From a8d535af9985d7f1e7a28fc999b84518ed9a59e5 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 25 Jan 2021 15:45:03 +0000 Subject: [PATCH 06/42] 1st big project --- subjects/the-pages/README.md | 27 ++++++++++++++++----------- subjects/the-pages/audit/README.md | 14 +++++++------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/subjects/the-pages/README.md b/subjects/the-pages/README.md index f27f8846..67f6fc47 100644 --- a/subjects/the-pages/README.md +++ b/subjects/the-pages/README.md @@ -1,31 +1,36 @@ ## the-pages -In this exercise, create a mini-horror game inspired on ["Slender: The Eight Pages"](https://en.wikipedia.org/wiki/Slender:_The_Eight_Pages) game. +In this exercise, one will create a mini-horror game inspired on ["Slender: The Eight Pages"](https://en.wikipedia.org/wiki/Slender:_The_Eight_Pages) game. ### Objectives -Just like in the Slender game, the goal of your game should be to get all the 8 pages spread around the map in different locations, while being chased by a monster/creature (a "Creep"). +Just like in the Slender game, the goal of your game should be, while being chased by a monster/creature (a "Creep"), to get all the 8 pages spread around the map in different locations. -To find models of scary monsters/creatures, you can easily choose checking the [Mixamo website](https://www.mixamo.com/#/). Or you can use the models on the ["Creeps.zip"](https://assets.01-edu.org/Unreal-Engine-Projects/ThePages/Creeps.zip) file as well as the [assets](https://assets.01-edu.org/Unreal-Engine-Projects/ThePages/ThePages.zip) (basics animations, character, enemies and props) you will need for this project. +To find models of scary monsters/creatures: +- you can easily choose checking the [Mixamo website](https://www.mixamo.com/#/). + +- alternatively, you can use the models on the ["Creeps.zip"](https://assets.01-edu.org/Unreal-Engine-Projects/ThePages/Creeps.zip) file. + +- you can also check in the [assets](https://assets.01-edu.org/Unreal-Engine-Projects/ThePages/ThePages.zip) (basics animations, character, enemies and props) you will need for this project. ### Instructions -On starting the game, it should ask the player to press a button to enter the game. Once the player does that, the actual gameplay level should be loaded. +On startin, the game should ask the player to press a button to enter the game. Once the player does that, the actual gameplay level should be loaded. The map for your game should be a large squared landscape terrain, scaled at 10 by 10 units. The action should be happening at night time in a forest-like environment. Your map should contain: - trees, some little facilities (like shelters or little buildings), monuments etc... You should use the [Foliage Tool](https://docs.unrealengine.com/en-US/BuildingWorlds/Foliage/index.html) to spread trees, rocks and grass around the landscape and to make them have different sizes, scales and rotations. - - To create buildings, you will be using the built in [BSP](https://www.worldofleveldesign.com/categories/ue4/bsp-01-what-is-bsp.php). This method will allow you to create complex meshes and apply textures to it (Useful when you have no 3D modeling skill like me). -- 8 pages spread around the map in the facilities or monuments you created, but should be placed in different spots of those locations in each game. -- at least three different kind of floor surface: dirt, grass and concrete. + - To create buildings, you will be using the built in [BSP](https://www.worldofleveldesign.com/categories/ue4/bsp-01-what-is-bsp.php). This method will allow you to create complex meshes and apply textures to it (Useful when you have no 3D modeling skills). +- the map should also contain 8 pages spread around it in the facilities or monuments you created, but should be placed in different spots of those locations in each game. +- the map should have at least three different kind of floor surface: dirt, grass and concrete. -For the creature or monster that you choose to do: +For the creature or monster that you choose to design: -- It can only move (very slowly so it does not catch up to the player that quickly) when it is not on the player field of view. This means if the player sees it, it should stop. +- It can only move (very slowly so it does not catch up to the player that quickly) when it is not within the player field of view. This means if the player sees it, it should stop. - Randomly, the "Creep" should teleport to another location. - The "Creep" never appears before the player collects at least 1 page on the map. - While completing the task of collecting the 8 pages, the monster should randomly disturb our experience by appearing on the player screen, making that task more difficult. -- When the creep is on the player sight, a disturbing music/sound must be played and the camera should start stuttering like in the original game. +- When the creep is within the player's sight, a disturbing music/sound must be played and the camera should start stuttering like in the original game. The player should control a FPS (First Person Shooter) Character that: @@ -34,7 +39,7 @@ The player should control a FPS (First Person Shooter) Character that: - A sound should be played when the player collects a page and a text should appear temporarily on screen showing how many pages are missing (example: 5 / 8 Pages). - can toggle a flashlight on and off by pressing the "F" key. - A sound should be played when toggling the flashlight on or off. -- when walking, should produce the sound of footsteps on the floor. +- when walking should produce the sound of footsteps on the floor. - The sound of player footsteps should be different on at least 3 different surfaces: concrete, dirt and grass. - Once the player collects the 8 pages, the forest turns from night to day for a while and then the game ends and the credits show up on the screen. - The credits should mention the names of the developers. diff --git a/subjects/the-pages/audit/README.md b/subjects/the-pages/audit/README.md index 493e5f4d..39aff086 100644 --- a/subjects/the-pages/audit/README.md +++ b/subjects/the-pages/audit/README.md @@ -1,22 +1,22 @@ ### Functional -###### When you open the game, do you have to press a button to start playing? +###### When you open the game, is there a button to press to start playing? ###### Is the map a large squared landscape terrain, scaled at 10 by 10 units? ###### Is the action happening at night time in a forest-like environment? -###### Does the map contain tress, little facilities (like shelters or little buildings), monuments, rocks and grass around the landscape? +###### Does the map contain trees, little facilities (like shelters or little buildings), monuments, rocks and grass around the landscape? ###### Were the buildings created using [BSP](https://www.worldofleveldesign.com/categories/ue4/bsp-01-what-is-bsp.php)? ###### Does the map contain 8 pages spread around the map in the facilities or monuments the student created? -###### Does the map contains at least three different types of floor surface: dirt, grass and concrete. +###### Does the map contains at least three different types of floor surfaces: dirt, grass and concrete? ###### If you exit and re-enter the game, did the pages changed spots on the locations? -###### Does the monster stop if it enters the field of view of the player? +###### Does the monster come to standstill if it enters the field of view of the player? ###### Does the "Creep" randomly teleports to another location? @@ -34,7 +34,7 @@ ###### Is a sound played when the player collects a page? -###### Is it displayed a text saying how many pages there are left, every time the player collects a page? +###### Is a text displayed stating how many pages are left every time the player collects a page? ###### Can the player toggle a flashlight on or off when pressing the "F" key? @@ -42,11 +42,11 @@ ###### Can you hear the sound of the player footsteps when he walks? -###### Is there three different sounds to the footsteps, when on dirt, grass and concrete? +###### Are there three different sounds to the footsteps, when on dirt, grass and concrete? ###### Does the forest turns from night time to day time when the player collects all of the 8 pages? -###### When finishing the game, does the credits (names of the developers) show up? +###### When finishing the game, do the credits (names of the developers) show up? ### Bonus From f41bdcb73e2b0145048be97429a04250935fae29 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 25 Jan 2021 16:42:01 +0000 Subject: [PATCH 07/42] second big project reviewed --- subjects/stealth-boom/README.md | 24 ++++++++++----------- subjects/stealth-boom/audit/README.md | 30 +++++++++++++-------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/subjects/stealth-boom/README.md b/subjects/stealth-boom/README.md index f625ee6e..f2c483b7 100644 --- a/subjects/stealth-boom/README.md +++ b/subjects/stealth-boom/README.md @@ -4,7 +4,7 @@ In this project, you will have to create an entire stealth game using Unreal Eng ### Objectives -The idea of this project is to create a little 10 minutes gameplay game with missions, stealth based gameplay and AI patrolling NPC. +The idea of this project is to create a little 10 minutes gameplay game with missions, with stealth based gameplay and with an AI patrolling NPC. The basics assets you will need for this project can be found in the [Stealth-Boom.zip](https://assets.01-edu.org/Unreal-Engine-Projects/StealthBoom.zip) file. It contains the basic animations, character, enemies and props you will need for this project. @@ -14,7 +14,7 @@ The following aspects should be fulfilled: - Create a map where the player can walk around. - - This map should contain places for the player to hide from enemies by crouching, hide behind walls, and all other props you may use to help to make a stealth game. + - This map should contain places for the player to hide from enemies by crouching, hide behind walls, and all other props you may use to help it make a stealth game. - Buildings with at least 2 floors. - Pickable ammunition and weapons around the map. @@ -36,35 +36,35 @@ The following aspects should be fulfilled: - Start the game - Adjust the general sound of the game - Change the graphics settings - - When changing the resolution, a pop-up should appear in the middle of the screen asking if the player wants to keep the graphics setting he/she just applied. If `Yes` is clicked within 10 seconds, the settings are set, otherwise, if the 10 seconds delay is over or if the player click `No`, the settings go back to the old ones. + - When changing the resolution, a pop-up should appear in the middle of the screen asking if the player wants to keep the graphics setting he/she just applied. If `Yes` is clicked within 10 seconds, the settings are set, otherwise, if the 10 seconds delay is over or if the player clicks `No`, the settings go back to the old ones. - Change the mouse sensitivity - - Invert mouse vertical axis + - Invert the mouse vertical axis -- You should have at least 3 types of enemies: `Guards` (patrol around and are look for intruders), `Drones` (same as Guards but can fly), and `Cameras` (stationary and look for intruders). More enemies can be added if you want to. +- You should have at least 3 types of enemies: `Guards` (who patrol around and are lookig for intruders), `Drones` (same as Guards but which can fly), and `Cameras` (stationary and looking for intruders). More enemies can be added if you want to. - Guards AI: - Guards should be able to patrol around the map; - A Guard is able to see the player, if the player crosses his field of view; - - When the player enters the field of view of a Guard, the Guard enters into chase mode and must start running after the player, take cover and shooting at the player. + - When the player enters the field of view of a Guard, the Guard enters into chasing mode and must start running after the player, takes cover and shoots at the player. - If the player leaves the field of view for a certain time, the Guard goes back to patrol mode. - Drones AI: - Drones should be able to patrol around the map; - A light color should determine the state of the drone (Blue for patrolling, Red for chasing the player); - - Once the player crosses the drone camera, the drone light turns red and the drone enters chase mode; - - When a drone is in chase mode, all the guards on the area are alerted, and should enter chase mode as well; + - Once the player crosses the drone camera, the drone light turns red and the drone enters chasing mode; + - When a drone is in chasing mode, all the guards on the area are alerted, and should enter chasing mode as well; - When the player is out of the drone sight, the drone turns back to patrol mode; - The sight radius should be inferior on the drones that on the guards. - Camera AI: - Cameras should be placed on walls; - - Cameras should have the same light sign as the drone, so when the player is in the camera sight, the camera light turns red and all Guards enter in chase mode; - - As the Drones, Cameras warn guards, whenever the player passes through the camera field of view; + - Cameras should have the same light sign as the drone, so when the player is in the camera sight, the camera light turns red and all Guards enter in chasing mode; + - Like the Drones, Cameras warn guards, whenever the player passes through the camera field of view; - Some Cameras should lock access of certain areas of the map (for example, close doors) when the player is detected by that camera. -- Drones, Guards and Cameras should have sounds effect whenever they change from chase to patrol mode, as wel as the other way around. +- Drones, Guards and Cameras should have sounds effect whenever they change from chase to patrol mode, as well as the other way around. - All AI should be implemented using Behavior Trees except for the Camera. -- The player mission is up to you, either it can be some task to fix, kill all guards without getting caught or collect documents... Whatever you choose, the player should have enemies on his way to diver him away from his objective. +- The player mission is up to you, either it can be some task to fix, kill all guards without getting caught or collect documents... Whatever you choose, the player should have enemies on his way to divert him away from his objective. - When the player successfully completes his mission, a pop up should appear saying that the mission is completed. diff --git a/subjects/stealth-boom/audit/README.md b/subjects/stealth-boom/audit/README.md index 7e27c5a9..11bf3e45 100644 --- a/subjects/stealth-boom/audit/README.md +++ b/subjects/stealth-boom/audit/README.md @@ -4,15 +4,15 @@ ###### Does the map contain buildings, pickable ammunition and weapons placed around the map? -###### Does the player has all the minimal animation required (walking, running, melee attacking, aiming, reloading, shooting, crouching, crouch walking, crouch aiming, crouch reloading, crouch shooting)? +###### Does the player have all the minimal animation required (walking, running, melee attacking, aiming, reloading, shooting, crouching, crouch walking, crouch aiming, crouch reloading, crouch shooting)? ###### Is there a sound for the player shooting? -###### Are there bullets impact when shooting at a wall? +###### Are there bullets impacts present when shooting at a wall? -###### When the player is hit are there any blood particles? +###### When the player is hit, are there any blood particles? -###### A main menu with the five options is displaying on the screen? +###### Is a main menu with the five options displayed on the screen? ###### Can the general sound of the game be managed directly on the settings menu? @@ -22,15 +22,15 @@ ###### Are the mouse settings (mouse sensitivity, invert mouse vertical axis) functioning according to their descriptions? -###### Does the guards and drones wander around the map? +###### Do the guards and drones wander around the map? -###### When a player enters the field of view of a guard does he switches to chase mode, running and shooting towards the player while also taking cover? +###### When a player enters the field of view of a guard, does he switches to chasing mode, running and shooting towards the player while also taking cover? -###### Does the drone light switches between each state? Blue for patrolling and red for chase mode (when a player crosses his sight)? +###### Does the drone light switches between each state? Blue for patrolling and red for chase mode (when a player crosses its sight)? -###### Whenever a drone turns to chase mode, do all the guards on the area get alerted and switch to chase mode as well? +###### Whenever a drone turns to chasing mode, do all the guards in the area get alerted and switch to chasing mode as well? -###### Does the drone comes back to patrol mode when the player is out of the drone sight? +###### Does the drone come back to patrol mode when the player is out of the drone sight? ###### Is the sight radius of the drones smaller than the guards? @@ -38,13 +38,13 @@ ###### Do cameras have similar light sign as the drones (red for alert mode and blue for patrol)? -###### As the drones, do the cameras alert guards on the area, switching them to chase mode? - -###### Do some cameras lock access to certain areas of the map, when they detect a player? +###### As the drones, do the cameras alert guards on the area, switching them to chasing mode? ###### Do Guards, Drones and Cameras play an alert sound when a player gets detected? -###### Does the camera can close some part of the map (Doors, open traps and kill the player etc…) to the player when the player is being detected? +###### Do some cameras lock access to certain areas of the map, when they detect a player? + +###### Can the camera close some part of the map (thru closed doors, open traps and tries to kill the player etc…) to the player when the player is being detected? ###### Are Behavior Trees used to implement the AI of the Guards and Drones? @@ -56,11 +56,11 @@ ###### Does the player health decreases when he gets shot by the guards? -###### When the player loses all his health (dies), does he get to choose either to quit the game, go back to the main menu or to start over? +###### When the player loses all his health (dies), does he get to choose whether to quit the game, go back to the main menu, or to start over? ###### If the player starts over does he spawn back at the starting point? -###### The lifespan of the game is at least 6 minutes long from launch to mission complete? +###### Is the lifespan of the game at least 6 minutes long from launch to mission completed? #### Bonus From b3167f411417871814b3e87b2500f4e9fe862077 Mon Sep 17 00:00:00 2001 From: OGordoo Date: Mon, 25 Jan 2021 17:07:58 +0000 Subject: [PATCH 08/42] rust exercises for exams --- subjects/matrix_determinant/README.md | 56 +++++++++++++++++ subjects/order_books/README.md | 91 +++++++++++++++++++++++++++ subjects/partial_sums/README.md | 67 ++++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 subjects/matrix_determinant/README.md create mode 100644 subjects/order_books/README.md create mode 100644 subjects/partial_sums/README.md diff --git a/subjects/matrix_determinant/README.md b/subjects/matrix_determinant/README.md new file mode 100644 index 00000000..09efd5ae --- /dev/null +++ b/subjects/matrix_determinant/README.md @@ -0,0 +1,56 @@ +## matrix_determinant + +### Instructions + +Write a matrix_determinant function that receives a 3x3 matrix ([[isize; 3]; 3]) and returns its determinant (isize). + +This is how you calculate a 2x2 matrix determinant: + +```sh +|a b| +|c d| + +a*d - b*c +``` + +To calculate a 3x3 matrix determinant (below) you have to take 'a' and multiply it by the determinant of the matrix you get if you get rid of 'a' column and row. Then you subtract the multiplication of 'b' and the determinant of the matrix you get if you get rid of 'b' column and row. And finally, you do the same process for 'c' and add it to the previous result. + +```sh +|a b c| +|d e f| +|g h i| +``` + +### Expected Function + +```rs +pub fn matrix_determinant(matrix: [[isize; 3]; 3]) -> isize { + +} +``` + +### Example + +Here is a program to test your function: + +```rs +fn main() { + let matrix = [[1, 2, 4], [2, -1, 3], [4, 0, 1]]; + + println!( + "The determinant of the matrix:\n|1 2 4|\n|2 -1 3| = {}\n|4 0 1|", + matrix_determinant(matr) + ); +} +``` + +And its output: + +```sh +$ cargo run +The determinant of the matrix: +|1 2 4| +|2 -1 3| = 35 +|4 0 1| +$ +``` diff --git a/subjects/order_books/README.md b/subjects/order_books/README.md new file mode 100644 index 00000000..e527a399 --- /dev/null +++ b/subjects/order_books/README.md @@ -0,0 +1,91 @@ +## order_books + +### Instructions + +Build a module called `library` with two sub-modules inside it: + +- `writers` which contains a structure called `Writer` that has a first_name (String), last_name (String) and a set of books (Vec\). +- `books` which contains a structure called `Book` that has a title (String) and a year of publish (u64). + +You will also have to create (outside the previous modules) a function `order_books` that receives a writer (Writer) and orders the set of books alphabetically. + +### Expected Functions and Structs + +```rs +pub fn order_books(writer: &mut Writer) { + +} +``` + +```rs +struct Writer { + +} +``` + +```rs +struct Book { + +} +``` + +### Example + +Here is a program to test your function and structs: + +```rs +fn main() { + let mut writer_a = Writer { + first_name: "William".to_string(), + last_name: "Shakespeare".to_string(), + books: vec![ + Book { + title: "Hamlet".to_string(), + year: 1600, + }, + Book { + title: "Othelo".to_string(), + year: 1603, + }, + Book { + title: "Romeo and Juliet".to_string(), + year: 1593, + }, + Book { + title: "MacBeth".to_string(), + year: 1605, + }, + ], + }; + + println!("Before ordering"); + for b in &writer_a.books { + println!("{:?}", b.title); + } + + order_books(&mut writer_a); + + println!("\nAfter ordering"); + for b in writer_a.books { + println!("{:?}", b.title); + } +} +``` + +And its output: + +```sh +$ cargo run +Before ordering +"Hamlet" +"Othelo" +"Romeo and Juliet" +"MacBeth" + +After ordering +"Hamlet" +"MacBeth" +"Othelo" +"Romeo and Juliet" +$ +``` diff --git a/subjects/partial_sums/README.md b/subjects/partial_sums/README.md new file mode 100644 index 00000000..e1d665d1 --- /dev/null +++ b/subjects/partial_sums/README.md @@ -0,0 +1,67 @@ +## partial_sums + +### Instructions + +Write a `partial_sums` function that receives a reference of an array of u64 and returns a vector with the partial sums of the received array. + +This is how partial sums work: + +1- First you split the array in its partitions: + +```sh +[1, 2, 3, 4, 5] + | + V +[1, 2, 3, 4, 5] +[1, 2, 3, 4] +[1, 2, 3] +[1, 2] +[1] +[] +``` + +2- Then you add each partition together: + +```sh +[1, 2, 3, 4, 5] = 15 +[1, 2, 3, 4] = 10 +[1, 2, 3] = 6 +[1, 2] = 3 +[1] = 1 +[] = 0 +``` + +3- So, in conclusion: + +```rs +partial_sums(&[1, 2, 3, 4, 5]) // == [15, 10, 6, 3 ,1, 0] +``` + +### Expected Result + +```rs +pub fn matrix_determinant(arr: &[u64]) -> Vec<64>{ + +} +``` + +### Example + +Here is a program to test your function: + +```rs +fn main() { + println!( + "Partial sums of [5, 18, 3, 23] is : {:?}", + parts_sums(&[5, 18, 3, 23]) + ); +} +``` + +And its output: + +```sh +$ cargo run +Partial sums of [5, 18, 3, 23] is : [49, 26, 23, 5, 0] +$ +``` From a4c02f8ef03b06f8ab080edb1186d3cabc29de73 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 25 Jan 2021 17:20:11 +0000 Subject: [PATCH 09/42] third big project reviewed for unreal engine --- subjects/jumpo/README.md | 16 ++++++------- subjects/jumpo/audit/README.md | 44 +++++++++++++++++----------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/subjects/jumpo/README.md b/subjects/jumpo/README.md index c6d01a45..499815e2 100644 --- a/subjects/jumpo/README.md +++ b/subjects/jumpo/README.md @@ -1,10 +1,10 @@ ## jumpo -In this project, you will have to create a 2D sidescroller game. You will be using for the first time an external SDK to compile your game: the Android SDK Tool for Unreal Engine, that allows you to create a [.apk file](https://fileinfo.com/extension/apk) that can be installed and played on any Android devices. +In this project, you will have to create a 2D sidescroller game. You will be using for the first time an external SDK to compile your game: the Android SDK Tool for Unreal Engine, which allows you to create a [.apk file](https://fileinfo.com/extension/apk) that can be installed and played on any Android devices. ### Objectives -In this game for Android the player will control a character in a similar game to Google Chrome Running Dinosaur but with coins or gems. So the game will have buttons on screen and that will be bound to character actions like jumping, ducking, etc... Another goal of this project is the sprite and [flipbook](https://docs.unrealengine.com/en-US/AnimatingObjects/Paper2D/Flipbooks/index.html) creation that is used to animate 2D art. +In this game for Android, the player will control a character in a similar game than the Google Chrome Running Dinosaur but with coins or gems. So the game will have buttons on screen and that will be bound to character actions like jumping, ducking, etc... Another goal of this project is the sprite and [flipbook](https://docs.unrealengine.com/en-US/AnimatingObjects/Paper2D/Flipbooks/index.html) creation that is used to animate 2D art. The basic assets you will need for this project can be found in the ["Jumpo.zip"](https://assets.01-edu.org/Unreal-Engine-Projects/Jumpo/Jumpo.zip) file. @@ -15,7 +15,7 @@ The following are the requirements for this project: - This game should have a main menu that must have a: - Start button, that loads the game. - - Stats button, that shows you how many coins you’ve collected overall, how many times you died, number of games and highest score. You can add more information if you want to. + - Stats button, that shows you how many coins you have collected overall, how many times you died, the number of games done and the highest score. You can add more information if you want to. - Leaderboard button, that shows the 5 highest scores ever made. - Credits button, that shows the names of the developers that worked on the project. - Character button, that shows the locked and unlocked characters. @@ -33,10 +33,10 @@ These are the requirements regarding the game map: For the character these are the requisites: -- You are free to choose what character you want to use in your game. You can use the resource ones or you can check [this website](https://www.spriters-resource.com/) for more characters and sprites. +- You are free to choose which character you want to use in your game. You can use the resource ones or you can check [this website](https://www.spriters-resource.com/) for more characters and sprites. - The character should be "running" from left to right, so the character must be headed right. - The character should actually be static in relation to the background and only the background is moving from right to left, giving the illusion that the character is the one moving. - - Once a part of the background is out of sight it gets destroyed or moved to the right. + - Once a part of the background is out of sight, it gets destroyed or moved to the right. - If the character does not die, the map should be infinite. - Each action (running, jumping, ducking and dying) should play a different animation (a different flipbook). - Use the .png or .tga files to extract and create a flipbook. @@ -51,7 +51,7 @@ For the character these are the requisites: - When the invincibility bar gets emptied, the character comes back to normal. - The jump and roll button should be accessible using thumbs when holding the phone (in the lower corners). - During the game, the highest ever score should appear on the top middle of the screen and the current score right below it. -- A pause button should appear somewhere on the screen but should not disturb the player experience. Top right is a good place for it. +- A pause button should appear somewhere on the screen but should not disturb the player experience. The top right corner is a good place for it. - When the player presses the pause button or when the character dies, three buttons should appear: - Retry -> Restarts the game and all progress is lost if the game is in pause. - Menu -> Goes back to the main menu and all progress is lost if the game is in pause. @@ -61,7 +61,7 @@ For the character these are the requisites: In addition to the requirements of the map and the character, these are other aspects that need to be taken into account: -- When closing the app and launching it again, all the player data should remain as he leaved before. +- When closing the app and launching it again, all the player data should remain as he leaved it before. On the main menu: @@ -70,7 +70,7 @@ On the main menu: - When first opening the game, there should be only one character unlocked. - When a player dies, the Leaderboard should be updated accordingly to the score the player just made if it is on the 5 best score ever. - Also the Stats should be updated after every game, whether it is or it is not one of the best 5 scores ever. -- On the Leaderbord and on the Stats tabs, a button to reset all the stats should be available. +- On the Leaderboard and on the Stats tabs, a button to reset all the stats should be available. #### Android diff --git a/subjects/jumpo/audit/README.md b/subjects/jumpo/audit/README.md index 9a248703..e0853a8a 100644 --- a/subjects/jumpo/audit/README.md +++ b/subjects/jumpo/audit/README.md @@ -1,46 +1,46 @@ #### Functional -###### A main menu is displayed at the game startup, displaying 5 options? +###### Is a main menu displayed at the game startup offering 5 options? -###### Does the Credits button shows you the names of the developers that worked on the project? +###### Does the Credits button show you the names of the developers that worked on the project? -###### Does the Quit button makes the player quit the game? +###### Does the Quit button make the player quit the game? -###### Does the Start button on the main menu starts a new game? +###### Does the Start button on the main menu start a new game? -###### Does the Character button shows you the unlockable characters and the price to unlock them? +###### Does the Character button show you the unlockable characters and the price to unlock them? -###### Does the Leaderboard button shows the 5 best scores? +###### Does the Leaderboard button show the 5 best scores? -###### Does the Stats button shows the games stats (amount of coins you’ve collected overall, how many times you died, number of games and highest score)? +###### Does the Stats button show the games stats (amount of coins you have collected overall, how many times you died, number of games and highest score)? -###### Does the maps contain obstacles that the player has to dodge? +###### Does the map contain obstacles that the player has to dodge? ###### Can you confirm that there is no 3D objects in the game? ###### Is the game meant to be played in landscape mode? -###### Is the player heading right? +###### Is the player heading on the right side? -###### Is actually the background moving from right to left, giving the illusion that the player is the one moving? +###### Is the background moving from right to left, giving the illusion that the player is the one moving? ###### Is the map infinite if the character does not hit anything? ###### Does each action (running, jumping, ducking and dying) play a different flipbook? -###### When the character hits an obstacle does he dies? +###### When the character hits an obstacle does he die? -###### When the character dies does a score screen gets displayed and the player needs to enter 3 characters to save his score in the Leaderboard? +###### When the character dies, is a score screen displayed, and the player needs to enter 3 characters to save his score in the Leaderboard? ###### If the score of the player is one of the best 5 scores ever, does the Leaderboard gets updated? ###### Can the character collect coins/gems? -###### Does the invincibility bar fills up when collecting coins/gems? +###### Does the invincibility bar fill up when collecting coins/gems? -###### Does the character becomes invincible for a little while once the player touches the invincibility bar? +###### Does the character becomes invincible for a little while once the player touch the invincibility bar? -###### When the invincibility bar gets emptied does the character comes back to normal? +###### When the invincibility bar gets emptied, does the character come back to normal? ###### Are the jump and duck/roll button accessible using thumbs when holding the phone? @@ -52,19 +52,19 @@ ###### Is a pause button available to the player? -###### Does the Retry button on the pause menu starts a new game, losing the previous progress made? +###### Does the Retry button on the pause menu start a new game, losing the previous progress made? -###### Does the Menu button on the pause menu takes the player to the main menu, losing the previous progress made? +###### Does the Menu button on the pause menu take the player to the main menu, losing the previous progress made? -###### When pressing the pause button, the game stop on the background and the retry, menu and quit button appear on screen? +###### When pressing the pause button, does the game stop on the background and the retry, menu, and quit button appear on screen? -###### Does the Quit button on the pause menu, quits the entire app? +###### Does the Quit button on the pause menu, quit the entire app? -###### When quitting the app and turning back, does the Stats and Leaderboard menu still contains data? +###### When quitting the app and turning back, does the Stats and Leaderboard menu still contain data? -###### If in the Leaderboard or Stats menu you press the reset button, is all data reset to 0? +###### If in the Leaderboard or Stats menu you press the reset button, is all the data reset to 0? -###### Is the apk is built using the latest Android SDK version? +###### Is the apk built using the latest Android SDK version? #### Bonus From 3cb2a3001db6ba395f264657a6740693a11f79b5 Mon Sep 17 00:00:00 2001 From: MSilva95 Date: Mon, 25 Jan 2021 18:28:57 +0000 Subject: [PATCH 10/42] rust exam subjecs --- subjects/counting_words/README.md | 50 ++++++++++++ subjects/division_and_remainder/README.md | 14 ++-- subjects/easy_traits/README.md | 49 ++++++++++++ subjects/lastup/README.md | 36 +++++++++ subjects/queens/README.md | 92 +++++++++++++++++++++++ subjects/rot21/README.md | 44 +++++++++++ 6 files changed, 278 insertions(+), 7 deletions(-) create mode 100644 subjects/counting_words/README.md create mode 100644 subjects/easy_traits/README.md create mode 100644 subjects/lastup/README.md create mode 100644 subjects/queens/README.md create mode 100644 subjects/rot21/README.md diff --git a/subjects/counting_words/README.md b/subjects/counting_words/README.md new file mode 100644 index 00000000..dc3edb34 --- /dev/null +++ b/subjects/counting_words/README.md @@ -0,0 +1,50 @@ +## counting_words + +### Instructions + +In this program you will have to create a function `counting_words` that +receives a `&str` and returns each word and the number of times it appears on the string. + +The program will count as a word the following: + +- A number like ("0" or "1234") will count as 1. +- A simple word or letter like ("a" or "they") will count as 1. +- Two simple words joined by a single apostrophe ("it's" or "they're") will count as 1. + +The program must respect the following rules: + +- The count is case insensitive ("HELLO", "Hello", and "hello") are 3 uses of the same word. +- All forms of punctuation have to be ignored except for the apostrophe if used like the example above. +- The words can be separated by any form of whitespace (ie "\t", "\n", " "). + +### Expected Function + +```rust +fn counting_words(words: &str) -> HashMap {} +``` + +### Usage + +Here is a possible program to test your function : + +```rust +use counting_words::counting_words; +use std::collections::HashMap; + +fn main() { + println!("{:?}", counting_words("Hello, world!")); + println!("{:?}", counting_words("“Two things are infinite: the universe and human stupidity; and I'm not sure about the universe.” + ― Albert Einstein ")); + println!("{:?}", counting_words("Batman, BATMAN, batman, Stop stop")); +} +``` + +And its output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +{"hello": 1, "world": 1} +{"and": 2, "human": 1, "universe": 2, "the": 2, "i\'m": 1, "about": 1, "einstein": 1, "are": 1, "infinite": 1, "sure": 1, "albert": 1, "two": 1, "things": 1, "not": 1, "stupidity": 1} +{"batman": 3, "stop": 2} +student@ubuntu:~/[[ROOT]]/test$ +``` diff --git a/subjects/division_and_remainder/README.md b/subjects/division_and_remainder/README.md index f6a758da..71f58c97 100644 --- a/subjects/division_and_remainder/README.md +++ b/subjects/division_and_remainder/README.md @@ -20,13 +20,13 @@ Here is a program to test you're function use division_and_remainder::division_and_remainder; fn main() { - let x = 9; - let y = 4; - let (division, remainder) = divide(x, y); - println!( - "{}/{}: division = {}, remainder = {}", - x, y, division, remainder - ); + let x = 9; + let y = 4; + let (division, remainder) = divide(x, y); + println!( + "{}/{}: division = {}, remainder = {}", + x, y, division, remainder + ); } ``` diff --git a/subjects/easy_traits/README.md b/subjects/easy_traits/README.md new file mode 100644 index 00000000..8f7c5053 --- /dev/null +++ b/subjects/easy_traits/README.md @@ -0,0 +1,49 @@ +## easy_traits + +### Instructions + +Your task is to implement the trait `AppendStr` for the type String, and `AppendVec` for a vector of strings. + +The trait `AppendStr` has only one function, which is appending `"world"` to any object implementing this trait. +And `AppendVec` will append `"three"` to a vector of strings. + +### Expected Function + +```rust +trait AppendStr { + fn append_str(self) -> Self; +} + +trait AppendVec { + fn append_vec(&mut self) -> Self; +} + +impl AppendStr for String {} + +impl AppendVec for Vec {} +``` + +### Usage + +Here is a program to test your function. + +```rust +use easy_traits::easy_traits; + +fn main() { + let s = String::from("hello ").append_str(); + println!("{}", s); + + let l = vec![String::from("one"), String::from("two")].append_vec(); + println!("{:?}", l); +} +``` + +And its output + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +hello world +["one", "two", "three"] +student@ubuntu:~/[[ROOT]]/test$ +``` diff --git a/subjects/lastup/README.md b/subjects/lastup/README.md new file mode 100644 index 00000000..8c6eb910 --- /dev/null +++ b/subjects/lastup/README.md @@ -0,0 +1,36 @@ +## lastup + +### Instructions + +Complete the `lastup` function that takes a string and puts the last letter of each word in uppercase and the rest in lowercase. + +### Expected Functions + +```rust +pub fn lastup(input: &str) -> String { +} +``` + +### Usage + +Here is a program to test your function. + +```rust +use lastup::lastup; + +fn main() { + println!("{}", lastup("joe is missing")); + println!("{}", lastup("jill is leaving A")); + println!("{}",lastup("heLLo THere!")); +} +``` + +And its output + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +joE iS missinG +jilL iS leavinG A +hellO therE! +student@ubuntu:~/[[ROOT]]/test$ +``` diff --git a/subjects/queens/README.md b/subjects/queens/README.md new file mode 100644 index 00000000..493b71ff --- /dev/null +++ b/subjects/queens/README.md @@ -0,0 +1,92 @@ +## queens + +### Instructions + +In a chess game, a queen can attack pieces which are on the same row, +column, or diagonal. + +Your purpose in this exercise is to find out if two queens can attack +each other using the same rules. + +The chess board will be represented as an 8 by 8 array. + +So, given the position of the two queens on a chess board, you will have to +implement the function `can_attack` in the given struct `Queen` with +the purpose of finding out if the two queens can attack each other or not. + +For this to be possible, you will also have to implement the struct `ChessPosition` +with the function `new` that will allow you to verify if the position is valid or not. If the position is valid it will return that position and if it is invalid it will return `None`. + +So if you are told that the white queen is at (2, 3) and the black queen is at (5, 6), +then you would know you have got a set-up like so: + +``` +_ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ +_ _ _ W _ _ _ _ +_ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ +_ _ _ _ _ _ B _ +_ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ +``` + +In this case, the two queens can attack each other because both pieces share a diagonal. + +### Expected Function + +```rust +#[derive(Debug)] +pub struct ChessPosition { + rank: i32, + file: i32, +} + +#[derive(Debug)] +pub struct Queen { + position: ChessPosition, +} + +impl ChessPosition { + pub fn new(rank: i32, file: i32) -> Option {} +} + +impl Queen { + pub fn can_attack(&self, other: &Queen) -> bool {} +} +``` + +### Usage + +Here is a possible program to test your function : + +```rust +use queens::queens; + +fn main() { + let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap()); + let black_queen = Queen::new(ChessPosition::new(0, 4).unwrap()); + + println!( + "Is it possible for the queens to attack each other? => {}", + white_queen.can_attack(&black_queen) + ); + + let white_queen = Queen::new(ChessPosition::new(1, 2).unwrap()); + let black_queen = Queen::new(ChessPosition::new(0, 4).unwrap()); + + println!( + "Is it possible for the queens to attack each other? => {}", + white_queen.can_attack(&black_queen) + ); +} +``` + +And its output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +Is it possible for the queens to attack each other? => true +Is it possible for the queens to attack each other? => false +student@ubuntu:~/[[ROOT]]/test$ +``` diff --git a/subjects/rot21/README.md b/subjects/rot21/README.md new file mode 100644 index 00000000..cef47cee --- /dev/null +++ b/subjects/rot21/README.md @@ -0,0 +1,44 @@ +## rot21 + +### Instructions + +Your purpose in this exercise is to create a `rot21` function that works like the ROT13 cipher. + +Your function will receive a string and it will rotate each letter of that string 21 times to the right. + +Your function should only change letters. If the string includes punctuation, symbols and numbers +they will remain the same. + +### Expected functions + +```rust +pub fn rot21(input: &str) -> String {} +``` + +### Usage + +Here is a program to test your function. + +```rust +use rot21::rot21; + +fn main() { + println!("The letter \"a\" becomes: {}", rot21("a")); + println!("The letter \"m\" becomes: {}", rot21("m")); + println!("The word \"MISS\" becomes: {}", rot21("MISS")); + println!("Your cypher wil be: {}", rot21("Testing numbers 1 2 3")); + println!("Your cypher wil be: {}", rot21("rot21 works!")); +} + +``` + +And its output + +```console +The letter "a" becomes: v +The letter "m" becomes: h +The word "MISS" becomes: HDNN +Your cypher wil be: Oznodib iphwzmn 1 2 3 +Your cypher wil be: mjo21 rjmfn! +student@ubuntu:~/[[ROOT]]/test$ +``` From fb929c60fa67c270206c827066a74e76841e7bff Mon Sep 17 00:00:00 2001 From: Christopher Fremond <34804391+Frenchris@users.noreply.github.com> Date: Tue, 26 Jan 2021 18:02:09 +0000 Subject: [PATCH 11/42] Update README.md --- subjects/hellorust/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subjects/hellorust/README.md b/subjects/hellorust/README.md index 763401af..33950b0f 100644 --- a/subjects/hellorust/README.md +++ b/subjects/hellorust/README.md @@ -1,4 +1,4 @@ -## hellorust +## hello_rust ### Introduction From 26bc6429c027017b57ac35cf88df54ea7a43a096 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 26 Jan 2021 18:07:12 +0000 Subject: [PATCH 12/42] renaming of subject --- subjects/hello_rust/README.md | 99 +++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 subjects/hello_rust/README.md diff --git a/subjects/hello_rust/README.md b/subjects/hello_rust/README.md new file mode 100644 index 00000000..33950b0f --- /dev/null +++ b/subjects/hello_rust/README.md @@ -0,0 +1,99 @@ +## hello_rust + +### Introduction + +Hello and welcome to rust. +The goal of this first exercise is to configure your repository properly and to give you a set of rules for the whole piscine rust. +Make sure those rules are followed consistenly during the whole piscine. + +### Instructions + +#### 1- get-ready + +Create in your [Gitea](https://git.[[DOMAIN]]) account the repository named `[[ROOT]]`. + +This repository will be the folder where all the exercices must be uploaded. + +Once created, clone that repository on your desktop. + +If your username was `choumi` this is the command that will need to be used : + +`git clone git@git.[[DOMAIN]]:choumi/[[ROOT]].git` + +This command needs to be adapted with **your own username**. + +If the `git clone` gives you an authenticity of host error, your SSH key must be configured. +Follow the steps below. + +#### SSH Configuration + +Execute the following commands: + +```console +mkdir -p ~/.ssh +ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N '' +cat ~/.ssh/id_ed25519.pub +``` + +- Copy the result and paste it in the content field of adding an ssh key in your settings (adapt the link with your username). + +[https://git.[[DOMAIN]]/choumi/settings/keys](https://git.[[DOMAIN]]/choumi/settings/keys) + +- Confirm by clicking on the add key button. + +Once this is done the git clone command should work now. + +#### gitignore file + +Once you repository is cloned, +create and edit the .gitignore file in your repository and add this line: +```console +**/target/* +``` +The goal of this setup is to avoid any binary files to be pushed in your gitea accidentaly. + + +#### 2- get-ready + +Below are the commands that you must use during this piscine for initiating programs and functions. This command that you are going to depend in what is asked in the subject. + +#### Commands for a program + +```console +cargo new --vcs=none name-of-exercise +``` + +#### Commands for a function + +```console +cargo --vcs=none new --lib name-of-exercise +``` + +#### 3- try it yourself + +Execute the below command inside your repository + +```console +cargo new --vcs=none hello_rust +``` + +Then adapt the `main.rs` so that it would display `Hello, Rust!` + +You can test it with the below command inside the folder of your exercise. + +```console +cargo run +``` +This command will compile, and run the binary. + +#### 4- return your solution + +After that the `hello_rust` project is executing correctly, it needs to be uploaded to the repository with the following commands : + +1. `git add hello_rust/` +2. `git commit -m "My very first rust commit"` +3. `git push` + +Once these steps are applied, the project can now be submitted for grading on the platform by clicking on the "RUN HELLO_RUST..." button. + +This action will run the tests on your submitted `hello_rust` folder. From ec36485648cd0275cde7cb0abeb7530c8c38eda7 Mon Sep 17 00:00:00 2001 From: Augusto Date: Tue, 26 Jan 2021 18:39:16 +0000 Subject: [PATCH 13/42] Fix a typo in the roman_numbers exercise --- subjects/roman_numbers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subjects/roman_numbers/README.md b/subjects/roman_numbers/README.md index c4c8ea5c..2b6ff317 100644 --- a/subjects/roman_numbers/README.md +++ b/subjects/roman_numbers/README.md @@ -1,7 +1,7 @@ ## roman_numbers ### Instructions -Implement the From Trait to create a roman number from a u32 the roman number should be in subtractive notation (the common way to write roman number I, II, II, IV, V, VI, VII, VIII, IX, X ...) +Implement the From Trait to create a roman number from a u32 the roman number should be in subtractive notation (the common way to write roman number I, II, III, IV, V, VI, VII, VIII, IX, X ...) For this start by defining the digits as `RomanDigit` with the values I, V, X, L, C, D, M and Nulla for 0 From df14481572e292c5b8df62df2a83e0da1744ab39 Mon Sep 17 00:00:00 2001 From: Augusto Date: Tue, 26 Jan 2021 18:40:34 +0000 Subject: [PATCH 14/42] Add the subject for the exercise display_table --- subjects/display_table/README.md | 79 ++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 subjects/display_table/README.md diff --git a/subjects/display_table/README.md b/subjects/display_table/README.md new file mode 100644 index 00000000..a5453699 --- /dev/null +++ b/subjects/display_table/README.md @@ -0,0 +1,79 @@ +## display_table + +### Instructions + +- Implement the std::fmt::Display trait for the structure table so the table is printed like in the [Usage](#usage) the length of each column must adjust to the longest element of the column and the element must be centered in the "cell" when possible, if the length of the element doesn't allow to center exactly it must alight slightly to the right. + + - Note: If the table is empty `println!` must not print anything. + +- Define the associated function `new` that create a new empty table. + +- Define the method function `add_row` that adds a new row to the table created from a slice of strings. + +### Expected function + +```rust +pub struct Table { + pub headers: Vec, + pub body: Vec>, +} + +impl fmt::Display for Table { +} + +impl Table { + fn new() -> Table { + } + + fn add_row(&mut self, row: &[String]) { + } +} +``` + +### Usage + +Here is a possible test for your function: + +```rust +fn main() { + let mut table = Table::new(); + println!("{}", table); + table.headers = vec![ + String::from("Model"), + String::from("Piece N°"), + String::from("In Stock"), + String::from("Description"), + ]; + table.add_row(&[ + String::from("model 1"), + String::from("43-EWQE304"), + String::from("30"), + String::from("Piece for x"), + ]); + table.add_row(&[ + String::from("model 2"), + String::from("98-QCVX5433"), + String::from("100000000"), + String::from("-"), + ]); + table.add_row(&[ + String::from("model y"), + String::from("78-NMNH"), + String::from("60"), + String::from("nothing"), + ]); + println!("{}", table); +} +``` + +And its output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +| Model | Piece N° | In Stock | Description | +|---------+-------------+-----------+-------------| +| model 1 | 43-EWQE304 | 30 | Piece for x | +| model 2 | 98-QCVX5433 | 100000000 | - | +| model y | 78-NMNH | 60 | nothing | +student@ubuntu:~/[[ROOT]]/test$ +``` From eec65f28a9671940fa78e876854d7ae35bdff580 Mon Sep 17 00:00:00 2001 From: Augusto Date: Tue, 26 Jan 2021 22:11:16 +0000 Subject: [PATCH 15/42] Add the subject for the exercise `display_table` --- subjects/display_table/README.md | 4 +- subjects/filter_table/README.md | 85 ++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 subjects/filter_table/README.md diff --git a/subjects/display_table/README.md b/subjects/display_table/README.md index a5453699..31419c7f 100644 --- a/subjects/display_table/README.md +++ b/subjects/display_table/README.md @@ -22,10 +22,10 @@ impl fmt::Display for Table { } impl Table { - fn new() -> Table { + pub fn new() -> Table { } - fn add_row(&mut self, row: &[String]) { + pub fn add_row(&mut self, row: &[String]) { } } ``` diff --git a/subjects/filter_table/README.md b/subjects/filter_table/README.md new file mode 100644 index 00000000..f33ce790 --- /dev/null +++ b/subjects/filter_table/README.md @@ -0,0 +1,85 @@ +## filter_table + +### Instructions + +- Define the functions: + + - new: creates a new empty table. + + - add_rows: adds a new row to the table from a slice of strings. + + - filter_cols: that receives a closure that receives a `&str` and returns a `bool` value: + + - filter_cols returns a table with all the columns that yielded true when applied to the header. + + - filter_rows: that receives a closure that receives a `&str` and returns a `bool` value + + - filter_rows returns a table with all the columns that yielded true when applied to the elements of the selected column. + +### Expected function + +```rust +pub struct Table { + pub headers: Vec, + pub body: Vec>, +} + +impl Table { + pub fn new() -> Table { + } + + pub fn add_row(&mut self, row: &[String]) { + } + + pub fn filter_col(&self, filter: ) -> Option { + + } + + pub fn filter_row(&self, col_name: &str, filter: ) -> Option { + } +} +``` + +### Usage + +Here is a possible test for your function: + +```rust +fn main() { + let mut table = Table::new(); + table.headers = vec![ + "Name".to_string(), + "Last Name".to_string(), + "ID Number".to_string(), + ]; + table.add_row(&[ + "Adam".to_string(), + "Philips".to_string(), + "123456789".to_string(), + ]); + table.add_row(&[ + "Adamaris".to_string(), + "Shelby".to_string(), + "1111123456789".to_string(), + ]); + table.add_row(&[ + "Ackerley".to_string(), + "Philips".to_string(), + "123456789".to_string(), + ]); + let filter_names = |col: &str| col == "Name"; + println!("{:?}", table.filter_col(filter_names)); + + let filter_philips = |lastname: &str| lastname == "Philips"; + println!("{:?}", table.filter_row("Last Name", filter_philips)); +} +``` + +And its output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +Some(Table { headers: ["Name"], body: [["Adam"], ["Adamaris"], ["Ackerley"]] }) +Some(Table { headers: ["Name", "Last Name", "ID Number"], body: [["Adam", "Philips", "123456789"], ["Ackerley", "Philips", "123456789"]] }) +student@ubuntu:~/[[ROOT]]/test$ +``` From 7397c5c7b49d6fbab46f40e10236c6b8ed889b31 Mon Sep 17 00:00:00 2001 From: Augusto Date: Wed, 27 Jan 2021 10:20:27 +0000 Subject: [PATCH 16/42] Add the subject for the exercise `flat_tree` --- subjects/flat_tree/README.md | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 subjects/flat_tree/README.md diff --git a/subjects/flat_tree/README.md b/subjects/flat_tree/README.md new file mode 100644 index 00000000..3ecda4c6 --- /dev/null +++ b/subjects/flat_tree/README.md @@ -0,0 +1,43 @@ +## flat_rust + +### Instructions + +- Define the functions `flatten_tree` that receives a std::collections::BTreeSet and returns a new `Vec` with the elements in the binary tree in order. + +### Expected function + +```rust +pub fn flatten_tree>(tree: &BTreeSet) -> Vec { +} +``` + +### Usage + +Here is a possible test for your function: + +```rust +fn main() { + let mut tree = BTreeSet::new(); + tree.insert(34); + tree.insert(0); + tree.insert(9); + tree.insert(30); + println!("{:?}", flatten_tree(&tree)); + + let mut tree = BTreeSet::new(); + tree.insert("Slow"); + tree.insert("kill"); + tree.insert("will"); + tree.insert("Horses"); + println!("{:?}", flatten_tree(&tree)); +} +``` + +And its output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +[0, 9, 30, 34] +["Horses", "Slow", "kill", "will"] +student@ubuntu:~/[[ROOT]]/test$ +``` From 6d4ca52b21b9001c68f4ad33bcc89e550dca63cf Mon Sep 17 00:00:00 2001 From: Augusto Date: Wed, 27 Jan 2021 12:17:25 +0000 Subject: [PATCH 17/42] Add the subject for the exercise `blood_types_s` A simplified version of `blood_types` --- subjects/blood_types_s/README.md | 92 ++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 subjects/blood_types_s/README.md diff --git a/subjects/blood_types_s/README.md b/subjects/blood_types_s/README.md new file mode 100644 index 00000000..9fe00071 --- /dev/null +++ b/subjects/blood_types_s/README.md @@ -0,0 +1,92 @@ +## blood_types_s + +### Instructions + +Use the following table to define the methods asked: + +| Blood Types | Donate Blood to | Receive Blood From | +|-------------|------------------|--------------------| +| A+ | A+, AB+ | A+, A-, O+, O- | +| O+ | O+, A+, B+, AB+ | O+, O- | +| B+ | O+, O- | B+, B-, O+, O- | +| AB+ | AB+ | Everyone | +| A- | A+, A-, AB+, AB- | A-, O- | +| O- | Everyone | O- | +| B- | B+, B-, AB+, AB- | B-, O- | +| AB- | AB+, AB- | AB-, A-, B-, O- | + +Write three methods for BloodType: + +- `can_receive_from`: which returns true if `self` can receive blood from `other` blood type +- `donors`: which returns all the blood types that can give blood to `self` +- `recipients`: which returns all the blood types that can receive blood from `self` + +### Expected Functions and Structures + +```rust +#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)] +pub enum Antigen { + A, + AB, + B, + O, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +enum RhFactor { + Positive, + Negative, +} + +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] +pub struct BloodType { + pub antigen: Antigen, + pub rh_factor: RhFactor, +} + +impl BloodType { + pub fn can_receive_from(&self, other: &Self) -> bool { + } + + pub fn donors(&self) -> Vec { + } + + pub fn recipients(&self) -> Vec { +} +``` + +### Usage + +Here is a program to test your function. + +```rust +use blood_types_s::{Antigen, BloodType, RhFactor}; + +fn main() { + let blood_type = BloodType { + antigen: Antigen::O, + rh_factor: RhFactor::Positive, + }; + println!("recipients of O+ {:?}", blood_type.recipients()); + println!("donors of O+ {:?}", blood_type.donors()); + let another_blood_type = BloodType { + antigen: Antigen::O, + rh_factor: RhFactor::Positive, + }; + println!( + "donors of O+ can receive from {:?} {:?}", + &another_blood_type, + blood_type.can_receive_from(&another_blood_type) + ); +} +``` + +And its output + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +recipients of O+ [BloodType { antigen: AB, rh_factor: Positive }, BloodType { antigen: O, rh_factor: Positive }, BloodType { antigen: A, rh_factor: Positive }, BloodType { antigen: B, rh_factor: Positive }] +donors of O+ [BloodType { antigen: O, rh_factor: Positive }, BloodType { antigen: O, rh_factor: Negative }] +donors of O+ can receive from BloodType { antigen: O, rh_factor: Positive } true +student@ubuntu:~/[[ROOT]]/test$ +``` From 65ba9208fcd311a0ac08f522f84fca0d55b6e6f5 Mon Sep 17 00:00:00 2001 From: OGordoo Date: Wed, 27 Jan 2021 14:46:34 +0000 Subject: [PATCH 18/42] new subjects for rust exams --- subjects/brain_fuck/README.md | 42 ++++++++++++++++++ subjects/nextprime/README.md | 37 ++++++++++++++++ subjects/previousprime/README.md | 33 +++++++++++++++ subjects/rpn/README.md | 73 ++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+) create mode 100644 subjects/brain_fuck/README.md create mode 100644 subjects/nextprime/README.md create mode 100644 subjects/previousprime/README.md create mode 100644 subjects/rpn/README.md diff --git a/subjects/brain_fuck/README.md b/subjects/brain_fuck/README.md new file mode 100644 index 00000000..b6832d5c --- /dev/null +++ b/subjects/brain_fuck/README.md @@ -0,0 +1,42 @@ +## brain_fuck + +### Instructions + +Write a `Brainfuck` interpreter program. +The source code will be given as first parameter. +The code will always be valid, with less than 4096 operations. +`Brainfuck` is a minimalist language. It consists of an array of bytes (in this exercice 2048 bytes) all initialized with zero, and with a pointer to its first byte. + +Every operator consists of a single character : + +- '>' increment the pointer +- '<' decrement the pointer +- '+' increment the pointed byte +- '-' decrement the pointed byte +- '.' print the pointed byte on standard output +- '[' go to the matching ']' if the pointed byte is 0 (loop start) +- ']' go to the matching '[' if the pointed byte is not 0 (loop end) + +Any other character is a comment. + +For receiving arguments from the command line you should use something like: + +```rust + fn main() { + let args: Vec = std::env::args().collect(); + + rpn(&args[1]); + } + +``` + +### Usage + +```console +$ cargo run "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>." +Hello World! +$ cargo run "+++++[>++++[>++++H>+++++i<<-]>>>++\n<<<<-]>>--------.>+++++.>." +Hi +$ cargo run "++++++++++[>++++++++++>++++++++++>++++++++++<<<-]>---.>--.>-.>++++++++++." +abc +``` diff --git a/subjects/nextprime/README.md b/subjects/nextprime/README.md new file mode 100644 index 00000000..5c1ef2fc --- /dev/null +++ b/subjects/nextprime/README.md @@ -0,0 +1,37 @@ +## nextprime + +### Instructions + +Write a function that returns the first prime number that is equal or superior to the `int` passed as parameter. + +The function must be optimized in order to avoid time-outs with the tester. + +(We consider that only positive numbers can be prime numbers) + +### Expected function + +```rust +pub fn next_prime(nbr: u64) -> u64 { + +} +``` + +### Usage + +Here is a possible program to test your function : + +```rust +fn main() { + println!("The next prime after 4 is: {}", next_prime(4)); + println!("The next prime after 11 is: {}", next_prime(11)); +} +``` + +And its output : + +```console +$ cargo run +The next prime after 4 is: 5 +The next prime after 11 is: 11 +$ +``` diff --git a/subjects/previousprime/README.md b/subjects/previousprime/README.md new file mode 100644 index 00000000..44ddbd0d --- /dev/null +++ b/subjects/previousprime/README.md @@ -0,0 +1,33 @@ +## prev_prime + +### Instructions + +Write a function that returns the first prime number that is equal or inferior to the `int` passed as parameter. + +If there are no primes inferior to the `int` passed as parameter the function should return 0. + +### Expected function + +```rust +pub fn prev_prime(nbr: u64) -> u64 { + +} +``` + +### Usage + +Here is a possible [program](TODO-LINK) to test your function : + +```rust +fn main() { + println!("The previous prime number before 34 is: {}", prev_prime(34)); +} +``` + +And its output : + +```console +$ cargo run +The previous prime number before 34 is: 31 +$ +``` diff --git a/subjects/rpn/README.md b/subjects/rpn/README.md new file mode 100644 index 00000000..122f90f5 --- /dev/null +++ b/subjects/rpn/README.md @@ -0,0 +1,73 @@ +## rpn + +### Instructions + +Write a program that takes a `string` which contains an equation written in +`Reverse Polish Notation` (RPN) as its first argument, that evaluates the equation, and that +prints the result on the standard output followed by a newline (`'\n'`). + +`Reverse Polish Notation` is a mathematical notation in which every operator +follows all of its operands. In RPN, every operator encountered evaluates the +previous 2 operands, and the result of this operation then becomes the first of +the two operands for the subsequent operator. Operands and operators must be +spaced by at least one space. + +The following operators must be implemented : `+`, `-`, `*`, `/`, and `%`. + +If the `string` is not valid or if there is not exactly one argument, `Error` must be printed +on the standard output followed by a newline. +If the `string` has extra spaces it is still considered valid. + +All the given operands must fit in a `int`. + +Examples of formulas converted in RPN: + +3 + 4 >> 3 4 + + +((1 \* 2) \* 3) - 4 >> 1 2 \* 3 \* 4 - or 3 1 2 \* \* 4 - + +50 \* (5 - (10 / 9)) >> 5 10 9 / - 50 \* + +Here is how to evaluate a formula in RPN: + +``` +1 2 * 3 * 4 - +2 3 * 4 - +6 4 - +2 +``` + +Or: + +``` +3 1 2 * * 4 - +3 2 * 4 - +6 4 - +2 +``` + +For receiving arguments from the command line you should use something like: + +```rust + fn main() { + let args: Vec = std::env::args().collect(); + + rpn(&args[1]); + } + +``` + +### Usage + +````console +$ cargo run "1 2 * 3 * 4 +" +10 +$ cargo run "1 2 3 4 +" +Error +$ cargo run +Error +$ cargo run " 1 3 * 2 -" +1 +$ cargo run " 1 3 * ksd 2 -" +Error``` +```` From 6f057baf12ebdcd0ee16d282874ccdb03258eb51 Mon Sep 17 00:00:00 2001 From: OGordoo Date: Wed, 27 Jan 2021 14:53:44 +0000 Subject: [PATCH 19/42] brain_fuck fix --- subjects/brain_fuck/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subjects/brain_fuck/README.md b/subjects/brain_fuck/README.md index b6832d5c..abcf729d 100644 --- a/subjects/brain_fuck/README.md +++ b/subjects/brain_fuck/README.md @@ -25,7 +25,7 @@ For receiving arguments from the command line you should use something like: fn main() { let args: Vec = std::env::args().collect(); - rpn(&args[1]); + brain_fuck(&args[1]); } ``` From a59ab0eed95a593e2002f68f72a46fa877f9a83c Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 27 Jan 2021 15:52:41 +0000 Subject: [PATCH 20/42] typo fix --- subjects/hello_rust/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subjects/hello_rust/README.md b/subjects/hello_rust/README.md index 33950b0f..0747855c 100644 --- a/subjects/hello_rust/README.md +++ b/subjects/hello_rust/README.md @@ -66,7 +66,7 @@ cargo new --vcs=none name-of-exercise #### Commands for a function ```console -cargo --vcs=none new --lib name-of-exercise +cargo new --vcs=none --lib name-of-exercise ``` #### 3- try it yourself From 9b2ea16be389853655499c98907c93d9018d4930 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 27 Jan 2021 15:53:41 +0000 Subject: [PATCH 21/42] cleanup of wrong folder --- subjects/hellorust/README.md | 99 ------------------------------------ 1 file changed, 99 deletions(-) delete mode 100644 subjects/hellorust/README.md diff --git a/subjects/hellorust/README.md b/subjects/hellorust/README.md deleted file mode 100644 index 33950b0f..00000000 --- a/subjects/hellorust/README.md +++ /dev/null @@ -1,99 +0,0 @@ -## hello_rust - -### Introduction - -Hello and welcome to rust. -The goal of this first exercise is to configure your repository properly and to give you a set of rules for the whole piscine rust. -Make sure those rules are followed consistenly during the whole piscine. - -### Instructions - -#### 1- get-ready - -Create in your [Gitea](https://git.[[DOMAIN]]) account the repository named `[[ROOT]]`. - -This repository will be the folder where all the exercices must be uploaded. - -Once created, clone that repository on your desktop. - -If your username was `choumi` this is the command that will need to be used : - -`git clone git@git.[[DOMAIN]]:choumi/[[ROOT]].git` - -This command needs to be adapted with **your own username**. - -If the `git clone` gives you an authenticity of host error, your SSH key must be configured. -Follow the steps below. - -#### SSH Configuration - -Execute the following commands: - -```console -mkdir -p ~/.ssh -ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N '' -cat ~/.ssh/id_ed25519.pub -``` - -- Copy the result and paste it in the content field of adding an ssh key in your settings (adapt the link with your username). - -[https://git.[[DOMAIN]]/choumi/settings/keys](https://git.[[DOMAIN]]/choumi/settings/keys) - -- Confirm by clicking on the add key button. - -Once this is done the git clone command should work now. - -#### gitignore file - -Once you repository is cloned, -create and edit the .gitignore file in your repository and add this line: -```console -**/target/* -``` -The goal of this setup is to avoid any binary files to be pushed in your gitea accidentaly. - - -#### 2- get-ready - -Below are the commands that you must use during this piscine for initiating programs and functions. This command that you are going to depend in what is asked in the subject. - -#### Commands for a program - -```console -cargo new --vcs=none name-of-exercise -``` - -#### Commands for a function - -```console -cargo --vcs=none new --lib name-of-exercise -``` - -#### 3- try it yourself - -Execute the below command inside your repository - -```console -cargo new --vcs=none hello_rust -``` - -Then adapt the `main.rs` so that it would display `Hello, Rust!` - -You can test it with the below command inside the folder of your exercise. - -```console -cargo run -``` -This command will compile, and run the binary. - -#### 4- return your solution - -After that the `hello_rust` project is executing correctly, it needs to be uploaded to the repository with the following commands : - -1. `git add hello_rust/` -2. `git commit -m "My very first rust commit"` -3. `git push` - -Once these steps are applied, the project can now be submitted for grading on the platform by clicking on the "RUN HELLO_RUST..." button. - -This action will run the tests on your submitted `hello_rust` folder. From a8ecdb0587be979e2a826f1255dab5a297b32b47 Mon Sep 17 00:00:00 2001 From: augusto-mantilla Date: Thu, 28 Jan 2021 15:55:12 +0000 Subject: [PATCH 22/42] Add missing line in the subject --- subjects/rot21/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/subjects/rot21/README.md b/subjects/rot21/README.md index cef47cee..aa20978f 100644 --- a/subjects/rot21/README.md +++ b/subjects/rot21/README.md @@ -35,6 +35,7 @@ fn main() { And its output ```console +student@ubuntu:~/[[ROOT]]/test$ cargo run The letter "a" becomes: v The letter "m" becomes: h The word "MISS" becomes: HDNN From 797c1a4c05c62a0ead5ce7df7301d428cc791cb7 Mon Sep 17 00:00:00 2001 From: Augusto Date: Thu, 28 Jan 2021 20:47:58 +0000 Subject: [PATCH 23/42] Fix typos in the subject of the exercise blood_types --- subjects/blood_types/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/subjects/blood_types/README.md b/subjects/blood_types/README.md index 5aba94f1..061abb96 100644 --- a/subjects/blood_types/README.md +++ b/subjects/blood_types/README.md @@ -2,12 +2,12 @@ ### Instructions -In this exercise you will create a model data model of blood types and an API to deal with blood types +In this exercise you will create a data model of blood types and an API to deal with blood types -Start by creating the data representation of the blood types: +Start by copying the data representation of the blood types: - Create the enumerator `Antigen` that has 4 possibilities: A, B, O and AB And the enumerator `RhFactor` that has two possible values: Positive and Negative -- After, create the struct BloodType that contains two fields with the names antigen and rh_factor +- After, copy the struct BloodType that contains two fields with the names antigen and rh_factor - To provide a simple way to create blood types implement the trait FromStr for BloodType (which will allow us to use the `parse` method and the associated function from_str, so we can do: @@ -19,11 +19,11 @@ Start by creating the data representation of the blood types: - Implement the trait std::Debug for BloodType allowing to print a vector such as [BloodType { antigen: A, rh_factor: Positive}, BloodType{ antigen: B, rh_factor: Negative}] as [ A+, A-] using the formatting {:?} -Write three methods for BloodType: +- Lastly, write three methods for BloodType: -- `can_receive_from`: which returns true if self can receive blood from `other` blood type -- `donors`: which returns all the blood types that can give blood to self -- `recipients`: which returns all the blood types that can receive blood from self + - `can_receive_from`: which returns true if `self` can receive blood from `other` blood type + - `donors`: which returns all the blood types that can give blood to `self` + - `recipients`: which returns all the blood types that can receive blood from `self` ### Expected Functions and Structures From f231674fc9be8efdce8140aa2ea97a0b64ebfe2f Mon Sep 17 00:00:00 2001 From: xpetit <32063953+xpetit@users.noreply.github.com> Date: Mon, 1 Feb 2021 14:55:58 +0100 Subject: [PATCH 24/42] Update docker-compose version --- sh/debian/configure.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sh/debian/configure.sh b/sh/debian/configure.sh index cbb27f8c..102892d7 100755 --- a/sh/debian/configure.sh +++ b/sh/debian/configure.sh @@ -126,9 +126,9 @@ 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.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose +curl -L "https://github.com/docker/compose/releases/download/1.28.2/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.27.4/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose +curl -L https://raw.githubusercontent.com/docker/compose/1.28.2/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose # Generate SSH key ssh-keygen -ted25519 -f ~/.ssh/id_ed25519 -N '' From 55ecdeb58a1d69b7ac48de2eee14ba90317fe98f Mon Sep 17 00:00:00 2001 From: xpetit <32063953+xpetit@users.noreply.github.com> Date: Mon, 1 Feb 2021 15:28:26 +0100 Subject: [PATCH 25/42] use Cloudflare DNS server --- sh/debian/configure.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sh/debian/configure.sh b/sh/debian/configure.sh index 102892d7..2efabe5a 100755 --- a/sh/debian/configure.sh +++ b/sh/debian/configure.sh @@ -133,6 +133,9 @@ curl -L https://raw.githubusercontent.com/docker/compose/1.28.2/contrib/completi # 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 From bd3d3d80a18752445d006208a9953b94a040cc16 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 1 Feb 2021 18:08:30 +0000 Subject: [PATCH 26/42] precisions added --- subjects/hello_rust/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/subjects/hello_rust/README.md b/subjects/hello_rust/README.md index 0747855c..5201edaa 100644 --- a/subjects/hello_rust/README.md +++ b/subjects/hello_rust/README.md @@ -52,6 +52,11 @@ create and edit the .gitignore file in your repository and add this line: ``` The goal of this setup is to avoid any binary files to be pushed in your gitea accidentaly. +Do not forget to push it to your repository. + +1. `git add .gitignore` +2. `git commit -m "My very first gitignore commit"` +3. `git push` #### 2- get-ready @@ -71,7 +76,7 @@ cargo new --vcs=none --lib name-of-exercise #### 3- try it yourself -Execute the below command inside your repository +Execute the below command for creating a **program** inside your repository ```console cargo new --vcs=none hello_rust From 7f9e8fa957d7a127f9c07dfdab736377324c416b Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 2 Feb 2021 13:20:52 +0000 Subject: [PATCH 27/42] details added --- subjects/fibonacci2/README.md | 16 +++++++++++---- subjects/scalar/README.md | 37 ++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/subjects/fibonacci2/README.md b/subjects/fibonacci2/README.md index 7cd2af06..681e4633 100644 --- a/subjects/fibonacci2/README.md +++ b/subjects/fibonacci2/README.md @@ -2,12 +2,21 @@ ### Instructions -Complete the body of the function `fibonacci`. +Complete the body of the **function** `fibonacci`. -This functions receives a number n and returns the nth number in the fibonacci series. +This functions receives a number `n` and returns the nth number in the fibonacci series. -The Fibonacci Series starts like this: 0, 1, 1, 2, 3, 5, 8, 13... so fibonacci(2) = 1 and fibonnacci(4) = 3 +The Fibonacci Series starts like this: 0, 1, 1, 2, 3, 5, 8, 13 etc... +Each number in the series is calculated by the summing of the two previous ones (With the exception of the two first ones which are defined as 0 and 1). +- so fibonacci(2) = 1 (1 + 1) +- and fibonnacci(4) = 3 (1 + 2) +### TNotions + +#### Primitives +- https://doc.rust-lang.org/stable/rust-by-example/primitives.html +#### Functions +- https://doc.rust-lang.org/stable/rust-by-example/fn.html ### Expected function @@ -42,4 +51,3 @@ The element in the position 22 in fibonacci series is 17711 The element in the position 20 in fibonacci series is 6765 student@ubuntu:~/[[ROOT]]/test$ ``` - diff --git a/subjects/scalar/README.md b/subjects/scalar/README.md index c7c20e72..6f86ed9d 100644 --- a/subjects/scalar/README.md +++ b/subjects/scalar/README.md @@ -1,43 +1,52 @@ -## Scaler +## Scalar ### Instructions -Create the following functions, that receives two parameters: -- sum, that returns the sum between two values from 0 to 255 -- diff, that returns the difference between two values from -32768 to 32767 -- pro, that returns the product of the multiplication between two values from -128 to 127 -- quo, that returns the quotient of the division between two values -- rem, that returns the remainder of the division between two values +Create the following **functions**, which each receives two parameters: +- `sum`, which returns the sum between two values from 0 to 255 +- `diff`, which returns the difference between two values from -32768 to 32767 +- `pro`, which returns the product of the multiplication between two values from -128 to 127 +- `quo`, which returns the quotient of the division between two values (32bit and you have to figure out the second part) +- `rem`, which returns the remainder of the division between two values (32bit and you have to figure out the second part) + +You **must** complete the Expected functions parameters data type accordingly (Replace the Xs)! + ### Notions - https://doc.rust-lang.org/book/ch03-02-data-types.html -### Expected functions +### Expected functions (Incomplete, you must precise the Data Types) ```rust -pub fn sum(a:, b: ) -> { +pub fn sum(a: X , b: X) -> X { } -pub fn diff(a: , b: ) -> { +pub fn diff(a: X, b: X) -> X { } -pub fn pro(a: , b: ) -> { +pub fn pro(a: X, b: X) -> X { } -pub fn quo(a: , b: ) -> { +pub fn quo(a: X, b: X) -> X { } -pub fn rem(a: , b: ) -> { +pub fn rem(a: X, b: X) -> X { } ``` -### Usage: +### Usage (do not forget to comment the ERROR test if you want to use all the tests): ```rust +use scalar::sum; +use scalar::diff; +use scalar::pro; +use scalar::quo; +use scalar::rem; + fn main() { // sum println!("sum : {}", sum(234, 2)); From 10abb32eeefed91d861dee5cf6bec31a578a211b Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 3 Feb 2021 18:59:38 +0000 Subject: [PATCH 28/42] various clarifications and reformating --- subjects/fibonacci2/README.md | 8 +++----- subjects/find_factorial/README.md | 8 +++++++- subjects/groceries/README.md | 11 ++++++----- subjects/looping/README.md | 6 +++--- subjects/matrix_transposition/README.md | 22 ++++++++++++++++------ subjects/reverse_string/README.md | 11 +++++++++-- subjects/scalar/README.md | 25 +++++++++++-------------- subjects/speed_transformation/README.md | 5 +++-- subjects/temperature_conv/README.md | 21 ++++++++++++++++----- 9 files changed, 74 insertions(+), 43 deletions(-) diff --git a/subjects/fibonacci2/README.md b/subjects/fibonacci2/README.md index 681e4633..2b53c86b 100644 --- a/subjects/fibonacci2/README.md +++ b/subjects/fibonacci2/README.md @@ -11,12 +11,10 @@ Each number in the series is calculated by the summing of the two previous ones - so fibonacci(2) = 1 (1 + 1) - and fibonnacci(4) = 3 (1 + 2) -### TNotions +### Notions -#### Primitives -- https://doc.rust-lang.org/stable/rust-by-example/primitives.html -#### Functions -- https://doc.rust-lang.org/stable/rust-by-example/fn.html +- [Primitives](https://doc.rust-lang.org/stable/rust-by-example/primitives.html) +- [Functions](https://doc.rust-lang.org/stable/rust-by-example/fn.html) ### Expected function diff --git a/subjects/find_factorial/README.md b/subjects/find_factorial/README.md index dfb88d15..183e78fe 100644 --- a/subjects/find_factorial/README.md +++ b/subjects/find_factorial/README.md @@ -2,7 +2,13 @@ ### Instruccions -Complete the function `factorial` to return the factorial of a given number +Complete the **function** `factorial` to return the factorial of a given number. + +As a reminder the factorial of a number is the product of all the integers from 1 to that number. + +Example: the factorial of 6 (written 6!) is 1*2*3*4*5*6 = 720. + +Do not forget the rules for 0 and 1. ### Expected Function diff --git a/subjects/groceries/README.md b/subjects/groceries/README.md index eeac4cb2..28c00fa5 100644 --- a/subjects/groceries/README.md +++ b/subjects/groceries/README.md @@ -2,13 +2,14 @@ ### Instructions -Create a function called `insert` that inserts a new element at the end of the Vec +Create a **function** called `insert` that inserts a new element at the end of the `Vec`. -And another function `at_index` that returns the value found at the index passed as an argument +And another **function** `at_index` that returns the value found at the index passed as an argument. ### Notions -[Common Collections]( https://doc.rust-lang.org/stable/book/ch08-00-common-collections.html) +- [Common Collections](https://doc.rust-lang.org/stable/book/ch08-00-common-collections.html) +- [Vectors]https://doc.rust-lang.org/stable/book/ch08-01-vectors.html) ### Expected Functions @@ -16,7 +17,7 @@ And another function `at_index` that returns the value found at the index passed pub fn insert(vec: &mut Vec, val: String) { } -pub fn at_index(vec: &Vec, index: ) -> String { +pub fn at_index(vec: &Vec, index: usize) -> String { } ``` @@ -25,7 +26,7 @@ pub fn at_index(vec: &Vec, index: ) -> String { Here is a possible program to test your function: ```rust -use groceries::{insert, at_index} +use groceries::{insert, at_index}; fn main() { let mut groceries = vec![ diff --git a/subjects/looping/README.md b/subjects/looping/README.md index 0be35338..982b05b6 100644 --- a/subjects/looping/README.md +++ b/subjects/looping/README.md @@ -2,11 +2,11 @@ ### Instructions -Write a program that prints a riddle, receives input from the user and checks that the answer is correct +Write a **program** that prints a riddle, receives input from the user and checks that the answer is correct. -The program must allow indefinite number of trials and only quit after the correct answer is given +The program must allow indefinite number of trials and only quit after the correct answer is given. -Every time the user introduces an incorrect answer the program must print the riddle again and after the user gives the correct answer the program must print the number of tries that took to get the correct answer +Every time the user introduces an incorrect answer the program must print the riddle again and after the user gives the correct answer the program must print the number of tries that took to get the correct answer. Riddle: I am the beginning of the end, and the end of time and space. I am essential to creation, and I surround every place. What am I? diff --git a/subjects/matrix_transposition/README.md b/subjects/matrix_transposition/README.md index a1d479fe..2357a77e 100644 --- a/subjects/matrix_transposition/README.md +++ b/subjects/matrix_transposition/README.md @@ -2,9 +2,9 @@ ### Instructions -- Define the structure matrix as a tuple of tuples of `i32`'s +- Define the structure matrix as a tuple of 2 tuples of 2 `i32`'s. -- Define a function that calculate the transpose matrix of a 2x2 matrix. +- Define a function that calculates the transpose matrix of a 2x2 matrix. - Note: @@ -17,13 +17,21 @@ Example: ( c d ) ( b d ) ``` -- Matrix must implement Debug, PartialEq and Eq. You can use derive +- Matrix must implement Debug, PartialEq and Eq. You can use derive. -- Remember that you're defining a library so you have to make public the elements that are going to be called from an external crate. +- Remember that you are defining a library so you have to make public the elements that are going to be called from an external crate. ### Notions -[Chapter 7]( https://doc.rust-lang.org/stable/book/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html ) +- [Defining a struct](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html) + +- [The Tuple Type](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html?highlight=accessing%20a%20tuple#compound-types) + +- [Tuple Structs without Named Fields](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html?highlight=tuple#using-tuple-structs-without-named-fields-to-create-different-types) + +- [Adding Useful Functionality with Derived Traits](https://doc.rust-lang.org/stable/book/ch05-02-example-structs.html?highlight=debug%20deriv#adding-useful-functionality-with-derived-traits) + +- [Chapter 7](https://doc.rust-lang.org/stable/book/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html) ### Expected Function @@ -37,6 +45,8 @@ pub fn transpose(m: Matrix) -> Matrix { Here is a posible program to test your function ```rust +use matrix_transposition::transpose; + fn main() { let matrix = Matrix((1, 3), (4, 5)); println!("Original matrix {:?}", matrix); @@ -44,7 +54,7 @@ fn main() { } ``` -And it's output: +And its output: ```console student@ubuntu:~/[[ROOT]]/test$ cargo run diff --git a/subjects/reverse_string/README.md b/subjects/reverse_string/README.md index 2dbc251a..25b8aed4 100644 --- a/subjects/reverse_string/README.md +++ b/subjects/reverse_string/README.md @@ -2,7 +2,14 @@ ### Instructions -Write a function `rev_str` that takes a `&str` as a parameter, and returns a string with its words reversed. +Write a **function** `rev_str` that takes a `&str` as a parameter, and returns a `String` with its letters reversed. + +### Notions + +- [Strings](https://doc.rust-lang.org/rust-by-example/std/str.html) +- [Primitive Type str](https://doc.rust-lang.org/std/primitive.str.html) +- [Primtive Type char](https://doc.rust-lang.org/std/primitive.char.html) +- [Module std::string](https://doc.rust-lang.org/std/string/index.html) ### Expected Functions @@ -27,7 +34,7 @@ fn main() { } ``` -And it's output: +And its output: ```console student@ubuntu:~/[[ROOT]]/test$ cargo run diff --git a/subjects/scalar/README.md b/subjects/scalar/README.md index 6f86ed9d..8417bd97 100644 --- a/subjects/scalar/README.md +++ b/subjects/scalar/README.md @@ -11,7 +11,7 @@ Create the following **functions**, which each receives two parameters: You **must** complete the Expected functions parameters data type accordingly (Replace the Xs)! ### Notions -- https://doc.rust-lang.org/book/ch03-02-data-types.html +- [Data Types](https://doc.rust-lang.org/book/ch03-02-data-types.html) ### Expected functions (Incomplete, you must precise the Data Types) @@ -38,30 +38,27 @@ pub fn rem(a: X, b: X) -> X { } ``` -### Usage (do not forget to comment the ERROR test if you want to use all the tests): +### Usage : +#### Note that There is no output for this test for you to train to comment accordingly. ```rust -use scalar::sum; -use scalar::diff; -use scalar::pro; -use scalar::quo; -use scalar::rem; +use scalar::*; fn main() { // sum - println!("sum : {}", sum(234, 2)); + println!("sum : {}", sum(234, 2)); // 'sum : 236' println!("sum : {}", sum(1, 255)); // 'ERROR: attempt to add with overflow' // diff - println!("diff : {}", diff(234, 2)); + println!("diff : {}", diff(234, 2)); // 'diff : 232' println!("diff : {}", diff(-32768, 32766)); // 'ERROR: attempt to subtract with overflow' // product - println!("pro : {}", pro(23, 2)); + println!("pro : {}", pro(23, 2)); // 'pro : 46' println!("pro : {}", pro(-128, 2)); // 'ERROR: attempt to multiply with overflow' // quotient - println!("quo : {}", quo(22.0, 2.0)); - println!("quo : {}", quo(-128.23, 2.0)); + println!("quo : {}", quo(22.0, 2.0));// 'quo : 11' + println!("quo : {}", quo(-128.23, 2.0));// 'quo : -64.115' // remainder - println!("rem : {}", rem(22.0, 2.0)); - println!("rem : {}", rem(-128.23, 2.0)); + println!("rem : {}", rem(22.0, 2.0));// 'rem : 0' + println!("rem : {}", rem(-128.23, 2.0));// 'rem : -0.22999573' } ``` diff --git a/subjects/speed_transformation/README.md b/subjects/speed_transformation/README.md index 25573ed0..16be31cf 100644 --- a/subjects/speed_transformation/README.md +++ b/subjects/speed_transformation/README.md @@ -2,19 +2,20 @@ ### Instructions -Create a function that receives the speed in km/h (kilometers per hour) and returns the equivalent in m/s (meters per second) +Create a **function** that receives the speed in km/h (kilometers per hour) and returns the equivalent in m/s (meters per second). ### Expected Function ```rust pub fn km_per_hour_to_meters_per_second(km_h: f64) -> f64 { - (10.0 / 36.0) * km_h } ``` ### Usage ```rust +use speed_transformation::km_per_hour_to_meters_per_second; + fn main() { let km_h = 100.0; let m_s = km_per_hour_to_meters_per_second(km_h); diff --git a/subjects/temperature_conv/README.md b/subjects/temperature_conv/README.md index 0c0a8671..223e3fca 100644 --- a/subjects/temperature_conv/README.md +++ b/subjects/temperature_conv/README.md @@ -2,15 +2,17 @@ ### Instructions -Write two functions to transform values of temperatures from celcius to fahrenheit and the other way arraound: +Write two functions which convert values of temperatures from `fahrenheit` to `celcius` and the other way around. -### Expected funcions +To pass this exercise you must use (9/5) in **both** functions. + +### Expected functions ```rust -fn fahrenheit_to_celsius(f: f64) -> f64 { +pub fn fahrenheit_to_celsius(f: f64) -> f64 { } -fn celsius_to_fahrenheit(c: f64) -> f64 { +pub fn celsius_to_fahrenheit(c: f64) -> f64 { } ``` @@ -19,9 +21,18 @@ fn celsius_to_fahrenheit(c: f64) -> f64 { ```rust use temperature_conv::*; - fn main() { println!("{} F = {} C", -459.67, fahrenheit_to_celsius(-459.67)); println!("{} C = {} F", 0.0, celsius_to_fahrenheit(0.0)); } ``` + +And its output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +-459.67 F = -273.15 C +0 C = 32 F +student@ubuntu:~/[[ROOT]]/test$ +``` + From 2521ab931d87473657567bc5c55d828e48e9410d Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 3 Feb 2021 19:06:07 +0000 Subject: [PATCH 29/42] correction in matrix_transposition --- subjects/matrix_transposition/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/subjects/matrix_transposition/README.md b/subjects/matrix_transposition/README.md index 2357a77e..b538a7d1 100644 --- a/subjects/matrix_transposition/README.md +++ b/subjects/matrix_transposition/README.md @@ -46,6 +46,7 @@ Here is a posible program to test your function ```rust use matrix_transposition::transpose; +use matrix_transposition::Matrix; fn main() { let matrix = Matrix((1, 3), (4, 5)); From 4e29a4e19846c82361638e695c7221092580b99a Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 3 Feb 2021 19:53:35 +0000 Subject: [PATCH 30/42] additional informations --- subjects/division_and_remainder/README.md | 14 +++++++++++--- subjects/matrix_transposition/README.md | 2 ++ subjects/tuples/README.md | 18 ++++++++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/subjects/division_and_remainder/README.md b/subjects/division_and_remainder/README.md index 71f58c97..525e4171 100644 --- a/subjects/division_and_remainder/README.md +++ b/subjects/division_and_remainder/README.md @@ -2,7 +2,15 @@ ### Instructions -Create a function divide that receives two i32 and returns a tuple in which the first element is the result of the integer division between the two numbers and the second is the remainder of the division. +Create a **function** `divide` that receives two i32 and returns a tuple in which the first element is the result of the integer division between the two numbers and the second is the remainder of the division. + +### Notions + +- [The Tuple Type](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html?highlight=accessing%20a%20tuple#compound-types) + +- [Tuples](https://doc.rust-lang.org/rust-by-example/primitives/tuples.html) + +- [Tuple Structs without Named Fields](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html?highlight=tuple#using-tuple-structs-without-named-fields-to-create-different-types) ### Expected Function @@ -14,10 +22,10 @@ pub fn divide(x: i32, y: i32) -> (i32, i32) { ### Usage -Here is a program to test you're function +Here is a program to test your function ```rust -use division_and_remainder::division_and_remainder; +use division_and_remainder::divide; fn main() { let x = 9; diff --git a/subjects/matrix_transposition/README.md b/subjects/matrix_transposition/README.md index b538a7d1..64863790 100644 --- a/subjects/matrix_transposition/README.md +++ b/subjects/matrix_transposition/README.md @@ -27,6 +27,8 @@ Example: - [The Tuple Type](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html?highlight=accessing%20a%20tuple#compound-types) +- [Tuples](https://doc.rust-lang.org/rust-by-example/primitives/tuples.html) + - [Tuple Structs without Named Fields](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html?highlight=tuple#using-tuple-structs-without-named-fields-to-create-different-types) - [Adding Useful Functionality with Derived Traits](https://doc.rust-lang.org/stable/book/ch05-02-example-structs.html?highlight=debug%20deriv#adding-useful-functionality-with-derived-traits) diff --git a/subjects/tuples/README.md b/subjects/tuples/README.md index be01cc7f..2209f676 100644 --- a/subjects/tuples/README.md +++ b/subjects/tuples/README.md @@ -2,12 +2,26 @@ ### Instructions -- Define a tuple structure to represent a student. +- Define a tuple structure to represent a `Student`. - Each student is identified by an id number of type i32, his/her name and his/her last name as a string Print the content of the tuple to stdout - Then define three functions to return the id, first name and last name. +### Notions + +- [Defining a struct](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html) + +- [The Tuple Type](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html?highlight=accessing%20a%20tuple#compound-types) + +- [Tuples](https://doc.rust-lang.org/rust-by-example/primitives/tuples.html) + +- [Tuple Structs without Named Fields](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html?highlight=tuple#using-tuple-structs-without-named-fields-to-create-different-types) + +- [Adding Useful Functionality with Derived Traits](https://doc.rust-lang.org/stable/book/ch05-02-example-structs.html?highlight=debug%20deriv#adding-useful-functionality-with-derived-traits) + +- [Chapter 7](https://doc.rust-lang.org/stable/book/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html) + ### Expected Functions ```rust @@ -23,7 +37,7 @@ pub fn last_name(student: &Student) -> String { ### Usage -Here is a program to test you're functions +Here is a program to test your functions ```rust use tuples::*; From 7d11821cacb3fc3e33fb0f88eae305a82c43eaa5 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 3 Feb 2021 20:01:41 +0000 Subject: [PATCH 31/42] bolding function --- subjects/matrix_transposition/README.md | 2 +- subjects/tuples/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subjects/matrix_transposition/README.md b/subjects/matrix_transposition/README.md index 64863790..8405c648 100644 --- a/subjects/matrix_transposition/README.md +++ b/subjects/matrix_transposition/README.md @@ -4,7 +4,7 @@ - Define the structure matrix as a tuple of 2 tuples of 2 `i32`'s. -- Define a function that calculates the transpose matrix of a 2x2 matrix. +- Define a **function** that calculates the transpose matrix of a 2x2 matrix. - Note: diff --git a/subjects/tuples/README.md b/subjects/tuples/README.md index 2209f676..7d84a580 100644 --- a/subjects/tuples/README.md +++ b/subjects/tuples/README.md @@ -6,7 +6,7 @@ - Each student is identified by an id number of type i32, his/her name and his/her last name as a string Print the content of the tuple to stdout -- Then define three functions to return the id, first name and last name. +- Then define three **functions** to return the id, first name and last name. ### Notions From 9bfa6513479601273f12cad3dba59988fa6ec823 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 4 Feb 2021 22:52:51 +0000 Subject: [PATCH 32/42] changes upon review --- subjects/fibonacci2/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/subjects/fibonacci2/README.md b/subjects/fibonacci2/README.md index 2b53c86b..5b06a394 100644 --- a/subjects/fibonacci2/README.md +++ b/subjects/fibonacci2/README.md @@ -7,9 +7,6 @@ Complete the body of the **function** `fibonacci`. This functions receives a number `n` and returns the nth number in the fibonacci series. The Fibonacci Series starts like this: 0, 1, 1, 2, 3, 5, 8, 13 etc... -Each number in the series is calculated by the summing of the two previous ones (With the exception of the two first ones which are defined as 0 and 1). -- so fibonacci(2) = 1 (1 + 1) -- and fibonnacci(4) = 3 (1 + 2) ### Notions From e226c81464894a90a487402757cf664ad0c431c2 Mon Sep 17 00:00:00 2001 From: xpetit <32063953+xpetit@users.noreply.github.com> Date: Fri, 5 Feb 2021 17:12:23 +0100 Subject: [PATCH 33/42] Update docker-test-image.md --- docs/docker-test-image.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docker-test-image.md b/docs/docker-test-image.md index 993b39a1..94a31483 100644 --- a/docs/docker-test-image.md +++ b/docs/docker-test-image.md @@ -26,7 +26,7 @@ The container runs with the following settings (options of `docker run`) : - 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, read-only. +- `--volume volume_containing_student_repository:/jail/student` + - 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). From 743a8af6dcf760d8d974db24730d25093a11efa2 Mon Sep 17 00:00:00 2001 From: lee Date: Tue, 2 Feb 2021 16:29:36 +0000 Subject: [PATCH 34/42] c project --- subjects/atm_management_system/README.md | 126 ++++++++++++++ .../atm_management_system/atm_system/Makefile | 16 ++ .../atm_system/data/records.txt | 6 + .../atm_system/data/users.txt | 2 + .../atm_system/src/auth.c | 59 +++++++ .../atm_system/src/header.h | 37 ++++ .../atm_system/src/main.c | 104 +++++++++++ .../atm_system/src/system.c | 161 ++++++++++++++++++ .../atm_management_system/audit/README.md | 91 ++++++++++ 9 files changed, 602 insertions(+) create mode 100644 subjects/atm_management_system/README.md create mode 100644 subjects/atm_management_system/atm_system/Makefile create mode 100644 subjects/atm_management_system/atm_system/data/records.txt create mode 100644 subjects/atm_management_system/atm_system/data/users.txt create mode 100644 subjects/atm_management_system/atm_system/src/auth.c create mode 100644 subjects/atm_management_system/atm_system/src/header.h create mode 100644 subjects/atm_management_system/atm_system/src/main.c create mode 100644 subjects/atm_management_system/atm_system/src/system.c create mode 100644 subjects/atm_management_system/audit/README.md diff --git a/subjects/atm_management_system/README.md b/subjects/atm_management_system/README.md new file mode 100644 index 00000000..198a0880 --- /dev/null +++ b/subjects/atm_management_system/README.md @@ -0,0 +1,126 @@ +## ATM + +### Objective + +The objective for this projects is to show, that you have learned to program and you are able to adapt to new languages. + +The programming language you are about to use is [C](https://en.wikipedia.org/wiki/C_%28programming_language%29). It will not be asked to create +a project from scratch, but **to add features or fix the code of a given application**. + +### Instructions + +You will be provided with an ATM management system where users can do the following actions: + +- Login/Register +- Create a new account +- Update information of existing account +- Check the details of existing accounts +- Check list of owned account +- Make transaction +- Remove existing account + +The application provided will just handle the **login**, **creation of new accounts** and **check list of owned accounts**. The rest of the features must +be implemented by you. + +### File System + +It will be provided a folder that you can find [here](https://downgit.github.io/#/home?url=https://github.com/01-edu/public/tree/master/subjects/atm-management-system/atm-system/), this folder will have the following fs: + +```console +. +| +├── data +│   ├── records.txt +│   └── users.txt +├── Makefile +├── README.md +└── src +    ├── auth.c +    ├── header.h +    ├── main.c +    └── system.c +``` + +The `data` folder presented above will contain information about the users and their accounts: + +- `users.txt` will be the a file that stores all information about each user +- `records.txt` will be the a file that stores all information relevant to the accounts for each user + +The format for the content saved in the file will be displayed like this : + +`users.txt` (name, password): + +```console +Alice 1234password +Michel password1234 +.... +``` + +`records.txt` (user name, account id, date of creation, country, phone nº, type of account) : + +```console +Alice 0 10/02/2020 german 986134231 11090830.00 current +Michel 2 10/10/2021 portugal 914134431 1920.42 saving +Alice 1 10/10/2000 finland 986134231 1234.21 saving +.... +``` + +### Features + +The following features must be done by you. + +1. **Registration**, you must be able to register new users, it cannot exist users with the same name (names must be unique). They must be saved into the right file + +2. **Update information of existing account**, users must be able to update their country or phone number\ + + 2.1. You must ask users to input the account id they want to change, followed by a prompt asking which field they want to also change (the only fields that are permitted to update is the phone number and the country). + + 2.2. When ever users update an account it must be then saved into the corresponding file. + +3. **Check the details of existing accounts**, users must able to check just one account. + + 3.1. For this it must be asked to input the account id they want to see + + 3.2. If the account is either saving, fixed01, fixed02 and fixed03 the system will display + the information of that account and the interest you will acquire depending on the account: + - saving: rate interest 0.07% + - fixed01(1 year account): rate interest 0.04% + - fixed02(2 year account): rate interest 0.05% + - fixed03(3 year account): rate interest 0.08% + - If the account is current you must display `You will not get interests because the account is of type current` + +4. **Make transaction**, users must be able to create transactions, withdrawing or depositing money to a certain account. All transactions + must be updated and saved into the corresponding file + +5. **Remove existing account**, users must be able to delete their own account, same must happened here, updates must be saved into the corresponding file. + +6. **Transfer owner**, users can transfer their account to another user, by: + + 6.1. Identifying the account and the user they want to transfer the ownership to + + 6.2. Saving the information in the corresponding file + +### Example + +You can find an example of the final application [here](TODO:link_to_youtube_video). Do not forget that you are free to +implement what ever kind of interface you desire. It just needs to obey the instructions given above so it can pass the audit. + +### Bonus + +You can create bonus features or update the terminal interface: + +- Better terminal interface +- Encryption of passwords +- Adding own Makefile +- Adding more features + +This project will help you learn about: + +- [C](https://en.wikipedia.org/wiki/C_%28programming_language%29) languages + - Language Fundamentals +- Data manipulation + - File [stdino](TODO:link) + - Data structures +- Makefile +- Terminal UI +- Memory management diff --git a/subjects/atm_management_system/atm_system/Makefile b/subjects/atm_management_system/atm_system/Makefile new file mode 100644 index 00000000..62befd2c --- /dev/null +++ b/subjects/atm_management_system/atm_system/Makefile @@ -0,0 +1,16 @@ +objects = src/main.o src/system.o src/auth.o + +atm : $(objects) + cc -o atm $(objects) + +main.o : src/header.h +kbd.o : src/header.h +command.o : src/header.h +display.o : src/header.h +insert.o : src/header.h +search.o : src/header.h +files.o : src/header.h +utils.o : src/header.h + +clean : + rm -f $(objects) diff --git a/subjects/atm_management_system/atm_system/data/records.txt b/subjects/atm_management_system/atm_system/data/records.txt new file mode 100644 index 00000000..b9d75f71 --- /dev/null +++ b/subjects/atm_management_system/atm_system/data/records.txt @@ -0,0 +1,6 @@ +Alice 0 10/10/2012 Africa 291321234 22432.52 saving + +Michel 2 2/5/2001 Portugal 123543455 10023.230000 fixed01 + +Michel 123 10/10/2020 UK 1234123 12345.30 saving + diff --git a/subjects/atm_management_system/atm_system/data/users.txt b/subjects/atm_management_system/atm_system/data/users.txt new file mode 100644 index 00000000..00694cf8 --- /dev/null +++ b/subjects/atm_management_system/atm_system/data/users.txt @@ -0,0 +1,2 @@ +Alice q1w2e3r4t5y6 +Michel q1w2e3r4t5y6 diff --git a/subjects/atm_management_system/atm_system/src/auth.c b/subjects/atm_management_system/atm_system/src/auth.c new file mode 100644 index 00000000..c3e61b08 --- /dev/null +++ b/subjects/atm_management_system/atm_system/src/auth.c @@ -0,0 +1,59 @@ +#include +#include "header.h" + +char *USERS = "./data/users.txt"; + +void loginMenu(char a[50], char pass[50]) +{ + struct termios oflags, nflags; + + system("clear"); + printf("\n\n\n\t\t\t\t Bank Management System\n\t\t\t\t\t User Login:"); + scanf("%s", a); + + // disabling echo + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; + + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) + { + perror("tcsetattr"); + return exit(1); + } + printf("\n\n\n\n\n\t\t\t\tEnter the password to login:"); + scanf("%s", pass); + + // restore terminal + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) + { + perror("tcsetattr"); + return exit(1); + } +}; + +const char *getPassword(struct User u) +{ + FILE *fp; + struct User userChecker; + + if ((fp = fopen("./data/users.txt", "r")) == NULL) + { + printf("Error! opening file"); + exit(1); + } + + while (fscanf(fp, "%s %s", userChecker.name, userChecker.password) != EOF) + { + if (strcmp(userChecker.name, u.name) == 0) + { + fclose(fp); + char *buff = userChecker.password; + return buff; + } + } + + fclose(fp); + return "no user found"; +} \ No newline at end of file diff --git a/subjects/atm_management_system/atm_system/src/header.h b/subjects/atm_management_system/atm_system/src/header.h new file mode 100644 index 00000000..61d7971a --- /dev/null +++ b/subjects/atm_management_system/atm_system/src/header.h @@ -0,0 +1,37 @@ +#include +#include +#include + +struct Date +{ + int month, day, year; +}; + +// all fields for each record of an account +struct Record +{ + char name[100]; + char country[100]; + int phone; + char accountType[10]; + int accountNbr; + double amount; + struct Date deposit; + struct Date withdraw; +}; + +struct User +{ + char name[50]; + char password[50]; +}; + +// authentication functions +void loginMenu(char a[50], char pass[50]); +void registerMenu(char a[50], char pass[50]); +const char *getPassword(struct User u); + +// system function +void createNewAcc(struct User u); +void mainMenu(struct User u); +void checkAllAccounts(struct User u); diff --git a/subjects/atm_management_system/atm_system/src/main.c b/subjects/atm_management_system/atm_system/src/main.c new file mode 100644 index 00000000..9829a876 --- /dev/null +++ b/subjects/atm_management_system/atm_system/src/main.c @@ -0,0 +1,104 @@ +#include "header.h" + +void mainMenu(struct User u) +{ + int option; + system("clear"); + printf("\n\n\t\t======= ATM =======\n\n"); + printf("\n\t\t-->> Feel free to choose one of the options below <<--\n"); + printf("\n\t\t[1]- Create a new account\n"); + printf("\n\t\t[2]- Update information of account\n"); + printf("\n\t\t[3]- Check accounts\n"); + printf("\n\t\t[4]- Check list of owned account\n"); + printf("\n\t\t[5]- Make Transaction\n"); + printf("\n\t\t[6]- Remove existing account\n"); + printf("\n\t\t[7]- Transfer ownership\n"); + printf("\n\t\t[8]- Exit\n"); + scanf("%d", &option); + + switch (option) + { + case 1: + createNewAcc(u); + break; + case 2: + // student TODO : add your **Update information of existing account** function + // here + break; + case 3: + // student TODO : add your **Check the details of existing accounts** function + // here + break; + case 4: + checkAllAccounts(u); + break; + case 5: + // student TODO : add your **Make transaction** function + // here + break; + case 6: + // student TODO : add your **Remove existing account** function + // here + break; + case 7: + // student TODO : add your **Transfer owner** function + // here + break; + case 8: + exit(1); + break; + default: + printf("Invalid operation!\n"); + } +}; + +void initMenu(struct User *u) +{ + int r = 0; + int option; + system("clear"); + printf("\n\n\t\t======= ATM =======\n"); + printf("\n\t\t-->> Feel free to login / register :\n"); + printf("\n\t\t[1]- login\n"); + printf("\n\t\t[2]- register\n"); + printf("\n\t\t[3]- exit\n"); + while (!r) + { + scanf("%d", &option); + switch (option) + { + case 1: + loginMenu(u->name, u->password); + if (strcmp(u->password, getPassword(*u)) == 0) + { + printf("\n\nPassword Match!"); + } + else + { + printf("\nWrong password!! or User Name\n"); + exit(1); + } + r = 1; + break; + case 2: + // student TODO : add your **Registration** function + // here + r = 1; + break; + case 3: + exit(1); + break; + default: + printf("Insert a valid operation!\n"); + } + } +}; + +int main() +{ + struct User u; + + initMenu(&u); + mainMenu(u); + return 0; +} diff --git a/subjects/atm_management_system/atm_system/src/system.c b/subjects/atm_management_system/atm_system/src/system.c new file mode 100644 index 00000000..1a5f03c9 --- /dev/null +++ b/subjects/atm_management_system/atm_system/src/system.c @@ -0,0 +1,161 @@ +#include "header.h" + +const char *RECORDS = "./data/records.txt"; + +int getAccountFromFile(FILE *ptr, char name[50], struct Record *r) +{ + return fscanf(ptr, "%s %d %d/%d/%d %s %d %lf %s", + name, + &r->accountNbr, + &r->deposit.month, + &r->deposit.day, + &r->deposit.year, + r->country, + &r->phone, + &r->amount, + r->accountType) != EOF; +} + +void saveAccountToFile(FILE *ptr, char name[50], struct Record r) +{ + fprintf(ptr, "%s %d %d/%d/%d %s %d %.2lf %s\n\n", + name, + r.accountNbr, + r.deposit.month, + r.deposit.day, + r.deposit.year, + r.country, + r.phone, + r.amount, + r.accountType); +} + +void stayOrReturn(int notGood, void f(struct User u), struct User u) +{ + int option; + if (notGood == 0) + { + system("clear"); + printf("\n✖ Record not found!!\n"); + invalid: + printf("\nEnter 0 to try again, 1 to return to main menu and 2 to exit:"); + scanf("%d", &option); + if (option == 0) + f(u); + else if (option == 1) + mainMenu(u); + else if (option == 2) + exit(0); + else + { + printf("Insert a valid operation!\n"); + goto invalid; + } + } + else + { + printf("\nEnter 1 to go to the main menu and 0 to exit:"); + scanf("%d", &option); + } + if (option == 1) + { + system("clear"); + mainMenu(u); + } + else + { + system("clear"); + exit(1); + } +} + +void success(struct User u) +{ + int option; + printf("\n✔ Success!\n\n"); +invalid: + printf("Enter 1 to go to the main menu and 0 to exit!\n"); + scanf("%d", &option); + system("clear"); + if (option == 1) + { + mainMenu(u); + } + else if (option == 0) + { + exit(1); + } + else + { + printf("Insert a valid operation!\n"); + goto invalid; + } +} + +void createNewAcc(struct User u) +{ + struct Record r; + struct Record cr; + char userName[50]; + FILE *pf = fopen(RECORDS, "a+"); + +noAccount: + system("clear"); + printf("\t\t\t===== New record =====\n"); + + printf("\nEnter today's date(mm/dd/yyyy):"); + scanf("%d/%d/%d", &r.deposit.month, &r.deposit.day, &r.deposit.year); + printf("\nEnter the account number:"); + scanf("%d", &r.accountNbr); + + while (getAccountFromFile(pf, userName, &cr)) + { + if (strcmp(userName, u.name) == 0 && cr.accountNbr == r.accountNbr) + { + printf("✖ This Account already exists for this user\n\n"); + goto noAccount; + } + } + printf("\nEnter the country:"); + scanf("%s", r.country); + printf("\nEnter the phone number:"); + scanf("%d", &r.phone); + printf("\nEnter amount to deposit: $"); + scanf("%lf", &r.amount); + printf("\nChoose the type of account:\n\t-> saving\n\t-> current\n\t-> fixed01(for 1 year)\n\t-> fixed02(for 2 years)\n\t-> fixed03(for 3 years)\n\n\tEnter your choice:"); + scanf("%s", r.accountType); + + saveAccountToFile(pf, u.name, r); + + fclose(pf); + success(u); +} + +void checkAllAccounts(struct User u) +{ + char userName[100]; + struct Record r; + + FILE *pf = fopen(RECORDS, "r"); + + system("clear"); + printf("\t\t====== All accounts from user, %s =====\n\n", u.name); + while (getAccountFromFile(pf, userName, &r)) + { + if (strcmp(userName, u.name) == 0) + { + printf("_____________________\n"); + printf("\nAccount number:%d\nDeposit Date:%d/%d/%d \ncountry:%s \nPhone number:%d \nAmount deposited: $%.2f \nType Of Account:%s\n", + r.accountNbr, + r.deposit.day, + r.deposit.month, + r.deposit.year, + r.country, + r.phone, + r.amount, + r.accountType); + } + } + fclose(pf); + success(u); +} diff --git a/subjects/atm_management_system/audit/README.md b/subjects/atm_management_system/audit/README.md new file mode 100644 index 00000000..9847fda0 --- /dev/null +++ b/subjects/atm_management_system/audit/README.md @@ -0,0 +1,91 @@ +#### Functional + +##### Open the application and register a new user with the name `"Alice"` and the password `"q1w2e3r4t5y6"` + +###### Is this user saved in the file `"./data/users.txt"`, and if so are all credentials correct (name and password)? + +##### Open the application and register again the user `"Alice"`. + +###### Did it displayed an error message saying that this user already exists? + +##### Open the application and register again the user `"Alice"`, then open the file `"./data/users.txt"`. + +###### Are all the user names unique? (ex: no repetition on the name Alice) + +##### Try and login as `"Alice"`. + +###### Was Alice able to enter the main menu? + +##### Try to create two accounts using the user Alice, then select the option `"Update information of account"` and select an account number that does not exist for Alice. + +###### Did the application displayed some kind of error message saying that this account does not exist? + +##### Utilizing the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. + +###### Did the the application prompt a choice of updating the **phone number** or the **country**? + +##### Utilizing the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the phone number of that account. + +###### Was the phone number of that account updated in the application and the file `"records.txt"`? + +##### Utilizing the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the country of that account. + +###### Was the country of that account updated in the application and the file `"records.txt"`? + +##### Utilizing the user Alice try to create a new account with: date `"10/10/2012"` account number `"834213"`, country `"UK"`, phone number `"291231392"`, deposit amount $`"1001.20"`, type of account `"saving"`. Then select `"Check accounts"` choose the account you just created. + +###### Did the application displayed the account information and the gain of $5.84 of interest on day 10 of every moth? + +##### Utilizing the user Alice create again an account but with account number `"320421"` and type of account `"fixed01"` the rest can be the same as the last account. Then select `"Check accounts"` choose the account you just created. + +###### Did the application displayed the account information and the gain of $40.05 of interest on 10/10/2013? + +##### Utilizing the user Alice create again an account but with account number `"3214"` and type of account `"fixed02"` the rest can be the same as the last account. Then select `"Check accounts"` choose the account you just created. + +###### Did the application displayed the account information and the gain of $100.12 of interest on 10/10/2014? + +##### Utilizing the user Alice create again an account but with account number `"3212"` and type of account `"fixed03"` the rest can be the same as the last account. Then select `"Check accounts"` choose the account you just created. + +###### Did the application displayed the account information and the gain of $240.29 of interest on 10/10/2015? + +##### Utilizing the user Alice select the option `"Make transaction"`. Then choose the account with the id `"3212"` + +###### Are you able to choose between withdrawing or depositing? + +##### Utilizing the user Alice select the option `"Make transaction"`, choose the account with the id `"3212"`. Then try to withdraw money. + +###### Are you able to withdraw money? + +###### And if so, did the withdraw was updated in the file `"records.txt"`? + +###### Is it not possible to withdraw an amount superior to your available balance? + +##### Try to deposit money into the account `"3212"`. + +###### Were you able to deposit money into this account? + +###### And if so did it update the file `"records.txt"`? + +##### Utilizing the use Alice try to select the option `"Remove existing account"` and remove the accounts `"834213"`, `"320421"` and `"3214"`. + +###### Can you confirm that those account were deleted, both in the application and file `"records.txt"`? + +##### Utilizing the use Alice select the option `"Remove existing account"` and try to remove and nonexisting account. + +###### Did the application prompt some king of error saying that the account does not exits? + +##### Create another user named `"Michel"`. Then by using the user Alice select the option `"transfer owner"` and try to transfer ownership of the account `"3212"` to Michel. + +###### Were you able to transfer the ownership of this account to Michel? And if so did it update both application and file named `"records.txt"`? + +#### Bonus + +###### +Did the student update the terminal interface? + +###### +Is the password saved in the file `"users.txt"` encrypted? + +###### +Did the student make their own Makefile? + +###### +Did the student add more features to the project? + +###### +Did the student optimise the code already given? \ No newline at end of file From 54f65c4832046c0e841a423e87fd71e9280104d1 Mon Sep 17 00:00:00 2001 From: OGordoo Date: Tue, 2 Feb 2021 16:54:39 +0000 Subject: [PATCH 35/42] typos --- subjects/atm_management_system/README.md | 43 ++++++++++++------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/subjects/atm_management_system/README.md b/subjects/atm_management_system/README.md index 198a0880..f036a0ed 100644 --- a/subjects/atm_management_system/README.md +++ b/subjects/atm_management_system/README.md @@ -2,7 +2,7 @@ ### Objective -The objective for this projects is to show, that you have learned to program and you are able to adapt to new languages. +The objective for this project is to show that you have learned to program and you are able to adapt to new languages. The programming language you are about to use is [C](https://en.wikipedia.org/wiki/C_%28programming_language%29). It will not be asked to create a project from scratch, but **to add features or fix the code of a given application**. @@ -13,11 +13,11 @@ You will be provided with an ATM management system where users can do the follow - Login/Register - Create a new account -- Update information of existing account +- Update information of existing accounts - Check the details of existing accounts -- Check list of owned account -- Make transaction -- Remove existing account +- Check list of owned accounts +- Make transactions +- Remove existing accounts The application provided will just handle the **login**, **creation of new accounts** and **check list of owned accounts**. The rest of the features must be implemented by you. @@ -71,23 +71,24 @@ The following features must be done by you. 1. **Registration**, you must be able to register new users, it cannot exist users with the same name (names must be unique). They must be saved into the right file -2. **Update information of existing account**, users must be able to update their country or phone number\ +2. **Update information of existing account**, users must be able to update their country or phone number - 2.1. You must ask users to input the account id they want to change, followed by a prompt asking which field they want to also change (the only fields that are permitted to update is the phone number and the country). + 2.1. You must ask users to input the account id they want to change, followed by a prompt asking which field they want to also change (the only fields that are permitted to update is the phone number and the country). - 2.2. When ever users update an account it must be then saved into the corresponding file. + 2.2. Whenever users update an account, it must be saved into the corresponding file. -3. **Check the details of existing accounts**, users must able to check just one account. +3. **Check the details of existing accounts**, users must be able to check just one account at a time. - 3.1. For this it must be asked to input the account id they want to see + 3.1. For this it must be asked to input the account id they want to see - 3.2. If the account is either saving, fixed01, fixed02 and fixed03 the system will display - the information of that account and the interest you will acquire depending on the account: - - saving: rate interest 0.07% - - fixed01(1 year account): rate interest 0.04% - - fixed02(2 year account): rate interest 0.05% - - fixed03(3 year account): rate interest 0.08% - - If the account is current you must display `You will not get interests because the account is of type current` + 3.2. If the account is either saving, fixed01, fixed02 and fixed03 the system will display + the information of that account and the interest you will acquire depending on the account: + + - saving: rate interest 0.07% + - fixed01(1 year account): rate interest 0.04% + - fixed02(2 year account): rate interest 0.05% + - fixed03(3 year account): rate interest 0.08% + - If the account is current you must display `You will not get interests because the account is of type current` 4. **Make transaction**, users must be able to create transactions, withdrawing or depositing money to a certain account. All transactions must be updated and saved into the corresponding file @@ -96,14 +97,14 @@ The following features must be done by you. 6. **Transfer owner**, users can transfer their account to another user, by: - 6.1. Identifying the account and the user they want to transfer the ownership to + 6.1. Identifying the account and the user they want to transfer the ownership to - 6.2. Saving the information in the corresponding file + 6.2. Saving the information in the corresponding file ### Example You can find an example of the final application [here](TODO:link_to_youtube_video). Do not forget that you are free to -implement what ever kind of interface you desire. It just needs to obey the instructions given above so it can pass the audit. +implement whatever kind of interface you desire. It just needs to obey the instructions given above so it can pass the audit. ### Bonus @@ -116,7 +117,7 @@ You can create bonus features or update the terminal interface: This project will help you learn about: -- [C](https://en.wikipedia.org/wiki/C_%28programming_language%29) languages +- [C](https://en.wikipedia.org/wiki/C_%28programming_language%29) language - Language Fundamentals - Data manipulation - File [stdino](TODO:link) From 0950f6b522927ff1d8d2d3c64e0a1c13b6858acc Mon Sep 17 00:00:00 2001 From: lee Date: Tue, 2 Feb 2021 18:05:08 +0000 Subject: [PATCH 36/42] adding links --- subjects/atm_management_system/README.md | 2 +- subjects/atm_management_system/audit/README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subjects/atm_management_system/README.md b/subjects/atm_management_system/README.md index f036a0ed..dfc79372 100644 --- a/subjects/atm_management_system/README.md +++ b/subjects/atm_management_system/README.md @@ -120,7 +120,7 @@ This project will help you learn about: - [C](https://en.wikipedia.org/wiki/C_%28programming_language%29) language - Language Fundamentals - Data manipulation - - File [stdino](TODO:link) + - File manipulation - Data structures - Makefile - Terminal UI diff --git a/subjects/atm_management_system/audit/README.md b/subjects/atm_management_system/audit/README.md index 9847fda0..a7d33ed7 100644 --- a/subjects/atm_management_system/audit/README.md +++ b/subjects/atm_management_system/audit/README.md @@ -66,17 +66,17 @@ ###### And if so did it update the file `"records.txt"`? -##### Utilizing the use Alice try to select the option `"Remove existing account"` and remove the accounts `"834213"`, `"320421"` and `"3214"`. +##### Utilizing the user Alice try to select the option `"Remove existing account"` and remove the accounts `"834213"`, `"320421"` and `"3214"`. ###### Can you confirm that those account were deleted, both in the application and file `"records.txt"`? -##### Utilizing the use Alice select the option `"Remove existing account"` and try to remove and nonexisting account. +##### Utilizing the user Alice select the option `"Remove existing account"` and try to remove and nonexisting account. ###### Did the application prompt some king of error saying that the account does not exits? ##### Create another user named `"Michel"`. Then by using the user Alice select the option `"transfer owner"` and try to transfer ownership of the account `"3212"` to Michel. -###### Were you able to transfer the ownership of this account to Michel? And if so did it update both application and file named `"records.txt"`? +###### Were you able to transfer the ownership of this account to Michel? And if so did it update both application and file `"records.txt"`? #### Bonus From 88ed0cb9dbce761d8a23e8788908105c0293873f Mon Sep 17 00:00:00 2001 From: lee Date: Wed, 3 Feb 2021 09:19:06 +0000 Subject: [PATCH 37/42] youtube link --- subjects/atm_management_system/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subjects/atm_management_system/README.md b/subjects/atm_management_system/README.md index dfc79372..35ebc5af 100644 --- a/subjects/atm_management_system/README.md +++ b/subjects/atm_management_system/README.md @@ -103,7 +103,7 @@ The following features must be done by you. ### Example -You can find an example of the final application [here](TODO:link_to_youtube_video). Do not forget that you are free to +You can find an example of the final application [here](https://www.youtube.com/watch?v=1LjwbIFt5Qo). Do not forget that you are free to implement whatever kind of interface you desire. It just needs to obey the instructions given above so it can pass the audit. ### Bonus From 877a77616ddedd4b80403489864fb32849c69e27 Mon Sep 17 00:00:00 2001 From: lee Date: Wed, 3 Feb 2021 10:24:56 +0000 Subject: [PATCH 38/42] typos --- .../atm_management_system/audit/README.md | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/subjects/atm_management_system/audit/README.md b/subjects/atm_management_system/audit/README.md index a7d33ed7..95bcd071 100644 --- a/subjects/atm_management_system/audit/README.md +++ b/subjects/atm_management_system/audit/README.md @@ -8,7 +8,7 @@ ###### Did it displayed an error message saying that this user already exists? -##### Open the application and register again the user `"Alice"`, then open the file `"./data/users.txt"`. +##### Open the file `"./data/users.txt"`. ###### Are all the user names unique? (ex: no repetition on the name Alice) @@ -20,43 +20,43 @@ ###### Did the application displayed some kind of error message saying that this account does not exist? -##### Utilizing the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. +##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. ###### Did the the application prompt a choice of updating the **phone number** or the **country**? -##### Utilizing the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the phone number of that account. +##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the phone number of that account. ###### Was the phone number of that account updated in the application and the file `"records.txt"`? -##### Utilizing the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the country of that account. +##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the country of that account. ###### Was the country of that account updated in the application and the file `"records.txt"`? -##### Utilizing the user Alice try to create a new account with: date `"10/10/2012"` account number `"834213"`, country `"UK"`, phone number `"291231392"`, deposit amount $`"1001.20"`, type of account `"saving"`. Then select `"Check accounts"` choose the account you just created. +##### Resorting to the user Alice try to create a new account with: date `"10/10/2012"` account number `"834213"`, country `"UK"`, phone number `"291231392"`, deposit amount $`"1001.20"`, type of account `"saving"`. Then select `"Check accounts"` choose the account you just created. ###### Did the application displayed the account information and the gain of $5.84 of interest on day 10 of every moth? -##### Utilizing the user Alice create again an account but with account number `"320421"` and type of account `"fixed01"` the rest can be the same as the last account. Then select `"Check accounts"` choose the account you just created. +##### Resorting to the user Alice create again an account but with account number "320421" and type of account "fixed01" with the rest of the information as in the last account . Then select `"Check accounts"` and choose the account you just created. ###### Did the application displayed the account information and the gain of $40.05 of interest on 10/10/2013? -##### Utilizing the user Alice create again an account but with account number `"3214"` and type of account `"fixed02"` the rest can be the same as the last account. Then select `"Check accounts"` choose the account you just created. +##### Resorting to the user Alice create again an account but with account number `"3214"` and type of account `"fixed02"` with the rest of the information as in the last account. Then select `"Check accounts"` and choose the account you just created. ###### Did the application displayed the account information and the gain of $100.12 of interest on 10/10/2014? -##### Utilizing the user Alice create again an account but with account number `"3212"` and type of account `"fixed03"` the rest can be the same as the last account. Then select `"Check accounts"` choose the account you just created. +##### Resorting to the user Alice create again an account but with account number `"3212"` and type of account `"fixed03"` with the rest of the information as in the last account. Then select `"Check accounts"` and choose the account you just created. ###### Did the application displayed the account information and the gain of $240.29 of interest on 10/10/2015? -##### Utilizing the user Alice select the option `"Make transaction"`. Then choose the account with the id `"3212"` +##### Resorting to the user Alice select the option `"Make transaction"`. Then choose the account with the id `"3212"` ###### Are you able to choose between withdrawing or depositing? -##### Utilizing the user Alice select the option `"Make transaction"`, choose the account with the id `"3212"`. Then try to withdraw money. +##### Resorting to the user Alice select the option `"Make transaction"`, choose the account with the id `"3212"`. Then try to withdraw money. ###### Are you able to withdraw money? -###### And if so, did the withdraw was updated in the file `"records.txt"`? +###### And if so, was the withdraw updated in the file `"records.txt"`? ###### Is it not possible to withdraw an amount superior to your available balance? @@ -66,15 +66,15 @@ ###### And if so did it update the file `"records.txt"`? -##### Utilizing the user Alice try to select the option `"Remove existing account"` and remove the accounts `"834213"`, `"320421"` and `"3214"`. +##### Resorting to the user Alice try to select the option `"Remove existing account"` and remove the accounts `"834213"`, `"320421"` and `"3214"`. ###### Can you confirm that those account were deleted, both in the application and file `"records.txt"`? -##### Utilizing the user Alice select the option `"Remove existing account"` and try to remove and nonexisting account. +##### Resorting to the user Alice select the option `"Remove existing account"` and try to remove and nonexisting account. -###### Did the application prompt some king of error saying that the account does not exits? +###### Did the application prompt some type of error saying that the account does not exists? -##### Create another user named `"Michel"`. Then by using the user Alice select the option `"transfer owner"` and try to transfer ownership of the account `"3212"` to Michel. +##### Create another user named `"Michel"`. Then by using Alice select the option `"transfer owner"` and try to transfer ownership of the account `"3212"` to Michel. ###### Were you able to transfer the ownership of this account to Michel? And if so did it update both application and file `"records.txt"`? From f6747c9c5fd8e1b50c8ffe47225b626ea8258d1e Mon Sep 17 00:00:00 2001 From: lee Date: Wed, 3 Feb 2021 18:51:58 +0000 Subject: [PATCH 39/42] adding bonus --- subjects/atm_management_system/README.md | 20 ++++++++++++------- .../atm_management_system/audit/README.md | 4 ++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/subjects/atm_management_system/README.md b/subjects/atm_management_system/README.md index 35ebc5af..ac65c0a8 100644 --- a/subjects/atm_management_system/README.md +++ b/subjects/atm_management_system/README.md @@ -101,19 +101,24 @@ The following features must be done by you. 6.2. Saving the information in the corresponding file -### Example - -You can find an example of the final application [here](https://www.youtube.com/watch?v=1LjwbIFt5Qo). Do not forget that you are free to -implement whatever kind of interface you desire. It just needs to obey the instructions given above so it can pass the audit. - ### Bonus -You can create bonus features or update the terminal interface: +As bonus you can add a verification to the field **Transfer owner**. Every time a user transfers ownership of an account the other user who received the account +can be alerted that it received and account from someone instantly. +Example if you have two terminals opened logged in two different users, and one send the account to the other user, +the user who received the account should be instantly notified +One of the ways of doing this is by using pipes and child processes (communication between process) + +You can also do more bonus features or update the terminal interface: - Better terminal interface - Encryption of passwords - Adding own Makefile -- Adding more features + +### Example + +You can find an example of the final application [here](https://www.youtube.com/watch?v=1LjwbIFt5Qo). Do not forget that you are free to +implement whatever kind of interface you desire. It just needs to obey the instructions given above so it can pass the audit. This project will help you learn about: @@ -125,3 +130,4 @@ This project will help you learn about: - Makefile - Terminal UI - Memory management +- Pipes and child processes diff --git a/subjects/atm_management_system/audit/README.md b/subjects/atm_management_system/audit/README.md index 95bcd071..db5ebf7e 100644 --- a/subjects/atm_management_system/audit/README.md +++ b/subjects/atm_management_system/audit/README.md @@ -80,6 +80,10 @@ #### Bonus +##### Open two terminals and login with two different users. Then transfer ownership of an account to the other user. + +###### +Was the user whom received the account notified instantly? + ###### +Did the student update the terminal interface? ###### +Is the password saved in the file `"users.txt"` encrypted? From 36e7f070a244bafad0174568302168db9524b8d3 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 4 Feb 2021 18:28:13 +0000 Subject: [PATCH 40/42] readme review --- subjects/atm-management-system/README.md | 133 +++++++++++++++ .../atm-management-system/atm_system/Makefile | 16 ++ .../atm_system/data/records.txt | 6 + .../atm_system/data/users.txt | 2 + .../atm_system/src/auth.c | 59 +++++++ .../atm_system/src/header.h | 37 ++++ .../atm_system/src/main.c | 104 +++++++++++ .../atm_system/src/system.c | 161 ++++++++++++++++++ .../atm-management-system/audit/README.md | 95 +++++++++++ 9 files changed, 613 insertions(+) create mode 100644 subjects/atm-management-system/README.md create mode 100644 subjects/atm-management-system/atm_system/Makefile create mode 100644 subjects/atm-management-system/atm_system/data/records.txt create mode 100644 subjects/atm-management-system/atm_system/data/users.txt create mode 100644 subjects/atm-management-system/atm_system/src/auth.c create mode 100644 subjects/atm-management-system/atm_system/src/header.h create mode 100644 subjects/atm-management-system/atm_system/src/main.c create mode 100644 subjects/atm-management-system/atm_system/src/system.c create mode 100644 subjects/atm-management-system/audit/README.md diff --git a/subjects/atm-management-system/README.md b/subjects/atm-management-system/README.md new file mode 100644 index 00000000..8b72b657 --- /dev/null +++ b/subjects/atm-management-system/README.md @@ -0,0 +1,133 @@ +## ATM + +### Objective + +The objective for this project is to show that you have acquired programming logic and that you are able to adapt to new languages. + +The programming language you are about to use is [C](https://en.wikipedia.org/wiki/C_%28programming_language%29). It will not be asked to create +a project from scratch, insted you will have **to add features or fix the code of a given application**. + +### Instructions + +You will be provided with an ATM management system where users can do the following actions: + +- Login/Register +- Create a new account +- Check the details of existing accounts +- Update information of existing accounts +- Remove existing accounts +- Check list of owned accounts +- Make transactions + +> The application provided will just handle the **login**, the **creation of new accounts** and **checking the list of owned accounts**. The rest of the features must +be implemented by yourself. + +### File System + +A folder which you can find [here](https://downgit.github.io/#/home?url=https://github.com/01-edu/public/tree/master/subjects/atm-management-system/atm-system/) is provided, this folder will have the following `fs`(file system): + +```console +. +| +├── data +│   ├── records.txt +│   └── users.txt +├── Makefile +├── README.md +└── src +    ├── auth.c +    ├── header.h +    ├── main.c +    └── system.c +``` + +The `data` folder presented above will contain information about the users and their accounts: + +- `users.txt` will be the a file that stores all information about each user +- `records.txt` will be the a file that stores all information relevant to the accounts for each user + +The format for the content saved in the file will be displayed like this : + +`users.txt` (name, password): + +```console +Alice 1234password +Michel password1234 +.... +``` + +`records.txt` (user name, account id, date of creation, country, phone nº, type of account) : + +```console +Alice 0 10/02/2020 german 986134231 11090830.00 current +Michel 2 10/10/2021 portugal 914134431 1920.42 savings +Alice 1 10/10/2000 finland 986134231 1234.21 savings +.... +``` + +### Features + +The following features must be implemented by yourself. + +1. The **Registration** feature, you must be able to register new users, users with the same name can not exist (names must be unique). They must be saved in the right file. + +2. The **Update information of existing account** feature, users must be able to update their country or phone number. + + 2.1. You must ask users to input the account `id` they want to change, followed by a prompt asking which field they want to also change (the only fields that are permitted to update is the phone number and the country). + + 2.2. Whenever users update an account, it must be saved into the corresponding file. + +3. The **Checking the details of existing accounts** feature, users must be able to check just one account at a time. + + 3.1. For this it must be asked to input the account id they want to see + + 3.2. If the account is either `savings`, `fixed01`, `fixed02` and `fixed03` the system will display + the information of that account and the interest you will acquire depending on the account: + + - savings: interest rate 0.07% + - fixed01(1 year account): interest rate 0.04% + - fixed02(2 year account): interest rate 0.05% + - fixed03(3 year account): interest rate 0.08% + - If the account is current you must display `You will not get interests because the account is of type current` + +4. The **Make transaction** feature, users must be able to create transactions, withdrawing or depositing money to a certain account. All transactions + must be updated and saved into the corresponding file. + +5. The **Remove existing account** feature, users must be able to delete their own account, the same must happen here, updates must be saved into the corresponding file. + +6. The **Transfer owner** feature, users can transfer their account to another user, by: + + 6.1. Identifying the account and the user they want to transfer the ownership to + + 6.2. Saving the information in the corresponding file + +### Bonus + +As bonus you can add a verification to the field **Transfer owner**. Every time a user transfers ownership of an account the other user who received the account +can be alerted that he or she received an account from someone instantly. +Example: if you have two terminals opened logged with two different users, and one send the account to the other user, +the user who received the account should be instantly notified. +One of the ways of doing this is by using pipes and child processes (communication between processes). + +You can also do more bonus features or update the terminal interface: + +- Better terminal interface (TUI) +- Encryption of passwords +- Adding your own Makefile + +### Example + +You can find an example of the final application [here](https://www.youtube.com/watch?v=xVtikDcGG2E). Do not forget that you are free to +implement whichever kind of interface you desire. It just needs to obey the instructions given above so it can pass the audit. + +This project will help you learn about: + +- [C](https://en.wikipedia.org/wiki/C_%28programming_language%29) language + - Language Fundamentals +- Data manipulation + - File manipulation + - Data structures +- Makefile +- Terminal UI +- Memory management +- Pipes and child processes diff --git a/subjects/atm-management-system/atm_system/Makefile b/subjects/atm-management-system/atm_system/Makefile new file mode 100644 index 00000000..62befd2c --- /dev/null +++ b/subjects/atm-management-system/atm_system/Makefile @@ -0,0 +1,16 @@ +objects = src/main.o src/system.o src/auth.o + +atm : $(objects) + cc -o atm $(objects) + +main.o : src/header.h +kbd.o : src/header.h +command.o : src/header.h +display.o : src/header.h +insert.o : src/header.h +search.o : src/header.h +files.o : src/header.h +utils.o : src/header.h + +clean : + rm -f $(objects) diff --git a/subjects/atm-management-system/atm_system/data/records.txt b/subjects/atm-management-system/atm_system/data/records.txt new file mode 100644 index 00000000..b9d75f71 --- /dev/null +++ b/subjects/atm-management-system/atm_system/data/records.txt @@ -0,0 +1,6 @@ +Alice 0 10/10/2012 Africa 291321234 22432.52 saving + +Michel 2 2/5/2001 Portugal 123543455 10023.230000 fixed01 + +Michel 123 10/10/2020 UK 1234123 12345.30 saving + diff --git a/subjects/atm-management-system/atm_system/data/users.txt b/subjects/atm-management-system/atm_system/data/users.txt new file mode 100644 index 00000000..00694cf8 --- /dev/null +++ b/subjects/atm-management-system/atm_system/data/users.txt @@ -0,0 +1,2 @@ +Alice q1w2e3r4t5y6 +Michel q1w2e3r4t5y6 diff --git a/subjects/atm-management-system/atm_system/src/auth.c b/subjects/atm-management-system/atm_system/src/auth.c new file mode 100644 index 00000000..c3e61b08 --- /dev/null +++ b/subjects/atm-management-system/atm_system/src/auth.c @@ -0,0 +1,59 @@ +#include +#include "header.h" + +char *USERS = "./data/users.txt"; + +void loginMenu(char a[50], char pass[50]) +{ + struct termios oflags, nflags; + + system("clear"); + printf("\n\n\n\t\t\t\t Bank Management System\n\t\t\t\t\t User Login:"); + scanf("%s", a); + + // disabling echo + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; + + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) + { + perror("tcsetattr"); + return exit(1); + } + printf("\n\n\n\n\n\t\t\t\tEnter the password to login:"); + scanf("%s", pass); + + // restore terminal + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) + { + perror("tcsetattr"); + return exit(1); + } +}; + +const char *getPassword(struct User u) +{ + FILE *fp; + struct User userChecker; + + if ((fp = fopen("./data/users.txt", "r")) == NULL) + { + printf("Error! opening file"); + exit(1); + } + + while (fscanf(fp, "%s %s", userChecker.name, userChecker.password) != EOF) + { + if (strcmp(userChecker.name, u.name) == 0) + { + fclose(fp); + char *buff = userChecker.password; + return buff; + } + } + + fclose(fp); + return "no user found"; +} \ No newline at end of file diff --git a/subjects/atm-management-system/atm_system/src/header.h b/subjects/atm-management-system/atm_system/src/header.h new file mode 100644 index 00000000..61d7971a --- /dev/null +++ b/subjects/atm-management-system/atm_system/src/header.h @@ -0,0 +1,37 @@ +#include +#include +#include + +struct Date +{ + int month, day, year; +}; + +// all fields for each record of an account +struct Record +{ + char name[100]; + char country[100]; + int phone; + char accountType[10]; + int accountNbr; + double amount; + struct Date deposit; + struct Date withdraw; +}; + +struct User +{ + char name[50]; + char password[50]; +}; + +// authentication functions +void loginMenu(char a[50], char pass[50]); +void registerMenu(char a[50], char pass[50]); +const char *getPassword(struct User u); + +// system function +void createNewAcc(struct User u); +void mainMenu(struct User u); +void checkAllAccounts(struct User u); diff --git a/subjects/atm-management-system/atm_system/src/main.c b/subjects/atm-management-system/atm_system/src/main.c new file mode 100644 index 00000000..9829a876 --- /dev/null +++ b/subjects/atm-management-system/atm_system/src/main.c @@ -0,0 +1,104 @@ +#include "header.h" + +void mainMenu(struct User u) +{ + int option; + system("clear"); + printf("\n\n\t\t======= ATM =======\n\n"); + printf("\n\t\t-->> Feel free to choose one of the options below <<--\n"); + printf("\n\t\t[1]- Create a new account\n"); + printf("\n\t\t[2]- Update information of account\n"); + printf("\n\t\t[3]- Check accounts\n"); + printf("\n\t\t[4]- Check list of owned account\n"); + printf("\n\t\t[5]- Make Transaction\n"); + printf("\n\t\t[6]- Remove existing account\n"); + printf("\n\t\t[7]- Transfer ownership\n"); + printf("\n\t\t[8]- Exit\n"); + scanf("%d", &option); + + switch (option) + { + case 1: + createNewAcc(u); + break; + case 2: + // student TODO : add your **Update information of existing account** function + // here + break; + case 3: + // student TODO : add your **Check the details of existing accounts** function + // here + break; + case 4: + checkAllAccounts(u); + break; + case 5: + // student TODO : add your **Make transaction** function + // here + break; + case 6: + // student TODO : add your **Remove existing account** function + // here + break; + case 7: + // student TODO : add your **Transfer owner** function + // here + break; + case 8: + exit(1); + break; + default: + printf("Invalid operation!\n"); + } +}; + +void initMenu(struct User *u) +{ + int r = 0; + int option; + system("clear"); + printf("\n\n\t\t======= ATM =======\n"); + printf("\n\t\t-->> Feel free to login / register :\n"); + printf("\n\t\t[1]- login\n"); + printf("\n\t\t[2]- register\n"); + printf("\n\t\t[3]- exit\n"); + while (!r) + { + scanf("%d", &option); + switch (option) + { + case 1: + loginMenu(u->name, u->password); + if (strcmp(u->password, getPassword(*u)) == 0) + { + printf("\n\nPassword Match!"); + } + else + { + printf("\nWrong password!! or User Name\n"); + exit(1); + } + r = 1; + break; + case 2: + // student TODO : add your **Registration** function + // here + r = 1; + break; + case 3: + exit(1); + break; + default: + printf("Insert a valid operation!\n"); + } + } +}; + +int main() +{ + struct User u; + + initMenu(&u); + mainMenu(u); + return 0; +} diff --git a/subjects/atm-management-system/atm_system/src/system.c b/subjects/atm-management-system/atm_system/src/system.c new file mode 100644 index 00000000..1a5f03c9 --- /dev/null +++ b/subjects/atm-management-system/atm_system/src/system.c @@ -0,0 +1,161 @@ +#include "header.h" + +const char *RECORDS = "./data/records.txt"; + +int getAccountFromFile(FILE *ptr, char name[50], struct Record *r) +{ + return fscanf(ptr, "%s %d %d/%d/%d %s %d %lf %s", + name, + &r->accountNbr, + &r->deposit.month, + &r->deposit.day, + &r->deposit.year, + r->country, + &r->phone, + &r->amount, + r->accountType) != EOF; +} + +void saveAccountToFile(FILE *ptr, char name[50], struct Record r) +{ + fprintf(ptr, "%s %d %d/%d/%d %s %d %.2lf %s\n\n", + name, + r.accountNbr, + r.deposit.month, + r.deposit.day, + r.deposit.year, + r.country, + r.phone, + r.amount, + r.accountType); +} + +void stayOrReturn(int notGood, void f(struct User u), struct User u) +{ + int option; + if (notGood == 0) + { + system("clear"); + printf("\n✖ Record not found!!\n"); + invalid: + printf("\nEnter 0 to try again, 1 to return to main menu and 2 to exit:"); + scanf("%d", &option); + if (option == 0) + f(u); + else if (option == 1) + mainMenu(u); + else if (option == 2) + exit(0); + else + { + printf("Insert a valid operation!\n"); + goto invalid; + } + } + else + { + printf("\nEnter 1 to go to the main menu and 0 to exit:"); + scanf("%d", &option); + } + if (option == 1) + { + system("clear"); + mainMenu(u); + } + else + { + system("clear"); + exit(1); + } +} + +void success(struct User u) +{ + int option; + printf("\n✔ Success!\n\n"); +invalid: + printf("Enter 1 to go to the main menu and 0 to exit!\n"); + scanf("%d", &option); + system("clear"); + if (option == 1) + { + mainMenu(u); + } + else if (option == 0) + { + exit(1); + } + else + { + printf("Insert a valid operation!\n"); + goto invalid; + } +} + +void createNewAcc(struct User u) +{ + struct Record r; + struct Record cr; + char userName[50]; + FILE *pf = fopen(RECORDS, "a+"); + +noAccount: + system("clear"); + printf("\t\t\t===== New record =====\n"); + + printf("\nEnter today's date(mm/dd/yyyy):"); + scanf("%d/%d/%d", &r.deposit.month, &r.deposit.day, &r.deposit.year); + printf("\nEnter the account number:"); + scanf("%d", &r.accountNbr); + + while (getAccountFromFile(pf, userName, &cr)) + { + if (strcmp(userName, u.name) == 0 && cr.accountNbr == r.accountNbr) + { + printf("✖ This Account already exists for this user\n\n"); + goto noAccount; + } + } + printf("\nEnter the country:"); + scanf("%s", r.country); + printf("\nEnter the phone number:"); + scanf("%d", &r.phone); + printf("\nEnter amount to deposit: $"); + scanf("%lf", &r.amount); + printf("\nChoose the type of account:\n\t-> saving\n\t-> current\n\t-> fixed01(for 1 year)\n\t-> fixed02(for 2 years)\n\t-> fixed03(for 3 years)\n\n\tEnter your choice:"); + scanf("%s", r.accountType); + + saveAccountToFile(pf, u.name, r); + + fclose(pf); + success(u); +} + +void checkAllAccounts(struct User u) +{ + char userName[100]; + struct Record r; + + FILE *pf = fopen(RECORDS, "r"); + + system("clear"); + printf("\t\t====== All accounts from user, %s =====\n\n", u.name); + while (getAccountFromFile(pf, userName, &r)) + { + if (strcmp(userName, u.name) == 0) + { + printf("_____________________\n"); + printf("\nAccount number:%d\nDeposit Date:%d/%d/%d \ncountry:%s \nPhone number:%d \nAmount deposited: $%.2f \nType Of Account:%s\n", + r.accountNbr, + r.deposit.day, + r.deposit.month, + r.deposit.year, + r.country, + r.phone, + r.amount, + r.accountType); + } + } + fclose(pf); + success(u); +} diff --git a/subjects/atm-management-system/audit/README.md b/subjects/atm-management-system/audit/README.md new file mode 100644 index 00000000..db5ebf7e --- /dev/null +++ b/subjects/atm-management-system/audit/README.md @@ -0,0 +1,95 @@ +#### Functional + +##### Open the application and register a new user with the name `"Alice"` and the password `"q1w2e3r4t5y6"` + +###### Is this user saved in the file `"./data/users.txt"`, and if so are all credentials correct (name and password)? + +##### Open the application and register again the user `"Alice"`. + +###### Did it displayed an error message saying that this user already exists? + +##### Open the file `"./data/users.txt"`. + +###### Are all the user names unique? (ex: no repetition on the name Alice) + +##### Try and login as `"Alice"`. + +###### Was Alice able to enter the main menu? + +##### Try to create two accounts using the user Alice, then select the option `"Update information of account"` and select an account number that does not exist for Alice. + +###### Did the application displayed some kind of error message saying that this account does not exist? + +##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. + +###### Did the the application prompt a choice of updating the **phone number** or the **country**? + +##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the phone number of that account. + +###### Was the phone number of that account updated in the application and the file `"records.txt"`? + +##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the country of that account. + +###### Was the country of that account updated in the application and the file `"records.txt"`? + +##### Resorting to the user Alice try to create a new account with: date `"10/10/2012"` account number `"834213"`, country `"UK"`, phone number `"291231392"`, deposit amount $`"1001.20"`, type of account `"saving"`. Then select `"Check accounts"` choose the account you just created. + +###### Did the application displayed the account information and the gain of $5.84 of interest on day 10 of every moth? + +##### Resorting to the user Alice create again an account but with account number "320421" and type of account "fixed01" with the rest of the information as in the last account . Then select `"Check accounts"` and choose the account you just created. + +###### Did the application displayed the account information and the gain of $40.05 of interest on 10/10/2013? + +##### Resorting to the user Alice create again an account but with account number `"3214"` and type of account `"fixed02"` with the rest of the information as in the last account. Then select `"Check accounts"` and choose the account you just created. + +###### Did the application displayed the account information and the gain of $100.12 of interest on 10/10/2014? + +##### Resorting to the user Alice create again an account but with account number `"3212"` and type of account `"fixed03"` with the rest of the information as in the last account. Then select `"Check accounts"` and choose the account you just created. + +###### Did the application displayed the account information and the gain of $240.29 of interest on 10/10/2015? + +##### Resorting to the user Alice select the option `"Make transaction"`. Then choose the account with the id `"3212"` + +###### Are you able to choose between withdrawing or depositing? + +##### Resorting to the user Alice select the option `"Make transaction"`, choose the account with the id `"3212"`. Then try to withdraw money. + +###### Are you able to withdraw money? + +###### And if so, was the withdraw updated in the file `"records.txt"`? + +###### Is it not possible to withdraw an amount superior to your available balance? + +##### Try to deposit money into the account `"3212"`. + +###### Were you able to deposit money into this account? + +###### And if so did it update the file `"records.txt"`? + +##### Resorting to the user Alice try to select the option `"Remove existing account"` and remove the accounts `"834213"`, `"320421"` and `"3214"`. + +###### Can you confirm that those account were deleted, both in the application and file `"records.txt"`? + +##### Resorting to the user Alice select the option `"Remove existing account"` and try to remove and nonexisting account. + +###### Did the application prompt some type of error saying that the account does not exists? + +##### Create another user named `"Michel"`. Then by using Alice select the option `"transfer owner"` and try to transfer ownership of the account `"3212"` to Michel. + +###### Were you able to transfer the ownership of this account to Michel? And if so did it update both application and file `"records.txt"`? + +#### Bonus + +##### Open two terminals and login with two different users. Then transfer ownership of an account to the other user. + +###### +Was the user whom received the account notified instantly? + +###### +Did the student update the terminal interface? + +###### +Is the password saved in the file `"users.txt"` encrypted? + +###### +Did the student make their own Makefile? + +###### +Did the student add more features to the project? + +###### +Did the student optimise the code already given? \ No newline at end of file From 513ec227f615975db52b3f6a3754ff88bc69971a Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 5 Feb 2021 16:11:35 +0000 Subject: [PATCH 41/42] correction of audit and removal of extra folder --- .../atm-management-system/audit/README.md | 20 +-- subjects/atm_management_system/README.md | 133 --------------- .../atm_management_system/atm_system/Makefile | 16 -- .../atm_system/data/records.txt | 6 - .../atm_system/data/users.txt | 2 - .../atm_system/src/auth.c | 59 ------- .../atm_system/src/header.h | 37 ---- .../atm_system/src/main.c | 104 ----------- .../atm_system/src/system.c | 161 ------------------ .../atm_management_system/audit/README.md | 95 ----------- 10 files changed, 10 insertions(+), 623 deletions(-) delete mode 100644 subjects/atm_management_system/README.md delete mode 100644 subjects/atm_management_system/atm_system/Makefile delete mode 100644 subjects/atm_management_system/atm_system/data/records.txt delete mode 100644 subjects/atm_management_system/atm_system/data/users.txt delete mode 100644 subjects/atm_management_system/atm_system/src/auth.c delete mode 100644 subjects/atm_management_system/atm_system/src/header.h delete mode 100644 subjects/atm_management_system/atm_system/src/main.c delete mode 100644 subjects/atm_management_system/atm_system/src/system.c delete mode 100644 subjects/atm_management_system/audit/README.md diff --git a/subjects/atm-management-system/audit/README.md b/subjects/atm-management-system/audit/README.md index db5ebf7e..caf2ae7b 100644 --- a/subjects/atm-management-system/audit/README.md +++ b/subjects/atm-management-system/audit/README.md @@ -1,16 +1,16 @@ #### Functional -##### Open the application and register a new user with the name `"Alice"` and the password `"q1w2e3r4t5y6"` +##### Open the application and register a new user with the name `"Alice"` and the password `"q1w2e3r4t5y6"`. -###### Is this user saved in the file `"./data/users.txt"`, and if so are all credentials correct (name and password)? +###### Is this user saved in the file `"./data/users.txt"`, and if so, are all credentials correct (name and password)? -##### Open the application and register again the user `"Alice"`. +##### Open the application and re-register the user `"Alice"`. -###### Did it displayed an error message saying that this user already exists? +###### Did it display an error message stating that this user already exist? ##### Open the file `"./data/users.txt"`. -###### Are all the user names unique? (ex: no repetition on the name Alice) +###### Are all the user's names unique? (ex: no repetition on the name Alice) ##### Try and login as `"Alice"`. @@ -18,21 +18,21 @@ ##### Try to create two accounts using the user Alice, then select the option `"Update information of account"` and select an account number that does not exist for Alice. -###### Did the application displayed some kind of error message saying that this account does not exist? +###### Did the application displayed some kind of error message stating that this account does not exist? -##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. +##### Resorting to the user Alice, try and select the option `"Update information of account"` and select one of the accounts you created for Alice. ###### Did the the application prompt a choice of updating the **phone number** or the **country**? -##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the phone number of that account. +##### Resorting to the user Alice, try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the phone number of that account. ###### Was the phone number of that account updated in the application and the file `"records.txt"`? -##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the country of that account. +##### Resorting to the user Alice, try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the country of that account. ###### Was the country of that account updated in the application and the file `"records.txt"`? -##### Resorting to the user Alice try to create a new account with: date `"10/10/2012"` account number `"834213"`, country `"UK"`, phone number `"291231392"`, deposit amount $`"1001.20"`, type of account `"saving"`. Then select `"Check accounts"` choose the account you just created. +##### Resorting to the user Alice, try to create a new account with: date `"10/10/2012"` account number `"834213"`, country `"UK"`, phone number `"291231392"`, deposit amount $`"1001.20"`, type of account `"saving"`. Then select `"Check accounts"` choose the account you just created. ###### Did the application displayed the account information and the gain of $5.84 of interest on day 10 of every moth? diff --git a/subjects/atm_management_system/README.md b/subjects/atm_management_system/README.md deleted file mode 100644 index ac65c0a8..00000000 --- a/subjects/atm_management_system/README.md +++ /dev/null @@ -1,133 +0,0 @@ -## ATM - -### Objective - -The objective for this project is to show that you have learned to program and you are able to adapt to new languages. - -The programming language you are about to use is [C](https://en.wikipedia.org/wiki/C_%28programming_language%29). It will not be asked to create -a project from scratch, but **to add features or fix the code of a given application**. - -### Instructions - -You will be provided with an ATM management system where users can do the following actions: - -- Login/Register -- Create a new account -- Update information of existing accounts -- Check the details of existing accounts -- Check list of owned accounts -- Make transactions -- Remove existing accounts - -The application provided will just handle the **login**, **creation of new accounts** and **check list of owned accounts**. The rest of the features must -be implemented by you. - -### File System - -It will be provided a folder that you can find [here](https://downgit.github.io/#/home?url=https://github.com/01-edu/public/tree/master/subjects/atm-management-system/atm-system/), this folder will have the following fs: - -```console -. -| -├── data -│   ├── records.txt -│   └── users.txt -├── Makefile -├── README.md -└── src -    ├── auth.c -    ├── header.h -    ├── main.c -    └── system.c -``` - -The `data` folder presented above will contain information about the users and their accounts: - -- `users.txt` will be the a file that stores all information about each user -- `records.txt` will be the a file that stores all information relevant to the accounts for each user - -The format for the content saved in the file will be displayed like this : - -`users.txt` (name, password): - -```console -Alice 1234password -Michel password1234 -.... -``` - -`records.txt` (user name, account id, date of creation, country, phone nº, type of account) : - -```console -Alice 0 10/02/2020 german 986134231 11090830.00 current -Michel 2 10/10/2021 portugal 914134431 1920.42 saving -Alice 1 10/10/2000 finland 986134231 1234.21 saving -.... -``` - -### Features - -The following features must be done by you. - -1. **Registration**, you must be able to register new users, it cannot exist users with the same name (names must be unique). They must be saved into the right file - -2. **Update information of existing account**, users must be able to update their country or phone number - - 2.1. You must ask users to input the account id they want to change, followed by a prompt asking which field they want to also change (the only fields that are permitted to update is the phone number and the country). - - 2.2. Whenever users update an account, it must be saved into the corresponding file. - -3. **Check the details of existing accounts**, users must be able to check just one account at a time. - - 3.1. For this it must be asked to input the account id they want to see - - 3.2. If the account is either saving, fixed01, fixed02 and fixed03 the system will display - the information of that account and the interest you will acquire depending on the account: - - - saving: rate interest 0.07% - - fixed01(1 year account): rate interest 0.04% - - fixed02(2 year account): rate interest 0.05% - - fixed03(3 year account): rate interest 0.08% - - If the account is current you must display `You will not get interests because the account is of type current` - -4. **Make transaction**, users must be able to create transactions, withdrawing or depositing money to a certain account. All transactions - must be updated and saved into the corresponding file - -5. **Remove existing account**, users must be able to delete their own account, same must happened here, updates must be saved into the corresponding file. - -6. **Transfer owner**, users can transfer their account to another user, by: - - 6.1. Identifying the account and the user they want to transfer the ownership to - - 6.2. Saving the information in the corresponding file - -### Bonus - -As bonus you can add a verification to the field **Transfer owner**. Every time a user transfers ownership of an account the other user who received the account -can be alerted that it received and account from someone instantly. -Example if you have two terminals opened logged in two different users, and one send the account to the other user, -the user who received the account should be instantly notified -One of the ways of doing this is by using pipes and child processes (communication between process) - -You can also do more bonus features or update the terminal interface: - -- Better terminal interface -- Encryption of passwords -- Adding own Makefile - -### Example - -You can find an example of the final application [here](https://www.youtube.com/watch?v=1LjwbIFt5Qo). Do not forget that you are free to -implement whatever kind of interface you desire. It just needs to obey the instructions given above so it can pass the audit. - -This project will help you learn about: - -- [C](https://en.wikipedia.org/wiki/C_%28programming_language%29) language - - Language Fundamentals -- Data manipulation - - File manipulation - - Data structures -- Makefile -- Terminal UI -- Memory management -- Pipes and child processes diff --git a/subjects/atm_management_system/atm_system/Makefile b/subjects/atm_management_system/atm_system/Makefile deleted file mode 100644 index 62befd2c..00000000 --- a/subjects/atm_management_system/atm_system/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -objects = src/main.o src/system.o src/auth.o - -atm : $(objects) - cc -o atm $(objects) - -main.o : src/header.h -kbd.o : src/header.h -command.o : src/header.h -display.o : src/header.h -insert.o : src/header.h -search.o : src/header.h -files.o : src/header.h -utils.o : src/header.h - -clean : - rm -f $(objects) diff --git a/subjects/atm_management_system/atm_system/data/records.txt b/subjects/atm_management_system/atm_system/data/records.txt deleted file mode 100644 index b9d75f71..00000000 --- a/subjects/atm_management_system/atm_system/data/records.txt +++ /dev/null @@ -1,6 +0,0 @@ -Alice 0 10/10/2012 Africa 291321234 22432.52 saving - -Michel 2 2/5/2001 Portugal 123543455 10023.230000 fixed01 - -Michel 123 10/10/2020 UK 1234123 12345.30 saving - diff --git a/subjects/atm_management_system/atm_system/data/users.txt b/subjects/atm_management_system/atm_system/data/users.txt deleted file mode 100644 index 00694cf8..00000000 --- a/subjects/atm_management_system/atm_system/data/users.txt +++ /dev/null @@ -1,2 +0,0 @@ -Alice q1w2e3r4t5y6 -Michel q1w2e3r4t5y6 diff --git a/subjects/atm_management_system/atm_system/src/auth.c b/subjects/atm_management_system/atm_system/src/auth.c deleted file mode 100644 index c3e61b08..00000000 --- a/subjects/atm_management_system/atm_system/src/auth.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include "header.h" - -char *USERS = "./data/users.txt"; - -void loginMenu(char a[50], char pass[50]) -{ - struct termios oflags, nflags; - - system("clear"); - printf("\n\n\n\t\t\t\t Bank Management System\n\t\t\t\t\t User Login:"); - scanf("%s", a); - - // disabling echo - tcgetattr(fileno(stdin), &oflags); - nflags = oflags; - nflags.c_lflag &= ~ECHO; - nflags.c_lflag |= ECHONL; - - if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) - { - perror("tcsetattr"); - return exit(1); - } - printf("\n\n\n\n\n\t\t\t\tEnter the password to login:"); - scanf("%s", pass); - - // restore terminal - if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) - { - perror("tcsetattr"); - return exit(1); - } -}; - -const char *getPassword(struct User u) -{ - FILE *fp; - struct User userChecker; - - if ((fp = fopen("./data/users.txt", "r")) == NULL) - { - printf("Error! opening file"); - exit(1); - } - - while (fscanf(fp, "%s %s", userChecker.name, userChecker.password) != EOF) - { - if (strcmp(userChecker.name, u.name) == 0) - { - fclose(fp); - char *buff = userChecker.password; - return buff; - } - } - - fclose(fp); - return "no user found"; -} \ No newline at end of file diff --git a/subjects/atm_management_system/atm_system/src/header.h b/subjects/atm_management_system/atm_system/src/header.h deleted file mode 100644 index 61d7971a..00000000 --- a/subjects/atm_management_system/atm_system/src/header.h +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -struct Date -{ - int month, day, year; -}; - -// all fields for each record of an account -struct Record -{ - char name[100]; - char country[100]; - int phone; - char accountType[10]; - int accountNbr; - double amount; - struct Date deposit; - struct Date withdraw; -}; - -struct User -{ - char name[50]; - char password[50]; -}; - -// authentication functions -void loginMenu(char a[50], char pass[50]); -void registerMenu(char a[50], char pass[50]); -const char *getPassword(struct User u); - -// system function -void createNewAcc(struct User u); -void mainMenu(struct User u); -void checkAllAccounts(struct User u); diff --git a/subjects/atm_management_system/atm_system/src/main.c b/subjects/atm_management_system/atm_system/src/main.c deleted file mode 100644 index 9829a876..00000000 --- a/subjects/atm_management_system/atm_system/src/main.c +++ /dev/null @@ -1,104 +0,0 @@ -#include "header.h" - -void mainMenu(struct User u) -{ - int option; - system("clear"); - printf("\n\n\t\t======= ATM =======\n\n"); - printf("\n\t\t-->> Feel free to choose one of the options below <<--\n"); - printf("\n\t\t[1]- Create a new account\n"); - printf("\n\t\t[2]- Update information of account\n"); - printf("\n\t\t[3]- Check accounts\n"); - printf("\n\t\t[4]- Check list of owned account\n"); - printf("\n\t\t[5]- Make Transaction\n"); - printf("\n\t\t[6]- Remove existing account\n"); - printf("\n\t\t[7]- Transfer ownership\n"); - printf("\n\t\t[8]- Exit\n"); - scanf("%d", &option); - - switch (option) - { - case 1: - createNewAcc(u); - break; - case 2: - // student TODO : add your **Update information of existing account** function - // here - break; - case 3: - // student TODO : add your **Check the details of existing accounts** function - // here - break; - case 4: - checkAllAccounts(u); - break; - case 5: - // student TODO : add your **Make transaction** function - // here - break; - case 6: - // student TODO : add your **Remove existing account** function - // here - break; - case 7: - // student TODO : add your **Transfer owner** function - // here - break; - case 8: - exit(1); - break; - default: - printf("Invalid operation!\n"); - } -}; - -void initMenu(struct User *u) -{ - int r = 0; - int option; - system("clear"); - printf("\n\n\t\t======= ATM =======\n"); - printf("\n\t\t-->> Feel free to login / register :\n"); - printf("\n\t\t[1]- login\n"); - printf("\n\t\t[2]- register\n"); - printf("\n\t\t[3]- exit\n"); - while (!r) - { - scanf("%d", &option); - switch (option) - { - case 1: - loginMenu(u->name, u->password); - if (strcmp(u->password, getPassword(*u)) == 0) - { - printf("\n\nPassword Match!"); - } - else - { - printf("\nWrong password!! or User Name\n"); - exit(1); - } - r = 1; - break; - case 2: - // student TODO : add your **Registration** function - // here - r = 1; - break; - case 3: - exit(1); - break; - default: - printf("Insert a valid operation!\n"); - } - } -}; - -int main() -{ - struct User u; - - initMenu(&u); - mainMenu(u); - return 0; -} diff --git a/subjects/atm_management_system/atm_system/src/system.c b/subjects/atm_management_system/atm_system/src/system.c deleted file mode 100644 index 1a5f03c9..00000000 --- a/subjects/atm_management_system/atm_system/src/system.c +++ /dev/null @@ -1,161 +0,0 @@ -#include "header.h" - -const char *RECORDS = "./data/records.txt"; - -int getAccountFromFile(FILE *ptr, char name[50], struct Record *r) -{ - return fscanf(ptr, "%s %d %d/%d/%d %s %d %lf %s", - name, - &r->accountNbr, - &r->deposit.month, - &r->deposit.day, - &r->deposit.year, - r->country, - &r->phone, - &r->amount, - r->accountType) != EOF; -} - -void saveAccountToFile(FILE *ptr, char name[50], struct Record r) -{ - fprintf(ptr, "%s %d %d/%d/%d %s %d %.2lf %s\n\n", - name, - r.accountNbr, - r.deposit.month, - r.deposit.day, - r.deposit.year, - r.country, - r.phone, - r.amount, - r.accountType); -} - -void stayOrReturn(int notGood, void f(struct User u), struct User u) -{ - int option; - if (notGood == 0) - { - system("clear"); - printf("\n✖ Record not found!!\n"); - invalid: - printf("\nEnter 0 to try again, 1 to return to main menu and 2 to exit:"); - scanf("%d", &option); - if (option == 0) - f(u); - else if (option == 1) - mainMenu(u); - else if (option == 2) - exit(0); - else - { - printf("Insert a valid operation!\n"); - goto invalid; - } - } - else - { - printf("\nEnter 1 to go to the main menu and 0 to exit:"); - scanf("%d", &option); - } - if (option == 1) - { - system("clear"); - mainMenu(u); - } - else - { - system("clear"); - exit(1); - } -} - -void success(struct User u) -{ - int option; - printf("\n✔ Success!\n\n"); -invalid: - printf("Enter 1 to go to the main menu and 0 to exit!\n"); - scanf("%d", &option); - system("clear"); - if (option == 1) - { - mainMenu(u); - } - else if (option == 0) - { - exit(1); - } - else - { - printf("Insert a valid operation!\n"); - goto invalid; - } -} - -void createNewAcc(struct User u) -{ - struct Record r; - struct Record cr; - char userName[50]; - FILE *pf = fopen(RECORDS, "a+"); - -noAccount: - system("clear"); - printf("\t\t\t===== New record =====\n"); - - printf("\nEnter today's date(mm/dd/yyyy):"); - scanf("%d/%d/%d", &r.deposit.month, &r.deposit.day, &r.deposit.year); - printf("\nEnter the account number:"); - scanf("%d", &r.accountNbr); - - while (getAccountFromFile(pf, userName, &cr)) - { - if (strcmp(userName, u.name) == 0 && cr.accountNbr == r.accountNbr) - { - printf("✖ This Account already exists for this user\n\n"); - goto noAccount; - } - } - printf("\nEnter the country:"); - scanf("%s", r.country); - printf("\nEnter the phone number:"); - scanf("%d", &r.phone); - printf("\nEnter amount to deposit: $"); - scanf("%lf", &r.amount); - printf("\nChoose the type of account:\n\t-> saving\n\t-> current\n\t-> fixed01(for 1 year)\n\t-> fixed02(for 2 years)\n\t-> fixed03(for 3 years)\n\n\tEnter your choice:"); - scanf("%s", r.accountType); - - saveAccountToFile(pf, u.name, r); - - fclose(pf); - success(u); -} - -void checkAllAccounts(struct User u) -{ - char userName[100]; - struct Record r; - - FILE *pf = fopen(RECORDS, "r"); - - system("clear"); - printf("\t\t====== All accounts from user, %s =====\n\n", u.name); - while (getAccountFromFile(pf, userName, &r)) - { - if (strcmp(userName, u.name) == 0) - { - printf("_____________________\n"); - printf("\nAccount number:%d\nDeposit Date:%d/%d/%d \ncountry:%s \nPhone number:%d \nAmount deposited: $%.2f \nType Of Account:%s\n", - r.accountNbr, - r.deposit.day, - r.deposit.month, - r.deposit.year, - r.country, - r.phone, - r.amount, - r.accountType); - } - } - fclose(pf); - success(u); -} diff --git a/subjects/atm_management_system/audit/README.md b/subjects/atm_management_system/audit/README.md deleted file mode 100644 index db5ebf7e..00000000 --- a/subjects/atm_management_system/audit/README.md +++ /dev/null @@ -1,95 +0,0 @@ -#### Functional - -##### Open the application and register a new user with the name `"Alice"` and the password `"q1w2e3r4t5y6"` - -###### Is this user saved in the file `"./data/users.txt"`, and if so are all credentials correct (name and password)? - -##### Open the application and register again the user `"Alice"`. - -###### Did it displayed an error message saying that this user already exists? - -##### Open the file `"./data/users.txt"`. - -###### Are all the user names unique? (ex: no repetition on the name Alice) - -##### Try and login as `"Alice"`. - -###### Was Alice able to enter the main menu? - -##### Try to create two accounts using the user Alice, then select the option `"Update information of account"` and select an account number that does not exist for Alice. - -###### Did the application displayed some kind of error message saying that this account does not exist? - -##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. - -###### Did the the application prompt a choice of updating the **phone number** or the **country**? - -##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the phone number of that account. - -###### Was the phone number of that account updated in the application and the file `"records.txt"`? - -##### Resorting to the user Alice try and select the option `"Update information of account"` and select one of the accounts you created for Alice. Then update the country of that account. - -###### Was the country of that account updated in the application and the file `"records.txt"`? - -##### Resorting to the user Alice try to create a new account with: date `"10/10/2012"` account number `"834213"`, country `"UK"`, phone number `"291231392"`, deposit amount $`"1001.20"`, type of account `"saving"`. Then select `"Check accounts"` choose the account you just created. - -###### Did the application displayed the account information and the gain of $5.84 of interest on day 10 of every moth? - -##### Resorting to the user Alice create again an account but with account number "320421" and type of account "fixed01" with the rest of the information as in the last account . Then select `"Check accounts"` and choose the account you just created. - -###### Did the application displayed the account information and the gain of $40.05 of interest on 10/10/2013? - -##### Resorting to the user Alice create again an account but with account number `"3214"` and type of account `"fixed02"` with the rest of the information as in the last account. Then select `"Check accounts"` and choose the account you just created. - -###### Did the application displayed the account information and the gain of $100.12 of interest on 10/10/2014? - -##### Resorting to the user Alice create again an account but with account number `"3212"` and type of account `"fixed03"` with the rest of the information as in the last account. Then select `"Check accounts"` and choose the account you just created. - -###### Did the application displayed the account information and the gain of $240.29 of interest on 10/10/2015? - -##### Resorting to the user Alice select the option `"Make transaction"`. Then choose the account with the id `"3212"` - -###### Are you able to choose between withdrawing or depositing? - -##### Resorting to the user Alice select the option `"Make transaction"`, choose the account with the id `"3212"`. Then try to withdraw money. - -###### Are you able to withdraw money? - -###### And if so, was the withdraw updated in the file `"records.txt"`? - -###### Is it not possible to withdraw an amount superior to your available balance? - -##### Try to deposit money into the account `"3212"`. - -###### Were you able to deposit money into this account? - -###### And if so did it update the file `"records.txt"`? - -##### Resorting to the user Alice try to select the option `"Remove existing account"` and remove the accounts `"834213"`, `"320421"` and `"3214"`. - -###### Can you confirm that those account were deleted, both in the application and file `"records.txt"`? - -##### Resorting to the user Alice select the option `"Remove existing account"` and try to remove and nonexisting account. - -###### Did the application prompt some type of error saying that the account does not exists? - -##### Create another user named `"Michel"`. Then by using Alice select the option `"transfer owner"` and try to transfer ownership of the account `"3212"` to Michel. - -###### Were you able to transfer the ownership of this account to Michel? And if so did it update both application and file `"records.txt"`? - -#### Bonus - -##### Open two terminals and login with two different users. Then transfer ownership of an account to the other user. - -###### +Was the user whom received the account notified instantly? - -###### +Did the student update the terminal interface? - -###### +Is the password saved in the file `"users.txt"` encrypted? - -###### +Did the student make their own Makefile? - -###### +Did the student add more features to the project? - -###### +Did the student optimise the code already given? \ No newline at end of file From ff42a2c7f10a84f985e6ab446aea462537771f29 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 5 Feb 2021 16:14:05 +0000 Subject: [PATCH 42/42] renaming of source folder --- .../atm-management-system/{atm_system => atm-system}/Makefile | 0 .../{atm_system => atm-system}/data/records.txt | 0 .../{atm_system => atm-system}/data/users.txt | 0 .../atm-management-system/{atm_system => atm-system}/src/auth.c | 0 .../atm-management-system/{atm_system => atm-system}/src/header.h | 0 .../atm-management-system/{atm_system => atm-system}/src/main.c | 0 .../atm-management-system/{atm_system => atm-system}/src/system.c | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename subjects/atm-management-system/{atm_system => atm-system}/Makefile (100%) rename subjects/atm-management-system/{atm_system => atm-system}/data/records.txt (100%) rename subjects/atm-management-system/{atm_system => atm-system}/data/users.txt (100%) rename subjects/atm-management-system/{atm_system => atm-system}/src/auth.c (100%) rename subjects/atm-management-system/{atm_system => atm-system}/src/header.h (100%) rename subjects/atm-management-system/{atm_system => atm-system}/src/main.c (100%) rename subjects/atm-management-system/{atm_system => atm-system}/src/system.c (100%) diff --git a/subjects/atm-management-system/atm_system/Makefile b/subjects/atm-management-system/atm-system/Makefile similarity index 100% rename from subjects/atm-management-system/atm_system/Makefile rename to subjects/atm-management-system/atm-system/Makefile diff --git a/subjects/atm-management-system/atm_system/data/records.txt b/subjects/atm-management-system/atm-system/data/records.txt similarity index 100% rename from subjects/atm-management-system/atm_system/data/records.txt rename to subjects/atm-management-system/atm-system/data/records.txt diff --git a/subjects/atm-management-system/atm_system/data/users.txt b/subjects/atm-management-system/atm-system/data/users.txt similarity index 100% rename from subjects/atm-management-system/atm_system/data/users.txt rename to subjects/atm-management-system/atm-system/data/users.txt diff --git a/subjects/atm-management-system/atm_system/src/auth.c b/subjects/atm-management-system/atm-system/src/auth.c similarity index 100% rename from subjects/atm-management-system/atm_system/src/auth.c rename to subjects/atm-management-system/atm-system/src/auth.c diff --git a/subjects/atm-management-system/atm_system/src/header.h b/subjects/atm-management-system/atm-system/src/header.h similarity index 100% rename from subjects/atm-management-system/atm_system/src/header.h rename to subjects/atm-management-system/atm-system/src/header.h diff --git a/subjects/atm-management-system/atm_system/src/main.c b/subjects/atm-management-system/atm-system/src/main.c similarity index 100% rename from subjects/atm-management-system/atm_system/src/main.c rename to subjects/atm-management-system/atm-system/src/main.c diff --git a/subjects/atm-management-system/atm_system/src/system.c b/subjects/atm-management-system/atm-system/src/system.c similarity index 100% rename from subjects/atm-management-system/atm_system/src/system.c rename to subjects/atm-management-system/atm-system/src/system.c