#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <utility>
#include <set>
#include <functional>
bool operator>(const GameObject &a, const GameObject &b) {
return a.id > b.id;
}
bool operator<(const GameObject &a, const GameObject &b) {
return a.id < b.id;
}
template<class Tp, template<class> class Compare>
class DereferenceCompare {
public:
Compare<Tp> comp;
bool operator()(const Tp *const a, const Tp *const b) const {
return comp(*a, *b);
}
};
class GameDatabase {
public:
GameDatabase() = default;
void Insert(ObjectId id, std::string name, size_t x, size_t y) {
this->Remove(id);
GameObject tmp{id, name, x, y};
this->byId.insert(std::pair<ObjectId, GameObject>(id, tmp));
this->byPos[std::pair<size_t, size_t>(x, y)].insert(tmp);
this->byName[name].insert(tmp);
}
void Remove(ObjectId id) {
if (this->byId.find(id) != this->byId.end()) {
GameObject tmp = this->byId.at(id);
this->byPos[{tmp.x, tmp.y}].erase(tmp);
this->byName[tmp.name].erase(tmp);
this->byId.erase(id);
}
}
std::vector<GameObject> DataByName(std::string name) const {
std::vector<GameObject> tmp;
if (this->byName.find(name) != this->byName.end()) {
for (auto obj = this->byName.at(name).rbegin();
obj != this->byName.at(name).rend(); ++obj) {
tmp.push_back(*obj);
}
}
return tmp;
}
std::vector<GameObject> DataByPosition(size_t x, size_t y) const {
std::vector<GameObject> tmp;
if (this->byPos.find({x, y}) != this->byPos.end()) {
for (auto obj = this->byPos.at({x, y}).rbegin();
obj != this->byPos.at({x, y}).rend(); ++obj) {
tmp.push_back(*obj);
}
}
return tmp;
}
std::vector<GameObject> Data() const {
std::vector<GameObject> tmp;
for (auto pair = this->byId.rbegin();
pair != this->byId.rend(); ++pair) {
tmp.push_back(pair->second);
}
return tmp;
}
private:
std::map<ObjectId, GameObject> byId{};
std::map<std::pair<size_t, size_t>, std::set<GameObject>> byPos;
std::unordered_map<std::string, std::set<GameObject>> byName;
};