Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
<body>
<header>
<h1>World Tech Tree (MVP)</h1>
<nav>
<a href="sorted.html">Sorted View</a>
</nav>
</header>
<main>
<div id="tech-tree-container">
Expand Down
34 changes: 34 additions & 0 deletions sorted.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sorted Technologies</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>Sorted Technologies</h1>
<nav>
<a href="index.html">Graph View</a>
</nav>
</header>
<main>
<div id="sorted-tech-container">
<table id="sorted-table">
<thead>
<tr>
<th>Era</th>
<th>Level</th>
<th>Name</th>
<th>Prerequisites</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</main>
<script src="sorted.js"></script>
</body>
</html>
94 changes: 94 additions & 0 deletions sorted.js
Original file line number Diff line number Diff line change
@@ -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);
});
});

42 changes: 42 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down