Move graph computation from server to client
This commit is contained in:
parent
79e1259f5b
commit
c6bb3a12ce
|
|
@ -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() {
|
||||
try {
|
||||
const response = await fetch("/api/all-graphs");
|
||||
const response = await fetch("/api/chords");
|
||||
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;
|
||||
|
||||
|
|
@ -597,10 +607,100 @@
|
|||
updateUI();
|
||||
|
||||
} 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
|
||||
function updateUI() {
|
||||
hasPrev = currentIndex > 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue