t.p.n parity
|
|
@ -24,6 +24,7 @@ export default function (eleventyConfig) {
|
|||
|
||||
eleventyConfig.addPassthroughCopy("site-src/res");
|
||||
eleventyConfig.addPassthroughCopy("site-src/*.png");
|
||||
eleventyConfig.addPassthroughCopy("site-src/**/*.html");
|
||||
|
||||
eleventyConfig.setLayoutsDirectory("layout");
|
||||
|
||||
|
|
|
|||
10
site-src/fun-web-stuff.mdx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
title: Fun web stuff
|
||||
description: Stuff that mehbark made that you can play with on your browser
|
||||
---
|
||||
|
||||
- [Spout](/spout): Fun, oft-interactive HTML/JS pieces
|
||||
- [gol](https://pyrope.net/gol): [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway's_Game_of_Life) with checkboxes, made in elm
|
||||
- [TIMEDOG](https://pyrope.net/TIMEDOG): a clock that measures time in Patricia Taxxon's [TECHDOG](https://patriciataxxon.bandcamp.com/album/techdog-1-7)
|
||||
- [davehash](https://pyrope.net/davehash/): you know what a hash modus is, right?
|
||||
- [old site](https://web.archive.org/web/20260124004542/https://terezi.pyrope.net/): the site before this one. [aka onepn](/twopn)
|
||||
|
|
@ -12,13 +12,29 @@ export function PostLink({post}) {
|
|||
{" "}
|
||||
({tags.join(", ")})
|
||||
{" "}
|
||||
(<time datetime={post.date.toISOString()}>{post.date.toDateString()}</time>)
|
||||
(<time dateTime={post.date.toISOString()}>{post.date.toDateString()}</time>)
|
||||
</>
|
||||
}
|
||||
|
||||
## Posts
|
||||
## About me
|
||||
- [I go by mehbark](/awesomebark) on the internet!
|
||||
- I did get this domain just for the pun, but alas, I can't claim to be <span title="I think that's maybe Vriska?">the number one Terezi fan</span>.
|
||||
- I put code on [my Forgejo instance](https://g.pyrope.net) and [my GitHub](https://github.com/mehbark).
|
||||
- I had fun making posts on [cohost](https://cohost.org) before it died;
|
||||
I enjoyed making [CSS crimes](https://cohost.org/mehbark/tagged/css%20crimes) the most, of course.
|
||||
- I occasionally enjoy making bad video games and putting them on [my itch.io](https://mehbark.itch.io)
|
||||
|
||||
If you want to do something on your browser AS SOON AS POSSIBLE, check out [my page of fun web stuff](/fun-web-stuff)!
|
||||
|
||||
If you want longer-form stuff of even less consistent quality, check out [my blog](https://b.pyrope.net)!
|
||||
|
||||
---
|
||||
|
||||
## Latest posts
|
||||
<ul>
|
||||
{props.collections.post.toReversed().map(p =>
|
||||
<li key={p.url}><PostLink post={p} /></li>
|
||||
)}
|
||||
</ul>
|
||||
|
||||
---
|
||||
|
|
|
|||
63
site-src/layout/badges.njk
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<div class="badges">
|
||||
<a href="https://bambosh.dev/unofficial-homestuck-collection">
|
||||
<img src="/res/88x31/homestuck.gif" alt="homestuck" title="read it">
|
||||
</a>
|
||||
<a rel="me" href="https://critter.cafe/@mehbark">
|
||||
<img src="/res/88x31/mastodon_button_3.gif" alt="The mastodon mastodon playing with a paper airplane next to text that says Follow me on Mastodon" title="if you want">
|
||||
</a>
|
||||
<a href="https://cyber.dabamos.de/88x31/">
|
||||
<img src="/res/88x31/88x31.gif" alt="88 X 31" title="most of these are from here">
|
||||
</a>
|
||||
<img src="/res/88x31/stamp-sadness.gif" alt="i like stamps but they would look out of place sad face" title="i mean the fancy ones that aren't 88x31, they just don't line up">
|
||||
<a href="https://archlinux.org/">
|
||||
<img src="/res/88x31/archlinux.gif" alt="arch linux" title="it's just easier tbh">
|
||||
</a>
|
||||
<a href="https://www.w3.org/Style/CSS">
|
||||
<img src="/res/88x31/css2.gif" alt="made with cascading style sheets" title="very few of them, but some">
|
||||
</a>
|
||||
<a href="https://www.debian.org/">
|
||||
<img src="/res/88x31/debian.gif" alt="the debian logo next to text that says powered by debian" title="it really is; that's why it's still working">
|
||||
</a>
|
||||
<a href="https://store.steampowered.com/app/1610900/The_Genesis_Project/" target="_blank">
|
||||
<img src="/res/88x31/e-hs.gif" alt="text that says download SBURB next to the SBURB logo, the SBURB part is all fancy" title="not really but this is dang cool">
|
||||
</a>
|
||||
</a>
|
||||
<img src="/res/88x31/this-user-loves-terezi.png" alt="terezi next to text that says THIS USER LOVES TEREZI in terezi's typing quirk" title="(platonically)">
|
||||
<!--
|
||||
hi cefqrn hi hi hi hi hi hi hi hi
|
||||
-->
|
||||
<a href="https://www.mozilla.org/firefox/">
|
||||
<img src="/res/88x31/firefoxget.gif" alt="The firefox logo next to text that cycles between get firefox, rediscover the web, the browser you can trust, etcetera" title="i use it">
|
||||
</a>
|
||||
<img src="/res/88x31/ie_exploder.gif" alt="Text that says FREE: Microsoft Internet Exploder next to the internet explorer logo, which turns into the earth and then BLOWS UP" title="real fact, ask your local librarian">
|
||||
<a href="https://irc.pyrope.net">
|
||||
<img src="/res/88x31/ircworks.gif" alt="irc works" title="sometimes. uh, not right now">
|
||||
</a>
|
||||
<!--
|
||||
-->
|
||||
<img src="/res/88x31/2019.gif" alt="Still using buttons in 2019!" title="get it? because it isn't 2019?">
|
||||
<a href="https://www.vim.org/">
|
||||
<img src="/res/88x31/madewithvi.gif" alt="made with vi" title="technically the improved version and a bit of the vscode version and a bit of evil">
|
||||
</a>
|
||||
<img src="/res/88x31/i-was-on-cohost.gif" alt="eggbug next to text that says I was on cohost" title="i was!">
|
||||
<!--
|
||||
-->
|
||||
<a href="http://web.archive.org/web/20240000000000*/hackles.org">
|
||||
<img src="/res/88x31/hackles-button.png" alt="the two penguins from hackles looking at teal text that says hackles.org" border=0>
|
||||
</a>
|
||||
<img src="https://deep-freezer.neocities.org/images/misc_buttons/HomestuckButton.gif" alt="a pretty pixel art gif by @coldcalzone that shows the broad strokes of the acts of homestuck. very cool">
|
||||
<a href="http://www.sbcl.org/"><img src="https://www.sbcl.org/sbclbutton.png" alt="(get 'sbcl)"></a>
|
||||
<a href="https://terezi.pyrope.net"><img alt="terezi's head is seen from behind looking at the sky. on the right, it says terezi.pyrope.net and >:]" src="https://terezi.pyrope.net/88x31.png"></a>
|
||||
<a href="https://wowperfect.net/"><img title="wow, perfect" src="https://wowperfect.net/img/88x31.png"></a>
|
||||
<a href="https://coolstation.space"><img title="cool, station" src="https://coolstation.space/cool_assets/88x31/coolstation.gif"></a>
|
||||
<a href="https://spax.zone"><img title="Spaxolotl's zone" src="https://spax.zone/images/buttons/button.gif"></a>
|
||||
<a href="https://kokoscript.com"><img title="Koko's NetWeb Site" src="https://kokoscript.com/img/button/kokoscript.gif"></a>
|
||||
<a href="https://deerz.one"><img title="the (ida) deer zone" src="https://deerz.one/img/88x31/deerzone.gif"></a>
|
||||
<a href="https://moonbase.lgbt" title="Moonbase Dot LGBT"><img src="https://moonbase.lgbt/88x31/moonbase.gif" alt="Moonbase Dot LGBT" width="88" height="31" /></a>
|
||||
<a href="https://easrng.net"><img title="em's net" src="https://badges.easrng.net/easrng.gif"></a>
|
||||
<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" title="Lebsite Weague"><img src="/res/88x31/lebsite-weague.png" alt="lebsite weague" /></a>
|
||||
<a href="https://moonbase.lgbt/blog/nes-pictionary-in-memoriam/" title="NES Pictionary"><img src="https://moonbase.lgbt/88x31/nes-pictionary.png" alt="NES Pictionary" width="88" height="31"></a>
|
||||
<a href="https://nixos.org" title="fixes this"><img src="/res/88x31/nixos-88x31.png" alt="nixos logo" /></a>
|
||||
<iframe src="https://incr.easrng.net/badge?key=terezi.pyrope.net" style="background: url(//incr.easrng.net/bg.gif)" title="increment badge" width="88" height="31" frameborder="0"></iframe>
|
||||
<a href="https://lisanne.gay"><img alt="lisanne.gay 88x31" src="https://lisanne.gay/88x31_pls_DO_hotlink.png"></a>
|
||||
</div>
|
||||
|
|
@ -28,11 +28,21 @@ title: terezi.pyrope.net
|
|||
</head>
|
||||
<body>
|
||||
<h1 id="site-title"><a href="/">T3R3Z1.PYROP3.N3T</a></h1>
|
||||
<main>
|
||||
{% if title != "terezi.pyrope.net" %}
|
||||
<h1><a href="{{ url or "" }}">{{ title }}</a></h1>
|
||||
{% endif %}
|
||||
|
||||
{{ content | safe }}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
{% include "./badges.njk" %}
|
||||
<div class="webring">
|
||||
<h3>this web site is part of the m,cai webring</h3>
|
||||
<a href="https://spax.zone">←</a> <a href="/ring.html">everyone</a> <a href="https://lisanne.gay">→</a>
|
||||
</div>
|
||||
<iframe title="splat button" width="110" height="100" src="https://www.myinstants.com/instant/lancer-splat-18107/embed/" frameborder="0" scrolling="no"></iframe>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
BIN
site-src/res/88x31/2019.gif
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
site-src/res/88x31/88x31.gif
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
site-src/res/88x31/archlinux.gif
Normal file
|
After Width: | Height: | Size: 3 KiB |
BIN
site-src/res/88x31/css2.gif
Normal file
|
After Width: | Height: | Size: 940 B |
BIN
site-src/res/88x31/debian.gif
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
site-src/res/88x31/e-hs.gif
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
site-src/res/88x31/firefoxget.gif
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
site-src/res/88x31/hackles-button.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
site-src/res/88x31/homestuck.gif
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
site-src/res/88x31/i-was-on-cohost.gif
Normal file
|
After Width: | Height: | Size: 794 B |
BIN
site-src/res/88x31/ie_exploder.gif
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
site-src/res/88x31/ircworks.gif
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
site-src/res/88x31/lebsite-weague.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
site-src/res/88x31/madewithvi.gif
Normal file
|
After Width: | Height: | Size: 761 B |
BIN
site-src/res/88x31/mastodon_button_3.gif
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
site-src/res/88x31/nixos-88x31.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
site-src/res/88x31/stamp-sadness.gif
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
site-src/res/88x31/this-user-loves-terezi.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
|
|
@ -23,6 +23,11 @@ body {
|
|||
/* idk */
|
||||
/* font-feature-settings: "aalt", "c2sc", "ccmp", "cv13", "cv17", "cv19", "cv20", "cv25", "cv28", "cv37", "cv43", "cv44", "cv46", "cv47", "cv49", "cv55", "cv57", "cv62", "cv68", "cv69", "cv70", "cv71", "cv75", "cv76", "cv77", "cv79", "cv80", "cv81", "cv82", "cv84", "cv90", "cv91", "cv92", "cv98", "frac", "liga", "locl", "smcp", "ss01", "ss04", "ss05", "ss11", "ss12", "subs", "sups", "mark", "mkmk";
|
||||
*/
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
main {
|
||||
min-height: 60vh;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
|
@ -256,9 +261,53 @@ video {
|
|||
Courier,
|
||||
monospace;
|
||||
background: var(--accent2);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#site-title > a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
background-color: var(--accent2);
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*.badges a, marquee a, header a {
|
||||
border: none;
|
||||
background-color: #00000000;
|
||||
text-decoration: none;
|
||||
}*/
|
||||
.badges {
|
||||
image-rendering: pixelated;
|
||||
transition: transform 0.1s;
|
||||
overflow-x: clip;
|
||||
font-size: 0pt;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
.badges > * {
|
||||
display: inline-block;
|
||||
width: 88px;
|
||||
height: 31px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
/*
|
||||
.badges > :hover {
|
||||
transform: scale(2);
|
||||
}
|
||||
*/
|
||||
.badges > a > img,
|
||||
.badges .ff-container {
|
||||
width: 88px;
|
||||
height: 31px;
|
||||
}
|
||||
|
||||
.webring {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.webring > a {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
title: On the reverse-chronological ordering of items
|
||||
description: I pontificate on the merits and missteps of ordering items by their associated date in a fashion antiparallel to our logical conception of time.
|
||||
tags: post,short
|
||||
date: 2026-01-24 20:00:00
|
||||
---
|
||||
|
||||
the bit is that this is actually for testing reverse chron but i'm going to turn it into a little piece about reverse chron.
|
||||
|
|
|
|||
96
site-src/ring.html
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #b8b;
|
||||
padding-left: 1rem;
|
||||
background-color: #111;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
}
|
||||
|
||||
li {
|
||||
list-style-type: georgian;
|
||||
border-left: 1lh outset var(--color);
|
||||
}
|
||||
|
||||
a {
|
||||
color: #c3c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #b2b;
|
||||
}
|
||||
|
||||
canvas {
|
||||
border-radius: 4113cm;
|
||||
border: 1px solid #b8b;
|
||||
image-rendering: pixelated;
|
||||
width: min(514px, 95vw);
|
||||
}
|
||||
</style>
|
||||
<title>the m,cai webring</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script>
|
||||
// yo dawg,
|
||||
var updates_per_update = 1;
|
||||
window.onload = () => {
|
||||
let ch = [...document.querySelector("ul").children];
|
||||
for (let c of ch) c.appendChild(document.createElement("span"))
|
||||
for (let i = 0; i < ch.length; i++) {
|
||||
ch[i].onmouseover = () => {
|
||||
for (let c of ch) c.querySelector("span").innerText = "";
|
||||
|
||||
let l = ch[i==0?ch.length-1:i-1].querySelector("span");
|
||||
let r = ch[i==ch.length-1?0:i+1].querySelector("span");
|
||||
l.innerText = "(left)";
|
||||
r.innerText = "(right)";
|
||||
};
|
||||
}
|
||||
|
||||
let c = document.querySelector("canvas").getContext("2d");
|
||||
let [cx, cy] = [256, 256];
|
||||
let randr = (l, h) => Math.random() * (h-l) + l;
|
||||
let parts = ch.map(c => ({x: cx, y: cy, color: c.style.getPropertyValue("--color")}));
|
||||
let dist = (x1, y1, x2, y2) => Math.sqrt((x2-x1)**2 + (y2-y1)**2);
|
||||
function update() {
|
||||
// c.clearRect(0, 0, 512, 512);
|
||||
for (const p of parts) {
|
||||
c.fillStyle = p.color;
|
||||
c.fillRect(p.x, p.y, 1, 1);
|
||||
p.x += Math.round(randr(-1, 1));
|
||||
p.y += Math.round(randr(-1, 1));
|
||||
if (dist(cx, cy, p.x, p.y) >= 257) {
|
||||
if (p.x > cx) p.x--;
|
||||
if (p.x < cx) p.x++;
|
||||
if (p.y > cy) p.y--;
|
||||
if (p.y < cy) p.y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
setInterval(() => {for (let i=0;i<updates_per_update;i++)update()}, 0);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>the m,cai webring</h1>
|
||||
<ul>
|
||||
<li style="--color: #008282"><a href="https://terezi.pyrope.net">terezi.pyrope.net</a>
|
||||
<li style="--color: #a0a08b"><a href="https://lisanne.gay">lisanne.gay</a>
|
||||
<li style="--color: #14a02e"><a href="https://coolstation.space">coolstation.space</a>
|
||||
<li style="--color: #306850"><a href="https://spax.zone">spax.zone</a>
|
||||
</ul>
|
||||
<canvas width=512 height=512></canvas>
|
||||
</body>
|
||||
</html>
|
||||
646
site-src/spout/index.html
Normal file
|
|
@ -0,0 +1,646 @@
|
|||
<!doctype html>
|
||||
<html><head><title>spout</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="spout" property="og:title" />
|
||||
<meta content="i post html" property="og:description" />
|
||||
<meta content="https://terezi.pyrope.net/spout" property="og:url" />
|
||||
<meta content="#008282" data-react-helmet="true" name="theme-color" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
html {
|
||||
--fg: #ede;
|
||||
--bg: #233;
|
||||
--accent: #76a6e4;
|
||||
color: var(--fg);
|
||||
background-color: var(--bg);
|
||||
}
|
||||
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a[href^="#s"], a[href^="#s"]:visited {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a, a:visited {
|
||||
color: var(--accent);
|
||||
text-decoration: dotted underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: solid underline;
|
||||
}
|
||||
|
||||
article {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid var(--fg);
|
||||
margin-inline: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
width: min(calc(95vw - 4rem), 15cm);
|
||||
}
|
||||
|
||||
canvas {
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.emoticon {
|
||||
font-family: "Courier New", "Courier Std", courier, monospace;
|
||||
font-weight: bold;
|
||||
color: #008282;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.controls > button {
|
||||
flex: 1;
|
||||
aspect-ratio: 1;
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.1em;
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
// pretty neat, right?
|
||||
let hl_ref = () => {
|
||||
if (!document.location.hash) return;
|
||||
document.querySelectorAll("article").forEach(a => a.style.backgroundColor = null);
|
||||
document.querySelector(document.location.hash).style.backgroundColor = "#344";
|
||||
};
|
||||
window.onhashchange = hl_ref;
|
||||
|
||||
Number.prototype.map = function(a,b,c,d){return c+(d-c)*((this-a)/(b-a))};
|
||||
let elems = (s, ids) => ids.split(" ").map(i => document.getElementById(`s${s}-${i}`));
|
||||
window.onload = () => {
|
||||
hl_ref();
|
||||
let [s9lhs, s9rhs] = elems(9, "lhs rhs");
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
params.get("s9-lhs") && (s9lhs.value = params.get("s9-lhs"));
|
||||
params.get("s9-rhs") && (s9rhs.value = params.get("s9-rhs"));
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="margin: 1rem">spout: reverse-chron html pieces by <a href="https://terezi.pyrope.net">mehbark</a></h1>
|
||||
|
||||
<article id="s16">
|
||||
<h1><a href="#s16">#</a> binary search over the integers (todo)</h1>
|
||||
|
||||
<h2 id="s16num">0</h2>
|
||||
<p>low: <span id="s16low">?</span>, high: <span id="s16high">?</span></p>
|
||||
</article>
|
||||
|
||||
<article id="s15">
|
||||
<h1><a href="#s15">#</a> eva interface stuff style noodling</h1>
|
||||
|
||||
<div style="display: grid; background-color: black; filter: blur(0.5px) saturate(1.2); padding: 1rem; justify-items: center; align-items: center; aspect-ratio: 2/1;">
|
||||
<div style="background: repeating-linear-gradient(-45deg, red, red 0.99cm, transparent 1cm, transparent 2cm, red 2.01cm); filter: blur(2px) drop-shadow(0 0 1px red); grid-area: 1/1; width: 100%; height: 100%"></div>
|
||||
<div style="background-color: black; grid-area: 1/1; z-index: 1; width: 90%; height: 80%; text-align: center">
|
||||
<h1 style="color: red; font-weight: 900; filter: drop-shadow(0 0 2px red); font-size: 24pt; margin: 0;">EMERGENCY</h1>
|
||||
<p style="color: orange;filter: drop-shadow(0 0 2px orange);">bla bla stuff is happening i have finished the show but not eoe</p>
|
||||
<svg version="1.1"
|
||||
viewBox="0 0 300 100"
|
||||
style="display: block; height: 2cm; margin-inline: auto; margin-top: 1.5rem;"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.ok {
|
||||
filter: drop-shadow(0 0 3px orange);
|
||||
fill: orange;
|
||||
}
|
||||
|
||||
.bad {
|
||||
filter: drop-shadow(0 0 3px #fb1515);
|
||||
fill: #fb1515;
|
||||
}
|
||||
|
||||
.meh {
|
||||
filter: drop-shadow(0 0 3px #e35c1a);
|
||||
fill: #e35c1a;
|
||||
}
|
||||
</style>
|
||||
<defs>
|
||||
<svg id="box" viewBox="0 0 300 100">
|
||||
<path d="M 0,0 h 275 l 25,25 v 75 h -275 l -25,-25 Z" />
|
||||
<text x="0" y="0">yo</text>
|
||||
</svg>
|
||||
</defs>
|
||||
<use href="#box" class="ok" width="90" height="30" x="3" y="3" />
|
||||
<use href="#box" class="ok" width="90" height="30" x="3" y="36"/>
|
||||
<use href="#box" class="ok" width="90" height="30" x="3" y="69"/>
|
||||
<use href="#box" class="meh" width="90" height="30" x="95" y="3" />
|
||||
<use href="#box" class="meh" width="90" height="30" x="95" y="36"/>
|
||||
<use href="#box" class="ok" width="90" height="30" x="95" y="69"/>
|
||||
<use href="#box" class="bad" width="90" height="30" x="188" y="3" />
|
||||
<use href="#box" class="bad" width="90" height="30" x="188" y="36"/>
|
||||
<use href="#box" class="meh" width="90" height="30" x="188" y="69"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article id="s14">
|
||||
<h1><a href="#s14">#</a> fake book covers</h1>
|
||||
<p><a href="https://eggbugstestplace.jcink.net/index.php?showtopic=74">chorum thread</a>, i have an idea</p>
|
||||
<div id="s14-book-1">
|
||||
<h1>Suturing Spectra</h1>
|
||||
<h2>Case Studies in Chromatic Containment</h2>
|
||||
<div class="strip"></div>
|
||||
<p>Stanton Parker</p>
|
||||
<p class=series>Practical Anomalous Physics: Volume One</p>
|
||||
</div>
|
||||
<p>The original SCP logo was designed by far2, based on <a href="https://youtube.com/watch?v=AEbUZomoBpk">a free asset</a> from <a href="https://en.wikipedia.org/wiki/Adobe_Illustrator">Adobe Illustrator</a>'s "Mad Science" asset library, which in turn was based on the <a href="https://en.wikipedia.org/wiki/File:ESD-warning-symbol.svg">electrostatic discharge warning symbol</a>. The first high-resolution PNG version of the logo was made by Aelanna, based on the original SCP logo. <a href="https://commons.wikimedia.org/wiki/File:SCP_Foundation_(emblem).svg">SCP Foundation (emblem)</a>, <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode" rel="license">CC BY-SA 3.0</a>
|
||||
<style>
|
||||
#s14-book-1 {
|
||||
width: 6cm;
|
||||
height: 7.8cm;
|
||||
background: url(https://upload.wikimedia.org/wikipedia/commons/e/ec/SCP_Foundation_%28emblem%29.svg) #fffefd;
|
||||
background-size: 10cm;
|
||||
background-position: 2cm -0.3cm;
|
||||
background-repeat: no-repeat;
|
||||
color: #2c2c2c;
|
||||
//padding: 0.5cm 1cm;
|
||||
font-family: "Charter", charter, serif;
|
||||
outline: 0.2cm solid black;
|
||||
filter: blur(0.25px);
|
||||
}
|
||||
|
||||
/*
|
||||
#s14-book-1::before {
|
||||
backdrop-filter: blur(10px);
|
||||
content: "";
|
||||
display: block;
|
||||
position: relative;
|
||||
inset: 0;
|
||||
}
|
||||
*/
|
||||
|
||||
#s14-book-1 > h1 {
|
||||
font-size: 18pt;
|
||||
width: 7cm;
|
||||
margin-left: 0.4cm;
|
||||
padding-top: 0.4cm;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#s14-book-1 > h2 {
|
||||
font-size: 13pt;
|
||||
font-variant: italic;
|
||||
margin-left: 0.4cm;
|
||||
width: 4cm;
|
||||
margin-top: 0.4cm;
|
||||
margin-bottom: 0.3cm;
|
||||
}
|
||||
|
||||
#s14-book-1 > .strip {
|
||||
height: 1cm;
|
||||
background: linear-gradient(to right in hsl, #f00, #0f0, #000, #0ff, #00f, #f0f);
|
||||
}
|
||||
|
||||
#s14-book-1 > p {
|
||||
margin-left: 0.4cm;
|
||||
width: 2.5cm;
|
||||
font-size: 10pt;
|
||||
margin-top: 0.3cm;
|
||||
}
|
||||
|
||||
#s14-book-1 > .series {
|
||||
font-style: italic;
|
||||
width: 2cm;
|
||||
}
|
||||
</style>
|
||||
</article>
|
||||
|
||||
<article id="s13">
|
||||
<h1><a href="#s13">#</a> can i embed a godot game?</h1>
|
||||
<details><summary>of course</summary>
|
||||
<iframe src="https://terezi.pyrope.net/s13" width=300 height=300 title="basic asteroid game"></iframe>
|
||||
</article>
|
||||
|
||||
<article id="s12">
|
||||
<h1><a href="#s12">#</a> sπgot</h1>
|
||||
<h2>hey, that's almost a spout!</h2>
|
||||
<p>here's a π spigot from <a href="https://www.gavalas.dev/blog/spigot-algorithms-for-pi-in-python/">this blog post</a>.
|
||||
a while ago, i implemented one of the algorithms here in scheme. it was fun to get a megabyte of π, and i want you to be able to have a similar experience <span class=emoticon>:D</span>.
|
||||
this version is unproven, <a href="https://www.gavalas.dev/blog/spigot-algorithms-for-pi-in-python/#the-open-problem">as discussed in the original article</a>, buuuut <abbr title="i don't really care">idrc</abbr>.
|
||||
fair warning: especially with larger batch sizes, this is liable to freeze up the tab. tread carefully!
|
||||
</p>
|
||||
<pre id=s12-output style="overflow: auto; height: 36ch; width: 100%; word-break: break-all; white-space: pre-wrap;">
|
||||
3.</pre>
|
||||
<button onclick='
|
||||
if (this.interval) {
|
||||
clearInterval(this.interval);
|
||||
this.interval = null;
|
||||
this.innerText = "sπgot!";
|
||||
return;
|
||||
}
|
||||
this.innerText = "sτop!";
|
||||
function* gen() {
|
||||
let [q, r, t, i] = [1n, 180n, 60n, 2n];
|
||||
while (true) {
|
||||
let u = 3n*(3n*i+1n)*(3n*i+2n);
|
||||
let y = (q*(27n*i-12n)+5n*r)/(5n*t);
|
||||
yield y;
|
||||
[q, r, t, i] = [10n*q*i*(2n*i-1n), 10n*u*(q*(5n*i-2n)+r-y*t), t*u, i+1n];
|
||||
}
|
||||
}
|
||||
|
||||
let [output, digits, batch, error] = elems(12, "output digits batch error");
|
||||
let g = gen();
|
||||
g.next();
|
||||
this.interval = setInterval(() => {
|
||||
let n = +batch.value;
|
||||
let str = "";
|
||||
let digs = +digits.innerText;
|
||||
try {
|
||||
for (let i = 0; i < n; i++) {
|
||||
str += g.next().value;
|
||||
digs++;
|
||||
}
|
||||
} catch (e) {
|
||||
clearInterval(this.interval);
|
||||
this.interval = null;
|
||||
this.innerText = "error :[";
|
||||
error.innerText = e.toString();
|
||||
} finally {
|
||||
output.innerText += str;
|
||||
digits.innerText = digs;
|
||||
}
|
||||
}, 0);
|
||||
'>sπgot!</button> <span id=s12-digits style="font-family: monospace">1</span> digits in batches of <input id=s12-batch type=number min=1 max=100000 value=10></input> <p style="color: red" id=s12-error></span>
|
||||
<p>gotta say, it's really sweet working with native generators. not really necessary here, but elegant.
|
||||
bigints were the real hero, i almost discarded the idea before i remembered js had them <span class=emoticon>:P</span>
|
||||
<p>at around 2<sup>15</sup> digits, the bigints become too big to allocate, at least on my machine. lame!
|
||||
</article>
|
||||
|
||||
<article id="s11">
|
||||
<h1><a href="#s11">#</a> emanresu A π approximation</h1>
|
||||
<p>this is a geminic sequel to <a href="#s10">s10</a>, which does exist yet!
|
||||
<p>this technique is taken from <a href="https://codegolf.stackexchange.com/questions/275564/count-squares-in-my-pi-approximation">this code golf question</a>.
|
||||
i hope i can do it!
|
||||
<canvas id="s11-canvas" width=300 height=300></canvas><br>
|
||||
<input type=range id="s11-slider" min=0 max=12 value=0 onchange='
|
||||
let [canvas, slider, best] = elems(11, "canvas slider best");
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.clearRect(0, 0, 4113, 4113);
|
||||
|
||||
let steps = +slider.value;
|
||||
|
||||
let c = (x, y) => x*x + y*y <= 1;
|
||||
|
||||
let inside = 0;
|
||||
// why do all of the steps if we do not save work
|
||||
// for colors, fool!
|
||||
for (let i = steps; i >= 1; i--) {
|
||||
let side_len = 2**-i;
|
||||
let square_size = side_len**2;
|
||||
ctx.fillStyle = `hsl(${i.map(8, 1, 0, 360)}deg, 70%, 50%)`
|
||||
for (let x = 0; x < 1; x += side_len) {
|
||||
for (let y = 0; y < 1; y += side_len) {
|
||||
if (c(x + side_len, y)) {
|
||||
ctx.fillRect(x.map(0, 1, 0, 300), y.map(0, 1, 300, 0), 300/(2**i), 300/(2**i));
|
||||
if (i == steps) inside += square_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
best.innerText = inside * 4;
|
||||
'/> best guess: <span id="s11-best">idk</span>
|
||||
<p>i did it! not super efficiently, but it was fun. the slider goes up to 12, which is <em>really</em> pushing it, so exercise caution
|
||||
</article>
|
||||
|
||||
<article id="s10">
|
||||
<h1><a href="#s10">#</a> Monte Carlo π approximation</h1>
|
||||
<p>this is a prequel to <a href="#s11">s11</a>, which does exist yet!
|
||||
<p>a while ago, i made <a href="https://cohost.org/mehbark/post/5961356-mehbark-s-mini-progr">this cohost post</a> about approximating π,
|
||||
and i'd like to implement my favorite approach here</p>
|
||||
<canvas id="s10-canvas" width=314 height=314></canvas><br>
|
||||
<input id="s10-samples" type="number" min=1 value=1000> in batches of <input id="s10-batch" type="number" min=1 value=10> <button onclick='
|
||||
let [canvas, samples, inside, total, best, batch] = elems(10, "canvas samples inside total best batch");
|
||||
let n = +samples.value;
|
||||
let b = +batch.value;
|
||||
let [ins, tot] = [+inside.innerText, +total.innerText];
|
||||
if (!(n > 0)) {
|
||||
alert(`come on, ${n} samples?`);
|
||||
return;
|
||||
}
|
||||
let ctx = canvas.getContext("2d");
|
||||
setTimeout(function sample() {
|
||||
for (let i = 0; i < b; i++) {
|
||||
let x = Math.random();
|
||||
let y = Math.random();
|
||||
let win = x*x + y*y <= 1;
|
||||
ctx.fillStyle = win ? "#76a6e4" : "#ede";
|
||||
ctx.fillRect(x.map(0, 1, 0, 300), y.map(0, 1, 300, 0), 1, 1);
|
||||
|
||||
if (win) ins++;
|
||||
tot++;
|
||||
|
||||
if (!n--) break;
|
||||
}
|
||||
|
||||
inside.innerText = ins;
|
||||
total.innerText = tot;
|
||||
best.innerText = 4 * ins/tot;
|
||||
if (n > 0) setTimeout(sample, 0);
|
||||
}, 0);
|
||||
'>sample!</button><br>
|
||||
<p>current best guess: <span id="s10-inside">0</span>/<span id="s10-total">0</span> * 4 = <span id="s10-best">idk</span>
|
||||
<p>this is thoroughly ingrained in my brain, but i hope it's still fairly intuitive for others.
|
||||
i like how the boundary becomes more clear with more samples, it makes the accuracy more understandable <abbr title="in my opinion">imo</abbr>
|
||||
</article>
|
||||
|
||||
<article id="s9">
|
||||
<h1><a href="#s9">#</a> apropos of <a href="#s7">s7</a></h1>
|
||||
<p>i may not be stupid!
|
||||
<p>the technique as applied in <a href="#s6">s6</a> may be pointless, but, for a general equality, points that can move in two directions could actually be interesting!
|
||||
that might be here! in ! th efuture</p>
|
||||
<canvas id="s9-canvas" width=300 height=300></canvas><br>
|
||||
<input id="s9-lhs" value="x*x + y*y"> = <input id="s9-rhs" value="1"> <button onclick='
|
||||
if (this.innerText == "stop D:") {
|
||||
clearInterval(this.interval);
|
||||
this.innerText = "graph!";
|
||||
return;
|
||||
}
|
||||
this.innerText = "stop D:";
|
||||
let [lhs, rhs, canvas, samples] = elems(9, "lhs rhs canvas samples");
|
||||
let ctx = canvas.getContext("2d");
|
||||
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
|
||||
let f = eval(`(x, y) => {with (Math) {return abs((${lhs.value}) - (${rhs.value}))}}`);
|
||||
|
||||
let guys = [];
|
||||
for (let x = x0; x <= x1; x += (x1 - x0)/samples.value) {
|
||||
for (let y = y0; y <= y1; y += (y1 - y0)/samples.value) {
|
||||
guys.push({x, y, last: 100, r: Math.random()/10, t: Math.random()*6.28});
|
||||
}
|
||||
}
|
||||
let step = () => {
|
||||
for (let guy of guys) {
|
||||
let diff = f(guy.x, guy.y);
|
||||
if (guy.r < 0.01) guy.r = 0.01;
|
||||
if (diff > guy.last) {
|
||||
guy.r *= 0.5;
|
||||
guy.t += Math.random()/10;
|
||||
} else {
|
||||
guy.last = diff;
|
||||
guy.x += guy.r*Math.cos(guy.t);
|
||||
guy.y += guy.r*Math.sin(guy.t);
|
||||
guy.r *= 1.1;
|
||||
}
|
||||
if (diff > 0.1 && Math.random() > 0.1) guy.last = diff;
|
||||
}
|
||||
};
|
||||
let draw = () => {
|
||||
ctx.fillStyle = "#76a6e4";
|
||||
ctx.clearRect(0, 0, 1000, 1000);
|
||||
for (let {x, y, t} of guys) {
|
||||
ctx.fillStyle = `hsl(${t/6.28}turn 100% 60%)`;
|
||||
ctx.fillRect(x.map(x0, x1, 0, 300), y.map(y0, y1, 300, 0), 1, 1);
|
||||
}
|
||||
};
|
||||
|
||||
draw();
|
||||
// the stop button works now, so why limit steps?
|
||||
let steps = 1/0;
|
||||
this.interval = setInterval(function loop() {step(); draw(); if (steps-- <= 0) clearInterval(this.interval)}, 0)
|
||||
'>graph!</button> <input type=number id=s9-samples value=100></input> samples<sup>2</sup>
|
||||
<p>okay dang this looks freaking great. hue is based on angle, look at the code! i love this
|
||||
<p>i have decided that instead of making it more accurate, i will leave it at this place of looking very cool
|
||||
</article>
|
||||
|
||||
<article id="s8">
|
||||
<h1><a href="#s8">#</a> s(oko)8(an)</h1>
|
||||
<p>i never got anywhere with width-hacking on cohost, but can i implement a normal game in programming language‽
|
||||
<p><abbr title="work in progress">WIP</abbr>! functional! really needs undo though!</p>
|
||||
<p>see <a href="http://www.sokobano.de/wiki/index.php?title=Level_format">here</a> if you want to know the #lingo</p>
|
||||
<textarea id="s8-input" rows=20 style="width: 100%; padding: 0; resize: vertical">
|
||||
# #
|
||||
# # #
|
||||
# # #
|
||||
# # #
|
||||
# # #
|
||||
# # #
|
||||
# # #
|
||||
|
||||
##########
|
||||
#........####
|
||||
# $$$$$$$# #
|
||||
#.$......# #
|
||||
# $$$$$$ # #
|
||||
#......$+# #
|
||||
#$$$$$$$ # #
|
||||
# ####
|
||||
##########
|
||||
"Steaming Hot" by David Buchweitz</textarea>
|
||||
<div class="controls"><button id="s8-l">←</button><button id="s8-u">↑</button><button id="s8-d">↓</button><button id="s8-r">→</button></div>
|
||||
<div>winning? <span id="s8-winning">no.</span> moves? <span id="s8-moves"></span></div>
|
||||
<script>
|
||||
let [input, l, u, d, r, winning, moves] = elems(8, "input l u d r winning moves");
|
||||
let step = (dx, dy, c) => () => {
|
||||
let puzzle = input.value.split("\n");
|
||||
let max_width = puzzle.reduce((m, s) => Math.max(m, s.length), 0);
|
||||
puzzle = puzzle.map(s => s.padEnd(max_width).split(""));
|
||||
|
||||
let in_bounds = (x, y) => 0 <= x && x < max_width && 0 <= y && y < puzzle.length;
|
||||
let at = (x, y) => {
|
||||
let c = in_bounds(x, y) ? puzzle[y][x] : "#";
|
||||
let out = {wall: false, player: false, goal: false, box: false, c, x, y};
|
||||
switch (c) {
|
||||
case "*":
|
||||
out.goal = true;
|
||||
case "$":
|
||||
out.box = true;
|
||||
break;
|
||||
|
||||
case "+":
|
||||
out.goal = true;
|
||||
case "@":
|
||||
out.player = true;
|
||||
break;
|
||||
|
||||
case "#":
|
||||
out.wall = true;
|
||||
break;
|
||||
case ".":
|
||||
out.goal = true;
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
};
|
||||
let open = sq => !sq.wall && !sq.box;
|
||||
let set = (x, y, c) => puzzle[y][x] = c;
|
||||
|
||||
let px, py;
|
||||
for (let y = 0; y < puzzle.length; y++) {
|
||||
for (let x = 0; x < max_width; x++) {
|
||||
if (!at(x, y).player) continue;
|
||||
px = x;
|
||||
py = y;
|
||||
}
|
||||
}
|
||||
if (typeof px == "undefined") {
|
||||
winning.innerText = "THERE ISN'T A PLAYER DOOFUS";
|
||||
return;
|
||||
}
|
||||
|
||||
let [p, m] = [at(px, py), at(px + dx, py + dy)];
|
||||
|
||||
if (open(m)) {
|
||||
set(px, py, p.goal ? "." : " ");
|
||||
set(m.x, m.y, m.goal ? "+" : "@");
|
||||
moves.innerText += c;
|
||||
} else if (m.box) {
|
||||
let m2 = at(px + 2*dx, py + 2*dy);
|
||||
if (open(m2)) {
|
||||
moves.innerText += c;
|
||||
set(px, py, p.goal ? "." : " ");
|
||||
set(m.x, m.y, m.goal ? "+" : "@");
|
||||
set(m2.x, m2.y, m2.goal ? "*" : "$");
|
||||
}
|
||||
}
|
||||
|
||||
input.value = puzzle.map(r => r.join("")).join("\n");
|
||||
|
||||
let won = !puzzle.join().includes("$");
|
||||
winning.innerText = won ? "yes!" : "no.";
|
||||
};
|
||||
|
||||
l.onclick = step(-1, 0, "l");
|
||||
u.onclick = step( 0, -1, "u");
|
||||
d.onclick = step( 0, 1, "d");
|
||||
r.onclick = step( 1, 0, "r");
|
||||
</script>
|
||||
|
||||
</article>
|
||||
<article id="s7">
|
||||
<h1><a href="#s7">#</a> i may be stupid</h1>
|
||||
<p>i realized something when talking about <a href="#s7">s7</a>: i may be stupid.
|
||||
first of all, it's worth understanding that <a href="#s7">s7</a> is actually my third go at this technique,
|
||||
the first time was on <code>about:blank</code> in canvas, and the second time was in <a href="https://www.lexaloffle.com/picotron.php">picotron</a>.</p>
|
||||
<canvas id="s7-canvas" width=300 height=300></canvas><br>
|
||||
<input id="s7-input" value="sin(x)"> <button id="s7-graph" onclick='
|
||||
let ctx = document.getElementById("s7-canvas").getContext("2d");
|
||||
ctx.fillStyle = "#76a6e4";
|
||||
|
||||
let f = eval(`x => {with (Math) {return ${document.getElementById("s7-input").value}}}`);
|
||||
let deriv = f => x => (f(x + 1e-6) - f(x))/1e-6;
|
||||
let order = +document.getElementById("s7-deriv").innerText;
|
||||
for (let i = 0; i < order; i++) f = deriv(f);
|
||||
|
||||
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
|
||||
ctx.clearRect(0, 0, 1000, 1000);
|
||||
for (let x = x0; x <= x1; x += (x1 - x0)/1200) {
|
||||
ctx.fillRect(x.map(x0, x1, 0, 300), f(x).map(y0, y1, 300, 0), 1, 1);
|
||||
};
|
||||
'>graph!</button> <button id="s7-deriv" onclick='
|
||||
this.innerText++;
|
||||
let n = +this.innerText;
|
||||
document.getElementById("s7-th").innerText = n > 10 && n < 20 ? "th" : ["th", "st", "nd", "rd", ...Array(6).fill("th")][n%10];
|
||||
document.getElementById("s7-graph").click();
|
||||
'>0</button><span id="s7-th">th</span> derivative
|
||||
<p>i just have to graph the function! the other method just looks cooler and is less reliable
|
||||
<p>here's the important part of the code: <code>ctx.fillRect(x.map(x0, x1, 0, 300), f(x).map(y0, y1, 300, 0), 1, 1)</code>
|
||||
<p>i also added approximated derivatives for fun <span class=emoticon>:D</span>
|
||||
</article>
|
||||
<article id="s6">
|
||||
<h1><a href="#s6">#</a> a very fun approach to graphing</h1>
|
||||
<p>now, this is hardly “production-grade,” but it is fun. first play, then talk.</p>
|
||||
<canvas id="s6-canvas" width=300 height=300></canvas><br>
|
||||
<input id="s6-input" value="sin(x)" onkeyup='
|
||||
let ctx = document.getElementById("s6-canvas").getContext("2d");
|
||||
ctx.fillStyle = "#76a6e4";
|
||||
let f = eval(`(x, y) => {with (Math) {return y - (${this.value})}}`);
|
||||
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
|
||||
let guys = [];
|
||||
for (let x = x0; x <= x1; x += (x1 - x0)/600) {
|
||||
guys.push({x, y: 0, dy: 0.1, lastDiff: 1});
|
||||
};
|
||||
let draw = () => {
|
||||
ctx.clearRect(0, 0, 1000, 1000);
|
||||
for (let guy of guys) {
|
||||
ctx.fillRect(guy.x.map(x0, x1, 0, 300), guy.y.map(y0, y1, 0, 300), 1, 1);
|
||||
}
|
||||
};
|
||||
let step = () => {
|
||||
for (let guy of guys) {
|
||||
let diff = Math.abs(f(guy.x, guy.y + guy.dy));
|
||||
if (Math.abs(guy.dy) < 0.005) guy.dy = 0.01 * (Math.random() - 0.5);
|
||||
if (diff > guy.lastDiff) {
|
||||
guy.dy = -guy.dy/1.5;
|
||||
} else {
|
||||
guy.y += guy.dy;
|
||||
guy.dy = guy.dy * 2;
|
||||
guy.lastDiff = diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
let total_diff = () => guys.reduce((sum, g) => sum + g.lastDiff, 0);
|
||||
let delay = 100;
|
||||
draw();
|
||||
setTimeout(function frame() {
|
||||
step();
|
||||
draw();
|
||||
console.log(total_diff());
|
||||
if (total_diff() > 1) window.setTimeout(frame, delay);
|
||||
}, delay);
|
||||
'>
|
||||
<p>now this is a very janky demo for many, many reasons, but there's a kernel of an idea here that's very cool: moving a bunch of things independently to do a big thing.
|
||||
<p>some ideas to make this suck less:
|
||||
<ul>
|
||||
<li>fix the horrendous onchange behavior to actually stop the previous attempt
|
||||
<li>use <a href="https://en.wikipedia.org/wiki/Newton%27s_method">Newton's method</a> with an approximated derivative
|
||||
<li>tweak parameters
|
||||
</ul>
|
||||
<p>now look at the code!
|
||||
</article>
|
||||
<article id="s5">
|
||||
<h1><a href="#s5">#</a> why spout</h1>
|
||||
<p>i have <a href="https://b.pyrope.net">my blog</a> for when i want to make really legit-looking posts.
|
||||
it's made with <a href="https://docs.racket-lang.org/pollen/">pollen</a>, which is great, and i can make even the most lame posts (currently all of the posts) look very nice.
|
||||
however, there's a whole build system, the book is a program after all, a lot of things have to happen to make a post there happen. so i wanted something smaller. micro, if you will.
|
||||
hence, spout! i just write some html (which, tbh, i kinda prefer to markdown) with no restrictions. ssh, edit file, save file, done. it's great! it <em>really</em> needs an RSS feed, though…
|
||||
</article>
|
||||
<article id="s4">
|
||||
<h1><a href="#s4">#</a> oh i'm totally going to</h1>
|
||||
<canvas width=20 height=20 style="outline: 1px solid var(--fg)"></canvas>
|
||||
<button onclick="
|
||||
let ctx = document.querySelector('#s4 > canvas').getContext('2d');
|
||||
ctx.fillStyle = `rgb(${Math.random()*256}, ${Math.random()*256}, ${Math.random()*256})`;
|
||||
ctx.fillRect(Math.floor(Math.random()*20), Math.floor(Math.random()*20), 1, 1);
|
||||
">pixel it</button>
|
||||
</article>
|
||||
<article id="s3">
|
||||
<h1><a href="#s3">#</a> this is, obviously, just an html page</h1>
|
||||
<p>i can do <span style="color: transparent; background-clip: text; background: linear-gradient(to right, #008282, #005682); -webkit-background-clip: text;">whatever</span> i want!
|
||||
heck, i could even put <button onclick="this.innerText++; document.getElementById('s3-s').innerText = 's';">1</button> javascript<span id="s3-s"></span>
|
||||
</article>
|
||||
<article id="s2">
|
||||
<h1><a href="#s2">#</a> hello, again</h1>
|
||||
<p>this is the second
|
||||
<p>also easy to write!
|
||||
<p>note the # links
|
||||
</article>
|
||||
<article id="s1">
|
||||
<h1><a href="#s1">#</a> hello, spout</h1>
|
||||
<p>this is the first spout post
|
||||
<p>it is easy to write
|
||||
<p>that is important!
|
||||
</article>
|
||||
<p>Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License.</p>
|
||||
<p>i hope that's sufficient? you can use my stuff</p>
|
||||
<!-- woo spooky secret
|
||||
<article id="s0">
|
||||
<h1><a href="#s0">#</a> title</h1>
|
||||
</article>
|
||||
-->
|
||||
</body>
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
title: What is twopn?
|
||||
description: How I made a new website without exploding
|
||||
tags: post,short,meta
|
||||
date: 2026-01-24 18:00:00
|
||||
---
|
||||
|
||||
twopn is new website and stuff [lisannne](https://lisanne.gay) and [poly wolf](https://wolfgirl.dev/blog)
|
||||
|
|
|
|||