| @@ -45,6 +45,11 @@ class _SolarSystem(_UniqueObject): | |||||
| return self._data["security"] | return self._data["security"] | ||||
| @property | @property | ||||
| def coords(self): | |||||
| """The solar system's coordinates, as a 3-tuple of floats (x, y, z).""" | |||||
| return tuple(self._data["coords"]) | |||||
| @property | |||||
| def faction(self): | def faction(self): | ||||
| """The solar system's faction, as a _Faction object, or None.""" | """The solar system's faction, as a _Faction object, or None.""" | ||||
| if "faction" in self._data: | if "faction" in self._data: | ||||
| @@ -66,6 +71,11 @@ class _SolarSystem(_UniqueObject): | |||||
| """Whether the solar system is in nullsec.""" | """Whether the solar system is in nullsec.""" | ||||
| return self.security >= 0.45 | return self.security >= 0.45 | ||||
| @property | |||||
| def is_whspace(self): | |||||
| """Whether the solar system is in wormhole space.""" | |||||
| return self.region.is_whspace | |||||
| class _Constellation(_UniqueObject): | class _Constellation(_UniqueObject): | ||||
| """Represents a constellation.""" | """Represents a constellation.""" | ||||
| @@ -87,6 +97,11 @@ class _Constellation(_UniqueObject): | |||||
| return self._universe.faction(self._data["faction"]) | return self._universe.faction(self._data["faction"]) | ||||
| return self.region.faction | return self.region.faction | ||||
| @property | |||||
| def is_whspace(self): | |||||
| """Whether the constellation is in wormhole space.""" | |||||
| return self.region.is_whspace | |||||
| class _Region(_UniqueObject): | class _Region(_UniqueObject): | ||||
| """Represents a region.""" | """Represents a region.""" | ||||
| @@ -103,6 +118,11 @@ class _Region(_UniqueObject): | |||||
| return self._universe.faction(self._data["faction"]) | return self._universe.faction(self._data["faction"]) | ||||
| return None | return None | ||||
| @property | |||||
| def is_whspace(self): | |||||
| """Whether the region is in wormhole space.""" | |||||
| return self._id >= 11000000 | |||||
| class _Faction(_UniqueObject): | class _Faction(_UniqueObject): | ||||
| """Represents a faction.""" | """Represents a faction.""" | ||||
| @@ -173,7 +193,8 @@ class _DummySolarSystem(_SolarSystem): | |||||
| "name": "Unknown", | "name": "Unknown", | ||||
| "constellation": -1, | "constellation": -1, | ||||
| "region": -1, | "region": -1, | ||||
| "security": 0.0 | |||||
| "security": 0.0, | |||||
| "coords": (0, 0, 0) | |||||
| }) | }) | ||||
| @@ -288,6 +309,12 @@ class Universe: | |||||
| return _DummySolarSystem(self) | return _DummySolarSystem(self) | ||||
| return _SolarSystem(self, sid, self._systems[sid]) | return _SolarSystem(self, sid, self._systems[sid]) | ||||
| def systems(self): | |||||
| """Return an iterator over all _SolarSystems.""" | |||||
| self._load() | |||||
| for sid in self._systems: | |||||
| yield self.system(sid) | |||||
| def constellation(self, cid): | def constellation(self, cid): | ||||
| """Return a _Constellation with the given ID. | """Return a _Constellation with the given ID. | ||||
| @@ -1,8 +1,9 @@ | |||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
| from flask import g, json | |||||
| from flask_mako import render_template | from flask_mako import render_template | ||||
| from ._provided import blueprint | |||||
| from ._provided import app, blueprint | |||||
| def home(): | def home(): | ||||
| """Render and return the main map page.""" | """Render and return the main map page.""" | ||||
| @@ -16,3 +17,22 @@ def navitem(): | |||||
| def map(): | def map(): | ||||
| """Render and return the main map page.""" | """Render and return the main map page.""" | ||||
| return home() | return home() | ||||
| @blueprint.rroute("/map/data.json") | |||||
| def mapdata(): | |||||
| """Render and return the map data as a JSON object.""" | |||||
| payload = { | |||||
| "galaxy": { | |||||
| system.id: { | |||||
| "name": system.name, | |||||
| "coords": system.coords, | |||||
| "security": system.security | |||||
| } | |||||
| for system in g.eve.universe.systems() if not system.is_whspace | |||||
| } | |||||
| } | |||||
| resp = app.response_class(response=json.dumps(payload), status=200, | |||||
| mimetype="application/json") | |||||
| resp.cache_control.private = True | |||||
| resp.cache_control.max_age = 24 * 60 * 60 | |||||
| return resp | |||||
| @@ -150,7 +150,9 @@ def _build_galaxy_skeleton(ids, names): | |||||
| assert isinstance(sid, int) | assert isinstance(sid, int) | ||||
| d[sid] = { | d[sid] = { | ||||
| "name": names[sid], | "name": names[sid], | ||||
| "constellation": -1, "region": -1, "security": 0.0 | |||||
| "constellation": -1, | |||||
| "region": -1, | |||||
| "security": 0.0 | |||||
| } | } | ||||
| print("done.") | print("done.") | ||||
| @@ -160,15 +162,18 @@ def _load_assoc_for_system(galaxy, system, rid, cid): | |||||
| data = _load_yaml(system / "solarsystem.staticdata") | data = _load_yaml(system / "solarsystem.staticdata") | ||||
| sid = data["solarSystemID"] | sid = data["solarSystemID"] | ||||
| sec = data["security"] | sec = data["security"] | ||||
| coords = data["center"] | |||||
| assert isinstance(sid, int) | assert isinstance(sid, int) | ||||
| assert isinstance(sec, float) | assert isinstance(sec, float) | ||||
| assert sid >= 0 | assert sid >= 0 | ||||
| assert sec >= -1.0 and sec <= 1.0 | assert sec >= -1.0 and sec <= 1.0 | ||||
| assert len(coords) == 3 and all(isinstance(val, float) for val in coords) | |||||
| galaxy["systems"][sid]["constellation"] = cid | galaxy["systems"][sid]["constellation"] = cid | ||||
| galaxy["systems"][sid]["region"] = rid | galaxy["systems"][sid]["region"] = rid | ||||
| galaxy["systems"][sid]["security"] = sec | galaxy["systems"][sid]["security"] = sec | ||||
| galaxy["systems"][sid]["coords"] = coords | |||||
| if "factionID" in data: | if "factionID" in data: | ||||
| facid = data["factionID"] | facid = data["factionID"] | ||||
| @@ -0,0 +1,3 @@ | |||||
| #map .system { | |||||
| fill: currentColor; | |||||
| } | |||||
| @@ -0,0 +1,47 @@ | |||||
| $(function() { | |||||
| $("#map").html("<p>Loading map data...</p>"); | |||||
| $.getJSON( "map/data.json", function(data) { | |||||
| $("#map").empty(); | |||||
| var svg = d3.select("#map").append("svg") | |||||
| .attr("width", 1000) | |||||
| .attr("height", 1000); // TODO: dynamic | |||||
| var xmin = Infinity, xmax = -Infinity, | |||||
| ymin = Infinity, ymax = -Infinity; | |||||
| for (var sid in data["galaxy"]) { | |||||
| var system = data["galaxy"][sid]; | |||||
| var x = system["coords"][0]; | |||||
| var y = system["coords"][2]; | |||||
| if (x < xmin) xmin = x; | |||||
| if (x > xmax) xmax = x; | |||||
| if (y < ymin) ymin = y; | |||||
| if (y > ymax) ymax = y; | |||||
| } | |||||
| var width = xmax - xmin; | |||||
| var height = ymax - ymin; | |||||
| var scale = 1000; | |||||
| svg.attr("viewBox", "0 0 " + scale + " " + scale); | |||||
| svg.selectAll("circle") | |||||
| .data(Object.values(data["galaxy"])) | |||||
| .enter() | |||||
| .append("circle") | |||||
| .attr("cx", (d) => { | |||||
| var x = d["coords"][0]; | |||||
| return (x - xmin) / width * scale; | |||||
| }) | |||||
| .attr("cy", (d) => { | |||||
| var y = d["coords"][2]; | |||||
| return (y - ymin) / height * scale; | |||||
| }) | |||||
| .attr("r", 1) | |||||
| .attr("class", (d) => { | |||||
| var sec = d["security"]; | |||||
| var klass = sec < 0.05 ? "null" : | |||||
| Number(sec).toFixed(1).replace(".", "_"); | |||||
| return "system sec-" + klass; | |||||
| }); | |||||
| }); | |||||
| }); | |||||
| @@ -2,6 +2,16 @@ | |||||
| <%block name="title"> | <%block name="title"> | ||||
| ${self.support.maketitle("Map")} | ${self.support.maketitle("Map")} | ||||
| </%block> | </%block> | ||||
| <%block name="extracss"> | |||||
| ${self.support.makecss("map.css")} | |||||
| </%block> | |||||
| <%block name="extrajs"> | |||||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.4.1/d3.min.js" integrity="sha256-4mL8TQfOJSbg0f42dQw5cKLl2ngQXUSXqfQnvK11M44=" crossorigin="anonymous"></script> | |||||
| ${self.support.makejs("map.js")} | |||||
| </%block> | |||||
| <h2>Map</h2> | <h2>Map</h2> | ||||
| ## TODO | |||||
| <p>No map available yet!</p> | |||||
| <div id="map"> | |||||
| <noscript> | |||||
| <p>JavaScript is required to display the galaxy map.</p> | |||||
| </noscript> | |||||
| </div> | |||||