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.
 
 
 
 
 

277 lines
7.4 KiB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. import gzip
  4. from pathlib import Path
  5. import shutil
  6. import sys
  7. import yaml
  8. _REGION = 3
  9. _CONSTELLATION = 4
  10. _SOLAR_SYSTEM = 5
  11. def _load_yaml(filename):
  12. with filename.open("rb") as fp:
  13. return yaml.load(fp, Loader=yaml.CLoader)
  14. def _verify_typeids(sde_dir):
  15. print("Verifying typeIDs... ", end="", flush=True)
  16. filename = sde_dir / "fsd" / "typeIDs.yaml"
  17. with filename.open("rb") as fp:
  18. data = yaml.load(fp.read(1024 * 16), Loader=yaml.CLoader)
  19. assert data[_REGION]["groupID"] == _REGION
  20. assert data[_REGION]["name"]["en"] == "Region"
  21. assert data[_CONSTELLATION]["groupID"] == _CONSTELLATION
  22. assert data[_CONSTELLATION]["name"]["en"] == "Constellation"
  23. assert data[_SOLAR_SYSTEM]["groupID"] == _SOLAR_SYSTEM
  24. assert data[_SOLAR_SYSTEM]["name"]["en"] == "Solar System"
  25. print("done.")
  26. def _load_ids(sde_dir):
  27. print("Loading itemIDs... ", end="", flush=True)
  28. data = _load_yaml(sde_dir / "bsd" / "invItems.yaml")
  29. ids = {_REGION: [], _CONSTELLATION: [], _SOLAR_SYSTEM: []}
  30. for entry in data:
  31. if entry["typeID"] in ids:
  32. ids[entry["typeID"]].append(entry["itemID"])
  33. print("done.")
  34. return ids
  35. def _load_names(sde_dir):
  36. print("Loading itemNames... ", end="", flush=True)
  37. data = _load_yaml(sde_dir / "bsd" / "invNames.yaml")
  38. names = {}
  39. for entry in data:
  40. name = entry["itemName"]
  41. assert isinstance(name, str)
  42. names[entry["itemID"]] = name
  43. print("done.")
  44. return names
  45. def _build_galaxy_skeleton(ids, names):
  46. print("Building galaxy skeleton... ", end="", flush=True)
  47. galaxy = {"regions": {}, "constellations": {}, "systems": {}}
  48. d = galaxy["regions"]
  49. for rid in ids[_REGION]:
  50. assert isinstance(rid, int)
  51. d[rid] = {
  52. "name": names[rid]
  53. }
  54. d = galaxy["constellations"]
  55. for cid in ids[_CONSTELLATION]:
  56. assert isinstance(cid, int)
  57. d[cid] = {
  58. "name": names[cid],
  59. "region": -1
  60. }
  61. d = galaxy["systems"]
  62. for sid in ids[_SOLAR_SYSTEM]:
  63. assert isinstance(sid, int)
  64. d[sid] = {
  65. "name": names[sid],
  66. "constellation": -1, "region": -1, "security": 0.0
  67. }
  68. print("done.")
  69. return galaxy
  70. def _load_assoc_for_system(galaxy, system, rid, cid):
  71. data = _load_yaml(system / "solarsystem.staticdata")
  72. sid = data["solarSystemID"]
  73. sec = data["security"]
  74. assert isinstance(sid, int)
  75. assert isinstance(sec, float)
  76. assert sid >= 0
  77. assert sec >= -1.0 and sec <= 1.0
  78. galaxy["systems"][sid]["constellation"] = cid
  79. galaxy["systems"][sid]["region"] = rid
  80. galaxy["systems"][sid]["security"] = sec
  81. if "factionID" in data:
  82. facid = data["factionID"]
  83. assert isinstance(facid, int)
  84. assert facid >= 0
  85. galaxy["systems"][sid]["faction"] = facid
  86. def _load_assoc_for_constellation(galaxy, constellation, rid):
  87. data = _load_yaml(constellation / "constellation.staticdata")
  88. cid = data["constellationID"]
  89. assert isinstance(cid, int)
  90. assert cid >= 0
  91. galaxy["constellations"][cid]["region"] = rid
  92. if "factionID" in data:
  93. facid = data["factionID"]
  94. assert isinstance(facid, int)
  95. assert facid >= 0
  96. galaxy["constellations"][cid]["faction"] = facid
  97. for system in constellation.iterdir():
  98. if not system.is_dir():
  99. continue
  100. _load_assoc_for_system(galaxy, system, rid, cid)
  101. def _load_assoc_for_region(galaxy, region):
  102. data = _load_yaml(region / "region.staticdata")
  103. rid = data["regionID"]
  104. assert isinstance(rid, int)
  105. assert rid >= 0
  106. if "factionID" in data:
  107. facid = data["factionID"]
  108. assert isinstance(facid, int)
  109. assert facid >= 0
  110. galaxy["regions"][rid]["faction"] = facid
  111. for constellation in region.iterdir():
  112. if not constellation.is_dir():
  113. continue
  114. _load_assoc_for_constellation(galaxy, constellation, rid)
  115. def _load_galaxy_associations(sde_dir, galaxy):
  116. print("Loading galaxy staticdata... ", end="", flush=True)
  117. univdir = sde_dir / "fsd" / "universe"
  118. for base in univdir.iterdir():
  119. if not base.is_dir():
  120. continue
  121. for region in base.iterdir():
  122. if not region.is_dir():
  123. continue
  124. _load_assoc_for_region(galaxy, region)
  125. print("done.")
  126. for cid, constellation in galaxy["constellations"].items():
  127. if constellation["region"] < 0:
  128. print("[WARNING] Orphaned constellation: %d=%s" % (
  129. cid, constellation["name"]))
  130. for sid, system in galaxy["systems"].items():
  131. if system["region"] < 0 or system["constellation"] < 0:
  132. print("[WARNING] Orphaned system: %d=%s" % (sid, system["name"]))
  133. def _load_factions(sde_dir):
  134. print("Loading factions... ", end="", flush=True)
  135. data = _load_yaml(sde_dir / "bsd" / "chrFactions.yaml")
  136. factions = {}
  137. for entry in data:
  138. fid = entry["factionID"]
  139. name = entry["factionName"]
  140. assert isinstance(fid, int)
  141. assert isinstance(name, str)
  142. assert fid >= 0
  143. factions[fid] = {"name": name}
  144. print("done.")
  145. return factions
  146. def _dump_galaxy(out_dir, galaxy):
  147. print("Dumping galaxy... ", end="", flush=True)
  148. filename = out_dir / "galaxy.yml"
  149. with filename.open("w") as fp:
  150. fp.write(yaml.dump(galaxy, Dumper=yaml.CDumper))
  151. print("done.")
  152. def _dump_entities(out_dir, factions):
  153. print("Dumping entities... ", end="", flush=True)
  154. entities = {"factions": factions}
  155. filename = out_dir / "entities.yml"
  156. with filename.open("w") as fp:
  157. fp.write(yaml.dump(entities, Dumper=yaml.CDumper))
  158. print("done.")
  159. def _compress(out_dir):
  160. targets = ["galaxy", "entities"]
  161. for basename in targets:
  162. print("Compressing %s... " % basename, end="", flush=True)
  163. fn_src = out_dir / (basename + ".yml")
  164. fn_dst = out_dir / (basename + ".yml.gz")
  165. with fn_src.open("rb") as f_in:
  166. with gzip.open(str(fn_dst), "wb") as f_out:
  167. shutil.copyfileobj(f_in, f_out)
  168. print("done.")
  169. def _cleanup(out_dir):
  170. print("Cleaning up... ", end="", flush=True)
  171. targets = ["galaxy", "entities"]
  172. for basename in targets:
  173. (out_dir / (basename + ".yml")).unlink()
  174. print("done.")
  175. def import_sde(sde_dir, out_dir):
  176. """Import the SDE unzipped at sde_dir to out_dir."""
  177. print("EVE Online static data import")
  178. print("- from: %s" % sde_dir)
  179. print("- to: %s" % out_dir)
  180. _verify_typeids(sde_dir)
  181. ids = _load_ids(sde_dir)
  182. print("Counts: regions=%d, constellations=%d, systems=%d" % (
  183. len(ids[_REGION]), len(ids[_CONSTELLATION]), len(ids[_SOLAR_SYSTEM])))
  184. names = _load_names(sde_dir)
  185. galaxy = _build_galaxy_skeleton(ids, names)
  186. del ids
  187. del names
  188. _load_galaxy_associations(sde_dir, galaxy)
  189. _dump_galaxy(out_dir, galaxy)
  190. del galaxy
  191. factions = _load_factions(sde_dir)
  192. _dump_entities(out_dir, factions)
  193. del factions
  194. _compress(out_dir)
  195. _cleanup(out_dir)
  196. def main():
  197. if len(sys.argv) < 2:
  198. print("usage: %s <sde_directory>" % sys.argv[0])
  199. exit(1)
  200. sde_dir = Path(sys.argv[1]).resolve()
  201. out_dir = Path(__file__).resolve().parent.parent / "data" / "universe"
  202. import_sde(sde_dir, out_dir)
  203. if __name__ == "__main__":
  204. main()