Tester Stable
This commit is contained in:
parent
f25d3cc8da
commit
2fba0b1d53
17 changed files with 769 additions and 113 deletions
|
@ -2,17 +2,15 @@
|
|||
# CMake Configuration for the Sortiva Project
|
||||
# ========================================================
|
||||
|
||||
# Specify the minimum CMake version required
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
# Project name, languages, and version
|
||||
project(sortiva
|
||||
LANGUAGES CXX
|
||||
VERSION 1.0.0
|
||||
LANGUAGES CXX
|
||||
VERSION 1.0.0
|
||||
)
|
||||
|
||||
# ========================================================
|
||||
# C++ Standard and General Settings
|
||||
# Global Settings
|
||||
# ========================================================
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20) # Use C++20
|
||||
|
@ -22,11 +20,11 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Generate compile commands (useful
|
|||
set(USE_FOLDERS ON) # Organize targets into folders (for IDEs)
|
||||
set(BUILD_SHARED_LIBS OFF) # Build static libraries by default
|
||||
|
||||
# =======================================================
|
||||
# ========================================================
|
||||
# Helper Functions:
|
||||
# Puts Targets into a Folder
|
||||
# Finds all files in a dir wich are defined file-types
|
||||
# =======================================================
|
||||
# ========================================================
|
||||
# This function puts targets into a specified folder.
|
||||
# It checks if the target exists and gets the actual target (if it is aliased).
|
||||
# It then sets the folder property for the target.
|
||||
|
@ -93,6 +91,17 @@ FetchContent_Declare(
|
|||
)
|
||||
FetchContent_MakeAvailable(sol2)
|
||||
|
||||
# --- Add Lua
|
||||
FetchContent_Declare(
|
||||
lua
|
||||
GIT_REPOSITORY "https://github.com/marovira/lua"
|
||||
GIT_TAG "5.4.4"
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(lua)
|
||||
|
||||
set(LUA_BUILD_INTERPRETER ON)
|
||||
|
||||
# ========================================================
|
||||
# Helper Function: Set Common Target Properties
|
||||
# ========================================================
|
||||
|
@ -101,8 +110,10 @@ FetchContent_MakeAvailable(sol2)
|
|||
|
||||
function(set_common_properties target)
|
||||
target_link_libraries(${target} PRIVATE sol2::sol2) # Link with Sol2
|
||||
target_compile_definitions(${target} PRIVATE SOL_ALL_SAFETIES_ON=1)
|
||||
target_include_directories(${target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) # Include project headers
|
||||
target_sources(${target} PRIVATE ${SVA_COMMON_FILES}) # Include common files
|
||||
target_link_libraries(${target} PRIVATE lua::lua)
|
||||
endfunction()
|
||||
|
||||
# ========================================================
|
||||
|
@ -111,11 +122,8 @@ endfunction()
|
|||
|
||||
set(GUI_TARGET_NAME "${PROJECT_NAME}")
|
||||
# --- Create GUI Executable
|
||||
|
||||
find_files(SVA_GUI_FILES "./src/gui/" hpp cpp h c hxx cxx)
|
||||
find_files(SVA_GUI_FILES "./src/" hpp cpp h c hxx cxx)
|
||||
add_executable(${GUI_TARGET_NAME}
|
||||
src/main.cpp # Entry point for the GUI application
|
||||
src/sva.hpp # Header file for the console
|
||||
${SVA_GUI_FILES}
|
||||
)
|
||||
|
||||
|
@ -200,21 +208,22 @@ if(${SVA_BUILD_TEST})
|
|||
enable_testing()
|
||||
|
||||
# --- Create Test Executable
|
||||
set(TEST_TARGET_NAME "${GUI_TARGET_NAME}_test")
|
||||
add_executable(
|
||||
sortiva_test
|
||||
${TEST_TARGET_NAME}
|
||||
tests/test_main.cpp # Test entry point
|
||||
tests/test_sorting_functions.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
sortiva_test
|
||||
${TEST_TARGET_NAME}
|
||||
PRIVATE GTest::gtest_main # Link Google Test framework
|
||||
)
|
||||
set_common_properties(sortiva_test)
|
||||
set_common_properties(${TEST_TARGET_NAME})
|
||||
|
||||
# --- Enable Google Test's test discovery feature
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(sortiva_test)
|
||||
gtest_discover_tests(${TEST_TARGET_NAME})
|
||||
|
||||
# put google test targets into a folder
|
||||
put_targets_into_folder(
|
||||
|
@ -227,3 +236,28 @@ if(${SVA_BUILD_TEST})
|
|||
)
|
||||
endif()
|
||||
|
||||
# Option to create an includes target
|
||||
set(SVA_CREATE_INCLUDES_TARGET ON CACHE BOOL "Create an includes target")
|
||||
|
||||
if(${SVA_CREATE_INCLUDES_TARGET})
|
||||
set(INCLUDES_TARGET_NAME "${GUI_TARGET_NAME}_includes")
|
||||
set(INCLUDE_FILES)
|
||||
find_files(
|
||||
INCLUDE_FILES
|
||||
"include/"
|
||||
hpp h hxx
|
||||
)
|
||||
message(STATUS "Include files: ${INCLUDE_FILES}")
|
||||
add_custom_target(${INCLUDES_TARGET_NAME}
|
||||
SOURCES
|
||||
${INCLUDE_FILES}
|
||||
)
|
||||
set_target_properties(${INCLUDES_TARGET_NAME} PROPERTIES FOLDER "sva")
|
||||
endif()
|
||||
|
||||
put_targets_into_folder(
|
||||
FOLDER "sva"
|
||||
TARGETS
|
||||
${GUI_TARGET_NAME}
|
||||
${TEST_TARGET_NAME}
|
||||
)
|
||||
|
|
106
include/Profiling/Timer.hpp
Normal file
106
include/Profiling/Timer.hpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
#pragma once
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <assert.h>
|
||||
|
||||
struct timer_result
|
||||
{
|
||||
double seconds = 0;
|
||||
double difftime = 0;
|
||||
};
|
||||
|
||||
struct Timer {
|
||||
enum State : u8
|
||||
{
|
||||
running = 0,
|
||||
paused = 1
|
||||
};
|
||||
State state = paused;
|
||||
|
||||
std::clock_t begin;
|
||||
std::clock_t elapsed = 0;
|
||||
std::optional<std::ostream*> out;
|
||||
std::optional<timer_result*> result;
|
||||
|
||||
Timer() : begin(std::clock()) {}
|
||||
Timer(std::ostream& o) : begin(std::clock()), out(&o) {}
|
||||
Timer(timer_result& r) : begin(std::clock()), result(&r) {}
|
||||
Timer(std::ostream& o, timer_result& r) : begin(std::clock()), out(&o), result(&r) {}
|
||||
Timer(State initial_state) : state(initial_state), begin(std::clock())
|
||||
{
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
}
|
||||
|
||||
Timer(std::ostream& o, State initial_state) : state(initial_state), begin(std::clock()), out(&o)
|
||||
{
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
}
|
||||
Timer(timer_result& r, State initial_state) : state(initial_state), begin(std::clock()), result(&r)
|
||||
{
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
}
|
||||
|
||||
Timer(std::ostream& o, timer_result& r, State initial_state) : state(initial_state), begin(std::clock()), out(&o), result(&r)
|
||||
{
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
}
|
||||
|
||||
void reset(State init_state) {
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
else
|
||||
begin = std::clock();
|
||||
elapsed = 0;
|
||||
state = init_state;
|
||||
lap();
|
||||
}
|
||||
|
||||
void set_state(State new_state)
|
||||
{
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
|
||||
if (new_state == running)
|
||||
{
|
||||
begin = std::clock();
|
||||
}
|
||||
else // pausing
|
||||
{
|
||||
assert(begin != 0);
|
||||
elapsed += std::clock() - begin;
|
||||
begin = 0;
|
||||
}
|
||||
|
||||
lap();
|
||||
this->state = new_state;
|
||||
}
|
||||
|
||||
void lap()
|
||||
{
|
||||
std::clock_t total_time = elapsed;
|
||||
if (state == running)
|
||||
{
|
||||
total_time += std::clock() - begin;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
result.value()->seconds = static_cast<double>(total_time) / CLOCKS_PER_SEC;
|
||||
result.value()->difftime = static_cast<double>(total_time) / CLOCKS_PER_SEC;
|
||||
}
|
||||
if (out)
|
||||
{
|
||||
*out.value() << static_cast<double>(total_time) / CLOCKS_PER_SEC << " seconds.\n";
|
||||
*out.value() << "Total time = " << static_cast<double>(total_time) / CLOCKS_PER_SEC << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
~Timer() {
|
||||
lap();
|
||||
}
|
||||
};
|
167
include/list.hpp
Normal file
167
include/list.hpp
Normal file
|
@ -0,0 +1,167 @@
|
|||
#pragma once
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* @brief A thread-safe dynamic array container class
|
||||
*
|
||||
* List provides a fixed-size array container with thread-safe access through mutex protection.
|
||||
* It supports construction with a size or initializer list, as well as copy/move operations.
|
||||
* All operations that access or modify the internal data are protected by a mutex.
|
||||
*
|
||||
* @tparam T The type of elements stored in the list
|
||||
*/
|
||||
template <typename T>
|
||||
class List {
|
||||
public:
|
||||
/**
|
||||
* @brief Type alias for the element type stored in the list
|
||||
*
|
||||
* This type represents the template parameter T that defines
|
||||
* the type of elements contained in the List container.
|
||||
*/
|
||||
using value_type = T;
|
||||
|
||||
/**
|
||||
* @brief Constructs a List with specified size
|
||||
* @param size The number of elements to allocate
|
||||
*/
|
||||
explicit List(std::size_t size)
|
||||
: data_(std::make_unique<T[]>(size))
|
||||
, size_(size) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructs a List from an initializer list
|
||||
* @param init The initializer list containing initial values
|
||||
*/
|
||||
List(std::initializer_list<T> init)
|
||||
: data_(std::make_unique<T[]>(init.size()))
|
||||
, size_(init.size()) {
|
||||
std::lock_guard lock(mutex_);
|
||||
std::copy(init.begin(), init.end(), data_.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param other The List to copy from
|
||||
* @thread_safety Both this and other List's mutexes are locked during copy
|
||||
*/
|
||||
List(const List& other) {
|
||||
std::lock_guard lock(mutex_);
|
||||
std::lock_guard<std::mutex> other_lock(other.mutex_);
|
||||
data_ = std::make_unique<T[]>(other.size_);
|
||||
std::copy(other.data_.get(), other.data_.get() + other.size_, data_.get());
|
||||
size_ = other.size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
* @param other The List to move from
|
||||
* @thread_safety Both this and other List's mutexes are locked during move
|
||||
*/
|
||||
List(List&& other) noexcept {
|
||||
std::lock_guard lock(mutex_);
|
||||
std::lock_guard<std::mutex> other_lock(other.mutex_);
|
||||
data_ = std::move(other.data_);
|
||||
size_ = other.size_;
|
||||
other.size_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator
|
||||
* @param other The List to copy from
|
||||
* @return Reference to this List
|
||||
* @thread_safety Both this and other List's mutexes are locked during assignment
|
||||
*/
|
||||
List& operator=(const List& other) {
|
||||
if (this != &other) {
|
||||
std::lock_guard lock(mutex_);
|
||||
std::lock_guard<std::mutex> other_lock(other.mutex_);
|
||||
data_ = std::make_unique<T[]>(other.size_);
|
||||
std::copy(other.data_.get(), other.data_.get() + other.size_, data_.get());
|
||||
size_ = other.size_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator
|
||||
* @param other The List to move from
|
||||
* @return Reference to this List
|
||||
* @thread_safety Both this and other List's mutexes are locked during move
|
||||
*/
|
||||
List& operator=(List&& other) noexcept {
|
||||
if (this != &other) {
|
||||
std::lock_guard lock(mutex_);
|
||||
std::lock_guard<std::mutex> other_lock(other.mutex_);
|
||||
data_ = std::move(other.data_);
|
||||
size_ = other.size_;
|
||||
other.size_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access element at specified index with bounds wrapping
|
||||
* @param index The index of the element to access
|
||||
* @return Reference to the element at the wrapped index
|
||||
* @thread_safety Protected by mutex
|
||||
*/
|
||||
T& operator[](std::size_t index) {
|
||||
std::lock_guard lock(mutex_);
|
||||
return data_[index % size_];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access const element at specified index with bounds wrapping
|
||||
* @param index The index of the element to access
|
||||
* @return Const reference to the element at the wrapped index
|
||||
* @thread_safety Protected by mutex
|
||||
*/
|
||||
const T& operator[](std::size_t index) const {
|
||||
std::lock_guard lock(mutex_);
|
||||
return data_[index % size_];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get const element at specified index with bounds wrapping
|
||||
* @param index The index of the element to access
|
||||
* @return Const reference to the element at the wrapped index
|
||||
* @thread_safety Protected by mutex
|
||||
*/
|
||||
const T& get(std::size_t index) const
|
||||
{
|
||||
std::lock_guard lock(mutex_);
|
||||
return data_[index % size_];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set element at specified index with bounds wrapping
|
||||
* @param index The index of the element to set
|
||||
* @param value The value to set at the specified index
|
||||
* @thread_safety Protected by mutex
|
||||
*/
|
||||
void set(std::size_t index, const T& value) {
|
||||
std::lock_guard lock(mutex_);
|
||||
data_[index % size_] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the size of the List
|
||||
* @return The number of elements in the List
|
||||
* @thread_safety Protected by mutex
|
||||
*/
|
||||
std::size_t size() const {
|
||||
std::lock_guard lock(mutex_);
|
||||
return size_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<T[]> data_; ///< Underlying array storage
|
||||
std::size_t size_; ///< Number of elements in the array
|
||||
mutable std::mutex mutex_; ///< Mutex for thread-safe access
|
||||
};
|
22
include/std.hpp
Normal file
22
include/std.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#define SHOW(variable) std::cout << #variable << " = " << (variable) << std::endl;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG
|
||||
#define ASSERT(condition, message) while(!(condition)) { std::cerr << "Assertion failed: " << #condition << "\n\t" << (message); exit(1); }
|
||||
#define FATAL_ASSERT(condition, message) ASSERT(condition, message)
|
||||
#else
|
||||
#define RELEASE
|
||||
#define FATAL_ASSERT(condition, message) ASSERT(condition, message) exit(1);
|
||||
#define ASSERT(condition, message) if(!(condition)) { std::cerr << "Assertion failed: " << #condition << "\nIn File: " << __FILE__ << "\nOn line: " << __LINE__ << "\n\t" << (message); }
|
||||
#endif
|
||||
|
||||
#include "types.hpp"
|
||||
#include "list.hpp"
|
||||
#include "flagman.hpp"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "Profiling/Timer.hpp"
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
@ -84,3 +84,4 @@ typedef TRect<double> rectd;
|
|||
typedef TRect<uintmax_t> rectu;
|
||||
typedef TRect<intmax_t> recti;
|
||||
|
||||
#include "list.hpp"
|
1
src/Renderer.cpp
Normal file
1
src/Renderer.cpp
Normal file
|
@ -0,0 +1 @@
|
|||
#include "Renderer.h"
|
7
src/Renderer.h
Normal file
7
src/Renderer.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
|
||||
};
|
42
src/SortingTester.cpp
Normal file
42
src/SortingTester.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "SortingTester.h"
|
||||
|
||||
|
||||
SortingTester::SortingTester() : list(10)
|
||||
{
|
||||
lua.lua.open_libraries(sol::lib::coroutine, sol::lib::table);
|
||||
lua.lua.new_usertype<SortingTester>("List",
|
||||
"size", &SortingTester::list_size,
|
||||
"swap", &SortingTester::list_swap,
|
||||
"greater", &SortingTester::list_greater,
|
||||
"less", &SortingTester::list_less,
|
||||
"equal", &SortingTester::list_equal
|
||||
);
|
||||
|
||||
lua.lua["list"] = this;
|
||||
}
|
||||
|
||||
void SortingTester::load(const std::string& script)
|
||||
{
|
||||
if(lua.load(script) != safesol::LuaResultType::SUCCESS)
|
||||
{
|
||||
std::cerr << "Error loading file" << std::endl;
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
#include "internal_script.hpp"
|
||||
|
||||
void SortingTester::load_internal()
|
||||
{
|
||||
if (lua.script(std_intern_sorting_script) != safesol::LuaResultType::SUCCESS)
|
||||
{
|
||||
std::cerr << "Error loading internal script" << std::endl;
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void SortingTester::populate(const populate_function& f)
|
||||
{
|
||||
for (size_t i = 0; i < list.size(); i++)
|
||||
f(i, list[i]);
|
||||
}
|
152
src/SortingTester.h
Normal file
152
src/SortingTester.h
Normal file
|
@ -0,0 +1,152 @@
|
|||
#pragma once
|
||||
#define SVA_LIST_CALLBACKS
|
||||
#include <std.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include "lua/safesol.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
class SortingTester
|
||||
{
|
||||
List<u64> list;
|
||||
|
||||
safesol lua;
|
||||
|
||||
Timer timer = Timer(Timer::State::paused);
|
||||
|
||||
using populate_function = std::function<void(size_t, u64&)>;
|
||||
|
||||
template<typename ...Args>
|
||||
sol::protected_function_result run_function(const sol::protected_function& function, Args&&... args)
|
||||
{
|
||||
timer.set_state(Timer::State::running);
|
||||
sol::protected_function_result result = function(std::forward<Args>(args)...);
|
||||
timer.set_state(Timer::State::paused);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool list_greater(size_t index1, size_t index2)
|
||||
{
|
||||
if (active_result)
|
||||
++active_result->count_greater;
|
||||
return list[index1] > list[index2];
|
||||
}
|
||||
|
||||
bool list_less(size_t index1, size_t index2)
|
||||
{
|
||||
if (active_result)
|
||||
++active_result->count_less;
|
||||
return list[index1] < list[index2];
|
||||
}
|
||||
|
||||
bool list_equal(size_t index1, size_t index2)
|
||||
{
|
||||
if (active_result)
|
||||
++active_result->count_equal;
|
||||
return list[index1] == list[index2];
|
||||
}
|
||||
|
||||
void list_swap(size_t index1, size_t index2)
|
||||
{
|
||||
if (active_result)
|
||||
++active_result->count_swaps;
|
||||
// list[index1] ^= list[index2];
|
||||
// list[index2] ^= list[index1];
|
||||
// list[index1] ^= list[index2];
|
||||
auto tmp = list[index1];
|
||||
list[index1] = list[index2];
|
||||
list[index2] = tmp;
|
||||
}
|
||||
|
||||
size_t list_size() const
|
||||
{
|
||||
return list.size();
|
||||
}
|
||||
|
||||
bool is_sorted()
|
||||
{
|
||||
if (list.size() <= 1)
|
||||
return true;
|
||||
for (size_t i = 1; i < list.size(); ++i)
|
||||
{
|
||||
if (list[i - 1] > list[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
struct run_result
|
||||
{
|
||||
timer_result timer;
|
||||
// counts
|
||||
u64 count_swaps = 0;
|
||||
u64 count_greater = 0;
|
||||
u64 count_less = 0;
|
||||
u64 count_equal = 0;
|
||||
// counts for comparisons
|
||||
u64 count_comparisons = 0;
|
||||
};
|
||||
private:
|
||||
run_result* active_result = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
SortingTester();
|
||||
|
||||
void load(const std::string& script);
|
||||
void load_internal();
|
||||
|
||||
template<typename ...Args>
|
||||
run_result run(const std::string& function_name, Args&&... args)
|
||||
{
|
||||
run_result result;
|
||||
timer.result.emplace(&result.timer);
|
||||
timer.reset(Timer::State::paused);
|
||||
active_result = &result;
|
||||
|
||||
// Create a bound member function using std::bind
|
||||
auto bound_run_function = std::bind(&SortingTester::run_function<Args...>,
|
||||
this,
|
||||
std::placeholders::_1,
|
||||
std::forward<Args>(args)...);
|
||||
|
||||
safesol::LuaResultType runstate = lua.run_on_caller(function_name, bound_run_function);
|
||||
|
||||
if (runstate != safesol::LuaResultType::SUCCESS)
|
||||
{
|
||||
std::cerr << "Error running function \"" << function_name << "\": " << static_cast<u16>(runstate) << std::endl;
|
||||
exit(static_cast<int>(runstate));
|
||||
}
|
||||
|
||||
if (!is_sorted())
|
||||
{
|
||||
std::cerr << "[ERROR] The algorithm \"" << function_name << "\" did not sort the list" << std::endl;
|
||||
std::cerr << "[List] [ ";
|
||||
for (size_t i = 0; i < list.size(); i++)
|
||||
{
|
||||
if(i == list.size()-1)
|
||||
{
|
||||
std::cerr << list[i] << " ]";
|
||||
continue;
|
||||
}
|
||||
std::cerr << list[i] << ", ";
|
||||
}
|
||||
std::flush(std::cerr);
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
result.count_comparisons = result.count_equal + result.count_greater + result.count_less;
|
||||
|
||||
active_result = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void populate(const populate_function& f);
|
||||
};
|
|
@ -1,13 +0,0 @@
|
|||
#include "View.h"
|
||||
#include <raylibs/raygui.h>
|
||||
|
||||
void View::draw()
|
||||
{
|
||||
BeginDrawing();
|
||||
ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
void View::update()
|
||||
{
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
#pragma once
|
||||
#include "raylib.h"
|
||||
#include <types.hpp>
|
||||
|
||||
class View
|
||||
{
|
||||
friend class ViewManager;
|
||||
public:
|
||||
View(rectu rect) : m_rect(rect) {}
|
||||
virtual ~View() = default;
|
||||
virtual void draw();
|
||||
virtual void update();
|
||||
virtual void onMouseDown(vec2d mousePos) {}
|
||||
virtual void onMouseUp(vec2d mousePos) {}
|
||||
virtual void onMouseMove(vec2d mousePos) {}
|
||||
virtual void onKeyDown(int key) {}
|
||||
virtual void onKeyUp(int key) {}
|
||||
virtual void onKeyPress(int key) {}
|
||||
virtual void onFocus() {}
|
||||
virtual void onBlur() {}
|
||||
|
||||
virtual void onResize(vec2d factor)
|
||||
{
|
||||
m_rect.width = static_cast<rectu::type>(static_cast<float>(m_rect.width) * factor.x);
|
||||
m_rect.height = static_cast<rectu::type>(static_cast<float>(m_rect.height) * factor.y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
vec2u getPosition() const { return {m_rect.x, m_rect.y}; }
|
||||
vec2u getSize() const { return {m_rect.width, m_rect.height}; }
|
||||
const rectu& getRect() const { return m_rect; }
|
||||
void setPosition(vec2u pos) { m_rect.x = pos.x; m_rect.y = pos.y; }
|
||||
void setSize(vec2u size) { m_rect.width = size.x; m_rect.height = size.y; }
|
||||
void setRect(rectu &rect) { m_rect = rect; }
|
||||
virtual void Resize(float multiplier)
|
||||
{
|
||||
m_rect.width = static_cast<rectu::type>(static_cast<float>(m_rect.width) * multiplier);
|
||||
m_rect.height = static_cast<rectu::type>(static_cast<float>(m_rect.height) * multiplier);
|
||||
}
|
||||
private:
|
||||
rectu m_rect;
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
#include "ViewManager.h"
|
||||
|
||||
ViewManager::ViewManager()
|
||||
{
|
||||
m_viewportSize = { GetScreenWidth(), GetScreenHeight() };
|
||||
m_mainView = new View({ 0, 0, m_viewportSize.x, m_viewportSize.y });
|
||||
}
|
||||
|
||||
void ViewManager::update()
|
||||
{
|
||||
if (IsWindowResized())
|
||||
{
|
||||
m_viewportSize = { GetScreenWidth(), GetScreenHeight() };
|
||||
m_mainView->onResize({ static_cast<float>(m_viewportSize.x), static_cast<float>(m_viewportSize.y) });
|
||||
}
|
||||
m_mainView->update();
|
||||
}
|
||||
|
||||
void ViewManager::draw()
|
||||
{
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#pragma once
|
||||
#include "View.h"
|
||||
#include <vector>
|
||||
#include <types.hpp>
|
||||
|
||||
class ViewManager
|
||||
{
|
||||
vec2u m_viewportSize;
|
||||
public:
|
||||
ViewManager();
|
||||
~ViewManager();
|
||||
void update();
|
||||
void draw();
|
||||
private:
|
||||
View* m_mainView;
|
||||
};
|
27
src/internal_script.hpp
Normal file
27
src/internal_script.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
inline const char* std_intern_sorting_script = R"(
|
||||
-- bubble sort
|
||||
function bubble_sort()
|
||||
isSorted = false
|
||||
while isSorted == false do
|
||||
movedElements = 0
|
||||
for x=1, list:size(), 1 do
|
||||
if list:greater(x, x+1) then
|
||||
movedElements = movedElements + 1
|
||||
list:swap(x, x+1)
|
||||
end
|
||||
end
|
||||
if movedElements == 0 then
|
||||
isSorted = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function do_nothing()
|
||||
end
|
||||
|
||||
-- other functions
|
||||
|
||||
|
||||
)";
|
61
src/lua/safesol.cpp
Normal file
61
src/lua/safesol.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include "safesol.h"
|
||||
|
||||
safesol::LuaResultType safesol::script(const std::string& script)
|
||||
{
|
||||
sol::load_result result = lua.load(script);
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cout << "Error loading script: " << err.what() << std::endl;
|
||||
return LuaResultType::LOAD_ERROR;
|
||||
}
|
||||
|
||||
sol::protected_function_result script_result = result();
|
||||
|
||||
if (!script_result.valid()) {
|
||||
sol::error err = script_result;
|
||||
std::cout << "Error running script: " << err.what() << std::endl;
|
||||
return LuaResultType::SCRIPT_ERROR;
|
||||
}
|
||||
|
||||
return LuaResultType::SUCCESS;
|
||||
}
|
||||
|
||||
safesol::LuaResultType safesol::script(const char* script)
|
||||
{
|
||||
sol::load_result result = lua.load(script);
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cout << "Error loading script: " << err.what() << std::endl;
|
||||
return LuaResultType::LOAD_ERROR;
|
||||
}
|
||||
|
||||
sol::protected_function_result script_result = result();
|
||||
|
||||
if (!script_result.valid()) {
|
||||
sol::error err = script_result;
|
||||
std::cout << "Error running script: " << err.what() << std::endl;
|
||||
return LuaResultType::SCRIPT_ERROR;
|
||||
}
|
||||
|
||||
return LuaResultType::SUCCESS;
|
||||
}
|
||||
|
||||
safesol::LuaResultType safesol::load(const std::string& file)
|
||||
{
|
||||
sol::load_result result = lua.load_file(file);
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cout << "Error loading file: " << err.what() << std::endl;
|
||||
return LuaResultType::LOAD_ERROR;
|
||||
}
|
||||
|
||||
sol::protected_function_result script_result = result();
|
||||
|
||||
if (!script_result.valid()) {
|
||||
sol::error err = script_result;
|
||||
std::cout << "Error running script: " << err.what() << std::endl;
|
||||
return LuaResultType::SCRIPT_ERROR;
|
||||
}
|
||||
|
||||
return LuaResultType::SUCCESS;
|
||||
}
|
55
src/lua/safesol.h
Normal file
55
src/lua/safesol.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
#include <std.hpp>
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
class safesol
|
||||
{
|
||||
public:
|
||||
enum class LuaResultType : u8
|
||||
{
|
||||
SUCCESS = 0,
|
||||
LOAD_ERROR = 1,
|
||||
SCRIPT_ERROR,
|
||||
RUN_ERROR,
|
||||
UNKNOWN_ERROR
|
||||
};
|
||||
|
||||
sol::state lua;
|
||||
|
||||
|
||||
LuaResultType script(const std::string& script);
|
||||
LuaResultType script(const char* script);
|
||||
|
||||
LuaResultType load(const std::string& file);
|
||||
|
||||
template<typename ...Args>
|
||||
sol::protected_function_result default_caller(const sol::protected_function& function, Args&&... args)
|
||||
{
|
||||
return function(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
LuaResultType run(const std::string& function_name, Args&&... args)
|
||||
{
|
||||
return run_on_caller(function_name, default_caller, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename ...Args, typename Caller = std::function<sol::protected_function_result(const sol::protected_function&, Args&&...)>>
|
||||
LuaResultType run_on_caller(const std::string& function_name, const Caller& caller, Args&&... args)
|
||||
{
|
||||
auto function = lua[function_name];
|
||||
if (!function.valid()) {
|
||||
std::cout << "Error: function " << function_name << " not found" << std::endl;
|
||||
return LuaResultType::RUN_ERROR;
|
||||
}
|
||||
|
||||
auto result = caller(function, std::forward<Args>(args)...);
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cout << "Error running function " << function_name << ": " << err.what() << std::endl;
|
||||
return LuaResultType::RUN_ERROR;
|
||||
}
|
||||
|
||||
return LuaResultType::SUCCESS;
|
||||
}
|
||||
};
|
78
src/main.cpp
78
src/main.cpp
|
@ -6,8 +6,14 @@
|
|||
|
||||
#include "gui/drawing_helper.hpp"
|
||||
|
||||
#define RESOURCES_PATH "G:\\School\\Belegarbeit\\sortiva\\res\\"
|
||||
#define RESOURCES_PATH "G:/School/Belegarbeit/sortiva/res/"
|
||||
|
||||
#define SETTINGS_PATH "./.config.cfg"
|
||||
|
||||
#define NO_GUI
|
||||
|
||||
|
||||
#ifndef NO_GUI
|
||||
|
||||
int screenWidth = 1280;
|
||||
int screenHeight = 720;
|
||||
|
@ -23,13 +29,77 @@ GAME_STATES gameState = SVA_STATE_TITLE;
|
|||
void UpdateDrawFrame(); // Update and Draw one frame
|
||||
|
||||
#include "gui/themes/dark.h"
|
||||
#include <filesystem>
|
||||
#include "gui/Views/ViewManager.h"
|
||||
#endif
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
#ifdef NO_GUI
|
||||
#include "SortingTester.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <random>
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<u64> dis(0, 10);
|
||||
|
||||
void populate(size_t index, u64& value)
|
||||
{
|
||||
value = dis(gen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
sva_console_init();
|
||||
|
||||
#ifdef NO_GUI
|
||||
|
||||
std::cout << "Sortiva - Sorting Algorithm Visualizer" << std::endl;
|
||||
std::cout << "No GUI mode" << std::endl;
|
||||
|
||||
SortingTester tester;
|
||||
tester.populate( populate );
|
||||
|
||||
tester.load_internal();
|
||||
|
||||
SortingTester::run_result result = tester.run("bubble_sort");
|
||||
|
||||
std::cout << "Time: " << result.timer.seconds << " seconds" << std::endl;
|
||||
std::cout << "Difftime: " << result.timer.difftime << std::endl;
|
||||
|
||||
|
||||
std::cout << "Count swaps: " << result.count_swaps << std::endl;
|
||||
std::cout << "Count comparisons: " << result.count_comparisons << std::endl;
|
||||
std::cout << "\tCount greater: " << result.count_greater << std::endl;
|
||||
std::cout << "\tCount less: " << result.count_less << std::endl;
|
||||
std::cout << "\tCount equal: " << result.count_equal << std::endl;
|
||||
|
||||
std::cout << "\n\n";
|
||||
|
||||
|
||||
result = tester.run("do_nothing");
|
||||
|
||||
std::cout << "Time: " << result.timer.seconds << " seconds" << std::endl;
|
||||
std::cout << "Difftime: " << result.timer.difftime << std::endl;
|
||||
|
||||
|
||||
std::cout << "Count swaps: " << result.count_swaps << std::endl;
|
||||
std::cout << "Count comparisons: " << result.count_comparisons << std::endl;
|
||||
std::cout << "\tCount greater: " << result.count_greater << std::endl;
|
||||
std::cout << "\tCount less: " << result.count_less << std::endl;
|
||||
std::cout << "\tCount equal: " << result.count_equal << "\n\n";
|
||||
|
||||
std::cout << "\nPress any key to exit..." << std::endl;
|
||||
getchar();
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NO_GUI
|
||||
if(!DirectoryExists(RESOURCES_PATH))
|
||||
{
|
||||
std::cerr << "Resources folder not found!" << std::endl;
|
||||
|
@ -62,9 +132,11 @@ int main(int argc, char** argv)
|
|||
UpdateDrawFrame();
|
||||
}
|
||||
CloseWindow();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef NO_GUI
|
||||
//----------------------------------------------------------------------------------
|
||||
// Render Functions
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -150,3 +222,5 @@ void RenderGameplayState()
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue