Move graph computation from server to client

This commit is contained in:
Michael Winter 2026-04-01 16:37:45 +02:00
parent 79e1259f5b
commit c6bb3a12ce

View file

@ -578,12 +578,22 @@
}); });
} }
// Load from Flask API - get ALL graphs at once // Load from Flask API - get chords and compute graphs client-side
async function loadAllGraphs() { async function loadAllGraphs() {
try { try {
const response = await fetch("/api/all-graphs"); const response = await fetch("/api/chords");
if (!response.ok) throw new Error("API not available"); if (!response.ok) throw new Error("API not available");
allGraphsData = await response.json(); const data = await response.json();
// Compute graphs from raw chord data client-side
const graphs = data.chords.map((chord, index) => {
return calculateGraph(chord, index);
});
allGraphsData = {
total: data.total,
graphs: graphs
};
totalSteps = allGraphsData.total - 1; totalSteps = allGraphsData.total - 1;
@ -597,10 +607,100 @@
updateUI(); updateUI();
} catch (e) { } catch (e) {
console.log("Error loading graphs:", e); console.log("Error loading chords:", e);
} }
} }
// Compute graph (nodes + edges) from raw chord data - client-side version
function calculateGraph(chord, index) {
if (!chord) return { nodes: [], edges: [] };
const nodes = [];
const dims = [2, 3, 5, 7];
// Calculate cents for each pitch
for (let i = 0; i < chord.length; i++) {
const pitch = chord[i];
const fraction = parseFraction(pitch.fraction || "1");
const cents = fraction > 0 ? 1200 * Math.log2(fraction) : 0;
nodes.push({
id: i,
cents: Math.round(cents),
fraction: pitch.fraction || "1",
hs_array: pitch.hs_array || []
});
}
// Find edges: differ by ±1 in exactly one dimension (ignoring dim 0)
const edges = [];
for (let i = 0; i < chord.length; i++) {
for (let j = i + 1; j < chord.length; j++) {
const hs1 = chord[i].hs_array || [];
const hs2 = chord[j].hs_array || [];
if (!hs1.length || !hs2.length) continue;
// Count differences in dims 1, 2, 3
let diffCount = 0;
let diffDim = -1;
for (let d = 1; d < hs1.length; d++) {
const diff = hs2[d] - hs1[d];
if (Math.abs(diff) === 1) {
diffCount++;
diffDim = d;
} else if (diff !== 0) {
break; // diff > 1 in this dimension
}
}
// Check if exactly one dimension differs
if (diffCount === 1 && diffDim > 0) {
// Calculate frequency ratio
const diffHs = [];
for (let d = 0; d < hs1.length; d++) {
diffHs.push(hs1[d] - hs2[d]);
}
let numerator = 1;
let denominator = 1;
for (let dIdx = 0; dIdx < dims.length; dIdx++) {
const exp = diffHs[dIdx];
if (exp > 0) {
numerator *= Math.pow(dims[dIdx], exp);
} else if (exp < 0) {
denominator *= Math.pow(dims[dIdx], -exp);
}
}
const ratio = denominator > 1 ? `${numerator}/${denominator}` : `${numerator}`;
edges.push({
source: i,
target: j,
ratio: ratio,
dim: diffDim
});
}
}
}
return { nodes, edges, index };
}
// Parse fraction string to number
function parseFraction(fracStr) {
if (typeof fracStr === 'number') return fracStr;
if (!fracStr) return 1;
if (fracStr.includes('/')) {
const [num, den] = fracStr.split('/').map(Number);
return num / den;
}
return Number(fracStr);
}
// Update UI elements // Update UI elements
function updateUI() { function updateUI() {
hasPrev = currentIndex > 0; hasPrev = currentIndex > 0;