A corporation manager and dashboard for EVE Online
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

244 lines
6.4 KiB

  1. # -*- coding: utf-8 -*-
  2. import gzip
  3. from threading import Lock
  4. import yaml
  5. __all__ = ["Universe"]
  6. class _UniqueObject:
  7. """Base class for uniquely ID'd objects in the universe."""
  8. def __init__(self, universe, id_, data):
  9. self._universe = universe
  10. self._id = id_
  11. self._data = data
  12. @property
  13. def id(self):
  14. """The object's unique ID, as an integer."""
  15. return self._id
  16. class _SolarSystem(_UniqueObject):
  17. """Represents a solar system."""
  18. @property
  19. def name(self):
  20. """The solar system's name, as a string."""
  21. return self._data["name"]
  22. @property
  23. def constellation(self):
  24. """The solar system's constellation, as a _Constellation object."""
  25. return self._universe.constellation(self._data["constellation"])
  26. @property
  27. def region(self):
  28. """The solar system's region, as a _Region object."""
  29. return self._universe.region(self._data["region"])
  30. @property
  31. def security(self):
  32. """The solar system's security status, as a float."""
  33. return self._data["security"]
  34. @property
  35. def faction(self):
  36. """The solar system's faction, as a _Faction object, or None."""
  37. if "faction" in self._data:
  38. return self._universe.faction(self._data["faction"])
  39. return self.constellation.faction
  40. @property
  41. def is_nullsec(self):
  42. """Whether the solar system is in nullsec."""
  43. return self.security < 0.05
  44. @property
  45. def is_lowsec(self):
  46. """Whether the solar system is in nullsec."""
  47. return self.security >= 0.05 and self.security < 0.45
  48. @property
  49. def is_highsec(self):
  50. """Whether the solar system is in nullsec."""
  51. return self.security >= 0.45
  52. class _Constellation(_UniqueObject):
  53. """Represents a constellation."""
  54. @property
  55. def name(self):
  56. """The constellation's name, as a string."""
  57. return self._data["name"]
  58. @property
  59. def region(self):
  60. """The constellation's region, as a _Region object."""
  61. return self._universe.region(self._data["region"])
  62. @property
  63. def faction(self):
  64. """The constellation's faction, as a _Faction object, or None."""
  65. if "faction" in self._data:
  66. return self._universe.faction(self._data["faction"])
  67. return self.region.faction
  68. class _Region(_UniqueObject):
  69. """Represents a region."""
  70. @property
  71. def name(self):
  72. """The region's name, as a string."""
  73. return self._data["name"]
  74. @property
  75. def faction(self):
  76. """The region's faction, as a _Faction object, or None."""
  77. if "faction" in self._data:
  78. return self._universe.faction(self._data["faction"])
  79. return None
  80. class _Faction(_UniqueObject):
  81. """Represents a faction."""
  82. @property
  83. def name(self):
  84. """The faction's name, as a string."""
  85. return self._data["name"]
  86. class _DummySolarSystem(_SolarSystem):
  87. """Represents an unknown or invalid solar system."""
  88. def __init__(self, universe):
  89. super().__init__(universe, -1, {
  90. "name": "Unknown",
  91. "constellation": -1,
  92. "region": -1,
  93. "security": 0.0
  94. })
  95. class _DummyConstellation(_Constellation):
  96. """Represents an unknown or invalid constellation."""
  97. def __init__(self, universe):
  98. super().__init__(universe, -1, {
  99. "name": "Unknown",
  100. "region": -1
  101. })
  102. class _DummyRegion(_Region):
  103. """Represents an unknown or invalid region."""
  104. def __init__(self, universe):
  105. super().__init__(universe, -1, {
  106. "name": "Unknown"
  107. })
  108. class _DummyFaction(_Faction):
  109. """Represents an unknown or invalid faction."""
  110. def __init__(self, universe):
  111. super().__init__(universe, -1, {
  112. "name": "Unknown"
  113. })
  114. class Universe:
  115. """EVE API module for static universe data."""
  116. def __init__(self, datadir):
  117. self._dir = datadir
  118. self._lock = Lock()
  119. self._loaded = False
  120. self._systems = {}
  121. self._constellations = {}
  122. self._regions = {}
  123. self._factions = {}
  124. @staticmethod
  125. def _load_yaml(path):
  126. """Load in and return a YAML file with the given path."""
  127. with gzip.open(str(path), "rb") as fp:
  128. return yaml.load(fp, Loader=yaml.CLoader)
  129. def _load(self):
  130. """Load in universe data. This can be called multiple times safely."""
  131. if self._loaded:
  132. return
  133. with self._lock:
  134. if self._loaded:
  135. return
  136. galaxy = self._load_yaml(self._dir / "galaxy.yml.gz")
  137. self._systems = galaxy["systems"]
  138. self._constellations = galaxy["constellations"]
  139. self._regions = galaxy["regions"]
  140. del galaxy
  141. entities = self._load_yaml(self._dir / "entities.yml.gz")
  142. self._factions = entities["factions"]
  143. del entities
  144. self._loaded = True
  145. def system(self, sid):
  146. """Return a _SolarSystem with the given ID.
  147. If the ID is invalid, return a dummy unknown object with ID -1.
  148. """
  149. self._load()
  150. if sid not in self._systems:
  151. return _DummySolarSystem(self)
  152. return _SolarSystem(self, sid, self._systems[sid])
  153. def constellation(self, cid):
  154. """Return a _Constellation with the given ID.
  155. If the ID is invalid, return a dummy unknown object with ID -1.
  156. """
  157. self._load()
  158. if cid not in self._constellations:
  159. return _DummyConstellation(self)
  160. return _Constellation(self, cid, self._constellations[cid])
  161. def region(self, rid):
  162. """Return a _Region with the given ID.
  163. If the ID is invalid, return a dummy unknown object with ID -1.
  164. """
  165. self._load()
  166. if rid not in self._regions:
  167. return _DummyRegion(self)
  168. return _Region(self, rid, self._regions[rid])
  169. def faction(self, fid):
  170. """Return a _Faction with the given ID.
  171. If the ID is invalid, return a dummy unknown object with ID -1.
  172. """
  173. self._load()
  174. if fid not in self._factions:
  175. return _DummyFaction(self)
  176. return _Faction(self, fid, self._factions[fid])
  177. def ship(self, sid):
  178. """Return a _Ship with the given ID.
  179. If the ID is invalid, return a dummy unknown object with ID -1.
  180. """
  181. ...
  182. raise NotImplementedError()