#pragma once
#include <set>
#include <map>
struct Coordinates {
size_t x;
size_t y;
};
bool operator<(const Coordinates& lhs, const Coordinates& rhs) {
return tie(lhs.x, lhs.y) < tie(rhs.x, rhs.y);
}
bool operator>(const Coordinates& lhs, const Coordinates& rhs) {
return tie(lhs.x, lhs.y) > tie(rhs.x, rhs.y);
}
bool operator==(const Coordinates& lhs, const Coordinates& rhs) {
return tie(lhs.x, lhs.y) == tie(rhs.x, rhs.y);
}
bool operator<(const GameObject& lhs, const GameObject& rhs) {
return lhs.id < rhs.id;
}
bool operator>(const GameObject& lhs, const GameObject& rhs) {
return lhs.id > rhs.id;
}
bool operator==(const GameObject& lhs, const GameObject& rhs) {
return lhs.id == rhs.id;
}
class GameDatabase {
public:
GameDatabase() = default;
/// вставляет в базу объект с именем [name] и позицией [x, y]
/// если объект с таким id в базе уже есть, заменяет его новым
void Insert(ObjectId id, string name, size_t x, size_t y) {
Remove(id);
auto new_game_object = GameObject{id, name, x, y};
database_.insert(new_game_object);
database_by_id_[id] = new_game_object;
database_by_name_[name].insert(new_game_object);
database_by_coordinates_[Coordinates{x, y}].insert(new_game_object);
}
/// удаляет элемент по id
/// если такого элемента нет, ничего не делает
void Remove(ObjectId id) {
auto find_it = database_by_id_.find(id);
if (find_it != database_by_id_.end()) {
database_.erase(find_it->second);
database_by_name_[find_it->second.name].erase(find_it->second);
database_by_coordinates_[
Coordinates{find_it->second.x,find_it->second.y}].
erase(find_it->second);
database_by_id_.erase(id);
}
}
/// возвращает вектор объектов c именем [name]
/// сортировка по убыванию id
vector<GameObject> DataByName(string name) const {
vector<GameObject> v;
try {
v = vector<GameObject>(database_by_name_.at(name).rbegin(),
database_by_name_.at(name).rend());
} catch (out_of_range& e) {}
return v;
}
/// возвращает вектор объектов, находящихся в позиции [x, y]
/// сортировка по убыванию id
vector<GameObject> DataByPosition(size_t x, size_t y) const {
vector<GameObject> v;
try {
return vector<GameObject>(
database_by_coordinates_.at(Coordinates{x, y}).rbegin(),
database_by_coordinates_.at(Coordinates{x, y}).rend());
} catch (out_of_range& e) {}
return v;
}
/// возвращает вектор всех объектов из базы
/// сортировка по убыванию id
vector<GameObject> Data() const {
return vector<GameObject>(database_.rbegin(), database_.rend());
}
private:
set<GameObject> database_;
map<ObjectId, GameObject> database_by_id_;
map<string, set<GameObject>> database_by_name_;
map<Coordinates, set<GameObject>> database_by_coordinates_;
};