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.
+
+
+___
+
+## 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.
+
+
+
+___
+
+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 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.
+
+
+
+
+___
+
+## 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