Header only SImDatabase

This commit is contained in:
2022-09-24 00:54:34 +02:00
parent 488fcb87cc
commit ace71d7670
20 changed files with 451 additions and 556 deletions
-42
View File
@@ -1,42 +0,0 @@
#ifndef GERMANAIRLINESVA_FILE_CONFIG_H
#define GERMANAIRLINESVA_FILE_CONFIG_H
#include <map>
#include <fstream>
#include <map>
#include <string>
#include <vector>
#include "constants.h"
#include "util.hpp"
namespace germanairlinesva
{
namespace file
{
namespace config
{
class Config
{
private:
std::string user;
std::string scenery;
std::string token;
void writeFile() const;
public:
Config();
void updateScenery(std::string scenery);
inline const std::string getUser() const { return this->user; }
inline const std::string getScenery() const { return this->scenery; }
inline const std::string getToken() const { return this->token; }
};
} // namespace config
} // namespace file
} // namespace germanairlinesva
#endif
+73
View File
@@ -0,0 +1,73 @@
#ifndef GERMANAIRLINESVA_FILE_CONFIG_H
#define GERMANAIRLINESVA_FILE_CONFIG_H
#include <map>
#include <fstream>
#include <map>
#include <string>
#include <vector>
#include "constants.h"
#include "util.hpp"
namespace germanairlinesva
{
namespace file
{
namespace config
{
class Config
{
private:
std::string user;
std::string scenery;
std::string token;
inline void writeFile() const
{
std::ofstream out(BASE_DIRECTORY CONFIG);
out << "scenery=" << this->scenery << "\n";
out << "user=" << this->user << "\n";
out << "token=" << this->token << "\n";
out.close();
}
public:
inline Config()
{
std::ifstream in(BASE_DIRECTORY CONFIG);
std::string line;
while (std::getline(in, line)) {
std::vector<std::string> fields = util::split(line, '=');
if (fields.size() >= 2) {
util::trim(fields[0]);
util::trim(fields[1]);
if (fields[0] == "scenery") {
this->scenery = fields[1];
} else if (fields[0] == "user") {
this->user = fields[1];
} else if (fields[0] == "token") {
this->token = fields[1];
}
}
}
in.close();
}
inline void updateScenery(std::string scenery)
{
this->scenery = scenery;
this->writeFile();
}
inline const std::string getUser() const { return this->user; }
inline const std::string getScenery() const { return this->scenery; }
inline const std::string getToken() const { return this->token; }
};
} // namespace config
} // namespace file
} // namespace germanairlinesva
#endif
@@ -37,17 +37,29 @@ namespace file
public:
// From X-Plane or MakeRwys
Gate(std::string designator,
double latitude,
double longitude,
std::uint8_t radius);
inline Gate(std::string designator,
double latitude,
double longitude,
std::uint8_t radius)
: designator(designator), center({latitude, longitude}),
radius(radius){};
// From Database
Gate(std::string designator,
struct geodata::point center,
std::uint8_t radius);
inline Gate(std::string designator,
struct geodata::point center,
std::uint8_t radius)
: designator(designator), center(center), radius(radius){};
void toFile(std::ofstream &out) const;
bool contains(geodata::point coordinates) const;
inline void toFile(std::ofstream &out) const
{
writeString(out, this->designator);
write<decltype(this->center)>(out, this->center);
write<decltype(this->radius)>(out, this->radius);
}
inline bool contains(geodata::point coordinates) const
{
return geodata::distanceEarthP(this->center, coordinates);
}
inline const std::string to_string() const
{
@@ -40,20 +40,45 @@ namespace file
public:
// From X-Plane or MakeRwys
Runway(std::string designator,
double latitudeStart,
double longitudeStart,
double latitudeEnd,
double longitudeEnd,
double width);
inline Runway(std::string designator,
double latitudeStart,
double longitudeStart,
double latitudeEnd,
double longitudeEnd,
double width)
: designator(designator), width(width)
{
this->length = geodata::distanceEarthD(latitudeStart,
longitudeStart,
latitudeEnd,
longitudeEnd);
this->trueHeading = geodata::bearingDD(latitudeStart,
longitudeStart,
latitudeEnd,
longitudeEnd);
this->bounds =
geodata::calculateBoxDD({latitudeStart, longitudeStart},
{latitudeEnd, longitudeEnd},
this->trueHeading,
this->width);
};
// From database
Runway(std::string designator,
struct geodata::box bounds,
std::uint8_t width,
std::uint16_t length,
double trueHeading);
inline Runway(std::string designator,
struct geodata::box bounds,
std::uint8_t width,
std::uint16_t length,
double trueHeading)
: designator(designator), bounds(bounds), width(width),
length(length), trueHeading(trueHeading){};
void toFile(std::ofstream &out) const;
inline void toFile(std::ofstream &out) const
{
writeString(out, this->designator);
write<decltype(this->bounds)>(out, this->bounds);
write<decltype(this->width)>(out, this->width);
write<decltype(this->length)>(out, this->length);
write<decltype(this->trueHeading)>(out, this->trueHeading);
}
inline const std::string to_string() const
{
-76
View File
@@ -1,76 +0,0 @@
#ifndef GERMANAIRLINESVA_FILE_SIMDATABASE_H
#define GERMANAIRLINESVA_FILE_SIMDATABASE_H
#include <cstdint>
#include <cstring>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
#include "config/config.h"
#include "constants.h"
#include "simdata/gate.h"
#include "simdata/runway.h"
#include "simdata/simdataXP.h"
/*
* 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::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
airports;
void fromFile();
void readVersion1(std::ifstream &in);
public:
SimDatabase(int xPlaneVersion,
const char *hash,
std::unique_ptr<config::Config> &configuration,
std::function<void(const std::string)> toLog);
void toFile() const;
inline std::size_t getCount() const { return this->airports.size(); }
inline const std::pair<const std::vector<Gate>,
const std::vector<Runway>>
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<Gate>, std::vector<Runway>>();
}
}
};
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
#endif
+183
View File
@@ -0,0 +1,183 @@
#ifndef GERMANAIRLINESVA_FILE_SIMDATABASE_H
#define GERMANAIRLINESVA_FILE_SIMDATABASE_H
#include <cstdint>
#include <cstring>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
#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::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
airports;
inline void readVersion1(std::ifstream &in)
{
std::uint16_t numAirports = read<std::uint16_t>(in);
for (int i = 0; i < numAirports; i++) {
// ICAO
std::string icao = readString(in);
// Gates
std::uint16_t numGates = read<std::uint16_t>(in);
for (int j = 0; j < numGates; j++) {
std::string designator = readString(in);
struct geodata::point center = read<struct geodata::point>(in);
std::uint8_t radius = read<std::uint8_t>(in);
this->airports[icao].first.emplace_back(designator,
center,
radius);
}
// Runways
std::uint8_t numRunways = read<std::uint8_t>(in);
for (int j = 0; j < numRunways; j++) {
std::string designator = readString(in);
// Center
struct geodata::box bounds = read<struct geodata::box>(in);
std::uint8_t width = read<std::uint8_t>(in);
std::uint16_t length = read<std::uint16_t>(in);
double trueHeading = read<double>(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<std::uint8_t>(in);
if (version == 1) {
this->readVersion1(in);
}
}
public:
inline SimDatabase(int xPlaneVersion,
const char *hash,
std::unique_ptr<config::Config> &configuration,
std::function<void(const std::string)> 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<const char *>(header), 6);
// Num Airports
write<std::uint16_t>(out, airports.size());
// Airport
for (const std::pair<
const std::string,
std::pair<std::vector<Gate>, std::vector<Runway>>> &airport :
airports) {
std::string icao = airport.first;
const std::vector<Gate> gates = airport.second.first;
const std::vector<Runway> runways = airport.second.second;
// ICAO
writeString(out, icao);
// Gates
write<std::uint16_t>(out, gates.size());
for (const Gate &gate : gates) {
gate.toFile(out);
}
// Runways
write<std::uint8_t>(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<Gate>,
const std::vector<Runway>>
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<Gate>, std::vector<Runway>>();
}
}
};
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
#endif
-42
View File
@@ -1,42 +0,0 @@
#ifndef GERMANAIRLINESVA_FILE_SIMDATAXP_H
#define GERMANAIRLINESVA_FILE_SIMDATAXP_H
#include <fstream>
#include <map>
#include <string>
#include "simdata/gate.h"
#include "simdata/runway.h"
#include "simdata/simDatabase.h"
#include "util.hpp"
namespace germanairlinesva
{
namespace file
{
namespace simdata
{
int scan(
const std::string defaultFile,
const std::string sceneryPack,
const std::string logFile,
std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
&airports);
void makeAirport(
const std::string &kind,
std::ifstream &infile,
std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
&airports,
std::ofstream &logfile);
void makeGate15(std::vector<Gate> &gates,
const std::vector<std::string> &fields);
void makeRunway(std::vector<Runway> &runways,
const std::vector<std::string> &fields);
void makeGate1300(std::vector<Gate> &gates,
const std::vector<std::string> &fields);
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
#endif
+207
View File
@@ -0,0 +1,207 @@
#ifndef GERMANAIRLINESVA_FILE_SIMDATAXP_H
#define GERMANAIRLINESVA_FILE_SIMDATAXP_H
#include <fstream>
#include <map>
#include <string>
#include "simdata/gate.hpp"
#include "simdata/runway.hpp"
#include "util.hpp"
namespace germanairlinesva
{
namespace file
{
namespace simdata
{
inline void makeGate15(std::vector<Gate> &gates,
const std::vector<std::string> &fields)
{
std::string gateName;
for (size_t j = 4; j < fields.size() - 1; j++) {
gateName += fields[j] + " ";
}
gateName += fields.back();
gateName = std::regex_replace(gateName, std::regex{","}, "0");
gates.emplace_back(gateName,
std::stod(fields[1]),
std::stod(fields[2]),
40);
}
inline void makeRunway(std::vector<Runway> &runways,
const std::vector<std::string> &fields)
{
runways.emplace_back(fields[8],
std::stod(fields[9]),
std::stod(fields[10]),
std::stod(fields[18]),
std::stod(fields[19]),
std::stod(fields[1]));
runways.emplace_back(fields[17],
std::stod(fields[18]),
std::stod(fields[19]),
std::stod(fields[9]),
std::stod(fields[10]),
std::stod(fields[1]));
}
inline void makeGate1300(std::vector<Gate> &gates,
const std::vector<std::string> &fields)
{
std::string gateName;
for (size_t j = 6; j < fields.size() - 1; j++) {
gateName += fields[j] + " ";
}
gateName += fields.back();
gateName = std::regex_replace(gateName, std::regex{","}, "0");
gates.emplace_back(gateName,
std::stod(fields[1]),
std::stod(fields[2]),
40);
}
inline void makeAirport(
const std::string &kind,
std::ifstream &infile,
std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
&airports,
std::ofstream &logfile)
{
std::string line;
std::string *currentIcao = nullptr;
std::vector<Gate> tmpGates;
std::vector<Runway> tmpRunways;
int apCount = 0;
int validCount = 0;
while (std::getline(infile, line)) {
std::vector<std::string> fields = util::split(line, ' ');
fields = util::select_T<std::string>(fields, [](const std::string &s) {
return s.length() > 0;
});
if (fields.empty())
continue;
if (fields[0] == "1") {
// Write to file if ICAO is valid, and we have gates and runways
if (currentIcao != nullptr && !tmpRunways.empty() &&
!tmpGates.empty()) {
airports[*currentIcao] = {tmpGates, tmpRunways};
validCount += 1;
logfile << "\t<STATUS> " << *currentIcao << " committed"
<< std::endl;
} else if (currentIcao != nullptr) {
logfile << "\t<STATUS> " << *currentIcao
<< " had no gates or runways" << std::endl;
}
tmpGates = std::vector<Gate>();
tmpRunways = std::vector<Runway>();
currentIcao = new std::string(fields[4]);
apCount += 1;
logfile << "\t<" << kind << "> " << line << std::endl;
} else if (currentIcao != nullptr && fields[0] == "15") {
makeGate15(tmpGates, fields);
logfile << "\t\t<GATE OLD> " << line << std::endl;
} else if (fields[0] == "16" || fields[0] == "17") {
// Write to file if ICAO is valid, and we have gates and runways
if (currentIcao != nullptr && !tmpRunways.empty() &&
!tmpGates.empty()) {
airports[*currentIcao] = {tmpGates, tmpRunways};
validCount += 1;
logfile << "\t<STATUS> " << *currentIcao << " committed"
<< std::endl;
} else if (currentIcao != nullptr) {
logfile << "\t<STATUS> " << *currentIcao
<< " had no gates or runways" << std::endl;
}
tmpGates = std::vector<Gate>();
tmpRunways = std::vector<Runway>();
currentIcao = nullptr;
logfile << "\t<" << kind << " SKIPPED> " << line << std::endl;
} else if (currentIcao != nullptr && fields[0] == "100") {
makeRunway(tmpRunways, fields);
logfile << "\t\t<RUNWAY> " << line << std::endl;
} else if (currentIcao != nullptr && fields[0] == "1300") {
makeGate1300(tmpGates, fields);
logfile << "\t\t<GATE> " << line << std::endl;
}
}
if (currentIcao != nullptr && !tmpRunways.empty() && !tmpGates.empty()) {
airports[*currentIcao] = {tmpGates, tmpRunways};
validCount += 1;
logfile << "\t<STATUS> " << *currentIcao << " committed" << std::endl;
}
logfile << "<STATUS> " << apCount << " airports found, of which "
<< validCount << " are valid" << std::endl;
}
inline int scan(
const std::string defaultFile,
const std::string sceneryPack,
const std::string logFile,
std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
&airports)
{
std::ifstream base(defaultFile);
if (!base.good()) {
return 1;
}
std::ifstream custom(sceneryPack);
if (!custom.good()) {
base.close();
return 2;
}
std::ofstream logfile(logFile, std::fstream::trunc);
if (!logfile.good()) {
base.close();
custom.close();
return 3;
}
// Default
logfile << "<FILE> " << defaultFile << std::endl;
makeAirport("DEFAULT", base, airports, logfile);
base.close();
std::string line;
size_t pos;
std::vector<std::string> packs;
while (std::getline(custom, line)) {
if ((pos = line.find("SCENERY_PACK")) != std::string::npos) {
std::string path = util::rtrim_copy(line.substr(pos + 13)) +
"Earth nav data/apt.dat";
packs.emplace_back(path);
}
}
std::reverse(packs.begin(), packs.end());
for (std::string const &path : packs) {
std::ifstream pack(path);
if (pack.good()) {
logfile << "<FILE> " << path << std::endl;
makeAirport("CUSTOM", pack, airports, logfile);
pack.close();
} else {
pack.close();
logfile << "<STATUS>"
<< "Could not find " << path << std::endl;
}
}
logfile << std::endl
<< "<STATUS> Total airports: " << airports.size() << std::endl;
custom.close();
logfile.close();
return 0;
}
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
#endif