#pragma once #include #include #include #include #define REGION_TYPE_CITY 6 #define REGION_TYPE_AREA 5 #define REGION_TYPE_DISTRICT 4 #define REGION_TYPE_COUNTRY 3 #define REGION_TYPE_CONTINENT 1 /** Класс, позволяющий узнавать, принадлежит ли регион с одним RegionID региону с другим RegionID. * Информацию об иерархии регионов загружает из текстового файла. * Умеет, по запросу, обновлять данные. */ class RegionsHierarchy : private boost::noncopyable { private: time_t file_modification_time = 0; using RegionID = UInt32; using RegionType = UInt8; using RegionDepth = UInt8; using RegionPopulation = UInt32; /// отношение parent; 0, если родителей нет - обычная lookup таблица. using RegionParents = std::vector; /// тип региона using RegionTypes = std::vector; /// глубина в дереве, начиная от страны (страна: 1, корень: 0) using RegionDepths = std::vector; /// население региона. Если больше 2^32 - 1, то приравнивается к этому максимуму. using RegionPopulations = std::vector; /// регион -> родительский регион RegionParents parents; /// регион -> город, включающий его или 0, если такого нет RegionParents city; /// регион -> страна, включающая его или 0, если такого нет RegionParents country; /// регион -> область, включающая его или 0, если такой нет RegionParents area; /// регион -> округ, включающий его или 0, если такого нет RegionParents district; /// регион -> континет (первый при подъёме по иерархии регионов), включающий его или 0, если такого нет RegionParents continent; /// регион -> континет (последний при подъёме по иерархии регионов), включающий его или 0, если такого нет RegionParents top_continent; /// регион -> население или 0, если неизвестно. RegionPopulations populations; /// регион - глубина в дереве RegionDepths depths; /// path to file with data std::string path; public: RegionsHierarchy(); RegionsHierarchy(const std::string & path_); /// Перезагружает, при необходимости, иерархию регионов. Непотокобезопасно. void reload(); bool in(RegionID lhs, RegionID rhs) const { if (lhs >= parents.size()) return false; while (lhs != 0 && lhs != rhs) lhs = parents[lhs]; return lhs != 0; } RegionID toCity(RegionID region) const { if (region >= city.size()) return 0; return city[region]; } RegionID toCountry(RegionID region) const { if (region >= country.size()) return 0; return country[region]; } RegionID toArea(RegionID region) const { if (region >= area.size()) return 0; return area[region]; } RegionID toDistrict(RegionID region) const { if (region >= district.size()) return 0; return district[region]; } RegionID toContinent(RegionID region) const { if (region >= continent.size()) return 0; return continent[region]; } RegionID toTopContinent(RegionID region) const { if (region >= top_continent.size()) return 0; return top_continent[region]; } RegionID toParent(RegionID region) const { if (region >= parents.size()) return 0; return parents[region]; } RegionDepth getDepth(RegionID region) const { if (region >= depths.size()) return 0; return depths[region]; } RegionPopulation getPopulation(RegionID region) const { if (region >= populations.size()) return 0; return populations[region]; } }; class RegionsHierarchySingleton : public Singleton, public RegionsHierarchy { friend class Singleton; protected: RegionsHierarchySingleton() { } };