Compare commits
2 Commits
fb3ebc10ff
...
e2f804bac7
Author | SHA1 | Date | |
---|---|---|---|
e2f804bac7 | |||
91cbb6c841 |
7
app.go
7
app.go
@@ -35,7 +35,8 @@ func (a *App) startup(ctx context.Context) {
|
|||||||
redirectURI = "http://localhost:8080/callback"
|
redirectURI = "http://localhost:8080/callback"
|
||||||
}
|
}
|
||||||
|
|
||||||
a.ssi = NewESISSO(clientID, redirectURI, []string{"esi-ui.write_waypoint.v1"})
|
// Add location read scope so we can fetch character locations
|
||||||
|
a.ssi = NewESISSO(clientID, redirectURI, []string{"esi-ui.write_waypoint.v1", "esi-location.read_location.v1"})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Greet returns a greeting for the given name
|
// Greet returns a greeting for the given name
|
||||||
@@ -130,7 +131,9 @@ func (a *App) ListCharacters() ([]CharacterInfo, error) {
|
|||||||
|
|
||||||
// GetCharacterLocations exposes current locations for all characters
|
// GetCharacterLocations exposes current locations for all characters
|
||||||
func (a *App) GetCharacterLocations() ([]CharacterLocation, error) {
|
func (a *App) GetCharacterLocations() ([]CharacterLocation, error) {
|
||||||
if a.ssi == nil { return nil, errors.New("ESI not initialised") }
|
if a.ssi == nil {
|
||||||
|
return nil, errors.New("ESI not initialised")
|
||||||
|
}
|
||||||
ctx, cancel := context.WithTimeout(a.ctx, 6*time.Second)
|
ctx, cancel := context.WithTimeout(a.ctx, 6*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return a.ssi.GetCharacterLocations(ctx)
|
return a.ssi.GetCharacterLocations(ctx)
|
||||||
|
@@ -133,23 +133,23 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
|||||||
setPositions(positions);
|
setPositions(positions);
|
||||||
const connections = computeNodeConnections(systems);
|
const connections = computeNodeConnections(systems);
|
||||||
setConnections(connections);
|
setConnections(connections);
|
||||||
// Compute per-system mean inbound angle from in-region neighbors
|
// Compute per-system mean outbound BEARING (0=north, clockwise positive) to in-region neighbors
|
||||||
const angleMap: Record<string, number> = {};
|
const angleMap: Record<string, number> = {};
|
||||||
systems.forEach((sys, name) => {
|
systems.forEach((sys, name) => {
|
||||||
const neighbors = (sys.connectedSystems || '').split(',').map(s => s.trim()).filter(Boolean);
|
const neighbors = (sys.connectedSystems || '').split(',').map(s => s.trim()).filter(Boolean);
|
||||||
let sumX = 0, sumY = 0, count = 0;
|
let sumSin = 0, sumCos = 0, count = 0;
|
||||||
for (const n of neighbors) {
|
for (const n of neighbors) {
|
||||||
const neighbor = systems.get(n);
|
const neighbor = systems.get(n);
|
||||||
if (!neighbor) continue;
|
if (!neighbor) continue;
|
||||||
const ax = sys.x - neighbor.x;
|
const dx = neighbor.x - sys.x;
|
||||||
const ay = sys.y - neighbor.y; // vector pointing into this system
|
const dy = neighbor.y - sys.y; // screen coords (y down)
|
||||||
const a = Math.atan2(ay, ax);
|
const bearing = Math.atan2(dx, -dy); // bearing relative to north
|
||||||
sumX += Math.cos(a);
|
sumSin += Math.sin(bearing);
|
||||||
sumY += Math.sin(a);
|
sumCos += Math.cos(bearing);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
angleMap[name] = Math.atan2(sumY, sumX);
|
angleMap[name] = Math.atan2(sumSin, sumCos); // average bearing
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setMeanInboundAngle(angleMap);
|
setMeanInboundAngle(angleMap);
|
||||||
@@ -226,12 +226,14 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
|||||||
let angle: number | undefined = undefined;
|
let angle: number | undefined = undefined;
|
||||||
const inbound = meanInboundAngle[fromName];
|
const inbound = meanInboundAngle[fromName];
|
||||||
if (inbound !== undefined) {
|
if (inbound !== undefined) {
|
||||||
angle = inbound + Math.PI; // opposite direction of mean inbound
|
angle = inbound; // mean outbound bearing already computed
|
||||||
} else {
|
} else {
|
||||||
const curPos = universeRegionPosCache.get(regionName);
|
const curPos = universeRegionPosCache.get(regionName);
|
||||||
const toPos = universeRegionPosCache.get(toRegion);
|
const toPos = universeRegionPosCache.get(toRegion);
|
||||||
if (curPos && toPos) {
|
if (curPos && toPos) {
|
||||||
angle = Math.atan2(toPos.y - curPos.y, toPos.x - curPos.x);
|
const dxr = toPos.x - curPos.x;
|
||||||
|
const dyr = toPos.y - curPos.y;
|
||||||
|
angle = Math.atan2(dxr, -dyr); // bearing to remote region
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (angle === undefined) {
|
if (angle === undefined) {
|
||||||
@@ -240,6 +242,8 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
|||||||
for (let i = 0; i < key.length; i++) h = (h * 31 + key.charCodeAt(i)) >>> 0;
|
for (let i = 0; i < key.length; i++) h = (h * 31 + key.charCodeAt(i)) >>> 0;
|
||||||
angle = (h % 360) * (Math.PI / 180);
|
angle = (h % 360) * (Math.PI / 180);
|
||||||
}
|
}
|
||||||
|
// Flip 180° so indicator points away from existing connections
|
||||||
|
angle = angle + Math.PI;
|
||||||
|
|
||||||
const gkey = `${fromName}__${toRegion}`;
|
const gkey = `${fromName}__${toRegion}`;
|
||||||
const prev = grouped.get(gkey);
|
const prev = grouped.get(gkey);
|
||||||
@@ -670,8 +674,8 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
|||||||
const yoff = -18 - (idx % 3) * 10; // stagger small vertical offsets if multiple in same system
|
const yoff = -18 - (idx % 3) * 10; // stagger small vertical offsets if multiple in same system
|
||||||
return (
|
return (
|
||||||
<g key={`char-${c.character_id}-${idx}`} transform={`translate(${pos.x}, ${pos.y + yoff})`}>
|
<g key={`char-${c.character_id}-${idx}`} transform={`translate(${pos.x}, ${pos.y + yoff})`}>
|
||||||
<circle r={4} fill="#00d1ff" stroke="#ffffff" strokeWidth={1} />
|
<rect x={-2} y={-9} width={Math.max(c.character_name.length * 5, 24)} height={14} rx={3} fill="#0f172a" opacity={0.9} stroke="#00d1ff" strokeWidth={1} />
|
||||||
<text x={6} y={3} fontSize={8} fill="#ffffff">{c.character_name}</text>
|
<text x={Math.max(c.character_name.length * 5, 24) / 2 - 2} y={2} textAnchor="middle" fontSize={8} fill="#ffffff">{c.character_name}</text>
|
||||||
</g>
|
</g>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -682,8 +686,8 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
|||||||
if (!pos) return null;
|
if (!pos) return null;
|
||||||
const len = 26;
|
const len = 26;
|
||||||
const r0 = 10; // start just outside node
|
const r0 = 10; // start just outside node
|
||||||
const dx = Math.cos(ind.angle);
|
const dx = Math.sin(ind.angle);
|
||||||
const dy = Math.sin(ind.angle);
|
const dy = -Math.cos(ind.angle);
|
||||||
const x1 = pos.x + dx * r0;
|
const x1 = pos.x + dx * r0;
|
||||||
const y1 = pos.y + dy * r0;
|
const y1 = pos.y + dy * r0;
|
||||||
const x2 = x1 + dx * len;
|
const x2 = x1 + dx * len;
|
||||||
|
Reference in New Issue
Block a user