import everything!
This commit is contained in:
commit
ac21716d38
120 changed files with 9953 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
media
|
||||
private
|
36
.pnpm-debug.log
Normal file
36
.pnpm-debug.log
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"0 debug pnpm:scope": {
|
||||
"selected": 1
|
||||
},
|
||||
"1 debug pnpm:package-manifest": {
|
||||
"initial": {},
|
||||
"prefix": "/home/zestylemonade/content"
|
||||
},
|
||||
"2 debug pnpm:context": {
|
||||
"currentLockfileExists": false,
|
||||
"storeDir": "/home/zestylemonade/.pnpm-store/v3",
|
||||
"virtualStoreDir": "/home/zestylemonade/content/node_modules/.pnpm"
|
||||
},
|
||||
"3 debug pnpm:stage": {
|
||||
"prefix": "/home/zestylemonade/content",
|
||||
"stage": "resolution_started"
|
||||
},
|
||||
"4 error pnpm": {
|
||||
"code": "ERR_PNPM_FETCH_404",
|
||||
"hint": "xterm-addot-fit is not in the npm registry, or you have no permission to fetch it.\n\nNo authorization header was set for the request.",
|
||||
"request": {
|
||||
"url": "https://registry.npmjs.org/xterm-addot-fit"
|
||||
},
|
||||
"response": {
|
||||
"size": 0
|
||||
},
|
||||
"pkgName": "xterm-addot-fit",
|
||||
"pkgsStack": [],
|
||||
"err": {
|
||||
"name": "pnpm",
|
||||
"message": "GET https://registry.npmjs.org/xterm-addot-fit: Not Found - 404",
|
||||
"code": "ERR_PNPM_FETCH_404",
|
||||
"stack": "pnpm: GET https://registry.npmjs.org/xterm-addot-fit: Not Found - 404\n at RetryOperation._fn (/usr/lib/node_modules/pnpm/dist/pnpm.cjs:85709:19)\n at processTicksAndRejections (node:internal/process/task_queues:96:5)"
|
||||
}
|
||||
}
|
||||
}
|
8
.well-known/matrix/client
Normal file
8
.well-known/matrix/client
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"m.homeserver": {
|
||||
"base_url": "https://celery.eu.org"
|
||||
},
|
||||
"org.matrix.msc3575.proxy": {
|
||||
"url": "https://syncv3.celery.eu.org"
|
||||
}
|
||||
}
|
3
.well-known/matrix/server
Normal file
3
.well-known/matrix/server
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"m.server": "celery.eu.org:443"
|
||||
}
|
4
.well-known/mta-sts.txt
Normal file
4
.well-known/mta-sts.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
version: STSv1
|
||||
mode: enforce
|
||||
max_age: 86400
|
||||
mx: celery.eu.org
|
BIN
adderall.jpg
Normal file
BIN
adderall.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 193 KiB |
52
adderall.md
Normal file
52
adderall.md
Normal file
|
@ -0,0 +1,52 @@
|
|||
::: header
|
||||
# adderall
|
||||
:::
|
||||
::: section
|
||||
I was prescribed adderall a few years ago, but stopped because of
|
||||
the side effects (trouble sleeping and bad dreams from what I can
|
||||
remember). Fast forward to about a month ago, and I was having a lot of
|
||||
trouble focusing. I stumbled upon the old adderall pills, and because
|
||||
nothing can ever go wrong, took them.
|
||||
|
||||
The effects were great, so I went to a psychiatrist to try to get a
|
||||
prescription. I was successful and and got some new pills.
|
||||
|
||||
![A photograph of three adderall pills. Two are oblong, with the one on
|
||||
the right being circular.](adderall.jpg)
|
||||
|
||||
From left to right: old pills, new pills, and extra bonus pills (pure
|
||||
amphetamine salts) that aren't relevant. The old pills have "adderall
|
||||
xr" printed on them (are brand name) and the new ones say "ELI-511"
|
||||
(manufactured from "elite laboratories"). Both of the doses are are
|
||||
10mg. The new pills were clearly visually different, but I assumed that
|
||||
adderall was tightly regulated so they'd have the same effect.
|
||||
|
||||
The effects were *noticably* different. I tried taking the new pills one
|
||||
day then the old pills on another, and it was almost like two different
|
||||
medications.
|
||||
|
||||
I did a bit of precursory research to see if it was only me and found
|
||||
some people grumbling about how it's a tiktok trend and mass hysteria,
|
||||
except that I have never used tiktok in my life.
|
||||
|
||||
Searching for the brand name, it seems
|
||||
like there are recurring problems with elite labs
|
||||
([one](https://rd.celery.eu.org/r/ADHD/comments/164zo38/elite_pharmaceutical_adderall/),
|
||||
[two](https://rd.celery.eu.org/r/ADHD/comments/15tzbkk/generic_adderall_xr_from_elite_laboratories/),
|
||||
[three](https://rd.celery.eu.org/r/ADHD/comments/cwgshb/generic_adderall_switch_teva_to_elite/)).
|
||||
The descriptions (especially "it feels like sleep deprevation" and "it
|
||||
makes me jittery") matches my experience pretty well! Every once in a
|
||||
while, I felt like I was going to have a heart attack.
|
||||
|
||||
## going further
|
||||
|
||||
todo: self blinded trials
|
||||
|
||||
## notes
|
||||
|
||||
to look at:
|
||||
|
||||
- https://news.ycombinator.com/item?id=35111061
|
||||
- https://en.wikipedia.org/wiki/Adderall
|
||||
- https://www.npr.org/sections/health-shots/2019/05/12/722216512/bottle-of-lies-exposes-the-dark-side-of-the-generic-drug-boom
|
||||
:::
|
76
adhd.html
Normal file
76
adhd.html
Normal file
|
@ -0,0 +1,76 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8" />
|
||||
<title>adhd</title>
|
||||
<link rel="stylesheet" href="/assets/style2.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>adhd</h1>
|
||||
</header>
|
||||
<section>
|
||||
<p>
|
||||
It's not overstimulation, it's <em>under</em>stimulation. Everything else is
|
||||
always more interesting than the thing you're currently doing. That link
|
||||
is more interesting than the tab I'm looking at, and now I have 279 (at
|
||||
the time of writing) tabs open. That hobby is more interesting than what
|
||||
I'm doing, and now have have 30 hobbies and suck at all of them. I have
|
||||
something important tomorrow, but there's 100 things more interesting
|
||||
right now. I get bored after approximately ten seconds.
|
||||
</p>
|
||||
<p>
|
||||
Normal people get bored and distracted too, but the difference is
|
||||
this is chronic and is always on and can cause incredibly absurd or
|
||||
at least interesting results over the long term. If there's a way
|
||||
to get stimulation, adhd people will try it. For example: complex
|
||||
music (ie. breakcore, dnb, psytrance), strong food flavors, doing
|
||||
random bullshit and seeing what happens, and maybe some masochistic
|
||||
tendancies. But once it becomes the new normal, it doesn't work as well;
|
||||
the default is to be understimulated.
|
||||
</p>
|
||||
<p>
|
||||
The task of focusing on things is like a solid brick wall, but mental
|
||||
instead of physical. Some people don't think it exists, or that I'm
|
||||
making it up. People who do want to help usually can't, since they don't
|
||||
really understand having adhd. Useless advice is ubiquitous: "That solid
|
||||
brick wall doesn't really exist!" or "Use your inner strength to break
|
||||
through the solid brick wall!" or "I did xyz to reach my goal behind
|
||||
this distinct lack of solid brick wall!" or "Just do the thing lol".
|
||||
</p>
|
||||
<p>
|
||||
Some people like natural methods to help with it, such as exercise or
|
||||
meditation. It's certainly possible to scale the solid brick wall, and
|
||||
get better at it over time. However, I'd rather take the easy way out
|
||||
and take what's effectively a magical pill that removes this pain from
|
||||
my life (adderall). I'm still not sure if adhd has any nice benefit,
|
||||
or if its a completely waste of time; "hyperfocus" is nice, but honestly
|
||||
I'd rather be able to focus normally so I don't lose track of time.
|
||||
</p>
|
||||
<p>
|
||||
At this point, it's probably a good idea to declare attention bankrupcy
|
||||
and close every tab and start fresh. I probably won't though, since I
|
||||
don't like closing unread tabs.
|
||||
</p>
|
||||
<blockquote>
|
||||
When focus is precious and slippery, willpower and energy become rare
|
||||
and valuable resources.
|
||||
</blockquote>
|
||||
<p>Some other neat side effects</p>
|
||||
<ul>
|
||||
<li>
|
||||
My memory is broken. I remember some things perfectly but forget other things within seconds.
|
||||
</li>
|
||||
<li>
|
||||
I can starve or get dehydrated by accident by forgetting to eat/drink
|
||||
</li>
|
||||
<li>
|
||||
Adderall makes me shit a lot for some reason? It seems to happen to a
|
||||
lot of people, but nlm doesn't have anything. If anyone knows, please
|
||||
tell me <!-- i'm reachable at @tezlm:celery.eu.org on matrix and
|
||||
ZestyLemonade#1012 on discord. yup, i still have a numeric username -->
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
55
adhd.md
Normal file
55
adhd.md
Normal file
|
@ -0,0 +1,55 @@
|
|||
::: header
|
||||
# adhd
|
||||
:::
|
||||
|
||||
::: section
|
||||
It's not overstimulation, it's *under*stimulation. Everything else is
|
||||
always more interesting than the thing you're currently doing. That link
|
||||
is more interesting than the tab I'm looking at, and now I have 279 (at
|
||||
the time of writing) tabs open. That hobby is more interesting than what
|
||||
I'm doing, and now have have 30 hobbies and suck at all of them. I have
|
||||
something important tomorrow, but there's 100 things more interesting
|
||||
right now. I get bored after approximately ten seconds.
|
||||
|
||||
Normal people get bored and distracted too, but the difference is
|
||||
this is chronic and is always on and can cause incredibly absurd or
|
||||
at least interesting results over the long term. If there's a way
|
||||
to get stimulation, adhd people will try it. For example: complex
|
||||
music (ie. breakcore, dnb, psytrance), strong food flavors, doing
|
||||
random bullshit and seeing what happens, and maybe some masochistic
|
||||
tendancies. But once it becomes the new normal, it doesn't work as well;
|
||||
the default is to be understimulated.
|
||||
|
||||
The task of focusing on things is like a solid brick wall, but mental
|
||||
instead of physical. Some people don't think it exists, or that I'm
|
||||
making it up. People who do want to help usually can't, since they don't
|
||||
really understand having adhd. Useless advice is ubiquitous: "That solid
|
||||
brick wall doesn't really exist!" or "Use your inner strength to break
|
||||
through the solid brick wall!" or "I did xyz to reach my goal behind
|
||||
this distinct lack of solid brick wall!" or "Just do the thing lol".
|
||||
|
||||
Some people like natural methods to help with it, such as exercise or
|
||||
meditation. It's certainly possible to scale the solid brick wall, and
|
||||
get better at it over time. However, I'd rather take the easy way out
|
||||
and take what's effectively a magical pill that removes this pain from
|
||||
my life (adderall). I'm still not sure if adhd has any nice benefit,
|
||||
or if its a completely waste of time; "hyperfocus" is nice, but honestly
|
||||
I'd rather be able to focus normally so I don't lose track of time.
|
||||
|
||||
At this point, it's probably a good idea to declare attention bankrupcy
|
||||
and close every tab and start fresh. I probably won't though, since I
|
||||
don't like closing unread tabs.
|
||||
|
||||
> When focus is precious and slippery, willpower and energy become rare
|
||||
> and valuable resources.
|
||||
|
||||
Some other neat side effects
|
||||
|
||||
- My memory is broken. I remember some things perfectly but forget other
|
||||
things within seconds.
|
||||
- I can starve or get dehydrated by accident by forgetting to eat/drink
|
||||
- Adderall makes me shit a lot for some reason? It seems to happen to a
|
||||
lot of people, but nlm doesn't have anything. If anyone knows, please
|
||||
tell me <!-- i'm reachable at @tezlm:celery.eu.org on matrix and
|
||||
ZestyLemonade#1012 on discord. yup, i still have a numeric username -->
|
||||
:::
|
6
assets/code.css
Normal file
6
assets/code.css
Normal file
|
@ -0,0 +1,6 @@
|
|||
.hljs-number, .hljs-literal { color: #ff9e64; }
|
||||
.hljs-string { color: #9ece6a; }
|
||||
.hljs-attr { color: #7dcfff; }
|
||||
.hljs-keyword { color: #bb9af7; }
|
||||
.hljs-comment { color: #565f89; }
|
||||
.hljs-built_in { color: #e0af68; }
|
28
assets/directory.css
Normal file
28
assets/directory.css
Normal file
|
@ -0,0 +1,28 @@
|
|||
table {
|
||||
width: 100%;
|
||||
font-family: ui-monospace, "Segoe UI Mono", "Source Code Pro", monospace;
|
||||
}
|
||||
|
||||
table td:nth-child(1), table th:nth-child(1) {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table td:nth-child(2), table th:nth-child(2),
|
||||
table td:nth-child(3), table th:nth-child(3) {
|
||||
width: auto;
|
||||
text-align: right;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
table td:nth-child(3), table th:nth-child(3) {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
.git {
|
||||
padding: 1em;
|
||||
border: solid #41ead4 2px;
|
||||
border-radius: 4px;
|
||||
background: #41ead422;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
21
assets/essay.css
Normal file
21
assets/essay.css
Normal file
|
@ -0,0 +1,21 @@
|
|||
@font-face {
|
||||
font-family: "times"
|
||||
src: url("/assets/fonts/TimesNewerRoman-Regular.otf");
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: "times" !important;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
body {
|
||||
max-width: 550px;
|
||||
padding-top: 2em;
|
||||
background: #fdfdfd;
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4361ee;
|
||||
}
|
||||
|
BIN
assets/fonts/TimesNewerLicense.pdf
Normal file
BIN
assets/fonts/TimesNewerLicense.pdf
Normal file
Binary file not shown.
BIN
assets/fonts/TimesNewerRoman-Bold.otf
Normal file
BIN
assets/fonts/TimesNewerRoman-Bold.otf
Normal file
Binary file not shown.
BIN
assets/fonts/TimesNewerRoman-BoldItalic.otf
Normal file
BIN
assets/fonts/TimesNewerRoman-BoldItalic.otf
Normal file
Binary file not shown.
BIN
assets/fonts/TimesNewerRoman-Italic.otf
Normal file
BIN
assets/fonts/TimesNewerRoman-Italic.otf
Normal file
Binary file not shown.
BIN
assets/fonts/TimesNewerRoman-Regular.otf
Normal file
BIN
assets/fonts/TimesNewerRoman-Regular.otf
Normal file
Binary file not shown.
26
assets/index.css
Normal file
26
assets/index.css
Normal file
|
@ -0,0 +1,26 @@
|
|||
canvas {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
main {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
#pre {
|
||||
background: transparent;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#main {
|
||||
font-family: monospace;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
68
assets/index.js
Normal file
68
assets/index.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
// the cool spinning circles on index.html
|
||||
const canvas = document.getElementById("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const rnd = (n) => Math.floor(Math.random() * n);
|
||||
const colors = ["#f0d644", "#63eebe", "#9e4adf"]; // i like neon
|
||||
const points = [];
|
||||
let time = 0;
|
||||
|
||||
// handle page resizes without ruining everything
|
||||
function resize() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
ctx.width = canvas.width;
|
||||
ctx.height = canvas.height;
|
||||
}
|
||||
|
||||
// math moment
|
||||
function rotation(point) {
|
||||
return point.rot + time * point.speed;
|
||||
}
|
||||
|
||||
function length(point) {
|
||||
return Math.min(time * point.speed, point.speed * 4);
|
||||
}
|
||||
|
||||
function arc(point) {
|
||||
const angle = rotation(point);
|
||||
return [angle, angle + length(point)];
|
||||
}
|
||||
|
||||
// initialize the canvas
|
||||
function init() {
|
||||
resize();
|
||||
window.addEventListener("resize", resize);
|
||||
|
||||
for (let i = 0; i < 10 + rnd(4); i++) {
|
||||
points.push({
|
||||
color: colors[rnd(colors.length)],
|
||||
radius: Math.random() * 600 + 300,
|
||||
speed: Math.random() / 10 + 0.1,
|
||||
rot: Math.random() * 2 * Math.PI,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// the heart and soul of the circles
|
||||
function anim() {
|
||||
// center points
|
||||
const cx = ctx.width / 2;
|
||||
const cy = ctx.height / 2;
|
||||
|
||||
ctx.clearRect(0, 0, ctx.width, ctx.height);
|
||||
ctx.globalAlpha = time / 3; // fade in
|
||||
ctx.lineWidth = 4;
|
||||
|
||||
for (let point of points) {
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = point.color;
|
||||
ctx.arc(cx, cy, point.radius, ...arc(point));
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
time += 0.01;
|
||||
setTimeout(anim, 1000 / 60);
|
||||
}
|
||||
|
||||
init();
|
||||
setTimeout(anim, 1000);
|
133
assets/index2.js
Normal file
133
assets/index2.js
Normal file
|
@ -0,0 +1,133 @@
|
|||
const pre = document.getElementById("main");
|
||||
|
||||
// the cool spinning circles on index.html
|
||||
const rnd = (n) => Math.floor(Math.random() * n);
|
||||
const points = [];
|
||||
let time = 0;
|
||||
let charRows, charCols, charHeight;
|
||||
|
||||
// handle page resizes without ruining everything
|
||||
function resize() {
|
||||
const canvas = new OffscreenCanvas(100, 100);
|
||||
const context = canvas.getContext("2d");
|
||||
context.font = getComputedStyle(pre).font;
|
||||
const measured = context.measureText("x");
|
||||
charHeight = measured.fontBoundingBoxAscent + 5;
|
||||
charRows = Math.floor((window.innerHeight) / charHeight);
|
||||
charCols = Math.floor((window.innerWidth - 5) / measured.width);
|
||||
}
|
||||
|
||||
const shades = " .:=+*#%".split("");
|
||||
// const shades = "01234567".split("");
|
||||
|
||||
const shaders = [
|
||||
// stripes
|
||||
(t, x, y) => {
|
||||
return shades[Math.floor(Math.abs((x * t / 30) + (y * t / 15)) * t / 10) % 8]
|
||||
},
|
||||
|
||||
// circles
|
||||
(t, x, y) => {
|
||||
return shades[Math.floor(Math.sqrt(x ** 2 + y ** 2) * (t / 10)) % 8]
|
||||
},
|
||||
|
||||
// mandelbrot
|
||||
(t, x, y) => {
|
||||
const scale = 20000 / (t + 100) ** 2;
|
||||
let x0 = x * scale - .803, y0 = y * scale - .167, x1 = 0, y1 = 0, i = 0;
|
||||
for (; i < 100 && x1 ** 2 + y1 ** 2 <= 2 ** 2; i++) {
|
||||
const tmp = x1 ** 2 - y1 ** 2 + x0;
|
||||
y1 = 2 * x1 * y1 + y0;
|
||||
x1 = tmp;
|
||||
}
|
||||
return shades[Math.floor(i) % 8];
|
||||
},
|
||||
|
||||
(t, x, y) => {
|
||||
const xs = x * t / 3;
|
||||
const ys = y * t / 3;
|
||||
return shades[Math.floor(Math.abs((xs % ys || 0) - (ys % xs || 0))) % 8]
|
||||
},
|
||||
|
||||
(t, x, y) => {
|
||||
const s = ((x / y + t / 10) & 1 / y & 1) && y > 0;
|
||||
return shades[Math.floor(s) % 8]
|
||||
},
|
||||
|
||||
(t, x, y) => {
|
||||
return shades[(Math.cos(50*Math.sin((y)/(x))+5*(t/30))+1)*4<<0];
|
||||
},
|
||||
|
||||
// FIXME: broken on some screen resolutions
|
||||
// (t, x, y) => {
|
||||
// const rows = [
|
||||
// " __ ",
|
||||
// " ________ / /__ _______ __ ___ __ __ ____ _________ _",
|
||||
// " / ___/ _ \\/ / _ \\/ ___/ / / // _ \\/ / / // __ \\/ ___/ __ `/",
|
||||
// "/ /__/ __/ / __/ / / /_/ // __/ /_/ // /_/ / / / /_/ / ",
|
||||
// "\\___/\\___/_/\\___/_/ \\__, (_)___/\\__,_(_)____/_/ \\__, / ",
|
||||
// " /____/ /____/ ",
|
||||
// ];
|
||||
// const tween = Math.sin(t / 30 + x * 2) * 3;
|
||||
// const ch = rows[Math.round(tween + y * (charRows / 2)) + (rows.length / 2)]?.[Math.round(x * (charCols / 2)) + rows[0].length / 2];
|
||||
// return ch || " ";
|
||||
// },
|
||||
];
|
||||
|
||||
// const shader = shaders[Math.random() * shaders.length << 0];
|
||||
const shader = shaders[2];
|
||||
|
||||
function shade(x, y) {
|
||||
return shader(
|
||||
time,
|
||||
(x / (charCols / 2)) - 1,
|
||||
(y / (charRows / 2)) - 1,
|
||||
);
|
||||
}
|
||||
|
||||
const rows = [];
|
||||
function draw() {
|
||||
if (rows.length !== charRows) {
|
||||
while (rows.length) rows.pop().remove();
|
||||
for (let i = 0; i < charRows; i++) {
|
||||
const el = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||||
el.setAttribute("x", 5);
|
||||
el.setAttribute("y", i * charHeight + charHeight);
|
||||
el.setAttribute("fill", "grey");
|
||||
el.style.fontSize = "16px";
|
||||
el.style.whiteSpace = "pre";
|
||||
el.textContent = "you are at celery.eu.org";
|
||||
rows.push(el);
|
||||
pre.append(el);
|
||||
}
|
||||
}
|
||||
|
||||
for (let y = 0; y < charRows; y++) {
|
||||
let buf = "";
|
||||
for (let x = 0; x < charCols; x++) {
|
||||
buf += shade(x, y);
|
||||
}
|
||||
rows[y].textContent = buf;
|
||||
}
|
||||
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
function init() {
|
||||
resize();
|
||||
window.addEventListener("resize", resize);
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
points.push({
|
||||
shade: "celry"[Math.floor(Math.random() * 5)],
|
||||
radius: Math.random() * 600 + 300,
|
||||
speed: Math.random() / 10 + 0.1,
|
||||
rot: Math.random() * 2 * Math.PI,
|
||||
});
|
||||
}
|
||||
|
||||
draw();
|
||||
}
|
||||
|
||||
init();
|
||||
setInterval(() => time++, 1000 / 60);
|
104
assets/read.css
Normal file
104
assets/read.css
Normal file
|
@ -0,0 +1,104 @@
|
|||
body {
|
||||
background: #fdfdfd;
|
||||
color: #333333;
|
||||
font: 20px/1.6 Georgia, "Times New Roman", serif;
|
||||
padding: 2em;
|
||||
margin: 0 auto;
|
||||
max-width: 650px;
|
||||
}
|
||||
|
||||
input {
|
||||
box-sizing: border-box;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
margin: 1em 0 4px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
body > ol, body > ul {
|
||||
margin: 1em 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4361ee;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
font-family: ui-monospace, "Segoe UI Mono", "Source Code Pro", monospace;
|
||||
line-height: 1.2;
|
||||
background: #eaeaea;
|
||||
padding: 1px 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 6px;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
border-left: solid #888888 3px;
|
||||
font-style: italic;
|
||||
color: #343434;
|
||||
}
|
||||
|
||||
img, video {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 500px;
|
||||
object-fit: scale-down;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 auto;
|
||||
display: table;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
color: #888;
|
||||
display: table-caption;
|
||||
caption-side: bottom;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: #1d1d23;
|
||||
color: #fbfbfb;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #7fdeff;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
background: #18181e;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
color: #cacaca;
|
||||
}
|
||||
}
|
39
assets/rss.css
Normal file
39
assets/rss.css
Normal file
|
@ -0,0 +1,39 @@
|
|||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
article {
|
||||
background: var(--background15);
|
||||
border: solid var(--background2) 1px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
font-size: 1.2rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
h3:hover {
|
||||
background: #41ead422;
|
||||
}
|
||||
|
||||
article p {
|
||||
margin: 4px 0;
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
footer {
|
||||
font-size: .8rem;
|
||||
color: var(--color2);
|
||||
}
|
||||
|
||||
li + li {
|
||||
margin-top: 16px;
|
||||
}
|
94
assets/style.css
Normal file
94
assets/style.css
Normal file
|
@ -0,0 +1,94 @@
|
|||
:root {
|
||||
--background: #222225;
|
||||
--color: #dddddd;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--color);
|
||||
font: 16px/1.4 system-ui, "Segoe UI", "Cantarell", sans-serif;
|
||||
padding: 2em;
|
||||
margin: 0 auto;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
margin: 1em 0 4px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, code, pre {
|
||||
font-family: Consolas, monaco, monospace;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #41ead4;
|
||||
text-decoration: underline #318479;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background: #41ead422;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style-position: outside;
|
||||
padding-left: calc(2rem);
|
||||
}
|
||||
|
||||
body > ol, body > ul,
|
||||
details > ol, details > ul {
|
||||
margin: 1em 0 0;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
background: #1a1a1a;
|
||||
padding: 1px 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 4px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
border-left: solid #444444 3px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
details {
|
||||
border: solid #444444 1px;
|
||||
padding: 8px;
|
||||
background: #202021;
|
||||
}
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.copytext {
|
||||
cursor: pointer;
|
||||
color: #cb72dc;
|
||||
text-decoration: underline #8d5098;
|
||||
}
|
||||
|
||||
.copytext:hover {
|
||||
background: #cb72dc22;
|
||||
}
|
||||
|
||||
.copytext a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
background: inherit;
|
||||
}
|
101
assets/style2.css
Normal file
101
assets/style2.css
Normal file
|
@ -0,0 +1,101 @@
|
|||
:root {
|
||||
--background1: #222225;
|
||||
--background15: #1b1b1f;
|
||||
--background2: #151519;
|
||||
--color: #cccccc;
|
||||
--color2: #aaaaaa;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background1);
|
||||
color: var(--color);
|
||||
font: 16px/1.4 system-ui, "Segoe UI", "Cantarell", sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
header, section, main {
|
||||
padding: 16px max(calc(50vw - 300px), 16px);
|
||||
}
|
||||
|
||||
header {
|
||||
background: var(--background2);
|
||||
padding: 114px max(calc(50vw - 300px), 16px) 16px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
padding-top: 16px;
|
||||
margin-bottom: -8px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, code, pre, kbd, .eval {
|
||||
font-family: Consolas, monaco, monospace;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #41ead4;
|
||||
text-decoration: underline #318479;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background: #41ead422;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style-position: outside;
|
||||
padding-left: calc(2rem);
|
||||
}
|
||||
|
||||
body > ol, body > ul,
|
||||
details > ol, details > ul {
|
||||
margin: 1em 0 0;
|
||||
}
|
||||
|
||||
code, pre, kbd {
|
||||
background: #1a1a1a;
|
||||
padding: 1px 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 4px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
border-left: solid #444444 3px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
details {
|
||||
border: solid #444444 1px;
|
||||
padding: 8px;
|
||||
background: #202021;
|
||||
}
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.eval {
|
||||
color: #aaa;
|
||||
font-style: italic;
|
||||
margin-top: -.9rem;
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
kbd {
|
||||
border: solid #3a3a3a 1px;
|
||||
box-shadow: 1px 1px #2f2f2f;
|
||||
}
|
90
batch-sync.md
Normal file
90
batch-sync.md
Normal file
|
@ -0,0 +1,90 @@
|
|||
::: header
|
||||
# batch and sync
|
||||
:::
|
||||
::: section
|
||||
I'd like to introduce a new api architecture. I know someone has probably
|
||||
invented it before me and can't wait to find out, so I won't try to
|
||||
create a new name for it.
|
||||
|
||||
In this api architecture, you have a single querying endpoint and
|
||||
many batched action endpoints. At a high level, the client sends
|
||||
a QUERY message and receives continual SYNCs when any interesting
|
||||
data in the query updates. Think of this kind of like the [elm
|
||||
architecture](https://guide.elm-lang.org/architecture/) over the network.
|
||||
|
||||
For example, imagine the client dispatches a query for user
|
||||
preferences. Later the user settings are changed on a different (or
|
||||
the same) client. The first client automatically gets the new settings,
|
||||
because it has an active query for it.
|
||||
|
||||
## on the client
|
||||
|
||||
How does this look like on the client side in practice? You may be
|
||||
tempted to use websockets, but use long polling instead. It isn't as
|
||||
inefficient as you may think, and has some benefits.
|
||||
|
||||
- able to use quic/http3
|
||||
- automatic throttling on low bandwidth
|
||||
- can do single/one time queries easily, much easier to script
|
||||
- simpler to implement since you don't need to do the websocket authentication dance
|
||||
|
||||
This can be implemented with `POST /sync[?after=position]`, where a
|
||||
new position is returned with each sync. You can also cache the current
|
||||
state and position to resume when the tab is loaded later. Maybe even put the
|
||||
api client in a SharedWorker so every tab shares one logical connection.
|
||||
|
||||
Feel free to use whatever you like though, this high level architecture
|
||||
can apply to most things. Though, don't be tempted to create multiple ways
|
||||
to receive data, instead having a single source of truth. Querying/syncing
|
||||
doesn't use requests/responses, and instead is fully asynchronous.
|
||||
|
||||
For querying, it can be as simple as getting a few keys and values
|
||||
to graphql or even a minature sql dialect if you need that much
|
||||
flexibility. Some queries don't need to be reactive, like searching.
|
||||
|
||||
Besides the single data receiving endpoint, have batching for all
|
||||
other endpoints where it makes sense (ie. don't allow bulk account
|
||||
registering).
|
||||
|
||||
## on the server
|
||||
|
||||
As long as you have only one writer/reducer (but as many readers/syncers
|
||||
as you want), it's fairly simple. Give every record in your database
|
||||
that you want to sync a "last updated at" timestamp. The position you
|
||||
return to the client is the larges timestamp of all the items you're
|
||||
returning. For higher availability, use something like raft to choose
|
||||
a new reducer/writer if the main one fails.
|
||||
|
||||
If you must be Web Scale™ and have multiple reducers, timestamps don't
|
||||
quite cut it since servers can be desynced.
|
||||
|
||||
To keep readers up to date, consider use a pubsub mechanism. If you're
|
||||
using postgres, there's already one built in. If you need more scale,
|
||||
there's plenty of existing software - I advise against making your own
|
||||
since its one of those things that looks simple at first but gets more
|
||||
complex over time.
|
||||
|
||||
For ratelimiting things that only affect local user by requests per second,
|
||||
ratelimit things that affect other users by total batched items per second
|
||||
|
||||
## issues
|
||||
|
||||
For small apps that don't need realtime data or complex querying, you
|
||||
probably don't need to bother with syncing: while simple to implement,
|
||||
it's still unneeded complexity. I do recommend trying to [make apis
|
||||
batched](https://matklad.github.io/2023/11/15/push-ifs-up-and-fors-down.html#Push-Fors-Down)
|
||||
whenever though, since it's pretty much free performance.
|
||||
|
||||
Sorting can be hard with reactivity, but is fine if you only ever answer
|
||||
queries once.
|
||||
|
||||
Pagination is annoying to implement, but still reasonable. Again, this
|
||||
is one of those things that this architecture doesn't handle well and
|
||||
rest is better at. I'd probably add extra GET endpoints to paginate.
|
||||
|
||||
## conslusion
|
||||
|
||||
I'm not sure how well this scales in practice, but it seems nice from an
|
||||
initial inspection. Rest is a fairly leaky abstraction, since not every
|
||||
action happens on a single object.
|
||||
:::
|
50
caft-63e645b.md
Normal file
50
caft-63e645b.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
# ifritserv/caft docs
|
||||
|
||||
- minecraft server: <span class="copytext" onclick="navigator.clipboard.writeText(this.innerText);return false">ifritserv.zapto.org:2023</span> (click to copy)
|
||||
- discord guild: https://discord.gg/jK58DJ58Zh
|
||||
|
||||
## features
|
||||
|
||||
- Compatible with vanilla 1.20.1
|
||||
- Terralith worldgen
|
||||
- Incendium nether worldgen + nether items
|
||||
- Every mob can drop its head
|
||||
- Serverside Carpet
|
||||
- Wear any item in your helmet slot
|
||||
- `/flex` to show off the item you're holding in chat
|
||||
- `/skin` to change your skin
|
||||
- `/deathboard` to see a death leaderboard
|
||||
- `/whereis` to find items in nearby inventories
|
||||
|
||||
## how to
|
||||
|
||||
<details>
|
||||
|
||||
<summary>how to use the raid (shadow legends) farm</summary>
|
||||
|
||||
1. Get bad omen from any pillager outpost. There's one directly accessible from the nether.
|
||||
2. Go to the raid farm.
|
||||
3. Immediately go into the water elevator (or you lose bad omen)
|
||||
4. If you're not on your first raid, skip to step 9
|
||||
5. A raid will start. Ignore it for now.
|
||||
6. Stand below the chest.
|
||||
7. Put all your items into the chest except some food and a sword.
|
||||
8. Organize your inventory in a way that it's filled with the items you want to collect. If you want totems, leave some empty space in your inventory. ![screenshot of inventory setup](https://celery.eu.org/_matrix/media/r0/download/celery.eu.org/bb2ad5b01f62d9fc566bbc3e3946694d5c26adf91725949427471876096) <br />
|
||||
9. Do the same thing with the hopper: ![screenshot of hopper setup](https://celery.eu.org/_matrix/media/r0/download/celery.eu.org/446b74ac4550035f00eb9d56d8fa616a9514516e1725949428184907776) <br />
|
||||
10. Wait for the horns to stop ("ominous horn blaring", with subtitles)
|
||||
11. Flip the lever. The fence gate should be closed.
|
||||
12. Attack through the gap between the hopper and the chest until everything is dead.
|
||||
13. If there's too many items on top of the hopper, take the lava bucket from the chest and place it on top of the hopper so the items burn.
|
||||
14. Make sure to put back the lava bucket.
|
||||
15. If you're done, take your items.
|
||||
16. Flip the lever. The fence gate should be open.
|
||||
17. On the ladders, go as far forwards as you can, then stop pressing w and you will drop right into the water.
|
||||
18. If you want, repeat from step 3. Otherwise, you can leave the farm without doing anything special.
|
||||
|
||||
**Note:** you might also want to see [the video by ianxofour](https://youtube.com/watch?v=hVHFIfZAL54) for more background information.
|
||||
|
||||
</details>
|
||||
|
||||
## server map
|
||||
|
||||
// todo
|
74
caustic.md
Normal file
74
caustic.md
Normal file
|
@ -0,0 +1,74 @@
|
|||
::: header
|
||||
# caustic
|
||||
:::
|
||||
|
||||
::: section
|
||||
In some communities, there exists difficult users. They don't break
|
||||
any rules and aren't outright hostile, but are subtly caustic and
|
||||
annoying. Left unchecked, they can kill a healthy community. Or at the
|
||||
very least drastically change the culture.
|
||||
|
||||
They take many forms. Maybe when someone asks for help on some code, they
|
||||
comment on the code style or formatting. Maybe they do give some bits
|
||||
of advice, but they always seem to say "you're doing xyz wrong" instead
|
||||
of explaining how to fix xyz. Worst of all, some of them participate
|
||||
constantly. Then I think of myself, and other interactions across the
|
||||
web. It seems like the culture of the internet is being pushed in this
|
||||
direction.
|
||||
|
||||
This all kind of ties into modern internet culture a little. I don't have
|
||||
a word for it but i call it "polite hostility", or sometimes "advertiser
|
||||
friendly hostility". People tend to superficially follow the rules,
|
||||
follow the social norms, follow what is said while ignoring what is
|
||||
not. But when you look under the hood and they show their true colors,
|
||||
there's still toxicity.
|
||||
|
||||
There are several theories I can draw from these observations. Perhaps
|
||||
website design is pushing people for more "in-the-moment"
|
||||
discourse. It promotes reactionary responses; quick emotional
|
||||
or empty responses are rewarded, while more in depth thought is
|
||||
discouraged. Go to a popular sites (youtube, tiktok, twitter/x,
|
||||
reddit). Read the comments. How many are fluff or reactions, with
|
||||
no substance? Is it more like a village, where everyone knows
|
||||
each other, or a [train station; a liminal space strangers pass
|
||||
through](https://www.marginalia.nu/log/82_killing_community/)?
|
||||
|
||||
Another theory is that people want to
|
||||
find their tribe; to fit in. [Humans are social
|
||||
creatures](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2527715/),
|
||||
who want to recognize and be recognized. Even without peer pressure,
|
||||
people will adopt other cultures over time. Time procures normalcy. And
|
||||
this begs the question: what culture have we brought to the internet? Is
|
||||
it a culture we're happy with?
|
||||
|
||||
When you make a bad decision, you're a moron. When a good
|
||||
decision is made, it retrospectively was the [obvious choice all
|
||||
along](https://en.wikipedia.org/wiki/Hindsight_bias). It's easier to doubt
|
||||
than to hope, if only to stop yourself from becoming an outcast. People
|
||||
like to follow the trends, be it fashion, news, other people, or thoughts.
|
||||
|
||||
People who follow trends rarely create them. For fashion, blindly
|
||||
following trends can be harmless fun. When it comes to thoughts, parroting
|
||||
without thinking can be dangerous. Because it's the trendy thing to do,
|
||||
people tend to superficially follow thoughts, follow the social norms,
|
||||
follow what is said while ignoring what isn't.
|
||||
|
||||
Everyone has the right to express themselves, the right to speak their
|
||||
mind. Preventing people from freely expressing thought is the most
|
||||
effective ways to stop free thought. And yet, there exist [things you
|
||||
can't say](http://www.paulgraham.com/say.html). Things that should be
|
||||
said, and things that probably shouldn't. What's good and bad and in
|
||||
fashion is in constant flux, but getting more ideas into the world would
|
||||
certainly be nice.
|
||||
|
||||
Everyone also has the right to ignore what others have to say. You get
|
||||
free speech, but nobody has to listen to you. Try to push your ideas
|
||||
into places where they're not wanted, and you'll lose your friends and
|
||||
get ignored. Maybe the ideas come in the form of unwanted or irrelevant
|
||||
cynicism. Maybe it's commenting on the code style or formatting when
|
||||
someone asks for help on some code. Worst of all, it might be talking
|
||||
without letting other people chime in. Get your own space to talk
|
||||
about yourself.
|
||||
|
||||
Read between the lines.
|
||||
:::
|
34
comms.md
Normal file
34
comms.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
::: header
|
||||
# theory of communications
|
||||
|
||||
*[warning: this is a draft]*
|
||||
:::
|
||||
|
||||
::: section
|
||||
I've noticed there are only really 4 unique ways people on the internet
|
||||
communicate with each other:
|
||||
|
||||
- **irc**-like: instant and ephemeral, synchronous
|
||||
- **email**-like: personal async
|
||||
- **usenet**-like: forums, communal async
|
||||
- **rss**-like: broadcast
|
||||
|
||||
While the naming is mostly for fun, I do think that in essence these
|
||||
really are the four horsemen of communication. On the irc side, you
|
||||
have software like slack, discord, or matrix, along with a plethora
|
||||
of bad recreations across thousands of apps. Rss has been forked into
|
||||
microblogging and youtube. Usenet is the great grandpapi of forums like
|
||||
reddit. And there's email, which to this date nobody has been able to
|
||||
make any significant improvement on.
|
||||
|
||||
Now, there's no reason why you couldn't combine rss, usenet, and email
|
||||
in one client. Unfortunately, irc kind of does its own thing compared to
|
||||
email/usenet/rss, and since nearly every system since then copied its
|
||||
mannerisms its difficult to work irc-like into a system that tries to
|
||||
combine all four together.
|
||||
|
||||
to write about:
|
||||
- interoperability between multiple similar systems, federation and standard apis
|
||||
- interoperability between different systems, and getting irc to work well with them (prior art zulip + discord forum channels, autothreading)
|
||||
- inbox vs feeds, when they switch between subscriptions to recommendations, benefits/downsides
|
||||
:::
|
60
conduit-faq.md
Normal file
60
conduit-faq.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
::: header
|
||||
# conduit faq
|
||||
|
||||
this should be moved into the [actual website](https://conduit.rs) at some point
|
||||
:::
|
||||
|
||||
::: section
|
||||
## what features are supported?
|
||||
|
||||
- room versions 3-5 (unstable) and 6-10 (stable)
|
||||
- spaces
|
||||
- threads (although somewhat in a beta state)
|
||||
- voice calls, with [coturn](https://github.com/coturn/coturn) set up
|
||||
- appservices (meaning bridges will work)
|
||||
|
||||
## can i prune old media/events?
|
||||
|
||||
no
|
||||
|
||||
## why isn't conduit working?
|
||||
|
||||
a few common problems:
|
||||
|
||||
1. do you have a publicly reachable domain name? and a public + static ip address?
|
||||
2. does that domain name have a valid tls certificate? (look at [certbot](https://certbot.eff.org/) or [caddy](https://caddyserver.com/) (reverse proxy))
|
||||
3. is conduit running, and can you contact it from localhost?
|
||||
4. what about from outside localhost?
|
||||
5. is the response for `/` "hello from conduit!"?
|
||||
6. have you previously had a different matrix homeserver (synapse, dendrite) running on the same domain? if so, wait a day or two for the other servers to forget the old key
|
||||
|
||||
## how do i make the first user account on conduit?
|
||||
|
||||
1. enable registration
|
||||
2. register an account then quickly disable registration
|
||||
|
||||
(yeah, maybe not the best method at the moment)
|
||||
|
||||
## how do i configure conduit to ______?
|
||||
|
||||
in config.toml:
|
||||
|
||||
- disable federation: `enable_federation = false`
|
||||
- disable appending a lightning bolt to my display name: `enable_lightning_bolt = false`
|
||||
- use that coturn thing i set up: [check out this document](https://gitlab.com/famedly/conduit/-/blob/next/TURN.md?ref_type=heads)
|
||||
|
||||
## what is conduit using as its database, and how do i back up rocksdb?
|
||||
|
||||
[rocksdb](https://github.com/facebook/rocksdb/wiki). conduit technically
|
||||
supports sqlite, but it's not recommended (conduit currently abuses
|
||||
sqlite as a key/value rather than a relational database).
|
||||
|
||||
to back up the database, stop conduit, start conduit (to compact the db),
|
||||
stop conduit again, backup the files in the data directory, then start
|
||||
conduit. yes, unfortunately it is this janky. if you use zfs or btrfs,
|
||||
snapshots may work, though i haven't tested it.
|
||||
|
||||
## how do i migrate from {synapse, dendrite}?
|
||||
|
||||
you can't
|
||||
:::
|
69
design.md
Normal file
69
design.md
Normal file
|
@ -0,0 +1,69 @@
|
|||
::: header
|
||||
# design
|
||||
:::
|
||||
|
||||
::: section
|
||||
## Steps
|
||||
|
||||
1. Good design leads to good software. There are three main parts that need to work together:
|
||||
1. **Technology**: This is the foundation. Bad theory leads to bad design.
|
||||
2. **Interface**: If the interface is clunky or annoying to use, it won't be used.
|
||||
3. **Humans**: It needs to complement human tendencies. Don't encourage bad habits.
|
||||
2. Implement your design. Don't bother with perfection, instead make it only complete enough to be usable.
|
||||
3. Test your design and look for weak spots. If you find any, do a quick repition of steps 1 and 2. If you think your design is flawed, take a moment to think about it - some parts may be salvageable.
|
||||
|
||||
## Tips
|
||||
|
||||
1. Build for yourself. Don't worry about what other people think. Some of the best software is designed and used by only one person.
|
||||
2. Try to be extensible, being able to adapt to any needs.
|
||||
3. Try to be composable, being able to work together with other stuff.
|
||||
4. It's better to have the three parts of your design complement each other than have one get all the attention. I've seen flashy interfaces that don't work, incredible ideas that aren't implemented, and cool technology that is unusable.
|
||||
5. Not everything needs to be implemented. If you have a good idea that doesn't fit, write it down in a "ideas for later" or "sequels" notebook or document.
|
||||
|
||||
## Ideas
|
||||
|
||||
With that being said, here are some ideas I've had. It's my sequels page,
|
||||
and feel free to take as many or as little as you want! These have both
|
||||
random fragments that can be integrated to larger projects, or large
|
||||
projects on their own. There they are in no particular order:
|
||||
|
||||
1. **vote tagging**: Think of this like chat reactions for tagging posts. Instead of the creator or moderators tagging their post, other users do the tagging. A good news post could get many #news reactions.
|
||||
1. negative tags: Instead of only being able to upvote tags, it's possible to downvote tags.
|
||||
2. tag pages: You can see the newest, hottest, top, etc tagged posts. Each tag forms its own ad-hoc subreddit-like group which can be subscribed to.
|
||||
2. **subjective moderation**: Instead of a few moderator actions being canonical for everyone, people can subscribe/unsubscribe from someone's moderation.
|
||||
1. filters: You could combine block/approve lists into collections of filters. This doesn't need to be for moderation and can also be ie. "show me funny posts" or "show me posts about $topic"
|
||||
3. **your world of files**: A social media platform where instead of sharing posts, people share files. Kind of like a shared drive.
|
||||
1. as a blog: People could be authorized to write to their own files in subfolders, ie. have `posts/hello-world/hello.md` and `posts/hello-world/comments/` where people can write comments.
|
||||
2. as a wiki: Maybe file changes could be tracked, and people could create shared wikis
|
||||
3. as a repository: This could be used like a git repo, where you have a `code/` folder with `issues/`, `patches/` (prs/mrs), `discussions/` and so forth
|
||||
4. **logical inbox**: Some kind of software that combines inboxes and notifications between many other platforms into one platform.
|
||||
1. like rss: Rss is wonderful, but unfortunately not supported everywhere. Something that converts email to rss or gives an http api would be nice, where it could then be added to the inbox.
|
||||
2. chat segmentation: Take a chat log from {discord, slack, matrix, etc} and split it into topic-based threads for the inbox.
|
||||
3. all the comments: Find a way to combine comments and their ranking/scores from many different platforms together.
|
||||
4. semantic deduplication: Sometimes you can get repeats in multiple places. Being able to deduplicate and merge comments, replies, activity into one entry would be incredible.
|
||||
5. **language model functions**: It would be wonderful to have a server that lets you create "functions" to process and transform text. It could let you finetune t5-base to do whatever you want, and expose and endpoint for "calling" it as a function.
|
||||
1. model library: Maybe have a registry that people can publish stuff to, ie. "extract recipe json from html" or "summarize text".
|
||||
2. other models: t5 has an insane payoff/speed ratio, but I get that sometimes you need a decoder-only model for long running interactions.
|
||||
3. serverless, but actually: The server could let you export (quantized, distilled?) models (maybe in onnx) and let you run them where they need to be.
|
||||
6. **find everything**: Some way to find everything on your computer.
|
||||
1. now with semantics: Index the embeddings of media like images, audio, and video instead of only subtitles/ocr
|
||||
2. custom google: Search the web by crawling specific domains or using an index, maybe from some kind of index repository
|
||||
3. history is important: A way to do a full text search across all the websites you've visited, maybe combined with "logical inbox" above
|
||||
7. **rust x typescript**: This would be my ideal scripting language. Rust is great, but needs more work to setup and prototype in. Typescript doesn't have `match` or `enum`. I'm not sure whether borrow checking is good in a scripting language or not, but having some way to check how data moves is great.
|
||||
1. easy ffi: It should be easy to move from a small script into rust, or rust to the small script.
|
||||
2. raii: Even if there isn't any borrow checking.
|
||||
3. targeting wasm: I think webassembly is a perfectly cromulent target.
|
||||
4. or a minimal runtime: Alternatively, it could be easily embeddable.
|
||||
8. **language design**: These are a some ideas that could be integrated into programming languages.
|
||||
1. `fn main(ctx: Context)`: Main takes a context which is the gateway to all io and side effects. 3rd party modules can't access the filesystem unless you explicitly pass `ctx.fs`. Different contexts exist for different platforms.
|
||||
2. rich stdlib and extlib: The extended library extra useful and well supported stuff that shouldn't be in a minimal stdlib, like sqlite or images
|
||||
3. tabular tables: A helper around struct-of-arrays. It's meant to be a dataframes replacement, but does have nice things like joins and views into the table. Maybe like C# and linq, but less baked into the language.
|
||||
4. content addressing: Packages are content addressed, like with ipfs. (see scrapscript?)
|
||||
5. time management: Dealing with time is hard because you're dealing with a localized format. Stdlib only deals with unix time, with extra libraries to do intl (ie. `Temporal::new().with_timezone(...).with_calendar(...).with_format(...)` which is used for parsing and serialization). You can only do things like "get the day/year" with the extra library.
|
||||
6. layered cloning: `.clone()` is implicit and automatic, and is a mix of cow/arc/references.
|
||||
9. **helpful documentation**: I think some projects, like nixos, could benefit from better documentation. But there are also entire areas that need better docs.
|
||||
1. debugging: How do you debug? How do you use a debugger? A lot of people still resort to print() because debuggers seem too foreign.
|
||||
2. performance tips: Too many people focus on things like Big O notation, while low hanging fruit with greater effect are untouched. Optimizing memory access and batching/vectorization, for example, are pretty useful to understand.
|
||||
3. computers in general: This isn't ain't your grandma's book. These are things like staying safe online, using software, and making computers work for you. While I do think things should be improved by design if possible, I also don't people should use fisher-price computers. People are smarter than you think and will read helpful and consise documentation if it exists and is readily available.
|
||||
4. writing: There's so many holes for educational resources and so many people who could write helpful docs for it, but that won't happen if technical users don't know how to simplify their writing for the noobs.
|
||||
:::
|
34
federation.md
Normal file
34
federation.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
::: header
|
||||
# federation
|
||||
:::
|
||||
|
||||
::: section
|
||||
I think federation is overrated. Federation lets instances with different
|
||||
rules and moderation interoperate with each other. It's difficult to
|
||||
spam proof and has scaling issues.
|
||||
|
||||
A better alternative would be to have oauth2/oidc apis integrated into
|
||||
the browser and standardized apis. There's already rss for anything
|
||||
feed-like, but there should be additional apis for reading and managing
|
||||
items.
|
||||
|
||||
I do think federation can have potential with changes. My favorite design
|
||||
idea is being offline-first with servers existing as dumb relays and
|
||||
pointers to names. Alternatively, servers aggregate in a state based
|
||||
protocol (like matrix or bluesky) rather than op based (activitypub),
|
||||
giving more consistency and reliability.
|
||||
|
||||
Of course, the protocols themselves aren't the only part of the
|
||||
problem. If you want to be successful, there's also ui/ux, culture,
|
||||
and the network effect. The network effect is hard to overcome, so don't
|
||||
bother designing something for the world; instead, design something you
|
||||
and your friends would like and slowly.
|
||||
|
||||
By far the biggest issue I've seen is choosing a server, which
|
||||
interestingly enough isn't a tech problem. People understand how to use
|
||||
email servers, which are chosen for the domain name and stability. On
|
||||
the other hand, activitypub users try to tell people to choose servers
|
||||
based on hobbies or interests, which is confusing since regular people™
|
||||
have multiple interests or might not want to tie their identity to one
|
||||
specifically.
|
||||
:::
|
8
fetch
Normal file
8
fetch
Normal file
|
@ -0,0 +1,8 @@
|
|||
[38;2;173;153;47m⢸[38;2;169;149;45m⣿[38;2;165;146;44m⣷[38;2;179;159;48m⣶[38;2;170;151;46m⣦[38;2;161;143;43m⣤[38;2;142;126;37m⣀ [0m [38;5;128mZest[38;5;129myLem[38;5;93monade
|
||||
[38;2;177;157;48m⢸⣿⣿⣿⣿[38;2;177;156;47m⣿[38;2;168;168;71m⣿[38;2;153;191;117m⣷[38;2;114;161;112m⣦[38;2;66;94;65m⡀ [0m [38;5;128m---[38;5;129m-----[38;5;93m----[38;5;99m-
|
||||
[38;2;128;58;184m⢀[38;2;104;47;148m⡀ [38;2;177;157;48m⢸⣿⣿[38;2;173;161;56m⣿[38;2;160;179;93m⣿[38;2;148;196;129m⣿[38;2;143;202;141m⣿[38;2;144;203;142m⣿[38;2;143;202;141m⣿[38;2;141;199;139m⣷[38;2;90;128;89m⡄ [0m [38;5;128mMat[38;5;129mrix:[38;5;93m @[38;5;99mtezl[38;5;63mm:ce[38;5;69mlery.[38;5;33meu.o[38;5;39mrg
|
||||
[38;2;118;53;169m⢰[38;2;125;57;179m⣿⣿[38;2;126;57;180m⣦[38;2;113;50;162m⣄[38;2;175;158;49m⢸[38;2;165;172;78m⣿[38;2;153;189;114m⣿[38;2;143;203;141m⣿⣿⣿[38;2;144;203;141m⣿⣿⣿[38;2;143;203;141m⣿[38;2;126;177;124m⣷ [0m [38;5;128mEma[38;5;129mil: [38;5;93m [38;5;99mtezlm[38;5;63m@cel[38;5;69mery.[38;5;33meu.or[38;5;39mg
|
||||
[38;2;117;120;176m⢸[38;2;134;137;200m⣿[38;2;133;137;200m⣿[38;2;139;135;204m⣿[38;2;151;131;213m⣿[38;2;157;151;214m⣿[38;2;159;169;205m⣿[38;2;166;168;202m⣿[38;2;169;167;200m⣿[38;2;169;167;201m⣿[38;2;163;162;201m⣿[38;2;158;158;201m⣿⣿⣿[38;2;158;158;200m⣿[38;2;143;143;181m⡿ [0m [38;5;128mWe[38;5;129mbsit[38;5;93me: [38;5;99mhttp[38;5;63ms://[38;5;69mceler[38;5;33my.eu[38;5;39m.org
|
||||
[38;2;121;88;178m⣹[38;2;146;107;205m⣿[38;2;162;121;220m⣿[38;2;166;127;224m⣿[38;2;157;150;217m⣿[38;2;151;171;211m⣿[38;2;149;168;209m⣿[38;2;149;159;205m⣿[38;2;152;153;201m⣿[38;2;158;157;201m⣿[38;2;159;158;202m⣿⣿[38;2;158;157;201m⣿[38;2;150;149;191m⣿[38;2;126;125;160m⠃ [0m
|
||||
[38;2;97;44;139m⣀[38;2;126;57;180m⣴[38;2;121;55;173m⣿[38;2;126;58;180m⣿⣿[38;2;125;57;179m⣿⣿[38;2;130;102;191m⣿[38;2;133;137;200m⣿⣿[38;2;134;138;201m⣿⣿[38;2;135;138;201m⣿[38;2;143;145;201m⣿[38;2;149;149;196m⣿[38;2;154;153;196m⠟[38;2;128;127;162m⠁ [0m [0m
|
||||
[38;2;114;52;163m⠙[38;2;127;58;181m⠛[38;2;126;58;180m⠿[38;2;122;56;175m⢿[38;2;127;58;182m⣿[38;2;127;58;181m⣿[38;2;130;102;192m⣿[38;2;135;139;202m⣿[38;2;135;139;203m⣿[38;2;121;124;182m⣿[38;2;134;138;202m⠿[38;2;121;125;182m⠟⠋[38;2;58;60;88m⠁ [0m
|
BIN
guhsunsbud.png
Normal file
BIN
guhsunsbud.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
15
index.html
Normal file
15
index.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>celery</title>
|
||||
<meta charset="utf8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/style.css"></link>
|
||||
<link rel="stylesheet" href="/assets/index.css"></link>
|
||||
<script defer src="/assets/index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
<div style="font-style: italic; color: #aaa">celery.eu.org is currently undergoing unplanned mainenence</div>
|
||||
</body>
|
||||
</html>
|
16
index2.html
Normal file
16
index2.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>celery</title>
|
||||
<meta charset="utf8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/style.css"></link>
|
||||
<link rel="stylesheet" href="/assets/index.css"></link>
|
||||
<script defer src="/assets/index2.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<svg id="main">
|
||||
<noscript>you are at celery.eu.org</noscript>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
71
index2.js
Normal file
71
index2.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
const pre = document.getElementById("main");
|
||||
|
||||
// the cool spinning circles on index.html
|
||||
// const ctx = canvas.getContext("2d");
|
||||
const rnd = (n) => Math.floor(Math.random() * n);
|
||||
const colors = ["#f0d644", "#63eebe", "#9e4adf"]; // i like neon
|
||||
const points = [];
|
||||
let time = 0;
|
||||
|
||||
// handle page resizes without ruining everything
|
||||
function resize() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
ctx.width = canvas.width;
|
||||
ctx.height = canvas.height;
|
||||
}
|
||||
|
||||
// math moment
|
||||
function rotation(point) {
|
||||
return point.rot + time * point.speed;
|
||||
}
|
||||
|
||||
function length(point) {
|
||||
return Math.min(time * point.speed, point.speed * 4);
|
||||
}
|
||||
|
||||
function arc(point) {
|
||||
const angle = rotation(point);
|
||||
return [angle, angle + length(point)];
|
||||
}
|
||||
|
||||
// initialize the canvas
|
||||
function init() {
|
||||
resize();
|
||||
window.addEventListener("resize", resize);
|
||||
|
||||
for (let i = 0; i < 10 + rnd(4); i++) {
|
||||
points.push({
|
||||
color: colors[rnd(colors.length)],
|
||||
radius: Math.random() * 600 + 300,
|
||||
speed: Math.random() / 10 + 0.1,
|
||||
rot: Math.random() * 2 * Math.PI,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// the heart and soul of the circles
|
||||
function anim() {
|
||||
// center points
|
||||
const cx = ctx.width / 2;
|
||||
const cy = ctx.height / 2;
|
||||
|
||||
ctx.clearRect(0, 0, ctx.width, ctx.height);
|
||||
ctx.globalAlpha = time / 3; // fade in
|
||||
ctx.lineWidth = 4;
|
||||
|
||||
for (let point of points) {
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = point.color;
|
||||
ctx.arc(cx, cy, point.radius, ...arc(point));
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
time += 0.01;
|
||||
setTimeout(anim, 1000 / 60);
|
||||
}
|
||||
|
||||
pre.textContent = "you are at celery.eu.org"
|
||||
|
||||
init();
|
||||
setTimeout(anim, 1000);
|
31
inochi2d.md
Normal file
31
inochi2d.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
# inochi2d guide
|
||||
|
||||
## prerequisites
|
||||
|
||||
- git
|
||||
- python3 and pip
|
||||
- a webcam
|
||||
- openseeface
|
||||
|
||||
## building openseeface
|
||||
|
||||
```bash
|
||||
git clone https://github.com/emilianavt/OpenSeeFace
|
||||
cd OpenSeeFace
|
||||
pip install onnxruntime opencv-python pillow numpy
|
||||
python3 facetracker.py -v 4 --fps 60
|
||||
```
|
||||
|
||||
## inochi2d-session
|
||||
|
||||
1. [Download the latest release](https://github.com/Inochi2D/inochi-session/releases)
|
||||
2. Run it
|
||||
3. Open your `.inp` model (in File > Open)
|
||||
4. View → Virtual Space → enter a name and hit the plus arrow → select your new zone → set to OpenSeeFace → osf_bind_port = 11573, osf_bind_ip = 127.0.0.1 → save changes → save
|
||||
5. Drag away the Scene Settings window because all the actually important things are hiding under there
|
||||
6. Drag Tracking to wherever you like
|
||||
7. Hit "Refresh"
|
||||
8. Play around with the settings a little bit until it suits you
|
||||
|
||||
You can zoom in by selecting your puppet and c-scroll. Double-click to
|
||||
hide ui. Set the background in Scene Settings if you like.
|
52
llm-arch.md
Normal file
52
llm-arch.md
Normal file
|
@ -0,0 +1,52 @@
|
|||
::: header
|
||||
# language model architectures
|
||||
:::
|
||||
::: section
|
||||
By now, many people have heard of transformers. And yeah, they're cool,
|
||||
but there are other architectures that are also worth taking a look at.
|
||||
|
||||
## word2vec
|
||||
|
||||
While not technically not generative nor a single architecture,
|
||||
[word2vec](http://jalammar.github.io/illustrated-word2vec/) is the
|
||||
earliest language models worth talking about. It takes in input text and
|
||||
creates [embeddings](https://en.wikipedia.org/wiki/Word_embedding),
|
||||
numerical representations of the words. What makes
|
||||
embeddings so special is that they capture semantic
|
||||
meaning. Famously, the input `queen` and `king-man+woman` give
|
||||
[similar](https://datascience.stackexchange.com/a/45253) embeddings.
|
||||
|
||||
Under the hood, it
|
||||
|
||||
## rnns
|
||||
|
||||
Recurrent neural networks are able to take an input state and input token,
|
||||
and produce the next best token.
|
||||
|
||||
## rnns + lstm
|
||||
|
||||
[long short term memory](https://en.wikipedia.org/wiki/Long_short-term_memory)
|
||||
|
||||
## transformer (encoder/decoder)
|
||||
|
||||
The [transformer](http://jalammar.github.io/illustrated-transformer/) takes input text and transforms it into output text, token by token. Previous models, like [rnns](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) and
|
||||
|
||||
## transformer (decoder only)
|
||||
|
||||
What if you only want to generate text? Then
|
||||
you only need the decoder. This is what
|
||||
[gpt2](https://openai.com/research/better-language-models) uses.
|
||||
|
||||
## transformer (encoder only)
|
||||
|
||||
What if you only want to embed text? Then you only need the encoder. Only
|
||||
having embedding is still useful for similarity search, to be able to
|
||||
compare the embeddings of the query and content.
|
||||
|
||||
## rwkv
|
||||
|
||||
transformers x rnns
|
||||
|
||||
## samba state
|
||||
|
||||
a newer model, haven't researched this one yet
|
138
mac.html
Normal file
138
mac.html
Normal file
|
@ -0,0 +1,138 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>macimas's ui thing</title>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 20px;
|
||||
margin: 0;
|
||||
background: #151518;
|
||||
color: #eaeaea;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
height: 400px;
|
||||
width: 600px;
|
||||
background: #2a2c31;
|
||||
border: solid #5865f2 4px;
|
||||
border-radius: 16px;
|
||||
display: grid;
|
||||
grid-template-areas: "header nav" "main nav";
|
||||
grid-template-columns: 1fr 64px;
|
||||
grid-template-rows: 64px 1fr;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
border-bottom: solid #131416 2px;
|
||||
grid-area: header;
|
||||
display: flex;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
|
||||
header > img {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
header > .info {
|
||||
flex: 1;
|
||||
margin: auto 8px;
|
||||
}
|
||||
|
||||
header > .menu {
|
||||
background: #131416;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
border-radius: 50%;
|
||||
border: solid #4c4c4e 2px;
|
||||
}
|
||||
|
||||
main > div[data-item="map"] {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
padding: 8px;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
main > div[data-item="map"] > .item {
|
||||
background: #131416;
|
||||
padding: 8px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
nav {
|
||||
background: #131416;
|
||||
grid-area: nav;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
nav > .item {
|
||||
background: #2a2c31;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
margin-right: 6px;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
background: #aaaaaa;
|
||||
}
|
||||
|
||||
.icon.green {
|
||||
background: #23a559;
|
||||
}
|
||||
|
||||
.space {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<header>
|
||||
<img src="/guhsunsbud.png" />
|
||||
<div class="info">
|
||||
<div style="font-weight: bold">guhsunsbud</div>
|
||||
<div><div class="icon"></div>20 members<div class="space"></div><div class="icon green"></div>10 online</div>
|
||||
</div>
|
||||
<div class="menu"></div>
|
||||
</header>
|
||||
<main>
|
||||
<div data-item="info" class="hidden"></div>
|
||||
<div data-item="map" class="hidden">
|
||||
<div class="item"><div class="icon"></div> Train Station</div>
|
||||
<div class="item"><div class="icon"></div> Beach</div>
|
||||
<div class="item"><div class="icon"></div> House</div>
|
||||
<div class="item"><div class="icon"></div> House</div>
|
||||
<div class="item"><div class="icon"></div> House</div>
|
||||
<div class="item"><div class="icon"></div> House</div>
|
||||
</div>
|
||||
<div data-item="members"></div>
|
||||
<div data-item="chat" class="hidden"></div>
|
||||
</main>
|
||||
<nav>
|
||||
<div class="item"></div>
|
||||
<div class="item"></div>
|
||||
<div class="item"></div>
|
||||
<div class="item"></div>
|
||||
</nav>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
3
math.html
Normal file
3
math.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
<body>
|
||||
<p>sqrt(3^2 + 4*2)</p>
|
||||
</body>
|
68
matrix.html
Normal file
68
matrix.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="charset" content="utf8" />
|
||||
<meta name="initial-device-width" content="1" />
|
||||
<title>matrix</title>
|
||||
<style>
|
||||
body {
|
||||
background: #f8f8f8;
|
||||
color: #222222;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 2em;
|
||||
font: 1em/1.3 serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3b74c9;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline wavy;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>matrix</h1>
|
||||
<p><a href="https://matrix.org/">Matrix</a> is a <font color="#c8324e">decentralized</font> <font color="#c732c3">open</font> <font color="#32c767">secure</font> and otherwise (mostly) <font color="#c78d32">bullshit-free</font> <font color="#3282c7">protocol</font> you can use for instant messaging</p>
|
||||
<h2>what</h2>
|
||||
<p>Let's break it down a bit, in order of importance:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><font color="#3282c7">protocol</font>: matrix is not an app, it's a protocol (much like email or http). You know how can use any web browser to use http, like chrome or <a href="https://www.mozilla.org/en-US/firefox/new/">firefox</a>? Or any email client to use an email server? The same applies here!</p>
|
||||
<p>You can choose any client, like <a href="https://app.element.io/">element (web, ios, android)</a>, <a href="https://cinny.in/">cinny (web)</a>, <a href="https://fluffychat.im/">fluffychat (ios, android)</a> or any of the <a href="https://matrix.org/ecosystem/clients/">many other clients</a> to use matrix. Anything that can <a href="https://spec.matrix.org/latest/">speak matrix</a> (warning: technical jargon) can interact with the entire ecosystem!</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><font color="#c8324e">decentralized</font>: You can host your own <a href="https://matrix.org/ecosystem/servers/">homeserver</a> (if you're technically inclined), or join an <a href="https://servers.joinmatrix.org/">existing one</a>. There's no one owner of matrix like there is with reddit.com, <s>twitter</s> x.com, or discord.com.</p>
|
||||
<p>Every homeserver can talk to each other - think of it like email, where a gmail user can email a outlook user. This was how the internet is meant to work, despite companies wanting walled gardens.</p>
|
||||
</li>
|
||||
<li><p><font color="#32c767">open</font>: The protocol, along with pretty much all servers and clients, are all open source. Not only that, you can <a href="https://github.com/matrix-org/matrix-spec-proposals/">propose changes</a> to the protocol yourself if you really wanted to. Programmers can develop their own applications on matrix - in a nutshell, 3rd party apps are not only allowed, they're encouraged!</p></li>
|
||||
<li>
|
||||
<p><font color="#c732c3">secure (and private)</font>: <a href="https://www.un.org/en/about-us/universal-declaration-of-human-rights#:~:text=No%20one%20shall%20be%20subjected%20to%20arbitrary%20interference%20with%20his%20privacy">Privacy is a human right</a>, so matrix can and does end to encrypt private conversations with strong, auditable encryption. (For nerds: matrix uses <a href="https://gitlab.matrix.org/matrix-org/olm/-/blob/master/docs/olm.md">olm</a>, which is in incarnation of <a href="https://signal.org/">signal</a>'s double-ratchet algorithm).</a>
|
||||
<p>Some applications such as iMessage are closed source, so when apple touts e2ee you need to take their word for it. Other platforms, like discord, don't have e2ee at all!</p>
|
||||
<p>Plus, clients have dignity and will ask you before sending telemetry, which is nice considering the sheer number of applications trying to shovel tons of data to their servers without warning.</p>
|
||||
</li>
|
||||
<li><p><font color="#c78d32">bullshit-free</font>: All of these points combine into a pretty potent cocktail. There's no ceo that can ruin anything. You can own your own data.</p></li>
|
||||
</ul>
|
||||
<h2>why</h2>
|
||||
<p>In case the overview/philisophical-ish reasons didn't mean much to you, here are more, concrete, reasons</p>
|
||||
<ul>
|
||||
<li><b>searching</b> and <b>unread markers</b>: iMessage neither lets you search past messages or jump to the last unread message in 2023?</li>
|
||||
<li><b>finer permissions</b>: You can control who can do what in each group</li>
|
||||
<li><b>larger uploads</b>: Most homeservers let you upload files larger than 8mb for free. And you host your own homeserver, you can set the limit arbitrarily high.</li>
|
||||
<li><b>spaces</b>: <a href="https://element.io/blog/spaces-the-next-frontier/">Spaces</a> are collections of chatrooms and other spaces, where each room can be in multiple spaces. Use them as a folder, or as to create communities. Once they "clicked", I firmly believe this is the best method of organization. (And yes, you can create a space that contains itself if you mess around enough.)</li>
|
||||
<li><b>invite only rooms</b>: Discord only lets you invite people with invite links. Matrix lets you send people invites directly. (There are other neat things, like aliases, if you have a public room)</li>
|
||||
<li><b>no phone number requirement</b>: You don't need a phone number to use matrix.</li>
|
||||
<li><b>no ads</b>: Telegram users will understand.</li>
|
||||
</ul>
|
||||
<h2>why not</h2>
|
||||
<p>Matrix is great, but it's not perfect.</p>
|
||||
<ul>
|
||||
<li><b>beta quality clients</b>: a lot of clients (including flagship element) behave a little janky or bad <a href="https://en.wikipedia.org/wiki/Computer_accessibility">a11y</a>. This will be fixed in due time, but for now it won't be entirely smooth.</li>
|
||||
<li><b>sketchy notification support</b>: notifications behave a bit funkily - they're overengineered yet to rigid to support that many use cases</li>
|
||||
<li><b>no rbac</b>: permissions exist, but without the granularity <a href="https://support.discord.com/hc/en-us/articles/214836687-Role-Management-101">discord has</a> with roles and overrides. Don't get me wrong though, <a href="https://matrix.org/docs/communities/moderation/">power levels</a> are enough for the vast majority of communities.</li>
|
||||
<li><b>mediocre multi-user calls</b>: The tl;dr is element currently embeds a different voice call website <a href="https://jitsi.org/">jitsi</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
301
matrix.md
Normal file
301
matrix.md
Normal file
|
@ -0,0 +1,301 @@
|
|||
::: header
|
||||
# thoughts on matrix
|
||||
:::
|
||||
|
||||
::: section
|
||||
I've used matrix for a while now. While the core idea is excellent and
|
||||
there's so many good ideas, there's so many bad parts and annoyances
|
||||
with it. Parts of the protocol feel like they were patched together by
|
||||
someone until they went "eh looks about right", while other parts are
|
||||
incoherent or give off strong design-by-comittee vibes. I'm going to
|
||||
keep using matrix, but because of these problems I won't suggest it to
|
||||
any other people.
|
||||
|
||||
This critique looks at matrix from an end user's perspecive as well as
|
||||
from a more technical perspective and is mostly a thought dump, so it
|
||||
may be hard to follow.
|
||||
|
||||
## threads
|
||||
|
||||
Threads are implemented as fancy replies. This makes it easy for people
|
||||
using clients without threads to accidentally reply to a threaded message
|
||||
from outside of a thread, causing things to break. It also causes
|
||||
per-thread typing notifications and read receipts to be chronically
|
||||
broken. Once you send a message in a thread it's permanently added to
|
||||
"my threads" with no way of removing it later. There's also pretty much
|
||||
no qol features, like thread titles/names or being able to archive old
|
||||
threads. There's no way to lock threads (though this is fairly niche and
|
||||
to my knowledge would be extremely difficult to implement). On top of all
|
||||
that, there's no way disable threads in a room. Thread only rooms would
|
||||
be nice and technically only need special ui, but don't currently exist.
|
||||
|
||||
Making threads their own rooms (threads as rooms) would solve some of
|
||||
these problems, but would cause problems elsewhere. Searching messages
|
||||
across the main room and threads would be harder to implement. Access
|
||||
control would need to be synced, and "rogue threads" which don't set
|
||||
power levels for the parent room's moderators could be created. There's
|
||||
no way to add other people to threads (ie. in the case of "reply in
|
||||
thread"). Letting people peek in threads without joining would rely on
|
||||
features that don't exist currently, like federated peeking as well as
|
||||
a version of history_visibility for peeking. This could also lead to
|
||||
amplification: currently, creating a thread is as expensive as sending
|
||||
a message, wheras each thread as room would need its own set of state
|
||||
(m.room.create, m.room.member, m.room.join_rules, etc)
|
||||
|
||||
(Aside: it looks like having a "main thread/chat" and "threads" are
|
||||
fundementally incompatible. Most people would like messages would be
|
||||
properly threaded, but there's an easier to use main thread and ui
|
||||
encouraging its use. There's a fundemental tension and neither option
|
||||
is quite correct.)
|
||||
|
||||
## push rules
|
||||
|
||||
Push rules are how a matrix client and server decides whether a message
|
||||
sends a push notification, makes a sound, and so forth.
|
||||
|
||||
All push rules go in one giant blob in global account data, which I
|
||||
think some of which should have been split out into per-room account
|
||||
data. Push rules have seemingly arbitrary groupings: muting
|
||||
a room goes in the `overrides` group, but receiving notifications for
|
||||
all messages goes in the `rooms` group.
|
||||
|
||||
When changing a lot of room-specific push rules, the rules can overwrite
|
||||
each other in flight, causing some room-specific push rules to reset/be
|
||||
dropped. This is technically an issue with all push rules, but most of the
|
||||
time it isn't noticable to end users. Push rules get around this by having
|
||||
an entire separate set of apis for changing fine-grained account data.
|
||||
|
||||
The rules are written in a json <abbr title="domain specific
|
||||
language">dsl</abbr>-like thing that is needlessly flexible. This causes
|
||||
performance issues. Simultaneously, they're somehow extremely rigid. It
|
||||
is only possible to use one of the 6 predefined conditions and the only
|
||||
counters that exist are `notify_count` and `highlight_count`. Notably,
|
||||
there's no `unread_count`. My workaround for now is to patch clients
|
||||
to not notify unless the highlight tweak is set, and use `notify_count`
|
||||
as an unread count.
|
||||
|
||||
Mentions are currently implemented as searching the message body for a
|
||||
display name/username, which can cause accidental notifications. Saying
|
||||
people's names without notifying them needs workarounds like
|
||||
1337speek. This is slated to be fixed with intentional mentions,
|
||||
where mentions are extracted to their own json field. Unfortunately,
|
||||
it looks like encrypted messages will put the mentions in encrypted
|
||||
content, breaking rules (todo: heard this from somewhere, but need a
|
||||
source). Ironically, the one time metadata is made less leaky, it also
|
||||
happens to be the one time where it makes sense and is needed for good ux.
|
||||
|
||||
The `/notifications` endpoint paginates through a list of pings/mentions,
|
||||
though due to the above paragraph won't show any mentions in encrypted
|
||||
rooms. There's no way to filter mentions per room/space or if it's @room.
|
||||
Although "list of mentions" makes sense naively, it would be much better
|
||||
to have an inbox where messages be added and removed.
|
||||
|
||||
No client supports marking rooms, threads, or events as unread.
|
||||
|
||||
There's no way to temporarily mute rooms (or all notifications). Since a
|
||||
room can be in multiple spaces, there's no easy way to mute all rooms in
|
||||
a space. There's no way to only mute @room notifications while allowing
|
||||
user mentions.
|
||||
|
||||
## e2ee
|
||||
|
||||
Matrix's implementation of end to end encryption leaks a lot of metadata,
|
||||
including but not limited to room name/topic/avatar, member per-room
|
||||
displaynames/avatars, and reactions.
|
||||
|
||||
Newly joined members can't view old e2ee messages. This is fixable,
|
||||
but not yet fixed.
|
||||
|
||||
It's also remarkably easy to get undecryptable messages by accident,
|
||||
and is the **single biggest reason** why I'm not recommending matrix to
|
||||
anyone else for now. It needs to be more robust and have a better ux.
|
||||
|
||||
## apis
|
||||
|
||||
Syncing is slow and sends tons of extra data, though sliding sync is
|
||||
aiming to fix it. No comment will be made on sliding sync, as its apis
|
||||
are currently in flux. EDIT: Sliding sync is shaping up quite nicely,
|
||||
but I think there are some mistakes, like `room_name_like` and sorting.
|
||||
|
||||
Similarily, the authentication mess is slated to be replaced with OIDC,
|
||||
so no comment there until it's fleshed out more properly. The current
|
||||
system isn't terrible, but isn't great either. Getting a seamless ux,
|
||||
both for users and server admins, looks like it will be pretty difficult
|
||||
to achieve.
|
||||
|
||||
A lot of apis are unergonomic or difficult to use. For example, every
|
||||
event/message needs to be sent with a random transaction id, which is
|
||||
annoying when trying to use webhooks. The api doesn't use one event model:
|
||||
there are events, events without room_id, stripped state events, and
|
||||
stripped state events with `origin_server_ts`. The application service
|
||||
api doesn't support e2ee without workarounds *yet*.
|
||||
|
||||
The media repository (media repo) lets users store blobs, but it feels
|
||||
tacked on instead of part of the protocol. Each piece of media is stored
|
||||
on a single canonicical and trusted server (aka point of failure), unlike
|
||||
rooms. There is no way to delete uploaded blobs from the media repo.
|
||||
|
||||
The apis are trying to be generic while geared towards instant messaging:
|
||||
`/search` is only indexes blessed keys and even types, which are
|
||||
different per server. This could be fixed by having a blessed `body`
|
||||
property that is always indexed, regardless of event type. Events are
|
||||
able to form graphs but can't be recursively queried. Rooms didn't
|
||||
have types until relatively recently, and most clients will display
|
||||
all rooms regardless of type anyway. There also isn't any subtyping
|
||||
(mutable types, ie. to convert a room between a normal room and dm).
|
||||
|
||||
I know instant messaging is the main puropse of matrix,
|
||||
but for medium-large communities I *really* wish there
|
||||
was some form of forum system. Something similar to
|
||||
tildes.net would be ideal, especially the [hierarchical
|
||||
tagging](https://docs.tildes.net/instructions/hierarchical-tags)
|
||||
and [comment
|
||||
labelling](https://docs.tildes.net/instructions/commenting-on-tildes#labelling-comments),
|
||||
though the extra sorting/filtering is probably too much to ask.
|
||||
|
||||
## bots
|
||||
|
||||
Bots are hard to get right, as there's no way to use structured commands
|
||||
(ie. discord and telegram slash commands). Bots need to parse the
|
||||
message's body. This has problems, since reply fallbacks exist. Parsing
|
||||
mentions and other things from the body is also difficult, requiring
|
||||
parsing html.
|
||||
|
||||
There's no way to specify interactions, like buttons, menus, canned
|
||||
responses, preset reactions, etc. Reaction-based uis are the best to
|
||||
currently exist, but it takes n + 1 events where n is the number of
|
||||
"buttons".
|
||||
|
||||
Matrix seems to be heading towards a widget-based ui system, where
|
||||
widgets are embedded webpages/webapps. Clients that want to support
|
||||
widgets would need to embed an entire web browser. Even though it could
|
||||
be more flexible, it would be much more annoying for bot developers to
|
||||
learn an entirely separate widget api as well as well as use html/css/js
|
||||
instead of matrix events and json. Since widgets seem to be able to do
|
||||
interactions on behalf of the user(?), clients need to take extra care
|
||||
in implementing sandboxing and access control. Widget ui would also
|
||||
wouldn't fit in as well with the rest of the client. Widgets might
|
||||
have issues with privacy and tracking because they can use arbitrary
|
||||
html/js/css.
|
||||
|
||||
Bots can use the full set of html, including tables and
|
||||
details/summary. However, different clients may only support certain
|
||||
subsets of html.
|
||||
|
||||
## potpourri
|
||||
|
||||
Matrix can be generalized as logs of arbitrary json events combined
|
||||
with a crdt of map<(type, state), event>. Although this could be led
|
||||
to *so many* use cases, the official client-server api isn't flexible
|
||||
enough as mentioned above. However, it's entirely possible to use the
|
||||
core matrix protocol with a custom client-server api + custom client,
|
||||
activitypub style.
|
||||
|
||||
Messages can either be text or a single file, but not both (like a file
|
||||
with a comment) or multiple attachments.
|
||||
|
||||
Clients are missing features or are buggy. A lot of spec is dictated by
|
||||
synapse and element, even when spec.matrix.org says otherwise. Old and
|
||||
buggy room versions exist in the wild, with no incentive to upgrade.
|
||||
Federation is excellent in theory, but in practice servers tend to drop
|
||||
events.
|
||||
|
||||
Power levels are pretty rudimentary. There's no way allow/deny specific
|
||||
rel_types, only event types. There is no role based access control.
|
||||
|
||||
There's no way to peek into dms. (Or federated rooms, for that matter.)
|
||||
|
||||
There are many msc (matrix spec change) proposals that seem to have
|
||||
gotten stuck, like custom emoji/stickers.
|
||||
|
||||
Room-specific user displaynames/avatars can be overwritten when the
|
||||
global displayname/avatar is changed.
|
||||
|
||||
Anything added to spec can't be removed later, which is to be expected
|
||||
for a protocol. But when mscs are opened, events are sent with unstable
|
||||
identifiers. Clients later will need to support both the official type
|
||||
and unstable identifier to support past events.
|
||||
|
||||
Moderation is lacking, and it's pretty much required to use a bot
|
||||
([mjolnir](https://github.com/matrix-org/mjolnir)) (not that bad,
|
||||
but a bit annoying for smaller rooms). When cleaning up spam, a
|
||||
redaction event must be sent for each message/event - bulk redactions
|
||||
([msc2244](https://github.com/matrix-org/matrix-spec-proposals/pull/2244))
|
||||
have been merged but isn't in spec and doesn't seem to be implemented
|
||||
by any server.
|
||||
|
||||
`GET /state` returns the content of a state event, not the full event
|
||||
itself.
|
||||
|
||||
## conclusion
|
||||
|
||||
7.8/10 too much water
|
||||
|
||||
## wishlist
|
||||
|
||||
In no particular order. These requests shouldn't be too difficult
|
||||
to implement, but would improve usability by *so* much. These aren't
|
||||
nearly fleshed out to be full mscs.
|
||||
|
||||
- Cleanup threads and improve usability
|
||||
- ~~`DELETE /rooms/{roomId}/threads/{eventId}` to stop participating in
|
||||
a thread~~
|
||||
- `PUT /rooms/{roomId}/threads/{eventId}/participation` to change
|
||||
whether you're participating in or aren't participating in a thread.
|
||||
- Thread-only rooms.
|
||||
- Redo power levels
|
||||
- Base them on `(from_event_type, rel_type, to_event_type)` tuples rather
|
||||
than `(event_type)` alone.
|
||||
- Implement rbac (roles). Ideally, it would use explicit deny as the
|
||||
permission model. May be blocked on "give every member a role" use cases.
|
||||
- Add a way to make spaces sync subsets of state with the child
|
||||
rooms. msc3216 and msc2962 exist for power levels, which may be enough
|
||||
for most use cases
|
||||
- Add a way to mute rooms temporarily. Maybe add a push rule condition
|
||||
for this, or better yet redo push rules entirely. (I know the whole
|
||||
"don't rewrite what works", but seriously...)
|
||||
- Make aliases and visibility less confusing. There's room visibility,
|
||||
history visibility, local/published/main alias(es), and the
|
||||
room directory. In ui, room directory could be merged into room
|
||||
visibility. I'm not sure how to simplify aliases without reducing
|
||||
functionality.
|
||||
- Improve /notifications to be more like a proper inbox
|
||||
- Use intentional mentions (even in encrypeted rooms) to populate the list
|
||||
- `DELETE /notifications` + `DELETE /notifications/{eventId}` along
|
||||
with automatically removing old notifications to enhance usability
|
||||
- `PUT /notifications/{eventId}` to bookmark an event for later (though,
|
||||
this may be better served with "starred/bookmarked messages")
|
||||
- Some way to reorder notifications? Maybe the `PUT` endpoint could
|
||||
take an "order" key.
|
||||
- Add a `m.preset_reactions` or `m.interactions` key for bots.
|
||||
- Bot supplied edits or annotations?
|
||||
- `unread_count` to view the number of unread messages in a room, see msc2654
|
||||
- This might only be something I want, but another presence/status type
|
||||
different from online for when you're explicitly available to talk to
|
||||
woul be nice. I really want to be able to have a clear split between
|
||||
"being on the internet" and "willing to have my attention taken"
|
||||
|
||||
<!--
|
||||
## the far future?
|
||||
|
||||
Some random ideas on how matrix could look in the far future...
|
||||
|
||||
Memberships could be made ephemeral. A user's membership could be
|
||||
`allow` (invite, join) or `deny` (kick, leave, ban). In private rooms,
|
||||
the default membership would be `deny` and in public rooms it would
|
||||
be `allow`. When a member's membership is explicitly set to `allow`,
|
||||
they are invited to the room. A member can send a special ephemeral
|
||||
(or timeline) event to tell other servers they have acknowledged the
|
||||
membership change and are now joined. Of course in practice, more
|
||||
memberships/states would need to be added, like `null`/`default` or
|
||||
`knock`. The main problem would be making restricted rooms work.
|
||||
|
||||
No matter how many apis you try to add, some use case will need something
|
||||
special. I wonder how feasable it would be to use wasm instead of
|
||||
room versions for permissions, custom sorting/filtering/indexing,
|
||||
and deriving custom unsigned/state. It could even do state resolution,
|
||||
although this is extremely difficult, may have security issues, and is
|
||||
probably impractical. The main problem is wasm would need to be embedded
|
||||
in the event or be placed in the media repo.
|
||||
-->
|
||||
:::
|
13
meta.html
Normal file
13
meta.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ayo</title>
|
||||
<meta charset="utf8">
|
||||
<meta content="metatesting" property="og:site_name" />
|
||||
<meta content="title4" property="og:title" />
|
||||
<meta content="description4" property="og:description" />
|
||||
<meta content="image" property="og:type" />
|
||||
<meta content="https://celery.eu.org/media/ketchup.jpg" property="og:image" />
|
||||
</head>
|
||||
</html>
|
||||
|
29
mindus.html
Normal file
29
mindus.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ayo</title>
|
||||
<meta charset="utf8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
<body>
|
||||
<h1>hello</h1>
|
||||
<pre id="output"></pre>
|
||||
<form id="form"><input id="input" /></form>
|
||||
<script>
|
||||
const form = document.getElementById("form");
|
||||
const input = document.getElementById("input");
|
||||
const output = document.getElementById("output");
|
||||
|
||||
const ws = new WebSocket(`wss://${location.host}/mindus/live`);
|
||||
ws.onmessage = ({ data }) => output.innerText += data + "\n";
|
||||
|
||||
form.addEventListener("submit", (e) => {
|
||||
e.preventDefault();
|
||||
output.innerText += `=> ${input.value}\n`;
|
||||
ws.send(input.value + "\n");
|
||||
input.value = "";
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
18
ml.html
Normal file
18
ml.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8" />
|
||||
<title>machine learning</title>
|
||||
<link rel="stylesheet" href="/assets/style2.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>machine learning</h1>
|
||||
</header>
|
||||
<section>
|
||||
<p>
|
||||
todo: write stuff here. start with gradiant descent, then perceptrons, networks, rnns, transformers
|
||||
</p>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
34
nix.html
Normal file
34
nix.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8" />
|
||||
<title>nix</title>
|
||||
<link rel="stylesheet" href="/assets/style2.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>nix</h1>
|
||||
</header>
|
||||
<section>
|
||||
<h2>the language</h2>
|
||||
<p>Nix is a language. It has numbers. You can add them.</p>
|
||||
<pre><code><span class="num">1</span> <span class="op">+</span> <span class="num">2</span></code></pre>
|
||||
<div class="eval">= 3</div>
|
||||
<p>The above expression evaluates to <code><span class="num">3</span></code>. If you have nix installed, try running <code>nix repl</code> and pasting that in.</p>
|
||||
<pre><code><span class="str">"hello nix!"</span></code></pre>
|
||||
<div class="eval">= "hello nix!"</div>
|
||||
<p>Here you can see a string.</p>
|
||||
<pre><code><span class="str">"escapes\nand\nnewlines"</span> <span class="op">==</span> <span class="str">"escapes
|
||||
and
|
||||
newlines"</span></code></pre>
|
||||
<div class="eval">= true</div>
|
||||
<p>Nix has booleans.</p>
|
||||
<pre><code><span class="op">!(</span><span class="key">true</span> <span class="op">&&</span> <span class="key">false</span><span class="op">) || </span><span class="key">false</span></code></pre>
|
||||
<div class="eval">= true</div>
|
||||
<p>Nix has sets, key value pairs known as records, maps, or objects in other lanugages. They can be nested.</p>
|
||||
<pre><code><span class="op">{ </span><span class="id">foo</span> <span class="op">=</span> <span class="num">123</span><span class="op">; }.</span><span class="id">foo</span></code></pre>
|
||||
<div class="eval">= 123</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
233
nix.md
Normal file
233
nix.md
Normal file
|
@ -0,0 +1,233 @@
|
|||
::: header
|
||||
# nix
|
||||
:::
|
||||
::: section
|
||||
## nix, the language
|
||||
|
||||
Nix is a language. It has numbers. You can add them.
|
||||
|
||||
```nix
|
||||
1 + 2
|
||||
```
|
||||
|
||||
<div class="eval">= 3</div>
|
||||
|
||||
The above expression evaluates to `3`. If you have nix installed, try
|
||||
running `nix repl` and pasting that in. Nix also has strings.
|
||||
|
||||
```nix
|
||||
"hello nix!"
|
||||
```
|
||||
<div class="eval">= "hello nix!"</div>
|
||||
|
||||
```nix
|
||||
"escapes\nand\nnewlines" == "escapes
|
||||
and
|
||||
newlines"
|
||||
```
|
||||
<div class="eval">= true</div>
|
||||
|
||||
Nix has booleans.
|
||||
|
||||
```nix
|
||||
!(true && false) || false
|
||||
```
|
||||
<div class="eval">= true</div>
|
||||
|
||||
Nix has sets, or key value pairs. These are known as records, maps,
|
||||
or objects in other lanugages.
|
||||
|
||||
```nix
|
||||
{ foo = 123; }.foo
|
||||
```
|
||||
<div class="eval">= 123</div>
|
||||
|
||||
Sets can be nested.
|
||||
|
||||
```nix
|
||||
# There isn't any hard rule on which style to use
|
||||
{ foo = { bar = "baz"; }; } == { foo.bar = "baz"; }
|
||||
```
|
||||
<div class="eval">= true</div>
|
||||
|
||||
The `let` and `in` keyword defines a variable for a given scope.
|
||||
|
||||
```nix
|
||||
let
|
||||
foo = 3;
|
||||
bar = foo * 3;
|
||||
in
|
||||
bar
|
||||
```
|
||||
<div class="eval">= 9</div>
|
||||
|
||||
Nix has pure functions that transform inputs to outputs without side
|
||||
effects.
|
||||
|
||||
```nix
|
||||
let
|
||||
incr = n: n + 1;
|
||||
in
|
||||
incr 5
|
||||
```
|
||||
<div class="eval">= 6</div>
|
||||
|
||||
To use multiple parameters, either pass a set or use currying (create
|
||||
a function that returns another function).
|
||||
|
||||
```nix
|
||||
let
|
||||
addSet = input: input.a + input.b;
|
||||
addDestructure = { a, b }: a + b;
|
||||
addCurry = a: b: a + b;
|
||||
in {
|
||||
foo = addSet { a = 10; b = 20; };
|
||||
bar = addDestructure { a = 10; b = 20; };
|
||||
baz = addCurry 30 40;
|
||||
}
|
||||
```
|
||||
<div class="eval">= { bar = 30; baz = 70; foo = 30; }</div>
|
||||
|
||||
Destructuring optional fields.
|
||||
|
||||
```nix
|
||||
let
|
||||
# this will use b = 5 if b is not defined
|
||||
addOptional = { a, b ? 5 }: a + b;
|
||||
in {
|
||||
foo = addOptional { a = 1; };
|
||||
bar = addOptional { a = 1; b = 1; };
|
||||
}
|
||||
```
|
||||
<div class="eval">= { bar = 2; foo = 6; }</div>
|
||||
|
||||
The `inherit` keyword.
|
||||
|
||||
```nix
|
||||
let
|
||||
key1 = "something here";
|
||||
key2 = "something else";
|
||||
in {
|
||||
inherit key1 key2;
|
||||
}
|
||||
```
|
||||
<div class="eval">= { key1 = "something here"; key2 = "something else"; }</div>
|
||||
|
||||
Nix provides many builtin functions in the `builtins` set. If you're
|
||||
using the repl, press <kbd>tab</kbd> to get a list of them.
|
||||
|
||||
```nix
|
||||
{
|
||||
system = builtins.currentSystem;
|
||||
}
|
||||
```
|
||||
<div class="eval">= { system = "x86_64-linux"; }</div>
|
||||
|
||||
Finally, nix has a path type. When
|
||||
|
||||
```nix
|
||||
{
|
||||
sourceCode = ./path/to/sources;
|
||||
}
|
||||
```
|
||||
<div class="eval">= { system = "x86_64-linux"; }</div>
|
||||
:::
|
||||
|
||||
::: section
|
||||
## nix, the build tool
|
||||
|
||||
Nix provides a builtin function to create *derivations*. These are special
|
||||
descriptions of how to derive build outputs from source code. Build
|
||||
outputs can be anything, such as binaries, shared libraries, or a
|
||||
docker tarball.
|
||||
|
||||
```nix
|
||||
derivation {
|
||||
name = "foobar";
|
||||
# here is where you'd
|
||||
# src = ./path/to/source
|
||||
|
||||
# the $out variable has the location of where the build outputs should go
|
||||
# the build outputs can be a file or a folder of any structure
|
||||
# the $src variable has the location of the sources
|
||||
builder = "/bin/sh";
|
||||
args = ["-c" "echo 'Hello, derivation!' > $out"];
|
||||
|
||||
system = builtins.currentSystem;
|
||||
}
|
||||
```
|
||||
<div class="eval">= derivation «/nix/store/ha5hof1nput-foobar.drv»</div>
|
||||
|
||||
To build this, use `:b (copy-pasted code)` in the repl. It should print
|
||||
a path to the build outputs.
|
||||
|
||||
[NixOS/nixpkgs](https://github.com/NixOS/nixpkgs) is a combination package
|
||||
repository and standard library, containing thousands of derivations and
|
||||
functions. Using the `derivation` function is almost always unnecessary,
|
||||
since nixpkgs probably has a helper for whatever language or build system
|
||||
you want to use. Even if you need to manually make a derivation, there is
|
||||
`mkDerivation` which is a bit higher level than `derivation`.
|
||||
|
||||
[Nix flakes](https://nixos.wiki/wiki/Flakes) are how derivations and
|
||||
packages are managed, and is what you probably want to be using.
|
||||
|
||||
You've probably heard it before, but it's worth repeating: although
|
||||
more difficult to set up, using nix over other build systems gives you
|
||||
reproducability. This means that the same nix expression and source code
|
||||
will *always* produce the same outputs. If it works on one nix user's
|
||||
machine, it will work every nix user's machine. If a build fails, it
|
||||
fails for everyone.
|
||||
|
||||
Flakes work by taking in an explicit set of inputs along with the build
|
||||
steps. Anything that isn't explicitly defined as an input, whether
|
||||
it's binaries, paths, or environment variables, is not given to the
|
||||
derivation's builder.
|
||||
|
||||
Here's an example flake:
|
||||
|
||||
```nix
|
||||
{
|
||||
description = "any useful description here";
|
||||
|
||||
inputs = {
|
||||
# this is a flake identifier
|
||||
nixpkgs.url = "github:NixOS/nixpkgs";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs }: {
|
||||
packages.x86_64-linux.default = inputs.nixpkgs.legacyPackages.x86_64-linux.hello;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This code should be put inside `flake.nix` at the root of a git
|
||||
repository. Running `nix flake new hello-world` would create a directory
|
||||
called `hello-world` pre-initialized with a flake like this. From there,
|
||||
run `nix build` to build (the binary will be in `result/bin/hello`), or
|
||||
`nix run` to build and run the binary.
|
||||
|
||||
Maybe you've noticed already, but the flake isn't really building anything
|
||||
new - it's exporting an already made derivation from nixpkgs. Here is
|
||||
another flake:
|
||||
|
||||
```nix
|
||||
{
|
||||
description = "any useful description here";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs";
|
||||
|
||||
outputs = { self, nixpkgs }: let
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
||||
in {
|
||||
packages.x86_64-linux.default = pkgs.stdenv.mkDerivation {
|
||||
name = "hello";
|
||||
src = self;
|
||||
buildPhase = "echo '#!/bin/sh\necho hello world' > bin; chmod +x bin";
|
||||
installPhase = "mkdir -p $out/bin; mv bin $out/bin/hello";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
<div style="min-height:500px"></div>
|
25
no.html
Normal file
25
no.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ayo</title>
|
||||
<meta charset="utf8">
|
||||
<meta content="no." property="og:title" />
|
||||
<meta content="no." property="og:description" />
|
||||
<meta content="https://i.redd.it/o0gjdu4ivlx51.jpg" property="og:image" />
|
||||
<meta content="#ff0000" data-react-helmet="true" name="theme-color" />
|
||||
<link rel="stylesheet" href="/assets/style.css"></link>
|
||||
</head>
|
||||
<body>
|
||||
<h1>no.</h1>
|
||||
<ul>
|
||||
<li>no</li>
|
||||
<li>no.</li>
|
||||
<li><a href="https://en.uncyclopedia.co/wiki/Nooooooooooooooooooo!">no</a></li>
|
||||
<li><a href="https://www.reddit.com/r/no/top/?t=all">no</a></li>
|
||||
<li>No</li>
|
||||
<li><a href="https://www.merriam-webster.com/dictionary/no">no</a></li>
|
||||
<li>no!</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
15
pnpm-lock.yaml
Normal file
15
pnpm-lock.yaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
lockfileVersion: 5.3
|
||||
|
||||
specifiers:
|
||||
xterm-addon-fit: ^0.5.0
|
||||
|
||||
dependencies:
|
||||
xterm-addon-fit: 0.5.0
|
||||
|
||||
packages:
|
||||
|
||||
/xterm-addon-fit/0.5.0:
|
||||
resolution: {integrity: sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==}
|
||||
peerDependencies:
|
||||
xterm: ^4.0.0
|
||||
dev: false
|
8
public/FFFB-dendrite.md
Normal file
8
public/FFFB-dendrite.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# dendrite
|
||||
|
||||
I've been running Dendrite for over a week now, and there are signifigant performance improvements.
|
||||
|
||||
If I knew how Dendrite currently was, though, I probably wouldn't switch yet. It's currently missing a few features.
|
||||
|
||||
For now, it works. Hopefully it will get better over time.
|
||||
|
4
public/FFFC-synapse.md
Normal file
4
public/FFFC-synapse.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# synapse
|
||||
|
||||
synapse is a literal resource management game on a small vps change my mind
|
||||
|
22
public/FFFD-todo.md
Normal file
22
public/FFFD-todo.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# todo list
|
||||
|
||||
## done
|
||||
|
||||
- get a server
|
||||
- get a domain
|
||||
- get a ssl certificate
|
||||
- make a file server
|
||||
- make a [server stats](/stats) page
|
||||
- set up synapse
|
||||
- set up [cinny](/cinny/)
|
||||
|
||||
## todo
|
||||
|
||||
- move to dendrite, when it works
|
||||
- set up a git server
|
||||
- file uploading
|
||||
- gemini capsule
|
||||
- improve stats page
|
||||
- get my own domain? (current one from [sky](https://skybldev.eu.org), but it will be hard to switch because of the matrix server)
|
||||
- temporary pastebin
|
||||
|
16
public/FFFE-symbols.md
Normal file
16
public/FFFE-symbols.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# symbols
|
||||
|
||||
for copying and pasting
|
||||
|
||||
- `°` degrees
|
||||
- `™` tm
|
||||
- `½` half
|
||||
- `¼` quarter
|
||||
- `²` square
|
||||
- `³` cube
|
||||
- `√` sqrt
|
||||
- `‰` perthousanth
|
||||
- `§` section
|
||||
- `¶` paragraph
|
||||
- `•` bullet point
|
||||
|
4
public/FFFF-first.md
Normal file
4
public/FFFF-first.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# first page
|
||||
|
||||
the first page on my site!
|
||||
|
BIN
public/altdrag.zip
Normal file
BIN
public/altdrag.zip
Normal file
Binary file not shown.
BIN
public/amine.png
Normal file
BIN
public/amine.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 242 KiB |
177
public/blender-violet.xml
Normal file
177
public/blender-violet.xml
Normal file
|
@ -0,0 +1,177 @@
|
|||
<!-- stolen from https://github.com/kame404/Blender-Themes/ -->
|
||||
<bpy>
|
||||
<Theme>
|
||||
<user_interface>
|
||||
<ThemeUserInterface
|
||||
>
|
||||
<wcol_regular>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_regular>
|
||||
<wcol_tool>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_tool>
|
||||
<wcol_toolbar_item>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_toolbar_item>
|
||||
<wcol_radio>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_radio>
|
||||
<wcol_text>
|
||||
<ThemeWidgetColors
|
||||
item="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_text>
|
||||
<wcol_option>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_option>
|
||||
<wcol_toggle>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_toggle>
|
||||
<wcol_num>
|
||||
<ThemeWidgetColors
|
||||
item="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_num>
|
||||
<wcol_numslider>
|
||||
<ThemeWidgetColors
|
||||
item="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_numslider>
|
||||
<wcol_menu>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eab3"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_menu>
|
||||
<wcol_pulldown>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eab3"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_pulldown>
|
||||
<wcol_menu_back>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_menu_back>
|
||||
<wcol_pie_menu>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_pie_menu>
|
||||
<wcol_tooltip>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_tooltip>
|
||||
<wcol_menu_item>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_menu_item>
|
||||
<wcol_progress>
|
||||
<ThemeWidgetColors
|
||||
inner_sel="#9333eaff"
|
||||
item="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_progress>
|
||||
<wcol_list_item>
|
||||
<ThemeWidgetColors
|
||||
item="#9333eaff"
|
||||
>
|
||||
</ThemeWidgetColors>
|
||||
</wcol_list_item>
|
||||
</ThemeUserInterface>
|
||||
</user_interface>
|
||||
<view_3d>
|
||||
<ThemeView3D
|
||||
frame_current="#9333ea"
|
||||
>
|
||||
</ThemeView3D>
|
||||
</view_3d>
|
||||
<graph_editor>
|
||||
<ThemeGraphEditor
|
||||
frame_current="#9333ea"
|
||||
>
|
||||
</ThemeGraphEditor>
|
||||
</graph_editor>
|
||||
<file_browser>
|
||||
<ThemeFileBrowser
|
||||
selected_file="#9333ea"
|
||||
>
|
||||
</ThemeFileBrowser>
|
||||
</file_browser>
|
||||
<nla_editor>
|
||||
<ThemeNLAEditor
|
||||
frame_current="#9333ea"
|
||||
>
|
||||
</ThemeNLAEditor>
|
||||
</nla_editor>
|
||||
<dopesheet_editor>
|
||||
<ThemeDopeSheet
|
||||
frame_current="#9333ea"
|
||||
>
|
||||
</ThemeDopeSheet>
|
||||
</dopesheet_editor>
|
||||
<image_editor>
|
||||
<ThemeImageEditor
|
||||
frame_current="#9333ea"
|
||||
>
|
||||
</ThemeImageEditor>
|
||||
</image_editor>
|
||||
<sequence_editor>
|
||||
<ThemeSequenceEditor
|
||||
frame_current="#9333ea"
|
||||
>
|
||||
</ThemeSequenceEditor>
|
||||
</sequence_editor>
|
||||
<properties>
|
||||
<ThemeProperties
|
||||
match="#9333ea"
|
||||
active_modifier="#9333eaff"
|
||||
>
|
||||
</ThemeProperties>
|
||||
</properties>
|
||||
<outliner>
|
||||
<ThemeOutliner
|
||||
selected_highlight="#3b145e"
|
||||
active="#581f8c"
|
||||
>
|
||||
</ThemeOutliner>
|
||||
</outliner>
|
||||
<clip_editor>
|
||||
<ThemeClipEditor
|
||||
frame_current="#9333ea"
|
||||
>
|
||||
</ThemeClipEditor>
|
||||
</clip_editor>
|
||||
</Theme>
|
||||
<ThemeStyle>
|
||||
</ThemeStyle>
|
||||
</bpy>
|
BIN
public/corpus.txt.bz2
Normal file
BIN
public/corpus.txt.bz2
Normal file
Binary file not shown.
19
public/dogsearch/index.html
Normal file
19
public/dogsearch/index.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>dog search</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<script src="script.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>dog search</h1>
|
||||
<main>
|
||||
<h2 id="count"></h2>
|
||||
<pre id="grid"></pre>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
50
public/dogsearch/script.js
Normal file
50
public/dogsearch/script.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
const rnd = (arr) => arr[Math.floor(Math.random() * arr.length)];
|
||||
const grid = [];
|
||||
const size = 1000;
|
||||
|
||||
let count = 0;
|
||||
for (let i = 0; i < size; i++) {
|
||||
grid.push("");
|
||||
for (let j = 0; j < size; j++) {
|
||||
grid[i] += rnd(["d", "o", "g"]);
|
||||
if (check(i, j)) count++;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("grid").innerText = grid.join("\n");
|
||||
document.getElementById("count").innerText = "There are " + count + " dogs";
|
||||
|
||||
function check(i, j) {
|
||||
switch (grid[i][j]) {
|
||||
case "d":
|
||||
if (!grid[i - 1]) break;
|
||||
if (grid[i - 1] == "d") break;
|
||||
if (grid[i - 2]) {
|
||||
if (grid[i - 1][j] == "o" && grid[i - 2][j] == "g") return true;
|
||||
if (grid[i - 1][j - 1] == "o" && grid[i - 2][j - 2] == "g")
|
||||
return true;
|
||||
if (grid[i - 1][j + 1] == "o" && grid[i - 2][j + 2] == "g")
|
||||
return true;
|
||||
}
|
||||
if (grid[i][j + 1] == "o" && grid[i][j + 2] == "g") return true;
|
||||
if (grid[i][j - 1] == "o" && grid[i][j - 2] == "g") return true;
|
||||
break;
|
||||
case "g":
|
||||
if (!grid[i - 1]) break;
|
||||
if (grid[i - 1][j] == "g") break;
|
||||
if (grid[i - 2]) {
|
||||
if (grid[i - 1][j] == "o" && grid[i - 2][j] == "d") return true;
|
||||
if (grid[i - 1][j - 1] == "o" && grid[i - 2][j - 2] == "d")
|
||||
return true;
|
||||
if (grid[i - 1][j + 1] == "o" && grid[i - 2][j + 2] == "d")
|
||||
return true;
|
||||
}
|
||||
if (grid[i][j + 1] == "o" && grid[i][j + 2] == "d") return true;
|
||||
if (grid[i][j - 1] == "o" && grid[i][j - 2] == "d") return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
10
public/dogsearch/style.css
Normal file
10
public/dogsearch/style.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
body {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
margin: 2em;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 1em;
|
||||
display: block;
|
||||
}
|
||||
|
14
public/dots/.alacritty.yml
Normal file
14
public/dots/.alacritty.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
colors:
|
||||
primary:
|
||||
background: '#1A1D2B'
|
||||
key_bindings:
|
||||
- { key: "N", mods: "control|shift", action: SpawnNewInstance }
|
||||
|
||||
font:
|
||||
normal:
|
||||
family: Iosevka Zesty
|
||||
size: 8
|
||||
|
||||
window:
|
||||
opacity: 0.9
|
||||
|
1
public/dots/.config/bspwm
Symbolic link
1
public/dots/.config/bspwm
Symbolic link
|
@ -0,0 +1 @@
|
|||
/home/zestylemonade/.config/bspwm
|
1
public/dots/.config/helix
Symbolic link
1
public/dots/.config/helix
Symbolic link
|
@ -0,0 +1 @@
|
|||
/home/zestylemonade/.config/helix/
|
1
public/dots/.config/nvim
Symbolic link
1
public/dots/.config/nvim
Symbolic link
|
@ -0,0 +1 @@
|
|||
/home/zestylemonade/.config/nvim
|
1
public/dots/.config/polybar
Symbolic link
1
public/dots/.config/polybar
Symbolic link
|
@ -0,0 +1 @@
|
|||
/home/zestylemonade/.config/polybar
|
1
public/dots/.config/rofi
Symbolic link
1
public/dots/.config/rofi
Symbolic link
|
@ -0,0 +1 @@
|
|||
/home/zestylemonade/.config/rofi
|
1
public/dots/.config/sxhkd
Symbolic link
1
public/dots/.config/sxhkd
Symbolic link
|
@ -0,0 +1 @@
|
|||
/home/zestylemonade/.config/sxhkd
|
1
public/dots/.config/touchegg
Symbolic link
1
public/dots/.config/touchegg
Symbolic link
|
@ -0,0 +1 @@
|
|||
/home/zestylemonade/.config/touchegg
|
267
public/dots/.z.sh
Normal file
267
public/dots/.z.sh
Normal file
|
@ -0,0 +1,267 @@
|
|||
# Copyright (c) 2009 rupa deadwyler. Licensed under the WTFPL license, Version 2
|
||||
|
||||
# maintains a jump-list of the directories you actually use
|
||||
#
|
||||
# INSTALL:
|
||||
# * put something like this in your .bashrc/.zshrc:
|
||||
# . /path/to/z.sh
|
||||
# * cd around for a while to build up the db
|
||||
# * PROFIT!!
|
||||
# * optionally:
|
||||
# set $_Z_CMD in .bashrc/.zshrc to change the command (default z).
|
||||
# set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z).
|
||||
# set $_Z_MAX_SCORE lower to age entries out faster (default 9000).
|
||||
# set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
|
||||
# set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself.
|
||||
# set $_Z_EXCLUDE_DIRS to an array of directories to exclude.
|
||||
# set $_Z_OWNER to your username if you want use z while sudo with $HOME kept
|
||||
#
|
||||
# USE:
|
||||
# * z foo # cd to most frecent dir matching foo
|
||||
# * z foo bar # cd to most frecent dir matching foo and bar
|
||||
# * z -r foo # cd to highest ranked dir matching foo
|
||||
# * z -t foo # cd to most recently accessed dir matching foo
|
||||
# * z -l foo # list matches instead of cd
|
||||
# * z -e foo # echo the best match, don't cd
|
||||
# * z -c foo # restrict matches to subdirs of $PWD
|
||||
# * z -x # remove the current directory from the datafile
|
||||
# * z -h # show a brief help message
|
||||
|
||||
[ -d "${_Z_DATA:-$HOME/.z}" ] && {
|
||||
echo "ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory."
|
||||
}
|
||||
|
||||
_z() {
|
||||
|
||||
local datafile="${_Z_DATA:-$HOME/.z}"
|
||||
|
||||
# if symlink, dereference
|
||||
[ -h "$datafile" ] && datafile=$(readlink "$datafile")
|
||||
|
||||
# bail if we don't own ~/.z and $_Z_OWNER not set
|
||||
[ -z "$_Z_OWNER" -a -f "$datafile" -a ! -O "$datafile" ] && return
|
||||
|
||||
_z_dirs () {
|
||||
[ -f "$datafile" ] || return
|
||||
|
||||
local line
|
||||
while read line; do
|
||||
# only count directories
|
||||
[ -d "${line%%\|*}" ] && echo "$line"
|
||||
done < "$datafile"
|
||||
return 0
|
||||
}
|
||||
|
||||
# add entries
|
||||
if [ "$1" = "--add" ]; then
|
||||
shift
|
||||
|
||||
# $HOME and / aren't worth matching
|
||||
[ "$*" = "$HOME" -o "$*" = '/' ] && return
|
||||
|
||||
# don't track excluded directory trees
|
||||
if [ ${#_Z_EXCLUDE_DIRS[@]} -gt 0 ]; then
|
||||
local exclude
|
||||
for exclude in "${_Z_EXCLUDE_DIRS[@]}"; do
|
||||
case "$*" in "$exclude"*) return;; esac
|
||||
done
|
||||
fi
|
||||
|
||||
# maintain the data file
|
||||
local tempfile="$datafile.$RANDOM"
|
||||
local score=${_Z_MAX_SCORE:-9000}
|
||||
_z_dirs | awk -v path="$*" -v now="$(date +%s)" -v score=$score -F"|" '
|
||||
BEGIN {
|
||||
rank[path] = 1
|
||||
time[path] = now
|
||||
}
|
||||
$2 >= 1 {
|
||||
# drop ranks below 1
|
||||
if( $1 == path ) {
|
||||
rank[$1] = $2 + 1
|
||||
time[$1] = now
|
||||
} else {
|
||||
rank[$1] = $2
|
||||
time[$1] = $3
|
||||
}
|
||||
count += $2
|
||||
}
|
||||
END {
|
||||
if( count > score ) {
|
||||
# aging
|
||||
for( x in rank ) print x "|" 0.99*rank[x] "|" time[x]
|
||||
} else for( x in rank ) print x "|" rank[x] "|" time[x]
|
||||
}
|
||||
' 2>/dev/null >| "$tempfile"
|
||||
# do our best to avoid clobbering the datafile in a race condition.
|
||||
if [ $? -ne 0 -a -f "$datafile" ]; then
|
||||
env rm -f "$tempfile"
|
||||
else
|
||||
[ "$_Z_OWNER" ] && chown $_Z_OWNER:"$(id -ng $_Z_OWNER)" "$tempfile"
|
||||
env mv -f "$tempfile" "$datafile" || env rm -f "$tempfile"
|
||||
fi
|
||||
|
||||
# tab completion
|
||||
elif [ "$1" = "--complete" -a -s "$datafile" ]; then
|
||||
_z_dirs | awk -v q="$2" -F"|" '
|
||||
BEGIN {
|
||||
q = substr(q, 3)
|
||||
if( q == tolower(q) ) imatch = 1
|
||||
gsub(/ /, ".*", q)
|
||||
}
|
||||
{
|
||||
if( imatch ) {
|
||||
if( tolower($1) ~ q ) print $1
|
||||
} else if( $1 ~ q ) print $1
|
||||
}
|
||||
' 2>/dev/null
|
||||
|
||||
else
|
||||
# list/go
|
||||
local echo fnd last list opt typ
|
||||
while [ "$1" ]; do case "$1" in
|
||||
--) while [ "$1" ]; do shift; fnd="$fnd${fnd:+ }$1";done;;
|
||||
-*) opt=${1:1}; while [ "$opt" ]; do case ${opt:0:1} in
|
||||
c) fnd="^$PWD $fnd";;
|
||||
e) echo=1;;
|
||||
h) echo "${_Z_CMD:-z} [-cehlrtx] args" >&2; return;;
|
||||
l) list=1;;
|
||||
r) typ="rank";;
|
||||
t) typ="recent";;
|
||||
x) sed -i -e "\:^${PWD}|.*:d" "$datafile";;
|
||||
esac; opt=${opt:1}; done;;
|
||||
*) fnd="$fnd${fnd:+ }$1";;
|
||||
esac; last=$1; [ "$#" -gt 0 ] && shift; done
|
||||
[ "$fnd" -a "$fnd" != "^$PWD " ] || list=1
|
||||
|
||||
# if we hit enter on a completion just go there
|
||||
case "$last" in
|
||||
# completions will always start with /
|
||||
/*) [ -z "$list" -a -d "$last" ] && builtin cd "$last" && return;;
|
||||
esac
|
||||
|
||||
# no file yet
|
||||
[ -f "$datafile" ] || return
|
||||
|
||||
local cd
|
||||
cd="$( < <( _z_dirs ) awk -v t="$(date +%s)" -v list="$list" -v typ="$typ" -v q="$fnd" -F"|" '
|
||||
function frecent(rank, time) {
|
||||
# relate frequency and time
|
||||
dx = t - time
|
||||
return int(10000 * rank * (3.75/((0.0001 * dx + 1) + 0.25)))
|
||||
}
|
||||
function output(matches, best_match, common) {
|
||||
# list or return the desired directory
|
||||
if( list ) {
|
||||
if( common ) {
|
||||
printf "%-10s %s\n", "common:", common > "/dev/stderr"
|
||||
}
|
||||
cmd = "sort -n >&2"
|
||||
for( x in matches ) {
|
||||
if( matches[x] ) {
|
||||
printf "%-10s %s\n", matches[x], x | cmd
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if( common && !typ ) best_match = common
|
||||
print best_match
|
||||
}
|
||||
}
|
||||
function common(matches) {
|
||||
# find the common root of a list of matches, if it exists
|
||||
for( x in matches ) {
|
||||
if( matches[x] && (!short || length(x) < length(short)) ) {
|
||||
short = x
|
||||
}
|
||||
}
|
||||
if( short == "/" ) return
|
||||
for( x in matches ) if( matches[x] && index(x, short) != 1 ) {
|
||||
return
|
||||
}
|
||||
return short
|
||||
}
|
||||
BEGIN {
|
||||
gsub(" ", ".*", q)
|
||||
hi_rank = ihi_rank = -9999999999
|
||||
}
|
||||
{
|
||||
if( typ == "rank" ) {
|
||||
rank = $2
|
||||
} else if( typ == "recent" ) {
|
||||
rank = $3 - t
|
||||
} else rank = frecent($2, $3)
|
||||
if( $1 ~ q ) {
|
||||
matches[$1] = rank
|
||||
} else if( tolower($1) ~ tolower(q) ) imatches[$1] = rank
|
||||
if( matches[$1] && matches[$1] > hi_rank ) {
|
||||
best_match = $1
|
||||
hi_rank = matches[$1]
|
||||
} else if( imatches[$1] && imatches[$1] > ihi_rank ) {
|
||||
ibest_match = $1
|
||||
ihi_rank = imatches[$1]
|
||||
}
|
||||
}
|
||||
END {
|
||||
# prefer case sensitive
|
||||
if( best_match ) {
|
||||
output(matches, best_match, common(matches))
|
||||
exit
|
||||
} else if( ibest_match ) {
|
||||
output(imatches, ibest_match, common(imatches))
|
||||
exit
|
||||
}
|
||||
exit(1)
|
||||
}
|
||||
')"
|
||||
|
||||
if [ "$?" -eq 0 ]; then
|
||||
if [ "$cd" ]; then
|
||||
if [ "$echo" ]; then echo "$cd"; else builtin cd "$cd"; fi
|
||||
fi
|
||||
else
|
||||
return $?
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
alias ${_Z_CMD:-z}='_z 2>&1'
|
||||
|
||||
[ "$_Z_NO_RESOLVE_SYMLINKS" ] || _Z_RESOLVE_SYMLINKS="-P"
|
||||
|
||||
if type compctl >/dev/null 2>&1; then
|
||||
# zsh
|
||||
[ "$_Z_NO_PROMPT_COMMAND" ] || {
|
||||
# populate directory list, avoid clobbering any other precmds.
|
||||
if [ "$_Z_NO_RESOLVE_SYMLINKS" ]; then
|
||||
_z_precmd() {
|
||||
(_z --add "${PWD:a}" &)
|
||||
: $RANDOM
|
||||
}
|
||||
else
|
||||
_z_precmd() {
|
||||
(_z --add "${PWD:A}" &)
|
||||
: $RANDOM
|
||||
}
|
||||
fi
|
||||
[[ -n "${precmd_functions[(r)_z_precmd]}" ]] || {
|
||||
precmd_functions[$(($#precmd_functions+1))]=_z_precmd
|
||||
}
|
||||
}
|
||||
_z_zsh_tab_completion() {
|
||||
# tab completion
|
||||
local compl
|
||||
read -l compl
|
||||
reply=(${(f)"$(_z --complete "$compl")"})
|
||||
}
|
||||
compctl -U -K _z_zsh_tab_completion _z
|
||||
elif type complete >/dev/null 2>&1; then
|
||||
# bash
|
||||
# tab completion
|
||||
complete -o filenames -C '_z --complete "$COMP_LINE"' ${_Z_CMD:-z}
|
||||
[ "$_Z_NO_PROMPT_COMMAND" ] || {
|
||||
# populate directory list. avoid clobbering other PROMPT_COMMANDs.
|
||||
grep "_z --add" <<< "$PROMPT_COMMAND" >/dev/null || {
|
||||
PROMPT_COMMAND="$PROMPT_COMMAND"$'\n''(_z --add "$(command pwd '$_Z_RESOLVE_SYMLINKS' 2>/dev/null)" 2>/dev/null &);'
|
||||
}
|
||||
}
|
||||
fi
|
34
public/dots/.zshrc
Normal file
34
public/dots/.zshrc
Normal file
|
@ -0,0 +1,34 @@
|
|||
# history
|
||||
HISTFILE=~/.histfile
|
||||
HISTSIZE=1000
|
||||
SAVEHIST=1000
|
||||
setopt histignoredups histignorespace incappendhistory
|
||||
|
||||
# completion
|
||||
zstyle ':completion:*' completer _complete _ignored
|
||||
zstyle ':completion:*' matcher-list '' 'r:|[._-/]=* r:|=*'
|
||||
zstyle :compinstall filename '/home/zestylemonade/.zshrc'
|
||||
autoload -Uz compinit && compinit
|
||||
|
||||
# aliases
|
||||
alias ls="lsd --color=auto --icon=never"
|
||||
alias ll="ls -lh"
|
||||
alias cat="bat"
|
||||
alias vim="vim -p"
|
||||
alias ..="cd .."
|
||||
|
||||
# exports
|
||||
export EDITOR="nvim"
|
||||
export GOPATH="$HOME/.go"
|
||||
export PATH="$PATH:$HOME/.local/bin:$GOPATH/bin"
|
||||
|
||||
# misc
|
||||
. ~/.z.sh
|
||||
bindkey -e
|
||||
unset _Z_RESOLVE_SYMLINKS
|
||||
export _Z_NO_RESOLVE_SYMLINKS=1
|
||||
|
||||
# sugar
|
||||
echo -e "\e[90mlogged in as \e[36m`whoami`\e[0m@\e[34m`hostname`\e[90m!\e[0m"
|
||||
export PS1='%(!.%1F.%8F)%~%f%(0?.. %1F[%B%?%b]%f)%(!.#.>) '
|
||||
|
270
public/dots/nnn.h
Normal file
270
public/dots/nnn.h
Normal file
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* BSD 2-Clause License
|
||||
*
|
||||
* Copyright (C) 2014-2016, Lazaros Koromilas <lostd@2f30.org>
|
||||
* Copyright (C) 2014-2016, Dimitris Papastamos <sin@2f30.org>
|
||||
* Copyright (C) 2016-2022, Arun Prakash Jana <engineerarun@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <curses.h>
|
||||
|
||||
#define CONTROL(c) ((c) & 0x1f)
|
||||
|
||||
#ifndef ESC
|
||||
#define ESC (27)
|
||||
#endif
|
||||
|
||||
#ifndef DEL
|
||||
#define DEL (127)
|
||||
#endif
|
||||
|
||||
/* Supported actions */
|
||||
enum action {
|
||||
SEL_BACK = 1,
|
||||
SEL_OPEN,
|
||||
SEL_NAV_IN,
|
||||
SEL_NEXT,
|
||||
SEL_PREV,
|
||||
SEL_PGDN,
|
||||
SEL_PGUP,
|
||||
SEL_CTRL_D,
|
||||
SEL_CTRL_U,
|
||||
SEL_HOME,
|
||||
SEL_END,
|
||||
SEL_FIRST,
|
||||
SEL_CDHOME,
|
||||
SEL_CDBEGIN,
|
||||
SEL_CDLAST,
|
||||
SEL_CDROOT,
|
||||
SEL_BMOPEN,
|
||||
SEL_REMOTE,
|
||||
SEL_CYCLE,
|
||||
SEL_CYCLER,
|
||||
SEL_CTX1,
|
||||
SEL_CTX2,
|
||||
SEL_CTX3,
|
||||
SEL_CTX4,
|
||||
#ifdef CTX8
|
||||
SEL_CTX5,
|
||||
SEL_CTX6,
|
||||
SEL_CTX7,
|
||||
SEL_CTX8,
|
||||
#endif
|
||||
SEL_MARK,
|
||||
SEL_BMARK,
|
||||
SEL_FLTR,
|
||||
SEL_MFLTR,
|
||||
SEL_HIDDEN,
|
||||
SEL_DETAIL,
|
||||
SEL_STATS,
|
||||
SEL_CHMODX,
|
||||
SEL_ARCHIVE,
|
||||
SEL_SORT,
|
||||
SEL_REDRAW,
|
||||
SEL_SEL,
|
||||
SEL_SELMUL,
|
||||
SEL_SELALL,
|
||||
SEL_SELINV,
|
||||
SEL_SELEDIT,
|
||||
SEL_CP,
|
||||
SEL_MV,
|
||||
SEL_CPMVAS,
|
||||
SEL_RM,
|
||||
SEL_OPENWITH,
|
||||
SEL_NEW,
|
||||
SEL_RENAME,
|
||||
SEL_RENAMEMUL,
|
||||
SEL_UMOUNT,
|
||||
SEL_HELP,
|
||||
SEL_AUTONEXT,
|
||||
SEL_EDIT,
|
||||
SEL_PLUGIN,
|
||||
SEL_SHELL,
|
||||
SEL_LAUNCH,
|
||||
SEL_PROMPT,
|
||||
SEL_LOCK,
|
||||
SEL_SESSIONS,
|
||||
SEL_EXPORT,
|
||||
SEL_TIMETYPE,
|
||||
SEL_QUITCTX,
|
||||
SEL_QUITCD,
|
||||
SEL_QUIT,
|
||||
SEL_QUITERR,
|
||||
#ifndef NOMOUSE
|
||||
SEL_CLICK,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Associate a pressed key to an action */
|
||||
struct key {
|
||||
int sym; /* Key pressed */
|
||||
enum action act; /* Action */
|
||||
};
|
||||
|
||||
static struct key bindings[] = {
|
||||
/* Back */
|
||||
{ KEY_LEFT, SEL_BACK },
|
||||
{ 'n', SEL_BACK },
|
||||
/* Inside or select */
|
||||
{ KEY_ENTER, SEL_OPEN },
|
||||
{ '\r', SEL_OPEN },
|
||||
/* Pure navigate inside */
|
||||
{ KEY_RIGHT, SEL_NAV_IN },
|
||||
{ 'i', SEL_NAV_IN },
|
||||
/* Next */
|
||||
{ 'e', SEL_NEXT },
|
||||
{ KEY_DOWN, SEL_NEXT },
|
||||
/* Previous */
|
||||
{ 'u', SEL_PREV },
|
||||
{ KEY_UP, SEL_PREV },
|
||||
/* Page down */
|
||||
{ KEY_NPAGE, SEL_PGDN },
|
||||
/* Page up */
|
||||
{ KEY_PPAGE, SEL_PGUP },
|
||||
/* Ctrl+D */
|
||||
{ 'E', SEL_CTRL_D },
|
||||
/* Ctrl+U */
|
||||
{ 'U', SEL_CTRL_U },
|
||||
/* First entry */
|
||||
{ KEY_HOME, SEL_HOME },
|
||||
{ 'g', SEL_HOME },
|
||||
/* Last entry */
|
||||
{ KEY_END, SEL_END },
|
||||
{ 'G', SEL_END },
|
||||
/* Go to first file */
|
||||
{ '\'', SEL_FIRST },
|
||||
/* HOME */
|
||||
{ '~', SEL_CDHOME },
|
||||
/* Initial directory */
|
||||
{ '@', SEL_CDBEGIN },
|
||||
/* Last visited dir */
|
||||
{ '-', SEL_CDLAST },
|
||||
/* Go to / */
|
||||
{ '`', SEL_CDROOT },
|
||||
/* Leader key */
|
||||
{ '_', SEL_BMOPEN },
|
||||
/* Connect to server over SSHFS */
|
||||
{ 'c', SEL_REMOTE },
|
||||
/* Cycle contexts in forward direction */
|
||||
{ '\t', SEL_CYCLE },
|
||||
/* Cycle contexts in reverse direction */
|
||||
{ KEY_BTAB, SEL_CYCLER },
|
||||
/* Go to/create context N */
|
||||
{ '1', SEL_CTX1 },
|
||||
{ '2', SEL_CTX2 },
|
||||
{ '3', SEL_CTX3 },
|
||||
{ '4', SEL_CTX4 },
|
||||
#ifdef CTX8
|
||||
{ '5', SEL_CTX5 },
|
||||
{ '6', SEL_CTX6 },
|
||||
{ '7', SEL_CTX7 },
|
||||
{ '8', SEL_CTX8 },
|
||||
#endif
|
||||
/* Mark a path to visit later */
|
||||
{ ',', SEL_MARK },
|
||||
/* Create a bookmark */
|
||||
{ 'b', SEL_BMARK },
|
||||
/* Filter */
|
||||
{ '/', SEL_FLTR },
|
||||
/* Toggle filter mode */
|
||||
{ CONTROL('N'), SEL_MFLTR },
|
||||
/* Toggle hide .dot files */
|
||||
{ '.', SEL_HIDDEN },
|
||||
/* Detailed listing */
|
||||
{ 'd', SEL_DETAIL },
|
||||
/* File details */
|
||||
{ 'f', SEL_STATS },
|
||||
{ CONTROL('F'), SEL_STATS },
|
||||
/* Toggle executable status */
|
||||
{ '*', SEL_CHMODX },
|
||||
/* Create archive */
|
||||
{ 'z', SEL_ARCHIVE },
|
||||
/* Sort toggles */
|
||||
{ 't', SEL_SORT },
|
||||
{ CONTROL('T'), SEL_SORT },
|
||||
/* Redraw window */
|
||||
{ CONTROL('L'), SEL_REDRAW },
|
||||
/* Select current file path */
|
||||
{ CONTROL('J'), SEL_SEL },
|
||||
{ ' ', SEL_SEL },
|
||||
/* Toggle select multiple files */
|
||||
{ 'm', SEL_SELMUL },
|
||||
/* Select all files in current dir */
|
||||
{ 'a', SEL_SELALL },
|
||||
/* Invert selection in current dir */
|
||||
{ 'A', SEL_SELINV },
|
||||
/* Copy from selection buffer */
|
||||
{ 'p', SEL_CP },
|
||||
/* Move from selection buffer */
|
||||
{ 'v', SEL_MV },
|
||||
/* Copy/move from selection buffer and rename */
|
||||
{ 'w', SEL_CPMVAS },
|
||||
/* Delete from selection buffer */
|
||||
{ 'x', SEL_RM },
|
||||
/* Open in a custom application */
|
||||
{ 'o', SEL_OPENWITH },
|
||||
/* Create a new file */
|
||||
{ 'l', SEL_NEW },
|
||||
/* Show rename prompt */
|
||||
{ CONTROL('R'), SEL_RENAME },
|
||||
/* Rename contents of current dir */
|
||||
{ 'r', SEL_RENAMEMUL },
|
||||
/* Disconnect a SSHFS mount point */
|
||||
{ 'C', SEL_UMOUNT },
|
||||
/* Show help */
|
||||
{ '?', SEL_HELP },
|
||||
/* Quit a context */
|
||||
{ '+', SEL_AUTONEXT },
|
||||
/* Edit in EDITOR */
|
||||
{ 'y', SEL_EDIT },
|
||||
/* Run a plugin */
|
||||
{ ';', SEL_PLUGIN },
|
||||
/* Run command */
|
||||
{ '!', SEL_SHELL },
|
||||
{ CONTROL(']'), SEL_SHELL },
|
||||
/* Launcher */
|
||||
{ '=', SEL_LAUNCH },
|
||||
/* Show command prompt */
|
||||
{ ']', SEL_PROMPT },
|
||||
/* Manage sessions */
|
||||
{ 's', SEL_SESSIONS },
|
||||
/* Export list */
|
||||
{ '>', SEL_EXPORT },
|
||||
/* Set time type */
|
||||
{ 'T', SEL_TIMETYPE },
|
||||
/* Quit a context */
|
||||
{ 'q', SEL_QUITCTX },
|
||||
/* Change dir on quit */
|
||||
{ CONTROL('G'), SEL_QUITCD },
|
||||
/* Quit */
|
||||
{ CONTROL('Q'), SEL_QUIT },
|
||||
/* Quit with an error code */
|
||||
{ 'Q', SEL_QUITERR },
|
||||
#ifndef NOMOUSE
|
||||
{ KEY_MOUSE, SEL_CLICK },
|
||||
#endif
|
||||
};
|
BIN
public/from-javascript-to-rust.pdf
Normal file
BIN
public/from-javascript-to-rust.pdf
Normal file
Binary file not shown.
1
public/iosevka-zesty/.uuid
Normal file
1
public/iosevka-zesty/.uuid
Normal file
|
@ -0,0 +1 @@
|
|||
ca645177-1508-4e84-8259-9017e79e6c91
|
110
public/iosevka-zesty/LICENSE.md
Normal file
110
public/iosevka-zesty/LICENSE.md
Normal file
|
@ -0,0 +1,110 @@
|
|||
Copyright (c) 2015-2022, Renzhi Li (aka. Belleve Invis, belleve@typeof.net)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
--------------------------
|
||||
|
||||
|
||||
SIL Open Font License v1.1
|
||||
====================================================
|
||||
|
||||
|
||||
Preamble
|
||||
----------
|
||||
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
|
||||
Definitions
|
||||
-------------
|
||||
|
||||
`"Font Software"` refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
`"Reserved Font Name"` refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
`"Original Version"` refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
`"Modified Version"` refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
`"Author"` refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
|
||||
Permission & Conditions
|
||||
------------------------
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1. Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2. Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3. No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4. The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5. The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
|
||||
|
||||
Termination
|
||||
-----------
|
||||
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
BIN
public/iosevka-zesty/iosevka-zesty-bold.ttf
Normal file
BIN
public/iosevka-zesty/iosevka-zesty-bold.ttf
Normal file
Binary file not shown.
BIN
public/iosevka-zesty/iosevka-zesty-bolditalic.ttf
Normal file
BIN
public/iosevka-zesty/iosevka-zesty-bolditalic.ttf
Normal file
Binary file not shown.
BIN
public/iosevka-zesty/iosevka-zesty-extended.ttf
Normal file
BIN
public/iosevka-zesty/iosevka-zesty-extended.ttf
Normal file
Binary file not shown.
BIN
public/iosevka-zesty/iosevka-zesty-extendedbold.ttf
Normal file
BIN
public/iosevka-zesty/iosevka-zesty-extendedbold.ttf
Normal file
Binary file not shown.
BIN
public/iosevka-zesty/iosevka-zesty-extendedbolditalic.ttf
Normal file
BIN
public/iosevka-zesty/iosevka-zesty-extendedbolditalic.ttf
Normal file
Binary file not shown.
BIN
public/iosevka-zesty/iosevka-zesty-extendeditalic.ttf
Normal file
BIN
public/iosevka-zesty/iosevka-zesty-extendeditalic.ttf
Normal file
Binary file not shown.
BIN
public/iosevka-zesty/iosevka-zesty-italic.ttf
Normal file
BIN
public/iosevka-zesty/iosevka-zesty-italic.ttf
Normal file
Binary file not shown.
BIN
public/iosevka-zesty/iosevka-zesty-regular.ttf
Normal file
BIN
public/iosevka-zesty/iosevka-zesty-regular.ttf
Normal file
Binary file not shown.
39
public/iosevka-zesty/plans.toml
Normal file
39
public/iosevka-zesty/plans.toml
Normal file
|
@ -0,0 +1,39 @@
|
|||
[buildPlans.iosevka-zesty]
|
||||
family = "Iosevka Zesty"
|
||||
spacing = "normal"
|
||||
serifs = "sans"
|
||||
no-cv-ss = true
|
||||
no-ligation = true
|
||||
|
||||
[buildPlans.iosevka-zesty.variants.design]
|
||||
two = "straight-neck"
|
||||
eight = "two-circles"
|
||||
nine = "straight-bar"
|
||||
brace = "straight"
|
||||
number-sign = "slanted"
|
||||
dollar = "open"
|
||||
cent = "open"
|
||||
percent = "rings-continuous-slash"
|
||||
|
||||
[buildPlans.iosevka-zesty.weights.regular]
|
||||
shape = 400
|
||||
menu = 400
|
||||
css = 400
|
||||
|
||||
[buildPlans.iosevka-zesty.weights.bold]
|
||||
shape = 700
|
||||
menu = 700
|
||||
css = 700
|
||||
|
||||
[buildPlans.iosevka-zesty.slopes.upright]
|
||||
angle = 0
|
||||
shape = "upright"
|
||||
menu = "upright"
|
||||
css = "normal"
|
||||
|
||||
[buildPlans.iosevka-zesty.slopes.italic]
|
||||
angle = 9.4
|
||||
shape = "italic"
|
||||
menu = "italic"
|
||||
css = "italic"
|
||||
|
6
public/iosevka-zesty/readme.txt
Normal file
6
public/iosevka-zesty/readme.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
this is my custom build of iosevka, see plans.toml for the exact config
|
||||
|
||||
if you want, you can download them (why else would i put them in /public/?)
|
||||
|
||||
the iosevka license is attached if you want to read it
|
||||
|
1
public/minesweeper-captcha
Submodule
1
public/minesweeper-captcha
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit d0a72669c9e0d1bbbae2f3d832d291592d1a4f22
|
BIN
public/pfp.png
Normal file
BIN
public/pfp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
BIN
public/pkl.zip
Normal file
BIN
public/pkl.zip
Normal file
Binary file not shown.
92
public/platformer/data.js
Normal file
92
public/platformer/data.js
Normal file
|
@ -0,0 +1,92 @@
|
|||
// the game data
|
||||
export default {
|
||||
// the platforms
|
||||
parts: [
|
||||
// x, y, width, height, type
|
||||
[100, 100, 200, 50],
|
||||
[400, 50, 200, 50],
|
||||
[700, 0, 50, 50],
|
||||
[900, -50, 50, 50],
|
||||
[1100, -100, 50, 100],
|
||||
[1200, -200, 50, 50],
|
||||
[1300, -300, 50, 50],
|
||||
[1150, -400, 100, 50],
|
||||
[800, -450, 100, 50],
|
||||
[450, -500, 100, 50],
|
||||
[300, -600, 50, 50],
|
||||
[400, -700, 50, 50],
|
||||
[300, -800, 50, 50],
|
||||
[400, -900, 150, 50],
|
||||
[450, -1000, 50, 50],
|
||||
[450, -1100, 50, 50],
|
||||
[450, -1200, 100, 50],
|
||||
[700, -1300, 50, 50, "checkpoint"],
|
||||
[850, -1400, 50, 50],
|
||||
[1000, -1500, 50, 50],
|
||||
[1400, -1400, 50, 50],
|
||||
[1800, -1350, 50, 50],
|
||||
[2150, -1350, 50, 50],
|
||||
[2150, -1450, 50, 50],
|
||||
[2150, -1550, 50, 50],
|
||||
[2150, -1650, 50, 50],
|
||||
[2150, -1750, 50, 50, "checkpoint"],
|
||||
[2125, -1850, 100, 50],
|
||||
[2100, -1950, 150, 50],
|
||||
[2075, -2050, 200, 50],
|
||||
[2050, -2150, 100, 50],
|
||||
[2200, -2150, 100, 50],
|
||||
[2150, -2250, 50, 50, "checkpoint"],
|
||||
[2000, -2350, 50, 50],
|
||||
[1850, -2450, 50, 50],
|
||||
[1600, -2500, 50, 50],
|
||||
[1350, -2550, 50, 50],
|
||||
[1050, -2600, 50, 50],
|
||||
[775, -2650, 50, 50],
|
||||
[400, -2650, 50, 50],
|
||||
[25, -2650, 50, 50],
|
||||
[-350, -2650, 50, 50, "checkpoint"],
|
||||
[-750, -2650, 50, 50],
|
||||
[-1200, -2500, 50, 50],
|
||||
[-1500, -2200, 50, 50],
|
||||
[-1900, -1900, 50, 50],
|
||||
[-2100, -2000, 50, 50, "final"],
|
||||
],
|
||||
|
||||
// the player
|
||||
player: {
|
||||
x: 200,
|
||||
y: 0,
|
||||
velx: 0,
|
||||
vely: 0,
|
||||
savex: 200,
|
||||
savey: 85,
|
||||
size: 15,
|
||||
canJump: false,
|
||||
},
|
||||
|
||||
// inputs - done this way so you can press multiple keys at once
|
||||
input: {
|
||||
up: false,
|
||||
down: false,
|
||||
left: false,
|
||||
right: false,
|
||||
},
|
||||
|
||||
// colors for each thing
|
||||
color: {
|
||||
player: "#f92a38",
|
||||
background: "#ffffff",
|
||||
dots: "#f6f6f6",
|
||||
platforms: "#222222",
|
||||
shadow: "#dddddd",
|
||||
checkpoint: "#4feab4",
|
||||
active: "#52e5a5",
|
||||
final: "#52e5cd",
|
||||
win: "#6befd9",
|
||||
},
|
||||
|
||||
// rendering stuff
|
||||
camera: [0, 0], // camera position
|
||||
size: [0, 0], // window/canvas size
|
||||
anim: [0, 0, 1], // checkpoint animation details
|
||||
};
|
13
public/platformer/index.html
Normal file
13
public/platformer/index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>canvas testing</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<script src="script.js" type="module" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
</body>
|
||||
</html>
|
213
public/platformer/script.js
Normal file
213
public/platformer/script.js
Normal file
|
@ -0,0 +1,213 @@
|
|||
import game from "./data.js"; // import the game data
|
||||
|
||||
// import elements from html
|
||||
const canvas = document.getElementById("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
// resize the canvas to full screen
|
||||
function resize() {
|
||||
const w = window.innerWidth;
|
||||
const h = window.innerHeight;
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
ctx.width = w;
|
||||
ctx.height = h;
|
||||
game.size = [w, h];
|
||||
}
|
||||
|
||||
// reset the player to the last checkpoint (or start)
|
||||
function die() {
|
||||
game.player.x = game.player.savex;
|
||||
game.player.y = game.player.savey;
|
||||
game.player.velx = 0;
|
||||
game.player.vely = 0;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
requestAnimationFrame(draw); // to continuously animate
|
||||
|
||||
const offx = game.camera[0] - game.size[0] / 2;
|
||||
const offy = game.camera[1] - game.size[1] / 2;
|
||||
const c = game.color;
|
||||
|
||||
const point = (x, y) => [x - offx, y - offy];
|
||||
const color = (which) => (ctx.fillStyle = game.color[which]);
|
||||
const rect = (x, y, w, h) => ctx.fillRect(...point(x, y), w, h);
|
||||
|
||||
// draw background
|
||||
color("background");
|
||||
ctx.fillRect(0, 0, game.size[0], game.size[1]);
|
||||
color("dots");
|
||||
for (let i = 0; i < 40; i++) {
|
||||
for (let j = 0; j < 30; j++) {
|
||||
const spacing = 60;
|
||||
const depth = 0.5;
|
||||
ctx.beginPath();
|
||||
ctx.arc(
|
||||
i * spacing - (offx % (spacing / depth)) * depth,
|
||||
j * spacing - (offy % (spacing / depth)) * depth,
|
||||
5,
|
||||
0,
|
||||
2 * Math.PI
|
||||
);
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
// draw checkpoint animation (if there is one)
|
||||
if (game.anim[2] < 1) {
|
||||
color("shadow");
|
||||
ctx.globalAlpha = 1 - game.anim[2];
|
||||
ctx.beginPath();
|
||||
ctx.arc(
|
||||
...point(game.anim[0], game.anim[1]),
|
||||
game.anim[2] * 100 + 25,
|
||||
0,
|
||||
2 * Math.PI
|
||||
);
|
||||
ctx.fill();
|
||||
ctx.globalAlpha = 1;
|
||||
game.anim[2] += 0.04;
|
||||
}
|
||||
|
||||
// draw platforms
|
||||
for (let part of game.parts) {
|
||||
color("shadow");
|
||||
for (let i = 6; i > 0; i--) {
|
||||
rect(part[0] + i, part[1] + i, part[2], part[3]);
|
||||
}
|
||||
color(part[4] || "platforms");
|
||||
rect(part[0], part[1], part[2], part[3]);
|
||||
}
|
||||
|
||||
// draw player
|
||||
color("player");
|
||||
rect(game.player.x, game.player.y, game.player.size, game.player.size);
|
||||
}
|
||||
|
||||
function update() {
|
||||
const p = game.player;
|
||||
const c = game.camera;
|
||||
|
||||
// handle input
|
||||
const i = game.input;
|
||||
const speed = 2;
|
||||
if (i.up && p.canJump) p.vely = -14;
|
||||
if (i.down) p.vely += 0.8;
|
||||
if (i.left) p.velx -= speed;
|
||||
if (i.right) p.velx += speed;
|
||||
|
||||
// update x position
|
||||
if (move("x", p.velx, p.velx < 0 ? -1 : 1)) {
|
||||
p.velx = 0;
|
||||
}
|
||||
|
||||
// reset jump if they're falling or already jumping (there's a small grace period though)
|
||||
if (Math.abs(p.vely) > 3) p.canJump = false;
|
||||
|
||||
// update y position
|
||||
const collided = move("y", p.vely, p.vely < 0 ? -1 : 1);
|
||||
if (collided) {
|
||||
if (p.vely >= 0) {
|
||||
// if they fell onto a platform then let them jump
|
||||
p.canJump = true;
|
||||
|
||||
// if they hit a checkpoint
|
||||
if (collided[4] === "checkpoint" || collided[4] === "final") {
|
||||
// unset the other checkpoints
|
||||
for (let part of game.parts.filter((i) => i[4] === "active")) {
|
||||
part[4] = "checkpoint";
|
||||
}
|
||||
|
||||
const x = collided[0] + collided[2] / 2;
|
||||
const y = collided[1] + collided[3] / 2;
|
||||
|
||||
// play the checkpoint animation
|
||||
game.anim = [x, y, 0];
|
||||
game.player.savex = x - game.player.size / 2;
|
||||
game.player.savey = y - collided[3] / 2 - game.player.size;
|
||||
|
||||
// they won!
|
||||
if (collided[4] === "final") {
|
||||
alert("ayo you win");
|
||||
|
||||
// reset the inputs, `alert()` does weird things
|
||||
input.up = false;
|
||||
input.down = false;
|
||||
input.left = false;
|
||||
input.right = false;
|
||||
}
|
||||
|
||||
// don't spam animation; change platform color
|
||||
collided[4] = collided[4] === "final" ? "win" : "active";
|
||||
}
|
||||
}
|
||||
|
||||
p.vely = 0;
|
||||
}
|
||||
|
||||
// they fell out of the world
|
||||
if (p.y > 1000) die();
|
||||
|
||||
// update velocity
|
||||
p.velx *= 0.8;
|
||||
p.vely = Math.min(30, p.vely + 0.8);
|
||||
|
||||
// update camera
|
||||
c[0] = (c[0] * 9 + p.x) / 10;
|
||||
c[1] = (c[1] * 9 + p.y) / 10;
|
||||
|
||||
// move, and return the platform the player collided with if any
|
||||
function move(key, amt, speed) {
|
||||
for (let i = 0; i < Math.abs(amt) - 1; i++) {
|
||||
p[key] += speed;
|
||||
const c = collision();
|
||||
if (c) {
|
||||
p[key] -= speed;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// check if there was a collision
|
||||
function collision() {
|
||||
const s = game.player.size;
|
||||
for (let part of game.parts) {
|
||||
const inside =
|
||||
p.x + s > part[0] &&
|
||||
p.y + s > part[1] &&
|
||||
p.x < part[0] + part[2] &&
|
||||
p.y < part[1] + part[3];
|
||||
if (inside) return part;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// handle input
|
||||
function input(e) {
|
||||
const i = game.input;
|
||||
const down = e.type === "keydown";
|
||||
switch (e.key) {
|
||||
case "ArrowUp":
|
||||
return (i.up = down);
|
||||
case "ArrowDown":
|
||||
return (i.down = down);
|
||||
case "ArrowLeft":
|
||||
return (i.left = down);
|
||||
case "ArrowRight":
|
||||
return (i.right = down);
|
||||
case "r":
|
||||
return die();
|
||||
}
|
||||
}
|
||||
|
||||
// run the game!
|
||||
resize();
|
||||
draw();
|
||||
setInterval(update, 1000 / 60);
|
||||
|
||||
window.addEventListener("resize", resize);
|
||||
window.addEventListener("keydown", input);
|
||||
window.addEventListener("keyup", input);
|
7
public/platformer/style.css
Normal file
7
public/platformer/style.css
Normal file
|
@ -0,0 +1,7 @@
|
|||
/* mmmm css */
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
2103
public/pnpm-lock.yaml
Normal file
2103
public/pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
BIN
public/reminder.mbp
Normal file
BIN
public/reminder.mbp
Normal file
Binary file not shown.
1
public/snek
Submodule
1
public/snek
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit bf62d20fe90755e089a59c4bc4dff8d00525887b
|
3201
public/test.txt
Normal file
3201
public/test.txt
Normal file
File diff suppressed because it is too large
Load diff
22
raid.md
Normal file
22
raid.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# how to use the raid (shadow legends) farm
|
||||
|
||||
1. get bad omen from any pillager outpost (there's one directly accessible from the nether)
|
||||
2. go to the raid farm
|
||||
3. immediately go into the water elevator (or you lose bad omen)
|
||||
4. if you're not on your first raid, skip to step 9
|
||||
5. a raid will start. ignore it for now
|
||||
6. stand below the chest
|
||||
7. put all your items into the chest except some food and a sword
|
||||
8. organize your inventory in a way that it's filled with the items you want to collect (see first image) (if you want totems, leave some empty space in your inventory)
|
||||
9. do the same thing with the hopper (second image)
|
||||
10. wait for the horns to stop (with subtitles, wait for "ominous horn blaring" to disappear)
|
||||
11. flip the lever (fence gate will be closed)
|
||||
12. attack through the gap between the hopper and the chest until everything is dead
|
||||
13. if there's too many items on top of the hopper, take the lava bucket from the chest and place it on top of the hopper so the items burn
|
||||
14. make sure to put back the lava bucket
|
||||
15. if you're done, take your items
|
||||
16. flip the lever (fence gate open)
|
||||
17. on the ladders, go as far forwards as you can, then stop pressing w and you will drop right into the water
|
||||
18. if you're done, just leave, otherwise repeat from step 3
|
||||
|
||||
![screenshot of inventory setup](https://celery.eu.org/_matrix/media/r0/download/celery.eu.org/bb2ad5b01f62d9fc566bbc3e3946694d5c26adf91725949427471876096)
|
105
rfc/index.html
Normal file
105
rfc/index.html
Normal file
|
@ -0,0 +1,105 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>List of failed RFCs</title>
|
||||
<link rel="stylesheet" href="rfc.css"></link>
|
||||
<link rel="stylesheet" href="normal.css"></link>
|
||||
<link rel="stylesheet" href="wikihow.css"></link>
|
||||
</head>
|
||||
<body>
|
||||
<article class="normal">
|
||||
<table class="info">
|
||||
<tr><td>Stream:</td><td>Independent Submission</td></tr>
|
||||
<tr><td>RFC:</td><td><a href="#no">12383</a></td></tr>
|
||||
<tr><td>Category:</td><td>Euclid</td></tr>
|
||||
<tr><td>Published:</td><td>Tomorrow</td></tr>
|
||||
<tr><td>Hotel:</td><td>Trivago</td></tr>
|
||||
</table>
|
||||
|
||||
<h1>RFC 12383<br>Folder limits</h1>
|
||||
<h2>Status of this Memo</h2>
|
||||
<p> This memo provides absolutely no information to the Internet community. This memo does not specify an Internet standard of any kind. Distribution of this memo is unlimited, assuming nobody mints this as a NFT.</p>
|
||||
<h2>Introduction</h2>
|
||||
<p>This RFC is attempts to fix inconsistencies found on many servers. Folders are commonly used as a form of organizing files. However, many admins store hundreds or thousands of files inside these folders. In the physical world, this would be impossible. To remedy this, this RFC defines an upper limit on the number of files per folder. Although this is not an internet standard, it is advised to note that there is no limit to our power, and that we may lower the limit at any time.</p>
|
||||
<h2>Requirements Language</h2>
|
||||
<p>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHOULD", "WOULD BE A GOOD IDEA TO", "PLEASE DON'T", "IF YOU WANT TO", and "ABSOLUTELY NOT" in this document are to be interpreted as described in <a href="https://www.rfc-editor.org/info/bcp14">BCP 14</a> when, and only when, they appear in SQL case.</p>
|
||||
<h2>Implementation</h2>
|
||||
<p>The number of files per folder are to be limited to 493 because it is a very nice number<sup>1</sup>. Any attempt to shove more than the maximum number of files into a single folder MUST result in an out of space error.</p>
|
||||
<p>An additional data structure, "pile", MUST be implemented for mass file storage. A pile must have no upper limit to the number of files, however listing files MUST take an additional <code>2^ni</code> milliseconds of time, where n = number of files and i = impatience of user.</p>
|
||||
<h2>Footnotes</h2>
|
||||
<ol>
|
||||
<li>An easy way to remember this number is that it is your mother's weight in kilograms.</li>
|
||||
</ol>
|
||||
<h2>Comments</h2>
|
||||
<textarea disabled>Comments are disabled for this RFC.</textarea>
|
||||
</article>
|
||||
<div class="sep"></div>
|
||||
<article class="wikihow">
|
||||
<div class="how">
|
||||
<div class="block">
|
||||
<div class="content">
|
||||
<div style="height: 4px;"></div>
|
||||
<h1>How to Communicate Effectively</h1>
|
||||
<p>Even with nothing to send besides shitposts, communication can be a rewarding process. TCP is an important part of the internet, and is evolving to this day! Make sure to have a stable internet connection to increase speed by minimizing packet loss.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block">
|
||||
<div class="title">
|
||||
<div>Part <div>1</div></div>
|
||||
<h2>Get a friend</h2>
|
||||
</div>
|
||||
<a href="https://www.reddit.com/r/disneyvacation/comments/9otz7t/how_to_browse_rfunny/"><img src="wiki1.png"></a>
|
||||
<div class="content">
|
||||
<p><span class="num">1</span><b>Make sure to have a friend to communicate with.</b> Without a target to send your shitposts to, it can be very difficult to get anywhere while communicating.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block">
|
||||
<div class="title">
|
||||
<div>Part <div>2</div></div>
|
||||
<h2>SYN</h2>
|
||||
</div>
|
||||
<a href="https://www.wikihow.com/Yell-Like-Tarzan"><img src="wiki2.png"></a>
|
||||
<div class="content">
|
||||
<p><span class="num">2</span><b>Initiate the connection by sending a SYN packet.</b> This is the first packet you send when initiating a connection.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block">
|
||||
<div class="title">
|
||||
<div>Part <div>3</div></div>
|
||||
<h2>SYN/ACK</h2>
|
||||
</div>
|
||||
<a href="https://www.wikihow.com/Yell-Like-Tarzan"><img src="wiki3.png"></a>
|
||||
<div class="content">
|
||||
<p><span class="num">3</span><b>Acknowledge the connection by sending an ACK+SYN packet.</b> This is done by your friend to accept the connection. They will need to set both the ACK and SYN flag.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block">
|
||||
<div class="title">
|
||||
<div>Part <div>4</div></div>
|
||||
<h2>ACK</h2>
|
||||
</div>
|
||||
<a href="https://www.wikihow.com/Deal-With-Someone-Yelling-at-You"><img src="wiki4.png"></a>
|
||||
<div class="content">
|
||||
<p><span class="num">4</span><b>Complete connection establishment with an ACK packet.</b> This is the final step in connecting.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block">
|
||||
<div class="title">
|
||||
<div>Part <div>5</div></div>
|
||||
<h2>(optional) Secure your communications with TLS</h2>
|
||||
</div>
|
||||
<a href="https://media.istockphoto.com/photos/calculator-in-hands-picture-id172781076"><img src="wiki5.png"></a>
|
||||
<div class="content">
|
||||
<p><span class="num">5</span><b>It is a good idea to secure your communications with transport layer security.</b> How to perform TLS is out of scope for this tutorial, but remember that TLS is a good idea.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
||||
|
31
rfc/normal.css
Normal file
31
rfc/normal.css
Normal file
|
@ -0,0 +1,31 @@
|
|||
.normal {
|
||||
font: 14px/1.2 sans-serif;
|
||||
max-width: 550px;
|
||||
margin: 0 auto;
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.normal h1 {
|
||||
padding-bottom: 1em;
|
||||
border-bottom: solid #ddd 1px;
|
||||
}
|
||||
|
||||
.normal a { text-decoration: none }
|
||||
.normal a:hover { background: #eeeeee }
|
||||
|
||||
.normal .info {
|
||||
font-size: 0.9em;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.normal img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.normal textarea {
|
||||
width: 100%;
|
||||
height: 10em;
|
||||
background: #eee;
|
||||
border: solid #aaa 1px;
|
||||
}
|
||||
|
10
rfc/rfc.css
Normal file
10
rfc/rfc.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sep {
|
||||
height: 1em;
|
||||
background: #222222;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue