Ширяев Денис Александрович
08.11.2021 00:30 (18 д. 22:30)
[5709432]
#include <set>
#include <map>
#include <unordered_map>
#include <utility>
#include <functional>
#include <string>
#include <vector>
using std::vector;
using std::string;
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, const string &name, size_t x, size_t y);
/// удаляет элемент по id
/// если такого элемента нет, ничего не делает
void Remove(ObjectId id);
/// возвращает вектор объектов c именем [name]
/// сортировка по убыванию id
vector<GameObject> DataByName(string name) const;
/// возвращает вектор объектов, находящихся в позиции [x, y]
/// сортировка по убыванию id
vector<GameObject> DataByPosition(size_t x, size_t y) const;
/// возвращает вектор всех объектов из базы
/// сортировка по убыванию id
vector<GameObject> Data() const;
private:
/// быстрый доступ по id
std::map<ObjectId, GameObject, std::greater<ObjectId>> _data_id;
/// быстрый доступ по позиции
std::map<std::pair<size_t, size_t>,
std::set<GameObject *, DereferenceCompare<GameObject,
std::greater>>> _data_pos;
/// быстрый доступ по имени
std::unordered_map<string, std::set<GameObject *,
DereferenceCompare<GameObject, std::greater>>> _data_name;
};
bool cmp(const GameObject &a, const GameObject &b) {
return a.id > b.id;
}
void GameDatabase::Insert(ObjectId id, const string &name, size_t x, size_t y) {
_data_id[id] = {id, name, x, y};
_data_pos[{x, y}].insert(&_data_id[id]);
_data_name[name].insert(&_data_id[id]);
}
void GameDatabase::Remove(ObjectId id) {
auto item = _data_id[id];
_data_pos[{item.x, item.y}].erase(&item);
_data_name[item.name].erase(&item);
_data_id.erase(id);
}
vector<GameObject> GameDatabase::DataByName(string name) const {
vector<GameObject> data;
if (_data_name.find(name) == _data_name.end())
return data;
for (auto gmObj : _data_name.at(name))
data.push_back(*gmObj);
return data;
}
vector<GameObject> GameDatabase::DataByPosition(size_t x, size_t y) const {
vector<GameObject> data;
if (_data_pos.find({x, y}) == _data_pos.end())
return data;
for (auto gmObj : _data_pos.at({x, y}))
data.push_back(*gmObj);
return data;
}
vector<GameObject> GameDatabase::Data() const {
vector<GameObject> data;
for (const auto &item : _data_id) {
data.push_back(item.second);
}
return data;
}