aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/DI/auto_wirable.hpp28
-rw-r--r--src/DI/auto_wirable.tpp10
-rw-r--r--src/DI/container.hpp65
-rw-r--r--src/DI/container.tpp53
-rw-r--r--src/DI/function_wrapper.hpp20
-rw-r--r--src/DI/function_wrapper.tpp9
-rw-r--r--src/DI/interfaces/wrapper.hpp17
-rw-r--r--src/DI/object_type.cpp18
-rw-r--r--src/DI/object_type.hpp35
-rw-r--r--src/DI/object_wrapper.hpp20
-rw-r--r--src/DI/object_wrapper.tpp9
-rw-r--r--src/argument_parser.cpp100
-rw-r--r--src/argument_parser.hpp27
-rw-r--r--src/bootstrap.cpp36
-rw-r--r--src/bootstrap.hpp5
-rw-r--r--src/game_of_life.cpp97
-rw-r--r--src/interfaces/argument_parser.hpp23
-rw-r--r--src/interfaces/randomization.hpp31
-rw-r--r--src/randomization.hpp35
-rw-r--r--src/randomization/generator.cpp (renamed from src/randomization.cpp)9
-rw-r--r--src/randomization/generator.hpp18
-rw-r--r--src/randomization/seed_generator.cpp11
-rw-r--r--src/randomization/seed_generator.hpp17
24 files changed, 574 insertions, 125 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1e4d106..54ee94f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -10,8 +10,12 @@ endfunction(target_link_libraries_system)
file(GLOB SOURCES
game_of_life.cpp
+ bootstrap.cpp
conversion.cpp
- randomization.cpp)
+ argument_parser.cpp
+ randomization/generator.cpp
+ randomization/seed_generator.cpp
+ DI/object_type.cpp)
add_executable(${PROJECT_NAME} ${SOURCES})
diff --git a/src/DI/auto_wirable.hpp b/src/DI/auto_wirable.hpp
new file mode 100644
index 0000000..13d252e
--- /dev/null
+++ b/src/DI/auto_wirable.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "DI/container.hpp"
+
+#include <memory>
+
+// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
+class IGenericAutoWirable
+{
+public:
+ virtual ~IGenericAutoWirable() = default;
+};
+
+template <class Interface>
+class IAutoWirable : public IGenericAutoWirable
+{
+public:
+ static Interface resolve();
+};
+
+template <class Interface, class ObjectImpl, class... Dependencies>
+class AutoWirable : public IAutoWirable<Interface>
+{
+public:
+ static std::shared_ptr<Interface> resolve(const Container &container);
+};
+
+#include "auto_wirable.tpp"
diff --git a/src/DI/auto_wirable.tpp b/src/DI/auto_wirable.tpp
new file mode 100644
index 0000000..6c0d111
--- /dev/null
+++ b/src/DI/auto_wirable.tpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "auto_wirable.hpp"
+
+template <class Interface, class ObjectImpl, class... Dependencies>
+std::shared_ptr<Interface>
+AutoWirable<Interface, ObjectImpl, Dependencies...>::resolve(const Container &container)
+{
+ return std::make_shared<ObjectImpl>(container.get<Dependencies>()...);
+}
diff --git a/src/DI/container.hpp b/src/DI/container.hpp
new file mode 100644
index 0000000..2402894
--- /dev/null
+++ b/src/DI/container.hpp
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "DI/object_type.hpp"
+#include "interfaces/wrapper.hpp"
+
+#include <functional>
+#include <memory>
+#include <type_traits>
+#include <unordered_map>
+
+class Container;
+
+template <typename Interface>
+class BindingBuilder
+{
+public:
+ explicit BindingBuilder(Container *container);
+
+ template <class ObjectImpl,
+ class = std::enable_if_t<std::is_base_of_v<Interface, ObjectImpl>>>
+ void to();
+
+ void to_factory(Interface func);
+
+private:
+ Container *_container;
+};
+
+template <typename Satan>
+struct is_func : public std::false_type // NOLINT(readability-identifier-naming)
+{
+};
+
+template <typename Satan, typename... Args>
+struct is_func<std::function<Satan(Args...)>> : public std::true_type
+{
+};
+
+class Container
+{
+public:
+ Container() = default;
+
+ template <class Interface>
+ BindingBuilder<Interface> bind();
+
+ template <class Interface, class = std::enable_if_t<std::is_abstract_v<Interface>>>
+ std::shared_ptr<Interface> get() const;
+
+ /*
+ template <typename Interface,
+ typename = std::enable_if_t<
+ !std::is_abstract_v<Interface> &&
+ std::is_invocable_v<Interface, typename Interface::argument_type>>>
+ Interface get() const;
+ */
+
+ template <typename Interface, typename = std::enable_if_t<is_func<Interface>::value>>
+ Interface get() const;
+
+ std::unordered_map<BaseObjectType, std::shared_ptr<IGenericWrapper>, ObjectTypeHasher>
+ bindings;
+};
+
+#include "container.tpp"
diff --git a/src/DI/container.tpp b/src/DI/container.tpp
new file mode 100644
index 0000000..21bf81a
--- /dev/null
+++ b/src/DI/container.tpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "container.hpp"
+
+#include "function_wrapper.hpp"
+#include "object_wrapper.hpp"
+
+template <class Interface>
+BindingBuilder<Interface>::BindingBuilder(Container *container) : _container(container)
+{
+}
+
+template <class Interface>
+template <class ObjectImpl, class>
+void BindingBuilder<Interface>::to()
+{
+ _container->bindings.emplace(
+ ObjectType<Interface>(),
+ std::dynamic_pointer_cast<IGenericWrapper>(
+ std::make_shared<ObjectWrapper<Interface, ObjectImpl>>(*_container)));
+}
+
+template <class Interface>
+void BindingBuilder<Interface>::to_factory(Interface func)
+{
+ _container->bindings.emplace(ObjectType<Interface>(),
+ std::dynamic_pointer_cast<IGenericWrapper>(
+ std::make_shared<FunctionWrapper<Interface>>(func)));
+}
+
+template <class Interface>
+BindingBuilder<Interface> Container::bind()
+{
+ return BindingBuilder<Interface>(this);
+}
+
+template <class Interface, class>
+std::shared_ptr<Interface> Container::get() const
+{
+ auto wrapper = std::dynamic_pointer_cast<IWrapper<std::shared_ptr<Interface>>>(
+ bindings.at(ObjectType<Interface>()));
+
+ return wrapper->get();
+}
+
+template <typename Interface, typename>
+Interface Container::get() const
+{
+ auto wrapper = std::dynamic_pointer_cast<IWrapper<Interface>>(
+ bindings.at(ObjectType<Interface>()));
+
+ return wrapper->get();
+}
diff --git a/src/DI/function_wrapper.hpp b/src/DI/function_wrapper.hpp
new file mode 100644
index 0000000..e4b6779
--- /dev/null
+++ b/src/DI/function_wrapper.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "DI/container.hpp"
+#include "DI/interfaces/wrapper.hpp"
+
+#include <memory>
+
+template <class Interface>
+class FunctionWrapper : public IWrapper<Interface>
+{
+public:
+ explicit FunctionWrapper(Interface func) : _func(func) {}
+
+ [[nodiscard]] Interface get() const;
+
+private:
+ const Interface _func;
+};
+
+#include "function_wrapper.tpp"
diff --git a/src/DI/function_wrapper.tpp b/src/DI/function_wrapper.tpp
new file mode 100644
index 0000000..4e09957
--- /dev/null
+++ b/src/DI/function_wrapper.tpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "function_wrapper.hpp"
+
+template <class Interface>
+Interface FunctionWrapper<Interface>::get() const
+{
+ return _func;
+}
diff --git a/src/DI/interfaces/wrapper.hpp b/src/DI/interfaces/wrapper.hpp
new file mode 100644
index 0000000..3cc75a0
--- /dev/null
+++ b/src/DI/interfaces/wrapper.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <memory>
+
+// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
+class IGenericWrapper
+{
+public:
+ virtual ~IGenericWrapper() = default;
+};
+
+template <class Interface>
+class IWrapper : public IGenericWrapper
+{
+public:
+ [[nodiscard]] virtual Interface get() const = 0;
+};
diff --git a/src/DI/object_type.cpp b/src/DI/object_type.cpp
new file mode 100644
index 0000000..60c7c78
--- /dev/null
+++ b/src/DI/object_type.cpp
@@ -0,0 +1,18 @@
+#include "object_type.hpp"
+
+BaseObjectType::BaseObjectType(const std::type_info &type_info) : _type_info(type_info) {}
+
+bool BaseObjectType::operator==(const BaseObjectType &object_type) const
+{
+ return hash() == object_type.hash();
+}
+
+std::size_t BaseObjectType::hash() const
+{
+ return _type_info.hash_code();
+}
+
+std::size_t ObjectTypeHasher::operator()(const BaseObjectType &object_type) const
+{
+ return object_type.hash();
+}
diff --git a/src/DI/object_type.hpp b/src/DI/object_type.hpp
new file mode 100644
index 0000000..f690a64
--- /dev/null
+++ b/src/DI/object_type.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <typeinfo>
+
+class BaseObjectType
+{
+public:
+ explicit BaseObjectType(const std::type_info &type_info);
+
+ bool operator==(const BaseObjectType &object_type) const;
+
+ [[nodiscard]] std::size_t hash() const;
+
+private:
+ const std::type_info &_type_info;
+};
+
+template <class Object>
+class ObjectType : public BaseObjectType
+{
+public:
+ ObjectType() : BaseObjectType(typeid(Object)) {}
+};
+
+class IObjectTypeHasher
+{
+public:
+ virtual std::size_t operator()(const BaseObjectType &object_type) const = 0;
+};
+
+class ObjectTypeHasher : public IObjectTypeHasher
+{
+public:
+ std::size_t operator()(const BaseObjectType &object_type) const override;
+};
diff --git a/src/DI/object_wrapper.hpp b/src/DI/object_wrapper.hpp
new file mode 100644
index 0000000..0ae66df
--- /dev/null
+++ b/src/DI/object_wrapper.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "DI/container.hpp"
+#include "DI/interfaces/wrapper.hpp"
+
+#include <memory>
+
+template <class Interface, class ObjectImpl>
+class ObjectWrapper : public IWrapper<std::shared_ptr<Interface>>
+{
+public:
+ explicit ObjectWrapper(const Container &container) : _container(container) {}
+
+ [[nodiscard]] std::shared_ptr<Interface> get() const;
+
+private:
+ const Container &_container;
+};
+
+#include "object_wrapper.tpp"
diff --git a/src/DI/object_wrapper.tpp b/src/DI/object_wrapper.tpp
new file mode 100644
index 0000000..7efefc4
--- /dev/null
+++ b/src/DI/object_wrapper.tpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "object_wrapper.hpp"
+
+template <class Interface, class ObjectImpl>
+std::shared_ptr<Interface> ObjectWrapper<Interface, ObjectImpl>::get() const
+{
+ return ObjectImpl::resolve(_container);
+}
diff --git a/src/argument_parser.cpp b/src/argument_parser.cpp
new file mode 100644
index 0000000..b5f14bc
--- /dev/null
+++ b/src/argument_parser.cpp
@@ -0,0 +1,100 @@
+#include "argument_parser.hpp"
+
+#include "conversion.hpp"
+#include "interfaces/randomization.hpp"
+
+#include <cstdlib>
+#include <iostream>
+#include <string_view>
+
+namespace
+{
+void optarg_error(char arg, const std::string_view &error)
+{
+ std::cout << "Error: Invalid option argument for -" << arg << ". " << error
+ << std::endl;
+ exit(EXIT_FAILURE);
+}
+
+/**
+ * Returns the current optarg as a string view.
+ */
+std::string_view get_str_optarg()
+{
+ return std::string_view(optarg);
+}
+
+/**
+ * Returns the current optarg as a unsigned integer.
+ *
+ * @param arg The current command-line argument character
+ * @param check_zero Whether or not to make sure that the result is not zero
+ */
+unsigned int get_uint_optarg(char arg, bool check_zero = false)
+{
+ auto conversion_result = str_to_uint(get_str_optarg());
+
+ if (!conversion_result.success || (check_zero && conversion_result.result == 0))
+ {
+ optarg_error(arg, conversion_result.fail_reason);
+ }
+
+ return conversion_result.result;
+}
+} // namespace
+
+ArgumentParser::ArgumentParser(
+ IRandomNumberGeneratorFactory random_number_generator_factory)
+ : _random_number_generator_factory(std::move(random_number_generator_factory))
+{
+}
+
+ParsedArguments
+ArgumentParser::parse(const std::vector<option> &options,
+ const std::string_view &short_options, const int &argc,
+ char *const *argv) // NOLINT(cppcoreguidelines-avoid-c-arrays,
+ // modernize-avoid-c-arrays)
+{
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
+ const auto args = std::vector<std::string_view>(argv, argv + argc);
+
+ const auto program_name = args[0];
+
+ ParsedArguments parsed_arguments;
+
+ char arg = 0;
+ while ((arg = static_cast<char>(getopt_long(argc, argv, short_options.data(),
+ options.data(), nullptr))) != -1)
+ {
+ switch (arg)
+ {
+ case 's':
+ {
+ auto seed = get_uint_optarg(arg, true);
+
+ parsed_arguments.random_gen = _random_number_generator_factory(seed);
+ break;
+ }
+ case 'h':
+ {
+ std::cout << "Usage: " << program_name
+ << " [OPTION]...\n\n"
+ "Options:\n"
+ << " -s, --seed SEED The randomization seed used\n"
+ " -h --help Displays usage information"
+ << std::endl;
+ exit(EXIT_SUCCESS);
+ }
+ case '?':
+ {
+ std::cout << "\nTry '" << program_name << " --help' for more information"
+ << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ default:
+ abort();
+ }
+ }
+
+ return parsed_arguments;
+}
diff --git a/src/argument_parser.hpp b/src/argument_parser.hpp
new file mode 100644
index 0000000..0bcaeb5
--- /dev/null
+++ b/src/argument_parser.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "DI/auto_wirable.hpp"
+#include "interfaces/argument_parser.hpp"
+#include "interfaces/randomization.hpp"
+
+#include <getopt.h>
+#include <string_view>
+#include <vector>
+
+class ArgumentParser
+ : public IArgumentParser,
+ public AutoWirable<IArgumentParser, ArgumentParser, IRandomNumberGeneratorFactory>
+{
+public:
+ explicit ArgumentParser(
+ IRandomNumberGeneratorFactory random_number_generator_factory);
+
+ ParsedArguments
+ parse(const std::vector<option> &options, const std::string_view &short_options,
+ const int &argc,
+ char *const *argv) override; // NOLINT(cppcoreguidelines-avoid-c-arrays,
+ // modernize-avoid-c-arrays)
+
+private:
+ IRandomNumberGeneratorFactory _random_number_generator_factory;
+};
diff --git a/src/bootstrap.cpp b/src/bootstrap.cpp
new file mode 100644
index 0000000..85498bc
--- /dev/null
+++ b/src/bootstrap.cpp
@@ -0,0 +1,36 @@
+#include "bootstrap.hpp"
+
+// Interfaces
+#include "interfaces/argument_parser.hpp"
+#include "interfaces/randomization.hpp"
+
+// Implementations
+#include "argument_parser.hpp"
+#include "randomization/generator.hpp"
+#include "randomization/seed_generator.hpp"
+
+#include <memory>
+#include <random>
+
+Container bootstrap()
+{
+ auto container = Container();
+
+ container.bind<IArgumentParser>().to<ArgumentParser>();
+
+ container.bind<IRandomNumberGeneratorFactory>().to_factory(
+ [](const unsigned int &seed)
+ {
+ return std::dynamic_pointer_cast<IRandomNumberGenerator>(
+ std::make_shared<RandomNumberGenerator>(seed));
+ });
+
+ container.bind<ISeedGeneratorFactory>().to_factory(
+ []()
+ {
+ return std::dynamic_pointer_cast<ISeedGenerator>(
+ std::make_shared<SeedGenerator>(std::make_unique<std::random_device>()));
+ });
+
+ return container;
+}
diff --git a/src/bootstrap.hpp b/src/bootstrap.hpp
new file mode 100644
index 0000000..a822017
--- /dev/null
+++ b/src/bootstrap.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "DI/container.hpp"
+
+Container bootstrap();
diff --git a/src/game_of_life.cpp b/src/game_of_life.cpp
index 3cd662b..9f7b019 100644
--- a/src/game_of_life.cpp
+++ b/src/game_of_life.cpp
@@ -1,94 +1,29 @@
-#include "conversion.hpp"
-#include "randomization.hpp"
+#include "bootstrap.hpp"
+#include "interfaces/argument_parser.hpp"
+#include "interfaces/randomization.hpp"
#include <getopt.h>
-#include <iostream>
-#include <memory>
-#include <string_view>
#include <vector>
-namespace
-{
-void optarg_error(char arg, const std::string_view &error)
-{
- std::cout << "Error: Invalid option argument for -" << arg << ". " << error
- << std::endl;
- exit(EXIT_FAILURE);
-}
-
-/**
- * Returns the current optarg as a string view.
- */
-std::string_view get_str_optarg()
-{
- return std::string_view(optarg);
-}
-
-/**
- * Returns the current optarg as a unsigned integer.
- *
- * @param arg The current command-line argument character
- * @param check_zero Whether or not to make sure that the result is not zero
- */
-unsigned int get_uint_optarg(char arg, bool check_zero = false)
-{
- auto conversion_result = str_to_uint(get_str_optarg());
-
- if (!conversion_result.success || (check_zero && conversion_result.result == 0))
- {
- optarg_error(arg, conversion_result.fail_reason);
- }
-
- return conversion_result.result;
-}
-} // namespace
-
-constexpr std::array<option, 8> options = {
- option({"seed", required_argument, nullptr, 's'}),
- option({"help", no_argument, nullptr, 0}), option({nullptr, 0, nullptr, 0})};
+const std::vector<option> options = {option({"seed", required_argument, nullptr, 's'}),
+ option({"help", no_argument, nullptr, 'h'}),
+ option({nullptr, 0, nullptr, 0})};
int main(int argc, char *argv[])
{
- auto args = std::vector<std::string_view>(argv, argv + argc);
+ auto container = bootstrap();
- std::shared_ptr<RandomNumberGenerator> random_gen = nullptr;
+ auto argument_parser = container.get<IArgumentParser>();
- char arg = 0;
- while ((arg = static_cast<char>(
- getopt_long(argc, argv, "s:", options.data(), nullptr))) != -1)
- {
- switch (arg)
- {
- case 's':
- {
- auto seed = get_uint_optarg(arg, true);
-
- random_gen = std::make_shared<RandomNumberGenerator>(seed);
- break;
- }
- case 0:
- {
- std::cout << "Usage: " << args[0]
- << " [OPTION]...\n\n"
- "Options:\n"
- << " -s, --seed SEED The randomization seed used\n"
- " --help Displays usage information"
- << std::endl;
- return EXIT_SUCCESS;
- }
- case '?':
- {
- std::cout << "\nTry '" << args[0] << " --help' for more information"
- << std::endl;
- return EXIT_FAILURE;
- }
- default:
- abort();
- }
- }
+ auto parsed_arguments = argument_parser->parse(options, "s:h", argc, argv);
- if (random_gen == nullptr)
+ if (parsed_arguments.random_gen == nullptr)
{
- random_gen = std::make_shared<RandomNumberGenerator>();
+ auto seed_generator_factory = container.get<ISeedGeneratorFactory>();
+ auto random_number_generator_factory =
+ container.get<IRandomNumberGeneratorFactory>();
+
+ parsed_arguments.random_gen =
+ random_number_generator_factory(seed_generator_factory()->random_seed());
}
}
diff --git a/src/interfaces/argument_parser.hpp b/src/interfaces/argument_parser.hpp
new file mode 100644
index 0000000..222d9e0
--- /dev/null
+++ b/src/interfaces/argument_parser.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "interfaces/randomization.hpp"
+
+#include <getopt.h>
+#include <memory>
+#include <string_view>
+#include <vector>
+
+struct ParsedArguments
+{
+ std::shared_ptr<IRandomNumberGenerator> random_gen = nullptr;
+};
+
+class IArgumentParser
+{
+public:
+ virtual ParsedArguments
+ parse(const std::vector<option> &options, const std::string_view &short_options,
+ const int &argc,
+ char *const *argv) = 0; // NOLINT(cppcoreguidelines-avoid-c-arrays,
+ // modernize-avoid-c-arrays)
+};
diff --git a/src/interfaces/randomization.hpp b/src/interfaces/randomization.hpp
new file mode 100644
index 0000000..78456a2
--- /dev/null
+++ b/src/interfaces/randomization.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <functional>
+#include <memory>
+
+class ISeedGenerator
+{
+public:
+ [[nodiscard]] virtual unsigned int random_seed() const = 0;
+};
+
+using ISeedGeneratorFactory = std::function<std::shared_ptr<ISeedGenerator>()>;
+
+/**
+ * Pseudo-random unsigned integer generator.
+ */
+class IRandomNumberGenerator
+{
+public:
+ /**
+ * Returns a number in the range of a to b.
+ *
+ * @param a A number lower than b
+ * @param b A number greater than a
+ */
+ [[nodiscard]] virtual unsigned int in_range(const unsigned int &a,
+ const unsigned int &b) const = 0;
+};
+
+using IRandomNumberGeneratorFactory =
+ std::function<std::shared_ptr<IRandomNumberGenerator>(const unsigned int &seed)>;
diff --git a/src/randomization.hpp b/src/randomization.hpp
deleted file mode 100644
index b4931d7..0000000
--- a/src/randomization.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-
-#include <memory>
-#include <random>
-
-/**
- * Pseudo-random unsigned integer generator.
- */
-class RandomNumberGenerator
-{
-public:
- /**
- * Creates a pseudo-random number generator.
- *
- * @param seed A number generation seed
- */
- explicit RandomNumberGenerator(const unsigned int &seed);
-
- /**
- * Creates a pesudo-random number generator.
- */
- RandomNumberGenerator();
-
- /**
- * Generates a number in the range of a to b.
- *
- * @param a A number lower than b
- * @param b A number greater than a
- */
- [[nodiscard]] unsigned int in_range(const unsigned int &a,
- const unsigned int &b) const;
-
-private:
- std::unique_ptr<std::mt19937> _generator;
-};
diff --git a/src/randomization.cpp b/src/randomization/generator.cpp
index 8f233d2..b9bcb8a 100644
--- a/src/randomization.cpp
+++ b/src/randomization/generator.cpp
@@ -1,17 +1,10 @@
-#include "randomization.hpp"
+#include "generator.hpp"
RandomNumberGenerator::RandomNumberGenerator(const unsigned int &seed)
{
this->_generator = std::make_unique<std::mt19937>(seed);
}
-RandomNumberGenerator::RandomNumberGenerator()
-{
- std::random_device random_device;
-
- this->_generator = std::make_unique<std::mt19937>(random_device());
-}
-
unsigned int RandomNumberGenerator::in_range(const unsigned int &a,
const unsigned int &b) const
{
diff --git a/src/randomization/generator.hpp b/src/randomization/generator.hpp
new file mode 100644
index 0000000..3acfc98
--- /dev/null
+++ b/src/randomization/generator.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "interfaces/randomization.hpp"
+
+#include <memory>
+#include <random>
+
+class RandomNumberGenerator : public IRandomNumberGenerator
+{
+public:
+ explicit RandomNumberGenerator(const unsigned int &seed);
+
+ [[nodiscard]] unsigned int in_range(const unsigned int &a,
+ const unsigned int &b) const override;
+
+private:
+ std::unique_ptr<std::mt19937> _generator;
+};
diff --git a/src/randomization/seed_generator.cpp b/src/randomization/seed_generator.cpp
new file mode 100644
index 0000000..fdb2b12
--- /dev/null
+++ b/src/randomization/seed_generator.cpp
@@ -0,0 +1,11 @@
+#include "seed_generator.hpp"
+
+SeedGenerator::SeedGenerator(const std::shared_ptr<std::random_device> &random_device)
+ : _random_device(random_device)
+{
+}
+
+unsigned int SeedGenerator::random_seed() const
+{
+ return (*_random_device)();
+}
diff --git a/src/randomization/seed_generator.hpp b/src/randomization/seed_generator.hpp
new file mode 100644
index 0000000..238fdbe
--- /dev/null
+++ b/src/randomization/seed_generator.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "interfaces/randomization.hpp"
+
+#include <memory>
+#include <random>
+
+class SeedGenerator : public ISeedGenerator
+{
+public:
+ explicit SeedGenerator(const std::shared_ptr<std::random_device> &random_device);
+
+ [[nodiscard]] unsigned int random_seed() const override;
+
+private:
+ const std::shared_ptr<std::random_device> &_random_device;
+};