Add balance quota to cap faction territory sizes
- Branch sizes are inherently skewed and a branch IS its faction's territory, so without a cap one faction would dominate the start. - Each branch now keeps only min(eligible, quota) of its eligible middle systems, closest to the middle band (|d−0.5|, index tiebreak); quota = the median of the three branches' eligible sizes. The big branch's overflow stays neutral wild space; a small branch keeps all. - Expose g.factions.quota and g.factions.territories for the map's territory-region fill. - Add tests verifying the quota, kept-set membership, near-equal faction sizes, and no-faction-outruns-typical-branch invariants. - Fix landing.json: entry 4 now references ice assets (was mislabeled lava land with ice clips); entry 5 uses lava-land-02 + lava surface/ takeoff clips. - Add original art asset lava-shop-02.png and update docs to describe the balance rule.
This commit is contained in:
parent
e2878da59c
commit
42bf6c17e0
Binary file not shown.
|
After Width: | Height: | Size: 2.7 MiB |
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_comment": "FACTIONS — the three powers + neutral space. WORLDGEN LAYER (js/galaxy/Galaxy.js → the faction pass, at roster build): the jump tree's top-level BRANCHES (subtrees rooted at the home system's gate neighbors — home has ≤ maxGates gates, so ≤ 3 branches) each become ONE FACTION's territory. TERRITORY rule: a branch's systems at depth 2 … (maxDepth−1) (home = depth 0, its gate neighbors = depth 1) — the ring right outside home and every branch's dead-end tips stay NEUTRAL WILD SPACE, and anything not in a territory is neutral. CAPITALS: the NEUTRAL CAPITAL is a seeded pick of the home system's direct gate neighbors (ALWAYS); its system stays faction-neutral even though it roots a faction's branch (a neutral hub at the edge of that corridor). Each FACTION CAPITAL (apex / mindweave / zenith) is a seeded pick inside its branch's territory, preferred in the middle band (d in 0.37..0.63 — data/galaxy.json → distribution.zones' middle slice), on a non-barren system (it must host a planet); the branch↔faction assignment is a SEEDED SHUFFLE — new galaxy ⇒ new order/placement, same seed ⇒ identical (the determinism contract). Each capital's system grows its capital planet in content generation (js/galaxy/SystemGenerator.js: class capitalNeutral / capitalApex / capitalMindweave / capitalZenith>, planets.png frames 18..21 per data/planets.json → capitals, the 'capital' settlement per data/settlements.json — the faction ones owner:<faction>, the neutral one owner-less; that is the reputation faction seam, js/reputation/Reputation.js → factionStanding()). BRIDGES (data/gates.json → bridges) link the branches across the middle belt so the factions can reach — and fight — each other without routing through the trunk. REACHABILITY / COMBAT / TRADE off the territories is the NEXT layer (the reserved reputation standing + the map's territory-region pass): `color` = the faction's map/diplomacy color (the galaxy plate's star-ring layer, js/ui/GalaxyView.js); the capital planet's ART carries the same hue (frames 18..21).",
|
||||
"_comment": "FACTIONS — the three powers + neutral space. WORLDGEN LAYER (js/galaxy/Galaxy.js → the faction pass, at roster build): the jump tree's top-level BRANCHES (subtrees rooted at the home system's gate neighbors — home has ≤ maxGates gates, so ≤ 3 branches) each become ONE FACTION's territory. TERRITORY rule: a branch's systems at depth 2 … (maxDepth−1) (home = depth 0, its gate neighbors = depth 1) are ELIGIBLE — the ring right outside home and every branch's dead-end tips stay NEUTRAL WILD SPACE, and anything not in a territory is neutral. BALANCE QUOTA (no dominant faction at the start — branch sizes are inherently skewed, and a branch IS its faction's territory): each branch keeps only its min(eligible, quota) systems, closest to the middle band (|d−0.5|), quota = the MEDIAN of the three branches' eligible sizes (the big branch's overflow stays neutral wild space; a small branch keeps everything it has; a balanced galaxy is untouched) — exposed as g.factions.quota / .territories. CAPITALS: the NEUTRAL CAPITAL is a seeded pick of the home system's direct gate neighbors (ALWAYS); its system stays faction-neutral even though it roots a faction's branch (a neutral hub at the edge of that corridor). Each FACTION CAPITAL (apex / mindweave / zenith) is a seeded pick inside its branch's territory, preferred in the middle band (d in 0.37..0.63 — data/galaxy.json → distribution.zones' middle slice), on a non-barren system (it must host a planet); the branch↔faction assignment is a SEEDED SHUFFLE — new galaxy ⇒ new order/placement, same seed ⇒ identical (the determinism contract). Each capital's system grows its capital planet in content generation (js/galaxy/SystemGenerator.js: class capitalNeutral / capitalApex / capitalMindweave / capitalZenith>, planets.png frames 18..21 per data/planets.json → capitals, the 'capital' settlement per data/settlements.json — the faction ones owner:<faction>, the neutral one owner-less; that is the reputation faction seam, js/reputation/Reputation.js → factionStanding()). BRIDGES (data/gates.json → bridges) link the branches across the middle belt so the factions can reach — and fight — each other without routing through the trunk. REACHABILITY / COMBAT / TRADE off the territories is the NEXT layer (the reserved reputation standing + the map's territory-region pass): `color` = the faction's map/diplomacy color (the galaxy plate's star-ring layer, js/ui/GalaxyView.js); the capital planet's ART carries the same hue (frames 18..21).",
|
||||
"factions": {
|
||||
"neutral": { "label": "Neutral", "color": "#b9c4d6" },
|
||||
"apex": { "label": "Apex", "color": "#ff4d4d" },
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@
|
|||
{ "land": "ice-land-01.mp4", "surface": "ice-surface-01.mp4", "takeoff": "ice-takeoff-01.mp4", "shop": "ice-shop-01.mp4" },
|
||||
{ "land": "ice-land-02.mp4", "surface": "ice-surface-02.mp4", "takeoff": "ice-takeoff-02.mp4", "shop": "ice-shop-02.mp4" },
|
||||
{ "land": "ice-land-03.mp4", "surface": "ice-surface-03.mp4", "takeoff": "ice-takeoff-03.mp4", "shop": "ice-shop-03.mp4" },
|
||||
{ "land": "lava-land-01.mp4", "surface": "ice-surface-01.mp4", "takeoff": "ice-takeoff-01.mp4", "shop": "ice-shop-01.mp4" },
|
||||
{ "land": "ice-land-02.mp4", "surface": "ice-surface-02.mp4", "takeoff": "ice-takeoff-02.mp4", "shop": "ice-shop-02.mp4" },
|
||||
{ "land": "ice-land-01.mp4", "surface": "ice-surface-01.mp4", "takeoff": "ice-takeoff-01.mp4", "shop": "ice-shop-01.mp4" },
|
||||
{ "land": "lava-land-02.mp4", "surface": "lava-surface-02.mp4", "takeoff": "lava-takeoff-02.mp4", "shop": "ice-shop-02.mp4" },
|
||||
{ "land": "ice-land-03.mp4", "surface": "ice-surface-03.mp4", "takeoff": "ice-takeoff-03.mp4", "shop": "ice-shop-03.mp4" }
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@
|
|||
]
|
||||
},
|
||||
"galaxy": {
|
||||
"_comment": "THE GALAXY TAB (js/ui/GalaxyView.js) — the whole-galaxy chart on the plate: one GLOWING STAR per system (colored by its archetype, data/systems.json → types, pulsing on that archetype's heartbeat in `pulse`), THIN LANES where the jump gates connect (the JumpNetwork spanning tree — a maze), the CHARTED REGION (the convex hull of the visited systems, inflated — the discovered-area shading), HOME + SHIP markers, ambient dust + the core glow. TRAVELED lanes (the run jumped them — saved with the run) glow brighter + carry a flow packet; FRONTIER lanes (one end visited) are the 'next step'; unexplored lanes are faint threads. Hover = the star's readout + its link state to the current system — STARS ONLY, and the zone hugs each star's drawn dot (glow radius + a few px of mouse pad), so the lanes between the stars never trigger it; click a CHARTED star = its chart in the SYSTEM tab; uncharted stars are readouts only. FACTIONS (planned, not yet implemented): the snapshot carries per-system `faction: null` — the reserved seams are a faction color layer over the stars + a per-faction territory region (the same hull/fill recipe as `hull`, per faction color + relation alpha).",
|
||||
"_comment": "THE GALAXY TAB (js/ui/GalaxyView.js) — the whole-galaxy chart on the plate: one GLOWING STAR per system (colored by its archetype, data/systems.json → types, pulsing on that archetype's heartbeat in `pulse`), THIN LANES where the jump gates connect (the JumpNetwork spanning tree — a maze), the CHARTED REGION (the convex hull of the visited systems, inflated — the discovered-area shading), HOME + SHIP markers, ambient dust + the core glow. TRAVELED lanes (the run jumped them — saved with the run) glow brighter + carry a flow packet; FRONTIER lanes (one end visited) are the 'next step'; unexplored lanes are faint threads. Hover = the star's readout + its link state to the current system — STARS ONLY, and the zone hugs each star's drawn dot (glow radius + a few px of mouse pad), so the lanes between the stars never trigger it; click a CHARTED star = its chart in the SYSTEM tab; uncharted stars are readouts only. FACTIONS (live — data/factions.json, the roster's faction pass, js/galaxy/Galaxy.js): the snapshot carries per-system `faction` (null = neutral wild space) + `capital` — the live seams are the faction RING layer over the stars (see `factions` below) + a per-faction territory-region FILL (the same hull/fill recipe as `hull`, per faction color + relation alpha — the next layer).",
|
||||
"name": "GALAXY",
|
||||
"platePadding": 26,
|
||||
"_platePadding": "margin kept between the outermost stars and the plate edge at 1× zoom, in PLATE px (js/ui/GalaxyView.js → fitPadded). The field is 2:1 to match the plate, so the fully-zoomed-out galaxy fills the plate with this much breathing room on all sides.",
|
||||
|
|
|
|||
|
|
@ -22,11 +22,15 @@
|
|||
* non-barren system of its branch, each system carrying the capital
|
||||
* world (class capital<faction>, frame 19/20/21) + the 'capital'
|
||||
* settlement owned by the faction;
|
||||
* - the TERRITORY RULE: every system of a faction's branch at depth 2 …
|
||||
* (branch maxDepth − 1) carries that branch's faction; the ring right
|
||||
* outside home (depth 1) and the branch tips (maxDepth) stay neutral —
|
||||
* except a faction capital demoted onto a branch root (only when the
|
||||
* branch has no territory at all);
|
||||
* - the TERRITORY RULE + BALANCE QUOTA: each branch's middle systems
|
||||
* (depth 2 … maxDepth − 1) are ELIGIBLE; each branch keeps its
|
||||
* min(eligible, quota) closest to the middle band (|d − 0.5|, index
|
||||
* tiebreak), quota = the MEDIAN of the eligible sizes — no faction
|
||||
* outruns a typical branch (no dominant faction; the overflow stays
|
||||
* neutral wild space, and a small branch keeps everything it has);
|
||||
* the ring right outside home (depth 1) + the branch tips (maxDepth)
|
||||
* stay neutral — except a faction capital demoted onto a branch root
|
||||
* (only when the branch has no territory at all);
|
||||
* - ARID: every arid planet is ALWAYS habitable (no roll) and hosts a
|
||||
* COLONY (data/settlements.json → settledKindByClass); arid worlds
|
||||
* show up in the roster (rebalanced planetClasses);
|
||||
|
|
@ -180,30 +184,73 @@ const isBarren = (id) => {
|
|||
}
|
||||
check('faction capitals: capital world (class + frame + habitable) + faction-owned settlement', capWorlds, capWhy);
|
||||
|
||||
// TERRITORY: depth 2 … (branch maxDepth − 1) of each branch = that
|
||||
// branch's faction; the depth-1 ring + the branch tips stay neutral
|
||||
// (except a faction capital demoted onto a branch root — only when the
|
||||
// branch has no territory at all).
|
||||
// TERRITORY + BALANCE QUOTA: the branch's middle systems (depth 2 …
|
||||
// maxDepth − 1) are ELIGIBLE; each branch keeps its min(eligible, quota)
|
||||
// closest to the middle band (|d − 0.5|, index tiebreak) — quota = the
|
||||
// MEDIAN of the eligible sizes, so no faction can outsize a typical
|
||||
// branch (the overflow stays neutral wild space); a small branch keeps
|
||||
// everything it has (except a faction capital demoted onto a branch
|
||||
// root — only when the branch has no territory at all).
|
||||
const branchMax = new Map(g.factions.branches.map((b) => [b, 0]));
|
||||
for (const [id, d] of depth) if (id !== HOME && branchOf.has(id)) branchMax.set(branchOf.get(id), Math.max(branchMax.get(branchOf.get(id)), d));
|
||||
const eligibleOf = new Map(g.factions.branches.map((b) => [b, []]));
|
||||
for (const [id, d] of depth) {
|
||||
if (id === HOME || !branchOf.has(id)) continue;
|
||||
const b = branchOf.get(id);
|
||||
branchMax.set(b, Math.max(branchMax.get(b), d));
|
||||
}
|
||||
for (const r of g.records) {
|
||||
if (r.id === HOME || !branchOf.has(r.id)) continue;
|
||||
const b = branchOf.get(r.id);
|
||||
const d = depth.get(r.id);
|
||||
if (d >= 2 && d <= branchMax.get(b) - 1) eligibleOf.get(b).push(r.id);
|
||||
}
|
||||
const sizes = g.factions.branches.map((b) => eligibleOf.get(b).length).sort((x, y) => x - y);
|
||||
const quota = sizes[Math.floor((sizes.length - 1) / 2)];
|
||||
const idx = new Map(g.records.map((r, i) => [r.id, i]));
|
||||
const mid = (id) => Math.abs((g.byId.get(id)?.d ?? 0.5) - 0.5);
|
||||
const keepOf = new Map(g.factions.branches.map((b) => {
|
||||
const elig = eligibleOf.get(b);
|
||||
return [b, new Set(elig.slice().sort((a, c) => mid(a) - mid(c) || idx.get(a) - idx.get(c)).slice(0, Math.min(elig.length, quota)))];
|
||||
}));
|
||||
|
||||
check('balance quota: the median of the branches’ eligible sizes', g.factions.quota === quota, `${g.factions.quota} vs ${quota} (sizes ${sizes.join(',')})`);
|
||||
|
||||
let terrOk = true;
|
||||
let terrWhy = '';
|
||||
for (const r of g.records) {
|
||||
if (r.id === HOME || !branchOf.has(r.id)) continue;
|
||||
const d = depth.get(r.id);
|
||||
const b = branchOf.get(r.id);
|
||||
const fid = g.factions.branchFaction[b];
|
||||
const maxD = branchMax.get(b);
|
||||
const expectFaction = d >= 2 && d <= maxD - 1 ? fid : null;
|
||||
const expectFaction = keepOf.get(b).has(r.id) ? fid : null;
|
||||
const got = r.faction === fid ? fid : null;
|
||||
const demoted = g.factions.capitals[fid] === r.id && expectFaction === null;
|
||||
if (got !== expectFaction && !(demoted && got === fid)) {
|
||||
terrOk = false;
|
||||
terrWhy = `${r.id}: d=${d} maxD=${maxD} expect=${expectFaction} got=${got}`;
|
||||
terrWhy = `${r.id}: keep=${keepOf.get(b).has(r.id)} expect=${expectFaction} got=${got}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
check('territory rule: depth 2…(maxDepth−1) per branch = the branch\u2019s faction; ring + tips neutral', terrOk, terrWhy);
|
||||
check('territory rule: the branch’s kept (quota-capped) middle systems = its faction; the rest neutral', terrOk, terrWhy);
|
||||
|
||||
// NO DOMINANT FACTION: every territory is exactly its branch's
|
||||
// min(eligible, quota) systems — the big branch is trimmed to the
|
||||
// median, the small branch keeps everything; and the kept set is the
|
||||
// middle-band-nearest one (the map's territory-region fill will read
|
||||
// factions.territories).
|
||||
let terrSizeOk = true;
|
||||
let terrSizeWhy = '';
|
||||
for (const b of g.factions.branches) {
|
||||
const terr = g.factions.territories?.[b] ?? [];
|
||||
const want = Math.min(eligibleOf.get(b).length, quota);
|
||||
if (terr.length !== want) { terrSizeOk = false; terrSizeWhy = `${b}: ${terr.length} systems, want ${want}`; break; }
|
||||
for (const id of terr) {
|
||||
if (!keepOf.get(b).has(id)) { terrSizeOk = false; terrSizeWhy = `${b}: ${id} is not among its ${want} middle-band-nearest eligible systems`; break; }
|
||||
}
|
||||
if (!terrSizeOk) break;
|
||||
}
|
||||
check('no dominant faction: every territory is its branch’s min(eligible, quota) middle-band systems', terrSizeOk, terrSizeWhy);
|
||||
const terrSizes = g.factions.branches.map((b) => g.factions.territories[b].length);
|
||||
check('faction sizes near-equal: max territory ≤ quota (no faction outruns a typical branch)', Math.max(...terrSizes) <= quota, `sizes ${terrSizes.join('/')} quota ${quota}`);
|
||||
|
||||
// OWNERS: every settlement in a faction-controlled system is owned by
|
||||
// that faction (neutral systems: owner null) — the reputation seam is
|
||||
|
|
|
|||
|
|
@ -460,10 +460,15 @@ defaults to "current system charted, nothing traveled" (old saves load).
|
|||
**FACTIONS (the worldgen layer is LIVE — data/factions.json):** the
|
||||
roster's faction pass (`js/galaxy/Galaxy.js → _assignFactions`) assigns
|
||||
**territories** — each top-level BRANCH of the jump tree (a subtree
|
||||
rooted at one of home's gate neighbors) is one faction's territory,
|
||||
starting one system into the branch and stopping one before its
|
||||
dead-end tips (the ring right outside home + the branch tips stay
|
||||
neutral wild space) — and designates the **four capitals**: the NEUTRAL
|
||||
rooted at one of home's gate neighbors) is one faction's territory: a
|
||||
branch's middle systems (depth 2 … maxDepth−1) are ELIGIBLE, and each
|
||||
branch keeps its min(eligible, quota) closest to the middle band (|d −
|
||||
0.5|), **quota = the MEDIAN of the three branches' eligible sizes** —
|
||||
the BALANCE rule: branch sizes are inherently skewed (a branch IS its
|
||||
faction's territory), so without the cap one faction would dominate the
|
||||
start; the big branch's overflow stays neutral wild space, a small
|
||||
branch keeps everything it has (the ring right outside home + the
|
||||
branch tips always stay neutral) — and designates the **four capitals**: the NEUTRAL
|
||||
capital (always a direct gate neighbor of home, its system stays
|
||||
neutral) + one faction capital per faction (apex / mindweave / zenith,
|
||||
middle band, seeded). The branch↔faction order is a SEEDED SHUFFLE — a
|
||||
|
|
|
|||
|
|
@ -354,11 +354,19 @@ export class Galaxy {
|
|||
* reshuffles who sits where (never a fixed order), same seed ⇒
|
||||
* identical placement.
|
||||
* TERRITORY — a branch's systems at depth 2 … (maxDepth−1) (home =
|
||||
* depth 0, its gate neighbors = depth 1): the ring right outside
|
||||
* home and every branch's dead-end tips stay NEUTRAL WILD SPACE;
|
||||
* anything not in a territory is neutral. A faction capital always
|
||||
* sits in its faction's territory (fallbacks only when the branch
|
||||
* is too short to have one).
|
||||
* depth 0, its gate neighbors = depth 1) are ELIGIBLE; the ring
|
||||
* right outside home and every branch's dead-end tips stay NEUTRAL
|
||||
* WILD SPACE; anything not in a territory is neutral. A faction
|
||||
* capital always sits in its faction's territory (fallbacks only
|
||||
* when the branch is too short to have one).
|
||||
* BALANCE QUOTA (no dominant faction — branch sizes are inherently
|
||||
* skewed, and a branch IS its faction's territory): each branch
|
||||
* keeps only the min(eligible, quota) of its eligible systems,
|
||||
* closest to the middle band (|d − 0.5|, index tiebreak —
|
||||
* deterministic); quota = the MEDIAN of the three branches'
|
||||
* eligible sizes. The big branch's overflow stays neutral wild
|
||||
* space; a small branch keeps everything it has (a working
|
||||
* territory beats an empty one).
|
||||
*
|
||||
* @param {Set<string>|null} barren the gate-only dead ends (excluded from
|
||||
* capital candidacy — they can't host a world)
|
||||
|
|
@ -414,12 +422,45 @@ export class Galaxy {
|
|||
for (const id of nodesOf.get(b)) m = Math.max(m, depth.get(id) ?? 1);
|
||||
maxDepthOf.set(b, m);
|
||||
}
|
||||
// Territory = the branch's middle systems (depth 2 … maxDepth−1):
|
||||
// TERRITORY = the branch's middle systems (depth 2 … maxDepth−1):
|
||||
// the depth-1 ring at home and the branch tips stay neutral.
|
||||
const inTerritory = (id, b) => {
|
||||
const d = depth.get(id) ?? 0;
|
||||
return d >= 2 && d <= (maxDepthOf.get(b) ?? 1) - 1;
|
||||
};
|
||||
const eligibleOf = new Map();
|
||||
for (const b of branchRoots) {
|
||||
eligibleOf.set(
|
||||
b,
|
||||
(nodesOf.get(b) ?? []).filter((id) => {
|
||||
const d = depth.get(id) ?? 0;
|
||||
return d >= 2 && d <= (maxDepthOf.get(b) ?? 1) - 1;
|
||||
}),
|
||||
);
|
||||
}
|
||||
// BALANCE QUOTA (no dominant faction at the start — branch sizes are
|
||||
// inherently skewed, and a branch IS its faction's territory, so an
|
||||
// unbalanced galaxy would crown a dominant faction): quota = the
|
||||
// MEDIAN of the three branches' eligible sizes; the big branch keeps
|
||||
// only its systems nearest the middle band (|d − 0.5| — the "middle
|
||||
// of the galaxy" design, where the bridges sit too; index tiebreak
|
||||
// for determinism) and its overflow stays NEUTRAL WILD SPACE; a small
|
||||
// branch keeps everything it has (a working territory beats an empty
|
||||
// one). A balanced galaxy is untouched (median = each size).
|
||||
const sizes = branchRoots.map((b) => eligibleOf.get(b).length).sort((x, y) => x - y);
|
||||
const quota = sizes.length ? sizes[Math.floor((sizes.length - 1) / 2)] : 0;
|
||||
const index = new Map(this.records.map((r, i) => [r.id, i]));
|
||||
const midRank = (id) => Math.abs((this.byId.get(id)?.d ?? 0.5) - 0.5);
|
||||
const territoryOf = new Map();
|
||||
for (const b of branchRoots) {
|
||||
const elig = eligibleOf.get(b) ?? [];
|
||||
territoryOf.set(
|
||||
b,
|
||||
new Set(
|
||||
elig
|
||||
.slice()
|
||||
.sort((a, c) => midRank(a) - midRank(c) || index.get(a) - index.get(c))
|
||||
.slice(0, Math.min(elig.length, quota)),
|
||||
),
|
||||
);
|
||||
}
|
||||
const inTerritory = (id, b) => territoryOf.get(b)?.has(id) ?? false;
|
||||
const inBand = (id) => {
|
||||
const rec = this.byId.get(id);
|
||||
return !!rec && rec.d >= dMin && rec.d <= dMax;
|
||||
|
|
@ -490,6 +531,11 @@ export class Galaxy {
|
|||
capitals,
|
||||
branches: branchRoots,
|
||||
branchFaction: Object.fromEntries(branchFaction),
|
||||
// The BALANCE QUOTA (the median of the branches' eligible territory
|
||||
// sizes) + each branch's final territory (its kept systems, sorted
|
||||
// — the map's territory-region fill will read these).
|
||||
quota,
|
||||
territories: Object.fromEntries(branchRoots.map((b) => [b, [...(territoryOf.get(b) ?? [])].sort()])),
|
||||
};
|
||||
const missing = FACTIONS.filter((f) => !capitals[f]);
|
||||
if (missing.length > 0) {
|
||||
|
|
@ -774,6 +820,8 @@ export class Galaxy {
|
|||
capitals: this.factions.capitals,
|
||||
branches: this.factions.branches,
|
||||
branchFaction: this.factions.branchFaction,
|
||||
quota: this.factions.quota,
|
||||
territories: this.factions.territories,
|
||||
} : null,
|
||||
jumpNetworkEdges: this.jumpNetwork ? [...this.jumpNetwork.gates.values()].reduce((n, t) => n + t.length, 0) : null,
|
||||
jumpNetworkBridges: this.jumpNetwork?.bridges ?? [],
|
||||
|
|
|
|||
Loading…
Reference in New Issue