36 create game repository #37
Merged@github-juk3n wants to merge
36-create-game-repository into mainMerged as
9e2b7d493199.7 files changed
modified
app/CMakeLists.txt +1 -1 | @@ -18,7 +18,7 @@ find_package(SQLite3 REQUIRED) | ||
| 18 | 18 | |
| 19 | 19 | include_directories(${CMAKE_SOURCE_DIR}/include) |
| 20 | 20 | enable_testing() |
| 21 | -add_executable(fluffy src/main.cpp src/fluffyApplication.cpp) | |
| 21 | +add_executable(fluffy src/main.cpp src/fluffyApplication.cpp src/gameRepository.cpp) | |
| 22 | 22 | |
| 23 | 23 | add_executable( |
| 24 | 24 | tests |
| @@ -18,7 +18,7 @@ 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) | 21 | +add_executable(fluffy src/main.cpp src/fluffyApplication.cpp src/gameRepository.cpp) |
| 22 | 22 | ||
| 23 | add_executable( | 23 | add_executable( |
| 24 | tests | 24 | tests |
modified
app/include/database.hpp +1 -0 | @@ -3,6 +3,7 @@ | ||
| 3 | 3 | #include <sqlite3.h> |
| 4 | 4 | #include <string> |
| 5 | 5 | #include <memory> |
| 6 | +#include <filesystem> | |
| 6 | 7 | |
| 7 | 8 | #include <game.hpp> |
| 8 | 9 | #include <output.hpp> |
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <sqlite3.h> | 3 | #include <sqlite3.h> |
| 4 | #include <string> | 4 | #include <string> |
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | +#include <filesystem> | ||
| 6 | 7 | ||
| 7 | #include <game.hpp> | 8 | #include <game.hpp> |
| 8 | #include <output.hpp> | 9 | #include <output.hpp> |
modified
app/include/fluffyApplication.hpp +5 -3 | @@ -10,27 +10,29 @@ | ||
| 10 | 10 | #include <unistd.h> |
| 11 | 11 | #include <limits.h> |
| 12 | 12 | #include <memory> |
| 13 | +#include <filesystem> | |
| 13 | 14 | |
| 14 | 15 | #include <game.hpp> |
| 15 | 16 | #include <database.hpp> |
| 16 | 17 | #include <output.hpp> |
| 18 | +#include <gameRepository.hpp> | |
| 17 | 19 | |
| 18 | 20 | class FluffyApplication { |
| 19 | 21 | public: |
| 20 | 22 | FluffyApplication(int argc, char const *argv[]); |
| 21 | 23 | |
| 22 | 24 | private: |
| 25 | + std::unique_ptr<GameRepositoryInterface> gameRepository = nullptr; | |
| 23 | 26 | std::shared_ptr<Output> output{}; |
| 24 | 27 | std::string version{ "v0.1.3" }; |
| 25 | - std::vector<Game> games; | |
| 26 | - | |
| 28 | + | |
| 27 | 29 | auto addGame(Database& database, std::string name, std::string path) -> void; |
| 28 | 30 | |
| 29 | 31 | auto removeGame(Database& database, std::string name) -> void; |
| 30 | 32 | |
| 31 | 33 | auto runGame(std::string gameName) -> void; |
| 32 | 34 | |
| 33 | - auto handleCommand(const std::string& command, const std::vector<std::string>& arguments, Database& database) -> void; | |
| 35 | + auto handleCommand(const std::string& command, const std::vector<std::string>& arguments) -> void; | |
| 34 | 36 | |
| 35 | 37 | auto handleFlags(std::vector<std::string> flags) -> void; |
| 36 | 38 | |
| @@ -10,27 +10,29 @@ | |||
| 10 | #include <unistd.h> | 10 | #include <unistd.h> |
| 11 | #include <limits.h> | 11 | #include <limits.h> |
| 12 | #include <memory> | 12 | #include <memory> |
| 13 | +#include <filesystem> | ||
| 13 | 14 | ||
| 14 | #include <game.hpp> | 15 | #include <game.hpp> |
| 15 | #include <database.hpp> | 16 | #include <database.hpp> |
| 16 | #include <output.hpp> | 17 | #include <output.hpp> |
| 18 | +#include <gameRepository.hpp> | ||
| 17 | 19 | ||
| 18 | class FluffyApplication { | 20 | class FluffyApplication { |
| 19 | public: | 21 | public: |
| 20 | FluffyApplication(int argc, char const *argv[]); | 22 | FluffyApplication(int argc, char const *argv[]); |
| 21 | 23 | ||
| 22 | private: | 24 | private: |
| 25 | + std::unique_ptr<GameRepositoryInterface> gameRepository = nullptr; | ||
| 23 | std::shared_ptr<Output> output{}; | 26 | std::shared_ptr<Output> output{}; |
| 24 | std::string version{ "v0.1.3" }; | 27 | std::string version{ "v0.1.3" }; |
| 25 | - std::vector<Game> games; | 28 | + |
| 26 | - | ||
| 27 | auto addGame(Database& database, std::string name, std::string path) -> void; | 29 | auto addGame(Database& database, std::string name, std::string path) -> void; |
| 28 | 30 | ||
| 29 | auto removeGame(Database& database, std::string name) -> void; | 31 | auto removeGame(Database& database, std::string name) -> void; |
| 30 | 32 | ||
| 31 | auto runGame(std::string gameName) -> void; | 33 | auto runGame(std::string gameName) -> void; |
| 32 | 34 | ||
| 33 | - auto handleCommand(const std::string& command, const std::vector<std::string>& arguments, Database& database) -> void; | 35 | + auto handleCommand(const std::string& command, const std::vector<std::string>& arguments) -> void; |
| 34 | 36 | ||
| 35 | auto handleFlags(std::vector<std::string> flags) -> void; | 37 | auto handleFlags(std::vector<std::string> flags) -> void; |
| 36 | 38 | ||
added
app/include/gameRepository.hpp +23 -0 | new file mode 100644 | ||
| @@ -0,0 +1,23 @@ | ||
| 1 | +#pragma once | |
| 2 | + | |
| 3 | +#include "gameRepositoryInterface.hpp" | |
| 4 | +#include "database.hpp" | |
| 5 | + | |
| 6 | +#include <vector> | |
| 7 | +#include <memory> | |
| 8 | + | |
| 9 | +class GameRepository : public GameRepositoryInterface { | |
| 10 | +private: | |
| 11 | + std::unique_ptr<Database> database = nullptr; | |
| 12 | + | |
| 13 | +public: | |
| 14 | + GameRepository(std::unique_ptr<Database> database); | |
| 15 | + | |
| 16 | + void addGame(const std::string &name, const std::string &path); | |
| 17 | + | |
| 18 | + Game getGameByName(const std::string& name); | |
| 19 | + | |
| 20 | + std::vector<Game> getGames(); | |
| 21 | + | |
| 22 | + void deleteGame(const std::string& name); | |
| 23 | +}; | |
| \ No newline at end of file | ||
| new file mode 100644 | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | +#pragma once | ||
| 2 | + | ||
| 3 | +#include "gameRepositoryInterface.hpp" | ||
| 4 | +#include "database.hpp" | ||
| 5 | + | ||
| 6 | +#include <vector> | ||
| 7 | +#include <memory> | ||
| 8 | + | ||
| 9 | +class GameRepository : public GameRepositoryInterface { | ||
| 10 | +private: | ||
| 11 | + std::unique_ptr<Database> database = nullptr; | ||
| 12 | + | ||
| 13 | +public: | ||
| 14 | + GameRepository(std::unique_ptr<Database> database); | ||
| 15 | + | ||
| 16 | + void addGame(const std::string &name, const std::string &path); | ||
| 17 | + | ||
| 18 | + Game getGameByName(const std::string& name); | ||
| 19 | + | ||
| 20 | + std::vector<Game> getGames(); | ||
| 21 | + | ||
| 22 | + void deleteGame(const std::string& name); | ||
| 23 | +}; | ||
| \ No newline at end of file | \ No newline at end of file | ||
added
app/include/gameRepositoryInterface.hpp +16 -0 | new file mode 100644 | ||
| @@ -0,0 +1,16 @@ | ||
| 1 | +#pragma once | |
| 2 | + | |
| 3 | +#include "game.hpp" | |
| 4 | + | |
| 5 | +#include <vector> | |
| 6 | + | |
| 7 | +class GameRepositoryInterface { | |
| 8 | +public: | |
| 9 | + virtual void addGame(const std::string &name, const std::string &path) = 0; | |
| 10 | + | |
| 11 | + virtual Game getGameByName(const std::string& name) = 0; | |
| 12 | + | |
| 13 | + virtual std::vector<Game> getGames() = 0; | |
| 14 | + | |
| 15 | + virtual void deleteGame(const std::string& name) = 0; | |
| 16 | +}; | |
| \ No newline at end of file | ||
| new file mode 100644 | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | +#pragma once | ||
| 2 | + | ||
| 3 | +#include "game.hpp" | ||
| 4 | + | ||
| 5 | +#include <vector> | ||
| 6 | + | ||
| 7 | +class GameRepositoryInterface { | ||
| 8 | +public: | ||
| 9 | + virtual void addGame(const std::string &name, const std::string &path) = 0; | ||
| 10 | + | ||
| 11 | + virtual Game getGameByName(const std::string& name) = 0; | ||
| 12 | + | ||
| 13 | + virtual std::vector<Game> getGames() = 0; | ||
| 14 | + | ||
| 15 | + virtual void deleteGame(const std::string& name) = 0; | ||
| 16 | +}; | ||
| \ No newline at end of file | \ No newline at end of file | ||
modified
app/src/fluffyApplication.cpp +18 -31 | @@ -2,38 +2,23 @@ | ||
| 2 | 2 | |
| 3 | 3 | #include <iostream> |
| 4 | 4 | |
| 5 | -auto FluffyApplication::addGame(Database& database, std::string name, std::string path) -> void { | |
| 6 | - std::string command = | |
| 7 | - "INSERT INTO games (GAME_NAME, GAME_PATH) VALUES ("; | |
| 8 | - command += "'" + name + "', \"" + path + "\");"; | |
| 9 | - database.executeSqlCommand(command); | |
| 10 | -} | |
| 11 | - | |
| 12 | -auto FluffyApplication::removeGame(Database& database, std::string name) -> void{ | |
| 13 | - std::string command = "DELETE FROM games WHERE GAME_NAME="; | |
| 14 | - command += "'" + name + "';"; | |
| 15 | - database.executeSqlCommand(command); | |
| 16 | -} | |
| 17 | - | |
| 18 | 5 | auto FluffyApplication::runGame(std::string gameName) -> void { |
| 19 | - std::string pathToRun = ""; | |
| 20 | - for (auto &game : games) { | |
| 21 | - if (gameName == game.getName()) { | |
| 22 | - pathToRun = game.getPath(); | |
| 23 | - } | |
| 24 | - } | |
| 6 | + std::string pathToRun = gameRepository->getGameByName(gameName).getPath(); | |
| 25 | 7 | system(pathToRun.c_str()); |
| 26 | 8 | } |
| 27 | 9 | |
| 28 | -auto FluffyApplication::handleCommand(const std::string& command, const std::vector<std::string>& arguments, Database& database) -> void{ | |
| 10 | +auto FluffyApplication::handleCommand( | |
| 11 | + const std::string& command, | |
| 12 | + const std::vector<std::string>& arguments | |
| 13 | +) -> void { | |
| 29 | 14 | if (command == "show") { |
| 30 | - for (auto &game : games) { | |
| 15 | + for (auto &game : gameRepository->getGames()) { | |
| 31 | 16 | std::cout << game.getName() << ": " << game.getPath() << std::endl; |
| 32 | 17 | } |
| 33 | 18 | } |
| 34 | 19 | else if (command == "rm") { |
| 35 | 20 | std::string gameName{arguments[0]}; |
| 36 | - removeGame(database, gameName); | |
| 21 | + gameRepository->deleteGame(gameName); | |
| 37 | 22 | } |
| 38 | 23 | else if (command == "add") { |
| 39 | 24 | std::string gameName{arguments[0]}; |
| @@ -49,7 +34,7 @@ auto FluffyApplication::handleCommand(const std::string& command, const std::vec | ||
| 49 | 34 | } |
| 50 | 35 | } |
| 51 | 36 | |
| 52 | - addGame(database, gameName, temp); | |
| 37 | + gameRepository->addGame(gameName, temp); | |
| 53 | 38 | } |
| 54 | 39 | else if (command == "play") { |
| 55 | 40 | std::string gameName{arguments[0]}; |
| @@ -74,10 +59,10 @@ auto FluffyApplication::handleCommand(const std::string& command, const std::vec | ||
| 74 | 59 | auto FluffyApplication::handleFlags(std::vector<std::string> flags) -> void { |
| 75 | 60 | for (const auto& flag : flags) { |
| 76 | 61 | if (flag == "-d") { |
| 77 | - output->turnOnDebug(); | |
| 62 | + output->turnOnDebug(); | |
| 78 | 63 | } |
| 79 | 64 | else { |
| 80 | - output->printMessage("unkown option: '" + flag + "'"); | |
| 65 | + output->printMessage("unkown option: '" + flag + "'"); | |
| 81 | 66 | } |
| 82 | 67 | } |
| 83 | 68 | } |
| @@ -115,18 +100,20 @@ auto FluffyApplication::parseCommand(int argc, char const* argv[]) { | ||
| 115 | 100 | |
| 116 | 101 | FluffyApplication::FluffyApplication(int argc, char const *argv[]) { |
| 117 | 102 | output = std::make_shared<Output>(); |
| 118 | - auto flags = parseFlags(argc, argv); | |
| 119 | - handleFlags(flags); | |
| 120 | 103 | |
| 121 | 104 | auto databasePath{ std::filesystem::path(getExecutablePath().parent_path().string() + "/data.db") }; |
| 122 | - Database database{databasePath, output}; | |
| 123 | - games = database.getGames(); | |
| 105 | + | |
| 106 | + gameRepository = std::make_unique<GameRepository>( | |
| 107 | + std::make_unique<Database>(databasePath, output) | |
| 108 | + ); | |
| 124 | 109 | |
| 110 | + auto flags = parseFlags(argc, argv); | |
| 111 | + handleFlags(flags); | |
| 125 | 112 | if (argc - flags.size() > 1) { |
| 126 | 113 | auto [command, arguments] = parseCommand(argc, argv); |
| 127 | - if (command != "") handleCommand(command, arguments, database); | |
| 114 | + if (command != "") handleCommand(command, arguments); | |
| 128 | 115 | } |
| 129 | 116 | else { |
| 130 | - handleCommand("--help", {}, database); | |
| 117 | + handleCommand("--help", {}); | |
| 131 | 118 | } |
| 132 | 119 | } |
| @@ -2,38 +2,23 @@ | |||
| 2 | 2 | ||
| 3 | #include <iostream> | 3 | #include <iostream> |
| 4 | 4 | ||
| 5 | -auto FluffyApplication::addGame(Database& database, std::string name, std::string path) -> void { | ||
| 6 | - std::string command = | ||
| 7 | - "INSERT INTO games (GAME_NAME, GAME_PATH) VALUES ("; | ||
| 8 | - command += "'" + name + "', \"" + path + "\");"; | ||
| 9 | - database.executeSqlCommand(command); | ||
| 10 | -} | ||
| 11 | - | ||
| 12 | -auto FluffyApplication::removeGame(Database& database, std::string name) -> void{ | ||
| 13 | - std::string command = "DELETE FROM games WHERE GAME_NAME="; | ||
| 14 | - command += "'" + name + "';"; | ||
| 15 | - database.executeSqlCommand(command); | ||
| 16 | -} | ||
| 17 | - | ||
| 18 | auto FluffyApplication::runGame(std::string gameName) -> void { | 5 | auto FluffyApplication::runGame(std::string gameName) -> void { |
| 19 | - std::string pathToRun = ""; | 6 | + std::string pathToRun = gameRepository->getGameByName(gameName).getPath(); |
| 20 | - for (auto &game : games) { | ||
| 21 | - if (gameName == game.getName()) { | ||
| 22 | - pathToRun = game.getPath(); | ||
| 23 | - } | ||
| 24 | - } | ||
| 25 | system(pathToRun.c_str()); | 7 | system(pathToRun.c_str()); |
| 26 | } | 8 | } |
| 27 | 9 | ||
| 28 | -auto FluffyApplication::handleCommand(const std::string& command, const std::vector<std::string>& arguments, Database& database) -> void{ | 10 | +auto FluffyApplication::handleCommand( |
| 11 | + const std::string& command, | ||
| 12 | + const std::vector<std::string>& arguments | ||
| 13 | +) -> void { | ||
| 29 | if (command == "show") { | 14 | if (command == "show") { |
| 30 | - for (auto &game : games) { | 15 | + for (auto &game : gameRepository->getGames()) { |
| 31 | std::cout << game.getName() << ": " << game.getPath() << std::endl; | 16 | std::cout << game.getName() << ": " << game.getPath() << std::endl; |
| 32 | } | 17 | } |
| 33 | } | 18 | } |
| 34 | else if (command == "rm") { | 19 | else if (command == "rm") { |
| 35 | std::string gameName{arguments[0]}; | 20 | std::string gameName{arguments[0]}; |
| 36 | - removeGame(database, gameName); | 21 | + gameRepository->deleteGame(gameName); |
| 37 | } | 22 | } |
| 38 | else if (command == "add") { | 23 | else if (command == "add") { |
| 39 | std::string gameName{arguments[0]}; | 24 | std::string gameName{arguments[0]}; |
| @@ -49,7 +34,7 @@ auto FluffyApplication::handleCommand(const std::string& command, const std::vec | |||
| 49 | } | 34 | } |
| 50 | } | 35 | } |
| 51 | 36 | ||
| 52 | - addGame(database, gameName, temp); | 37 | + gameRepository->addGame(gameName, temp); |
| 53 | } | 38 | } |
| 54 | else if (command == "play") { | 39 | else if (command == "play") { |
| 55 | std::string gameName{arguments[0]}; | 40 | std::string gameName{arguments[0]}; |
| @@ -74,10 +59,10 @@ auto FluffyApplication::handleCommand(const std::string& command, const std::vec | |||
| 74 | auto FluffyApplication::handleFlags(std::vector<std::string> flags) -> void { | 59 | auto FluffyApplication::handleFlags(std::vector<std::string> flags) -> void { |
| 75 | for (const auto& flag : flags) { | 60 | for (const auto& flag : flags) { |
| 76 | if (flag == "-d") { | 61 | if (flag == "-d") { |
| 77 | - output->turnOnDebug(); | 62 | + output->turnOnDebug(); |
| 78 | } | 63 | } |
| 79 | else { | 64 | else { |
| 80 | - output->printMessage("unkown option: '" + flag + "'"); | 65 | + output->printMessage("unkown option: '" + flag + "'"); |
| 81 | } | 66 | } |
| 82 | } | 67 | } |
| 83 | } | 68 | } |
| @@ -115,18 +100,20 @@ auto FluffyApplication::parseCommand(int argc, char const* argv[]) { | |||
| 115 | 100 | ||
| 116 | FluffyApplication::FluffyApplication(int argc, char const *argv[]) { | 101 | FluffyApplication::FluffyApplication(int argc, char const *argv[]) { |
| 117 | output = std::make_shared<Output>(); | 102 | output = std::make_shared<Output>(); |
| 118 | - auto flags = parseFlags(argc, argv); | ||
| 119 | - handleFlags(flags); | ||
| 120 | 103 | ||
| 121 | auto databasePath{ std::filesystem::path(getExecutablePath().parent_path().string() + "/data.db") }; | 104 | auto databasePath{ std::filesystem::path(getExecutablePath().parent_path().string() + "/data.db") }; |
| 122 | - Database database{databasePath, output}; | 105 | + |
| 123 | - games = database.getGames(); | 106 | + gameRepository = std::make_unique<GameRepository>( |
| 107 | + std::make_unique<Database>(databasePath, output) | ||
| 108 | + ); | ||
| 124 | 109 | ||
| 110 | + auto flags = parseFlags(argc, argv); | ||
| 111 | + handleFlags(flags); | ||
| 125 | if (argc - flags.size() > 1) { | 112 | if (argc - flags.size() > 1) { |
| 126 | auto [command, arguments] = parseCommand(argc, argv); | 113 | auto [command, arguments] = parseCommand(argc, argv); |
| 127 | - if (command != "") handleCommand(command, arguments, database); | 114 | + if (command != "") handleCommand(command, arguments); |
| 128 | } | 115 | } |
| 129 | else { | 116 | else { |
| 130 | - handleCommand("--help", {}, database); | 117 | + handleCommand("--help", {}); |
| 131 | } | 118 | } |
| 132 | } | 119 | } |
added
app/src/gameRepository.cpp +37 -0 | new file mode 100644 | ||
| @@ -0,0 +1,37 @@ | ||
| 1 | +#include "gameRepository.hpp" | |
| 2 | + | |
| 3 | +GameRepository::GameRepository(std::unique_ptr<Database> database) | |
| 4 | +{ | |
| 5 | + this->database = std::move(database); | |
| 6 | +} | |
| 7 | + | |
| 8 | +void GameRepository::addGame(const std::string &name, const std::string &path) | |
| 9 | +{ | |
| 10 | + std::string command = | |
| 11 | + "INSERT INTO games (GAME_NAME, GAME_PATH) VALUES ("; | |
| 12 | + command += "'" + name + "', \"" + path + "\");"; | |
| 13 | + this->database->executeSqlCommand(command); | |
| 14 | +} | |
| 15 | + | |
| 16 | +Game GameRepository::getGameByName(const std::string &name) | |
| 17 | +{ | |
| 18 | + auto games = this->database->getGames(); | |
| 19 | + for (auto &game : games) { | |
| 20 | + if (name == game.getName()) { | |
| 21 | + return game; | |
| 22 | + } | |
| 23 | + } | |
| 24 | + return Game(0, "", ""); | |
| 25 | +} | |
| 26 | + | |
| 27 | +std::vector<Game> GameRepository::getGames() | |
| 28 | +{ | |
| 29 | + return this->database->getGames(); | |
| 30 | +} | |
| 31 | + | |
| 32 | +void GameRepository::deleteGame(const std::string &name) | |
| 33 | +{ | |
| 34 | + std::string command = "DELETE FROM games WHERE GAME_NAME="; | |
| 35 | + command += "'" + name + "';"; | |
| 36 | + this->database->executeSqlCommand(command); | |
| 37 | +} | |
| \ No newline at end of file | ||
| new file mode 100644 | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | +#include "gameRepository.hpp" | ||
| 2 | + | ||
| 3 | +GameRepository::GameRepository(std::unique_ptr<Database> database) | ||
| 4 | +{ | ||
| 5 | + this->database = std::move(database); | ||
| 6 | +} | ||
| 7 | + | ||
| 8 | +void GameRepository::addGame(const std::string &name, const std::string &path) | ||
| 9 | +{ | ||
| 10 | + std::string command = | ||
| 11 | + "INSERT INTO games (GAME_NAME, GAME_PATH) VALUES ("; | ||
| 12 | + command += "'" + name + "', \"" + path + "\");"; | ||
| 13 | + this->database->executeSqlCommand(command); | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +Game GameRepository::getGameByName(const std::string &name) | ||
| 17 | +{ | ||
| 18 | + auto games = this->database->getGames(); | ||
| 19 | + for (auto &game : games) { | ||
| 20 | + if (name == game.getName()) { | ||
| 21 | + return game; | ||
| 22 | + } | ||
| 23 | + } | ||
| 24 | + return Game(0, "", ""); | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +std::vector<Game> GameRepository::getGames() | ||
| 28 | +{ | ||
| 29 | + return this->database->getGames(); | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +void GameRepository::deleteGame(const std::string &name) | ||
| 33 | +{ | ||
| 34 | + std::string command = "DELETE FROM games WHERE GAME_NAME="; | ||
| 35 | + command += "'" + name + "';"; | ||
| 36 | + this->database->executeSqlCommand(command); | ||
| 37 | +} | ||
| \ No newline at end of file | \ No newline at end of file | ||