From 7d71827c25ff1ab47c03aaa26f63a9a754b3d549 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Sun, 3 Jul 2022 11:24:05 -0400 Subject: Condensed solar system csv files into one. Add argument parser for help and different systems --- src/diargs.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/game.cpp | 9 +++---- src/main.cpp | 27 ++++++++++++++++--- src/system.cpp | 73 ++++++++++++++++---------------------------------- 4 files changed, 135 insertions(+), 58 deletions(-) create mode 100644 src/diargs.cpp (limited to 'src') diff --git a/src/diargs.cpp b/src/diargs.cpp new file mode 100644 index 0000000..b7aa79e --- /dev/null +++ b/src/diargs.cpp @@ -0,0 +1,84 @@ +/** + * diargs.cpp + * Copyright (c) 2022 Jon Santmyer + * + * 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. + */ +#include "diargs.hpp" +#include +#include + +namespace diargs +{ + +ArgumentParser::ArgumentParser( + void (*failfunc)(int), + ArgumentList &arguments, + ArgsPair argcv) +{ + /*Raw c strings passed to string_view for safety*/ + std::vector argv(argcv.argc); + for(int arg = 0; arg < argcv.argc; arg++) { + argv[arg] = std::string_view(argcv.argv[arg]); + } + + /*Skip the first argument because it will always be the path to the program*/ + for(auto it = argv.begin() + 1; it != argv.end(); it++) { + if(it->at(0) == '-') { /*Argument could be shortform*/ + if(it->at(1) == '-') { /*Argument is longform*/ + std::string_view parsing = std::string_view(it->data() + 2); + if(parsing.size() == 0) continue; + for(auto &argdef : arguments.arguments) { + if(argdef->longform != parsing) continue; + auto newit = argdef->parse(argv, it); + if(newit == std::nullopt) { + failfunc(-1); + return; + } + it = newit.value_or(argv.end()); + break; + } + continue; + } + std::string_view parsing = (*it); + for(char c : parsing) { + for(auto &argdef : arguments.arguments) { + if(argdef->shortform != c) continue; + auto newit = argdef->parse(argv, it); + if(newit == std::nullopt) { + failfunc(-1); + return; + } + it = newit.value_or(argv.end()); + } + } + continue; + } /*When argument is unmarked, it's an ordered type*/ + for(auto argit = arguments.arguments.begin(); + argit != arguments.arguments.end(); + argit++) { + if((*argit)->shortform != 0 || !(*argit)->longform.empty()) continue; + it = (*argit)->parse(argv, it).value_or(argv.end()); + arguments.arguments.erase(argit); + break; + } + } +} + +} diff --git a/src/game.cpp b/src/game.cpp index b1d0b00..d992a99 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -21,7 +21,7 @@ Game::State Game::m_state = State::RUNNING; Game::WindowContexts Game::contexts; void -Game::setup(unsigned w, unsigned h) +Game::setup(unsigned w, unsigned h, const std::string &sysname) { KeyMan::loadKeybindsFrom("keybinds.csv"); @@ -32,22 +32,21 @@ Game::setup(unsigned w, unsigned h) unsigned int viewh = h - 1; unsigned int infow = 24; unsigned int infoh = 12; - unsigned int timeh = 10; + unsigned int timeh = h - infoh; TimeMan::init(); m_contexts.emplace(WINCTX_GAME, WindowContext()); + m_contexts.emplace(WINCTX_TITLE, WindowContext()); WindowContext *gameContext = &m_contexts[WINCTX_GAME]; gameContext->registerWindow(WINDOW_SYSTEMVIEW_ID, "System View", infow, 0, w - infow, viewh); gameContext->registerWindow(WINDOW_BODYINFO_ID, "Body Info", 0, 0, infow, infoh); - gameContext->registerWindow(WINDOW_EVENTS_ID, "Events", 0, infoh, infow, viewh - infoh - timeh); gameContext->registerWindow(WINDOW_TIMEMAN_ID, "Time", 0, viewh - timeh, infow, timeh); - gameContext->registerWindow(WINDOW_SYSTEMVIEW_SEARCH_ID, "Search", infow, 0, (w - infow) / 4, viewh, true); m_currentContext = WINCTX_GAME; m_camera = std::make_unique((*gameContext)[WINDOW_SYSTEMVIEW_ID].screen()); - m_system = std::make_unique(); + m_system = std::make_unique(sysname); m_systemView.view(m_system.get()); KeyMan::registerBind('\x1B', BIND_G_ESCAPE, CTX_GLOBAL, "Escape from focused searchbox / window"); diff --git a/src/main.cpp b/src/main.cpp index 9ff09a6..5fafaf8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,21 +1,42 @@ #include #include "game.hpp" +#include "diargs.hpp" #include #include #include +void +printusage(int err) +{ + std::cout << "systemviewer " << VERSION << std::endl << + "Usage: systemviewer [OPTION]... [FILE]" << std::endl << + "With no FILE, FILE is assumed to be data/sol.csv" << std::endl << + "-h --help : print this message" << std::endl; + + std::exit(err); +} + int main(int argc, char **argv) { - (void)argc; - (void)argv; + std::string system = "dat/sol.csv"; + bool helpflag; + + diargs::ArgsPair args{argc, argv}; + diargs::ArgumentList arglist( + diargs::OrderedArgument(system), + diargs::ToggleArgument("help", 'h', helpflag, true) + ); + diargs::ArgumentParser(printusage, arglist, args); + + if(helpflag) printusage(0); struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); fcntl(STDIN_FILENO, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); - Game::setup(w.ws_col, w.ws_row); + Game::setup(w.ws_col, w.ws_row, system); while(Game::running()) { Game::turn(); diff --git a/src/system.cpp b/src/system.cpp index 974d0dc..61cb8be 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -11,7 +11,7 @@ static double G = 6.6743 * std::pow(10, -11); -ecs::Entity & +void System::addOrbital(const std::string &name, const std::string &orbitingName, unsigned long a, @@ -25,64 +25,36 @@ System::addOrbital(const std::string &name, w *= (std::numbers::pi / 180.0); SystemTreeNode *treeNode = getNode(orbitingName); - ecs::Entity &newOrbital = m_entityMan.newEntity() + ecs::Entity newOrbital = m_entityMan.newEntity() .addComponent(ecs::PositionComponent{vex::vec2{0, 0}}) .addComponent(ecs::MassComponent{m}) - .addComponent(ecs::OrbitalComponent{.origin = treeNode->entityId, .a = (long)a, .e = e, .w = w, .M = M, .T = 0, .v = 0}) .addComponent(ecs::RenderCircleComponent{r}) .addComponent(ecs::NameComponent{name}); - treeNode->children.push_back({newOrbital.id, {}}); - return newOrbital; + if(treeNode != nullptr) { + newOrbital.addComponent(ecs::OrbitalComponent{.origin = (unsigned)treeNode->entityId, .a = (long)a, .e = e, .w = w, .M = M, .T = 0, .v = 0}); + treeNode->children.push_back({(int)newOrbital.id, {}}); + }else{ + m_systemTree.entityId = newOrbital.id; + } } -System::System() +System::System(const std::string &name) { - auto sol = m_entityMan.newEntity() - .addComponent(ecs::PositionComponent{vex::vec2{0, 0}}) - .addComponent(ecs::MassComponent{unit::solMass}) - .addComponent(ecs::RenderCircleComponent{695700}) - .addComponent(ecs::NameComponent{"Sol"}); - m_systemTree.entityId = sol.id; - - csv::CSVFile<',', std::string, std::string, double, double, double, double, double, double> planetData("data/sol_planets.csv"); - for(auto &planet : planetData.get()) { - std::string name = std::get<0>(planet); - std::string orbiting = std::get<1>(planet); - double sma = std::get<2>(planet) * unit::AU; - double e = std::get<3>(planet); - unit::Mass m = unit::earthMass * std::get<4>(planet); - double r = std::get<5>(planet) * unit::earthRad; - double M = std::get<6>(planet); - double w = std::get<7>(planet); + m_systemTree.entityId = -1; + csv::CSVFile<',', std::string, std::string, double, double, double, double, double, double, std::string> bodyData(name); + for(auto &body : bodyData.get()) { + std::string name = std::get<0>(body); + std::string orbiting = std::get<1>(body); + double sma = std::get<2>(body) * unit::AU; + double e = std::get<3>(body); + unit::Mass m = unit::earthMass * std::get<4>(body); + double r = std::get<5>(body) * unit::earthRad; + double M = std::get<6>(body); + double w = std::get<7>(body); + + if(name == "Missing") name = std::get<8>(body); addOrbital(name, orbiting, sma, e, m, r, M, w); } - - csv::CSVFile<',', std::string, std::string, double, double, double, double, double, double> satelliteData("data/sol_satellites.csv"); - for(auto &satellite : satelliteData.get()) { - std::string name = std::get<0>(satellite); - std::string orbiting = std::get<1>(satellite); - double sma = std::get<2>(satellite) * unit::AU; - double e = std::get<3>(satellite); - unit::Mass m = unit::earthMass * std::get<4>(satellite); - double r = std::get<5>(satellite) * unit::earthRad; - double M = std::get<6>(satellite); - double w = std::get<7>(satellite); - addOrbital(name, orbiting, sma, e, m, r, M, w); - } - - csv::CSVFile<',', std::string, double, double, double, double, double, std::string> asteroidData("data/sol_asteroids.csv"); - for(auto &asteroid : asteroidData.get()) { - std::string name = std::get<0>(asteroid); - if(name == "Missing") name = std::get<6>(asteroid); - addOrbital(name, - "Sol", - (unsigned long)(std::get<1>(asteroid) * unit::AU), - std::get<2>(asteroid), - unit::Mass(0), - (unsigned)std::get<3>(asteroid), - std::get<4>(asteroid), - std::get<5>(asteroid)); - } } constexpr static double tau = std::numbers::pi * 2; @@ -161,6 +133,7 @@ System::traverseSystemTree(SystemTreeNode &node, const std::string &name) System::SystemTreeNode * System::getNode(const std::string &name) { + if(m_systemTree.entityId == -1) return nullptr; SystemTreeNode *treeRes = traverseSystemTree(m_systemTree, name); if(treeRes == nullptr) treeRes = &m_systemTree; -- cgit v1.2.1