Skip to content

Commit 91231f0

Browse files
committed
progressive with intellegence
1 parent a1028ff commit 91231f0

2 files changed

Lines changed: 104 additions & 14 deletions

File tree

modules/visualization/lattice_interactions.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ function selectNode(node) {
1313

1414
if (node.data.quest_type) content += `<div style="margin: 10px 0; background: rgba(255,255,255,0.05); padding: 8px; border-radius: 4px;"><strong>Quest Type:</strong> ${node.data.quest_type}</div>`;
1515

16+
if (node.availableSustainable && node.availableSustainable.size > 0) {
17+
content += '<h4 style="border-bottom: 1px solid #30363d; margin-bottom: 10px;">Sustainable Pipeline</h4><div style="display:flex; flex-wrap:wrap; gap:5px; margin-bottom: 15px;">';
18+
node.availableSustainable.forEach(itemId => {
19+
const item = nodeMap.get(itemId);
20+
content += `<span style="background: rgba(126, 231, 135, 0.1); color: var(--ability-color); border: 1px solid rgba(126, 231, 135, 0.3); padding: 2px 6px; border-radius: 4px; font-size: 11px;">${item ? item.name : itemId}</span>`;
21+
});
22+
content += '</div>';
23+
}
24+
1625
// Categorize Edges
1726
const consumeTypes = ['consumes', 'requires_stat', 'requires_ability', 'requires_quest'];
1827
const produceTypes = ['rewards', 'stat_rewards', 'provides_ability', 'unlocks_cadence', 'unlocks_location'];

modules/visualization/lattice_rendering.js

Lines changed: 95 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,18 @@ function renderQuestFlow() {
4848
abilities = nodesData.filter(n => n.type === 'Ability' && cadenceProvidedAbilityIds.has(n.id));
4949
}
5050

51-
const flowEntities = [...quests, ...cadences, ...abilities];
51+
let refinements = [];
52+
if (currentView === 'progressive') {
53+
const abilityIds = new Set(abilities.map(a => a.id));
54+
refinements = nodesData.filter(n =>
55+
n.type === 'Refinement' &&
56+
n.in_edges &&
57+
n.in_edges.requires_ability &&
58+
n.in_edges.requires_ability.some(aId => abilityIds.has(aId))
59+
);
60+
}
61+
62+
const flowEntities = [...quests, ...cadences, ...abilities, ...refinements];
5263
const entityMap = new Map(flowEntities.map(n => [n.id, n]));
5364

5465
// 3. Build Dependency Graph for Layout (Base Progression)
@@ -91,6 +102,17 @@ function renderQuestFlow() {
91102
}
92103
});
93104
}
105+
// Refinement Dependencies (Ability -> Refinement)
106+
if (q.type === 'Refinement') {
107+
if (q.in_edges && q.in_edges.requires_ability) {
108+
q.in_edges.requires_ability.forEach(reqId => {
109+
if (entityMap.has(reqId)) {
110+
adj.get(reqId).push(q.id);
111+
revAdj.get(q.id).push(reqId);
112+
}
113+
});
114+
}
115+
}
94116
});
95117

96118
// 4. Calculate Tiers for Core Entities
@@ -111,32 +133,81 @@ function renderQuestFlow() {
111133
});
112134
}
113135

114-
// 5. Add Non-Shared Item Nodes (Local to producing quest)
136+
// 5. Intelligence: Sustainability Propagation
137+
const sustainablyAvailable = new Map();
138+
const sortedEntities = [...flowEntities].sort((a, b) => (entityTiers.get(a.id) || 0) - (entityTiers.get(b.id) || 0));
139+
140+
sortedEntities.forEach(node => {
141+
node.sustainableOutputs = new Set();
142+
node.availableSustainable = new Set();
143+
144+
const parents = revAdj.get(node.id) || [];
145+
parents.forEach(pId => {
146+
const pAvailable = sustainablyAvailable.get(pId);
147+
if (pAvailable) {
148+
pAvailable.forEach(itemId => node.availableSustainable.add(itemId));
149+
}
150+
});
151+
152+
if (node.type === 'Quest' && node.data.quest_type === 'Recurring') {
153+
if (node.out_edges && node.out_edges.rewards) {
154+
node.out_edges.rewards.forEach(rew => node.sustainableOutputs.add(rew.targetId));
155+
}
156+
} else if (node.type === 'Refinement' && currentView === 'progressive') {
157+
let canRun = true;
158+
if (node.out_edges && node.out_edges.consumes) {
159+
node.out_edges.consumes.forEach(cons => {
160+
if (!node.availableSustainable.has(cons.targetId)) canRun = false;
161+
});
162+
} else {
163+
canRun = false; // Refinement without inputs?
164+
}
165+
166+
if (canRun) {
167+
node.isSustainablyActive = true;
168+
if (node.out_edges && node.out_edges.produces) {
169+
node.out_edges.produces.forEach(prod => node.sustainableOutputs.add(prod.targetId));
170+
}
171+
}
172+
}
173+
174+
const nodeTotalAvailable = new Set(node.availableSustainable);
175+
node.sustainableOutputs.forEach(itemId => nodeTotalAvailable.add(itemId));
176+
sustainablyAvailable.set(node.id, nodeTotalAvailable);
177+
});
178+
179+
// 6. Add Non-Shared Item Nodes (Local to producing entity)
115180
const productionNodes = [];
116181
const productionEdges = [];
117182

118183
if (currentView === 'advanced' || currentView === 'progressive') {
119-
quests.forEach(q => {
120-
if (q.data.quest_type === 'Recurring' && q.out_edges && q.out_edges.rewards) {
121-
const questTier = entityTiers.get(q.id) || 0;
122-
q.out_edges.rewards.forEach(rew => {
123-
const itemTemplate = nodesData.find(n => n.id === rew.targetId);
184+
sortedEntities.forEach(node => {
185+
if (node.sustainableOutputs.size > 0) {
186+
const nodeTier = entityTiers.get(node.id) || 0;
187+
node.sustainableOutputs.forEach(itemId => {
188+
const itemTemplate = nodesData.find(n => n.id === itemId);
124189
if (itemTemplate) {
125-
const uniqueId = `prod-${q.id}-${itemTemplate.id}`;
126-
const rate = (rew.quantity * 60) / (q.data.duration || 10);
190+
const uniqueId = `prod-${node.id}-${itemTemplate.id}`;
127191

192+
let rateInfo = "";
193+
if (node.type === 'Quest') {
194+
const rew = node.out_edges.rewards.find(r => r.targetId === itemId);
195+
const rate = (rew.quantity * 60) / (node.data.duration || 10);
196+
rateInfo = ` (${rate.toFixed(1)}/m)`;
197+
}
198+
128199
const itemNode = {
129200
...itemTemplate,
130201
id: uniqueId,
131-
baseId: itemTemplate.id, // For selection/sidebar
132-
name: `${itemTemplate.name} (${rate.toFixed(1)}/m)`,
133-
tier: questTier + 1,
202+
baseId: itemTemplate.id,
203+
name: `${itemTemplate.name}${rateInfo}`,
204+
tier: nodeTier + 1,
134205
isProduction: true
135206
};
136207
productionNodes.push(itemNode);
137208
productionEdges.push({
138-
id: `edge-${q.id}-${uniqueId}`,
139-
source: q.id,
209+
id: `edge-${node.id}-${uniqueId}`,
210+
source: node.id,
140211
target: uniqueId,
141212
category: 'economy'
142213
});
@@ -240,6 +311,16 @@ function renderQuestFlow() {
240311
shape = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
241312
shape.setAttribute('points', '0,-14 14,0 0,14 -14,0');
242313
shape.setAttribute('fill', 'var(--ability-color)');
314+
} else if (node.type === 'Refinement') {
315+
shape = document.createElementNS("http://www.w3.org/2000/svg", "rect");
316+
shape.setAttribute('x', '-12'); shape.setAttribute('y', '-12');
317+
shape.setAttribute('width', '24'); shape.setAttribute('height', '24');
318+
shape.setAttribute('rx', '8');
319+
shape.setAttribute('fill', node.isSustainablyActive ? 'var(--refinement-color)' : '#333');
320+
if (!node.isSustainablyActive && currentView === 'progressive') {
321+
shape.setAttribute('stroke', '#666');
322+
shape.setAttribute('stroke-dasharray', '2,2');
323+
}
243324
} else {
244325
shape = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
245326
shape.setAttribute('points', '-14,-7 -14,7 0,14 14,7 14,-7 0,-14');

0 commit comments

Comments
 (0)