From 245cbec983ed3836abcaa2ba96412de2acecb08a Mon Sep 17 00:00:00 2001 From: Sasza Stanczew Date: Mon, 6 May 2024 11:58:30 +0200 Subject: [PATCH] Reliable - pierwszy commit --- CreatingReliableSoftwareCpp/LICENSE | 19 + .../Presentation/agenda.md | 28 + .../Presentation/builder.md | 806 +++ .../Presentation/compilation.md | 43 + .../Presentation/decorator.md | 577 ++ .../Presentation/design_patterns_intro.md | 1 + .../Presentation/examples/builder/builder.cpp | 204 + .../examples/builder/builder/CMakeLists.txt | 29 + .../examples/builder/builder/main.cpp | 65 + .../examples/builder/builder/ships.json | 20 + .../builder/builder/src/Battle/CMakeLists.txt | 8 + .../src/Battle/include/Battle/Action.h | 24 + .../src/Battle/include/Battle/Attack.h | 12 + .../src/Battle/include/Battle/BattleField.h | 19 + .../src/Battle/include/Battle/Defense.h | 12 + .../src/Battle/include/Battle/Escape.h | 18 + .../builder/builder/src/Battle/src/Attack.cpp | 22 + .../builder/src/Battle/src/BattleField.cpp | 16 + .../builder/src/Battle/src/Defense.cpp | 13 + .../builder/builder/src/Battle/src/Escape.cpp | 22 + .../builder/builder/src/CMakeLists.txt | 5 + .../builder/builder/src/Core/CMakeLists.txt | 8 + .../src/Core/include/Core/BasicPrintVisitor.h | 12 + .../Core/include/Core/DifficultLvlStrategy.h | 12 + .../Core/include/Core/PrettyPrintVisitor.h | 12 + .../src/Core/include/Core/PrintVisitor.h | 11 + .../builder/src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../src/Core/src/BasicPrintVisitor.cpp | 22 + .../src/Core/src/PrettyPrintVisitor.cpp | 33 + .../builder/builder/src/Core/src/Time.cpp | 24 + .../builder/builder/src/Player/CMakeLists.txt | 9 + .../builder/src/Player/include/Player/Enemy.h | 66 + .../Player/EnemyEasyDifficultLvlStrategy.h | 17 + .../Player/EnemyHardDifficultLvlStrategy.h | 17 + .../src/Player/include/Player/Player.h | 22 + .../src/Player/include/Player/RealPlayer.h | 26 + .../src/EnemyEasyDifficultLvlStrategy.cpp | 28 + .../src/EnemyHardDifficultLvlStrategy.cpp | 31 + .../builder/builder/src/Player/src/Player.cpp | 11 + .../builder/src/Player/src/RealPlayer.cpp | 56 + .../builder/builder/src/Ship/CMakeLists.txt | 15 + .../src/Ship/include/Ship/AlcoholFactory.h | 14 + .../builder/src/Ship/include/Ship/Cargo.h | 59 + .../Ship/include/Ship/CargoDamageVisitor.h | 25 + .../src/Ship/include/Ship/CargoFactory.h | 12 + .../src/Ship/include/Ship/FruitFactory.h | 14 + .../src/Ship/include/Ship/ItemFactory.h | 14 + .../builder/src/Ship/include/Ship/Ship.h | 70 + .../src/Ship/include/Ship/ShipBuilder.h | 28 + .../Ship/ShipEasyDifficultLvlStrategy.h | 10 + .../Ship/ShipHardDifficultLvlStrategy.h | 10 + .../src/Ship/include/Ship/ShipJsonBuilder.h | 26 + .../builder/builder/src/Ship/src/Cargo.cpp | 54 + .../src/Ship/src/CargoDamageVisitor.cpp | 20 + .../builder/builder/src/Ship/src/Ship.cpp | 107 + .../builder/src/Ship/src/ShipBuilder.cpp | 68 + .../Ship/src/ShipEasyDifficultLvlStrategy.cpp | 12 + .../Ship/src/ShipHardDifficultLvlStrategy.cpp | 12 + .../builder/src/Ship/src/ShipJsonBuilder.cpp | 48 + .../builder/builder/src/Store/CMakeLists.txt | 7 + .../builder/src/Store/include/Store/Store.h | 30 + .../builder/builder/src/Store/src/Store.cpp | 41 + .../builder/builder/tests/CMakeLists.txt | 21 + .../builder/builder/tests/CargoMock.h | 3 + .../builder/builder/tests/ShipUnitTests.cpp | 9 + .../builder/builder/tests/StoreUnitTests.cpp | 11 + .../examples/builder/builder2.cpp | 152 + .../examples/builder/builder3.cpp | 173 + .../examples/decorator/decorator.cpp | 162 + .../decorator/decorator/CMakeLists.txt | 29 + .../examples/decorator/decorator/main.cpp | 53 + .../examples/decorator/decorator/ships.json | 20 + .../decorator/src/Battle/CMakeLists.txt | 8 + .../src/Battle/include/Battle/Action.h | 24 + .../src/Battle/include/Battle/Attack.h | 12 + .../src/Battle/include/Battle/BattleField.h | 19 + .../src/Battle/include/Battle/Defense.h | 12 + .../src/Battle/include/Battle/Escape.h | 18 + .../decorator/src/Battle/src/Attack.cpp | 22 + .../decorator/src/Battle/src/BattleField.cpp | 16 + .../decorator/src/Battle/src/Defense.cpp | 13 + .../decorator/src/Battle/src/Escape.cpp | 22 + .../decorator/decorator/src/CMakeLists.txt | 5 + .../decorator/src/Core/CMakeLists.txt | 8 + .../src/Core/include/Core/BasicPrintVisitor.h | 12 + .../Core/include/Core/DifficultLvlStrategy.h | 12 + .../Core/include/Core/FullInfoPrintVisitor.h | 15 + .../Core/include/Core/PrettyPrintVisitor.h | 12 + .../src/Core/include/Core/PrintVisitor.h | 11 + .../decorator/src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../src/Core/src/BasicPrintVisitor.cpp | 22 + .../src/Core/src/FullInfoPrintVisitor.cpp | 24 + .../src/Core/src/PrettyPrintVisitor.cpp | 33 + .../decorator/decorator/src/Core/src/Time.cpp | 24 + .../decorator/src/Player/CMakeLists.txt | 9 + .../src/Player/include/Player/Enemy.h | 66 + .../Player/EnemyEasyDifficultLvlStrategy.h | 17 + .../Player/EnemyHardDifficultLvlStrategy.h | 17 + .../src/Player/include/Player/Player.h | 22 + .../src/Player/include/Player/RealPlayer.h | 26 + .../src/EnemyEasyDifficultLvlStrategy.cpp | 28 + .../src/EnemyHardDifficultLvlStrategy.cpp | 31 + .../decorator/src/Player/src/Player.cpp | 11 + .../decorator/src/Player/src/RealPlayer.cpp | 56 + .../decorator/src/Ship/CMakeLists.txt | 17 + .../src/Ship/include/Ship/AlcoholFactory.h | 14 + .../src/Ship/include/Ship/AlcoholType.h | 6 + .../decorator/src/Ship/include/Ship/Cargo.h | 63 + .../Ship/include/Ship/CargoDamageVisitor.h | 25 + .../src/Ship/include/Ship/CargoFactory.h | 12 + .../src/Ship/include/Ship/DecoratedCargo.h | 17 + .../src/Ship/include/Ship/FruitFactory.h | 14 + .../src/Ship/include/Ship/ItemFactory.h | 14 + .../src/Ship/include/Ship/ItemType.h | 6 + .../decorator/src/Ship/include/Ship/Ship.h | 70 + .../src/Ship/include/Ship/ShipBuilder.h | 28 + .../Ship/ShipEasyDifficultLvlStrategy.h | 10 + .../Ship/ShipHardDifficultLvlStrategy.h | 10 + .../src/Ship/include/Ship/ShipJsonBuilder.h | 26 + .../src/Ship/include/Ship/Valuable.h | 31 + .../src/Ship/include/Ship/Vulnerable.h | 29 + .../decorator/src/Ship/src/Cargo.cpp | 46 + .../src/Ship/src/CargoDamageVisitor.cpp | 20 + .../decorator/src/Ship/src/DecoratedCargo.cpp | 8 + .../decorator/decorator/src/Ship/src/Ship.cpp | 108 + .../decorator/src/Ship/src/ShipBuilder.cpp | 68 + .../Ship/src/ShipEasyDifficultLvlStrategy.cpp | 12 + .../Ship/src/ShipHardDifficultLvlStrategy.cpp | 12 + .../src/Ship/src/ShipJsonBuilder.cpp | 48 + .../decorator/src/Ship/src/Vulnerable.cpp | 32 + .../decorator/src/Store/CMakeLists.txt | 7 + .../decorator/src/Store/include/Store/Store.h | 30 + .../decorator/src/Store/src/Store.cpp | 41 + .../decorator/decorator/tests/CMakeLists.txt | 21 + .../decorator/decorator/tests/CargoMock.h | 3 + .../decorator/tests/ShipUnitTests.cpp | 9 + .../decorator/tests/StoreUnitTests.cpp | 11 + .../examples/decorator/decorator2.cpp | 209 + .../examples/decorator/decorator3.cpp | 186 + .../examples/observer/observer.cpp | 69 + .../examples/observer/observer/CMakeLists.txt | 19 + .../examples/observer/observer/main.cpp | 44 + .../observer/observer/src/CMakeLists.txt | 3 + .../observer/observer/src/Core/CMakeLists.txt | 3 + .../observer/src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../observer/observer/src/Core/src/Time.cpp | 24 + .../observer/observer/src/Ship/CMakeLists.txt | 7 + .../observer/src/Ship/include/Ship/Cargo.h | 41 + .../observer/src/Ship/include/Ship/Ship.h | 52 + .../observer/observer/src/Ship/src/Cargo.cpp | 31 + .../observer/observer/src/Ship/src/Ship.cpp | 107 + .../observer/src/Store/CMakeLists.txt | 7 + .../observer/src/Store/include/Store/Store.h | 26 + .../observer/observer/src/Store/src/Store.cpp | 47 + .../observer/observer/tests/CMakeLists.txt | 21 + .../observer/observer/tests/CargoMock.h | 3 + .../observer/observer/tests/ShipUnitTests.cpp | 9 + .../observer/tests/StoreUnitTests.cpp | 11 + .../examples/observer/observer2.cpp | 88 + .../examples/observer/observer3.cpp | 101 + .../examples/refactoring/CMakeLists.txt | 14 + .../examples/refactoring/README.md | 10 + .../examples/refactoring/refactoring.cpp | 216 + .../refactoring/soultions/refactoring1.cpp | 234 + .../refactoring/soultions/refactoring2.cpp | 261 + .../examples/strategy/strategy.cpp | 120 + .../examples/strategy/strategy/CMakeLists.txt | 20 + .../examples/strategy/strategy/main.cpp | 38 + .../strategy/strategy/src/CMakeLists.txt | 4 + .../strategy/strategy/src/Core/CMakeLists.txt | 3 + .../Core/include/Core/DifficultLvlStrategy.h | 12 + .../strategy/src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../strategy/strategy/src/Core/src/Time.cpp | 24 + .../strategy/src/Player/CMakeLists.txt | 8 + .../src/Player/include/Player/Enemy.h | 20 + .../Player/EnemyEasyDifficultLvlStrategy.h | 17 + .../Player/EnemyHardDifficultLvlStrategy.h | 17 + .../strategy/src/Player/src/Enemy.cpp | 19 + .../src/EnemyEasyDifficultLvlStrategy.cpp | 28 + .../src/EnemyHardDifficultLvlStrategy.cpp | 31 + .../strategy/strategy/src/Ship/CMakeLists.txt | 11 + .../strategy/src/Ship/include/Ship/Cargo.h | 43 + .../strategy/src/Ship/include/Ship/Ship.h | 57 + .../Ship/ShipEasyDifficultLvlStrategy.h | 10 + .../Ship/ShipHardDifficultLvlStrategy.h | 10 + .../strategy/strategy/src/Ship/src/Cargo.cpp | 31 + .../strategy/strategy/src/Ship/src/Ship.cpp | 108 + .../Ship/src/ShipEasyDifficultLvlStrategy.cpp | 12 + .../Ship/src/ShipHardDifficultLvlStrategy.cpp | 12 + .../strategy/src/Store/CMakeLists.txt | 7 + .../strategy/src/Store/include/Store/Store.h | 26 + .../strategy/strategy/src/Store/src/Store.cpp | 48 + .../strategy/strategy/tests/CMakeLists.txt | 21 + .../strategy/strategy/tests/CargoMock.h | 3 + .../strategy/strategy/tests/ShipUnitTests.cpp | 9 + .../strategy/tests/StoreUnitTests.cpp | 11 + .../examples/strategy/strategy2.cpp | 168 + .../examples/strategy/strategy3.cpp | 198 + .../templateMethod/CMakeLists.txt | 21 + .../templateMethod/templateMethod/main.cpp | 72 + .../templateMethod/src/Battle/CMakeLists.txt | 8 + .../src/Battle/include/Battle/Action.h | 24 + .../src/Battle/include/Battle/Attack.h | 12 + .../src/Battle/include/Battle/BattleField.h | 19 + .../src/Battle/include/Battle/Defense.h | 12 + .../src/Battle/include/Battle/Escape.h | 18 + .../templateMethod/src/Battle/src/Attack.cpp | 22 + .../src/Battle/src/BattleField.cpp | 16 + .../templateMethod/src/Battle/src/Defense.cpp | 13 + .../templateMethod/src/Battle/src/Escape.cpp | 22 + .../templateMethod/src/CMakeLists.txt | 5 + .../templateMethod/src/Core/CMakeLists.txt | 8 + .../src/Core/include/Core/BasicPrintVisitor.h | 12 + .../Core/include/Core/DifficultLvlStrategy.h | 12 + .../Core/include/Core/PrettyPrintVisitor.h | 12 + .../src/Core/include/Core/PrintVisitor.h | 11 + .../src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../src/Core/src/BasicPrintVisitor.cpp | 22 + .../src/Core/src/PrettyPrintVisitor.cpp | 33 + .../templateMethod/src/Core/src/Time.cpp | 24 + .../templateMethod/src/Player/CMakeLists.txt | 9 + .../src/Player/include/Player/Enemy.h | 66 + .../Player/EnemyEasyDifficultLvlStrategy.h | 17 + .../Player/EnemyHardDifficultLvlStrategy.h | 17 + .../src/Player/include/Player/Player.h | 22 + .../src/Player/include/Player/RealPlayer.h | 26 + .../src/EnemyEasyDifficultLvlStrategy.cpp | 28 + .../src/EnemyHardDifficultLvlStrategy.cpp | 31 + .../templateMethod/src/Player/src/Player.cpp | 11 + .../src/Player/src/RealPlayer.cpp | 56 + .../templateMethod/src/Ship/CMakeLists.txt | 12 + .../src/Ship/include/Ship/Cargo.h | 49 + .../Ship/include/Ship/CargoDamageVisitor.h | 25 + .../src/Ship/include/Ship/Ship.h | 65 + .../Ship/ShipEasyDifficultLvlStrategy.h | 10 + .../Ship/ShipHardDifficultLvlStrategy.h | 10 + .../templateMethod/src/Ship/src/Cargo.cpp | 43 + .../src/Ship/src/CargoDamageVisitor.cpp | 20 + .../templateMethod/src/Ship/src/Ship.cpp | 111 + .../Ship/src/ShipEasyDifficultLvlStrategy.cpp | 12 + .../Ship/src/ShipHardDifficultLvlStrategy.cpp | 12 + .../templateMethod/src/Store/CMakeLists.txt | 7 + .../src/Store/include/Store/Store.h | 30 + .../templateMethod/src/Store/src/Store.cpp | 41 + .../templateMethod/tests/CMakeLists.txt | 21 + .../templateMethod/tests/CargoMock.h | 3 + .../templateMethod/tests/ShipUnitTests.cpp | 9 + .../templateMethod/tests/StoreUnitTests.cpp | 11 + .../Presentation/examples/visitor/visitor.cpp | 93 + .../examples/visitor/visitor/CMakeLists.txt | 20 + .../examples/visitor/visitor/main.cpp | 56 + .../visitor/visitor/src/CMakeLists.txt | 4 + .../visitor/visitor/src/Core/CMakeLists.txt | 8 + .../src/Core/include/Core/BasicPrintVisitor.h | 12 + .../Core/include/Core/DifficultLvlStrategy.h | 12 + .../Core/include/Core/PrettyPrintVisitor.h | 12 + .../src/Core/include/Core/PrintVisitor.h | 11 + .../visitor/src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../src/Core/src/BasicPrintVisitor.cpp | 22 + .../src/Core/src/PrettyPrintVisitor.cpp | 33 + .../visitor/visitor/src/Core/src/Time.cpp | 24 + .../visitor/visitor/src/Player/CMakeLists.txt | 8 + .../visitor/src/Player/include/Player/Enemy.h | 42 + .../Player/EnemyEasyDifficultLvlStrategy.h | 17 + .../Player/EnemyHardDifficultLvlStrategy.h | 17 + .../src/EnemyEasyDifficultLvlStrategy.cpp | 28 + .../src/EnemyHardDifficultLvlStrategy.cpp | 31 + .../visitor/visitor/src/Ship/CMakeLists.txt | 12 + .../visitor/src/Ship/include/Ship/Cargo.h | 49 + .../Ship/include/Ship/CargoDamageVisitor.h | 25 + .../visitor/src/Ship/include/Ship/Ship.h | 60 + .../Ship/ShipEasyDifficultLvlStrategy.h | 10 + .../Ship/ShipHardDifficultLvlStrategy.h | 10 + .../visitor/visitor/src/Ship/src/Cargo.cpp | 43 + .../src/Ship/src/CargoDamageVisitor.cpp | 20 + .../visitor/visitor/src/Ship/src/Ship.cpp | 105 + .../Ship/src/ShipEasyDifficultLvlStrategy.cpp | 12 + .../Ship/src/ShipHardDifficultLvlStrategy.cpp | 12 + .../visitor/visitor/src/Store/CMakeLists.txt | 7 + .../visitor/src/Store/include/Store/Store.h | 30 + .../visitor/visitor/src/Store/src/Store.cpp | 41 + .../visitor/visitor/tests/CMakeLists.txt | 21 + .../visitor/visitor/tests/CargoMock.h | 3 + .../visitor/visitor/tests/ShipUnitTests.cpp | 9 + .../visitor/visitor/tests/StoreUnitTests.cpp | 11 + .../examples/visitor/visitor2.cpp | 71 + .../examples/visitor/visitor3.cpp | 128 + .../examples/visitor/visitor4.cpp | 113 + .../Presentation/exceptions.md | 431 ++ .../Presentation/exercises/SHM/CMakeLists.txt | 11 + .../exercises/SHM/src/CMakeLists.txt | 2 + .../exercises/SHM/src/Ship/CMakeLists.txt | 3 + .../SHM/src/Ship/include/Ship/Cargo.h | 28 + .../SHM/src/Ship/include/Ship/Ship.h | 33 + .../exercises/SHM/src/Ship/src/Cargo.cpp | 28 + .../exercises/SHM/src/Ship/src/Ship.cpp | 48 + .../exercises/SHM/src/Store/CMakeLists.txt | 7 + .../SHM/src/Store/include/Store/Store.h | 19 + .../exercises/SHM/src/Store/src/Store.cpp | 21 + .../exercises/SHM/tests/CMakeLists.txt | 21 + .../exercises/SHM/tests/CargoMock.h | 3 + .../exercises/SHM/tests/ShipUnitTests.cpp | 9 + .../exercises/SHM/tests/StoreUnitTests.cpp | 11 + .../exercises/builder/CMakeLists.txt | 29 + .../Presentation/exercises/builder/README.md | 39 + .../Presentation/exercises/builder/main.cpp | 60 + .../Presentation/exercises/builder/ships.json | 20 + .../builder/src/Battle/CMakeLists.txt | 8 + .../src/Battle/include/Battle/Action.h | 24 + .../src/Battle/include/Battle/Attack.h | 12 + .../src/Battle/include/Battle/BattleField.h | 19 + .../src/Battle/include/Battle/Defense.h | 12 + .../src/Battle/include/Battle/Escape.h | 18 + .../builder/src/Battle/src/Attack.cpp | 22 + .../builder/src/Battle/src/BattleField.cpp | 16 + .../builder/src/Battle/src/Defense.cpp | 13 + .../builder/src/Battle/src/Escape.cpp | 22 + .../exercises/builder/src/CMakeLists.txt | 5 + .../exercises/builder/src/Core/CMakeLists.txt | 8 + .../src/Core/include/Core/BasicPrintVisitor.h | 12 + .../Core/include/Core/DifficultLvlStrategy.h | 12 + .../Core/include/Core/PrettyPrintVisitor.h | 12 + .../src/Core/include/Core/PrintVisitor.h | 11 + .../builder/src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../src/Core/src/BasicPrintVisitor.cpp | 22 + .../src/Core/src/PrettyPrintVisitor.cpp | 33 + .../exercises/builder/src/Core/src/Time.cpp | 24 + .../builder/src/Player/CMakeLists.txt | 9 + .../builder/src/Player/include/Player/Enemy.h | 66 + .../Player/EnemyEasyDifficultLvlStrategy.h | 17 + .../Player/EnemyHardDifficultLvlStrategy.h | 17 + .../src/Player/include/Player/Player.h | 22 + .../src/Player/include/Player/RealPlayer.h | 26 + .../src/EnemyEasyDifficultLvlStrategy.cpp | 28 + .../src/EnemyHardDifficultLvlStrategy.cpp | 31 + .../builder/src/Player/src/Player.cpp | 11 + .../builder/src/Player/src/RealPlayer.cpp | 56 + .../exercises/builder/src/Ship/CMakeLists.txt | 15 + .../builder/src/Ship/include/Ship/Cargo.h | 49 + .../Ship/include/Ship/CargoDamageVisitor.h | 25 + .../builder/src/Ship/include/Ship/Ship.h | 70 + .../src/Ship/include/Ship/ShipBuilder.h | 28 + .../Ship/ShipEasyDifficultLvlStrategy.h | 10 + .../Ship/ShipHardDifficultLvlStrategy.h | 10 + .../src/Ship/include/Ship/ShipJsonBuilder.h | 26 + .../exercises/builder/src/Ship/src/Cargo.cpp | 43 + .../src/Ship/src/CargoDamageVisitor.cpp | 20 + .../exercises/builder/src/Ship/src/Ship.cpp | 107 + .../builder/src/Ship/src/ShipBuilder.cpp | 68 + .../Ship/src/ShipEasyDifficultLvlStrategy.cpp | 12 + .../Ship/src/ShipHardDifficultLvlStrategy.cpp | 12 + .../builder/src/Ship/src/ShipJsonBuilder.cpp | 48 + .../builder/src/Store/CMakeLists.txt | 7 + .../builder/src/Store/include/Store/Store.h | 30 + .../exercises/builder/src/Store/src/Store.cpp | 41 + .../exercises/builder/tests/CMakeLists.txt | 21 + .../exercises/builder/tests/CargoMock.h | 3 + .../exercises/builder/tests/ShipUnitTests.cpp | 9 + .../builder/tests/StoreUnitTests.cpp | 11 + .../exercises/decorator/CMakeLists.txt | 29 + .../exercises/decorator/README.md | 25 + .../Presentation/exercises/decorator/main.cpp | 53 + .../exercises/decorator/ships.json | 20 + .../decorator/src/Battle/CMakeLists.txt | 8 + .../src/Battle/include/Battle/Action.h | 24 + .../src/Battle/include/Battle/Attack.h | 12 + .../src/Battle/include/Battle/BattleField.h | 19 + .../src/Battle/include/Battle/Defense.h | 12 + .../src/Battle/include/Battle/Escape.h | 18 + .../decorator/src/Battle/src/Attack.cpp | 22 + .../decorator/src/Battle/src/BattleField.cpp | 16 + .../decorator/src/Battle/src/Defense.cpp | 13 + .../decorator/src/Battle/src/Escape.cpp | 22 + .../exercises/decorator/src/CMakeLists.txt | 5 + .../decorator/src/Core/CMakeLists.txt | 8 + .../src/Core/include/Core/BasicPrintVisitor.h | 12 + .../Core/include/Core/DifficultLvlStrategy.h | 12 + .../Core/include/Core/FullInfoPrintVisitor.h | 15 + .../Core/include/Core/PrettyPrintVisitor.h | 12 + .../src/Core/include/Core/PrintVisitor.h | 11 + .../decorator/src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../src/Core/src/BasicPrintVisitor.cpp | 22 + .../src/Core/src/FullInfoPrintVisitor.cpp | 24 + .../src/Core/src/PrettyPrintVisitor.cpp | 33 + .../exercises/decorator/src/Core/src/Time.cpp | 24 + .../decorator/src/Player/CMakeLists.txt | 9 + .../src/Player/include/Player/Enemy.h | 66 + .../Player/EnemyEasyDifficultLvlStrategy.h | 17 + .../Player/EnemyHardDifficultLvlStrategy.h | 17 + .../src/Player/include/Player/Player.h | 22 + .../src/Player/include/Player/RealPlayer.h | 26 + .../src/EnemyEasyDifficultLvlStrategy.cpp | 28 + .../src/EnemyHardDifficultLvlStrategy.cpp | 31 + .../decorator/src/Player/src/Player.cpp | 11 + .../decorator/src/Player/src/RealPlayer.cpp | 56 + .../decorator/src/Ship/CMakeLists.txt | 15 + .../src/Ship/include/Ship/AlcoholFactory.h | 14 + .../src/Ship/include/Ship/AlcoholType.h | 6 + .../decorator/src/Ship/include/Ship/Cargo.h | 60 + .../Ship/include/Ship/CargoDamageVisitor.h | 25 + .../src/Ship/include/Ship/CargoFactory.h | 12 + .../src/Ship/include/Ship/FruitFactory.h | 14 + .../src/Ship/include/Ship/ItemFactory.h | 14 + .../src/Ship/include/Ship/ItemType.h | 6 + .../decorator/src/Ship/include/Ship/Ship.h | 70 + .../src/Ship/include/Ship/ShipBuilder.h | 28 + .../Ship/ShipEasyDifficultLvlStrategy.h | 10 + .../Ship/ShipHardDifficultLvlStrategy.h | 10 + .../src/Ship/include/Ship/ShipJsonBuilder.h | 26 + .../decorator/src/Ship/src/Cargo.cpp | 46 + .../src/Ship/src/CargoDamageVisitor.cpp | 20 + .../exercises/decorator/src/Ship/src/Ship.cpp | 108 + .../decorator/src/Ship/src/ShipBuilder.cpp | 68 + .../Ship/src/ShipEasyDifficultLvlStrategy.cpp | 12 + .../Ship/src/ShipHardDifficultLvlStrategy.cpp | 12 + .../src/Ship/src/ShipJsonBuilder.cpp | 48 + .../decorator/src/Store/CMakeLists.txt | 7 + .../decorator/src/Store/include/Store/Store.h | 30 + .../decorator/src/Store/src/Store.cpp | 41 + .../exercises/decorator/tests/CMakeLists.txt | 21 + .../exercises/decorator/tests/CargoMock.h | 3 + .../decorator/tests/ShipUnitTests.cpp | 9 + .../decorator/tests/StoreUnitTests.cpp | 11 + .../exercises/exampleProject/CMakeLists.txt | 13 + .../exercises/exampleProject/README.md | 10 + .../exampleProject/exampleProject.cpp | 5 + .../exercises/exception/CMakeLists.txt | 14 + .../exercises/exception/README.md | 13 + .../Presentation/exercises/exception/main.cpp | 44 + .../exercises/exception/soulutions/main.cpp | 68 + .../exercises/observer/CMakeLists.txt | 19 + .../Presentation/exercises/observer/README.md | 143 + .../Presentation/exercises/observer/main.cpp | 22 + .../exercises/observer/src/CMakeLists.txt | 3 + .../observer/src/Core/CMakeLists.txt | 3 + .../observer/src/Core/include/Core/Time.h | 11 + .../src/Core/include/Core/TimeObserver.h | 5 + .../exercises/observer/src/Core/src/Time.cpp | 6 + .../observer/src/Ship/CMakeLists.txt | 7 + .../observer/src/Ship/include/Ship/Cargo.h | 41 + .../observer/src/Ship/include/Ship/Ship.h | 45 + .../exercises/observer/src/Ship/src/Cargo.cpp | 31 + .../exercises/observer/src/Ship/src/Ship.cpp | 74 + .../observer/src/Store/CMakeLists.txt | 7 + .../observer/src/Store/include/Store/Store.h | 19 + .../observer/src/Store/src/Store.cpp | 21 + .../exercises/observer/tests/CMakeLists.txt | 21 + .../exercises/observer/tests/CargoMock.h | 3 + .../observer/tests/ShipUnitTests.cpp | 9 + .../observer/tests/StoreUnitTests.cpp | 11 + .../exercises/strategy/CMakeLists.txt | 20 + .../Presentation/exercises/strategy/README.md | 38 + .../Presentation/exercises/strategy/main.cpp | 38 + .../exercises/strategy/src/CMakeLists.txt | 4 + .../strategy/src/Core/CMakeLists.txt | 3 + .../strategy/src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../exercises/strategy/src/Core/src/Time.cpp | 24 + .../strategy/src/Player/CMakeLists.txt | 8 + .../src/Player/include/Player/Enemy.h | 19 + .../strategy/src/Player/src/Enemy.cpp | 15 + .../strategy/src/Ship/CMakeLists.txt | 9 + .../strategy/src/Ship/include/Ship/Cargo.h | 41 + .../strategy/src/Ship/include/Ship/Ship.h | 55 + .../exercises/strategy/src/Ship/src/Cargo.cpp | 31 + .../exercises/strategy/src/Ship/src/Ship.cpp | 114 + .../strategy/src/Store/CMakeLists.txt | 7 + .../strategy/src/Store/include/Store/Store.h | 26 + .../strategy/src/Store/src/Store.cpp | 48 + .../exercises/strategy/tests/CMakeLists.txt | 21 + .../exercises/strategy/tests/CargoMock.h | 3 + .../strategy/tests/ShipUnitTests.cpp | 9 + .../strategy/tests/StoreUnitTests.cpp | 11 + .../exercises/streamer/CMakeLists.txt | 14 + .../Presentation/exercises/streamer/README.md | 17 + .../exercises/streamer/solution/streamer.cpp | 207 + .../exercises/streamer/streamer.cpp | 70 + .../exercises/templateMethod/CMakeLists.txt | 21 + .../exercises/templateMethod/README.md | 35 + .../exercises/templateMethod/main.cpp | 73 + .../templateMethod/src/Battle/CMakeLists.txt | 8 + .../src/Battle/include/Battle/Action.h | 21 + .../src/Battle/include/Battle/Attack.h | 12 + .../src/Battle/include/Battle/BattleField.h | 19 + .../src/Battle/include/Battle/Defense.h | 12 + .../templateMethod/src/Battle/src/Attack.cpp | 22 + .../src/Battle/src/BattleField.cpp | 16 + .../templateMethod/src/Battle/src/Defense.cpp | 13 + .../templateMethod/src/CMakeLists.txt | 5 + .../templateMethod/src/Core/CMakeLists.txt | 8 + .../src/Core/include/Core/BasicPrintVisitor.h | 12 + .../Core/include/Core/DifficultLvlStrategy.h | 12 + .../Core/include/Core/PrettyPrintVisitor.h | 12 + .../src/Core/include/Core/PrintVisitor.h | 11 + .../src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../src/Core/src/BasicPrintVisitor.cpp | 22 + .../src/Core/src/PrettyPrintVisitor.cpp | 33 + .../templateMethod/src/Core/src/Time.cpp | 24 + .../templateMethod/src/Player/CMakeLists.txt | 9 + .../src/Player/include/Player/Enemy.h | 39 + .../Player/EnemyEasyDifficultLvlStrategy.h | 17 + .../Player/EnemyHardDifficultLvlStrategy.h | 17 + .../src/EnemyEasyDifficultLvlStrategy.cpp | 28 + .../src/EnemyHardDifficultLvlStrategy.cpp | 31 + .../templateMethod/src/Ship/CMakeLists.txt | 12 + .../src/Ship/include/Ship/Cargo.h | 49 + .../Ship/include/Ship/CargoDamageVisitor.h | 25 + .../src/Ship/include/Ship/Ship.h | 65 + .../Ship/ShipEasyDifficultLvlStrategy.h | 10 + .../Ship/ShipHardDifficultLvlStrategy.h | 10 + .../templateMethod/src/Ship/src/Cargo.cpp | 43 + .../src/Ship/src/CargoDamageVisitor.cpp | 20 + .../templateMethod/src/Ship/src/Ship.cpp | 111 + .../Ship/src/ShipEasyDifficultLvlStrategy.cpp | 12 + .../Ship/src/ShipHardDifficultLvlStrategy.cpp | 12 + .../templateMethod/src/Store/CMakeLists.txt | 7 + .../src/Store/include/Store/Store.h | 30 + .../templateMethod/src/Store/src/Store.cpp | 41 + .../templateMethod/tests/CMakeLists.txt | 21 + .../templateMethod/tests/CargoMock.h | 3 + .../templateMethod/tests/ShipUnitTests.cpp | 9 + .../templateMethod/tests/StoreUnitTests.cpp | 11 + .../exercises/visitor/CMakeLists.txt | 20 + .../Presentation/exercises/visitor/README.md | 67 + .../Presentation/exercises/visitor/main.cpp | 38 + .../exercises/visitor/src/CMakeLists.txt | 4 + .../exercises/visitor/src/Core/CMakeLists.txt | 3 + .../Core/include/Core/DifficultLvlStrategy.h | 12 + .../visitor/src/Core/include/Core/Time.h | 27 + .../src/Core/include/Core/TimeObserver.h | 6 + .../exercises/visitor/src/Core/src/Time.cpp | 24 + .../visitor/src/Player/CMakeLists.txt | 8 + .../visitor/src/Player/include/Player/Enemy.h | 20 + .../Player/EnemyEasyDifficultLvlStrategy.h | 17 + .../Player/EnemyHardDifficultLvlStrategy.h | 17 + .../visitor/src/Player/src/Enemy.cpp | 19 + .../src/EnemyEasyDifficultLvlStrategy.cpp | 28 + .../src/EnemyHardDifficultLvlStrategy.cpp | 31 + .../exercises/visitor/src/Ship/CMakeLists.txt | 11 + .../visitor/src/Ship/include/Ship/Cargo.h | 43 + .../visitor/src/Ship/include/Ship/Ship.h | 57 + .../Ship/ShipEasyDifficultLvlStrategy.h | 10 + .../Ship/ShipHardDifficultLvlStrategy.h | 10 + .../exercises/visitor/src/Ship/src/Cargo.cpp | 31 + .../exercises/visitor/src/Ship/src/Ship.cpp | 108 + .../Ship/src/ShipEasyDifficultLvlStrategy.cpp | 12 + .../Ship/src/ShipHardDifficultLvlStrategy.cpp | 12 + .../visitor/src/Store/CMakeLists.txt | 7 + .../visitor/src/Store/include/Store/Store.h | 26 + .../exercises/visitor/src/Store/src/Store.cpp | 48 + .../exercises/visitor/tests/CMakeLists.txt | 21 + .../exercises/visitor/tests/CargoMock.h | 3 + .../exercises/visitor/tests/ShipUnitTests.cpp | 9 + .../visitor/tests/StoreUnitTests.cpp | 11 + .../Presentation/good_practise_dry.md | 39 + .../Presentation/good_practise_intro.md | 200 + .../Presentation/good_practise_kiss.md | 38 + .../Presentation/good_practise_solid.md | 896 +++ .../Presentation/images/MVC.png | Bin 0 -> 150842 bytes .../images/acyclic_visitor_bench.png | Bin 0 -> 32011 bytes .../images/acyclic_visitor_uml.png | Bin 0 -> 34564 bytes .../Presentation/images/ammunition_uml.png | Bin 0 -> 17345 bytes .../Presentation/images/ammunition_uml2.png | Bin 0 -> 24734 bytes .../Presentation/images/ammunition_uml3.png | Bin 0 -> 16949 bytes .../images/benchmark_observer.png | Bin 0 -> 26077 bytes .../Presentation/images/builder_uml.png | Bin 0 -> 48208 bytes .../Presentation/images/command_uml.png | Bin 0 -> 41348 bytes .../images/decorator_cargo__uml.png | Bin 0 -> 60255 bytes .../Presentation/images/decorator_uml.png | Bin 0 -> 21371 bytes .../images/dependency_inversion.png | Bin 0 -> 20826 bytes .../images/factory_method_uml.png | Bin 0 -> 24919 bytes .../Presentation/images/observer.png | Bin 0 -> 51484 bytes .../Presentation/images/palyer_uml.png | Bin 0 -> 69407 bytes .../Presentation/images/strategy.png | Bin 0 -> 43674 bytes .../images/strategy_broken_architecture.png | Bin 0 -> 24787 bytes .../images/strategy_good_architecture.png | Bin 0 -> 32984 bytes .../images/strategy_perfect_architecture.png | Bin 0 -> 23161 bytes .../images/template_method_uml.png | Bin 0 -> 25405 bytes .../Presentation/images/visitor.png | Bin 0 -> 59029 bytes .../Presentation/images/visitor_acyclic.png | Bin 0 -> 43290 bytes .../Presentation/images/visitor_bench.png | Bin 0 -> 28203 bytes .../images/visitor_better_design.png | Bin 0 -> 29900 bytes .../images/visitor_first_apprach.png | Bin 0 -> 33182 bytes .../Presentation/index.html | 188 + .../Presentation/introduction.md | 58 + .../Presentation/logger.md | 220 + .../Presentation/observer.md | 615 ++ .../Presentation/recap.md | 8 + .../Presentation/refactor.md | 880 +++ .../Presentation/strategy.md | 735 ++ .../Presentation/template_method.md | 577 ++ .../Presentation/testing_gmock.md | 681 ++ .../Presentation/testing_gtest.md | 473 ++ .../Presentation/visitor.md | 600 ++ CreatingReliableSoftwareCpp/README.md | 1 + CreatingReliableSoftwareCpp/bower.json | 24 + .../css/print/paper.css | 203 + CreatingReliableSoftwareCpp/css/print/pdf.css | 165 + CreatingReliableSoftwareCpp/css/reset.css | 30 + CreatingReliableSoftwareCpp/css/reveal.css | 1606 +++++ CreatingReliableSoftwareCpp/css/reveal.scss | 1777 +++++ .../css/theme/README.md | 21 + .../css/theme/beige.css | 277 + .../css/theme/black.css | 273 + .../css/theme/blood.css | 296 + .../css/theme/coders.css | 308 + .../css/theme/coders_white.css | 294 + .../css/theme/league.css | 279 + .../css/theme/moon.css | 277 + .../css/theme/night.css | 271 + .../css/theme/serif.css | 273 + .../css/theme/simple.css | 276 + CreatingReliableSoftwareCpp/css/theme/sky.css | 280 + .../css/theme/solarized.css | 277 + .../css/theme/source/beige.scss | 39 + .../css/theme/source/black.scss | 49 + .../css/theme/source/blood.scss | 78 + .../css/theme/source/league.scss | 34 + .../css/theme/source/moon.scss | 57 + .../css/theme/source/night.scss | 34 + .../css/theme/source/serif.scss | 35 + .../css/theme/source/simple.scss | 43 + .../css/theme/source/sky.scss | 46 + .../css/theme/source/solarized.scss | 63 + .../css/theme/source/white.scss | 49 + .../css/theme/template/mixins.scss | 29 + .../css/theme/template/settings.scss | 45 + .../css/theme/template/theme.scss | 325 + .../css/theme/white.css | 273 + CreatingReliableSoftwareCpp/demo.html | 425 ++ CreatingReliableSoftwareCpp/gruntfile.js | 189 + .../img/altkom_logo.png | Bin 0 -> 14919 bytes .../img/altkom_logo2.png | Bin 0 -> 157271 bytes CreatingReliableSoftwareCpp/img/cpp_logo.png | Bin 0 -> 46138 bytes CreatingReliableSoftwareCpp/img/mateusz.png | Bin 0 -> 3489728 bytes CreatingReliableSoftwareCpp/js/reveal.js | 6191 +++++++++++++++++ CreatingReliableSoftwareCpp/js/reveal.min.js | 9 + .../lib/css/monokai.css | 71 + .../lib/css/zenburn.css | 80 + .../lib/font/league-gothic/LICENSE | 2 + .../lib/font/league-gothic/league-gothic.css | 10 + .../lib/font/league-gothic/league-gothic.eot | Bin 0 -> 25696 bytes .../lib/font/league-gothic/league-gothic.ttf | Bin 0 -> 64256 bytes .../lib/font/league-gothic/league-gothic.woff | Bin 0 -> 30764 bytes .../lib/font/rajdhani/Rajdhani-Bold.ttf | Bin 0 -> 373192 bytes .../lib/font/rajdhani/Rajdhani-Light.ttf | Bin 0 -> 357516 bytes .../lib/font/rajdhani/Rajdhani-Medium.ttf | Bin 0 -> 357884 bytes .../lib/font/rajdhani/Rajdhani-Regular.ttf | Bin 0 -> 352088 bytes .../lib/font/rajdhani/Rajdhani-SemiBold.ttf | Bin 0 -> 363500 bytes .../lib/font/rajdhani/rajdhani.css | 20 + .../lib/font/source-sans-pro/LICENSE | 45 + .../source-sans-pro-italic.eot | Bin 0 -> 75720 bytes .../source-sans-pro-italic.ttf | Bin 0 -> 238084 bytes .../source-sans-pro-italic.woff | Bin 0 -> 98556 bytes .../source-sans-pro-regular.eot | Bin 0 -> 88070 bytes .../source-sans-pro-regular.ttf | Bin 0 -> 288008 bytes .../source-sans-pro-regular.woff | Bin 0 -> 114324 bytes .../source-sans-pro-semibold.eot | Bin 0 -> 89897 bytes .../source-sans-pro-semibold.ttf | Bin 0 -> 284640 bytes .../source-sans-pro-semibold.woff | Bin 0 -> 115648 bytes .../source-sans-pro-semibolditalic.eot | Bin 0 -> 75706 bytes .../source-sans-pro-semibolditalic.ttf | Bin 0 -> 240944 bytes .../source-sans-pro-semibolditalic.woff | Bin 0 -> 98816 bytes .../font/source-sans-pro/source-sans-pro.css | 39 + .../lib/js/html5shiv.js | 7 + CreatingReliableSoftwareCpp/lib/js/promise.js | 2 + .../plugin/highlight/highlight.js | 303 + .../plugin/markdown/example.html | 134 + .../plugin/markdown/example.md | 36 + .../plugin/markdown/markdown.js | 446 ++ .../plugin/markdown/marked.js | 6 + .../plugin/math/math.js | 92 + .../plugin/multiplex/client.js | 13 + .../plugin/multiplex/index.js | 64 + .../plugin/multiplex/master.js | 34 + .../plugin/multiplex/package.json | 19 + .../plugin/notes-server/client.js | 65 + .../plugin/notes-server/index.js | 69 + .../plugin/notes-server/notes.html | 585 ++ .../plugin/notes/notes.html | 854 +++ .../plugin/notes/notes.js | 178 + .../plugin/print-pdf/print-pdf.js | 67 + .../plugin/search/search.js | 206 + .../plugin/zoom-js/zoom.js | 277 + .../test/assets/external-script-a.js | 1 + .../test/assets/external-script-b.js | 1 + .../test/assets/external-script-c.js | 1 + .../test/assets/external-script-d.js | 1 + .../test/examples/assets/beeping.txt | 2 + .../test/examples/assets/beeping.wav | Bin 0 -> 422472 bytes .../test/examples/assets/image1.png | Bin 0 -> 21991 bytes .../test/examples/assets/image2.png | Bin 0 -> 10237 bytes .../test/examples/barebones.html | 41 + .../test/examples/embedded-media.html | 53 + .../test/examples/math.html | 205 + .../test/examples/slide-backgrounds.html | 143 + .../test/examples/slide-transitions.html | 100 + .../test/qunit-2.5.0.css | 436 ++ .../test/qunit-2.5.0.js | 5188 ++++++++++++++ CreatingReliableSoftwareCpp/test/simple.md | 12 + .../test/test-dependencies-async.html | 78 + .../test/test-dependencies.html | 54 + .../test/test-grid-navigation.html | 74 + .../test/test-iframe-backgrounds.html | 104 + .../test/test-iframes.html | 108 + .../test-markdown-element-attributes.html | 132 + .../test/test-markdown-element-attributes.js | 44 + .../test/test-markdown-external.html | 37 + .../test/test-markdown-external.js | 20 + .../test/test-markdown-options.html | 40 + .../test/test-markdown-options.js | 27 + .../test/test-markdown-slide-attributes.html | 127 + .../test/test-markdown-slide-attributes.js | 44 + .../test/test-markdown.html | 51 + .../test/test-markdown.js | 11 + .../test/test-pdf.html | 82 + CreatingReliableSoftwareCpp/test/test-pdf.js | 12 + .../test/test-plugins.html | 105 + .../test/test-state.html | 139 + CreatingReliableSoftwareCpp/test/test.html | 85 + CreatingReliableSoftwareCpp/test/test.js | 614 ++ 730 files changed, 51141 insertions(+) create mode 100644 CreatingReliableSoftwareCpp/LICENSE create mode 100644 CreatingReliableSoftwareCpp/Presentation/agenda.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/builder.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/compilation.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/decorator.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/design_patterns_intro.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/ships.json create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Action.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Attack.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/BattleField.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Defense.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Escape.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Attack.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/BattleField.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Defense.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Escape.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/BasicPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/DifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/PrettyPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/PrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/BasicPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/PrettyPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/Player.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/RealPlayer.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/EnemyHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/Player.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/RealPlayer.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/AlcoholFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/CargoDamageVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/CargoFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/FruitFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ItemFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipBuilder.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipJsonBuilder.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/CargoDamageVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipBuilder.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipJsonBuilder.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder2.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/builder/builder3.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/ships.json create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Action.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Attack.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/BattleField.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Defense.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Escape.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Attack.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/BattleField.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Defense.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Escape.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/BasicPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/DifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/FullInfoPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/PrettyPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/PrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/BasicPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/FullInfoPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/PrettyPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/Player.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/RealPlayer.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/EnemyHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/Player.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/RealPlayer.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/AlcoholFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/AlcoholType.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/CargoDamageVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/CargoFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/DecoratedCargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/FruitFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ItemFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ItemType.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipBuilder.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipJsonBuilder.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Valuable.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Vulnerable.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/CargoDamageVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/DecoratedCargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipBuilder.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipJsonBuilder.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Vulnerable.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator2.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator3.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer2.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/observer/observer3.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/refactoring/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/refactoring/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/refactoring/refactoring.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/refactoring/soultions/refactoring1.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/refactoring/soultions/refactoring2.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/DifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/Enemy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/EnemyHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/ShipHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy2.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy3.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Action.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Attack.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/BattleField.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Defense.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Escape.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Attack.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/BattleField.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Defense.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Escape.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/BasicPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/DifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/PrettyPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/PrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/BasicPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/PrettyPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/Player.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/RealPlayer.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/EnemyHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/Player.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/RealPlayer.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/CargoDamageVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/CargoDamageVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/ShipHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/BasicPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/DifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/PrettyPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/PrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/BasicPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/PrettyPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/src/EnemyHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/CargoDamageVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/CargoDamageVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/ShipHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor2.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor3.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor4.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exceptions.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/ships.json create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Action.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Attack.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/BattleField.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Defense.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Escape.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Attack.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/BattleField.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Defense.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Escape.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/BasicPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/DifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/PrettyPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/PrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/BasicPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/PrettyPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/Player.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/RealPlayer.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/EnemyHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/Player.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/RealPlayer.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/CargoDamageVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipBuilder.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipJsonBuilder.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/CargoDamageVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipBuilder.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipJsonBuilder.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/ships.json create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Action.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Attack.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/BattleField.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Defense.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Escape.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Attack.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/BattleField.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Defense.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Escape.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/BasicPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/DifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/FullInfoPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/PrettyPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/PrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/BasicPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/FullInfoPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/PrettyPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/Player.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/RealPlayer.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/EnemyHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/Player.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/RealPlayer.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/AlcoholFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/AlcoholType.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/CargoDamageVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/CargoFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/FruitFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ItemFactory.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ItemType.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipBuilder.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipJsonBuilder.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/CargoDamageVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipBuilder.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipJsonBuilder.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/exampleProject.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/exception/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/exception/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/exception/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/exception/soulutions/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/src/Enemy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/streamer/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/streamer/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/streamer/solution/streamer.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/streamer/streamer.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Action.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Attack.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/BattleField.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Defense.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/Attack.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/BattleField.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/Defense.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/BasicPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/DifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/PrettyPrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/PrintVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/BasicPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/PrettyPrintVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/src/EnemyHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/CargoDamageVisitor.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/CargoDamageVisitor.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/ShipHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/README.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/main.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/DifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/Time.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/TimeObserver.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/src/Time.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/Enemy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/Enemy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/EnemyHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/Cargo.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/Ship.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/Cargo.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/Ship.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/ShipHardDifficultLvlStrategy.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/include/Store/Store.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/src/Store.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/CMakeLists.txt create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/CargoMock.h create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/ShipUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/StoreUnitTests.cpp create mode 100644 CreatingReliableSoftwareCpp/Presentation/good_practise_dry.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/good_practise_intro.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/good_practise_kiss.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/good_practise_solid.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/MVC.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/acyclic_visitor_bench.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/acyclic_visitor_uml.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/ammunition_uml.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/ammunition_uml2.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/ammunition_uml3.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/benchmark_observer.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/builder_uml.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/command_uml.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/decorator_cargo__uml.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/decorator_uml.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/dependency_inversion.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/factory_method_uml.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/observer.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/palyer_uml.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/strategy.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/strategy_broken_architecture.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/strategy_good_architecture.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/strategy_perfect_architecture.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/template_method_uml.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/visitor.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/visitor_acyclic.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/visitor_bench.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/visitor_better_design.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/images/visitor_first_apprach.png create mode 100644 CreatingReliableSoftwareCpp/Presentation/index.html create mode 100644 CreatingReliableSoftwareCpp/Presentation/introduction.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/logger.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/observer.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/recap.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/refactor.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/strategy.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/template_method.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/testing_gmock.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/testing_gtest.md create mode 100644 CreatingReliableSoftwareCpp/Presentation/visitor.md create mode 100644 CreatingReliableSoftwareCpp/README.md create mode 100644 CreatingReliableSoftwareCpp/bower.json create mode 100644 CreatingReliableSoftwareCpp/css/print/paper.css create mode 100644 CreatingReliableSoftwareCpp/css/print/pdf.css create mode 100644 CreatingReliableSoftwareCpp/css/reset.css create mode 100644 CreatingReliableSoftwareCpp/css/reveal.css create mode 100644 CreatingReliableSoftwareCpp/css/reveal.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/README.md create mode 100644 CreatingReliableSoftwareCpp/css/theme/beige.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/black.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/blood.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/coders.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/coders_white.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/league.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/moon.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/night.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/serif.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/simple.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/sky.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/solarized.css create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/beige.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/black.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/blood.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/league.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/moon.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/night.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/serif.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/simple.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/sky.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/solarized.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/source/white.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/template/mixins.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/template/settings.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/template/theme.scss create mode 100644 CreatingReliableSoftwareCpp/css/theme/white.css create mode 100644 CreatingReliableSoftwareCpp/demo.html create mode 100644 CreatingReliableSoftwareCpp/gruntfile.js create mode 100644 CreatingReliableSoftwareCpp/img/altkom_logo.png create mode 100644 CreatingReliableSoftwareCpp/img/altkom_logo2.png create mode 100644 CreatingReliableSoftwareCpp/img/cpp_logo.png create mode 100644 CreatingReliableSoftwareCpp/img/mateusz.png create mode 100644 CreatingReliableSoftwareCpp/js/reveal.js create mode 100644 CreatingReliableSoftwareCpp/js/reveal.min.js create mode 100644 CreatingReliableSoftwareCpp/lib/css/monokai.css create mode 100644 CreatingReliableSoftwareCpp/lib/css/zenburn.css create mode 100644 CreatingReliableSoftwareCpp/lib/font/league-gothic/LICENSE create mode 100644 CreatingReliableSoftwareCpp/lib/font/league-gothic/league-gothic.css create mode 100644 CreatingReliableSoftwareCpp/lib/font/league-gothic/league-gothic.eot create mode 100644 CreatingReliableSoftwareCpp/lib/font/league-gothic/league-gothic.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/league-gothic/league-gothic.woff create mode 100644 CreatingReliableSoftwareCpp/lib/font/rajdhani/Rajdhani-Bold.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/rajdhani/Rajdhani-Light.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/rajdhani/Rajdhani-Medium.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/rajdhani/Rajdhani-Regular.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/rajdhani/Rajdhani-SemiBold.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/rajdhani/rajdhani.css create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/LICENSE create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-italic.eot create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-italic.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-italic.woff create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-regular.eot create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-regular.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-regular.woff create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-semibold.eot create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-semibold.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-semibold.woff create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-semibolditalic.eot create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-semibolditalic.ttf create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro-semibolditalic.woff create mode 100644 CreatingReliableSoftwareCpp/lib/font/source-sans-pro/source-sans-pro.css create mode 100644 CreatingReliableSoftwareCpp/lib/js/html5shiv.js create mode 100644 CreatingReliableSoftwareCpp/lib/js/promise.js create mode 100644 CreatingReliableSoftwareCpp/plugin/highlight/highlight.js create mode 100644 CreatingReliableSoftwareCpp/plugin/markdown/example.html create mode 100644 CreatingReliableSoftwareCpp/plugin/markdown/example.md create mode 100644 CreatingReliableSoftwareCpp/plugin/markdown/markdown.js create mode 100644 CreatingReliableSoftwareCpp/plugin/markdown/marked.js create mode 100644 CreatingReliableSoftwareCpp/plugin/math/math.js create mode 100644 CreatingReliableSoftwareCpp/plugin/multiplex/client.js create mode 100644 CreatingReliableSoftwareCpp/plugin/multiplex/index.js create mode 100644 CreatingReliableSoftwareCpp/plugin/multiplex/master.js create mode 100644 CreatingReliableSoftwareCpp/plugin/multiplex/package.json create mode 100644 CreatingReliableSoftwareCpp/plugin/notes-server/client.js create mode 100644 CreatingReliableSoftwareCpp/plugin/notes-server/index.js create mode 100644 CreatingReliableSoftwareCpp/plugin/notes-server/notes.html create mode 100644 CreatingReliableSoftwareCpp/plugin/notes/notes.html create mode 100644 CreatingReliableSoftwareCpp/plugin/notes/notes.js create mode 100644 CreatingReliableSoftwareCpp/plugin/print-pdf/print-pdf.js create mode 100644 CreatingReliableSoftwareCpp/plugin/search/search.js create mode 100644 CreatingReliableSoftwareCpp/plugin/zoom-js/zoom.js create mode 100644 CreatingReliableSoftwareCpp/test/assets/external-script-a.js create mode 100644 CreatingReliableSoftwareCpp/test/assets/external-script-b.js create mode 100644 CreatingReliableSoftwareCpp/test/assets/external-script-c.js create mode 100644 CreatingReliableSoftwareCpp/test/assets/external-script-d.js create mode 100644 CreatingReliableSoftwareCpp/test/examples/assets/beeping.txt create mode 100644 CreatingReliableSoftwareCpp/test/examples/assets/beeping.wav create mode 100644 CreatingReliableSoftwareCpp/test/examples/assets/image1.png create mode 100644 CreatingReliableSoftwareCpp/test/examples/assets/image2.png create mode 100644 CreatingReliableSoftwareCpp/test/examples/barebones.html create mode 100644 CreatingReliableSoftwareCpp/test/examples/embedded-media.html create mode 100644 CreatingReliableSoftwareCpp/test/examples/math.html create mode 100644 CreatingReliableSoftwareCpp/test/examples/slide-backgrounds.html create mode 100644 CreatingReliableSoftwareCpp/test/examples/slide-transitions.html create mode 100644 CreatingReliableSoftwareCpp/test/qunit-2.5.0.css create mode 100644 CreatingReliableSoftwareCpp/test/qunit-2.5.0.js create mode 100644 CreatingReliableSoftwareCpp/test/simple.md create mode 100644 CreatingReliableSoftwareCpp/test/test-dependencies-async.html create mode 100644 CreatingReliableSoftwareCpp/test/test-dependencies.html create mode 100644 CreatingReliableSoftwareCpp/test/test-grid-navigation.html create mode 100644 CreatingReliableSoftwareCpp/test/test-iframe-backgrounds.html create mode 100644 CreatingReliableSoftwareCpp/test/test-iframes.html create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown-element-attributes.html create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown-element-attributes.js create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown-external.html create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown-external.js create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown-options.html create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown-options.js create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown-slide-attributes.html create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown-slide-attributes.js create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown.html create mode 100644 CreatingReliableSoftwareCpp/test/test-markdown.js create mode 100644 CreatingReliableSoftwareCpp/test/test-pdf.html create mode 100644 CreatingReliableSoftwareCpp/test/test-pdf.js create mode 100644 CreatingReliableSoftwareCpp/test/test-plugins.html create mode 100644 CreatingReliableSoftwareCpp/test/test-state.html create mode 100644 CreatingReliableSoftwareCpp/test/test.html create mode 100644 CreatingReliableSoftwareCpp/test/test.js diff --git a/CreatingReliableSoftwareCpp/LICENSE b/CreatingReliableSoftwareCpp/LICENSE new file mode 100644 index 0000000..d15cf3b --- /dev/null +++ b/CreatingReliableSoftwareCpp/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2020 Hakim El Hattab, http://hakim.se, and reveal.js contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/agenda.md b/CreatingReliableSoftwareCpp/Presentation/agenda.md new file mode 100644 index 0000000..735274e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/agenda.md @@ -0,0 +1,28 @@ + + +### Agenda + +* Exceptions + * How to throw and catch exceptions + * Working with excpetions + * Alternative ways to signal an error +* Good practise: + * SOLID + * DRY + * KISS +* Code refactoring +* Testing + * GTEST + * GMOCK +* How to create simple thread safe logger +* Design patterns + * Observer + * Strategy + * Visitor + * Template method + * Command + * Builder + * Factory + * Decorator + + diff --git a/CreatingReliableSoftwareCpp/Presentation/builder.md b/CreatingReliableSoftwareCpp/Presentation/builder.md new file mode 100644 index 0000000..aa7860a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/builder.md @@ -0,0 +1,806 @@ +## Builder + +Whenever we need to create some complex object, which may have a lot of parameters, we end up with a constructor which takes plenty of arguments. In most cases we even don't want to set up all of this, so we create dozens of constructors which allow us to set up only needed parameters. And when we add another parameter, we need to add few more constructors. That's Horrible, isn't it? So how we can solve such a problem? How to create only one Constructor and allow user to build an object by injecting only needed parameters. In previous sentence I use a word `buid`, and this is exactly a design pattern that I want to present you. + +Builder UML +___ + +## Ship + +This is the constructor of class `Ship`. We can easily imagine that in the future we will add at least a few more parameters. + +```C++ +Ship::Ship(Time* time, + std::unique_ptr> strategy, + const std::string& name, + int capacity, + int maxCrew, + int crew, + std::unique_ptr&& visitor, + int armor, + int maxArmor, + int canons, + int maxCanons, + int durability, + int maxDurability) + : _time(time), + _strategy(std::move(strategy)), + _name(name), + _capacity(capacity), + _maxCrew(maxCrew), + _crew(crew), + _visitor(std::move(visitor)), + _armor(armor), + _maxArmor(maxArmor), + _canons(canons), + _maxCanons(maxCanons) + _durability(durability), + _maxDurability(maxDurability) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } + assert(time); + _time->attach(this); +} +``` + + +___ + +## Create a ship + +Can you explain to me which number argument is an `armor` value, and which is a `cannon` value? Reading such code is quite hard. We can easily provide values in wrong order and instead of setting `armor` we will set a `maxCrew` or something else. + +```C++ +auto ship = Ship( + time, + std::move(strategy), + "Black Pearl", + 200, + 100, + 50, + std:move(visitor), + 100, + 200, + 20, + 25, + 1000, + 1000); +``` + + +___ + +## A new way + +This is a new way of creating a ship. What do you think about this approach? + +```C++ +// We need to provide all mandatory parameters, the rest will have default values. +auto ship = Ship(time, name, capacity, maxCrew, maxArmor, maxCannons, maxDurability) + // Provide optional arguemnts + .setDifficultLvlStrategy(std::move(strategy)) + .setCrew(100) + .setPrintVisitor(std::move(visitor)) + .setArmor(100) + .setCannons(10) + .setDurability(1000) + .build(); +``` + + +___ + +## A better way + +In previous example, we still need to provide few arguments in constructor before we will create an object. We can refactor this code and verify in `build` method if all mandatory parameters were set. + +```C++ +auto ship = ShipBuilder().setTime(time) + .setName("Black Pearl") + .setCapacity(500) + .setMaxCrew(200) + .setMaxArmor(1000) + .setMaxCannons(20) + .setMaxDurability(1000) + .setDifficultLvlStrategy(std::move(strategy)) + .setCrew(100) + .setPrintVisitor(std::move(visitor)) + .setArmor(100) + .setCannons(10) + .setDurability(1000) + .build(); +``` + + +___ + +## Builder class + +```C++ +class ShipBuilder { +public: + ShipBuilder() + : _ship(std::make_unique()) {} + + [[nodiscard]] std::unique_ptr build() { + if (!_ship) { + std::cout << "Builder may be use once\n"; + return nullptr; + } + + // Check mandatory fields + if (!_ship->time() || + _ship->name().empty() || + _ship->capacity() == -1 || + _ship->maxCrew() == -1 || + _ship->maxArmor() == -1 || + _ship->maxCannons() == -1 || + _ship->maxDurability() == -1) { + std::cout << "Mandatory fields are not set!\n"; + return nullptr; + } + + return std::move(_ship); + } + +private: + std::unique_ptr _ship; +}; +``` + + +___ + +## Setters + +Now we need to add all setters to `ShipBuilder` class + +```C++ + ShipBuilder& setTime(Time* time) { + _ship->setTime(time); + return *this; + } + ShipBuilder& setStrategy(std::unique_ptr> strategy) { + _ship->setStrategy(std::move(strategy)); + return *this; + } + ShipBuilder& setName(const std::string& name) { + _ship->setName(name); + return *this; + } + ShipBuilder& setCapacity(int capacity) { + _ship->setCapacity(capacity); + return *this; + } + ShipBuilder& setMaxCrew(int maxCrew) { + _ship->setMaxCrew(maxCrew); + return *this; + } + ShipBuilder& setCrew(int crew) { + _ship->setCrew(crew); + return *this; + } + ShipBuilder& setVisitor(std::unique_ptr visitor) { + _ship->setVisitor(std::move(visitor)); + return *this; + } + ShipBuilder& setArmor(int armor) { + _ship->setArmor(armor); + return *this; + } + ShipBuilder& setMaxArmor(int maxArmor) { + _ship->setMaxArmor(maxArmor); + return *this; + } + ShipBuilder& setCannons(int cannons) { + _ship->setCannons(cannons); + return *this; + } + ShipBuilder& setMaxCannons(int maxCannons) { + _ship->setMaxCannons(maxCannons); + return *this; + } + ShipBuilder& setDurability(int durability) { + _ship->setDurability(durability); + return *this; + } + ShipBuilder& setMaxDurability(int maxDurability) { + _ship->setMaxDurability(maxDurability); + return *this; + } +``` + + +___ + +## The ugly part + +Unfortunately, if we want to follow the encapsulation rule we need to duplicate `setters` in class `Ship` we need also provide getters for all members (even if we don't use them by other classes). + +```C++ +class Ship { +public: + Ship& setTime(Time* time) { + _time = time; + return *this; + } + Ship& setStrategy(std::unique_ptr> strategy) { + _strategy = std::move(strategy); + return *this; + } + Ship& setName(const std::string& name) { + _name = name; + return *this; + } + Ship& setCapacity(int capacity) { + _capacity = capacity; + return *this; + } + Ship& setMaxCrew(int maxCrew) { + _maxCrew = maxCrew; + return *this; + } + Ship& setCrew(int crew) { + _crew = crew; + return *this; + } + Ship& setVisitor(std::unique_ptr visitor) { + visitor = std::move(_visitor); + return *this; + } + Ship& setArmor(int armor) { + _armor = armor; + return *this; + } + Ship& setMaxArmor(int maxArmor) { + _maxArmor = maxArmor; + return *this; + } + Ship& setCannons(int cannons) { + _canons = cannons; + return *this; + } + Ship& setMaxCannons(int maxCannons) { + _maxCannons = maxCannons; + return *this; + } + Ship& setDurability(int durability) { + _durability = durability; + return *this; + } + Ship& setMaxDurability(int maxDurability) { + _maxDurability = maxDurability; + return *this; + } + + const Time* time() const { return _time; } + const std::string& name() const { return _name; } + int capacity() const { return _capacity; } + int maxCrew() const { return _maxCrew; } + int crew() const { return _crew; } + int armor() const { return _armor; } + int maxArmor() const { return _maxArmor; } + int canons() const { return _canons; } + int maxCannons() const { return _maxCannons; } + int durability() const { return _durability; } + int maxDurability() const { return _maxDurability; } + +private: + // Allow to be created only by std::unique_ptr + friend std::unique_ptr std::make_unique(); + Ship() = default; + + Time* _time{}; + std::unique_ptr> _strategy{}; + std::string _name{}; + int _capacity{-1}; + int _maxCrew{-1}; + int _crew{10}; + std::unique_ptr _visitor{}; + int _armor{0}; + int _maxArmor{-1}; + int _canons{0}; + int _maxCannons{-1}; + int _durability{100}; + int _maxDurability{-1}; +}; +``` + + + +___ + +## Clean up + +In my opinion, a better option is to declare friendship with class `ShipBuilder`. Generally, friend with other classes is not a good idea. But in builder pattern we have a lot of profits: + +* Don't need to duplicate setters +* Some of the fields should not be changed after Ship will be built, but still we need to have a setter for this field +* We don't need to return a reference to `Ship` for all setters. +* Don't need to have getters for all members + +___ + +```C++ +class Ship { +public: + void setCrew(int crew) { _crew = crew; } + void setArmor(int armor) { _armor = armor; } + void setCannons(int cannons) { _canons = cannons; } + void setDurability(int durability) { _durability = durability; } + + const std::string& name() const { return _name; } + int capacity() const { return _capacity; } + int crew() const { return _crew; } + int armor() const { return _armor; } + int canons() const { return _canons; } + int durability() const { return _durability; } + +private: + // Allow to be created only by std::unique_ptr + friend std::unique_ptr std::make_unique(); + Ship() = default; +} +``` + +___ + +```C++ +class ShipBuilder { +public: + ShipBuilder() + : _ship(std::make_unique()) {} + + [[nodiscard]] std::unique_ptr build() { + if (!_ship) { + std::cout << "Builder may be use once\n"; + return nullptr; + } + + // Check mandatory fields + if (!_ship->_time || + _ship->_name.empty() || + _ship->_capacity == -1 || + _ship->_maxCrew == -1 || + _ship->_maxArmor == -1 || + _ship->_maxCannons == -1 || + _ship->_maxDurability == -1) { + std::cout << "Mandatory fields are not set!\n"; + return nullptr; + } + + return std::move(_ship); + } + + ShipBuilder& setTime(Time* time) { + _ship->_time = time; + return *this; + } + ShipBuilder& setStrategy(std::unique_ptr> strategy) { + _ship->_strategy = std::move(strategy); + return *this; + } + ShipBuilder& setName(const std::string& name) { + _ship->_name = name; + return *this; + } + ShipBuilder& setCapacity(int capacity) { + _ship->_capacity = capacity; + return *this; + } + ShipBuilder& setMaxCrew(int maxCrew) { + _ship->_maxCrew = maxCrew; + return *this; + } + ShipBuilder& setCrew(int crew) { + _ship->_crew = crew; + return *this; + } + ShipBuilder& setVisitor(std::unique_ptr visitor) { + _ship->_visitor = std::move(visitor); + return *this; + } + ShipBuilder& setArmor(int armor) { + _ship->_armor = armor; + return *this; + } + ShipBuilder& setMaxArmor(int maxArmor) { + _ship->_maxArmor = maxArmor; + return *this; + } + ShipBuilder& setCannons(int cannons) { + _ship->_canons = cannons; + return *this; + } + ShipBuilder& setMaxCannons(int maxCannons) { + _ship->_maxCannons = maxCannons; + return *this; + } + ShipBuilder& setDurability(int durability) { + _ship->_durability = durability; + return *this; + } + ShipBuilder& setMaxDurability(int maxDurability) { + _ship->_maxDurability = maxDurability; + return *this; + } + +private: + std::unique_ptr _ship; +}; +``` + +___ + +## Usage + +For both implementations, we use builder in the same way: + +```C++ +int main() { + auto ship = ShipBuilder().build(); + if (ship) { + std::cout << "Ship name: " << ship->name() << '\n'; + } + + Time time; + auto ship2 = ShipBuilder() + .setTime(&time) + .setName("Black Pearl") + .setCapacity(500) + .setMaxCrew(200) + .setMaxArmor(1000) + .setMaxCannons(20) + .setMaxDurability(1000) + .build(); + + if (ship2) { + std::cout << "Ship name: " << ship2->name() << '\n'; + } +} +``` + + +```bash +Mandatory fields are not set! +Ship name: Black Pearl +``` + + +___ + +## gRPC + +A perfect example of builder is an gRPC library. We use the builder pattern to create a server object, which we can customize. Based on provided arguments we can create synchronous or asynchronous server, with or without compression, with one or more services, with additional options like max response size etc... + +```C++ +grpc::Status status; +std::shared_ptr provider = + grpc::FileWatcherAuthorizationPolicyProvider::Create( + authz_policy_path, /*refresh_interval_sec=*/3600, &status); +auto option = std::make_unqiue(); +grpc::ChannelArguments args; +args.SetMaxReceiveMessageSize(4096); +args.SetMaxSendMessageSize(4096); +option->UpdateArguments(args); + +std::unique_ptr server = + grpc::ServerBuilder().AddListeningPort("127.0.0.1:10000", InsecureServerCredentials()) + .RegisterService(&service1) + .RegisterService("127.0.0.1:9999", &service2) + .SetAuthorizationPolicyProvider(provider) + .SetOption(std::move(option)) + .SetDefaultCompressionLevel(grpc::GRPC_COMPRESS_LEVEL_HIGH) + .BuildAndStart(); +``` + + +___ + +## DRY + +At the beginning, we decided to have 3 types of ships. We always need to remember which value to pass to each parameter to create a specific type of ship. If we decide that something is not okay with balance, we need to change this parameter everywhere. If we forget to change it in some code, we end up with different parameters for the same ship type. We can of course decided to have some global variable, but this is an ugly solution. **We should wrap the whole logic in one place**. To make it more flexible, we will describe all parameters in a JSON file, so we will not be forced to recompile the whole binary every time we change the ship parameters. Because we don't want to modify existing code, we just create a new class that inherit `private` from the `ShipBuilder` so we can't use the interface `ShipBuilder` outside, but still `ShipJsonBuilder` may use this implementation. + +```C++ +class ShipJsonBuilder : private ShipBuilder { +public: + ShipJsonBuilder(const std::filesystem::path& path) { parseFile(path); } + + std::unique_ptr buildBrig(Time* time, const std::string& name) const { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["brig"]["capacity"]) + .setMaxCrew(_shipsData["brig"]["maxCrew"]) + .setMaxArmor(_shipsData["brig"]["maxArmor"]) + .setMaxCannons(_shipsData["brig"]["maxCannons"]) + .setMaxDurability(_shipsData["brig"]["maxDurability"]) + .build(); + } + std::unique_ptr buildFrigate(Time* time, const std::string& name) const; + std::unique_ptr buildGaleon(Time* time, const std::string& name) const; + +private: + json _shipsData; + void parseFile(const std::filesystem::path& path); // Parse file and store data in _shipsData +}; +``` + + + +___ + +## Usage + +Now, we can easily create one of existing types of ship, without worry about which values to pass. What's more, we read the file from JSON, so we decouple values from the binary, so every time we make some changes in balance, we don't need to recompile any single file. + +```C++ +int main() { + Time time; + + auto ship1 = ShipJsonBuilder().buildGaleon(&time, "Queens Anne Revenge"); + if (ship1) { + std::cout << "Ship name: " << ship1->name() << '\n'; + } + + auto ship2 = ShipJsonBuilder().buildFrigate(&time, "Black Pearl"); + if (ship2) { + std::cout << "Ship name: " << ship2->name() << '\n'; + } + + auto ship3 = ShipJsonBuilder().buildBrig(&time, "Black Widow"); + if (ship3) { + std::cout << "Ship name: " << ship3->name() << '\n'; + } +} +``` + + +```bash +Ship name: Queens Anne Revenge +Ship name: Black Pearl +Ship name: Black Widow +``` + + +___ + +## Different builder + +But there is even more! Currently, we focus only on one builder, which always create a `Ship` class. We also create a `ShipJsonBuilder` which reuse implementation from `ShipBuilder` and allow to user read default parameters from the file, so we always create a `Ship` of the same type with equal parameters. We also saw that gRPC use the same logic to also user create various type of server. Furthermore, gRPC add plenty of methods which allow us to set parameters of this server. We can even go further and create a few types of builder, and then pass a pointer to the base class to `Driector` and create a different object. + +```C++ +class CrewBuilder { +public: + CrewBuilder& setName(const std::string& name) = 0; + CrewBuilder& setWeapon(std::unique_ptr&& weapon) = 0; + CrewBuilder& setHp(Hp hp) = 0; + std::unique_ptr build() = 0; +}; +``` + + + +```C++ +class PirateBuilder : public CrewBuilder { +public: + CrewBuilder& setName(const std::string& name) override { /* some implementation */ } + CrewBuilder& setWeapon(std::unique_ptr&& weapon) override { /* some implementation */ } + CrewBuilder& setHp(Hp hp) override { /* some implementation */ } + std::unique_ptr build() { return std::make_unique(/* args */); } +}; +``` + +___ + +## Tavern + +Based on which tavern we are, we can recruit, for instance: +* the marine, +* the volunteer, +* the pirate + +Each kind of Sailor will act differently in combat and during sail. They also have a different pay. We don't want to hard-code a type of Tavern on every island, because during a game, we can for instance conquer an island and free it forms pirates, so we will no longer recruit their pirates, but maybe a marine or volunteer. That's why we should pass a builder class as an argument to tavern, so we can easily swap it during a game. + + +```C++ +class Tawern { +public: + Tawern(std::unique_ptr&& builder): _builder(std::move(builder)) {} + + std::unique_ptr recruit(const std::string& name, std::unique_ptr&& weapon) { + return _builder->setName(name).setWeapon(weapon).setHp(40).build(); + } + +private: + std::unique_ptr _builder; +}; +``` + + +___ + +## Mixing two design patterns + +If you have a feeling that this looks similar to factory method, you are right! Both design patterns are similar. There are few main differences: + +* Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately. +* Builder often builds a Composite. +* Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed. +* Sometimes creational patterns are complementary: Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementations. + + +___ + +## Exercise 1 + +* Go to the directory Ship and create class ShipBuilder. The mandatory fields are: + * name + * capacity + * time +* The non-mandatory fields are: + * difficultStrategy -> default value should be set as Easy + * crew -> default value should be set as 10 + * durability -> default value should be set as 1000 + * armor -> default value should be set as 0 + * PrintVisitor -> default value should be set as Pretty Print +* Try to build your own Ship! +___ + +## Exercise 2 + +* Go to the directory Ship and finish implementation of class ShipJsonBuilder. You should allow building 3 types of ship: + * Brig + * Frigate + * Galoen +* If you want to read a JSON filed, just use operator[] to get any of nested field, example: _shipsData["brige"]["armor"] +* Try to build a ship using a new builder. +* Try to change some values in ships.json and run binary without recompilation. You should see new values! + +___ + +## Factory method + +Because we saw in the previous example a factory method patter, I want to tell a little more about it. Whenever we want to hide implementation details about creation of new object (and also a final type) we should use factory method. + +Factory method UML + +___ + +Interface of factory: +```C++ +class Factory { +public: + virtual std::unique_ptr create(const std::string& name, std::unique_ptr&& weapon, int hp) = 0; +}; +``` + + +Implementations: + + +```C++ +class PirateBuilder : public CrewBuilder { +public: + std::unique_ptr create(const std::string& name, std::unique_ptr&& weapon, int hp) override { + return std::make_unique(name, std::move(weapon), hp); + } +}; + +class MarineBuilder : public CrewBuilder { +public: + std::unique_ptr create(const std::string& name, std::unique_ptr&& weapon, int hp) override { + return std::make_unique(name, std::move(weapon), hp); + } +}; +``` + + +Class that use factory to create object: + + +```C++ +class Tawern { +public: + Tawern(std::unique_ptr&& factory): _factory(std::move(factory)) {} + std::unique_ptr recruit(const std::string& name, std::unique_ptr&& weapon) { + return _factory->create(name, std::move(weapon), 40); + } +private: + std::unique_ptr _factory_; +}; +``` + + + +___ + +## Exercise 3 + +* Go to the directory Ship and create abstract class FruitFactory. +* Create FruitFactory +* Create ItemFactory +* Create AlcoholFactory +* Test in main.cpp if you can create any type of cargo +* How to handle scenario, when different cargo takes other arguments? + +___ + +## Different arguments + +At the end, I want to talk about different arguments in constructors. We have three derived class from `Cargo`, each class takes different arguments. + +```C++ +struct Fruit : public Cargo { + int rottenCounter; + + Fruit(size_t amount, int rottenCounter); + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Item : public Cargo { + enum class Type { Common, Rare, Epic, Legendary }; + Type type; + + Item(size_t amount, Type type); + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Alcohol : public Cargo { + enum class Type { White, Spiced, Dark}; + + int power; + Type type; + Alcohol(size_t amount, int power, Type type); + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; +``` + + + +___ + +## How to solve it? + +**Of course by using template!** + + +```C++ +template +class CargoFactory { +public: + virtual std::unique_ptr create(size_t amount, Args... args) = 0; +}; +``` + + +```C++ +class FruitFactory : public CargoFactory { +public: + std::unique_ptr create(size_t amount, int rottenCounter) override { + return std::make_unique(amount, rottenCounter); + } +}; + +class AlcoholFactory : public CargoFactory { +public: + std::unique_ptr create(size_t amount, int power, Alcohol::Type type) override { + return std::make_unique(amount, power, type); + } +}; + +class ItemFactory : public CargoFactory { +public: + std::unique_ptr create(size_t amount, Item::Type type) override { + return std::make_unique(amount, type); + } +}; +``` + + \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/compilation.md b/CreatingReliableSoftwareCpp/Presentation/compilation.md new file mode 100644 index 0000000..898e363 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/compilation.md @@ -0,0 +1,43 @@ +# Cloning and building example project +___ + +## Setup + +* Clone repository: https://github.com/nauka-programowania-MA/CreatingReliableSoftwareCpp +* Go to exercises/exampleProject +* Compile it and run: + * mkdir build + * cd build + * cmake .. + * make -j4 (where 4 is available threads) + * ./ExampleProject +* Should print Hello World + +If you don't have linux, you can use replit + +* Click Create C++ +* Name it and confirm with button Create Repl. +* Click three dot on the rigt top screen and click upload folder +* Now find your directory with repo and upload it +* Congratulation, you can use linux shell wit sanitizers, cmake and valgridn support :) + + +___ + +## replit + +If you decided to use replit please configure this file: `replit.nix`: + +```bash +{ pkgs }: { + deps = [ + pkgs.clang_12 + pkgs.ccls + pkgs.gdb + pkgs.gnumake + pkgs.vim + pkgs.valgrind + pkgs.cmake + ]; +} +``` \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/decorator.md b/CreatingReliableSoftwareCpp/Presentation/decorator.md new file mode 100644 index 0000000..e797b17 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/decorator.md @@ -0,0 +1,577 @@ +## Decorator + +The last design pattern that I mention today is a `decorator`. Before we talk about it, let's extend `Cargo` class and handle a few new functionalities: + +* The item may be damaged during a time (we have salty air) so it can lose his value during travelling +* The fruit may rotten, so we also want to lower its price every day +* The alcohol price should be based on it's power +* The value of item should be higher based on its type (common is cheapest but legendary has a big value) + +___ + +## New implementation + +Let's start with a new implementation of class `Fruit`. Now we inherit from `TimeObserver` to count days. We also take in account that the price will be lowered every day. + +```C++ +struct Fruit : public Cargo, public TimeObserver { + static constexpr int MAX_TIME = 20; + static constexpr int BASE_PRICE = 10; + int rottenCounter; + Time* time; + + Fruit(Time* time, size_t amount, int rottenCounter) + : Cargo(amount), time(time), rottenCounter(rottenCounter) { + time->attach(this); + } + + // Rule of 5 + ~Fruit() { + time->detach(this); + } + + size_t getPrice() const override { + return (rottenCounter * BASE_PRICE) / MAX_TIME; + } + + const std::string& name() const override { + static const std::string name = "Banana"; + return name; + } + + void nextDay() override { + rottenCounter = std::max(0, rottenCounter - 1); + } +}; +``` + + + +___ + +```C++ +struct Item : public Cargo, public TimeObserver { + enum class Type { Common = 100, + Rare = 300, + Epic = 1000, + Legendary = 2500 }; + static constexpr int MAX_DURABILITY = 100; + Time* time; + Type type; + int durability{MAX_DURABILITY}; + + Item(Time* time, size_t amount, Type type) + : Cargo(amount), time(time), type(type) { + time->attach(this); + } + + // Rule of 5 + ~Item() { + time->detach(this); + } + + size_t getPrice() const override { + return (durability * static_cast(type)) / MAX_DURABILITY; + } + + const std::string& name() const override { + static const std::string name = "Item"; + return name; + } + + void nextDay() override { + durability = std::max(0, durability - 1); + } +}; +``` + +___ + +## Duplication of code + +At the end, we also implement a `Alcohol` class. As you can see, we duplicate behavior few times. `Item` and `Fruit` may lose value each day. Price of `Item` and `Alcohol` depend on it's type etc… + +```C++ +struct Alcohol : public Cargo { + enum class Type { White = 100, + Spiced = 200, + Dark = 300, + Seasoned = 500 }; + static constexpr int MAX_POWER = 96; + int power; + Type type; + + Alcohol(size_t amount, int power, Type type) + : Cargo(amount), power(power), type(type) {} + + size_t getPrice() const override { + return (power * static_cast(type)) / MAX_POWER; + } + + const std::string& name() const override { + static const std::string name = "Rum"; + return name; + } +}; +``` + + +___ + +The following code works as we want to. However, whenever we want to change a logic, for instance instead of decrement the counter every day, we want to subtract `durability` and `rottenCounter` every second day. We need to do this in two places. And when we will add more cargo, we will need to do this everywhere. This is not a good example of easy to maintenance code. + +```C++ +int main() { + Time time; + std::unique_ptr cargo = std::make_unique(&time, 10, Item::Type::Epic); + + for (int i = 1; i <= 15; ++i) { + std::cout << "DAY: " << i << " | Name: " << cargo->name() << " | Price: " << cargo->getPrice() << '\n'; + ++time; + } +} +``` + + +``` +DAY: 1 | Name: Item | Price: 1000 +DAY: 2 | Name: Item | Price: 990 +DAY: 3 | Name: Item | Price: 980 +DAY: 4 | Name: Item | Price: 970 +DAY: 5 | Name: Item | Price: 960 +DAY: 6 | Name: Item | Price: 950 +DAY: 7 | Name: Item | Price: 940 +DAY: 8 | Name: Item | Price: 930 +DAY: 9 | Name: Item | Price: 920 +DAY: 10 | Name: Item | Price: 910 +DAY: 11 | Name: Item | Price: 900 +DAY: 12 | Name: Item | Price: 890 +DAY: 13 | Name: Item | Price: 880 +DAY: 14 | Name: Item | Price: 870 +DAY: 15 | Name: Item | Price: 860 +``` + + +___ + +## Drawback + +According to one of SOLID rule **O**pen-close, we should write an easy to extend code, which don't require from us modification of already implemented code. Unfortunately, we need to modify each class to append a new logic, like: `decrement durability each day` or `get price based on durability or type`. What's more, we don't want to simulate `rotten of fruit` or lose `durability` by items that are stored in `shops`. So we need to add some `bool` flag like `isInShop` to ignore time elapsing. When the code grows and grows, we need to add more such flags and duplicate more code. This is definitely not the way we should develop a code. A better solution is to make a `Fruit` or `Item` class unaware of time elapsing. We can also make class `item` and `Alcohol` unaware of different types, and it's prices. This will allow to decouple the code, and make it easier to extend. + +___ + +## Decorator + +Instead of implement the whole logic to every class, and then make some `bool` flags to omit a few of them. We can use a `decorator` pattern. Let's start from the interface. The `DecoratedCargo` inherit form `Cargo` class and take as an argument `unique_ptr` for class `Cargo`. This interface has also two protected function allowing to get underlying cargo. + +```C++ +class DecoratedCargo : public Cargo { +public: + explicit DecoratedCargo(std::unique_ptr&& cargo) + : _cargo(std::move(cargo)) { + assert(_cargo); + } + +protected: + Cargo& cargo() { return *_cargo; } + const Cargo& cargo() const { return *_cargo; } + +private: + std::unique_ptr _cargo; +}; +``` + + +___ + +## Vulnerable + +A `Vulnerable` class inherit from `TimeObserver` to simulate time elapsing and from `DecoratedCargo`. When we calculate the price, it will calculate percentage value based on `durability` and `maxDurability`. Price can be manipulated by other decorator, so we call `getPrice`. + +```C++ +class Vulnerable : public DecoratedCargo, public TimeObserver { +public: + Vulnerable(std::unique_ptr&& cargo, Time* time, int durability, int maxDurability) + : DecoratedCargo(std::move(cargo)), _time(time), _durability(durability), _maxDurability(maxDurability) { + assert(_time); + time->attach(this); + } + + // Rule of 5 + ~Vulnerable() { + _time->detach(this); + } + + void nextDay() override { + _durability = std::max(0, _durability - 1); + } + + size_t getPrice() const override { + return (_durability * cargo().getPrice()) / _maxDurability; + } + + const std::string& name() const override { + return cargo().name(); + } + +private: + Time* _time; + int _durability; + int _maxDurability; +}; +``` + + +___ + +## Valuable + +A `Valuable` class is a template class that take `enum` as a template argument. It will be used later when we calculate a price. We will treat it as a multiplier for already calculated price. + +```C++ +template +class Valuable : public DecoratedCargo { +public: + Valuable(std::unique_ptr&& cargo, ValueType value) + : DecoratedCargo(std::move(cargo)), _value(value) { + } + + size_t getPrice() const override { + return cargo().getPrice() * static_cast(_value); + } + + const std::string& name() const override { + return cargo().name(); + } + +private: + ValueType _value; +}; +``` + + +___ + +## Type + +Because we want to make `Item` and `Alcohol` and any other type unaware about its type. We move it to the separate files. This allows us to develop new functionality without modification of existing code. For instance, when we decided later that we want to add also a `type` for `Fruit` we will create a new file and that's all! We don't need to recompile anything, and also don't need to modify anything. So even if `Fruit` is in a separate repository, and we can't modify it. We still can add new behavior. + +```C++ +enum class ItemType { Common = 1, + Rare = 3, + Epic = 10, + Legendary = 25 }; + +enum class AlcoholType { White = 1, + Spiced = 2, + Dark = 3, + Seasoned = 5 }; +``` + + + +___ + +## Usage + +Now we can concatenate any decorator with a `Cargo` type, so we can add new functionality `in fly`. + +```C++ +int main() { + Time time; + std::unique_ptr cargo = std::make_unique( + std::make_unique>( + std::make_unique(10), ItemType::Epic), + &time, 100, 100); + + for (int i = 1; i <= 15; ++i) { + std::cout << "DAY: " << i << " | Name: " << cargo->name() << " | Price: " << cargo->getPrice() << '\n'; + ++time; + } +} +``` + + +```bash +DAY: 1 | Name: Item | Price: 1000 +DAY: 2 | Name: Item | Price: 990 +DAY: 3 | Name: Item | Price: 980 +DAY: 4 | Name: Item | Price: 970 +DAY: 5 | Name: Item | Price: 960 +DAY: 6 | Name: Item | Price: 950 +DAY: 7 | Name: Item | Price: 940 +DAY: 8 | Name: Item | Price: 930 +DAY: 9 | Name: Item | Price: 920 +DAY: 10 | Name: Item | Price: 910 +DAY: 11 | Name: Item | Price: 900 +DAY: 12 | Name: Item | Price: 890 +DAY: 13 | Name: Item | Price: 880 +DAY: 14 | Name: Item | Price: 870 +DAY: 15 | Name: Item | Price: 860 +``` + + +___ + +## Store + +If cargo is inside the store, we just don't add a `Vulnerable` decorator! + +```C++ +Time time; +std::unique_ptr cargo = std::make_unique( + std::make_unique>( + std::make_unique(10), ItemType::Epic), + &time, 100, 100); +std::unique_ptr cargo2 = + std::make_unique>( + std::make_unique(10), ItemType::Epic); + +for (int i = 1; i <= 15; ++i) { + std::cout << "DAY: " << i << " | Name: " << cargo->name() << " | Price: " << cargo->getPrice(); + std::cout << " |-| Name: " << cargo2->name() << " | Price: " << cargo2->getPrice() << '\n'; + ++time; +} +``` + + +```bash +DAY: 1 | Name: Item | Price: 1000 |-| Name: Item | Price: 1000 +DAY: 2 | Name: Item | Price: 990 |-| Name: Item | Price: 1000 +DAY: 3 | Name: Item | Price: 980 |-| Name: Item | Price: 1000 +DAY: 4 | Name: Item | Price: 970 |-| Name: Item | Price: 1000 +DAY: 5 | Name: Item | Price: 960 |-| Name: Item | Price: 1000 +DAY: 6 | Name: Item | Price: 950 |-| Name: Item | Price: 1000 +DAY: 7 | Name: Item | Price: 940 |-| Name: Item | Price: 1000 +DAY: 8 | Name: Item | Price: 930 |-| Name: Item | Price: 1000 +DAY: 9 | Name: Item | Price: 920 |-| Name: Item | Price: 1000 +DAY: 10 | Name: Item | Price: 910 |-| Name: Item | Price: 1000 +DAY: 11 | Name: Item | Price: 900 |-| Name: Item | Price: 1000 +DAY: 12 | Name: Item | Price: 890 |-| Name: Item | Price: 1000 +DAY: 13 | Name: Item | Price: 880 |-| Name: Item | Price: 1000 +DAY: 14 | Name: Item | Price: 870 |-| Name: Item | Price: 1000 +DAY: 15 | Name: Item | Price: 860 |-| Name: Item | Price: 1000 +``` + + +___ + +## Decorator + +The decorator pattern can be used to extend (decorate) the functionality of a certain object statically, or in some cases at run-time, independently of other instances of the same class, provided some groundwork is done at design time. This is achieved by designing a new Decorator class that wraps the original class. + +Decorator UML + + +___ + +Decorator also helps with **D**ependency inversion. Because `decorator` classes are in low-lvl, so we can easily add a new decorator without changing anything in higher layers. + +Decorator Cargo UML + + +___ + +## Drawbacks + +Decorator is powerfull desing pattenr, but as everything it also has some drawbacks. + +* The main problem is that we need to use plenty of `unique_ptr` this will use more memory and also will be slower, because we need to call a few virtual functions. +* If we add to many decorators, the code became hard to read +* Debugging code containing decorators also may be more difficult, because we need to jump between a few of the same methods (but located in different decorators) before we reach the final result. So find a bug will be harder +* If the result of one decorator has an impact on another, we may cause a hard to spot bug when we swap the order. So we shouldn't create a decorator, which should be stored in order, because a risk of concatenated them wrong is high. +___ + +## Different approach + +As one popular proverb says: "Time is money". And if our code must be as fast as possible, and we can't afford a price, that few decorators means calling of few virtual functions, which also make the code much harder to optimize by compiler. We need to rising with decorator. I have good news for you: No, you don't need to! We have two types of polymorphism, so instead of using a `dynamic` one, let's use a `static`. + +___ + +## Get rid of virtual + +First, the class `Cargo` is no longer virtual. We don't need to implement rule of 5 and create a virtual destructor. We move constructors to `protected` section, to make it create only by derived classes (sth similar to abstract class, which we can't create). + +```C++ +struct Cargo { + size_t amount; + + auto operator<=>(const Cargo&) const = default; + +protected: + // Only derived class can create it + Cargo(size_t amount) + : amount(amount) {} + Cargo() = default; +}; +``` + + +___ + +Next, we also remove all virtual functions from derived classes. + +```C++ +struct Fruit : public Cargo { + static constexpr int BASE_PRICE = 10; + + Fruit(size_t amount) + : Cargo(amount) {} + + size_t getPrice() const { + return BASE_PRICE; + } + + const std::string& name() const { + static const std::string name = "Banana"; + return name; + } +}; +``` + + +```C++ +struct Item : public Cargo { + static constexpr int BASE_PRICE = 100; + + Item(size_t amount) + : Cargo(amount) {} + + size_t getPrice() const { + return BASE_PRICE; + } + + const std::string& name() const { + static const std::string name = "Item"; + return name; + } +}; +``` + + +___ + +We don't need to have a base class for decorator. We can move directly to implementation. + +```C++ +template +class Vulnerable : public TimeObserver { +public: + Vulnerable(Neasted neasted, Time* time, int durability, int maxDurability) + : _neasted(neasted), _time(time), _durability(durability), _maxDurability(maxDurability) { + assert(_time); + time->attach(this); + } + + // Rule of 5 + ~Vulnerable() { _time->detach(this);} + + void nextDay() override { + _durability = std::max(0, _durability - 1); + } + + size_t getPrice() const { + return (_durability * _neasted.getPrice()) / _maxDurability; + } + + const std::string& name() const { + return _neasted.name(); + } + +private: + Neasted _neasted; + Time* _time; + int _durability; + int _maxDurability; +}; +``` + + + +___ + +As you can see, we have even less code, and we avoid a lot of virtual functions. If we decide that an object is too heavy to copy, we can pass a pointer. The main bottleneck of decorator which slows down the code was calling a lot of virtual functions. Without virtual functions, our code is much faster. + +```C++ +template +class Valuable { +public: + Valuable(Neasted neasted, ValueType value) + : _neasted(neasted), _value(value) { + } + + size_t getPrice() const { + return _neasted.getPrice() * static_cast(_value); + } + + const std::string& name() const { + return _neasted.name(); + } + +private: + Neasted _neasted; + ValueType _value; +}; +``` + + +___ + +Even usage seems more intuitive, because we don't need to create a lot of `unique_ptr` even for small objects. + +```C++ +int main() { + Time time; + auto cargo = Vulnerable(Valuable(Item(10), ItemType::Epic), &time, 100, 100); + auto cargo2 = Valuable(Item(10), ItemType::Epic); + + for (int i = 1; i <= 15; ++i) { + std::cout << "DAY: " << i << " | Name: " << cargo.name() << " | Price: " << cargo.getPrice(); + std::cout << " |-| Name: " << cargo2.name() << " | Price: " << cargo2.getPrice() << '\n'; + ++time; + } +} +``` + + +```bash +DAY: 1 | Name: Item | Price: 1000 |-| Name: Item | Price: 1000 +DAY: 2 | Name: Item | Price: 990 |-| Name: Item | Price: 1000 +DAY: 3 | Name: Item | Price: 980 |-| Name: Item | Price: 1000 +DAY: 4 | Name: Item | Price: 970 |-| Name: Item | Price: 1000 +DAY: 5 | Name: Item | Price: 960 |-| Name: Item | Price: 1000 +DAY: 6 | Name: Item | Price: 950 |-| Name: Item | Price: 1000 +DAY: 7 | Name: Item | Price: 940 |-| Name: Item | Price: 1000 +DAY: 8 | Name: Item | Price: 930 |-| Name: Item | Price: 1000 +DAY: 9 | Name: Item | Price: 920 |-| Name: Item | Price: 1000 +DAY: 10 | Name: Item | Price: 910 |-| Name: Item | Price: 1000 +DAY: 11 | Name: Item | Price: 900 |-| Name: Item | Price: 1000 +DAY: 12 | Name: Item | Price: 890 |-| Name: Item | Price: 1000 +DAY: 13 | Name: Item | Price: 880 |-| Name: Item | Price: 1000 +DAY: 14 | Name: Item | Price: 870 |-| Name: Item | Price: 1000 +DAY: 15 | Name: Item | Price: 860 |-| Name: Item | Price: 1000 +``` + + +___ + +## Ecerice 1 + +* Go into directory Ship and implement DecoratedCargo: + * It should take a std::unique_ptr<Cargo> and has protected getter to this field. +* Implement Vunreable class: + * It should inherit from TimeObserver and DecoratedCargo + * It should take additional parameters in C'tor: Time, durability and maxDurability + * It should simulate time elapsing. Every day should subtract durability + * It should return price back on current durability of cargo + +___ + +## Exercise 2 + +* Implement Valuable class: + * It should inherit from DecoratedCargo + * it should be a template that takes enum type of value + * It should return value based on type (cast it to enum and multiply by current value) +* Try to compile code form main.cpp +* You may have some trouble with running code if you don't write a code carefully :) think where is a problem. diff --git a/CreatingReliableSoftwareCpp/Presentation/design_patterns_intro.md b/CreatingReliableSoftwareCpp/Presentation/design_patterns_intro.md new file mode 100644 index 0000000..9dfa41d --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/design_patterns_intro.md @@ -0,0 +1 @@ +# Design patterns \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder.cpp new file mode 100644 index 0000000..accfa68 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder.cpp @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include + +struct Time {}; +template +struct DifficultStrategy {}; +struct PrintVisitor {}; + +class Ship { +public: + Ship& setTime(Time* time) { + _time = time; + return *this; + } + Ship& setStrategy(std::unique_ptr> strategy) { + _strategy = std::move(strategy); + return *this; + } + Ship& setName(const std::string& name) { + _name = name; + return *this; + } + Ship& setCapacity(int capacity) { + _capacity = capacity; + return *this; + } + Ship& setMaxCrew(int maxCrew) { + _maxCrew = maxCrew; + return *this; + } + Ship& setCrew(int crew) { + _crew = crew; + return *this; + } + Ship& setVisitor(std::unique_ptr visitor) { + visitor = std::move(_visitor); + return *this; + } + Ship& setArmor(int armor) { + _armor = armor; + return *this; + } + Ship& setMaxArmor(int maxArmor) { + _maxArmor = maxArmor; + return *this; + } + Ship& setCannons(int cannons) { + _canons = cannons; + return *this; + } + Ship& setMaxCannons(int maxCannons) { + _maxCannons = maxCannons; + return *this; + } + Ship& setDurability(int durability) { + _durability = durability; + return *this; + } + Ship& setMaxDurability(int maxDurability) { + _maxDurability = maxDurability; + return *this; + } + + const Time* time() const { return _time; } + const std::string& name() const { return _name; } + int capacity() const { return _capacity; } + int maxCrew() const { return _maxCrew; } + int crew() const { return _crew; } + int armor() const { return _armor; } + int maxArmor() const { return _maxArmor; } + int canons() const { return _canons; } + int maxCannons() const { return _maxCannons; } + int durability() const { return _durability; } + int maxDurability() const { return _maxDurability; } + +private: + // Allow to be created only by std::unique_ptr + friend std::unique_ptr std::make_unique(); + Ship() = default; + + Time* _time{}; + std::unique_ptr> _strategy{}; + std::string _name{}; + int _capacity{-1}; + int _maxCrew{-1}; + int _crew{10}; + std::unique_ptr _visitor{}; + int _armor{0}; + int _maxArmor{-1}; + int _canons{0}; + int _maxCannons{-1}; + int _durability{100}; + int _maxDurability{-1}; +}; + +class ShipBuilder { +public: + ShipBuilder() + : _ship(std::make_unique()) {} + + [[nodiscard]] std::unique_ptr build() { + if (!_ship) { + std::cout << "Builder may be use once\n"; + return nullptr; + } + + // Check mandatory fields + if (!_ship->time() || + _ship->name().empty() || + _ship->capacity() == -1 || + _ship->maxCrew() == -1 || + _ship->maxArmor() == -1 || + _ship->maxCannons() == -1 || + _ship->maxDurability() == -1) { + std::cout << "Mandatory fields are not set!\n"; + return nullptr; + } + + return std::move(_ship); + } + + ShipBuilder& setTime(Time* time) { + _ship->setTime(time); + return *this; + } + ShipBuilder& setStrategy(std::unique_ptr> strategy) { + _ship->setStrategy(std::move(strategy)); + return *this; + } + ShipBuilder& setName(const std::string& name) { + _ship->setName(name); + return *this; + } + ShipBuilder& setCapacity(int capacity) { + _ship->setCapacity(capacity); + return *this; + } + ShipBuilder& setMaxCrew(int maxCrew) { + _ship->setMaxCrew(maxCrew); + return *this; + } + ShipBuilder& setCrew(int crew) { + _ship->setCrew(crew); + return *this; + } + ShipBuilder& setVisitor(std::unique_ptr visitor) { + _ship->setVisitor(std::move(visitor)); + return *this; + } + ShipBuilder& setArmor(int armor) { + _ship->setArmor(armor); + return *this; + } + ShipBuilder& setMaxArmor(int maxArmor) { + _ship->setMaxArmor(maxArmor); + return *this; + } + ShipBuilder& setCannons(int cannons) { + _ship->setCannons(cannons); + return *this; + } + ShipBuilder& setMaxCannons(int maxCannons) { + _ship->setMaxCannons(maxCannons); + return *this; + } + ShipBuilder& setDurability(int durability) { + _ship->setDurability(durability); + return *this; + } + ShipBuilder& setMaxDurability(int maxDurability) { + _ship->setMaxDurability(maxDurability); + return *this; + } + +private: + std::unique_ptr _ship; +}; + +int main() { + auto ship = ShipBuilder().build(); + if (ship) { + std::cout << "Ship name: " << ship->name() << '\n'; + } + + Time time; + auto ship2 = ShipBuilder() + .setTime(&time) + .setName("Black Pearl") + .setCapacity(500) + .setMaxCrew(200) + .setMaxArmor(1000) + .setMaxCannons(20) + .setMaxDurability(1000) + .build(); + + if (ship2) { + std::cout << "Ship name: " << ship2->name() << '\n'; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/CMakeLists.txt new file mode 100644 index 0000000..751c5ff --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +include(FetchContent) +FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG v3.11.3 +) +FetchContent_MakeAvailable(json) + +target_link_libraries(${PROJECT_NAME} + Battle + Ship + Store + Core + Player + nlohmann_json::nlohmann_json +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/main.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/main.cpp new file mode 100644 index 0000000..9608adf --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/main.cpp @@ -0,0 +1,65 @@ +#include +#include +#include + +#include "Battle/BattleField.h" +#include "Core/BasicPrintVisitor.h" +#include "Core/PrettyPrintVisitor.h" +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Player/RealPlayer.h" +#include "Ship/AlcoholFactory.h" +#include "Ship/Cargo.h" +#include "Ship/CargoDamageVisitor.h" +#include "Ship/FruitFactory.h" +#include "Ship/ItemFactory.h" +#include "Ship/Ship.h" +#include "Ship/ShipBuilder.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Ship/ShipJsonBuilder.h" +#include "Store/Store.h" + +int main() { + Time time; + + auto ship = ShipBuilder() + .setTime(&time) + .setName("Black Widow") + .setCapacity(1000) + .setCrew(40) + .setStrategy(std::make_unique()) + .setVisitor(std::make_unique()) + .setArmor(100) + .setDurability(1000) + .build(); + ship->load(AlcoholFactory().create(300, 40, Alcohol::Type::Spiced)); + ship->load(FruitFactory().create(200, 15)); + ship->load(FruitFactory().create(150, 15)); + ship->load(ItemFactory().create(250, Item::Type::Epic)); + ship->printCargo(); + RealPlayer user("Mateusz", std::move(ship)); + + Enemy enemy("Enemy1", + ShipJsonBuilder("../ships.json").buildGaleon(&time, "Queens Anne revenge"), + std::make_unique(), + CargoDamageVisitor{}); + + BattleField battefield{&user, &enemy}; + while (true) { + for (auto* player : battefield.players()) { + std::cout << "-------------------------------------------------------------------\n"; + std::cout << "Player HP: " << user.getShip().durability() << " ARMOR: " << user.getShip().armor() << " | "; + std::cout << "Enemy HP: " << enemy.getShip().durability() << " ARMOR: " << enemy.getShip().armor() << '\n'; + std::cout << "-------------------------------------------------------------------\n"; + for (size_t i = 0; i < 3; ++i) { + const auto status = player->makeAction(battefield); + if (status == Action::Status::Escaped || status == Action::Status::Defeated) { + return 0; + } + } + } + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/ships.json b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/ships.json new file mode 100644 index 0000000..9b19770 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/ships.json @@ -0,0 +1,20 @@ +{ + "brige":{ + "capacity":1000, + "crew":40, + "durability":1000, + "armor":100 + }, + "frigate":{ + "capacity":1500, + "crew":70, + "durability":2000, + "armor":500 + }, + "galeon":{ + "capacity":2500, + "crew":120, + "durability":3000, + "armor":1000 + } + } \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/CMakeLists.txt new file mode 100644 index 0000000..acd8033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Battle src/Defense.cpp src/BattleField.cpp src/Attack.cpp src/Escape.cpp) + +target_include_directories(Battle PUBLIC include) + +target_link_libraries(Battle + Ship + Player +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Action.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Action.h new file mode 100644 index 0000000..f271d40 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Action.h @@ -0,0 +1,24 @@ +#pragma once + +class Player; +class Ship; + +class Action { +public: + // As you can see keeping type here, require modify a base class whenever we add a new class, this volatile an open-close principle. + // We should be able to extend code without modification already implemented one + enum class Type { + Attack, + Defense, + Escape + }; + + enum class Status { + Escaped, + Defeated, + Nothing, + }; + + virtual Status operator()(Player* player, Ship* enemyShip) = 0; + virtual Type type() const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Attack.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Attack.h new file mode 100644 index 0000000..a06cba0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Attack.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Attack : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Attack; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/BattleField.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/BattleField.h new file mode 100644 index 0000000..6196660 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/BattleField.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Ship; +class Player; + +class BattleField { +public: + BattleField(Player* player, Player* enemy); + + Ship* getPlayerShip() const; + Ship* getEnemyShip() const; + std::vector players() const; + +private: + Player* _player; + Player* _enemy; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Defense.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Defense.h new file mode 100644 index 0000000..fefd271 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Defense.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Defense : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Type::Defense; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Escape.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Escape.h new file mode 100644 index 0000000..97dc54d --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/include/Battle/Escape.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Battle/Action.h" + +#include + +class Player; +class Ship; + +class Escape : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Escape; } + +private: + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Attack.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Attack.cpp new file mode 100644 index 0000000..b3f5e8a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Attack.cpp @@ -0,0 +1,22 @@ +#include "Battle/Attack.h" + +#include +#include + +#include + +Action::Status Attack::operator()(Player* player, Ship* enemyShip) { + const int damage = player->attack(*enemyShip); + std::cout << "Player ship: " << player->getShip().name() << " attack ship: " << enemyShip->name() << '\n'; + if (damage) { + std::cout << "Dealed damage: " << damage << '\n'; + } else { + std::cout << "Missed\n"; + } + + if (enemyShip->durability() <= 0) { + return Status::Defeated; + } + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/BattleField.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/BattleField.cpp new file mode 100644 index 0000000..4e10569 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/BattleField.cpp @@ -0,0 +1,16 @@ +#include "Battle/BattleField.h" + +#include + +BattleField::BattleField(Player* player, Player* enemy) + : _player{player}, _enemy{enemy} {} + +Ship* BattleField::getPlayerShip() const { + return &_player->getShip(); +} +Ship* BattleField::getEnemyShip() const { + return &_enemy->getShip(); +} +std::vector BattleField::players() const { + return {_player, _enemy}; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Defense.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Defense.cpp new file mode 100644 index 0000000..a170c81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Defense.cpp @@ -0,0 +1,13 @@ +#include "Battle/Defense.h" + +#include +#include + +#include + +Action::Status Defense::operator()(Player* player, Ship*) { + player->getShip().increaseArmor(50); + std::cout << "Player ship: " << player->getShip().name() << " defense\n"; + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Escape.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Escape.cpp new file mode 100644 index 0000000..5b222fa --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Battle/src/Escape.cpp @@ -0,0 +1,22 @@ +#include "Battle/Escape.h" + +#include +#include + +#include + +std::random_device Escape::_rd{}; + +Action::Status Escape::operator()(Player* player, Ship*) { + std::cout << "Player ship: " << player->getShip().name() << " try to escape!\n"; + + std::uniform_int_distribution dice(0, 20); + const auto res = dice(_seed); + if (res > 12) { + std::cout << "Player escaped!\n"; + return Status::Escaped; + } + + std::cout << "Escape maneuver failed!\n"; + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/CMakeLists.txt new file mode 100644 index 0000000..9434ff8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(Battle) +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/CMakeLists.txt new file mode 100644 index 0000000..db39d82 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Core src/Time.cpp src/BasicPrintVisitor.cpp src/PrettyPrintVisitor.cpp) + +target_include_directories(Core PUBLIC include) + +target_link_libraries(Core + Ship + Store +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/BasicPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/BasicPrintVisitor.h new file mode 100644 index 0000000..cd3406f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/BasicPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class BasicPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/DifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/DifficultLvlStrategy.h new file mode 100644 index 0000000..7c23854 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/DifficultLvlStrategy.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +template +class DifficultLvlStrategy { +public: + virtual Res handle(T&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/PrettyPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/PrettyPrintVisitor.h new file mode 100644 index 0000000..58dc6ad --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/PrettyPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class PrettyPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/PrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/PrintVisitor.h new file mode 100644 index 0000000..bec94c0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/PrintVisitor.h @@ -0,0 +1,11 @@ +#pragma once + +class Store; +class Ship; + +class PrintVisitor { +public: + virtual ~PrintVisitor() = default; + virtual void visit(const Store&) const = 0; + virtual void visit(const Ship&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/BasicPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/BasicPrintVisitor.cpp new file mode 100644 index 0000000..05960c1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/BasicPrintVisitor.cpp @@ -0,0 +1,22 @@ +#include + +#include +#include +#include +#include + +void BasicPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << std::setw(15) << cargo->getPrice() << "\n"; + } +} + +void BasicPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << "\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/PrettyPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/PrettyPrintVisitor.cpp new file mode 100644 index 0000000..99b6738 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/PrettyPrintVisitor.cpp @@ -0,0 +1,33 @@ +#include + +#include +#include +#include +#include + +void PrettyPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} + +void PrettyPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/CMakeLists.txt new file mode 100644 index 0000000..b266b3f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(Player src/EnemyEasyDifficultLvlStrategy.cpp src/EnemyHardDifficultLvlStrategy.cpp src/Player.cpp src/RealPlayer.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Battle + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..e44bd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/Enemy.h @@ -0,0 +1,66 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include +#include +#include + +#include +#include + +template +class Enemy : public Player { +public: + Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + std::unique_ptr> _strategy; + DamageVisitor _damageVisitor; +}; + +template +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor) + : _name(name), _ship(std::move(ship)), _strategy(std::move(strategy)), _damageVisitor(visitor) {} + +template +int Enemy::attack(Ship& playerShip) { + if (const auto damage = _strategy->handle(playerShip)) { + for (auto& cargo : playerShip.cargoes()) { + cargo->accept(_damageVisitor); + } + return damage; + } + + return 0; +} + +template +Ship* Enemy::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getPlayerShip(); +} + +template +std::unique_ptr Enemy::chooseAction(const BattleField& battleField) const { + static bool flag = true; + if (flag) { + flag = !flag; + return std::make_unique(); + } + + flag = !flag; + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..d2b7b05 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyEasyDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h new file mode 100644 index 0000000..ac01b4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyHardDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/Player.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/Player.h new file mode 100644 index 0000000..7717389 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/Player.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include + +class BattleField; +class Ship; + +class Player { +public: + virtual ~Player() = default; + virtual int attack(Ship& playerShip) = 0; + virtual Ship& getShip() = 0; + virtual const Ship& getShip() const = 0; + + Action::Status makeAction(const BattleField& battleField); + +protected: + virtual Ship* chooseEnemyShip(const BattleField& battleField) const = 0; + virtual std::unique_ptr chooseAction(const BattleField& battleField) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/RealPlayer.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/RealPlayer.h new file mode 100644 index 0000000..04d8b1a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/include/Player/RealPlayer.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include + +class RealPlayer : public Player { +public: + RealPlayer(const std::string& name, std::unique_ptr&& ship); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..0ff5663 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp @@ -0,0 +1,28 @@ +#include "Player/EnemyEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyEasyDifficultLvlStrategy::_rd{}; + +EnemyEasyDifficultLvlStrategy::EnemyEasyDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyEasyDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 5) { + // miss + return 0; + } else if (res > 19) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(25, 50); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/EnemyHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/EnemyHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..790cd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/EnemyHardDifficultLvlStrategy.cpp @@ -0,0 +1,31 @@ +#include "Player/EnemyHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyHardDifficultLvlStrategy::_rd{}; + +EnemyHardDifficultLvlStrategy::EnemyHardDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyHardDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 3) { + // miss + return 0; + } else if (res == 20) { + // turbo critical + multiplier = 3; + } else if (res > 15) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(30, 60); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/Player.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/Player.cpp new file mode 100644 index 0000000..5e1f83b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/Player.cpp @@ -0,0 +1,11 @@ +#include "Player/Player.h" + +Action::Status Player::makeAction(const BattleField& battleField) { + std::unique_ptr action = chooseAction(battleField); + if (action->type() == Action::Type::Attack) { + Ship* enemyShip = chooseEnemyShip(battleField); + return (*action)(this, enemyShip); + } + + return (*action)(this, nullptr); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/RealPlayer.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/RealPlayer.cpp new file mode 100644 index 0000000..b5cd4de --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Player/src/RealPlayer.cpp @@ -0,0 +1,56 @@ +#include "Player/RealPlayer.h" + +#include +#include +#include +#include +#include + +#include + +std::random_device RealPlayer::_rd{}; + +RealPlayer::RealPlayer(const std::string& name, std::unique_ptr&& ship) + : _name(name), _ship(std::move(ship)) {} + +int RealPlayer::attack(Ship& playerShip) { + std::uniform_int_distribution dice(0, 20); + const int res = dice(_seed); + int input = 0; + int damage = 0; + std::cout << "Choose Ammo: 1) Round Shot 2) Chain Shot 3) Grape Shot: "; + std::cin >> input; + + if (input == 1 && res > 4) { + damage = 50; + } else if (input == 2 && res > 7) { + damage = 80; + } else if (input == 3 && res > 10) { + damage = 100; + } else { + return 0; + } + + playerShip.takeDamage(damage); + return damage; +} + +Ship* RealPlayer::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getEnemyShip(); +} + +std::unique_ptr RealPlayer::chooseAction(const BattleField& battleField) const { + int input = 0; + std::cout << "Choose Action: 1) Attack 2) Defense 3) Escape: "; + std::cin >> input; + + if (input == 1) { + return std::make_unique(); + } + if (input == 3) { + return std::make_unique(); + } + + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..a1adb4e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp + src/ShipEasyDifficultLvlStrategy.cpp + src/ShipHardDifficultLvlStrategy.cpp + src/CargoDamageVisitor.cpp + src/ShipBuilder.cpp + src/ShipJsonBuilder.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core + nlohmann_json::nlohmann_json +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/AlcoholFactory.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/AlcoholFactory.h new file mode 100644 index 0000000..2f4928f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/AlcoholFactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include +#include + +class AlcoholFactory : public CargoFactory { +public: + std::unique_ptr create(size_t amount, int power, Alcohol::Type type) override { + return std::make_unique(amount, power, type); + } +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..afd4120 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +#include "Ship/CargoDamageVisitor.h" + +#include + +struct Cargo { + size_t amount; + + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; + virtual void accept(const CargoDamageVisitor& visitor) = 0; +}; + +struct Fruit : public Cargo { + int rottenCounter; + + Fruit(size_t amount, int rottenCounter); + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Item : public Cargo { + enum class Type { Common, Rare, Epic, Legendary }; + Type type; + + Item(size_t amount, Type type); + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Alcohol : public Cargo { + enum class Type { White, Spiced, Dark}; + + int power; + Type type; + + Alcohol(size_t amount, int power, Type type); + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/CargoDamageVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/CargoDamageVisitor.h new file mode 100644 index 0000000..6e84c58 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/CargoDamageVisitor.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class Fruit; +class Alcohol; +class Item; + +class CargoDamageVisitor { +public: + CargoDamageVisitor() = default; + virtual ~CargoDamageVisitor() = default; + CargoDamageVisitor(const CargoDamageVisitor&) = default; + CargoDamageVisitor(CargoDamageVisitor&&) = default; + CargoDamageVisitor& operator=(const CargoDamageVisitor&) = default; + CargoDamageVisitor& operator=(CargoDamageVisitor&&) = default; + + virtual void operator()(Fruit& fruit) const; + virtual void operator()(Alcohol& alcohol) const; + virtual void operator()(Item& item) const; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/CargoFactory.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/CargoFactory.h new file mode 100644 index 0000000..53c1e9f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/CargoFactory.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +class Cargo; + +template +class CargoFactory { +public: + virtual std::unique_ptr create(size_t amount, Args... args) = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/FruitFactory.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/FruitFactory.h new file mode 100644 index 0000000..c882d2a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/FruitFactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include +#include + +class FruitFactory : public CargoFactory { +public: + std::unique_ptr create(size_t amount, int rottenCounter) override { + return std::make_unique(amount, rottenCounter); + } +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ItemFactory.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ItemFactory.h new file mode 100644 index 0000000..4224e56 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ItemFactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include +#include + +class ItemFactory : public CargoFactory { +public: + std::unique_ptr create(size_t amount, Item::Type type) override { + return std::make_unique(amount, type); + } +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..88e6495 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/Ship.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include "Ship/Cargo.h" + +class PrintVisitor; +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + const std::vector>& cargoes() const; + + void increaseArmor(int armor) { _armor += armor; } + int durability() const { return _durability; } + int armor() const { return _armor; } + +private: + // Allow to be created only by std::unique_ptr + friend std::unique_ptr std::make_unique(); + friend class ShipBuilder; + Ship() = default; + void initialize(); + + bool unloadCargo(const std::string& cargoName, int amount); + void rebel(); + + Time* _time; + std::unique_ptr> _strategy; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + int _armor{0}; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipBuilder.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipBuilder.h new file mode 100644 index 0000000..8c1922a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipBuilder.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include + +class PrintVisitor; +class Time; + +class ShipBuilder { +public: + ShipBuilder(); + + [[nodiscard]] std::unique_ptr build(); + + ShipBuilder& setTime(Time* time); + ShipBuilder& setStrategy(std::unique_ptr> strategy); + ShipBuilder& setName(const std::string& name); + ShipBuilder& setCapacity(int capacity); + ShipBuilder& setCrew(int crew); + ShipBuilder& setVisitor(std::unique_ptr visitor); + ShipBuilder& setArmor(int armor); + ShipBuilder& setDurability(int durability); + +private: + std::unique_ptr _ship; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..ce7627a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h new file mode 100644 index 0000000..a5f6a64 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipJsonBuilder.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipJsonBuilder.h new file mode 100644 index 0000000..ff495c8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/include/Ship/ShipJsonBuilder.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include + +#include "Ship/ShipBuilder.h" + +using json = nlohmann::json; + +class Time; +class Ship; + +class ShipJsonBuilder : private ShipBuilder { +public: + ShipJsonBuilder(const std::filesystem::path& path); + + std::unique_ptr buildBrig(Time* time, const std::string& name); + std::unique_ptr buildFrigate(Time* time, const std::string& name); + std::unique_ptr buildGaleon(Time* time, const std::string& name); + +private: + void parseFile(const std::filesystem::path& path); + + json _shipsData; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..19e980f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/Cargo.cpp @@ -0,0 +1,54 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +Fruit::Fruit(size_t amount, int rottenCounter) + : Cargo(amount), rottenCounter(rottenCounter) { +} + +void Fruit::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +Item::Item(size_t amount, Type type) + : Cargo(amount), type(type) { +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +void Item::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +Alcohol::Alcohol(size_t amount, int power, Type type) + : Cargo(amount), power(power), type(type) {} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} + +void Alcohol::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/CargoDamageVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/CargoDamageVisitor.cpp new file mode 100644 index 0000000..6ff89e2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/CargoDamageVisitor.cpp @@ -0,0 +1,20 @@ +#include + +#include + +std::random_device CargoDamageVisitor::_rd{}; + +void CargoDamageVisitor::operator()(Fruit& fruit) const { + std::uniform_int_distribution dice(0, 5); + fruit.amount -= dice(_seed); +} + +void CargoDamageVisitor::operator()(Alcohol& alcohol) const { + std::uniform_int_distribution dice(0, 10); + alcohol.amount -= (dice(_seed) / 2); +} + +void CargoDamageVisitor::operator()(Item& item) const { + std::uniform_int_distribution dice(0, 20); + item.amount -= (dice(_seed) / 4); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..6871c94 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/Ship.cpp @@ -0,0 +1,107 @@ +#include "Ship/Ship.h" + +#include +#include + +#include +#include +#include +#include + +void Ship::initialize() { + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + if (!_strategy->handle(*this)) { + rebel(); + } +} + +void Ship::printCargo() const { + _visitor->visit(*this); +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const std::string& cargoName, int amount, StatusCode& code) noexcept { + if (!unloadCargo(cargoName, amount)) { + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const std::string& cargoName, int amount) { + if (!unloadCargo(cargoName, amount)) { + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _armor -= damage; + if (_armor >= 0) { + return; + } + + _durability += _armor; + _armor = 0; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +const std::vector>& Ship::cargoes() const { + return _cargoes; +} + +bool Ship::unloadCargo(const std::string& cargoName, int amount) { + while (amount != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount > amount) { + (*it)->amount -= amount; + return true; + } + amount -= (*it)->amount; + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipBuilder.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipBuilder.cpp new file mode 100644 index 0000000..fb77e5f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipBuilder.cpp @@ -0,0 +1,68 @@ +#include "Ship/ShipBuilder.h" + +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include +#include + +ShipBuilder::ShipBuilder() + : _ship(std::make_unique()) { + _ship->_strategy = std::make_unique(); + _ship->_visitor = std::make_unique(); +} + +std::unique_ptr ShipBuilder::build() { + if (!_ship) { + std::cout << "Builder may be use once\n"; + return nullptr; + } + + // Check mandatory fields + if (!_ship->_time || _ship->_name.empty() || _ship->_capacity == -1) { + std::cout << "Mandatory fields are not set!\n"; + return nullptr; + } + + _ship->initialize(); + return std::move(_ship); +} + +ShipBuilder& ShipBuilder::setTime(Time* time) { + _ship->_time = time; + return *this; +} + +ShipBuilder& ShipBuilder::setStrategy(std::unique_ptr> strategy) { + _ship->_strategy = std::move(strategy); + return *this; +} + +ShipBuilder& ShipBuilder::setName(const std::string& name) { + _ship->_name = name; + return *this; +} + +ShipBuilder& ShipBuilder::setCapacity(int capacity) { + _ship->_capacity = capacity; + return *this; +} + +ShipBuilder& ShipBuilder::setCrew(int crew) { + _ship->_crew = crew; + return *this; +} + +ShipBuilder& ShipBuilder::setVisitor(std::unique_ptr visitor) { + _ship->_visitor = std::move(visitor); + return *this; +} + +ShipBuilder& ShipBuilder::setArmor(int armor) { + _ship->_armor = armor; + return *this; +} + +ShipBuilder& ShipBuilder::setDurability(int durability) { + _ship->_durability = durability; + return *this; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..6d1a148 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipEasyDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..2a6815a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipHardDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipHardDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew(), status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew(), status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipJsonBuilder.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipJsonBuilder.cpp new file mode 100644 index 0000000..a9b653a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Ship/src/ShipJsonBuilder.cpp @@ -0,0 +1,48 @@ +#include "Ship/ShipJsonBuilder.h" + +#include "Ship/Ship.h" + +#include +#include +#include + +ShipJsonBuilder::ShipJsonBuilder(const std::filesystem::path& path) { + parseFile(path); +} + +std::unique_ptr ShipJsonBuilder::buildBrig(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["brige"]["capacity"]) + .setCrew(_shipsData["brige"]["crew"]) + .setArmor(_shipsData["brige"]["armor"]) + .setDurability(_shipsData["brige"]["durability"]) + .build(); +} +std::unique_ptr ShipJsonBuilder::buildFrigate(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["frigate"]["capacity"]) + .setCrew(_shipsData["frigate"]["crew"]) + .setArmor(_shipsData["frigate"]["armor"]) + .setDurability(_shipsData["frigate"]["durability"]) + .build(); +} +std::unique_ptr ShipJsonBuilder::buildGaleon(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["galeon"]["capacity"]) + .setCrew(_shipsData["galeon"]["crew"]) + .setArmor(_shipsData["galeon"]["armor"]) + .setDurability(_shipsData["galeon"]["durability"]) + .build(); +} + +void ShipJsonBuilder::parseFile(const std::filesystem::path& path) { + std::ifstream file(path); + if (!file.is_open()) { + std::cout << "Can't open a file! erno: " << strerror(errno) << '\n'; + abort(); + } + _shipsData = json::parse(file); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/include/Store/Store.h new file mode 100644 index 0000000..fbbbf9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/include/Store/Store.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class PrintVisitor; + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos, std::unique_ptr&& visitor); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + const std::vector>& cargoes() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/src/Store.cpp new file mode 100644 index 0000000..07a9e35 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/src/Store/src/Store.cpp @@ -0,0 +1,41 @@ +#include "Store/Store.h" + +#include + +Store::Store(std::vector>&& cargos, std::unique_ptr&& visitor) + : _seed(_rd()), _cargoes(std::move(cargos)), _visitor(std::move(visitor)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +const std::vector>& Store::cargoes() const { + return _cargoes; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +void Store::printCargo() const { + _visitor->visit(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder2.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder2.cpp new file mode 100644 index 0000000..1832c35 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder2.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include + +struct Time {}; +template +struct DifficultStrategy {}; +struct PrintVisitor {}; + +class Ship { +public: + void setCrew(int crew) { _crew = crew; } + void setArmor(int armor) { _armor = armor; } + void setCannons(int cannons) { _canons = cannons; } + void setDurability(int durability) { _durability = durability; } + + const std::string& name() const { return _name; } + int capacity() const { return _capacity; } + int crew() const { return _crew; } + int armor() const { return _armor; } + int canons() const { return _canons; } + int durability() const { return _durability; } + +private: + // Allow to be created only by std::unique_ptr + friend std::unique_ptr std::make_unique(); + friend class ShipBuilder; + Ship() = default; + + Time* _time{}; + std::unique_ptr> _strategy{}; + std::string _name{}; + int _capacity{-1}; + int _maxCrew{-1}; + int _crew{10}; + std::unique_ptr _visitor{}; + int _armor{0}; + int _maxArmor{-1}; + int _canons{0}; + int _maxCannons{-1}; + int _durability{100}; + int _maxDurability{-1}; +}; + +class ShipBuilder { +public: + ShipBuilder() + : _ship(std::make_unique()) {} + + [[nodiscard]] std::unique_ptr build() { + if (!_ship) { + std::cout << "Builder may be use once\n"; + return nullptr; + } + + // Check mandatory fields + if (!_ship->_time || + _ship->_name.empty() || + _ship->_capacity == -1 || + _ship->_maxCrew == -1 || + _ship->_maxArmor == -1 || + _ship->_maxCannons == -1 || + _ship->_maxDurability == -1) { + std::cout << "Mandatory fields are not set!\n"; + return nullptr; + } + + return std::move(_ship); + } + + ShipBuilder& setTime(Time* time) { + _ship->_time = time; + return *this; + } + ShipBuilder& setStrategy(std::unique_ptr> strategy) { + _ship->_strategy = std::move(strategy); + return *this; + } + ShipBuilder& setName(const std::string& name) { + _ship->_name = name; + return *this; + } + ShipBuilder& setCapacity(int capacity) { + _ship->_capacity = capacity; + return *this; + } + ShipBuilder& setMaxCrew(int maxCrew) { + _ship->_maxCrew = maxCrew; + return *this; + } + ShipBuilder& setCrew(int crew) { + _ship->_crew = crew; + return *this; + } + ShipBuilder& setVisitor(std::unique_ptr visitor) { + _ship->_visitor = std::move(visitor); + return *this; + } + ShipBuilder& setArmor(int armor) { + _ship->_armor = armor; + return *this; + } + ShipBuilder& setMaxArmor(int maxArmor) { + _ship->_maxArmor = maxArmor; + return *this; + } + ShipBuilder& setCannons(int cannons) { + _ship->_canons = cannons; + return *this; + } + ShipBuilder& setMaxCannons(int maxCannons) { + _ship->_maxCannons = maxCannons; + return *this; + } + ShipBuilder& setDurability(int durability) { + _ship->_durability = durability; + return *this; + } + ShipBuilder& setMaxDurability(int maxDurability) { + _ship->_maxDurability = maxDurability; + return *this; + } + +private: + std::unique_ptr _ship; +}; + +int main() { + auto ship = ShipBuilder().build(); + if (ship) { + std::cout << "Ship name: " << ship->name() << '\n'; + } + + Time time; + auto ship2 = ShipBuilder() + .setTime(&time) + .setName("Black Pearl") + .setCapacity(500) + .setMaxCrew(200) + .setMaxArmor(1000) + .setMaxCannons(20) + .setMaxDurability(1000) + .build(); + + if (ship2) { + std::cout << "Ship name: " << ship2->name() << '\n'; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder3.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder3.cpp new file mode 100644 index 0000000..40358a7 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder3.cpp @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include +#include + +struct Time {}; +template +struct DifficultStrategy {}; +struct PrintVisitor {}; + +class Ship { +public: + void setCrew(int crew) { _crew = crew; } + void setArmor(int armor) { _armor = armor; } + void setCannons(int cannons) { _canons = cannons; } + void setDurability(int durability) { _durability = durability; } + + const std::string& name() const { return _name; } + int capacity() const { return _capacity; } + int crew() const { return _crew; } + int armor() const { return _armor; } + int canons() const { return _canons; } + int durability() const { return _durability; } + +private: + // Allow to be created only by std::unique_ptr + friend std::unique_ptr std::make_unique(); + friend class ShipBuilder; + Ship() = default; + + Time* _time{}; + std::unique_ptr> _strategy{}; + std::string _name{}; + int _capacity{-1}; + int _maxCrew{-1}; + int _crew{10}; + std::unique_ptr _visitor{}; + int _armor{0}; + int _maxArmor{-1}; + int _canons{0}; + int _maxCannons{-1}; + int _durability{100}; + int _maxDurability{-1}; +}; + +class ShipBuilder { +public: + ShipBuilder() + : _ship(std::make_unique()) {} + + [[nodiscard]] std::unique_ptr build() { + if (!_ship) { + std::cout << "Builder may be use once\n"; + return nullptr; + } + + // Check mandatory fields + if (!_ship->_time || + _ship->_name.empty() || + _ship->_capacity == -1 || + _ship->_maxCrew == -1 || + _ship->_maxArmor == -1 || + _ship->_maxCannons == -1 || + _ship->_maxDurability == -1) { + std::cout << "Mandatory fields are not set!\n"; + return nullptr; + } + + return std::move(_ship); + } + + ShipBuilder& setTime(Time* time) { + _ship->_time = time; + return *this; + } + ShipBuilder& setStrategy(std::unique_ptr> strategy) { + _ship->_strategy = std::move(strategy); + return *this; + } + ShipBuilder& setName(const std::string& name) { + _ship->_name = name; + return *this; + } + ShipBuilder& setCapacity(int capacity) { + _ship->_capacity = capacity; + return *this; + } + ShipBuilder& setMaxCrew(int maxCrew) { + _ship->_maxCrew = maxCrew; + return *this; + } + ShipBuilder& setCrew(int crew) { + _ship->_crew = crew; + return *this; + } + ShipBuilder& setVisitor(std::unique_ptr visitor) { + _ship->_visitor = std::move(visitor); + return *this; + } + ShipBuilder& setArmor(int armor) { + _ship->_armor = armor; + return *this; + } + ShipBuilder& setMaxArmor(int maxArmor) { + _ship->_maxArmor = maxArmor; + return *this; + } + ShipBuilder& setCannons(int cannons) { + _ship->_canons = cannons; + return *this; + } + ShipBuilder& setMaxCannons(int maxCannons) { + _ship->_maxCannons = maxCannons; + return *this; + } + ShipBuilder& setDurability(int durability) { + _ship->_durability = durability; + return *this; + } + ShipBuilder& setMaxDurability(int maxDurability) { + _ship->_maxDurability = maxDurability; + return *this; + } + +private: + std::unique_ptr _ship; +}; + +class ShipJsonBuilder : private ShipBuilder { +public: + std::unique_ptr buildBrig(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(500) + .setMaxCrew(200) + .setMaxArmor(1000) + .setMaxCannons(20) + .setMaxDurability(1000) + .build(); + } + std::unique_ptr buildFrigate(); + std::unique_ptr buildGaleon(); +}; + +int main() { + auto ship = ShipBuilder().build(); + if (ship) { + std::cout << "Ship name: " << ship->name() << '\n'; + } + + Time time; + auto ship2 = ShipBuilder() + .setTime(&time) + .setName("Black Pearl") + .setCapacity(500) + .setMaxCrew(200) + .setMaxArmor(1000) + .setMaxCannons(20) + .setMaxDurability(1000) + .build(); + + if (ship2) { + std::cout << "Ship name: " << ship2->name() << '\n'; + } + + auto ship3 = ShipJsonBuilder().buildBrig(&time, "Black Widow"); + if (ship3) { + std::cout << "Ship name: " << ship3->name() << '\n'; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator.cpp new file mode 100644 index 0000000..fa1cf6e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator.cpp @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include +#include +#include + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} + +struct Cargo { + size_t amount; + + Cargo(size_t amount) + : amount(amount) {} + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; +}; + +struct Fruit : public Cargo, public TimeObserver { + static constexpr int MAX_TIME = 20; + static constexpr int BASE_PRICE = 10; + int rottenCounter; + Time* time; + + Fruit(Time* time, size_t amount, int rottenCounter) + : Cargo(amount), time(time), rottenCounter(rottenCounter) { + time->attach(this); + } + + // Rule of 5 + ~Fruit() { + time->detach(this); + } + + size_t getPrice() const override { + return (rottenCounter * BASE_PRICE) / MAX_TIME; + } + + const std::string& name() const override { + static const std::string name = "Banana"; + return name; + } + + void nextDay() override { + rottenCounter = std::max(0, rottenCounter - 1); + } +}; + +struct Item : public Cargo, public TimeObserver { + enum class Type { Common = 100, + Rare = 300, + Epic = 1000, + Legendary = 2500 }; + static constexpr int MAX_DURABILITY = 100; + Time* time; + Type type; + int durability{MAX_DURABILITY}; + + Item(Time* time, size_t amount, Type type) + : Cargo(amount), time(time), type(type) { + time->attach(this); + } + + // Rule of 5 + ~Item() { + time->detach(this); + } + + size_t getPrice() const override { + return (durability * static_cast(type)) / MAX_DURABILITY; + } + + const std::string& name() const override { + static const std::string name = "Item"; + return name; + } + + void nextDay() override { + durability = std::max(0, durability - 1); + } +}; + +struct Alcohol : public Cargo { + enum class Type { White = 100, + Spiced = 200, + Dark = 300, + Seasoned = 500 }; + static constexpr int MAX_POWER = 96; + int power; + Type type; + + Alcohol(size_t amount, int power, Type type) + : Cargo(amount), power(power), type(type) {} + + size_t getPrice() const override { + return (power * static_cast(type)) / MAX_POWER; + } + + const std::string& name() const override { + static const std::string name = "Rum"; + return name; + } +}; + +int main() { + Time time; + std::unique_ptr cargo = std::make_unique(&time, 10, Item::Type::Epic); + + for (int i = 1; i <= 15; ++i) { + std::cout << "DAY: " << i << " | Name: " << cargo->name() << " | Price: " << cargo->getPrice() << '\n'; + ++time; + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/CMakeLists.txt new file mode 100644 index 0000000..751c5ff --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +include(FetchContent) +FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG v3.11.3 +) +FetchContent_MakeAvailable(json) + +target_link_libraries(${PROJECT_NAME} + Battle + Ship + Store + Core + Player + nlohmann_json::nlohmann_json +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/main.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/main.cpp new file mode 100644 index 0000000..dd12d5f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/main.cpp @@ -0,0 +1,53 @@ +#include +#include +#include + +#include "Battle/BattleField.h" +#include "Core/BasicPrintVisitor.h" +#include "Core/FullInfoPrintVisitor.h" +#include "Core/PrettyPrintVisitor.h" +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Player/RealPlayer.h" +#include "Ship/AlcoholFactory.h" +#include "Ship/AlcoholType.h" +#include "Ship/Cargo.h" +#include "Ship/CargoDamageVisitor.h" +#include "Ship/FruitFactory.h" +#include "Ship/ItemFactory.h" +#include "Ship/ItemType.h" +#include "Ship/Ship.h" +#include "Ship/ShipBuilder.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Ship/ShipJsonBuilder.h" +#include "Ship/Valuable.h" +#include "Ship/Vulnerable.h" +#include "Store/Store.h" + +int main() { + Time time; + + auto ship = ShipBuilder() + .setTime(&time) + .setName("Black Widow") + .setCapacity(2500) + .setCrew(40) + .setStrategy(std::make_unique()) + .setVisitor(std::make_unique()) + .setArmor(100) + .setDurability(1000) + .build(); + ship->load(std::make_unique>(AlcoholFactory().create(800, 40), AlcoholType::Seasoned)); + ship->load(std::make_unique(FruitFactory().create(500), &time, 15, 15)); + ship->load(std::make_unique(FruitFactory().create(700), &time, 20, 20)); + ship->load(std::make_unique(std::make_unique>(ItemFactory().create(250), ItemType::Epic), &time, 100, 100)); + + for (size_t i = 1; i <= 15; ++i) { + std::cout << "day: " << i << '\n'; + ship->printCargo(); + ++time; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/ships.json b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/ships.json new file mode 100644 index 0000000..9b19770 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/ships.json @@ -0,0 +1,20 @@ +{ + "brige":{ + "capacity":1000, + "crew":40, + "durability":1000, + "armor":100 + }, + "frigate":{ + "capacity":1500, + "crew":70, + "durability":2000, + "armor":500 + }, + "galeon":{ + "capacity":2500, + "crew":120, + "durability":3000, + "armor":1000 + } + } \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/CMakeLists.txt new file mode 100644 index 0000000..acd8033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Battle src/Defense.cpp src/BattleField.cpp src/Attack.cpp src/Escape.cpp) + +target_include_directories(Battle PUBLIC include) + +target_link_libraries(Battle + Ship + Player +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Action.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Action.h new file mode 100644 index 0000000..f271d40 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Action.h @@ -0,0 +1,24 @@ +#pragma once + +class Player; +class Ship; + +class Action { +public: + // As you can see keeping type here, require modify a base class whenever we add a new class, this volatile an open-close principle. + // We should be able to extend code without modification already implemented one + enum class Type { + Attack, + Defense, + Escape + }; + + enum class Status { + Escaped, + Defeated, + Nothing, + }; + + virtual Status operator()(Player* player, Ship* enemyShip) = 0; + virtual Type type() const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Attack.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Attack.h new file mode 100644 index 0000000..a06cba0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Attack.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Attack : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Attack; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/BattleField.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/BattleField.h new file mode 100644 index 0000000..6196660 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/BattleField.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Ship; +class Player; + +class BattleField { +public: + BattleField(Player* player, Player* enemy); + + Ship* getPlayerShip() const; + Ship* getEnemyShip() const; + std::vector players() const; + +private: + Player* _player; + Player* _enemy; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Defense.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Defense.h new file mode 100644 index 0000000..fefd271 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Defense.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Defense : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Type::Defense; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Escape.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Escape.h new file mode 100644 index 0000000..97dc54d --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/include/Battle/Escape.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Battle/Action.h" + +#include + +class Player; +class Ship; + +class Escape : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Escape; } + +private: + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Attack.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Attack.cpp new file mode 100644 index 0000000..b3f5e8a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Attack.cpp @@ -0,0 +1,22 @@ +#include "Battle/Attack.h" + +#include +#include + +#include + +Action::Status Attack::operator()(Player* player, Ship* enemyShip) { + const int damage = player->attack(*enemyShip); + std::cout << "Player ship: " << player->getShip().name() << " attack ship: " << enemyShip->name() << '\n'; + if (damage) { + std::cout << "Dealed damage: " << damage << '\n'; + } else { + std::cout << "Missed\n"; + } + + if (enemyShip->durability() <= 0) { + return Status::Defeated; + } + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/BattleField.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/BattleField.cpp new file mode 100644 index 0000000..4e10569 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/BattleField.cpp @@ -0,0 +1,16 @@ +#include "Battle/BattleField.h" + +#include + +BattleField::BattleField(Player* player, Player* enemy) + : _player{player}, _enemy{enemy} {} + +Ship* BattleField::getPlayerShip() const { + return &_player->getShip(); +} +Ship* BattleField::getEnemyShip() const { + return &_enemy->getShip(); +} +std::vector BattleField::players() const { + return {_player, _enemy}; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Defense.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Defense.cpp new file mode 100644 index 0000000..a170c81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Defense.cpp @@ -0,0 +1,13 @@ +#include "Battle/Defense.h" + +#include +#include + +#include + +Action::Status Defense::operator()(Player* player, Ship*) { + player->getShip().increaseArmor(50); + std::cout << "Player ship: " << player->getShip().name() << " defense\n"; + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Escape.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Escape.cpp new file mode 100644 index 0000000..5b222fa --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Battle/src/Escape.cpp @@ -0,0 +1,22 @@ +#include "Battle/Escape.h" + +#include +#include + +#include + +std::random_device Escape::_rd{}; + +Action::Status Escape::operator()(Player* player, Ship*) { + std::cout << "Player ship: " << player->getShip().name() << " try to escape!\n"; + + std::uniform_int_distribution dice(0, 20); + const auto res = dice(_seed); + if (res > 12) { + std::cout << "Player escaped!\n"; + return Status::Escaped; + } + + std::cout << "Escape maneuver failed!\n"; + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/CMakeLists.txt new file mode 100644 index 0000000..9434ff8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(Battle) +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/CMakeLists.txt new file mode 100644 index 0000000..25b294b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Core src/Time.cpp src/BasicPrintVisitor.cpp src/PrettyPrintVisitor.cpp src/FullInfoPrintVisitor.cpp) + +target_include_directories(Core PUBLIC include) + +target_link_libraries(Core + Ship + Store +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/BasicPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/BasicPrintVisitor.h new file mode 100644 index 0000000..cd3406f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/BasicPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class BasicPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/DifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/DifficultLvlStrategy.h new file mode 100644 index 0000000..7c23854 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/DifficultLvlStrategy.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +template +class DifficultLvlStrategy { +public: + virtual Res handle(T&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/FullInfoPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/FullInfoPrintVisitor.h new file mode 100644 index 0000000..c932bc6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/FullInfoPrintVisitor.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class FullInfoPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; + +private: + void print() const; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/PrettyPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/PrettyPrintVisitor.h new file mode 100644 index 0000000..58dc6ad --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/PrettyPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class PrettyPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/PrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/PrintVisitor.h new file mode 100644 index 0000000..bec94c0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/PrintVisitor.h @@ -0,0 +1,11 @@ +#pragma once + +class Store; +class Ship; + +class PrintVisitor { +public: + virtual ~PrintVisitor() = default; + virtual void visit(const Store&) const = 0; + virtual void visit(const Ship&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/BasicPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/BasicPrintVisitor.cpp new file mode 100644 index 0000000..a0afe9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/BasicPrintVisitor.cpp @@ -0,0 +1,22 @@ +#include + +#include +#include +#include +#include + +void BasicPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount() << std::setw(15) << cargo->getPrice() << "\n"; + } +} + +void BasicPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount() << "\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/FullInfoPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/FullInfoPrintVisitor.cpp new file mode 100644 index 0000000..a43d164 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/FullInfoPrintVisitor.cpp @@ -0,0 +1,24 @@ +#include + +#include +#include +#include +#include + +void FullInfoPrintVisitor::visit(const Store& store) const { + std::cout << "Don't have time to implement this, sorry xD\n"; +} + +void FullInfoPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount() << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/PrettyPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/PrettyPrintVisitor.cpp new file mode 100644 index 0000000..e639a1b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/PrettyPrintVisitor.cpp @@ -0,0 +1,33 @@ +#include + +#include +#include +#include +#include + +void PrettyPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount() << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} + +void PrettyPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount() << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/CMakeLists.txt new file mode 100644 index 0000000..b266b3f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(Player src/EnemyEasyDifficultLvlStrategy.cpp src/EnemyHardDifficultLvlStrategy.cpp src/Player.cpp src/RealPlayer.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Battle + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..e44bd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/Enemy.h @@ -0,0 +1,66 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include +#include +#include + +#include +#include + +template +class Enemy : public Player { +public: + Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + std::unique_ptr> _strategy; + DamageVisitor _damageVisitor; +}; + +template +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor) + : _name(name), _ship(std::move(ship)), _strategy(std::move(strategy)), _damageVisitor(visitor) {} + +template +int Enemy::attack(Ship& playerShip) { + if (const auto damage = _strategy->handle(playerShip)) { + for (auto& cargo : playerShip.cargoes()) { + cargo->accept(_damageVisitor); + } + return damage; + } + + return 0; +} + +template +Ship* Enemy::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getPlayerShip(); +} + +template +std::unique_ptr Enemy::chooseAction(const BattleField& battleField) const { + static bool flag = true; + if (flag) { + flag = !flag; + return std::make_unique(); + } + + flag = !flag; + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..d2b7b05 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyEasyDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h new file mode 100644 index 0000000..ac01b4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyHardDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/Player.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/Player.h new file mode 100644 index 0000000..7717389 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/Player.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include + +class BattleField; +class Ship; + +class Player { +public: + virtual ~Player() = default; + virtual int attack(Ship& playerShip) = 0; + virtual Ship& getShip() = 0; + virtual const Ship& getShip() const = 0; + + Action::Status makeAction(const BattleField& battleField); + +protected: + virtual Ship* chooseEnemyShip(const BattleField& battleField) const = 0; + virtual std::unique_ptr chooseAction(const BattleField& battleField) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/RealPlayer.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/RealPlayer.h new file mode 100644 index 0000000..04d8b1a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/include/Player/RealPlayer.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include + +class RealPlayer : public Player { +public: + RealPlayer(const std::string& name, std::unique_ptr&& ship); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..0ff5663 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp @@ -0,0 +1,28 @@ +#include "Player/EnemyEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyEasyDifficultLvlStrategy::_rd{}; + +EnemyEasyDifficultLvlStrategy::EnemyEasyDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyEasyDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 5) { + // miss + return 0; + } else if (res > 19) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(25, 50); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/EnemyHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/EnemyHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..790cd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/EnemyHardDifficultLvlStrategy.cpp @@ -0,0 +1,31 @@ +#include "Player/EnemyHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyHardDifficultLvlStrategy::_rd{}; + +EnemyHardDifficultLvlStrategy::EnemyHardDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyHardDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 3) { + // miss + return 0; + } else if (res == 20) { + // turbo critical + multiplier = 3; + } else if (res > 15) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(30, 60); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/Player.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/Player.cpp new file mode 100644 index 0000000..5e1f83b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/Player.cpp @@ -0,0 +1,11 @@ +#include "Player/Player.h" + +Action::Status Player::makeAction(const BattleField& battleField) { + std::unique_ptr action = chooseAction(battleField); + if (action->type() == Action::Type::Attack) { + Ship* enemyShip = chooseEnemyShip(battleField); + return (*action)(this, enemyShip); + } + + return (*action)(this, nullptr); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/RealPlayer.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/RealPlayer.cpp new file mode 100644 index 0000000..b5cd4de --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Player/src/RealPlayer.cpp @@ -0,0 +1,56 @@ +#include "Player/RealPlayer.h" + +#include +#include +#include +#include +#include + +#include + +std::random_device RealPlayer::_rd{}; + +RealPlayer::RealPlayer(const std::string& name, std::unique_ptr&& ship) + : _name(name), _ship(std::move(ship)) {} + +int RealPlayer::attack(Ship& playerShip) { + std::uniform_int_distribution dice(0, 20); + const int res = dice(_seed); + int input = 0; + int damage = 0; + std::cout << "Choose Ammo: 1) Round Shot 2) Chain Shot 3) Grape Shot: "; + std::cin >> input; + + if (input == 1 && res > 4) { + damage = 50; + } else if (input == 2 && res > 7) { + damage = 80; + } else if (input == 3 && res > 10) { + damage = 100; + } else { + return 0; + } + + playerShip.takeDamage(damage); + return damage; +} + +Ship* RealPlayer::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getEnemyShip(); +} + +std::unique_ptr RealPlayer::chooseAction(const BattleField& battleField) const { + int input = 0; + std::cout << "Choose Action: 1) Attack 2) Defense 3) Escape: "; + std::cin >> input; + + if (input == 1) { + return std::make_unique(); + } + if (input == 3) { + return std::make_unique(); + } + + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..2c9233d --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/CMakeLists.txt @@ -0,0 +1,17 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp + src/ShipEasyDifficultLvlStrategy.cpp + src/ShipHardDifficultLvlStrategy.cpp + src/CargoDamageVisitor.cpp + src/ShipBuilder.cpp + src/ShipJsonBuilder.cpp + src/DecoratedCargo.cpp + src/Vulnerable.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core + nlohmann_json::nlohmann_json +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/AlcoholFactory.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/AlcoholFactory.h new file mode 100644 index 0000000..60a3ed6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/AlcoholFactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include +#include + +class AlcoholFactory : public CargoFactory { +public: + std::unique_ptr create(size_t amount, int power) override { + return std::make_unique(amount, power); + } +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/AlcoholType.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/AlcoholType.h new file mode 100644 index 0000000..a59d85a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/AlcoholType.h @@ -0,0 +1,6 @@ +#pragma once + +enum class AlcoholType { White = 1, + Spiced = 2, + Dark = 3, + Seasoned = 5 }; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..5183c15 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include + +#include "Ship/CargoDamageVisitor.h" + +#include + +struct Cargo { + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + virtual size_t amount() const { return _amount; } + virtual size_t& amount() { return _amount; } + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; + virtual void accept(const CargoDamageVisitor& visitor) = 0; + +protected: + Cargo() = default; + +private: + size_t _amount; +}; + +struct Fruit : public Cargo { + static constexpr int BASE_PRICE = 10; + + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Item : public Cargo { + static constexpr int BASE_PRICE = 100; + + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Alcohol : public Cargo { + static constexpr int MAX_POWER = 96; + static constexpr int BASE_PRICE = 100; + int power; + + Alcohol(size_t amount, int power); + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/CargoDamageVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/CargoDamageVisitor.h new file mode 100644 index 0000000..6e84c58 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/CargoDamageVisitor.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class Fruit; +class Alcohol; +class Item; + +class CargoDamageVisitor { +public: + CargoDamageVisitor() = default; + virtual ~CargoDamageVisitor() = default; + CargoDamageVisitor(const CargoDamageVisitor&) = default; + CargoDamageVisitor(CargoDamageVisitor&&) = default; + CargoDamageVisitor& operator=(const CargoDamageVisitor&) = default; + CargoDamageVisitor& operator=(CargoDamageVisitor&&) = default; + + virtual void operator()(Fruit& fruit) const; + virtual void operator()(Alcohol& alcohol) const; + virtual void operator()(Item& item) const; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/CargoFactory.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/CargoFactory.h new file mode 100644 index 0000000..53c1e9f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/CargoFactory.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +class Cargo; + +template +class CargoFactory { +public: + virtual std::unique_ptr create(size_t amount, Args... args) = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/DecoratedCargo.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/DecoratedCargo.h new file mode 100644 index 0000000..8e2616a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/DecoratedCargo.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include + +class DecoratedCargo : public Cargo { +public: + explicit DecoratedCargo(std::unique_ptr&& cargo); + +protected: + Cargo& cargo() { return *_cargo; } + const Cargo& cargo() const { return *_cargo; } + +private: + std::unique_ptr _cargo; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/FruitFactory.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/FruitFactory.h new file mode 100644 index 0000000..3906a69 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/FruitFactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include +#include + +class FruitFactory : public CargoFactory<> { +public: + std::unique_ptr create(size_t amount) override { + return std::make_unique(amount); + } +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ItemFactory.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ItemFactory.h new file mode 100644 index 0000000..fc949e3 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ItemFactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include +#include + +class ItemFactory : public CargoFactory<> { +public: + std::unique_ptr create(size_t amount) override { + return std::make_unique(amount); + } +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ItemType.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ItemType.h new file mode 100644 index 0000000..266429b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ItemType.h @@ -0,0 +1,6 @@ +#pragma once + +enum class ItemType { Common = 1, + Rare = 3, + Epic = 10, + Legendary = 25 }; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..88e6495 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Ship.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include "Ship/Cargo.h" + +class PrintVisitor; +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + const std::vector>& cargoes() const; + + void increaseArmor(int armor) { _armor += armor; } + int durability() const { return _durability; } + int armor() const { return _armor; } + +private: + // Allow to be created only by std::unique_ptr + friend std::unique_ptr std::make_unique(); + friend class ShipBuilder; + Ship() = default; + void initialize(); + + bool unloadCargo(const std::string& cargoName, int amount); + void rebel(); + + Time* _time; + std::unique_ptr> _strategy; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + int _armor{0}; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipBuilder.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipBuilder.h new file mode 100644 index 0000000..8c1922a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipBuilder.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include + +class PrintVisitor; +class Time; + +class ShipBuilder { +public: + ShipBuilder(); + + [[nodiscard]] std::unique_ptr build(); + + ShipBuilder& setTime(Time* time); + ShipBuilder& setStrategy(std::unique_ptr> strategy); + ShipBuilder& setName(const std::string& name); + ShipBuilder& setCapacity(int capacity); + ShipBuilder& setCrew(int crew); + ShipBuilder& setVisitor(std::unique_ptr visitor); + ShipBuilder& setArmor(int armor); + ShipBuilder& setDurability(int durability); + +private: + std::unique_ptr _ship; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..ce7627a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h new file mode 100644 index 0000000..a5f6a64 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipJsonBuilder.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipJsonBuilder.h new file mode 100644 index 0000000..ff495c8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/ShipJsonBuilder.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include + +#include "Ship/ShipBuilder.h" + +using json = nlohmann::json; + +class Time; +class Ship; + +class ShipJsonBuilder : private ShipBuilder { +public: + ShipJsonBuilder(const std::filesystem::path& path); + + std::unique_ptr buildBrig(Time* time, const std::string& name); + std::unique_ptr buildFrigate(Time* time, const std::string& name); + std::unique_ptr buildGaleon(Time* time, const std::string& name); + +private: + void parseFile(const std::filesystem::path& path); + + json _shipsData; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Valuable.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Valuable.h new file mode 100644 index 0000000..9807d57 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Valuable.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include + +template +class Valuable : public DecoratedCargo { +public: + Valuable(std::unique_ptr&& cargo, ValueType value) + : DecoratedCargo(std::move(cargo)), _value(value) { + } + + size_t amount() const override { return cargo().amount(); } + size_t& amount() override { return cargo().amount(); } + + size_t getPrice() const override { + return cargo().getPrice() * static_cast(_value); + } + + const std::string& name() const override { + return cargo().name(); + } + + void accept(const CargoDamageVisitor& visitor) override { + cargo().accept(visitor); + } + +private: + ValueType _value; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Vulnerable.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Vulnerable.h new file mode 100644 index 0000000..c7cbced --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/include/Ship/Vulnerable.h @@ -0,0 +1,29 @@ +#include "Ship/DecoratedCargo.h" + +#include + +class Time; + +class Vulnerable : public DecoratedCargo, public TimeObserver { +public: + Vulnerable(std::unique_ptr&& cargo, Time* time, int durability, int maxDurability); + + Vulnerable(const Vulnerable&) = default; + Vulnerable(Vulnerable&&) = default; + Vulnerable& operator=(const Vulnerable&) = default; + Vulnerable& operator=(Vulnerable&&) = default; + ~Vulnerable(); + + size_t amount() const override { return cargo().amount(); } + size_t& amount() override { return cargo().amount(); } + + void nextDay() override; + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; + +private: + Time* _time; + int _durability; + int _maxDurability; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..0fa653f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Cargo.cpp @@ -0,0 +1,46 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : _amount(amount) {} + +size_t Fruit::getPrice() const { + return BASE_PRICE; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +void Fruit::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Item::getPrice() const { + return BASE_PRICE; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +void Item::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +Alcohol::Alcohol(size_t amount, int power) + : Cargo(amount), power(power) {} + +size_t Alcohol::getPrice() const { + return (power * BASE_PRICE) / MAX_POWER; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} + +void Alcohol::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/CargoDamageVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/CargoDamageVisitor.cpp new file mode 100644 index 0000000..0792d32 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/CargoDamageVisitor.cpp @@ -0,0 +1,20 @@ +#include + +#include + +std::random_device CargoDamageVisitor::_rd{}; + +void CargoDamageVisitor::operator()(Fruit& fruit) const { + std::uniform_int_distribution dice(0, 5); + fruit.amount() -= dice(_seed); +} + +void CargoDamageVisitor::operator()(Alcohol& alcohol) const { + std::uniform_int_distribution dice(0, 10); + alcohol.amount() -= (dice(_seed) / 2); +} + +void CargoDamageVisitor::operator()(Item& item) const { + std::uniform_int_distribution dice(0, 20); + item.amount() -= (dice(_seed) / 4); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/DecoratedCargo.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/DecoratedCargo.cpp new file mode 100644 index 0000000..ea9f724 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/DecoratedCargo.cpp @@ -0,0 +1,8 @@ +#include "Ship/DecoratedCargo.h" + +#include + +DecoratedCargo::DecoratedCargo(std::unique_ptr&& cargo) + : _cargo(std::move(cargo)) { + assert(_cargo); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..6754047 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Ship.cpp @@ -0,0 +1,108 @@ +#include "Ship/Ship.h" + +#include +#include + +#include +#include +#include +#include + +void Ship::initialize() { + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + if (!_strategy->handle(*this)) { + rebel(); + } +} + +void Ship::printCargo() const { + _visitor->visit(*this); +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount()) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const std::string& cargoName, int amount, StatusCode& code) noexcept { + if (!unloadCargo(cargoName, amount)) { + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + std::cout << "cap: " << _capacity << " | amount: " << cargo->amount() << std::endl; + if (_capacity > cargo->amount()) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const std::string& cargoName, int amount) { + if (!unloadCargo(cargoName, amount)) { + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _armor -= damage; + if (_armor >= 0) { + return; + } + + _durability += _armor; + _armor = 0; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +const std::vector>& Ship::cargoes() const { + return _cargoes; +} + +bool Ship::unloadCargo(const std::string& cargoName, int amount) { + while (amount != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount() > amount) { + (*it)->amount() -= amount; + return true; + } + amount -= (*it)->amount(); + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipBuilder.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipBuilder.cpp new file mode 100644 index 0000000..fb77e5f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipBuilder.cpp @@ -0,0 +1,68 @@ +#include "Ship/ShipBuilder.h" + +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include +#include + +ShipBuilder::ShipBuilder() + : _ship(std::make_unique()) { + _ship->_strategy = std::make_unique(); + _ship->_visitor = std::make_unique(); +} + +std::unique_ptr ShipBuilder::build() { + if (!_ship) { + std::cout << "Builder may be use once\n"; + return nullptr; + } + + // Check mandatory fields + if (!_ship->_time || _ship->_name.empty() || _ship->_capacity == -1) { + std::cout << "Mandatory fields are not set!\n"; + return nullptr; + } + + _ship->initialize(); + return std::move(_ship); +} + +ShipBuilder& ShipBuilder::setTime(Time* time) { + _ship->_time = time; + return *this; +} + +ShipBuilder& ShipBuilder::setStrategy(std::unique_ptr> strategy) { + _ship->_strategy = std::move(strategy); + return *this; +} + +ShipBuilder& ShipBuilder::setName(const std::string& name) { + _ship->_name = name; + return *this; +} + +ShipBuilder& ShipBuilder::setCapacity(int capacity) { + _ship->_capacity = capacity; + return *this; +} + +ShipBuilder& ShipBuilder::setCrew(int crew) { + _ship->_crew = crew; + return *this; +} + +ShipBuilder& ShipBuilder::setVisitor(std::unique_ptr visitor) { + _ship->_visitor = std::move(visitor); + return *this; +} + +ShipBuilder& ShipBuilder::setArmor(int armor) { + _ship->_armor = armor; + return *this; +} + +ShipBuilder& ShipBuilder::setDurability(int durability) { + _ship->_durability = durability; + return *this; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..6d1a148 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipEasyDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..2a6815a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipHardDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipHardDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew(), status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew(), status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipJsonBuilder.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipJsonBuilder.cpp new file mode 100644 index 0000000..a9b653a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/ShipJsonBuilder.cpp @@ -0,0 +1,48 @@ +#include "Ship/ShipJsonBuilder.h" + +#include "Ship/Ship.h" + +#include +#include +#include + +ShipJsonBuilder::ShipJsonBuilder(const std::filesystem::path& path) { + parseFile(path); +} + +std::unique_ptr ShipJsonBuilder::buildBrig(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["brige"]["capacity"]) + .setCrew(_shipsData["brige"]["crew"]) + .setArmor(_shipsData["brige"]["armor"]) + .setDurability(_shipsData["brige"]["durability"]) + .build(); +} +std::unique_ptr ShipJsonBuilder::buildFrigate(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["frigate"]["capacity"]) + .setCrew(_shipsData["frigate"]["crew"]) + .setArmor(_shipsData["frigate"]["armor"]) + .setDurability(_shipsData["frigate"]["durability"]) + .build(); +} +std::unique_ptr ShipJsonBuilder::buildGaleon(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["galeon"]["capacity"]) + .setCrew(_shipsData["galeon"]["crew"]) + .setArmor(_shipsData["galeon"]["armor"]) + .setDurability(_shipsData["galeon"]["durability"]) + .build(); +} + +void ShipJsonBuilder::parseFile(const std::filesystem::path& path) { + std::ifstream file(path); + if (!file.is_open()) { + std::cout << "Can't open a file! erno: " << strerror(errno) << '\n'; + abort(); + } + _shipsData = json::parse(file); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Vulnerable.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Vulnerable.cpp new file mode 100644 index 0000000..41d6a80 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Ship/src/Vulnerable.cpp @@ -0,0 +1,32 @@ +#include "Ship/Vulnerable.h" + +#include + +#include + +Vulnerable::Vulnerable(std::unique_ptr&& cargo, Time* time, int durability, int maxDurability) + : DecoratedCargo(std::move(cargo)), _time(time), _durability(durability), _maxDurability(maxDurability) { + assert(_time); + time->attach(this); +} + +// Rule of 5 +Vulnerable::~Vulnerable() { + _time->detach(this); +} + +void Vulnerable::nextDay() { + _durability = std::max(0, _durability - 1); +} + +size_t Vulnerable::getPrice() const { + return (_durability * cargo().getPrice()) / _maxDurability; +} + +const std::string& Vulnerable::name() const { + return cargo().name(); +} + +void Vulnerable::accept(const CargoDamageVisitor& visitor) { + cargo().accept(visitor); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/include/Store/Store.h new file mode 100644 index 0000000..fbbbf9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/include/Store/Store.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class PrintVisitor; + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos, std::unique_ptr&& visitor); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + const std::vector>& cargoes() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/src/Store.cpp new file mode 100644 index 0000000..a950548 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/src/Store/src/Store.cpp @@ -0,0 +1,41 @@ +#include "Store/Store.h" + +#include + +Store::Store(std::vector>&& cargos, std::unique_ptr&& visitor) + : _seed(_rd()), _cargoes(std::move(cargos)), _visitor(std::move(visitor)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount() += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +const std::vector>& Store::cargoes() const { + return _cargoes; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +void Store::printCargo() const { + _visitor->visit(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator2.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator2.cpp new file mode 100644 index 0000000..e3e8814 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator2.cpp @@ -0,0 +1,209 @@ +#include +#include +#include +#include +#include +#include +#include + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} + +struct Cargo { + size_t amount; + + Cargo(size_t amount) + : amount(amount) {} + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; + +protected: + Cargo() = default; +}; + +class DecoratedCargo : public Cargo { +public: + explicit DecoratedCargo(std::unique_ptr&& cargo) + : _cargo(std::move(cargo)) { + assert(_cargo); + } + +protected: + Cargo& cargo() { return *_cargo; } + const Cargo& cargo() const { return *_cargo; } + +private: + std::unique_ptr _cargo; +}; + +class Vulnerable : public DecoratedCargo, public TimeObserver { +public: + Vulnerable(std::unique_ptr&& cargo, Time* time, int durability, int maxDurability) + : DecoratedCargo(std::move(cargo)), _time(time), _durability(durability), _maxDurability(maxDurability) { + assert(_time); + time->attach(this); + } + + // Rule of 5 + ~Vulnerable() { + _time->detach(this); + } + + void nextDay() override { + _durability = std::max(0, _durability - 1); + } + + size_t getPrice() const override { + return (_durability * cargo().getPrice()) / _maxDurability; + } + + const std::string& name() const override { + return cargo().name(); + } + +private: + Time* _time; + int _durability; + int _maxDurability; +}; + +template +class Valuable : public DecoratedCargo { +public: + Valuable(std::unique_ptr&& cargo, ValueType value) + : DecoratedCargo(std::move(cargo)), _value(value) { + } + + size_t getPrice() const override { + return cargo().getPrice() * static_cast(_value); + } + + const std::string& name() const override { + return cargo().name(); + } + +private: + ValueType _value; +}; + +struct Fruit : public Cargo { + static constexpr int BASE_PRICE = 10; + + using Cargo::Cargo; + + size_t getPrice() const override { + return BASE_PRICE; + } + + const std::string& name() const override { + static const std::string name = "Banana"; + return name; + } +}; + +enum class ItemType { Common = 1, + Rare = 3, + Epic = 10, + Legendary = 25 }; + +struct Item : public Cargo { + static constexpr int BASE_PRICE = 100; + + using Cargo::Cargo; + + size_t getPrice() const override { + return BASE_PRICE; + } + + const std::string& name() const override { + static const std::string name = "Item"; + return name; + } +}; + +enum class AlcoholType { White = 1, + Spiced = 2, + Dark = 3, + Seasoned = 5 }; + +struct Alcohol : public Cargo { + static constexpr int MAX_POWER = 96; + static constexpr int BASE_PRICE = 100; + int power; + + Alcohol(size_t amount, int power) + : Cargo(amount), power(power) {} + + size_t getPrice() const override { + return (power * BASE_PRICE) / MAX_POWER; + } + + const std::string& name() const override { + static const std::string name = "Rum"; + return name; + } +}; + +int main() { + Time time; + std::unique_ptr cargo = std::make_unique( + std::make_unique>( + std::make_unique(10), ItemType::Epic), + &time, 100, 100); + std::unique_ptr cargo2 = + std::make_unique>( + std::make_unique(10), ItemType::Epic); + + for (int i = 1; i <= 15; ++i) { + std::cout << "DAY: " << i << " | Name: " << cargo->name() << " | Price: " << cargo->getPrice(); + std::cout << " |-| Name: " << cargo2->name() << " | Price: " << cargo2->getPrice() << '\n'; + ++time; + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator3.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator3.cpp new file mode 100644 index 0000000..951f520 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/decorator/decorator3.cpp @@ -0,0 +1,186 @@ +#include +#include +#include +#include +#include +#include +#include + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} + +struct Cargo { + size_t amount; + + auto operator<=>(const Cargo&) const = default; + +protected: + // Only derived class can create it + Cargo(size_t amount) + : amount(amount) {} + Cargo() = default; +}; + +template +class Vulnerable : public TimeObserver { +public: + Vulnerable(Neasted neasted, Time* time, int durability, int maxDurability) + : _neasted(neasted), _time(time), _durability(durability), _maxDurability(maxDurability) { + assert(_time); + time->attach(this); + } + + // Rule of 5 + ~Vulnerable() { + _time->detach(this); + } + + void nextDay() override { + _durability = std::max(0, _durability - 1); + } + + size_t getPrice() const { + return (_durability * _neasted.getPrice()) / _maxDurability; + } + + const std::string& name() const { + return _neasted.name(); + } + +private: + Neasted _neasted; + Time* _time; + int _durability; + int _maxDurability; +}; + +template +class Valuable { +public: + Valuable(Neasted neasted, ValueType value) + : _neasted(neasted), _value(value) { + } + + size_t getPrice() const { + return _neasted.getPrice() * static_cast(_value); + } + + const std::string& name() const { + return _neasted.name(); + } + +private: + Neasted _neasted; + ValueType _value; +}; + +struct Fruit : public Cargo { + static constexpr int BASE_PRICE = 10; + + Fruit(size_t amount) + : Cargo(amount) {} + + size_t getPrice() const { + return BASE_PRICE; + } + + const std::string& name() const { + static const std::string name = "Banana"; + return name; + } +}; + +enum class ItemType { Common = 1, + Rare = 3, + Epic = 10, + Legendary = 25 }; + +struct Item : public Cargo { + static constexpr int BASE_PRICE = 100; + + Item(size_t amount) + : Cargo(amount) {} + + size_t getPrice() const { + return BASE_PRICE; + } + + const std::string& name() const { + static const std::string name = "Item"; + return name; + } +}; + +enum class AlcoholType { White = 1, + Spiced = 2, + Dark = 3, + Seasoned = 5 }; + +struct Alcohol : public Cargo { + static constexpr int MAX_POWER = 96; + static constexpr int BASE_PRICE = 100; + int power; + + Alcohol(size_t amount, int power) + : Cargo(amount), power(power) {} + + size_t getPrice() const { + return (power * BASE_PRICE) / MAX_POWER; + } + + const std::string& name() const { + static const std::string name = "Rum"; + return name; + } +}; + +int main() { + Time time; + auto cargo = Vulnerable(Valuable(Item(10), ItemType::Epic), &time, 100, 100); + auto cargo2 = Valuable(Item(10), ItemType::Epic); + + for (int i = 1; i <= 15; ++i) { + std::cout << "DAY: " << i << " | Name: " << cargo.name() << " | Price: " << cargo.getPrice(); + std::cout << " |-| Name: " << cargo2.name() << " | Price: " << cargo2.getPrice() << '\n'; + ++time; + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer.cpp new file mode 100644 index 0000000..91a5c4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include + +class Browser { +public: + struct Observer { + virtual ~Observer() = default; + virtual void browserAboutToQuit() = 0; + virtual void browserFocusChanged() = 0; + }; + + ~Browser() { + std::cout << "Browser is closing\n"; + notifyOnQuit(); + std::cout << "Browser closed\n"; + } + // Rule of 5 :) + + void attach(Observer* observer) { _observers.push_back(observer); } + void detach(Observer* observer) { std::erase(_observers, observer); } + +private: + void notifyOnQuit() const { + std::ranges::for_each(_observers, std::mem_fn(&Observer::browserAboutToQuit)); + } + void notifyOnFocusChanfed() const { + std::ranges::for_each(_observers, std::mem_fn(&Observer::browserFocusChanged)); + } + + std::vector _observers; +}; + +class TabStripManager : public Browser::Observer { +public: + TabStripManager(Browser* browser) + : _browser(browser) { + assert(browser); + browser->attach(this); + } + + ~TabStripManager() { + if (_browser) { + _browser->detach(this); + } + } + // Rule of 5 :) + + void browserAboutToQuit() override { + std::cout << "TabStripManager will close tabs\n"; + _browser = nullptr; + } + + void browserFocusChanged() override { + std::cout << "TabStripManager lost focus\n"; + } + +private: + Browser* _browser; +}; + +int main() { + std::unique_ptr browser = std::make_unique(); + TabStripManager manager(browser.get()); + browser = nullptr; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/CMakeLists.txt new file mode 100644 index 0000000..c6cd3a2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(${PROJECT_NAME} + Ship + Store + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/main.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/main.cpp new file mode 100644 index 0000000..9bd33cf --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/main.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +#include "Core/Time.h" +#include "Ship/Cargo.h" +#include "Ship/Ship.h" +#include "Store/Store.h" + +int main() { + Time time; + + std::vector> cargoes; + cargoes.push_back(std::make_unique(1'000)); + cargoes.push_back(std::make_unique(1'000)); + cargoes.push_back(std::make_unique(1'000)); + auto store = std::unique_ptr>( + [&cargoes, &time]() { + auto* store = new Store(std::move(cargoes)); + try { + time.attach(store); + } catch (...) { + abort(); + } + return store; }(), + [&time](Store* store) { + time.detach(store); + delete store; + }); + + Ship ship(&time, "Black Widow", 1000, 40); + ship.load(std::make_unique(300)); + ship.load(std::make_unique(200)); + ship.load(std::make_unique(150)); + ship.printCargo(); + + for (int i = 0; i < 10; ++i) { + ++time; + std::cout << "\nDAY: " << time.day() << "\n"; + // std::cout << "crew: " << ship.crew() << '\n'; + // ship.printCargo(); + store->printCargo(); + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/CMakeLists.txt new file mode 100644 index 0000000..482b48c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(Core) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/CMakeLists.txt new file mode 100644 index 0000000..5db9b9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(Core src/Time.cpp) + +target_include_directories(Core PUBLIC include) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..8523b82 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Ship src/Ship.cpp src/Cargo.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..3faa7e4 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +struct Cargo { + size_t amount; + + explicit Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; +}; + +struct Fruit : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Item : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Alcohol : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..3badb50 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/include/Ship/Ship.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include + +#include +#include "Ship/Cargo.h" + +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + Ship(Time* time, const std::string& name, int capacity, int crew); + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const Cargo& cargo, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const Cargo& cargo); + +private: + bool consume(const std::string& cargoName); + void rebel(); + + Time* _time; + std::string _name; + int _capacity; + int _crew; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..9c55175 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/src/Cargo.cpp @@ -0,0 +1,31 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..5fa6796 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Ship/src/Ship.cpp @@ -0,0 +1,107 @@ +#include "Ship/Ship.h" + +#include + +#include +#include +#include +#include +#include + +Ship::Ship(Time* time, const std::string& name, int capacity, int crew) + : _time(time), _name(name), _capacity(capacity), _crew(crew) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + bool shouldRebel = !consume("Rum"); + shouldRebel |= !consume("Banana"); + if (shouldRebel) { + rebel(); + } +} + +void Ship::printCargo() const { + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : _cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const Cargo& cargo, StatusCode& code) noexcept { + if (auto it = std::find_if(_cargoes.begin(), _cargoes.end(), [&cargo](const auto& item) { return *item == cargo; }); it != _cargoes.end()) { + _cargoes.erase(it); + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const Cargo& cargo) { + if (auto it = std::find_if(_cargoes.begin(), _cargoes.end(), [&cargo](const auto& item) { return *item == cargo; }); it != _cargoes.end()) { + _cargoes.erase(it); + throw std::runtime_error("Missing cargo"); + } +} + +bool Ship::consume(const std::string& cargoName) { + int left = _crew; + + while (left != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount > left) { + (*it)->amount -= left; + return true; + } + left -= (*it)->amount; + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/include/Store/Store.h new file mode 100644 index 0000000..1eb93cb --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/include/Store/Store.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/src/Store.cpp new file mode 100644 index 0000000..c5e0f60 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/src/Store/src/Store.cpp @@ -0,0 +1,47 @@ +#include "Store/Store.h" + +#include +#include + +Store::Store(std::vector>&& cargos) + : _seed(_rd()), _cargoes(std::move(cargos)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +// Shame on me, I copy-past it. But remember DRY!! +// This is only to speed up process of creating exercises, sorry :) +void Store::printCargo() const { + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : _cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer2.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer2.cpp new file mode 100644 index 0000000..8bb9990 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer2.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include + +template +struct Observer { + virtual ~Observer() = default; + virtual void update(State state) = 0; +}; + +class Browser { +public: + enum class State { + Closing, + FocusChanged + }; + using BrowserObserver = Observer; + + ~Browser() { + std::cout << "Browser is closing\n"; + notify(State::Closing); + std::cout << "Browser closed\n"; + } + // Rule of 5 :) + + void attach(BrowserObserver* observer) { _observers.push_back(observer); } + void detach(BrowserObserver* observer) { std::erase(_observers, observer); } + +private: + void notify(State state) const { + std::ranges::for_each(_observers, [state](auto* observer) { + observer->update(state); + }); + } + + std::vector _observers; +}; + +class TabStripManager : public Browser::BrowserObserver { +public: + TabStripManager(Browser* browser) + : _browser(browser) { + assert(browser); + browser->attach(this); + } + + ~TabStripManager() { + if (_browser) { + _browser->detach(this); + } + } + // Rule of 5 :) + + // dispatch message + void update(Browser::State state) override { + switch (state) { + case Browser::State::Closing: { + browserAboutToQuit(); + return; + } + case Browser::State::FocusChanged: { + browserFocusChanged(); + return; + } + } + } + +private: + void browserAboutToQuit() { + std::cout << "TabStripManager will close tabs\n"; + _browser = nullptr; + } + + void browserFocusChanged() { + std::cout << "TabStripManager lost focus\n"; + } + + Browser* _browser; +}; + +int main() { + std::unique_ptr browser = std::make_unique(); + TabStripManager manager(browser.get()); + browser = nullptr; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer3.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer3.cpp new file mode 100644 index 0000000..2abbd8b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/observer/observer3.cpp @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include +#include + +template +struct Observer { + // First, we don't need to use polymorphism, so also virtual D'tor is redundant + using OnUpdate = std::function; + + explicit Observer(OnUpdate fun) + : _onUpdate(std::move(fun)) {} + void update(const Subject& subject, State state) { + std::invoke(_onUpdate, subject, state); + } + +private: + OnUpdate _onUpdate; +}; + +class Browser; + +enum class BrowserState { + Closing, + FocusChanged +}; + +using BrowserObserver = Observer; + +class Browser { +public: + void attach(BrowserObserver* observer) { _observers.emplace(observer); } + void detach(BrowserObserver* observer) { _observers.erase(observer); } + void setFocus(bool focus) { + if (std::exchange(_hasFocus, focus) != focus) { + notify(BrowserState::FocusChanged); + } + } + bool hasFocus() const { return _hasFocus; } + +private: + void notify(BrowserState state) const { + std::ranges::for_each(_observers, [state, this](auto* observer) { + observer->update(*this, state); + }); + } + + bool _hasFocus{false}; + std::set _observers; +}; + +class Extension { +public: + explicit Extension(const std::string& name) + : _name(name) {} + // D'tor is not needed neither the rule of 5 + + // dispatch message + void update(const Browser& browser, BrowserState state) { + switch (state) { + case BrowserState::Closing: + return; + case BrowserState::FocusChanged: { + if (browser.hasFocus()) { + displayExtension(); + } + return; + } + } + } + +private: + void displayExtension() { + std::cout << "This is an extension: " << _name << '\n'; + } + + std::string _name; +}; + +int main() { + std::unique_ptr browser = std::make_unique(); + Extension extension1("A"); + Extension extension2("B"); + Extension extension3("C"); + BrowserObserver observer1([&extension1](const Browser& browser, BrowserState state) { + extension1.update(browser, state); + }); + BrowserObserver observer2([&extension2](const Browser& browser, BrowserState state) { + extension2.update(browser, state); + }); + BrowserObserver observer3([&extension3](const Browser& browser, BrowserState state) { + extension3.update(browser, state); + }); + browser->attach(&observer1); + browser->attach(&observer2); + browser->attach(&observer3); + browser->setFocus(true); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/CMakeLists.txt new file mode 100644 index 0000000..9d78935 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Refactoring) + +set(SRC_LIST + refactoring.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/README.md b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/README.md new file mode 100644 index 0000000..7b9454c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/README.md @@ -0,0 +1,10 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise + +* Try to refactore code \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/refactoring.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/refactoring.cpp new file mode 100644 index 0000000..354c36c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/refactoring.cpp @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct Credentail { + int cert_; +}; + +struct Download { + enum ConnectionType { Telnet, + Ssh }; + + std::string url_; + Credentail credentail_; + int maxMbps_; + bool cache_; + ConnectionType type_; +}; + +struct Upload { + enum ConnectionType { Telnet, + Ssh }; + + std::string url_; + Credentail credentail_; + int maxMbps_; + int size_; + ConnectionType type_; +}; + +struct RemoveFromCache { + std::string url_; +}; + +struct ClearCache { +}; + +struct Image { + std::vector bitmap_; +}; + +class Server { +public: + void handle(const Download& request, void (*callback)(bool, Image)) { + Image image; + + for (const auto& pair : cache_) { + if (pair.second == request.url_) { + image = pair.first; + callback(true, image); + return; + } + } + + if (download(request, &image)) { + if (request.cache_) { + cache_.push_back(std::pair(image, request.url_)); + } + + callback(true, image); + return; + } + + callback(false, Image{}); + } + + void handle(const Upload& request, void (*callback)(bool, Image)) { + if (request.size_ > 100) { + callback(false, Image{}); + return; + } + + Image image; + bool succes = upload(request, &image); + + callback(succes, Image{}); + } + + void handle(const RemoveFromCache& request, void (*callback)(bool, Image)) { + for (auto it = cache_.begin(); it != cache_.end(); ++it) { + if (it->second == request.url_) { + cache_.erase(it); + callback(true, Image{}); + return; + } + } + + callback(false, Image{}); + } + + void handle(const ClearCache& request, void (*callback)(bool, Image)) { + cache_.clear(); + + callback(true, Image{}); + } + +private: + bool download(const Download& request, Image* image) { + if (request.type_ == Download::Ssh && request.credentail_.cert_ != 123) { + return false; + } + if (request.type_ == Download::Telnet && request.credentail_.cert_ != 231) { + return false; + } + + // Simulate some other error + if (request.maxMbps_ % 2) { + return false; + } + image->bitmap_ = {97, 98, 99, 100, 101, 102}; + return true; + } + + bool upload(const Upload& request, const Image* image) { + if (request.type_ == Upload::Ssh && request.credentail_.cert_ != 1234) { + return false; + } + if (request.type_ == Upload::Telnet && request.credentail_.cert_ != 5432) { + return false; + } + + // Simulate some other error + if (!request.maxMbps_ % 2) { + return false; + } + return true; + } + + std::vector> cache_; +}; + +class RequestHandler { +public: + enum RequestType { Download, + Upload, + Remove, + Clear }; + + void start(Server* server) { + std::thread(&RequestHandler::run, this, server).detach(); + } + + void stop() { + stop_ = true; + } + + void pushRequest(void* request, RequestType type, void (*callback)(bool, Image)) { + requests_.push(std::tuple(request, type, callback)); + } + +private: + void run(Server* server) { + while (!stop_) { + auto tuple = waitForRequest(); + switch (std::get<1>(tuple)) { + case Download: + server->handle(*((::Download*)(std::get<0>(tuple))), std::get<2>(tuple)); + break; + case Upload: + server->handle(*((::Upload*)(std::get<0>(tuple))), std::get<2>(tuple)); + break; + case Remove: + server->handle(*((RemoveFromCache*)(std::get<0>(tuple))), std::get<2>(tuple)); + break; + case Clear: + server->handle(*((ClearCache*)(std::get<0>(tuple))), std::get<2>(tuple)); + break; + } + } + } + + std::tuple waitForRequest() { + while (requests_.empty() || !stop_) { + } + + auto pair = requests_.front(); + requests_.pop(); + + return pair; + } + + bool stop_; + std::queue> requests_; +}; + +int main() { + Server server; + RequestHandler handler; + + handler.start(&server); + + Download d{"sth.png", 123, 100, true, Download::Ssh}; + handler.pushRequest((void*)(&d), + RequestHandler::Download, + [](bool succes, Image image) { + if (succes) { + for (auto el : image.bitmap_) { + std::cout << el << ' '; + } + std::cout << '\n'; + } else { + std::cout << "FAILED!\n"; + } + }); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + handler.stop(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/soultions/refactoring1.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/soultions/refactoring1.cpp new file mode 100644 index 0000000..6ce7d45 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/soultions/refactoring1.cpp @@ -0,0 +1,234 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct Credentail { + int cert_; +}; + +struct Download { + enum class ConnectionType { Telnet, + Ssh }; + + std::string url_; + Credentail credentail_; + int maxMbps_; + bool cache_; + ConnectionType type_; +}; + +struct Upload { + enum class ConnectionType { Telnet, + Ssh }; + + std::string url_; + Credentail credentail_; + int maxMbps_; + int size_; + ConnectionType type_; +}; + +struct RemoveFromCache { + std::string url_; +}; + +struct ClearCache { +}; + +struct Image { + std::vector bitmap_; +}; + +class Server { +public: + enum class ErrorCode { + Ok, + WrongUrl, + CanNotConnect, + WrongCredential, + MaximumSizeExceeded, + MissingImage, + }; + using CallbackType = void (*)(ErrorCode, Image); + + void handle(const Download& request, CallbackType callback) { + if (const auto it = findImage(request.url_); it != std::cend(cache_)) { + callback(ErrorCode::Ok, it->first); + return; + } + + Image img; + const auto ec = download(request, img); + if (ec == ErrorCode::Ok) { + if (request.cache_) { + cache_.emplace_back(img, request.url_); + } + } + + callback(ec, img); + } + + void handle(const Upload& request, CallbackType callback) const { + if (request.size_ > 100) { + callback(ErrorCode::MaximumSizeExceeded, Image{}); + return; + } + + Image img; + callback(upload(request, img), img); + } + + void handle(const RemoveFromCache& request, CallbackType callback) { + if (const auto it = findImage(request.url_); it != std::cend(cache_)) { + cache_.erase(it); + callback(ErrorCode::Ok, Image{}); + return; + } + + callback(ErrorCode::MissingImage, Image{}); + } + + void handle(const ClearCache& request, CallbackType callback) { + cache_.clear(); + callback(ErrorCode::Ok, Image{}); + } + +private: + std::vector>::const_iterator findImage(const std::string& url) const { + return std::find_if(cbegin(cache_), cend(cache_), + [url](const auto& pair) { + const auto& [image, this_url] = pair; + return this_url == url; + }); + } + + ErrorCode download(const Download& request, Image& image) const { + if (request.type_ == Download::ConnectionType::Ssh && request.credentail_.cert_ != 123) { + return ErrorCode::WrongCredential; + } + if (request.type_ == Download::ConnectionType::Telnet && request.credentail_.cert_ != 231) { + return ErrorCode::CanNotConnect; + } + + // Simulate some other error + if (request.maxMbps_ % 2) { + return ErrorCode::WrongUrl; + } + image.bitmap_ = {97, 98, 99, 100, 101, 102}; + return ErrorCode::Ok; + } + + ErrorCode upload(const Upload& request, const Image& image) const { + if (request.type_ == Upload::ConnectionType::Ssh && request.credentail_.cert_ != 1234) { + return ErrorCode::WrongCredential; + } + if (request.type_ == Upload::ConnectionType::Telnet && request.credentail_.cert_ != 5432) { + return ErrorCode::CanNotConnect; + } + + // Simulate some other error + if (!request.maxMbps_ % 2) { + return ErrorCode::WrongUrl; + } + return ErrorCode::Ok; + } + + std::vector> cache_; +}; + +class RequestHandler { +public: + using RequestType = std::variant; + + void start(Server* server) { + std::thread(&RequestHandler::run, this, server).detach(); + } + + void stop() { + stop_ = true; + cv_.notify_one(); + } + + void pushRequest(const RequestType& request, Server::CallbackType callback) { + { + std::lock_guard lock(m_); + requests_.emplace(request, callback); + } + cv_.notify_one(); + } + +private: + using QueueType = std::pair; + + void run(Server* server) { + while (!stop_) { + const auto res = waitForRequest(); + if (!res) { + return; + } + + const auto [request, callback] = *res; + switch (request.index()) { + case 0: + server->handle(std::get(request), callback); + break; + case 1: + server->handle(std::get(request), callback); + break; + case 2: + server->handle(std::get(request), callback); + break; + case 3: + server->handle(std::get(request), callback); + break; + } + } + } + + std::optional waitForRequest() { + std::unique_lock lk(m_); + cv_.wait(lk, [&]() { return !requests_.empty() || stop_; }); + if (stop_) { + return std::nullopt; + } + auto pair = requests_.front(); + requests_.pop(); + + return pair; + } + + std::mutex m_; + std::condition_variable cv_; + std::atomic stop_{false}; + std::queue requests_; +}; + +int main() { + Server server; + RequestHandler handler; + + handler.start(&server); + + handler.pushRequest(Download{"sth.png", 123, 100, true, Download::ConnectionType::Ssh}, + [](Server::ErrorCode ec, Image image) { + if (ec == Server::ErrorCode::Ok) { + for (auto el : image.bitmap_) { + std::cout << el << ' '; + } + std::cout << '\n'; + } else { + std::cout << "FAILED!\n"; + } + }); + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + handler.stop(); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/soultions/refactoring2.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/soultions/refactoring2.cpp new file mode 100644 index 0000000..62017d6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/refactoring/soultions/refactoring2.cpp @@ -0,0 +1,261 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct Image { + std::vector bitmap_; +}; + +struct Credentail { + int cert_; +}; + +struct DownloadRequest { + enum class ConnectionType { Telnet, + Ssh }; + + std::string url_; + Credentail credentail_; + int maxMbps_; + bool cache_; + ConnectionType type_; +}; + +struct UploadRequest { + enum class ConnectionType { Telnet, + Ssh }; + + std::string url_; + Credentail credentail_; + int maxMbps_; + int size_; + ConnectionType type_; +}; + +class Command { +public: + enum class ErrorCode { + Ok, + WrongUrl, + CanNotConnect, + WrongCredential, + MaximumSizeExceeded, + MissingImage, + }; + + class Delegate { + public: + virtual ~Delegate() = default; + virtual ErrorCode removeFromCache(const std::string& url) = 0; + virtual void clearCache() = 0; + virtual void addToCache(const std::vector& data, const std::string& url) = 0; + virtual ErrorCode download(std::vector& data, const DownloadRequest& request) const = 0; + virtual ErrorCode upload(const std::vector& data, const UploadRequest& request) const = 0; + }; + + explicit Command(Delegate* delegate) + : delegate_(delegate) {} + + // Rule of 5! + virtual ~Command() = default; + Command(const Command&) = default; + Command(Command&&) = default; + Command& operator=(const Command&) = default; + Command& operator=(Command&&) = default; + + virtual void operator()() const = 0; + +protected: + Delegate* delegate_; +}; + +class DownloadImageCommand : public Command { +public: + using CallbackType = void (*)(ErrorCode, Image); + + ~DownloadImageCommand() override = default; + + DownloadImageCommand(Delegate* delegate, CallbackType callback, const DownloadRequest& request) + : Command(delegate), callback_(callback), request_(request) {} + + void operator()() const override { + std::vector data; + if (auto ec = delegate_->download(data, request_); ec == Command::ErrorCode::Ok) { + // Do some conversion on vector + if (request_.cache_) { + delegate_->addToCache(data, request_.url_); + } + Image image{data}; + callback_(ec, std::move(image)); + } else { + callback_(ec, Image{}); + } + }; + +private: + CallbackType callback_; + DownloadRequest request_; +}; + +class UploadImageCommand : public Command { +public: + using CallbackType = void (*)(ErrorCode); + + ~UploadImageCommand() override = default; + + UploadImageCommand(Delegate* delegate, const Image& image, CallbackType callback, const UploadRequest& request) + : Command(delegate), image_(image), callback_(callback), request_(request) {} + + void operator()() const override { + callback_(delegate_->upload(image_.bitmap_, request_)); + }; + +private: + Image image_; + CallbackType callback_; + UploadRequest request_; +}; + +class Server : public Command::Delegate { +public: + ~Server() override = default; + + Command::ErrorCode removeFromCache(const std::string& url) override { + if (const auto it = findFile(url); it != std::cend(cache_)) { + cache_.erase(it); + return Command::ErrorCode::Ok; + } + + return Command::ErrorCode::MissingImage; + } + + void clearCache() override { + cache_.clear(); + } + + void addToCache(const std::vector& data, const std::string& url) override { + cache_.emplace_back(data, url); + } + + Command::ErrorCode download(std::vector& data, const DownloadRequest& request) const override { + if (request.type_ == DownloadRequest::ConnectionType::Ssh && request.credentail_.cert_ != 123) { + return Command::ErrorCode::WrongCredential; + } + if (request.type_ == DownloadRequest::ConnectionType::Telnet && request.credentail_.cert_ != 231) { + return Command::ErrorCode::CanNotConnect; + } + + // Simulate some other error + if (request.maxMbps_ % 2) { + return Command::ErrorCode::WrongUrl; + } + + data = {97, 98, 99, 100, 101, 102}; + return Command::ErrorCode::Ok; + } + + Command::ErrorCode upload(const std::vector& data, const UploadRequest& request) const override { + if (request.type_ == UploadRequest::ConnectionType::Ssh && request.credentail_.cert_ != 1234) { + return Command::ErrorCode::WrongCredential; + } + if (request.type_ == UploadRequest::ConnectionType::Telnet && request.credentail_.cert_ != 5432) { + return Command::ErrorCode::CanNotConnect; + } + + // Simulate some other error + if (!request.maxMbps_ % 2) { + return Command::ErrorCode::WrongUrl; + } + return Command::ErrorCode::Ok; + } + +private: + std::vector, std::string>>::const_iterator findFile(const std::string& url) const { + return std::find_if(cbegin(cache_), cend(cache_), + [url](const auto& pair) { + const auto& [data, this_url] = pair; + return this_url == url; + }); + } + + std::vector, std::string>> cache_; +}; + +class RequestHandler { +public: + void start() { + std::thread(&RequestHandler::run, this).detach(); + } + + void stop() { + stop_ = true; + cv_.notify_one(); + } + + void pushRequest(std::unique_ptr command) { + { + std::lock_guard lock(m_); + requests_.push(std::move(command)); + } + cv_.notify_one(); + } + +private: + void run() { + while (!stop_) { + const auto request = waitForRequest(); + if (!request || !*request) { + return; + } + + (**request)(); + } + } + + std::optional> waitForRequest() { + std::unique_lock lk(m_); + cv_.wait(lk, [&]() { return !requests_.empty() || stop_; }); + if (stop_) { + return std::nullopt; + } + + std::unique_ptr request = std::move(requests_.front()); + requests_.pop(); + + return std::move(request); + } + + std::mutex m_; + std::condition_variable cv_; + std::atomic stop_{false}; + std::queue> requests_; +}; + +int main() { + Server server; + RequestHandler handler; + + handler.start(); + handler.pushRequest(std::make_unique( + &server, + [](Command::ErrorCode ec, Image img) { + if (ec == Command::ErrorCode::Ok) { + std::copy(cbegin(img.bitmap_), cend(img.bitmap_), std::ostream_iterator(std::cout, " ")); + std::cout << '\n'; + } else { + std::cout << "Sth went wrong!\n"; + } + }, + DownloadRequest{"Sth123", Credentail{123}, 200, true, DownloadRequest::ConnectionType::Ssh})); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + handler.stop(); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy.cpp new file mode 100644 index 0000000..16be8a6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include + +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + virtual void fire() = 0; + virtual void draw() = 0; + virtual int getDamage() const = 0; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; + +class FireStrategy { +public: + virtual void fire(const Ammunition& ammunition) = 0; +}; + +class SDLFireStrategy : public FireStrategy { +public: + void fire(const Ammunition& ammunition) override { + std::cout << "SDL Deal: " << ammunition.getDamage() << " damage!" << '\n'; + } +}; + +class WAMFireStrategy : public FireStrategy { +public: + void fire(const Ammunition& ammunition) override { + std::cout << "WAM Deal: " << ammunition.getDamage() << " damage!" << '\n'; + } +}; + +class DrawStrategy { +public: + virtual void draw(const Ammunition& ammunition) = 0; +}; + +class OpenGLDrawStrategy : public DrawStrategy { +public: + void draw(const Ammunition& ammunition) override { + std::cout << "OpenGL Ammunition: " << ammunition.amount() << '\n'; + } +}; + +class MetalDrawStrategy : public DrawStrategy { +public: + void draw(const Ammunition& ammunition) override { + std::cout << "Metal Ammunition: " << ammunition.amount() << '\n'; + } +}; + +class RoundShot : public Ammunition { +public: + RoundShot(size_t amount, std::unique_ptr&& fireStrategy, std::unique_ptr&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 10; } + +private: + std::unique_ptr _fireStrategy; + std::unique_ptr _drawStrategy; +}; + +class ChainShot : public Ammunition { +public: + ChainShot(size_t amount, std::unique_ptr&& fireStrategy, std::unique_ptr&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 15; } + +private: + std::unique_ptr _fireStrategy; + std::unique_ptr _drawStrategy; +}; + +class GrapeShot : public Ammunition { +public: + GrapeShot(size_t amount, std::unique_ptr&& fireStrategy, std::unique_ptr&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 20; } + +private: + std::unique_ptr _fireStrategy; + std::unique_ptr _drawStrategy; +}; + +int main() { + std::unique_ptr grapeShot = std::make_unique( + 100, std::make_unique(), std::make_unique()); + + grapeShot->fire(); + grapeShot->draw(); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/CMakeLists.txt new file mode 100644 index 0000000..4b33b70 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(${PROJECT_NAME} + Ship + Store + Core + Player +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/main.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/main.cpp new file mode 100644 index 0000000..247c2fb --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/main.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Ship/Cargo.h" +#include "Ship/Ship.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Store/Store.h" + +int main() { + Time time; + + Ship ship(&time, std::make_unique(), "Black Widow", 1000, 40); + ship.load(std::make_unique(300)); + ship.load(std::make_unique(200)); + ship.load(std::make_unique(150)); + ship.printCargo(); + + for (int i = 0; i < 10; ++i) { + ++time; + std::cout << "\nDAY: " << time.day() << "\n"; + std::cout << "crew: " << ship.crew() << '\n'; + ship.printCargo(); + } + + std::cout << "\n\n****************************************************\n"; + auto ship2 = std::make_unique(&time, std::make_unique(), "Queens Anne revenge", 1000, 40); + Enemy enemy("Enemy1", std::move(ship2), std::make_unique()); + + for (int i = 0; i < 15; ++i) { + enemy.attack(ship); + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/CMakeLists.txt new file mode 100644 index 0000000..c29ff6c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/CMakeLists.txt new file mode 100644 index 0000000..5db9b9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(Core src/Time.cpp) + +target_include_directories(Core PUBLIC include) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/DifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/DifficultLvlStrategy.h new file mode 100644 index 0000000..7c23854 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/DifficultLvlStrategy.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +template +class DifficultLvlStrategy { +public: + virtual Res handle(T&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/CMakeLists.txt new file mode 100644 index 0000000..f96d5d4 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Player src/Enemy.cpp src/EnemyEasyDifficultLvlStrategy.cpp src/EnemyHardDifficultLvlStrategy.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..840bc42 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/Enemy.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include +#include + +class Ship; + +class Enemy { +public: + Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy); + + void attack(Ship& playerShip); + +private: + std::string _name; + std::unique_ptr _ship; + std::unique_ptr> _strategy; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..d2b7b05 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyEasyDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h new file mode 100644 index 0000000..ac01b4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyHardDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/Enemy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/Enemy.cpp new file mode 100644 index 0000000..7cbbe29 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/Enemy.cpp @@ -0,0 +1,19 @@ +#include "Player/Enemy.h" + +#include + +#include +#include +#include + +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy) + : _name(name), _ship(std::move(ship)), _strategy(std::move(strategy)) {} + +void Enemy::attack(Ship& playerShip) { + std::cout << "Player: " << _name << " attack ship: " << playerShip.name() << '\n'; + if (const auto damage = _strategy->handle(playerShip)) { + std::cout << "Dealed damage: " << damage << '\n'; + } else { + std::cout << "Missed\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..0ff5663 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp @@ -0,0 +1,28 @@ +#include "Player/EnemyEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyEasyDifficultLvlStrategy::_rd{}; + +EnemyEasyDifficultLvlStrategy::EnemyEasyDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyEasyDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 5) { + // miss + return 0; + } else if (res > 19) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(25, 50); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/EnemyHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/EnemyHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..790cd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Player/src/EnemyHardDifficultLvlStrategy.cpp @@ -0,0 +1,31 @@ +#include "Player/EnemyHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyHardDifficultLvlStrategy::_rd{}; + +EnemyHardDifficultLvlStrategy::EnemyHardDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyHardDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 3) { + // miss + return 0; + } else if (res == 20) { + // turbo critical + multiplier = 3; + } else if (res > 15) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(30, 60); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..6d03561 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/CMakeLists.txt @@ -0,0 +1,11 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp + src/ShipEasyDifficultLvlStrategy.cpp + src/ShipHardDifficultLvlStrategy.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..7ed1893 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +#include + +struct Cargo { + size_t amount; + + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; +}; + +struct Fruit : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Item : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Alcohol : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..e92d9c9 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/Ship.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include "Ship/Cargo.h" + +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew); + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + +private: + bool unloadCargo(const std::string& cargoName, int amount); + void rebel(); + + Time* _time; + std::unique_ptr> _strategy; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..ce7627a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h new file mode 100644 index 0000000..a5f6a64 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..9c55175 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/Cargo.cpp @@ -0,0 +1,31 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..2e60865 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/Ship.cpp @@ -0,0 +1,108 @@ +#include "Ship/Ship.h" + +#include + +#include +#include +#include +#include +#include + +Ship::Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew) + : _time(time), _strategy(std::move(strategy)), _name(name), _capacity(capacity), _crew(crew) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + if (!_strategy->handle(*this)) { + rebel(); + } +} + +void Ship::printCargo() const { + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : _cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const std::string& cargoName, int amount, StatusCode& code) noexcept { + if (!unloadCargo(cargoName, amount)) { + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const std::string& cargoName, int amount) { + if (!unloadCargo(cargoName, amount)) { + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _durability -= damage; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +bool Ship::unloadCargo(const std::string& cargoName, int amount) { + while (amount != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount > amount) { + (*it)->amount -= amount; + return true; + } + amount -= (*it)->amount; + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..6d1a148 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipEasyDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/ShipHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/ShipHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..2a6815a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Ship/src/ShipHardDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipHardDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew(), status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew(), status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/include/Store/Store.h new file mode 100644 index 0000000..1eb93cb --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/include/Store/Store.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/src/Store.cpp new file mode 100644 index 0000000..41d32fe --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/src/Store/src/Store.cpp @@ -0,0 +1,48 @@ +#include "Store/Store.h" + +#include +#include + +Store::Store(std::vector>&& cargos) + : _seed(_rd()), _cargoes(std::move(cargos)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +// Shame on me, I copy-past it. But remember DRY!! +// This is only to speed up process of creating exercises, sorry :) +void Store::printCargo() const { + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : _cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy2.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy2.cpp new file mode 100644 index 0000000..6c46ef6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy2.cpp @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include +#include + +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + virtual void fire() = 0; + virtual void draw() = 0; + virtual int getDamage() const = 0; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; + +class ChainShot; +class RoundShot; +class GrapeShot; + +class FireStrategy { +public: + virtual void fire(const ChainShot& shot) = 0; + virtual void fire(const RoundShot& shot) = 0; + virtual void fire(const GrapeShot& shot) = 0; +}; + +class SDLFireStrategy : public FireStrategy { +public: + void fire(const ChainShot& shot) override; + void fire(const RoundShot& shot) override; + void fire(const GrapeShot& shot) override; +}; + +class WAMFireStrategy : public FireStrategy { +public: + void fire(const ChainShot& shot) override; + void fire(const RoundShot& shot) override; + void fire(const GrapeShot& shot) override; +}; + +class DrawStrategy { +public: + virtual void draw(const ChainShot& shot) = 0; + virtual void draw(const RoundShot& shot) = 0; + virtual void draw(const GrapeShot& shot) = 0; +}; + +class OpenGLDrawStrategy : public DrawStrategy { +public: + void draw(const ChainShot& shot) override; + void draw(const RoundShot& shot) override; + void draw(const GrapeShot& shot) override; +}; + +class MetalDrawStrategy : public DrawStrategy { +public: + void draw(const ChainShot& shot) override; + void draw(const RoundShot& shot) override; + void draw(const GrapeShot& shot) override; +}; + +class RoundShot : public Ammunition { +public: + RoundShot(size_t amount, std::unique_ptr&& fireStrategy, std::unique_ptr&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 10; } + +private: + std::unique_ptr _fireStrategy; + std::unique_ptr _drawStrategy; +}; + +class ChainShot : public Ammunition { +public: + ChainShot(size_t amount, std::unique_ptr&& fireStrategy, std::unique_ptr&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 15; } + +private: + std::unique_ptr _fireStrategy; + std::unique_ptr _drawStrategy; +}; + +class GrapeShot : public Ammunition { +public: + GrapeShot(size_t amount, std::unique_ptr&& fireStrategy, std::unique_ptr&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 20; } + +private: + std::unique_ptr _fireStrategy; + std::unique_ptr _drawStrategy; +}; + +void SDLFireStrategy::fire(const ChainShot& shot) { + std::cout << "SDL Chain Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} +void SDLFireStrategy::fire(const RoundShot& shot) { + std::cout << "SDL Round Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} +void SDLFireStrategy::fire(const GrapeShot& shot) { + std::cout << "SDL Grape Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} + +void WAMFireStrategy::fire(const ChainShot& shot) { + std::cout << "WAM Chain Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} +void WAMFireStrategy::fire(const RoundShot& shot) { + std::cout << "WAM Round Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} +void WAMFireStrategy::fire(const GrapeShot& shot) { + std::cout << "WAM Grape Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} + +void OpenGLDrawStrategy::draw(const ChainShot& shot) { + std::cout << "OpenGL Chain Shot: " << shot.amount() << '\n'; +} +void OpenGLDrawStrategy::draw(const RoundShot& shot) { + std::cout << "OpenGL Round Shot: " << shot.amount() << '\n'; +} +void OpenGLDrawStrategy::draw(const GrapeShot& shot) { + std::cout << "OpenGL Grape Shot: " << shot.amount() << '\n'; +} + +void MetalDrawStrategy::draw(const ChainShot& shot) { + std::cout << "Metal Chain Shot: " << shot.amount() << '\n'; +} +void MetalDrawStrategy::draw(const RoundShot& shot) { + std::cout << "Metal Round Shot: " << shot.amount() << '\n'; +} +void MetalDrawStrategy::draw(const GrapeShot& shot) { + std::cout << "Metal Grape Shot: " << shot.amount() << '\n'; +} + +int main() { + std::unique_ptr grapeShot = std::make_unique( + 100, std::make_unique(), std::make_unique()); + + grapeShot->fire(); + grapeShot->draw(); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy3.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy3.cpp new file mode 100644 index 0000000..8160319 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy3.cpp @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include +#include +#include + +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + virtual void fire() = 0; + virtual void draw() = 0; + virtual int getDamage() const = 0; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; + +class ChainShot; +class RoundShot; +class GrapeShot; + +template +class FireStrategy { +public: + virtual void fire(const T& shot) = 0; +}; + +class SDLFireRoundShotStrategy : public FireStrategy { +public: + void fire(const RoundShot& shot) override; +}; + +class SDLFireChainShotStrategy : public FireStrategy { +public: + void fire(const ChainShot& shot) override; +}; + +class SDLFireGrapeShotStrategy : public FireStrategy { +public: + void fire(const GrapeShot& shot) override; +}; + +class WAMFireRoundShotStrategy : public FireStrategy { +public: + void fire(const RoundShot& shot) override; +}; + +class WAMFirChainShotStrategy : public FireStrategy { +public: + void fire(const ChainShot& shot) override; +}; + +class WAMFireGrapeShotStrategy : public FireStrategy { +public: + void fire(const GrapeShot& shot) override; +}; + +template +class DrawStrategy { +public: + virtual void draw(const T& shot) = 0; +}; + +class OpenGLDrawRoundShotStrategy : public DrawStrategy { +public: + void draw(const RoundShot& shot) override; +}; + +class OpenGLDrawChainShotStrategy : public DrawStrategy { +public: + void draw(const ChainShot& shot) override; +}; + +class OpenGLDrawGrapeShotStrategy : public DrawStrategy { +public: + void draw(const GrapeShot& shot) override; +}; + +class MetalDrawRoundShotStrategy : public DrawStrategy { +public: + void draw(const RoundShot& shot) override; +}; + +class MetalDrawChainShotStrategy : public DrawStrategy { +public: + void draw(const ChainShot& shot) override; +}; + +class MetalDrawGrapeShotStrategy : public DrawStrategy { +public: + void draw(const GrapeShot& shot) override; +}; + +class RoundShot : public Ammunition { +public: + RoundShot(size_t amount, std::unique_ptr>&& fireStrategy, std::unique_ptr>&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 10; } + +private: + std::unique_ptr> _fireStrategy; + std::unique_ptr> _drawStrategy; +}; + +class ChainShot : public Ammunition { +public: + ChainShot(size_t amount, std::unique_ptr>&& fireStrategy, std::unique_ptr>&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 15; } + +private: + std::unique_ptr> _fireStrategy; + std::unique_ptr> _drawStrategy; +}; + +class GrapeShot : public Ammunition { +public: + GrapeShot(size_t amount, std::unique_ptr>&& fireStrategy, std::unique_ptr>&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 20; } + +private: + std::unique_ptr> _fireStrategy; + std::unique_ptr> _drawStrategy; +}; + +void SDLFireChainShotStrategy::fire(const ChainShot& shot) { + std::cout << "SDL Chain Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} +void SDLFireRoundShotStrategy::fire(const RoundShot& shot) { + std::cout << "SDL Round Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} +void SDLFireGrapeShotStrategy::fire(const GrapeShot& shot) { + std::cout << "SDL Grape Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} + +void WAMFirChainShotStrategy::fire(const ChainShot& shot) { + std::cout << "WAM Chain Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} +void WAMFireRoundShotStrategy::fire(const RoundShot& shot) { + std::cout << "WAM Round Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} +void WAMFireGrapeShotStrategy::fire(const GrapeShot& shot) { + std::cout << "WAM Grape Shot Deal: " << shot.getDamage() << " damage!" << '\n'; +} + +void OpenGLDrawChainShotStrategy::draw(const ChainShot& shot) { + std::cout << "OpenGL Chain Shot: " << shot.amount() << '\n'; +} +void OpenGLDrawRoundShotStrategy::draw(const RoundShot& shot) { + std::cout << "OpenGL Round Shot: " << shot.amount() << '\n'; +} +void OpenGLDrawGrapeShotStrategy::draw(const GrapeShot& shot) { + std::cout << "OpenGL Grape Shot: " << shot.amount() << '\n'; +} + +void MetalDrawChainShotStrategy::draw(const ChainShot& shot) { + std::cout << "Metal Chain Shot: " << shot.amount() << '\n'; +} +void MetalDrawRoundShotStrategy::draw(const RoundShot& shot) { + std::cout << "Metal Round Shot: " << shot.amount() << '\n'; +} +void MetalDrawGrapeShotStrategy::draw(const GrapeShot& shot) { + std::cout << "Metal Grape Shot: " << shot.amount() << '\n'; +} + +int main() { + std::unique_ptr grapeShot = std::make_unique( + 100, std::make_unique(), std::make_unique()); + + grapeShot->fire(); + grapeShot->draw(); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/CMakeLists.txt new file mode 100644 index 0000000..9d2ce9e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(${PROJECT_NAME} + Battle + Ship + Store + Core + Player +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/main.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/main.cpp new file mode 100644 index 0000000..01bfde8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/main.cpp @@ -0,0 +1,72 @@ +#include +#include +#include + +#include "Battle/BattleField.h" +#include "Core/BasicPrintVisitor.h" +#include "Core/PrettyPrintVisitor.h" +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Player/RealPlayer.h" +#include "Ship/Cargo.h" +#include "Ship/CargoDamageVisitor.h" +#include "Ship/Ship.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Store/Store.h" + +int main() { + Time time; + std::vector> cargoes; + cargoes.push_back(std::make_unique(1'000)); + cargoes.push_back(std::make_unique(1'000)); + cargoes.push_back(std::make_unique(1'000)); + auto store = std::unique_ptr>( + [&cargoes, &time]() { + auto* store = new Store(std::move(cargoes), std::make_unique()); + try { + time.attach(store); + } catch (...) { + abort(); + } + return store; }(), + [&time](Store* store) { + time.detach(store); + delete store; + }); + + Ship ship(&time, std::make_unique(), "Black Widow", 1000, 40, std::make_unique()); + ship.load(std::make_unique(300)); + ship.load(std::make_unique(200)); + ship.load(std::make_unique(150)); + + std::cout << "Ship\n"; + ship.printCargo(); + std::cout << "\nStore\n"; + store->printCargo(); + + std::cout << "\n\n****************************************************\n"; + auto ship2 = std::make_unique(&time, std::make_unique(), "Queens Anne revenge", 1000, 40, std::make_unique()); + Enemy enemy("Enemy1", std::move(ship2), std::make_unique(), CargoDamageVisitor{}); + + auto ship3 = std::make_unique(&time, std::make_unique(), "Black Pearl", 1000, 40, std::make_unique()); + RealPlayer user("Mateusz", std::move(ship3)); + + BattleField battefield{&user, &enemy}; + while (true) { + for (auto* player : battefield.players()) { + std::cout << "-------------------------------------------------------------------\n"; + std::cout << "Player HP: " << user.getShip().durability() << " ARMOR: " << user.getShip().armor() << " | "; + std::cout << "Enemy HP: " << enemy.getShip().durability() << " ARMOR: " << enemy.getShip().armor() << '\n'; + std::cout << "-------------------------------------------------------------------\n"; + for (size_t i = 0; i < 3; ++i) { + const auto status = player->makeAction(battefield); + if (status == Action::Status::Escaped || status == Action::Status::Defeated) { + return 0; + } + } + } + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/CMakeLists.txt new file mode 100644 index 0000000..acd8033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Battle src/Defense.cpp src/BattleField.cpp src/Attack.cpp src/Escape.cpp) + +target_include_directories(Battle PUBLIC include) + +target_link_libraries(Battle + Ship + Player +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Action.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Action.h new file mode 100644 index 0000000..f271d40 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Action.h @@ -0,0 +1,24 @@ +#pragma once + +class Player; +class Ship; + +class Action { +public: + // As you can see keeping type here, require modify a base class whenever we add a new class, this volatile an open-close principle. + // We should be able to extend code without modification already implemented one + enum class Type { + Attack, + Defense, + Escape + }; + + enum class Status { + Escaped, + Defeated, + Nothing, + }; + + virtual Status operator()(Player* player, Ship* enemyShip) = 0; + virtual Type type() const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Attack.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Attack.h new file mode 100644 index 0000000..a06cba0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Attack.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Attack : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Attack; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/BattleField.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/BattleField.h new file mode 100644 index 0000000..6196660 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/BattleField.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Ship; +class Player; + +class BattleField { +public: + BattleField(Player* player, Player* enemy); + + Ship* getPlayerShip() const; + Ship* getEnemyShip() const; + std::vector players() const; + +private: + Player* _player; + Player* _enemy; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Defense.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Defense.h new file mode 100644 index 0000000..fefd271 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Defense.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Defense : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Type::Defense; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Escape.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Escape.h new file mode 100644 index 0000000..97dc54d --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/include/Battle/Escape.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Battle/Action.h" + +#include + +class Player; +class Ship; + +class Escape : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Escape; } + +private: + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Attack.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Attack.cpp new file mode 100644 index 0000000..b3f5e8a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Attack.cpp @@ -0,0 +1,22 @@ +#include "Battle/Attack.h" + +#include +#include + +#include + +Action::Status Attack::operator()(Player* player, Ship* enemyShip) { + const int damage = player->attack(*enemyShip); + std::cout << "Player ship: " << player->getShip().name() << " attack ship: " << enemyShip->name() << '\n'; + if (damage) { + std::cout << "Dealed damage: " << damage << '\n'; + } else { + std::cout << "Missed\n"; + } + + if (enemyShip->durability() <= 0) { + return Status::Defeated; + } + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/BattleField.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/BattleField.cpp new file mode 100644 index 0000000..4e10569 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/BattleField.cpp @@ -0,0 +1,16 @@ +#include "Battle/BattleField.h" + +#include + +BattleField::BattleField(Player* player, Player* enemy) + : _player{player}, _enemy{enemy} {} + +Ship* BattleField::getPlayerShip() const { + return &_player->getShip(); +} +Ship* BattleField::getEnemyShip() const { + return &_enemy->getShip(); +} +std::vector BattleField::players() const { + return {_player, _enemy}; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Defense.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Defense.cpp new file mode 100644 index 0000000..a170c81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Defense.cpp @@ -0,0 +1,13 @@ +#include "Battle/Defense.h" + +#include +#include + +#include + +Action::Status Defense::operator()(Player* player, Ship*) { + player->getShip().increaseArmor(50); + std::cout << "Player ship: " << player->getShip().name() << " defense\n"; + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Escape.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Escape.cpp new file mode 100644 index 0000000..5b222fa --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Battle/src/Escape.cpp @@ -0,0 +1,22 @@ +#include "Battle/Escape.h" + +#include +#include + +#include + +std::random_device Escape::_rd{}; + +Action::Status Escape::operator()(Player* player, Ship*) { + std::cout << "Player ship: " << player->getShip().name() << " try to escape!\n"; + + std::uniform_int_distribution dice(0, 20); + const auto res = dice(_seed); + if (res > 12) { + std::cout << "Player escaped!\n"; + return Status::Escaped; + } + + std::cout << "Escape maneuver failed!\n"; + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/CMakeLists.txt new file mode 100644 index 0000000..9434ff8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(Battle) +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/CMakeLists.txt new file mode 100644 index 0000000..db39d82 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Core src/Time.cpp src/BasicPrintVisitor.cpp src/PrettyPrintVisitor.cpp) + +target_include_directories(Core PUBLIC include) + +target_link_libraries(Core + Ship + Store +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/BasicPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/BasicPrintVisitor.h new file mode 100644 index 0000000..cd3406f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/BasicPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class BasicPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/DifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/DifficultLvlStrategy.h new file mode 100644 index 0000000..7c23854 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/DifficultLvlStrategy.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +template +class DifficultLvlStrategy { +public: + virtual Res handle(T&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/PrettyPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/PrettyPrintVisitor.h new file mode 100644 index 0000000..58dc6ad --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/PrettyPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class PrettyPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/PrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/PrintVisitor.h new file mode 100644 index 0000000..bec94c0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/PrintVisitor.h @@ -0,0 +1,11 @@ +#pragma once + +class Store; +class Ship; + +class PrintVisitor { +public: + virtual ~PrintVisitor() = default; + virtual void visit(const Store&) const = 0; + virtual void visit(const Ship&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/BasicPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/BasicPrintVisitor.cpp new file mode 100644 index 0000000..05960c1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/BasicPrintVisitor.cpp @@ -0,0 +1,22 @@ +#include + +#include +#include +#include +#include + +void BasicPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << std::setw(15) << cargo->getPrice() << "\n"; + } +} + +void BasicPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << "\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/PrettyPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/PrettyPrintVisitor.cpp new file mode 100644 index 0000000..99b6738 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/PrettyPrintVisitor.cpp @@ -0,0 +1,33 @@ +#include + +#include +#include +#include +#include + +void PrettyPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} + +void PrettyPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/CMakeLists.txt new file mode 100644 index 0000000..b266b3f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(Player src/EnemyEasyDifficultLvlStrategy.cpp src/EnemyHardDifficultLvlStrategy.cpp src/Player.cpp src/RealPlayer.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Battle + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..e44bd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/Enemy.h @@ -0,0 +1,66 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include +#include +#include + +#include +#include + +template +class Enemy : public Player { +public: + Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + std::unique_ptr> _strategy; + DamageVisitor _damageVisitor; +}; + +template +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor) + : _name(name), _ship(std::move(ship)), _strategy(std::move(strategy)), _damageVisitor(visitor) {} + +template +int Enemy::attack(Ship& playerShip) { + if (const auto damage = _strategy->handle(playerShip)) { + for (auto& cargo : playerShip.cargoes()) { + cargo->accept(_damageVisitor); + } + return damage; + } + + return 0; +} + +template +Ship* Enemy::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getPlayerShip(); +} + +template +std::unique_ptr Enemy::chooseAction(const BattleField& battleField) const { + static bool flag = true; + if (flag) { + flag = !flag; + return std::make_unique(); + } + + flag = !flag; + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..d2b7b05 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyEasyDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h new file mode 100644 index 0000000..ac01b4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyHardDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/Player.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/Player.h new file mode 100644 index 0000000..7717389 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/Player.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include + +class BattleField; +class Ship; + +class Player { +public: + virtual ~Player() = default; + virtual int attack(Ship& playerShip) = 0; + virtual Ship& getShip() = 0; + virtual const Ship& getShip() const = 0; + + Action::Status makeAction(const BattleField& battleField); + +protected: + virtual Ship* chooseEnemyShip(const BattleField& battleField) const = 0; + virtual std::unique_ptr chooseAction(const BattleField& battleField) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/RealPlayer.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/RealPlayer.h new file mode 100644 index 0000000..04d8b1a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/include/Player/RealPlayer.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include + +class RealPlayer : public Player { +public: + RealPlayer(const std::string& name, std::unique_ptr&& ship); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..0ff5663 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp @@ -0,0 +1,28 @@ +#include "Player/EnemyEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyEasyDifficultLvlStrategy::_rd{}; + +EnemyEasyDifficultLvlStrategy::EnemyEasyDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyEasyDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 5) { + // miss + return 0; + } else if (res > 19) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(25, 50); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/EnemyHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/EnemyHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..790cd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/EnemyHardDifficultLvlStrategy.cpp @@ -0,0 +1,31 @@ +#include "Player/EnemyHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyHardDifficultLvlStrategy::_rd{}; + +EnemyHardDifficultLvlStrategy::EnemyHardDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyHardDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 3) { + // miss + return 0; + } else if (res == 20) { + // turbo critical + multiplier = 3; + } else if (res > 15) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(30, 60); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/Player.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/Player.cpp new file mode 100644 index 0000000..5e1f83b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/Player.cpp @@ -0,0 +1,11 @@ +#include "Player/Player.h" + +Action::Status Player::makeAction(const BattleField& battleField) { + std::unique_ptr action = chooseAction(battleField); + if (action->type() == Action::Type::Attack) { + Ship* enemyShip = chooseEnemyShip(battleField); + return (*action)(this, enemyShip); + } + + return (*action)(this, nullptr); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/RealPlayer.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/RealPlayer.cpp new file mode 100644 index 0000000..b5cd4de --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Player/src/RealPlayer.cpp @@ -0,0 +1,56 @@ +#include "Player/RealPlayer.h" + +#include +#include +#include +#include +#include + +#include + +std::random_device RealPlayer::_rd{}; + +RealPlayer::RealPlayer(const std::string& name, std::unique_ptr&& ship) + : _name(name), _ship(std::move(ship)) {} + +int RealPlayer::attack(Ship& playerShip) { + std::uniform_int_distribution dice(0, 20); + const int res = dice(_seed); + int input = 0; + int damage = 0; + std::cout << "Choose Ammo: 1) Round Shot 2) Chain Shot 3) Grape Shot: "; + std::cin >> input; + + if (input == 1 && res > 4) { + damage = 50; + } else if (input == 2 && res > 7) { + damage = 80; + } else if (input == 3 && res > 10) { + damage = 100; + } else { + return 0; + } + + playerShip.takeDamage(damage); + return damage; +} + +Ship* RealPlayer::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getEnemyShip(); +} + +std::unique_ptr RealPlayer::chooseAction(const BattleField& battleField) const { + int input = 0; + std::cout << "Choose Action: 1) Attack 2) Defense 3) Escape: "; + std::cin >> input; + + if (input == 1) { + return std::make_unique(); + } + if (input == 3) { + return std::make_unique(); + } + + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..d2f40e2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/CMakeLists.txt @@ -0,0 +1,12 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp + src/ShipEasyDifficultLvlStrategy.cpp + src/ShipHardDifficultLvlStrategy.cpp + src/CargoDamageVisitor.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..3771b7a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +#include "Ship/CargoDamageVisitor.h" + +#include + +struct Cargo { + size_t amount; + + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; + virtual void accept(const CargoDamageVisitor& visitor) = 0; +}; + +struct Fruit : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Item : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Alcohol : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/CargoDamageVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/CargoDamageVisitor.h new file mode 100644 index 0000000..6e84c58 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/CargoDamageVisitor.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class Fruit; +class Alcohol; +class Item; + +class CargoDamageVisitor { +public: + CargoDamageVisitor() = default; + virtual ~CargoDamageVisitor() = default; + CargoDamageVisitor(const CargoDamageVisitor&) = default; + CargoDamageVisitor(CargoDamageVisitor&&) = default; + CargoDamageVisitor& operator=(const CargoDamageVisitor&) = default; + CargoDamageVisitor& operator=(CargoDamageVisitor&&) = default; + + virtual void operator()(Fruit& fruit) const; + virtual void operator()(Alcohol& alcohol) const; + virtual void operator()(Item& item) const; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..186d0bb --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/Ship.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include "Ship/Cargo.h" + +class PrintVisitor; +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew, std::unique_ptr&& visitor); + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + const std::vector>& cargoes() const; + + void increaseArmor(int armor) { _armor += armor; } + int durability() const { return _durability; } + int armor() const { return _armor; } + +private: + bool unloadCargo(const std::string& cargoName, int amount); + void rebel(); + + Time* _time; + std::unique_ptr> _strategy; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + int _armor{0}; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..ce7627a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h new file mode 100644 index 0000000..a5f6a64 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..31d75b7 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/Cargo.cpp @@ -0,0 +1,43 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +void Fruit::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +void Item::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} + +void Alcohol::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/CargoDamageVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/CargoDamageVisitor.cpp new file mode 100644 index 0000000..6ff89e2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/CargoDamageVisitor.cpp @@ -0,0 +1,20 @@ +#include + +#include + +std::random_device CargoDamageVisitor::_rd{}; + +void CargoDamageVisitor::operator()(Fruit& fruit) const { + std::uniform_int_distribution dice(0, 5); + fruit.amount -= dice(_seed); +} + +void CargoDamageVisitor::operator()(Alcohol& alcohol) const { + std::uniform_int_distribution dice(0, 10); + alcohol.amount -= (dice(_seed) / 2); +} + +void CargoDamageVisitor::operator()(Item& item) const { + std::uniform_int_distribution dice(0, 20); + item.amount -= (dice(_seed) / 4); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..2529f92 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/Ship.cpp @@ -0,0 +1,111 @@ +#include "Ship/Ship.h" + +#include +#include + +#include +#include +#include +#include + +Ship::Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew, std::unique_ptr&& visitor) + : _time(time), _strategy(std::move(strategy)), _name(name), _capacity(capacity), _crew(crew), _visitor(std::move(visitor)) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + if (!_strategy->handle(*this)) { + rebel(); + } +} + +void Ship::printCargo() const { + _visitor->visit(*this); +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const std::string& cargoName, int amount, StatusCode& code) noexcept { + if (!unloadCargo(cargoName, amount)) { + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const std::string& cargoName, int amount) { + if (!unloadCargo(cargoName, amount)) { + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _armor -= damage; + if (_armor >= 0) { + return; + } + + _durability += _armor; + _armor = 0; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +const std::vector>& Ship::cargoes() const { + return _cargoes; +} + +bool Ship::unloadCargo(const std::string& cargoName, int amount) { + while (amount != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount > amount) { + (*it)->amount -= amount; + return true; + } + amount -= (*it)->amount; + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..6d1a148 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipEasyDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/ShipHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/ShipHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..2a6815a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Ship/src/ShipHardDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipHardDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew(), status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew(), status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/include/Store/Store.h new file mode 100644 index 0000000..fbbbf9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/include/Store/Store.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class PrintVisitor; + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos, std::unique_ptr&& visitor); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + const std::vector>& cargoes() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/src/Store.cpp new file mode 100644 index 0000000..07a9e35 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/src/Store/src/Store.cpp @@ -0,0 +1,41 @@ +#include "Store/Store.h" + +#include + +Store::Store(std::vector>&& cargos, std::unique_ptr&& visitor) + : _seed(_rd()), _cargoes(std::move(cargos)), _visitor(std::move(visitor)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +const std::vector>& Store::cargoes() const { + return _cargoes; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +void Store::printCargo() const { + _visitor->visit(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/templateMethod/templateMethod/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor.cpp new file mode 100644 index 0000000..3554151 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include + +class AmmunitionVisitor; + +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + virtual void accept(const AmmunitionVisitor&) = 0; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; + +class RoundShot; +class ChainShot; +class GrapeShot; + +class AmmunitionVisitor { +public: + virtual ~AmmunitionVisitor() = default; + virtual void visit(const RoundShot&) const = 0; + virtual void visit(const ChainShot&) const = 0; + virtual void visit(const GrapeShot&) const = 0; +}; + +class RoundShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AmmunitionVisitor& visitor) { + visitor.visit(*this); + } +}; + +class ChainShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AmmunitionVisitor& visitor) { + visitor.visit(*this); + } +}; + +class GrapeShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AmmunitionVisitor& visitor) { + visitor.visit(*this); + } +}; + +class DamageVisitor : public AmmunitionVisitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Round shot make 20 damages\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Chain shot make 30 damages\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Grape shot make 40 damages\n"; + } +}; + +class SoundVisitor : public AmmunitionVisitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Fiuuuuuuuu Bam!\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam!\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam bam bam bam!\n"; + } +}; + +int main() { + std::unique_ptr grapeShot = std::make_unique(100); + SoundVisitor soundVisitor; + DamageVisitor damageVisitor; + grapeShot->accept(soundVisitor); + grapeShot->accept(damageVisitor); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/CMakeLists.txt new file mode 100644 index 0000000..4b33b70 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(${PROJECT_NAME} + Ship + Store + Core + Player +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/main.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/main.cpp new file mode 100644 index 0000000..0cf86be --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/main.cpp @@ -0,0 +1,56 @@ +#include +#include +#include + +#include "Core/BasicPrintVisitor.h" +#include "Core/PrettyPrintVisitor.h" +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Ship/Cargo.h" +#include "Ship/CargoDamageVisitor.h" +#include "Ship/Ship.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Store/Store.h" + +int main() { + Time time; + std::vector> cargoes; + cargoes.push_back(std::make_unique(1'000)); + cargoes.push_back(std::make_unique(1'000)); + cargoes.push_back(std::make_unique(1'000)); + auto store = std::unique_ptr>( + [&cargoes, &time]() { + auto* store = new Store(std::move(cargoes), std::make_unique()); + try { + time.attach(store); + } catch (...) { + abort(); + } + return store; }(), + [&time](Store* store) { + time.detach(store); + delete store; + }); + + Ship ship(&time, std::make_unique(), "Black Widow", 1000, 40, std::make_unique()); + ship.load(std::make_unique(300)); + ship.load(std::make_unique(200)); + ship.load(std::make_unique(150)); + + std::cout << "Ship\n"; + ship.printCargo(); + std::cout << "\nStore\n"; + store->printCargo(); + + std::cout << "\n\n****************************************************\n"; + auto ship2 = std::make_unique(&time, std::make_unique(), "Queens Anne revenge", 1000, 40, std::make_unique()); + Enemy enemy("Enemy1", std::move(ship2), std::make_unique(), CargoDamageVisitor{}); + + for (int i = 0; i < 5; ++i) { + enemy.attack(ship); + ship.printCargo(); + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/CMakeLists.txt new file mode 100644 index 0000000..c29ff6c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/CMakeLists.txt new file mode 100644 index 0000000..db39d82 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Core src/Time.cpp src/BasicPrintVisitor.cpp src/PrettyPrintVisitor.cpp) + +target_include_directories(Core PUBLIC include) + +target_link_libraries(Core + Ship + Store +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/BasicPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/BasicPrintVisitor.h new file mode 100644 index 0000000..cd3406f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/BasicPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class BasicPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/DifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/DifficultLvlStrategy.h new file mode 100644 index 0000000..7c23854 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/DifficultLvlStrategy.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +template +class DifficultLvlStrategy { +public: + virtual Res handle(T&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/PrettyPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/PrettyPrintVisitor.h new file mode 100644 index 0000000..58dc6ad --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/PrettyPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class PrettyPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/PrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/PrintVisitor.h new file mode 100644 index 0000000..bec94c0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/PrintVisitor.h @@ -0,0 +1,11 @@ +#pragma once + +class Store; +class Ship; + +class PrintVisitor { +public: + virtual ~PrintVisitor() = default; + virtual void visit(const Store&) const = 0; + virtual void visit(const Ship&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/BasicPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/BasicPrintVisitor.cpp new file mode 100644 index 0000000..05960c1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/BasicPrintVisitor.cpp @@ -0,0 +1,22 @@ +#include + +#include +#include +#include +#include + +void BasicPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << std::setw(15) << cargo->getPrice() << "\n"; + } +} + +void BasicPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << "\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/PrettyPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/PrettyPrintVisitor.cpp new file mode 100644 index 0000000..99b6738 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/PrettyPrintVisitor.cpp @@ -0,0 +1,33 @@ +#include + +#include +#include +#include +#include + +void PrettyPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} + +void PrettyPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/CMakeLists.txt new file mode 100644 index 0000000..4dbb77f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Player src/EnemyEasyDifficultLvlStrategy.cpp src/EnemyHardDifficultLvlStrategy.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..59fc1f1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/Enemy.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +#include + +#include +#include +#include +#include +#include + +template +class Enemy { +public: + Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor); + + void attack(Ship& playerShip); + +private: + std::string _name; + std::unique_ptr _ship; + std::unique_ptr> _strategy; + DamageVisitor _damageVisitor; +}; + +template +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor) + : _name(name), _ship(std::move(ship)), _strategy(std::move(strategy)), _damageVisitor(visitor) {} + +template +void Enemy::attack(Ship& playerShip) { + std::cout << "Player: " << _name << " attack ship: " << playerShip.name() << '\n'; + if (const auto damage = _strategy->handle(playerShip)) { + std::cout << "Dealed damage: " << damage << '\n'; + for (auto& cargo : playerShip.cargoes()) { + cargo->accept(_damageVisitor); + } + } else { + std::cout << "Missed\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..d2b7b05 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyEasyDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h new file mode 100644 index 0000000..ac01b4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyHardDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..0ff5663 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp @@ -0,0 +1,28 @@ +#include "Player/EnemyEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyEasyDifficultLvlStrategy::_rd{}; + +EnemyEasyDifficultLvlStrategy::EnemyEasyDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyEasyDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 5) { + // miss + return 0; + } else if (res > 19) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(25, 50); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/src/EnemyHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/src/EnemyHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..790cd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Player/src/EnemyHardDifficultLvlStrategy.cpp @@ -0,0 +1,31 @@ +#include "Player/EnemyHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyHardDifficultLvlStrategy::_rd{}; + +EnemyHardDifficultLvlStrategy::EnemyHardDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyHardDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 3) { + // miss + return 0; + } else if (res == 20) { + // turbo critical + multiplier = 3; + } else if (res > 15) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(30, 60); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..d2f40e2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/CMakeLists.txt @@ -0,0 +1,12 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp + src/ShipEasyDifficultLvlStrategy.cpp + src/ShipHardDifficultLvlStrategy.cpp + src/CargoDamageVisitor.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..3771b7a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +#include "Ship/CargoDamageVisitor.h" + +#include + +struct Cargo { + size_t amount; + + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; + virtual void accept(const CargoDamageVisitor& visitor) = 0; +}; + +struct Fruit : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Item : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Alcohol : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/CargoDamageVisitor.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/CargoDamageVisitor.h new file mode 100644 index 0000000..6e84c58 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/CargoDamageVisitor.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class Fruit; +class Alcohol; +class Item; + +class CargoDamageVisitor { +public: + CargoDamageVisitor() = default; + virtual ~CargoDamageVisitor() = default; + CargoDamageVisitor(const CargoDamageVisitor&) = default; + CargoDamageVisitor(CargoDamageVisitor&&) = default; + CargoDamageVisitor& operator=(const CargoDamageVisitor&) = default; + CargoDamageVisitor& operator=(CargoDamageVisitor&&) = default; + + virtual void operator()(Fruit& fruit) const; + virtual void operator()(Alcohol& alcohol) const; + virtual void operator()(Item& item) const; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..7300a0d --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/Ship.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include "Ship/Cargo.h" + +class PrintVisitor; +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew, std::unique_ptr&& visitor); + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + const std::vector>& cargoes() const; + +private: + bool unloadCargo(const std::string& cargoName, int amount); + void rebel(); + + Time* _time; + std::unique_ptr> _strategy; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..ce7627a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h new file mode 100644 index 0000000..a5f6a64 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..31d75b7 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/Cargo.cpp @@ -0,0 +1,43 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +void Fruit::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +void Item::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} + +void Alcohol::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/CargoDamageVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/CargoDamageVisitor.cpp new file mode 100644 index 0000000..6ff89e2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/CargoDamageVisitor.cpp @@ -0,0 +1,20 @@ +#include + +#include + +std::random_device CargoDamageVisitor::_rd{}; + +void CargoDamageVisitor::operator()(Fruit& fruit) const { + std::uniform_int_distribution dice(0, 5); + fruit.amount -= dice(_seed); +} + +void CargoDamageVisitor::operator()(Alcohol& alcohol) const { + std::uniform_int_distribution dice(0, 10); + alcohol.amount -= (dice(_seed) / 2); +} + +void CargoDamageVisitor::operator()(Item& item) const { + std::uniform_int_distribution dice(0, 20); + item.amount -= (dice(_seed) / 4); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..b3b15c9 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/Ship.cpp @@ -0,0 +1,105 @@ +#include "Ship/Ship.h" + +#include +#include + +#include +#include +#include +#include + +Ship::Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew, std::unique_ptr&& visitor) + : _time(time), _strategy(std::move(strategy)), _name(name), _capacity(capacity), _crew(crew), _visitor(std::move(visitor)) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + if (!_strategy->handle(*this)) { + rebel(); + } +} + +void Ship::printCargo() const { + _visitor->visit(*this); +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const std::string& cargoName, int amount, StatusCode& code) noexcept { + if (!unloadCargo(cargoName, amount)) { + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const std::string& cargoName, int amount) { + if (!unloadCargo(cargoName, amount)) { + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _durability -= damage; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +const std::vector>& Ship::cargoes() const { + return _cargoes; +} + +bool Ship::unloadCargo(const std::string& cargoName, int amount) { + while (amount != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount > amount) { + (*it)->amount -= amount; + return true; + } + amount -= (*it)->amount; + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..6d1a148 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipEasyDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/ShipHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/ShipHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..2a6815a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Ship/src/ShipHardDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipHardDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew(), status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew(), status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/include/Store/Store.h new file mode 100644 index 0000000..fbbbf9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/include/Store/Store.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class PrintVisitor; + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos, std::unique_ptr&& visitor); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + const std::vector>& cargoes() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/src/Store.cpp new file mode 100644 index 0000000..07a9e35 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/src/Store/src/Store.cpp @@ -0,0 +1,41 @@ +#include "Store/Store.h" + +#include + +Store::Store(std::vector>&& cargos, std::unique_ptr&& visitor) + : _seed(_rd()), _cargoes(std::move(cargos)), _visitor(std::move(visitor)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +const std::vector>& Store::cargoes() const { + return _cargoes; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +void Store::printCargo() const { + _visitor->visit(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor2.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor2.cpp new file mode 100644 index 0000000..42170f1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor2.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; + +class RoundShot final : public Ammunition { +public: + using Ammunition::Ammunition; +}; + +class ChainShot final : public Ammunition { +public: + using Ammunition::Ammunition; +}; + +class GrapeShot final : public Ammunition { +public: + using Ammunition::Ammunition; +}; + +class DamageVisitor { +public: + void operator()(const RoundShot& shot) const { + std::cout << "Round shot make 20 damages\n"; + } + void operator()(const ChainShot& shot) const { + std::cout << "Chain shot make 30 damages\n"; + } + void operator()(const GrapeShot& shot) const { + std::cout << "Grape shot make 40 damages\n"; + } +}; + +class SoundVisitor { +public: + void operator()(const RoundShot& shot) const { + std::cout << "Fiuuuuuuuu Bam!\n"; + } + void operator()(const ChainShot& shot) const { + std::cout << "Fiuuuuuuuuuuu Bam bam!\n"; + } + void operator()(const GrapeShot& shot) const { + std::cout << "Fiuuuuuuuuuuu Bam bam bam bam bam!\n"; + } +}; + +int main() { + using Shot = std::variant; + + Shot shot = GrapeShot(100); + SoundVisitor soundVisitor; + DamageVisitor damageVisitor; + std::visit(damageVisitor, shot); + std::visit(soundVisitor, shot); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor3.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor3.cpp new file mode 100644 index 0000000..926fef7 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor3.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +class AbstractVisitor; + +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + virtual void accept(const AbstractVisitor&) = 0; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; + +class RoundShot; +class ChainShot; +class GrapeShot; + +class AbstractVisitor { +protected: + // Can be only use by derived class + virtual ~AbstractVisitor() = default; +}; + +class RoundShotVisitor { +public: + virtual void visit(const RoundShot& shot) const = 0; + +protected: + virtual ~RoundShotVisitor() = default; +}; + +class GrapeShotVisitor { +public: + virtual void visit(const GrapeShot& shot) const = 0; + +protected: + virtual ~GrapeShotVisitor() = default; +}; + +class ChainShotVisitor { +public: + virtual void visit(const ChainShot& shot) const = 0; + +protected: + virtual ~ChainShotVisitor() = default; +}; + +class DamageVisitor : public AbstractVisitor, + public RoundShotVisitor, + public GrapeShotVisitor, + public ChainShotVisitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Round shot make 20 damages\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Chain shot make 30 damages\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Grape shot make 40 damages\n"; + } +}; + +class SoundVisitor : public AbstractVisitor, + public RoundShotVisitor, + public GrapeShotVisitor, + public ChainShotVisitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Fiuuuuuuuu Bam!\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam!\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam bam bam bam!\n"; + } +}; + +class RoundShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast(&visitor)) { + v->visit(*this); + } + } +}; + +class ChainShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast(&visitor)) { + v->visit(*this); + } + } +}; + +class GrapeShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast(&visitor)) { + v->visit(*this); + } + } +}; + +int main() { + std::unique_ptr grapeShot = std::make_unique(100); + SoundVisitor soundVisitor; + DamageVisitor damageVisitor; + grapeShot->accept(soundVisitor); + grapeShot->accept(damageVisitor); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor4.cpp b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor4.cpp new file mode 100644 index 0000000..8cec69b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/examples/visitor/visitor4.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +class AbstractVisitor; + +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + virtual void accept(const AbstractVisitor&) = 0; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; + +class RoundShot; +class ChainShot; +class GrapeShot; + +class AbstractVisitor { +protected: + // Can be only use by derived class + virtual ~AbstractVisitor() = default; +}; + +template +class Visitor { +public: + virtual void visit(const T& shot) const = 0; + +protected: + virtual ~Visitor() = default; +}; + +class DamageVisitor : public AbstractVisitor, + public Visitor, + public Visitor, + public Visitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Round shot make 20 damages\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Chain shot make 30 damages\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Grape shot make 40 damages\n"; + } +}; + +class SoundVisitor : public AbstractVisitor, + public Visitor, + public Visitor, + public Visitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Fiuuuuuuuu Bam!\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam!\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam bam bam bam!\n"; + } +}; + +class RoundShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast*>(&visitor)) { + v->visit(*this); + } + } +}; + +class ChainShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast*>(&visitor)) { + v->visit(*this); + } + } +}; + +class GrapeShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast*>(&visitor)) { + v->visit(*this); + } + } +}; + +int main() { + std::unique_ptr grapeShot = std::make_unique(100); + SoundVisitor soundVisitor; + DamageVisitor damageVisitor; + grapeShot->accept(soundVisitor); + grapeShot->accept(damageVisitor); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exceptions.md b/CreatingReliableSoftwareCpp/Presentation/exceptions.md new file mode 100644 index 0000000..12f9dde --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exceptions.md @@ -0,0 +1,431 @@ +# Exceptions +___ + +## Throw + +If you want to throw an exception you can simply call `throw` + +```C++ +void foo() { + throw "Error"; +} +``` + +If you want to catch an error you need to use `try-catch` + + +```C++ +void bar() { + try { + foo(); + } catch (const std::exception& err) { + std::cout << err.what() << '\n'; + } +} +``` + +___ + +## What happens during throw? + +Programm will stop executing the next line, when reach `throw` command. It will startup **unwind** a stack untill it reach the first `try-catch` block which will catch this exception. Because the stack is unwinded all variables which go out of scope will be properly destructed. + +
+
+ +```C++ +struct Foo { + explicit Foo(int id): id(id) { std::cout << "C'tor id: " << id << "\n"; } + ~Foo() { std::cout << "D'tor id: " << id << "\n"; } + + int id; +}; + +void fun2() { + Foo foo(2); + std::cout << "This will print!\n"; + throw std::runtime_error("Bad!"); + std::cout << "This will not print!\n"; +} + +void fun1() { + std::cout << "We start here!\n"; + Foo foo(1); + std::cout << "After construction of Foo we call function fun2 which throw\n"; + fun2(); + std::cout << "This will not print!\n"; +} + +int main() { + try { + fun1(); + std::cout << "This will not print!\n"; + } catch (const std::exception& err) { + std::cout << "exception: " << err.what() << '\n'; + } + std::cout << "Exit\n"; +} +``` + +
+
+ +```bash +We start here! +C'tor id: 1 +After construction of Foo we call function fun2 which throw +C'tor id: 2 +This will print! +D'tor id: 2 +D'tor id: 1 +exception: Bad! +Exit +``` + +
+
+ +___ + +## Hierarchy + +There are more than 30 exceptions in C++! Each exception could be a base class of other (see cppreference). The most common are: + +* logic_error +* out_of_range +* bad_optional_access +* runtime_error +* bad_weak_ptr +* bad_alloc +___ + +## How to properly catch an error + +```C++ +void doSth() { + std::cout << "Hello! "; + throw std::invalid_argument("SthBad!"); +} + +int main() { + try { + doSth(); + } catch (const std::invalid_argument& err) { + std::cout << "invalid_argument: " << err.what() << '\n'; + } catch (const std::logic_error& err) { + std::cout << "logic_error: " << err.what() << '\n'; + } catch (const std::exception& err) { + std::cout << "exception: " << err.what() << '\n'; + } catch (...) { + std::cout << "Undefined error!\n"; + } +} +``` +Output: `Hello! invalid_argument: SthBad!`. + + + +___ + +What happens when I will try to catch an error with an unordered hierarchy? + +```C++ +void doSth() { + std::cout << "Hello! "; + throw std::invalid_argument("SthBad!"); +} + +int main() { + try { + doSth(); + } catch (const std::logic_error& err) { + std::cout << "logic_error: " << err.what() << '\n'; + } catch (const std::invalid_argument& err) { + std::cout << "invalid_argument: " << err.what() << '\n'; + } catch (...) { + std::cout << "Undefined error!\n"; + } +} +``` + +Output: `Hello! logic_error: SthBad!` + + +```bash +main.cpp: In function ‘int main()’: +main.cpp:21:7: warning: exception of type ‘std::invalid_argument’ will be caught + 21 | } catch (const std::invalid_argument& err) { + | ^~~~~ +main.cpp:19:7: warning: by earlier handler for ‘std::logic_error’ + 19 | } catch (const std::logic_error& err) { +``` + + +___ + +You can quickly create your error class by inheriting from the base class `std::exception`. We need to `override` one method which will return a proper error message: `virtual const char* what() const noexcept` + +```C++ +class MyError : public std::exception { +public: + explicit MyError(const std::string& what): _what(what) {} + explicit MyError(const char* what): MyError(std::string(what)) {} + explicit MyError(std::string_view what): MyError(std::string(what)) {} + const char* what() const noexcept override { return _what.c_str(); } +private: + std::string _what; +}; + +class OtherError : public MyError { +public: + using MyError::MyError; +}; + +void doSth() { + throw OtherError("SthBad!"); +} + +int main() { + try { + doSth(); + } catch (const OtherError& err) { + std::cout << "OtherError: " << err.what() << '\n'; + } catch (const MyError& err) { + std::cout << "MyError: " << err.what() << '\n'; + } catch (const std::exception& err) { + std::cout << "exception: " << err.what() << '\n'; + } +} +``` + + +___ + +It's important to use your error classes instead of those defined by the standard library. It will allow you to determine if the error comes from the standard library or your functions. + +```C++ +class MyError : public std::exception { +public: + explicit MyError(const std::string& what): _what(what) {} + const char* what() const noexcept override { return _what.c_str(); } +private: + std::string _what; +}; + +class Foo { +public: + const std::string& getProcessName(uint64_t pid) { return _processes.at(pid); } + void addProcess(uint64_t pid, const std::string& processName) { + if (_processes.contains(pid)) { + throw MyError(std::format("Process with PID {} already exist", pid)); + } + _processes[pid] = processName; + } +private: + std::map _processes; +}; + +int main() { + try { + Foo foo; + const auto& processName = foo.getProcessName(20); + foo.addProcess(1234, "MySuperprocess!"); + } catch (const MyError& err) { + std::cout << "MyError: " << err.what() << '\n'; + } catch (const std::exception& err) { + std::cout << "exception: " << err.what() << '\n'; + } +} +``` + +___ + +## Ways to signal an error + +* throw an exception +* return enum class ErrorCode +* return nullptr +* return false +* return std::optional (C++17) +* return std::expected (C++23) +___ + +## Descriptive errors + +We have three ways to strictly describe what happens wrong: `exception`, `enum class`, and `std::expected`. Using these types we can say what exactly goes wrong, like: providing the wrong credentials, or we can't find some element, etc... + +
+
+ +```C++ +int foo(const std::string& num) { + if (num != "42") { + throw std::runtime_error("Number is different than 42!"); + } + + return 42; +} + +enum class StatusCode { + Ok, + Not42Number +}; + +StatusCode foo2(const std::string& num, int& res) { + if (num != "42") { + return StatusCode::Not42Number; + } + + res = 42; + return StatusCode::Ok; +} +``` + +
+
+ +```C++ +enum class ParserError { + invalid_input, + overflow +}; + +std::expected parse(std::string_view str) { + if (str.size() > 1'000) { + return std::unexpected(ParserError::overflow); + } else if (str.empty()) { + return std::unexpected(ParserError::invalid_input); + } + + return 42; +} + +int main() { + if (const auto num = parse("something")) { + std::cout << "value: " << *num << '\n'; + } else if (num.error() == ParserError::overflow) { + std::cout << "error: overflow\n"; + } else if (num.error() == ParserError::invalid_input) { + std::cout << "invalid_input!\n"; + } +} +``` +
+ +
+ +___ + +## Non descriptive errors + +There are also three ways how to inform about the error but without describing why. This is useful for simple functions that may have only one error like whether there is a value inside the map or not. + +```C++ +std::unique_ptr foo3(const std::string& num) { + if (num != "42") { + return nullptr; + } + + return std::make_unique(42); +} + +bool foo4(const std::string& num, int& res) { + if (num != "42") { + return false; + } + + res = 42; + return true; +} + +std::optional foo5(const std::string& num) { + if (num != "42") { + return std::nullopt; + } + + return 42; +} +``` + + +___ + +### std::optional - more info + +Introduced in c++17 `std::optional` is a useful class that may have a value or not. + +* Doesn't allocate data on heap! +* Require additional storage info -> bigger size +* Not as efficient as normal integer -> need to perform additional actions + +```C++ +class Foo { + int a; + int b; + int c; + int d; +}; + +int main() { + std::cout << sizeof(int) << '\n'; + std::cout << sizeof(std::optional) << '\n'; + std::cout << sizeof(Foo) << '\n'; + std::cout << sizeof(std::optional) << '\n'; +} +``` + + +```C++ +4 +8 +16 +20 +``` + + +___ + +### std::expected - more info + +Introduced in c++23 `std::expected` is a useful class that may store one of two values: +* expected -> the return value which we expect +* unexpected -> the value that will be returned when something goes wrong + +In most cases as an unexpected value, we return an enum code with a description of what went wrong, but we can return anything (except reference) + + +```C++ +struct Foo { + void print() const { std::cout << "Sorry your function doesn't work!"; } +}; + +std::expected parse(std::string_view str) { + if (str.empty()) { + return std::unexpected(Foo{}); + } + return "42"; +} + +int main() { + if (const auto num = parse("")) { + std::cout << "value: " << *num << '\n'; + } else { + num.error().print(); + } +} +``` + + +```bash +Sorry your function doesn't work! +``` + + +___ + +## Exercise + +* Create an exception class `Exception` which inherits from `std::exception` and two classes `ParserException` and `ReaderException` which inherit form class `Exception`. +* Rewrite a code to `ParserException` in the method `parse` and `ReaderException` in the method `read`. +* Try to catch errors in `main` and print them +* Rewrite a code once again and return `nullopt` when an error occurs instead of throwing an exception \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/CMakeLists.txt new file mode 100644 index 0000000..6e8f2b6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/CMakeLists.txt new file mode 100644 index 0000000..e13b23f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(Ship) +add_subdirectory(Store) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..2f46bbd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(Ship src/Ship.cpp src/Cargo.cpp) + +target_include_directories(Ship PUBLIC include) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..2ba4877 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +struct Cargo { + size_t amount; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; +}; + +struct Fruit : public Cargo { + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Item : public Cargo { + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Alcohol : public Cargo { + size_t getPrice() const override; + const std::string& name() const override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..2a355fa --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/include/Ship/Ship.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +#include "Ship/Cargo.h" + +class Ship { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + Ship(const std::string& name, int capacity); + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const Cargo& cargo, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const Cargo& cargo); + +private: + std::string _name; + int _capacity; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..3fd59ca --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/src/Cargo.cpp @@ -0,0 +1,28 @@ +#include "Ship/Cargo.h" + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Fruit"}; + return name; +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Alcohol"}; + return name; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..4c66981 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Ship/src/Ship.cpp @@ -0,0 +1,48 @@ +#include "Ship/Ship.h" + +#include +#include + +Ship::Ship(const std::string& name, int capacity): + _name(name), _capacity(capacity) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } + } + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const Cargo& cargo, StatusCode& code) noexcept { + if (auto it = std::find_if(_cargoes.begin(), _cargoes.end(), [&cargo](const auto& item){ return *item == cargo; }) ; it != _cargoes.end()) { + _cargoes.erase(it); + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const Cargo& cargo) { + if (auto it = std::find_if(_cargoes.begin(), _cargoes.end(), [&cargo](const auto& item){ return *item == cargo; }) ; it != _cargoes.end()) { + _cargoes.erase(it); + throw std::runtime_error("Missing cargo"); + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/include/Store/Store.h new file mode 100644 index 0000000..cb4d5f3 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/include/Store/Store.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include + +class Store { +public: + Store() = default; + explicit Store(std::vector>&& cargos); + + size_t getTotalPrice() const; + std::vector getCargosName() const; + +private: + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/src/Store.cpp new file mode 100644 index 0000000..2fe4f85 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/src/Store/src/Store.cpp @@ -0,0 +1,21 @@ +#include "Store/Store.h" + +Store::Store(std::vector>&& cargos): _cargoes(std::move(cargos)) {} + +size_t Store::getTotalPrice() const { + size_t value {0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..a80abf7 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + Ship ship("Black Widow", 100); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..697a39f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/SHM/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + Store store; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/CMakeLists.txt new file mode 100644 index 0000000..751c5ff --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +include(FetchContent) +FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG v3.11.3 +) +FetchContent_MakeAvailable(json) + +target_link_libraries(${PROJECT_NAME} + Battle + Ship + Store + Core + Player + nlohmann_json::nlohmann_json +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/README.md b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/README.md new file mode 100644 index 0000000..0c8a0c6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/README.md @@ -0,0 +1,39 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +* Go to the directory `Ship` and create class `ShipBuilder`. The mandatory fields are: + * name + * capacity + * time +* The non-mandatory fields are: + * difficultStrategy -> default value should be set as **Easy** + * crew -> default value should be set as **10** + * durability -> default value should be set as **1000** + * armor -> default value should be set as **0** + * PrintVisitor -> default value should be set as **Pretty Print** +* Try to build your own `Ship`! + +## Exercise 2 + +* Go to the directory `Ship` and finish implementation of class `ShipJsonBuilder`. You should allow building 3 types of ship: + * Brig + * Frigate + * Galoen +* If you want to read a JSON filed, just use operator[], example: `_shipsData["brige"]["armor"]` +* Try to build a ship using a new builder. +* Try to change some values in `ships.json` and run binary without recompilation. You should see new values! + +## Exercise 3 + +* Go to the directory `Ship` and create abstract class `FruitFactory`. +* Create `FruitFactory` +* Create `ItemFactory` +* Create `AlcoholFactory` +* Test in main.cpp if you can create any type of cargo +* How to handle scenario, when different cargo takes other arguments? diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/main.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/main.cpp new file mode 100644 index 0000000..2609baf --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/main.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +#include "Battle/BattleField.h" +#include "Core/BasicPrintVisitor.h" +#include "Core/PrettyPrintVisitor.h" +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Player/RealPlayer.h" +#include "Ship/Cargo.h" +#include "Ship/CargoDamageVisitor.h" +#include "Ship/Ship.h" +#include "Ship/ShipBuilder.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipJsonBuilder.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Store/Store.h" + +int main() { + Time time; + + auto ship = ShipBuilder() + .setTime(&time) + .setName("Black Widow") + .setCapacity(1000) + .setCrew(40) + .setStrategy(std::make_unique()) + .setVisitor(std::make_unique()) + .setArmor(100) + .setDurability(1000) + .build(); + ship->load(std::make_unique(300)); + ship->load(std::make_unique(200)); + ship->load(std::make_unique(150)); + RealPlayer user("Mateusz", std::move(ship)); + + Enemy enemy("Enemy1", + ShipJsonBuilder("../ships.json").buildGaleon(&time, "Queens Anne revenge"), + std::make_unique(), + CargoDamageVisitor{}); + + BattleField battefield{&user, &enemy}; + while (true) { + for (auto* player : battefield.players()) { + std::cout << "-------------------------------------------------------------------\n"; + std::cout << "Player HP: " << user.getShip().durability() << " ARMOR: " << user.getShip().armor() << " | "; + std::cout << "Enemy HP: " << enemy.getShip().durability() << " ARMOR: " << enemy.getShip().armor() << '\n'; + std::cout << "-------------------------------------------------------------------\n"; + for (size_t i = 0; i < 3; ++i) { + const auto status = player->makeAction(battefield); + if (status == Action::Status::Escaped || status == Action::Status::Defeated) { + return 0; + } + } + } + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/ships.json b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/ships.json new file mode 100644 index 0000000..9b19770 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/ships.json @@ -0,0 +1,20 @@ +{ + "brige":{ + "capacity":1000, + "crew":40, + "durability":1000, + "armor":100 + }, + "frigate":{ + "capacity":1500, + "crew":70, + "durability":2000, + "armor":500 + }, + "galeon":{ + "capacity":2500, + "crew":120, + "durability":3000, + "armor":1000 + } + } \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/CMakeLists.txt new file mode 100644 index 0000000..acd8033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Battle src/Defense.cpp src/BattleField.cpp src/Attack.cpp src/Escape.cpp) + +target_include_directories(Battle PUBLIC include) + +target_link_libraries(Battle + Ship + Player +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Action.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Action.h new file mode 100644 index 0000000..f271d40 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Action.h @@ -0,0 +1,24 @@ +#pragma once + +class Player; +class Ship; + +class Action { +public: + // As you can see keeping type here, require modify a base class whenever we add a new class, this volatile an open-close principle. + // We should be able to extend code without modification already implemented one + enum class Type { + Attack, + Defense, + Escape + }; + + enum class Status { + Escaped, + Defeated, + Nothing, + }; + + virtual Status operator()(Player* player, Ship* enemyShip) = 0; + virtual Type type() const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Attack.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Attack.h new file mode 100644 index 0000000..a06cba0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Attack.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Attack : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Attack; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/BattleField.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/BattleField.h new file mode 100644 index 0000000..6196660 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/BattleField.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Ship; +class Player; + +class BattleField { +public: + BattleField(Player* player, Player* enemy); + + Ship* getPlayerShip() const; + Ship* getEnemyShip() const; + std::vector players() const; + +private: + Player* _player; + Player* _enemy; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Defense.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Defense.h new file mode 100644 index 0000000..fefd271 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Defense.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Defense : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Type::Defense; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Escape.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Escape.h new file mode 100644 index 0000000..97dc54d --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/include/Battle/Escape.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Battle/Action.h" + +#include + +class Player; +class Ship; + +class Escape : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Escape; } + +private: + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Attack.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Attack.cpp new file mode 100644 index 0000000..b3f5e8a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Attack.cpp @@ -0,0 +1,22 @@ +#include "Battle/Attack.h" + +#include +#include + +#include + +Action::Status Attack::operator()(Player* player, Ship* enemyShip) { + const int damage = player->attack(*enemyShip); + std::cout << "Player ship: " << player->getShip().name() << " attack ship: " << enemyShip->name() << '\n'; + if (damage) { + std::cout << "Dealed damage: " << damage << '\n'; + } else { + std::cout << "Missed\n"; + } + + if (enemyShip->durability() <= 0) { + return Status::Defeated; + } + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/BattleField.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/BattleField.cpp new file mode 100644 index 0000000..4e10569 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/BattleField.cpp @@ -0,0 +1,16 @@ +#include "Battle/BattleField.h" + +#include + +BattleField::BattleField(Player* player, Player* enemy) + : _player{player}, _enemy{enemy} {} + +Ship* BattleField::getPlayerShip() const { + return &_player->getShip(); +} +Ship* BattleField::getEnemyShip() const { + return &_enemy->getShip(); +} +std::vector BattleField::players() const { + return {_player, _enemy}; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Defense.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Defense.cpp new file mode 100644 index 0000000..a170c81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Defense.cpp @@ -0,0 +1,13 @@ +#include "Battle/Defense.h" + +#include +#include + +#include + +Action::Status Defense::operator()(Player* player, Ship*) { + player->getShip().increaseArmor(50); + std::cout << "Player ship: " << player->getShip().name() << " defense\n"; + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Escape.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Escape.cpp new file mode 100644 index 0000000..5b222fa --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Battle/src/Escape.cpp @@ -0,0 +1,22 @@ +#include "Battle/Escape.h" + +#include +#include + +#include + +std::random_device Escape::_rd{}; + +Action::Status Escape::operator()(Player* player, Ship*) { + std::cout << "Player ship: " << player->getShip().name() << " try to escape!\n"; + + std::uniform_int_distribution dice(0, 20); + const auto res = dice(_seed); + if (res > 12) { + std::cout << "Player escaped!\n"; + return Status::Escaped; + } + + std::cout << "Escape maneuver failed!\n"; + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/CMakeLists.txt new file mode 100644 index 0000000..9434ff8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(Battle) +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/CMakeLists.txt new file mode 100644 index 0000000..db39d82 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Core src/Time.cpp src/BasicPrintVisitor.cpp src/PrettyPrintVisitor.cpp) + +target_include_directories(Core PUBLIC include) + +target_link_libraries(Core + Ship + Store +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/BasicPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/BasicPrintVisitor.h new file mode 100644 index 0000000..cd3406f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/BasicPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class BasicPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/DifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/DifficultLvlStrategy.h new file mode 100644 index 0000000..7c23854 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/DifficultLvlStrategy.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +template +class DifficultLvlStrategy { +public: + virtual Res handle(T&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/PrettyPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/PrettyPrintVisitor.h new file mode 100644 index 0000000..58dc6ad --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/PrettyPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class PrettyPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/PrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/PrintVisitor.h new file mode 100644 index 0000000..bec94c0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/PrintVisitor.h @@ -0,0 +1,11 @@ +#pragma once + +class Store; +class Ship; + +class PrintVisitor { +public: + virtual ~PrintVisitor() = default; + virtual void visit(const Store&) const = 0; + virtual void visit(const Ship&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/BasicPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/BasicPrintVisitor.cpp new file mode 100644 index 0000000..05960c1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/BasicPrintVisitor.cpp @@ -0,0 +1,22 @@ +#include + +#include +#include +#include +#include + +void BasicPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << std::setw(15) << cargo->getPrice() << "\n"; + } +} + +void BasicPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << "\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/PrettyPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/PrettyPrintVisitor.cpp new file mode 100644 index 0000000..99b6738 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/PrettyPrintVisitor.cpp @@ -0,0 +1,33 @@ +#include + +#include +#include +#include +#include + +void PrettyPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} + +void PrettyPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/CMakeLists.txt new file mode 100644 index 0000000..b266b3f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(Player src/EnemyEasyDifficultLvlStrategy.cpp src/EnemyHardDifficultLvlStrategy.cpp src/Player.cpp src/RealPlayer.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Battle + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..e44bd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/Enemy.h @@ -0,0 +1,66 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include +#include +#include + +#include +#include + +template +class Enemy : public Player { +public: + Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + std::unique_ptr> _strategy; + DamageVisitor _damageVisitor; +}; + +template +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor) + : _name(name), _ship(std::move(ship)), _strategy(std::move(strategy)), _damageVisitor(visitor) {} + +template +int Enemy::attack(Ship& playerShip) { + if (const auto damage = _strategy->handle(playerShip)) { + for (auto& cargo : playerShip.cargoes()) { + cargo->accept(_damageVisitor); + } + return damage; + } + + return 0; +} + +template +Ship* Enemy::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getPlayerShip(); +} + +template +std::unique_ptr Enemy::chooseAction(const BattleField& battleField) const { + static bool flag = true; + if (flag) { + flag = !flag; + return std::make_unique(); + } + + flag = !flag; + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..d2b7b05 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyEasyDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h new file mode 100644 index 0000000..ac01b4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyHardDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/Player.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/Player.h new file mode 100644 index 0000000..7717389 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/Player.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include + +class BattleField; +class Ship; + +class Player { +public: + virtual ~Player() = default; + virtual int attack(Ship& playerShip) = 0; + virtual Ship& getShip() = 0; + virtual const Ship& getShip() const = 0; + + Action::Status makeAction(const BattleField& battleField); + +protected: + virtual Ship* chooseEnemyShip(const BattleField& battleField) const = 0; + virtual std::unique_ptr chooseAction(const BattleField& battleField) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/RealPlayer.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/RealPlayer.h new file mode 100644 index 0000000..04d8b1a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/include/Player/RealPlayer.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include + +class RealPlayer : public Player { +public: + RealPlayer(const std::string& name, std::unique_ptr&& ship); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..0ff5663 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp @@ -0,0 +1,28 @@ +#include "Player/EnemyEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyEasyDifficultLvlStrategy::_rd{}; + +EnemyEasyDifficultLvlStrategy::EnemyEasyDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyEasyDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 5) { + // miss + return 0; + } else if (res > 19) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(25, 50); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/EnemyHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/EnemyHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..790cd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/EnemyHardDifficultLvlStrategy.cpp @@ -0,0 +1,31 @@ +#include "Player/EnemyHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyHardDifficultLvlStrategy::_rd{}; + +EnemyHardDifficultLvlStrategy::EnemyHardDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyHardDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 3) { + // miss + return 0; + } else if (res == 20) { + // turbo critical + multiplier = 3; + } else if (res > 15) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(30, 60); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/Player.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/Player.cpp new file mode 100644 index 0000000..5e1f83b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/Player.cpp @@ -0,0 +1,11 @@ +#include "Player/Player.h" + +Action::Status Player::makeAction(const BattleField& battleField) { + std::unique_ptr action = chooseAction(battleField); + if (action->type() == Action::Type::Attack) { + Ship* enemyShip = chooseEnemyShip(battleField); + return (*action)(this, enemyShip); + } + + return (*action)(this, nullptr); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/RealPlayer.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/RealPlayer.cpp new file mode 100644 index 0000000..b5cd4de --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Player/src/RealPlayer.cpp @@ -0,0 +1,56 @@ +#include "Player/RealPlayer.h" + +#include +#include +#include +#include +#include + +#include + +std::random_device RealPlayer::_rd{}; + +RealPlayer::RealPlayer(const std::string& name, std::unique_ptr&& ship) + : _name(name), _ship(std::move(ship)) {} + +int RealPlayer::attack(Ship& playerShip) { + std::uniform_int_distribution dice(0, 20); + const int res = dice(_seed); + int input = 0; + int damage = 0; + std::cout << "Choose Ammo: 1) Round Shot 2) Chain Shot 3) Grape Shot: "; + std::cin >> input; + + if (input == 1 && res > 4) { + damage = 50; + } else if (input == 2 && res > 7) { + damage = 80; + } else if (input == 3 && res > 10) { + damage = 100; + } else { + return 0; + } + + playerShip.takeDamage(damage); + return damage; +} + +Ship* RealPlayer::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getEnemyShip(); +} + +std::unique_ptr RealPlayer::chooseAction(const BattleField& battleField) const { + int input = 0; + std::cout << "Choose Action: 1) Attack 2) Defense 3) Escape: "; + std::cin >> input; + + if (input == 1) { + return std::make_unique(); + } + if (input == 3) { + return std::make_unique(); + } + + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..a1adb4e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp + src/ShipEasyDifficultLvlStrategy.cpp + src/ShipHardDifficultLvlStrategy.cpp + src/CargoDamageVisitor.cpp + src/ShipBuilder.cpp + src/ShipJsonBuilder.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core + nlohmann_json::nlohmann_json +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..3771b7a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +#include "Ship/CargoDamageVisitor.h" + +#include + +struct Cargo { + size_t amount; + + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; + virtual void accept(const CargoDamageVisitor& visitor) = 0; +}; + +struct Fruit : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Item : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Alcohol : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/CargoDamageVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/CargoDamageVisitor.h new file mode 100644 index 0000000..6e84c58 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/CargoDamageVisitor.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class Fruit; +class Alcohol; +class Item; + +class CargoDamageVisitor { +public: + CargoDamageVisitor() = default; + virtual ~CargoDamageVisitor() = default; + CargoDamageVisitor(const CargoDamageVisitor&) = default; + CargoDamageVisitor(CargoDamageVisitor&&) = default; + CargoDamageVisitor& operator=(const CargoDamageVisitor&) = default; + CargoDamageVisitor& operator=(CargoDamageVisitor&&) = default; + + virtual void operator()(Fruit& fruit) const; + virtual void operator()(Alcohol& alcohol) const; + virtual void operator()(Item& item) const; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..88e6495 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/Ship.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include "Ship/Cargo.h" + +class PrintVisitor; +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + const std::vector>& cargoes() const; + + void increaseArmor(int armor) { _armor += armor; } + int durability() const { return _durability; } + int armor() const { return _armor; } + +private: + // Allow to be created only by std::unique_ptr + friend std::unique_ptr std::make_unique(); + friend class ShipBuilder; + Ship() = default; + void initialize(); + + bool unloadCargo(const std::string& cargoName, int amount); + void rebel(); + + Time* _time; + std::unique_ptr> _strategy; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + int _armor{0}; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipBuilder.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipBuilder.h new file mode 100644 index 0000000..8c1922a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipBuilder.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include + +class PrintVisitor; +class Time; + +class ShipBuilder { +public: + ShipBuilder(); + + [[nodiscard]] std::unique_ptr build(); + + ShipBuilder& setTime(Time* time); + ShipBuilder& setStrategy(std::unique_ptr> strategy); + ShipBuilder& setName(const std::string& name); + ShipBuilder& setCapacity(int capacity); + ShipBuilder& setCrew(int crew); + ShipBuilder& setVisitor(std::unique_ptr visitor); + ShipBuilder& setArmor(int armor); + ShipBuilder& setDurability(int durability); + +private: + std::unique_ptr _ship; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..ce7627a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h new file mode 100644 index 0000000..a5f6a64 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipJsonBuilder.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipJsonBuilder.h new file mode 100644 index 0000000..ff495c8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/include/Ship/ShipJsonBuilder.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include + +#include "Ship/ShipBuilder.h" + +using json = nlohmann::json; + +class Time; +class Ship; + +class ShipJsonBuilder : private ShipBuilder { +public: + ShipJsonBuilder(const std::filesystem::path& path); + + std::unique_ptr buildBrig(Time* time, const std::string& name); + std::unique_ptr buildFrigate(Time* time, const std::string& name); + std::unique_ptr buildGaleon(Time* time, const std::string& name); + +private: + void parseFile(const std::filesystem::path& path); + + json _shipsData; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..31d75b7 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/Cargo.cpp @@ -0,0 +1,43 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +void Fruit::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +void Item::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} + +void Alcohol::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/CargoDamageVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/CargoDamageVisitor.cpp new file mode 100644 index 0000000..6ff89e2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/CargoDamageVisitor.cpp @@ -0,0 +1,20 @@ +#include + +#include + +std::random_device CargoDamageVisitor::_rd{}; + +void CargoDamageVisitor::operator()(Fruit& fruit) const { + std::uniform_int_distribution dice(0, 5); + fruit.amount -= dice(_seed); +} + +void CargoDamageVisitor::operator()(Alcohol& alcohol) const { + std::uniform_int_distribution dice(0, 10); + alcohol.amount -= (dice(_seed) / 2); +} + +void CargoDamageVisitor::operator()(Item& item) const { + std::uniform_int_distribution dice(0, 20); + item.amount -= (dice(_seed) / 4); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..6871c94 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/Ship.cpp @@ -0,0 +1,107 @@ +#include "Ship/Ship.h" + +#include +#include + +#include +#include +#include +#include + +void Ship::initialize() { + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + if (!_strategy->handle(*this)) { + rebel(); + } +} + +void Ship::printCargo() const { + _visitor->visit(*this); +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const std::string& cargoName, int amount, StatusCode& code) noexcept { + if (!unloadCargo(cargoName, amount)) { + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const std::string& cargoName, int amount) { + if (!unloadCargo(cargoName, amount)) { + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _armor -= damage; + if (_armor >= 0) { + return; + } + + _durability += _armor; + _armor = 0; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +const std::vector>& Ship::cargoes() const { + return _cargoes; +} + +bool Ship::unloadCargo(const std::string& cargoName, int amount) { + while (amount != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount > amount) { + (*it)->amount -= amount; + return true; + } + amount -= (*it)->amount; + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipBuilder.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipBuilder.cpp new file mode 100644 index 0000000..fb77e5f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipBuilder.cpp @@ -0,0 +1,68 @@ +#include "Ship/ShipBuilder.h" + +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include +#include + +ShipBuilder::ShipBuilder() + : _ship(std::make_unique()) { + _ship->_strategy = std::make_unique(); + _ship->_visitor = std::make_unique(); +} + +std::unique_ptr ShipBuilder::build() { + if (!_ship) { + std::cout << "Builder may be use once\n"; + return nullptr; + } + + // Check mandatory fields + if (!_ship->_time || _ship->_name.empty() || _ship->_capacity == -1) { + std::cout << "Mandatory fields are not set!\n"; + return nullptr; + } + + _ship->initialize(); + return std::move(_ship); +} + +ShipBuilder& ShipBuilder::setTime(Time* time) { + _ship->_time = time; + return *this; +} + +ShipBuilder& ShipBuilder::setStrategy(std::unique_ptr> strategy) { + _ship->_strategy = std::move(strategy); + return *this; +} + +ShipBuilder& ShipBuilder::setName(const std::string& name) { + _ship->_name = name; + return *this; +} + +ShipBuilder& ShipBuilder::setCapacity(int capacity) { + _ship->_capacity = capacity; + return *this; +} + +ShipBuilder& ShipBuilder::setCrew(int crew) { + _ship->_crew = crew; + return *this; +} + +ShipBuilder& ShipBuilder::setVisitor(std::unique_ptr visitor) { + _ship->_visitor = std::move(visitor); + return *this; +} + +ShipBuilder& ShipBuilder::setArmor(int armor) { + _ship->_armor = armor; + return *this; +} + +ShipBuilder& ShipBuilder::setDurability(int durability) { + _ship->_durability = durability; + return *this; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..6d1a148 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipEasyDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..2a6815a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipHardDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipHardDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew(), status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew(), status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipJsonBuilder.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipJsonBuilder.cpp new file mode 100644 index 0000000..a9b653a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Ship/src/ShipJsonBuilder.cpp @@ -0,0 +1,48 @@ +#include "Ship/ShipJsonBuilder.h" + +#include "Ship/Ship.h" + +#include +#include +#include + +ShipJsonBuilder::ShipJsonBuilder(const std::filesystem::path& path) { + parseFile(path); +} + +std::unique_ptr ShipJsonBuilder::buildBrig(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["brige"]["capacity"]) + .setCrew(_shipsData["brige"]["crew"]) + .setArmor(_shipsData["brige"]["armor"]) + .setDurability(_shipsData["brige"]["durability"]) + .build(); +} +std::unique_ptr ShipJsonBuilder::buildFrigate(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["frigate"]["capacity"]) + .setCrew(_shipsData["frigate"]["crew"]) + .setArmor(_shipsData["frigate"]["armor"]) + .setDurability(_shipsData["frigate"]["durability"]) + .build(); +} +std::unique_ptr ShipJsonBuilder::buildGaleon(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["galeon"]["capacity"]) + .setCrew(_shipsData["galeon"]["crew"]) + .setArmor(_shipsData["galeon"]["armor"]) + .setDurability(_shipsData["galeon"]["durability"]) + .build(); +} + +void ShipJsonBuilder::parseFile(const std::filesystem::path& path) { + std::ifstream file(path); + if (!file.is_open()) { + std::cout << "Can't open a file! erno: " << strerror(errno) << '\n'; + abort(); + } + _shipsData = json::parse(file); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/include/Store/Store.h new file mode 100644 index 0000000..fbbbf9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/include/Store/Store.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class PrintVisitor; + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos, std::unique_ptr&& visitor); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + const std::vector>& cargoes() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/src/Store.cpp new file mode 100644 index 0000000..07a9e35 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/src/Store/src/Store.cpp @@ -0,0 +1,41 @@ +#include "Store/Store.h" + +#include + +Store::Store(std::vector>&& cargos, std::unique_ptr&& visitor) + : _seed(_rd()), _cargoes(std::move(cargos)), _visitor(std::move(visitor)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +const std::vector>& Store::cargoes() const { + return _cargoes; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +void Store::printCargo() const { + _visitor->visit(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/builder/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/CMakeLists.txt new file mode 100644 index 0000000..751c5ff --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +include(FetchContent) +FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG v3.11.3 +) +FetchContent_MakeAvailable(json) + +target_link_libraries(${PROJECT_NAME} + Battle + Ship + Store + Core + Player + nlohmann_json::nlohmann_json +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/README.md b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/README.md new file mode 100644 index 0000000..f3a591a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/README.md @@ -0,0 +1,25 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +* Go into directory `Ship` and implement `DecoratedCargo`: + * It should take a `std::unique_ptr` and has protected getter to this field. +* Implement `Vunreable` class: + * It should inherit from `TimeObserver` and `DecoratedCargo` + * It should take additional parameters in C'tor: `Time`, `durability` and `maxDurability` + * It should simulate time elapsing. Every day should subtract durability + * It should return price back on current durability of cargo + +## Exercise 2 + +* Implement `Valuable` class: + * It should inherit from `DecoratedCargo` + * it should be a template that takes `enum` type of value + * It should return value based on type (cast it to enum and multiply by current value) +* Try to compile code form `main.cpp` +* You may have some trouble with running code if you don't write a code carefully :) think where is a problem. diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/main.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/main.cpp new file mode 100644 index 0000000..dd12d5f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/main.cpp @@ -0,0 +1,53 @@ +#include +#include +#include + +#include "Battle/BattleField.h" +#include "Core/BasicPrintVisitor.h" +#include "Core/FullInfoPrintVisitor.h" +#include "Core/PrettyPrintVisitor.h" +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Player/RealPlayer.h" +#include "Ship/AlcoholFactory.h" +#include "Ship/AlcoholType.h" +#include "Ship/Cargo.h" +#include "Ship/CargoDamageVisitor.h" +#include "Ship/FruitFactory.h" +#include "Ship/ItemFactory.h" +#include "Ship/ItemType.h" +#include "Ship/Ship.h" +#include "Ship/ShipBuilder.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Ship/ShipJsonBuilder.h" +#include "Ship/Valuable.h" +#include "Ship/Vulnerable.h" +#include "Store/Store.h" + +int main() { + Time time; + + auto ship = ShipBuilder() + .setTime(&time) + .setName("Black Widow") + .setCapacity(2500) + .setCrew(40) + .setStrategy(std::make_unique()) + .setVisitor(std::make_unique()) + .setArmor(100) + .setDurability(1000) + .build(); + ship->load(std::make_unique>(AlcoholFactory().create(800, 40), AlcoholType::Seasoned)); + ship->load(std::make_unique(FruitFactory().create(500), &time, 15, 15)); + ship->load(std::make_unique(FruitFactory().create(700), &time, 20, 20)); + ship->load(std::make_unique(std::make_unique>(ItemFactory().create(250), ItemType::Epic), &time, 100, 100)); + + for (size_t i = 1; i <= 15; ++i) { + std::cout << "day: " << i << '\n'; + ship->printCargo(); + ++time; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/ships.json b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/ships.json new file mode 100644 index 0000000..9b19770 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/ships.json @@ -0,0 +1,20 @@ +{ + "brige":{ + "capacity":1000, + "crew":40, + "durability":1000, + "armor":100 + }, + "frigate":{ + "capacity":1500, + "crew":70, + "durability":2000, + "armor":500 + }, + "galeon":{ + "capacity":2500, + "crew":120, + "durability":3000, + "armor":1000 + } + } \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/CMakeLists.txt new file mode 100644 index 0000000..acd8033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Battle src/Defense.cpp src/BattleField.cpp src/Attack.cpp src/Escape.cpp) + +target_include_directories(Battle PUBLIC include) + +target_link_libraries(Battle + Ship + Player +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Action.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Action.h new file mode 100644 index 0000000..f271d40 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Action.h @@ -0,0 +1,24 @@ +#pragma once + +class Player; +class Ship; + +class Action { +public: + // As you can see keeping type here, require modify a base class whenever we add a new class, this volatile an open-close principle. + // We should be able to extend code without modification already implemented one + enum class Type { + Attack, + Defense, + Escape + }; + + enum class Status { + Escaped, + Defeated, + Nothing, + }; + + virtual Status operator()(Player* player, Ship* enemyShip) = 0; + virtual Type type() const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Attack.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Attack.h new file mode 100644 index 0000000..a06cba0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Attack.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Attack : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Attack; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/BattleField.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/BattleField.h new file mode 100644 index 0000000..6196660 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/BattleField.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Ship; +class Player; + +class BattleField { +public: + BattleField(Player* player, Player* enemy); + + Ship* getPlayerShip() const; + Ship* getEnemyShip() const; + std::vector players() const; + +private: + Player* _player; + Player* _enemy; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Defense.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Defense.h new file mode 100644 index 0000000..fefd271 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Defense.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Defense : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Type::Defense; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Escape.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Escape.h new file mode 100644 index 0000000..97dc54d --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/include/Battle/Escape.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Battle/Action.h" + +#include + +class Player; +class Ship; + +class Escape : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Escape; } + +private: + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Attack.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Attack.cpp new file mode 100644 index 0000000..b3f5e8a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Attack.cpp @@ -0,0 +1,22 @@ +#include "Battle/Attack.h" + +#include +#include + +#include + +Action::Status Attack::operator()(Player* player, Ship* enemyShip) { + const int damage = player->attack(*enemyShip); + std::cout << "Player ship: " << player->getShip().name() << " attack ship: " << enemyShip->name() << '\n'; + if (damage) { + std::cout << "Dealed damage: " << damage << '\n'; + } else { + std::cout << "Missed\n"; + } + + if (enemyShip->durability() <= 0) { + return Status::Defeated; + } + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/BattleField.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/BattleField.cpp new file mode 100644 index 0000000..4e10569 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/BattleField.cpp @@ -0,0 +1,16 @@ +#include "Battle/BattleField.h" + +#include + +BattleField::BattleField(Player* player, Player* enemy) + : _player{player}, _enemy{enemy} {} + +Ship* BattleField::getPlayerShip() const { + return &_player->getShip(); +} +Ship* BattleField::getEnemyShip() const { + return &_enemy->getShip(); +} +std::vector BattleField::players() const { + return {_player, _enemy}; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Defense.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Defense.cpp new file mode 100644 index 0000000..a170c81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Defense.cpp @@ -0,0 +1,13 @@ +#include "Battle/Defense.h" + +#include +#include + +#include + +Action::Status Defense::operator()(Player* player, Ship*) { + player->getShip().increaseArmor(50); + std::cout << "Player ship: " << player->getShip().name() << " defense\n"; + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Escape.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Escape.cpp new file mode 100644 index 0000000..5b222fa --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Battle/src/Escape.cpp @@ -0,0 +1,22 @@ +#include "Battle/Escape.h" + +#include +#include + +#include + +std::random_device Escape::_rd{}; + +Action::Status Escape::operator()(Player* player, Ship*) { + std::cout << "Player ship: " << player->getShip().name() << " try to escape!\n"; + + std::uniform_int_distribution dice(0, 20); + const auto res = dice(_seed); + if (res > 12) { + std::cout << "Player escaped!\n"; + return Status::Escaped; + } + + std::cout << "Escape maneuver failed!\n"; + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/CMakeLists.txt new file mode 100644 index 0000000..9434ff8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(Battle) +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/CMakeLists.txt new file mode 100644 index 0000000..25b294b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Core src/Time.cpp src/BasicPrintVisitor.cpp src/PrettyPrintVisitor.cpp src/FullInfoPrintVisitor.cpp) + +target_include_directories(Core PUBLIC include) + +target_link_libraries(Core + Ship + Store +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/BasicPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/BasicPrintVisitor.h new file mode 100644 index 0000000..cd3406f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/BasicPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class BasicPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/DifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/DifficultLvlStrategy.h new file mode 100644 index 0000000..7c23854 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/DifficultLvlStrategy.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +template +class DifficultLvlStrategy { +public: + virtual Res handle(T&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/FullInfoPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/FullInfoPrintVisitor.h new file mode 100644 index 0000000..c932bc6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/FullInfoPrintVisitor.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class FullInfoPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; + +private: + void print() const; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/PrettyPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/PrettyPrintVisitor.h new file mode 100644 index 0000000..58dc6ad --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/PrettyPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class PrettyPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/PrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/PrintVisitor.h new file mode 100644 index 0000000..bec94c0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/PrintVisitor.h @@ -0,0 +1,11 @@ +#pragma once + +class Store; +class Ship; + +class PrintVisitor { +public: + virtual ~PrintVisitor() = default; + virtual void visit(const Store&) const = 0; + virtual void visit(const Ship&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/BasicPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/BasicPrintVisitor.cpp new file mode 100644 index 0000000..a0afe9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/BasicPrintVisitor.cpp @@ -0,0 +1,22 @@ +#include + +#include +#include +#include +#include + +void BasicPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount() << std::setw(15) << cargo->getPrice() << "\n"; + } +} + +void BasicPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount() << "\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/FullInfoPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/FullInfoPrintVisitor.cpp new file mode 100644 index 0000000..a43d164 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/FullInfoPrintVisitor.cpp @@ -0,0 +1,24 @@ +#include + +#include +#include +#include +#include + +void FullInfoPrintVisitor::visit(const Store& store) const { + std::cout << "Don't have time to implement this, sorry xD\n"; +} + +void FullInfoPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount() << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/PrettyPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/PrettyPrintVisitor.cpp new file mode 100644 index 0000000..e639a1b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/PrettyPrintVisitor.cpp @@ -0,0 +1,33 @@ +#include + +#include +#include +#include +#include + +void PrettyPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount() << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} + +void PrettyPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount() << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/CMakeLists.txt new file mode 100644 index 0000000..b266b3f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(Player src/EnemyEasyDifficultLvlStrategy.cpp src/EnemyHardDifficultLvlStrategy.cpp src/Player.cpp src/RealPlayer.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Battle + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..e44bd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/Enemy.h @@ -0,0 +1,66 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include +#include +#include + +#include +#include + +template +class Enemy : public Player { +public: + Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + std::unique_ptr> _strategy; + DamageVisitor _damageVisitor; +}; + +template +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor) + : _name(name), _ship(std::move(ship)), _strategy(std::move(strategy)), _damageVisitor(visitor) {} + +template +int Enemy::attack(Ship& playerShip) { + if (const auto damage = _strategy->handle(playerShip)) { + for (auto& cargo : playerShip.cargoes()) { + cargo->accept(_damageVisitor); + } + return damage; + } + + return 0; +} + +template +Ship* Enemy::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getPlayerShip(); +} + +template +std::unique_ptr Enemy::chooseAction(const BattleField& battleField) const { + static bool flag = true; + if (flag) { + flag = !flag; + return std::make_unique(); + } + + flag = !flag; + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..d2b7b05 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyEasyDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h new file mode 100644 index 0000000..ac01b4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyHardDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/Player.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/Player.h new file mode 100644 index 0000000..7717389 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/Player.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include + +class BattleField; +class Ship; + +class Player { +public: + virtual ~Player() = default; + virtual int attack(Ship& playerShip) = 0; + virtual Ship& getShip() = 0; + virtual const Ship& getShip() const = 0; + + Action::Status makeAction(const BattleField& battleField); + +protected: + virtual Ship* chooseEnemyShip(const BattleField& battleField) const = 0; + virtual std::unique_ptr chooseAction(const BattleField& battleField) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/RealPlayer.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/RealPlayer.h new file mode 100644 index 0000000..04d8b1a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/include/Player/RealPlayer.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Player/Player.h" + +#include +#include +#include + +class RealPlayer : public Player { +public: + RealPlayer(const std::string& name, std::unique_ptr&& ship); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +protected: + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + +private: + std::string _name; + std::unique_ptr _ship; + static std::random_device _rd; + std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..0ff5663 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp @@ -0,0 +1,28 @@ +#include "Player/EnemyEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyEasyDifficultLvlStrategy::_rd{}; + +EnemyEasyDifficultLvlStrategy::EnemyEasyDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyEasyDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 5) { + // miss + return 0; + } else if (res > 19) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(25, 50); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/EnemyHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/EnemyHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..790cd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/EnemyHardDifficultLvlStrategy.cpp @@ -0,0 +1,31 @@ +#include "Player/EnemyHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyHardDifficultLvlStrategy::_rd{}; + +EnemyHardDifficultLvlStrategy::EnemyHardDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyHardDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 3) { + // miss + return 0; + } else if (res == 20) { + // turbo critical + multiplier = 3; + } else if (res > 15) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(30, 60); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/Player.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/Player.cpp new file mode 100644 index 0000000..5e1f83b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/Player.cpp @@ -0,0 +1,11 @@ +#include "Player/Player.h" + +Action::Status Player::makeAction(const BattleField& battleField) { + std::unique_ptr action = chooseAction(battleField); + if (action->type() == Action::Type::Attack) { + Ship* enemyShip = chooseEnemyShip(battleField); + return (*action)(this, enemyShip); + } + + return (*action)(this, nullptr); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/RealPlayer.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/RealPlayer.cpp new file mode 100644 index 0000000..b5cd4de --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Player/src/RealPlayer.cpp @@ -0,0 +1,56 @@ +#include "Player/RealPlayer.h" + +#include +#include +#include +#include +#include + +#include + +std::random_device RealPlayer::_rd{}; + +RealPlayer::RealPlayer(const std::string& name, std::unique_ptr&& ship) + : _name(name), _ship(std::move(ship)) {} + +int RealPlayer::attack(Ship& playerShip) { + std::uniform_int_distribution dice(0, 20); + const int res = dice(_seed); + int input = 0; + int damage = 0; + std::cout << "Choose Ammo: 1) Round Shot 2) Chain Shot 3) Grape Shot: "; + std::cin >> input; + + if (input == 1 && res > 4) { + damage = 50; + } else if (input == 2 && res > 7) { + damage = 80; + } else if (input == 3 && res > 10) { + damage = 100; + } else { + return 0; + } + + playerShip.takeDamage(damage); + return damage; +} + +Ship* RealPlayer::chooseEnemyShip(const BattleField& battleField) const { + // To simplify palyer and enemy has one ship + return battleField.getEnemyShip(); +} + +std::unique_ptr RealPlayer::chooseAction(const BattleField& battleField) const { + int input = 0; + std::cout << "Choose Action: 1) Attack 2) Defense 3) Escape: "; + std::cin >> input; + + if (input == 1) { + return std::make_unique(); + } + if (input == 3) { + return std::make_unique(); + } + + return std::make_unique(); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..a1adb4e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp + src/ShipEasyDifficultLvlStrategy.cpp + src/ShipHardDifficultLvlStrategy.cpp + src/CargoDamageVisitor.cpp + src/ShipBuilder.cpp + src/ShipJsonBuilder.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core + nlohmann_json::nlohmann_json +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/AlcoholFactory.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/AlcoholFactory.h new file mode 100644 index 0000000..60a3ed6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/AlcoholFactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include +#include + +class AlcoholFactory : public CargoFactory { +public: + std::unique_ptr create(size_t amount, int power) override { + return std::make_unique(amount, power); + } +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/AlcoholType.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/AlcoholType.h new file mode 100644 index 0000000..a59d85a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/AlcoholType.h @@ -0,0 +1,6 @@ +#pragma once + +enum class AlcoholType { White = 1, + Spiced = 2, + Dark = 3, + Seasoned = 5 }; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..a52042f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include + +#include "Ship/CargoDamageVisitor.h" + +#include + +struct Cargo { + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + size_t amount() const { return _amount; } + size_t& amount() { return _amount; } + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; + virtual void accept(const CargoDamageVisitor& visitor) = 0; + +private: + size_t _amount; +}; + +struct Fruit : public Cargo { + static constexpr int BASE_PRICE = 10; + + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Item : public Cargo { + static constexpr int BASE_PRICE = 100; + + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Alcohol : public Cargo { + static constexpr int MAX_POWER = 96; + static constexpr int BASE_PRICE = 100; + int power; + + Alcohol(size_t amount, int power); + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/CargoDamageVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/CargoDamageVisitor.h new file mode 100644 index 0000000..6e84c58 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/CargoDamageVisitor.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class Fruit; +class Alcohol; +class Item; + +class CargoDamageVisitor { +public: + CargoDamageVisitor() = default; + virtual ~CargoDamageVisitor() = default; + CargoDamageVisitor(const CargoDamageVisitor&) = default; + CargoDamageVisitor(CargoDamageVisitor&&) = default; + CargoDamageVisitor& operator=(const CargoDamageVisitor&) = default; + CargoDamageVisitor& operator=(CargoDamageVisitor&&) = default; + + virtual void operator()(Fruit& fruit) const; + virtual void operator()(Alcohol& alcohol) const; + virtual void operator()(Item& item) const; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/CargoFactory.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/CargoFactory.h new file mode 100644 index 0000000..53c1e9f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/CargoFactory.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +class Cargo; + +template +class CargoFactory { +public: + virtual std::unique_ptr create(size_t amount, Args... args) = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/FruitFactory.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/FruitFactory.h new file mode 100644 index 0000000..3906a69 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/FruitFactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include +#include + +class FruitFactory : public CargoFactory<> { +public: + std::unique_ptr create(size_t amount) override { + return std::make_unique(amount); + } +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ItemFactory.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ItemFactory.h new file mode 100644 index 0000000..fc949e3 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ItemFactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include +#include + +class ItemFactory : public CargoFactory<> { +public: + std::unique_ptr create(size_t amount) override { + return std::make_unique(amount); + } +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ItemType.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ItemType.h new file mode 100644 index 0000000..266429b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ItemType.h @@ -0,0 +1,6 @@ +#pragma once + +enum class ItemType { Common = 1, + Rare = 3, + Epic = 10, + Legendary = 25 }; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..88e6495 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/Ship.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include "Ship/Cargo.h" + +class PrintVisitor; +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + const std::vector>& cargoes() const; + + void increaseArmor(int armor) { _armor += armor; } + int durability() const { return _durability; } + int armor() const { return _armor; } + +private: + // Allow to be created only by std::unique_ptr + friend std::unique_ptr std::make_unique(); + friend class ShipBuilder; + Ship() = default; + void initialize(); + + bool unloadCargo(const std::string& cargoName, int amount); + void rebel(); + + Time* _time; + std::unique_ptr> _strategy; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + int _armor{0}; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipBuilder.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipBuilder.h new file mode 100644 index 0000000..8c1922a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipBuilder.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include + +class PrintVisitor; +class Time; + +class ShipBuilder { +public: + ShipBuilder(); + + [[nodiscard]] std::unique_ptr build(); + + ShipBuilder& setTime(Time* time); + ShipBuilder& setStrategy(std::unique_ptr> strategy); + ShipBuilder& setName(const std::string& name); + ShipBuilder& setCapacity(int capacity); + ShipBuilder& setCrew(int crew); + ShipBuilder& setVisitor(std::unique_ptr visitor); + ShipBuilder& setArmor(int armor); + ShipBuilder& setDurability(int durability); + +private: + std::unique_ptr _ship; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..ce7627a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h new file mode 100644 index 0000000..a5f6a64 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipJsonBuilder.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipJsonBuilder.h new file mode 100644 index 0000000..ff495c8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/include/Ship/ShipJsonBuilder.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include + +#include "Ship/ShipBuilder.h" + +using json = nlohmann::json; + +class Time; +class Ship; + +class ShipJsonBuilder : private ShipBuilder { +public: + ShipJsonBuilder(const std::filesystem::path& path); + + std::unique_ptr buildBrig(Time* time, const std::string& name); + std::unique_ptr buildFrigate(Time* time, const std::string& name); + std::unique_ptr buildGaleon(Time* time, const std::string& name); + +private: + void parseFile(const std::filesystem::path& path); + + json _shipsData; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..0fa653f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/Cargo.cpp @@ -0,0 +1,46 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : _amount(amount) {} + +size_t Fruit::getPrice() const { + return BASE_PRICE; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +void Fruit::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Item::getPrice() const { + return BASE_PRICE; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +void Item::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +Alcohol::Alcohol(size_t amount, int power) + : Cargo(amount), power(power) {} + +size_t Alcohol::getPrice() const { + return (power * BASE_PRICE) / MAX_POWER; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} + +void Alcohol::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/CargoDamageVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/CargoDamageVisitor.cpp new file mode 100644 index 0000000..0792d32 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/CargoDamageVisitor.cpp @@ -0,0 +1,20 @@ +#include + +#include + +std::random_device CargoDamageVisitor::_rd{}; + +void CargoDamageVisitor::operator()(Fruit& fruit) const { + std::uniform_int_distribution dice(0, 5); + fruit.amount() -= dice(_seed); +} + +void CargoDamageVisitor::operator()(Alcohol& alcohol) const { + std::uniform_int_distribution dice(0, 10); + alcohol.amount() -= (dice(_seed) / 2); +} + +void CargoDamageVisitor::operator()(Item& item) const { + std::uniform_int_distribution dice(0, 20); + item.amount() -= (dice(_seed) / 4); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..6754047 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/Ship.cpp @@ -0,0 +1,108 @@ +#include "Ship/Ship.h" + +#include +#include + +#include +#include +#include +#include + +void Ship::initialize() { + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + if (!_strategy->handle(*this)) { + rebel(); + } +} + +void Ship::printCargo() const { + _visitor->visit(*this); +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount()) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const std::string& cargoName, int amount, StatusCode& code) noexcept { + if (!unloadCargo(cargoName, amount)) { + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + std::cout << "cap: " << _capacity << " | amount: " << cargo->amount() << std::endl; + if (_capacity > cargo->amount()) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const std::string& cargoName, int amount) { + if (!unloadCargo(cargoName, amount)) { + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _armor -= damage; + if (_armor >= 0) { + return; + } + + _durability += _armor; + _armor = 0; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +const std::vector>& Ship::cargoes() const { + return _cargoes; +} + +bool Ship::unloadCargo(const std::string& cargoName, int amount) { + while (amount != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount() > amount) { + (*it)->amount() -= amount; + return true; + } + amount -= (*it)->amount(); + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipBuilder.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipBuilder.cpp new file mode 100644 index 0000000..fb77e5f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipBuilder.cpp @@ -0,0 +1,68 @@ +#include "Ship/ShipBuilder.h" + +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include +#include + +ShipBuilder::ShipBuilder() + : _ship(std::make_unique()) { + _ship->_strategy = std::make_unique(); + _ship->_visitor = std::make_unique(); +} + +std::unique_ptr ShipBuilder::build() { + if (!_ship) { + std::cout << "Builder may be use once\n"; + return nullptr; + } + + // Check mandatory fields + if (!_ship->_time || _ship->_name.empty() || _ship->_capacity == -1) { + std::cout << "Mandatory fields are not set!\n"; + return nullptr; + } + + _ship->initialize(); + return std::move(_ship); +} + +ShipBuilder& ShipBuilder::setTime(Time* time) { + _ship->_time = time; + return *this; +} + +ShipBuilder& ShipBuilder::setStrategy(std::unique_ptr> strategy) { + _ship->_strategy = std::move(strategy); + return *this; +} + +ShipBuilder& ShipBuilder::setName(const std::string& name) { + _ship->_name = name; + return *this; +} + +ShipBuilder& ShipBuilder::setCapacity(int capacity) { + _ship->_capacity = capacity; + return *this; +} + +ShipBuilder& ShipBuilder::setCrew(int crew) { + _ship->_crew = crew; + return *this; +} + +ShipBuilder& ShipBuilder::setVisitor(std::unique_ptr visitor) { + _ship->_visitor = std::move(visitor); + return *this; +} + +ShipBuilder& ShipBuilder::setArmor(int armor) { + _ship->_armor = armor; + return *this; +} + +ShipBuilder& ShipBuilder::setDurability(int durability) { + _ship->_durability = durability; + return *this; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..6d1a148 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipEasyDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..2a6815a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipHardDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipHardDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew(), status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew(), status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipJsonBuilder.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipJsonBuilder.cpp new file mode 100644 index 0000000..a9b653a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Ship/src/ShipJsonBuilder.cpp @@ -0,0 +1,48 @@ +#include "Ship/ShipJsonBuilder.h" + +#include "Ship/Ship.h" + +#include +#include +#include + +ShipJsonBuilder::ShipJsonBuilder(const std::filesystem::path& path) { + parseFile(path); +} + +std::unique_ptr ShipJsonBuilder::buildBrig(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["brige"]["capacity"]) + .setCrew(_shipsData["brige"]["crew"]) + .setArmor(_shipsData["brige"]["armor"]) + .setDurability(_shipsData["brige"]["durability"]) + .build(); +} +std::unique_ptr ShipJsonBuilder::buildFrigate(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["frigate"]["capacity"]) + .setCrew(_shipsData["frigate"]["crew"]) + .setArmor(_shipsData["frigate"]["armor"]) + .setDurability(_shipsData["frigate"]["durability"]) + .build(); +} +std::unique_ptr ShipJsonBuilder::buildGaleon(Time* time, const std::string& name) { + return setTime(time) + .setName(name) + .setCapacity(_shipsData["galeon"]["capacity"]) + .setCrew(_shipsData["galeon"]["crew"]) + .setArmor(_shipsData["galeon"]["armor"]) + .setDurability(_shipsData["galeon"]["durability"]) + .build(); +} + +void ShipJsonBuilder::parseFile(const std::filesystem::path& path) { + std::ifstream file(path); + if (!file.is_open()) { + std::cout << "Can't open a file! erno: " << strerror(errno) << '\n'; + abort(); + } + _shipsData = json::parse(file); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/include/Store/Store.h new file mode 100644 index 0000000..fbbbf9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/include/Store/Store.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class PrintVisitor; + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos, std::unique_ptr&& visitor); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + const std::vector>& cargoes() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/src/Store.cpp new file mode 100644 index 0000000..a950548 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/src/Store/src/Store.cpp @@ -0,0 +1,41 @@ +#include "Store/Store.h" + +#include + +Store::Store(std::vector>&& cargos, std::unique_ptr&& visitor) + : _seed(_rd()), _cargoes(std::move(cargos)), _visitor(std::move(visitor)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount() += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +const std::vector>& Store::cargoes() const { + return _cargoes; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +void Store::printCargo() const { + _visitor->visit(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/decorator/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/CMakeLists.txt new file mode 100644 index 0000000..91a27d2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(ExampleProject) + +set(SRC_LIST + exampleProject.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/README.md b/CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/README.md new file mode 100644 index 0000000..14082ac --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/README.md @@ -0,0 +1,10 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Run program + +Run program ./ExampleProject and check output, which should be "Hello World"; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/exampleProject.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/exampleProject.cpp new file mode 100644 index 0000000..ab426f2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/exampleProject/exampleProject.cpp @@ -0,0 +1,5 @@ +#include + +int main() { + std::cout << "Hello world!\n"; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/exception/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/exception/CMakeLists.txt new file mode 100644 index 0000000..f50ba0c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/exception/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Exception) + +set(SRC_LIST + main.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/exception/README.md b/CreatingReliableSoftwareCpp/Presentation/exercises/exception/README.md new file mode 100644 index 0000000..62a4147 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/exception/README.md @@ -0,0 +1,13 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +* Create an exception class `Exception` which inherits from `std`::exception` and two classes `ParserException` and `ReaderException` which inherit form class `Exception`. +* Rewrite a code to `ParserException` in the method `parse` and `ReaderException` in the method `read`. +* Try to catch errors in `main` and print them +* Rewrite a code once again and return `nullopt` when an error occurs instead of throwing an exception \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/exception/main.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/exception/main.cpp new file mode 100644 index 0000000..3b31264 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/exception/main.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include + +int parse(const std::string& str) { + if (str.empty()) { + std::cout << "String is empty!"; + return 0; + } + if (str.size() > 20) { + std::cout << "Value is to big to fit in integer!"; + return 0; + } + + return std::stoi(str); +} + +std::string read(const std::vector& vec) { + if (vec.empty()) { + std::cout << "Vector is empty, can't read"; + return ""; + } + if (vec.size() > 20) { + std::cout << "Vector is to big"; + return ""; + } + + return std::accumulate(vec.begin(), vec.end(), std::string{}, [](const auto& str, int num){ + if (str.empty()) { + return std::to_string(num); + } + return str + ", " + std::to_string(num); + }); +} + +int main() { + std::cout << "Parsed number: " << parse("-123") << '\n'; + std::cout << "Read numbers: " << read({1,2,3-1,-2,-3}) << '\n'; + std::cout << "Parsed number: " << parse("123456789012345678901234") << '\n'; + std::cout << "Read numbers: " << read({}) << '\n'; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/exception/soulutions/main.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/exception/soulutions/main.cpp new file mode 100644 index 0000000..abbcf1d --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/exception/soulutions/main.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include + +class Error : public std::exception { +public: + explicit Error(const std::string& what): _what(what) {} + explicit Error(const char* what): Error(std::string(what)) {} + explicit Error(std::string_view what): Error(std::string(what)) {} + const char* what() const noexcept override { return _what.c_str(); } +private: + std::string _what; +}; + +class ParserException : public Error { +public: + using Error::Error; +}; + +class ReaderException : public Error { +public: + using Error::Error; +}; + +int parse(const std::string& str) { + if (str.empty()) { + throw ParserException("String is empty!"); + } + if (str.size() > 20) { + throw ParserException("Value is to big to fit in integer!"); + } + + return std::stoi(str); +} + +std::string read(const std::vector& vec) { + if (vec.empty()) { + throw ReaderException("Vector is empty, can't read"); + } + if (vec.size() > 20) { + throw ReaderException("Vector is to big"); + return ""; + } + + return std::accumulate(vec.begin(), vec.end(), std::string{}, [](const auto& str, int num){ + if (str.empty()) { + return std::to_string(num); + } + return str + ", " + std::to_string(num); + }); +} + +int main() { + try { + std::cout << "Parsed number: " << parse("-123") << '\n'; + std::cout << "Read numbers: " << read({1,2,3-1,-2,-3}) << '\n'; + std::cout << "Parsed number: " << parse("123456789012345678901234") << '\n'; + std::cout << "Read numbers: " << read({}) << '\n'; + } catch (const ReaderException& ec) { + std::cout << "ReaderException: " << ec.what() << '\n'; + } catch (const ParserException& ec) { + std::cout << "ParserException: " << ec.what() << '\n'; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/CMakeLists.txt new file mode 100644 index 0000000..c6cd3a2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(${PROJECT_NAME} + Ship + Store + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/README.md b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/README.md new file mode 100644 index 0000000..706fe9f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/README.md @@ -0,0 +1,143 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +* Go into directory *Core* and implement *Time* and *TimeObserver* class +* Class *Time* should have 4 methods: + * void attach(TimeObserver* observer); -> attach observer + * void detach(TimeObserver* observer); -> detach observer + * Time& operator++(); -> increment day and notify observers + * size_t day() const; -> return current day +* Go into directory *Ship* and make *Ship* class inherit from *TimeObserver* +* Each time the observer will be triggered, you should give the crew food and drink +* Each crew member should consume **1** rum and **1** banana (I know they usually eat biscuits) +* If you don't have enough cargo crew should rebel +* Each day of a rebel you should subtract **5** members of the crew +* If the number of crew drops below **0**, throw an exception "Game Over" + +Example (We have 40 members of crew): +Day: 0 +crew: 40 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Rum | 300 | +|Banana | 200 | +|Banana | 150 | +|----------------|----------------| + +DAY: 1 +crew: 40 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Rum | 260 | +|Banana | 160 | +|Banana | 150 | +|----------------|----------------| + +DAY: 2 +crew: 40 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Rum | 220 | +|Banana | 120 | +|Banana | 150 | +|----------------|----------------| + +DAY: 3 +crew: 40 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Rum | 180 | +|Banana | 80 | +|Banana | 150 | +|----------------|----------------| + +DAY: 4 +crew: 40 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Rum | 140 | +|Banana | 40 | +|Banana | 150 | +|----------------|----------------| + +DAY: 5 +crew: 40 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Rum | 100 | +|Banana | 150 | +|----------------|----------------| + +DAY: 6 +crew: 40 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Rum | 60 | +|Banana | 110 | +|----------------|----------------| + +DAY: 7 +crew: 40 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Rum | 20 | +|Banana | 70 | +|----------------|----------------| + +********** Crew rebel ********** + +DAY: 8 +crew: 35 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Banana | 30 | +|----------------|----------------| + +********** Crew rebel ********** + +DAY: 9 +crew: 30 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|----------------|----------------| + +********** Crew rebel ********** + +DAY: 10 +crew: 25 +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|----------------|----------------| + +## Exercise 2 + +* Go into directory *Store* and make *Store* class inherit from *TimeObserver* +* Class *Store* should don't know anything about class *Time* +* We should attach and detach observer outside of class. Think about how you can make it exception-safe (RAII) +* Each time the observer will be triggered, you should change the number of available cargo in the store +* Each time draw a number between -50 and 50 and add it to the amount of cargo +* Print everyday cargo from the Shop and verify if the amount changes + +## Exercise 3 + +* Rewrite Observer to use modern approach -> by value semantic. +* Rewrite class Ship +* Rewrite class Store +* Question: Which class was easier to rewrite? diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/main.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/main.cpp new file mode 100644 index 0000000..363f2ea --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/main.cpp @@ -0,0 +1,22 @@ +#include + +#include "Core/Time.h" +#include "Ship/Cargo.h" +#include "Ship/Ship.h" +#include "Store/Store.h" + +int main() { + Time time; + Ship ship(&time, "Black Widow", 1000, 40); + + ship.load(std::make_unique(300)); + ship.load(std::make_unique(200)); + ship.printCargo(); + + for (int i = 0; i < 8; ++i) { + ++time; + std::cout << "\nDAY: " << time.day() << "\n"; + std::cout << "crew: " << ship.crew() << '\n'; + ship.printCargo(); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/CMakeLists.txt new file mode 100644 index 0000000..482b48c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(Core) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/CMakeLists.txt new file mode 100644 index 0000000..5db9b9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(Core src/Time.cpp) + +target_include_directories(Core PUBLIC include) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/include/Core/Time.h new file mode 100644 index 0000000..8a5e089 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/include/Core/Time.h @@ -0,0 +1,11 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..106a258 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,5 @@ +#pragma once + +struct TimeObserver { + +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/src/Time.cpp new file mode 100644 index 0000000..0ab265b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Core/src/Time.cpp @@ -0,0 +1,6 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..8523b82 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Ship src/Ship.cpp src/Cargo.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..3faa7e4 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +struct Cargo { + size_t amount; + + explicit Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; +}; + +struct Fruit : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Item : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Alcohol : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..4fde92b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/include/Ship/Ship.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include + +#include "Ship/Cargo.h" + +class Ship { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + Ship(const std::string& name, int capacity, int crew); + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const Cargo& cargo, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const Cargo& cargo); + +private: + bool consume(const std::string& cargoName); + void rebel(); + + std::string _name; + int _capacity; + int _crew; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..9c55175 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/src/Cargo.cpp @@ -0,0 +1,31 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..261bcfa --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Ship/src/Ship.cpp @@ -0,0 +1,74 @@ +#include "Ship/Ship.h" + +#include +#include +#include +#include +#include + +Ship::Ship(const std::string& name, int capacity, int crew) + : _name(name), _capacity(capacity), _crew(crew) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::printCargo() const { + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : _cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const Cargo& cargo, StatusCode& code) noexcept { + if (auto it = std::find_if(_cargoes.begin(), _cargoes.end(), [&cargo](const auto& item) { return *item == cargo; }); it != _cargoes.end()) { + _cargoes.erase(it); + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const Cargo& cargo) { + if (auto it = std::find_if(_cargoes.begin(), _cargoes.end(), [&cargo](const auto& item) { return *item == cargo; }); it != _cargoes.end()) { + _cargoes.erase(it); + throw std::runtime_error("Missing cargo"); + } +} + +bool Ship::consume(const std::string& cargoName) { + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/include/Store/Store.h new file mode 100644 index 0000000..cb4d5f3 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/include/Store/Store.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include + +class Store { +public: + Store() = default; + explicit Store(std::vector>&& cargos); + + size_t getTotalPrice() const; + std::vector getCargosName() const; + +private: + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/src/Store.cpp new file mode 100644 index 0000000..2fe4f85 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/src/Store/src/Store.cpp @@ -0,0 +1,21 @@ +#include "Store/Store.h" + +Store::Store(std::vector>&& cargos): _cargoes(std::move(cargos)) {} + +size_t Store::getTotalPrice() const { + size_t value {0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/observer/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/CMakeLists.txt new file mode 100644 index 0000000..4b33b70 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(${PROJECT_NAME} + Ship + Store + Core + Player +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/README.md b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/README.md new file mode 100644 index 0000000..180991e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/README.md @@ -0,0 +1,38 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +* Go into directory Core and implement ShipStrategy as a template class +* Strategy should have one pure virtual function: Res handle(T&) +* Implement in directory Ship class ShipEasyDifficultLvlStrategy + * Each cargo supplies 2 sailors, so if you have 40 crew, you need 20 banas and 20 rum +* Implement NextDay by using strategy class +* Run code, and verify result + +## Exercise 2 + +* Implement in directory *Player* class *PalyerEasyDifficultLvlStrategy* +    * Strategy should roll a die (1-20): +    * If result is lower than 5 -> 0 DMG +    * If result is higher than 19 -> multiple damage by 2 +    * Damage should be rolled from (25 to 50) +    * deal damage to the ship and return how much damage was deal. Print it in console +* Add all necessary implementation to the *Enemy* file +* Test it + +## Exercise 3 + +* Implement tow new classes *EnemyHardDifficultLvlStrategy* and *ShipHardDifficultLvlStrategy* + * Strategy for Ship, should subtract cargo equal crew size +    * Strategy for Enemy should roll a die (1-20): +     * If result is lower than 3 -> 0 DMG + * If result is higher than 15 but not equal 20 -> multiple damage by 3 +     * If result is higher than 19 -> multiple damage by 3 +     * Damage should be rolled from (30 to 60) +* You shouldn't modify any existing file, except the main.cpp, where you should use a new strategy +* Run code and verify the result \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/main.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/main.cpp new file mode 100644 index 0000000..38b7c17 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/main.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Ship/Cargo.h" +#include "Ship/Ship.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Store/Store.h" + +int main() { + Time time; + + Ship ship(&time, "Black Widow", 1000, 40); + ship.load(std::make_unique(300)); + ship.load(std::make_unique(200)); + ship.load(std::make_unique(150)); + ship.printCargo(); + + for (int i = 0; i < 10; ++i) { + ++time; + std::cout << "\nDAY: " << time.day() << "\n"; + std::cout << "crew: " << ship.crew() << '\n'; + ship.printCargo(); + } + + std::cout << "\n\n****************************************************\n"; + auto ship2 = std::make_unique(&time, "Queens Anne revenge", 1000, 40); + Enemy enemy("Enemy1", std::move(ship2)); + + for (int i = 0; i < 15; ++i) { + enemy.attack(ship); + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/CMakeLists.txt new file mode 100644 index 0000000..c29ff6c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/CMakeLists.txt new file mode 100644 index 0000000..5db9b9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(Core src/Time.cpp) + +target_include_directories(Core PUBLIC include) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/CMakeLists.txt new file mode 100644 index 0000000..1dc7329 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Player src/Enemy.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..4a5039b --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/include/Player/Enemy.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include +#include + +class Ship; + +class Enemy { +public: + Enemy(const std::string& name, std::unique_ptr&& ship); + + void attack(Ship& playerShip); + +private: + std::string _name; + std::unique_ptr _ship; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/src/Enemy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/src/Enemy.cpp new file mode 100644 index 0000000..d3f3a9c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Player/src/Enemy.cpp @@ -0,0 +1,15 @@ +#include "Player/Enemy.h" + +#include + +#include +#include +#include + +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship) + : _name(name), _ship(std::move(ship)) {} + +void Enemy::attack(Ship& playerShip) { + std::cout << "Player: " << _name << " attack ship: " << playerShip.name() << '\n'; + playerShip.dealDamage(100); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..a6a3997 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..b4afe1f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +struct Cargo { + size_t amount; + + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; +}; + +struct Fruit : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Item : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Alcohol : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..df72ed4 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/include/Ship/Ship.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include + +#include +#include "Ship/Cargo.h" + +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + Ship(Time* time, const std::string& name, int capacity, int crew); + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + +private: + bool consume(const std::string& cargoName); + void rebel(); + + Time* _time; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..9c55175 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/src/Cargo.cpp @@ -0,0 +1,31 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..766f7dd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Ship/src/Ship.cpp @@ -0,0 +1,114 @@ +#include "Ship/Ship.h" + +#include + +#include +#include +#include +#include +#include + +Ship::Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew) + : _time(time), _strategy(std::move(strategy)), _name(name), _capacity(capacity), _crew(crew) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + bool shouldRebel = !consume("Rum"); + shouldRebel |= !consume("Banana"); + if (shouldRebel) { + rebel(); + } +} + +void Ship::printCargo() const { + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : _cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const Cargo& cargo, StatusCode& code) noexcept { + if (auto it = std::find_if(_cargoes.begin(), _cargoes.end(), [&cargo](const auto& item) { return *item == cargo; }); it != _cargoes.end()) { + _cargoes.erase(it); + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const Cargo& cargo) { + if (auto it = std::find_if(_cargoes.begin(), _cargoes.end(), [&cargo](const auto& item) { return *item == cargo; }); it != _cargoes.end()) { + _cargoes.erase(it); + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _durability -= damage; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +bool Ship::consume(const std::string& cargoName) { + int left = _crew; + + while (left != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount > left) { + (*it)->amount -= left; + return true; + } + left -= (*it)->amount; + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/include/Store/Store.h new file mode 100644 index 0000000..1eb93cb --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/include/Store/Store.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/src/Store.cpp new file mode 100644 index 0000000..41d32fe --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/src/Store/src/Store.cpp @@ -0,0 +1,48 @@ +#include "Store/Store.h" + +#include +#include + +Store::Store(std::vector>&& cargos) + : _seed(_rd()), _cargoes(std::move(cargos)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +// Shame on me, I copy-past it. But remember DRY!! +// This is only to speed up process of creating exercises, sorry :) +void Store::printCargo() const { + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : _cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/strategy/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/CMakeLists.txt new file mode 100644 index 0000000..7103268 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Streamer) + +set(SRC_LIST + streamer.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/README.md b/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/README.md new file mode 100644 index 0000000..c37b48c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/README.md @@ -0,0 +1,17 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise + +* Open project streamer +* Create Mpeg2Streamer class +* Create MjpegStreamer class +* Allow to add data to stream +* Allow to add/remove receivers +* start/stop stream +* validate data +* Make some dummy implementations that will allow to compile code \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/solution/streamer.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/solution/streamer.cpp new file mode 100644 index 0000000..8ce0e89 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/solution/streamer.cpp @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include +#include + +class Streamer { +public: + using IpAddress = std::string; + using Port = uint16_t; + using Vlan = uint16_t; + + struct StreamInfo { + IpAddress sourceAddress_; + IpAddress destinationAddress_; + Port sourcePort_; + Port destinationPort_; + Vlan vlan_; + + bool operator==(const StreamInfo& other) const { + return std::tie(sourceAddress_, destinationAddress_, sourcePort_, destinationPort_, vlan_) == + std::tie(other.sourceAddress_, other.destinationAddress_, other.sourcePort_, other.destinationPort_, other.vlan_); + } + }; + + virtual ~Streamer() = default; + Streamer() = default; + Streamer(const Streamer&) = default; + Streamer& operator=(const Streamer&) = default; + Streamer(Streamer&&) = default; + Streamer& operator=(Streamer&&) = default; + + virtual bool addReceiver(const StreamInfo& info) = 0; + virtual bool removeReceiver(const StreamInfo& info) = 0; + virtual bool addData(const std::vector& data) = 0; + virtual bool validateData(const std::vector& data) const = 0; + virtual bool startStream() = 0; + virtual bool stopStream() = 0; + virtual bool streamInProgress() const = 0; +}; + +class StreamerImpl : public Streamer { +public: + StreamerImpl(std::initializer_list info) + : info_(info) { + std::cout << "C'tor: td::initializer_list info\n"; + } + + StreamerImpl(const StreamInfo& info) + : info_(1, info) { + std::cout << "C'tor: const StreamInfo& info\n"; + } + + bool addReceiver(const StreamInfo& info) override { + if (findReceiver(info) == std::cend(info_)) { + info_.push_back(info); + return true; + } + + return false; + } + + bool removeReceiver(const StreamInfo& info) override { + if (const auto it = findReceiver(info); it != std::cend(info_)) { + info_.erase(it); + return true; + } + + return false; + } + + bool addData(const std::vector& data) override { + // Used pure virtual functions -> this will be implemented by derived class! + if (!validateData(data) || streamInProgress()) { + return false; + } + + data_ = data; + return true; + } + +protected: + std::vector::const_iterator findReceiver(const StreamInfo& info) const { + return std::find(cbegin(info_), cend(info_), info); + } + + std::vector info_; + std::vector data_; +}; + +class Mpeg2Streamer : public StreamerImpl { +public: + using StreamerImpl::StreamerImpl; + + bool validateData(const std::vector& data) const override { + return data.size() % 2; + } + + bool startStream() override { + if (streamInProgress()) { + return false; + } + + inProgress_ = true; + std::thread([data = std::ref(data_), inProgress = std::ref(inProgress_)]() { + for (const auto el : data.get()) { + if (!inProgress.get()) { + return; + } + std::cout << el << ' ' << std::flush; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + }).detach(); + return true; + } + + bool stopStream() override { + if (!streamInProgress()) { + return false; + } + + inProgress_ = false; + return true; + } + + bool streamInProgress() const override { + return inProgress_ && !data_.empty(); + } + +private: + std::atomic inProgress_{false}; +}; + +class MjpegStreamer : public StreamerImpl { +public: + using StreamerImpl::StreamerImpl; + + bool validateData(const std::vector& data) const override { + return !(data.size() % 2); + } + + bool startStream() override { + if (streamInProgress() || data_.front() == 5) { + return false; + } + + inProgress_ = true; + std::thread([data = std::ref(data_), inProgress = std::ref(inProgress_)]() { + for (const auto el : data.get() | std::views::reverse) { + if (!inProgress.get()) { + return; + } + std::cout << el << ' ' << std::flush; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + }).detach(); + + return true; + } + + bool stopStream() override { + if (!streamInProgress() || data_.back() == 10) { + return false; + } + + inProgress_ = false; + return true; + } + + bool streamInProgress() const override { + return inProgress_; + } + +private: + std::atomic inProgress_{false}; +}; + +int main() { + std::unique_ptr streamer = std::make_unique( + Streamer::StreamInfo{"192.168.0.0", "192.168.10.24", 5432, 5432, 12}); + + // true + std::cout << std::boolalpha << streamer->addData({1, 2, 3, 4, 5, 6, 7}) << '\n'; + std::cout << streamer->startStream() << '\n'; + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << '\n' + << streamer->stopStream() << '\n'; + + // false + std::cout << std::boolalpha << streamer->addData({1, 2, 3, 4, 5, 6}) << '\n'; + + // NEW TYPE OF STREAMER + streamer = std::make_unique( + Streamer::StreamInfo{"192.168.0.0", "192.168.10.24", 5432, 5432, 12}); + + // true + std::cout << std::boolalpha << streamer->addData({1, 2, 3, 4, 5, 6}) << '\n'; + std::cout << streamer->startStream() << '\n'; + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << '\n' + << streamer->stopStream() << '\n'; + + // false + std::cout << std::boolalpha << streamer->addData({1, 2, 3, 4, 5, 6, 7}) << '\n'; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/streamer.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/streamer.cpp new file mode 100644 index 0000000..daa53d6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/streamer/streamer.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include + +class Streamer { +public: + struct StreamInfo { + std::string sourceAddress_; + std::string destinationAddress_; + uint16_t sourcePort_; + uint16_t destinationPort_; + uint16_t vlan_; + + bool operator==(const StreamInfo& other) const { + return std::tie(sourceAddress_, destinationAddress_, sourcePort_, destinationPort_, vlan_) == + std::tie(other.sourceAddress_, other.destinationAddress_, other.sourcePort_, other.destinationPort_, other.vlan_); + } + }; + + virtual ~Streamer() = default; + Streamer(const Streamer&) = default; + Streamer(Streamer&&) = default; + Streamer& operator=(const Streamer&) = default; + Streamer& operator=(Streamer&&) = default; + + Streamer(const std::vector& info) + : info_(info) {} + + virtual bool addReceiver(const StreamInfo& info) = 0; + virtual bool removeReceiver(const StreamInfo& info) = 0; + virtual bool addData(const std::vector& data) = 0; + virtual bool validateData(const std::vector& data) const = 0; + virtual bool startStream() = 0; + virtual bool stopStream() = 0; + virtual bool streamInProgress() const = 0; + +private: + std::vector info_; +}; + +// Create two classes and add some dummy implementations to allow check if code works :) + +int main() { + // Testing Mpeg2Streamer + std::unique_ptr streamer = std::make_unique( + Streamer::StreamInfo{"192.168.0.0", "192.168.10.24", 5432, 5432, 12}); + + std::cout << std::boolalpha << streamer->addData({1, 2, 3, 4, 5, 6, 7}) << '\n'; + std::cout << streamer->startStream() << '\n'; + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << '\n' + << streamer->stopStream() << '\n'; + std::cout << std::boolalpha << streamer->addData({1, 2, 3, 4, 5, 6}) << '\n'; + + // Testing MjpegStreamer + streamer = std::make_unique( + Streamer::StreamInfo{"192.168.0.0", "192.168.10.24", 5432, 5432, 12}); + + // true + std::cout << std::boolalpha << streamer->addData({1, 2, 3, 4, 5, 6}) << '\n'; + std::cout << streamer->startStream() << '\n'; + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << '\n' + << streamer->stopStream() << '\n'; + std::cout << std::boolalpha << streamer->addData({1, 2, 3, 4, 5, 6, 7}) << '\n'; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/CMakeLists.txt new file mode 100644 index 0000000..9d2ce9e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(${PROJECT_NAME} + Battle + Ship + Store + Core + Player +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/README.md b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/README.md new file mode 100644 index 0000000..e27d56c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/README.md @@ -0,0 +1,35 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +* Go into directory Player and implement a base class `Player`, this class should have 3 public virtual members: + * `virtual int attack(Ship& playerShip) = 0;` + * `virtual Ship& getShip() = 0;` + * `virtual const Ship& getShip() const = 0;` +* Add to `Player` class a non-virtual function: `Action::Status makeAction(const BattleField& battleField);`. +* Add to `Player` class 2 virtual protected function (a template method): + * `virtual Ship* chooseEnemyShip(const BattleField& battleField) const = 0;` + * `virtual std::unique_ptr chooseAction(const BattleField& battleField) const = 0;` +* Implement some logic in method `makeAction` based on 2 template method: + * To simplify, Player can only attack or defense + * Use class Command from directory `Battle` + +## Exercise 2 + +* Implement class `RealUser` which will inherit from class `Player`. Implement both template methods: + * Don't make it too complex, just ask user about action and type of ammunition, then you can randomly choose a damage or if missed. + * To increase defense, you can use method `setArmor` from `Ship` class. +* Rewrite class `Enemy` to inherit from `Player` add also implementation for both template methods +* Uncomment code in main, check if you can perform a real battle! + +## Exercise 3 + +* Go into directory `Battle` and implement class `Escape` which will inherit from class `Action`. + * Roll a die (1 to 20), if value is bigger than `12` a player successfully escaped. +* Noticed that we shouldn't modify existing code, but we need to do this in two place, where? +* How would you refactor the code? \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/main.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/main.cpp new file mode 100644 index 0000000..f9eb477 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/main.cpp @@ -0,0 +1,73 @@ +#include +#include +#include + +#include "Battle/BattleField.h" +#include "Core/BasicPrintVisitor.h" +#include "Core/PrettyPrintVisitor.h" +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Player/RealPlayer.h" +#include "Ship/Cargo.h" +#include "Ship/CargoDamageVisitor.h" +#include "Ship/Ship.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Store/Store.h" + +int main() { + Time time; + std::vector> cargoes; + cargoes.push_back(std::make_unique(1'000)); + cargoes.push_back(std::make_unique(1'000)); + cargoes.push_back(std::make_unique(1'000)); + auto store = std::unique_ptr>( + [&cargoes, &time]() { + auto* store = new Store(std::move(cargoes), std::make_unique()); + try { + time.attach(store); + } catch (...) { + abort(); + } + return store; }(), + [&time](Store* store) { + time.detach(store); + delete store; + }); + + Ship ship(&time, std::make_unique(), "Black Widow", 1000, 40, std::make_unique()); + ship.load(std::make_unique(300)); + ship.load(std::make_unique(200)); + ship.load(std::make_unique(150)); + + std::cout << "Ship\n"; + ship.printCargo(); + std::cout << "\nStore\n"; + store->printCargo(); + + std::cout << "\n\n****************************************************\n"; + auto ship2 = std::make_unique(&time, std::make_unique(), "Queens Anne revenge", 1000, 40, std::make_unique()); + Enemy enemy("Enemy1", std::move(ship2), std::make_unique(), CargoDamageVisitor{}); + + // UNCOMMENT THIS IN EXERCISE 2 + // auto ship3 = std::make_unique(&time, std::make_unique(), "Black Pearl", 1000, 40, std::make_unique()); + // RealPlayer user("Mateusz", std::move(ship3)); + + // BattleField battefield{&user, &enemy}; + // while (true) { + // for (auto* player : battefield.players()) { + // std::cout << "-------------------------------------------------------------------\n"; + // std::cout << "Player HP: " << user.getShip().durability() << " ARMOR: " << user.getShip().armor() << " | "; + // std::cout << "Enemy HP: " << enemy.getShip().durability() << " ARMOR: " << enemy.getShip().armor() << '\n'; + // std::cout << "-------------------------------------------------------------------\n"; + // for (size_t i = 0; i < 3; ++i) { + // const auto status = player->makeAction(battefield); + // if (status == Action::Status::Escaped || status == Action::Status::Defeated) { + // return 0; + // } + // } + // } + // } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/CMakeLists.txt new file mode 100644 index 0000000..38fdc09 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Battle src/Defense.cpp src/BattleField.cpp src/Attack.cpp) + +target_include_directories(Battle PUBLIC include) + +target_link_libraries(Battle + Ship + Player +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Action.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Action.h new file mode 100644 index 0000000..d4ddfa6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Action.h @@ -0,0 +1,21 @@ +#pragma once + +class Player; +class Ship; + +class Action { +public: + enum class Type { + Attack, + Defense + }; + + enum class Status { + Escaped, + Defeated, + Nothing, + }; + + virtual Status operator()(Player* player, Ship* enemyShip) = 0; + virtual Type type() const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Attack.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Attack.h new file mode 100644 index 0000000..a06cba0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Attack.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Attack : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Action::Type::Attack; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/BattleField.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/BattleField.h new file mode 100644 index 0000000..6196660 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/BattleField.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Ship; +class Player; + +class BattleField { +public: + BattleField(Player* player, Player* enemy); + + Ship* getPlayerShip() const; + Ship* getEnemyShip() const; + std::vector players() const; + +private: + Player* _player; + Player* _enemy; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Defense.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Defense.h new file mode 100644 index 0000000..fefd271 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/include/Battle/Defense.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Battle/Action.h" + +class Player; +class Ship; + +class Defense : public Action { +public: + Status operator()(Player* player, Ship* enemyShip) override; + Type type() const override { return Type::Defense; } +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/Attack.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/Attack.cpp new file mode 100644 index 0000000..b3f5e8a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/Attack.cpp @@ -0,0 +1,22 @@ +#include "Battle/Attack.h" + +#include +#include + +#include + +Action::Status Attack::operator()(Player* player, Ship* enemyShip) { + const int damage = player->attack(*enemyShip); + std::cout << "Player ship: " << player->getShip().name() << " attack ship: " << enemyShip->name() << '\n'; + if (damage) { + std::cout << "Dealed damage: " << damage << '\n'; + } else { + std::cout << "Missed\n"; + } + + if (enemyShip->durability() <= 0) { + return Status::Defeated; + } + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/BattleField.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/BattleField.cpp new file mode 100644 index 0000000..4e10569 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/BattleField.cpp @@ -0,0 +1,16 @@ +#include "Battle/BattleField.h" + +#include + +BattleField::BattleField(Player* player, Player* enemy) + : _player{player}, _enemy{enemy} {} + +Ship* BattleField::getPlayerShip() const { + return &_player->getShip(); +} +Ship* BattleField::getEnemyShip() const { + return &_enemy->getShip(); +} +std::vector BattleField::players() const { + return {_player, _enemy}; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/Defense.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/Defense.cpp new file mode 100644 index 0000000..a170c81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Battle/src/Defense.cpp @@ -0,0 +1,13 @@ +#include "Battle/Defense.h" + +#include +#include + +#include + +Action::Status Defense::operator()(Player* player, Ship*) { + player->getShip().increaseArmor(50); + std::cout << "Player ship: " << player->getShip().name() << " defense\n"; + + return Status::Nothing; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/CMakeLists.txt new file mode 100644 index 0000000..9434ff8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(Battle) +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/CMakeLists.txt new file mode 100644 index 0000000..db39d82 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Core src/Time.cpp src/BasicPrintVisitor.cpp src/PrettyPrintVisitor.cpp) + +target_include_directories(Core PUBLIC include) + +target_link_libraries(Core + Ship + Store +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/BasicPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/BasicPrintVisitor.h new file mode 100644 index 0000000..cd3406f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/BasicPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class BasicPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/DifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/DifficultLvlStrategy.h new file mode 100644 index 0000000..7c23854 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/DifficultLvlStrategy.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +template +class DifficultLvlStrategy { +public: + virtual Res handle(T&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/PrettyPrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/PrettyPrintVisitor.h new file mode 100644 index 0000000..58dc6ad --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/PrettyPrintVisitor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Core/PrintVisitor.h" + +class Store; +class Ship; + +class PrettyPrintVisitor : public PrintVisitor { +public: + void visit(const Store&) const override; + void visit(const Ship&) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/PrintVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/PrintVisitor.h new file mode 100644 index 0000000..bec94c0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/PrintVisitor.h @@ -0,0 +1,11 @@ +#pragma once + +class Store; +class Ship; + +class PrintVisitor { +public: + virtual ~PrintVisitor() = default; + virtual void visit(const Store&) const = 0; + virtual void visit(const Ship&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/BasicPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/BasicPrintVisitor.cpp new file mode 100644 index 0000000..05960c1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/BasicPrintVisitor.cpp @@ -0,0 +1,22 @@ +#include + +#include +#include +#include +#include + +void BasicPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << std::setw(15) << cargo->getPrice() << "\n"; + } +} + +void BasicPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + for (const auto& cargo : cargoes) { + std::cout << std::setw(15) << std::left << cargo->name() << std::setw(15) << cargo->amount << "\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/PrettyPrintVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/PrettyPrintVisitor.cpp new file mode 100644 index 0000000..99b6738 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/PrettyPrintVisitor.cpp @@ -0,0 +1,33 @@ +#include + +#include +#include +#include +#include + +void PrettyPrintVisitor::visit(const Store& store) const { + const auto& cargoes = store.cargoes(); + + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} + +void PrettyPrintVisitor::visit(const Ship& ship) const { + const auto& cargoes = ship.cargoes(); + + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/CMakeLists.txt new file mode 100644 index 0000000..1ec8794 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(Player src/EnemyEasyDifficultLvlStrategy.cpp src/EnemyHardDifficultLvlStrategy.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Battle + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..d70c028 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/Enemy.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include +#include + +template +class Enemy { +public: + Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor); + + int attack(Ship& playerShip) override; + Ship& getShip() { return *_ship; } + const Ship& getShip() const { return *_ship; } + +private: + std::string _name; + std::unique_ptr _ship; + std::unique_ptr> _strategy; + DamageVisitor _damageVisitor; +}; + +template +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy, DamageVisitor visitor) + : _name(name), _ship(std::move(ship)), _strategy(std::move(strategy)), _damageVisitor(visitor) {} + +template +int Enemy::attack(Ship& playerShip) { + if (const auto damage = _strategy->handle(playerShip)) { + for (auto& cargo : playerShip.cargoes()) { + cargo->accept(_damageVisitor); + } + return damage; + } + + return 0; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..d2b7b05 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyEasyDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h new file mode 100644 index 0000000..ac01b4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyHardDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..0ff5663 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp @@ -0,0 +1,28 @@ +#include "Player/EnemyEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyEasyDifficultLvlStrategy::_rd{}; + +EnemyEasyDifficultLvlStrategy::EnemyEasyDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyEasyDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 5) { + // miss + return 0; + } else if (res > 19) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(25, 50); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/src/EnemyHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/src/EnemyHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..790cd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Player/src/EnemyHardDifficultLvlStrategy.cpp @@ -0,0 +1,31 @@ +#include "Player/EnemyHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyHardDifficultLvlStrategy::_rd{}; + +EnemyHardDifficultLvlStrategy::EnemyHardDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyHardDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 3) { + // miss + return 0; + } else if (res == 20) { + // turbo critical + multiplier = 3; + } else if (res > 15) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(30, 60); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..d2f40e2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/CMakeLists.txt @@ -0,0 +1,12 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp + src/ShipEasyDifficultLvlStrategy.cpp + src/ShipHardDifficultLvlStrategy.cpp + src/CargoDamageVisitor.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..3771b7a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +#include "Ship/CargoDamageVisitor.h" + +#include + +struct Cargo { + size_t amount; + + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; + virtual void accept(const CargoDamageVisitor& visitor) = 0; +}; + +struct Fruit : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Item : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; + +struct Alcohol : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; + void accept(const CargoDamageVisitor& visitor) override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/CargoDamageVisitor.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/CargoDamageVisitor.h new file mode 100644 index 0000000..6e84c58 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/CargoDamageVisitor.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class Fruit; +class Alcohol; +class Item; + +class CargoDamageVisitor { +public: + CargoDamageVisitor() = default; + virtual ~CargoDamageVisitor() = default; + CargoDamageVisitor(const CargoDamageVisitor&) = default; + CargoDamageVisitor(CargoDamageVisitor&&) = default; + CargoDamageVisitor& operator=(const CargoDamageVisitor&) = default; + CargoDamageVisitor& operator=(CargoDamageVisitor&&) = default; + + virtual void operator()(Fruit& fruit) const; + virtual void operator()(Alcohol& alcohol) const; + virtual void operator()(Item& item) const; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed{_rd()}; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..186d0bb --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/Ship.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include "Ship/Cargo.h" + +class PrintVisitor; +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew, std::unique_ptr&& visitor); + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + const std::vector>& cargoes() const; + + void increaseArmor(int armor) { _armor += armor; } + int durability() const { return _durability; } + int armor() const { return _armor; } + +private: + bool unloadCargo(const std::string& cargoName, int amount); + void rebel(); + + Time* _time; + std::unique_ptr> _strategy; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + int _armor{0}; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..ce7627a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h new file mode 100644 index 0000000..a5f6a64 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..31d75b7 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/Cargo.cpp @@ -0,0 +1,43 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +void Fruit::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +void Item::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} + +void Alcohol::accept(const CargoDamageVisitor& visitor) { + visitor(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/CargoDamageVisitor.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/CargoDamageVisitor.cpp new file mode 100644 index 0000000..6ff89e2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/CargoDamageVisitor.cpp @@ -0,0 +1,20 @@ +#include + +#include + +std::random_device CargoDamageVisitor::_rd{}; + +void CargoDamageVisitor::operator()(Fruit& fruit) const { + std::uniform_int_distribution dice(0, 5); + fruit.amount -= dice(_seed); +} + +void CargoDamageVisitor::operator()(Alcohol& alcohol) const { + std::uniform_int_distribution dice(0, 10); + alcohol.amount -= (dice(_seed) / 2); +} + +void CargoDamageVisitor::operator()(Item& item) const { + std::uniform_int_distribution dice(0, 20); + item.amount -= (dice(_seed) / 4); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..2529f92 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/Ship.cpp @@ -0,0 +1,111 @@ +#include "Ship/Ship.h" + +#include +#include + +#include +#include +#include +#include + +Ship::Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew, std::unique_ptr&& visitor) + : _time(time), _strategy(std::move(strategy)), _name(name), _capacity(capacity), _crew(crew), _visitor(std::move(visitor)) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + if (!_strategy->handle(*this)) { + rebel(); + } +} + +void Ship::printCargo() const { + _visitor->visit(*this); +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const std::string& cargoName, int amount, StatusCode& code) noexcept { + if (!unloadCargo(cargoName, amount)) { + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const std::string& cargoName, int amount) { + if (!unloadCargo(cargoName, amount)) { + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _armor -= damage; + if (_armor >= 0) { + return; + } + + _durability += _armor; + _armor = 0; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +const std::vector>& Ship::cargoes() const { + return _cargoes; +} + +bool Ship::unloadCargo(const std::string& cargoName, int amount) { + while (amount != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount > amount) { + (*it)->amount -= amount; + return true; + } + amount -= (*it)->amount; + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..6d1a148 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipEasyDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/ShipHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/ShipHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..2a6815a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Ship/src/ShipHardDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipHardDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew(), status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew(), status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/include/Store/Store.h new file mode 100644 index 0000000..fbbbf9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/include/Store/Store.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class PrintVisitor; + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos, std::unique_ptr&& visitor); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + const std::vector>& cargoes() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; + std::unique_ptr _visitor; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/src/Store.cpp new file mode 100644 index 0000000..07a9e35 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/src/Store/src/Store.cpp @@ -0,0 +1,41 @@ +#include "Store/Store.h" + +#include + +Store::Store(std::vector>&& cargos, std::unique_ptr&& visitor) + : _seed(_rd()), _cargoes(std::move(cargos)), _visitor(std::move(visitor)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +const std::vector>& Store::cargoes() const { + return _cargoes; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +void Store::printCargo() const { + _visitor->visit(*this); +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/templateMethod/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/CMakeLists.txt new file mode 100644 index 0000000..4b33b70 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.16) +project(SHM LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +enable_testing() + +add_subdirectory(src) +add_subdirectory(tests) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(${PROJECT_NAME} + Ship + Store + Core + Player +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/README.md b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/README.md new file mode 100644 index 0000000..142e27c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/README.md @@ -0,0 +1,67 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +* Go into directory `Core` and implement a base class `PrintVisitor` which should implement `visit` method for two objects: `Ship` and `Store` +* Create `PrettyPrintVisitor` which will print cargo from `Ship` and `Sotore` (just move the implementation `printCargo`). +* Add the rest of necessary implementation for `Ship` and `Store`. Visitor should be taken as `std::unique_ptr` +* Verify in the `main.cpp` if cargo print in the same way as previously. + +Example: + +``` +Ship +|----------------|----------------| +| NAME | AMOUNT | +|----------------|----------------| +|Rum | 300 | +|Banana | 200 | +|Banana | 150 | +|----------------|----------------| + +Store +|----------------|----------------|----------------| +| NAME | AMOUNT | PRICE | +|----------------|----------------|----------------| +|Rum | 1000 | 40 | +|Banana | 1000 | 20 | +|Item | 1000 | 30 | +|----------------|----------------|----------------| +``` + +## Exercise 2 + +* Create another visitor: `BasicPrintVisitor` which should print the cargo but without special frames, just raw info. +* For `Ship` print Name and Amount +* For `Store` print Name Amount and Price +* You shouldn't modify anything in your code, just change the visitor in `main.cpp` and you should get a new output + +Example: + +``` +Ship +Rum 300 +Banana 200 +Banana 150 + +Store +Rum 1000 40 +Banana 1000 20 +Item 1000 30 +``` + +## Exercise 3 + +* Create CargoDamageVisitor. You don't need to create a base class, because we know that we will not extend this code, +* You should create three `operator()` one for each cargo type: Alcohol, Fruit, Item, +* For fruit, you should draw a number between 0 and 5 and subtract such an amount of cargo +* For alcohol, you should draw a number between 0 and 10 and subtract half an amount of cargo +* For item, you should draw a number between 0 and 20 and subtract one quarter of cargo +* Visitor should be taken as a template argument by Player class +* Apply visitor whenever you successfully deal damage to ship +* Check in the main class if ship lost cargo after get damaged. \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/main.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/main.cpp new file mode 100644 index 0000000..247c2fb --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/main.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +#include "Core/Time.h" +#include "Player/Enemy.h" +#include "Player/EnemyEasyDifficultLvlStrategy.h" +#include "Player/EnemyHardDifficultLvlStrategy.h" +#include "Ship/Cargo.h" +#include "Ship/Ship.h" +#include "Ship/ShipEasyDifficultLvlStrategy.h" +#include "Ship/ShipHardDifficultLvlStrategy.h" +#include "Store/Store.h" + +int main() { + Time time; + + Ship ship(&time, std::make_unique(), "Black Widow", 1000, 40); + ship.load(std::make_unique(300)); + ship.load(std::make_unique(200)); + ship.load(std::make_unique(150)); + ship.printCargo(); + + for (int i = 0; i < 10; ++i) { + ++time; + std::cout << "\nDAY: " << time.day() << "\n"; + std::cout << "crew: " << ship.crew() << '\n'; + ship.printCargo(); + } + + std::cout << "\n\n****************************************************\n"; + auto ship2 = std::make_unique(&time, std::make_unique(), "Queens Anne revenge", 1000, 40); + Enemy enemy("Enemy1", std::move(ship2), std::make_unique()); + + for (int i = 0; i < 15; ++i) { + enemy.attack(ship); + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/CMakeLists.txt new file mode 100644 index 0000000..c29ff6c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(Core) +add_subdirectory(Player) +add_subdirectory(Ship) +add_subdirectory(Store) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/CMakeLists.txt new file mode 100644 index 0000000..5db9b9a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(Core src/Time.cpp) + +target_include_directories(Core PUBLIC include) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/DifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/DifficultLvlStrategy.h new file mode 100644 index 0000000..7c23854 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/DifficultLvlStrategy.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +template +class DifficultLvlStrategy { +public: + virtual Res handle(T&) const = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/Time.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/Time.h new file mode 100644 index 0000000..83824bd --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/Time.h @@ -0,0 +1,27 @@ +#pragma once + +class TimeObserver; + +#include +#include +#include +#include + +class Time { +public: + enum class State { + Closing, + FocusChanged + }; + + void attach(TimeObserver* observer); + void detach(TimeObserver* observer); + Time& operator++(); + size_t day() const { return _day; } + +private: + void notify() const; + + size_t _day{0}; + std::set _observers; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/TimeObserver.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/TimeObserver.h new file mode 100644 index 0000000..2bbf49e --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/include/Core/TimeObserver.h @@ -0,0 +1,6 @@ +#pragma once + +struct TimeObserver { + virtual ~TimeObserver() = default; + virtual void nextDay() = 0; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/src/Time.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/src/Time.cpp new file mode 100644 index 0000000..5faf899 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Core/src/Time.cpp @@ -0,0 +1,24 @@ +#include "Core/Time.h" + +#include "Core/TimeObserver.h" + +#include +#include + +void Time::attach(TimeObserver* observer) { + _observers.emplace(observer); +} + +void Time::detach(TimeObserver* observer) { + _observers.erase(observer); +} + +Time& Time::operator++() { + ++_day; + notify(); + return *this; +} + +void Time::notify() const { + std::ranges::for_each(_observers, std::mem_fn(&TimeObserver::nextDay)); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/CMakeLists.txt new file mode 100644 index 0000000..f96d5d4 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(Player src/Enemy.cpp src/EnemyEasyDifficultLvlStrategy.cpp src/EnemyHardDifficultLvlStrategy.cpp) + +target_include_directories(Player PUBLIC include) + +target_link_libraries(Player + Core + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/Enemy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/Enemy.h new file mode 100644 index 0000000..840bc42 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/Enemy.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include +#include + +class Ship; + +class Enemy { +public: + Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy); + + void attack(Ship& playerShip); + +private: + std::string _name; + std::unique_ptr _ship; + std::unique_ptr> _strategy; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..d2b7b05 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/EnemyEasyDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyEasyDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h new file mode 100644 index 0000000..ac01b4c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/include/Player/EnemyHardDifficultLvlStrategy.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Ship; + +class EnemyHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + EnemyHardDifficultLvlStrategy(); + int handle(Ship& ship) const override; + +private: + static std::random_device _rd; + mutable std::mt19937 _seed; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/Enemy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/Enemy.cpp new file mode 100644 index 0000000..fe28321 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/Enemy.cpp @@ -0,0 +1,19 @@ +#include "Player/Enemy.h" + +#include + +#include +#include +#include + +Enemy::Enemy(const std::string& name, std::unique_ptr&& ship, std::unique_ptr>&& strategy): + _name(name), _ship(std::move(ship)), _strategy(std::move(strategy)) {} + +void Enemy::attack(Ship& playerShip) { + std::cout << "Player: " << _name << " attack ship: " << playerShip.name() << '\n'; + if (const auto damage = _strategy->handle(playerShip)) { + std::cout << "Dealed damage: " << damage << '\n'; + } else { + std::cout << "Missed\n"; + } +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..0ff5663 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/EnemyEasyDifficultLvlStrategy.cpp @@ -0,0 +1,28 @@ +#include "Player/EnemyEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyEasyDifficultLvlStrategy::_rd{}; + +EnemyEasyDifficultLvlStrategy::EnemyEasyDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyEasyDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 5) { + // miss + return 0; + } else if (res > 19) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(25, 50); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/EnemyHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/EnemyHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..790cd81 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Player/src/EnemyHardDifficultLvlStrategy.cpp @@ -0,0 +1,31 @@ +#include "Player/EnemyHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +std::random_device EnemyHardDifficultLvlStrategy::_rd{}; + +EnemyHardDifficultLvlStrategy::EnemyHardDifficultLvlStrategy() + : _seed(_rd()) {} + +int EnemyHardDifficultLvlStrategy::handle(Ship& ship) const { + std::uniform_int_distribution dice(1, 20); + int multiplier = 1; + const int res = dice(_seed); + + if (res < 3) { + // miss + return 0; + } else if (res == 20) { + // turbo critical + multiplier = 3; + } else if (res > 15) { + // criticall + multiplier = 2; + } + + std::uniform_int_distribution damage(30, 60); + const int total = damage(_seed) * multiplier; + ship.takeDamage(total); + + return total; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/CMakeLists.txt new file mode 100644 index 0000000..6d03561 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/CMakeLists.txt @@ -0,0 +1,11 @@ +add_library(Ship + src/Ship.cpp + src/Cargo.cpp + src/ShipEasyDifficultLvlStrategy.cpp + src/ShipHardDifficultLvlStrategy.cpp) + +target_include_directories(Ship PUBLIC include) + +target_link_libraries(Ship + Core +) diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/Cargo.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/Cargo.h new file mode 100644 index 0000000..7ed1893 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/Cargo.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +#include + +struct Cargo { + size_t amount; + + Cargo(size_t amount); + virtual ~Cargo() = default; + Cargo(const Cargo&) = default; + Cargo(Cargo&&) = default; + Cargo& operator=(const Cargo&) = default; + Cargo& operator=(Cargo&&) = default; + + auto operator<=>(const Cargo&) const = default; + + virtual size_t getPrice() const = 0; + virtual const std::string& name() const = 0; +}; + +struct Fruit : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Item : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; + +struct Alcohol : public Cargo { + using Cargo::Cargo; + + size_t getPrice() const override; + const std::string& name() const override; +}; \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/Ship.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/Ship.h new file mode 100644 index 0000000..e92d9c9 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/Ship.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include "Ship/Cargo.h" + +class Time; + +class Ship : public TimeObserver { +public: + enum class StatusCode { + OK, + MissingCargo, + LackOfSpace + }; + + Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew); + ~Ship(); + Ship(const Ship&) = default; + Ship(Ship&&) = default; + Ship& operator=(const Ship&) = default; + Ship& operator=(Ship&&) = default; + + // Override from TimeObserver + void nextDay() override; + + std::string& name() { return _name; } + const std::string& name() const { return _name; } + int crew() const { return _crew; } + + void printCargo() const; + + Cargo* load(std::unique_ptr&& cargo, StatusCode& code) noexcept; + void unload(const std::string& name, int amount, StatusCode& code) noexcept; + + // May throw + Cargo* load(std::unique_ptr&& cargo); + void unload(const std::string& name, int amount); + + void takeDamage(int damage); + +private: + bool unloadCargo(const std::string& cargoName, int amount); + void rebel(); + + Time* _time; + std::unique_ptr> _strategy; + std::string _name; + int _capacity; + int _crew; + int _durability{1000}; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h new file mode 100644 index 0000000..ce7627a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/ShipEasyDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipEasyDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h new file mode 100644 index 0000000..a5f6a64 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/include/Ship/ShipHardDifficultLvlStrategy.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class Ship; + +class ShipHardDifficultLvlStrategy : public DifficultLvlStrategy { +public: + bool handle(Ship& ship) const override; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/Cargo.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/Cargo.cpp new file mode 100644 index 0000000..9c55175 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/Cargo.cpp @@ -0,0 +1,31 @@ +#include "Ship/Cargo.h" + +Cargo::Cargo(size_t amount) + : amount(amount) {} + +size_t Fruit::getPrice() const { + return 20; +} + +const std::string& Fruit::name() const { + static std::string name{"Banana"}; + return name; +} + +size_t Item::getPrice() const { + return 30; +} + +const std::string& Item::name() const { + static std::string name{"Item"}; + return name; +} + +size_t Alcohol::getPrice() const { + return 40; +} + +const std::string& Alcohol::name() const { + static std::string name{"Rum"}; + return name; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/Ship.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/Ship.cpp new file mode 100644 index 0000000..2e60865 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/Ship.cpp @@ -0,0 +1,108 @@ +#include "Ship/Ship.h" + +#include + +#include +#include +#include +#include +#include + +Ship::Ship(Time* time, std::unique_ptr> strategy, const std::string& name, int capacity, int crew) + : _time(time), _strategy(std::move(strategy)), _name(name), _capacity(capacity), _crew(crew) { + if (_capacity < 0) { + throw std::runtime_error("Capacity can't be negative value!"); + } + assert(time); + _time->attach(this); +} + +Ship::~Ship() { + _time->detach(this); +} + +void Ship::nextDay() { + if (!_strategy->handle(*this)) { + rebel(); + } +} + +void Ship::printCargo() const { + std::cout << "|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT |" << '\n'; + std::cout << "|----------------|----------------|\n"; + for (const auto& cargo : _cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "|\n"; + } + std::cout << "|----------------|----------------|\n"; +} + +Cargo* Ship::load(std::unique_ptr&& cargo, StatusCode& code) noexcept { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + code = StatusCode::LackOfSpace; + return _cargoes.back().get(); + } + + code = StatusCode::OK; + return nullptr; +} + +void Ship::unload(const std::string& cargoName, int amount, StatusCode& code) noexcept { + if (!unloadCargo(cargoName, amount)) { + code = StatusCode::MissingCargo; + return; + } + + code = StatusCode::OK; +} + +Cargo* Ship::load(std::unique_ptr&& cargo) { + if (_capacity > cargo->amount) { + _cargoes.push_back(std::move(cargo)); + return _cargoes.back().get(); + } + + throw std::runtime_error("Lack of space"); +} + +void Ship::unload(const std::string& cargoName, int amount) { + if (!unloadCargo(cargoName, amount)) { + throw std::runtime_error("Missing cargo"); + } +} + +void Ship::takeDamage(int damage) { + _durability -= damage; + if (_durability <= 0) { + std::cout << "Ship: " << _name << " was destroyed!\n"; + } +} + +bool Ship::unloadCargo(const std::string& cargoName, int amount) { + while (amount != 0) { + auto it = std::ranges::find_if(_cargoes, [&cargoName](const auto& cargo) { return cargo->name() == cargoName; }); + if (it != _cargoes.end()) { + if ((*it)->amount > amount) { + (*it)->amount -= amount; + return true; + } + amount -= (*it)->amount; + _cargoes.erase(it); + } else { + return false; + } + } + + return true; +} + +void Ship::rebel() { + std::cout << "\n********** Crew rebel **********\n"; + _crew -= 5; + + if (_crew < 5) { + throw std::runtime_error("There is not enought crew! Game over!"); + } +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp new file mode 100644 index 0000000..6d1a148 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/ShipEasyDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipEasyDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipEasyDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/ShipHardDifficultLvlStrategy.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/ShipHardDifficultLvlStrategy.cpp new file mode 100644 index 0000000..2a6815a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Ship/src/ShipHardDifficultLvlStrategy.cpp @@ -0,0 +1,12 @@ +#include "Ship/ShipHardDifficultLvlStrategy.h" + +#include "Ship/Ship.h" + +bool ShipHardDifficultLvlStrategy::handle(Ship& ship) const { + Ship::StatusCode status; + ship.unload("Rum", ship.crew(), status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew(), status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/CMakeLists.txt new file mode 100644 index 0000000..30a4ee2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(Store src/Store.cpp) + +target_include_directories(Store PUBLIC include) + +target_link_libraries(Store + Ship +) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/include/Store/Store.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/include/Store/Store.h new file mode 100644 index 0000000..1eb93cb --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/include/Store/Store.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Ship/Cargo.h" + +#include +#include +#include +#include +#include + +class Store : public TimeObserver { +public: + explicit Store(std::vector>&& cargos); + + // Override from TimeObserver + void nextDay() override; + + size_t getTotalPrice() const; + std::vector getCargosName() const; + void printCargo() const; + +private: + static std::random_device _rd; + std::mt19937 _seed; + std::vector> _cargoes; +}; diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/src/Store.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/src/Store.cpp new file mode 100644 index 0000000..41d32fe --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/src/Store/src/Store.cpp @@ -0,0 +1,48 @@ +#include "Store/Store.h" + +#include +#include + +Store::Store(std::vector>&& cargos) + : _seed(_rd()), _cargoes(std::move(cargos)) {} + +std::random_device Store::_rd{}; + +void Store::nextDay() { + std::uniform_int_distribution dist(-50, 50); + for (auto& cargo : _cargoes) { + cargo->amount += dist(_seed); + } +} + +size_t Store::getTotalPrice() const { + size_t value{0}; + for (const auto& cargo : _cargoes) { + value += cargo->getPrice(); + } + + return value; +} + +std::vector Store::getCargosName() const { + std::vector names; + for (const auto& cargo : _cargoes) { + names.push_back(cargo->name()); + } + + return names; +} + +// Shame on me, I copy-past it. But remember DRY!! +// This is only to speed up process of creating exercises, sorry :) +void Store::printCargo() const { + std::cout << "|----------------|----------------|----------------|\n"; + std::cout << "| NAME " + << "| AMOUNT " + << "| PRICE |" << '\n'; + std::cout << "|----------------|----------------|----------------|\n"; + for (const auto& cargo : _cargoes) { + std::cout << "|" << std::setw(15) << std::left << cargo->name() << " | " << std::setw(15) << cargo->amount << "| " << std::setw(15) << cargo->getPrice() << "|\n"; + } + std::cout << "|----------------|----------------|----------------|\n"; +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/CMakeLists.txt b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/CMakeLists.txt new file mode 100644 index 0000000..7dea033 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.11.0 +) +FetchContent_MakeAvailable(googletest) +add_library(GTest::GTest INTERFACE IMPORTED) +target_link_libraries(GTest::GTest INTERFACE gtest_main) +target_link_libraries(GTest::GTest INTERFACE gmock_main) + +add_executable(SHM_Tests ShipUnitTests.cpp StoreUnitTests.cpp) + +target_link_libraries(SHM_Tests + PRIVATE + GTest::GTest + Ship + Store) + +add_test(shm_gtests SHM_Tests) \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/CargoMock.h b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/CargoMock.h new file mode 100644 index 0000000..10044a1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/CargoMock.h @@ -0,0 +1,3 @@ +#pragma once + +// Write mock here \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/ShipUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/ShipUnitTests.cpp new file mode 100644 index 0000000..da29d07 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/ShipUnitTests.cpp @@ -0,0 +1,9 @@ +#include "Ship/Cargo.h" +#include "Ship/Ship.h" + +#include + +TEST(ShipTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/StoreUnitTests.cpp b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/StoreUnitTests.cpp new file mode 100644 index 0000000..0562132 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/exercises/visitor/tests/StoreUnitTests.cpp @@ -0,0 +1,11 @@ +#include "CargoMock.h" +#include "Ship/Cargo.h" +#include "Store/Store.h" + +#include +#include + +TEST(StoreTests, ShouldCreate) +{ + +} diff --git a/CreatingReliableSoftwareCpp/Presentation/good_practise_dry.md b/CreatingReliableSoftwareCpp/Presentation/good_practise_dry.md new file mode 100644 index 0000000..49ec54f --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/good_practise_dry.md @@ -0,0 +1,39 @@ +# DRY +___ + +## Don't Repeat Yourself + +* If you have two identical functionality, like searching for some resource, just make a separate function and always call it +* Create some utility files, which will contain functions reused in your project +* It could contain functions for: + * Filtering + * Searching + * Removing + * Operate with string etc... +* If you have some value/ string which is used in few places, create one constexpr variable for it and always refer to this variable instead magic value/ string +___ + +```C++ +class Foo { + constexpr static const char* DATABASE_NAME = "superDb"; + constexpr static size_t CONNECTION_TIMEOUT_SECONDS = 30; + +public: + // Don't hardcode value here, instead of create a variable which store this info + void connect(const std::string& dbName = DATABASE_NAME) { + db.createConnection(dbName, CONNECTION_TIMEOUT_SECONDS); + } + + bool connected() const { return db.connected(); } + + json sendRequest(const json& request) { + // use already implemented functions + if (!connected()) { + connect(); + } + + return db.request(request); + } +}; +``` + \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/good_practise_intro.md b/CreatingReliableSoftwareCpp/Presentation/good_practise_intro.md new file mode 100644 index 0000000..9ed5cfb --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/good_practise_intro.md @@ -0,0 +1,200 @@ +# Good practise +___ + +## What can we do better? + +```C++ +class Bar { +public: + void doSth() { + std::cout << "Do sth\n"; + } +}; + +class Foo { +public: + Foo(std::string name) { + name_ = name; + bar_ = new Bar(); + } + + ~Foo() { + delete bar_; + bar_ = nullptr; + } + + void printName() { + std::cout << name_ << std::endl; + } + + void doSth() { + bar_->doSth(); + } + +private: + Bar* bar_; + std::string name_; +}; +``` + + +___ + +## Refactor + +```C++ +class Bar { +public: + // doSth should be cont method because only print sth + void doSth() { + std::cout << "Do sth\n"; + } +}; + +class Foo { +public: + // Get string by const& or use std::move when initialize + Foo(std::string name) { + // Use initialization list, instead assign inside C'tor + name_ = name; + // Avoid usage of new, use unique_ptr and make_unique method + // Class Foo will be hard to test because we can't substitute bar objects! + // Bar should be provided in C'tor -> Dependency injection + bar_ = new Bar(); + } + + ~Foo() { + // Unneccessary, because we should use unique_ptr + delete bar_; + bar_ = nullptr; + } + + // Should be const method + void printName() { + // better use '\n' then endline + // If you need to flush stream use flush() method + std::cout << name_ << std::endl; + } + + // If there is a risk, that ptr may by empty, we shoudl validate it + void doSth() { + bar_->doSth(); + } + +private: + Bar* bar_; + std::string name_; +}; +``` + + +___ + +## What can we do better? + +```C++ +class Screen { +public: + Screen(int height, int width) : height_(height), width_(width) {} + Screen(int size) : height_(size), width_(size) {} + ~Screen() {} + + void print(const std::vector& numbers) { + int current = 0; + for (int j = 0; j < width_; ++j) { + std::cout << "_"; + } + std::cout << '\n'; + + for (int i = 0; i < height_; ++i) { + std::cout << "|"; + for (int j = 0; j < width_; ++j) { + int num_width = std::to_string(numbers[current]).size(); + std::cout << numbers[current]; + j += num_width; + if (j < width_) { + std::cout << ' '; + } + ++current; + } + std::cout << "|\n"; + } + + for (int j = 0; j < width_; ++j) { + std::cout << "_"; + } + std::cout << '\n'; + } +private: + Screen() {} + int height_; + int width_; +}; +``` + + +___ + +## Refactor + +```C++ +class Screen { +public: + // Use alias -> using Height = int + Screen(int height, int width) + : height_(height), width_(width) {} + // User probably not expect square screen when initialize with one value + // C'tor with on argument should be mark as explicit. + Screen(int size) + : height_(size), width_(size) {} + // Not needed here, we also break rule of 5 + ~Screen() {} + + // Should be const method + void print(const std::vector& numbers) { + int current = 0; + + // This function repeat twice. + // Should be separate function like print underscore + for (int j = 0; j < width_; ++j) { + // This is not efficient better use std::cout << string(width_, '_') << '\n'; + std::cout << "_"; + } + std::cout << '\n'; + + // This is hard to understand. There is already implemented stream mainpulators + // like which allow to use `setw` to describe the width ov vlaue + // or added in c++20 std::format() + for (int i = 0; i < height_; ++i) { + std::cout << "|"; + for (int j = 0; j < width_; ++j) { + // should be const + int num_width = std::to_string(numbers[current]).size(); + std::cout << numbers[current]; + // do sth with `j` which should be handled by for loop + j += num_width; + if (j < width_) { + std::cout << ' '; + } + ++current; + } + std::cout << "|\n"; + } + + // DRY - do not repeat yourself + for (int j = 0; j < width_; ++j) { + std::cout << "_"; + } + std::cout << '\n'; + } + +private: + // By default when we create at least one C'tor, the compiler will not add a default one + Screen() {} + + int height_; + int width_; +}; +``` + + diff --git a/CreatingReliableSoftwareCpp/Presentation/good_practise_kiss.md b/CreatingReliableSoftwareCpp/Presentation/good_practise_kiss.md new file mode 100644 index 0000000..c26547c --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/good_practise_kiss.md @@ -0,0 +1,38 @@ +# KISS +___ + +## keep it simple, stupid + +* Writing only enough code to pass a unit test, which relates to TDD and the first SOLID principle – Single Responsibility. +* Intuitive approaches to writing software, approachable and simply understood by everyone. +___ + +## Small understandable classes and methods + +```C++ +class ImageStorage { +public: + Image* getImage(const std::string& url) { + const auto it = std::ranges::find_if(images_, [&url](const auto& image) { return image->url() == url; }); + if (it != std::cend(images_)) { + return it->get(); + } + + return nullptr; + } + + Image* store(std::unique_ptr&& image) { + if (const auto* image = getImage()) { + return image; + } + + images_.push_back(std::move(image)); + return images_.back().get(); + } + +private: + std::vector> images_; +}; +``` + + \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/good_practise_solid.md b/CreatingReliableSoftwareCpp/Presentation/good_practise_solid.md new file mode 100644 index 0000000..b21f762 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/good_practise_solid.md @@ -0,0 +1,896 @@ +# SOLID +___ + +## S - Single resposibility (1) + +* A class (module) should has one and only one reason to change, meaning that a class should has only one job. +* When we create a class UrlDownloader it shouldn't: + * Make a connection -> We should have separate object for that like TcpConnection + * Display it -> We should have separate class to do that like Canvas + * Modifying the response, like resizing, it should be done by other class like Bitmap + * Cache it -> We should have other class to store cached images like FileCache + +* Advantages: + * Testing – A class with one responsibility will have far fewer test cases. + * Lower coupling – Less functionality in a single class will have fewer dependencies. + * Organization – Smaller, well-organized classes are easier to search than monolithic ones. +___ + +## S - Single resposibility (2) + +Let's say we want to create a program that downloads images and allows us to display them. In such cases we need to implement a few classes that are responsible for: + +* Download object: Create request, make connection, download raw bits + * ImageDownloader, TcpConnection class +* Image representation: Store info about image, bitmap, allow to modify it. + * Image, Bitmap class +* User interface: Print object + * Canvas, Window class +* Cache: Cache object for future usage and quick access + * FileStorage, RamStorage class + +___ + +## S - Single resposibility (3) + +* By following of rule one responsibility let's create Image class. This class will be responsible for: + * Store bitmap + * Store url of image to allow identification of it + * This class don't need to know how to display an image or resize it + +```C++ +class Image { +public: + Image(const std::string& url, const Bitmap& bitmap) + : url_(url), bitmap_(bitmap) {} + Image(const std::string& url, Bitmap&& bitmap) + : url_(url), bitmap_(std::move(bitmap)) {} + + const Bitmap& bitmap() const { return bitmap_; } + const std::string& url() const { return url_; } + +private: + std::string url_; + Bitmap bitmap_; +}; +``` + + +___ + +Let's create a second class form this module, a Bitmap class. This class will be responsible for: +* Store raw bit +* Store type of image (png, jpg) +* Store additional info about image like: size, name, url etc... + +```C++ +class Bitmap { +public: + struct Pixel { uint8_t r; uint8_t g; uint8_t b; } + enum class Type { PNG, JPG }; + + Image(size_t width, size_t height, Type type, std::vector bits) + : _width(width), _height(height), _type(type), _bits(std::move(bits)) {} + + void resize(size_t newWidth, size_t newHeight) { ... } + void mirrorReflection() { ... } + // getter like, witdh(), height() etc... + +private: + size_t _width; + size_t _height; + Type _type; + std::vector _bits; +}; +``` + + +* Does Bitmap follow the rule of single responsibility? + +___ + +Bitmap keeps info about types of images. So when we want to support a new type of image we need to modify the Image class and also modify the methods, like resize, mirror reflection, etc... because each type of image may be formatted differently. That's why we should separate this class. I will show it later when we will talk about other rules from SOLID. +___ + +Let's create a second module, which will be resposible for printing image. We starts from a Canvas class. This class will be responsible for: +* Knowing how to display bitmap +* Store additional info about canvas like: size +* This class don't need to know how to transform image or resize it. + +```C++ +class Canvas { +public: + Canvas(size_t width, size_t height) : _width(width), _height(height) {} + + void print(const Image& img) const { + const auto& bitmap = img.bitmap(); + const size_t imgWidth = bitmap.width(); + const size_t imgHeight = bitmap.height(); + if (imgWidth > _width || imgHeight > _height) { + bitmap.resize(_width, _height); + } + .... + } + +private: + size_t _width; + size_t _height; +}; + +``` + + +* Does Canvas follow the rule of single responsibility? + + +___ + +Once again no. Canvas is tightly coupled with types of images, so whenever we add a new type of image we need to rewrite methods. As you can see, one change (adding a new type of image) demands a user to reimplement the `Canvas` class and `Bitmap` class and probably even more classes. This is not a single responsibility. The class should have one reason to change and now class has a lot of reasons to change. Once again I will show you later how we can resolve it. + +___ + +## Single resposibility in STL + +SOLID is also valid for static polymorphism. As an example, we can check the STL algorithm like `std::stransform`. + +```C++ +template +OutputIt transform(InputIt first1, InputIt last1, + OutputIt d_first, UnaryOp unary_op) +{ + while (first1 != last1) + *d_first++ = unary_op(*first1++); + + return d_first; +} +``` + +Transform performs one operation e2e: iterate through the input range, call `unary_op`, and store the result in an output range. + +___ + +## Single resposibility in STL (2) + +Another example will be a `std::vector` class. The whole interface is strongly connected with a dynamically allocated array, we can: + +* push_back +* insert +* erase + +But we don't have methods like: + + +* sort +* unique +* transform + +Now you can understand, why `std::remove` is a separate method, because `std::vector` should not have logic, on how to rearrange an array, because this is not a part of its responsibility. `std::vector` gives us an interface only for adding, modifying, and removing elements form a dynamic array and STL algorithm give us a possibility to rearrange the container. + + +___ + +## Breaking single resposibility in STL + +Two years after the STL library was introduced we get also a `std::string` which is not a good example of a single responsibility. You may ask why. Let's check `std::string` interface: + +* find +* rfind +* find_first_of +* find_first_not_of +* find_last_of +* find_last_not_of +* replace +* substr +* contains +* starts_with +* ends_with + +I know that this is handy, to have such a method I use them a lot. But this is not exactly a doo design. Because every standard when `std::string` grows, the authors of libraries need to modify the class and can introduce new bugs, so development of this class is hard. + + +___ + +## std::list + +You can argue that `std::list` also has a specific functions like: + +* merge +* splice +* remove +* remove_if +* reverse +* unique +* sort + +yes, I agree, but these functions are specified to the type. `std::list` can perform these operations differently, because we may manipulate the pointers. This is an implementation of detail for `std::list`. STL algorithm should not know that this specific iterator should be treated differently. + + +___ + +## Single resposibility - summary + +In short words, we can say that a single responsibility means that a function, class, or module should not implement details of two orthogonal issues. +___ + +## O - Open-Closed (1) + +* Objects or entities should be open for extension but closed for modification. + * When we add new functionality or a new type our changes should not require modification of existing code + * When we have a bug in code of course we need to modify it :) + +* Advantages: + * We stop ourselves from modifying existing code and causing potential new bugs + * We mainly focus on adding new functionalities rather than modifying code to fit the new version + +___ + +## O - Open-Closed (2) + +We implemented an Image class which stores information about `URL` and `bitmap`, now we have a task that we should also have the possibility to store info about: +* date when the image was downloaded +* date when the image was created originally +* a place where the image was taken + +We need to ask ourselves whether these pieces of information are required for the existing code or not. + +* If required, we probably need to modify the class `Image` extend an interface, and add new fields. But still, this is done by extension of already implemented code. Other classes still compile, and we decide which class should use a new functionality. +* If not required, we probably need to add a derived class that will have this information and use it in a new part of the code that we implement. So we don't modify anything from existing code, we just add a new functionality. + + +```C++ +class DescribedImage : public Image { +public: + DescribedImage(const std::string& url, const Bitmap& bitmap, DateTime downloadTime, DateTime imageTime, Coordinate place): + Image(url, bitmap), _downloadTime(downloadTime), _imageTime(imageTime), _place(place) {} + + const DateTime& downloadTime() const { return _downloadTime; } + const DateTime& imageTime() const { return _imageTime; } + const Coordinate& place() const { return _place; } + +private: + DateTime _downloadTime; + DateTime _imageTime; + Coordinate _place; +}; +``` + + +___ + +## O - Open-Closed (3) + +When we depend on interfaces, we can also add easily new functionality by extending them. Unfortunately, if other classes inherit from these interfaces we need to write the implementation for each class, which requires modification of existing code and we break the rule `open-close` in such a way we need to think about what will change often: types or methods? + +* If types we can use for instance a strategy design pattern, because when we create a new type, we need to create a new strategy only for this type and we don't modify anything in existing code. +* If methods we can use for instance a visitor design pattern, because when we add a new method, we need to implement a visit method only for this new one, but the existing code doesn't change. +* I will describe more these patterns in the section design patterns + +___ + +## Visitor + +```C++ +class BitmapVisitor { +public: + virtual ~BitmapVisitor() = default; + + virtual void visit(JPGImage& image, /* other args */) = 0; + virtual void visit(PNGImage& image, /* other args */) = 0; + virtual void visit(GIFImage& image, /* other args */) = 0; + virtual void visit(SVGImage& image, /* other args */) = 0; +}; +``` + +```C++ +class ResizeVisitor : public BitmapVisitor { +public: + void visit(JPGImage& image, /* other args */) override; + void visit(PNGImage& image, /* other args */) override; + void visit(GIFImage& image, /* other args */) override; + void visit(SVGImage& image, /* other args */) override; +}; + +class RotateVisitor : public BitmapVisitor { +public: + void visit(JPGImage& image, /* other args */) override; + void visit(PNGImage& image, /* other args */) override; + void visit(GIFImage& image, /* other args */) override; + void visit(SVGImage& image, /* other args */) override; +}; +``` + + +___ + +## Strategy + +```C++ +class DownloadStrategy { +public: + virtual ~DownloadStrategy() = default; + using DownloadToVectorCallback = std::function&&)>; + using DownloadToStringCallback = std::function; + using DownloadToFileCallback = std::function; + + virtual void downloadToVector(const std::string& url, DownloadToVectorCallback callback) = 0; + virtual void downloadToString(const std::string& url, DownloadToStringCallback callback) = 0; + virtual void downloadToFile(const std::string& url, const std::string& path, DownloadToFileCallback callback) = 0; +}; +``` + +```C++ +class ImageDownloadStrategy : public DownloadStrategy { +public: + void downloadToVector(const std::string& url, DownloadToVectorCallback callback) override; + void downloadToString(const std::string& url, DownloadToStringCallback callback) override; + void downloadToFile(const std::string& url, const std::string& path, DownloadToFileCallback callback) override; +}; + +class VideoDownloadStrategy : public DownloadStrategy { +public: + void downloadToVector(const std::string& url, DownloadToVectorCallback callback) override; + void downloadToString(const std::string& url, DownloadToStringCallback callback) override; + void downloadToFile(const std::string& url, const std::string& path, DownloadToFileCallback callback) override; +}; +``` + + +___ + +## STL + +As previously for static polymorphism, we also should apply SOLID principles. Once more look at the STL library. It was designed for the open-close principle. because if we want to add new behavior like a new algorithm we don't need to modify anything from the STL library. So every user can do that in its code. For instance, I want to implement the `tranform_if` method: + +```C++ +template +OUT transform_if(IN first, IN last, OUT out, PRED pred, FUN fun) { + while (first != last) { + if (pred(*first)) { + *out = fun(*first); + } else { + *out = *first; + } + ++out; + ++first; + } + + return out; +} +``` + + +___ + +## Open-close summary + +Adding new functionality or types to your code should not require modification of existing code. + +___ + +## L - Liskov Substitution + +* Subtypes must be substitutable for their base types. + * Preconditions cannot be strengthened in a substitute + * Postconditions cannot be weakened in a substitute + * Invariants of the super type must be preserved in a substitute + +* Advantages: + * We will not be surprised when we use a method from the interface that exists with an exception or will be empty + * We will not be surprised when a method acts weird in terms of validation of input data or output data + * Our code will be readable and reliable +___ + +## Shapes + +Let's put aside the topic of downloading for a moment. I want to show you an another example. The problem with Shapes. This is common example, so you can saw it before on the internet. I have one question for you, **which example A or B is the correct one**? + +
+
+ +**A** + +```C++ +class Square { +public: + virtual void setWidth(int); + virtual int getArea() const; +protected: + int width{}; +}; + +class Rectangle : public Square { +public: + virtual void setHeight(int); + int getArea() const override; +private: + int height{}; +}; +``` +
+ +
+ +**B** + +```C++ +class Rectangle { +public: + virtual void setWidth(int); + virtual void setHeight(int); + virtual int getArea() const; +private: + int width{}; + int height{}; +}; + +class Square : public Rectangle { +public: + int getArea() const override; +}; +``` +
+ +
+ + +___ + +The answer is A, because in B we need to modify invariants. Let's check the following code form example B: + +```C++ +class Square : public Rectangle { +public: + void setWidth(int width) override { + // This shape needs to be a square, so both width and height need to be the same + _width = width; + _height = width; + } + void setHeight(int height) override { + // This shape needs to be a square, so both width and height need to be the same + _width = height; + _height = height; + } + int getArea() const override; +}; +``` + +I hope you see, why this is not a good example of inheritance, and option A is much better. + + +___ + +## L - Liskov Substitution + +Backing to previous example. Now we want to implement a downloader class, that allow to fetch any type of data to `std::vector`. + +```C++ +class Downloader { +public: + using Callback = std::function&&)>; + + virtual void downloadToVector(const std::string& url, Callback callback) { + if (!validateUrl(url)) { + throw InvalidUrlException(url); + } + startDownloading(url, callback); + } + +private: + bool validateUrl(const std::string& url); + void startDownloading(const std::string& url, Callback callback); +}; +``` + + +Now we want to add also a downloader that loads data not from the network, but from the database. We use the same virtual function, because `URL` we can treat as the destination of the table (eg: "databaseName.tableName"). So we implement a new class: + + +```C++ +class DatabaseDownloader : public Downloader { +public: + virtual void downloadToVector(const std::string& tableName, Callback callback) { + // Check if user provide string: databaseName.tableName + if (!validatePath(url)) { + throw InvalidTableNameException(tableName); + } + startDownloading(tableName, callback); + } +} +``` + + +___ + +## L - Liskov Substitution (2) + +In the previous example, we once again modify invariants. A programmer who has used the `Downloader` class for a long time, will be sure, that he needs to provide a valid `URL` address. He will be very surprised when he will get an exception `InvalidTableNameException`. This is a dangerous situation because sometimes we may not see such an exception and the program will continue with invalid data. The wrong output will show later, so finding a root cause may be hard and for a few days, we will greet with debugger. + +Another bad example will be when we change the preconditions: + + +```C++ +class Ship { +public: + virtual StatusCode sail() { + if (_numberOfCrew < 20) { + return StatusCode::NotEnoughSailor; + } + if (_cargoWeight > _maxLoad) { + return StatusCode::ShipOverloaded; + } + return StatusCode::OK; + } +}; + +class WarShip : public Ship { + StatusCode sail() override { + // Weakened precondition (previously was 20) + if (_numberOfCrew < 15) { + return StatusCode::NotEnoughSailor; + } + // Strengthened precondition (now we need also add the weight of cannons) + if (_cargoWeight + _cannonsWeight > _maxLoad) {s + return StatusCode::ShipOverloaded; + } + return StatusCode::OK; + } +}; +``` + + +___ + +You may ask me: Why our ship can't behave differently? How can I develop a few types of ships? The answer is easy, just create an interface for the ship, and then in implementation, you will provide a different behavior, but if you inherit from an already implemented class you should not break the Liskov substitution, because we don't know which class will be under the pointer or reference. We have assumption that a base class has some prediction, so we need to satisfy them ant everything should work. + +```C++ +class Ship { +public: + virtual ~Ship(); + virtual StatusCode sail() = 0 +}; + +class CargoShip : public Ship { +public: + StatusCode sail() override { + if (_numberOfCrew < 20) { + return StatusCode::NotEnoughSailor; + } + if (_cargoWeight > _maxLoad) { + return StatusCode::ShipOverloaded; + } + return StatusCode::OK; + } +}; + +class WarShip : public Ship { + StatusCode sail() override { + if (_numberOfCrew < 15) { + return StatusCode::NotEnoughSailor; + } + if (_cargoWeight + _cannonsWeight > _maxLoad) {s + return StatusCode::ShipOverloaded; + } + return StatusCode::OK; + } +}; +``` + + + +___ + +## STL once more + +Let's check `std::transform` method. This algorithm satisfies all rules o far: **S**ingle responsibility, **O**pen-close and also a **L**iskov substitution. The **L** letter is supported, because we have a class `InputIt` and `OutputIt` which need to provide interface like: `operator++`, `operator*`, `operator=` and `operator!=`. We demand from a provided class that these 4 methods need to be implemented. On the other case, the code will not compile. Still, we may provide the wrong implementation, but this is our bug, not a bug from `transform` method. + +```C++ +template +OutputIt transform(InputIt first1, InputIt last1, + OutputIt d_first, UnaryOp unary_op) +{ + while (first1 != last1) + *d_first++ = unary_op(*first1++); + + return d_first; +} +``` + + +___ + +## Liskov Substitution - summary + +Make sure that inheritance is about behavior not about data + +___ + +## I - Interface Segregation + +* A client should never be forced to implement an interface that it doesn’t use, or clients shouldn’t be forced to depend on methods they do not use +    * When we inherit from some interface, we should always implement all methods +    * There is an exception. This may be hard to achieve this for the observer class, because sometimes we need to know only about one event, but other classes could need more events, That is why we do not always implement all of them. +* Advantages: +    * We will not be surprised when we use a method from interface which exits with an exception or will be empty +    * We don't need to worry about how to implement a function which don't make a sense for new class +    * We will follow a rule: Single responsibility. Actually, this is a special case of single responsibility. +___ + +## I - Interface Segregation (2) + +Let's rewrite the interface for the `Download` class to have only one function download, and create classes that will be responsible for downloading a specific type of info, like Image. + + +```C++ +class Downloader { +public: + using DownloadImageFinishedCallback = std::function; + using DownloadCertificateFinishedCallback = std::function; + using DownloadAudioFinishedCallback = std::function; + using DownloadVideoFinishedCallback = std::function; + + virtual ~Downloader() = default; + + virtual void downloadImage(const std::string& url, DownloadImageFinishedCallback callback) = 0; + virtual void downloadCertificate(const std::string& url, DownloadCertificateFinishedCallback callback) = 0; + virtual void downloadAudio(const std::string& url, DownloadAudioFinishedCallback callback) = 0; + virtual void downloadVideo(const std::string& url, DownloadVideoFinishedCallback callback) = 0; +}; +``` + + +```C++ +class Downloader { +public: + using DownloadCallback = std::function&)>; + + virtual ~Downloader() = default; + + virtual void download(const std::string& url, DownloadCallback cb) = 0; +}; +``` + + +___ + +## I - Interface Segregation (3) + +Now depending on what we want to download we can use one of the implementations. Of course, we lose a multitasking object which knows how to download everything, but do we need it? Based on the first rule `single responsibility` is better to have a simpler class. + +```C++ +class ImageDownloader : public Downloader { +public: + void download(const std::string& url, DownloadCallback cb) { + // download an image + } +}; +``` + +```C++ +class VideoDownloader : public Downloader { +public: + void download(const std::string& url, DownloadCallback cb) { + // download a video + } +}; +``` + +___ + +## I - Interface Segregation (4) + +Ok, but what if I need all of these 4 methods. In such case I need to provide 4 object co C'tor of class, to be able to download everything. + +```C++ +class UrlDownloader { + UrlDownloader(ImageDownloader* imageDownloader, + VideoDownloader* videoDownloader, + CertificateDownloader* certificateDownloader, + AudioDownloader* audioDownloader) {} +}; +``` + + +Yes, but this is ok. Usual, classes will not need to all downloader objects. For instance, a `Player` will need to have only 2 objects: `AudioDownloader` and `VideoDownloader`. Another class like `Canvas` will need to have only `ImageDownloader` and `SecurityManager` will need to download only a certificate. Having smaller classes allows us to provide only the functionality that we need. We can also achieve the same by splitting the interface of `Downloader` into 4 smaller classes, instead of having one function `download`. This depends on what will be more useful in our case. **Noticed that this is what I show you earlier → a strategy design pattern**. + + +___ + +```C++ +class ImageDownloader { +public: + using DownloadImageFinishedCallback = std::function; + virtual void downloadImage(const std::string& url, DownloadImageFinishedCallback callback) = 0; +}; +class VideoDownloader { +public: + using DownloadVideoFinishedCallback = std::function; + virtual void downloadVideo(const std::string& url, DownloadVideoFinishedCallback callback) = 0; +}; +class CertificateDownloader { +public: + using DownloadCertificateFinishedCallback = std::function; + virtual void downloadCertificate(const std::string& url, DownloadCertificateFinishedCallback callback) = 0; +}; +class AudioDownloader { +public: + using DownloadAudioFinishedCallback = std::function; + virtual void downloadAudio(const std::string& url, DownloadAudioFinishedCallback callback) = 0; +}; +``` +```C++ +class Player { +public: + Player(AudioDownloader* audioDownloader, VideoDownloader* videoDownloader): + _audioDownloader(audioDownloader), _videoDownloader(videoDownloader) {} + + void playAudio(const std::string& url) { + _audioDownloader->downloadAudio(url, [](Result res, const Audio* audio){ OnAutioDownloaded(res, autio); }); + } + + void playAudio(const std::string& url) { + _videoDownloader->downloadVideo(url, [](Result res, const Audio* audio){ OnAutioDownloaded(res, autio); }); + } +} +``` + + +___ + +## STL example + +Of course, I can't leave this principle without show you that STL library also follow this rule. Once more, check `std::transform` class. We have two types of interface: `InputIt` and `OutputIt`. Each iterator require something else. `Input` is use for reading and `output` for store values. That's why we can for instance `read` form a file or `write` to the file. If we use only one interface, `read-write` we will lose this possibility, because `input_iterator` can't store a value the same as `output-iterator` can't read a value. Keeping 2 interfaces, we allow to read and write from anything. + +```C++ +template +OutputIt transform(InputIt first1, InputIt last1, + OutputIt d_first, UnaryOp unary_op) +{ + while (first1 != last1) + *d_first++ = unary_op(*first1++); + + return d_first; +} +``` + + + +___ + +## Interface segregation - summary + +Make sure interfaces don't include unnecessary dependencies + +___ + +## D - Dependency Inversion + +* High-level modules should not depend on low-level modules. Both should depend on abstraction +* Abstraction should not depend on details. Details should depend on abstraction +* In other words this principle allows for decoupling classes +* Advantages: + * We can easy substitute object of any other class which inherit from the same interface + * This also makes testing easy, because we can mock each object! + +___ + +## D - Dependency Inversion (2) + +Take a look for a `Player` class which has two functions and two members and allow to `playAudio` or `palyVideo`. + +```C++ +class Player { +public: + void playAudio(const std::string& url) { + _audioDownloader.downloadAudio(url, [](Result res, const Audio* audio) { + OnAudioDownloaded(res, autio); }); + } + + void playVideo(const std::string& url) { + _videoDownloader.downloadVideo(url, [](Result res, const Video* video) { + OnVideoDownloaded(res, video); }); + } + +private: + Mp3AudioDownloader _audioDownloader; + Mp4VideoDownloader _videoDownloader; +} +``` + + + +At first sight, everything still works correctly. We can download everything as previously. But what happens when we want to test this class by using mock? Or instead of `Mp3AudioDownloader`, we want to provide `WAVAudioDownloader`, **Creating objects inside class tightly coupled these classes together!**. + +___ + +## D - Dependency Inversion (3) + +High level module should not depend on low level module and vice versa. Both should depends on abstraction: + +```C++ +class Player { +public: + Player(AudioDownloader* audioDownloader, VideoDownloader* videoDownloader) + : _audioDownloader(audioDownloader), _videoDownloader(videoDownloader) {} + + void playAudio(const std::string& url) { + _audioDownloader.downloadAudio(url, [](Result res, const Audio* audio) { OnAudioDownloaded(res, autio); }); + } + + void playVideo(const std::string& url) { + _videoDownloader.downloadVideo(url, [](Result res, const Video* video) { OnVideoDownloaded(res, video); }); + } + +private: + AudioDownloader* _audioDownloader; + VideoDownloader* _videoDownloader; +}; + +int main() { + WAVAudioDownloader wavDownloader; + MP4VideoDownloader mp4Downloader; + Player(&wavDownloader, &mp4Downloader); +} +``` + +___ + +## UML + +Dependency inversion +___ + +## MVC + +The good example of dependency inversion is model-view-controller. Model should be a high level because it will rarely be modified, but view and controller should be on low level because we will continuously add new functionality there. Additionally, we should create two interfaces in the module, one for communication with Controller and the second for communication with view. + +MVC + +___ + +## STL for the fifth time + +And let's back to the `std::transform` method. We represent a set of requirements for each iterator. We demand comparison, dereference etc… if we provide such implementation it will work. Furthermore, we don't need to know what exactly is passed here until it satisfies interface. So `transform` don't depend on low level modules we need to satisfy interface to compile the code. + +```C++ +template +OutputIt transform(InputIt first1, InputIt last1, + OutputIt d_first, UnaryOp unary_op) +{ + while (first1 != last1) + *d_first++ = unary_op(*first1++); + + return d_first; +} +``` + + +___ + +## Dependency inversion - summary + +Prefer depend on abstraction instead of concrete types. + +___ + +## Exercise + +* Open project streamer +* Create Mpeg2Streamer class +* Create MjpegStreamer class +* Allow to add data to stream +* Allow to add/remove receivers +* start/stop stream +* validate data +* Make some dummy implementations that will allow to compile code + +```C++ +virtual bool addReceiver(const StreamInfo& info) = 0; +virtual bool removeReceiver(const StreamInfo& info) = 0; +virtual bool addData(const std::vector& data) = 0; +virtual bool validateData(const std::vector& data) const = 0; +virtual bool startStream() = 0; +virtual bool stopStream() = 0; +virtual bool streamInProgress() const = 0; +``` + + \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/images/MVC.png b/CreatingReliableSoftwareCpp/Presentation/images/MVC.png new file mode 100644 index 0000000000000000000000000000000000000000..a6aa82167355c150315dc882bed13d06f765b3c6 GIT binary patch literal 150842 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�=zY8r%zd-Js>sg|g8 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 aU0>yF62v+qZNWZ^8lF0*k3DhykN*J>72T%* literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/acyclic_visitor_bench.png b/CreatingReliableSoftwareCpp/Presentation/images/acyclic_visitor_bench.png new file mode 100644 index 0000000000000000000000000000000000000000..35ea8b7740e2c572ea1d47a2edcd2af81913150a GIT binary patch literal 32011 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 AC;$Ke literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/ammunition_uml.png b/CreatingReliableSoftwareCpp/Presentation/images/ammunition_uml.png new file mode 100644 index 0000000000000000000000000000000000000000..2fef9b5a9d6557121d99442fda45df1f95e70663 GIT binary patch literal 17345 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/ammunition_uml2.png b/CreatingReliableSoftwareCpp/Presentation/images/ammunition_uml2.png new file mode 100644 index 0000000000000000000000000000000000000000..4e0de073254c19cd894bd1d799dfb7f623f119c6 GIT binary patch literal 24734 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 Vh?BoH2qxQPW@2efIOlTze*lWt9;5&O literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/ammunition_uml3.png b/CreatingReliableSoftwareCpp/Presentation/images/ammunition_uml3.png new file mode 100644 index 0000000000000000000000000000000000000000..71a2926cfcd106dd52d56b8b0bac11fdebc6dc75 GIT binary patch literal 16949 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/builder_uml.png b/CreatingReliableSoftwareCpp/Presentation/images/builder_uml.png new file mode 100644 index 0000000000000000000000000000000000000000..10ece2f319f03c397dae5492ae86265c67ac7499 GIT binary patch literal 48208 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/command_uml.png b/CreatingReliableSoftwareCpp/Presentation/images/command_uml.png new file mode 100644 index 0000000000000000000000000000000000000000..0ffe15e5aa7b6ea80f6ea86917380db46faffc60 GIT binary patch literal 41348 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
B`79%|;&i7S3bF^lO?HP^e=&^_TH?!y5(;*}l~ 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/decorator_uml.png b/CreatingReliableSoftwareCpp/Presentation/images/decorator_uml.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf6b03a07b35de1ccfa8e291c86e1c5757926e6 GIT binary patch literal 21371 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 Uy#3+~JXDjx)78&qol`;+016`xjQ{`u literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/dependency_inversion.png b/CreatingReliableSoftwareCpp/Presentation/images/dependency_inversion.png new file mode 100644 index 0000000000000000000000000000000000000000..1e4da168d6421ae3e66f979bc6c3388d4b9f2874 GIT binary patch literal 20826 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/factory_method_uml.png b/CreatingReliableSoftwareCpp/Presentation/images/factory_method_uml.png new file mode 100644 index 0000000000000000000000000000000000000000..9e93a7e7df37efd4c17aecd9675fbcf809bf66b8 GIT binary patch literal 24919 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�T}$%j}jAeWw5HN_x&<*1XMwZ~&aEj6-;nYG3O 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 zip≷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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/strategy.png b/CreatingReliableSoftwareCpp/Presentation/images/strategy.png new file mode 100644 index 0000000000000000000000000000000000000000..76b4a7477e92484746c7fe5febe236f01752c394 GIT binary patch literal 43674 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 ZzZ)TQdQcyZ_Ea+P(NNP>tyZ>s_CFsE5lsL9 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/strategy_broken_architecture.png b/CreatingReliableSoftwareCpp/Presentation/images/strategy_broken_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..84cbfe993e640245093fc5b99b735e9db491364a GIT binary patch literal 24787 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/strategy_good_architecture.png b/CreatingReliableSoftwareCpp/Presentation/images/strategy_good_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..9fbb90e1c709ab3292c8c1d5d58c8d27463c1232 GIT binary patch literal 32984 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/strategy_perfect_architecture.png b/CreatingReliableSoftwareCpp/Presentation/images/strategy_perfect_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..d2b7cba2e3fbc358d8706c457f108e0439b6b404 GIT binary patch literal 23161 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/template_method_uml.png b/CreatingReliableSoftwareCpp/Presentation/images/template_method_uml.png new file mode 100644 index 0000000000000000000000000000000000000000..8f5a857b95511b9dc7844df36a5d8d1e9ec92d29 GIT binary patch literal 25405 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/visitor.png b/CreatingReliableSoftwareCpp/Presentation/images/visitor.png new file mode 100644 index 0000000000000000000000000000000000000000..5eb9afad710f638e5de8a6491d5d50f5da72a9bb GIT binary patch literal 59029 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 z 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/images/visitor_better_design.png b/CreatingReliableSoftwareCpp/Presentation/images/visitor_better_design.png new file mode 100644 index 0000000000000000000000000000000000000000..c018e3442d4162b2c23a6e859b15b33f4d1365f0 GIT binary patch literal 29900 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 literal 0 HcmV?d00001 diff --git a/CreatingReliableSoftwareCpp/Presentation/index.html b/CreatingReliableSoftwareCpp/Presentation/index.html new file mode 100644 index 0000000..eabf840 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/index.html @@ -0,0 +1,188 @@ + + + + + + + Creating reliable software in C++ + + + + + + + + + + + + + +

+ + + + + + diff --git a/CreatingReliableSoftwareCpp/Presentation/introduction.md b/CreatingReliableSoftwareCpp/Presentation/introduction.md new file mode 100644 index 0000000..1524aae --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/introduction.md @@ -0,0 +1,58 @@ + + +

Presentation authors

+ +
+
+ Mateusz +
+
+ Mateusz Adamski +
+
+___ + + +

Mateusz Adamski

+ +
+
+ +Experience: + +* Trainer at Coders School and Altkom Academy +* C++ developer: worked in Nokia, Opera, Consult red and Synerise + +Training experience: + +* [C++ trainings @ Coders School](https://coders.school/) +* [C++ trainings @ Altkom Academy](https://www.altkomakademia.pl/) +* [C++ trainings @ Sages](https://www.sages.pl/) +* [Nokia Academy](http://nokiawroclaw.pl/nasze-akcje/akademia/) +* Internal corporate trainings + +
+ +
+ Mateusz +
+ +___ + +## Let's introduce yourself! + +* Your name and experience form C++ programing. +* Have you ever used std::optional +* Which design patterns do you know? +* Are you familiar with GTEST? +* Do you know SOLID? +* What do you expect from today's session? + +___ + +## Contract + +* 🎰 Vegas rule +* 🗣 Discussion, not a lecture +* ☕️ Additional breaks on demand +* ⌚️ Be on time after breaks \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/logger.md b/CreatingReliableSoftwareCpp/Presentation/logger.md new file mode 100644 index 0000000..180ce00 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/logger.md @@ -0,0 +1,220 @@ +# logger +___ + +## source_loaction + +Since C++20 we got a nice functionality to perform easy and efficient logging. + +```C++ +void log(const std::string_view message, + const std::source_location location = + std::source_location::current()) +{ + std::cout << std::format("{}({}:{}) '{}':{}\n", + location.file_name(), + location.line(), + location.column(), + location.function_name(), + message); +} + +template void fun(T x) +{ + log(x); +} + +int main(int, char*[]) +{ + log("Hello world!"); + fun("Hello C++20!"); +} +``` + +```bash +prog.cc(24:8) 'int main(int, char**)': Hello world! +prog.cc(19:8) 'void fun(T) [with T = const char*]': Hello C++20! +``` + + +___ + +It's easy to rebuild a little this solution and create own logger: + +```C++ +enum LogType {INF, WRN, ERR}; + +struct Logger { + Logger(LogType logType, std::source_location location = std::source_location::current()): + logType_{logType}, + location_{location} {} + + Logger& operator<<(std::string_view message) { + file_ << std::format("[{}]({}): {}({}:{}) `{}`: {}\n", + toString(logType_), + std::chrono::system_clock::now(), + location_.file_name(), + location_.line(), + location_.column(), + location_.function_name(), + message); + file_ << std::flush; + + return *this; + } + +private: + std::string_view toString(LogType logType) { + switch (logType) { + case INF: return "I"; + case WRN: return "W"; + case ERR: return "E"; + default: return "UNKNOWN!"; + } + } + + LogType logType_; + std::source_location location_; + static std::ofstream file_; +}; + +std::ofstream Logger::file_("log.txt"); +``` + +___ + +Ok now is time to log sth + +```C++ +int main() { + Logger(INF) << "Hello!" << "And Hi" << "And Dzien dobry!"; + Logger(WRN) << "Ojej!"; + Logger(ERR) << "Critical!!!" << "UPS!" << "Bad bad!"; +} +``` + +And in file `log.txt` we got: + + +```C++ +[I](2024-03-17 15:29:34.248747710): prog.cc(55:15) `int main()`: Hello! +[I](2024-03-17 15:29:34.248817593): prog.cc(55:15) `int main()`: And Hi +[I](2024-03-17 15:29:34.248832174): prog.cc(55:15) `int main()`: And Dzien dobry! +[W](2024-03-17 15:29:34.248843859): prog.cc(56:15) `int main()`: Ojej! +[E](2024-03-17 15:29:34.248855275): prog.cc(57:15) `int main()`: Critical!!! +[E](2024-03-17 15:29:34.248866476): prog.cc(57:15) `int main()`: UPS! +[E](2024-03-17 15:29:34.248877615): prog.cc(57:15) `int main()`: Bad bad! +``` + + +___ + +## Second version + +We can also write a whole output when the logger will be destroyed, this allows to log only one line. + +```C++ +Logger::Logger(LogType logType, std::source_location location) + : logType_{logType}, + location_{location} { + file_ << std::format("[{}]({}): {}({}:{}) `{}`:", + toString(logType_), + std::chrono::system_clock::now(), + location_.file_name(), + location_.line(), + location_.column(), + location_.function_name()); +} + +Logger::~Logger() { + file_ << std::endl; // flush and new line +} + +Logger& Logger::operator<<(const std::string& str) { + file_ << " " << str; + return *this; +} +``` + + +___ + +```C++ +int main() { + Logger(INF) << "Hello!" << "And Hi" << "And Dzien dobry!"; + Logger(WRN) << "Ojej!"; + Logger(ERR) << "Critical!!!" << "UPS!" << "Bad bad!"; +} +``` + +And in file `log.txt` we got: + + +```C++ +[I](2024-03-17 15:29:34.248747710): prog.cc(55:15) `int main()`: Hello! And Hi And Dzien dobry! +[W](2024-03-17 15:29:34.248843859): prog.cc(56:15) `int main()`: Ojej! +[E](2024-03-17 15:29:34.248855275): prog.cc(57:15) `int main()`: Critical!!! UPS! Bad bad! +``` + + +___ + +## Ok but this is not thread safe! + +Now we need to make the code a thread-safe and put the `id` of the thread. We need to lock a mutex before writing output to the file and keep it until we destroy a logger. Ofc we risk that someone will create a logger instance and don't destroy them in the following line, but we assume that we use it correctly. We can add a special function that wraps this for use (the most common is macro). + +```C++ +Logger::Logger(LogType logType, std::source_location location): logType_{logType}, location_{location} { + formatted_ = std::format("[{}][th:{}]({}): {}({}:{}) `{}`:", + toString(logType_), + std::this_thread::get_id(), + std::chrono::system_clock::now(), + location_.file_name(), + location_.line(), + location_.column(), + location_.function_name()); +} + +Logger& Logger::operator<<(const std::string& str) { + formatted_ = std::format("{} {}", std::move(formatted_), str); + return *this; +} + +Logger::~Logger() { + std::lock_guard lg(loggMutex_); + loggFile_ << formatted_ << std::endl; +} +``` + + +___ + +```C++ +#define LOG_INF Logger(INF) +#define LOG_ERR Logger(ERR) +#define LOG_WRN Logger(WRN) + +int main() { + LOG_INF << "This" << "is" << "an" << "info"; + LOG_WRN << "This" << "is" << "a" << "warning"; + LOG_ERR << "This" << "is" << "an" << "error"; +} +``` + +```C++ +[I][th:1](2024-03-17 15:53:04.743470912): prog.cc(86:5) `int main()`: This is an info +[W][th:1](2024-03-17 15:53:04.743541096): prog.cc(87:5) `int main()`: This is a warning +[E][th:1](2024-03-17 15:53:04.743558245): prog.cc(88:5) `int main()`: This is an error +``` + + + +___ + +## Cleanup + +At the beginning of the program, we should also clear all logged data, this is easy to achieve: + +```C++ +// Always clear file when program start +std::ofstream Logger::loggFile_("log.txt", std::ofstream::trunc); +``` diff --git a/CreatingReliableSoftwareCpp/Presentation/observer.md b/CreatingReliableSoftwareCpp/Presentation/observer.md new file mode 100644 index 0000000..5d35cc0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/observer.md @@ -0,0 +1,615 @@ +# Observer + +One of the most popular design patterns is an observer. Almost every project uses at least one observer. This popular pattern is used to notify other classes about some changes. There are two types of observers: + +* Pull observer: We inform a class about change, but this class needs to find out what changed +* Push observer: We send all necessary information to class about what changes + +A first approach is more flexible, but forcing a class to get info on what changed, may take a long time to get this info, which may cause an observer slower + + +A second approach is less flexible because we need to create a method per change, to be sure, that the other class will know what happens and can use changed values without explicitly taking arguments or checking the state from the observed class + +___ + +The observer design pattern is a behavioural pattern listed among the 23 well-known "Gang of Four" design patterns that address recurring design challenges in order to design flexible and reusable object-oriented software, yielding objects that are easier to implement, change, test and reuse. Observer has the following traits: + +* A one-to-many dependency between objects should be defined without making the objects tightly coupled. +* When one object changes state, an open-ended number of dependent objects should be updated automatically. +* An object can notify multiple other objects + +Observer UML + +___ + +## Simple example + +We want to inform other classes when the browser will change the focus or will be closed. + +```C++ +struct Observer { + virtual ~Observer() = default; + virtual void browserAboutToQuit() = 0; + virtual void browserFocusChanged() = 0; +} +``` +___ + +```C++ +class Browser { +public: + struct Observer { /* implementation */ }; + + ~Browser() { + std::cout << "Browser is closing\n"; + notifyOnQuit(); + std::cout << "Browser closed\n"; + } + // Rule of 5 :) + + void attach(Observer* observer) { _observers.push_back(observer); } + void detach(Observer* observer) { std::erase(_observers, observer); } + +private: + void notifyOnQuit() const { + std::ranges::for_each(_observers, std::mem_fn(&Observer::browserAboutToQuit)); + } + void notifyOnFocusChanfed() const { + std::ranges::for_each(_observers, std::mem_fn(&Observer::browserFocusChanged)); + } + + std::vector _observers; +}; +``` + +___ + +```C++ +class TabStripManager : public Browser::Observer { +public: + TabStripManager(Browser* browser): _browser(browser) { + browser->attach(this); + } + + ~TabStripManager() { + _browser->detach(this); + } + // Rule of 5 :) + + void browserAboutToQuit() override { + std::cout << "TabStripManager will close tabs\n"; + } + + void browserFocusChanged() override { + std::cout << "TabStripManager lost focus\n"; + } + +private: + Browser* _browser; +}; + +``` + + +___ + +```C++ +int main() { + std::unique_ptr browser = std::make_unique(); + TabStripManager manager(browser.get()); + browser = nullptr; +} +``` + +```bash +Browser is closing +TabStripManager will close tabs +Browser closed +``` + +___ + +## Problem with observer + +Let's check once more the class `TabStripManager`, did you spot a problem here? + +```C++ +class TabStripManager : public Browser::Observer { +public: + TabStripManager(Browser* browser): _browser(browser) { + browser->attach(this); + } + + ~TabStripManager() { + _browser->detach(this); + } + // Rule of 5 :) + + void browserAboutToQuit() override { + std::cout << "TabStripManager will close tabs\n"; + } + + void browserFocusChanged() override { + std::cout << "TabStripManager lost focus\n"; + } + +private: + Browser* _browser; +}; + +``` + + +___ + +## About to quit + +Observer is a useful mechanism to inform other classes that hold a pointer to our class to invalidate this pointer because we are destroying it. If we forget to invalidate the observer we will call` detach` in destructor which will cause a UB because we hold a dangling pointer. + +```C++ +class TabStripManager : public Browser::Observer { +public: + TabStripManager(Browser* browser): _browser(browser) { + assert(browser); + browser->attach(this); + } + + ~TabStripManager() { + if (_browser) { + _browser->detach(this); + } + } + // Rule of 5 :) + + void browserAboutToQuit() override { + std::cout << "TabStripManager will close tabs\n"; + _browser = nullptr; + } + + void browserFocusChanged() override { + std::cout << "TabStripManager lost focus\n"; + } + +private: + Browser* _browser; +}; +``` + + + +___ + +## Template observer + +Do we always need to copy and paste the `Observer` class to every other class that wants to use the pattern? And do we always need to add a method for every state? Can we do this without duplicating the code? + + +Spoiler was in the topic, yes we can! + + +```C++ +template +struct Observer { + virtual ~Observer() = default; + virtual void update(State state) = 0; +}; +``` + +___ + +```C++ +class Browser { +public: + enum class State { + Closing, + FocusChanged + }; + using BrowserObserver = Observer; + + ~Browser() { + std::cout << "Browser is closing\n"; + notify(State::Closing); + std::cout << "Browser closed\n"; + } + // Rule of 5 :) + + void attach(BrowserObserver* observer) { _observers.push_back(observer); } + void detach(BrowserObserver* observer) { std::erase(_observers, observer); } + +private: + void notify(State state) const { + std::ranges::for_each(_observers, [state](auto* observer){ + observer->update(state); + }); + } + + std::vector _observers; +}; +``` + + +___ + +```C++ +class TabStripManager : public Browser::BrowserObserver { +public: + TabStripManager(Browser* browser): _browser(browser) { + assert(browser); + browser->attach(this); + } + + ~TabStripManager() { + if (_browser) { + _browser->detach(this); + } + } + // Rule of 5 :) + + // dispatch message + void update(Browser::State state) override { + switch (state) { + case Browser::State::Closing: { + browserAboutToQuit(); + return; + } + case Browser::State::FocusChanged: { + browserFocusChanged(); + return; + } + } + } + +private: + void browserAboutToQuit() { + std::cout << "TabStripManager will close tabs\n"; + _browser = nullptr; + } + + void browserFocusChanged() { + std::cout << "TabStripManager lost focus\n"; + } + + Browser* _browser; +}; +``` + + +___ + +## Still we have the same behavior + +```C++ +int main() { + std::unique_ptr browser = std::make_unique(); + TabStripManager manager(browser.get()); + browser = nullptr; +} +``` + +```bash +Browser is closing +TabStripManager will close tabs +Browser closed +``` + +___ + +## Problem with observer part 2 + +Let's check once more the class `Browser` do you spot any problem here? + +```C++ +class Browser { +public: + enum class State { + Closing, + FocusChanged + }; + using BrowserObserver = Observer; + + ~Browser() { + std::cout << "Browser is closing\n"; + notify(State::Closing); + std::cout << "Browser closed\n"; + } + // Rule of 5 :) + + void attach(BrowserObserver* observer) { _observers.push_back(observer); } + void detach(BrowserObserver* observer) { std::erase(_observers, observer); } + +private: + void notify(State state) const { + std::ranges::for_each(_observers, [state](auto* observer){ + observer->update(state); + }); + } + + std::vector _observers; +}; +``` + +___ + +## Attach / dettach + +Question1: How do we bahve, when someone will attach twice the same observer? + +- 1) Register it twice, and than notify twice? Like `std::recursive_mutex`? +- 2) Throw an exception? +- 3) Return an error? +- 4) Ignore it, and only print some warning logs about that? + +The answer is not that easy, as usual, it depends, on what we want to achieve + + +Question2: How do we bahve, when someone will detach twice the same observer? + + +- 1) Check if someone attach it twice? +- 2) Throw an exception? +- 3) Return an error? +- 4) Ignore it, and only print some warning logs about that? + +I guess you know the answer :) it depens. + + +___ + +## Problem with observer part 3 + +This is not all the problems that we may have with the observer, let's check this snippet of code. Do you spot any problem here? + +```C++ +class Browser { +public: + enum class State { + Closing, + FocusChanged + }; + using BrowserObserver = Observer; + + void attach(BrowserObserver* observer) { _observers.emplace(observer); } + void detach(BrowserObserver* observer) { _observers.erase(observer); } + void setFocus(bool focus) { + if (std::exchange(_hasFocus, focus) != focus) { + notify(State::FocusChanged); + } + } + bool hasFocus() const { return _hasFocus; } + +private: + void notify(State state) const { + std::ranges::for_each(_observers, [state](auto* observer){ + observer->update(state); + }); + } + + bool _hasFocus{false}; + std::set _observers; +}; +``` + +___ + +## Maybe now? + +```C++ +class Extension : public Browser::BrowserObserver { +public: + Extension(Browser* browser, const std::string& name): _browser(browser), _name(name) { browser->attach(this); } + // Rule of 5 :) + ~Extension() { if (_browser) { _browser->detach(this); } } + + // dispatch message + void update(Browser::State state) override { + switch (state) { + case Browser::State::Closing: return; + case Browser::State::FocusChanged: { + if (_browser->hasFocus()) { displayExtension(); } + return; + } + } + } + +private: + void displayExtension() { + std::cout << "This is an extension: " << _name << '\n'; + } + + Browser* _browser; + std::string _name; +}; +``` + +___ + +## Order of observer + +What will be printed? + +```C++ +int main() { + std::unique_ptr browser = std::make_unique(); + Extension extA(browser.get(), "A"); + Extension extB(browser.get(), "B"); + Extension extC(browser.get(), "C"); + browser->setFocus(true); +} +``` + +The order is unknown because we use `std::set`. Generally, we should **never depend on the order of calling an observer**. Because in the future someone can change the implementation and the program will stop working! + + +___ + +## Exercise + +* Go into directory Core and implement Time and TimeObserver class +* Class Time should have 4 methods: + * void attach(TimeObserver* observer); -> attach observer + * void detach(TimeObserver* observer); -> detach observer + * Time& operator++(); -> increment day and notify observers + * size_t day() const; -> return current day +* Go into directory Ship and make Ship class inherit from TimeObserver +* Each time the observer will be triggered, you should give the crew food and drink +* Each crew member should consume 1 rum and 1 banana (I know they usually eat biscuits) +* If you don't have enough cargo crew should rebel +* Each day of a rebel you should subtract 5 members of the crew +* If the number of crew drops below 0, throw an exception "Game Over" + +___ + +## Exercise 2 + +* Go into directory Store and make Store class inherit from *TimeObserver* +* Class Store should don't know anything about class Time +* We should attach and detach observer outside of class. Think about how you can make it exception-safe (RAII) +* Each time the observer will be triggered, you should change the number of available cargo in the store +* Each time draw a number between -50 and 50 and add it to the amount of cargo +* Print everyday cargo from the Shop and verify if the amount changes +___ + +## Moder apporach + +In modern C++ we try to avoid too many references or pointers because they are problematic. We will try to implement an observer pattern by using value semantics. First let's get rid of the virtual function, and forcing classes to inherit from the observer class. + +```C++ +template +struct Observer { + // First, we don't need to use polymorphism, so also virtual D'tor is redundant + using OnUpdate = std::function; + + explciit Observer(OnUpdate fun): _onUpdate(std::move(fun)) {} + void update(const Subject& subject, State state) { + std::invoke(_onUpdate, subject, state); + } +private: + OnUpdate _onUpdate; +}; +``` + + +___ + +Now move out of the `Browser` class `BorwserObserver` so the files that want to use `BrowserObserver` don't need to include the whole `Browser` file in the header. Only in the source file we will need a `Browser` library, so every time the `Browser` class changes we don't need to recompile a lot of files. + +```C++ +class Browser; + +enum class BrowserState { + Closing, + FocusChanged +}; + +using BrowserObserver = Observer; +``` +___ + +We will still use pointer as `Observer` because they are easy to use (we know that each address is unique) but we can change it to some `uuid` or sth similar to get rid of the pointer also in a `Borwser` class. + +```C++ +class Browser { +public: + void attach(BrowserObserver* observer) { _observers.emplace(observer); } + void detach(BrowserObserver* observer) { _observers.erase(observer); } + void setFocus(bool focus) { + if (std::exchange(_hasFocus, focus) != focus) { + notify(BrowserState::FocusChanged); + } + } + bool hasFocus() const { return _hasFocus; } + +private: + void notify(BrowserState state) const { + std::ranges::for_each(_observers, [state, this](auto* observer){ + observer->update(*this, state); + }); + } + + bool _hasFocus{false}; + std::set _observers; +}; +``` + +___ + +Extension class doesn't need to inherit from `Observer` so we get rid of destructor and vtable. Another advantage is that we separate observers from extension classes. Now it will be a separate object. + +```C++ +class Extension { +public: + explicit Extension(const std::string& name): _name(name) { } + // D'tor is not needed neither the rule of 5 + + // dispatch message + void update(const Browser& browser, BrowserState state) { + switch (state) { + case BrowserState::Closing: + return; + case BrowserState::FocusChanged: { + if (browser.hasFocus()) { + displayExtension(); + } + return; + } + } + } + +private: + void displayExtension() { + std::cout << "This is an extension: " << _name << '\n'; + } + + std::string _name; +}; +``` + +___ + +We have three separate objects, one is a `Browser` the second is an `Extension` and the third is a `BrowserObserver`. We still can use traditional observer patterns, where we use inheritance, but in a lot of cases, we can avoid virtual and make our code faster. + +```C++ +int main() { + std::unique_ptr browser = std::make_unique(); + Extension extension1("A"); + Extension extension2("B"); + Extension extension3("C"); + BrowserObserver observer1([&extension1](const Browser& browser, BrowserState state){ + extension1.update(browser, state); + }); + BrowserObserver observer2([&extension2](const Browser& browser, BrowserState state){ + extension2.update(browser, state); + }); + BrowserObserver observer3([&extension3](const Browser& browser, BrowserState state){ + extension3.update(browser, state); + }); + browser->attach(&observer1); + browser->attach(&observer2); + browser->attach(&observer3); + browser->setFocus(true); +} +``` + +___ + +## Benchmark + +By using value semantics, we may also get around 10% faster code. This depends on what we do as an observer, it the action is long, we will not see any difference, but for quick actions we may improve a performance. + + + +Benchamrk Observer + +___ + +## The last drawback of Oobserver + +Please don't use it everywhere, because your code becomes more complicated when you will have hundreds of observers. Remember you can't relay on the order of notification, so if class `A` calls `notify` which triggers class `B` which also triggers a notification for class `C` which also triggers a notification for class `D` you will have really complicated structure and finding bugs and fixing it will be hard. +___ + +## Exercise 3 + +* Rewrite Observer to use modern approach -> by value semantic. +* Rewrite class Ship +* Rewrite class Store +* Question: Which class was easier to rewrite? diff --git a/CreatingReliableSoftwareCpp/Presentation/recap.md b/CreatingReliableSoftwareCpp/Presentation/recap.md new file mode 100644 index 0000000..458df21 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/recap.md @@ -0,0 +1,8 @@ + + +# Recap + +___ + +## What do you remember from today's session? + diff --git a/CreatingReliableSoftwareCpp/Presentation/refactor.md b/CreatingReliableSoftwareCpp/Presentation/refactor.md new file mode 100644 index 0000000..1d0d0c0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/refactor.md @@ -0,0 +1,880 @@ +# Refactoring + +___ + +## Old C++98/11 code + +Please everyone to sit comfortably. I will show You a piece of code which I had to reactor a few years ago. This code will be simpler than those which I handled, but general ideas stayed, like: `void*` etc... + +Let's start from Valgrind output about this piece of code: + + +```C++ +==1667238== More than 10000000 total errors detected. I'm not reporting any more. +==1667238== Final error counts will be inaccurate. Go fix your program! +``` + +___ + +## General idea + +We want to have a `RequestHandler` which will store requests in the queue and handle them on a separate thread. We have 4 requests: +* Download sth, for instnace an image, +* Upload sth, +* Remove data from cache, +* Clear all cached values. + +We have an API to Server class that has one method handle, which has 4 overloads, each for one request. + +___ + +## Requests + +
+
+ +```C++ +struct Credentail { int cert_; }; + +struct Download { + enum ConnectionType { Telnet, + Ssh }; + + std::string url_; + Credentail credentail_; + int maxMbps_; + bool cache_; + ConnectionType type_; +}; +``` +
+
+ +```C++ +struct Upload { + enum ConnectionType { Telnet, + Ssh }; + + std::string url_; + Image image_; + Credentail credentail_; + int maxMbps_; + int size_; + ConnectionType type_; +}; +``` +
+
+ +
+
+ +```C++ +struct RemoveFromCache { + std::string url_; +}; +``` +
+
+ +```C++ +struct ClearCache { +}; +``` +
+
+___ + +## Server class + +```C++ +class Server { +public: + void handle(const Download& request, void (*callback)(bool, Image)); + + void handle(const Upload& request, void (*callback)(bool, Image)); + + void handle(const RemoveFromCache& request, void (*callback)(bool, Image)); + + void handle(const ClearCache& request, void (*callback)(bool, Image)); + +private: + bool download(const Download& request, Image* image); + + bool upload(const Upload& request, const Image* image); + + std::vector> cache_; +}; +``` + +___ + +## Server class - one of handle method + +```C++ +void handle(const Download& request, void (*callback)(bool, Image)) { + Image image; + + for (const auto& pair : cache_) { + if (pair.second == request.url_) { + image = pair.first; + callback(true, image); + return; + } + } + + if (download(request, &image)) { + if (request.cache_) { + cache_.push_back(std::pair(image, request.url_)); + } + + callback(true, image); + return; + } + + callback(false, Image{}); +} +``` + +___ + +## Server class - download method + +```C++ +bool download(const Download& request, Image* image) { + if (request.type_ == Download::Ssh && request.credentail_.cert_ != 123) { + return false; + } + if (request.type_ == Download::Telnet && request.credentail_.cert_ != 231) { + return false; + } + + // Simulate some other error + if (request.maxMbps_ % 2) { + return false; + } + image->bitmap_ = {97, 98, 99, 100, 101, 102}; + return true; +} +``` + +___ + +## Let's stop here for a while + +* What's wrong with this code? +* How we can improve it? +* Which modern C++ feature we should use here? + +```C++ +void handle(const Download& request, void (*callback)(bool, Image)) { + Image image; + for (const auto& pair : cache_) { + if (pair.second == request.url_) { + image = pair.first; + callback(true, image); + return; + } + } + if (download(request, &image)) { + if (request.cache_) { + cache_.push_back(std::pair(image, request.url_)); + } + callback(true, image); + return; + } + callback(false, Image{}); +} + +bool download(const Download& request, Image* image) { + if (request.type_ == Download::Ssh && request.credentail_.cert_ != 123) { + return false; + } + if (request.type_ == Download::Telnet && request.credentail_.cert_ != 231) { + return false; + } + // Simulate some other error + if (request.maxMbps_ % 2) { + return false; + } + image->bitmap_ = {97, 98, 99, 100, 101, 102}; + return true; +} +``` + + +___ + +## Now will be only worse! + +```C++ +class RequestHandler { +public: + enum RequestType { Download, Upload, Remove, Clear }; + + void start(Server* server); + + void stop(); + + void pushRequest(void* request, RequestType type, void (*callback)(bool, Image)); + +private: + void run(Server* server); + std::tuple waitForRequest(); + + bool stop_; + std::queue> requests_; +}; +``` + +___ + +## Implementations (1) + +```C++ +void start(Server* server) { + std::thread(&RequestHandler::run, this, server).detach(); +} + +void stop() { + stop_ = true; +} + +void pushRequest(void* request, RequestType type, void (*callback)(bool, Image)) { + requests_.push(std::tuple( + request, type, callback)); +} +``` + +___ + +## Implementations (2) + +```C++ + void run(Server* server) { + while (!stop_) { + auto tuple = waitForRequest(); + switch (std::get<1>(tuple)) { + case Download: + server->handle(*((::Download*)(std::get<0>(tuple))), std::get<2>(tuple)); + break; + case Upload: + server->handle(*((::Upload*)(std::get<0>(tuple))), std::get<2>(tuple)); + break; + case Remove: + server->handle(*((RemoveFromCache*)(std::get<0>(tuple))), std::get<2>(tuple)); + break; + case Clear: + server->handle(*((ClearCache*)(std::get<0>(tuple))), std::get<2>(tuple)); + break; + } + } + } + + std::tuple waitForRequest() { + while (requests_.empty() || !stop_) { + } + + auto pair = requests_.front(); + requests_.pop(); + + return pair; + } +``` + +___ + +## The funny part - it actually works! + +```C++ +int main() { + Server server; + RequestHandler handler; + + handler.start(&server); + + Download d{"sth.png", 123, 100, true, Download::Ssh}; + handler.pushRequest((void*)(&d), + RequestHandler::Download, + [](bool succes, Image image) { + if (succes) { + for (auto el : image.bitmap_) { + std::cout << el << ' '; + } + std::cout << '\n'; + } else { + std::cout << "FAILED!\n"; + } + }); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + handler.stop(); +} +``` + + +___ + +## Let's fix this ugly code! + +For Requests we only need add `enum class` instead of `enum` the rest seems ok. + +
+
+ +```C++ +struct Credentail { int cert_; }; + +struct Download { + enum class ConnectionType { Telnet, + Ssh }; + + std::string url_; + Credentail credentail_; + int maxMbps_; + bool cache_; + ConnectionType type_; +}; +``` +
+
+ +```C++ +struct Upload { + enum class ConnectionType { Telnet, + Ssh }; + + std::string url_; + Image image_; + Credentail credentail_; + int maxMbps_; + int size_; + ConnectionType type_; +}; +``` +
+
+ +
+
+ +```C++ +struct RemoveFromCache { + std::string url_; +}; +``` +
+
+ +```C++ +struct ClearCache { +}; +``` +
+
+ +___ + +## Alias and status code + +The `bool` flag is the best option for describing an error + +```C++ +enum class StatusCode { + Ok, + WrongUrl, + CanNotConnect, + WrongCredential, + MaximumSizeExceeded, + MissingImage, +}; +``` + +Let's add also an aliast for `callback` + + +```C++ +using CallbackType = void (*)(StatusCode, Image); + +void handle(const Download& request, CallbackType callback); +``` + +___ + +## Use references and STL algorithms (1) + +```C++ +void handle(const Download& request, CallbackType callback) { + if (const auto it = findImage(request.url_); it != std::cend(cache_)) { + callback(StatusCode::Ok, it->first); + return; + } + + Image img; + const auto status = download(request, img); + if (status == StatusCode::Ok) { + if (request.cache_) { + cache_.emplace_back(img, request.url_); + } + } + + callback(status, img); +} +``` + +___ + +## Use references and STL algorithms (2) + +```C++ +std::vector>::const_iterator findImage(const std::string& url) const { + return std::find_if(cbegin(cache_), cend(cache_), + [url](const auto& pair) { + const auto& [_, thisUrl] = pair; + return thisUrl == url; + }); +} + +StatusCode download(const Download& request, Image& image) const { + if (request.type_ == Download::ConnectionType::Ssh && request.credentail_.cert_ != 123) { + return StatusCode::WrongCredential; + } + if (request.type_ == Download::ConnectionType::Telnet && request.credentail_.cert_ != 231) { + return StatusCode::CanNotConnect; + } + + // Simulate some other error + if (request.maxMbps_ % 2) { + return StatusCode::WrongUrl; + } + image.bitmap_ = {97, 98, 99, 100, 101, 102}; + return StatusCode::Ok; +} +``` + + +___ + +## Use references and STL algorithms (3) + +```C++ +void handle(const Upload& request, CallbackType callback) const { + if (request.size_ > 100) { + callback(StatusCode::MaximumSizeExceeded, Image{}); + return; + } + + callback(upload(request), Image{}); +} + +void handle(const RemoveFromCache& request, CallbackType callback) { + if (const auto it = findImage(request.url_); it != std::cend(cache_)) { + cache_.erase(it); + callback(StatusCode::Ok, Image{}); + return; + } + + callback(StatusCode::MissingImage, Image{}); +} +``` + +___ + +## Let's fix void* + +Could be better, but this work and is safe. + +```C++ +using RequestType = std::variant; + +void pushRequest(const RequestType& request, Server::CallbackType callback) { + requests_.emplace(request, callback); +} + +void run(Server* server) { + const auto [request, callback] = waitForRequest(); + switch (request.index()) { + case 0: + server->handle(std::get(request), callback); + break; + case 1: + server->handle(std::get(request), callback); + break; + case 2: + server->handle(std::get(request), callback); + break; + case 3: + server->handle(std::get(request), callback); + break; + } +} +``` + +___ + +## Make it thread safe (1) + +```C++ +void start(Server* server) { + std::thread(&RequestHandler::run, this, server).detach(); +} + +void stop() { + stop_ = true; + cv_.notify_one(); +} + +void pushRequest(const RequestType& request, Server::CallbackType callback) { + { + std::lock_guard lock(m_); + requests_.emplace(request, callback); + } + cv_.notify_one(); +} + +using QueueType = std::pair; + +std::mutex m_; +std::condition_variable cv_; +std::atomic stop_{false}; +std::queue requests_; +``` + +___ + +## Make it thread safe (2) + +```C++ +std::optional waitForRequest() { + std::unique_lock lk(m_); + cv_.wait(lk, [&]() { return !requests_.empty() || stop_; }); + if (stop_) { + return std::nullopt; + } + auto pair = requests_.front(); + requests_.pop(); + + return pair; +} +``` +___ + +## Usage actually not change + +```C++ +Server server; +RequestHandler handler; + +handler.start(&server); + +handler.pushRequest(Download{"sth.png", 123, 100, true, Download::ConnectionType::Ssh}, + [](Server::StatusCode status, Image image) { + if (status == Server::StatusCode::Ok) { + for (auto el : image.bitmap_) { + std::cout << el << ' '; + } + std::cout << '\n'; + } else { + std::cout << "FAILED!\n"; + } + }); + +std::this_thread::sleep_for(std::chrono::milliseconds(10)); +handler.stop(); +``` + +___ + +## Valgird is almost satisfied + +It is suspicious only for a pointer to a server that was created in another thread. It marks it as possibly lost, but we know that we didn't do any allocation, because we created it on the stack, and pass only the address. + +```C++ +==1678528== LEAK SUMMARY: +==1678528== definitely lost: 0 bytes in 0 blocks +==1678528== indirectly lost: 0 bytes in 0 blocks +==1678528== possibly lost: 288 bytes in 1 blocks +==1678528== still reachable: 0 bytes in 0 blocks +==1678528== suppressed: 0 bytes in 0 blocks +==1678528== +==1678528== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) +``` +___ + +## Further improvements + +We can have 2 callbacks. One returns a downloaded image and error code, and the second returns only an error code. We can change the name of function `handle` to `download`, `upload` etc.. because inside `switch` we know which function we call because we know the type of request (there is no polymorphism). So we can avoid unnecessary arguments for image, especially this is important when classes don't have default C'tor. We should only make it as a template to allow the download other things than `Images.` We can also use `std::visit` method to avoid switch case. + +___ + +## Better solution - use OOP + +This particular example works, but what happens when we extend the program to handle also other types like Videos and audio? We need to extend server interface to handle different types. + +```C++ + void handle(const DownloadVideo& request, void (*callback)(bool, Video)); + void handle(const UploadVideo& request, void (*callback)(bool, Video)); + + void handle(const DownloadAudio& request, void (*callback)(bool, Audio)); + void handle(const UploadAudio& request, void (*callback)(bool, Audio)); + + void handle(const DownloadCertificates& request, void (*callback)(bool, Certificates)); + void handle(const UploadCertificates& request, void (*callback)(bool, Certificates)); +``` + + +Server class grow and grow, and now have a lot of resposibilities and depends form implementations of `Image`, `Video`, `Audio` and `Certificates` this is bad, really bad. We should folow SOLID principles. + + +___ + +## Command pattern + +Let's create an abstraction and break the dependency between `Server` and `Request`. `Command` object will have only one method `operator()` that we can call. This operator will perform one action like: `Download`, `Upload`, `RemoveFormCache`, `ClearCache`. + +```C++ +class Command { +public: + enum class StatusCode { + Ok, WrongUrl, CanNotConnect, WrongCredential, MaximumSizeExceeded, MissingImage + }; + + // Rule of 5! + virtual ~Command() = default; + Command(const Command&) = default; + Command(Command&&) = default; + Command& operator=(const Command&) = default; + Command& operator=(Command&&) = default; + + virtual void operator()() const = 0; +}; +``` + + + +___ + +## Delegate pattern + +Because `Command` needs to know only how to deal with Files like `Image`, `Video` or `Audio`. We need to create a `Delegate` that delegates the rest of the actions to the `Server` class. + +```C++ +class Command { + class Delegate { + public: + virtual ~Delegate() = default; + virtual StatusCode removeFromCache(const std::string& url) = 0; + virtual void clearCache() = 0; + virtual void addToCache(const std::vector& data, const std::string& url) = 0; + virtual StatusCode download(std::vector& data, const DownloadRequest& request) const = 0; + virtual StatusCode upload(const std::vector& data, const UploadRequest& request) const = 0; + }; + + explicit Command(Delegate* delegate) + : delegate_(delegate) {} + // ... +protected: + Delegate* delegate_; +}; +``` + + +___ + +## Server class + +Now server-class depends on abstraction which is `Delegate` and only performs actions with connecting with network and caching values. we can also create another class that will cache values. Class `Command` depends on abstraction, because we don't need to know which class will implement delegate methods. + +```C++ +class Server : public Command::Delegate { +public: + ~Server() override = default; + + Command::StatusCode removeFromCache(const std::string& url) override; + + void clearCache() override; + + void addToCache(const std::vector& data, const std::string& url) override; + + Command::StatusCode download(std::vector& data, const DownloadRequest& request) const override; + + Command::StatusCode upload(const std::vector& data, const UploadRequest& request) const override; + +private: + std::vector, std::string>>::const_iterator findFile(const std::string& url) const; + + std::vector, std::string>> cache_; +}; +``` + + + +___ + +## Easy to extend + +Now we can create whatever command we want to. + +```C++ +class UploadImageCommand : public Command { +public: + using CallbackType = void (*)(StatusCode); + + ~UploadImageCommand() override = default; + + UploadImageCommand(Delegate* delegate, const Image& image, CallbackType callback, const UploadRequest& request) + : Command(delegate), image_(image), callback_(callback), request_(request) {} + + void operator()() const override { + callback_(delegate_->upload(image_.bitmap_, request_)); + }; + +private: + Image image_; + CallbackType callback_; + UploadRequest request_; +}; +``` + + + +___ + +## Download Image command + +We can deal with different parameters, and callbacks. + +```C++ +class DownloadImageCommand : public Command { +public: + using CallbackType = void (*)(StatusCode, Image); + + ~DownloadImageCommand() override = default; + + DownloadImageCommand(Delegate* delegate, CallbackType callback, const DownloadRequest& request) + : Command(delegate), callback_(callback), request_(request) {} + + void operator()() const override { + std::vector data; + if (auto status = delegate_->download(data, request_); status == Command::StatusCode::Ok) { + // Do some conversion on vector + if (request_.cache_) { + delegate_->addToCache(data, request_.url_); + } + Image image{data}; + callback_(status, std::move(image)); + } else { + callback_(status, Image{}); + } + }; + +private: + CallbackType callback_; + DownloadRequest request_; +}; +``` + + +___ + +## Request handler + +Request handlers also break their dependency on the server. We don't need to know about `Server` class anymore. We just push the command on queue and call `operator()`. + +```C++ +class RequestHandler { +public: + void start() { + std::thread(&RequestHandler::run, this).detach(); + } + + void stop() { + stop_ = true; + cv_.notify_one(); + } + + void pushRequest(std::unique_ptr command) { + { + std::lock_guard lock(m_); + requests_.push(std::move(command)); + } + cv_.notify_one(); + } + +private: + void run() { + while (!stop_) { + const auto request = waitForRequest(); + if (!request) { + return; + } + + (*request)(); + } + } + + std::unique_ptr waitForRequest() { + std::unique_lock lk(m_); + cv_.wait(lk, [&]() { return !requests_.empty() || stop_; }); + if (stop_) { + return nullptr; + } + + std::unique_ptr request = std::move(requests_.front()); + requests_.pop(); + + return request; + } + + std::mutex m_; + std::condition_variable cv_; + std::atomic stop_{false}; + std::queue> requests_; +}; +``` + + +___ + +## Usage + +```C++ +int main() { + Server server; + RequestHandler handler; + + handler.start(); + handler.pushRequest(std::make_unique( + &server, + [](Command::StatusCode status, Image img) { + if (status == Command::StatusCode::Ok) { + std::copy(cbegin(img.bitmap_), cend(img.bitmap_), + std::ostream_iterator(std::cout, " ")); + std::cout << '\n'; + } else { + std::cout << "Sth went wrong!\n"; + } + }, + DownloadRequest{"Sth123", Credentail{123}, 200, true, DownloadRequest::ConnectionType::Ssh})); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + handler.stop(); +} +``` + +___ + +## Valgrind + +Now we have easy to extend code, which also satisfies Valgrind. + +```C++ +==1790927== +==1790927== HEAP SUMMARY: +==1790927== in use at exit: 0 bytes in 0 blocks +==1790927== total heap usage: 11 allocs, 11 frees, 74,770 bytes allocated +==1790927== +==1790927== All heap blocks were freed -- no leaks are possible +==1790927== +==1790927== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) +``` \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/strategy.md b/CreatingReliableSoftwareCpp/Presentation/strategy.md new file mode 100644 index 0000000..3421691 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/strategy.md @@ -0,0 +1,735 @@ +# Strategy + +The second most popular design pattern is a strategy. If I need to bet how many of you used this pattern at least once I will say all of you. Strategy is the most common pattern used by the STL library and makes it so flexible. That's why we should use it often (maybe not everywhere) but in most cases, strategy will be an answer. + +Why we should use strategy? As David Thomas and Andrew Hunt said in the book: *Inheritance is Rarely the Answer*. + + +___ + +## Example of bad inheritance + +Before we talk about strategy patterns, let's look at the bad design of the application. We want to create three types of ammunition: *Round*, *Chain* and *Grape*. Each type of ammunition needs to be displayed as an icon (for instance when we check, the inventory, or buy it from the store) and also needs to be animated when a ship `fires` this ammunition during combat. + + +We decided to solve this problem by create inheritance. We inherit from class `Ammunition` and create three classes of `Shots`, then depending on which graphic library we used we `draw` it using `metal` or `OpenGL`. + + +Amunnition UML + + +___ + +## Next iteration + +After we successfully implemented the `draw` method, we decided to add `SDL` and `WindowsAnimationManager` libraries for displaying animation during combat. Because we already use `OpenGL` and `metal` libraries, we still need to support them. So we need to create another layer of inheritance. + +Amunnition UML + + + +___ + +I hope all of you saw that this is not a good example of a design application. Each time we add support for a new library, we need to create another layer of inheritance. How we can make it more flexible? The answer is the `Strategy` design pattern. + +Amunnition UML + + + +___ + +## Simplify + +First of all, we don't want to break 2 of the SOLID letters: **L**iskov substitution and **S**ingle responsibility. That's why we should inherit from class which all methods make sense for us. We create two strategies, one for `fire` and one for `draw`. We also want to avoid an oversized hierarchy of class. + +Amunnition UML + + + +___ + +## Implementation + +The ammunition class will be a base class with the interface. It also contains info about the amount of ammunition. + +```C++ +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + virtual void fire() = 0; + virtual void draw() = 0; + virtual int getDamage() const = 0; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; +``` +___ + +```C++ +class FireStrategy { +public: + virtual void fire(const Ammunition& ammunition) = 0; +}; + +class SDLFireStrategy : public FireStrategy { +public: + void fire(const Ammunition& ammunition) override { + std::cout << "SDL Deal: " << ammunition.getDamage() << " damage!" << '\n'; + } +}; + +class WAMFireStrategy : public FireStrategy { +public: + void fire(const Ammunition& ammunition) override { + std::cout << "WAM Deal: " << ammunition.getDamage() << " damage!" << '\n'; + } +}; +``` + +```C++ +class DrawStrategy { +public: + virtual void draw(const Ammunition& ammunition) = 0; +}; + +class OpenGLDrawStrategy : public DrawStrategy { +public: + void draw(const Ammunition& ammunition) override { + std::cout << "OpenGL Ammunition: " << ammunition.amount() << '\n'; + } +}; + +class MetalDrawStrategy : public DrawStrategy { +public: + void draw(const Ammunition& ammunition) override { + std::cout << "Metal Ammunition: " << ammunition.amount() << '\n'; + } +}; +``` + + +___ + +```C++ +class RoundShot : public Ammunition { +public: + RoundShot(size_t amount, std::unique_ptr&& fireStrategy, std::unique_ptr&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { _fireStrategy->fire(*this /* other args if needed*/); } + void draw() override { _drawStrategy->draw(*this /* other args if needed*/); } + int getDamage() const override { return 10; } +private: + std::unique_ptr _fireStrategy; + std::unique_ptr _drawStrategy; +}; +``` + +```C++ +class ChainShot : public Ammunition { +public: + ChainShot(size_t amount, std::unique_ptr&& fireStrategy, std::unique_ptr&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { _fireStrategy->fire(*this /* other args if needed*/); } + void draw() override { _drawStrategy->draw(*this /* other args if needed*/); } + int getDamage() const override { return 15; } +private: + std::unique_ptr _fireStrategy; + std::unique_ptr _drawStrategy; +}; +``` + + +```C++ +class GrapeShot : public Ammunition { +public: + GrapeShot(size_t amount, std::unique_ptr&& fireStrategy, std::unique_ptr&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { _fireStrategy->fire(*this /* other args if needed*/); } + void draw() override { _drawStrategy->draw(*this /* other args if needed*/); } + int getDamage() const override { return 20; } +private: + std::unique_ptr _fireStrategy; + std::unique_ptr _drawStrategy; +}; +``` + + + +___ + +## Usage + +We can easily inject any strategy into an ammunition class. This will help us keep another solid rule **D**ependency inversion and also dependency injection. + +```C++ +int main() { + std::unique_ptr grapeShot = std::make_unique( + 100, std::make_unique(), std::make_unique()); + + grapeShot->fire(); + grapeShot->draw(); +} +``` + +```bash +SDL Deal: 20 damage! +OpenGL Ammunition: 100 +``` + + +___ + +## Drawback + +The main drawback of the strategy pattern is visible when we try to add a new type. In such case, we need to implement a new behavior for each of these classes: + +* DrawOpenGLStrategy +* DrawMetalStrategy +* WamFireStrategy +* SDLFireStrategy + +This will be not such big deal, when we have access to all of the source code, but in case, when we can't modify this it will be problematic + + +___ + +## Improvement + +For now, `DrawStrategy` and `FireStrategy`, have one `virtual` function which probably needs to distinguish which type of ammunition should be drawn or animate. That's why we can create a more flexible interface, which takes a specific type and we don't need to use any casting. + +```C++ +class FireStrategy { +public: + virtual void fire(const ChainShot& shot) = 0; + virtual void fire(const RoundShot& shot) = 0; + virtual void fire(const GrapeShot& shot) = 0; +}; +``` + +___ + +```C++ +class SDLFireStrategy : public FireStrategy { +public: + void fire(const ChainShot& shot) override { + std::cout << "SDL Chain Shot Deal: " << shot.getDamage() << " damage!" << '\n'; + } + void fire(const RoundShot& shot) override { + std::cout << "SDL Round Shot Deal: " << shot.getDamage() << " damage!" << '\n'; + } + void fire(const GrapeShot& shot) override { + std::cout << "SDL Grape Shot Deal: " << shot.getDamage() << " damage!" << '\n'; + } +}; +``` + +```C++ +class WAMFireStrategy : public FireStrategy { +public: + void fire(const ChainShot& shot) override { + std::cout << "WAM Chain Shot Deal: " << shot.getDamage() << " damage!" << '\n'; + } + void fire(const RoundShot& shot) override { + std::cout << "WAM Round Shot Deal: " << shot.getDamage() << " damage!" << '\n'; + } + void fire(const GrapeShot& shot) override { + std::cout << "WAM Grape Shot Deal: " << shot.getDamage() << " damage!" << '\n'; + } +}; +``` + + +___ + +```C++ +class DrawStrategy { +public: + virtual void draw(const ChainShot& shot) = 0; + virtual void draw(const RoundShot& shot) = 0; + virtual void draw(const GrapeShot& shot) = 0; +}; +``` + +```C++ +class OpenGLDrawStrategy : public DrawStrategy { +public: + void draw(const ChainShot& shot) override { + std::cout << "OpenGL Chain Shot: " << shot.amount() << '\n'; + } + void draw(const RoundShot& shot) override { + std::cout << "OpenGL Round Shot: " << shot.amount() << '\n'; + } + void draw(const GrapeShot& shot) override { + std::cout << "OpenGL Grape Shot: " << shot.amount() << '\n'; + } +}; +``` + + +```C++ +class MetalDrawStrategy : public DrawStrategy { +public: + void draw(const ChainShot& shot) override { + std::cout << "Metal Chain Shot: " << shot.amount() << '\n'; + } + void draw(const RoundShot& shot) override { + std::cout << "Metal Round Shot: " << shot.amount() << '\n'; + } + void draw(const GrapeShot& shot) override { + std::cout << "Metal Grape Shot: " << shot.amount() << '\n'; + } +}; +``` + + +___ + +## Usage + +Now the function exactly knows, which type is handling, and can animate it or draw it correctly, without any type checking. + +```C++ +int main() { + std::unique_ptr grapeShot = std::make_unique( + 100, std::make_unique(), std::make_unique()); + + grapeShot->fire(); + grapeShot->draw(); +} +``` + +```bash +SDL Grape Shot Deal: 20 damage! +OpenGL Grape Shot: 100 +``` + + +___ + +## Separate implementation + +Strategy can distinguish type, but still depends on all types, let's rewrite the code once more and use another letter form SOLID: **I**nterface segregation. Each implementation will be a separate strategy class, so when we add a new type, other strategies will not know about it. + +```C++ +class FireChainShotStrategy { +public: + virtual void fire(const ChainShot& shot) = 0; +}; + +class FireRoundShotStrategy { + virtual void fire(const RoundShot& shot) = 0; +}; + +class FireGrapeShotStrategy { + virtual void fire(const GrapeShot& shot) = 0; +}; + +class SDLFireChainShotStrategy : public FireChainShotStrategy { +public: + void fire(const ChainShot& shot) override; +}; + +class SDLFireRoundShotStrategy : public FireRoundShotStrategy { +public: + void fire(const RoundShot& shot) override; +}; + +class SDLFireGrapeShotStrategy : public FireGrapeShotStrategy { +public: + void fire(const GrapeShot& shot) override; +}; +``` + + +___ + +```C++ +class DrawChainShotStrategy { +public: + virtual void draw(const ChainShot& shot) = 0; +}; + +class DrawRoundShotStrategy { + virtual void draw(const RoundShot& shot) = 0; +}; + +class DrawGrapeShotStrategy { + virtual void draw(const GrapeShot& shot) = 0; +}; +``` + +```C++ +class OpnGLDrawChainShotStrategy : public DrawChainShotStrategy { +public: + void draw(const ChainShot& shot) override; +}; + +class OpenGLDrawRoundShotStrategy : public DrawRoundShotStrategy { +public: + void draw(const RoundShot& shot) override; +}; + +class OpenGLDrawGrapeShotStrategy : public DrawGrapeShotStrategy { +public: + void draw(const GrapeShot& shot) override; +}; +``` + + +___ + +## Single resposibility + +In the beginning, we may think that we will need to create too many classes because each `Ammunition` type needs 4 classes (2 for draw, and 2 for fire), but when we take a look at the first letter of SOLID - **S**ingle responsibility, we understand that now we follow this rule. Previously `OpenGLDrawStrategy` and `MEtalDrawStrategy` needed to know about 3 different types of ammunition, and we broke all rules: +* Single resposinility -> each class need to know about all types +* Open close -> code was not open for extension, when we add a new type, we need to implement behavior in all 4 classes, even if we don't want to, which may cause to break another letter: +* Liskov substitution -> we may inherit from an interface which is not fully suitable for us, that's why we should: +* Interface segregation -> separate too big interface into a smaller one. +* Dependency inversion -> High level class DrawStrategy nad FireStrategy depends on low level classes RoundShot, ChainShot and GrapeShot. + +As you can see, the following implementation of strategy, with many small classes is the correct one. + + +___ + +## Broken Dependency inversion + +Dependency inversion -> High level class DrawStrategy nad FireStrategy depends on low level classes RoundShot, ChainShot and GrapeShot. + +Broken architecture + +___ + +## Modern approach + +Following the rule of SOLID, we almost reached a perfect architecture, but the one thing left. Class `DrawChainStrategy`, `DrawRoundStrategy`, and `DrawGrapeStrategy` is connected with a specific type like: `RoundShot` or `ChainShot`. We follow all SOLID rules, but still there is one thing to improve. **Do you know how we can improve it**? + +Good architecture + +___ + +## Template strategy + +By creating a template for `DrawStrategy` we remove all dependencies between specific types of ammunition and strategy: + +```C++ +template +class DrawStrategy { + virtual ~DrawStrategy() = default; + virtual void draw(const T&) const = 0; +}; +``` + + +Perfect architecture + + +___ + +## Full implementation + +```C++ +template +class FireStrategy { +public: + virtual void fire(const T& shot) = 0; +}; + +class SDLFireRoundShotStrategy : public FireStrategy { +public: + void fire(const RoundShot& shot) override; +}; + +class SDLFireChainShotStrategy : public FireStrategy { +public: + void fire(const ChainShot& shot) override; +}; + +class SDLFireGrapeShotStrategy : public FireStrategy { +public: + void fire(const GrapeShot& shot) override; +}; +``` + +```C++ +class WAMFireRoundShotStrategy : public FireStrategy { +public: + void fire(const RoundShot& shot) override; +}; + +class WAMFirChainShotStrategy : public FireStrategy { +public: + void fire(const ChainShot& shot) override; +}; + +class WAMFireGrapeShotStrategy : public FireStrategy { +public: + void fire(const GrapeShot& shot) override; +}; +``` + + +___ + +```C++ +template +class DrawStrategy { +public: + virtual void draw(const T& shot) = 0; +}; + +class OpenGLDrawRoundShotStrategy : public DrawStrategy { +public: + void draw(const RoundShot& shot) override; +}; + +class OpenGLDrawChainShotStrategy : public DrawStrategy { +public: + void draw(const ChainShot& shot) override; +}; + +class OpenGLDrawGrapeShotStrategy : public DrawStrategy { +public: + void draw(const GrapeShot& shot) override; +}; +``` + +```C++ +class MetalDrawRoundShotStrategy : public DrawStrategy { +public: + void draw(const RoundShot& shot) override; +}; + +class MetalDrawChainShotStrategy : public DrawStrategy { +public: + void draw(const ChainShot& shot) override; +}; + +class MetalDrawGrapeShotStrategy : public DrawStrategy { +public: + void draw(const GrapeShot& shot) override; +}; +``` + + +___ + +```C++ +class RoundShot : public Ammunition { +public: + RoundShot(size_t amount, std::unique_ptr>&& fireStrategy, std::unique_ptr>&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 10; } + +private: + std::unique_ptr> _fireStrategy; + std::unique_ptr> _drawStrategy; +}; +``` + +```C++ +class ChainShot : public Ammunition { +public: + ChainShot(size_t amount, std::unique_ptr>&& fireStrategy, std::unique_ptr>&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 15; } + +private: + std::unique_ptr> _fireStrategy; + std::unique_ptr> _drawStrategy; +}; +``` + + +___ + +```C++ +class GrapeShot : public Ammunition { +public: + GrapeShot(size_t amount, std::unique_ptr>&& fireStrategy, std::unique_ptr>&& drawStrategy) + : Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {} + void fire() override { + _fireStrategy->fire(*this /* other args if needed*/); + } + void draw() override { + _drawStrategy->draw(*this /* other args if needed*/); + } + int getDamage() const override { return 20; } + +private: + std::unique_ptr> _fireStrategy; + std::unique_ptr> _drawStrategy; +}; +``` + +```C++ +int main() { + std::unique_ptr grapeShot = std::make_unique( + 100, std::make_unique(), std::make_unique()); + + grapeShot->fire(); + grapeShot->draw(); +} +``` + + +```bash +SDL Grape Shot Deal: 20 damage! +OpenGL Grape Shot: 100 +``` + + +___ + +## Exercise 1 + +* Go into directory Core and implement ShipStrategy as a template class +* Strategy should have one pure virtual function: Res handle(T&) +* Implement in directory Ship class ShipEasyDifficultLvlStrategy + * Each cargo supplies 2 sailors, so if you have 40 crew, you need 20 banas and 20 rum +* Implement NextDay by using strategy class +* Run code, and verify result + +___ + +## Exercise 2 + +* Implement in directory *Player* class *PalyerEasyDifficultLvlStrategy* +    * Strategy should roll a die (1-20): +    * If result is lower than 5 -> 0 DMG +    * If result is higher than 19 -> multiple damage by 2 +    * Damage should be rolled from (25 to 50) +    * deal damage to the ship and return how much damage was deal. Print it in console +* Add all necessary implementation to the *Enemy* file +* Test it + +___ + +## Exercise 3 + +* Implement new classes *EnemyHardDifficultLvlStrategy* and *ShipHardDifficultLvlStrategy* + * Strategy for Ship, should subtract cargo equal crew size +    * Strategy for Enemy should roll a die (1-20): +     * If result is lower than 3 -> 0 DMG + * If result is higher than 15 but not equal 20 -> multiple damage by 3 +     * If result is higher than 19 -> multiple damage by 3 +     * Damage should be rolled from (30 to 60) + * You shouldn't modify any existing file, except the main.cpp, where you should use a new strategy +* Run code and verify the result + +___ + +## Strategy is everywhere + +Before we go on to the next design pattern. I want to show you that `Strategy` is almost everywhere. Let's closely look at some STL algorithms: + +```C++ +template< class RandomIt > +void sort( RandomIt first, RandomIt last ); +``` + + +```C++ +template< class RandomIt, class Compare > +void nth_element( RandomIt first, RandomIt nth, RandomIt last, Compare comp ); +``` + + +```C++ +template< class InputIt1, class InputIt2, class OutputIt, class Compare > +OutputIt set_difference( InputIt1 first1, InputIt1 last1, + InputIt2 first2, InputIt2 last2, + OutputIt d_first, Compare comp ); +``` + + +**What is common for all of these functions?** + + + +___ + +STL library was designed by using design patterns, which gives this library a lot of flexibility. Users who want to use one of the STL algorithms, need to provide a strategy, mostly it will be a lambda object, which tells the algorithm how to treat a specific object. What's more, it uses modern by-value semantics, because we don't have any polymorphisms and virtual functions. The first version of STL was designed in 1994-1998, so this modern approach has 30 years :) I think we should learn a lot from this design, because not always need to solve everything by creating virtual classes. + +___ + +## Rewrite Difficult Strategy + +```C++ +template +class Ship : public TimeObserver { +public: + Ship(Time* time, DifficultLvlStrategy strategy, const std::string& name, int capacity, int crew); + // ohter public methods + +private: + // other members + DifficultLvlStrategy _strategy; +}; +``` + +```C++ +int main() { + auto strategy = [](Ship& ship[]){ + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; + }; + + Ship ship(&time, strategy, "Black Widow", 1000, 40); +} +``` + + +___ + +## If we don't like templates + +```C++ +class Ship : public TimeObserver { +public: + Ship(Time* time, std::function strategy, const std::string& name, int capacity, int crew); + // ohter public methods + +private: + // other members + std::function _strategy; +}; +``` + +```C++ +int main() { + auto strategy = [](Ship& ship[]){ + Ship::StatusCode status; + ship.unload("Rum", ship.crew() / 2, status); + Ship::StatusCode status2; + ship.unload("Banana", ship.crew() / 2, status2); + + return status == Ship::StatusCode::OK && status2 == Ship::StatusCode::OK; + }; + + Ship ship(&time,strategy, "Black Widow", 1000, 40); +} +``` + diff --git a/CreatingReliableSoftwareCpp/Presentation/template_method.md b/CreatingReliableSoftwareCpp/Presentation/template_method.md new file mode 100644 index 0000000..3abf0ac --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/template_method.md @@ -0,0 +1,577 @@ +# Template method + +This design pattern similar to strategy was used by you, even if you didn't notice that. This is a very popular approach whenever you have some functionality to be handled, but a base class shouldn't contain such logic. Let's check the following example: + +```C++ +class Player { +public: + virtual ~Player() = default; + void attack() { + std::cout << "Player " << _name << " turn\n"; + const auto [damage, attackedPlayer] = doAttack(); + std::cout << "Deal: " << damage << " to player: " << attackedPlayer->name() << "\n"; + } + +protected: + std::pair doAttack(); +}; +``` + + +```C++ +class Enemy : public Player { +protected: + std::pair doAttack() { + const Player* player = choosePlayer(); + const int damage = calculateDamage(player); + + return {damage, player}; + } +}; +``` + + +___ + +## UML + +Template method is a pattern, that allow you to create a sketch of algorithm, but details will be implemented by derived classes. Each class will decide how to acct in a various scenario, for instance enemy will use AI to choice an opponent to fight, but real user need to take an input from keyboard or mouse. + +Template method UML + +___ + +## GTEST + +A perfect example of template method is a GTEST. Whenever you inherit from `testing::Test` class you actually get possibility to overload two virtual functions: + +* void SetUp() +* void TearDown() + +A base class has two virtual function that are empty. So if you don't provide any implementation in the derived class, it will do nothing. This class may look like: + + +```C++ +class Test { +public: + Test() { + // do stuff related with test + SetUp(); + } + + ~Test() { + // cleanup stuff releated with test + TearDown(); + } + +protected: + virtual void SetUp() {} + virtual void TearDown() {} +}; +``` + + + +___ + +## Pirates once more + +To show you how useful this pattern is, let's implement a new functionality in our project. We need to implement a real battle! Because we played recently a baldurs gate 3 we decided to implement is as a turn based. We create the following rules to battle: + +* Each player (enemy or real user) roll a die who will start first +* After a roll we add initiative and based on the final result we decide who will begin +* Player can do 3 actions. It could choose any of these: + * Sail + * Attack + * Protect + * Boarding + * try to escape +* For instance, player can sail twice and then make boarding or attack 3 times with canons +* After one player finish, next player perform his turn +* Battle ends when all ships from enemy side will be sunk or enemy run away + + + +___ + +## Battle + +We create a simple class for battle. We can have few enemies and only one real player. The battle will ends when user or enemy espacded or one will be defeated. + +```C++ +class Battle { +public: + void battle() { + const std::vector& sorted = calculateOrderOfPlayers(_battleField->players()); + while (true) { + for (const auto* player : sorted) { + for (size_t i = 0 ; i < 3 ; ++i) { + const auto status = player->makeAction(*_battleField); + if (status == Action::Status::Escaped || + status == Action::Status::EnemyDefeated || + status == Action::Status::PlayerDefeated) { + return; + } + } + } + } + } + +private: + std::unique_ptr _battleField; +} +``` + + +___ + +## Player + +A player should have one function `makeAction` that should return `Status`. In this method, we will create a draft of algorithm. User need to choose which ship will make an action (Player may have few ships), then choose action and if action is equal `board` or `attack` he needs to choose enemy ship. + +```C++ +class Player { +public: + virtual ~Player() = default; + Action::Status makeAction(const BattleField& battleField) { + Ship* ship = chooseShip(battleField); + std::unique_ptr action = chooseAction(battleField); + if (action->type() == Action::Type::Board || action->type() == Action::Type::Attack) { + Ship* enemyShip = choosEnemyShip(battleField); + return (*action)(ship, enemyShip); + } + + return (*action)(ship, nullptr); + } + +protected: + virtual Ship* chooseShip(const BattleField& battleField) const = 0; + virtual Ship* chooseEnemyShip(const BattleField& battleField) const = 0; + virtual std::unique_ptr chooseAction(const BattleField& battleField) const = 0; +}; +``` + + +___ + +## Enemy + +Enemy class will be directed by an AI, so we implement some logic and based on it, it will decide what to do. + +```C++ +class Enemy : public Player { +public: +protected: + Ship* chooseShip(const BattleField& battleField) const override { + // Check the battlefield and choos the best ship + } + + Ship* chooseEnemyShip(const BattleField& battleField) const override { + // Check the battlefield and choose the weakened player ship which is closest + } + + std::unique_ptr chooseAction(const BattleField& battleField) const override { + // If don't have chance to whin escape + // If don't have ship in range sail + // If want to bard but it is too far sail + } +}; +``` + + +___ + +## User + +For user class we need to take an input from real person. In the future, we should also add possibility to revert user action and allow choosing once again. + +```C++ +class User : public Player { +public: +protected: + Ship* chooseShip(const BattleField& battleField) const override { + return GetUserInput(battleField, Type::ChoosePlayerShip); + } + + Ship* chooseEnemyShip(const BattleField& battleField) const override { + return GetUserInput(battleField, Type::ChooseEnemyShip); + } + + std::unique_ptr chooseAction(const BattleField& battleField) const override { + return GetUserInput(battleField, Type::ChooseAction); + } +}; +``` + + + +___ + +## A Few desing patterns + +Can you named all desing patterns I used in this example? + +* The Player class is a Factory method (that was obvious) +* The BattleField class is a context pattern. We wrap all necessary information about battle here +* The Action class is a command pattern. We wrap the logic in command, and also allow reverting changes. + +___ + +## Enemy AI + +We need to develop the `Enemy` AI. First, we focus on implementation of the algorithm that will choose the enemy ship. In such case we want to measure few parameters and based on the score choose the best (this is something like min-max algorithm). + +```C++ +Ship* chooseEnemyShip(const BattleField& battleField) const override final { + // Sort form highest value to the lowest + std::map> scores; + + for (const Ship* ship : battleField->getPlayerShip()) { + int score = 0; + score += calculateDistance(ship); + score += calculateThreat(ship); + score += calculatePossibleDamage(ship); + scores[score] = ship; + } + + return scores.begin()->second; +} +``` + + +We need to implement 3 methods: `calculateDistance`, `calculateThreat` and `calculatePossibleDamage`. We may choose how enemy will measure such things, because we can have a few types of enemy. + + +___ + +## Elite and Boss + +If we create a new hierarchy of derived class, we need to add implementation on how these classes should measure scores. It may depend on various things, like type of ammunition, protection, resistance, speed etc... + +```C++ +class Enemy : public Player { +protected: + // Don't allow to override this methods + Ship* chooseShip(const BattleField& battleField) const override final; + Ship* chooseEnemyShip(const BattleField& battleField) const override final; + std::unique_ptr chooseAction(const BattleField& battleField) const override final; + + // Define a new template methods + virtual int calculateDistance(Ship* ship) const = 0; + virtual int calculateThreat(Ship* ship) const = 0; + virtual int calculatePossibleDamage(Ship* ship) const = 0; +}; +``` + +```C++ +class FlameThrowerShip : public Enemy { +protected: + int calculateDistance(Ship* ship) override; + int calculateThreat(Ship* ship) override; + int calculatePossibleDamage(Ship* ship) override; +}; +``` + + +___ + +```C++ +int FlameThrowerShip::calculateDistance(Ship* ship) override { + // Because flame thrower has short range, we need to be very close to give a high score + const int distance = getDistance(_ship, ship); + if (distance < FLAME_THROWER_RANGE) { + return 10; + // We can reach in one turn + } else if (distance - _ship.speed() < FLAME_THROWER_RANGE) { + return 5; + } + + return 1; +} +``` + +```C++ +int FlameThrowerShip::calculateThreat(Ship* ship) override { + // The biggest threat for flameThroweShip is for instance a ship that deal explosive damage + // because may set on fire the oil + if (ship->hasExplosiveAmmo()) { + return 10; + } else if (ship->hasFlameThrower()) { + return 5; + } + + return 2; +} +``` + + +___ + +As we can see we can have few layers of template methods, and finally we achieve a final class (we should think about mark it as final also) which has implemented all logic. By using template method pattern we follow SOLID rules, because we have a single responsibility, our code is open to extension and don't demand modification of existing code (of course only if we add new types of enemies not modifying algorithm). And also we have dependency inversion, because low level modules depends on high level module's abstraction (base class defied interface → template methods that should be implemented) + +```C++ +int FlameThrowerShip::calculatePossibleDamage(Ship* ship) override { + // Check the type of shipe. for instance it may has some protection for fire (some black magic) + if (ship->hasProtectionToFire()) { + return 1; + } else if (ship->armor() > 50) { + return 5; + } + + return 10; +} +``` + + + +___ + +Lets summary everything on UML diagram + +Player UML +___ + +## Pros and cons + +Template method is a powerful design pattern, because we can hide from the end user that we use polymorphism. In case of usage of class `Player` we have one public method `makeAction` which is not virtual. The whole magic is hidden in protected methods. What's more template method is very flexible, for class `Player` we decided to mark class as `final` because we implement everything. But class `enemy` which is directed by `AI` create another set of `proceted virtual` function and demands form derived class to implement them. We can easily extend this code by adding new types of enemies. Unfortunately, we can't do this with new virtual functions. Whenever we add a new template method we need to implement it in every derived class (or leave it empty as in GTEST, but this is rarely scenario). + +**To summarize: Use this pattern for adding new implementations rather than new functions.** + + +___ + +## Exericse 1 + +* Go into directory Player and implement a base class Player, this class should have 3 public virtual members: + * virtual int attack(Ship& playerShip) = 0; + * virtual Ship& getShip() = 0; + * virtual const Ship& getShip() const = 0; +* Add to Player class a non-virtual function: Action::Status makeAction(const BattleField& battleField);. +* Add to Player class 2 virtual protected function (a template method): + * virtual Ship* chooseEnemyShip(const BattleField& battleField) const = 0; + * virtual std::unique_ptr chooseAction(const BattleField& battleField) const = 0; +* Implement some logic in method makeAction based on 2 template method: + * To simplify, Player can only attack or defense + * Use class Command from directory Battle + +___ + +## Exercise 2 + +* Implement class RealUser which will inherit from class Player. Implement both template methods: + * Don't make it too complex, just ask user about action and type of ammunition, then you can randomly choose a damage or if missed. + * To increase defense, you can use method setArmor from Ship class. +* Rewrite class Enemy to inherit from Player add also implementation for both template methods +* Uncomment code in main, check if you can perform a real battle! + +___ + +## A little abour command pattern + +Similar to `Strategy` or `Template method` we also have a `Command` pattern. This pattern is quite small, so I decided to talk about it in this section. The general idea is to provide functionality that we can do and optionally an option to undo this action. + +Template method UML + +___ + +## Battle Actions + +A perfect example of `command pattern` is a battle between two ships. We mentioned earlier that we want to give a few different actions to choose during the combat: + +* Sail +* Attack +* Protect +* Boarding +* try to escape + +Each player can do three actions per turn. Because a player may decide that he don't like his choose, we may add the possibility to undo an action in a single turn. + +___ + +## Action + +Let's create an interface for a `Action`. We should have two method `run` for running a command and `undo` for reverting. We may also have an additional info like `Status` in return statement. Keep in mind if this status may change it may be not a good idea to have it inside `Action` class because whenever we will add new field it needs to recompile all classes that include a `Action` class. A second disadvantage is that sometimes, we may not have access to this interface, so we can't add a new `Status`. I decided to put `Status` inside class `Action` because I know it will not be changed. If `Status` may change, I will put it in separate file which will be visible for all programmers or move the logic about if player `escaped` or was `defeated` outside `Action` class. + +```C++ +class Action { +public: + // This should not change so we can leave it here + enum class Status { + Escaped, + Defeated, + Nothing, + }; + + virtual Status run(Player* player, std::unique_ptr& enemyShip) = 0; + virtual void undo(Player& player, std::unique_ptr& enemyShip) = 0; +}; +``` + + +___ + +To implement class `Attack` we need to store one variable: the amount of damage. This is needed to revert a `takeDamage` operation. If we also simulate that part of cargo will be destroyed, we also need to keep info how many cargoes we subtract or create a `snapshot` of cargo and then apply this snapshot during revert. It depends on how big such snapshot will be and how hard it will be to undo the operation of destroying part of cargo. + +```C++ +class Attack : public Action { +public: + Status run(Player* player, std::unique_ptr& enemyShip) override { + _damage = calculateDamage(player); + std::cout << "Player Ship: " << player->getShip().name() << " attack: " << enemyShip->name() << '\n'; + if (_damage) { + enemyShip->takeDamage(_damage); + std::cout << "Dealed damage: " << _damage << '\n'; + return enemyShip->durability() <= 0 ? Status::Defeated : Status::Nothing; + } + + std::cout << "Missed\n"; + return Status::Nothing; + } + + void undo(Player* player, std::unique_ptr& enemyShip) override { + enemyShip->repair(_damage); + } + +private: + int _damage = 0; +}; +``` + + +___ + +## How to revert + +If we want to allow a user to revert operations, we need to store them. Because we decided to revert action only in a single turn, we need to keep max 3 actions. If the user ends the turn, we will clear it, so it will not be possible to undo action from the previous turn. + +```C++ +while (true) { + for (auto* player : players) { + std::vector> actions; + while (!endOfTurn()) { + const auto userInput = getuserInput(); + if (userInput.revertAction() && !actions.empty()) { + actions.back()->undo(); + continue; + } else if (userInput.revertAction() && actions.empty()) { + std::cout << "Can't undo more actions\n"; + continue; + } + + actions.push_back(player->makeAction(battefield, userInput)); + if (actions.back().status() == Action::Status::Escaped || + actions.back().status() == Action::Status::Defeated) { + std::cout << "The battle ends!\n"; + return; + } + } + } +} +``` + + +___ + +As you can see, we can easily implement a battle and give a user possibility to revert actions. This pattern also gives us an easy mechanism to add a new action in the future if we will want to extend a combat possibility. + +```C++ +class Boarding : public Action { +public: + Status run(Player* player, std::unique_ptr& enemyShip) override { + // Based on number and type of crew calculate a boarding result + const bool success = doBoarding(player->getShip(), enemyShip); + std::cout << "Player Ship: " << player->getShip().name() << " boarding: " << enemyShip->name() << '\n'; + if (success) { + // Hold a pointer to newaly added ship in case of revert + _shipPtr = player->addShip(std::move(enemyShip)); + std::cout << "Ship: " << _shipPtr->name() << "conquered\n"; + return Status::Defeated; + } + + // We lost some crew, but we escaped, so player still not loose + std::cout << "Boarding failed!\n"; + return Status::Nothing; + } + + void undo(Player* player, std::unique_ptr& enemyShip) override { + if (_shipPtr) { + enemyShip = player->moveShip(_shipPtr); + } + } + +private: + Ship* _shipPtr{nullptr}; +}; +``` + + +___ + +## Modern approach + +We should prefer `by-value` semantic. For `template method` pattern we use `virtual protected methods`, so it will be a tricky to rewrite it by using `by-value` semantic, but for `command` pattern this will be easy. We can check the `std::transform` method, specifically `UnaryOperator`. This is nothing but `command` pattern in modern approach. + +```C++ +template +OutputIt transform(InputIt first1, InputIt last1, + OutputIt d_first, UnaryOp unary_op) +{ + while (first1 != last1) + *d_first++ = unary_op(*first1++); + + return d_first; +} +``` + + +___ + +Whenever we want to do some action, but we don't need to undo it, we can choose faster and better approach with `std::function` and in c++23 `std::move_only_function`. This approach don't require virtual function and creating a base class for command, and we don't need to keep pointer or reference to base class. We will keep command by value, so it will be safer and probably even faster. + +```C++ +Status run(Player* player, std::unique_ptr& enemyShip) { + const auto damage = calculateDamage(player); + std::cout << "Player Ship: " << player->getShip().name() << " attack: " << enemyShip->name() << '\n'; + if (damage) { + enemyShip->takeDamage(damage); + std::cout << "Dealed damage: " << damage << '\n'; + return enemyShip->durability() <= 0 ? Status::Defeated : Status::Nothing; + } + + std::cout << "Missed\n"; + return Status::Nothing; +} +``` + + +```C++ +while (true) { + for (auto* player : players) { + std::vector& enemyShip)>> actions; + while (!endOfTurn()) { + const auto userInput = getuserInput(); + if (userInput.revertAction() && !actions.empty()) { + actions.back().undo(); + continue; + } else if (userInput.revertAction() && actions.empty()) { + continue; + } + + actions.push_back(player->makeAction(battefield, userInput)); + if (actions.back().status() == Action::Status::Escaped || actions.back().status() == Action::Status::Defeated) { + return; + } + } + } +} +``` + + +___ + +## Exericse 3 + +* Go into directory Battle and implement class Escape which will inherit from class Action. + * Roll a die (1 to 20), if value is bigger than 12 a player successfully escaped. +* Noticed that we shouldn't modify existing code, but we need to do this in two place, where? +* How would you refactor the code? diff --git a/CreatingReliableSoftwareCpp/Presentation/testing_gmock.md b/CreatingReliableSoftwareCpp/Presentation/testing_gmock.md new file mode 100644 index 0000000..cdd500a --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/testing_gmock.md @@ -0,0 +1,681 @@ +## GMOCK + +* Avoid depricated MOCK_METHDn and MOCK_CONST_METHODn +* Use MOCK_METHOD() +* Use Times when want to expect how many times function was call (by default it expect once) +* Use AtLeast To expect n or more calls +* Use WillOnce and WillRepeatedly to perform some actions +* Use SaveArg to save argument provided to mock function +* Use InSequence to perform sequenced actions +* You can mock non-virtual function +* Use StrictMock when you need to be sure about every call of this mock +* Use NiceMock when you don't care about function called for this mock +* Use ON_CALL and WillByDefault to perform some default action, when function will be called +* Use DoAll to perform more then one action +* Use Invoke to invoke funtion/lambda + + +___ + +## MOCK_METHOD + +MOCK_METHOD(return_type, name_of_function, arguments, parameters) + + +```C++ +class MockTurtle : public Turtle { + public: + ... + MOCK_METHOD(void, PenUp, (), (override)); + MOCK_METHOD(void, PenDown, (), (override)); + MOCK_METHOD(void, Forward, (int distance), (override)); + MOCK_METHOD(void, Turn, (int degrees), (override)); + MOCK_METHOD(void, GoTo, (int x, int y), (override)); + MOCK_METHOD(int, GetX, (), (const, override)); + MOCK_METHOD(int, GetY, (), (const, override)); +}; +``` + + +* const - Makes the mocked method a const method. Required if overriding a const method. +* override - Marks the method with override. Recommended if overriding a virtual method. +* noexcept - Marks the method with noexcept. Required if overriding a noexcept method. +* Calltype(...) - Sets the call type for the method (e.g. to STDMETHODCALLTYPE), useful in Windows. +* ref(...) - Marks the method with the reference qualification specified. Required if overriding a method that has reference qualifications. Eg ref(&) or ref(&&). + +___ + +## Test class + +Let's use once agin `Foo` and `Bar` class + +```C++ +class Bar { +public: + virtual ~Bar() = default; + + virtual bool doOtherStuff(const std::string& str, int*, const std::vector& vec) const { + // do some stuff + return false; + } +}; + +class MockBar : public Bar { +public: + ~MockBar() override = default; + MOCK_METHOD(bool, doOtherStuff, (const std::string&, int*, const std::vector&), (const override)); +}; + +class Foo { +public: + Foo(std::unique_ptr bar) + : val_(std::make_unique(42)), + bar_(std::move(bar)) {} + + bool doSth(const std::string& str) { + return bar_->doOtherStuff(str, val_.get(), {1, 2, 3, 4}); + } + +private: + std::unique_ptr val_; + std::unique_ptr bar_; +}; + +``` + +___ + +## Times + +```C++ +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + EXPECT_CALL(*mockBarPtr, doOtherStuff).Times(2); + + foo.doSth("Sth1"); + foo.doSth("Sth2"); +} +``` + + + +___ + +## AtLeast + +```C++ +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + EXPECT_CALL(*mockBarPtr, doOtherStuff).Times(testing::AtLeast(2)); + + foo.doSth("Sth1"); + foo.doSth("Sth2"); +} +``` + + +___ + +## WillOnce and WillRepeatedly + +```C++ +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + // Dont do that. Next exceptaion will override first one! + // EXPECT_CALL(*mockBarPtr, doOtherStuff).WillOnce(Return(false)); + // EXPECT_CALL(*mockBarPtr, doOtherStuff).WillOnce(Return(true)); + + // Correct one! + EXPECT_CALL(*mockBarPtr, doOtherStuff) + .WillOnce(Return(false)) + .WillOnce(Return(true)); + + EXPECT_FALSE(foo.doSth("Sth1")); + EXPECT_TRUE(foo.doSth("Sth2")); +} +``` + + +```C++ +TEST(ExampleTest, ShouldTest) { + //... + EXPECT_CALL(*mockBarPtr, doOtherStuff) + .WillOnce(Return(false)) + .WillOnce(Return(true)) + .WillRepeatedly(Return(false)); + + EXPECT_FALSE(foo.doSth("Sth1")); + EXPECT_TRUE(foo.doSth("Sth2")); + EXPECT_FALSE(foo.doSth("Sth3")); + EXPECT_FALSE(foo.doSth("Sth4")); +} +``` + + + +___ + + +## Save arguments provided to functions (1) + +We want to capture parameters provided to bar function. + +```C++ +class Bar { +public: + virtual ~Bar() = default; + + virtual bool doOtherStuff(const std::string& str, int val, const std::vector& vec) { + // do some stuff + return false; + } +}; + +class MockBar : public Bar { +public: + ~MockBar() override = default; + MOCK_METHOD(bool, doOtherStuff, (const std::string&, int, const std::vector&), (override)); +}; + +class Foo { +public: + Foo(std::unique_ptr bar) + : bar_(std::move(bar)) {} + + bool doSth(const std::string& str) { + return bar_->doOtherStuff(str, 42, {1, 2, 3, 4}); + } + +private: + std::unique_ptr bar_; +}; +``` + + +___ + +## Save arguments provided to functions (2) + +```C++ +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + int val; + std::vector vec; + // Also return true, instead of false like in original function + EXPECT_CALL(*mockBarPtr, doOtherStuff). + WillOnce(DoAll(SaveArg<1>(&val), SaveArg<2>(&vec), Return(true))); + + EXPECT_TRUE(foo.doSth("Sth")); + EXPECT_EQ(val, 42); + const auto expected = std::vector{1, 2, 3, 4}; + EXPECT_EQ(vec, expected); +} +``` + + +``` +[----------] 1 test from ExampleTest +[ RUN ] ExampleTest.ShouldTest +[ OK ] ExampleTest.ShouldTest (0 ms) +[----------] 1 test from ExampleTest (0 ms total) +``` + + +___ + +## Save pointer provided to function + +```C++ +class Bar { +public: + virtual ~Bar() = default; + + virtual bool doOtherStuff(const std::string& str, int* val, const std::vector& vec) { + // do some stuff + return false; + } +}; + +``` + + +```C++ +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + int* val; + std::vector vec; + // Capture by SaveArgPointee + EXPECT_CALL(*mockBarPtr, doOtherStuff). + WillOnce(DoAll(SaveArgPointee<1>(val), SaveArg<2>(&vec), Return(true))); + + EXPECT_TRUE(foo.doSth("Sth")); + EXPECT_EQ(*val, 42); + const auto expected = std::vector{1, 2, 3, 4}; + EXPECT_EQ(vec, expected); +} +``` + + +___ + +## Capture non-copyable object + +* There is a problem to capture non-copyable objects because we can't copy them! +* We need to make an ugly hack to capture this object -> move this object to our variable. +* This will be problematic when this object needs to be used in a function, but it will work when we used in on mock function because the argument will not be used later. + +```C++ +// Bar +bool doSth(const std::string& str) { + return bar_->doOtherStuff(str, std::make_unique(42), {1, 2, 3, 4}); +} + +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + std::unique_ptr val; + EXPECT_CALL(*mockBarPtr, doOtherStuff).WillOnce(DoAll(MoveObject<1>(&val), Return(true))); + + EXPECT_TRUE(foo.doSth("Sth")); + EXPECT_EQ(*val, 42); +} +``` + + +* There is no such function in gtest, so we need to implement somehow MoveObject + +___ + +## Move object + +```C++ +ACTION_TEMPLATE(MoveObject, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_1_VALUE_PARAMS(pointer)) { + using PtrType = std::remove_cv_t(args))>>; + // This unique_ptr will be deleted after function end + // so we need to capture it + *pointer = std::move(const_cast(std::get(args))); +} +``` + + +When we only need a raw pointer from `unique_ptr` + + +```C++ +ACTION_TEMPLATE(ExtractPtr, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_1_VALUE_PARAMS(pointer)) { + *pointer = std::get(args).get(); +} +``` + +But we will lost it, because `unique_ptr` will be deleted after exit form mock function! + + + + +This is a very old way, the better one is to just lambda instead, I will show this later + +___ + + +## InSequence (1) + +```C++ +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + testing::Sequence seq; + // Four expectations in sequence. There is no override like before + for (int i = 0; i < 4; ++i) { + EXPECT_CALL(*mockBarPtr, doOtherStuff) + .InSequence(seq) + .WillOnce(Return(i % 2)); + } + + EXPECT_FALSE(foo.doSth("Sth1")); + EXPECT_TRUE(foo.doSth("Sth2")); + EXPECT_FALSE(foo.doSth("Sth3")); + EXPECT_TRUE(foo.doSth("Sth4")); +} +``` + + + +___ + +## InSequence (2) + +This has the same behaviour like previous example + + +```C++ +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + { + testing::InSequence seq; + // Four expectations in sequence. There is no override like before + for (int i = 0; i < 4; ++i) { + EXPECT_CALL(*mockBarPtr, doOtherStuff).WillOnce(Return(i % 2)); + } + } + + EXPECT_FALSE(foo.doSth("Sth1")); + EXPECT_TRUE(foo.doSth("Sth2")); + EXPECT_FALSE(foo.doSth("Sth3")); + EXPECT_TRUE(foo.doSth("Sth4")); +} +``` + + +___ + +## InSequence - branch out + +```C++ +testing::Sequence s1, s2; + +EXPECT_CALL(foo, Method1()) + .InSequence(s1, s2); +EXPECT_CALL(bar, Method2()) + .InSequence(s1); +EXPECT_CALL(bar, Method3()) + .InSequence(s2); +EXPECT_CALL(foo, Method4()) + .InSequence(s2); +``` + + +```C++ + +---> Method2 (seq1) +(seq1 seq2) | + Method1----| + | + +---> Method3 ---> Method4 (seq2) +``` + + +___ + +## mock non-virtual function (1) + +We have the following class + + +```C++ +struct Packet {}; + +class ConcretePacketStream { +public: + void AppendPacket(Packet* new_packet) {} + const Packet* GetPacket(size_t packet_number) const {} + size_t NumberOfPackets() const {} +}; +``` + + + +___ + +## mock non-virtual function (2) + +We can create mock and instead of dynamic polymorphism use static polymorphism (templates) + + +```C++ +// A mock packet stream class. It inherits from no other, but defines +// GetPacket() and NumberOfPackets(). No need to add all functions like: AppendPacket +class MockPacketStream { +public: + // Do not add override! + MOCK_METHOD(const Packet*, GetPacket, (size_t packet_number), (const)); + MOCK_METHOD(size_t, NumberOfPackets, (), (const)); +}; + +// Now we can use static polymorphism to insert Mock class in a test, +// and real class in production code +template +class PacketReader { +public: + const Packet* ReadPackets(PacketStream* stream, size_t packet_num) { + return stream->GetPacket(packet_num); + } +}; +``` + + + +___ + +## mock non-virtual function (3) + +Now in test we can use mock class + + +```C++ +TEST(TestNonVirtualMethod, ShouldTest) { + MockPacketStream mock_stream; + EXPECT_CALL(mock_stream, GetPacket).WillOnce(Return(nullptr)); + + PacketReader reader; + reader.ReadPackets(&mock_stream, 12); +} +``` + + +And in production code the real one + + +```C++ +ConcretePacketStream stream; +PacketReader reader; + +auto* packet = reader.ReadPackets(&stream, 12); +``` + + + + +___ + +## StrictMock + +The usage of `StrictMock` is similar to normal mock, except that it makes all uninteresting calls failures: + +```C++ +class MockFoo : public Foo { + //... + MOCK_METHOD(void, Fun1, (), (override)); + MOCK_METHOD(void, Fun2, (), (override)); +}; + +TEST(SimpleTest, TestSth) { + StrictMock mock_foo; + // When Fun2 will be also called it cause test failed + EXPECT_CALL(mock_foo, Fun1()); +} +``` + + + +___ + + +## NiceMock + +* The usage of `StrictMock` is similar to normal mock, except that it reject uninteresting calls (we will not see them while run test) +* NiceMock and StrictMock only affects uninteresting calls (calls of methods with no expectations); they do not affect unexpected calls (calls of methods with expectations, but they don’t match) + +```C++ +class MockFoo : public Foo { + //... + MOCK_METHOD(void, Fun1, (), (override)); + MOCK_METHOD(void, Fun2, (), (override)); +}; + +TEST(SimpleTest, TestSth) { + NiceMock mock_foo; + // When Fun2 will be also called it will be ignored + EXPECT_CALL(mock_foo, Fun1()); +} +``` + + + +___ + +## ON_CALL and WillByDefault + +We can do whatever we want when some mock method will be called. We can even save all types of arguments, or move objects to test them (call later). + + +When a function takes for instance non-copyable callback, and we need to capture it to continue testing, we can move it inside lambda! This is much better than the tricky template shown before. + + +```C++ +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + // Nice way to capture all types of argument + int* ptr; + ON_CALL(*mockBarPtr, doOtherStuff) + .WillByDefault([&ptr](const std::string&, int* new_ptr, const std::vector&) { + ptr = new_ptr; + return true; + }); + + EXPECT_CALL(*mockBarPtr, doOtherStuff); + EXPECT_TRUE(foo.doSth("Sth1")); + EXPECT_EQ(*ptr, 42); +} +``` + + + +___ + +## DoAll + +If we need to combine a few actions, we can do this inside `doAll(...)` + + +```C++ +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + + std::string str; + int* ptr; + + EXPECT_CALL(*mockBarPtr, doOtherStuff) + .WillOnce(DoAll( + SaveArg<0>(&str), + SetArgPointee<1>(80), // Replace pointer value + SaveArgPointee<1>(ptr), // Capture value of arg1 + Return(true))); + + EXPECT_TRUE(foo.doSth("Sth1")); + EXPECT_EQ(str, "Sth1"); + EXPECT_EQ(*ptr, 80); +} +``` + + + +___ + +## Invoke (1) + +Let's change a little `MockBar` + + +```C++ +class MockBar : public Bar { +public: + ~MockBar() override = default; + MOCK_METHOD(bool, doOtherStuff, (const std::string&, int*, std::function), (const override)); +}; +``` + +Now we want to run callback. We can do this without capture it! + + +```C++ +EXPECT_CALL(*mockBarPtr, doOtherStuff) + .WillOnce(DoAll( + SaveArg<0>(&str), + SetArgPointee<1>(80), // Replace pointer value + SaveArgPointee<1>(ptr), // Capture value of arg1 + InvokeArgument<2>(500), // Invoke callback + Return(true))); +``` + + + +___ + +## Invoke (2) + +```C++ +class Helper { +public: + void validateArguments(const std::string& str, int* ptr, std::function callback) { + ASSERT_EQ(str.size(), 4); + EXPECT_EQ(str, "Sth1"); + ASSERT_TRUE(ptr); + EXPECT_EQ(*ptr, 42); + ASSERT_TRUE(callback); + callback(50); // We can invoke callback here + } +}; + +TEST(ExampleTest, ShouldTest) { + auto mockBar = std::make_unique(); + auto* mockBarPtr = mockBar.get(); + Foo foo(std::move(mockBar)); + Helper helper; + + EXPECT_CALL(*mockBarPtr, doOtherStuff) + .WillOnce(DoAll( + Invoke(&helper, &Helper::validateArguments), + Return(true))); + + EXPECT_TRUE(foo.doSth("Sth1")); +} +``` + + +___ + +## Exercise 2 + +Open project **SHM** and write test for class `Store.cpp` which will test it's interface. You need to mock `Cargo` class and check if you get correct result based on what you mock. Write mock in `Presentation/exercises/SHM/tests/CargoMock.h` for `Cargo` class. + +Go to `Presentation/exercises/SHM/build/test` and run test using command `./SHM_Tests`. \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/Presentation/testing_gtest.md b/CreatingReliableSoftwareCpp/Presentation/testing_gtest.md new file mode 100644 index 0000000..814b464 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/testing_gtest.md @@ -0,0 +1,473 @@ +## GTEST + +* TEST(...) Create single test +* TEST_F(...) Use fixtures for testing +* TEST_P(...) Use package of parameters for all tests +* EXPECT_* Check condition +* ASSERT_* Check condition and stop test if fails. +* EXPECT_PRED* Allow to create own predicate, and other format of display errors +* testing::FloatLE and testing::DoubleLE can be use for EXPECT_PRED_FORMAT* for floating-point comparison +* GTEST_SKIP() can be use for skipping the test +* EXPECT_EXIT can test signall which end program, like: SIGKILL +* EXPECT_THROW will catch and check exceptions + +___ + +## TEST + +To create a simple test we can use `TEST` macro + +```C++ +class Calculator { +public: + int add(int lsh, int rhs) { return lhs + rhs; } +}; + +TEST(CalculatorTest, ShouldAddTwoValues) { + Calculator calc; + EXPECT_EQ(calc.add(10, 20), 10 + 20); +} +``` + + +___ + +## TEST_F + +If we need to set up some structures before creating a test, we shouldn't do this every test, but instead create a test fixture that sets everything up during construction. It also provides useful methods which we can use in every test. This fixture is created first, then a test starts. + +```C++ +class DownloaderTest : public testing::Test { +public: + DownloaderTest() { + _connection = std::make_unique(); + _connection->set_certificates(_certificateMock); + _downloader = std::make_unqiue(_connection.get()); + } + + CertificateMock _certificateMock; + std::unqiue_ptr _connection; + std::unique_ptr _downloader; +}; + +TEST_F(DownloaderTest, shouldDownloadImage) { + EXPECT_CALL(_certificateMock, validate).WillOnce(Return(true)); + EXPECT_TRUE(_downloader.downloadImage("exampleImg")); +} +``` + +___ + +## TEST_P (1) + +Whenever we need to run the same test but with a different set of parameters we should use `TEST_P` + +```C++ +class Firewall { +public: + virtual ~Firewall() = default; + + virtual bool block(const std::string& ipAddress) = 0; +}; + +class WhiteListFirewall : public Firewall { +public: + void addToWhitelist(const std::string& ipAddress) { + whiteList_.push_back(ipAddress); + } + + bool block(const std::string& ipAddress) override { + return std::find(cbegin(whiteList_), cend(whiteList_), ipAddress) == std::cend(whiteList_); + } + +private: + std::vector whiteList_; +}; + +``` + + +___ + +## TEST_P (2) + +```C++ +class TestFirewall : public testing::TestWithParam> { +}; + +TEST_P(TestFirewall, ShouldFilterAdresses) { + auto firewall = std::make_unique(); + firewall->addToWhitelist("192.201.1.12"); + firewall->addToWhitelist("192.122.1.12"); + + const auto& [address, isBlock] = GetParam(); + EXPECT_EQ(firewall->block(address), isBlock); +} + +INSTANTIATE_TEST_SUITE_P(TestFirewallParameters, + TestFirewall, + testing::Values( + std::pair{"192.178.1.12", true}, + std::pair{"192.144.1.12", true}, + std::pair{"192.188.1.12", true}, + std::pair{"192.201.1.12", false}, + std::pair{"192.122.1.12", false})); +``` + + +___ + +## TEST_P (3) + +``` +[----------] 5 tests from TestFirewallParameters/TestFirewall +[ RUN ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/0 +[ OK ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/0 (0 ms) +[ RUN ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/1 +[ OK ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/1 (0 ms) +[ RUN ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/2 +[ OK ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/2 (0 ms) +[ RUN ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/3 +[ OK ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/3 (0 ms) +[ RUN ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/4 +[ OK ] TestFirewallParameters/TestFirewall.ShouldFilterAdresses/4 (0 ms) +[----------] 5 tests from TestFirewallParameters/TestFirewall (0 ms total) +``` + + +___ + +## TEST_P - inherit from other test + +```C++ +class BlackListFirewall : public Firewall { +public: + void addToBlacklist(const std::string& ipAddress) { + blackList_.push_back(ipAddress); + } + + bool block(const std::string& ipAddress) override { + return std::find(cbegin(blackList_), cend(blackList_), ipAddress) != std::cend(blackList_); + } + +private: + std::vector blackList_; +}; + +class BaseTestBlackListFirewall : public testing::Test { +public: + void SetUp() override { + firewall_ = std::make_unique(); + + firewall_->addToBlacklist("192.201.1.12"); + firewall_->addToBlacklist("192.122.1.12"); + firewall_->addToBlacklist("192.178.1.12"); + firewall_->addToBlacklist("192.144.1.12"); + firewall_->addToBlacklist("192.188.1.12"); + } + + BlackListFirewall* firewall() const { return firewall_.get(); } + +private: + std::unique_ptr firewall_; +}; +``` + + +___ + +## testing::WithParamInterface + +```C++ +class TestBlackListFirewall : public BaseTestBlackListFirewall, + public testing::WithParamInterface { +}; + +TEST_P(TestBlackListFirewall, ShouldBlock) { + EXPECT_TRUE(firewall()->block(GetParam())); +} + +INSTANTIATE_TEST_SUITE_P(TestBlackListFirewallPackage, + TestBlackListFirewall, + testing::Values( + "192.178.1.12", + "192.144.1.12", + "192.188.1.12", + "192.201.1.12", + "192.122.1.12")); +``` + + +``` +[----------] 5 tests from TestBlackListFirewallPackage/TestBlackListFirewall +[ RUN ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/0 +[ OK ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/0 (0 ms) +[ RUN ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/1 +[ OK ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/1 (0 ms) +[ RUN ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/2 +[ OK ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/2 (0 ms) +[ RUN ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/3 +[ OK ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/3 (0 ms) +[ RUN ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/4 +[ OK ] TestBlackListFirewallPackage/TestBlackListFirewall.ShouldBlock/4 (0 ms) +[----------] 5 tests from TestBlackListFirewallPackage/TestBlackListFirewall (0 ms total) +``` + + +___ + + +## EXPECT_PRED* - own error message + +```C++ +testing::AssertionResult isBlocked(Firewall* firewall, const std::string& addr, bool block) { + if (firewall->block(addr) == block) { + return testing::AssertionSuccess(); + } + + return testing::AssertionFailure() << addr << (block ? " should be blocked" : " shouldn't be blocked"); +} + +TEST_F(BaseTestBlackListFirewall, ShouldFilter) { + EXPECT_TRUE(isBlocked(firewall(), "192.188.1.12", true)); + EXPECT_TRUE(isBlocked(firewall(), "192.188.1.12", false)); +} +``` + + +``` +[----------] 1 test from BaseTestBlackListFirewall +[ RUN ] BaseTestBlackListFirewall.ShouldFilter +/home/mateusz.adamski/Documents/repoGit/advanced_cpp/examples/gtest.cpp:101: Failure +Value of: isBlocked(firewall(), "192.188.1.12", false) + Actual: false (192.188.1.12 shouldn't be blocked) +Expected: true +[ FAILED ] BaseTestBlackListFirewall.ShouldFilter (0 ms) +[----------] 1 test from BaseTestBlackListFirewall (0 ms total) +``` + + +___ + +## EXPECT_PRED* - check string + +```C++ +for (const auto& str : {"There is a nauka!", "nauka.programowania.ma@gmail.com"}) { + EXPECT_THAT(str, testing::MatchesRegex( + "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$")); + + ASSERT_THAT(str, testing::HasSubstr("nauka")); +} +``` + + +``` +[ RUN ] ExampleTest.ShouldFail +/home/mateusz.adamski/Documents/repoGit/advanced_cpp/examples/gtest.cpp:104: Failure +Value of: str +Expected: matches regular expression "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" + Actual: 0x5625cd2c080c pointing to "There is a nauka!" (of type char const*) +[ FAILED ] ExampleTest.ShouldFail (0 ms) +[----------] 1 test from ExampleTest (0 ms total) +``` + + +___ + +## EXPECT_PRED* - comparison of floating point numbers + +```C++ +std::vector> vec{ + {43.45, 43.45}, {44.34321, 45.1234}, {1.12, 1.1199999}}; + +for (const auto& [lhs, rhs] : vec) { + EXPECT_PRED_FORMAT2(testing::FloatLE, lhs, rhs); + EXPECT_PRED_FORMAT2(testing::DoubleLE, lhs, rhs); +} +``` + + +``` +[ RUN ] ExampleTest.ShouldFail +/home/mateusz.adamski/Documents/repoGit/advanced_cpp/examples/gtest.cpp:108: Failure +Expected: (lhs) <= (rhs) + Actual: 1.1200000000000001 vs 1.1199999 +[ FAILED ] ExampleTest.ShouldFail (0 ms) +[----------] 1 test from ExampleTest (0 ms total) + +[----------] Global test environment tear-down +``` + + +___ + +## GTEST_SKIP + +```C++ +TEST(ExampleTest, ShouldFail) { + GTEST_SKIP() << "Skipping test PR12345"; + + std::vector> vec{ + {43.45, 43.45}, {44.34321, 45.1234}, {1.12, 1.1199999}}; + + for (const auto& [lhs, rhs] : vec) { + EXPECT_PRED_FORMAT2(testing::FloatLE, lhs, rhs); + EXPECT_PRED_FORMAT2(testing::DoubleLE, lhs, rhs); + } +} +``` + + +``` +[ RUN ] ExampleTest.ShouldFail +/home/mateusz.adamski/Documents/repoGit/advanced_cpp/examples/gtest.cpp:102: Skipped +Skipping test PR12345 +``` + + +___ + +## Skipp all fixture + +```C++ +class BaseTestBlackListFirewall : public testing::Test { +public: + void SetUp() override { + GTEST_SKIP() << "Skipping test PR12345"; + firewall_ = std::make_unique(); + + firewall_->addToBlacklist("192.201.1.12"); + firewall_->addToBlacklist("192.122.1.12"); + firewall_->addToBlacklist("192.178.1.12"); + firewall_->addToBlacklist("192.144.1.12"); + firewall_->addToBlacklist("192.188.1.12"); + } + + BlackListFirewall* firewall() const { return firewall_.get(); } + +private: + std::unique_ptr firewall_; +}; +``` + + +``` +[----------] 3 tests from BaseTestBlackListFirewall +[ RUN ] BaseTestBlackListFirewall.ShouldFilter +/home/mateusz.adamski/Documents/repoGit/advanced_cpp/examples/gtest.cpp:76: Skipped +Skipping test PR12345 +[ SKIPPED ] BaseTestBlackListFirewall.ShouldFilter (0 ms) +[ RUN ] BaseTestBlackListFirewall.ShouldNotFilter +/home/mateusz.adamski/Documents/repoGit/advanced_cpp/examples/gtest.cpp:86: Skipped +Skipping test PR12345 +[ SKIPPED ] BaseTestBlackListFirewall.ShouldNotFilter (0 ms) +[ RUN ] BaseTestBlackListFirewall.ShouldReportError +/home/mateusz.adamski/Documents/repoGit/advanced_cpp/examples/gtest.cpp:96: Skipped +Skipping test PR12345 +[ SKIPPED ] BaseTestBlackListFirewall.ShouldReportError (0 ms) +[----------] 3 tests from BaseTestBlackListFirewall (0 ms total) +``` + + +___ + +## EXPECT_EXIT and EXPECT_THROW + +```C++ +TEST(MyDeathTest, NormalExit) { + EXPECT_EXIT(normalExit(), testing::ExitedWithCode(0), "Succes"); +} + +TEST(MyDeathTest, KillProcess) { + EXPECT_EXIT(killProcess(), testing::KilledBySignal(SIGKILL), + "Sending myself unblockable signal"); +} + +void foo(int val) { + if (val != 42) { + throw std::runtime_error("Wrong number"); + } +} + +TEST(MyDeathTest, NormalExit) { + EXPECT_THROW(foo(5), std::runtime_error); +} +``` + + +___ + +## Sharing Resources Between Tests + +```C++ +struct Foo { + std::string name_; + int value_; +}; + +class FooTest : public testing::Test { +public: + // Shared + static void SetUpTestSuite() { + if (!shared_resource_) { + shared_resource_ = std::make_unique(); + shared_resource_->name_ = "Shared Foo!\n"; + shared_resource_->value_ = 42; + } + } + + // Shared + static void TearDownTestSuite() { + shared_resource_ = nullptr; + } + + // Per-test + void SetUp() override {} + + // Per-test + void TearDown() override {} + +protected: + inline static std::unique_ptr shared_resource_; +}; + +TEST_F(FooTest, Test1) { + EXPECT_EQ(FooTest::shared_resource_->name_, "Shared Foo!\n"); + EXPECT_EQ(FooTest::shared_resource_->value_, 42); + FooTest::shared_resource_->name_ = "Foo!!!"; + FooTest::shared_resource_->value_ = 13; +} + +TEST_F(FooTest, Test2) { + EXPECT_EQ(FooTest::shared_resource_->name_, "Foo!!!"); + EXPECT_EQ(FooTest::shared_resource_->value_, 13); +} +``` + + +___ + +## Testing private code - should be avoided + +```C++ +class Foo { +private: + FRIEND_TEST(FooTest, PrivateTest); + + int doSth(int val) { return val; } +}; + +TEST(FooTest, PrivateTest) { + Foo foo; + EXPECT_EQ(foo.doSth(42), 42); +} +``` + + +___ + +## Exercise 1 + +Open project **SHM** and write test for class `Ship.cpp` which will test it's interface. Remember to test edge cases :). Test it well and fix issues. + +Go to `Presentation/exercises/SHM/build/test` and run test using command `./SHM_Tests`. diff --git a/CreatingReliableSoftwareCpp/Presentation/visitor.md b/CreatingReliableSoftwareCpp/Presentation/visitor.md new file mode 100644 index 0000000..6e393f4 --- /dev/null +++ b/CreatingReliableSoftwareCpp/Presentation/visitor.md @@ -0,0 +1,600 @@ +# Visitor + +Another popular design pattern is **Visitor**. As previously, I'm certain that You also use it at least once, but maybe you didn't know about it. Let's check the following STL algorithm: + +```C++ +class VariantVisitor +{ +public: + void operator()(int num) const { + std::cout << "int: " << num << "\n"; + } + void operator()(std::string str) const { + std::cout << "string: " << str << "\n"; + } +}; + +int main() { + std::variant variant; + variant = "Ala has a cat"; + // print: string: Ala has a cat + std::visit(VariantVisitor{}, variant); +} +``` + + + +**Seems familiar? If not, let's check another example** + +___ + +```C++ +class Shape +{ +public: + virtual ~Shape() = default; + virtual void accept( ShapeVisitor const& v ) = 0; 3 +}; + +class Circle : public Shape +{ + public: + explicit Circle( double radius ): radius_( radius ) {} + void accept( ShapeVisitor const& v ) override { v.visit( *this ); } + double radius() const { return radius_; } + private: + double radius_; +}; + +class Square : public Shape +{ +public: + explicit Square( double side ): side_( side ) {} + void accept( ShapeVisitor const& v ) override { v.visit( *this ); } + double side() const { return side_; } +private: + double side_; +}; +``` + +```C++ +class Draw : public ShapeVisitor +{ +public: + void visit( Circle const& c, /*...*/ ) const override; + void visit( Square const& s, /*...*/ ) const override; +}; + +class Translate : public ShapeVisitor +{ +public: + void visit( Circle const& c, /*...*/ ) const override; + void visit( Square const& s, /*...*/ ) const override; +}; +``` + + +___ + +## Visitor + +These two examples were two different implementations of the same design pattern which is `Visitor`. In short, the visitor is used to dispatch functions between a few types. + +Visitor UML + + +___ + +## Example + +Let's back to the pirates. In the previous example, we implemented the ammunition class and added an implementation of `fire` and `draw` methods, so what next? We need to add also `methods` that will calculate how much damage each ammunition does and what sound should be played. + +Visitor first apprach + + +___ + +## Drawback + +In the first approach, we can see that we tightly coupled the base class `Visitor` with a base class `Ammunition` and the implementation of `Visitor` with types of `Ammunition`. So we have a lot of dependencies. Unfortunately, the visitor is a nice pattern, but it is good only for extending functions, but it is closed for adding new types because when we add a new type of ammunition we also need to implement every visitor class. There is a solution for this, but it is inefficient, and can't be always used. I will talk about this solution later. For now, it should be enough to know that there is sth like `Acyclic visitor` that can solve this problem, but it is inefficient. In this solution, we have double dispatch and the compiler can't optimize such code, also we have to call 2 or 3 virtual functions which are not as fast as calling normal functions. +___ + +## Implementation + +let's start by defining an interface for both, the `Ammunition` and `Visitor` class. + +```C++ +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + virtual void accept(const AmmunitionVisitor&) = 0; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; +``` + +```C++ +class AmmunitionVisitor { +public: + virtual ~AmmunitionVisitor() = default; + virtual void visit(const RoundShot&) const = 0; + virtual void visit(const ChainShot&) const = 0; + virtual void visit(const GrapeShot&) const = 0; +}; +``` + + +___ + +Each class that is derived from `Ammunition` needs to create a definition of the `accept` method. The is needed because each class passes a pointer to `*this` which allows us to distinguish which inherited class was provided. + +```C++ +class RoundShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AmmunitionVisitor& visitor) { + visitor.visit(*this); + } +}; + +class ChainShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AmmunitionVisitor& visitor) { + visitor.visit(*this); + } +}; + +class GrapeShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AmmunitionVisitor& visitor) { + visitor.visit(*this); + } +}; +``` + + +___ + +At the end we provide implementation for each visitor + +```C++ +class DamageVisitor : public AmmunitionVisitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Round shot make 20 damages\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Chain shot make 30 damages\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Grape shot make 40 damages\n"; + } +}; + +class SoundVisitor : public AmmunitionVisitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Fiuuuuuuuu Bam!\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam!\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam bam bam bam!\n"; + } +}; +``` + + +___ + +## Usage + +```C++ +int main() { + std::unique_ptr grapeShot = std::make_unique(100); + SoundVisitor soundVisitor; + DamageVisitor damageVisitor; + grapeShot->accept(soundVisitor); + grapeShot->accept(damageVisitor); +} +``` + +```bash +Fiuuuuuuuuuuu Bam bam bam bam bam! +Grape shot make 40 damages +``` + + +___ + +## Drawbacks + +Visitor in this approach has 4 drawbacks: + +* First I mentioned earlier it will be hard to add a new type, we can solve it by using acyclic visitor +* Visitor is tightly coupled with other classes and not elastic. For instance, DamageVisitor implementations may be similar, but we need to implement a method for every class. We can separate common parts to another function, but still, it will be great if we can have one function for all types if needed. By using visitors, this is not possible +* If we want to introduce visitors in an already implemented hierarchy of classes we need to add the accept method to every base class, sometimes we don't have access to all files in the repo, or the repository is divided and it is not possible. There is a solution for this, which I will show you later +* If we add a new class that inherits from an already existing type, and we forget to override method, we will have the same behavior as the class that we inherit, which is a huge bug! + + +___ + +## Improvements + +As I said a few times, the modern approach uses by-value semantics, instead of virtual functions. We can use static or compile-time polymorphism to achieve the same and have even better performance. let's rewrite this example to use `std::variant` which allows us to decouple classes, and make a code more flexible and even faster (I will show you a benchmark later). + +```C++ +class Ammunition { +public: + Ammunition(size_t amount) + : _amount(amount) {} + virtual ~Ammunition() = default; + + size_t amount() const { return _amount; } + +private: + size_t _amount = 0; +}; + +class RoundShot final : public Ammunition { +public: + using Ammunition::Ammunition; +}; + +class ChainShot final : public Ammunition { +public: + using Ammunition::Ammunition; +}; + +class GrapeShot final : public Ammunition { +public: + using Ammunition::Ammunition; +}; +``` + + +___ + +```C++ +class DamageVisitor { +public: + void operator()(const RoundShot& shot) const { + std::cout << "Round shot make 20 damages\n"; + } + void operator()(const ChainShot& shot) const { + std::cout << "Chain shot make 30 damages\n"; + } + void operator()(const GrapeShot& shot) const { + std::cout << "Grape shot make 40 damages\n"; + } +}; + +class SoundVisitor { +public: + void operator()(const RoundShot& shot) const { + std::cout << "Fiuuuuuuuu Bam!\n"; + } + void operator()(const ChainShot& shot) const { + std::cout << "Fiuuuuuuuuuuu Bam bam!\n"; + } + void operator()(const GrapeShot& shot) const { + std::cout << "Fiuuuuuuuuuuu Bam bam bam bam bam!\n"; + } +}; +``` + +___ + +We get rid of a lot of virtual functions and simplify the code. + +```C++ +int main() { + using Shot = std::variant; + + Shot shot = GrapeShot(100); + SoundVisitor soundVisitor; + DamageVisitor damageVisitor; + std::visit(damageVisitor, shot); + std::visit(soundVisitor, shot); +} +``` + + +```bash +Grape shot make 40 damages +Fiuuuuuuuuuuu Bam bam bam bam bam! +``` + + +___ + +## Benchmark + +I created a cimple bechmark to show you, that visitors based on variant may be faster. It depends on how heavy the is function visit, if we perform a fast operation, we will gain a lot, but if the operation is heavy we will barely see the difference between both solutions. + +Visitor benchamrk + + +___ + +## Simplified class hierarchy + +Visitor better design + +___ + +## Drawback std::variant + +We improved our code, but still, one problem exists, we can't easily add new types. The variant also provides another drawback: When types differ in size a lot, we will waste a lot of memory. In such a case we may think about using `std::unique_ptr` but this will force us to use dynamic allocation, so we lost some improvements (not fully use by-value semantic). + + +Last things left: How to eliminate this problem by adding a new type? Let's check the `acyclic variant` class: + + + +___ + +## Acyclic visitor + +Visitor acyclic + +___ + +## Implementation + +First, we create an abstract visitor class and three types of visitor for each type. This allows us to cut dependency between each visitor, because each visitor has knowledge about only one ammunition type. + +```C++ +class AbstractVisitor { +protected: + // Can be only use by derived class + virtual ~AbstractVisitor() = default; +}; + +class RoundShotVisitor { +public: + virtual void visit(const RoundShot& shot) const = 0; + +protected: + virtual ~RoundShotVisitor() = default; +}; + +class GrapeShotVisitor { +public: + virtual void visit(const GrapeShot& shot) const = 0; + +protected: + virtual ~GrapeShotVisitor() = default; +}; + +class ChainShotVisitor { +public: + virtual void visit(const ChainShot& shot) const = 0; + +protected: + virtual ~ChainShotVisitor() = default; +}; +``` + + +___ + +Next, we create dedicated visitors for `damage` and for `sound`. To hide implementations detail, each class inherit also from `AbstractVisitor`. This allows to use any visitor as pointer to this abstract class. + +```C++ +class DamageVisitor : public AbstractVisitor, + public RoundShotVisitor, + public GrapeShotVisitor, + public ChainShotVisitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Round shot make 20 damages\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Chain shot make 30 damages\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Grape shot make 40 damages\n"; + } +}; + +class SoundVisitor : public AbstractVisitor, + public RoundShotVisitor, + public GrapeShotVisitor, + public ChainShotVisitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Fiuuuuuuuu Bam!\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam!\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Fiuuuuuuuuuuu Bam bam bam bam bam!\n"; + } +}; +``` + + +___ + +For now, everything looks ok. But unfortunately, because `AbstracVisitor` has empty interface, we need to cast visitor to a specific type. This `dynamic_cast` cost a lot and make code harder to optimize. That's why this visitor is much slower than previous implementations. + +```C++ +class RoundShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast(&visitor)) { + v->visit(*this); + } + } +}; + +class ChainShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast(&visitor)) { + v->visit(*this); + } + } +}; + +class GrapeShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast(&visitor)) { + v->visit(*this); + } + } +}; +``` + + +___ + +## Usage + +The usage of this code doesn't change in comparison to the first implementation. But we lost on efficiency. + +```C++ +int main() { + std::unique_ptr grapeShot = std::make_unique(100); + SoundVisitor soundVisitor; + DamageVisitor damageVisitor; + grapeShot->accept(soundVisitor); + grapeShot->accept(damageVisitor); +} + +``` + +```bash +Fiuuuuuuuuuuu Bam bam bam bam bam! +Grape shot make 40 damages +``` + + +___ + +## Lost efficiency + +Acyclic visitor benchmark +___ + +## Improvement + +When visitor operations are quick, better to avoid acyclic visitor to not make the code slower. But when the operations are heavy, the difference will be slightly visible, and we will decouple visitor and ammunition classes. There is also one improvement, that make a code easier to extend. Instead of writing every time a visitor for a type, we can use template. + +```C++ +template +class Visitor { +public: + virtual void visit(const T& shot) const = 0; + +protected: + virtual ~Visitor() = default; +}; + +class DamageVisitor : public AbstractVisitor, + public Visitor, + public Visitor, + public Visitor { +public: + void visit(const RoundShot& shot) const override { + std::cout << "Round shot make 20 damages\n"; + } + void visit(const ChainShot& shot) const override { + std::cout << "Chain shot make 30 damages\n"; + } + void visit(const GrapeShot& shot) const override { + std::cout << "Grape shot make 40 damages\n"; + } +}; +``` + + +___ + +```C++ +class RoundShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast*>(&visitor)) { + v->visit(*this); + } + } +}; + +class ChainShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast*>(&visitor)) { + v->visit(*this); + } + } +}; + +class GrapeShot : public Ammunition { +public: + using Ammunition::Ammunition; + void accept(const AbstractVisitor& visitor) { + if (const auto* v = dynamic_cast*>(&visitor)) { + v->visit(*this); + } + } +}; +``` + +___ + +## UML + +Acyclic visitor UML +___ + +## Exericse 1 + +* Go into directory Core and implement a base class PrintVisitor which should implement visit method for two objects: Ship and Store +* Create PrettyPrintVisitor which will print cargo from Ship and Sotore (just move the implementation from printCargo). +* Add the rest of necessary implementation for Ship and Store. Visitor should be taken as std::unique_ptr +* Verify in the main.cpp if cargo print in the same way as previously. + +___ + +## Exercise 2 + +* Create another visitor: BasicPrintVisitor which should print the cargo but without special frames, just raw info. +* For Ship print Name and Amount +* For Store print Name Amount and Price +* You shouldn't modify anything in your code, just change the visitor in main.cpp and you should get a new output +___ + +## Exercise 3 + +* Create CargoDamageVisitor. You don't need to create a base class, because we know that we will not extend this code, +* You should create three operator() one for each cargo type: Alcohol, Fruit, Item, +* For fruit, you should draw a number between 0 and 5 and subtract such an amount of cargo +* For alcohol, you should draw a number between 0 and 10 and subtract half an amount of cargo +* For item, you should draw a number between 0 and 20 and subtract one quarter of cargo +* Visitor should be taken as a template argument by Player class +* Apply visitor whenever you successfully deal damage to ship +* Check in the main class if ship lost cargo after get damaged. + +___ + +## Summary + +As you can see visitor is a very useful pattern to add additional functionality to your class, in such was you don't need to modify already existing code, instead you can inherit from visitor and create totally new functionality. You can also use `std::variant` if you want to avoid modify original class (by adding accept method) or when you can't modify class (for instance it is in separate repo). Version, with variant, is also more flexible and faster than traditional implementation. If you really want to break all dependencies between visitor class and subject, you can use acyclic visitor, but this solution is less efficient, so you need to be sure you can accept this in your code. \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/README.md b/CreatingReliableSoftwareCpp/README.md new file mode 100644 index 0000000..e217134 --- /dev/null +++ b/CreatingReliableSoftwareCpp/README.md @@ -0,0 +1 @@ +# CreatingReliableSoftwareCpp \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/bower.json b/CreatingReliableSoftwareCpp/bower.json new file mode 100644 index 0000000..bc825ab --- /dev/null +++ b/CreatingReliableSoftwareCpp/bower.json @@ -0,0 +1,24 @@ +{ + "name": "reveal.js", + "version": "3.9.2", + "main": [ + "js/reveal.js", + "css/reveal.css" + ], + "homepage": "http://revealjs.com", + "license": "MIT", + "description": "The HTML Presentation Framework", + "authors": [ + "Hakim El Hattab " + ], + "repository": { + "type": "git", + "url": "git://github.com/hakimel/reveal.js.git" + }, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test" + ] +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/print/paper.css b/CreatingReliableSoftwareCpp/css/print/paper.css new file mode 100644 index 0000000..27d19dd --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/print/paper.css @@ -0,0 +1,203 @@ +/* Default Print Stylesheet Template + by Rob Glazebrook of CSSnewbie.com + Last Updated: June 4, 2008 + + Feel free (nay, compelled) to edit, append, and + manipulate this file as you see fit. */ + + +@media print { + + /* SECTION 1: Set default width, margin, float, and + background. This prevents elements from extending + beyond the edge of the printed page, and prevents + unnecessary background images from printing */ + html { + background: #fff; + width: auto; + height: auto; + overflow: visible; + } + body { + background: #fff; + font-size: 20pt; + width: auto; + height: auto; + border: 0; + margin: 0 5%; + padding: 0; + overflow: visible; + float: none !important; + } + + /* SECTION 2: Remove any elements not needed in print. + This would include navigation, ads, sidebars, etc. */ + .nestedarrow, + .controls, + .fork-reveal, + .share-reveal, + .state-background, + .reveal .progress, + .reveal .backgrounds, + .reveal .slide-number { + display: none !important; + } + + /* SECTION 3: Set body font face, size, and color. + Consider using a serif font for readability. */ + body, p, td, li, div { + font-size: 20pt!important; + font-family: Georgia, "Times New Roman", Times, serif !important; + color: #000; + } + + /* SECTION 4: Set heading font face, sizes, and color. + Differentiate your headings from your body text. + Perhaps use a large sans-serif for distinction. */ + h1,h2,h3,h4,h5,h6 { + color: #000!important; + height: auto; + line-height: normal; + font-family: Georgia, "Times New Roman", Times, serif !important; + text-shadow: 0 0 0 #000 !important; + text-align: left; + letter-spacing: normal; + } + /* Need to reduce the size of the fonts for printing */ + h1 { font-size: 28pt !important; } + h2 { font-size: 24pt !important; } + h3 { font-size: 22pt !important; } + h4 { font-size: 22pt !important; font-variant: small-caps; } + h5 { font-size: 21pt !important; } + h6 { font-size: 20pt !important; font-style: italic; } + + /* SECTION 5: Make hyperlinks more usable. + Ensure links are underlined, and consider appending + the URL to the end of the link for usability. */ + a:link, + a:visited { + color: #000 !important; + font-weight: bold; + text-decoration: underline; + } + /* + .reveal a:link:after, + .reveal a:visited:after { + content: " (" attr(href) ") "; + color: #222 !important; + font-size: 90%; + } + */ + + + /* SECTION 6: more reveal.js specific additions by @skypanther */ + ul, ol, div, p { + visibility: visible; + position: static; + width: auto; + height: auto; + display: block; + overflow: visible; + margin: 0; + text-align: left !important; + } + .reveal pre, + .reveal table { + margin-left: 0; + margin-right: 0; + } + .reveal pre code { + padding: 20px; + border: 1px solid #ddd; + } + .reveal blockquote { + margin: 20px 0; + } + .reveal .slides { + position: static !important; + width: auto !important; + height: auto !important; + + left: 0 !important; + top: 0 !important; + margin-left: 0 !important; + margin-top: 0 !important; + padding: 0 !important; + zoom: 1 !important; + + overflow: visible !important; + display: block !important; + + text-align: left !important; + -webkit-perspective: none; + -moz-perspective: none; + -ms-perspective: none; + perspective: none; + + -webkit-perspective-origin: 50% 50%; + -moz-perspective-origin: 50% 50%; + -ms-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; + } + .reveal .slides section { + visibility: visible !important; + position: static !important; + width: auto !important; + height: auto !important; + display: block !important; + overflow: visible !important; + + left: 0 !important; + top: 0 !important; + margin-left: 0 !important; + margin-top: 0 !important; + padding: 60px 20px !important; + z-index: auto !important; + + opacity: 1 !important; + + page-break-after: always !important; + + -webkit-transform-style: flat !important; + -moz-transform-style: flat !important; + -ms-transform-style: flat !important; + transform-style: flat !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; + + -webkit-transition: none !important; + -moz-transition: none !important; + -ms-transition: none !important; + transition: none !important; + } + .reveal .slides section.stack { + padding: 0 !important; + } + .reveal section:last-of-type { + page-break-after: avoid !important; + } + .reveal section .fragment { + opacity: 1 !important; + visibility: visible !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; + } + .reveal section img { + display: block; + margin: 15px 0px; + background: rgba(255,255,255,1); + border: 1px solid #666; + box-shadow: none; + } + + .reveal section small { + font-size: 0.8em; + } + +} diff --git a/CreatingReliableSoftwareCpp/css/print/pdf.css b/CreatingReliableSoftwareCpp/css/print/pdf.css new file mode 100644 index 0000000..bf96ed1 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/print/pdf.css @@ -0,0 +1,165 @@ +/** + * This stylesheet is used to print reveal.js + * presentations to PDF. + * + * https://github.com/hakimel/reveal.js#pdf-export + */ + +* { + -webkit-print-color-adjust: exact; +} + +body { + margin: 0 auto !important; + border: 0; + padding: 0; + float: none !important; + overflow: visible; +} + +html { + width: 100%; + height: 100%; + overflow: visible; +} + +/* Remove any elements not needed in print. */ +.nestedarrow, +.reveal .controls, +.reveal .progress, +.reveal .playback, +.reveal.overview, +.fork-reveal, +.share-reveal, +.state-background { + display: none !important; +} + +h1, h2, h3, h4, h5, h6 { + text-shadow: 0 0 0 #000 !important; +} + +.reveal pre code { + overflow: hidden !important; + font-family: Courier, 'Courier New', monospace !important; +} + +ul, ol, div, p { + visibility: visible; + position: static; + width: auto; + height: auto; + display: block; + overflow: visible; + margin: auto; +} +.reveal { + width: auto !important; + height: auto !important; + overflow: hidden !important; +} +.reveal .slides { + position: static; + width: 100% !important; + height: auto !important; + zoom: 1 !important; + pointer-events: initial; + + left: auto; + top: auto; + margin: 0 !important; + padding: 0 !important; + + overflow: visible; + display: block; + + perspective: none; + perspective-origin: 50% 50%; +} + +.reveal .slides .pdf-page { + position: relative; + overflow: hidden; + z-index: 1; + + page-break-after: always; +} + +.reveal .slides section { + visibility: visible !important; + display: block !important; + position: absolute !important; + + margin: 0 !important; + padding: 0 !important; + box-sizing: border-box !important; + min-height: 1px; + + opacity: 1 !important; + + transform-style: flat !important; + transform: none !important; +} + +.reveal section.stack { + position: relative !important; + margin: 0 !important; + padding: 0 !important; + page-break-after: avoid !important; + height: auto !important; + min-height: auto !important; +} + +.reveal img { + box-shadow: none; +} + +.reveal .roll { + overflow: visible; + line-height: 1em; +} + +/* Slide backgrounds are placed inside of their slide when exporting to PDF */ +.reveal .slide-background { + display: block !important; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: auto !important; +} + +/* Display slide speaker notes when 'showNotes' is enabled */ +.reveal.show-notes { + max-width: none; + max-height: none; +} +.reveal .speaker-notes-pdf { + display: block; + width: 100%; + height: auto; + max-height: none; + top: auto; + right: auto; + bottom: auto; + left: auto; + z-index: 100; +} + +/* Layout option which makes notes appear on a separate page */ +.reveal .speaker-notes-pdf[data-layout="separate-page"] { + position: relative; + color: inherit; + background-color: transparent; + padding: 20px; + page-break-after: always; + border: 0; +} + +/* Display slide numbers when 'slideNumber' is enabled */ +.reveal .slide-number-pdf { + display: block; + position: absolute; + font-size: 14px; +} diff --git a/CreatingReliableSoftwareCpp/css/reset.css b/CreatingReliableSoftwareCpp/css/reset.css new file mode 100644 index 0000000..e238539 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/reset.css @@ -0,0 +1,30 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v4.0 | 20180602 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +main, menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, main, menu, nav, section { + display: block; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/reveal.css b/CreatingReliableSoftwareCpp/css/reveal.css new file mode 100644 index 0000000..b4bc4fd --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/reveal.css @@ -0,0 +1,1606 @@ +/*! + * reveal.js + * http://revealjs.com + * MIT licensed + * + * Copyright (C) 2020 Hakim El Hattab, http://hakim.se + */ +/********************************************* + * GLOBAL STYLES + *********************************************/ +html { + width: 100%; + height: 100%; + height: 100vh; + height: calc( var(--vh, 1vh) * 100); + overflow: hidden; } + +body { + height: 100%; + overflow: hidden; + position: relative; + line-height: 1; + margin: 0; + background-color: #fff; + color: #000; } + +/********************************************* + * VIEW FRAGMENTS + *********************************************/ +.reveal .slides section .fragment { + opacity: 0; + visibility: hidden; + transition: all .2s ease; } + .reveal .slides section .fragment.visible { + opacity: 1; + visibility: inherit; } + +.reveal .slides section .fragment.grow { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.grow.visible { + -webkit-transform: scale(1.3); + transform: scale(1.3); } + +.reveal .slides section .fragment.shrink { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.shrink.visible { + -webkit-transform: scale(0.7); + transform: scale(0.7); } + +.reveal .slides section .fragment.zoom-in { + -webkit-transform: scale(0.1); + transform: scale(0.1); } + .reveal .slides section .fragment.zoom-in.visible { + -webkit-transform: none; + transform: none; } + +.reveal .slides section .fragment.fade-out { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.fade-out.visible { + opacity: 0; + visibility: hidden; } + +.reveal .slides section .fragment.semi-fade-out { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.semi-fade-out.visible { + opacity: 0.5; + visibility: inherit; } + +.reveal .slides section .fragment.strike { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.strike.visible { + text-decoration: line-through; } + +.reveal .slides section .fragment.fade-up { + -webkit-transform: translate(0, 40px); + transform: translate(0, 40px); } + .reveal .slides section .fragment.fade-up.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-down { + -webkit-transform: translate(0, -40px); + transform: translate(0, -40px); } + .reveal .slides section .fragment.fade-down.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-right { + -webkit-transform: translate(-40px, 0); + transform: translate(-40px, 0); } + .reveal .slides section .fragment.fade-right.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-left { + -webkit-transform: translate(40px, 0); + transform: translate(40px, 0); } + .reveal .slides section .fragment.fade-left.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-in-then-out, +.reveal .slides section .fragment.current-visible { + opacity: 0; + visibility: hidden; } + .reveal .slides section .fragment.fade-in-then-out.current-fragment, + .reveal .slides section .fragment.current-visible.current-fragment { + opacity: 1; + visibility: inherit; } + +.reveal .slides section .fragment.fade-in-then-semi-out { + opacity: 0; + visibility: hidden; } + .reveal .slides section .fragment.fade-in-then-semi-out.visible { + opacity: 0.5; + visibility: inherit; } + .reveal .slides section .fragment.fade-in-then-semi-out.current-fragment { + opacity: 1; + visibility: inherit; } + +.reveal .slides section .fragment.highlight-red, +.reveal .slides section .fragment.highlight-current-red, +.reveal .slides section .fragment.highlight-green, +.reveal .slides section .fragment.highlight-current-green, +.reveal .slides section .fragment.highlight-blue, +.reveal .slides section .fragment.highlight-current-blue { + opacity: 1; + visibility: inherit; } + +.reveal .slides section .fragment.highlight-red.visible { + color: #ff2c2d; } + +.reveal .slides section .fragment.highlight-green.visible { + color: #216428; } + +.reveal .slides section .fragment.highlight-blue.visible { + color: #1b91ff; } + +.reveal .slides section .fragment.highlight-current-red.current-fragment { + color: #ff2c2d; } + +.reveal .slides section .fragment.highlight-current-green.current-fragment { + color: #17ff2e; } + +.reveal .slides section .fragment.highlight-current-blue.current-fragment { + color: #1b91ff; } + +/********************************************* + * DEFAULT ELEMENT STYLES + *********************************************/ +/* Fixes issue in Chrome where italic fonts did not appear when printing to PDF */ +.reveal:after { + content: ''; + font-style: italic; } + +.reveal iframe { + z-index: 1; } + +/** Prevents layering issues in certain browser/transition combinations */ +.reveal a { + position: relative; } + +.reveal .stretch { + max-width: none; + max-height: none; } + +.reveal pre.stretch code { + height: 100%; + max-height: 100%; + box-sizing: border-box; } + +/********************************************* + * CONTROLS + *********************************************/ +@-webkit-keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } + +@-webkit-keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + +.reveal .controls { + display: none; + position: absolute; + top: auto; + bottom: 12px; + right: 12px; + left: auto; + z-index: 11; + color: #000; + pointer-events: none; + font-size: 10px; } + .reveal .controls button { + position: absolute; + padding: 0; + background-color: transparent; + border: 0; + outline: 0; + cursor: pointer; + color: currentColor; + -webkit-transform: scale(0.9999); + transform: scale(0.9999); + transition: color 0.2s ease, opacity 0.2s ease, -webkit-transform 0.2s ease; + transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease; + z-index: 2; + pointer-events: auto; + font-size: inherit; + visibility: hidden; + opacity: 0; + -webkit-appearance: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } + .reveal .controls .controls-arrow:before, + .reveal .controls .controls-arrow:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 2.6em; + height: 0.5em; + border-radius: 0.25em; + background-color: currentColor; + transition: all 0.15s ease, background-color 0.8s ease; + -webkit-transform-origin: 0.2em 50%; + transform-origin: 0.2em 50%; + will-change: transform; } + .reveal .controls .controls-arrow { + position: relative; + width: 3.6em; + height: 3.6em; } + .reveal .controls .controls-arrow:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } + .reveal .controls .controls-arrow:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } + .reveal .controls .controls-arrow:hover:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(40deg); + transform: translateX(0.5em) translateY(1.55em) rotate(40deg); } + .reveal .controls .controls-arrow:hover:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); } + .reveal .controls .controls-arrow:active:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(36deg); + transform: translateX(0.5em) translateY(1.55em) rotate(36deg); } + .reveal .controls .controls-arrow:active:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); } + .reveal .controls .navigate-left { + right: 6.4em; + bottom: 3.2em; + -webkit-transform: translateX(-10px); + transform: translateX(-10px); } + .reveal .controls .navigate-right { + right: 0; + bottom: 3.2em; + -webkit-transform: translateX(10px); + transform: translateX(10px); } + .reveal .controls .navigate-right .controls-arrow { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + .reveal .controls .navigate-right.highlight { + -webkit-animation: bounce-right 2s 50 both ease-out; + animation: bounce-right 2s 50 both ease-out; } + .reveal .controls .navigate-up { + right: 3.2em; + bottom: 6.4em; + -webkit-transform: translateY(-10px); + transform: translateY(-10px); } + .reveal .controls .navigate-up .controls-arrow { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + .reveal .controls .navigate-down { + right: 3.2em; + bottom: -1.4em; + padding-bottom: 1.4em; + -webkit-transform: translateY(10px); + transform: translateY(10px); } + .reveal .controls .navigate-down .controls-arrow { + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); } + .reveal .controls .navigate-down.highlight { + -webkit-animation: bounce-down 2s 50 both ease-out; + animation: bounce-down 2s 50 both ease-out; } + .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled, + .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled { + opacity: 0.3; } + .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled:hover, + .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled:hover { + opacity: 1; } + .reveal .controls[data-controls-back-arrows="hidden"] .navigate-left.enabled, + .reveal .controls[data-controls-back-arrows="hidden"] .navigate-up.enabled { + opacity: 0; + visibility: hidden; } + .reveal .controls .enabled { + visibility: visible; + opacity: 0.9; + cursor: pointer; + -webkit-transform: none; + transform: none; } + .reveal .controls .enabled.fragmented { + opacity: 0.5; } + .reveal .controls .enabled:hover, + .reveal .controls .enabled.fragmented:hover { + opacity: 1; } + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-up, +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-down { + display: none; } + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-left, +.reveal:not(.has-vertical-slides) .controls .navigate-left { + bottom: 1.4em; + right: 5.5em; } + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-right, +.reveal:not(.has-vertical-slides) .controls .navigate-right { + bottom: 1.4em; + right: 0.5em; } + +.reveal:not(.has-horizontal-slides) .controls .navigate-up { + right: 1.4em; + bottom: 5em; } + +.reveal:not(.has-horizontal-slides) .controls .navigate-down { + right: 1.4em; + bottom: 0.5em; } + +.reveal.has-dark-background .controls { + color: #fff; } + +.reveal.has-light-background .controls { + color: #000; } + +.reveal.no-hover .controls .controls-arrow:hover:before, +.reveal.no-hover .controls .controls-arrow:active:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } + +.reveal.no-hover .controls .controls-arrow:hover:after, +.reveal.no-hover .controls .controls-arrow:active:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } + +@media screen and (min-width: 500px) { + .reveal .controls[data-controls-layout="edges"] { + top: 0; + right: 0; + bottom: 0; + left: 0; } + .reveal .controls[data-controls-layout="edges"] .navigate-left, + .reveal .controls[data-controls-layout="edges"] .navigate-right, + .reveal .controls[data-controls-layout="edges"] .navigate-up, + .reveal .controls[data-controls-layout="edges"] .navigate-down { + bottom: auto; + right: auto; } + .reveal .controls[data-controls-layout="edges"] .navigate-left { + top: 50%; + left: 0.8em; + margin-top: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-right { + top: 50%; + right: 0.8em; + margin-top: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-up { + top: 0.8em; + left: 50%; + margin-left: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-down { + bottom: -0.3em; + left: 50%; + margin-left: -1.8em; } } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + position: absolute; + display: none; + height: 3px; + width: 100%; + bottom: 0; + left: 0; + z-index: 10; + background-color: rgba(0, 0, 0, 0.2); + color: #fff; } + +.reveal .progress:after { + content: ''; + display: block; + position: absolute; + height: 10px; + width: 100%; + top: -10px; } + +.reveal .progress span { + display: block; + height: 100%; + width: 0px; + background-color: currentColor; + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * SLIDE NUMBER + *********************************************/ +.reveal .slide-number { + position: absolute; + display: block; + right: 8px; + bottom: 8px; + z-index: 31; + font-family: Helvetica, sans-serif; + font-size: 12px; + line-height: 1; + color: #fff; + background-color: rgba(0, 0, 0, 0.4); + padding: 5px; } + +.reveal .slide-number a { + color: currentColor; } + +.reveal .slide-number-delimiter { + margin: 0 3px; } + +/********************************************* + * SLIDES + *********************************************/ +.reveal { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + -ms-touch-action: pinch-zoom; + touch-action: pinch-zoom; } + +.reveal .slides { + position: absolute; + width: 100%; + height: 100%; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + pointer-events: none; + overflow: visible; + z-index: 1; + text-align: center; + -webkit-perspective: 600px; + perspective: 600px; + -webkit-perspective-origin: 50% 40%; + perspective-origin: 50% 40%; } + +.reveal .slides > section { + -webkit-perspective: 600px; + perspective: 600px; } + +.reveal .slides > section, +.reveal .slides > section > section { + display: none; + position: absolute; + width: 100%; + padding: 20px 0px; + pointer-events: auto; + z-index: 10; + -webkit-transform-style: flat; + transform-style: flat; + transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"] .slides section { + transition-duration: 400ms; } + +.reveal[data-transition-speed="slow"] .slides section { + transition-duration: 1200ms; } + +/* Slide-specific transition speed overrides */ +.reveal .slides section[data-transition-speed="fast"] { + transition-duration: 400ms; } + +.reveal .slides section[data-transition-speed="slow"] { + transition-duration: 1200ms; } + +.reveal .slides > section.stack { + padding-top: 0; + padding-bottom: 0; + pointer-events: none; + height: 100%; } + +.reveal .slides > section.present, +.reveal .slides > section > section.present { + display: block; + z-index: 11; + opacity: 1; } + +.reveal .slides > section:empty, +.reveal .slides > section > section:empty, +.reveal .slides > section[data-background-interactive], +.reveal .slides > section > section[data-background-interactive] { + pointer-events: none; } + +.reveal.center, +.reveal.center .slides, +.reveal.center .slides section { + min-height: 0 !important; } + +/* Don't allow interaction with invisible slides */ +.reveal .slides > section.future, +.reveal .slides > section > section.future, +.reveal .slides > section.past, +.reveal .slides > section > section.past { + pointer-events: none; } + +.reveal.overview .slides > section, +.reveal.overview .slides > section > section { + pointer-events: auto; } + +.reveal .slides > section.past, +.reveal .slides > section.future, +.reveal .slides > section > section.past, +.reveal .slides > section > section.future { + opacity: 0; } + +/********************************************* + * Mixins for readability of transitions + *********************************************/ +/********************************************* + * SLIDE TRANSITION + * Aliased 'linear' for backwards compatibility + *********************************************/ +.reveal.slide section { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + +.reveal .slides > section[data-transition=slide].past, +.reveal .slides > section[data-transition~=slide-out].past, +.reveal.slide .slides > section:not([data-transition]).past { + -webkit-transform: translate(-150%, 0); + transform: translate(-150%, 0); } + +.reveal .slides > section[data-transition=slide].future, +.reveal .slides > section[data-transition~=slide-in].future, +.reveal.slide .slides > section:not([data-transition]).future { + -webkit-transform: translate(150%, 0); + transform: translate(150%, 0); } + +.reveal .slides > section > section[data-transition=slide].past, +.reveal .slides > section > section[data-transition~=slide-out].past, +.reveal.slide .slides > section > section:not([data-transition]).past { + -webkit-transform: translate(0, -150%); + transform: translate(0, -150%); } + +.reveal .slides > section > section[data-transition=slide].future, +.reveal .slides > section > section[data-transition~=slide-in].future, +.reveal.slide .slides > section > section:not([data-transition]).future { + -webkit-transform: translate(0, 150%); + transform: translate(0, 150%); } + +.reveal.linear section { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + +.reveal .slides > section[data-transition=linear].past, +.reveal .slides > section[data-transition~=linear-out].past, +.reveal.linear .slides > section:not([data-transition]).past { + -webkit-transform: translate(-150%, 0); + transform: translate(-150%, 0); } + +.reveal .slides > section[data-transition=linear].future, +.reveal .slides > section[data-transition~=linear-in].future, +.reveal.linear .slides > section:not([data-transition]).future { + -webkit-transform: translate(150%, 0); + transform: translate(150%, 0); } + +.reveal .slides > section > section[data-transition=linear].past, +.reveal .slides > section > section[data-transition~=linear-out].past, +.reveal.linear .slides > section > section:not([data-transition]).past { + -webkit-transform: translate(0, -150%); + transform: translate(0, -150%); } + +.reveal .slides > section > section[data-transition=linear].future, +.reveal .slides > section > section[data-transition~=linear-in].future, +.reveal.linear .slides > section > section:not([data-transition]).future { + -webkit-transform: translate(0, 150%); + transform: translate(0, 150%); } + +/********************************************* + * CONVEX TRANSITION + * Aliased 'default' for backwards compatibility + *********************************************/ +.reveal .slides section[data-transition=default].stack, +.reveal.default .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=default].past, +.reveal .slides > section[data-transition~=default-out].past, +.reveal.default .slides > section:not([data-transition]).past { + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } + +.reveal .slides > section[data-transition=default].future, +.reveal .slides > section[data-transition~=default-in].future, +.reveal.default .slides > section:not([data-transition]).future { + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } + +.reveal .slides > section > section[data-transition=default].past, +.reveal .slides > section > section[data-transition~=default-out].past, +.reveal.default .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } + +.reveal .slides > section > section[data-transition=default].future, +.reveal .slides > section > section[data-transition~=default-in].future, +.reveal.default .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } + +.reveal .slides section[data-transition=convex].stack, +.reveal.convex .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=convex].past, +.reveal .slides > section[data-transition~=convex-out].past, +.reveal.convex .slides > section:not([data-transition]).past { + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } + +.reveal .slides > section[data-transition=convex].future, +.reveal .slides > section[data-transition~=convex-in].future, +.reveal.convex .slides > section:not([data-transition]).future { + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } + +.reveal .slides > section > section[data-transition=convex].past, +.reveal .slides > section > section[data-transition~=convex-out].past, +.reveal.convex .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } + +.reveal .slides > section > section[data-transition=convex].future, +.reveal .slides > section > section[data-transition~=convex-in].future, +.reveal.convex .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } + +/********************************************* + * CONCAVE TRANSITION + *********************************************/ +.reveal .slides section[data-transition=concave].stack, +.reveal.concave .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=concave].past, +.reveal .slides > section[data-transition~=concave-out].past, +.reveal.concave .slides > section:not([data-transition]).past { + -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } + +.reveal .slides > section[data-transition=concave].future, +.reveal .slides > section[data-transition~=concave-in].future, +.reveal.concave .slides > section:not([data-transition]).future { + -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } + +.reveal .slides > section > section[data-transition=concave].past, +.reveal .slides > section > section[data-transition~=concave-out].past, +.reveal.concave .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); + transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); } + +.reveal .slides > section > section[data-transition=concave].future, +.reveal .slides > section > section[data-transition~=concave-in].future, +.reveal.concave .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); + transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); } + +/********************************************* + * ZOOM TRANSITION + *********************************************/ +.reveal .slides section[data-transition=zoom], +.reveal.zoom .slides section:not([data-transition]) { + transition-timing-function: ease; } + +.reveal .slides > section[data-transition=zoom].past, +.reveal .slides > section[data-transition~=zoom-out].past, +.reveal.zoom .slides > section:not([data-transition]).past { + visibility: hidden; + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal .slides > section[data-transition=zoom].future, +.reveal .slides > section[data-transition~=zoom-in].future, +.reveal.zoom .slides > section:not([data-transition]).future { + visibility: hidden; + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +.reveal .slides > section > section[data-transition=zoom].past, +.reveal .slides > section > section[data-transition~=zoom-out].past, +.reveal.zoom .slides > section > section:not([data-transition]).past { + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal .slides > section > section[data-transition=zoom].future, +.reveal .slides > section > section[data-transition~=zoom-in].future, +.reveal.zoom .slides > section > section:not([data-transition]).future { + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +/********************************************* + * CUBE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ +.reveal.cube .slides { + -webkit-perspective: 1300px; + perspective: 1300px; } + +.reveal.cube .slides section { + padding: 30px; + min-height: 700px; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + box-sizing: border-box; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal.center.cube .slides section { + min-height: 0; } + +.reveal.cube .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0, 0, 0, 0.1); + border-radius: 4px; + -webkit-transform: translateZ(-20px); + transform: translateZ(-20px); } + +.reveal.cube .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2); + -webkit-transform: translateZ(-90px) rotateX(65deg); + transform: translateZ(-90px) rotateX(65deg); } + +.reveal.cube .slides > section.stack { + padding: 0; + background: none; } + +.reveal.cube .slides > section.past { + -webkit-transform-origin: 100% 0%; + transform-origin: 100% 0%; + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg); + transform: translate3d(-100%, 0, 0) rotateY(-90deg); } + +.reveal.cube .slides > section.future { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg); + transform: translate3d(100%, 0, 0) rotateY(90deg); } + +.reveal.cube .slides > section > section.past { + -webkit-transform-origin: 0% 100%; + transform-origin: 0% 100%; + -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg); + transform: translate3d(0, -100%, 0) rotateX(90deg); } + +.reveal.cube .slides > section > section.future { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg); + transform: translate3d(0, 100%, 0) rotateX(-90deg); } + +/********************************************* + * PAGE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ +.reveal.page .slides { + -webkit-perspective-origin: 0% 50%; + perspective-origin: 0% 50%; + -webkit-perspective: 3000px; + perspective: 3000px; } + +.reveal.page .slides section { + padding: 30px; + min-height: 700px; + box-sizing: border-box; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal.page .slides section.past { + z-index: 12; } + +.reveal.page .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0, 0, 0, 0.1); + -webkit-transform: translateZ(-20px); + transform: translateZ(-20px); } + +.reveal.page .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2); + -webkit-transform: translateZ(-90px) rotateX(65deg); } + +.reveal.page .slides > section.stack { + padding: 0; + background: none; } + +.reveal.page .slides > section.past { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(-40%, 0, 0) rotateY(-80deg); + transform: translate3d(-40%, 0, 0) rotateY(-80deg); } + +.reveal.page .slides > section.future { + -webkit-transform-origin: 100% 0%; + transform-origin: 100% 0%; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.reveal.page .slides > section > section.past { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(0, -40%, 0) rotateX(80deg); + transform: translate3d(0, -40%, 0) rotateX(80deg); } + +.reveal.page .slides > section > section.future { + -webkit-transform-origin: 0% 100%; + transform-origin: 0% 100%; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +/********************************************* + * FADE TRANSITION + *********************************************/ +.reveal .slides section[data-transition=fade], +.reveal.fade .slides section:not([data-transition]), +.reveal.fade .slides > section > section:not([data-transition]) { + -webkit-transform: none; + transform: none; + transition: opacity 0.5s; } + +.reveal.fade.overview .slides section, +.reveal.fade.overview .slides > section > section { + transition: none; } + +/********************************************* + * NO TRANSITION + *********************************************/ +.reveal .slides section[data-transition=none], +.reveal.none .slides section:not([data-transition]) { + -webkit-transform: none; + transform: none; + transition: none; } + +/********************************************* + * PAUSED MODE + *********************************************/ +.reveal .pause-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: black; + visibility: hidden; + opacity: 0; + z-index: 100; + transition: all 1s ease; } + +.reveal .pause-overlay .resume-button { + position: absolute; + bottom: 20px; + right: 20px; + color: #ccc; + border-radius: 2px; + padding: 6px 14px; + border: 2px solid #ccc; + font-size: 16px; + background: transparent; + cursor: pointer; } + .reveal .pause-overlay .resume-button:hover { + color: #fff; + border-color: #fff; } + +.reveal.paused .pause-overlay { + visibility: visible; + opacity: 1; } + +/********************************************* + * FALLBACK + *********************************************/ +.no-transforms { + overflow-y: auto; } + +.no-transforms .reveal { + overflow: visible; } + +.no-transforms .reveal .slides { + position: relative; + width: 80%; + max-width: 1280px; + height: auto; + top: 0; + margin: 0 auto; + text-align: center; } + +.no-transforms .reveal .controls, +.no-transforms .reveal .progress { + display: none; } + +.no-transforms .reveal .slides section { + display: block; + opacity: 1; + position: relative; + height: auto; + min-height: 0; + top: 0; + left: 0; + margin: 10vh 0; + margin: 70px 0; + -webkit-transform: none; + transform: none; } + +.reveal .no-transition, +.reveal .no-transition * { + transition: none !important; } + +/********************************************* + * PER-SLIDE BACKGROUNDS + *********************************************/ +.reveal .backgrounds { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + -webkit-perspective: 600px; + perspective: 600px; } + +.reveal .slide-background { + display: none; + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + visibility: hidden; + overflow: hidden; + background-color: rgba(0, 0, 0, 0); + transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +.reveal .slide-background-content { + position: absolute; + width: 100%; + height: 100%; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + +.reveal .slide-background.stack { + display: block; } + +.reveal .slide-background.present { + opacity: 1; + visibility: visible; + z-index: 2; } + +.print-pdf .reveal .slide-background { + opacity: 1 !important; + visibility: visible !important; } + +/* Video backgrounds */ +.reveal .slide-background video { + position: absolute; + width: 100%; + height: 100%; + max-width: none; + max-height: none; + top: 0; + left: 0; + -o-object-fit: cover; + object-fit: cover; } + +.reveal .slide-background[data-background-size="contain"] video { + -o-object-fit: contain; + object-fit: contain; } + +/* Immediate transition style */ +.reveal[data-background-transition=none] > .backgrounds .slide-background, +.reveal > .backgrounds .slide-background[data-background-transition=none] { + transition: none; } + +/* Slide */ +.reveal[data-background-transition=slide] > .backgrounds .slide-background, +.reveal > .backgrounds .slide-background[data-background-transition=slide] { + opacity: 1; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + +.reveal[data-background-transition=slide] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=slide] { + -webkit-transform: translate(-100%, 0); + transform: translate(-100%, 0); } + +.reveal[data-background-transition=slide] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=slide] { + -webkit-transform: translate(100%, 0); + transform: translate(100%, 0); } + +.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=slide] { + -webkit-transform: translate(0, -100%); + transform: translate(0, -100%); } + +.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=slide] { + -webkit-transform: translate(0, 100%); + transform: translate(0, 100%); } + +/* Convex */ +.reveal[data-background-transition=convex] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=convex] { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } + +.reveal[data-background-transition=convex] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=convex] { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } + +.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=convex] { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); } + +.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=convex] { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); } + +/* Concave */ +.reveal[data-background-transition=concave] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=concave] { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } + +.reveal[data-background-transition=concave] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=concave] { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } + +.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=concave] { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); } + +.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=concave] { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); } + +/* Zoom */ +.reveal[data-background-transition=zoom] > .backgrounds .slide-background, +.reveal > .backgrounds .slide-background[data-background-transition=zoom] { + transition-timing-function: ease; } + +.reveal[data-background-transition=zoom] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal[data-background-transition=zoom] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"] > .backgrounds .slide-background { + transition-duration: 400ms; } + +.reveal[data-transition-speed="slow"] > .backgrounds .slide-background { + transition-duration: 1200ms; } + +/********************************************* + * OVERVIEW + *********************************************/ +.reveal.overview { + -webkit-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; + -webkit-perspective: 700px; + perspective: 700px; } + .reveal.overview .slides { + -moz-transform-style: preserve-3d; } + .reveal.overview .slides section { + height: 100%; + top: 0 !important; + opacity: 1 !important; + overflow: hidden; + visibility: visible !important; + cursor: pointer; + box-sizing: border-box; } + .reveal.overview .slides section:hover, + .reveal.overview .slides section.present { + outline: 10px solid rgba(150, 150, 150, 0.4); + outline-offset: 10px; } + .reveal.overview .slides section .fragment { + opacity: 1; + transition: none; } + .reveal.overview .slides section:after, + .reveal.overview .slides section:before { + display: none !important; } + .reveal.overview .slides > section.stack { + padding: 0; + top: 0 !important; + background: none; + outline: none; + overflow: visible; } + .reveal.overview .backgrounds { + -webkit-perspective: inherit; + perspective: inherit; + -moz-transform-style: preserve-3d; } + .reveal.overview .backgrounds .slide-background { + opacity: 1; + visibility: visible; + outline: 10px solid rgba(150, 150, 150, 0.1); + outline-offset: 10px; } + .reveal.overview .backgrounds .slide-background.stack { + overflow: visible; } + +.reveal.overview .slides section, +.reveal.overview-deactivating .slides section { + transition: none; } + +.reveal.overview .backgrounds .slide-background, +.reveal.overview-deactivating .backgrounds .slide-background { + transition: none; } + +/********************************************* + * RTL SUPPORT + *********************************************/ +.reveal.rtl .slides, +.reveal.rtl .slides h1, +.reveal.rtl .slides h2, +.reveal.rtl .slides h3, +.reveal.rtl .slides h4, +.reveal.rtl .slides h5, +.reveal.rtl .slides h6 { + direction: rtl; + font-family: sans-serif; } + +.reveal.rtl pre, +.reveal.rtl code { + direction: ltr; } + +.reveal.rtl ol, +.reveal.rtl ul { + text-align: right; } + +.reveal.rtl .progress span { + float: right; } + +/********************************************* + * PARALLAX BACKGROUND + *********************************************/ +.reveal.has-parallax-background .backgrounds { + transition: all 0.8s ease; } + +/* Global transition speed settings */ +.reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds { + transition-duration: 400ms; } + +.reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds { + transition-duration: 1200ms; } + +/********************************************* + * OVERLAY FOR LINK PREVIEWS AND HELP + *********************************************/ +.reveal > .overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + background: rgba(0, 0, 0, 0.9); + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; } + +.reveal > .overlay.visible { + opacity: 1; + visibility: visible; } + +.reveal > .overlay .spinner { + position: absolute; + display: block; + top: 50%; + left: 50%; + width: 32px; + height: 32px; + margin: -16px 0 0 -16px; + z-index: 10; + background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D); + visibility: visible; + opacity: 0.6; + transition: all 0.3s ease; } + +.reveal > .overlay header { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 40px; + z-index: 2; + border-bottom: 1px solid #222; } + +.reveal > .overlay header a { + display: inline-block; + width: 40px; + height: 40px; + line-height: 36px; + padding: 0 10px; + float: right; + opacity: 0.6; + box-sizing: border-box; } + +.reveal > .overlay header a:hover { + opacity: 1; } + +.reveal > .overlay header a .icon { + display: inline-block; + width: 20px; + height: 20px; + background-position: 50% 50%; + background-size: 100%; + background-repeat: no-repeat; } + +.reveal > .overlay header a.close .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC); } + +.reveal > .overlay header a.external .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==); } + +.reveal > .overlay .viewport { + position: absolute; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + top: 40px; + right: 0; + bottom: 0; + left: 0; } + +.reveal > .overlay.overlay-preview .viewport iframe { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + border: 0; + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; } + +.reveal > .overlay.overlay-preview.loaded .viewport iframe { + opacity: 1; + visibility: visible; } + +.reveal > .overlay.overlay-preview.loaded .viewport-inner { + position: absolute; + z-index: -1; + left: 0; + top: 45%; + width: 100%; + text-align: center; + letter-spacing: normal; } + +.reveal > .overlay.overlay-preview .x-frame-error { + opacity: 0; + transition: opacity 0.3s ease 0.3s; } + +.reveal > .overlay.overlay-preview.loaded .x-frame-error { + opacity: 1; } + +.reveal > .overlay.overlay-preview.loaded .spinner { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +.reveal > .overlay.overlay-help .viewport { + overflow: auto; + color: #fff; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner { + width: 600px; + margin: auto; + padding: 20px 20px 80px 20px; + text-align: center; + letter-spacing: normal; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner .title { + font-size: 20px; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner table { + border: 1px solid #fff; + border-collapse: collapse; + font-size: 16px; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner table th, +.reveal > .overlay.overlay-help .viewport .viewport-inner table td { + width: 200px; + padding: 14px; + border: 1px solid #fff; + vertical-align: middle; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner table th { + padding-top: 20px; + padding-bottom: 20px; } + +/********************************************* + * PLAYBACK COMPONENT + *********************************************/ +.reveal .playback { + position: absolute; + left: 15px; + bottom: 20px; + z-index: 30; + cursor: pointer; + transition: all 400ms ease; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } + +.reveal.overview .playback { + opacity: 0; + visibility: hidden; } + +/********************************************* + * CODE HIGHLGIHTING + *********************************************/ +.reveal .hljs table { + margin: initial; } + +.reveal .hljs-ln-code, +.reveal .hljs-ln-numbers { + padding: 0; + border: 0; } + +.reveal .hljs-ln-numbers { + opacity: 0.6; + padding-right: 0.75em; + text-align: right; + vertical-align: top; } + +.reveal .hljs.has-highlights tr:not(.highlight-line) { + opacity: 0.4; } + +.reveal .hljs:not(:first-child).fragment { + position: absolute; + top: 0; + left: 0; + width: 100%; + box-sizing: border-box; } + +/********************************************* + * ROLLING LINKS + *********************************************/ +.reveal .roll { + display: inline-block; + line-height: 1.2; + overflow: hidden; + vertical-align: top; + -webkit-perspective: 400px; + perspective: 400px; + -webkit-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; } + +.reveal .roll:hover { + background: none; + text-shadow: none; } + +.reveal .roll span { + display: block; + position: relative; + padding: 0 2px; + pointer-events: none; + transition: all 400ms ease; + -webkit-transform-origin: 50% 0%; + transform-origin: 50% 0%; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + +.reveal .roll:hover span { + background: rgba(0, 0, 0, 0.5); + -webkit-transform: translate3d(0px, 0px, -45px) rotateX(90deg); + transform: translate3d(0px, 0px, -45px) rotateX(90deg); } + +.reveal .roll span:after { + content: attr(data-title); + display: block; + position: absolute; + left: 0; + top: 0; + padding: 0 2px; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform-origin: 50% 0%; + transform-origin: 50% 0%; + -webkit-transform: translate3d(0px, 110%, 0px) rotateX(-90deg); + transform: translate3d(0px, 110%, 0px) rotateX(-90deg); } + +/********************************************* + * SPEAKER NOTES + *********************************************/ +.reveal aside.notes { + display: none; } + +.reveal .speaker-notes { + display: none; + position: absolute; + width: 33.3333333333%; + height: 100%; + top: 0; + left: 100%; + padding: 14px 18px 14px 18px; + z-index: 1; + font-size: 18px; + line-height: 1.4; + border: 1px solid rgba(0, 0, 0, 0.05); + color: #222; + background-color: #f5f5f5; + overflow: auto; + box-sizing: border-box; + text-align: left; + font-family: Helvetica, sans-serif; + -webkit-overflow-scrolling: touch; } + .reveal .speaker-notes .notes-placeholder { + color: #ccc; + font-style: italic; } + .reveal .speaker-notes:focus { + outline: none; } + .reveal .speaker-notes:before { + content: 'Speaker notes'; + display: block; + margin-bottom: 10px; + opacity: 0.5; } + +.reveal.show-notes { + max-width: 75%; + overflow: visible; } + +.reveal.show-notes .speaker-notes { + display: block; } + +@media screen and (min-width: 1600px) { + .reveal .speaker-notes { + font-size: 20px; } } + +@media screen and (max-width: 1024px) { + .reveal.show-notes { + border-left: 0; + max-width: none; + max-height: 70%; + max-height: 70vh; + overflow: visible; } + .reveal.show-notes .speaker-notes { + top: 100%; + left: 0; + width: 100%; + height: 42.8571428571%; + height: 30vh; + border: 0; } } + +@media screen and (max-width: 600px) { + .reveal.show-notes { + max-height: 60%; + max-height: 60vh; } + .reveal.show-notes .speaker-notes { + top: 100%; + height: 66.6666666667%; + height: 40vh; } + .reveal .speaker-notes { + font-size: 14px; } } + +/********************************************* + * ZOOM PLUGIN + *********************************************/ +.zoomed .reveal *, +.zoomed .reveal *:before, +.zoomed .reveal *:after { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; } + +.zoomed .reveal .progress, +.zoomed .reveal .controls { + opacity: 0; } + +.zoomed .reveal .roll span { + background: none; } + +.zoomed .reveal .roll span:after { + visibility: hidden; } diff --git a/CreatingReliableSoftwareCpp/css/reveal.scss b/CreatingReliableSoftwareCpp/css/reveal.scss new file mode 100644 index 0000000..ab11f32 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/reveal.scss @@ -0,0 +1,1777 @@ +/*! + * reveal.js + * http://revealjs.com + * MIT licensed + * + * Copyright (C) 2020 Hakim El Hattab, http://hakim.se + */ + + +/********************************************* + * GLOBAL STYLES + *********************************************/ + +html { + width: 100%; + height: 100%; + height: 100vh; + height: calc( var(--vh, 1vh) * 100 ); + overflow: hidden; +} + +body { + height: 100%; + overflow: hidden; + position: relative; + line-height: 1; + margin: 0; + + background-color: #fff; + color: #000; +} + + +/********************************************* + * VIEW FRAGMENTS + *********************************************/ + +.reveal .slides section .fragment { + opacity: 0; + visibility: hidden; + transition: all .2s ease; + + &.visible { + opacity: 1; + visibility: inherit; + } +} + +.reveal .slides section .fragment.grow { + opacity: 1; + visibility: inherit; + + &.visible { + transform: scale( 1.3 ); + } +} + +.reveal .slides section .fragment.shrink { + opacity: 1; + visibility: inherit; + + &.visible { + transform: scale( 0.7 ); + } +} + +.reveal .slides section .fragment.zoom-in { + transform: scale( 0.1 ); + + &.visible { + transform: none; + } +} + +.reveal .slides section .fragment.fade-out { + opacity: 1; + visibility: inherit; + + &.visible { + opacity: 0; + visibility: hidden; + } +} + +.reveal .slides section .fragment.semi-fade-out { + opacity: 1; + visibility: inherit; + + &.visible { + opacity: 0.5; + visibility: inherit; + } +} + +.reveal .slides section .fragment.strike { + opacity: 1; + visibility: inherit; + + &.visible { + text-decoration: line-through; + } +} + +.reveal .slides section .fragment.fade-up { + transform: translate(0, 40px); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-down { + transform: translate(0, -40px); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-right { + transform: translate(-40px, 0); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-left { + transform: translate(40px, 0); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-in-then-out, +.reveal .slides section .fragment.current-visible { + opacity: 0; + visibility: hidden; + + &.current-fragment { + opacity: 1; + visibility: inherit; + } +} + +.reveal .slides section .fragment.fade-in-then-semi-out { + opacity: 0; + visibility: hidden; + + &.visible { + opacity: 0.5; + visibility: inherit; + } + + &.current-fragment { + opacity: 1; + visibility: inherit; + } +} + +.reveal .slides section .fragment.highlight-red, +.reveal .slides section .fragment.highlight-current-red, +.reveal .slides section .fragment.highlight-green, +.reveal .slides section .fragment.highlight-current-green, +.reveal .slides section .fragment.highlight-blue, +.reveal .slides section .fragment.highlight-current-blue { + opacity: 1; + visibility: inherit; +} + .reveal .slides section .fragment.highlight-red.visible { + color: #ff2c2d + } + .reveal .slides section .fragment.highlight-green.visible { + color: #17ff2e; + } + .reveal .slides section .fragment.highlight-blue.visible { + color: #1b91ff; + } + +.reveal .slides section .fragment.highlight-current-red.current-fragment { + color: #ff2c2d +} +.reveal .slides section .fragment.highlight-current-green.current-fragment { + color: #17ff2e; +} +.reveal .slides section .fragment.highlight-current-blue.current-fragment { + color: #1b91ff; +} + + +/********************************************* + * DEFAULT ELEMENT STYLES + *********************************************/ + +/* Fixes issue in Chrome where italic fonts did not appear when printing to PDF */ +.reveal:after { + content: ''; + font-style: italic; +} + +.reveal iframe { + z-index: 1; +} + +/** Prevents layering issues in certain browser/transition combinations */ +.reveal a { + position: relative; +} + +.reveal .stretch { + max-width: none; + max-height: none; +} + +.reveal pre.stretch code { + height: 100%; + max-height: 100%; + box-sizing: border-box; +} + + +/********************************************* + * CONTROLS + *********************************************/ + +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% {transform: translateX(0);} + 20% {transform: translateX(10px);} + 30% {transform: translateX(-5px);} +} + +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% {transform: translateY(0);} + 20% {transform: translateY(10px);} + 30% {transform: translateY(-5px);} +} + +$controlArrowSize: 3.6em; +$controlArrowSpacing: 1.4em; +$controlArrowLength: 2.6em; +$controlArrowThickness: 0.5em; +$controlsArrowAngle: 45deg; +$controlsArrowAngleHover: 40deg; +$controlsArrowAngleActive: 36deg; + +@mixin controlsArrowTransform( $angle ) { + &:before { + transform: translateX(($controlArrowSize - $controlArrowLength)/2) translateY(($controlArrowSize - $controlArrowThickness)/2) rotate( $angle ); + } + + &:after { + transform: translateX(($controlArrowSize - $controlArrowLength)/2) translateY(($controlArrowSize - $controlArrowThickness)/2) rotate( -$angle ); + } +} + +.reveal .controls { + $spacing: 12px; + + display: none; + position: absolute; + top: auto; + bottom: $spacing; + right: $spacing; + left: auto; + z-index: 11; + color: #000; + pointer-events: none; + font-size: 10px; + + button { + position: absolute; + padding: 0; + background-color: transparent; + border: 0; + outline: 0; + cursor: pointer; + color: currentColor; + transform: scale(.9999); + transition: color 0.2s ease, + opacity 0.2s ease, + transform 0.2s ease; + z-index: 2; // above slides + pointer-events: auto; + font-size: inherit; + + visibility: hidden; + opacity: 0; + + -webkit-appearance: none; + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); + } + + .controls-arrow:before, + .controls-arrow:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: $controlArrowLength; + height: $controlArrowThickness; + border-radius: $controlArrowThickness/2; + background-color: currentColor; + + transition: all 0.15s ease, background-color 0.8s ease; + transform-origin: floor(($controlArrowThickness/2)*10)/10 50%; + will-change: transform; + } + + .controls-arrow { + position: relative; + width: $controlArrowSize; + height: $controlArrowSize; + + @include controlsArrowTransform( $controlsArrowAngle ); + + &:hover { + @include controlsArrowTransform( $controlsArrowAngleHover ); + } + + &:active { + @include controlsArrowTransform( $controlsArrowAngleActive ); + } + } + + .navigate-left { + right: $controlArrowSize + $controlArrowSpacing*2; + bottom: $controlArrowSpacing + $controlArrowSize/2; + transform: translateX( -10px ); + } + + .navigate-right { + right: 0; + bottom: $controlArrowSpacing + $controlArrowSize/2; + transform: translateX( 10px ); + + .controls-arrow { + transform: rotate( 180deg ); + } + + &.highlight { + animation: bounce-right 2s 50 both ease-out; + } + } + + .navigate-up { + right: $controlArrowSpacing + $controlArrowSize/2; + bottom: $controlArrowSpacing*2 + $controlArrowSize; + transform: translateY( -10px ); + + .controls-arrow { + transform: rotate( 90deg ); + } + } + + .navigate-down { + right: $controlArrowSpacing + $controlArrowSize/2; + bottom: -$controlArrowSpacing; + padding-bottom: $controlArrowSpacing; + transform: translateY( 10px ); + + .controls-arrow { + transform: rotate( -90deg ); + } + + &.highlight { + animation: bounce-down 2s 50 both ease-out; + } + } + + // Back arrow style: "faded": + // Deemphasize backwards navigation arrows in favor of drawing + // attention to forwards navigation + &[data-controls-back-arrows="faded"] .navigate-left.enabled, + &[data-controls-back-arrows="faded"] .navigate-up.enabled { + opacity: 0.3; + + &:hover { + opacity: 1; + } + } + + // Back arrow style: "hidden": + // Never show arrows for backwards navigation + &[data-controls-back-arrows="hidden"] .navigate-left.enabled, + &[data-controls-back-arrows="hidden"] .navigate-up.enabled { + opacity: 0; + visibility: hidden; + } + + // Any control button that can be clicked is "enabled" + .enabled { + visibility: visible; + opacity: 0.9; + cursor: pointer; + transform: none; + } + + // Any control button that leads to showing or hiding + // a fragment + .enabled.fragmented { + opacity: 0.5; + } + + .enabled:hover, + .enabled.fragmented:hover { + opacity: 1; + } +} + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-up, +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-down { + display: none; +} + +// Adjust the layout when there are no vertical slides +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-left, +.reveal:not(.has-vertical-slides) .controls .navigate-left { + bottom: $controlArrowSpacing; + right: 0.5em + $controlArrowSpacing + $controlArrowSize; +} + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-right, +.reveal:not(.has-vertical-slides) .controls .navigate-right { + bottom: $controlArrowSpacing; + right: 0.5em; +} + +// Adjust the layout when there are no horizontal slides +.reveal:not(.has-horizontal-slides) .controls .navigate-up { + right: $controlArrowSpacing; + bottom: $controlArrowSpacing + $controlArrowSize; +} +.reveal:not(.has-horizontal-slides) .controls .navigate-down { + right: $controlArrowSpacing; + bottom: 0.5em; +} + +// Invert arrows based on background color +.reveal.has-dark-background .controls { + color: #fff; +} +.reveal.has-light-background .controls { + color: #000; +} + +// Disable active states on touch devices +.reveal.no-hover .controls .controls-arrow:hover, +.reveal.no-hover .controls .controls-arrow:active { + @include controlsArrowTransform( $controlsArrowAngle ); +} + +// Edge aligned controls layout +@media screen and (min-width: 500px) { + + $spacing: 0.8em; + + .reveal .controls[data-controls-layout="edges"] { + & { + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + .navigate-left, + .navigate-right, + .navigate-up, + .navigate-down { + bottom: auto; + right: auto; + } + + .navigate-left { + top: 50%; + left: $spacing; + margin-top: -$controlArrowSize/2; + } + + .navigate-right { + top: 50%; + right: $spacing; + margin-top: -$controlArrowSize/2; + } + + .navigate-up { + top: $spacing; + left: 50%; + margin-left: -$controlArrowSize/2; + } + + .navigate-down { + bottom: $spacing - $controlArrowSpacing + 0.3em; + left: 50%; + margin-left: -$controlArrowSize/2; + } + } + +} + + +/********************************************* + * PROGRESS BAR + *********************************************/ + +.reveal .progress { + position: absolute; + display: none; + height: 3px; + width: 100%; + bottom: 0; + left: 0; + z-index: 10; + + background-color: rgba( 0, 0, 0, 0.2 ); + color: #fff; +} + .reveal .progress:after { + content: ''; + display: block; + position: absolute; + height: 10px; + width: 100%; + top: -10px; + } + .reveal .progress span { + display: block; + height: 100%; + width: 0px; + + background-color: currentColor; + transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + } + +/********************************************* + * SLIDE NUMBER + *********************************************/ + +.reveal .slide-number { + position: absolute; + display: block; + right: 8px; + bottom: 8px; + z-index: 31; + font-family: Helvetica, sans-serif; + font-size: 12px; + line-height: 1; + color: #fff; + background-color: rgba( 0, 0, 0, 0.4 ); + padding: 5px; +} + +.reveal .slide-number a { + color: currentColor; +} + +.reveal .slide-number-delimiter { + margin: 0 3px; +} + +/********************************************* + * SLIDES + *********************************************/ + +.reveal { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + touch-action: pinch-zoom; +} + +.reveal .slides { + position: absolute; + width: 100%; + height: 100%; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + pointer-events: none; + + overflow: visible; + z-index: 1; + text-align: center; + perspective: 600px; + perspective-origin: 50% 40%; +} + +.reveal .slides>section { + perspective: 600px; +} + +.reveal .slides>section, +.reveal .slides>section>section { + display: none; + position: absolute; + width: 100%; + padding: 20px 0px; + pointer-events: auto; + + z-index: 10; + transform-style: flat; + transition: transform-origin 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), + transform 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), + visibility 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), + opacity 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); +} + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"] .slides section { + transition-duration: 400ms; +} +.reveal[data-transition-speed="slow"] .slides section { + transition-duration: 1200ms; +} + +/* Slide-specific transition speed overrides */ +.reveal .slides section[data-transition-speed="fast"] { + transition-duration: 400ms; +} +.reveal .slides section[data-transition-speed="slow"] { + transition-duration: 1200ms; +} + +.reveal .slides>section.stack { + padding-top: 0; + padding-bottom: 0; + pointer-events: none; + height: 100%; +} + +.reveal .slides>section.present, +.reveal .slides>section>section.present { + display: block; + z-index: 11; + opacity: 1; +} + +.reveal .slides>section:empty, +.reveal .slides>section>section:empty, +.reveal .slides>section[data-background-interactive], +.reveal .slides>section>section[data-background-interactive] { + pointer-events: none; +} + +.reveal.center, +.reveal.center .slides, +.reveal.center .slides section { + min-height: 0 !important; +} + +/* Don't allow interaction with invisible slides */ +.reveal .slides>section.future, +.reveal .slides>section>section.future, +.reveal .slides>section.past, +.reveal .slides>section>section.past { + pointer-events: none; +} + +.reveal.overview .slides>section, +.reveal.overview .slides>section>section { + pointer-events: auto; +} + +.reveal .slides>section.past, +.reveal .slides>section.future, +.reveal .slides>section>section.past, +.reveal .slides>section>section.future { + opacity: 0; +} + + +/********************************************* + * Mixins for readability of transitions + *********************************************/ + +@mixin transition-global($style) { + .reveal .slides section[data-transition=#{$style}], + .reveal.#{$style} .slides section:not([data-transition]) { + @content; + } +} +@mixin transition-stack($style) { + .reveal .slides section[data-transition=#{$style}].stack, + .reveal.#{$style} .slides section.stack { + @content; + } +} +@mixin transition-horizontal-past($style) { + .reveal .slides>section[data-transition=#{$style}].past, + .reveal .slides>section[data-transition~=#{$style}-out].past, + .reveal.#{$style} .slides>section:not([data-transition]).past { + @content; + } +} +@mixin transition-horizontal-future($style) { + .reveal .slides>section[data-transition=#{$style}].future, + .reveal .slides>section[data-transition~=#{$style}-in].future, + .reveal.#{$style} .slides>section:not([data-transition]).future { + @content; + } +} + +@mixin transition-vertical-past($style) { + .reveal .slides>section>section[data-transition=#{$style}].past, + .reveal .slides>section>section[data-transition~=#{$style}-out].past, + .reveal.#{$style} .slides>section>section:not([data-transition]).past { + @content; + } +} +@mixin transition-vertical-future($style) { + .reveal .slides>section>section[data-transition=#{$style}].future, + .reveal .slides>section>section[data-transition~=#{$style}-in].future, + .reveal.#{$style} .slides>section>section:not([data-transition]).future { + @content; + } +} + +/********************************************* + * SLIDE TRANSITION + * Aliased 'linear' for backwards compatibility + *********************************************/ + +@each $stylename in slide, linear { + .reveal.#{$stylename} section { + backface-visibility: hidden; + } + @include transition-horizontal-past(#{$stylename}) { + transform: translate(-150%, 0); + } + @include transition-horizontal-future(#{$stylename}) { + transform: translate(150%, 0); + } + @include transition-vertical-past(#{$stylename}) { + transform: translate(0, -150%); + } + @include transition-vertical-future(#{$stylename}) { + transform: translate(0, 150%); + } +} + +/********************************************* + * CONVEX TRANSITION + * Aliased 'default' for backwards compatibility + *********************************************/ + +@each $stylename in default, convex { + @include transition-stack(#{$stylename}) { + transform-style: preserve-3d; + } + + @include transition-horizontal-past(#{$stylename}) { + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + } + @include transition-horizontal-future(#{$stylename}) { + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + } + @include transition-vertical-past(#{$stylename}) { + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + } + @include transition-vertical-future(#{$stylename}) { + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + } +} + +/********************************************* + * CONCAVE TRANSITION + *********************************************/ + +@include transition-stack(concave) { + transform-style: preserve-3d; +} + +@include transition-horizontal-past(concave) { + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); +} +@include transition-horizontal-future(concave) { + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); +} +@include transition-vertical-past(concave) { + transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); +} +@include transition-vertical-future(concave) { + transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); +} + + +/********************************************* + * ZOOM TRANSITION + *********************************************/ + +@include transition-global(zoom) { + transition-timing-function: ease; +} +@include transition-horizontal-past(zoom) { + visibility: hidden; + transform: scale(16); +} +@include transition-horizontal-future(zoom) { + visibility: hidden; + transform: scale(0.2); +} +@include transition-vertical-past(zoom) { + transform: scale(16); +} +@include transition-vertical-future(zoom) { + transform: scale(0.2); +} + + +/********************************************* + * CUBE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ + +.reveal.cube .slides { + perspective: 1300px; +} + +.reveal.cube .slides section { + padding: 30px; + min-height: 700px; + backface-visibility: hidden; + box-sizing: border-box; + transform-style: preserve-3d; +} + .reveal.center.cube .slides section { + min-height: 0; + } + .reveal.cube .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0,0,0,0.1); + border-radius: 4px; + transform: translateZ( -20px ); + } + .reveal.cube .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0,0,0,0.2); + transform: translateZ(-90px) rotateX( 65deg ); + } + +.reveal.cube .slides>section.stack { + padding: 0; + background: none; +} + +.reveal.cube .slides>section.past { + transform-origin: 100% 0%; + transform: translate3d(-100%, 0, 0) rotateY(-90deg); +} + +.reveal.cube .slides>section.future { + transform-origin: 0% 0%; + transform: translate3d(100%, 0, 0) rotateY(90deg); +} + +.reveal.cube .slides>section>section.past { + transform-origin: 0% 100%; + transform: translate3d(0, -100%, 0) rotateX(90deg); +} + +.reveal.cube .slides>section>section.future { + transform-origin: 0% 0%; + transform: translate3d(0, 100%, 0) rotateX(-90deg); +} + + +/********************************************* + * PAGE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ + +.reveal.page .slides { + perspective-origin: 0% 50%; + perspective: 3000px; +} + +.reveal.page .slides section { + padding: 30px; + min-height: 700px; + box-sizing: border-box; + transform-style: preserve-3d; +} + .reveal.page .slides section.past { + z-index: 12; + } + .reveal.page .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0,0,0,0.1); + transform: translateZ( -20px ); + } + .reveal.page .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0,0,0,0.2); + + -webkit-transform: translateZ(-90px) rotateX( 65deg ); + } + +.reveal.page .slides>section.stack { + padding: 0; + background: none; +} + +.reveal.page .slides>section.past { + transform-origin: 0% 0%; + transform: translate3d(-40%, 0, 0) rotateY(-80deg); +} + +.reveal.page .slides>section.future { + transform-origin: 100% 0%; + transform: translate3d(0, 0, 0); +} + +.reveal.page .slides>section>section.past { + transform-origin: 0% 0%; + transform: translate3d(0, -40%, 0) rotateX(80deg); +} + +.reveal.page .slides>section>section.future { + transform-origin: 0% 100%; + transform: translate3d(0, 0, 0); +} + + +/********************************************* + * FADE TRANSITION + *********************************************/ + +.reveal .slides section[data-transition=fade], +.reveal.fade .slides section:not([data-transition]), +.reveal.fade .slides>section>section:not([data-transition]) { + transform: none; + transition: opacity 0.5s; +} + + +.reveal.fade.overview .slides section, +.reveal.fade.overview .slides>section>section { + transition: none; +} + + +/********************************************* + * NO TRANSITION + *********************************************/ + +@include transition-global(none) { + transform: none; + transition: none; +} + + +/********************************************* + * PAUSED MODE + *********************************************/ + +.reveal .pause-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: black; + visibility: hidden; + opacity: 0; + z-index: 100; + transition: all 1s ease; +} + +.reveal .pause-overlay .resume-button { + position: absolute; + bottom: 20px; + right: 20px; + color: #ccc; + border-radius: 2px; + padding: 6px 14px; + border: 2px solid #ccc; + font-size: 16px; + background: transparent; + cursor: pointer; + + &:hover { + color: #fff; + border-color: #fff; + } +} + +.reveal.paused .pause-overlay { + visibility: visible; + opacity: 1; +} + + +/********************************************* + * FALLBACK + *********************************************/ + +.no-transforms { + overflow-y: auto; +} + +.no-transforms .reveal { + overflow: visible; +} + +.no-transforms .reveal .slides { + position: relative; + width: 80%; + max-width: 1280px; + height: auto; + top: 0; + margin: 0 auto; + text-align: center; +} + +.no-transforms .reveal .controls, +.no-transforms .reveal .progress { + display: none; +} + +.no-transforms .reveal .slides section { + display: block; + opacity: 1; + position: relative; + height: auto; + min-height: 0; + top: 0; + left: 0; + margin: 10vh 0; + margin: 70px 0; + transform: none; +} + +.reveal .no-transition, +.reveal .no-transition * { + transition: none !important; +} + + +/********************************************* + * PER-SLIDE BACKGROUNDS + *********************************************/ + +.reveal .backgrounds { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + perspective: 600px; +} + .reveal .slide-background { + display: none; + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + visibility: hidden; + overflow: hidden; + + background-color: rgba( 0, 0, 0, 0 ); + + transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + } + + .reveal .slide-background-content { + position: absolute; + width: 100%; + height: 100%; + + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + } + + .reveal .slide-background.stack { + display: block; + } + + .reveal .slide-background.present { + opacity: 1; + visibility: visible; + z-index: 2; + } + + .print-pdf .reveal .slide-background { + opacity: 1 !important; + visibility: visible !important; + } + +/* Video backgrounds */ +.reveal .slide-background video { + position: absolute; + width: 100%; + height: 100%; + max-width: none; + max-height: none; + top: 0; + left: 0; + object-fit: cover; +} + .reveal .slide-background[data-background-size="contain"] video { + object-fit: contain; + } + +/* Immediate transition style */ +.reveal[data-background-transition=none]>.backgrounds .slide-background, +.reveal>.backgrounds .slide-background[data-background-transition=none] { + transition: none; +} + +/* Slide */ +.reveal[data-background-transition=slide]>.backgrounds .slide-background, +.reveal>.backgrounds .slide-background[data-background-transition=slide] { + opacity: 1; + backface-visibility: hidden; +} + .reveal[data-background-transition=slide]>.backgrounds .slide-background.past, + .reveal>.backgrounds .slide-background.past[data-background-transition=slide] { + transform: translate(-100%, 0); + } + .reveal[data-background-transition=slide]>.backgrounds .slide-background.future, + .reveal>.backgrounds .slide-background.future[data-background-transition=slide] { + transform: translate(100%, 0); + } + + .reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.past, + .reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=slide] { + transform: translate(0, -100%); + } + .reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.future, + .reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=slide] { + transform: translate(0, 100%); + } + + +/* Convex */ +.reveal[data-background-transition=convex]>.backgrounds .slide-background.past, +.reveal>.backgrounds .slide-background.past[data-background-transition=convex] { + opacity: 0; + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); +} +.reveal[data-background-transition=convex]>.backgrounds .slide-background.future, +.reveal>.backgrounds .slide-background.future[data-background-transition=convex] { + opacity: 0; + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); +} + +.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.past, +.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=convex] { + opacity: 0; + transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); +} +.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.future, +.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=convex] { + opacity: 0; + transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); +} + + +/* Concave */ +.reveal[data-background-transition=concave]>.backgrounds .slide-background.past, +.reveal>.backgrounds .slide-background.past[data-background-transition=concave] { + opacity: 0; + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); +} +.reveal[data-background-transition=concave]>.backgrounds .slide-background.future, +.reveal>.backgrounds .slide-background.future[data-background-transition=concave] { + opacity: 0; + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); +} + +.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.past, +.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=concave] { + opacity: 0; + transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); +} +.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.future, +.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=concave] { + opacity: 0; + transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); +} + +/* Zoom */ +.reveal[data-background-transition=zoom]>.backgrounds .slide-background, +.reveal>.backgrounds .slide-background[data-background-transition=zoom] { + transition-timing-function: ease; +} + +.reveal[data-background-transition=zoom]>.backgrounds .slide-background.past, +.reveal>.backgrounds .slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(16); +} +.reveal[data-background-transition=zoom]>.backgrounds .slide-background.future, +.reveal>.backgrounds .slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(0.2); +} + +.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.past, +.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(16); +} +.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.future, +.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(0.2); +} + + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"]>.backgrounds .slide-background { + transition-duration: 400ms; +} +.reveal[data-transition-speed="slow"]>.backgrounds .slide-background { + transition-duration: 1200ms; +} + + +/********************************************* + * OVERVIEW + *********************************************/ + +.reveal.overview { + perspective-origin: 50% 50%; + perspective: 700px; + + .slides { + // Fixes overview rendering errors in FF48+, not applied to + // other browsers since it degrades performance + -moz-transform-style: preserve-3d; + } + + .slides section { + height: 100%; + top: 0 !important; + opacity: 1 !important; + overflow: hidden; + visibility: visible !important; + cursor: pointer; + box-sizing: border-box; + } + .slides section:hover, + .slides section.present { + outline: 10px solid rgba(150,150,150,0.4); + outline-offset: 10px; + } + .slides section .fragment { + opacity: 1; + transition: none; + } + .slides section:after, + .slides section:before { + display: none !important; + } + .slides>section.stack { + padding: 0; + top: 0 !important; + background: none; + outline: none; + overflow: visible; + } + + .backgrounds { + perspective: inherit; + + // Fixes overview rendering errors in FF48+, not applied to + // other browsers since it degrades performance + -moz-transform-style: preserve-3d; + } + + .backgrounds .slide-background { + opacity: 1; + visibility: visible; + + // This can't be applied to the slide itself in Safari + outline: 10px solid rgba(150,150,150,0.1); + outline-offset: 10px; + } + + .backgrounds .slide-background.stack { + overflow: visible; + } +} + +// Disable transitions transitions while we're activating +// or deactivating the overview mode. +.reveal.overview .slides section, +.reveal.overview-deactivating .slides section { + transition: none; +} + +.reveal.overview .backgrounds .slide-background, +.reveal.overview-deactivating .backgrounds .slide-background { + transition: none; +} + + +/********************************************* + * RTL SUPPORT + *********************************************/ + +.reveal.rtl .slides, +.reveal.rtl .slides h1, +.reveal.rtl .slides h2, +.reveal.rtl .slides h3, +.reveal.rtl .slides h4, +.reveal.rtl .slides h5, +.reveal.rtl .slides h6 { + direction: rtl; + font-family: sans-serif; +} + +.reveal.rtl pre, +.reveal.rtl code { + direction: ltr; +} + +.reveal.rtl ol, +.reveal.rtl ul { + text-align: right; +} + +.reveal.rtl .progress span { + float: right +} + +/********************************************* + * PARALLAX BACKGROUND + *********************************************/ + +.reveal.has-parallax-background .backgrounds { + transition: all 0.8s ease; +} + +/* Global transition speed settings */ +.reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds { + transition-duration: 400ms; +} +.reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds { + transition-duration: 1200ms; +} + + +/********************************************* + * OVERLAY FOR LINK PREVIEWS AND HELP + *********************************************/ + +.reveal > .overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + background: rgba( 0, 0, 0, 0.9 ); + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; +} + .reveal > .overlay.visible { + opacity: 1; + visibility: visible; + } + + .reveal > .overlay .spinner { + position: absolute; + display: block; + top: 50%; + left: 50%; + width: 32px; + height: 32px; + margin: -16px 0 0 -16px; + z-index: 10; + background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D); + + visibility: visible; + opacity: 0.6; + transition: all 0.3s ease; + } + + .reveal > .overlay header { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 40px; + z-index: 2; + border-bottom: 1px solid #222; + } + .reveal > .overlay header a { + display: inline-block; + width: 40px; + height: 40px; + line-height: 36px; + padding: 0 10px; + float: right; + opacity: 0.6; + + box-sizing: border-box; + } + .reveal > .overlay header a:hover { + opacity: 1; + } + .reveal > .overlay header a .icon { + display: inline-block; + width: 20px; + height: 20px; + + background-position: 50% 50%; + background-size: 100%; + background-repeat: no-repeat; + } + .reveal > .overlay header a.close .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC); + } + .reveal > .overlay header a.external .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==); + } + + .reveal > .overlay .viewport { + position: absolute; + display: flex; + top: 40px; + right: 0; + bottom: 0; + left: 0; + } + + .reveal > .overlay.overlay-preview .viewport iframe { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + border: 0; + + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; + } + + .reveal > .overlay.overlay-preview.loaded .viewport iframe { + opacity: 1; + visibility: visible; + } + + .reveal > .overlay.overlay-preview.loaded .viewport-inner { + position: absolute; + z-index: -1; + left: 0; + top: 45%; + width: 100%; + text-align: center; + letter-spacing: normal; + } + .reveal > .overlay.overlay-preview .x-frame-error { + opacity: 0; + transition: opacity 0.3s ease 0.3s; + } + .reveal > .overlay.overlay-preview.loaded .x-frame-error { + opacity: 1; + } + + .reveal > .overlay.overlay-preview.loaded .spinner { + opacity: 0; + visibility: hidden; + transform: scale(0.2); + } + + .reveal > .overlay.overlay-help .viewport { + overflow: auto; + color: #fff; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner { + width: 600px; + margin: auto; + padding: 20px 20px 80px 20px; + text-align: center; + letter-spacing: normal; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner .title { + font-size: 20px; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner table { + border: 1px solid #fff; + border-collapse: collapse; + font-size: 16px; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner table th, + .reveal > .overlay.overlay-help .viewport .viewport-inner table td { + width: 200px; + padding: 14px; + border: 1px solid #fff; + vertical-align: middle; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner table th { + padding-top: 20px; + padding-bottom: 20px; + } + + +/********************************************* + * PLAYBACK COMPONENT + *********************************************/ + +.reveal .playback { + position: absolute; + left: 15px; + bottom: 20px; + z-index: 30; + cursor: pointer; + transition: all 400ms ease; + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); +} + +.reveal.overview .playback { + opacity: 0; + visibility: hidden; +} + + +/********************************************* + * CODE HIGHLGIHTING + *********************************************/ + +.reveal .hljs table { + margin: initial; +} + +.reveal .hljs-ln-code, +.reveal .hljs-ln-numbers { + padding: 0; + border: 0; +} + +.reveal .hljs-ln-numbers { + opacity: 0.6; + padding-right: 0.75em; + text-align: right; + vertical-align: top; +} + +.reveal .hljs.has-highlights tr:not(.highlight-line) { + opacity: 0.4; +} + +.reveal .hljs:not(:first-child).fragment { + position: absolute; + top: 0; + left: 0; + width: 100%; + box-sizing: border-box; +} + + +/********************************************* + * ROLLING LINKS + *********************************************/ + +.reveal .roll { + display: inline-block; + line-height: 1.2; + overflow: hidden; + + vertical-align: top; + perspective: 400px; + perspective-origin: 50% 50%; +} + .reveal .roll:hover { + background: none; + text-shadow: none; + } +.reveal .roll span { + display: block; + position: relative; + padding: 0 2px; + + pointer-events: none; + transition: all 400ms ease; + transform-origin: 50% 0%; + transform-style: preserve-3d; + backface-visibility: hidden; +} + .reveal .roll:hover span { + background: rgba(0,0,0,0.5); + transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg ); + } +.reveal .roll span:after { + content: attr(data-title); + + display: block; + position: absolute; + left: 0; + top: 0; + padding: 0 2px; + backface-visibility: hidden; + transform-origin: 50% 0%; + transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg ); +} + + +/********************************************* + * SPEAKER NOTES + *********************************************/ + +$notesWidthPercent: 25%; + +// Hide on-page notes +.reveal aside.notes { + display: none; +} + +// An interface element that can optionally be used to show the +// speaker notes to all viewers, on top of the presentation +.reveal .speaker-notes { + display: none; + position: absolute; + width: $notesWidthPercent / (1-$notesWidthPercent/100) * 1%; + height: 100%; + top: 0; + left: 100%; + padding: 14px 18px 14px 18px; + z-index: 1; + font-size: 18px; + line-height: 1.4; + border: 1px solid rgba( 0, 0, 0, 0.05 ); + color: #222; + background-color: #f5f5f5; + overflow: auto; + box-sizing: border-box; + text-align: left; + font-family: Helvetica, sans-serif; + -webkit-overflow-scrolling: touch; + + .notes-placeholder { + color: #ccc; + font-style: italic; + } + + &:focus { + outline: none; + } + + &:before { + content: 'Speaker notes'; + display: block; + margin-bottom: 10px; + opacity: 0.5; + } +} + + +.reveal.show-notes { + max-width: 100% - $notesWidthPercent; + overflow: visible; +} + +.reveal.show-notes .speaker-notes { + display: block; +} + +@media screen and (min-width: 1600px) { + .reveal .speaker-notes { + font-size: 20px; + } +} + +@media screen and (max-width: 1024px) { + .reveal.show-notes { + border-left: 0; + max-width: none; + max-height: 70%; + max-height: 70vh; + overflow: visible; + } + + .reveal.show-notes .speaker-notes { + top: 100%; + left: 0; + width: 100%; + height: (30/0.7)*1%; + height: 30vh; + border: 0; + } +} + +@media screen and (max-width: 600px) { + .reveal.show-notes { + max-height: 60%; + max-height: 60vh; + } + + .reveal.show-notes .speaker-notes { + top: 100%; + height: (40/0.6)*1%; + height: 40vh; + } + + .reveal .speaker-notes { + font-size: 14px; + } +} + + +/********************************************* + * ZOOM PLUGIN + *********************************************/ + +.zoomed .reveal *, +.zoomed .reveal *:before, +.zoomed .reveal *:after { + backface-visibility: visible !important; +} + +.zoomed .reveal .progress, +.zoomed .reveal .controls { + opacity: 0; +} + +.zoomed .reveal .roll span { + background: none; +} + +.zoomed .reveal .roll span:after { + visibility: hidden; +} diff --git a/CreatingReliableSoftwareCpp/css/theme/README.md b/CreatingReliableSoftwareCpp/css/theme/README.md new file mode 100644 index 0000000..5ebe72a --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/README.md @@ -0,0 +1,21 @@ +## Dependencies + +Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment including the Grunt dependencies installed before proceeding: https://github.com/hakimel/reveal.js#full-setup + +## Creating a Theme + +To create your own theme, start by duplicating a ```.scss``` file in [/css/theme/source](https://github.com/hakimel/reveal.js/blob/master/css/theme/source). It will be automatically compiled by Grunt from Sass to CSS (see the [Gruntfile](https://github.com/hakimel/reveal.js/blob/master/gruntfile.js)) when you run `npm run build -- css-themes`. + +Each theme file does four things in the following order: + +1. **Include [/css/theme/template/mixins.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/mixins.scss)** +Shared utility functions. + +2. **Include [/css/theme/template/settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss)** +Declares a set of custom variables that the template file (step 4) expects. Can be overridden in step 3. + +3. **Override** +This is where you override the default theme. Either by specifying variables (see [settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss) for reference) or by adding any selectors and styles you please. + +4. **Include [/css/theme/template/theme.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/theme.scss)** +The template theme file which will generate final CSS output based on the currently defined variables. diff --git a/CreatingReliableSoftwareCpp/css/theme/beige.css b/CreatingReliableSoftwareCpp/css/theme/beige.css new file mode 100644 index 0000000..615dd6d --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/beige.css @@ -0,0 +1,277 @@ +/** + * Beige theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #f7f2d3; + background: -moz-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, white), color-stop(100%, #f7f2d3)); + background: -webkit-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: -o-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: -ms-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background-color: #f7f3de; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #333; } + +::selection { + color: #fff; + background: rgba(79, 64, 28, 0.99); + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: rgba(79, 64, 28, 0.99); + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #333; + font-family: "League Gothic", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2), 0 5px 10px rgba(0, 0, 0, 0.25), 0 20px 20px rgba(0, 0, 0, 0.15); } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #8b743d; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #c0a86e; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #564826; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #333; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #8b743d; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #8b743d; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #8b743d; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #f7f3de; } } diff --git a/CreatingReliableSoftwareCpp/css/theme/black.css b/CreatingReliableSoftwareCpp/css/theme/black.css new file mode 100644 index 0000000..7dd88c2 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/black.css @@ -0,0 +1,273 @@ +/** + * Black theme for reveal.js. This is the opposite of the 'white' theme. + * + * By Hakim El Hattab, http://hakim.se + */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); +section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { + color: #222; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #191919; + background-color: #191919; } + +.reveal { + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 42px; + font-weight: normal; + color: #fff; } + +::selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #fff; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-weight: 600; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 2.5em; } + +.reveal h2 { + font-size: 1.6em; } + +.reveal h3 { + font-size: 1.3em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #42affa; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #8dcffc; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #068de9; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #fff; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #42affa; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #42affa; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #42affa; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #191919; } } diff --git a/CreatingReliableSoftwareCpp/css/theme/blood.css b/CreatingReliableSoftwareCpp/css/theme/blood.css new file mode 100644 index 0000000..5cbd488 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/blood.css @@ -0,0 +1,296 @@ +/** + * Blood theme for reveal.js + * Author: Walther http://github.com/Walther + * + * Designed to be used with highlight.js theme + * "monokai_sublime.css" available from + * https://github.com/isagalaev/highlight.js/ + * + * For other themes, change $codeBackground accordingly. + * + */ +@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic); +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #222; + background-color: #222; } + +.reveal { + font-family: Ubuntu, "sans-serif"; + font-size: 40px; + font-weight: normal; + color: #eee; } + +::selection { + color: #fff; + background: #a23; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #a23; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #eee; + font-family: Ubuntu, "sans-serif"; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: 2px 2px 2px #222; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2), 0 5px 10px rgba(0, 0, 0, 0.25), 0 20px 20px rgba(0, 0, 0, 0.15); } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #a23; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #dd5566; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #6a1520; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #eee; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #a23; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #a23; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #a23; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #222; } } + +.reveal p { + font-weight: 300; + text-shadow: 1px 1px #222; } + +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + font-weight: 700; } + +.reveal p code { + background-color: #23241f; + display: inline-block; + border-radius: 7px; } + +.reveal small code { + vertical-align: baseline; } diff --git a/CreatingReliableSoftwareCpp/css/theme/coders.css b/CreatingReliableSoftwareCpp/css/theme/coders.css new file mode 100644 index 0000000..133b81e --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/coders.css @@ -0,0 +1,308 @@ +/** + * Coders School theme for reveal.js. + * + * By Łukasz "Lukin" Ziobroń + */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); +@import url(../../lib/font/rajdhani/rajdhani.css); +section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { + color: #000; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #cac7c7; + background-color: #cac7c7; + background-image: url(../../img/altkom_logo.png); + background-size: 12%; + background-repeat: no-repeat; + background-position: 2% 98%; } + +.reveal { + font-family: Rajdhani, "Source Sans Pro", Helvetica, sans-serif; + font-size: 40px; + font-weight: normal; + color: #000; + /* frame for head - streaming + background-image: url(../../img/talking_head_placeholder.png); + background-size: 320px 180px; + background-repeat: no-repeat; + background-position: 98% 2%; */ } + +::selection { + color: #000; + background: #cac7c7; + text-shadow: none; } + +::-moz-selection { + color: #000; + background: #cac7c7; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 10px 0 20px 0; + color: #000; + font-family: "Rajdhani", "Source Sans Pro", Helvetica, sans-serif; + font-weight: 600; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 2.5em; } + +.reveal h2 { + font-size: 1.6em; } + +.reveal h3 { + font-size: 1.3em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + font-size: 0.8em; + line-height: 1.3; + text-align: justify; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: justify; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; + font-size: 0.8em; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 95%; + margin: 20px auto; + text-align: left; + font-size: 0.6em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + /*box-shadow: 0px 15px 30px rgba(0, 0, 0, 0.15);*/ } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 15px; + overflow: auto; + max-height: 560px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #cf802a; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #ce904e; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #068de9; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #fff; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + background: none; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.05); + border-color: #ce904e; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #cf802a; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #cf802a; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #191919; } } + +/********************************************* + * OWN BOXES + *********************************************/ +.reveal .box { + position: absolute; + /*box-shadow: 0 1px 4px rgba(0,0,0,0.5), 0 5px 25px rgba(0,0,0,0.2);*/ + background-color: rgba(0, 0, 0, 0.7); + color: #fff; + padding: 20px; + margin: 20px 0; + font-size: 0.6em; + text-align: left; } + +/********************************************* + * MULTICOLUMN SUPPORT + *********************************************/ +.multicolumn { + display: flex; } +.col { + flex: 1; } diff --git a/CreatingReliableSoftwareCpp/css/theme/coders_white.css b/CreatingReliableSoftwareCpp/css/theme/coders_white.css new file mode 100644 index 0000000..79b423c --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/coders_white.css @@ -0,0 +1,294 @@ +/** + * Coders School theme for reveal.js. + * + * By Łukasz "Lukin" Ziobroń + */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); +section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { + color: #222; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #fff; + background-color: #fff; + background-image: url(../../img/altkom_logo.png); + background-size: 10%; + background-repeat: no-repeat; + background-position: 1% 98%; } + +.reveal { + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 40px; + font-weight: normal; + color: #222; } + +::selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #222; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-weight: 600; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 2.5em; } + +.reveal h2 { + font-size: 1.6em; } + +.reveal h3 { + font-size: 1.3em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + font-size: 0.8em; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; + font-size: 0.9em; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.6em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 15px 30px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 560px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #cf802a; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #ce904e; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #068de9; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #222; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + background: none; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.05); + border-color: #ce904e; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #cf802a; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #cf802a; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #191919; } } + +/********************************************* + * OWN BOXES + *********************************************/ +.reveal .box { + position: absolute; + box-shadow: 0 1px 4px rgba(0,0,0,0.5), 0 5px 25px rgba(0,0,0,0.2); + background-color: rgba(0, 0, 0, 0.7); + color: #fff; + padding: 20px; + margin: 20px 0; + font-size: 0.6em; + text-align: left; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/theme/league.css b/CreatingReliableSoftwareCpp/css/theme/league.css new file mode 100644 index 0000000..f8fba4d --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/league.css @@ -0,0 +1,279 @@ +/** + * League theme for reveal.js. + * + * This was the default theme pre-3.0.0. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #1c1e20; + background: -moz-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #555a5f), color-stop(100%, #1c1e20)); + background: -webkit-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: -o-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: -ms-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background-color: #2b2b2b; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #eee; } + +::selection { + color: #fff; + background: #FF5E99; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #FF5E99; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #eee; + font-family: "League Gothic", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2); + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2), 0 5px 10px rgba(0, 0, 0, 0.25), 0 20px 20px rgba(0, 0, 0, 0.15); } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #13DAEC; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #71e9f4; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #0d99a5; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #eee; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #13DAEC; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #13DAEC; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #13DAEC; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #2b2b2b; } } diff --git a/CreatingReliableSoftwareCpp/css/theme/moon.css b/CreatingReliableSoftwareCpp/css/theme/moon.css new file mode 100644 index 0000000..d18f526 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/moon.css @@ -0,0 +1,277 @@ +/** + * Solarized Dark theme for reveal.js. + * Author: Achim Staebler + */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +/** + * Solarized colors by Ethan Schoonover + */ +html * { + color-profile: sRGB; + rendering-intent: auto; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #002b36; + background-color: #002b36; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #93a1a1; } + +::selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #eee8d5; + font-family: "League Gothic", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #268bd2; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #78b9e6; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #1a6091; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #93a1a1; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #268bd2; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #268bd2; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #268bd2; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #002b36; } } diff --git a/CreatingReliableSoftwareCpp/css/theme/night.css b/CreatingReliableSoftwareCpp/css/theme/night.css new file mode 100644 index 0000000..f5ccb52 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/night.css @@ -0,0 +1,271 @@ +/** + * Black theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(https://fonts.googleapis.com/css?family=Montserrat:700); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic); +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #111; + background-color: #111; } + +.reveal { + font-family: "Open Sans", sans-serif; + font-size: 40px; + font-weight: normal; + color: #eee; } + +::selection { + color: #fff; + background: #e7ad52; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #e7ad52; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #eee; + font-family: "Montserrat", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: -0.03em; + text-transform: none; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #e7ad52; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #f3d7ac; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #d08a1d; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #eee; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #e7ad52; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #e7ad52; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #e7ad52; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #111; } } diff --git a/CreatingReliableSoftwareCpp/css/theme/serif.css b/CreatingReliableSoftwareCpp/css/theme/serif.css new file mode 100644 index 0000000..6514a6f --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/serif.css @@ -0,0 +1,273 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is brown. + * + * This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed. + */ +.reveal a { + line-height: 1.3em; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #F0F1EB; + background-color: #F0F1EB; } + +.reveal { + font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif; + font-size: 40px; + font-weight: normal; + color: #000; } + +::selection { + color: #fff; + background: #26351C; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #26351C; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #383D3D; + font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: none; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #51483D; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #8b7c69; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #25211c; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #000; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #51483D; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #51483D; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #51483D; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #F0F1EB; } } diff --git a/CreatingReliableSoftwareCpp/css/theme/simple.css b/CreatingReliableSoftwareCpp/css/theme/simple.css new file mode 100644 index 0000000..a7a29a6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/simple.css @@ -0,0 +1,276 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is darkblue. + * + * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed. + * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { + color: #fff; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #fff; + background-color: #fff; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #000; } + +::selection { + color: #fff; + background: rgba(0, 0, 0, 0.99); + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: rgba(0, 0, 0, 0.99); + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #000; + font-family: "News Cycle", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: none; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #00008B; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #0000f1; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #00003f; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #000; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #00008B; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #00008B; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #00008B; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #fff; } } diff --git a/CreatingReliableSoftwareCpp/css/theme/sky.css b/CreatingReliableSoftwareCpp/css/theme/sky.css new file mode 100644 index 0000000..d8734c9 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/sky.css @@ -0,0 +1,280 @@ +/** + * Sky theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); +.reveal a { + line-height: 1.3em; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #add9e4; + background: -moz-radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #f7fbfc), color-stop(100%, #add9e4)); + background: -webkit-radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background: -o-radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background: -ms-radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background: radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background-color: #f7fbfc; } + +.reveal { + font-family: "Open Sans", sans-serif; + font-size: 40px; + font-weight: normal; + color: #333; } + +::selection { + color: #fff; + background: #134674; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #134674; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #333; + font-family: "Quicksand", sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: -0.08em; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #3b759e; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #74a7cb; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #264c66; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #333; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #3b759e; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #3b759e; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #3b759e; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #f7fbfc; } } diff --git a/CreatingReliableSoftwareCpp/css/theme/solarized.css b/CreatingReliableSoftwareCpp/css/theme/solarized.css new file mode 100644 index 0000000..f1a2b9e --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/solarized.css @@ -0,0 +1,277 @@ +/** + * Solarized Light theme for reveal.js. + * Author: Achim Staebler + */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +/** + * Solarized colors by Ethan Schoonover + */ +html * { + color-profile: sRGB; + rendering-intent: auto; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #fdf6e3; + background-color: #fdf6e3; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #657b83; } + +::selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #586e75; + font-family: "League Gothic", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #268bd2; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #78b9e6; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #1a6091; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #657b83; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #268bd2; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #268bd2; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #268bd2; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #fdf6e3; } } diff --git a/CreatingReliableSoftwareCpp/css/theme/source/beige.scss b/CreatingReliableSoftwareCpp/css/theme/source/beige.scss new file mode 100644 index 0000000..5564f53 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/beige.scss @@ -0,0 +1,39 @@ +/** + * Beige theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + + +// Override theme settings (see ../template/settings.scss) +$mainColor: #333; +$headingColor: #333; +$headingTextShadow: none; +$backgroundColor: #f7f3de; +$linkColor: #8b743d; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: rgba(79, 64, 28, 0.99); +$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); + +// Background generator +@mixin bodyBackground() { + @include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) ); +} + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/theme/source/black.scss b/CreatingReliableSoftwareCpp/css/theme/source/black.scss new file mode 100644 index 0000000..4720c8a --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/black.scss @@ -0,0 +1,49 @@ +/** + * Black theme for reveal.js. This is the opposite of the 'white' theme. + * + * By Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #191919; + +$mainColor: #fff; +$headingColor: #fff; + +$mainFontSize: 42px; +$mainFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingFontWeight: 600; +$linkColor: #42affa; +$linkColorHover: lighten( $linkColor, 15% ); +$selectionBackgroundColor: lighten( $linkColor, 25% ); + +$heading1Size: 2.5em; +$heading2Size: 1.6em; +$heading3Size: 1.3em; +$heading4Size: 1.0em; + +section.has-light-background { + &, h1, h2, h3, h4, h5, h6 { + color: #222; + } +} + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/theme/source/blood.scss b/CreatingReliableSoftwareCpp/css/theme/source/blood.scss new file mode 100644 index 0000000..4533fc0 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/blood.scss @@ -0,0 +1,78 @@ +/** + * Blood theme for reveal.js + * Author: Walther http://github.com/Walther + * + * Designed to be used with highlight.js theme + * "monokai_sublime.css" available from + * https://github.com/isagalaev/highlight.js/ + * + * For other themes, change $codeBackground accordingly. + * + */ + + // Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + +// Include theme-specific fonts + +@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic); + +// Colors used in the theme +$blood: #a23; +$coal: #222; +$codeBackground: #23241f; + +$backgroundColor: $coal; + +// Main text +$mainFont: Ubuntu, 'sans-serif'; +$mainColor: #eee; + +// Headings +$headingFont: Ubuntu, 'sans-serif'; +$headingTextShadow: 2px 2px 2px $coal; + +// h1 shadow, borrowed humbly from +// (c) Default theme by Hakim El Hattab +$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); + +// Links +$linkColor: $blood; +$linkColorHover: lighten( $linkColor, 20% ); + +// Text selection +$selectionBackgroundColor: $blood; +$selectionColor: #fff; + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- + +// some overrides after theme template import + +.reveal p { + font-weight: 300; + text-shadow: 1px 1px $coal; +} + +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + font-weight: 700; +} + +.reveal p code { + background-color: $codeBackground; + display: inline-block; + border-radius: 7px; +} + +.reveal small code { + vertical-align: baseline; +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/theme/source/league.scss b/CreatingReliableSoftwareCpp/css/theme/source/league.scss new file mode 100644 index 0000000..46ea04a --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/league.scss @@ -0,0 +1,34 @@ +/** + * League theme for reveal.js. + * + * This was the default theme pre-3.0.0. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + +// Override theme settings (see ../template/settings.scss) +$headingTextShadow: 0px 0px 6px rgba(0,0,0,0.2); +$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); + +// Background generator +@mixin bodyBackground() { + @include radial-gradient( rgba(28,30,32,1), rgba(85,90,95,1) ); +} + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/theme/source/moon.scss b/CreatingReliableSoftwareCpp/css/theme/source/moon.scss new file mode 100644 index 0000000..e47e5b5 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/moon.scss @@ -0,0 +1,57 @@ +/** + * Solarized Dark theme for reveal.js. + * Author: Achim Staebler + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + +/** + * Solarized colors by Ethan Schoonover + */ +html * { + color-profile: sRGB; + rendering-intent: auto; +} + +// Solarized colors +$base03: #002b36; +$base02: #073642; +$base01: #586e75; +$base00: #657b83; +$base0: #839496; +$base1: #93a1a1; +$base2: #eee8d5; +$base3: #fdf6e3; +$yellow: #b58900; +$orange: #cb4b16; +$red: #dc322f; +$magenta: #d33682; +$violet: #6c71c4; +$blue: #268bd2; +$cyan: #2aa198; +$green: #859900; + +// Override theme settings (see ../template/settings.scss) +$mainColor: $base1; +$headingColor: $base2; +$headingTextShadow: none; +$backgroundColor: $base03; +$linkColor: $blue; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: $magenta; + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/CreatingReliableSoftwareCpp/css/theme/source/night.scss b/CreatingReliableSoftwareCpp/css/theme/source/night.scss new file mode 100644 index 0000000..d49a282 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/night.scss @@ -0,0 +1,34 @@ +/** + * Black theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(https://fonts.googleapis.com/css?family=Montserrat:700); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #111; + +$mainFont: 'Open Sans', sans-serif; +$linkColor: #e7ad52; +$linkColorHover: lighten( $linkColor, 20% ); +$headingFont: 'Montserrat', Impact, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: -0.03em; +$headingTextTransform: none; +$selectionBackgroundColor: #e7ad52; + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/theme/source/serif.scss b/CreatingReliableSoftwareCpp/css/theme/source/serif.scss new file mode 100644 index 0000000..ec3fcb3 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/serif.scss @@ -0,0 +1,35 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is brown. + * + * This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed. + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Override theme settings (see ../template/settings.scss) +$mainFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; +$mainColor: #000; +$headingFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; +$headingColor: #383D3D; +$headingTextShadow: none; +$headingTextTransform: none; +$backgroundColor: #F0F1EB; +$linkColor: #51483D; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: #26351C; + +.reveal a { + line-height: 1.3em; +} + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/CreatingReliableSoftwareCpp/css/theme/source/simple.scss b/CreatingReliableSoftwareCpp/css/theme/source/simple.scss new file mode 100644 index 0000000..394c9cd --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/simple.scss @@ -0,0 +1,43 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is darkblue. + * + * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed. + * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + + +// Override theme settings (see ../template/settings.scss) +$mainFont: 'Lato', sans-serif; +$mainColor: #000; +$headingFont: 'News Cycle', Impact, sans-serif; +$headingColor: #000; +$headingTextShadow: none; +$headingTextTransform: none; +$backgroundColor: #fff; +$linkColor: #00008B; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: rgba(0, 0, 0, 0.99); + +section.has-dark-background { + &, h1, h2, h3, h4, h5, h6 { + color: #fff; + } +} + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/theme/source/sky.scss b/CreatingReliableSoftwareCpp/css/theme/source/sky.scss new file mode 100644 index 0000000..3fee67c --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/sky.scss @@ -0,0 +1,46 @@ +/** + * Sky theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); + + +// Override theme settings (see ../template/settings.scss) +$mainFont: 'Open Sans', sans-serif; +$mainColor: #333; +$headingFont: 'Quicksand', sans-serif; +$headingColor: #333; +$headingLetterSpacing: -0.08em; +$headingTextShadow: none; +$backgroundColor: #f7fbfc; +$linkColor: #3b759e; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: #134674; + +// Fix links so they are not cut off +.reveal a { + line-height: 1.3em; +} + +// Background generator +@mixin bodyBackground() { + @include radial-gradient( #add9e4, #f7fbfc ); +} + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/CreatingReliableSoftwareCpp/css/theme/source/solarized.scss b/CreatingReliableSoftwareCpp/css/theme/source/solarized.scss new file mode 100644 index 0000000..912be56 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/solarized.scss @@ -0,0 +1,63 @@ +/** + * Solarized Light theme for reveal.js. + * Author: Achim Staebler + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + + +/** + * Solarized colors by Ethan Schoonover + */ +html * { + color-profile: sRGB; + rendering-intent: auto; +} + +// Solarized colors +$base03: #002b36; +$base02: #073642; +$base01: #586e75; +$base00: #657b83; +$base0: #839496; +$base1: #93a1a1; +$base2: #eee8d5; +$base3: #fdf6e3; +$yellow: #b58900; +$orange: #cb4b16; +$red: #dc322f; +$magenta: #d33682; +$violet: #6c71c4; +$blue: #268bd2; +$cyan: #2aa198; +$green: #859900; + +// Override theme settings (see ../template/settings.scss) +$mainColor: $base00; +$headingColor: $base01; +$headingTextShadow: none; +$backgroundColor: $base3; +$linkColor: $blue; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: $magenta; + +// Background generator +// @mixin bodyBackground() { +// @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) ); +// } + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/CreatingReliableSoftwareCpp/css/theme/source/white.scss b/CreatingReliableSoftwareCpp/css/theme/source/white.scss new file mode 100644 index 0000000..7f06ffd --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/source/white.scss @@ -0,0 +1,49 @@ +/** + * White theme for reveal.js. This is the opposite of the 'black' theme. + * + * By Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #fff; + +$mainColor: #222; +$headingColor: #222; + +$mainFontSize: 42px; +$mainFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingFontWeight: 600; +$linkColor: #2a76dd; +$linkColorHover: lighten( $linkColor, 15% ); +$selectionBackgroundColor: lighten( $linkColor, 25% ); + +$heading1Size: 2.5em; +$heading2Size: 1.6em; +$heading3Size: 1.3em; +$heading4Size: 1.0em; + +section.has-dark-background { + &, h1, h2, h3, h4, h5, h6 { + color: #fff; + } +} + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/theme/template/mixins.scss b/CreatingReliableSoftwareCpp/css/theme/template/mixins.scss new file mode 100644 index 0000000..e0c5606 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/template/mixins.scss @@ -0,0 +1,29 @@ +@mixin vertical-gradient( $top, $bottom ) { + background: $top; + background: -moz-linear-gradient( top, $top 0%, $bottom 100% ); + background: -webkit-gradient( linear, left top, left bottom, color-stop(0%,$top), color-stop(100%,$bottom) ); + background: -webkit-linear-gradient( top, $top 0%, $bottom 100% ); + background: -o-linear-gradient( top, $top 0%, $bottom 100% ); + background: -ms-linear-gradient( top, $top 0%, $bottom 100% ); + background: linear-gradient( top, $top 0%, $bottom 100% ); +} + +@mixin horizontal-gradient( $top, $bottom ) { + background: $top; + background: -moz-linear-gradient( left, $top 0%, $bottom 100% ); + background: -webkit-gradient( linear, left top, right top, color-stop(0%,$top), color-stop(100%,$bottom) ); + background: -webkit-linear-gradient( left, $top 0%, $bottom 100% ); + background: -o-linear-gradient( left, $top 0%, $bottom 100% ); + background: -ms-linear-gradient( left, $top 0%, $bottom 100% ); + background: linear-gradient( left, $top 0%, $bottom 100% ); +} + +@mixin radial-gradient( $outer, $inner, $type: circle ) { + background: $outer; + background: -moz-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: -webkit-gradient( radial, center center, 0px, center center, 100%, color-stop(0%,$inner), color-stop(100%,$outer) ); + background: -webkit-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: -o-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: -ms-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: radial-gradient( center, $type cover, $inner 0%, $outer 100% ); +} \ No newline at end of file diff --git a/CreatingReliableSoftwareCpp/css/theme/template/settings.scss b/CreatingReliableSoftwareCpp/css/theme/template/settings.scss new file mode 100644 index 0000000..5a917f8 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/template/settings.scss @@ -0,0 +1,45 @@ +// Base settings for all themes that can optionally be +// overridden by the super-theme + +// Background of the presentation +$backgroundColor: #2b2b2b; + +// Primary/body text +$mainFont: 'Lato', sans-serif; +$mainFontSize: 40px; +$mainColor: #eee; + +// Vertical spacing between blocks of text +$blockMargin: 20px; + +// Headings +$headingMargin: 0 0 $blockMargin 0; +$headingFont: 'League Gothic', Impact, sans-serif; +$headingColor: #eee; +$headingLineHeight: 1.2; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingTextShadow: none; +$headingFontWeight: normal; +$heading1TextShadow: $headingTextShadow; + +$heading1Size: 3.77em; +$heading2Size: 2.11em; +$heading3Size: 1.55em; +$heading4Size: 1.00em; + +$codeFont: monospace; + +// Links and actions +$linkColor: #13DAEC; +$linkColorHover: lighten( $linkColor, 20% ); + +// Text selection +$selectionBackgroundColor: #FF5E99; +$selectionColor: #fff; + +// Generates the presentation background, can be overridden +// to return a background image or gradient +@mixin bodyBackground() { + background: $backgroundColor; +} diff --git a/CreatingReliableSoftwareCpp/css/theme/template/theme.scss b/CreatingReliableSoftwareCpp/css/theme/template/theme.scss new file mode 100644 index 0000000..9ccfaf5 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/template/theme.scss @@ -0,0 +1,325 @@ +// Base theme template for reveal.js + +/********************************************* + * GLOBAL STYLES + *********************************************/ + +body { + @include bodyBackground(); + background-color: $backgroundColor; +} + +.reveal { + font-family: $mainFont; + font-size: $mainFontSize; + font-weight: normal; + color: $mainColor; +} + +::selection { + color: $selectionColor; + background: $selectionBackgroundColor; + text-shadow: none; +} + +::-moz-selection { + color: $selectionColor; + background: $selectionBackgroundColor; + text-shadow: none; +} + +.reveal .slides section, +.reveal .slides section>section { + line-height: 1.3; + font-weight: inherit; +} + +/********************************************* + * HEADERS + *********************************************/ + +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: $headingMargin; + color: $headingColor; + + font-family: $headingFont; + font-weight: $headingFontWeight; + line-height: $headingLineHeight; + letter-spacing: $headingLetterSpacing; + + text-transform: $headingTextTransform; + text-shadow: $headingTextShadow; + + word-wrap: break-word; +} + +.reveal h1 {font-size: $heading1Size; } +.reveal h2 {font-size: $heading2Size; } +.reveal h3 {font-size: $heading3Size; } +.reveal h4 {font-size: $heading4Size; } + +.reveal h1 { + text-shadow: $heading1TextShadow; +} + + +/********************************************* + * OTHER + *********************************************/ + +.reveal p { + margin: $blockMargin 0; + line-height: 1.3; +} + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; +} +.reveal strong, +.reveal b { + font-weight: bold; +} + +.reveal em { + font-style: italic; +} + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + + text-align: left; + margin: 0 0 0 1em; +} + +.reveal ol { + list-style-type: decimal; +} + +.reveal ul { + list-style-type: disc; +} + +.reveal ul ul { + list-style-type: square; +} + +.reveal ul ul ul { + list-style-type: circle; +} + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; +} + +.reveal dt { + font-weight: bold; +} + +.reveal dd { + margin-left: 40px; +} + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: $blockMargin auto; + padding: 5px; + + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0,0,0,0.2); +} + .reveal blockquote p:first-child, + .reveal blockquote p:last-child { + display: inline-block; + } + +.reveal q { + font-style: italic; +} + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: $blockMargin auto; + + text-align: left; + font-size: 0.55em; + font-family: $codeFont; + line-height: 1.2em; + + word-wrap: break-word; + + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); +} + +.reveal code { + font-family: $codeFont; + text-transform: none; +} + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; +} + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; +} + +.reveal table th { + font-weight: bold; +} + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; +} + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; +} + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; +} + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; +} + +.reveal sup { + vertical-align: super; + font-size: smaller; +} +.reveal sub { + vertical-align: sub; + font-size: smaller; +} + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; +} + +.reveal small * { + vertical-align: top; +} + + +/********************************************* + * LINKS + *********************************************/ + +.reveal a { + color: $linkColor; + text-decoration: none; + + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; +} + .reveal a:hover { + color: $linkColorHover; + + text-shadow: none; + border: none; + } + +.reveal .roll span:after { + color: #fff; + background: darken( $linkColor, 15% ); +} + + +/********************************************* + * IMAGES + *********************************************/ + +.reveal section img { + margin: 15px 0px; + background: rgba(255,255,255,0.12); + border: 4px solid $mainColor; + + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); +} + + .reveal section img.plain { + border: 0; + box-shadow: none; + } + + .reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; + } + + .reveal a:hover img { + background: rgba(255,255,255,0.2); + border-color: $linkColor; + + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); + } + + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ + +.reveal .controls { + color: $linkColor; +} + + +/********************************************* + * PROGRESS BAR + *********************************************/ + +.reveal .progress { + background: rgba(0,0,0,0.2); + color: $linkColor; +} + .reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + -moz-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ + @media print { + .backgrounds { + background-color: $backgroundColor; + } +} diff --git a/CreatingReliableSoftwareCpp/css/theme/white.css b/CreatingReliableSoftwareCpp/css/theme/white.css new file mode 100644 index 0000000..43ef2c7 --- /dev/null +++ b/CreatingReliableSoftwareCpp/css/theme/white.css @@ -0,0 +1,273 @@ +/** + * White theme for reveal.js. This is the opposite of the 'black' theme. + * + * By Hakim El Hattab, http://hakim.se + */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); +section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { + color: #fff; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #fff; + background-color: #fff; } + +.reveal { + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 42px; + font-weight: normal; + color: #222; } + +::selection { + color: #fff; + background: #98bdef; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #98bdef; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #222; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-weight: 600; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 2.5em; } + +.reveal h2 { + font-size: 1.6em; } + +.reveal h3 { + font-size: 1.3em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #2a76dd; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #6ca0e8; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #1a53a1; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #222; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #2a76dd; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #2a76dd; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #2a76dd; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #fff; } } diff --git a/CreatingReliableSoftwareCpp/demo.html b/CreatingReliableSoftwareCpp/demo.html new file mode 100644 index 0000000..cf05e88 --- /dev/null +++ b/CreatingReliableSoftwareCpp/demo.html @@ -0,0 +1,425 @@ + + + + + + + reveal.js – The HTML Presentation Framework + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+

Reveal.js

+

The HTML Presentation Framework

+

+ Created by Hakim El Hattab and contributors +

+
+ +
+

Hello There

+

+ reveal.js enables you to create beautiful interactive slide decks using HTML. This presentation will show you examples of what it can do. +

+
+ + +
+
+

Vertical Slides

+

Slides can be nested inside of each other.

+

Use the Space key to navigate through all slides.

+
+ + Down arrow + +
+
+

Basement Level 1

+

Nested slides are useful for adding additional detail underneath a high level horizontal slide.

+
+
+

Basement Level 2

+

That's it, time to go back up.

+
+ + Up arrow + +
+
+ +
+

Slides

+

+ Not a coder? Not a problem. There's a fully-featured visual editor for authoring these, try it out at https://slides.com. +

+
+ +
+

Point of View

+

+ Press ESC to enter the slide overview. +

+

+ Hold down the alt key (ctrl in Linux) and click on any element to zoom towards it using zoom.js. Click again to zoom back out. +

+

+ (NOTE: Use ctrl + click in Linux.) +

+
+ +
+

Touch Optimized

+

+ Presentations look great on touch devices, like mobile phones and tablets. Simply swipe through your slides. +

+
+ +
+ +
+ +
+
+

Fragments

+

Hit the next arrow...

+

... to step through ...

+

... a fragmented slide.

+ + +
+
+

Fragment Styles

+

There's different types of fragments, like:

+

grow

+

shrink

+

fade-out

+

+ fade-right, + up, + down, + left +

+

fade-in-then-out

+

fade-in-then-semi-out

+

Highlight red blue green

+
+
+ +
+

Transition Styles

+

+ You can select from different transitions, like:
+ None - + Fade - + Slide - + Convex - + Concave - + Zoom +

+
+ +
+

Themes

+

+ reveal.js comes with a few themes built in:
+ + Black (default) - + White - + League - + Sky - + Beige - + Simple
+ Serif - + Blood - + Night - + Moon - + Solarized +

+
+ +
+
+

Slide Backgrounds

+

+ Set data-background="#dddddd" on a slide to change the background color. All CSS color formats are supported. +

+ + Down arrow + +
+
+

Image Backgrounds

+
<section data-background="image.png">
+
+
+

Tiled Backgrounds

+
<section data-background="image.png" data-background-repeat="repeat" data-background-size="100px">
+
+
+
+

Video Backgrounds

+
<section data-background-video="video.mp4,video.webm">
+
+
+
+

... and GIFs!

+
+
+ +
+

Background Transitions

+

+ Different background transitions are available via the backgroundTransition option. This one's called "zoom". +

+
Reveal.configure({ backgroundTransition: 'zoom' })
+
+ +
+

Background Transitions

+

+ You can override background transitions per-slide. +

+
<section data-background-transition="zoom">
+
+ +
+
+

Iframe Backgrounds

+

Since reveal.js runs on the web, you can easily embed other web content. Try interacting with the page in the background.

+
+
+ +
+

Pretty Code

+

+import React, { useState } from 'react';
+
+function Example() {
+  const [count, setCount] = useState(0);
+
+  return (
+    <div>
+      <p>You clicked {count} times</p>
+      <button onClick={() => setCount(count + 1)}>
+        Click me
+      </button>
+    </div>
+  );
+}
+					
+

Code syntax highlighting courtesy of highlight.js.

+
+ +
+

Marvelous List

+
    +
  • No order here
  • +
  • Or here
  • +
  • Or here
  • +
  • Or here
  • +
+
+ +
+

Fantastic Ordered List

+
    +
  1. One is smaller than...
  2. +
  3. Two is smaller than...
  4. +
  5. Three!
  6. +
+
+ +
+

Tabular Tables

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ItemValueQuantity
Apples$17
Lemonade$218
Bread$32
+
+ +
+

Clever Quotes

+

+ These guys come in two forms, inline: The nice thing about standards is that there are so many to choose from and block: +

+
+ “For years there has been a theory that millions of monkeys typing at random on millions of typewriters would + reproduce the entire works of Shakespeare. The Internet has proven this theory to be untrue.” +
+
+ +
+

Intergalactic Interconnections

+

+ You can link between slides internally, + like this. +

+
+ +
+

Speaker View

+

There's a speaker view. It includes a timer, preview of the upcoming slide as well as your speaker notes.

+

Press the S key to try it out.

+ + +
+ +
+

Export to PDF

+

Presentations can be exported to PDF, here's an example:

+ +
+ +
+

Global State

+

+ Set data-state="something" on a slide and "something" + will be added as a class to the document element when the slide is open. This lets you + apply broader style changes, like switching the page background. +

+
+ +
+

State Events

+

+ Additionally custom events can be triggered on a per slide basis by binding to the data-state name. +

+

+Reveal.addEventListener( 'customevent', function() {
+	console.log( '"customevent" has fired' );
+} );
+					
+
+ +
+

Take a Moment

+

+ Press B or . on your keyboard to pause the presentation. This is helpful when you're on stage and want to take distracting slides off the screen. +

+
+ +
+

Much more

+ +
+ +
+

THE END

+

+ - Try the online editor
+ - Source code & documentation +

+
+ +
+ +
+ + + + + + + diff --git a/CreatingReliableSoftwareCpp/gruntfile.js b/CreatingReliableSoftwareCpp/gruntfile.js new file mode 100644 index 0000000..acf34b6 --- /dev/null +++ b/CreatingReliableSoftwareCpp/gruntfile.js @@ -0,0 +1,189 @@ +const sass = require('node-sass'); + +module.exports = grunt => { + + require('load-grunt-tasks')(grunt); + + let port = grunt.option('port') || 8000; + let root = grunt.option('root') || '.'; + + if (!Array.isArray(root)) root = [root]; + + // Project configuration + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + meta: { + banner: + '/*!\n' + + ' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' + + ' * http://revealjs.com\n' + + ' * MIT licensed\n' + + ' *\n' + + ' * Copyright (C) 2020 Hakim El Hattab, http://hakim.se\n' + + ' */' + }, + + qunit: { + files: [ 'test/*.html' ] + }, + + uglify: { + options: { + banner: '<%= meta.banner %>\n', + ie8: true + }, + build: { + src: 'js/reveal.js', + dest: 'js/reveal.min.js' + } + }, + + sass: { + options: { + implementation: sass, + sourceMap: false + }, + core: { + src: 'css/reveal.scss', + dest: 'css/reveal.css' + }, + themes: { + expand: true, + cwd: 'css/theme/source', + src: ['*.sass', '*.scss'], + dest: 'css/theme', + ext: '.css' + } + }, + + autoprefixer: { + core: { + src: 'css/reveal.css' + } + }, + + cssmin: { + options: { + compatibility: 'ie9' + }, + compress: { + src: 'css/reveal.css', + dest: 'css/reveal.min.css' + } + }, + + jshint: { + options: { + curly: false, + eqeqeq: true, + immed: true, + esnext: true, + latedef: 'nofunc', + newcap: true, + noarg: true, + sub: true, + undef: true, + eqnull: true, + browser: true, + expr: true, + loopfunc: true, + globals: { + head: false, + module: false, + console: false, + unescape: false, + define: false, + exports: false, + require: false + } + }, + files: [ 'gruntfile.js', 'js/reveal.js' ] + }, + + connect: { + server: { + options: { + port: port, + base: root, + livereload: true, + open: true, + useAvailablePort: true + } + } + }, + + zip: { + bundle: { + src: [ + 'index.html', + 'css/**', + 'js/**', + 'lib/**', + 'images/**', + 'plugin/**', + '**.md' + ], + dest: 'reveal-js-presentation.zip' + } + }, + + watch: { + js: { + files: [ 'gruntfile.js', 'js/reveal.js' ], + tasks: 'js' + }, + theme: { + files: [ + 'css/theme/source/*.sass', + 'css/theme/source/*.scss', + 'css/theme/template/*.sass', + 'css/theme/template/*.scss' + ], + tasks: 'css-themes' + }, + css: { + files: [ 'css/reveal.scss' ], + tasks: 'css-core' + }, + test: { + files: [ 'test/*.html' ], + tasks: 'test' + }, + html: { + files: root.map(path => path + '/*.html') + }, + markdown: { + files: root.map(path => path + '/*.md') + }, + options: { + livereload: true + } + } + + }); + + // Default task + grunt.registerTask( 'default', [ 'css', 'js' ] ); + + // JS task + grunt.registerTask( 'js', [ 'jshint', 'uglify', 'qunit' ] ); + + // Theme CSS + grunt.registerTask( 'css-themes', [ 'sass:themes' ] ); + + // Core framework CSS + grunt.registerTask( 'css-core', [ 'sass:core', 'autoprefixer', 'cssmin' ] ); + + // All CSS + grunt.registerTask( 'css', [ 'sass', 'autoprefixer', 'cssmin' ] ); + + // Package presentation to archive + grunt.registerTask( 'package', [ 'default', 'zip' ] ); + + // Serve presentation locally + grunt.registerTask( 'serve', [ 'connect', 'watch' ] ); + + // Run tests + grunt.registerTask( 'test', [ 'jshint', 'qunit' ] ); + +}; diff --git a/CreatingReliableSoftwareCpp/img/altkom_logo.png b/CreatingReliableSoftwareCpp/img/altkom_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..abf064313043ccc16f18ee28e049848ed6d5d3b4 GIT binary patch literal 14919 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%0A7}ivC(8qO`H#v^X0Vt8AHiNK@WERj0o(#0 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%0Dy1^ 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

1VILEKF)c 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 oJ$#sP_4iYupTE6o$DEfBY{rbP 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

+
+ +
+

Creating reliable software in C++

+
+

Altkom Akademia

+
https://www.altkomakademia.pl + +
+
+ Altkom Akademia + +48 801 258 566 +
+ +
+ +
+ Altkom Akademia + Mateusz Adamski + nauka.programowania.ma@gmail.com +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Altkom Akademia

+ https://www.altkomakademia.pl + +

+ +
+
+
+ altkomakademia +
+ Zapraszamy do współpracy + ALTKOM AKADEMIA + ul. Chłodna 51, budynek WTT, + 00-867 Warszawa + Telefon: (+48 22) 460 99 99, + Fax: (+48 22) 460 99 90 + warszawa@altkom.pl +
+
+
+ +
+ +
+ Mateusz Adamski + nauka.programowania.ma@gmail.com +
+
+
+ +
+ +