remove so much stuff

This commit is contained in:
Barrett Ruth 2026-01-12 11:11:15 -05:00
parent 7f1c155a7b
commit dac0749890
54 changed files with 183 additions and 5010 deletions

View file

@ -1,259 +0,0 @@
(() => {
if (window.__BT_INDEX_INIT) return;
window.__BT_INDEX_INIT = true;
const TERMINAL_PROMPT = "barrett@ruth:~$ ";
let typing = false;
function promptEl() {
return document.querySelector(".terminal-prompt");
}
function promptTail() {
const el = promptEl();
if (!el) return "";
const s = el.textContent || "";
return s.startsWith(TERMINAL_PROMPT) ? s.slice(TERMINAL_PROMPT.length) : s;
}
function setPromptTailImmediate(tail) {
const el = promptEl();
if (!el) return;
el.textContent = TERMINAL_PROMPT + tail;
}
function persistPrompt() {
const el = promptEl();
if (el) sessionStorage.setItem("terminalPromptText", el.textContent);
}
(function restorePrompt() {
const saved = sessionStorage.getItem("terminalPromptText");
const el = promptEl();
if (saved && el) el.textContent = saved;
sessionStorage.removeItem("terminalPromptText");
})();
function normalizeDisplayPath(pathname) {
let p = pathname.replace(/\/index\.html$/, "/").replace(/\.html$/, "");
p = p.replace(/\/{2,}/g, "/");
if (p !== "/" && p.endsWith("/")) p = p.slice(0, -1);
return p === "/" ? "" : p;
}
function displayPathFromHref(href) {
const url = new URL(href, location.origin);
return normalizeDisplayPath(url.pathname);
}
function currentDisplayPath() {
return normalizeDisplayPath(location.pathname);
}
function animateToDisplayPath(displayPath, totalMs, done) {
if (typing) return;
typing = true;
const el = promptEl();
if (!el) {
typing = false;
return;
}
const targetTail = displayPath ? " " + displayPath : "";
const curTail = promptTail();
let i = 0;
const max = Math.min(curTail.length, targetTail.length);
while (i < max && curTail.charAt(i) === targetTail.charAt(i)) i++;
const delSteps = curTail.length - i;
const typeSteps = targetTail.length - i;
const totalSteps = delSteps + typeSteps;
if (totalSteps === 0) {
typing = false;
done && done();
return;
}
const stepMs = totalMs / totalSteps;
let delCount = 0;
function tickDelete() {
if (delCount < delSteps) {
setPromptTailImmediate(curTail.slice(0, curTail.length - delCount - 1));
delCount++;
setTimeout(tickDelete, stepMs);
} else {
let j = 0;
function tickType() {
if (j < typeSteps) {
setPromptTailImmediate(
curTail.slice(0, i) + targetTail.slice(i, i + j + 1),
);
j++;
setTimeout(tickType, stepMs);
} else {
typing = false;
done && done();
}
}
tickType();
}
}
tickDelete();
}
function renderPosts(topic) {
if (!window.postsByCategory) return;
const posts = document.getElementById("posts");
if (!posts) return;
posts.innerHTML = "";
const arr = window.postsByCategory[topic];
if (!arr) return;
for (const post of arr) {
const div = document.createElement("div");
div.className = "post";
const a = document.createElement("a");
const slug =
post.slug ||
post.id
?.split("/")
.pop()
?.replace(/\.mdx?$/, "");
a.href = `/${topic}/${slug}.html`;
a.textContent = post.data.title;
a.style.textDecoration = "underline";
div.appendChild(a);
posts.appendChild(div);
}
}
function handleDataTopicClick(e) {
const link = e.target.closest("[data-topic]");
if (!link) return;
e.preventDefault();
if (typing) return;
const path = window.location.pathname;
const isHome = path === "/" || path === "/index.html";
const topic = link.dataset.topic?.toLowerCase() || "";
const href = link.getAttribute("href") || "/";
const delay = 500;
const colorFn = window.getTopicColor || (() => "");
const topicKey = topic.split("/")[0];
const willNavigateAway = !(
isHome &&
topic &&
window.postsByCategory &&
window.postsByCategory[topic]
);
if (willNavigateAway) {
link.classList.add("active");
const c = colorFn(topicKey);
if (c) link.style.color = c;
} else {
document.querySelectorAll("[data-topic]").forEach((t) => {
t.classList.remove("active");
t.style.color = "";
});
link.classList.add("active");
const c = colorFn(topicKey);
if (c) link.style.color = c;
}
const displayPath = isHome ? `/${topic}` : displayPathFromHref(href);
animateToDisplayPath(displayPath, delay, () => {
if (
isHome &&
topic &&
window.postsByCategory &&
window.postsByCategory[topic]
) {
renderPosts(topic);
return;
}
persistPrompt();
const isMail = href.startsWith("mailto:");
if (isMail) {
window.location.href = href;
return;
}
if (link.target === "_blank") {
window.open(href, "_blank");
return;
}
window.location.href = href;
});
}
function handleHomeClick(e) {
const home = e.target.closest(".home-link");
if (!home) return;
e.preventDefault();
const isHome =
window.location.pathname === "/" ||
window.location.pathname === "/index.html";
const delay = 500;
if (isHome) {
animateToDisplayPath("", delay, () => {
const posts = document.getElementById("posts");
if (posts) posts.innerHTML = "";
document.querySelectorAll("[data-topic].active").forEach((t) => {
t.classList.remove("active");
t.style.color = "";
});
document.title = "";
});
} else {
persistPrompt();
animateToDisplayPath("", delay, () => {
window.location.href = "/";
});
}
}
document.addEventListener("DOMContentLoaded", () => {
const initial = currentDisplayPath();
if (initial) setPromptTailImmediate(" " + initial);
else setPromptTailImmediate("");
document.body.addEventListener("click", (e) => {
if (e.target.closest(".home-link")) return handleHomeClick(e);
if (e.target.closest(".topics [data-topic]"))
return handleDataTopicClick(e);
});
document.body.addEventListener(
"mouseenter",
(e) => {
const link = e.target.closest(".topics [data-topic]");
if (!link) return;
const raw = link.dataset.topic || "";
const key = raw.split("/")[0].toLowerCase();
const color = (window.getTopicColor && window.getTopicColor(key)) || "";
if (color) {
link.style.color = color;
link.style.textDecorationColor = color;
}
},
true,
);
document.body.addEventListener(
"mouseleave",
(e) => {
const link = e.target.closest(".topics [data-topic]");
if (!link) return;
if (!link.classList.contains("active")) {
link.style.color = "";
link.style.textDecorationColor = "";
}
},
true,
);
window.addEventListener("beforeunload", () => {
const el = promptEl();
if (el) el.textContent = TERMINAL_PROMPT;
});
});
})();

View file

@ -1,666 +0,0 @@
function urlToTopic() {
const path = window.location.pathname;
const pathParts = path.split("/");
return pathParts[2];
}
function getTextColor() {
return getComputedStyle(document.documentElement)
.getPropertyValue("--text")
.trim();
}
function setUpParameters(render, parameters, modelPrefix) {
parameters.forEach((param) => {
const slider = document.getElementById(`slider${modelPrefix}${param}`);
slider.oninput = function () {
slider.previousElementSibling.innerText = this.value;
render();
};
});
return parameters.map((param) => {
return parseFloat(
document.getElementById(`output${modelPrefix}${param}`).textContent,
);
});
}
function drawSolowGraph() {
const L = 150,
K_MAX = 500,
margin = { top: 50, right: 55, bottom: 40, left: 75 };
const [A, d, s, alpha] = setUpParameters(
drawSolowGraph,
["A", "d", "s", "alpha"],
"S",
);
const solowOutput = (K) => A * Math.pow(K, alpha) * Math.pow(L, 1 - alpha);
const solowDepreciation = (K) => d * K;
const solowInvestment = (Y) => s * Y;
const container = document.getElementById("solow-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
container.innerHTML = "";
const svg = d3
.select("#solow-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const x = d3.scaleLinear().domain([0, K_MAX]).range([0, width]);
const xAxis = svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x));
xAxis.selectAll("text").style("font-size", "1.5em");
xAxis
.append("text")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "2em")
.text("K");
const Y_MAX = solowOutput(K_MAX) + K_MAX / 10;
const y = d3.scaleLinear().domain([0, Y_MAX]).range([height, 0]);
const yAxis = svg.append("g").call(d3.axisLeft(y));
yAxis.selectAll("text").style("font-size", "1.5em");
yAxis
.append("text")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "2em")
.text("Y");
const outputData = Array.from({ length: K_MAX }, (_, k) => ({
K: k,
Y: solowOutput(k),
}));
svg
.append("path")
.datum(outputData)
.attr("fill", "none")
.attr("stroke", window.getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.K))
.y((d) => y(d.Y)),
);
svg
.append("foreignObject")
.attr("width", "2em")
.attr("height", "2em")
.attr("x", x(K_MAX))
.attr("y", y(outputData[K_MAX - 1].Y))
.append("xhtml:body")
.style("font-size", "0.75em")
.text("Y");
const depreciationData = Array.from({ length: K_MAX }, (_, k) => ({
K: k,
Y: solowDepreciation(k),
}));
svg
.append("path")
.datum(depreciationData)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.K))
.y((d) => y(d.Y)),
);
svg
.append("foreignObject")
.attr("width", "2em")
.attr("height", "2em")
.attr("x", x(K_MAX))
.attr("y", y(depreciationData[K_MAX - 1].Y))
.append("xhtml:body")
.style("font-size", "0.75em")
.append("xhtml:div")
.text("dK");
const investmentData = outputData.map((d) => ({
K: d.K,
Y: solowInvestment(d.Y),
}));
svg
.append("path")
.datum(investmentData)
.attr("fill", "none")
.attr("stroke", "purple")
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.K))
.y((d) => y(d.Y)),
);
svg
.append("text")
.attr("x", x(K_MAX))
.attr("y", y(investmentData[K_MAX - 1].Y))
.style("font-size", "0.75em")
.text("I");
const k_star = L * Math.pow((s * A) / d, 1 / (1 - alpha));
svg
.append("line")
.attr("x1", x(k_star))
.attr("y1", y((d * k_star) / s))
.attr("x2", x(k_star))
.attr("y2", y(0))
.attr("stroke-width", 1)
.attr("stroke-dasharray", "5,5");
const y_star = solowOutput(k_star);
svg
.append("text")
.attr("x", x(k_star) - 40)
.attr("y", y(y_star) - 40)
.style("font-size", "0.75em")
.text(`(${k_star.toFixed(0)}, ${y_star.toFixed(0)})`);
}
const formatNumber = (num) => {
return `~${num.toExponential(0)}`;
};
const normalFont = `style="font-weight: normal"`;
const updateRomerTable = (romerData) => {
const tableHeader = document.getElementById("romer-table-header");
const rowA_t = document.getElementById("row-A_t");
const rowY_t = document.getElementById("row-Y_t");
tableHeader.innerHTML = `<th ${normalFont}>t</th>`;
rowA_t.innerHTML = `<td class="romer-table-at">A_t</td>`;
rowY_t.innerHTML = `<td class="romer-table-yt">Y_t</td>`;
romerData.forEach((d) => {
if (d.year % 20 === 0 || d.year === 1) {
tableHeader.innerHTML += `<th ${normalFont}>${d.year}</th>`;
rowA_t.innerHTML += `<td>${formatNumber(d.A)}</td>`;
rowY_t.innerHTML += `<td>${formatNumber(d.Y)}</td>`;
}
});
};
function drawRomerGraph() {
const T_MAX = 100,
margin = { top: 50, right: 110, bottom: 40, left: 75 };
const [z, L, l, A0] = setUpParameters(
drawRomerGraph,
["z", "L", "l", "A0"],
"R",
);
const container = document.getElementById("romer-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
container.innerHTML = "";
const svg = d3
.select("#romer-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
let A = A0;
const romerData = [];
for (let t = 1; t <= T_MAX; ++t) {
const A_t = A * (1 + z * l * L);
const Y_t = A_t * (1 - l) * L;
romerData.push({ year: t, A: A_t, Y: Math.log10(Y_t) });
A = A_t;
}
const x = d3.scaleLinear().domain([1, T_MAX]).range([0, width]);
const xAxis = svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x));
xAxis.selectAll("text").style("font-size", "1.5em");
xAxis
.append("text")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "2em")
.text("t");
const y = d3
.scaleLinear()
.domain([0, romerData[romerData.length - 1].Y])
.range([height, 0]);
const yAxis = svg
.append("g")
.call(d3.axisLeft(y).ticks(10, d3.format(".1s")));
yAxis.selectAll("text").style("font-size", "1.5em");
yAxis
.append("text")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "2em")
.text("log(Y)");
svg
.append("path")
.datum(romerData)
.attr("fill", "none")
.attr("stroke", window.getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.year))
.y((d) => y(d.Y)),
);
svg
.append("text")
.attr("x", x(T_MAX))
.attr("y", y(romerData[T_MAX - 1].Y))
.style("font-size", "0.75em")
.text("log10(Y)");
updateRomerTable(romerData);
}
function drawRomerlGraph() {
const T_MAX = 100,
z = 0.01,
L = 50,
A0 = 50,
margin = { top: 50, right: 110, bottom: 40, left: 75 };
const [l, t0] = setUpParameters(drawRomerlGraph, ["lChange", "t0"], "");
const container = document.getElementById("romer-lchange-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
container.innerHTML = "";
const svg = d3
.select("#romer-lchange-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
let A = A0,
l_ = 0.1;
const romerData = [];
for (let t = 1; t <= t0; ++t) {
const A_t = A * (1 + z * l_ * L);
const Y_t = A_t * (1 - l_) * L;
romerData.push({ year: t, A: A_t, Y: Math.log10(Y_t) });
A = A_t;
}
for (let t = t0 + 1; t <= T_MAX; ++t) {
const A_t = A * (1 + z * l * L);
const Y_t = A_t * (1 - l) * L;
romerData.push({ year: t, A: A_t, Y: Math.log10(Y_t) });
A = A_t;
}
const x = d3.scaleLinear().domain([1, T_MAX]).range([0, width]);
const xAxis = svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x));
xAxis.selectAll("text").style("font-size", "1.5em");
xAxis
.append("text")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "2em")
.text("t");
const y = d3
.scaleLinear()
.domain([0, romerData[romerData.length - 1].Y])
.range([height, 0]);
const yAxis = svg
.append("g")
.call(d3.axisLeft(y).ticks(10, d3.format(".1s")));
yAxis.selectAll("text").style("font-size", "1.5em");
yAxis
.append("text")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "2em")
.text("log(Y)");
svg
.append("path")
.datum(romerData)
.attr("fill", "none")
.attr("stroke", window.getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.year))
.y((d) => y(d.Y)),
);
svg
.append("line")
.attr("x1", x(t0))
.attr("y1", y(romerData[T_MAX - 1].Y))
.attr("x2", x(t0))
.attr("y2", height)
.attr("stroke-width", 1)
.attr("stroke-dasharray", "4");
svg
.append("text")
.attr("x", x(0) + 15)
.attr("y", y(romerData[0].Y))
.style("font-size", "0.6em")
.text(`l0=${l_}`);
svg
.append("text")
.attr("x", x(t0) + 15)
.attr("y", y(romerData[t0].Y))
.style("font-size", "0.6em")
.text(`l1=${l}`);
svg
.append("text")
.attr("x", x(T_MAX))
.attr("y", y(romerData[T_MAX - 1].Y))
.style("font-size", "0.75em")
.text("log10(Y)");
}
function calculateRomerSolowData(
T_MAX,
L,
l,
A0,
alpha,
s,
d,
z,
t0 = Infinity,
L0,
l0,
alpha0,
z0,
) {
let A = A0,
K_t = 1,
romerSolowData = [];
for (let t = 1; t <= T_MAX; ++t) {
if (t > t0) {
alpha = alpha0;
z = z0;
l = l0;
L = L0;
}
const Y_t = A * Math.pow(K_t, alpha) * Math.pow((1 - l) * L, 1 - alpha);
const A_t = A * (1 + z * l * L);
K_t = K_t + s * Y_t - d * K_t;
romerSolowData.push({ year: t, A: A_t, K: K_t, Y: Math.log10(Y_t) });
A = A_t;
}
return romerSolowData;
}
function drawRomerSolowGraph() {
const T_MAX = 100,
margin = { top: 50, right: 110, bottom: 40, left: 75 };
const [z, l, L, A0, s, d, alpha] = setUpParameters(
drawRomerSolowGraph,
["z", "l", "L", "A0", "s", "d", "alpha"],
"RS",
);
const container = document.getElementById("romer-solow-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
container.innerHTML = "";
const svg = d3
.select("#romer-solow-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const romerSolowData = calculateRomerSolowData(
T_MAX,
L,
l,
A0,
alpha,
s,
d,
z,
);
const x = d3.scaleLinear().domain([1, T_MAX]).range([0, width]);
const xAxis = svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x));
xAxis.selectAll("text").style("font-size", "1.5em");
xAxis
.append("text")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "2em")
.text("t");
const y = d3
.scaleLinear()
.domain([0, romerSolowData[romerSolowData.length - 1].Y])
.range([height, 0]);
const yAxis = svg
.append("g")
.call(d3.axisLeft(y).ticks(10, d3.format(".1s")));
yAxis.selectAll("text").style("font-size", "1.5em");
yAxis
.append("text")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "2em")
.text("log(Y)");
svg
.append("path")
.datum(romerSolowData)
.attr("fill", "none")
.attr("stroke", window.getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.year))
.y((d) => y(d.Y)),
);
svg
.append("text")
.attr("x", x(T_MAX))
.attr("y", y(romerSolowData[T_MAX - 1].Y))
.style("font-size", "0.75em")
.text("log10(Y)");
}
function drawRomerSolowChangeGraph() {
const T_MAX = 100,
margin = { top: 20, right: 100, bottom: 20, left: 50 },
s = 0.2,
d = 0.2,
A0 = 50,
alpha = 0.33,
l = 0.5,
L = 100,
z = 0.5;
const [z0, l0, L0, alpha0, t0] = setUpParameters(
drawRomerSolowChangeGraph,
["z0", "l0", "L0", "alpha0", "t0"],
"RSC",
);
const container = document.getElementById("romer-solow-change-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
container.innerHTML = "";
const svg = d3
.select("#romer-solow-change-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const romerSolowData = calculateRomerSolowData(
T_MAX,
L,
l,
A0,
alpha,
s,
d,
z,
t0,
L0,
l0,
alpha0,
z0,
);
const x = d3.scaleLinear().domain([1, T_MAX]).range([0, width]);
const xAxis = svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x));
xAxis.selectAll("text").style("font-size", "1.5em");
xAxis
.append("text")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "2em")
.text("t");
const y = d3
.scaleLinear()
.domain([0, romerSolowData[romerSolowData.length - 1].Y])
.range([height, 0]);
const yAxis = svg
.append("g")
.call(d3.axisLeft(y).ticks(10, d3.format(".1s")));
yAxis.selectAll("text").style("font-size", "1.5em");
yAxis
.append("text")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "2em")
.text("log(Y)");
svg
.append("path")
.datum(romerSolowData)
.attr("fill", "none")
.attr("stroke", window.getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.year))
.y((d) => y(d.Y)),
);
svg
.append("line")
.attr("x1", x(t0))
.attr("y1", y(romerSolowData[T_MAX - 1].Y))
.attr("x2", x(t0))
.attr("y2", height)
.attr("stroke-width", 1)
.attr("stroke-dasharray", "4");
svg
.append("text")
.attr("x", x(T_MAX))
.attr("y", y(romerSolowData[T_MAX - 1].Y))
.style("font-size", "0.75em")
.text("log10(Y)");
}
drawSolowGraph();
drawRomerGraph();
drawRomerlGraph();
drawRomerSolowGraph();
drawRomerSolowChangeGraph();
window.onresize = () => {
drawSolowGraph();
drawRomerGraph();
drawRomerlGraph();
drawRomerSolowGraph();
drawRomerSolowChangeGraph();
};
new MutationObserver(() => {
drawSolowGraph();
drawRomerGraph();
drawRomerlGraph();
drawRomerSolowGraph();
drawRomerSolowChangeGraph();
}).observe(document.documentElement, {
attributes: true,
attributeFilter: ["data-theme"],
});