diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/game/StarCelestialCoordinate.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/game/StarCelestialCoordinate.cpp')
-rw-r--r-- | source/game/StarCelestialCoordinate.cpp | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/source/game/StarCelestialCoordinate.cpp b/source/game/StarCelestialCoordinate.cpp new file mode 100644 index 0000000..3652718 --- /dev/null +++ b/source/game/StarCelestialCoordinate.cpp @@ -0,0 +1,184 @@ +#include "StarCelestialCoordinate.hpp" +#include "StarCelestialTypes.hpp" +#include "StarJsonExtra.hpp" +#include "StarLexicalCast.hpp" +#include "StarStaticRandom.hpp" +#include "StarDataStreamExtra.hpp" + +namespace Star { + +CelestialCoordinate::CelestialCoordinate() : m_planetaryOrbitNumber(0), m_satelliteOrbitNumber(0) {} + +CelestialCoordinate::CelestialCoordinate(Vec3I location, int planetaryOrbitNumber, int satelliteOrbitNumber) + : m_location(move(location)), + m_planetaryOrbitNumber(planetaryOrbitNumber), + m_satelliteOrbitNumber(satelliteOrbitNumber) {} + +CelestialCoordinate::CelestialCoordinate(Json const& variant) : CelestialCoordinate() { + if (variant.isType(Json::Type::String)) { + String id = variant.toString(); + if (!id.empty() && !id.equalsIgnoreCase("null")) { + try { + auto plist = id.splitAny(" _:"); + + m_location[0] = lexicalCast<int>(plist.at(0)); + m_location[1] = lexicalCast<int>(plist.at(1)); + m_location[2] = lexicalCast<int>(plist.at(2)); + + if (plist.size() > 3) + m_planetaryOrbitNumber = lexicalCast<int>(plist.at(3)); + if (plist.size() > 4) + m_satelliteOrbitNumber = lexicalCast<int>(plist.at(4)); + + if (m_planetaryOrbitNumber <= 0) + throw CelestialException(strf("Planetary body number out of range in '%s'", id)); + if (m_satelliteOrbitNumber < 0) + throw CelestialException(strf("Satellite body number out of range in '%s'", id)); + } catch (StarException const& e) { + throw CelestialException(strf("Error parsing CelestialCoordinate from '%s'", id), e); + } + } + } else if (variant.isType(Json::Type::Object)) { + m_location = jsonToVec3I(variant.get("location")); + m_planetaryOrbitNumber = variant.getInt("planet", 0); + m_satelliteOrbitNumber = variant.getInt("satellite", 0); + } else if (!variant.isNull()) { + throw CelestialException( + strf("Improper variant type %s trying to convert to SystemCoordinate", variant.typeName())); + } +} + +bool CelestialCoordinate::isNull() const { + return m_location == Vec3I() && m_planetaryOrbitNumber == 0 && m_satelliteOrbitNumber == 0; +} + +bool CelestialCoordinate::isSystem() const { + return !isNull() && m_planetaryOrbitNumber == 0; +} + +bool CelestialCoordinate::isPlanetaryBody() const { + return !isNull() && m_planetaryOrbitNumber != 0 && m_satelliteOrbitNumber == 0; +} + +bool CelestialCoordinate::isSatelliteBody() const { + return !isNull() && m_planetaryOrbitNumber != 0 && m_satelliteOrbitNumber != 0; +} + +Vec3I CelestialCoordinate::location() const { + return m_location; +} + +CelestialCoordinate CelestialCoordinate::system() const { + if (isNull()) + throw CelestialException("CelestialCoordinate::system() called on null coordinate"); + return CelestialCoordinate(m_location); +} + +CelestialCoordinate CelestialCoordinate::planet() const { + if (isPlanetaryBody()) + return *this; + if (isSatelliteBody()) + return CelestialCoordinate(m_location, m_planetaryOrbitNumber); + throw CelestialException("CelestialCoordinate::planet() called on null or system coordinate type"); +} + +int CelestialCoordinate::orbitNumber() const { + if (isSatelliteBody()) + return m_satelliteOrbitNumber; + if (isPlanetaryBody()) + return m_planetaryOrbitNumber; + if (isSystem()) + return 0; + throw CelestialException("CelestialCoordinate::orbitNumber() called on null coordinate"); +} + +CelestialCoordinate CelestialCoordinate::parent() const { + if (isSatelliteBody()) + return CelestialCoordinate(m_location, m_planetaryOrbitNumber); + if (isPlanetaryBody()) + return CelestialCoordinate(m_location); + throw CelestialException("CelestialCoordinate::parent() called on null or system coordinate"); +} + +CelestialCoordinate CelestialCoordinate::child(int orbitNumber) const { + if (isSystem()) + return CelestialCoordinate(m_location, orbitNumber); + if (isPlanetaryBody()) + return CelestialCoordinate(m_location, m_planetaryOrbitNumber, orbitNumber); + throw CelestialException("CelestialCoordinate::child called on null or satellite coordinate"); +} + +Json CelestialCoordinate::toJson() const { + if (isNull()) { + return Json(); + } else { + return JsonObject{{"location", jsonFromVec3I(m_location)}, + {"planet", m_planetaryOrbitNumber}, + {"satellite", m_satelliteOrbitNumber}}; + } +} + +String CelestialCoordinate::id() const { + return toString(*this); +} + +double CelestialCoordinate::distance(CelestialCoordinate const& rhs) const { + return Vec2D(m_location[0] - rhs.m_location[0], m_location[1] - rhs.m_location[1]).magnitude(); +} + +String CelestialCoordinate::filename() const { + return id().replace(":", "_"); +} + +CelestialCoordinate::operator bool() const { + return !isNull(); +} + +bool CelestialCoordinate::operator<(CelestialCoordinate const& rhs) const { + return tie(m_location, m_planetaryOrbitNumber, m_satelliteOrbitNumber) + < tie(rhs.m_location, rhs.m_planetaryOrbitNumber, rhs.m_satelliteOrbitNumber); +} + +bool CelestialCoordinate::operator==(CelestialCoordinate const& rhs) const { + return tie(m_location, m_planetaryOrbitNumber, m_satelliteOrbitNumber) + == tie(rhs.m_location, rhs.m_planetaryOrbitNumber, rhs.m_satelliteOrbitNumber); +} + +bool CelestialCoordinate::operator!=(CelestialCoordinate const& rhs) const { + return tie(m_location, m_planetaryOrbitNumber, m_satelliteOrbitNumber) + != tie(rhs.m_location, rhs.m_planetaryOrbitNumber, rhs.m_satelliteOrbitNumber); +} + +std::ostream& operator<<(std::ostream& os, CelestialCoordinate const& coord) { + if (coord.isNull()) { + os << "null"; + } else { + format(os, "%s:%s:%s", coord.m_location[0], coord.m_location[1], coord.m_location[2]); + + if (coord.m_planetaryOrbitNumber) { + format(os, ":%s", coord.m_planetaryOrbitNumber); + if (coord.m_satelliteOrbitNumber) + format(os, ":%s", coord.m_satelliteOrbitNumber); + } + } + + return os; +} + +DataStream& operator>>(DataStream& ds, CelestialCoordinate& coordinate) { + ds.read(coordinate.m_location); + ds.read(coordinate.m_planetaryOrbitNumber); + ds.read(coordinate.m_satelliteOrbitNumber); + + return ds; +} + +DataStream& operator<<(DataStream& ds, CelestialCoordinate const& coordinate) { + ds.write(coordinate.m_location); + ds.write(coordinate.m_planetaryOrbitNumber); + ds.write(coordinate.m_satelliteOrbitNumber); + + return ds; +} + +} |