#include <cstdlib>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#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 {
std::map<ObjectId, GameObject, std::greater<ObjectId>> fastId;
std::map<std::pair<size_t, size_t>,
std::set<GameObject*, DereferenceCompare<GameObject,
std::greater>>> fastPos;
std::unordered_map<string, std::set<GameObject*,
DereferenceCompare<GameObject, std::greater>>> fastName;
public:
GameDatabase() = default;
void Insert(ObjectId id, string name, size_t x, size_t y) {
GameObject* obj = new GameObject;
obj->id = id;
obj->name = name;
obj->x = x;
obj->y = y;
fastId[id] = *obj;
fastPos[{x, y}].insert(obj);
fastName[name].insert(obj);
}
void Remove(ObjectId id) {
auto idIt = fastId.find(id);
if (idIt != fastId.end()) {
auto posIt = fastPos[{idIt->second.x, idIt->second.y}];
for (auto tempIt = posIt.begin(); tempIt != posIt.end(); ++tempIt) {
if ((*tempIt)->id == id) {
posIt.erase(tempIt);
break;
}
}
auto nameIt = fastName[idIt->second.name];
for (auto tempIt = nameIt.begin();
tempIt != nameIt.end(); ++tempIt) {
if ((*tempIt)->id == id) {
nameIt.erase(tempIt);
break;
}
}
fastId.erase(idIt);
}
}
vector<GameObject> DataByName(string name) const {
auto s = fastName.at(name);
return vector<GameObject> {s.begin(), s.end()};
}
vector<GameObject> DataByPosition(size_t x, size_t y) const {
auto s = fastPos.at({x, y});
return vector<GameObject> {s.begin(), s.end()};
}
vector<GameObject> Data() const {
return vector<GameObject>{fastId.begin(), fastId.end()};
}
};