diff --git a/application.cpp b/application.cpp index 18d6a6e..33258d6 100644 --- a/application.cpp +++ b/application.cpp @@ -10,10 +10,10 @@ Application::Application() : render_window({SCREEN_WIDTH, SCREEN_HEIGHT}, "Sliding Puzzle") {} -bool Application::init(int splitting, const std::string &path) +bool Application::init(const std::string &path, int splitting) { render_window.setFramerateLimit(60); - return board.init(splitting, path); + return board.init(path, splitting); } void Application::run() diff --git a/application.h b/application.h index 1b0e2bc..5f26532 100644 --- a/application.h +++ b/application.h @@ -9,7 +9,7 @@ public: explicit Application(); // Init game - bool init(int splitting, const std::string& path); + bool init(const std::string& path, int splitting); // Launch game void run(); diff --git a/board.cpp b/board.cpp index 265b356..299090e 100644 --- a/board.cpp +++ b/board.cpp @@ -157,18 +157,18 @@ bool Board::isWinCondition() const return std::all_of(vec_field.begin(), vec_field.end(), [](const Cell *cell){ return cell->current_index == cell->inital_index; }); } -bool Board::init(int splitting, const std::string& path) +bool Board::init(const std::string& path, int splitting) { // PREPARING INITIAL BOARD STATE // if (!global_texture.loadFromFile(path) ) - return EXIT_FAILURE; + return false; if (splitting <= 1) // If it's 1, the game is already over { sf::Sprite* sp = new sf::Sprite(global_texture); vec_field.push_back(new Cell{0, 0, sp}); - return EXIT_SUCCESS; // why not + return true; // why not } const int width = global_texture.getSize().x; @@ -218,7 +218,7 @@ bool Board::init(int splitting, const std::string& path) // Set initial position of cursor setSelectionVertex(selection_index); - return EXIT_SUCCESS; + return true; } int Board::Cell::side_length = 0; diff --git a/board.h b/board.h index 1e83106..ff4c4b7 100644 --- a/board.h +++ b/board.h @@ -39,7 +39,7 @@ public: bool isWinCondition() const; // Set play image - bool init(int splitting, const std::string& path); + bool init(const std::string& path, int splitting); private: diff --git a/filepath_util.h b/filepath_util.h index 91f3df6..dd7ef04 100644 --- a/filepath_util.h +++ b/filepath_util.h @@ -7,10 +7,19 @@ #include #include -static std::tuple file_info(const std::filesystem::directory_entry& entry) +namespace filepath { - const auto fs (std::filesystem::status(entry)); - return {entry.path(), - fs, - std::filesystem::is_regular_file(fs) ? std::filesystem::file_size(entry.path()) : 0u}; + static std::tuple getFileInfo(const std::filesystem::directory_entry& entry) + { + const auto file_status (std::filesystem::status(entry)); + return {entry.path(), file_status}; + } + + static bool endsWith(const std::string& string, const std::string& ending) + { + if (ending.size() > string.size()) + return false; + + return std::equal(ending.rbegin(), ending.rend(), string.rbegin()); + } } diff --git a/main.cpp b/main.cpp index f666eb8..da3bae7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,38 +1,111 @@ #include "application.h" #include "output_util.h" +#include "filepath_util.h" #include #include #include +#include -constexpr static int MIN_ARGC = 2; -constexpr static int MAX_ARGC = 4; +///////////////////////////////////////////////////////////////////////// + +static constexpr int NO_ARGC = 1; +static constexpr int MIN_ARGC = 2; +static constexpr int MAX_ARGC = 4; +static constexpr int DEFAULT_SPLITTING = 5; +static const std::string DEFAULT_PATH = "."; // current folder, I guess + +///////////////////////////////////////////////////////////////////////// static std::tuple error(const char* msg) { std::cout << msg; - return {EXIT_FAILURE, 0, {}}; + return {EXIT_FAILURE, -1, {}}; +} + +static std::tuple parsePath(const std::string &argv) +{ + std::filesystem::path path(argv); + if (!std::filesystem::exists(path)) + { + std::cout << "Path " << path << " does not exist.\n"; + return {EXIT_FAILURE, {}}; + } + + // Maybe user chose a specific image, not a folder + if (std::filesystem::is_regular_file(path)) + return {EXIT_SUCCESS, path.string()}; + + // So... it is a folder + // Creating a vector of everything in the given directory + std::vector> dir_items; + std::transform(std::filesystem::directory_iterator(path), {}, std::back_inserter(dir_items), filepath::getFileInfo); + + std::set allowed_ext = {".bmp", ".dds", ".jpg", ".png", ".tga", ".psd"}; + + // Now getting images + std::vector dir_image_items; + for (const auto &[local_path, status] : dir_items) + { + const std::string str_path = local_path.string(); + if (std::filesystem::is_regular_file(local_path) && + std::any_of(allowed_ext.begin(), allowed_ext.end(), [&](const std::string& e) { return filepath::endsWith(str_path, e); })) + { + dir_image_items.emplace_back(str_path); + } + } + + if (dir_image_items.empty()) + { + std::cout << "No images found at " << path << "\n --help for more information.\n"; + return {EXIT_FAILURE, {}}; + } + + std::cout << "Loading random image file from " << path << "\n"; + srand(static_cast(time(nullptr))); + return {EXIT_SUCCESS, dir_image_items[rand() & (dir_image_items.size() - 1)]}; } static std::tuple parseInput(int argc, char **argv) { - int splitting = -1; - std::string path; + int splitting = DEFAULT_SPLITTING; + std::string path = DEFAULT_PATH; switch (argc) { default: return error(output::NO_ARG_MSG); + case NO_ARGC: + { + // Just launch the application with default parameters + std::cout << "No arguments given. Launching at \"" + DEFAULT_PATH + "\" with splitting " + std::to_string(DEFAULT_SPLITTING) + "\n"; + const auto &[ret_code, ret_path] = parsePath(DEFAULT_PATH); + + if (ret_code) + return error(output::IMG_FAIL_MSG); + + path = ret_path; + break; + } + case MIN_ARGC: + { // maybe --help if (strcmp(argv[1], output::HELP_FLAG) == 0) return error(output::HELP_MSG); - /* HERE PARSE FILEPATH INSTEAD */ return error(output::NO_ARG_MSG); + const auto &[ret_code, ret_path] = parsePath(argv[1]); + + if (ret_code) + return error(output::IMG_FAIL_MSG); + + path = ret_path; break; + } case (MAX_ARGC - 1): case MAX_ARGC: + { // full stack if (strcmp(argv[1], output::SPLITTING_FLAG) == 0) { @@ -42,25 +115,31 @@ static std::tuple parseInput(int argc, char **argv) if (splitting < 1) return error(output::SPLITTING_MSG); - /* HERE PARSE FILEPATH INSTEAD */ return error(output::NO_ARG_MSG); - } + const auto &[ret_code, ret_path] = parsePath(argv[3]); - return error(output::NO_ARG_MSG); + if (ret_code) + return error(output::IMG_FAIL_MSG); + + path = ret_path; + } break; } + } return {EXIT_SUCCESS, splitting, path}; } +///////////////////////////////////////////////////////////////////////// + int main(int argc, char **argv) { - auto[ret_code, splitting, path] = parseInput(argc, argv); + const auto&[ret_code, splitting, path] = parseInput(argc, argv); if (ret_code) // Error code is EXIT_FAILURE return ret_code; Application app; - if (app.init(splitting, path)) + if (app.init(path, splitting)) { app.run(); return EXIT_SUCCESS; diff --git a/output_util.h b/output_util.h index 72cd93e..4577067 100644 --- a/output_util.h +++ b/output_util.h @@ -1,6 +1,7 @@ #pragma once -namespace output { +namespace output +{ const char* HELP_FLAG = "--help"; const char* SPLITTING_FLAG = "-s"; @@ -16,6 +17,5 @@ namespace output { " Hence, if your image is square, the amount of tiles\n" " will be num * num.\n"; const char* SPLITTING_MSG = "-s should be given with a positive num as in [-s num].\n"; - - + const char* IMG_FAIL_MSG = "Couldn't load image from given path.\n"; }