juk3n/fluffypublic Fork
⑂ bed72a2
Commits
⬇ Clone ▾
git clone https://git.rickub.com/juk3n/fluffy.git
git clone ssh://git@rickub.com/juk3n/fluffy.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

48 command design pattern (#49)Unverified

* added command class

* used show command in application

* added remove command

* added play command

* added add command

* removed unused code

---------

Co-authored-by: Adrian Duraj <adrian.duraj@onmail.com>
Adrian Duraj committed 2026-09-25T19:58:59+02:00 Browse files
bed72a2 parent: 1fbb4dc
modified app/CMakeLists.txt +2 -1
@@ -18,7 +18,8 @@ find_package(SQLite3 REQUIRED)
1818
1919 include_directories(${CMAKE_SOURCE_DIR}/include)
2020 enable_testing()
21-add_executable(fluffy src/main.cpp src/fluffyApplication.cpp src/gameRepository.cpp)
21+add_executable(fluffy src/main.cpp src/fluffyApplication.cpp src/gameRepository.cpp
22+ include/commands/showCommand.hpp)
2223
2324 add_executable(
2425 tests
@@ -18,7 +18,8 @@ find_package(SQLite3 REQUIRED)
18 18
19 include_directories(${CMAKE_SOURCE_DIR}/include)19 include_directories(${CMAKE_SOURCE_DIR}/include)
20 enable_testing()20 enable_testing()
21-add_executable(fluffy src/main.cpp src/fluffyApplication.cpp src/gameRepository.cpp)21+add_executable(fluffy src/main.cpp src/fluffyApplication.cpp src/gameRepository.cpp
22+ include/commands/showCommand.hpp)
22 23
23 add_executable(24 add_executable(
24 tests25 tests
added app/include/command.hpp +12 -0
new file mode 100644
@@ -0,0 +1,12 @@
1+#pragma once
2+
3+#include <memory>
4+#include <iostream>
5+
6+#include <gameRepository.hpp>
7+
8+class Command {
9+ public:
10+ virtual void execute() = 0;
11+ virtual ~Command() {}
12+};
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,12 @@
1+#pragma once
2+
3+#include <memory>
4+#include <iostream>
5+
6+#include <gameRepository.hpp>
7+
8+class Command {
9+ public:
10+ virtual void execute() = 0;
11+ virtual ~Command() {}
12+};
\ No newline at end of file\ No newline at end of file
added app/include/commands/addCommand.hpp +49 -0
new file mode 100644
@@ -0,0 +1,49 @@
1+#pragma once
2+
3+#include <memory>
4+#include <iostream>
5+
6+#include <command.hpp>
7+#include <gameRepository.hpp>
8+
9+class AddCommand: public Command {
10+ private:
11+ std::weak_ptr<GameRepositoryInterface> gameRepository;
12+ std::string gameName;
13+ std::string path;
14+ public:
15+ AddCommand(
16+ std::weak_ptr<GameRepositoryInterface> gameRepository,
17+ std::string gameName,
18+ std::string path
19+ ) {
20+ this->gameRepository = gameRepository;
21+ this->gameName = gameName;
22+ this->path = path;
23+ }
24+
25+ void execute() override {
26+ auto localPath = std::filesystem::path(path);
27+ std::string globalPath =
28+ std::filesystem::absolute(localPath).lexically_normal().string();
29+ std::string temp{};
30+ for (const auto a : globalPath) {
31+ if (a != ' ') {
32+ temp += a;
33+ } else {
34+ temp += "\' \'";
35+ }
36+ }
37+ if (std::shared_ptr<GameRepositoryInterface> gr = gameRepository.lock()) {
38+ Game currentGame = gr->getGameByName(gameName);
39+ if (currentGame.getName().length() != 0) {
40+ std::cout << "Game already exist" << std::endl;
41+ // output->printMessage("Game already exist");
42+ }
43+ else {
44+ gr->addGame(gameName, temp);
45+ }
46+ }
47+
48+ }
49+};
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,49 @@
1+#pragma once
2+
3+#include <memory>
4+#include <iostream>
5+
6+#include <command.hpp>
7+#include <gameRepository.hpp>
8+
9+class AddCommand: public Command {
10+ private:
11+ std::weak_ptr<GameRepositoryInterface> gameRepository;
12+ std::string gameName;
13+ std::string path;
14+ public:
15+ AddCommand(
16+ std::weak_ptr<GameRepositoryInterface> gameRepository,
17+ std::string gameName,
18+ std::string path
19+ ) {
20+ this->gameRepository = gameRepository;
21+ this->gameName = gameName;
22+ this->path = path;
23+ }
24+
25+ void execute() override {
26+ auto localPath = std::filesystem::path(path);
27+ std::string globalPath =
28+ std::filesystem::absolute(localPath).lexically_normal().string();
29+ std::string temp{};
30+ for (const auto a : globalPath) {
31+ if (a != ' ') {
32+ temp += a;
33+ } else {
34+ temp += "\' \'";
35+ }
36+ }
37+ if (std::shared_ptr<GameRepositoryInterface> gr = gameRepository.lock()) {
38+ Game currentGame = gr->getGameByName(gameName);
39+ if (currentGame.getName().length() != 0) {
40+ std::cout << "Game already exist" << std::endl;
41+ // output->printMessage("Game already exist");
42+ }
43+ else {
44+ gr->addGame(gameName, temp);
45+ }
46+ }
47+
48+ }
49+};
\ No newline at end of file\ No newline at end of file
added app/include/commands/playCommand.hpp +33 -0
new file mode 100644
@@ -0,0 +1,33 @@
1+#pragma once
2+
3+#include <memory>
4+
5+#include <command.hpp>
6+#include <gameRepository.hpp>
7+
8+class PlayCommand: public Command {
9+ private:
10+ std::weak_ptr<GameRepositoryInterface> gameRepository;
11+ std::string gameName;
12+
13+ public:
14+ PlayCommand(
15+ std::weak_ptr<GameRepositoryInterface> gameRepository,
16+ std::string gameName
17+ ) {
18+ this->gameRepository = gameRepository;
19+ this->gameName = gameName;
20+ }
21+
22+ void execute() override {
23+ if (std::shared_ptr<GameRepositoryInterface> gr = gameRepository.lock()) {
24+ std::string pathToRun = gr->getGameByName(gameName).getPath();
25+ if(pathToRun.empty()) {
26+ std::cout << "no application found" << std::endl;
27+ }
28+ else {
29+ system(pathToRun.c_str());
30+ }
31+ }
32+ }
33+};
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,33 @@
1+#pragma once
2+
3+#include <memory>
4+
5+#include <command.hpp>
6+#include <gameRepository.hpp>
7+
8+class PlayCommand: public Command {
9+ private:
10+ std::weak_ptr<GameRepositoryInterface> gameRepository;
11+ std::string gameName;
12+
13+ public:
14+ PlayCommand(
15+ std::weak_ptr<GameRepositoryInterface> gameRepository,
16+ std::string gameName
17+ ) {
18+ this->gameRepository = gameRepository;
19+ this->gameName = gameName;
20+ }
21+
22+ void execute() override {
23+ if (std::shared_ptr<GameRepositoryInterface> gr = gameRepository.lock()) {
24+ std::string pathToRun = gr->getGameByName(gameName).getPath();
25+ if(pathToRun.empty()) {
26+ std::cout << "no application found" << std::endl;
27+ }
28+ else {
29+ system(pathToRun.c_str());
30+ }
31+ }
32+ }
33+};
\ No newline at end of file\ No newline at end of file
added app/include/commands/removeCommand.hpp +27 -0
new file mode 100644
@@ -0,0 +1,27 @@
1+#pragma once
2+
3+#include <memory>
4+#include <iostream>
5+
6+#include <command.hpp>
7+
8+
9+class RemoveCommand: public Command {
10+ private:
11+ std::weak_ptr<GameRepositoryInterface> gameRepository;
12+ std::string gameName;
13+ public:
14+ RemoveCommand(
15+ std::weak_ptr<GameRepositoryInterface> gameRepository,
16+ const std::string &gameName
17+ ) {
18+ this->gameRepository = gameRepository;
19+ this->gameName = gameName;
20+ }
21+
22+ void execute() override {
23+ if(std::shared_ptr<GameRepositoryInterface> gr = gameRepository.lock()) {
24+ gr->deleteGame(gameName);
25+ }
26+ }
27+};
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,27 @@
1+#pragma once
2+
3+#include <memory>
4+#include <iostream>
5+
6+#include <command.hpp>
7+
8+
9+class RemoveCommand: public Command {
10+ private:
11+ std::weak_ptr<GameRepositoryInterface> gameRepository;
12+ std::string gameName;
13+ public:
14+ RemoveCommand(
15+ std::weak_ptr<GameRepositoryInterface> gameRepository,
16+ const std::string &gameName
17+ ) {
18+ this->gameRepository = gameRepository;
19+ this->gameName = gameName;
20+ }
21+
22+ void execute() override {
23+ if(std::shared_ptr<GameRepositoryInterface> gr = gameRepository.lock()) {
24+ gr->deleteGame(gameName);
25+ }
26+ }
27+};
\ No newline at end of file\ No newline at end of file
added app/include/commands/showCommand.hpp +24 -0
new file mode 100644
@@ -0,0 +1,24 @@
1+#pragma once
2+
3+#include <memory>
4+#include <iostream>
5+
6+#include <command.hpp>
7+
8+
9+class ShowCommand: public Command {
10+ private:
11+ std::weak_ptr<GameRepositoryInterface> gameRepository;
12+ public:
13+ ShowCommand(std::weak_ptr<GameRepositoryInterface> gameRepository) {
14+ this->gameRepository = gameRepository;
15+ }
16+
17+ void execute() override {
18+ if (std::shared_ptr<GameRepositoryInterface> repository = gameRepository.lock()) {
19+ for (auto &game : repository->getGames()) {
20+ std::cout << game.getName() << ": " << game.getPath() << std::endl;
21+ }
22+ }
23+ }
24+};
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,24 @@
1+#pragma once
2+
3+#include <memory>
4+#include <iostream>
5+
6+#include <command.hpp>
7+
8+
9+class ShowCommand: public Command {
10+ private:
11+ std::weak_ptr<GameRepositoryInterface> gameRepository;
12+ public:
13+ ShowCommand(std::weak_ptr<GameRepositoryInterface> gameRepository) {
14+ this->gameRepository = gameRepository;
15+ }
16+
17+ void execute() override {
18+ if (std::shared_ptr<GameRepositoryInterface> repository = gameRepository.lock()) {
19+ for (auto &game : repository->getGames()) {
20+ std::cout << game.getName() << ": " << game.getPath() << std::endl;
21+ }
22+ }
23+ }
24+};
\ No newline at end of file\ No newline at end of file
modified app/include/fluffyApplication.hpp +7 -4
@@ -16,15 +16,20 @@
1616 #include <database.hpp>
1717 #include <output.hpp>
1818 #include <gameRepository.hpp>
19+#include <command.hpp>
20+#include <commands/showCommand.hpp>
21+#include <commands/removeCommand.hpp>
22+#include <commands/playCommand.hpp>
23+#include <commands/addCommand.hpp>
1924
2025 class FluffyApplication {
2126 public:
2227 FluffyApplication(int argc, char const *argv[]);
2328
2429 private:
25- std::unique_ptr<GameRepositoryInterface> gameRepository = nullptr;
30+ std::shared_ptr<GameRepositoryInterface> gameRepository = nullptr;
2631 std::shared_ptr<Output> output{};
27- std::string version{ "v0.1.3" };
32+ std::string version{ "v0.1.4" };
2833 std::string helpMessage{
2934 "usage: fluffy [--flag | <command> <args>]\n\
3035 fluffy flags:\n\
@@ -36,8 +41,6 @@ fluffy commands:\n\
3641 show Show all games added to library\n\
3742 rm <game_name> Remove game from a library"};
3843
39- auto addGame(std::string name, std::string path) -> void;
40-
4144 auto removeGame(Database& database, std::string name) -> void;
4245
4346 auto runGame(std::string gameName) -> void;
@@ -16,15 +16,20 @@
16 #include <database.hpp>16 #include <database.hpp>
17 #include <output.hpp>17 #include <output.hpp>
18 #include <gameRepository.hpp>18 #include <gameRepository.hpp>
19+#include <command.hpp>
20+#include <commands/showCommand.hpp>
21+#include <commands/removeCommand.hpp>
22+#include <commands/playCommand.hpp>
23+#include <commands/addCommand.hpp>
19 24
20 class FluffyApplication {25 class FluffyApplication {
21 public:26 public:
22 FluffyApplication(int argc, char const *argv[]);27 FluffyApplication(int argc, char const *argv[]);
23 28
24 private:29 private:
25- std::unique_ptr<GameRepositoryInterface> gameRepository = nullptr;30+ std::shared_ptr<GameRepositoryInterface> gameRepository = nullptr;
26 std::shared_ptr<Output> output{};31 std::shared_ptr<Output> output{};
27- std::string version{ "v0.1.3" };32+ std::string version{ "v0.1.4" };
28 std::string helpMessage{33 std::string helpMessage{
29 "usage: fluffy [--flag | <command> <args>]\n\34 "usage: fluffy [--flag | <command> <args>]\n\
30 fluffy flags:\n\35 fluffy flags:\n\
@@ -36,8 +41,6 @@ fluffy commands:\n\
36 show Show all games added to library\n\41 show Show all games added to library\n\
37 rm <game_name> Remove game from a library"};42 rm <game_name> Remove game from a library"};
38 43
39- auto addGame(std::string name, std::string path) -> void;
40-
41 auto removeGame(Database& database, std::string name) -> void;44 auto removeGame(Database& database, std::string name) -> void;
42 45
43 auto runGame(std::string gameName) -> void;46 auto runGame(std::string gameName) -> void;
modified app/src/fluffyApplication.cpp +10 -36
@@ -17,27 +17,24 @@ auto FluffyApplication::handleCommand(
1717 const std::vector<std::string>& arguments
1818 ) -> void {
1919 if (command == "show") {
20- for (auto &game : gameRepository->getGames()) {
21- std::cout << game.getName() << ": " << game.getPath() << std::endl;
22- }
23- }
24- else if (command == "only-games") {
25- for (auto &game : gameRepository->getGames()) {
26- std::cout << game.getName() << std::endl;
27- }
20+ ShowCommand showCommand = ShowCommand(gameRepository);
21+ showCommand.execute();
2822 }
2923 else if (command == "rm") {
30- std::string gameName{arguments[0]};
31- gameRepository->deleteGame(gameName);
24+ std::string gameName = arguments[0];
25+ RemoveCommand removeCommand = RemoveCommand(gameRepository, gameName);
26+ removeCommand.execute();
3227 }
3328 else if (command == "add") {
3429 std::string gameName = arguments[0];
3530 std::string gamePath = arguments[1];
36- this->addGame(gameName, gamePath);
31+ AddCommand addCommand = AddCommand(gameRepository, gameName, gamePath);
32+ addCommand.execute();
3733 }
3834 else if (command == "play") {
3935 std::string gameName{arguments[0]};
40- runGame(gameName);
36+ PlayCommand playCommand = PlayCommand(gameRepository, gameName);
37+ playCommand.execute();
4138 }
4239 else if (command == "--version") {
4340 output->printMessage("fluffy " + version);
@@ -50,29 +47,6 @@ auto FluffyApplication::handleCommand(
5047 }
5148 }
5249
53-auto FluffyApplication::addGame(std::string name, std::string path) -> void {
54- std::string gameName{name};
55- auto localPath = std::filesystem::path(path);
56- std::string globalPath =
57- std::filesystem::absolute(localPath).lexically_normal().string();
58- std::string temp{};
59- for (const auto a : globalPath) {
60- if (a != ' ') {
61- temp += a;
62- } else {
63- temp += "\' \'";
64- }
65- }
66- Game currentGame = gameRepository->getGameByName(gameName);
67- if (currentGame.getName().length() != 0) {
68- output->printMessage("Game already exist");
69- }
70- else {
71- gameRepository->addGame(gameName, temp);
72- }
73-
74-}
75-
7650 auto FluffyApplication::handleFlags(std::vector<std::string> flags) -> void {
7751 for (const auto& flag : flags) {
7852 if (flag == "-d") {
@@ -120,7 +94,7 @@ FluffyApplication::FluffyApplication(int argc, char const *argv[]) {
12094
12195 auto databasePath{ std::filesystem::path(getExecutablePath().parent_path().string() + "/data.db") };
12296
123- gameRepository = std::make_unique<GameRepository>(
97+ gameRepository = std::make_shared<GameRepository>(
12498 std::make_unique<Database>(databasePath, output)
12599 );
126100
@@ -17,27 +17,24 @@ auto FluffyApplication::handleCommand(
17 const std::vector<std::string>& arguments17 const std::vector<std::string>& arguments
18 ) -> void {18 ) -> void {
19 if (command == "show") {19 if (command == "show") {
20- for (auto &game : gameRepository->getGames()) {20+ ShowCommand showCommand = ShowCommand(gameRepository);
21- std::cout << game.getName() << ": " << game.getPath() << std::endl;21+ showCommand.execute();
22- }
23- }
24- else if (command == "only-games") {
25- for (auto &game : gameRepository->getGames()) {
26- std::cout << game.getName() << std::endl;
27- }
28 }22 }
29 else if (command == "rm") {23 else if (command == "rm") {
30- std::string gameName{arguments[0]};24+ std::string gameName = arguments[0];
31- gameRepository->deleteGame(gameName);25+ RemoveCommand removeCommand = RemoveCommand(gameRepository, gameName);
26+ removeCommand.execute();
32 }27 }
33 else if (command == "add") {28 else if (command == "add") {
34 std::string gameName = arguments[0];29 std::string gameName = arguments[0];
35 std::string gamePath = arguments[1];30 std::string gamePath = arguments[1];
36- this->addGame(gameName, gamePath);31+ AddCommand addCommand = AddCommand(gameRepository, gameName, gamePath);
32+ addCommand.execute();
37 }33 }
38 else if (command == "play") {34 else if (command == "play") {
39 std::string gameName{arguments[0]};35 std::string gameName{arguments[0]};
40- runGame(gameName);36+ PlayCommand playCommand = PlayCommand(gameRepository, gameName);
37+ playCommand.execute();
41 }38 }
42 else if (command == "--version") {39 else if (command == "--version") {
43 output->printMessage("fluffy " + version);40 output->printMessage("fluffy " + version);
@@ -50,29 +47,6 @@ auto FluffyApplication::handleCommand(
50 }47 }
51 }48 }
52 49
53-auto FluffyApplication::addGame(std::string name, std::string path) -> void {
54- std::string gameName{name};
55- auto localPath = std::filesystem::path(path);
56- std::string globalPath =
57- std::filesystem::absolute(localPath).lexically_normal().string();
58- std::string temp{};
59- for (const auto a : globalPath) {
60- if (a != ' ') {
61- temp += a;
62- } else {
63- temp += "\' \'";
64- }
65- }
66- Game currentGame = gameRepository->getGameByName(gameName);
67- if (currentGame.getName().length() != 0) {
68- output->printMessage("Game already exist");
69- }
70- else {
71- gameRepository->addGame(gameName, temp);
72- }
73-
74-}
75-
76 auto FluffyApplication::handleFlags(std::vector<std::string> flags) -> void {50 auto FluffyApplication::handleFlags(std::vector<std::string> flags) -> void {
77 for (const auto& flag : flags) {51 for (const auto& flag : flags) {
78 if (flag == "-d") {52 if (flag == "-d") {
@@ -120,7 +94,7 @@ FluffyApplication::FluffyApplication(int argc, char const *argv[]) {
120 94
121 auto databasePath{ std::filesystem::path(getExecutablePath().parent_path().string() + "/data.db") };95 auto databasePath{ std::filesystem::path(getExecutablePath().parent_path().string() + "/data.db") };
122 96
123- gameRepository = std::make_unique<GameRepository>(97+ gameRepository = std::make_shared<GameRepository>(
124 std::make_unique<Database>(databasePath, output)98 std::make_unique<Database>(databasePath, output)
125 );99 );
126 100