#!/usr/bin/env node /** * Build Euclid's Elements Book VIII discourse JSON and Mermaid charts. * 27 propositions. Continued proportions. Depends on Book VII. Source: David E. Joyce. * * Charts: 2. Chart 1: Props 1-14. Chart 2: Props 15-27. */ const fs = require('fs'); const path = require('path'); const PROPS = [ { n: 1, short: "Continued proportion, extremes prime", full: "Continued proportion, extremes relatively prime: least in ratio" }, { n: 2, short: "Find numbers in continued proportion", full: "To find numbers in continued proportion, least in given ratio" }, { n: 3, short: "Least: extremes prime", full: "Least in continued proportion: extremes relatively prime" }, { n: 4, short: "Find continued proportion from ratios", full: "Given ratios in least numbers, find least in continued proportion" }, { n: 5, short: "Plane numbers: compound ratio", full: "Plane numbers have ratio compounded of ratios of sides" }, { n: 6, short: "First does not measure second", full: "Continued proportion: if first does not measure second, none measures another" }, { n: 7, short: "First measures last", full: "Continued proportion: if first measures last, it measures second" }, { n: 8, short: "Numbers between in proportion", full: "Numbers between two in continued proportion correspond to ratios" }, { n: 9, short: "Relatively prime: numbers to unit", full: "Two relatively prime: numbers between them as between each and unit" }, { n: 10, short: "Numbers from unit", full: "Numbers between number and unit correspond to between two numbers" }, { n: 11, short: "Mean proportional of squares", full: "Between two squares one mean proportional; duplicate ratio" }, { n: 12, short: "Two means between cubes", full: "Between two cubes two mean proportionals; triplicate ratio" }, { n: 13, short: "Products proportional", full: "Continued proportion: products proportional; products of products" }, { n: 14, short: "Square measures square", full: "Square measures square iff side measures side" }, { n: 15, short: "Cube measures cube", full: "Cube measures cube iff side measures side" }, { n: 16, short: "Square does not measure square", full: "Square does not measure square iff side does not measure side" }, { n: 17, short: "Cube does not measure cube", full: "Cube does not measure cube iff side does not measure side" }, { n: 18, short: "Similar plane: mean proportional", full: "Between similar plane numbers one mean proportional; duplicate ratio" }, { n: 19, short: "Similar solid: two means", full: "Between similar solid numbers two mean proportionals; triplicate ratio" }, { n: 20, short: "One mean: similar plane", full: "If one mean between two numbers, they are similar plane" }, { n: 21, short: "Two means: similar solid", full: "If two means between two numbers, they are similar solid" }, { n: 22, short: "Three in proportion: first square", full: "Three in continued proportion, first square: third square" }, { n: 23, short: "Four in proportion: first cube", full: "Four in continued proportion, first cube: fourth cube" }, { n: 24, short: "Ratio as square to square", full: "If ratio as square to square and first square, second square" }, { n: 25, short: "Ratio as cube to cube", full: "If ratio as cube to cube and first cube, second cube" }, { n: 26, short: "Similar plane: square ratio", full: "Similar plane numbers have ratio of square to square" }, { n: 27, short: "Similar solid: cube ratio", full: "Similar solid numbers have ratio of cube to cube" } ]; const DEPS = {}; for (let i = 1; i <= 27; i++) DEPS[i] = ["BookVII"]; DEPS[2] = ["BookVII", "Prop1"]; DEPS[3] = ["BookVII", "Prop2"]; DEPS[4] = ["BookVII", "Prop2"]; DEPS[5] = ["BookVII"]; DEPS[6] = ["BookVII", "Prop1"]; DEPS[7] = ["BookVII", "Prop1"]; DEPS[8] = ["BookVII"]; DEPS[9] = ["BookVII", "Prop8"]; DEPS[10] = ["BookVII", "Prop9"]; DEPS[11] = ["BookVII", "Prop8"]; DEPS[12] = ["BookVII", "Prop8"]; DEPS[13] = ["BookVII"]; DEPS[14] = ["BookVII", "Prop11"]; DEPS[15] = ["BookVII", "Prop12"]; DEPS[16] = ["BookVII", "Prop14"]; DEPS[17] = ["BookVII", "Prop15"]; DEPS[18] = ["BookVII", "Prop8"]; DEPS[19] = ["BookVII", "Prop8"]; DEPS[20] = ["BookVII", "Prop18"]; DEPS[21] = ["BookVII", "Prop19"]; DEPS[22] = ["BookVII", "Prop1"]; DEPS[23] = ["BookVII", "Prop1"]; DEPS[24] = ["BookVII", "Prop22"]; DEPS[25] = ["BookVII", "Prop23"]; DEPS[26] = ["BookVII", "Prop18"]; DEPS[27] = ["BookVII", "Prop19"]; const discourse = { schemaVersion: "1.0", discourse: { id: "euclid-elements-book-viii", name: "Euclid's Elements, Book VIII", subject: "number_theory", variant: "classical", description: "Continued proportions. 27 propositions. Depends on Book VII. Source: David E. Joyce.", structure: { books: 8, propositions: 27, foundationTypes: ["foundation"] } }, metadata: { created: "2026-03-18", lastUpdated: "2026-03-18", version: "1.0.0", license: "CC BY 4.0", authors: ["Welz, G."], methodology: "Programming Framework", citation: "Welz, G. (2026). Euclid's Elements Book VIII Dependency Graph. Programming Framework.", keywords: ["Euclid", "Elements", "Book VIII", "continued proportion", "plane", "solid"] }, sources: [ { id: "joyce", type: "digital", authors: "Joyce, David E.", title: "Euclid's Elements, Book VIII", year: "1996", url: "https://mathcs.clarku.edu/~djoyce/java/elements/bookVIII/bookVIII.html", notes: "Clark University" } ], nodes: [], edges: [], colorScheme: { foundation: { fill: "#95a5a6", stroke: "#7f8c8d" }, proposition: { fill: "#1abc9c", stroke: "#16a085" } } }; discourse.nodes.push( { id: "BookVII", type: "foundation", label: "Book VII — Number theory", shortLabel: "Book VII", short: "Foundation", book: 7, colorClass: "foundation" } ); for (const prop of PROPS) { discourse.nodes.push({ id: `Prop${prop.n}`, type: "proposition", label: prop.full, shortLabel: `Prop. VIII.${prop.n}`, short: prop.short, book: 8, number: prop.n, colorClass: "proposition" }); for (const dep of DEPS[prop.n] || ["BookVII"]) { discourse.edges.push({ from: dep, to: `Prop${prop.n}` }); } } const dataDir = path.join(__dirname, "..", "data"); fs.mkdirSync(dataDir, { recursive: true }); fs.writeFileSync(path.join(dataDir, "euclid-elements-book-viii.json"), JSON.stringify(discourse, null, 2), "utf8"); console.log("Wrote euclid-elements-book-viii.json"); function toMermaid(filter) { const nodes = filter ? discourse.nodes.filter(filter) : discourse.nodes; const nodeIds = new Set(nodes.map(n => n.id)); const edges = discourse.edges.filter(e => nodeIds.has(e.from) && nodeIds.has(e.to)); const lines = ["graph TD"]; for (const n of nodes) { const desc = n.short || (n.label && n.label.length > 35 ? n.label.slice(0, 32) + "..." : n.label || n.id); const lbl = (n.shortLabel || n.id) + "\\n" + (desc || ""); lines.push(` ${n.id}["${String(lbl).replace(/"/g, '\\"')}"]`); } for (const e of edges) { lines.push(` ${e.from} --> ${e.to}`); } lines.push(" classDef foundation fill:#95a5a6,color:#fff,stroke:#7f8c8d"); lines.push(" classDef proposition fill:#1abc9c,color:#fff,stroke:#16a085"); const foundIds = nodes.filter(n => n.type === "foundation").map(n => n.id).join(","); const propIds = nodes.filter(n => n.type === "proposition").map(n => n.id).join(","); if (foundIds) lines.push(` class ${foundIds} foundation`); lines.push(` class ${propIds} proposition`); return lines.join("\n"); } function closure(propMax) { const needed = new Set(["BookVII"]); for (let i = 1; i <= propMax; i++) needed.add(`Prop${i}`); let changed = true; while (changed) { changed = false; for (const e of discourse.edges) { if (needed.has(e.to) && !needed.has(e.from)) { needed.add(e.from); changed = true; } } } return n => needed.has(n.id); } const MATH_DB = process.env.MATH_DB || "/home/gdubs/copernicus-web-public/huggingface-space/mathematics-processes-database"; const GEOM_DIR = path.join(MATH_DB, "processes", "geometry_topology"); function htmlTemplate(title, subtitle, mermaid, nodes, edges) { const mermaidEscaped = mermaid.replace(//g, ">"); return ` ${title} - Mathematics Process

${title}

Mathematics Number Theory Source: Euclid's Elements

Description

${subtitle}

Source: Euclid's Elements, Book VIII (David E. Joyce, Clark University)

Dependency Flowchart

${mermaidEscaped}

Color Scheme

Gray
Book VII (foundation)
Teal
Propositions

Statistics

  • Nodes: ${nodes}
  • Edges: ${edges}

Keywords

  • Euclid
  • Elements
  • Book VIII
  • continued proportion
  • plane
  • solid
`; } if (fs.existsSync(GEOM_DIR)) { const filter1 = closure(14); const m1 = toMermaid(filter1); const nodes1 = discourse.nodes.filter(filter1); const edges1 = discourse.edges.filter(e => filter1({ id: e.from }) && filter1({ id: e.to })); fs.writeFileSync(path.join(GEOM_DIR, "geometry_topology-euclid-elements-book-viii-props-1-14.html"), htmlTemplate("Euclid's Elements Book VIII — Propositions 1–14", "Continued proportion, least in ratio, square/cube. Depends on Book VII.", m1, nodes1.length, edges1.length), "utf8"); console.log("Wrote geometry_topology-euclid-elements-book-viii-props-1-14.html"); const m2 = toMermaid(() => true); fs.writeFileSync(path.join(GEOM_DIR, "geometry_topology-euclid-elements-book-viii-props-15-27.html"), htmlTemplate("Euclid's Elements Book VIII — Propositions 15–27", "Similar plane/solid, mean proportionals, square/cube ratios.", m2, discourse.nodes.length, discourse.edges.length), "utf8"); console.log("Wrote geometry_topology-euclid-elements-book-viii-props-15-27.html"); } // Book VIII index if (fs.existsSync(GEOM_DIR)) { const indexHtml = ` Euclid's Elements Book VIII - Mathematics Process

Euclid's Elements Book VIII

Continued proportions. 27 propositions. Depends on Book VII. Plane numbers, solid numbers, mean proportionals.

Propositions 1–14 Continued proportion, squares, cubes Propositions 15–27 Similar plane/solid, ratios
`; fs.writeFileSync(path.join(GEOM_DIR, "geometry_topology-euclid-elements-book-viii.html"), indexHtml, "utf8"); console.log("Wrote geometry_topology-euclid-elements-book-viii.html"); } console.log("Done. Nodes:", discourse.nodes.length, "Edges:", discourse.edges.length);