-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
570 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
#include <std_include.hpp> | ||
|
||
#include "event_rankings.hpp" | ||
#include "player_records.hpp" | ||
#include "players.hpp" | ||
|
||
#include <utils/cryptography.hpp> | ||
#include <utils/string.hpp> | ||
#include <utils/nt.hpp> | ||
|
||
#define TABLE_DEF R"( | ||
create table if not exists `event_rankings` | ||
( | ||
id bigint unsigned not null auto_increment, | ||
player_id bigint unsigned not null, | ||
event_id int unsigned not null, | ||
player_rank bigint unsigned not null default 0, | ||
value int unsigned not null default 0, | ||
primary key (`id`), | ||
foreign key (`player_id`) references players(`id`), | ||
unique key `unique_player_event_rankings_type` (`player_id`, `event_id`) | ||
))" | ||
|
||
namespace database::event_rankings | ||
{ | ||
namespace | ||
{ | ||
std::unordered_map<std::string, event_ranking_lookup_type> lookup_type_map = | ||
{ | ||
{"BEST", lookup_best}, | ||
{"AROUND", lookup_around}, | ||
}; | ||
|
||
std::unordered_map<std::string, event_class> event_class_map = | ||
{ | ||
{"SNEAK", class_fob}, | ||
{"SNEAK_EVENT", class_fob_event}, | ||
{"LEAGUE", class_league}, | ||
{"LEAGUE_EVENT", class_league_event}, | ||
}; | ||
} | ||
|
||
std::optional<event_type> get_event_type_from_id(const std::uint32_t id, const std::string& type) | ||
{ | ||
const auto upper = utils::string::to_upper(type); | ||
const auto iter = event_class_map.find(upper); | ||
if (iter == event_class_map.end()) | ||
{ | ||
return {}; | ||
} | ||
|
||
if ((iter->second == class_fob || iter->second == class_fob_event) && id <= fob_event_end) | ||
{ | ||
return static_cast<event_type>(id); | ||
} | ||
else if ((iter->second == class_league || iter->second == class_league_event) && id <= (league_event_end - fob_event_end)) | ||
{ | ||
return static_cast<event_type>(id + league_event_start); | ||
} | ||
|
||
return {}; | ||
} | ||
|
||
std::optional<event_ranking_lookup_type> get_lookup_type_from_name(const std::string& name) | ||
{ | ||
const auto upper = utils::string::to_upper(name); | ||
const auto iter = lookup_type_map.find(upper); | ||
if (iter == lookup_type_map.end()) | ||
{ | ||
return {}; | ||
} | ||
|
||
return {iter->second}; | ||
} | ||
|
||
GET_FIELD_C(event_ranking, std::uint64_t, id); | ||
GET_FIELD_C(event_ranking, std::uint64_t, player_id); | ||
GET_FIELD_C(event_ranking, std::uint32_t, event_id); | ||
GET_FIELD_C(event_ranking, std::uint64_t, rank); | ||
GET_FIELD_C(event_ranking, std::uint32_t, value); | ||
GET_FIELD_C(event_ranking, std::uint32_t, fob_grade); | ||
GET_FIELD_C(event_ranking, std::uint32_t, league_grade); | ||
GET_FIELD_C(event_ranking, std::uint64_t, account_id); | ||
|
||
void create_entries(const std::uint64_t player_id) | ||
{ | ||
database::access([&](database_t& db) | ||
{ | ||
for (auto i = 0; i < event_count; i++) | ||
{ | ||
db->operator()( | ||
sqlpp::insert_into(event_ranking::table) | ||
.set(event_ranking::table.player_id = player_id, | ||
event_ranking::table.event_id = i) | ||
); | ||
} | ||
}); | ||
} | ||
|
||
bool set_event_value(const std::uint64_t player_id, const event_type event_id, const std::uint32_t value) | ||
{ | ||
return database::access<bool>([&](database_t& db) | ||
{ | ||
const auto result = db->operator()( | ||
sqlpp::update(event_ranking::table) | ||
.set(event_ranking::table.value = value) | ||
.where(event_ranking::table.player_id == player_id && event_ranking::table.event_id == static_cast<std::uint32_t>(event_id)) | ||
); | ||
|
||
return result != 0; | ||
}); | ||
} | ||
|
||
bool increment_event_value(const std::uint64_t player_id, const event_type event_id, const std::uint32_t count) | ||
{ | ||
return database::access<bool>([&](database_t& db) | ||
{ | ||
const auto result = db->operator()( | ||
sqlpp::update(event_ranking::table) | ||
.set(event_ranking::table.value = event_ranking::table.value + count) | ||
.where(event_ranking::table.player_id == player_id && event_ranking::table.event_id == static_cast<std::uint32_t>(event_id)) | ||
); | ||
|
||
return result != 0; | ||
}); | ||
} | ||
|
||
bool set_value_if_bigger(const std::uint64_t player_id, const event_type event_id, const std::uint32_t value) | ||
{ | ||
return database::access<bool>([&](database_t& db) | ||
{ | ||
const auto result = db->operator()( | ||
sqlpp::update(event_ranking::table) | ||
.set(event_ranking::table.value = value) | ||
.where(event_ranking::table.player_id == player_id && | ||
event_ranking::table.event_id == static_cast<std::uint32_t>(event_id) && event_ranking::table.value < value) | ||
); | ||
|
||
return result != 0; | ||
}); | ||
} | ||
|
||
bool reset_periodic_values() | ||
{ | ||
return database::access<bool>([&](database_t& db) | ||
{ | ||
const auto result = db->operator()( | ||
sqlpp::update(event_ranking::table) | ||
.set(event_ranking::table.value = 0, event_ranking::table.player_rank = 0) | ||
.where(event_ranking::table.event_id != static_cast<std::uint32_t>(ep_earned)) | ||
); | ||
|
||
return result != 0; | ||
}); | ||
} | ||
|
||
std::optional<std::uint64_t> get_player_rank(const std::uint64_t player_id, const event_type event_id) | ||
{ | ||
return database::access<std::optional<std::uint64_t>>([&](database_t& db) | ||
-> std::optional<std::uint64_t> | ||
{ | ||
auto results = db->operator()( | ||
sqlpp::select(event_ranking::table.player_rank) | ||
.from(event_ranking::table) | ||
.where(event_ranking::table.event_id == static_cast<std::uint32_t>(event_id) && | ||
event_ranking::table.player_id == player_id) | ||
); | ||
|
||
if (results.empty()) | ||
{ | ||
return {}; | ||
} | ||
|
||
return {results.front().player_rank}; | ||
}); | ||
} | ||
|
||
std::vector<event_ranking> get_entries(const event_type event_id, const std::uint64_t offset, const std::uint32_t num) | ||
{ | ||
return database::access<std::vector<event_ranking>>([&](database_t& db) | ||
-> std::vector<event_ranking> | ||
{ | ||
std::vector<event_ranking> list; | ||
|
||
auto joined_tables = event_ranking::table | ||
.join(player_records::player_record::table) | ||
.on(event_ranking::table.player_id == player_records::player_record::table.player_id) | ||
.join(players::player::table) | ||
.on(event_ranking::table.player_id == player_records::player_record::table.player_id && event_ranking::table.player_id == players::player::table.id); | ||
|
||
auto results = db->operator()( | ||
sqlpp::select(sqlpp::all_of(event_ranking::table), player_records::player_record::table.fob_grade, player_records::player_record::table.league_grade, | ||
players::player::table.account_id) | ||
.from(joined_tables) | ||
.where(event_ranking::table.player_rank != 0 && event_ranking::table.event_id == static_cast<std::uint32_t>(event_id)) | ||
.order_by(event_ranking::table.player_rank.asc()) | ||
.limit(num) | ||
.offset(offset) | ||
); | ||
|
||
for (auto& row : results) | ||
{ | ||
event_ranking entry{row}; | ||
entry.set_fob_grade(static_cast<std::uint32_t>(row.fob_grade)); | ||
entry.set_league_grade(static_cast<std::uint32_t>(row.league_grade)); | ||
entry.set_account_id(row.account_id); | ||
list.emplace_back(entry); | ||
} | ||
|
||
return list; | ||
}); | ||
} | ||
|
||
std::chrono::system_clock::time_point last_update{}; | ||
|
||
void update_entries(database_t& db) | ||
{ | ||
const auto now = std::chrono::system_clock::now(); | ||
if (now - last_update < 10min) | ||
{ | ||
return; | ||
} | ||
|
||
last_update = now; | ||
|
||
db->execute(R"( | ||
with ranked_players as ( | ||
select player_id, value, | ||
(select count(distinct value) + 1 | ||
from event_rankings pr2 | ||
where pr2.value > pr1.value) as new_rank | ||
from event_rankings pr1 | ||
) | ||
update event_rankings record | ||
join ranked_players ranked_player on record.player_id = ranked_player.player_id | ||
set record.player_rank = ranked_player.new_rank where record.value > 0; | ||
)"); | ||
} | ||
|
||
std::chrono::seconds get_last_update() | ||
{ | ||
auto a = last_update.time_since_epoch(); | ||
return std::chrono::duration_cast<std::chrono::seconds>(last_update.time_since_epoch()); | ||
} | ||
|
||
class table final : public table_interface | ||
{ | ||
public: | ||
void create(database_t& database) override | ||
{ | ||
database->execute(TABLE_DEF); | ||
} | ||
|
||
void run_tasks(database_t& database) | ||
{ | ||
update_entries(database); | ||
} | ||
}; | ||
} | ||
|
||
REGISTER_TABLE(database::event_rankings::table, -1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#pragma once | ||
|
||
#include "../database.hpp" | ||
|
||
#include "player_data.hpp" | ||
|
||
#include "utils/tpp.hpp" | ||
|
||
namespace database::event_rankings | ||
{ | ||
enum event_class | ||
{ | ||
class_fob, | ||
class_fob_event, | ||
class_league, | ||
class_league_event | ||
}; | ||
|
||
enum event_type | ||
{ | ||
fob_event_start = 0, | ||
ep_earned = 0, | ||
most_ep_in_mission = 1, | ||
cores_reached_defender = 2, | ||
cores_reached_no_defender = 3, | ||
damage_defender = 4, | ||
materials_stolen = 5, | ||
total_stealth = 6, | ||
unknown = 7, | ||
defense_deployments = 8, | ||
defense_deployments_support = 9, | ||
defense_deployments_support_received = 10, | ||
defender_neutralized_intruder = 11, | ||
successful_defenses = 12, | ||
times_neutralized_by_intruder = 13, | ||
fob_event_ranking = 14, | ||
fob_event_end = 14, | ||
|
||
league_event_start = 15, | ||
league_1 = 15, | ||
league_2 = 16, | ||
league_3 = 17, | ||
league_4 = 18, | ||
league_5 = 19, | ||
league_6 = 20, | ||
league_7 = 21, | ||
league_8 = 22, | ||
league_9 = 23, | ||
league_10 = 24, | ||
league_11 = 25, | ||
league_event_end = 25, | ||
|
||
event_count | ||
}; | ||
|
||
enum event_ranking_lookup_type | ||
{ | ||
lookup_best, // best global | ||
lookup_around // around your placement | ||
}; | ||
|
||
enum event_ranking_type | ||
{ | ||
event_type_sneak, // all time | ||
event_type_sneak_event // within period | ||
}; | ||
|
||
std::optional<event_ranking_lookup_type> get_lookup_type_from_name(const std::string& name); | ||
std::optional<event_type> get_event_type_from_id(const std::uint32_t id, const std::string& type); | ||
|
||
class event_ranking | ||
{ | ||
public: | ||
DEFINE_FIELD(id, sqlpp::integer_unsigned); | ||
DEFINE_FIELD(player_id, sqlpp::integer_unsigned); | ||
DEFINE_FIELD(event_id, sqlpp::integer_unsigned); | ||
DEFINE_FIELD(player_rank, sqlpp::integer_unsigned); | ||
DEFINE_FIELD(value, sqlpp::integer_unsigned); | ||
DEFINE_TABLE(event_rankings, id_field_t, player_id_field_t, event_id_field_t, player_rank_field_t, value_field_t); | ||
|
||
inline static table_t table; | ||
|
||
template <typename ...Args> | ||
event_ranking(const sqlpp::result_row_t<Args...>& row) | ||
{ | ||
this->id_ = row.id; | ||
this->player_id_ = row.player_id; | ||
this->event_id_ = static_cast<std::uint32_t>(row.event_id); | ||
this->rank_ = row.player_rank; | ||
this->value_ = static_cast<std::uint32_t>(row.value); | ||
} | ||
|
||
void set_league_grade(const std::uint32_t grade) | ||
{ | ||
this->league_grade_ = grade; | ||
} | ||
|
||
void set_fob_grade(const std::uint32_t grade) | ||
{ | ||
this->fob_grade_ = grade; | ||
} | ||
|
||
void set_account_id(const std::uint64_t account_id) | ||
{ | ||
this->account_id_ = account_id; | ||
} | ||
|
||
GET_FIELD_H(std::uint64_t, id); | ||
GET_FIELD_H(std::uint64_t, player_id); | ||
GET_FIELD_H(std::uint32_t, event_id); | ||
GET_FIELD_H(std::uint64_t, rank); | ||
GET_FIELD_H(std::uint32_t, value); | ||
GET_FIELD_H(std::uint32_t, fob_grade); | ||
GET_FIELD_H(std::uint32_t, league_grade); | ||
GET_FIELD_H(std::uint64_t, account_id); | ||
|
||
private: | ||
|
||
}; | ||
|
||
void create_entries(const std::uint64_t player_id); | ||
|
||
bool set_event_value(const std::uint64_t player_id, const event_type event_id, const std::uint32_t value); | ||
bool increment_event_value(const std::uint64_t player_id, const event_type event_id, const std::uint32_t count); | ||
bool set_value_if_bigger(const std::uint64_t player_id, const event_type event_id, const std::uint32_t value); | ||
|
||
std::optional<std::uint64_t> get_player_rank(const std::uint64_t player_id, const event_type event_id); | ||
|
||
std::vector<event_ranking> get_entries(const event_type event_id, const std::uint64_t offset, const std::uint32_t num); | ||
|
||
bool reset_periodic_values(); | ||
|
||
std::chrono::seconds get_last_update(); | ||
} |
Oops, something went wrong.