diff --git a/sorted.html b/sorted.html
new file mode 100644
index 0000000..6d29f84
--- /dev/null
+++ b/sorted.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+ Sorted Technologies
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sorted.js b/sorted.js
new file mode 100644
index 0000000..c9a116d
--- /dev/null
+++ b/sorted.js
@@ -0,0 +1,94 @@
+// Render a table of technologies sorted by era and dependency level
+
+document.addEventListener('DOMContentLoaded', async () => {
+ let data = [];
+ try {
+ const resp = await fetch('/api/tech-tree');
+ if (resp.ok) {
+ data = await resp.json();
+ } else {
+ throw new Error('Failed to load tech tree');
+ }
+ } catch (err) {
+ console.error('Error loading tech tree:', err);
+ return;
+ }
+
+ // Build adjacency map and compute dependency levels
+ const dependentsMap = {};
+ const levelMap = {};
+
+ data.forEach(t => {
+ (t.prerequisites || []).forEach(pr => {
+ if (!dependentsMap[pr]) dependentsMap[pr] = [];
+ dependentsMap[pr].push(t.id);
+ });
+ });
+
+ const queue = [];
+ data.forEach(t => {
+ if (!t.prerequisites || t.prerequisites.length === 0) {
+ levelMap[t.id] = 0;
+ queue.push(t.id);
+ }
+ });
+
+ while (queue.length) {
+ const current = queue.shift();
+ const currentLevel = levelMap[current];
+ (dependentsMap[current] || []).forEach(dep => {
+ const nextLevel = currentLevel + 1;
+ if (levelMap[dep] === undefined || nextLevel < levelMap[dep]) {
+ levelMap[dep] = nextLevel;
+ queue.push(dep);
+ }
+ });
+ }
+
+ data.forEach(t => {
+ if (levelMap[t.id] === undefined) levelMap[t.id] = 0;
+ t.level = levelMap[t.id];
+ });
+
+ const eraOrder = {
+ Ancient: 0,
+ Classical: 1,
+ Medieval: 2,
+ Renaissance: 3,
+ Industrial: 4,
+ Modern: 5,
+ Future: 6
+ };
+
+ // Sort technologies by era then dependency level
+ data.sort((a, b) => {
+ const eraCmp = (eraOrder[a.era] ?? 99) - (eraOrder[b.era] ?? 99);
+ if (eraCmp !== 0) return eraCmp;
+ const lvlCmp = a.level - b.level;
+ if (lvlCmp !== 0) return lvlCmp;
+ return a.name.localeCompare(b.name);
+ });
+
+ const tbody = document.querySelector('#sorted-table tbody');
+ data.forEach(t => {
+ const tr = document.createElement('tr');
+ const eraTd = document.createElement('td');
+ eraTd.textContent = t.era || '';
+ tr.appendChild(eraTd);
+
+ const lvlTd = document.createElement('td');
+ lvlTd.textContent = t.level;
+ tr.appendChild(lvlTd);
+
+ const nameTd = document.createElement('td');
+ nameTd.textContent = t.name;
+ tr.appendChild(nameTd);
+
+ const prereqTd = document.createElement('td');
+ prereqTd.textContent = (t.prerequisites || []).join(', ');
+ tr.appendChild(prereqTd);
+
+ tbody.appendChild(tr);
+ });
+});
+
diff --git a/style.css b/style.css
index cb6c3b4..27198a0 100644
--- a/style.css
+++ b/style.css
@@ -17,6 +17,20 @@ header {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
+header nav {
+ margin-top: 10px;
+}
+
+header nav a {
+ color: #fff;
+ margin: 0 10px;
+ text-decoration: none;
+}
+
+header nav a:hover {
+ text-decoration: underline;
+}
+
main {
display: flex;
flex-grow: 1;
@@ -44,6 +58,34 @@ main {
height: 80vh; /* Ensure the canvas has some initial height */
}
+#sorted-tech-container {
+ flex: 1;
+ border: 1px solid #ddd;
+ border-radius: 8px;
+ background-color: #fff;
+ box-shadow: 0 2px 6px rgba(0,0,0,0.05);
+ overflow: auto;
+ position: relative;
+}
+
+#sorted-table {
+ width: 100%;
+ border-collapse: collapse;
+}
+
+#sorted-table th,
+#sorted-table td {
+ border: 1px solid #ddd;
+ padding: 8px;
+ text-align: left;
+}
+
+#sorted-table th {
+ background-color: #f9f9f9;
+ position: sticky;
+ top: 0;
+}
+
#tech-info-panel {
border: 1px solid #ddd;
border-radius: 8px;
Sorted Technologies
+ +
+
+
+
+
+ | Era | +Level | +Name | +Prerequisites | +
|---|