diff --git a/.clang-format b/.clang-format index ffd5aa94..8e0b146b 100644 --- a/.clang-format +++ b/.clang-format @@ -1,98 +1,8 @@ -AccessModifierOffset: -2 -AlignAfterOpenBracket: DontAlign -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlines: Left -AlignOperands: true -AlignTrailingComments: false -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: true -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: true -AllowShortLoopsOnASingleLine: true -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: true -AlwaysBreakTemplateDeclarations: false -BinPackArguments: false -BinPackParameters: false -BraceWrapping: - AfterClass: true - AfterControlStatement: false - AfterEnum: false - AfterFunction: true - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: true - AfterUnion: false - BeforeCatch: false - BeforeElse: false - IndentBraces: false - SplitEmptyFunction: false - SplitEmptyNamespace: true - SplitEmptyRecord: true -BreakAfterJavaFieldAnnotations: true -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Custom -BreakBeforeInheritanceComma: true -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeColon -BreakConstructorInitializersBeforeComma: false -BreakStringLiterals: true -ColumnLimit: 120 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 2 -ContinuationIndentWidth: 2 -Cpp11BracedListStyle: false -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: true -FixNamespaceComments: true -ForEachMacros: -- foreach -- Q_FOREACH -- BOOST_FOREACH -IncludeCategories: -- Priority: 2 - Regex: ^"(llvm|llvm-c|clang|clang-c)/ -- Priority: 3 - Regex: ^(<|"(gtest|gmock|isl|json)/) -- Priority: 1 - Regex: .* -IncludeIsMainRegex: (Test)?$ -IndentCaseLabels: false -IndentWidth: 2 -IndentWrappedFunctionNames: true -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true +BasedOnStyle: Google +IndentWidth: 4 +AccessModifierOffset: -4 Language: Cpp -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 2 -NamespaceIndentation: Inner -ObjCBlockIndentWidth: 7 -ObjCSpaceAfterProperty: true -ObjCSpaceBeforeProtocolList: false -PointerAlignment: Right -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: false -SpaceAfterCStyleCast: false -SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 0 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: true -SpacesInParentheses: false -SpacesInSquareBrackets: false Standard: c++20 -TabWidth: 8 +TabWidth: 4 UseTab: Never diff --git a/.clang-tidy b/.clang-tidy index cdfaf8b2..c7cce2a4 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,30 +1,25 @@ --- Checks: "*, - -abseil-*, - -altera-*, - -android-*, - -fuchsia-*, - -google-*, - -llvm*, - -modernize-use-trailing-return-type, - -zircon-*, - -readability-else-after-return, - -readability-static-accessed-through-instance, - -readability-avoid-const-params-in-decls, - -cppcoreguidelines-non-private-member-variables-in-classes, - -misc-non-private-member-variables-in-classes, -" -WarningsAsErrors: '' -HeaderFilterRegex: '' -FormatStyle: none + -abseil-*, + -altera-*, + -android-*, + -fuchsia-*, + -google-*, + -llvm*, + -modernize-use-trailing-return-type, + -zircon-*, + -readability-else-after-return, + -readability-static-accessed-through-instance, + -readability-avoid-const-params-in-decls, + -cppcoreguidelines-non-private-member-variables-in-classes, + -misc-non-private-member-variables-in-classes" + +WarningsAsErrors: "" +HeaderFilterRegex: "" +FormatStyle: none CheckOptions: - key: readability-identifier-length.IgnoredVariableNames - value: 'x|y|z' + value: "x|y|z" - key: readability-identifier-length.IgnoredParameterNames - value: 'x|y|z' - - - - - + value: "x|y|z" diff --git a/CMakeLists.txt b/CMakeLists.txt index 45e19f03..614ddb95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.21) # manual dependency management # Only set the cxx_standard if it is not set by someone else -if (NOT DEFINED CMAKE_CXX_STANDARD) +if(NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 20) endif() @@ -25,7 +25,6 @@ project( include(cmake/PreventInSourceBuilds.cmake) include(ProjectOptions.cmake) - myproject_setup_options() myproject_global_options() @@ -73,10 +72,9 @@ if(BUILD_TESTING) add_subdirectory(test) endif() - if(myproject_BUILD_FUZZ_TESTS) message(AUTHOR_WARNING "Building Fuzz Tests, using fuzzing sanitizer https://www.llvm.org/docs/LibFuzzer.html") - if (NOT myproject_ENABLE_ADDRESS_SANITIZER AND NOT myproject_ENABLE_THREAD_SANITIZER) + if(NOT myproject_ENABLE_ADDRESS_SANITIZER AND NOT myproject_ENABLE_THREAD_SANITIZER) message(WARNING "You need asan or tsan enabled for meaningful fuzz testing") endif() add_subdirectory(fuzz_test) @@ -92,7 +90,7 @@ if(MSVC) endif() # set the startup project for the "play" button in MSVC -set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT intro) +set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT app) if(CMAKE_SKIP_INSTALL_RULES) return() @@ -104,7 +102,7 @@ include(cmake/PackageProject.cmake) # we know we want to ship myproject_package_project( TARGETS - intro + app myproject_options myproject_warnings # FIXME: this does not work! CK diff --git a/Dependencies.cmake b/Dependencies.cmake index a84378d2..00ab4f90 100644 --- a/Dependencies.cmake +++ b/Dependencies.cmake @@ -32,12 +32,17 @@ function(myproject_setup_dependencies) cpmaddpackage("gh:CLIUtils/CLI11@2.3.2") endif() - if(NOT TARGET ftxui::screen) - cpmaddpackage("gh:ArthurSonzogni/FTXUI#e23dbc7473654024852ede60e2121276c5aab660") - endif() - - if(NOT TARGET tools::tools) - cpmaddpackage("gh:lefticus/tools#update_build_system") + if(NOT TARGET Eigen3::Eigen) + cpmaddpackage( + GITLAB_REPOSITORY + "libeigen/eigen" + GIT_TAG + "3.4.0" + OPTIONS + "EIGEN_BUILD_DOC NO" + "EIGEN_LEAVE_TEST_IN_ALL_TARGET YES" + "BUILD_TESTING NO" + "EIGEN_BUILD_PKGCONFIG NO") endif() endfunction() diff --git a/README.md b/README.md index bc766ae4..75578629 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,7 @@ ## About cmake_template -**NOTE** This is undergoing a major overhaul on a new branch currently. - - -This is a C++ Best Practices GitHub template for getting up and running with C++ quickly. +This is a C++ Best Practices GitHub template fork for getting up and running with C++ quickly. By default (collectively known as `ENABLE_DEVELOPER_MODE`) diff --git a/README_building.md b/README_building.md deleted file mode 100644 index 99ceacfc..00000000 --- a/README_building.md +++ /dev/null @@ -1,192 +0,0 @@ -## Build Instructions - -A full build has different steps: -1) Specifying the compiler using environment variables -2) Configuring the project -3) Building the project - -For the subsequent builds, in case you change the source code, you only need to repeat the last step. - -### (1) Specify the compiler using environment variables - -By default (if you don't set environment variables `CC` and `CXX`), the system default compiler will be used. - -CMake uses the environment variables CC and CXX to decide which compiler to use. So to avoid the conflict issues only specify the compilers using these variables. - - -
-Commands for setting the compilers - -- Debian/Ubuntu/MacOS: - - Set your desired compiler (`clang`, `gcc`, etc): - - - Temporarily (only for the current shell) - - Run one of the followings in the terminal: - - - clang - - CC=clang CXX=clang++ - - - gcc - - CC=gcc CXX=g++ - - - Permanent: - - Open `~/.bashrc` using your text editor: - - gedit ~/.bashrc - - Add `CC` and `CXX` to point to the compilers: - - export CC=clang - export CXX=clang++ - - Save and close the file. - -- Windows: - - - Permanent: - - Run one of the followings in PowerShell: - - - Visual Studio generator and compiler (cl) - - [Environment]::SetEnvironmentVariable("CC", "cl.exe", "User") - [Environment]::SetEnvironmentVariable("CXX", "cl.exe", "User") - refreshenv - - Set the architecture using [vcvarsall](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#vcvarsall-syntax): - - vcvarsall.bat x64 - - - clang - - [Environment]::SetEnvironmentVariable("CC", "clang.exe", "User") - [Environment]::SetEnvironmentVariable("CXX", "clang++.exe", "User") - refreshenv - - - gcc - - [Environment]::SetEnvironmentVariable("CC", "gcc.exe", "User") - [Environment]::SetEnvironmentVariable("CXX", "g++.exe", "User") - refreshenv - - - - Temporarily (only for the current shell): - - $Env:CC="clang.exe" - $Env:CXX="clang++.exe" - -
- -### (2) Configure your build - -To configure the project, you could use `cmake`, or `ccmake` or `cmake-gui`. Each of them are explained in the following: - -#### (2.a) Configuring via cmake: -With Cmake directly: - - cmake -S . -B ./build - -Cmake will automatically create the `./build` folder if it does not exist, and it wil configure the project. - -Instead, if you have CMake version 3.21+, you can use one of the configuration presets that are listed in the CmakePresets.json file. - - cmake . --preset - cmake --build - -#### (2.b) Configuring via ccmake: - -With the Cmake Curses Dialog Command Line tool: - - ccmake -S . -B ./build - -Once `ccmake` has finished setting up, press 'c' to configure the project, -press 'g' to generate, and 'q' to quit. - -#### (2.c) Configuring via cmake-gui: - -To use the GUI of the cmake: - -2.c.1) Open cmake-gui from the project directory: -``` -cmake-gui . -``` -2.c.2) Set the build directory: - -![build_dir](https://user-images.githubusercontent.com/16418197/82524586-fa48e380-9af4-11ea-8514-4e18a063d8eb.jpg) - -2.c.3) Configure the generator: - -In cmake-gui, from the upper menu select `Tools/Configure`. - -**Warning**: if you have set `CC` and `CXX` always choose the `use default native compilers` option. This picks `CC` and `CXX`. Don't change the compiler at this stage! - -
-Windows - MinGW Makefiles - -Choose MinGW Makefiles as the generator: - -mingw - -
- -
-Windows - Visual Studio generator and compiler - -You should have already set `C` and `CXX` to `cl.exe`. - -Choose "Visual Studio 16 2019" as the generator: - -default_vs - -
- -
- -Windows - Visual Studio generator and Clang Compiler - -You should have already set `C` and `CXX` to `clang.exe` and `clang++.exe`. - -Choose "Visual Studio 16 2019" as the generator. To tell Visual studio to use `clang-cl.exe`: -- If you use the LLVM that is shipped with Visual Studio: write `ClangCl` under "optional toolset to use". - -visual_studio - -- If you use an external LLVM: write [`LLVM_v142`](https://github.com/zufuliu/llvm-utils#llvm-for-visual-studio-2017-and-2019) - under "optional toolset to use". - -visual_studio - -
-
- -2.c.4) Choose the Cmake options and then generate: - -![generate](https://user-images.githubusercontent.com/16418197/82781591-c97feb80-9e1f-11ea-86c8-f2748b96f516.png) - -### (3) Build the project -Once you have selected all the options you would like to use, you can build the -project (all targets): - - cmake --build ./build - -For Visual Studio, give the build configuration (Release, RelWithDeb, Debug, etc) like the following: - - cmake --build ./build -- /p:configuration=Release - - -### Running the tests - -You can use the `ctest` command run the tests. - -```shell -cd ./build -ctest -C Debug -cd ../ -``` - - diff --git a/README_dependencies.md b/README_dependencies.md deleted file mode 100644 index 42e4dab0..00000000 --- a/README_dependencies.md +++ /dev/null @@ -1,192 +0,0 @@ -## Dependencies - -Note about install commands: -- for Windows, we use [choco](https://chocolatey.org/install). -- for MacOS, we use [brew](https://brew.sh/). -- In case of an error in cmake, make sure that the dependencies are on the PATH. - - -### Too Long, Didn't Install - -This is a really long list of dependencies, and it's easy to mess up. That's why: - -#### Docker -We have a Docker image that's already set up for you. See the [Docker instructions](#docker-instructions). - -#### Setup-cpp - -We have [setup-cpp](https://github.com/aminya/setup-cpp) that is a cross-platform tool to install all the compilers and dependencies on the system. - -Please check [the setup-cpp documentation](https://github.com/aminya/setup-cpp) for more information. - -For example, on Windows, you can run the following to install llvm, cmake, ninja, ccache, and cppcheck. -```ps1 -# windows example (open shell as admin) -curl -LJO "https://github.com/aminya/setup-cpp/releases/download/v0.5.7/setup_cpp_windows.exe" -./setup_cpp_windows --compiler llvm --cmake true --ninja true --ccache true --cppcheck true - -RefreshEnv.cmd # reload the environment -``` - -### Necessary Dependencies -1. A C++ compiler that supports C++17. -See [cppreference.com](https://en.cppreference.com/w/cpp/compiler_support) -to see which features are supported by each compiler. -The following compilers should work: - - * [gcc 7+](https://gcc.gnu.org/) -
- Install command - - - Debian/Ubuntu: - - sudo apt install build-essential - - - Windows: - - choco install mingw -y - - - MacOS: - - brew install gcc -
- - * [clang 6+](https://clang.llvm.org/) -
- Install command - - - Debian/Ubuntu: - - bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" - - - Windows: - - Visual Studio 2019 ships with LLVM (see the Visual Studio section). However, to install LLVM separately: - - choco install llvm -y - - llvm-utils for using external LLVM with Visual Studio generator: - - git clone https://github.com/zufuliu/llvm-utils.git - cd llvm-utils/VS2017 - .\install.bat - - - MacOS: - - brew install llvm -
- - * [Visual Studio 2019 or higher](https://visualstudio.microsoft.com/) -
- Install command + Environment setup - - On Windows, you need to install Visual Studio 2019 because of the SDK and libraries that ship with it. - - Visual Studio IDE - 2019 Community (installs Clang too): - - choco install -y visualstudio2019community --package-parameters "add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended --includeOptional --passive --locale en-US" - - Put MSVC compiler, Clang compiler, and vcvarsall.bat on the path: - - choco install vswhere -y - refreshenv - - # change to x86 for 32bit - $clpath = vswhere -products * -latest -prerelease -find **/Hostx64/x64/* - $clangpath = vswhere -products * -latest -prerelease -find **/Llvm/bin/* - $vcvarsallpath = vswhere -products * -latest -prerelease -find **/Auxiliary/Build/* - - $path = [System.Environment]::GetEnvironmentVariable("PATH", "User") - [Environment]::SetEnvironmentVariable("Path", $path + ";$clpath" + ";$clangpath" + ";$vcvarsallpath", "User") - refreshenv - -
- - -2. [CMake 3.15+](https://cmake.org/) -
- Install Command - - - Debian/Ubuntu: - - sudo apt-get install cmake - - - Windows: - - choco install cmake -y - - - MacOS: - - brew install cmake - -
- -### Optional Dependencies -#### C++ Tools - * [Doxygen](http://doxygen.nl/) -
- Install Command - - - Debian/Ubuntu: - - sudo apt-get install doxygen - sudo apt-get install graphviz - - - Windows: - - choco install doxygen.install -y - choco install graphviz -y - - - MacOS: - - brew install doxygen - brew install graphviz - -
- - - * [ccache](https://ccache.dev/) -
- Install Command - - - Debian/Ubuntu: - - sudo apt-get install ccache - - - Windows: - - choco install ccache -y - - - MacOS: - - brew install ccache - -
- - - * [Cppcheck](http://cppcheck.sourceforge.net/) -
- Install Command - - - Debian/Ubuntu: - - sudo apt-get install cppcheck - - - Windows: - - choco install cppcheck -y - - - MacOS: - - brew install cppcheck - -
- - - * [include-what-you-use](https://include-what-you-use.org/) -
- Install Command - - Follow instructions here: - https://github.com/include-what-you-use/include-what-you-use#how-to-install -
diff --git a/README_docker.md b/README_docker.md deleted file mode 100644 index b1f5bf52..00000000 --- a/README_docker.md +++ /dev/null @@ -1,71 +0,0 @@ -## Docker Instructions - -If you have [Docker](https://www.docker.com/) installed, you can run this -in your terminal, when the Dockerfile is inside the `.devcontainer` directory: - -```bash -docker build -f ./.devcontainer/Dockerfile --tag=my_project:latest . -docker run -it my_project:latest -``` - -This command will put you in a `bash` session in a Ubuntu 20.04 Docker container, -with all of the tools listed in the [Dependencies](#dependencies) section already installed. -Additionally, you will have `g++-11` and `clang++-13` installed as the default -versions of `g++` and `clang++`. - -If you want to build this container using some other versions of gcc and clang, -you may do so with the `GCC_VER` and `LLVM_VER` arguments: - -```bash -docker build --tag=myproject:latest --build-arg GCC_VER=10 --build-arg LLVM_VER=11 . -``` - -The CC and CXX environment variables are set to GCC version 11 by default. -If you wish to use clang as your default CC and CXX environment variables, you -may do so like this: - -```bash -docker build --tag=my_project:latest --build-arg USE_CLANG=1 . -``` - -You will be logged in as root, so you will see the `#` symbol as your prompt. -You will be in a directory that contains a copy of the `cpp_starter_project`; -any changes you make to your local copy will not be updated in the Docker image -until you rebuild it. -If you need to mount your local copy directly in the Docker image, see -[Docker volumes docs](https://docs.docker.com/storage/volumes/). -TLDR: - -```bash -docker run -it \ - -v absolute_path_on_host_machine:absolute_path_in_guest_container \ - my_project:latest -``` - -You can configure and build [as directed above](#build) using these commands: - -```bash -/starter_project# mkdir build -/starter_project# cmake -S . -B ./build -/starter_project# cmake --build ./build -``` - -You can configure and build using `clang-13`, without rebuilding the container, -with these commands: - -```bash -/starter_project# mkdir build -/starter_project# CC=clang CXX=clang++ cmake -S . -B ./build -/starter_project# cmake --build ./build -``` - -The `ccmake` tool is also installed; you can substitute `ccmake` for `cmake` to -configure the project interactively. -All of the tools this project supports are installed in the Docker image; -enabling them is as simple as flipping a switch using the `ccmake` interface. -Be aware that some of the sanitizers conflict with each other, so be sure to -run them separately. - -A script called `build_examples.sh` is provided to help you to build the example -GUI projects in this container. - diff --git a/include/myproject/Utils/Random.hpp b/include/myproject/Utils/Random.hpp new file mode 100644 index 00000000..8f8d938a --- /dev/null +++ b/include/myproject/Utils/Random.hpp @@ -0,0 +1,38 @@ +#pragma once +#include +#include +#include +#include + +class Random { +public: + static inline void seed() { s_RandomEngine.seed(std::random_device()()); } + static inline void seed(uint32_t seed) { s_RandomEngine.seed(seed); } + + static inline int32_t nextInt32() { return s_int32Dist(s_RandomEngine); } + + static inline double nextDouble() { return s_doubleDist(s_RandomEngine); } + static inline double uniform(double min, double max) { + return min + (max - min) * nextDouble(); + } + static inline double gauss() { return s_normalDist(s_RandomEngine); } + + static inline std::mt19937& getEngine() { return s_RandomEngine; } + + static inline void saveState(std::ostream& os) { + os << s_RandomEngine << '\n' + << s_int32Dist << '\n' + << s_doubleDist << '\n' + << s_normalDist << '\n'; + } + + static inline void loadState(std::istream& os) { + os >> s_RandomEngine >> s_int32Dist >> s_doubleDist >> s_normalDist; + } + +private: + static inline thread_local std::mt19937 s_RandomEngine; + static inline std::uniform_int_distribution s_int32Dist; + static inline std::uniform_real_distribution s_doubleDist; + static inline std::normal_distribution s_normalDist; +}; \ No newline at end of file diff --git a/include/myproject/Utils/Sampler2d.hpp b/include/myproject/Utils/Sampler2d.hpp new file mode 100644 index 00000000..0d364744 --- /dev/null +++ b/include/myproject/Utils/Sampler2d.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +class Sampler2d { +public: + Sampler2d(const Eigen::AlignedBox2d& box); + + virtual ~Sampler2d(); + + virtual Eigen::Vector2d sample() const = 0; + + double getArea() const; + +protected: + Eigen::AlignedBox2d m_box; +}; + +class UniformSampler2d : public Sampler2d { +public: + using Sampler2d::Sampler2d; + + Eigen::Vector2d sample() const override; +}; diff --git a/include/myproject/sample_library.hpp b/include/myproject/sample_library/sample_library.hpp similarity index 54% rename from include/myproject/sample_library.hpp rename to include/myproject/sample_library/sample_library.hpp index 1b2b1772..fd0990ca 100644 --- a/include/myproject/sample_library.hpp +++ b/include/myproject/sample_library/sample_library.hpp @@ -1,15 +1,12 @@ -#ifndef SAMPLE_LIBRARY_HPP -#define SAMPLE_LIBRARY_HPP - +#pragma once #include [[nodiscard]] SAMPLE_LIBRARY_EXPORT int factorial(int) noexcept; -[[nodiscard]] constexpr int factorial_constexpr(int input) noexcept -{ - if (input == 0) { return 1; } +[[nodiscard]] constexpr int factorial_constexpr(int input) noexcept { + if (input == 0) { + return 1; + } - return input * factorial_constexpr(input - 1); + return input * factorial_constexpr(input - 1); } - -#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0f92a9d6..5ab2be1b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,2 +1,3 @@ +add_subdirectory(Utils) add_subdirectory(sample_library) -add_subdirectory(ftxui_sample) +add_subdirectory(app) diff --git a/src/Utils/CMakeLists.txt b/src/Utils/CMakeLists.txt new file mode 100644 index 00000000..5d261d34 --- /dev/null +++ b/src/Utils/CMakeLists.txt @@ -0,0 +1,25 @@ +include(GenerateExportHeader) + +add_library(Utils Random.cpp Sampler2d.cpp) + +add_library(myproject::Utils ALIAS Utils) + +target_link_libraries(Utils PRIVATE myproject_options myproject_warnings) +target_link_system_libraries(Utils PRIVATE Eigen3::Eigen) + +target_include_directories(Utils ${WARNING_GUARD} PUBLIC $ + $) + +target_compile_features(Utils PUBLIC cxx_std_20) + +set_target_properties( + Utils + PROPERTIES VERSION ${PROJECT_VERSION} + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN YES) + +generate_export_header(Utils EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/include/myproject/Utils_export.hpp) + +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(Utils PUBLIC Utils_STATIC_DEFINE) +endif() diff --git a/src/Utils/Random.cpp b/src/Utils/Random.cpp new file mode 100644 index 00000000..c7c74d1f --- /dev/null +++ b/src/Utils/Random.cpp @@ -0,0 +1 @@ +#include diff --git a/src/Utils/Sampler2d.cpp b/src/Utils/Sampler2d.cpp new file mode 100644 index 00000000..d683b5c3 --- /dev/null +++ b/src/Utils/Sampler2d.cpp @@ -0,0 +1,13 @@ +#include +#include + +Sampler2d::Sampler2d(const Eigen::AlignedBox2d& box) : m_box(box) {} + +Sampler2d::~Sampler2d() = default; + +double Sampler2d::getArea() const { return m_box.volume(); } + +Eigen::Vector2d UniformSampler2d::sample() const { + return {Random::uniform(m_box.min().x(), m_box.max().x()), + Random::uniform(m_box.min().y(), m_box.max().y())}; +} diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt new file mode 100644 index 00000000..73c39eec --- /dev/null +++ b/src/app/CMakeLists.txt @@ -0,0 +1,12 @@ +add_executable(app main.cpp) + +target_link_libraries(app PRIVATE myproject::myproject_options myproject::myproject_warnings Utils) + +target_link_system_libraries( + app + PRIVATE + CLI11::CLI11 + fmt::fmt + spdlog::spdlog) + +target_include_directories(app PRIVATE "${CMAKE_BINARY_DIR}/configured_files/include") diff --git a/src/app/main.cpp b/src/app/main.cpp new file mode 100644 index 00000000..a8fd817d --- /dev/null +++ b/src/app/main.cpp @@ -0,0 +1,46 @@ +#include + +#include +#include // project_name, project_version +#include + +int main(int argc, const char** argv) { + try { + CLI::App app{fmt::format("{} version {}", + myproject::cmake::project_name, + myproject::cmake::project_version)}; + + // std::optional message; + // app.add_option("-m,--message", message, "A message to print out"); + bool show_version = false; + app.add_flag("--version", show_version, "Show version information"); + + // bool is_turn_based = false; + // auto* turn_based = app.add_flag("--turn_based", is_turn_based); + + // bool is_loop_based = false; + // auto* loop_based = app.add_flag("--loop_based", is_loop_based); + + // turn_based->excludes(loop_based); + // loop_based->excludes(turn_based); + + CLI11_PARSE(app, argc, argv); + + if (show_version) { + fmt::print("{}\n", myproject::cmake::project_version); + return EXIT_SUCCESS; + } + + // if (message) { + // fmt::print("{}\n", *message); + // } + + Random::seed(); + std::cout << Random::nextDouble() << '\n'; + + } catch (const std::exception& e) { + spdlog::error("Unhandled exception in main: {}", e.what()); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/src/ftxui_sample/CMakeLists.txt b/src/ftxui_sample/CMakeLists.txt deleted file mode 100644 index fc5c65e2..00000000 --- a/src/ftxui_sample/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -add_executable(intro main.cpp) - -target_link_libraries( - intro - PRIVATE myproject::myproject_options - myproject::myproject_warnings) - -target_link_system_libraries( - intro - PRIVATE - CLI11::CLI11 - fmt::fmt - spdlog::spdlog - lefticus::tools - ftxui::screen - ftxui::dom - ftxui::component) - -target_include_directories(intro PRIVATE "${CMAKE_BINARY_DIR}/configured_files/include") diff --git a/src/ftxui_sample/main.cpp b/src/ftxui_sample/main.cpp deleted file mode 100644 index aa53beaf..00000000 --- a/src/ftxui_sample/main.cpp +++ /dev/null @@ -1,349 +0,0 @@ -#include -#include -#include -#include - -#include - -#include -#include // for ftxui -#include // for Slider -#include // for ScreenInteractive -#include - -#include - -// This file will be generated automatically when cur_you run the CMake -// configuration step. It creates a namespace called `myproject`. You can modify -// the source template at `configured_files/config.hpp.in`. -#include - -template struct GameBoard -{ - static constexpr std::size_t width = Width; - static constexpr std::size_t height = Height; - - std::array, width> strings; - std::array, width> values{}; - - std::size_t move_count{ 0 }; - - std::string &get_string(std::size_t cur_x, std::size_t cur_y) { return strings.at(cur_x).at(cur_y); } - - - void set(std::size_t cur_x, std::size_t cur_y, bool new_value) - { - get(cur_x, cur_y) = new_value; - - if (new_value) { - get_string(cur_x, cur_y) = " ON"; - } else { - get_string(cur_x, cur_y) = "OFF"; - } - } - - void visit(auto visitor) - { - for (std::size_t cur_x = 0; cur_x < width; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < height; ++cur_y) { visitor(cur_x, cur_y, *this); } - } - } - - [[nodiscard]] bool get(std::size_t cur_x, std::size_t cur_y) const { return values.at(cur_x).at(cur_y); } - - [[nodiscard]] bool &get(std::size_t cur_x, std::size_t cur_y) { return values.at(cur_x).at(cur_y); } - - GameBoard() - { - visit([](const auto cur_x, const auto cur_y, auto &gameboard) { gameboard.set(cur_x, cur_y, true); }); - } - - void update_strings() - { - for (std::size_t cur_x = 0; cur_x < width; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < height; ++cur_y) { set(cur_x, cur_y, get(cur_x, cur_y)); } - } - } - - void toggle(std::size_t cur_x, std::size_t cur_y) { set(cur_x, cur_y, !get(cur_x, cur_y)); } - - void press(std::size_t cur_x, std::size_t cur_y) - { - ++move_count; - toggle(cur_x, cur_y); - if (cur_x > 0) { toggle(cur_x - 1, cur_y); } - if (cur_y > 0) { toggle(cur_x, cur_y - 1); } - if (cur_x < width - 1) { toggle(cur_x + 1, cur_y); } - if (cur_y < height - 1) { toggle(cur_x, cur_y + 1); } - } - - [[nodiscard]] bool solved() const - { - for (std::size_t cur_x = 0; cur_x < width; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < height; ++cur_y) { - if (!get(cur_x, cur_y)) { return false; } - } - } - - return true; - } -}; - - -void consequence_game() -{ - auto screen = ftxui::ScreenInteractive::TerminalOutput(); - - GameBoard<3, 3> game_board; - - std::string quit_text; - - const auto update_quit_text = [&quit_text](const auto &game_board_param) { - quit_text = fmt::format("Quit ({} moves)", game_board_param.move_count); - if (game_board_param.solved()) { quit_text += " Solved!"; } - }; - - const auto make_buttons = [&] { - std::vector buttons; - for (std::size_t cur_x = 0; cur_x < game_board.width; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < game_board.height; ++cur_y) { - buttons.push_back(ftxui::Button(&game_board.get_string(cur_x, cur_y), [=, &game_board] { - if (!game_board.solved()) { game_board.press(cur_x, cur_y); } - update_quit_text(game_board); - })); - } - } - return buttons; - }; - - auto buttons = make_buttons(); - - auto quit_button = ftxui::Button(&quit_text, screen.ExitLoopClosure()); - - auto make_layout = [&] { - std::vector rows; - - std::size_t idx = 0; - - for (std::size_t cur_x = 0; cur_x < game_board.width; ++cur_x) { - std::vector row; - for (std::size_t cur_y = 0; cur_y < game_board.height; ++cur_y) { - row.push_back(buttons[idx]->Render()); - ++idx; - } - rows.push_back(ftxui::hbox(std::move(row))); - } - - rows.push_back(ftxui::hbox({ quit_button->Render() })); - - return ftxui::vbox(std::move(rows)); - }; - - - static constexpr int randomization_iterations = 100; - static constexpr int random_seed = 42; - - std::mt19937 gen32{ random_seed };// NOLINT fixed seed - - // NOLINTNEXTLINE This cannot be const - std::uniform_int_distribution cur_x(static_cast(0), game_board.width - 1); - // NOLINTNEXTLINE This cannot be const - std::uniform_int_distribution cur_y(static_cast(0), game_board.height - 1); - - for (int i = 0; i < randomization_iterations; ++i) { game_board.press(cur_x(gen32), cur_y(gen32)); } - game_board.move_count = 0; - update_quit_text(game_board); - - auto all_buttons = buttons; - all_buttons.push_back(quit_button); - auto container = ftxui::Container::Horizontal(all_buttons); - - auto renderer = ftxui::Renderer(container, make_layout); - - screen.Loop(renderer); -} - -struct Color -{ - lefticus::tools::uint_np8_t R{ static_cast(0) }; - lefticus::tools::uint_np8_t G{ static_cast(0) }; - lefticus::tools::uint_np8_t B{ static_cast(0) }; -}; - -// A simple way of representing a bitmap on screen using only characters -struct Bitmap : ftxui::Node -{ - Bitmap(std::size_t width, std::size_t height)// NOLINT same typed parameters adjacent to each other - : width_(width), height_(height) - {} - - Color &at(std::size_t cur_x, std::size_t cur_y) { return pixels.at(width_ * cur_y + cur_x); } - - void ComputeRequirement() override - { - requirement_ = ftxui::Requirement{ - .min_x = static_cast(width_), .min_y = static_cast(height_ / 2), .selected_box{ 0, 0, 0, 0 } - }; - } - - void Render(ftxui::Screen &screen) override - { - for (std::size_t cur_x = 0; cur_x < width_; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < height_ / 2; ++cur_y) { - auto &pixel = screen.PixelAt(box_.x_min + static_cast(cur_x), box_.y_min + static_cast(cur_y)); - pixel.character = "▄"; - const auto &top_color = at(cur_x, cur_y * 2); - const auto &bottom_color = at(cur_x, cur_y * 2 + 1); - pixel.background_color = ftxui::Color{ top_color.R.get(), top_color.G.get(), top_color.B.get() }; - pixel.foreground_color = ftxui::Color{ bottom_color.R.get(), bottom_color.G.get(), bottom_color.B.get() }; - } - } - } - - [[nodiscard]] auto width() const noexcept { return width_; } - - [[nodiscard]] auto height() const noexcept { return height_; } - - [[nodiscard]] auto &data() noexcept { return pixels; } - -private: - std::size_t width_; - std::size_t height_; - - std::vector pixels = std::vector(width_ * height_, Color{}); -}; - -void game_iteration_canvas() -{ - // this should probably have a `bitmap` helper function that does what cur_you expect - // similar to the other parts of FTXUI - auto bm = std::make_shared(50, 50);// NOLINT magic numbers - auto small_bm = std::make_shared(6, 6);// NOLINT magic numbers - - double fps = 0; - - std::size_t max_row = 0; - std::size_t max_col = 0; - - // to do, add total game time clock also, not just current elapsed time - auto game_iteration = [&](const std::chrono::steady_clock::duration elapsed_time) { - // in here we simulate however much game time has elapsed. Update animations, - // run character AI, whatever, update stats, etc - - // this isn't actually timing based for now, it's just updating the display however fast it can - fps = 1.0 - / (static_cast(std::chrono::duration_cast(elapsed_time).count()) - / 1'000'000.0);// NOLINT magic numbers - - for (std::size_t row = 0; row < max_row; ++row) { - for (std::size_t col = 0; col < bm->width(); ++col) { ++(bm->at(col, row).R); } - } - - for (std::size_t row = 0; row < bm->height(); ++row) { - for (std::size_t col = 0; col < max_col; ++col) { ++(bm->at(col, row).G); } - } - - // for the fun of it, let's have a second window doing interesting things - auto &small_bm_pixel = - small_bm->data().at(static_cast(elapsed_time.count()) % small_bm->data().size()); - - switch (elapsed_time.count() % 3) { - case 0: - small_bm_pixel.R += 11;// NOLINT Magic Number - break; - case 1: - small_bm_pixel.G += 11;// NOLINT Magic Number - break; - case 2: - small_bm_pixel.B += 11;// NOLINT Magic Number - break; - } - - - ++max_row; - if (max_row >= bm->height()) { max_row = 0; } - ++max_col; - if (max_col >= bm->width()) { max_col = 0; } - }; - - auto screen = ftxui::ScreenInteractive::TerminalOutput(); - - int counter = 0; - - auto last_time = std::chrono::steady_clock::now(); - - auto make_layout = [&] { - // This code actually processes the draw event - const auto new_time = std::chrono::steady_clock::now(); - - ++counter; - // we will dispatch to the game_iteration function, where the work happens - game_iteration(new_time - last_time); - last_time = new_time; - - // now actually draw the game elements - return ftxui::hbox({ bm | ftxui::border, - ftxui::vbox({ ftxui::text("Frame: " + std::to_string(counter)), - ftxui::text("FPS: " + std::to_string(fps)), - small_bm | ftxui::border }) }); - }; - - auto renderer = ftxui::Renderer(make_layout); - - - std::atomic refresh_ui_continue = true; - - // This thread exists to make sure that the event queue has an event to - // process at approximately a rate of 30 FPS - std::thread refresh_ui([&] { - while (refresh_ui_continue) { - using namespace std::chrono_literals; - std::this_thread::sleep_for(1.0s / 30.0);// NOLINT magic numbers - screen.PostEvent(ftxui::Event::Custom); - } - }); - - screen.Loop(renderer); - - refresh_ui_continue = false; - refresh_ui.join(); -} - -// NOLINTNEXTLINE(bugprone-exception-escape) -int main(int argc, const char **argv) -{ - try { - CLI::App app{ fmt::format("{} version {}", myproject::cmake::project_name, myproject::cmake::project_version) }; - - std::optional message; - app.add_option("-m,--message", message, "A message to print back out"); - bool show_version = false; - app.add_flag("--version", show_version, "Show version information"); - - bool is_turn_based = false; - auto *turn_based = app.add_flag("--turn_based", is_turn_based); - - bool is_loop_based = false; - auto *loop_based = app.add_flag("--loop_based", is_loop_based); - - turn_based->excludes(loop_based); - loop_based->excludes(turn_based); - - - CLI11_PARSE(app, argc, argv); - - if (show_version) { - fmt::print("{}\n", myproject::cmake::project_version); - return EXIT_SUCCESS; - } - - if (is_turn_based) { - consequence_game(); - } else { - game_iteration_canvas(); - } - - } catch (const std::exception &e) { - spdlog::error("Unhandled exception in main: {}", e.what()); - } -} diff --git a/src/sample_library/sample_library.cpp b/src/sample_library/sample_library.cpp index 878deae2..d566e4a4 100644 --- a/src/sample_library/sample_library.cpp +++ b/src/sample_library/sample_library.cpp @@ -1,13 +1,12 @@ -#include +#include -int factorial(int input) noexcept -{ - int result = 1; +int factorial(int input) noexcept { + int result = 1; - while (input > 0) { - result *= input; - --input; - } + while (input > 0) { + result *= input; + --input; + } - return result; + return result; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0739f424..0c2d33a9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,7 +7,7 @@ project(CmakeConfigPackageTests LANGUAGES CXX) if(PROJECT_IS_TOP_LEVEL OR TEST_INSTALLED_VERSION) enable_testing() - find_package(myproject CONFIG REQUIRED) # for intro, project_options, ... + find_package(myproject CONFIG REQUIRED) # for app, project_options, ... if(NOT TARGET myproject_options) message(FATAL_ERROR "Requiered config package not found!") @@ -20,13 +20,13 @@ endif() include(${Catch2_SOURCE_DIR}/extras/Catch.cmake) # Provide a simple smoke test to make sure that the CLI works and can display a --help message -add_test(NAME cli.has_help COMMAND intro --help) +add_test(NAME cli.has_help COMMAND app --help) # Provide a test to verify that the version being reported from the application # matches the version given to CMake. This will be important once you package # your program. Real world shows that this is the kind of simple mistake that is easy # to make, but also easy to test for. -add_test(NAME cli.version_matches COMMAND intro --version) +add_test(NAME cli.version_matches COMMAND app --version) set_tests_properties(cli.version_matches PROPERTIES PASS_REGULAR_EXPRESSION "${PROJECT_VERSION}") add_executable(tests tests.cpp) diff --git a/test/constexpr_tests.cpp b/test/constexpr_tests.cpp index fe36db5e..e069d20a 100644 --- a/test/constexpr_tests.cpp +++ b/test/constexpr_tests.cpp @@ -1,12 +1,10 @@ #include +#include -#include - -TEST_CASE("Factorials are computed with constexpr", "[factorial]") -{ - STATIC_REQUIRE(factorial_constexpr(0) == 1); - STATIC_REQUIRE(factorial_constexpr(1) == 1); - STATIC_REQUIRE(factorial_constexpr(2) == 2); - STATIC_REQUIRE(factorial_constexpr(3) == 6); - STATIC_REQUIRE(factorial_constexpr(10) == 3628800); +TEST_CASE("Factorials are computed with constexpr", "[factorial]") { + STATIC_REQUIRE(factorial_constexpr(0) == 1); + STATIC_REQUIRE(factorial_constexpr(1) == 1); + STATIC_REQUIRE(factorial_constexpr(2) == 2); + STATIC_REQUIRE(factorial_constexpr(3) == 6); + STATIC_REQUIRE(factorial_constexpr(10) == 3628800); } diff --git a/test/tests.cpp b/test/tests.cpp index 5b632e2e..375b2841 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -1,14 +1,10 @@ #include - - -#include - - -TEST_CASE("Factorials are computed", "[factorial]") -{ - REQUIRE(factorial(0) == 1); - REQUIRE(factorial(1) == 1); - REQUIRE(factorial(2) == 2); - REQUIRE(factorial(3) == 6); - REQUIRE(factorial(10) == 3628800); +#include + +TEST_CASE("Factorials are computed", "[factorial]") { + REQUIRE(factorial(0) == 1); + REQUIRE(factorial(1) == 1); + REQUIRE(factorial(2) == 2); + REQUIRE(factorial(3) == 6); + REQUIRE(factorial(10) == 3628800); }