diff --git a/include/app/app.h b/include/app/app.h index 66aafeb..660896c 100644 --- a/include/app/app.h +++ b/include/app/app.h @@ -180,6 +180,8 @@ struct Scene { element_pool[id]->click(); } +#warning "This does not take rotation into account \ +reference and use reverse-transform on point then AABB check instead" std::vector elements_at(Vec2 position) { std::vector result; @@ -211,6 +213,11 @@ struct App { uint64_t current_scene_id = 0; bool running = true; Vec2 mouse_position = {-1, -1}; + std::array down_keys{}; + std::vector pressed_keys; + std::vector released_keys; + Vec2 scroll = {0, 0}; + std::string text = ""; void exit() { running = false; @@ -246,6 +253,11 @@ struct App { Scene *scene = scene_pool[current_scene_id]; + pressed_keys.clear(); + released_keys.clear(); + scroll = {0, 0}; + text = ""; + Event e; while (window.poll(e)) { switch (e.type) { @@ -254,6 +266,12 @@ struct App { break; case Event::MOUSE_BUTTON_DOWN: scene->click(e.mouse_button.position); + down_keys[e.mouse_button.button] = true; + pressed_keys.push_back(e.mouse_button.button); + break; + case Event::MOUSE_BUTTON_UP: + down_keys[e.mouse_button.button] = false; + released_keys.push_back(e.mouse_button.button); break; case Event::MOUSE_MOVE: mouse_position = e.mouse_move.position; @@ -261,10 +279,24 @@ struct App { case Event::MOUSE_LEAVE: mouse_position = {-1, -1}; break; + case Event::KEY_DOWN: + down_keys[e.key.key] = true; + pressed_keys.push_back(e.key.key); + break; + case Event::KEY_UP: + down_keys[e.key.key] = false; + released_keys.push_back(e.key.key); + break; + case Event::SCROLL: + scroll = e.scroll; + break; + case Event::TEXT_INPUT: + text += *e.text_input; + delete e.text_input; + break; default: break; } - window.consume(e); } scene->update_scene(dt); diff --git a/include/binding/definitions.h b/include/binding/definitions.h index 9e131b2..32c4fc8 100644 --- a/include/binding/definitions.h +++ b/include/binding/definitions.h @@ -134,6 +134,16 @@ static mrb_value image_hash(mrb_state *mrb, mrb_value self) { return mrb_fixnum_value(id); } +static mrb_value image_width(mrb_state *mrb, mrb_value self) { + uint64_t id = get_id_Image(mrb, self); + return mrb_float_value(mrb, window.get_image_size(id).x); +} + +static mrb_value image_height(mrb_state *mrb, mrb_value self) { + uint64_t id = get_id_Image(mrb, self); + return mrb_float_value(mrb, window.get_image_size(id).y); +} + static void Animation_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t id = ((Wrapper *)ptr)->id; @@ -578,6 +588,18 @@ static mrb_value element_text_click_through_set(mrb_state *mrb, mrb_value self) return mrb_nil_value(); } +static mrb_value element_text_width(mrb_state *mrb, mrb_value self) { + uint64_t id = get_id_ElementText(mrb, self); + app::EText *element = (app::EText *)app::element_pool[id]; + return mrb_float_value(mrb, element->size(&window).x); +} + +static mrb_value element_text_height(mrb_state *mrb, mrb_value self) { + uint64_t id = get_id_ElementText(mrb, self); + app::EText *element = (app::EText *)app::element_pool[id]; + return mrb_float_value(mrb, element->size(&window).y); +} + static void ElementRect_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t id = ((Wrapper *)ptr)->id; @@ -1413,6 +1435,58 @@ static mrb_value app_mouse_position(mrb_state *mrb, mrb_value) { return result; } +static mrb_value app_is_down(mrb_state *mrb, mrb_value) { + mrb_sym key_sym; + mrb_get_args(mrb, "n", &key_sym); + std::string key_name = mrb_sym2name(mrb, key_sym); + Key key = get_key(key_name); + return mrb_bool_value(app_->down_keys[key]); +} + +static mrb_value app_is_pressed(mrb_state *mrb, mrb_value) { + mrb_sym key_sym; + mrb_get_args(mrb, "n", &key_sym); + std::string key_name = mrb_sym2name(mrb, key_sym); + Key key = get_key(key_name); + for (Key pressed_key : app_->pressed_keys) + if (pressed_key == key) + return mrb_bool_value(true); + return mrb_bool_value(false); +} + +static mrb_value app_is_released(mrb_state *mrb, mrb_value) { + mrb_sym key_sym; + mrb_get_args(mrb, "n", &key_sym); + std::string key_name = mrb_sym2name(mrb, key_sym); + Key key = get_key(key_name); + for (Key released_key : app_->released_keys) + if (released_key == key) + return mrb_bool_value(true); + return mrb_bool_value(false); +} + +static mrb_value app_map_key(mrb_state *mrb, mrb_value) { + mrb_sym key_sym; + mrb_sym action_sym; + mrb_get_args(mrb, "nn", &key_sym, &action_sym); + std::string key_name = mrb_sym2name(mrb, key_sym); + std::string action_name = mrb_sym2name(mrb, action_sym); + set_action_mapping(action_name, key_name); + return mrb_nil_value(); +} + +static mrb_value app_scroll(mrb_state *mrb, mrb_value) { + Vec2 scroll = app_->scroll; + mrb_value result = mrb_hash_new(mrb); + HASH_SET(result, x, mrb_float_value(mrb, scroll.x)); + HASH_SET(result, y, mrb_float_value(mrb, scroll.y)); + return result; +} + +static mrb_value app_text_input(mrb_state *mrb, mrb_value) { + return mrb_str_new_cstr(mrb, app_->text.c_str()); +} + static mrb_value app_exit(mrb_state *, mrb_value) { app_->exit(); return mrb_nil_value(); @@ -1428,6 +1502,8 @@ inline void setup() { ADD_METHOD(Image, "==", image_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Image, "eql?", image_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Image, "hash", image_hash, MRB_ARGS_NONE()); + ADD_METHOD(Image, "width", image_width, MRB_ARGS_NONE()); + ADD_METHOD(Image, "height", image_height, MRB_ARGS_NONE()); DEF_CLASS(Animation, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); ADD_METHOD(Animation, "==", animation_equal, MRB_ARGS_REQ(1)); @@ -1463,6 +1539,8 @@ inline void setup() { ADD_METHOD(ElementText, "z", element_text_z_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "click_through=", element_text_click_through_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "click_through", element_text_click_through_get, MRB_ARGS_NONE()); + ADD_METHOD(ElementText, "width", element_text_width, MRB_ARGS_NONE()); + ADD_METHOD(ElementText, "height", element_text_height, MRB_ARGS_NONE()); DEF_CLASS(ElementRect, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(1)); ADD_METHOD(ElementRect, "==", element_rect_equal, MRB_ARGS_REQ(1)); @@ -1527,7 +1605,13 @@ inline void setup() { ADD_MODULE_METHOD(App, "language=", app_language_set, MRB_ARGS_REQ(1)); ADD_MODULE_METHOD(App, "language", app_language_get, MRB_ARGS_NONE()); ADD_MODULE_METHOD(App, "mouse_position", app_mouse_position, MRB_ARGS_NONE()); - ADD_MODULE_METHOD(App, "exit", app_exit, MRB_ARGS_NONE()); + ADD_MODULE_METHOD(App, "down?", app_is_down, MRB_ARGS_REQ(1)); + ADD_MODULE_METHOD(App, "pressed?", app_is_pressed, MRB_ARGS_REQ(1)); + ADD_MODULE_METHOD(App, "released?", app_is_released, MRB_ARGS_REQ(1)); + ADD_MODULE_METHOD(App, "map_key", app_map_key, MRB_ARGS_REQ(2)); + ADD_MODULE_METHOD(App, "scroll", app_scroll, MRB_ARGS_NONE()); + ADD_MODULE_METHOD(App, "text_input", app_text_input, MRB_ARGS_NONE()); + ADD_MODULE_METHOD(App, "exit!", app_exit, MRB_ARGS_NONE()); } } // namespace definitions diff --git a/include/window/window.h b/include/window/window.h index 7b321d9..0dcaaee 100644 --- a/include/window/window.h +++ b/include/window/window.h @@ -40,6 +40,220 @@ inline Pool font_pool; // Text pool inline Pool text_pool; +enum Key : uint16_t { + Unknown = SDL_SCANCODE_UNKNOWN, + + A = SDL_SCANCODE_A, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + + Num0 = SDL_SCANCODE_0, + Num1, + Num2, + Num3, + Num4, + Num5, + Num6, + Num7, + Num8, + Num9, + + Space = SDL_SCANCODE_SPACE, + Enter = SDL_SCANCODE_RETURN, + Escape = SDL_SCANCODE_ESCAPE, + Tab = SDL_SCANCODE_TAB, + Backspace = SDL_SCANCODE_BACKSPACE, + + LeftShift = SDL_SCANCODE_LSHIFT, + RightShift = SDL_SCANCODE_RSHIFT, + LeftCtrl = SDL_SCANCODE_LCTRL, + RightCtrl = SDL_SCANCODE_RCTRL, + LeftAlt = SDL_SCANCODE_LALT, + RightAlt = SDL_SCANCODE_RALT, + CapsLock = SDL_SCANCODE_CAPSLOCK, + + Up = SDL_SCANCODE_UP, + Down = SDL_SCANCODE_DOWN, + Left = SDL_SCANCODE_LEFT, + Right = SDL_SCANCODE_RIGHT, + Home = SDL_SCANCODE_HOME, + End = SDL_SCANCODE_END, + PageUp = SDL_SCANCODE_PAGEUP, + PageDown = SDL_SCANCODE_PAGEDOWN, + + Delete = SDL_SCANCODE_DELETE, + Insert = SDL_SCANCODE_INSERT, + + Minus = SDL_SCANCODE_MINUS, + Equals = SDL_SCANCODE_EQUALS, + LeftBracket = SDL_SCANCODE_LEFTBRACKET, + RightBracket = SDL_SCANCODE_RIGHTBRACKET, + Semicolon = SDL_SCANCODE_SEMICOLON, + Apostrophe = SDL_SCANCODE_APOSTROPHE, + Grave = SDL_SCANCODE_GRAVE, + Comma = SDL_SCANCODE_COMMA, + Period = SDL_SCANCODE_PERIOD, + Slash = SDL_SCANCODE_SLASH, + Backslash = SDL_SCANCODE_NONUSBACKSLASH, + + F1 = SDL_SCANCODE_F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + + MouseLeft = 513, + MouseMiddle, + MouseRight +}; + +constexpr std::pair KEY_NAMES[] = { + {"a", Key::A}, + {"b", Key::B}, + {"c", Key::C}, + {"d", Key::D}, + {"e", Key::E}, + {"f", Key::F}, + {"g", Key::G}, + {"h", Key::H}, + {"i", Key::I}, + {"j", Key::J}, + {"k", Key::K}, + {"l", Key::L}, + {"m", Key::M}, + {"n", Key::N}, + {"o", Key::O}, + {"p", Key::P}, + {"q", Key::Q}, + {"r", Key::R}, + {"s", Key::S}, + {"t", Key::T}, + {"u", Key::U}, + {"v", Key::V}, + {"w", Key::W}, + {"x", Key::X}, + {"y", Key::Y}, + {"z", Key::Z}, + + {"num0", Key::Num0}, + {"num1", Key::Num1}, + {"num2", Key::Num2}, + {"num3", Key::Num3}, + {"num4", Key::Num4}, + {"num5", Key::Num5}, + {"num6", Key::Num6}, + {"num7", Key::Num7}, + {"num8", Key::Num8}, + {"num9", Key::Num9}, + + {"space", Key::Space}, + {"enter", Key::Enter}, + {"escape", Key::Escape}, + {"tab", Key::Tab}, + {"backspace", Key::Backspace}, + + {"left_shift", Key::LeftShift}, + {"right_shift", Key::RightShift}, + {"left_ctrl", Key::LeftCtrl}, + {"right_ctrl", Key::RightCtrl}, + {"left_alt", Key::LeftAlt}, + {"right_alt", Key::RightAlt}, + {"capslock", Key::CapsLock}, + + {"up", Key::Up}, + {"down", Key::Down}, + {"left", Key::Left}, + {"right", Key::Right}, + {"home", Key::Home}, + {"end", Key::End}, + {"page_up", Key::PageUp}, + {"page_down", Key::PageDown}, + + {"delete", Key::Delete}, + {"insert", Key::Insert}, + + {"minus", Key::Minus}, + {"equals", Key::Equals}, + {"left_bracket", Key::LeftBracket}, + {"right_bracket", Key::RightBracket}, + {"semicolon", Key::Semicolon}, + {"apostrophe", Key::Apostrophe}, + {"grave", Key::Grave}, + {"comma", Key::Comma}, + {"period", Key::Period}, + {"slash", Key::Slash}, + {"backslash", Key::Backslash}, + + {"f1", Key::F1}, + {"f2", Key::F2}, + {"f3", Key::F3}, + {"f4", Key::F4}, + {"f5", Key::F5}, + {"f6", Key::F6}, + {"f7", Key::F7}, + {"f8", Key::F8}, + {"f9", Key::F9}, + {"f10", Key::F10}, + {"f11", Key::F11}, + {"f12", Key::F12}, + + {"mouse_left", Key::MouseLeft}, + {"mouse_middle", Key::MouseMiddle}, + {"mouse_right", Key::MouseRight} +}; + +inline Key get_key_from_name(std::string_view name) { + for (const auto &[key_name, key] : KEY_NAMES) + if (key_name == name) + return key; + return Key::Unknown; +} + +inline std::unordered_map action_key_map; + +inline void set_action_mapping(const std::string &action_name, const std::string &key_name) { + Key key = get_key_from_name(key_name); + if (key != Key::Unknown) + action_key_map[action_name] = key; +} + +inline Key get_key(std::string &name) { + auto it = action_key_map.find(name); + if (it != action_key_map.end()) + return it->second; + return get_key_from_name(name); +} + struct Event { enum Type { NONE, @@ -56,20 +270,15 @@ struct Event { union { struct { - uint32_t key; + Key key; } key; - struct { - char *text; - uint32_t length; - } text_input; + std::string *text_input; + + Vec2 scroll; struct { - float x, y; - } scroll; - - struct { - uint8_t button; + Key button; Vec2 position; } mouse_button; @@ -125,16 +334,6 @@ public: bool poll(Event &event); // returns true if an event was polled, false otherwise - // consumes an event, (mostly for text input, to free the text input buffer) - // but also so the user can decide when they're done with the event explicitly. - void consume(Event &event); - - // Text input - // Starts accepting Unicode text input events, and stops acceptong normal key down/up events for those keys. - - void start_text_input(); - void stop_text_input(); - // Clipboard get // To be free'd by the caller after use. @@ -190,8 +389,6 @@ private: std::vector render_instructions; - bool text_input_active; - void compute_transform(); bool mouse_in_window(const Vec2 real_position, Vec2 &virtual_position); diff --git a/samples/button.rb b/samples/button.rb index 622af5d..c77b166 100644 --- a/samples/button.rb +++ b/samples/button.rb @@ -12,7 +12,7 @@ bg_animation = Animation.new [bg_image1, bg_image2], fps: 5 App.language = :en App.localize(:en, :btn_text, "Click %{name}!") -text = ElementText.new :btn_text, default_font, 0xFFFFFF, {name: "Me"}, position: {x: 50, y: 50}, z: 1, click_through: true, alpha: 1 +text = ElementText.new :btn_text, default_font, 0xFFFF00, {name: "Me"}, position: {x: 50, y: 50}, z: 1, click_through: true, alpha: 1 rect = ElementRect.new 100, 25, 0xFF0000, position: {x: 50, y: 50}, z: 0, rotation: 60, scale: { x: 1.5, y: 1 }, alpha: 0.4 @@ -28,40 +28,7 @@ rect.on_click do text.params! end - -=begin - -input handling: - -App.map_key(:space, :jump) # maps the space key to a :jump action (multiple keys can be mapped to the same action) -# all events here are in english ones, (so need to find which english key corresponds to the key in the current language of the keyboard) -key can be one of [:a..:z, :0..:9, :space, :enter, :shift, :ctrl, :alt, :tab, :backspace, :escape, :up, :down, :left, :right, :middle] - -this can be checked anywhere using: - -App.down?(:jump) # returns true if the jump action is currently being pressed -App.pressed?(:jump) # returns true if the jump action was just pressed this frame -App.released?(:jump) # returns true if the jump action was just released this frame - -for wheel, you can use: - -App.wheel # returns a hash with :x and :y values representing the wheel movement since the last frame (can be used for zooming, scrolling, etc.) - -mouse position can be accessed with: - -App.mouse_position # returns a hash with :x and :y values representing the current mouse position in the window - -For localized input, you can use: - -App.start_text_input! - -App.text_input # returns the text typed this frame as a string (useful for text input fields, chat, etc.) - # can be multiple characters if the user types fast, so you should append it to a string variable to get the full input - -App.stop_text_input! - - -=end +App.map_key :mouse_left, :press main_scene.on_update do |delta_time| # puts "Delta time: #{delta_time}ms" @@ -69,13 +36,20 @@ main_scene.on_update do |delta_time| # runs at 60fps, so you should see around 16-17ms being printed el = main_scene.elements_at(App.mouse_position) + + puts App.text_input if App.text_input != "" + + next unless App.pressed?(:press) + + puts "#{App.pressed?(:press)}, #{App.down?(:press)}, #{App.released?(:press)}" + for elem in el if elem == image_element - #puts "Hovering over image element" + puts "Down over image element" elsif elem == rect - #puts "Hovering over rect element" + puts "Down over rect element" elsif elem == text - #puts "Hovering over text element" + puts "Down over text element" end end diff --git a/src/window/window.cc b/src/window/window.cc index 2632e75..bcec760 100644 --- a/src/window/window.cc +++ b/src/window/window.cc @@ -15,7 +15,7 @@ Window::Window(Vec2 size, const char *title) { compute_transform(); - text_input_active = false; + SDL_StartTextInput(window); white_tex = SDL_CreateTexture( renderer, @@ -370,22 +370,17 @@ bool Window::poll(Event &event) { case SDL_EVENT_KEY_DOWN: event.type = Event::KEY_DOWN; - event.key.key = sdl_event.key.scancode; + event.key.key = (Key)sdl_event.key.scancode; break; case SDL_EVENT_KEY_UP: event.type = Event::KEY_UP; - event.key.key = sdl_event.key.scancode; + event.key.key = (Key)sdl_event.key.scancode; break; case SDL_EVENT_TEXT_INPUT: - if (!text_input_active) - return false; event.type = Event::TEXT_INPUT; - event.text_input.length = strlen(sdl_event.text.text); - event.text_input.text = (char *)malloc(event.text_input.length + 1); - strcpy(event.text_input.text, sdl_event.text.text); - event.text_input.text[event.text_input.length] = '\0'; + event.text_input = new std::string(sdl_event.text.text); break; case SDL_EVENT_WINDOW_MOUSE_LEAVE: @@ -394,7 +389,7 @@ bool Window::poll(Event &event) { case SDL_EVENT_MOUSE_BUTTON_DOWN: { event.type = Event::MOUSE_BUTTON_DOWN; - event.mouse_button.button = sdl_event.button.button; + event.mouse_button.button = (Key)(sdl_event.button.button + 512); Vec2 virtual_position; if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position)) event.mouse_button.position = virtual_position; @@ -404,7 +399,7 @@ bool Window::poll(Event &event) { case SDL_EVENT_MOUSE_BUTTON_UP: { event.type = Event::MOUSE_BUTTON_UP; - event.mouse_button.button = sdl_event.button.button; + event.mouse_button.button = (Key)(sdl_event.button.button + 512); Vec2 virtual_position; if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position)) event.mouse_button.position = virtual_position; @@ -444,26 +439,6 @@ bool Window::poll(Event &event) { return false; } -void Window::consume(Event &event) { - if (event.type == Event::TEXT_INPUT) { - free(event.text_input.text); - event.text_input.text = nullptr; - event.text_input.length = 0; - } - - event.type = Event::NONE; -} - -void Window::start_text_input() { - text_input_active = true; - SDL_StartTextInput(window); -} - -void Window::stop_text_input() { - text_input_active = false; - SDL_StopTextInput(window); -} - const char *Window::paste() { const char *clipboard_text = SDL_GetClipboardText(); if (clipboard_text == nullptr) { diff --git a/tests/a.out b/tests/a.out new file mode 100755 index 0000000..00bffa8 Binary files /dev/null and b/tests/a.out differ diff --git a/tests/array_vs_hash.cc b/tests/array_vs_hash.cc new file mode 100644 index 0000000..c43622f --- /dev/null +++ b/tests/array_vs_hash.cc @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono; + +int N = 1000000; // 1,000,000 tries +int L = 20; // string length + +string random_string(size_t length) { + static const string chars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + static random_device rd; + static mt19937 gen(rd()); + + uniform_int_distribution<> dist(0, chars.size() - 1); + + string s; + + for (size_t i = 0; i < length; i++) { + s += chars[dist(gen)]; + } + + return s; +} + +void test_array(int length) { + std::unordered_map hash_map; + hash_map.reserve(length * 2); // Reserve more to avoid rehashing + std::vector> array; + array.reserve(length); + + vector keys; + + for (int i = 0; i < length; ++i) { + string key = random_string(L); + + keys.push_back(key); + + hash_map[key] = i; + array.emplace_back(key, i); + } + + auto start = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < N; ++i) { + string &key = keys[i % length]; + + auto it = hash_map.find(key); + + volatile int value = it->second; + (void)value; + } + auto end = std::chrono::high_resolution_clock::now(); + auto hash_duration = std::chrono::duration_cast(end - start).count(); + + start = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < N; ++i) { + string &key = keys[i % length]; + + auto it = std::find_if(array.begin(), array.end(), [&key](const auto &pair) { + return pair.first == key; + }); + + volatile int value = it->second; + (void)value; + } + end = std::chrono::high_resolution_clock::now(); + auto array_duration = std::chrono::duration_cast(end - start).count(); + + std::cout << length << "," << hash_duration << "," << array_duration << "\n"; +} + +int main() { + std::cout << "elements,hash,array\n"; + + for (int length = 1; length <= 10; length++) + test_array(length); + for (int length = 10; length <= 100; length += 10) + test_array(length); + for (int length = 100; length <= 1000; length += 100) + test_array(length); + + return 0; +} \ No newline at end of file diff --git a/tests/benchmark.csv b/tests/benchmark.csv new file mode 100644 index 0000000..03a9261 --- /dev/null +++ b/tests/benchmark.csv @@ -0,0 +1,31 @@ +elements,hash,array +1,53,36 +2,57,49 +3,83,65 +4,99,84 +5,117,99 +6,132,115 +7,145,128 +8,163,141 +9,174,156 +10,191,167 +10,190,169 +20,339,306 +30,74,442 +40,71,579 +50,78,719 +60,74,874 +70,75,1064 +80,83,1244 +90,83,1394 +100,85,1477 +100,86,1485 +200,80,2912 +300,82,4401 +400,82,5946 +500,83,7526 +600,84,9256 +700,86,10927 +800,88,12828 +900,89,14502 +1000,90,16302 diff --git a/tests/benchmark.png b/tests/benchmark.png new file mode 100644 index 0000000..40418fa Binary files /dev/null and b/tests/benchmark.png differ diff --git a/tests/grapher.py b/tests/grapher.py new file mode 100644 index 0000000..4f7d732 --- /dev/null +++ b/tests/grapher.py @@ -0,0 +1,24 @@ +import pandas as pd +import matplotlib.pyplot as plt + +df = pd.read_csv("benchmark.csv") + +plt.figure(figsize=(10, 6)) + +plt.plot(df["elements"], df["hash"], marker='o', label="Hash map") +plt.plot(df["elements"], df["array"], marker='o', label="Array") + +# LOG SCALE +plt.xscale("log") +plt.yscale("log") + +plt.xlabel("Number of elements (log scale)") +plt.ylabel("Time (ms) (log scale)") +plt.title("Array vs Hash Map Lookup Performance") + +plt.grid(True, which="both", linestyle="--", alpha=0.5) +plt.legend() + +plt.show() + +plt.savefig("benchmark.png", dpi=200, bbox_inches="tight") \ No newline at end of file diff --git a/tests/o0-N20.png b/tests/o0-N20.png new file mode 100644 index 0000000..99c6bfa Binary files /dev/null and b/tests/o0-N20.png differ diff --git a/tests/o0-N3.png b/tests/o0-N3.png new file mode 100644 index 0000000..9f25884 Binary files /dev/null and b/tests/o0-N3.png differ