diff --git a/.appengine/app.yaml b/.appengine/app.yaml index 24039ac..9c6cdfb 100644 --- a/.appengine/app.yaml +++ b/.appengine/app.yaml @@ -38,6 +38,13 @@ handlers: http_headers: Content-Type: text/html; charset=utf-8 + - url: /story/the_philosophy_of_lovers + static_files: .build/the_philosophy_of_lovers.html + upload: .build/the_philosophy_of_lovers.html + secure: always + http_headers: + Content-Type: text/html; charset=utf-8 + - url: /story/bridge static_files: .build/bridge.html upload: .build/bridge.html @@ -94,6 +101,13 @@ handlers: http_headers: Content-Type: text/html; charset=utf-8 + - url: /kit + static_files: .build/kit.html + upload: .build/kit.html + secure: always + http_headers: + Content-Type: text/html; charset=utf-8 + - url: /word/quality static_files: .build/quality.html upload: .build/quality.html diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..707482b --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,51 @@ +{ + "init": true, + "name": "justindfuller.com", + "features": { + "ghcr.io/devcontainers/features/go:1": { + "version": "1.21.4", + "golangciLintVersion": "1.55.2" + }, + "ghcr.io/devcontainers/features/node:1": { + "version": "20.9.0" + } + }, + "hostRequirements": { + "cpus": 1 + }, + "image": "mcr.microsoft.com/devcontainers/universal:2", + "waitFor": "onCreateCommand", + "updateContentCommand": "go mod download", + "postCreateCommand": "go install github.com/cespare/reflex@latest", + "postAttachCommand": { + "server": "make server-watch" + }, + "customizations": { + "codespaces": { + "openFiles": [ + "README" + ] + }, + "vscode": { + "settings": { + "workbench.iconTheme": "fira-code-material-minimal", + "editor.fontFamily": "fira-code-nerd, FiraCode Nerd Font, Consolas, 'Courier New', monospace", + "editor.fontLigatures": true + }, + "extensions": [ + "golang.go", + "dbaeumer.vscode-eslint", + "ms-vscode.makefile-tools", + "DavidAnson.vscode-markdownlint", + "eamodio.gitlens", + "Entuent.fira-code-nerd-font" + ] + } + }, + "portsAttributes": { + "9000": { + "label": "Application", + "onAutoForward": "openBrowserOnce" + } + } +} \ No newline at end of file diff --git a/Makefile b/Makefile index 727043c..779ca12 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,9 @@ format: @go fmt ./...; @npm run test; +format-watch: + @reflex -s -- sh -c "$(MAKE) format"; + build: @rm -rf ./.build; @mkdir ./.build; @@ -23,10 +26,12 @@ build: @curl "http://localhost:9000/make" > ./.build/make.html; @curl "http://localhost:9000/grass" > ./.build/grass.html; @curl "http://localhost:9000/grass/worker.js" > ./.build/grass-service-worker.js; + @curl "http://localhost:9000/kit" > ./.build/kit.html; @curl "http://localhost:9000/aphorism" > ./.build/aphorism.html; @curl "http://localhost:9000/poem" > ./.build/poem.html; @curl "http://localhost:9000/story" > ./.build/story.html; @curl "http://localhost:9000/story/the_philosophy_of_trees" > ./.build/the_philosophy_of_trees.html; + @curl "http://localhost:9000/story/the_philosophy_of_lovers" > ./.build/the_philosophy_of_lovers.html; @curl "http://localhost:9000/story/bridge" > ./.build/bridge.html; @curl "http://localhost:9000/story/nothing" > ./.build/nothing.html; @curl "http://localhost:9000/review" > ./.build/review.html; @@ -37,3 +42,6 @@ build: @curl "http://localhost:9000/word/equipoise" > ./.build/equipoise.html; @curl "http://localhost:9000/word/flexible" > ./.build/flexible.html; @cp -r ./image ./.build + +build-watch: + @reflex -s -- sh -c "$(MAKE) build"; \ No newline at end of file diff --git a/README.md b/README.md index b233074..08ed093 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,4 @@ [![Build and Deploy to GAE](https://github.com/JustinDFuller/justindfuller.com/actions/workflows/deploy.yml/badge.svg?branch=main)](https://github.com/JustinDFuller/justindfuller.com/actions/workflows/deploy.yml) -[https://www.justindfuller.com](https://www.justindfuller.com) +[https://www.justindfuller.com](https://www.justindfuller.com) \ No newline at end of file diff --git a/aphorism/entries.txt b/aphorism/entries.txt index 999667c..a3c6707 100644 --- a/aphorism/entries.txt +++ b/aphorism/entries.txt @@ -44,7 +44,7 @@ Truth is only an agreement. There may be a single physical reality (or maybe not) but there is no reason to think a particular human can perfectly understand and interpret that reality. -Truth can only be subjective and never objective. We cannot experience or interpret anything except as a subject observing and object. +Truth can only be subjective and never objective. We cannot experience or interpret anything except as a subject observing an object. It is wrong to approach philosophy in search of perfect truth. It is wrong to discount a philosophical argument for being imperfect. The value of philosophy may sometimes be to generate more ideas. diff --git a/aphorism/main.css b/aphorism/main.css index 4855f41..d64c525 100644 --- a/aphorism/main.css +++ b/aphorism/main.css @@ -47,3 +47,22 @@ hr { margin-top: 30px; margin-bottom: 50px; } + +@media (prefers-color-scheme: dark) { + html, + body { + background-color: #020215; + color: white; + } + + main > a { + color: white; + } + + main > a:hover, + main > a:focus, + main > a:active { + background: white; + color: #020215; + } +} diff --git a/image/rabbit.jpg b/image/rabbit.jpg new file mode 100644 index 0000000..58ef24e Binary files /dev/null and b/image/rabbit.jpg differ diff --git a/image/wizard.jpg b/image/wizard.jpg new file mode 100644 index 0000000..5f53e5d Binary files /dev/null and b/image/wizard.jpg differ diff --git a/main.css b/main.css index 68a8307..f83e9ad 100644 --- a/main.css +++ b/main.css @@ -36,7 +36,7 @@ } main > a { - color: black; + color: #020215; padding: 10px 20px; border-radius: 2px; transition: background 500ms, color 500ms; @@ -48,7 +48,26 @@ main > a:hover, main > a:focus, main > a:active { - background: black; + background: #020215; color: white; } + + @media (prefers-color-scheme: dark) { + html, + body { + background-color: #020215; + color: white; + } + + main > a { + color: white; + } + + main > a:hover, + main > a:focus, + main > a:active { + background: white; + color: #020215; + } + } diff --git a/main.go b/main.go index 73df68b..bf19406 100644 --- a/main.go +++ b/main.go @@ -228,6 +228,15 @@ func main() { } }) + http.HandleFunc("/kit", func(w http.ResponseWriter, r *http.Request) { + if err := templates.ExecuteTemplate(w, "/make/kit.template.html", data{ + Title: "A Game with Kit", + Meta: "kit", + }); err != nil { + log.Printf("template execution error=%s template=%s", err, "/make/kit.template.html") + } + }) + http.HandleFunc("/story", func(w http.ResponseWriter, r *http.Request) { if err := templates.ExecuteTemplate(w, "/story/main.template.html", data{ Title: "Story", diff --git a/make/grass.css b/make/grass.css index e3577bf..a327f3f 100644 --- a/make/grass.css +++ b/make/grass.css @@ -65,28 +65,28 @@ progress { select { width: 100%; padding: 10px 20px; - border: 2px solid black; + border: 2px solid #020215; background: white; - color: black; + color: #020215; } button { padding: 10px 20px; - border-top: 2px solid black; - border-left: 2px solid black; - border-right: 4px solid black; - border-bottom: 4px solid black; + border-top: 2px solid #020215; + border-left: 2px solid #020215; + border-right: 4px solid #020215; + border-bottom: 4px solid #020215; border-radius: 2px; background: white; - color: black; + color: #020215; cursor: pointer; } button:hover { - border-top: 3px solid black; - border-left: 3px solid black; - border-right: 3px solid black; - border-bottom: 3px solid black; + border-top: 3px solid #020215; + border-left: 3px solid #020215; + border-right: 3px solid #020215; + border-bottom: 3px solid #020215; } select, @@ -117,10 +117,10 @@ label { cursor: pointer; text-align: center; width: 45%; - border-top: 2px solid black; - border-left: 2px solid black; - border-right: 4px solid black; - border-bottom: 4px solid black; + border-top: 2px solid #020215; + border-left: 2px solid #020215; + border-right: 4px solid #020215; + border-bottom: 4px solid #020215; border-radius: 4px; margin-bottom: 20px; } @@ -136,10 +136,10 @@ label { } .day:hover { - border-right: 3px solid black; - border-bottom: 3px solid black; - border-left: 3px solid black; - border-top: 3px solid black; + border-right: 3px solid #020215; + border-bottom: 3px solid #020215; + border-left: 3px solid #020215; + border-top: 3px solid #020215; } .day .icon { @@ -173,3 +173,26 @@ label { .day .temperature { min-width: 70px; } + +@media (prefers-color-scheme: dark) { + html, + body { + background-color: #020215; + color: white; + } + + main > a { + color: white; + } + + main > a:hover, + main > a:focus, + main > a:active { + background: white; + color: #020215; + } + + .day { + color: #020215; + } +} diff --git a/make/kit.css b/make/kit.css new file mode 100644 index 0000000..f0c8922 --- /dev/null +++ b/make/kit.css @@ -0,0 +1,145 @@ +* { + box-sizing: border-box; +} + +html, +body { + padding: 0; + margin: 0; + font-size: 18px; + min-height: 100vh; + max-height: 300px; + min-width: 600px; + font-size: 20px; + font-family: "Amiri", serif; +} + +main { + padding-bottom: 20px; +} + +#world, +#root { + width: 600px; + margin: auto; +} + +#root { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + height: 100vh; + max-height: 200px; +} + +.step { + padding: 30px; + border: 1px solid black; +} + +.step:hover { + font-weight: bold; + color: lightblue; + border: 3px solid lightblue; +} + +.step.selected { + font-weight: bold; + color: blue; + border: 3px solid blue; +} + +.step.correct { + font-weight: bold; + color: green; + border: 2px solid green; +} + +#world { + margin-top: 10px; + position: relative; + height: 100px; +} + +#floor { + position: absolute; + top: 110px; + left: 0; + right: 0; + z-index: 1; + border-bottom: 3px solid brown; + width: 100%; + min-width: 600px; +} + +@keyframes move { + 0% { + left: 0px; + } + 100% { + left: 433px; + } +} + +@keyframes talk { + 0% { + visibility: hidden; + } + 100% { + visibility: visible; + } +} + +#wizard { + position: absolute; + bottom: 0; + top: 0; + left: 30px; +} + +#wizard p { + visibility: hidden; + position: relative; + left: 65px; + bottom: 131px; +} + +#wizard.success p { + animation-delay: 2s; + animation-name: talk; + animation-fill-mode: forwards; +} + +#wizard img { + transform: scaleX(-1); + height: 100px; +} + +#wizard.success { + animation-duration: 2s; + animation-name: move; + animation-fill-mode: forwards; +} + +#rabbit { + transform: scaleX(-1); + position: absolute; + height: 50px; + right: 50px; + bottom: 0; +} + +blockquote { + width: 100vw; + max-width: 500px; + margin: auto; + border-left: 3px solid #020215; + padding: 20px; +} + +@media (max-width: 500px) { + blockquote { + margin: 5px; + } +} diff --git a/make/kit.js b/make/kit.js new file mode 100644 index 0000000..39ba8ec --- /dev/null +++ b/make/kit.js @@ -0,0 +1,76 @@ +const numbers = [ + { n: 1, selected: false }, + { n: 6, selected: false }, + { n: 8, selected: false }, + { n: 7, selected: false }, + { n: 2, selected: false }, + { n: 3, selected: false }, + { n: 5, selected: false }, + { n: 4, selected: false }, +]; +const root = document.querySelector("#root"); +const wizard = document.querySelector("#wizard"); + +function init() { + root.innerHTML = ""; + + let all = true; + + for (const i in numbers) { + const n = numbers[i]; + + if (n.n - 1 !== Number(i)) { + all = false; + } + } + + if (all) { + wizard.classList.add("success"); + } + + for (const i in numbers) { + const n = numbers[i]; + const step = document.createElement("div"); + + step.id = n.n; + step.innerText = n.n; + step.classList.add("step"); + + if (n.n - 1 === Number(i)) { + step.classList.add("correct"); + } + + root.appendChild(step); + step.addEventListener("click", function(e) { + this.classList.toggle("selected"); + + if (n.selected) { + n.selected = false; + + return; + } + + n.selected = true; + + for (const j in numbers) { + if (j === i) { + continue; + } + + const n2 = numbers[j]; + + if (n2.selected) { + n.selected = false; + n2.selected = false; + numbers[j] = n; + numbers[i] = n2; + init(); + + break; + } + } + }); + } +} + +init(); diff --git a/make/kit.template.html b/make/kit.template.html new file mode 100644 index 0000000..80bab44 --- /dev/null +++ b/make/kit.template.html @@ -0,0 +1,39 @@ + + + + {{ template "/meta.template.html" . }} + + + + +
+
+
+ +

WooHoo!

+
+ +
+
+
+ +
+ Kit: Dad, Can we make a game? +
+ Me: Sure, buddy. What kind of game? +
+ Kit: On the computer! Let's make a game with a bunch of + numbers all mixed up. You have to switch the numbers to put them in + order. And on the left side there is a wizard who lost his rabbit. On + the right side is his rabbit. When you get the numbers in the right + order the Wizard crosses to the other side and says, "Woohoo!" +
+
+ + + + diff --git a/make/main.css b/make/main.css index 238244d..3da0aa5 100644 --- a/make/main.css +++ b/make/main.css @@ -35,13 +35,13 @@ main { } main > a { - color: black; + color: #020215; padding: 10px 20px; border-radius: 2px; transition: background 500ms, color 500ms; - width: 200px; + width: 300px; max-width: 100%; text-align: center; } @@ -49,6 +49,25 @@ main > a { main > a:hover, main > a:focus, main > a:active { - background: black; + background: #020215; color: white; } + +@media (prefers-color-scheme: dark) { + html, + body { + background-color: #020215; + color: white; + } + + main > a { + color: white; + } + + main > a:hover, + main > a:focus, + main > a:active { + background: white; + color: #020215; + } +} diff --git a/make/main.template.html b/make/main.template.html index a543c2c..ecd2a70 100644 --- a/make/main.template.html +++ b/make/main.template.html @@ -13,6 +13,7 @@ Notes Interviews Grass + A Game with Kit