From 6b9502ea3e5bfb303616b43afee3a96a1b026e58 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 10 Aug 2020 02:34:09 +0100 Subject: [PATCH] Store items and icons into the db --- meson_options.txt | 1 + src/config.hpp.in | 1 + src/evloop.cpp | 7 ++-- src/evloop.hpp | 3 +- src/main.cpp | 5 ++- src/meson.build | 3 ++ src/oro/originsdb.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++ src/oro/originsdb.hpp | 24 ++++++++++++ src/timer_icons.cpp | 42 ++++++++++++++++++++ src/timer_icons.hpp | 37 ++++++++++++++++++ src/timer_items.cpp | 9 ++++- src/timer_items.hpp | 5 ++- 12 files changed, 219 insertions(+), 9 deletions(-) create mode 100644 src/oro/originsdb.cpp create mode 100644 src/oro/originsdb.hpp create mode 100644 src/timer_icons.cpp create mode 100644 src/timer_icons.hpp diff --git a/meson_options.txt b/meson_options.txt index f45184c..c186aea 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1 +1,2 @@ option('base_url', type: 'string', value: 'https://api.originsro.org') +option('database_file', type: 'string', value: 'originsro.db3') diff --git a/src/config.hpp.in b/src/config.hpp.in index 707a64f..e0f8a33 100644 --- a/src/config.hpp.in +++ b/src/config.hpp.in @@ -3,5 +3,6 @@ namespace duck { constexpr const char g_base_url[] = "@BASE_URL@"; +constexpr const char g_database[] = "@DATABASE@"; } //namespace duck diff --git a/src/evloop.cpp b/src/evloop.cpp index 7259f22..cff0153 100644 --- a/src/evloop.cpp +++ b/src/evloop.cpp @@ -1,7 +1,7 @@ #include "evloop.hpp" #include "timer_items.hpp" +#include "timer_icons.hpp" #include "eventia/eventia.hpp" -#include "eventia/timer.hpp" #include "roar11/ThreadPool.hpp" #include "oro/api.hpp" #include @@ -27,14 +27,15 @@ void join(roar11::ThreadPool& pool) { } //unnamed namespace -void test(oro::Api* api) { +void test(oro::Api* api, oro::OriginsDB* db) { const std::size_t thread_count = 2U; //std::min(std::max(3U, std::thread::hardware_concurrency()) - 1, 4U); std::cout << "Running with " << thread_count << " worker threads\n"; roar11::ThreadPool pool(thread_count); eve::Eventia worker; pool.submit(worker.event_functor()); - auto fetcher = worker.make_timer(3.0, &pool, api); + auto timer_items = worker.make_timer(3.0, &pool, api, db); + auto timer_icons = worker.make_timer(20.0, &pool, api, db); join(pool); } diff --git a/src/evloop.hpp b/src/evloop.hpp index 5a86842..11d56f5 100644 --- a/src/evloop.hpp +++ b/src/evloop.hpp @@ -2,10 +2,11 @@ namespace oro { class Api; + class OriginsDB; } //namespace oro namespace duck { -void test(oro::Api* api); +void test(oro::Api* api, oro::OriginsDB* db); } //namespace duck diff --git a/src/main.cpp b/src/main.cpp index 8215de0..177ff67 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ #include "oro/api.hpp" +#include "oro/originsdb.hpp" #include "orotool_config.hpp" -#include "SQLiteCpp/SQLiteCpp.h" #include "evloop.hpp" #include @@ -24,7 +24,8 @@ int main(int argc, char* argv[]) { std::cout << "answer: " << ping.second.message << '\n'; std::cout << "version: " << ping.second.version << '\n'; - duck::test(&oro_api); + oro::OriginsDB db; + duck::test(&oro_api, &db); /* { diff --git a/src/meson.build b/src/meson.build index 24a0dfa..76e6866 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,6 +20,7 @@ endif conf = configuration_data() conf.set('BASE_URL', base_url) +conf.set('DATABASE', get_option('database_file')) project_config_file = configure_file( input: 'config.hpp.in', output: meson.project_name() + '_config.hpp', @@ -44,6 +45,8 @@ executable(meson.project_name(), 'eventia/eventia.cpp', 'eventia/timer.cpp', 'timer_items.cpp', + 'timer_icons.cpp', + 'oro/originsdb.cpp', project_config_file, install: true, dependencies: lib_deps, diff --git a/src/oro/originsdb.cpp b/src/oro/originsdb.cpp new file mode 100644 index 0000000..7c41926 --- /dev/null +++ b/src/oro/originsdb.cpp @@ -0,0 +1,91 @@ +#include "originsdb.hpp" +#include "SQLiteCpp/Database.h" +#include "SQLiteCpp/Statement.h" +#include "SQLiteCpp/Transaction.h" +#include "orotool_config.hpp" +#include "SQLiteCpp/SQLiteCpp.h" +#include "oro/items.hpp" +#include "oro/icons.hpp" +#include "oro/base64.hpp" +#include + +namespace oro { + +namespace { + class Database : private std::unique_lock, public SQLite::Database { + public: + explicit Database(std::mutex& mtx) : + std::unique_lock(mtx), + SQLite::Database(duck::g_database, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE) + { + } + }; +} //unnamed namespace + +OriginsDB::OriginsDB() = default; + +OriginsDB::~OriginsDB() noexcept = default; + +void OriginsDB::overwrite (const Items& items) { + Database db(m_db_mutex); + + db.exec("DROP TABLE IF EXISTS items"); + SQLite::Transaction transaction(db); + + //example: + //{ + // "item_id":501, + // "unique_name":"Red_Potion", + // "name":"Red Potion", + // "type":"IT_HEALING", + // "npc_price":50 + //} + db.exec("CREATE TABLE items (item_id INTEGER PRIMARY KEY, unique_name TEXT, name TEXT, type INTEGER, subtype INTEGER, npc_price INTEGER, slots INTEGER, icon TEXT)"); + + SQLite::Statement query(db, "INSERT INTO items(item_id, unique_name, name, type, subtype, npc_price, slots) VALUES(?, ?, ?, ?, ?, ?, ?)"); + for (const auto& item : items.items) { + query.bind(1, item.item_id); + query.bind(2, item.unique_name); + query.bind(3, item.name); + query.bind(4, static_cast(item.type.value)); + if (item.subtype) + query.bind(5, static_cast(item.subtype->value)); + else + query.bind(5, nullptr); + query.bind(6, item.npc_price); + if (item.slots) + query.bind(7, *item.slots); + else + query.bind(7, nullptr); + + query.exec(); + query.reset(); + } + + transaction.commit(); +} + +void OriginsDB::update (const Icons& icons) { + //example: + //{ + // "item_id":501, + // "icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAP1BMVEX/AP/XqpHDkHqudmL////ox6X/9LxJSUm3t7eSkpLb29tubm7Kt6//8+u+QzDTjG7tZEfyhVmPIhi4o5v/8OVQ35yOAAAAAXRSTlMAQObYZgAAAAFiS0dEBI9o2VEAAAAHdElNRQfkAg4MBBc1u27AAAAAmElEQVQoz7WP2w6DIBAFsSyedavLRf//W7uQVmk0afvQeSIzOQSc+wfDcPOXnigE/1MYxxBw0szTYAMwv2kikunuPcBEc+8XknkCVNXOfHhADOYYVYG9mE92V2y08iksQBbRp+/CDM3CSRulKNb9E5o4p/QK6/Fe0WyhpVI6bxORZK7SD+pELn0t7ZqTd25raT35mrZL/TUPifEKODGf6AcAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDItMTRUMTI6MDQ6MjMrMDA6MDCsyg5gAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTAyLTE0VDEyOjA0OjIzKzAwOjAw3Ze23AAAAABJRU5ErkJggg==" + //} + + Database db(m_db_mutex); + SQLite::Transaction transaction(db); + SQLite::Statement query(db, "UPDATE items SET icon = ? WHERE item_id = ?"); + + for (const auto& ico : icons.icons) { + query.bind(1, ico.icon); + query.bind(2, ico.item_id); + query.exec(); + query.reset(); + + base64_decode(std::string_view(ico.icon).substr(std::string_view("data:image/png;base64,").size())); + } + + transaction.commit(); +} + +} //namespace oro diff --git a/src/oro/originsdb.hpp b/src/oro/originsdb.hpp new file mode 100644 index 0000000..896e146 --- /dev/null +++ b/src/oro/originsdb.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace oro { + +struct Items; +struct Icons; +struct Shops; +struct Creators; + +class OriginsDB { +public: + OriginsDB(); + ~OriginsDB() noexcept; + + void overwrite (const Items& items); + void update (const Icons& icons); + +private: + std::mutex m_db_mutex; +}; + +} //namespace oro diff --git a/src/timer_icons.cpp b/src/timer_icons.cpp new file mode 100644 index 0000000..dd17dbb --- /dev/null +++ b/src/timer_icons.cpp @@ -0,0 +1,42 @@ +#include "timer_icons.hpp" +#include "oro/originsdb.hpp" +#include "oro/api.hpp" +#include "eventia/private/context.hpp" +#include "roar11/ThreadPool.hpp" +#include +#include + +namespace duck { + TimerIcons::TimerIcons ( + const eve::Context& ctx, + double timeout, + roar11::ThreadPool* pool, + oro::Api* oro_api, + oro::OriginsDB* db + ) : + eve::Timer(timeout, ctx), + m_pool(pool), + m_oro_api(oro_api), + m_db(db) + { + assert(m_pool); + assert(m_oro_api); + } + + void TimerIcons::on_timer() { + m_pool->submit(&TimerIcons::fetch_data, this); + } + + void TimerIcons::fetch_data() { + auto icons = m_oro_api->items_icons(); + + { + const int next_timer = icons.first.retry_after / icons.first.rate_limit; + std::cout << "Next timer in " << next_timer << " secs\n"; + set_timer(static_cast(next_timer)); + } + + m_db->update(icons.second); + } + +} //namespace duck diff --git a/src/timer_icons.hpp b/src/timer_icons.hpp new file mode 100644 index 0000000..ee8bec4 --- /dev/null +++ b/src/timer_icons.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "eventia/private/context.hpp" +#include "eventia/timer.hpp" + +namespace roar11 { + class ThreadPool; +} //namespace roar11 + +namespace oro { + class Api; + class OriginsDB; +} //namespace oro + +namespace duck { + +class TimerIcons : eve::Timer { +public: + TimerIcons ( + const eve::Context& ctx, + double timeout, + roar11::ThreadPool* pool, + oro::Api* oro_api, + oro::OriginsDB* db + ); + + virtual void on_timer() override; + +private: + void fetch_data(); + + roar11::ThreadPool* m_pool; + oro::Api* m_oro_api; + oro::OriginsDB* m_db; +}; + +} //namespace duck diff --git a/src/timer_items.cpp b/src/timer_items.cpp index cd27b79..23e1509 100644 --- a/src/timer_items.cpp +++ b/src/timer_items.cpp @@ -1,4 +1,5 @@ #include "timer_items.hpp" +#include "oro/originsdb.hpp" #include "oro/api.hpp" #include "eventia/private/context.hpp" #include "roar11/ThreadPool.hpp" @@ -10,11 +11,13 @@ namespace duck { const eve::Context& ctx, double timeout, roar11::ThreadPool* pool, - oro::Api* oro_api + oro::Api* oro_api, + oro::OriginsDB* db ) : eve::Timer(timeout, ctx), m_pool(pool), - m_oro_api(oro_api) + m_oro_api(oro_api), + m_db(db) { assert(m_pool); assert(m_oro_api); @@ -32,6 +35,8 @@ namespace duck { std::cout << "Next timer in " << next_timer << " secs\n"; set_timer(static_cast(next_timer)); } + + m_db->overwrite(items.second); } } //namespace duck diff --git a/src/timer_items.hpp b/src/timer_items.hpp index 65f70e1..96ae39f 100644 --- a/src/timer_items.hpp +++ b/src/timer_items.hpp @@ -9,6 +9,7 @@ namespace roar11 { namespace oro { class Api; + class OriginsDB; } //namespace oro namespace duck { @@ -19,7 +20,8 @@ public: const eve::Context& ctx, double timeout, roar11::ThreadPool* pool, - oro::Api* oro_api + oro::Api* oro_api, + oro::OriginsDB* db ); virtual void on_timer() override; @@ -29,6 +31,7 @@ private: roar11::ThreadPool* m_pool; oro::Api* m_oro_api; + oro::OriginsDB* m_db; }; } //namespace duck