#ifndef GERMANAIRLINESVA_FILE_SIMDATA_SIMDATABASE_H #define GERMANAIRLINESVA_FILE_SIMDATA_SIMDATABASE_H #include #include #include #include #include #include #include #include #include #include #include "config/config.hpp" #include "constants.h" #include "simdata/gate.hpp" #include "simdata/runway.hpp" #include "simdata/simdataXP.hpp" /* * Header * * CHAR[5] | UINT8 * --------+-------- * VGAS | VERSION */ /* * Airport * * UINT8 | CHAR[] | UINT16 | GATE[] | UINT8 | RUNWAY[] * --------+--------+----------+--------+---------+--------- * STRLEN | ICAO | NUMGATES | GATES | NUMRWYS | RUNWAYS */ namespace germanairlinesva { namespace file { namespace simdata { class SimDatabase { private: std::map, std::vector>> airports; inline void readVersion1(std::ifstream &in) { std::uint16_t numAirports = read(in); for (int i = 0; i < numAirports; i++) { // ICAO std::string icao = readString(in); // Gates std::uint16_t numGates = read(in); for (int j = 0; j < numGates; j++) { std::string designator = readString(in); struct geodata::point center = read(in); std::uint8_t radius = read(in); this->airports[icao].first.emplace_back(designator, center, radius); } // Runways std::uint8_t numRunways = read(in); for (int j = 0; j < numRunways; j++) { std::string designator = readString(in); // Center struct geodata::box bounds = read(in); std::uint8_t width = read(in); std::uint16_t length = read(in); double trueHeading = read(in); this->airports[icao].second.emplace_back(designator, bounds, width, length, trueHeading); } } in.close(); } inline void fromFile() { std::ifstream in(BASE_DIRECTORY SIMDATABASE, std::ifstream::binary); // File Header std::string ident = readString(in, 5); if (ident.compare("VGAS") != 0) { throw std::invalid_argument("Wrong file"); } std::uint8_t version = read(in); if (version == 1) { this->readVersion1(in); } } public: inline SimDatabase(int xPlaneVersion, const char *hash, std::unique_ptr &configuration, std::function toLog) { if (strcmp(configuration->getScenery().c_str(), hash) != 0 || !util::fileExists(BASE_DIRECTORY SIMDATABASE)) { #ifdef XP scan(xPlaneVersion < 12000 ? XPLANE11_BASE_SCENERY : XPLANE12_BASE_SCENERY, XPLANE_CUSTOM_SCENERY, BASE_DIRECTORY "log.txt", airports); #else toLog("ESP SCAN WILL BE HERE"); #endif configuration->updateScenery(hash); this->toFile(); toLog("Sim Database updated"); } else { this->fromFile(); toLog("Sim Database loaded"); } } inline void toFile() const { std::ofstream out(BASE_DIRECTORY SIMDATABASE, std::fstream::binary); // File Header, Last member is version std::uint8_t header[] = {'V', 'G', 'A', 'S', '\0', 1}; out.write(reinterpret_cast(header), 6); // Num Airports write(out, airports.size()); // Airport for (const std::pair< const std::string, std::pair, std::vector>> &airport : airports) { std::string icao = airport.first; const std::vector gates = airport.second.first; const std::vector runways = airport.second.second; // ICAO writeString(out, icao); // Gates write(out, gates.size()); for (const Gate &gate : gates) { gate.toFile(out); } // Runways write(out, runways.size()); for (const Runway &runway : runways) { runway.toFile(out); } } out.close(); } inline std::size_t getCount() const { return this->airports.size(); } inline const std::pair, const std::vector> operator[](std::string key) { auto it = this->airports.find(key); if (it != this->airports.end()) { return this->airports[key]; } else { return std::pair, std::vector>(); } } }; } // namespace simdata } // namespace file } // namespace germanairlinesva #endif