Павлюк Роман Сергеевич
03.11.2021 23:33 (14 д. 21:33)
[5662279]
#pragma once
#include <vector>
#include <string>
#include <map>
#include <set>
#include <unordered_map>
#include <functional>
#include <utility>
bool operator>(const GameObject& a, const GameObject& b) {
return a.id > b.id;
}
template<class Tp, template<class> class Compare>
class DereferenceCompare {
Compare<Tp> comp;
public:
bool operator()(const Tp *const a, const Tp *const b) const {
return comp(*a, *b);
}
};
class GameDatabase {
public:
GameDatabase() = default;
/// вставляет в базу объект с именем [name] и позицией [x, y]
/// если объект с таким id в базе уже есть, заменяет его новым
void Insert(ObjectId id, std::string name, size_t x, size_t y) {
GameObject *newGameObject = new GameObject{id, name, x, y};
this->byId[id] = newGameObject;
this->byName[name].insert(newGameObject);
this->byPos[std::pair<size_t, size_t>(x, y)].insert(newGameObject);
}
/// удаляет элемент по id
/// если такого элемента нет, ничего не делает
void Remove(ObjectId id) {
if (this->byId.find(id) != this->byId.end()) {
GameObject* tmp = this->byId[id];
this->byId.erase(id);
this->byPos.find(std::pair<size_t, size_t>(tmp->x,
tmp->y))->second.erase(tmp);
this->byName.find(tmp->name)->second.erase(tmp);
}
}
/// возвращает вектор объектов c именем [name]
/// сортировка по убыванию id
std::vector<GameObject> DataByName(std::string name) const {
std::vector<GameObject> ans;
if (this->byName.find(name) != this->byName.end()) {
for (auto it : this->byName.at(name)) {
ans.push_back(*it);
}
}
return ans;
}
/// возвращает вектор объектов, находящихся в позиции [x, y]
/// сортировка по убыванию id
std::vector<GameObject> DataByPosition(size_t x, size_t y) const {
std::vector<GameObject> ans;
if (this->byPos.find(std::pair<size_t, size_t>(x, y))
!= this->byPos.end()) {
for (auto it : this->byPos.at(std::pair<size_t, size_t>(x, y))) {
ans.push_back(*it);
}
}
return ans;
}
/// возвращает вектор всех объектов из базы
/// сортировка по убыванию id
std::vector<GameObject> Data() const {
std::vector<GameObject> ans;
for (auto it : this->byId) {
ans.push_back(*it.second);
}
return ans;
}
private:
/// быстрый доступ по id
std::map<ObjectId, GameObject *, std::greater<ObjectId>> byId;
/// быстрый доступ по позиции
std::map<std::pair<size_t, size_t>,
std::set<GameObject *,
DereferenceCompare<GameObject, std::greater>>> byPos;
/// быстрый доступ по имени
std::unordered_map<std::string,
std::set<GameObject *,
DereferenceCompare<GameObject, std::greater>>> byName;
};