copernicusai / computer-science-processes-database /computer-science-database-table.html
garywelz's picture
Upload compact process flowchart databases
0202a12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Computer Science Processes Database</title>
<style>
:root {
--accent: #7c3aed;
--accent-soft: color-mix(in srgb, var(--accent) 12%, white);
--text: #172033;
--muted: #5d6678;
--border: #d9dee8;
--bg: #f6f8fb;
--card: #ffffff;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--text);
background: var(--bg);
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
.hero {
background: linear-gradient(135deg, var(--accent), #111827);
color: white;
padding: 42px 24px;
}
.hero-inner, main { max-width: 1280px; margin: 0 auto; }
.eyebrow { text-transform: uppercase; letter-spacing: .12em; opacity: .8; font-size: .78rem; }
h1 { margin: 8px 0 8px; font-size: clamp(2rem, 4vw, 3.5rem); line-height: 1; }
.hero p { margin: 0; max-width: 850px; opacity: .9; font-size: 1.08rem; }
main { padding: 24px; }
.grid { display: grid; gap: 16px; }
.stats { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); margin-bottom: 18px; }
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: 16px;
box-shadow: 0 8px 28px rgba(15, 23, 42, .08);
padding: 18px;
}
.stat-value { font-size: 2rem; font-weight: 800; color: var(--accent); }
.stat-label { color: var(--muted); font-size: .92rem; margin-top: 4px; }
.toolbar {
display: grid;
grid-template-columns: minmax(220px, 1fr) repeat(4, minmax(140px, 210px));
gap: 12px;
margin: 18px 0;
}
input, select {
width: 100%;
border: 1px solid var(--border);
border-radius: 12px;
padding: 11px 12px;
font: inherit;
background: white;
}
.section-title { display: flex; justify-content: space-between; align-items: end; gap: 16px; margin: 24px 0 12px; }
.section-title h2 { margin: 0; }
.section-title p { margin: 4px 0 0; color: var(--muted); }
.collections { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.collection-card { cursor: pointer; border-left: 5px solid var(--accent); }
.collection-card.active { outline: 3px solid color-mix(in srgb, var(--accent) 22%, transparent); }
.collection-card h3 { margin: 0 0 6px; }
.collection-card p { color: var(--muted); margin: 0 0 12px; }
.pill {
display: inline-flex;
align-items: center;
gap: 6px;
border: 1px solid var(--border);
border-radius: 999px;
padding: 4px 10px;
background: var(--accent-soft);
font-size: .84rem;
color: #243044;
}
.lens { grid-template-columns: minmax(260px, 1.2fr) minmax(260px, 2fr); }
.insights { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.frontier-links { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.frontier-links a {
display: inline-block;
border: 1px solid var(--border);
border-radius: 999px;
padding: 8px 12px;
background: white;
}
.table-wrap {
overflow: auto;
border: 1px solid var(--border);
border-radius: 16px;
background: white;
}
table { width: 100%; border-collapse: collapse; min-width: 1320px; }
th, td { padding: 12px 14px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
th { background: #eef2f7; font-size: .84rem; text-transform: uppercase; letter-spacing: .04em; color: #435066; }
tbody tr:hover { background: #f9fbff; }
.name-cell { font-weight: 750; min-width: 260px; }
.muted { color: var(--muted); }
.error { border-left: 5px solid #b91c1c; }
.hidden { display: none; }
footer { color: var(--muted); padding: 28px 0; font-size: .9rem; }
@media (max-width: 900px) {
.toolbar, .lens { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<header class="hero">
<div class="hero-inner">
<div class="eyebrow">Programming Framework</div>
<h1>Computer Science Processes</h1>
<p>Algorithms, systems, networks, security, machine learning, and software workflows.</p>
</div>
</header>
<main>
<div id="error" class="card error hidden"></div>
<section class="grid stats" id="stats"></section>
<section class="card">
<div class="section-title">
<div>
<h2 id="lensTitle">Discipline Lens</h2>
<p id="lensDescription"></p>
</div>
<span class="pill" id="lastUpdated">Loading</span>
</div>
<div class="grid insights" id="insights"></div>
<div class="frontier-links" id="frontierLinks"></div>
</section>
<section>
<div class="section-title">
<div>
<h2>Collections</h2>
<p>Discipline-specific groupings generated from the current process catalog.</p>
</div>
<button class="pill" id="clearCollection" type="button">Show all</button>
</div>
<div class="grid collections" id="collections"></div>
</section>
<section class="card">
<div class="toolbar">
<input id="search" type="search" placeholder="Search by process, subcategory, collection, or keyword">
<select id="subcategoryFilter"></select>
<select id="collectionFilter"></select>
<select id="complexityFilter"></select>
<select id="graphTypeFilter"></select>
</div>
<div class="section-title">
<div>
<h2>Process Database Table</h2>
<p><span id="visibleCount">0</span> matching processes.</p>
</div>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Process</th>
<th id="contextHeader">Context</th>
<th>Category</th>
<th>Complexity</th>
<th>Nodes</th>
<th>Edges</th>
<th>Conditionals</th>
<th>AND Gates</th>
<th>OR Gates</th>
<th>NOT Gates</th>
<th>Loops</th>
<th>Graph Type</th>
<th>Collections</th>
<th>Frontier</th>
</tr>
</thead>
<tbody id="processRows"></tbody>
</table>
</div>
</section>
<footer>
Static host: GCS. Data files: same-folder metadata.json, discipline-profile.json, and collections.json.
</footer>
</main>
<script>
const EMBEDDED_PROFILE = {"displayName": "Computer Science", "slug": "computer_science", "databaseDir": "computer-science-processes-database", "tableFile": "computer-science-database-table.html", "accent": "#7c3aed", "subtitle": "Algorithms, systems, networks, security, machine learning, and software workflows.", "lensTitle": "Computer Science Lens", "lensDescription": "Browse by algorithmic complexity, execution environment, invariants, and failure mode.", "facetLabels": {"subcategory": "Area", "collection": "Lens", "complexity": "Complexity"}, "insightCards": [{"label": "Best for", "value": "algorithms, systems, security, ML pipelines"}, {"label": "Research links", "value": "arXiv, Semantic Scholar, and Crossref"}, {"label": "Curation focus", "value": "separate theory, implementation, and operational concerns"}], "frontierSearches": [{"label": "arXiv", "urlTemplate": "https://arxiv.org/search/cs?query={query}&searchtype=all"}, {"label": "Crossref", "urlTemplate": "https://search.crossref.org/?q={query}+computer+science"}, {"label": "Semantic Scholar", "urlTemplate": "https://www.semanticscholar.org/search?q={query}"}], "contextColumnLabel": "System / Data Type", "defaultContext": "Computing system", "supportedGraphTypes": ["flowchart", "dependency_graph", "taxonomy", "state_transition", "influence_network"], "metricColumns": [{"id": "nodes", "label": "Nodes"}, {"id": "edges", "label": "Edges"}, {"id": "conditionals", "label": "Conditionals"}, {"id": "andGates", "label": "AND Gates"}, {"id": "orGates", "label": "OR Gates"}, {"id": "notGates", "label": "NOT Gates"}, {"id": "loops", "label": "Loops"}], "graphTypeLabels": {"flowchart": "Flowchart", "dependency_graph": "Dependency Graph", "taxonomy": "Taxonomy", "lineage_tree": "Lineage Tree", "influence_network": "Influence Network", "state_transition": "State Transition", "timeline": "Timeline"}, "featuredMaps": [{"label": "Whole of Computer Science", "url": "whole-of-computer-science.html", "description": "Computer Science is strongest as a layered abstraction stack with dependency and process links."}, {"label": "Computing Stack Map", "url": "computing-stack-map.html", "description": "Conceptual stack/subway map of computing layers and cross-cutting concerns."}], "generatedFrom": "scripts/processes/discipline_databases/enhanced_database_table.py", "collectionCount": 9};
let metadata = null;
let profile = EMBEDDED_PROFILE;
let collections = [];
let selectedCollection = "";
function sameFolderUrl(file) {
return new URL(file, window.location.href).href;
}
async function fetchJson(file, fallback) {
try {
const url = sameFolderUrl(file) + "?ts=" + Date.now();
const response = await fetch(url, { cache: "no-store" });
if (!response.ok) throw new Error("HTTP " + response.status);
return await response.json();
} catch (error) {
if (fallback !== undefined) return fallback;
throw error;
}
}
function getProcessCollections(process) {
if (Array.isArray(process.collections)) return process.collections;
if (Array.isArray(process.namedCollections)) return process.namedCollections;
return [];
}
function applyCollectionMemberships() {
const byProcess = new Map();
collections.forEach(collection => {
(collection.processIds || []).forEach(processId => {
if (!byProcess.has(processId)) byProcess.set(processId, new Set());
byProcess.get(processId).add(collection.id);
});
});
(metadata.processes || []).forEach(process => {
const existing = new Set(process.namedCollections || []);
const generated = byProcess.get(process.id) || new Set();
process.collections = Array.from(new Set([...existing, ...generated])).sort();
});
}
function normalizeText(value) {
return String(value || "").toLowerCase();
}
function processUrl(process) {
const subcategory = process.subcategory || "processes";
return "processes/" + encodeURIComponent(subcategory) + "/" + encodeURIComponent(process.id) + ".html";
}
function graphMetrics(process) {
return process.graphMetrics || {
nodes: process.nodes || 0,
edges: process.edges || 0,
conditionals: process.conditionals || 0,
andGates: process.andGates || 0,
orGates: process.orGates || 0,
notGates: process.notGates || 0,
loops: process.loops || 0
};
}
function metricValue(process, key) {
return Number(graphMetrics(process)[key] || 0).toLocaleString();
}
function graphTypeLabel(graphType) {
const labels = profile.graphTypeLabels || {};
const value = graphType || "flowchart";
return labels[value] || value.replace(/_/g, " ").replace(/\b\w/g, c => c.toUpperCase());
}
function frontierUrl(template, processName) {
return template.replace("{query}", encodeURIComponent(processName));
}
function renderStats() {
const stats = metadata.statistics || {};
const processes = metadata.processes || [];
const nodes = stats.totalNodes || processes.reduce((sum, p) => sum + Number(graphMetrics(p).nodes || 0), 0);
const edges = stats.totalEdges || processes.reduce((sum, p) => sum + Number(graphMetrics(p).edges || 0), 0);
const gates = stats.totalGates || processes.reduce((sum, p) => {
const metrics = graphMetrics(p);
return sum + Number(metrics.andGates || 0) + Number(metrics.orGates || 0) + Number(metrics.notGates || 0);
}, 0);
const subcats = Object.keys(metadata.subcategoryCounts || {}).length || metadata.subcategories || 0;
document.getElementById("stats").innerHTML = [
["Processes", metadata.totalProcesses || processes.length],
["Subcategories", subcats],
["Nodes", nodes],
["Edges", edges],
["Logic gates", gates],
["Collections", collections.length]
].map(([label, value]) => `<div class="card"><div class="stat-value">${Number(value || 0).toLocaleString()}</div><div class="stat-label">${label}</div></div>`).join("");
document.getElementById("lastUpdated").textContent = "Updated " + (metadata.lastUpdated || "unknown");
}
function renderLens() {
document.getElementById("lensTitle").textContent = profile.lensTitle || (profile.displayName + " Lens");
document.getElementById("lensDescription").textContent = profile.lensDescription || metadata.description || "";
document.getElementById("contextHeader").textContent = profile.contextColumnLabel || "Context";
document.getElementById("insights").innerHTML = (profile.insightCards || []).map(card => `
<div class="card">
<div class="stat-label">${card.label}</div>
<div style="font-weight:700;margin-top:6px">${card.value}</div>
</div>
`).join("");
const mapLinks = (profile.featuredMaps || []).map(link => {
return `<a href="${link.url}" target="_blank" rel="noopener noreferrer">${link.label}</a>`;
});
const searchLinks = (profile.frontierSearches || []).map(link => {
const sample = metadata.processes && metadata.processes[0] ? metadata.processes[0].name : profile.displayName;
return `<a href="${frontierUrl(link.urlTemplate, sample)}" target="_blank" rel="noopener noreferrer">${link.label}</a>`;
});
document.getElementById("frontierLinks").innerHTML = [...mapLinks, ...searchLinks].join("");
}
function renderCollections() {
document.getElementById("collections").innerHTML = collections.map(collection => `
<div class="card collection-card ${selectedCollection === collection.id ? "active" : ""}" data-id="${collection.id}">
<h3>${collection.label}</h3>
<p>${collection.description || ""}</p>
<span class="pill">${(collection.processIds || []).length} processes</span>
</div>
`).join("");
document.querySelectorAll(".collection-card").forEach(card => {
card.addEventListener("click", () => {
selectedCollection = card.dataset.id;
document.getElementById("collectionFilter").value = selectedCollection;
renderCollections();
renderRows();
});
});
}
function populateFilters() {
const processes = metadata.processes || [];
const subcategories = [...new Set(processes.map(p => p.subcategory_name || p.subcategory).filter(Boolean))].sort();
const complexities = [...new Set(processes.map(p => p.complexity).filter(Boolean))].sort();
const graphTypes = [...new Set(processes.map(p => p.graphType || "flowchart").filter(Boolean))].sort();
document.getElementById("subcategoryFilter").innerHTML = `<option value="">All ${profile.facetLabels?.subcategory || "subcategories"}</option>` + subcategories.map(v => `<option value="${v}">${v}</option>`).join("");
document.getElementById("collectionFilter").innerHTML = `<option value="">All ${profile.facetLabels?.collection || "collections"}</option>` + collections.map(c => `<option value="${c.id}">${c.label}</option>`).join("");
document.getElementById("complexityFilter").innerHTML = `<option value="">All complexity levels</option>` + complexities.map(v => `<option value="${v}">${v}</option>`).join("");
document.getElementById("graphTypeFilter").innerHTML = `<option value="">All graph types</option>` + graphTypes.map(v => `<option value="${v}">${graphTypeLabel(v)}</option>`).join("");
}
function filteredProcesses() {
const q = normalizeText(document.getElementById("search").value);
const subcategory = document.getElementById("subcategoryFilter").value;
const collection = document.getElementById("collectionFilter").value;
const complexity = document.getElementById("complexityFilter").value;
const graphType = document.getElementById("graphTypeFilter").value;
return (metadata.processes || []).filter(process => {
const processCollections = getProcessCollections(process);
const haystack = normalizeText([
process.name,
process.domainContext,
process.category,
process.subcategory,
process.subcategory_name,
process.complexity,
process.graphType,
processCollections.join(" "),
(process.keywords || []).join(" ")
].join(" "));
return (!q || haystack.includes(q))
&& (!subcategory || (process.subcategory_name || process.subcategory) === subcategory)
&& (!collection || processCollections.includes(collection))
&& (!complexity || process.complexity === complexity)
&& (!graphType || (process.graphType || "flowchart") === graphType);
});
}
function renderRows() {
const rows = filteredProcesses();
document.getElementById("visibleCount").textContent = rows.length.toLocaleString();
document.getElementById("processRows").innerHTML = rows.map(process => {
const processCollections = getProcessCollections(process);
const collectionLabels = processCollections.map(id => (collections.find(c => c.id === id) || {label: id}).label);
const primarySearch = (profile.frontierSearches || [])[0];
return `
<tr>
<td class="name-cell"><a href="${processUrl(process)}">${process.name}</a></td>
<td>${process.domainContext || ""}</td>
<td>${process.category || process.subcategory_name || process.subcategory || ""}</td>
<td>${process.complexity || ""}</td>
<td>${metricValue(process, "nodes")}</td>
<td>${metricValue(process, "edges")}</td>
<td>${metricValue(process, "conditionals")}</td>
<td>${metricValue(process, "andGates")}</td>
<td>${metricValue(process, "orGates")}</td>
<td>${metricValue(process, "notGates")}</td>
<td>${metricValue(process, "loops")}</td>
<td><span class="pill">${graphTypeLabel(process.graphType)}</span></td>
<td>${collectionLabels.map(label => `<span class="pill">${label}</span>`).join(" ") || '<span class="muted">Unassigned</span>'}</td>
<td>${primarySearch ? `<a href="${frontierUrl(primarySearch.urlTemplate, process.name)}" target="_blank" rel="noopener noreferrer">${primarySearch.label}</a>` : ""}</td>
</tr>
`;
}).join("");
}
function wireEvents() {
["search", "subcategoryFilter", "collectionFilter", "complexityFilter", "graphTypeFilter"].forEach(id => {
document.getElementById(id).addEventListener("input", () => {
selectedCollection = document.getElementById("collectionFilter").value;
renderCollections();
renderRows();
});
});
document.getElementById("clearCollection").addEventListener("click", () => {
selectedCollection = "";
document.getElementById("collectionFilter").value = "";
renderCollections();
renderRows();
});
}
async function init() {
try {
profile = await fetchJson("discipline-profile.json", profile);
metadata = await fetchJson("metadata.json");
metadata = await fetchJson("process-index.json", metadata);
collections = await fetchJson("collections.json", []);
applyCollectionMemberships();
renderStats();
renderLens();
renderCollections();
populateFilters();
wireEvents();
renderRows();
} catch (error) {
const el = document.getElementById("error");
el.classList.remove("hidden");
el.innerHTML = `<strong>Could not load database metadata.</strong><br><span class="muted">${error.message}</span>`;
}
}
init();
</script>
</body>
</html>