├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── CNAME
├── README.md
├── TODO.md
├── card
├── design
│ ├── index.css
│ └── index.js
└── index.html
├── contact.html
├── cv
├── .gitignore
├── design
│ ├── about
│ │ └── chris.png
│ ├── base.css
│ ├── crypto
│ │ ├── index.css
│ │ └── index.js
│ ├── index.css
│ ├── index.js
│ ├── open-source.css
│ ├── profile.css
│ └── section.css
├── index.html
├── secret.html
└── source
│ └── c6afd22545c477c9830ed96438a643317d6bbf38bb219df26ba837f3a10ecb99.cv
├── design
├── about
│ ├── avatar
│ │ ├── burp.mp3
│ │ ├── burp.ogg
│ │ ├── burp.opus
│ │ ├── burp.wav
│ │ ├── cookiengineer.jpg
│ │ ├── cookiengineer.png
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── melody.mp3
│ │ ├── melody.ogg
│ │ ├── melody.opus
│ │ ├── melody.wav
│ │ ├── ouch.mp3
│ │ ├── ouch.ogg
│ │ ├── ouch.opus
│ │ ├── ouch.wav
│ │ ├── vomit.mp3
│ │ ├── vomit.ogg
│ │ ├── vomit.opus
│ │ └── vomit.wav
│ └── index.css
├── consent
│ ├── booom.mp3
│ ├── cannon.png
│ ├── cookie.png
│ ├── cursor.cur
│ ├── cursor.png
│ ├── grass.png
│ ├── index.css
│ ├── index.js
│ ├── lazer.mp3
│ └── music.mp3
├── contact
│ ├── captcha-human.svg
│ ├── captcha-robot.svg
│ ├── human.mp3
│ ├── human.ogg
│ ├── human.opus
│ ├── index.css
│ ├── index.js
│ ├── robot.mp3
│ ├── robot.ogg
│ └── robot.opus
├── layout
│ ├── base.css
│ ├── cursor.cur
│ ├── fontello.woff
│ ├── fontello.woff2
│ ├── index.css
│ ├── momentum.css
│ ├── museo-sans-300.woff
│ ├── museo-sans-300.woff2
│ ├── museo-sans-500.woff
│ ├── museo-sans-500.woff2
│ ├── section.css
│ ├── timeline.css
│ ├── vera-mono.woff
│ └── vera-mono.woff2
├── magic
│ ├── index.css
│ └── index.js
├── menu
│ ├── index.css
│ └── index.js
└── search
│ ├── disabled.svg
│ ├── hardware-legacy.svg
│ ├── hardware-research-legacy.svg
│ ├── hardware-research.svg
│ ├── hardware-software-legacy.svg
│ ├── hardware-software-research-legacy.svg
│ ├── hardware-software-research.svg
│ ├── hardware-software.svg
│ ├── hardware.svg
│ ├── index.css
│ ├── index.js
│ ├── legacy.svg
│ ├── nothing.svg
│ ├── research-legacy.svg
│ ├── research.svg
│ ├── software-legacy.svg
│ ├── software-research-legacy.svg
│ ├── software-research.svg
│ └── software.svg
├── emergency.html
├── favicon.ico
├── index.html
├── projects.html
├── projects
├── adblock-proxy
│ └── adblock-proxy.zip
├── ai-1-flappy-evolution
│ ├── LICENSE_GPL3.txt
│ ├── README.md
│ ├── ai-1-flappy-evolution.zip
│ ├── background.png
│ ├── index.css
│ ├── index.html
│ ├── index.mjs
│ ├── screenshot-small.png
│ ├── screenshot.png
│ └── source
│ │ ├── Agent.mjs
│ │ ├── Brain.mjs
│ │ ├── Evolution.mjs
│ │ ├── Game.mjs
│ │ ├── Game.png
│ │ ├── Goal.mjs
│ │ ├── Goal.png
│ │ ├── Plane.mjs
│ │ ├── Plane.png
│ │ ├── Simulation.mjs
│ │ └── Twister.mjs
├── ai-2-pong
│ ├── LICENSE_GPL3.txt
│ ├── README.md
│ ├── ai-2-pong.zip
│ ├── background.png
│ ├── index.css
│ ├── index.html
│ ├── index.mjs
│ ├── screenshot-small.png
│ ├── screenshot.png
│ └── source
│ │ ├── Agent.mjs
│ │ ├── Ball.mjs
│ │ ├── Brain.mjs
│ │ ├── Game.mjs
│ │ ├── Game.png
│ │ ├── Paddle.blue.png
│ │ ├── Paddle.mjs
│ │ ├── Paddle.red.png
│ │ └── Twister.mjs
├── ai-3-pong-evolution
│ ├── LICENSE_GPL3.txt
│ ├── README.md
│ ├── ai-3-pong-evolution.zip
│ ├── background.png
│ ├── index.css
│ ├── index.html
│ ├── index.mjs
│ ├── screenshot-small.png
│ ├── screenshot.png
│ └── source
│ │ ├── Agent.mjs
│ │ ├── Ball.mjs
│ │ ├── Brain.mjs
│ │ ├── Evolution.mjs
│ │ ├── Game.mjs
│ │ ├── Game.png
│ │ ├── Paddle.blue.png
│ │ ├── Paddle.mjs
│ │ ├── Paddle.red.png
│ │ ├── Simulation.mjs
│ │ └── Twister.mjs
├── dns-proxy
│ ├── screenshot-01-small.png
│ └── screenshot-01.png
├── dnsquery
│ ├── screenshot-01-small.png
│ └── screenshot-01.png
├── gibook-editor
│ ├── gibook-editor.zip
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ └── screenshot-02.png
├── git-cockpit
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ └── screenshot-02.png
├── git-work
│ ├── git-work.zip
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ ├── screenshot-02.png
│ ├── screenshot-03-small.png
│ └── screenshot-03.png
├── github-scrumboard
│ ├── github-scrumboard-0.0.4.crx
│ ├── github-scrumboard.zip
│ ├── github_scrumboard-0.0.4.xpi
│ ├── screencast-01-small.png
│ └── screencast-01.gif
├── gnome-shell-extension-outta-space
│ └── gnome-shell-extension-outta-space.zip
├── jquery-desktop
│ └── jquery-desktop.zip
├── lycheejs-breeder
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ ├── screenshot-02.png
│ ├── screenshot-03-small.png
│ └── screenshot-03.png
├── lycheejs-engine
│ ├── lycheejs.zip
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ ├── screenshot-02.png
│ ├── screenshot-03-small.png
│ ├── screenshot-03.png
│ ├── screenshot-04-small.png
│ └── screenshot-04.png
├── lycheejs-fertilizer
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ └── screenshot-02.png
├── lycheejs-harvester
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ ├── screenshot-02.png
│ ├── screenshot-03-small.png
│ └── screenshot-03.png
├── me-want-cookies
│ ├── me-want-cookies.zip
│ ├── screenshot-01-small.png
│ └── screenshot-01.png
├── pacman-backup
│ ├── pacman-backup-1.0.0.zip
│ └── pacman-backup-2.0.1.zip
├── patienteninfo-service
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ └── screenshot-02.png
├── polyfillr
│ ├── polyfillr.zip
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ └── screenshot-02.png
├── research
│ ├── research.zip
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ ├── screenshot-02.png
│ ├── screenshot-03-small.png
│ └── screenshot-03.png
├── skye-drone
│ ├── skye-drone-01-small.jpg
│ ├── skye-drone-01.jpg
│ ├── skye-drone-02-small.jpg
│ └── skye-drone-02.jpg
├── stealth
│ ├── stealth-01-small.png
│ ├── stealth-01.png
│ ├── stealth-02-small.png
│ ├── stealth-02.png
│ ├── stealth-03-small.png
│ ├── stealth-03.png
│ ├── stealth-04-small.png
│ └── stealth-04.png
├── stegit
│ └── stegit.zip
├── switchine
│ ├── switchine-01-small.png
│ ├── switchine-01.png
│ ├── switchine-02-small.png
│ ├── switchine-02.png
│ ├── switchine-03-small.png
│ ├── switchine-03.png
│ ├── switchine-04-small.png
│ ├── switchine-04.png
│ └── switchine.zip
├── webmail
│ └── webmail.zip
├── webslide-me
│ └── webslide-me.zip
├── zynga-jukebox
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ ├── screenshot-02.png
│ ├── screenshot-03-small.png
│ ├── screenshot-03.png
│ └── zynga-jukebox.zip
└── zynga-speedrun
│ ├── css
│ ├── library.css
│ └── sidebar.css
│ ├── index.html
│ ├── js
│ ├── external
│ │ └── jquery-1.6.2.min.js
│ ├── init.js
│ ├── init_ui.js
│ └── modules
│ │ ├── FPS.js
│ │ ├── benchmark.control.js
│ │ ├── benchmark.hash.js
│ │ ├── benchmark.js
│ │ ├── benchmark.loops.js
│ │ ├── benchmark.plugins.js
│ │ ├── benchmark.position.js
│ │ └── helpers.js
│ ├── res
│ └── debug.png
│ ├── screenshot-01-small.png
│ ├── screenshot-01.png
│ ├── screenshot-02-small.png
│ ├── screenshot-02.png
│ ├── screenshot-03-small.png
│ ├── screenshot-03.png
│ └── zynga-speedrun.zip
├── talks.html
├── talks
├── 2012-ongamestart
│ └── screenshot-01.png
├── 2014-jsconf-eu
│ └── screenshot-01.png
├── 2014-karlsruhejs
│ └── screenshot-01.png
├── 2016-frankfurtjs
│ └── screenshot-01.png
└── 2018-frankfurt-datascience
│ └── screenshot-01.png
├── toolchain
├── actions
│ ├── DecryptCV.go
│ ├── EncryptCV.go
│ ├── Render.go
│ └── Serve.go
├── cmds
│ ├── cv
│ │ └── main.go
│ ├── render
│ │ └── main.go
│ └── serve
│ │ └── main.go
├── console
│ ├── Clear.go
│ ├── ClearLines.go
│ ├── Disable.go
│ ├── Enable.go
│ ├── Error.go
│ ├── Group.go
│ ├── GroupEnd.go
│ ├── GroupEndResult.go
│ ├── Info.go
│ ├── Inspect.go
│ ├── Log.go
│ ├── Message.go
│ ├── Progress.go
│ ├── Result.go
│ ├── Warn.go
│ ├── console.go
│ └── features.go
├── cvs
│ ├── Decrypt.go
│ ├── DeriveFilename.go
│ ├── DeriveKey.go
│ ├── Encrypt.go
│ └── cvs_test.go
├── go.mod
├── go.sum
├── routes
│ ├── ModifyFile.go
│ ├── RemoveFile.go
│ ├── RenderArticle.go
│ ├── RenderArticles.go
│ ├── RenderFeed.go
│ ├── RenderIndex.go
│ ├── ServeArticle.go
│ ├── ServeArticleIndex.go
│ └── ServeFile.go
├── structs
│ ├── Document.go
│ ├── Element.go
│ ├── Emojis.go
│ ├── Feed.go
│ ├── Index.go
│ ├── countWords.go
│ ├── generateId.go
│ └── parseInlineElements.go
├── templates
│ ├── Article.go
│ ├── Article.tpl
│ ├── Feed.go
│ ├── Feed.tpl
│ ├── Index.go
│ ├── Index.tpl
│ ├── RenderElement.go
│ ├── RenderElements.go
│ ├── RenderInteger.go
│ └── RenderStrings.go
└── utils
│ ├── IsNumber.go
│ ├── MIME.go
│ ├── RespondWith.go
│ ├── ToASCII.UTF8.json
│ ├── ToASCII.go
│ └── ToASCIIName.go
└── weblog
├── articles
├── .eslintrc.json
├── android-privacy-guide.html
├── android-privacy-guide.md
├── android-privacy-guide
│ ├── appwarden.jpg
│ ├── osmand.jpg
│ ├── permission-manager-x.jpg
│ ├── rethinkdns.jpg
│ └── superfreezz.jpg
├── archlinux-install-guide-grub.html
├── archlinux-install-guide-grub.md
├── archlinux-install-guide-uefi.html
├── archlinux-install-guide-uefi.md
├── dji-drone-reset-guide.html
├── dji-drone-reset-guide.md
├── dji-drone-reset-guide
│ └── dji-spark-with-controller.jpg
├── email-with-postfix-and-dovecot.html
├── email-with-postfix-and-dovecot.md
├── gameboy-advance.html
├── gameboy-advance.md
├── gameboy-advance
│ ├── gba-01-teardown.jpg
│ ├── gba-02-cleanup.jpg
│ ├── gba-03-displaymod.jpg
│ └── gba-04-ezflash-omega.jpg
├── i3-migration-guide.html
├── i3-migration-guide.md
├── i3-migration-guide
│ └── lxappearance.png
├── implementers-guide-to-socks.html
├── implementers-guide-to-socks.md
├── implementers-guide-to-socks
│ ├── SOCKS.mjs
│ ├── client-manual.mjs
│ ├── client.mjs
│ └── server.mjs
├── implementers-guide-to-websockets.html
├── implementers-guide-to-websockets.md
├── implementers-guide-to-websockets
│ ├── WS.mjs
│ ├── client.mjs
│ └── server.mjs
├── intel-nuc-homeserver.html
├── intel-nuc-homeserver.md
├── intel-nuc-homeserver
│ ├── fanless-intel-nuc-inside.jpg
│ └── fanless-intel-nuc.jpg
├── linux-assembly-part-1-syscalls.html
├── linux-assembly-part-1-syscalls.md
├── linux-assembly-part-2-declaring-data.html
├── linux-assembly-part-2-declaring-data.md
├── linux-assembly-part-3-control-flow.html
├── linux-assembly-part-3-control-flow.md
├── linux-assembly-part-4-arithmetic-operations.html
├── linux-assembly-part-4-arithmetic-operations.md
├── linux-assembly
│ ├── .gitignore
│ ├── calculator.asm
│ ├── hello-world.asm
│ └── stack.asm
├── maintenance-of-clearnets.html
├── maintenance-of-clearnets.md
├── maintenance-of-clearnets
│ ├── first-time.jpg
│ ├── heist-attack.pdf
│ ├── maximum-security-prison.jpg
│ └── telephone-operator-lady.jpg
├── malware-insights-github-actions-script-injection.html
├── malware-insights-github-actions-script-injection.md
├── mx518-repair-guide.html
├── mx518-repair-guide.md
├── mx518-repair-guide
│ ├── 01-mouse.jpg
│ ├── 02-topshell.jpg
│ ├── 03-mousewheel.jpg
│ └── 04-components.jpg
├── nokia-800-tough.html
├── nokia-800-tough.md
├── pacman-backup.html
├── pacman-backup.md
├── pacman-backup
│ └── screenshot.png
├── problems-with-web-browsers.html
├── problems-with-web-browsers.md
├── problems-with-web-browsers
│ ├── firefox-cache-on-mobile-internet.png
│ ├── firefox-network-connection-error.png
│ ├── firefox-network-protocol-error.png
│ ├── firefox-network-settings.png
│ ├── stackoverflow-print-preview.png
│ └── stealth-browser-settings.png
├── synaptics-touchpad-on-linux.html
├── synaptics-touchpad-on-linux.md
├── synaptics-touchpad-on-linux
│ ├── 70-synaptics.conf
│ └── lenovo-synaptics-touchpad.jpg
├── you-dont-need-lpm-tries.html
├── you-dont-need-lpm-tries.md
├── your-definition-of-privacy-is-wrong.html
├── your-definition-of-privacy-is-wrong.md
└── your-definition-of-privacy-is-wrong
│ ├── prefs.js
│ └── umatrix-usage.png
├── design
├── editor
│ ├── index.css
│ ├── index.js
│ ├── vera-mono.woff
│ └── vera-mono.woff2
├── index.css
└── layout
│ ├── article.css
│ ├── article.js
│ ├── highlight.css
│ └── highlight.js
├── editor.html
├── feed.xml
└── index.html
/.eslintignore:
--------------------------------------------------------------------------------
1 | /design/weblog/highlight.js
2 |
3 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true,
5 | "node": false
6 | },
7 | "extends": "eslint:recommended",
8 | "parserOptions": {
9 | "ecmaVersion": 2018
10 | },
11 | "globals": {
12 | "window": true
13 | },
14 | "overrides": [{
15 | "files": [ "*.mjs" ],
16 | "rules": {},
17 | "parserOptions": {
18 | "sourceType": "module"
19 | }
20 | }, {
21 | "files": [ "bin/console.mjs" ],
22 | "rules": { "no-control-regex": "off" }
23 | }, {
24 | "files": [ "design/contact.js" ],
25 | "rules": { "no-control-regex": "off", "no-misleading-character-class": "off" }
26 | }],
27 | "rules": {
28 | "no-restricted-globals": [
29 | "error",
30 | { "name": "console" },
31 | { "name": "location" },
32 | { "name": "URL" },
33 | { "name": "URLSearchParams" }
34 | ],
35 | "arrow-parens": [
36 | "error",
37 | "always"
38 | ],
39 | "indent": [
40 | "error",
41 | "tab"
42 | ],
43 | "linebreak-style": [
44 | "error",
45 | "unix"
46 | ],
47 | "no-unused-vars": [
48 | "error"
49 | ],
50 | "quotes": [
51 | "error",
52 | "single"
53 | ],
54 | "semi": [
55 | "error",
56 | "always"
57 | ]
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /cv/source/DECRYPTED.cv
2 | /toolchain/serve.bin
3 |
4 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | cookie.engineer
2 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 |
2 | ## Projects
3 |
4 | Missing Tholian Projects:
5 |
6 | - [ ] Add `tholian-warps` (with Screenshots)
7 |
8 | Missing Artificial Engineering Projects:
9 |
10 | - [ ] Add `lychee.js Strainer`
11 | - [ ] Add `Research` (with Screenshots)
12 | - [ ] Add `ESA Satellite` (Galileo Networking/Firmware Infrastructure)
13 | - [ ] Add `ML for Dummies`
14 | - [ ] Add `node-sdl2`
15 |
16 | Missing Cookie Engineer Projects:
17 |
18 | - [ ] Add `agenda` screenshots
19 | - [ ] Add `gooey` WebASM framework
20 | - [ ] Add `gosleeper` malware infiltration framework
21 | - [ ] Add `goroot` privilege escalation framework
22 | - [ ] Add `git-evac` Git Repo Management Tool with screenshots
23 | - [ ] Add `evolution-of-code`
24 | - [ ] Add `infiltrator`
25 | - [ ] Add `lecture-tool` or rename it to `lecturer`?
26 |
27 |
28 | ## Weblog
29 |
30 | - [ ] MX518 Repair Guide
31 |
32 | - https://web.archive.org/web/20120423073234/http://ece425web.groups.et.byu.net/stable/labs/8086InstructionSet.html
33 |
34 | - https://www.bencode.net/blob/nasmcheatsheet.pdf
35 | - https://github.com/Cee/NASM-Tutorial
36 | - https://github.com/0xAX/asm/tree/master/content
37 | - https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf
38 |
39 |
40 | - [ ] Linux Assembly Part 3 - Control Flow
41 | - Stack Pointers
42 | - Function Calls
43 |
44 | - [ ] Linux Assembly Part 4 - Arithmetic Operations
45 | - [ ] Linux Assembly Part 5 - String Operations
46 | - [ ] Linux Assembly Part 6 - Inline Assembly (Call Assembly from C)
47 | - [ ] Linux Assembly Part 7 - X87 FPU
48 |
49 | - [ ] Go Assembly Part 1
50 |
51 |
52 |
53 | - [ ] Human Eyes Only - How to combat LLMs with the Enigma Webfont
54 | - [ ] The Ugly Internet - Crime, Propaganda and War
55 | - [ ] The Bad Internet - Greed, Persuasion and Seduction
56 | - [ ] The Toxic Internet - Trolls, Useful Idiots and Fragile Egos
57 | - [ ] The Good Internet - Research, Curiosity and Knowledge
58 | - [ ] One Year of Cyber Attacks - Who tried to hack me?
59 | - [ ] One Year of Cyber Attacks - Never use these passwords
60 | - [ ] One Year of Cyber Attacks - The most malicious networks
61 | - [ ] Golang Pitfalls (e.g. filtered maps of references needing twice the RAM)
62 | - [ ] PureGo for EDR Evasion
63 | - [ ] Go Embedding GZip files
64 | - [ ] Memory Debugging and Profiling in Go
65 | - [ ] Unmarshalling and Marshalling in Go
66 | - [ ] The WHOIS protocol and its quirks and pitfalls
67 | - [ ] Fingerprinting with CSS
68 | - [ ] Implementer's Guide to HTTP
69 | - [ ] Implementer's Guide to HTTP Streaming
70 | - [ ] Implementer's Guide to CSS
71 |
72 |
--------------------------------------------------------------------------------
/card/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Cookie Engineer's Business Card
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
23 |
24 |
25 | Cookie . Engineer
26 | That's me. It's also my website.
27 |
28 | Network Analysis/Security
29 | Cyber Defense/Intelligence
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/cv/.gitignore:
--------------------------------------------------------------------------------
1 | /.temp.cv
2 |
3 |
--------------------------------------------------------------------------------
/cv/design/about/chris.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/cv/design/about/chris.png
--------------------------------------------------------------------------------
/cv/design/crypto/index.css:
--------------------------------------------------------------------------------
1 |
2 | section#crypto {
3 | width: 100% !important;
4 | height: unset !important;
5 | border: unset;
6 | background: unset;
7 | box-shadow: unset;
8 | }
9 |
10 | section#crypto h1 {
11 | display: block;
12 | margin: 0px;
13 | padding: 0px;
14 | font-family: 'museo-sans-500';
15 | font-size: 40px;
16 | line-height: 48px;
17 | font-weight: 500;
18 | text-align: center;
19 | }
20 |
21 | section#crypto article {
22 | display: block;
23 | position: static;
24 | top: unset;
25 | right: unset;
26 | bottom: unset;
27 | left: unset;
28 | width: 768px !important;
29 | height: auto !important;
30 | margin: 64px auto;
31 | padding: 16px;
32 | color: #ffffff;
33 | background: #252530;
34 | border: 0px solid transparent;
35 | border-radius: 16px;
36 | }
37 |
38 | section#crypto article input {
39 | display: block;
40 | box-sizing: border-box;
41 | width: calc(100% - 32px);
42 | margin: 16px auto 0px auto;
43 | font-family: 'museo-sans-300';
44 | font-size: 16px;
45 | font-weight: normal;
46 | color: #ffffff;
47 | background: #404040;
48 | border: 1px solid #ffffff;
49 | border-radius: 4px;
50 | appearance: none;
51 | -moz-appearance: none;
52 | -ms-appearance: none;
53 | -webkit-appearance: none;
54 | user-select: none;
55 | -moz-user-select: none;
56 | -ms-user-select: none;
57 | outline: none;
58 | }
59 |
60 | section#crypto article ul {
61 | margin: 16px 0px 0px 0px;
62 | padding: 0px 16px 0px 16px;
63 | list-style: disc;
64 | text-align: left;
65 | }
66 |
67 | section#crypto article ul li {
68 | opacity: 0;
69 | transition: 200ms all ease-out;
70 | }
71 |
72 | section#crypto article ul li[data-show="true"] {
73 | opacity: 1;
74 | transition: 200ms all ease-out;
75 | }
76 |
77 |
78 |
79 | @media print {
80 |
81 | section#crypto {
82 | display: none !important;
83 | }
84 |
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/cv/design/index.css:
--------------------------------------------------------------------------------
1 |
2 | @import url("./base.css");
3 | @import url("./section.css");
4 | @import url("./profile.css");
5 | @import url("./open-source.css");
6 |
7 |
--------------------------------------------------------------------------------
/cv/design/open-source.css:
--------------------------------------------------------------------------------
1 |
2 | section#open-source aside {
3 | top: 0px;
4 | padding: calc(64px + 16px) 0px 0px 0px;
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/cv/design/profile.css:
--------------------------------------------------------------------------------
1 |
2 | section#profile figure#avatar {
3 | display: block;
4 | position: relative;
5 | width: 100%;
6 | margin-block-start: 0px;
7 | margin-block-end: 0px;
8 | margin-inline-start: 0px;
9 | margin-inline-end: 0px;
10 | margin: 0px auto 0px auto;
11 | }
12 |
13 | section#profile figure#avatar img {
14 | display: inline-block;
15 | position: relative;
16 | width: 128px;
17 | height: 128px;
18 | margin: 0px 0px 0px calc((200px / 2) - 64px - 8px);
19 | border-radius: 72px;
20 | border: 8px solid #252530;
21 | vertical-align: middle;
22 | cursor: pointer;
23 | user-select: none;
24 | -moz-user-select: none;
25 | -ms-user-select: none;
26 | z-index: 2;
27 | }
28 |
29 | section#profile figure#avatar figcaption {
30 | display: inline-block;
31 | position: absolute;
32 | width: auto%;
33 | margin: 0px;
34 | padding: 16px 0px 16px calc(128px + 16px + 64px);
35 | top: calc(64px / 2);
36 | right: 1em;
37 | bottom: auto;
38 | left: 0px;
39 | font-family: 'museo-sans-300';
40 | font-size: 16px;
41 | line-height: 20px;
42 | vertical-align: middle;
43 | background: #252530;
44 | border-radius: 0px 64px 64px 0px;
45 | user-select: none;
46 | -moz-user-select: none;
47 | -ms-user-select: none;
48 | z-index: 1;
49 | }
50 |
51 | section#profile figure#avatar figcaption b {
52 | font-family: 'museo-sans-300';
53 | font-size: 18px;
54 | }
55 |
56 | section#profile aside {
57 | top: calc((128px / 2) + 32px + 8px);
58 | padding: 64px 0px 0px 0px;
59 | }
60 |
61 | section#profile article {
62 | top: calc(128px - 8px);
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/cv/secret.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Cookie Engineer's CV - Cyber Engineer
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
31 |
32 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/cv/source/c6afd22545c477c9830ed96438a643317d6bbf38bb219df26ba837f3a10ecb99.cv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/cv/source/c6afd22545c477c9830ed96438a643317d6bbf38bb219df26ba837f3a10ecb99.cv
--------------------------------------------------------------------------------
/design/about/avatar/burp.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/burp.mp3
--------------------------------------------------------------------------------
/design/about/avatar/burp.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/burp.ogg
--------------------------------------------------------------------------------
/design/about/avatar/burp.opus:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/burp.opus
--------------------------------------------------------------------------------
/design/about/avatar/burp.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/burp.wav
--------------------------------------------------------------------------------
/design/about/avatar/cookiengineer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/cookiengineer.jpg
--------------------------------------------------------------------------------
/design/about/avatar/cookiengineer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/cookiengineer.png
--------------------------------------------------------------------------------
/design/about/avatar/index.css:
--------------------------------------------------------------------------------
1 |
2 | section#about figure#avatar {
3 | display: block;
4 | position: relative;
5 | width: 640px;
6 | margin-block-start: 0px;
7 | margin-block-end: 0px;
8 | margin-inline-start: 0px;
9 | margin-inline-end: 0px;
10 | margin: 160px auto 0px auto;
11 | }
12 |
13 | section#about figure#avatar img {
14 | display: inline-block;
15 | position: relative;
16 | width: 256px;
17 | height: 256px;
18 | border-radius: 144px;
19 | border: 16px solid #252530;
20 | vertical-align: middle;
21 | user-select: none;
22 | -moz-user-select: none;
23 | -ms-user-select: none;
24 | z-index: 2;
25 | }
26 |
27 | section#about figure#avatar canvas {
28 | display: inline-block;
29 | position: absolute;
30 | width: 256px;
31 | height: 256px;
32 | top: 16px;
33 | right: auto;
34 | bottom: auto;
35 | left: 16px;
36 | user-select: none;
37 | -moz-user-select: none;
38 | -ms-user-select: none;
39 | z-index: 3;
40 | }
41 |
42 | section#about figure#avatar figcaption {
43 | display: inline-block;
44 | position: relative;
45 | width: 320px;
46 | margin: 0px 0px 0px -128px;
47 | padding: 24px 24px 24px 128px;
48 | font-family: 'museo-sans-300';
49 | font-size: 20px;
50 | vertical-align: middle;
51 | background: #252530;
52 | border-radius: 0px 128px 128px 0px;
53 | user-select: none;
54 | -moz-user-select: none;
55 | -ms-user-select: none;
56 | z-index: 1;
57 | }
58 |
59 | section#about figure#avatar figcaption small {
60 | font-size: 16px;
61 | }
62 |
63 | section#about figure#avatar figcaption b {
64 | color: #0f99cb;
65 | font-weight: bold;
66 | }
67 |
68 |
69 |
70 | @media print {
71 |
72 | section#about figure#avatar {
73 | margin: 0px auto;
74 | }
75 |
76 | section#about figure#avatar canvas {
77 | display: none;
78 | }
79 |
80 | section#about figure#avatar figcaption {
81 | padding: 0px 0px 0px 148px;
82 | background: transparent;
83 | border-radius: 0px;
84 | }
85 |
86 | }
87 |
88 |
89 |
90 | /*
91 | * XXX: Something is glitching here, should've been 640px
92 | * but Chrome does not agree. Maybe it's the scrollbar!?
93 | */
94 |
95 | @media screen and (max-width: 654px) {
96 |
97 | section#about figure#avatar {
98 | display: block;
99 | width: auto;
100 | }
101 |
102 | section#about figure#avatar img {
103 | display: block;
104 | margin: 0px auto;
105 | }
106 |
107 | section#about figure#avatar canvas {
108 | top: 16px;
109 | left: calc(50% - 128px);
110 | }
111 |
112 | section#about figure#avatar figcaption {
113 | display: block;
114 | width: auto;
115 | margin: 32px 0px;
116 | padding: 16px;
117 | border-radius: 4px;
118 | }
119 |
120 | }
121 |
122 |
--------------------------------------------------------------------------------
/design/about/avatar/melody.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/melody.mp3
--------------------------------------------------------------------------------
/design/about/avatar/melody.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/melody.ogg
--------------------------------------------------------------------------------
/design/about/avatar/melody.opus:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/melody.opus
--------------------------------------------------------------------------------
/design/about/avatar/melody.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/melody.wav
--------------------------------------------------------------------------------
/design/about/avatar/ouch.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/ouch.mp3
--------------------------------------------------------------------------------
/design/about/avatar/ouch.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/ouch.ogg
--------------------------------------------------------------------------------
/design/about/avatar/ouch.opus:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/ouch.opus
--------------------------------------------------------------------------------
/design/about/avatar/ouch.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/ouch.wav
--------------------------------------------------------------------------------
/design/about/avatar/vomit.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/vomit.mp3
--------------------------------------------------------------------------------
/design/about/avatar/vomit.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/vomit.ogg
--------------------------------------------------------------------------------
/design/about/avatar/vomit.opus:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/vomit.opus
--------------------------------------------------------------------------------
/design/about/avatar/vomit.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/about/avatar/vomit.wav
--------------------------------------------------------------------------------
/design/consent/booom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/consent/booom.mp3
--------------------------------------------------------------------------------
/design/consent/cannon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/consent/cannon.png
--------------------------------------------------------------------------------
/design/consent/cookie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/consent/cookie.png
--------------------------------------------------------------------------------
/design/consent/cursor.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/consent/cursor.cur
--------------------------------------------------------------------------------
/design/consent/cursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/consent/cursor.png
--------------------------------------------------------------------------------
/design/consent/grass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/consent/grass.png
--------------------------------------------------------------------------------
/design/consent/index.css:
--------------------------------------------------------------------------------
1 |
2 | #consent {
3 | display: block;
4 | position: fixed;
5 | width: 448px;
6 | top: auto;
7 | right: 0px;
8 | bottom: 0px;
9 | left: 0px;
10 | margin: 0px auto;
11 | padding: 8px;
12 | border: 1px solid #000000;
13 | color: #000000;
14 | background: #ffffff;
15 | border-radius: 8px 8px 0px 0px;
16 | box-sizing: border-box;
17 | transition: 250ms all ease-out;
18 | opacity: 1;
19 | z-index: 99;
20 | }
21 |
22 | #consent h3 {
23 | display: block;
24 | margin: 0px;
25 | padding: 0px;
26 | font-family: 'museo-sans-500';
27 | font-size: 24px;
28 | line-height: 32px;
29 | font-weight: 500;
30 | text-align: center;
31 | }
32 |
33 | #consent p {
34 | font-family: 'museo-sans-300';
35 | text-align: justify;
36 | margin: 8px 0px 16px 0px;
37 | padding: 0px;
38 | }
39 |
40 | #consent div {
41 | text-align: center;
42 | }
43 |
44 | #consent div button {
45 | margin: 0px 16px;
46 | }
47 |
48 | body.game #consent {
49 | opacity: 0;
50 | }
51 |
52 | body.game #consent h3,
53 | body.game #consent p,
54 | body.game #consent div,
55 | body.game #consent div button {
56 | display: none;
57 | }
58 |
59 | body.game {
60 | width: 100%;
61 | height: 100%;
62 | overflow: hidden;
63 | background: #000000;
64 | transition: all 250ms ease-out;
65 | cursor: url('./cursor.cur') 16 16, auto;
66 | }
67 |
68 | body.game header {
69 | display: none;
70 | }
71 |
72 | body.game section#about > h1 {
73 | display: none;
74 | }
75 |
76 | body.game section#about > article {
77 | display: none;
78 | }
79 |
80 | body.game section#about div#about-socialize {
81 | display: none;
82 | }
83 |
84 | body.game section#about figure#avatar figcaption {
85 | display: none;
86 | }
87 |
88 | body.game section#skills,
89 | body.game section#prototypes,
90 | body.game section#search,
91 | body.game section#open-source,
92 | body.game section#talks,
93 | body.game section#contact,
94 | body.game footer {
95 | display: none;
96 | }
97 |
98 |
99 |
100 | @media (max-width: 512px) {
101 |
102 | #consent {
103 | width: auto;
104 | }
105 |
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/design/consent/lazer.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/consent/lazer.mp3
--------------------------------------------------------------------------------
/design/consent/music.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/consent/music.mp3
--------------------------------------------------------------------------------
/design/contact/captcha-robot.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/design/contact/human.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/contact/human.mp3
--------------------------------------------------------------------------------
/design/contact/human.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/contact/human.ogg
--------------------------------------------------------------------------------
/design/contact/human.opus:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/contact/human.opus
--------------------------------------------------------------------------------
/design/contact/robot.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/contact/robot.mp3
--------------------------------------------------------------------------------
/design/contact/robot.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/contact/robot.ogg
--------------------------------------------------------------------------------
/design/contact/robot.opus:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/contact/robot.opus
--------------------------------------------------------------------------------
/design/layout/cursor.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/layout/cursor.cur
--------------------------------------------------------------------------------
/design/layout/fontello.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/layout/fontello.woff
--------------------------------------------------------------------------------
/design/layout/fontello.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/layout/fontello.woff2
--------------------------------------------------------------------------------
/design/layout/index.css:
--------------------------------------------------------------------------------
1 |
2 | @import url("./base.css");
3 | @import url("./section.css");
4 | @import url("./momentum.css");
5 | @import url("./timeline.css");
6 |
7 |
--------------------------------------------------------------------------------
/design/layout/museo-sans-300.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/layout/museo-sans-300.woff
--------------------------------------------------------------------------------
/design/layout/museo-sans-300.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/layout/museo-sans-300.woff2
--------------------------------------------------------------------------------
/design/layout/museo-sans-500.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/layout/museo-sans-500.woff
--------------------------------------------------------------------------------
/design/layout/museo-sans-500.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/layout/museo-sans-500.woff2
--------------------------------------------------------------------------------
/design/layout/vera-mono.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/layout/vera-mono.woff
--------------------------------------------------------------------------------
/design/layout/vera-mono.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/design/layout/vera-mono.woff2
--------------------------------------------------------------------------------
/design/magic/index.css:
--------------------------------------------------------------------------------
1 |
2 | * > ._magic_,
3 | * > ._magic_ > * {
4 | display: inline-block !important;
5 | position: fixed !important;
6 | top: 0px !important;
7 | left: 0px !important;
8 | width: 1px !important;
9 | height: 1px !important;
10 | font-color: transparent !important;
11 | font-size: 0.1px !important;
12 | line-height: 0.1px !important;
13 | vertical-align: top !important;
14 | speak: none !important;
15 | overflow: hidden !important;
16 | z-index: -1 !important;
17 | }
18 |
19 |
20 |
21 | @media print {
22 |
23 | * > ._magic_,
24 | * > ._magic_ > * {
25 | display: none !important;
26 | }
27 |
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/design/search/disabled.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/design/search/hardware-legacy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
10 |
16 |
18 |
19 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/design/search/hardware-research-legacy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
15 |
17 |
19 |
20 |
22 |
24 |
26 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/design/search/hardware-research.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
10 |
16 |
18 |
19 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/design/search/hardware-software.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
9 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/design/search/hardware.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/design/search/legacy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
10 |
13 |
15 |
17 |
18 |
20 |
24 |
25 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/design/search/nothing.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/design/search/research.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/design/search/software.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/favicon.ico
--------------------------------------------------------------------------------
/projects/adblock-proxy/adblock-proxy.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/adblock-proxy/adblock-proxy.zip
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Flappy Evolution
3 |
4 | This Game was a part of the AI Crash Course Workshop I held
5 | on various events. It's an in-Browser Implementation of a
6 | simple Evolutionary AI that evolves a simple Feed-Forward
7 | Neural Network strictly by using randomization and genetic
8 | cross-breeding, without any reinforcement Learning.
9 |
10 |
11 | ## License
12 |
13 | This project is licensed under [GNU GPL 3](./LICENSE_GPL3.txt)
14 | and is `(c) 2017-2021 Cookie Engineer`.
15 |
16 |
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/ai-1-flappy-evolution.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-1-flappy-evolution/ai-1-flappy-evolution.zip
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-1-flappy-evolution/background.png
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/index.css:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | margin: 0px;
4 | padding: 0px;
5 | background: #404552;
6 | }
7 |
8 | body * {
9 | -webkit-user-select: none;
10 | -moz-user-select: none;
11 | -ms-user-select: none;
12 | user-select: none;
13 | }
14 |
15 | aside {
16 | display: block;
17 | position: fixed;
18 | top: 0px;
19 | right: 0px;
20 | bottom: auto;
21 | left: 0px;
22 | margin: 0px;
23 | padding: 16px;
24 | text-align: center;
25 | border-left: 1px solid #2a2c36;
26 | background: #333742;
27 | z-index: 2;
28 | }
29 |
30 | aside h3 {
31 | display: block;
32 | margin: 0px auto 16px auto;
33 | padding: 0px;
34 | color: #ffffff;
35 | font-size: 32px;
36 | font-family: 'DejaVu Sans';
37 | text-align: center;
38 | line-height: 32px;
39 | vertical-align: middle;
40 | }
41 |
42 | aside a {
43 | display: block;
44 | position: absolute;
45 | top: 16px;
46 | right: 16px;
47 | color: #ffffff;
48 | font-family: 'DejaVu Sans';
49 | font-size: 16px;
50 | text-decoration: none;
51 | }
52 |
53 | aside a:hover,
54 | aside a:focus {
55 | color: #4dadd4;
56 | transition: all 250ms ease-out;
57 | }
58 |
59 | aside button {
60 | display: inline-block;
61 | vertical-align: top;
62 | font-size: 16px;
63 | line-height: 24px;
64 | color: #ffffff;
65 | background: #3e4351;
66 | border: 1px solid #2a2c36;
67 | border-radius: 4px;
68 | transition: all 250ms ease-out;
69 | vertical-align: middle;
70 | outline: none;
71 | cursor: pointer;
72 | }
73 |
74 | aside button:hover,
75 | aside button:focus {
76 | outline: none;
77 | background: #677085;
78 | transition: all 250ms ease-out;
79 | }
80 |
81 | aside button:active {
82 | outline: none;
83 | background: #4dadd4;
84 | transition: all 0ms ease-out;
85 | }
86 |
87 | aside button[disabled],
88 | aside button[disabled]:hover
89 | aside button[disabled]:focus,
90 | aside button[disabled]:active {
91 | color: #677085;
92 | background: #3e4351;
93 | }
94 |
95 | aside span {
96 | display: inline-block;
97 | width: 32px;
98 | }
99 |
100 | aside i {
101 | display: inline-block;
102 | margin: 0px 0px 0px 32px;
103 | color: #ffffff;
104 | font-family: 'DejaVu Sans';
105 | font-weight: normal;
106 | font-style: normal;
107 | vertical-align: middle;
108 | }
109 |
110 | canvas {
111 | position: absolute;
112 | top: 50%;
113 | top: calc(50% + 64px);
114 | right: auto;
115 | bottom: auto;
116 | left: 50%;
117 | transform: translate(-50%, -50%);
118 | border: 1px solid #2a2c36;
119 | -webkit-user-select: none;
120 | -moz-user-select: none;
121 | -ms-user-select: none;
122 | user-select: none;
123 | background: url('./background.png') center center;
124 | z-index: 1;
125 | }
126 |
127 |
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Flappy Plane Evolution
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Flappy Plane Evolution
19 | manual
20 | automatic
21 |
22 | normal
23 | fast
24 | hyper
25 | Manual: Click/Touch the Canvas to flap
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/index.mjs:
--------------------------------------------------------------------------------
1 |
2 | import { Simulation } from './source/Simulation.mjs';
3 |
4 |
5 |
6 | const SIMULATION = window.SIMULATION = new Simulation();
7 | const control = function(/* e */) {
8 |
9 | let player = SIMULATION.game.planes[0] || null;
10 | if (player !== null) {
11 | player.jump();
12 | }
13 |
14 | };
15 |
16 |
17 | let fps_buttons = Array.from(document.querySelectorAll('button.set-fps'));
18 | if (fps_buttons.length > 0) {
19 |
20 | fps_buttons.forEach((button) => {
21 |
22 | button.onclick = () => {
23 |
24 | let fps = parseInt(button.getAttribute('data-fps'), 10);
25 |
26 | if (Number.isNaN(fps) === false && fps > 0) {
27 | SIMULATION.setFPS(fps);
28 | }
29 |
30 | };
31 |
32 | });
33 |
34 | }
35 |
36 |
37 | let manual_button = document.querySelector('button#game-manual');
38 | if (manual_button !== null) {
39 |
40 | manual_button.onclick = () => {
41 |
42 | manual_button.setAttribute('disabled', true);
43 | fps_buttons.forEach((button) => button.setAttribute('disabled', true));
44 |
45 | SIMULATION.stop();
46 |
47 | setTimeout(() => {
48 |
49 | SIMULATION.game.population = [];
50 | SIMULATION.game.setFPS(60);
51 | SIMULATION.game.start();
52 |
53 | SIMULATION.update();
54 | SIMULATION.render();
55 |
56 | document.querySelector('canvas').addEventListener('click', control);
57 | auto_button.removeAttribute('disabled');
58 |
59 | }, 500);
60 |
61 | };
62 |
63 | manual_button.removeAttribute('disabled');
64 |
65 | }
66 |
67 |
68 | let auto_button = document.querySelector('button#game-auto');
69 | if (auto_button !== null) {
70 |
71 | auto_button.onclick = () => {
72 |
73 | auto_button.setAttribute('disabled', true);
74 | fps_buttons.forEach((button) => button.removeAttribute('disabled'));
75 |
76 | SIMULATION.stop();
77 |
78 | setTimeout(() => {
79 |
80 | SIMULATION.setFPS(60);
81 |
82 | SIMULATION.start();
83 | SIMULATION.update();
84 | SIMULATION.render();
85 |
86 | document.querySelector('canvas').removeEventListener('click', control);
87 | manual_button.removeAttribute('disabled');
88 |
89 | }, 500);
90 |
91 | };
92 |
93 | auto_button.removeAttribute('disabled');
94 |
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/screenshot-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-1-flappy-evolution/screenshot-small.png
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-1-flappy-evolution/screenshot.png
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/source/Agent.mjs:
--------------------------------------------------------------------------------
1 |
2 | import { Brain } from './Brain.mjs';
3 |
4 |
5 |
6 | const BRAIN_REFERENCE = {
7 | inputs: [
8 | 0.5, // plane position
9 | 0.6 // goal position
10 | ],
11 | outputs: [
12 | 1 // jump action
13 | ]
14 | };
15 |
16 |
17 |
18 | const Agent = function() {
19 |
20 | this.brain = new Brain();
21 | this.fitness = 0;
22 |
23 |
24 | // XXX: Brain needs a reference dataset
25 | this.brain.initialize(
26 | BRAIN_REFERENCE.inputs,
27 | BRAIN_REFERENCE.outputs
28 | );
29 |
30 | };
31 |
32 |
33 | Agent.prototype = {
34 |
35 | compute: function(inputs) {
36 | return this.brain.compute(inputs);
37 | },
38 |
39 | clone: function() {
40 |
41 | let clone = new Agent();
42 |
43 | // This will copy/paste the exact same Brain
44 | // onto our clone. We need this method for
45 | // having non-linked Survivors as Survivors
46 | // are Elite and can be bred into other Babies
47 | //
48 | // This avoids basically that one Agent can
49 | // by coincidence be used for several Entities
50 |
51 | clone.fitness = this.fitness;
52 | clone.brain.layers = JSON.parse(JSON.stringify(this.brain.layers));
53 |
54 |
55 | return clone;
56 |
57 | },
58 |
59 | crossover: function(agent) {
60 |
61 | let babies = [ new Agent(), new Agent() ];
62 | let brain0 = [];
63 | let brain1 = [];
64 | let weights_mum = this.brain.serialize();
65 | let weights_dad = agent.brain.serialize();
66 | let dnasplit = (Math.random() * weights_mum.length) | 0;
67 |
68 |
69 | for (let w = 0, wl = weights_mum.length; w < wl; w++) {
70 |
71 | // Cross-Breeding
72 | //
73 | // - DNA is "only" the weights of the brain
74 | // - first part of DNA is mum
75 | // - second part of DNA is dad
76 |
77 | if (w < dnasplit) {
78 | brain0[w] = weights_mum[w];
79 | brain1[w] = weights_dad[w];
80 | } else {
81 | brain0[w] = weights_dad[w];
82 | brain1[w] = weights_mum[w];
83 | }
84 |
85 |
86 | // Mutations
87 | //
88 | // - 10% Mutation Rate
89 | // - 25% Mutation Range
90 | // - Math.random() is only positive
91 | // - Math.random() * 2 - 1 can lead to negative value
92 |
93 | if (Math.random() <= 0.10) {
94 | brain0[w] += (Math.random() * 0.25 * 2) - 0.25;
95 | brain1[w] += (Math.random() * 0.25 * 2) - 0.25;
96 | }
97 |
98 | }
99 |
100 |
101 | // Baby Brains
102 | // - brain weights were generated by DNA above
103 |
104 | babies[0].brain.deserialize(brain0);
105 | babies[1].brain.deserialize(brain1);
106 |
107 |
108 | return babies;
109 |
110 | }
111 |
112 | };
113 |
114 |
115 |
116 | export { Agent };
117 |
118 |
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/source/Game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-1-flappy-evolution/source/Game.png
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/source/Goal.mjs:
--------------------------------------------------------------------------------
1 |
2 | let IMAGE = null;
3 |
4 | (function() {
5 |
6 | let img = new Image();
7 |
8 | img.onload = function() {
9 | IMAGE = this;
10 | };
11 |
12 | img.src = './source/Goal.png';
13 |
14 | })();
15 |
16 |
17 |
18 | const Goal = function(data) {
19 |
20 | this.x = 0;
21 | this.y = 0;
22 |
23 | this.alive = true;
24 | this.width = 40;
25 | this.height = 256;
26 | this.velocity = 3;
27 |
28 | if (data instanceof Object) {
29 | Object.assign(this, data);
30 | }
31 |
32 | };
33 |
34 |
35 | Goal.prototype = {
36 |
37 | update: function(/* game */) {
38 |
39 | this.x -= this.velocity;
40 |
41 |
42 | let x = this.x;
43 | let width = this.width;
44 |
45 |
46 | if (x + width < 0) {
47 | this.alive = false;
48 | }
49 |
50 | },
51 |
52 | render: function(context) {
53 |
54 | if (IMAGE !== null) {
55 |
56 | context.drawImage(
57 | IMAGE,
58 | this.x - 1 / 2 * this.width,
59 | this.y - 1 / 2 * this.height,
60 | this.width,
61 | this.height
62 | );
63 |
64 | /*
65 | context.strokeStyle = '#4dadd4';
66 | context.strokeRect(
67 | this.x - 1/2 * this.width,
68 | this.y - 1/2 * this.height,
69 | this.width,
70 | this.height
71 | );
72 | */
73 |
74 | }
75 |
76 | }
77 |
78 | };
79 |
80 |
81 |
82 | export { Goal };
83 |
84 |
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/source/Goal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-1-flappy-evolution/source/Goal.png
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/source/Plane.mjs:
--------------------------------------------------------------------------------
1 |
2 | let IMAGE = null;
3 |
4 | (function() {
5 |
6 | let img = new Image();
7 |
8 | img.onload = function() {
9 | IMAGE = this;
10 | };
11 |
12 | img.src = './source/Plane.png';
13 |
14 | })();
15 |
16 |
17 |
18 | const Plane = function() {
19 |
20 | this.x = 64;
21 | this.y = 254;
22 | this.width = 40;
23 | this.height = 32;
24 |
25 | this.alive = true;
26 | this.gravity = 0;
27 | this.velocity = 0.30;
28 |
29 | };
30 |
31 | Plane.prototype = {
32 |
33 | jump: function() {
34 | this.gravity = -6;
35 | },
36 |
37 | render: function(context) {
38 |
39 | let width = this.width;
40 | let height = this.height;
41 |
42 |
43 | context.save();
44 |
45 | context.translate(
46 | this.x,
47 | this.y
48 | );
49 |
50 | context.rotate(Math.PI / 2 * this.gravity / 20);
51 |
52 | if (IMAGE !== null) {
53 |
54 | context.drawImage(
55 | IMAGE,
56 | -1 / 2 * width,
57 | -1 / 2 * height,
58 | width,
59 | height
60 | );
61 |
62 | }
63 |
64 | context.restore();
65 |
66 | },
67 |
68 | update: function(game) {
69 |
70 | // Gravity is in Y direction
71 | // Plane never moves in X direction
72 | // (Game moves Goals, not Planes)
73 | this.gravity += this.velocity;
74 | this.y += this.gravity;
75 |
76 |
77 | let x = this.x;
78 | let y = this.y;
79 | let hw = this.width / 2;
80 | let hh = this.height / 2;
81 |
82 |
83 | // Plane moves outside Game Field
84 | // - dies if flapped too high
85 | // - dies if gravity caused crash
86 | if (y >= game.height || y <= 0) {
87 | this.alive = false;
88 | }
89 |
90 |
91 | if (this.alive === true) {
92 |
93 | // AABB collisions for Plane with each Goal
94 | for (let g = 0, gl = game.goals.length; g < gl; g++) {
95 |
96 | let goal = game.goals[g];
97 | let ghw = goal.width / 2;
98 | let ghh = goal.height / 2;
99 |
100 | // XXX: Boxes are 40px each
101 | // but game will be too hard to solve
102 | // let ghh = (goal.height - 80) / 2;
103 |
104 | let min_x = goal.x - ghw;
105 | let max_x = goal.x + ghw;
106 | let min_y = goal.y - ghh;
107 | let max_y = goal.y + ghh;
108 |
109 | if (x + hw > min_x && x - hw < max_x) {
110 |
111 | if (y - hh > min_y && y + hh < max_y) {
112 | // this.alive = true;
113 | } else {
114 | this.alive = false;
115 | break;
116 | }
117 |
118 | }
119 |
120 | }
121 |
122 | }
123 |
124 | }
125 |
126 | };
127 |
128 |
129 | export { Plane };
130 |
131 |
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/source/Plane.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-1-flappy-evolution/source/Plane.png
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/source/Simulation.mjs:
--------------------------------------------------------------------------------
1 |
2 | import { Game } from './Game.mjs';
3 | import { Evolution } from './Evolution.mjs';
4 |
5 |
6 |
7 | const Simulation = function() {
8 |
9 | this.evolution = new Evolution({ population: 64 });
10 | this.fps = 60;
11 | this.game = new Game();
12 |
13 | };
14 |
15 |
16 | Simulation.prototype = {
17 |
18 | start: function() {
19 |
20 | let population = this.evolution.cycle();
21 |
22 | this.game.population = population;
23 | this.game.start();
24 |
25 | },
26 |
27 | restart: function() {
28 |
29 | let population = this.evolution.cycle();
30 |
31 | this.game.population = population;
32 | this.game.restart();
33 |
34 | this.update();
35 | this.render();
36 |
37 | },
38 |
39 | stop: function() {
40 |
41 | this.game.stop();
42 |
43 | },
44 |
45 | update: function() {
46 |
47 | if (this.game._has_ended === false) {
48 | this.game.update();
49 | }
50 |
51 | if (this.game._has_ended === false) {
52 | setTimeout(() => this.update(), 1000 / this.fps);
53 | } else {
54 | setTimeout(() => this.restart(), 16);
55 | }
56 |
57 | },
58 |
59 | render: function() {
60 |
61 | if (this.game._has_ended === false) {
62 | this.game.render();
63 | }
64 |
65 | if (this.game._has_ended === false) {
66 | requestAnimationFrame(() => this.render());
67 | }
68 |
69 | },
70 |
71 |
72 |
73 | /*
74 | * CUSTOM API
75 | */
76 |
77 | setFPS: function(fps) {
78 |
79 | fps = typeof fps === 'number' ? fps : 60;
80 |
81 |
82 | if (this.fps !== fps) {
83 |
84 | this.fps = fps;
85 | this.game.setFPS(fps);
86 |
87 | return true;
88 |
89 | }
90 |
91 |
92 | return false;
93 |
94 | }
95 |
96 | };
97 |
98 |
99 |
100 | export { Simulation };
101 |
102 |
--------------------------------------------------------------------------------
/projects/ai-1-flappy-evolution/source/Twister.mjs:
--------------------------------------------------------------------------------
1 |
2 | const UPPER_MASK = 0x80000000;
3 | const LOWER_MASK = 0x7fffffff;
4 | const XOR_MATRIX = new Array(0x0, 0x9908b0df);
5 |
6 | const initialize = function(seed) {
7 |
8 | let index = 1;
9 | let N = this.N;
10 | let twister = this.twister;
11 |
12 |
13 | twister[0] = seed >>> 0;
14 |
15 |
16 | while (index < N) {
17 |
18 | let value = twister[index - 1] ^ (twister[index - 1] >>> 30);
19 |
20 | twister[index] = (((((value & 0xffff0000) >>> 16) * 1812433253) << 16) + (value & 0x0000ffff) * 1812433253) + index;
21 | twister[index] >>>= 0;
22 |
23 | index++;
24 |
25 | }
26 |
27 | this.index = index;
28 |
29 | };
30 |
31 | const random_int32 = function() {
32 |
33 | let index = this.index;
34 | let twister = this.twister;
35 | let value = 0;
36 | let M = this.M;
37 | let N = this.N;
38 |
39 |
40 | if (index >= N) {
41 |
42 | let i = 0;
43 |
44 | if (index === N + 1) {
45 | initialize.call(this, 5489);
46 | }
47 |
48 |
49 | while (i < N - M) {
50 |
51 | value = (twister[i] & UPPER_MASK) | (twister[i + 1] & LOWER_MASK);
52 | twister[i] = twister[i + M] ^ (value >>> 1) ^ XOR_MATRIX[value & 0x1];
53 |
54 | i++;
55 |
56 | }
57 |
58 | while (i < N - 1) {
59 |
60 | value = (twister[i] & UPPER_MASK) | (twister[i + 1] & LOWER_MASK);
61 | twister[i] = twister[i + (M - N)] ^ (value >>> 1) ^ XOR_MATRIX[value & 0x1];
62 |
63 | i++;
64 |
65 | }
66 |
67 |
68 | value = (twister[N - 1] & UPPER_MASK) | (twister[0] & LOWER_MASK);
69 | twister[N - 1] = twister[M - 1] ^ (value >>> 1) ^ XOR_MATRIX[value & 0x1];
70 |
71 | this.index = 0;
72 |
73 | }
74 |
75 |
76 | value = twister[this.index++];
77 |
78 | value ^= (value >>> 11);
79 | value ^= (value << 7) & 0x9d2c5680;
80 | value ^= (value << 15) & 0xefc60000;
81 | value ^= (value >>> 18);
82 |
83 |
84 | return value >>> 0;
85 |
86 | };
87 |
88 |
89 |
90 | const Twister = function(seed) {
91 |
92 | seed = typeof seed === 'number' ? (seed | 0) : ((Math.random() * Number.MAX_SAFE_INTEGER) | 0);
93 |
94 |
95 | this.N = 624;
96 | this.M = 397;
97 |
98 | this.twister = new Array(this.N);
99 | this.index = this.N + 1;
100 |
101 | this.__seed = seed;
102 |
103 |
104 | initialize.call(this, seed);
105 |
106 | seed = null;
107 |
108 | };
109 |
110 |
111 | Twister.prototype = {
112 |
113 | random: function() {
114 |
115 | return random_int32.call(this) * (1.0 / 4294967296.0);
116 |
117 | }
118 |
119 | };
120 |
121 |
122 |
123 | export { Twister };
124 |
--------------------------------------------------------------------------------
/projects/ai-2-pong/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Reinforcement Pong AI
3 |
4 | This Game was a part of the AI Crash Course Workshop I held
5 | on various events. It's an in-Browser Implementation of a
6 | simple Reinforcement AI that also can be manually played
7 | against.
8 |
9 |
10 | ## License
11 |
12 | This project is licensed under [GNU GPL 3](./LICENSE_GPL3.txt)
13 | and is `(c) 2017-2021 Cookie Engineer`.
14 |
15 |
--------------------------------------------------------------------------------
/projects/ai-2-pong/ai-2-pong.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-2-pong/ai-2-pong.zip
--------------------------------------------------------------------------------
/projects/ai-2-pong/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-2-pong/background.png
--------------------------------------------------------------------------------
/projects/ai-2-pong/index.css:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | margin: 0px;
4 | padding: 0px;
5 | background: #404552;
6 | }
7 |
8 | body * {
9 | -webkit-user-select: none;
10 | -moz-user-select: none;
11 | -ms-user-select: none;
12 | user-select: none;
13 | }
14 |
15 | aside {
16 | display: block;
17 | position: fixed;
18 | top: 0px;
19 | right: 0px;
20 | bottom: auto;
21 | left: 0px;
22 | margin: 0px;
23 | padding: 16px;
24 | text-align: center;
25 | border-left: 1px solid #2a2c36;
26 | background: #333742;
27 | z-index: 2;
28 | }
29 |
30 | aside h3 {
31 | display: block;
32 | margin: 0px auto 16px auto;
33 | padding: 0px;
34 | color: #ffffff;
35 | font-size: 32px;
36 | font-family: 'DejaVu Sans';
37 | text-align: center;
38 | line-height: 32px;
39 | vertical-align: middle;
40 | }
41 |
42 | aside a {
43 | display: block;
44 | position: absolute;
45 | top: 16px;
46 | right: 16px;
47 | color: #ffffff;
48 | font-family: 'DejaVu Sans';
49 | font-size: 16px;
50 | text-decoration: none;
51 | }
52 |
53 | aside a:hover,
54 | aside a:focus {
55 | color: #4dadd4;
56 | transition: all 250ms ease-out;
57 | }
58 |
59 | aside button {
60 | display: inline-block;
61 | vertical-align: top;
62 | font-size: 16px;
63 | line-height: 24px;
64 | color: #ffffff;
65 | background: #3e4351;
66 | border: 1px solid #2a2c36;
67 | border-radius: 4px;
68 | transition: all 250ms ease-out;
69 | vertical-align: middle;
70 | outline: none;
71 | cursor: pointer;
72 | }
73 |
74 | aside button:hover,
75 | aside button:focus {
76 | outline: none;
77 | background: #677085;
78 | transition: all 250ms ease-out;
79 | }
80 |
81 | aside button:active {
82 | outline: none;
83 | background: #4dadd4;
84 | transition: all 0ms ease-out;
85 | }
86 |
87 | aside button[disabled],
88 | aside button[disabled]:hover
89 | aside button[disabled]:focus,
90 | aside button[disabled]:active {
91 | color: #677085;
92 | background: #3e4351;
93 | }
94 |
95 | aside span {
96 | display: inline-block;
97 | width: 32px;
98 | }
99 |
100 | aside i {
101 | display: inline-block;
102 | margin: 0px 0px 0px 32px;
103 | color: #ffffff;
104 | font-family: 'DejaVu Sans';
105 | font-weight: normal;
106 | font-style: normal;
107 | vertical-align: middle;
108 | }
109 |
110 | canvas {
111 | position: absolute;
112 | top: 50%;
113 | top: calc(50% + 64px);
114 | right: auto;
115 | bottom: auto;
116 | left: 50%;
117 | transform: translate(-50%, -50%);
118 | border: 1px solid #2a2c36;
119 | -webkit-user-select: none;
120 | -moz-user-select: none;
121 | -ms-user-select: none;
122 | user-select: none;
123 | background: url('./background.png') center center;
124 | z-index: 1;
125 | }
126 |
127 |
--------------------------------------------------------------------------------
/projects/ai-2-pong/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Reinforcement Pong AI Demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | manual
19 | automatic
20 |
21 | normal
22 | fast
23 | hyper
24 | Manual: Use Arrow keys or WASD to move
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/projects/ai-2-pong/screenshot-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-2-pong/screenshot-small.png
--------------------------------------------------------------------------------
/projects/ai-2-pong/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-2-pong/screenshot.png
--------------------------------------------------------------------------------
/projects/ai-2-pong/source/Agent.mjs:
--------------------------------------------------------------------------------
1 |
2 | import { Brain } from './Brain.mjs';
3 |
4 |
5 |
6 | const BRAIN_REFERENCE = {
7 | inputs: [
8 | 0, 0.5, // paddle position
9 | 0, 0.8, // ball position
10 | 0.5, 0.2 // ball speed (1.0 == 25px/frame)
11 | ],
12 | outputs: [
13 | 0.8 // targeted y position
14 | ]
15 | };
16 |
17 |
18 |
19 | const Agent = function() {
20 |
21 | this.brain = new Brain();
22 |
23 |
24 | // XXX: Brain needs a reference dataset
25 | this.brain.initialize(
26 | BRAIN_REFERENCE.inputs,
27 | BRAIN_REFERENCE.outputs
28 | );
29 |
30 | };
31 |
32 | Agent.prototype = {
33 |
34 | compute: function(inputs) {
35 | return this.brain.compute(inputs);
36 | },
37 |
38 | learn: function(inputs, outputs) {
39 | return this.brain.learn(inputs, outputs);
40 | },
41 |
42 | clone: function() {
43 |
44 | let clone = new Agent();
45 |
46 | // This will copy/paste the exact same Brain
47 | // onto our clone. We need this method for
48 | // having non-linked properties, in case
49 | // this implementation is reused in an
50 | // Evolutionary algorithm.
51 |
52 | clone.brain.layers = JSON.parse(JSON.stringify(this.brain.layers));
53 |
54 |
55 | return clone;
56 |
57 | }
58 |
59 | };
60 |
61 |
62 | export { Agent };
63 |
64 |
--------------------------------------------------------------------------------
/projects/ai-2-pong/source/Ball.mjs:
--------------------------------------------------------------------------------
1 |
2 | const Ball = function(data) {
3 |
4 | this.x = 0;
5 | this.y = 0;
6 | this.vx = 0;
7 | this.vy = 0;
8 |
9 | this.last_hit = null;
10 | this.radius = 8;
11 | this.trail = [];
12 |
13 | this._t = 0;
14 | this._count = 0;
15 |
16 | if (data instanceof Object) {
17 | Object.assign(this, data);
18 | }
19 |
20 | };
21 |
22 |
23 | Ball.prototype = {
24 |
25 | render: function(context) {
26 |
27 | let radius = this.radius;
28 | let trail = this.trail;
29 |
30 |
31 | context.beginPath();
32 | context.fillStyle = '#f6336d';
33 | context.arc(
34 | this.x,
35 | this.y,
36 | radius,
37 | 0,
38 | 2 * Math.PI
39 | );
40 | context.fill();
41 |
42 |
43 | for (let t = trail.length - 1, tl = trail.length; t >= 0; t--) {
44 |
45 | let pos = trail[t];
46 | let a = t / tl;
47 |
48 | context.globalAlpha = a * 0.5;
49 | context.beginPath();
50 | context.fillStyle = '#f6336d';
51 | context.arc(
52 | pos.x,
53 | pos.y,
54 | a * radius,
55 | 0,
56 | 2 * Math.PI
57 | );
58 | context.fill();
59 |
60 | }
61 |
62 |
63 | context.globalAlpha = 1;
64 |
65 | },
66 |
67 | update: function(game) {
68 |
69 | this.x += this.vx;
70 | this.y += this.vy;
71 |
72 | let x = this.x;
73 | let y = this.y;
74 | let r = this.radius;
75 |
76 |
77 | if (x - r <= 0) {
78 | this.alive = false;
79 | this.last_hit = null;
80 | } else if (x + r >= game.width) {
81 | this.alive = false;
82 | this.last_hit = null;
83 | }
84 |
85 | if (y - r <= 0) {
86 | this.y = r;
87 | this.vy = -1 * this.vy;
88 | this.last_hit = null;
89 | } else if (y + r >= game.height) {
90 | this.y = game.height - r;
91 | this.vy = -1 * this.vy;
92 | this.last_hit = null;
93 | }
94 |
95 |
96 | this._count++;
97 |
98 |
99 | if (this._count > 2) {
100 |
101 |
102 | if (this.trail.length < 8) {
103 |
104 | this.trail.push({ x: this.x, y: this.y });
105 |
106 | } else {
107 |
108 | let pos = this.trail.splice(0, 1);
109 |
110 | pos.x = this.x;
111 | pos.y = this.y;
112 |
113 | this.trail.push(pos);
114 |
115 | }
116 |
117 |
118 | this._count = 0;
119 |
120 | }
121 |
122 | }
123 |
124 | };
125 |
126 |
127 |
128 | export { Ball };
129 |
130 |
--------------------------------------------------------------------------------
/projects/ai-2-pong/source/Game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-2-pong/source/Game.png
--------------------------------------------------------------------------------
/projects/ai-2-pong/source/Paddle.blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-2-pong/source/Paddle.blue.png
--------------------------------------------------------------------------------
/projects/ai-2-pong/source/Paddle.red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-2-pong/source/Paddle.red.png
--------------------------------------------------------------------------------
/projects/ai-2-pong/source/Twister.mjs:
--------------------------------------------------------------------------------
1 |
2 | const UPPER_MASK = 0x80000000;
3 | const LOWER_MASK = 0x7fffffff;
4 | const XOR_MATRIX = new Array(0x0, 0x9908b0df);
5 |
6 | const initialize = function(seed) {
7 |
8 | let index = 1;
9 | let N = this.N;
10 | let twister = this.twister;
11 |
12 |
13 | twister[0] = seed >>> 0;
14 |
15 |
16 | while (index < N) {
17 |
18 | let value = twister[index - 1] ^ (twister[index - 1] >>> 30);
19 |
20 | twister[index] = (((((value & 0xffff0000) >>> 16) * 1812433253) << 16) + (value & 0x0000ffff) * 1812433253) + index;
21 | twister[index] >>>= 0;
22 |
23 | index++;
24 |
25 | }
26 |
27 | this.index = index;
28 |
29 | };
30 |
31 | const random_int32 = function() {
32 |
33 | let index = this.index;
34 | let twister = this.twister;
35 | let value = 0;
36 | let M = this.M;
37 | let N = this.N;
38 |
39 |
40 | if (index >= N) {
41 |
42 | let i = 0;
43 |
44 | if (index === N + 1) {
45 | initialize.call(this, 5489);
46 | }
47 |
48 |
49 | while (i < N - M) {
50 |
51 | value = (twister[i] & UPPER_MASK) | (twister[i + 1] & LOWER_MASK);
52 | twister[i] = twister[i + M] ^ (value >>> 1) ^ XOR_MATRIX[value & 0x1];
53 |
54 | i++;
55 |
56 | }
57 |
58 | while (i < N - 1) {
59 |
60 | value = (twister[i] & UPPER_MASK) | (twister[i + 1] & LOWER_MASK);
61 | twister[i] = twister[i + (M - N)] ^ (value >>> 1) ^ XOR_MATRIX[value & 0x1];
62 |
63 | i++;
64 |
65 | }
66 |
67 |
68 | value = (twister[N - 1] & UPPER_MASK) | (twister[0] & LOWER_MASK);
69 | twister[N - 1] = twister[M - 1] ^ (value >>> 1) ^ XOR_MATRIX[value & 0x1];
70 |
71 | this.index = 0;
72 |
73 | }
74 |
75 |
76 | value = twister[this.index++];
77 |
78 | value ^= (value >>> 11);
79 | value ^= (value << 7) & 0x9d2c5680;
80 | value ^= (value << 15) & 0xefc60000;
81 | value ^= (value >>> 18);
82 |
83 |
84 | return value >>> 0;
85 |
86 | };
87 |
88 |
89 |
90 | const Twister = function(seed) {
91 |
92 | seed = typeof seed === 'number' ? (seed | 0) : ((Math.random() * Number.MAX_SAFE_INTEGER) | 0);
93 |
94 |
95 | this.N = 624;
96 | this.M = 397;
97 |
98 | this.twister = new Array(this.N);
99 | this.index = this.N + 1;
100 |
101 | this.__seed = seed;
102 |
103 |
104 | initialize.call(this, seed);
105 |
106 | seed = null;
107 |
108 | };
109 |
110 |
111 | Twister.prototype = {
112 |
113 | random: function() {
114 |
115 | return random_int32.call(this) * (1.0 / 4294967296.0);
116 |
117 | }
118 |
119 | };
120 |
121 |
122 |
123 | export { Twister };
124 |
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Pong Evolution
3 |
4 | This Game was a part of the AI Crash Course Workshop I held
5 | on various events. It's an in-Browser Implementation of a
6 | simple Evolutionary AI that can be scaled up with multiple
7 | Game Simulations in parallel in order to advance each Agent's
8 | Training and competitive advantages.
9 |
10 |
11 | ## License
12 |
13 | This project is licensed under [GNU GPL 3](./LICENSE_GPL3.txt)
14 | and is `(c) 2017-2021 Cookie Engineer`.
15 |
16 |
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/ai-3-pong-evolution.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-3-pong-evolution/ai-3-pong-evolution.zip
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-3-pong-evolution/background.png
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Reinforcement Pong AI Demo with Evolution
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Next Epoche
19 | (Please activate ECMAScript)
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/index.mjs:
--------------------------------------------------------------------------------
1 |
2 | import { Simulation } from './source/Simulation.mjs';
3 |
4 |
5 |
6 | const SIMULATION = window.SIMULATION = new Simulation({
7 | active: 0,
8 | games: 16
9 | });
10 |
11 | SIMULATION.setFPS(300);
12 | SIMULATION.start();
13 | SIMULATION.update();
14 | SIMULATION.render();
15 |
16 |
17 |
18 | let next_button = document.querySelector('aside button');
19 | if (next_button !== null) {
20 |
21 | next_button.onclick = () => {
22 | SIMULATION.evolution.cycle();
23 | };
24 |
25 | next_button.removeAttribute('disabled');
26 |
27 | }
28 |
29 |
30 | let menu = document.querySelector('aside menu');
31 | if (menu !== null) {
32 |
33 | menu.innerHTML = SIMULATION.games.map((game, g) => {
34 | return '#' + g + ' ';
35 | }).join('');
36 |
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/screenshot-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-3-pong-evolution/screenshot-small.png
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-3-pong-evolution/screenshot.png
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/source/Agent.mjs:
--------------------------------------------------------------------------------
1 |
2 | import { Brain } from './Brain.mjs';
3 |
4 |
5 |
6 | const BRAIN_REFERENCE = {
7 | inputs: [
8 | 0, 0.5, // paddle position
9 | 0, 0.8, // ball position
10 | 0.5, 0.2 // ball speed (1.0 == 25px/frame)
11 | ],
12 | outputs: [
13 | 0.8 // targeted y position
14 | ]
15 | };
16 |
17 |
18 |
19 | const Agent = function() {
20 |
21 | this.brain = new Brain();
22 | this.fitness = 0;
23 |
24 |
25 | // XXX: Brain needs a reference dataset
26 | this.brain.initialize(
27 | BRAIN_REFERENCE.inputs,
28 | BRAIN_REFERENCE.outputs
29 | );
30 |
31 | };
32 |
33 | Agent.prototype = {
34 |
35 | compute: function(inputs) {
36 | return this.brain.compute(inputs);
37 | },
38 |
39 | learn: function(inputs, outputs) {
40 | return this.brain.learn(inputs, outputs);
41 | },
42 |
43 | clone: function() {
44 |
45 | let clone = new Agent();
46 |
47 | // This will copy/paste the exact same Brain
48 | // onto our clone. We need this method for
49 | // having non-linked properties, in case
50 | // this implementation is reused in an
51 | // Evolutionary algorithm.
52 |
53 | clone.fitness = this.fitness;
54 | clone.brain.layers = JSON.parse(JSON.stringify(this.brain.layers));
55 |
56 |
57 | return clone;
58 |
59 | },
60 |
61 | crossover: function(agent) {
62 |
63 | let brain1 = this.brain.serialize();
64 | let brain2 = agent.brain.serialize();
65 | let brain3 = [];
66 | let brain4 = [];
67 |
68 | let split = Math.floor(Math.random() * brain1.length);
69 | let daughter = new Agent();
70 | let son = new Agent();
71 |
72 |
73 | for (let b = 0; b < brain1.length; b++) {
74 |
75 | if (b < split) {
76 | brain3.push(brain1[b]);
77 | brain4.push(brain2[b]);
78 | } else {
79 | brain3.push(brain2[b]);
80 | brain4.push(brain1[b]);
81 | }
82 |
83 | }
84 |
85 |
86 | daughter.brain.deserialize(brain3);
87 | son.brain.deserialize(brain4);
88 |
89 |
90 | return [ daughter, son ];
91 |
92 | }
93 |
94 | };
95 |
96 |
97 | export { Agent };
98 |
99 |
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/source/Ball.mjs:
--------------------------------------------------------------------------------
1 |
2 | const Ball = function(data) {
3 |
4 | this.x = 0;
5 | this.y = 0;
6 | this.vx = 0;
7 | this.vy = 0;
8 |
9 | this.last_hit = null;
10 | this.radius = 8;
11 | this.trail = [];
12 |
13 | this._t = 0;
14 | this._count = 0;
15 |
16 | if (data instanceof Object) {
17 | Object.assign(this, data);
18 | }
19 |
20 | };
21 |
22 |
23 | Ball.prototype = {
24 |
25 | render: function(context) {
26 |
27 | let radius = this.radius;
28 | let trail = this.trail;
29 |
30 |
31 | context.beginPath();
32 | context.fillStyle = '#f6336d';
33 | context.arc(
34 | this.x,
35 | this.y,
36 | radius,
37 | 0,
38 | 2 * Math.PI
39 | );
40 | context.fill();
41 |
42 |
43 | for (let t = trail.length - 1, tl = trail.length; t >= 0; t--) {
44 |
45 | let pos = trail[t];
46 | let a = t / tl;
47 |
48 | context.globalAlpha = a * 0.5;
49 | context.beginPath();
50 | context.fillStyle = '#f6336d';
51 | context.arc(
52 | pos.x,
53 | pos.y,
54 | a * radius,
55 | 0,
56 | 2 * Math.PI
57 | );
58 | context.fill();
59 |
60 | }
61 |
62 |
63 | context.globalAlpha = 1;
64 |
65 | },
66 |
67 | update: function(game) {
68 |
69 | this.x += this.vx;
70 | this.y += this.vy;
71 |
72 | let x = this.x;
73 | let y = this.y;
74 | let r = this.radius;
75 |
76 |
77 | if (x - r <= 0) {
78 | this.alive = false;
79 | this.last_hit = null;
80 | } else if (x + r >= game.width) {
81 | this.alive = false;
82 | this.last_hit = null;
83 | }
84 |
85 | if (y - r <= 0) {
86 | this.y = r;
87 | this.vy = -1 * this.vy;
88 | this.last_hit = null;
89 | } else if (y + r >= game.height) {
90 | this.y = game.height - r;
91 | this.vy = -1 * this.vy;
92 | this.last_hit = null;
93 | }
94 |
95 |
96 | this._count++;
97 |
98 |
99 | if (this._count > 2) {
100 |
101 |
102 | if (this.trail.length < 8) {
103 |
104 | this.trail.push({ x: this.x, y: this.y });
105 |
106 | } else {
107 |
108 | let pos = this.trail.splice(0, 1);
109 |
110 | pos.x = this.x;
111 | pos.y = this.y;
112 |
113 | this.trail.push(pos);
114 |
115 | }
116 |
117 |
118 | this._count = 0;
119 |
120 | }
121 |
122 | }
123 |
124 | };
125 |
126 |
127 |
128 | export { Ball };
129 |
130 |
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/source/Game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-3-pong-evolution/source/Game.png
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/source/Paddle.blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-3-pong-evolution/source/Paddle.blue.png
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/source/Paddle.red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/ai-3-pong-evolution/source/Paddle.red.png
--------------------------------------------------------------------------------
/projects/ai-3-pong-evolution/source/Twister.mjs:
--------------------------------------------------------------------------------
1 |
2 | const UPPER_MASK = 0x80000000;
3 | const LOWER_MASK = 0x7fffffff;
4 | const XOR_MATRIX = new Array(0x0, 0x9908b0df);
5 |
6 | const initialize = function(seed) {
7 |
8 | let index = 1;
9 | let N = this.N;
10 | let twister = this.twister;
11 |
12 |
13 | twister[0] = seed >>> 0;
14 |
15 |
16 | while (index < N) {
17 |
18 | let value = twister[index - 1] ^ (twister[index - 1] >>> 30);
19 |
20 | twister[index] = (((((value & 0xffff0000) >>> 16) * 1812433253) << 16) + (value & 0x0000ffff) * 1812433253) + index;
21 | twister[index] >>>= 0;
22 |
23 | index++;
24 |
25 | }
26 |
27 | this.index = index;
28 |
29 | };
30 |
31 | const random_int32 = function() {
32 |
33 | let index = this.index;
34 | let twister = this.twister;
35 | let value = 0;
36 | let M = this.M;
37 | let N = this.N;
38 |
39 |
40 | if (index >= N) {
41 |
42 | let i = 0;
43 |
44 | if (index === N + 1) {
45 | initialize.call(this, 5489);
46 | }
47 |
48 |
49 | while (i < N - M) {
50 |
51 | value = (twister[i] & UPPER_MASK) | (twister[i + 1] & LOWER_MASK);
52 | twister[i] = twister[i + M] ^ (value >>> 1) ^ XOR_MATRIX[value & 0x1];
53 |
54 | i++;
55 |
56 | }
57 |
58 | while (i < N - 1) {
59 |
60 | value = (twister[i] & UPPER_MASK) | (twister[i + 1] & LOWER_MASK);
61 | twister[i] = twister[i + (M - N)] ^ (value >>> 1) ^ XOR_MATRIX[value & 0x1];
62 |
63 | i++;
64 |
65 | }
66 |
67 |
68 | value = (twister[N - 1] & UPPER_MASK) | (twister[0] & LOWER_MASK);
69 | twister[N - 1] = twister[M - 1] ^ (value >>> 1) ^ XOR_MATRIX[value & 0x1];
70 |
71 | this.index = 0;
72 |
73 | }
74 |
75 |
76 | value = twister[this.index++];
77 |
78 | value ^= (value >>> 11);
79 | value ^= (value << 7) & 0x9d2c5680;
80 | value ^= (value << 15) & 0xefc60000;
81 | value ^= (value >>> 18);
82 |
83 |
84 | return value >>> 0;
85 |
86 | };
87 |
88 |
89 |
90 | const Twister = function(seed) {
91 |
92 | seed = typeof seed === 'number' ? (seed | 0) : ((Math.random() * Number.MAX_SAFE_INTEGER) | 0);
93 |
94 |
95 | this.N = 624;
96 | this.M = 397;
97 |
98 | this.twister = new Array(this.N);
99 | this.index = this.N + 1;
100 |
101 | this.__seed = seed;
102 |
103 |
104 | initialize.call(this, seed);
105 |
106 | seed = null;
107 |
108 | };
109 |
110 |
111 | Twister.prototype = {
112 |
113 | random: function() {
114 |
115 | return random_int32.call(this) * (1.0 / 4294967296.0);
116 |
117 | }
118 |
119 | };
120 |
121 |
122 |
123 | export { Twister };
124 |
--------------------------------------------------------------------------------
/projects/dns-proxy/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/dns-proxy/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/dns-proxy/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/dns-proxy/screenshot-01.png
--------------------------------------------------------------------------------
/projects/dnsquery/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/dnsquery/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/dnsquery/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/dnsquery/screenshot-01.png
--------------------------------------------------------------------------------
/projects/gibook-editor/gibook-editor.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/gibook-editor/gibook-editor.zip
--------------------------------------------------------------------------------
/projects/gibook-editor/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/gibook-editor/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/gibook-editor/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/gibook-editor/screenshot-01.png
--------------------------------------------------------------------------------
/projects/gibook-editor/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/gibook-editor/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/gibook-editor/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/gibook-editor/screenshot-02.png
--------------------------------------------------------------------------------
/projects/git-cockpit/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-cockpit/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/git-cockpit/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-cockpit/screenshot-01.png
--------------------------------------------------------------------------------
/projects/git-cockpit/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-cockpit/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/git-cockpit/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-cockpit/screenshot-02.png
--------------------------------------------------------------------------------
/projects/git-work/git-work.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-work/git-work.zip
--------------------------------------------------------------------------------
/projects/git-work/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-work/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/git-work/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-work/screenshot-01.png
--------------------------------------------------------------------------------
/projects/git-work/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-work/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/git-work/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-work/screenshot-02.png
--------------------------------------------------------------------------------
/projects/git-work/screenshot-03-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-work/screenshot-03-small.png
--------------------------------------------------------------------------------
/projects/git-work/screenshot-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/git-work/screenshot-03.png
--------------------------------------------------------------------------------
/projects/github-scrumboard/github-scrumboard-0.0.4.crx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/github-scrumboard/github-scrumboard-0.0.4.crx
--------------------------------------------------------------------------------
/projects/github-scrumboard/github-scrumboard.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/github-scrumboard/github-scrumboard.zip
--------------------------------------------------------------------------------
/projects/github-scrumboard/github_scrumboard-0.0.4.xpi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/github-scrumboard/github_scrumboard-0.0.4.xpi
--------------------------------------------------------------------------------
/projects/github-scrumboard/screencast-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/github-scrumboard/screencast-01-small.png
--------------------------------------------------------------------------------
/projects/github-scrumboard/screencast-01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/github-scrumboard/screencast-01.gif
--------------------------------------------------------------------------------
/projects/gnome-shell-extension-outta-space/gnome-shell-extension-outta-space.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/gnome-shell-extension-outta-space/gnome-shell-extension-outta-space.zip
--------------------------------------------------------------------------------
/projects/jquery-desktop/jquery-desktop.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/jquery-desktop/jquery-desktop.zip
--------------------------------------------------------------------------------
/projects/lycheejs-breeder/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-breeder/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-breeder/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-breeder/screenshot-01.png
--------------------------------------------------------------------------------
/projects/lycheejs-breeder/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-breeder/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-breeder/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-breeder/screenshot-02.png
--------------------------------------------------------------------------------
/projects/lycheejs-breeder/screenshot-03-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-breeder/screenshot-03-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-breeder/screenshot-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-breeder/screenshot-03.png
--------------------------------------------------------------------------------
/projects/lycheejs-engine/lycheejs.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-engine/lycheejs.zip
--------------------------------------------------------------------------------
/projects/lycheejs-engine/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-engine/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-engine/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-engine/screenshot-01.png
--------------------------------------------------------------------------------
/projects/lycheejs-engine/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-engine/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-engine/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-engine/screenshot-02.png
--------------------------------------------------------------------------------
/projects/lycheejs-engine/screenshot-03-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-engine/screenshot-03-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-engine/screenshot-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-engine/screenshot-03.png
--------------------------------------------------------------------------------
/projects/lycheejs-engine/screenshot-04-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-engine/screenshot-04-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-engine/screenshot-04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-engine/screenshot-04.png
--------------------------------------------------------------------------------
/projects/lycheejs-fertilizer/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-fertilizer/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-fertilizer/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-fertilizer/screenshot-01.png
--------------------------------------------------------------------------------
/projects/lycheejs-fertilizer/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-fertilizer/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-fertilizer/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-fertilizer/screenshot-02.png
--------------------------------------------------------------------------------
/projects/lycheejs-harvester/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-harvester/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-harvester/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-harvester/screenshot-01.png
--------------------------------------------------------------------------------
/projects/lycheejs-harvester/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-harvester/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-harvester/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-harvester/screenshot-02.png
--------------------------------------------------------------------------------
/projects/lycheejs-harvester/screenshot-03-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-harvester/screenshot-03-small.png
--------------------------------------------------------------------------------
/projects/lycheejs-harvester/screenshot-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/lycheejs-harvester/screenshot-03.png
--------------------------------------------------------------------------------
/projects/me-want-cookies/me-want-cookies.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/me-want-cookies/me-want-cookies.zip
--------------------------------------------------------------------------------
/projects/me-want-cookies/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/me-want-cookies/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/me-want-cookies/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/me-want-cookies/screenshot-01.png
--------------------------------------------------------------------------------
/projects/pacman-backup/pacman-backup-1.0.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/pacman-backup/pacman-backup-1.0.0.zip
--------------------------------------------------------------------------------
/projects/pacman-backup/pacman-backup-2.0.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/pacman-backup/pacman-backup-2.0.1.zip
--------------------------------------------------------------------------------
/projects/patienteninfo-service/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/patienteninfo-service/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/patienteninfo-service/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/patienteninfo-service/screenshot-01.png
--------------------------------------------------------------------------------
/projects/patienteninfo-service/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/patienteninfo-service/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/patienteninfo-service/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/patienteninfo-service/screenshot-02.png
--------------------------------------------------------------------------------
/projects/polyfillr/polyfillr.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/polyfillr/polyfillr.zip
--------------------------------------------------------------------------------
/projects/polyfillr/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/polyfillr/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/polyfillr/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/polyfillr/screenshot-01.png
--------------------------------------------------------------------------------
/projects/polyfillr/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/polyfillr/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/polyfillr/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/polyfillr/screenshot-02.png
--------------------------------------------------------------------------------
/projects/research/research.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/research/research.zip
--------------------------------------------------------------------------------
/projects/research/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/research/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/research/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/research/screenshot-01.png
--------------------------------------------------------------------------------
/projects/research/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/research/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/research/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/research/screenshot-02.png
--------------------------------------------------------------------------------
/projects/research/screenshot-03-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/research/screenshot-03-small.png
--------------------------------------------------------------------------------
/projects/research/screenshot-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/research/screenshot-03.png
--------------------------------------------------------------------------------
/projects/skye-drone/skye-drone-01-small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/skye-drone/skye-drone-01-small.jpg
--------------------------------------------------------------------------------
/projects/skye-drone/skye-drone-01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/skye-drone/skye-drone-01.jpg
--------------------------------------------------------------------------------
/projects/skye-drone/skye-drone-02-small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/skye-drone/skye-drone-02-small.jpg
--------------------------------------------------------------------------------
/projects/skye-drone/skye-drone-02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/skye-drone/skye-drone-02.jpg
--------------------------------------------------------------------------------
/projects/stealth/stealth-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/stealth/stealth-01-small.png
--------------------------------------------------------------------------------
/projects/stealth/stealth-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/stealth/stealth-01.png
--------------------------------------------------------------------------------
/projects/stealth/stealth-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/stealth/stealth-02-small.png
--------------------------------------------------------------------------------
/projects/stealth/stealth-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/stealth/stealth-02.png
--------------------------------------------------------------------------------
/projects/stealth/stealth-03-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/stealth/stealth-03-small.png
--------------------------------------------------------------------------------
/projects/stealth/stealth-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/stealth/stealth-03.png
--------------------------------------------------------------------------------
/projects/stealth/stealth-04-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/stealth/stealth-04-small.png
--------------------------------------------------------------------------------
/projects/stealth/stealth-04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/stealth/stealth-04.png
--------------------------------------------------------------------------------
/projects/stegit/stegit.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/stegit/stegit.zip
--------------------------------------------------------------------------------
/projects/switchine/switchine-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/switchine/switchine-01-small.png
--------------------------------------------------------------------------------
/projects/switchine/switchine-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/switchine/switchine-01.png
--------------------------------------------------------------------------------
/projects/switchine/switchine-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/switchine/switchine-02-small.png
--------------------------------------------------------------------------------
/projects/switchine/switchine-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/switchine/switchine-02.png
--------------------------------------------------------------------------------
/projects/switchine/switchine-03-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/switchine/switchine-03-small.png
--------------------------------------------------------------------------------
/projects/switchine/switchine-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/switchine/switchine-03.png
--------------------------------------------------------------------------------
/projects/switchine/switchine-04-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/switchine/switchine-04-small.png
--------------------------------------------------------------------------------
/projects/switchine/switchine-04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/switchine/switchine-04.png
--------------------------------------------------------------------------------
/projects/switchine/switchine.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/switchine/switchine.zip
--------------------------------------------------------------------------------
/projects/webmail/webmail.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/webmail/webmail.zip
--------------------------------------------------------------------------------
/projects/webslide-me/webslide-me.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/webslide-me/webslide-me.zip
--------------------------------------------------------------------------------
/projects/zynga-jukebox/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-jukebox/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/zynga-jukebox/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-jukebox/screenshot-01.png
--------------------------------------------------------------------------------
/projects/zynga-jukebox/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-jukebox/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/zynga-jukebox/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-jukebox/screenshot-02.png
--------------------------------------------------------------------------------
/projects/zynga-jukebox/screenshot-03-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-jukebox/screenshot-03-small.png
--------------------------------------------------------------------------------
/projects/zynga-jukebox/screenshot-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-jukebox/screenshot-03.png
--------------------------------------------------------------------------------
/projects/zynga-jukebox/zynga-jukebox.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-jukebox/zynga-jukebox.zip
--------------------------------------------------------------------------------
/projects/zynga-speedrun/css/library.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family:Helvetica, sans-serif;
3 | }
4 |
5 | .lib-abs {
6 | position:absolute;
7 | }
8 |
9 | .lib-shadow {
10 | box-shadow:inset 0px 0px 20px #000;
11 | -moz-box-shadow:inset 0px 0px 20px #000;
12 | -webkit-box-shadow:inset 0px 0px 20px #000;
13 | }
--------------------------------------------------------------------------------
/projects/zynga-speedrun/js/init.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | var Benchmark;
4 | $(document).ready(function() {
5 |
6 | // initialize benchmark
7 | Benchmark = new z.Benchmark();
8 |
9 | Benchmark.parseHash();
10 |
11 | // track performance statistics
12 | var stats = {
13 | fps: $('#ui-stats-fps')[0],
14 | pps: $('#ui-stats-pps')[0],
15 | paints: $('#ui-stats-paints')[0]
16 | };
17 |
18 | window.setInterval(function() {
19 | stats.fps.innerHTML = Benchmark.statistics.fps; // || Infinity;
20 | stats.pps.innerHTML = Benchmark.statistics.pps; // || Infinity;
21 | stats.paints.innerHTML = Benchmark.statistics.paints || 0;
22 | }, 100);
23 |
24 |
25 | });
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/projects/zynga-speedrun/js/init_ui.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 |
3 | // create little tab dots and mark current visible as active
4 | function switchUITabs(direction) {
5 |
6 | // update tabs visiblity
7 | var curTab = $('.ui-sidebar-tab.visible').removeClass('visible');
8 | var nextTab = curTab[direction]('.ui-sidebar-tab');
9 |
10 | // add 'visible' class to make tab visible, fall back to current if no prev/next
11 | nextTab = (nextTab.length ? nextTab : curTab).addClass('visible');
12 |
13 | // update tabs index indicator
14 | $('#ui-sidebar-tabs > *').removeClass().eq(nextTab.index()).addClass('active');
15 |
16 |
17 | }
18 |
19 | // update the sidebar form from the defaults/hash tag
20 | for (var s in Benchmark.options) {
21 | z.updateUIFromOption(s, Benchmark.options[s]);
22 | }
23 |
24 | // set up "update" button
25 | $('#ui-update').click(function() {
26 | z.updateOptionsFromUI();
27 | return false;
28 | });
29 |
30 | // set up sliders
31 | $('.ui-slider').change(function() {
32 | $(this.getAttribute('data-info')).text(this.value.match(/\./) ? this.value.substr(0, 3) : this.value);
33 | });
34 |
35 | // prev/forward tabs
36 | $('#ui-sidebar-tabs-prev, #ui-sidebar-tabs-next').click(function() {
37 | switchUITabs(this.id.split('-')[3]);
38 | });
39 |
40 | var tabIndex = $('#ui-sidebar-tabs');
41 | $('.ui-sidebar-tab').each(function() {
42 | $(' ').attr('data-href', '#' + this.id).addClass(this.className.match(/visible/) && 'active').appendTo(tabIndex);
43 | });
44 |
45 | });
46 |
--------------------------------------------------------------------------------
/projects/zynga-speedrun/js/modules/FPS.js:
--------------------------------------------------------------------------------
1 | var FPS;
2 | (function() {
3 |
4 | z.FPS = function() {
5 | this.context = document.createElement('div');
6 | this.context.id = 'fpscounter';
7 |
8 | this._init();
9 | };
10 |
11 | z.FPS.prototype = {
12 |
13 | _init: function() {
14 |
15 | // webkit keyframes for animation
16 | document.styleSheets[0].insertRule('@-webkit-keyframes fpscounter { from{} to{} }');
17 |
18 | this.context.style.cssText = 'position:absolute;top:0px;left:0px;background:black;color:white;-webkit-animation:fpscounter 16.6ms infinite;';
19 | document.body.appendChild(this.context);
20 |
21 | this.__lastLoop = +new Date();
22 |
23 | var that = this;
24 | this.context.addEventListener('webkitAnimationIteration', function(event) {
25 | that.__loop();
26 | });
27 |
28 | },
29 |
30 | __loop: function() {
31 |
32 | var now = +new Date(),
33 | fps = Math.floor(1000 / (now - this.__lastLoop));
34 |
35 | this.log(fps);
36 | this.__lastLoop = now;
37 |
38 | },
39 |
40 | log: function(value) {
41 | this.context.innerText = value;
42 | }
43 |
44 | };
45 |
46 | FPS = new z.FPS();
47 |
48 | })();
--------------------------------------------------------------------------------
/projects/zynga-speedrun/js/modules/benchmark.control.js:
--------------------------------------------------------------------------------
1 | $.extend(z.Benchmark.prototype, {
2 |
3 | start: function() {
4 |
5 | // width and height caching
6 | this.width = this.context.offsetWidth;
7 | this.height = this.context.offsetHeight;
8 |
9 | // create dynamic nodes
10 | var i, obj;
11 | for (i = 0; i < this.options.dynamicamount; i++) {
12 | obj = this._createNode();
13 | this.dynamicNodes.push(obj);
14 | this.context.appendChild(obj.node);
15 | this.runPlugins(obj);
16 | }
17 |
18 | // create static nodes
19 | for (i = 0; i < this.options.staticamount; i++) {
20 | obj = this._createNode();
21 | this.staticNodes.push(obj);
22 | this.context.appendChild(obj.node);
23 | this.runPlugins(obj);
24 |
25 | // initially run setPosition on the static object
26 | this.setPosition(obj);
27 |
28 | }
29 |
30 | // only update when context was reset
31 | if (!this._running) {
32 |
33 | this._running = true;
34 | this.statistics.started = +new Date();
35 |
36 | // initialize the renderLoop only on initialization
37 | if (!this._initialized) {
38 |
39 | this._initialized = true;
40 | this.__lastLoopTime = +new Date();
41 | this._renderLoop();
42 |
43 | }
44 | }
45 |
46 | },
47 |
48 | stop: function(msg) {
49 |
50 | // stop renderLoop
51 | this._running = false;
52 |
53 | this.context.style.cssText = 'text-align:center;color:white;background:black';
54 |
55 | // Bug: transforms are not reset via cssText
56 | this.context.style[z.css.transform] = ' ';
57 |
58 | this.context.innerHTML = 'Benchmark was stopped. ' + (msg || '');
59 |
60 | },
61 |
62 | reset: function() {
63 |
64 | // stop renderLoop
65 | this._running = false;
66 |
67 | // reset DOM representation
68 | this.context.innerHTML = ' ';
69 | this.context.style.cssText = '';
70 |
71 | // reset cache
72 | this.staticNodes = [];
73 | this.dynamicNodes = [];
74 |
75 | // reset statistics
76 | this.statistics.paints = 0;
77 |
78 | },
79 |
80 | update: function() {
81 |
82 | if (!this.options.width) {
83 | this.options.width = this.context.offsetWidth;
84 | } else {
85 | this.context.style.width = this.options.width + 'px';
86 | }
87 |
88 | if (!this.options.height) {
89 | this.options.height = this.context.offsetHeight;
90 | } else {
91 | this.context.style.height = this.options.height + 'px';
92 | }
93 |
94 | }
95 |
96 | });
97 |
--------------------------------------------------------------------------------
/projects/zynga-speedrun/js/modules/benchmark.hash.js:
--------------------------------------------------------------------------------
1 | $.extend(z.Benchmark.prototype, {
2 |
3 | parseHash: function(hash) {
4 |
5 | if (!hash || !hash.length) {
6 | hash = window.location.hash;
7 | }
8 |
9 | if (hash.match(/#/)) {
10 | hash = hash.split(/#/)[1];
11 | }
12 |
13 | var hashArr = hash.split(','),
14 | newOptions = {};
15 |
16 | // we got something to parse
17 | if (hashArr.length) {
18 |
19 | for (var h = 0, l = hashArr.length; h < l; h++) {
20 | var _tmp = hashArr[h].split('=');
21 | var key = _tmp[0],
22 | val = _tmp[1];
23 |
24 | newOptions[key] = !isNaN(parseInt(val, 10)) ? parseInt(val, 10) : val;
25 | }
26 |
27 | }
28 |
29 | this.setOptions(newOptions);
30 |
31 | },
32 |
33 | getHash: function() {
34 |
35 | var hashArr = [];
36 | for (var s in this.options) {
37 |
38 | if (this.options[s] !== this.defaults[s]) {
39 | hashArr.push(s + '=' + this.options[s]);
40 | }
41 | }
42 |
43 | return hashArr.join(',');
44 |
45 | },
46 |
47 | updateHash: function() {
48 | window.location.hash = this.getHash();
49 | }
50 |
51 | });
52 |
--------------------------------------------------------------------------------
/projects/zynga-speedrun/res/debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-speedrun/res/debug.png
--------------------------------------------------------------------------------
/projects/zynga-speedrun/screenshot-01-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-speedrun/screenshot-01-small.png
--------------------------------------------------------------------------------
/projects/zynga-speedrun/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-speedrun/screenshot-01.png
--------------------------------------------------------------------------------
/projects/zynga-speedrun/screenshot-02-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-speedrun/screenshot-02-small.png
--------------------------------------------------------------------------------
/projects/zynga-speedrun/screenshot-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-speedrun/screenshot-02.png
--------------------------------------------------------------------------------
/projects/zynga-speedrun/screenshot-03-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-speedrun/screenshot-03-small.png
--------------------------------------------------------------------------------
/projects/zynga-speedrun/screenshot-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-speedrun/screenshot-03.png
--------------------------------------------------------------------------------
/projects/zynga-speedrun/zynga-speedrun.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/projects/zynga-speedrun/zynga-speedrun.zip
--------------------------------------------------------------------------------
/talks/2012-ongamestart/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/talks/2012-ongamestart/screenshot-01.png
--------------------------------------------------------------------------------
/talks/2014-jsconf-eu/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/talks/2014-jsconf-eu/screenshot-01.png
--------------------------------------------------------------------------------
/talks/2014-karlsruhejs/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/talks/2014-karlsruhejs/screenshot-01.png
--------------------------------------------------------------------------------
/talks/2016-frankfurtjs/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/talks/2016-frankfurtjs/screenshot-01.png
--------------------------------------------------------------------------------
/talks/2018-frankfurt-datascience/screenshot-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/talks/2018-frankfurt-datascience/screenshot-01.png
--------------------------------------------------------------------------------
/toolchain/actions/DecryptCV.go:
--------------------------------------------------------------------------------
1 | package actions
2 |
3 | import "cookie.engineer/console"
4 | import "cookie.engineer/cvs"
5 | import "os"
6 | import "path/filepath"
7 |
8 | func DecryptCV(folder string, password string, output string) bool {
9 |
10 | var result bool = false
11 |
12 | console.Group("actions/DecryptCV")
13 |
14 | filename := cvs.DeriveFilename(password)
15 |
16 | cwd, err0 := os.Getwd()
17 |
18 | if err0 == nil {
19 |
20 | prettyname, err1 := filepath.Rel(cwd, folder + "/" + filename)
21 |
22 | if err1 == nil {
23 | console.Log("Input: " + prettyname)
24 | console.Log("Output: " + output)
25 | }
26 |
27 | } else {
28 | console.Log("Input: " + folder + "/" + filename)
29 | console.Log("Output: " + output)
30 | }
31 |
32 | encrypted, err1 := os.ReadFile(folder + "/" + filename)
33 |
34 | if err1 == nil {
35 |
36 | buffer := cvs.Decrypt(encrypted, password)
37 |
38 | if len(buffer) > 0 {
39 |
40 | err2 := os.WriteFile(output, buffer, 0666)
41 |
42 | if err2 == nil {
43 | result = true
44 | }
45 |
46 | }
47 |
48 | }
49 |
50 | console.GroupEndResult(result, "actions/DecryptCV")
51 |
52 | return result
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/toolchain/actions/EncryptCV.go:
--------------------------------------------------------------------------------
1 | package actions
2 |
3 | import "cookie.engineer/console"
4 | import "cookie.engineer/cvs"
5 | import "os"
6 | import "path/filepath"
7 |
8 | func EncryptCV(folder string, password string, input string) bool {
9 |
10 | var result bool = false
11 |
12 | console.Group("actions/EncryptCV")
13 |
14 | filename := cvs.DeriveFilename(password)
15 |
16 | cwd, err0 := os.Getwd()
17 |
18 | if err0 == nil {
19 |
20 | prettyname, err1 := filepath.Rel(cwd, folder + "/" + filename)
21 |
22 | if err1 == nil {
23 | console.Log("Input: " + input)
24 | console.Log("Output: " + prettyname)
25 | }
26 |
27 | } else {
28 | console.Log("Input: " + input)
29 | console.Log("Output: " + folder + "/" + filename)
30 | }
31 |
32 | buffer, err1 := os.ReadFile(input)
33 |
34 | if err1 == nil {
35 |
36 | encrypted := cvs.Encrypt(buffer, password)
37 |
38 | if len(encrypted) > 0 {
39 |
40 | err2 := os.WriteFile(folder + "/" + filename, encrypted, 0666)
41 |
42 | if err2 == nil {
43 | result = true
44 | }
45 |
46 | }
47 |
48 | }
49 |
50 | console.GroupEndResult(result, "actions/EncryptCV")
51 |
52 | return result
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/toolchain/actions/Render.go:
--------------------------------------------------------------------------------
1 | package actions
2 |
3 | import "cookie.engineer/routes"
4 | import "strings"
5 |
6 | func Render(root string, file string) bool {
7 |
8 | var result bool = false
9 |
10 | if !strings.Contains(file, "/") && strings.HasSuffix(file, ".md") {
11 | result = routes.RenderArticle(root, file)
12 | }
13 |
14 | return result
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/toolchain/actions/Serve.go:
--------------------------------------------------------------------------------
1 | package actions
2 |
3 | import "cookie.engineer/routes"
4 | import "cookie.engineer/utils"
5 | import "net/http"
6 | import "os"
7 | import "strconv"
8 | import "strings"
9 |
10 | func Serve(root string, port uint) bool {
11 |
12 | var result bool = false
13 |
14 | fsrv := http.FileServer(http.FS(os.DirFS(root)))
15 | http.Handle("/", fsrv)
16 |
17 | http.HandleFunc("/weblog/index.html", func(response http.ResponseWriter, request *http.Request) {
18 |
19 | if request.Method == http.MethodGet {
20 |
21 | routes.RenderArticles(root)
22 | routes.RenderFeed(root)
23 | routes.RenderIndex(root)
24 |
25 | routes.ServeFile(root, "weblog/index.html", response, request)
26 |
27 | } else {
28 |
29 | response.Header().Set("Content-Type", "text/html")
30 | response.WriteHeader(http.StatusMethodNotAllowed)
31 | response.Write([]byte{})
32 |
33 | }
34 |
35 | })
36 |
37 | http.HandleFunc("/weblog/articles/*.md", func(response http.ResponseWriter, request *http.Request) {
38 | routes.ServeArticleIndex(root, response, request)
39 | })
40 |
41 | http.HandleFunc("/weblog/articles/{file}", func(response http.ResponseWriter, request *http.Request) {
42 |
43 | if request.Method == http.MethodGet {
44 |
45 | file := request.PathValue("file")
46 |
47 | if strings.HasSuffix(file, ".md") {
48 | routes.ServeArticle(root, response, request)
49 | } else if strings.HasSuffix(file, ".html") {
50 | routes.ServeArticle(root, response, request)
51 | } else {
52 | routes.ServeFile(root, "weblog/articles/"+file, response, request)
53 | }
54 |
55 | } else if request.Method == http.MethodPost {
56 |
57 | file := request.PathValue("file")
58 |
59 | if strings.HasSuffix(file, ".md") {
60 | routes.ModifyFile(root, "weblog/articles/"+file, response, request)
61 | } else {
62 | utils.RespondWith(response, file, http.StatusMethodNotAllowed)
63 | }
64 |
65 | } else if request.Method == http.MethodDelete {
66 |
67 | file := request.PathValue("file")
68 |
69 | if strings.HasPrefix(file, "draft-") && strings.HasSuffix(file, ".md") {
70 | routes.RemoveFile(root, "weblog/articles/"+file, response, request)
71 | } else {
72 | utils.RespondWith(response, file, http.StatusMethodNotAllowed)
73 | }
74 |
75 | } else {
76 | utils.RespondWith(response, request.PathValue("file"), http.StatusMethodNotAllowed)
77 | }
78 |
79 | })
80 |
81 | err1 := http.ListenAndServe(":"+strconv.FormatUint(uint64(port), 10), nil)
82 |
83 | if err1 == nil {
84 | result = true
85 | }
86 |
87 | return result
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/toolchain/cmds/cv/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "cookie.engineer/console"
4 | import "cookie.engineer/actions"
5 | import "os"
6 | import "strings"
7 |
8 | func showHelp() {
9 |
10 | console.Info("")
11 | console.Info("CV Encrypter/Decrypter Tool")
12 | console.Info("")
13 |
14 | console.Group("Usage: [Action] [Password]")
15 | console.GroupEnd("-----")
16 |
17 | console.Group("Examples")
18 | console.Log("")
19 | console.Log("# Write decrypted CV to ../cv/source/DECRYPTED.cv")
20 | console.Log("cv decrypt \"password\";")
21 | console.Log("")
22 | console.Log("# Write encrypted CV to ../cv/source/.cv")
23 | console.Log("cv encrypt \"password\";")
24 | console.Log("")
25 | console.GroupEnd("--------")
26 |
27 | }
28 |
29 | func main() {
30 |
31 | action := ""
32 | password := ""
33 |
34 | if len(os.Args) == 3 {
35 |
36 | if os.Args[1] == "encrypt" {
37 |
38 | if os.Args[2] != "" {
39 | action = "encrypt"
40 | password = os.Args[2]
41 | }
42 |
43 | } else if os.Args[1] == "decrypt" {
44 |
45 | if os.Args[2] != "" {
46 | action = "decrypt"
47 | password = os.Args[2]
48 | }
49 |
50 | }
51 |
52 | }
53 |
54 | cwd, err1 := os.Getwd()
55 |
56 | if err1 == nil {
57 |
58 | if strings.HasSuffix(cwd, "/toolchain") {
59 | cwd = cwd[0:len(cwd)-10]
60 | }
61 |
62 | if action == "encrypt" {
63 |
64 | result := actions.EncryptCV(cwd + "/cv/source", password, cwd + "/cv/source/DECRYPTED.cv")
65 |
66 | if result == true {
67 | os.Exit(0)
68 | } else {
69 | os.Exit(1)
70 | }
71 |
72 | } else if action == "decrypt" {
73 |
74 | result := actions.DecryptCV(cwd + "/cv/source", password, cwd + "/cv/source/DECRYPTED.cv")
75 |
76 | if result == true {
77 | os.Exit(0)
78 | } else {
79 | os.Exit(1)
80 | }
81 |
82 | } else {
83 | showHelp()
84 | os.Exit(1)
85 | }
86 |
87 | } else {
88 | showHelp()
89 | os.Exit(1)
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/toolchain/cmds/render/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "cookie.engineer/console"
4 | import "cookie.engineer/actions"
5 | import "os"
6 | import "strings"
7 |
8 | func showUsage() {
9 |
10 | console.Group("Usage:")
11 | console.Log("render .md")
12 | console.Log("$PWD must be the cookie.engineer/ folder")
13 | console.GroupEnd("------")
14 |
15 | }
16 |
17 | func main() {
18 |
19 | cwd, err1 := os.Getwd()
20 |
21 | if err1 == nil {
22 |
23 | if strings.HasSuffix(cwd, "/server") {
24 | cwd = strings.TrimSpace(cwd[0:len(cwd)-7])
25 | }
26 |
27 | if strings.HasSuffix(cwd, "/toolchain") {
28 | cwd = strings.TrimSpace(cwd[0:len(cwd)-10])
29 | }
30 |
31 | file := ""
32 |
33 | if len(os.Args) == 2 {
34 |
35 | if strings.HasSuffix(os.Args[1], ".md") {
36 |
37 | file = os.Args[1]
38 |
39 | if strings.Contains(file, "/") {
40 | file = strings.TrimSpace(file[strings.LastIndex(file, "/")+1:])
41 | }
42 |
43 | }
44 |
45 | }
46 |
47 | if file != "" {
48 |
49 | result := actions.Render(cwd, file)
50 |
51 | if result == true {
52 | os.Exit(0)
53 | } else {
54 | os.Exit(1)
55 | }
56 |
57 | } else {
58 |
59 | showUsage()
60 | os.Exit(1)
61 |
62 | }
63 |
64 | } else {
65 |
66 | showUsage()
67 | os.Exit(1)
68 |
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/toolchain/cmds/serve/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "cookie.engineer/console"
4 | import "cookie.engineer/actions"
5 | import "os"
6 | import "strings"
7 |
8 | func main() {
9 |
10 | cwd, err1 := os.Getwd()
11 |
12 | if err1 == nil {
13 |
14 | if strings.HasSuffix(cwd, "/server") {
15 | cwd = strings.TrimSpace(cwd[0:len(cwd)-7])
16 | }
17 |
18 | if strings.HasSuffix(cwd, "/toolchain") {
19 | cwd = strings.TrimSpace(cwd[0:len(cwd)-10])
20 | }
21 |
22 | console.Log("Listening on http://localhost:3000")
23 |
24 | actions.Serve(cwd, 3000)
25 |
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/toolchain/console/Clear.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 |
5 | func Clear() {
6 |
7 | var has_errors bool = false
8 |
9 | for m := 0; m < len(MESSAGES); m++ {
10 |
11 | if MESSAGES[m].Method == "Error" {
12 | has_errors = true
13 | break
14 | }
15 |
16 | }
17 |
18 | MESSAGES = append(MESSAGES, NewMessage("Clear", ""))
19 |
20 | if has_errors == false {
21 |
22 | // clear screen and reset cursor
23 | os.Stdout.WriteString("\u001b[2J\u001b[0f")
24 |
25 | // clear scroll buffer
26 | os.Stdout.WriteString("\u001b[3J")
27 |
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/toolchain/console/ClearLines.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 | import "strconv"
5 |
6 | func ClearLines(number int) {
7 |
8 | if number < 32 {
9 |
10 | // move up x lines
11 | os.Stdout.WriteString("\033[" + strconv.Itoa(number) + "A")
12 |
13 | // clear from cursor to end of screen
14 | os.Stdout.WriteString("\033[J")
15 |
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/toolchain/console/Disable.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | func Disable(feature int) {
4 |
5 | if feature == FeatureAll {
6 |
7 | for feature := range features {
8 | features[feature] = false
9 | }
10 |
11 | } else {
12 |
13 | _, ok := features[feature]
14 |
15 | if ok == true {
16 | features[feature] = false
17 | }
18 |
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/toolchain/console/Enable.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | func Enable(feature int) {
4 |
5 | if feature == FeatureAll {
6 |
7 | for feature := range features {
8 | features[feature] = false
9 | }
10 |
11 | } else {
12 |
13 | _, ok := features[feature]
14 |
15 | if ok == true {
16 | features[feature] = true
17 | }
18 |
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/toolchain/console/Error.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 | import "strings"
5 |
6 | func Error(message string) {
7 |
8 | if features[FeatureError] == true {
9 |
10 | message = sanitize(message)
11 | offset := toOffset()
12 | MESSAGES = append(MESSAGES, NewMessage("Error", message))
13 |
14 | if strings.Contains(message, "\n") {
15 |
16 | var lines = strings.Split(message, "\n")
17 |
18 | if COLORS == true {
19 |
20 | for l := 0; l < len(lines); l++ {
21 | os.Stderr.WriteString("\u001b[41m" + offset + toSeparator(lines[l]) + lines[l] + "\u001b[K\n")
22 | }
23 |
24 | os.Stderr.WriteString("\u001b[0m")
25 |
26 | } else {
27 |
28 | for l := 0; l < len(lines); l++ {
29 | os.Stderr.WriteString(offset + toSeparator(lines[l]) + lines[l] + "\n")
30 | }
31 |
32 | }
33 |
34 | } else {
35 |
36 | if COLORS == true {
37 | os.Stderr.WriteString("\u001b[41m" + offset + toSeparator(message) + message + "\u001b[K\u001b[0m\n")
38 | } else {
39 | os.Stderr.WriteString(offset + toSeparator(message) + message + "\n")
40 | }
41 |
42 | }
43 |
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/toolchain/console/Group.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 |
5 | func Group(message string) {
6 |
7 | if features[FeatureGroup] == true {
8 |
9 | offset := toOffset()
10 | message = sanitize(message)
11 | MESSAGES = append(MESSAGES, NewMessage("Group", message))
12 | OFFSET++
13 |
14 | if COLORS == true {
15 | os.Stdout.WriteString("\u001b[40m" + offset + "/" + toSeparator(message) + message + "\u001b[K\u001b[0m\n")
16 | } else {
17 | os.Stdout.WriteString(offset + "/" + toSeparator(message) + message + "\n")
18 | }
19 |
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/toolchain/console/GroupEnd.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 |
5 | func GroupEnd(message string) {
6 |
7 | if features[FeatureGroup] == true {
8 |
9 | if OFFSET > 0 {
10 | OFFSET--
11 | }
12 |
13 | message = sanitize(message)
14 | offset := toOffset()
15 | MESSAGES = append(MESSAGES, NewMessage("GroupEnd", message))
16 |
17 | if COLORS == true {
18 | os.Stdout.WriteString("\u001b[40m" + offset + "\\" + toSeparator(message) + message + "\u001b[K\u001b[0m\n")
19 | } else {
20 | os.Stdout.WriteString(offset + "\\" + toSeparator(message) + message + "\n")
21 | }
22 |
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/toolchain/console/GroupEndResult.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 | import "strings"
5 |
6 | func GroupEndResult(result bool, message string) {
7 |
8 | if features[FeatureGroup] == true {
9 |
10 | if OFFSET > 0 {
11 | OFFSET--
12 | }
13 |
14 | message = sanitize(message)
15 | offset := toOffset()
16 |
17 | if result == true {
18 |
19 | message = strings.TrimSpace(message + " succeeded")
20 | MESSAGES = append(MESSAGES, NewMessage("GroupEnd", message))
21 |
22 | if COLORS == true {
23 | os.Stdout.WriteString("\u001b[42m" + offset + "\\" + toSeparator(message) + message + "\u001b[K\u001b[0m\n")
24 | } else {
25 | os.Stdout.WriteString(offset + "\\" + toSeparator(message) + message + "\n")
26 | }
27 |
28 | } else {
29 |
30 | message = strings.TrimSpace(message + " failed")
31 | MESSAGES = append(MESSAGES, NewMessage("GroupEnd", message))
32 |
33 | if COLORS == true {
34 | os.Stdout.WriteString("\u001b[41m" + offset + "\\" + toSeparator(message) + message + "\u001b[K\u001b[0m\n")
35 | } else {
36 | os.Stdout.WriteString(offset + "\\" + toSeparator(message) + message + "\n")
37 | }
38 |
39 | }
40 |
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/toolchain/console/Info.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 | import "strings"
5 |
6 | func Info(message string) {
7 |
8 | if features[FeatureInfo] == true {
9 |
10 | message = sanitize(message)
11 | offset := toOffset()
12 | MESSAGES = append(MESSAGES, NewMessage("Info", message))
13 |
14 | if strings.Contains(message, "\n") {
15 |
16 | var lines = strings.Split(message, "\n")
17 |
18 | if COLORS == true {
19 |
20 | for l := 0; l < len(lines); l++ {
21 | os.Stdout.WriteString("\u001b[42m" + offset + toSeparator(lines[l]) + lines[l] + "\u001b[K\n")
22 | }
23 |
24 | os.Stdout.WriteString("\u001b[0m")
25 |
26 | } else {
27 |
28 | for l := 0; l < len(lines); l++ {
29 | os.Stdout.WriteString(offset + toSeparator(lines[l]) + lines[l] + "\n")
30 | }
31 |
32 | }
33 |
34 | } else {
35 |
36 | if COLORS == true {
37 | os.Stdout.WriteString("\u001b[42m" + offset + toSeparator(message) + message + "\u001b[K\u001b[0m\n")
38 | } else {
39 | os.Stdout.WriteString(offset + toSeparator(message) + message + "\n")
40 | }
41 |
42 | }
43 |
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/toolchain/console/Log.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 | import "strings"
5 |
6 | func Log(message string) {
7 |
8 | if features[FeatureLog] == true {
9 |
10 | message = sanitize(message)
11 | offset := toOffset()
12 | MESSAGES = append(MESSAGES, NewMessage("Log", message))
13 |
14 | if strings.Contains(message, "\n") {
15 |
16 | var lines = strings.Split(message, "\n")
17 |
18 | if COLORS == true {
19 |
20 | for l := 0; l < len(lines); l++ {
21 | os.Stdout.WriteString("\u001b[40m" + offset + toSeparator(lines[l]) + lines[l] + "\u001b[K\n")
22 | }
23 |
24 | os.Stdout.WriteString("\u001b[0m")
25 |
26 | } else {
27 |
28 | for l := 0; l < len(lines); l++ {
29 | os.Stdout.WriteString(offset + toSeparator(lines[l]) + lines[l] + "\n")
30 | }
31 |
32 | }
33 |
34 | } else {
35 |
36 | if COLORS == true {
37 | os.Stdout.WriteString("\u001b[40m" + offset + toSeparator(message) + message + "\u001b[K\u001b[0m\n")
38 | } else {
39 | os.Stdout.WriteString(offset + toSeparator(message) + message + "\n")
40 | }
41 |
42 | }
43 |
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/toolchain/console/Message.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | type Message struct {
4 | Method string `json:"type"`
5 | Value string `json:"value"`
6 | }
7 |
8 | func NewMessage(method string, value string) Message {
9 |
10 | var message Message
11 |
12 | message.Method = method
13 | message.Value = value
14 |
15 | return message
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/toolchain/console/Progress.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 | import "strings"
5 |
6 | func Progress(message string) {
7 |
8 | if features[FeatureProgress] == true {
9 |
10 | message = strings.ReplaceAll(message, "\n", "")
11 | message = sanitize(message)
12 | offset := toOffset()
13 |
14 | if len(MESSAGES) > 0 {
15 |
16 | last_method := MESSAGES[len(MESSAGES)-1].Method
17 |
18 | if last_method == "Progress" {
19 | os.Stdout.WriteString("\033[A\033[2K\r")
20 | MESSAGES[len(MESSAGES)-1] = NewMessage("Progress", message)
21 | } else {
22 | MESSAGES = append(MESSAGES, NewMessage("Progress", message))
23 | }
24 |
25 | } else {
26 | MESSAGES = append(MESSAGES, NewMessage("Progress", message))
27 | }
28 |
29 | if COLORS == true {
30 | os.Stdout.WriteString("\u001b[40m" + offset + toSeparator(message) + message + "\u001b[K\u001b[0m\n")
31 | } else {
32 | os.Stdout.WriteString(offset + toSeparator(message) + message + "\n")
33 | }
34 |
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/toolchain/console/Result.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | func Result(result bool, message string) {
4 |
5 | if result == true {
6 | Info(message)
7 | } else {
8 | Error(message)
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/toolchain/console/Warn.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 | import "strings"
5 |
6 | func Warn(message string) {
7 |
8 | if features[FeatureWarn] == true {
9 |
10 | message = sanitize(message)
11 | offset := toOffset()
12 | MESSAGES = append(MESSAGES, NewMessage("Warn", message))
13 |
14 | if strings.Contains(message, "\n") {
15 |
16 | var lines = strings.Split(message, "\n")
17 |
18 | if COLORS == true {
19 |
20 | for l := 0; l < len(lines); l++ {
21 | os.Stdout.WriteString("\u001b[43m" + offset + toSeparator(lines[l]) + lines[l] + "\u001b[K\n")
22 | }
23 |
24 | os.Stdout.WriteString("\u001b[0m")
25 |
26 | } else {
27 |
28 | for l := 0; l < len(lines); l++ {
29 | os.Stdout.WriteString(offset + toSeparator(lines[l]) + lines[l] + "\n")
30 | }
31 |
32 | }
33 |
34 | } else {
35 |
36 | if COLORS == true {
37 | os.Stdout.WriteString("\u001b[43m" + offset + toSeparator(message) + message + "\u001b[K\u001b[0m\n")
38 | } else {
39 | os.Stdout.WriteString(offset + toSeparator(message) + message + "\n")
40 | }
41 |
42 | }
43 |
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/toolchain/console/console.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import "os"
4 | import "strings"
5 |
6 | var COLORS bool = true
7 | var MESSAGES []Message
8 | var OFFSET int = 0
9 |
10 | func init() {
11 |
12 | MESSAGES = make([]Message, 0)
13 |
14 | term := strings.ToLower(os.Getenv("TERM"))
15 |
16 | if term == "xterm" {
17 | COLORS = false
18 | } else if term == "xterm-16color" {
19 | COLORS = false
20 | } else if term == "xterm-88color" {
21 | COLORS = true
22 | } else if term == "xterm-256color" {
23 | COLORS = true
24 | } else if term == "xterm-kitty" {
25 | COLORS = true
26 | }
27 |
28 | no_color := strings.ToLower(os.Getenv("NO_COLOR"))
29 |
30 | if no_color != "" {
31 |
32 | if no_color == "yes" || no_color == "true" || no_color == "1" {
33 | COLORS = false
34 | }
35 |
36 | }
37 |
38 | }
39 |
40 | func sanitize(message string) string {
41 |
42 | var result string = message
43 |
44 | result = strings.ReplaceAll(result, "\t", " ")
45 |
46 | return result
47 |
48 | }
49 |
50 | func toOffset() string {
51 |
52 | var offset string
53 |
54 | if OFFSET > 0 {
55 |
56 | offset = "|"
57 |
58 | for o := 1; o < OFFSET; o++ {
59 | offset += "|"
60 | }
61 |
62 | }
63 |
64 | return offset
65 |
66 | }
67 |
68 | func toSeparator(message string) string {
69 |
70 | var separator string
71 |
72 | if strings.HasPrefix(message, ">") {
73 | separator = "-"
74 | } else if strings.HasPrefix(message, "-") {
75 | separator = "-"
76 | } else {
77 | separator = " "
78 | }
79 |
80 | return separator
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/toolchain/console/features.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | const (
4 | FeatureAll = 0
5 | FeatureGroup = 1
6 | FeatureLog = 2
7 | FeatureInfo = 3
8 | FeatureWarn = 4
9 | FeatureError = 5
10 | FeatureInspect = 6
11 | FeatureProgress = 7
12 | )
13 |
14 | var features map[int]bool
15 |
16 | func init() {
17 |
18 | features = make(map[int]bool)
19 |
20 | features[FeatureGroup] = true
21 | features[FeatureLog] = true
22 | features[FeatureInfo] = true
23 | features[FeatureWarn] = true
24 | features[FeatureError] = true
25 | features[FeatureInspect] = true
26 | features[FeatureProgress] = true
27 |
28 | }
29 |
30 |
31 |
--------------------------------------------------------------------------------
/toolchain/cvs/Decrypt.go:
--------------------------------------------------------------------------------
1 | package cvs
2 |
3 | import "cookie.engineer/console"
4 | import "crypto/aes"
5 | import "crypto/cipher"
6 | import "encoding/hex"
7 | import "strconv"
8 |
9 | func Decrypt(buffer []byte, password string) []byte {
10 |
11 | var result []byte
12 |
13 | console.Group("cvs/Decrypt")
14 |
15 | salt := buffer[0:16]
16 | iv := buffer[16:16+12]
17 | data := buffer[16+12:]
18 | key := DeriveKey(password, salt)
19 |
20 | console.Log("Salt: " + hex.EncodeToString(salt))
21 | console.Log("IV: " + hex.EncodeToString(iv))
22 | console.Log("Key: " + hex.EncodeToString(key))
23 | console.Log("Input Buffer: " + strconv.Itoa(len(data)) + " bytes")
24 |
25 | block, err0 := aes.NewCipher(key)
26 |
27 | if err0 == nil {
28 |
29 | aes_gcm, err1 := cipher.NewGCM(block)
30 |
31 | if err1 == nil {
32 |
33 | tmp, err2 := aes_gcm.Open(nil, iv, data, nil)
34 |
35 | if err2 == nil {
36 | console.Log("Output Buffer: " + strconv.Itoa(len(tmp)) + " bytes")
37 | result = tmp
38 | }
39 |
40 | }
41 |
42 | }
43 |
44 | console.GroupEnd("cvs/Decrypt")
45 |
46 | return result
47 |
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/toolchain/cvs/DeriveFilename.go:
--------------------------------------------------------------------------------
1 | package cvs
2 |
3 | import "encoding/hex"
4 | import "crypto/sha256"
5 |
6 | func DeriveFilename(password string) string {
7 |
8 | hasher := sha256.New()
9 | hasher.Write([]byte(password))
10 | bytes := hasher.Sum(nil)
11 |
12 | return hex.EncodeToString(bytes) + ".cv"
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/toolchain/cvs/DeriveKey.go:
--------------------------------------------------------------------------------
1 | package cvs
2 |
3 | import "golang.org/x/crypto/pbkdf2"
4 | import "crypto/sha256"
5 |
6 | func DeriveKey(password string, salt []byte) []byte {
7 | return pbkdf2.Key([]byte(password), salt, 250000, 32, sha256.New)
8 | }
9 |
--------------------------------------------------------------------------------
/toolchain/cvs/Encrypt.go:
--------------------------------------------------------------------------------
1 | package cvs
2 |
3 | import "cookie.engineer/console"
4 | import "crypto/aes"
5 | import "crypto/cipher"
6 | import "crypto/rand"
7 | import "encoding/hex"
8 | import "strconv"
9 |
10 | func Encrypt(buffer []byte, password string) []byte {
11 |
12 | var result []byte
13 |
14 | console.Group("cvs/Encrypt")
15 |
16 | salt := make([]byte, 16)
17 | rand.Read(salt)
18 |
19 | iv := make([]byte, 12)
20 | rand.Read(iv)
21 |
22 | key := DeriveKey(password, salt)
23 |
24 | console.Log("Salt: " + hex.EncodeToString(salt))
25 | console.Log("IV: " + hex.EncodeToString(iv))
26 | console.Log("Key: " + hex.EncodeToString(key))
27 | console.Log("Input Buffer: " + strconv.Itoa(len(buffer)) + " bytes")
28 |
29 | block, err0 := aes.NewCipher(key)
30 |
31 | if err0 == nil {
32 |
33 | aes_gcm, err1 := cipher.NewGCM(block)
34 |
35 | if err1 == nil {
36 |
37 | tmp := aes_gcm.Seal(nil, iv, buffer, nil)
38 |
39 | console.Log("Output Buffer: " + strconv.Itoa(len(tmp)) + " bytes")
40 |
41 | result = append(result, salt...)
42 | result = append(result, iv...)
43 | result = append(result, tmp...)
44 |
45 | }
46 |
47 | }
48 |
49 | console.GroupEnd("cvs/Encrypt")
50 |
51 | return result
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/toolchain/cvs/cvs_test.go:
--------------------------------------------------------------------------------
1 | package cvs
2 |
3 | import "testing"
4 |
5 | func TestEncryptDecrypt(t *testing.T) {
6 |
7 | t.Run("self-check", func(t *testing.T) {
8 |
9 | buffer := []byte("Hello, World!")
10 | password := "password123"
11 |
12 | encrypted := Encrypt(buffer, password)
13 | decrypted := Decrypt(encrypted, password)
14 |
15 | if string(buffer) != string(decrypted) {
16 | t.Errorf("Expected '%s' but got '%s'", buffer, decrypted)
17 | }
18 |
19 | })
20 |
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/toolchain/go.mod:
--------------------------------------------------------------------------------
1 | module cookie.engineer
2 |
3 | go 1.22
4 |
5 | require golang.org/x/crypto v0.27.0 // indirect
6 |
--------------------------------------------------------------------------------
/toolchain/go.sum:
--------------------------------------------------------------------------------
1 | golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
2 | golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
3 |
--------------------------------------------------------------------------------
/toolchain/routes/ModifyFile.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import "cookie.engineer/utils"
4 | import "net/http"
5 | import "io"
6 | import "os"
7 |
8 | func ModifyFile(root string, file string, response http.ResponseWriter, request *http.Request) {
9 |
10 | if request.Method == http.MethodPost {
11 |
12 | buffer, err1 := io.ReadAll(request.Body)
13 | result := false
14 |
15 | if err1 == nil {
16 |
17 | err2 := os.WriteFile(root + "/" + file, buffer, 0666)
18 |
19 | if err2 == nil {
20 | result = true
21 | }
22 |
23 | }
24 |
25 | if result == true {
26 | utils.RespondWith(response, file, http.StatusOK)
27 | } else {
28 | utils.RespondWith(response, file, http.StatusForbidden)
29 | }
30 |
31 | } else {
32 | utils.RespondWith(response, file, http.StatusMethodNotAllowed)
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/toolchain/routes/RemoveFile.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import "cookie.engineer/utils"
4 | import "fmt"
5 | import "net/http"
6 |
7 | func RemoveFile(root string, file string, response http.ResponseWriter, request *http.Request) {
8 |
9 | if request.Method == http.MethodDelete {
10 |
11 | fmt.Println("TODO: Remove file " + file)
12 | // TODO
13 |
14 | } else {
15 | utils.RespondWith(response, file, http.StatusMethodNotAllowed)
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/toolchain/routes/RenderArticle.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import "cookie.engineer/console"
4 | import "cookie.engineer/structs"
5 | import "cookie.engineer/templates"
6 | import "bytes"
7 | import "os"
8 | import "strings"
9 |
10 | func RenderArticle(root string, file string) bool {
11 |
12 | var result bool = false
13 |
14 | name := ""
15 |
16 | if strings.HasSuffix(file, ".html") {
17 | name = file[0:len(file)-5]
18 | } else if strings.HasSuffix(file, ".md") {
19 | name = file[0:len(file)-3]
20 | }
21 |
22 | if name != "" {
23 |
24 | buffer, err1 := os.ReadFile(root + "/weblog/articles/"+name+".md")
25 |
26 | if err1 == nil {
27 |
28 | document := structs.NewDocument(name+".md", string(buffer))
29 |
30 | var buffer bytes.Buffer
31 |
32 | if templates.Article != nil {
33 |
34 | err2 := templates.Article.Execute(&buffer, document)
35 |
36 | if err2 == nil {
37 |
38 | err3 := os.WriteFile(root+"/weblog/articles/"+name+".html", buffer.Bytes(), 0666)
39 |
40 | if err3 == nil {
41 | result = true
42 | }
43 |
44 | } else {
45 | console.Warn("File \"" + name + ".md\" cannot be parsed")
46 | }
47 |
48 | }
49 |
50 | } else {
51 | console.Warn("File \"" + name + ".md\" does not exist")
52 | }
53 |
54 | }
55 |
56 | if result == true {
57 | console.Info("Rendered \"" + name + ".md\"")
58 | } else {
59 | console.Error("Cannot render \"" + name + ".md\"")
60 | }
61 |
62 | return result
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/toolchain/routes/RenderArticles.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import "os"
4 | import "strings"
5 |
6 | func RenderArticles(root string) {
7 |
8 | entries, err1 := os.ReadDir(root + "/weblog/articles")
9 |
10 | if err1 == nil {
11 |
12 | for _, entry := range entries {
13 |
14 | name := entry.Name()
15 |
16 | if strings.HasSuffix(name, ".md") {
17 | RenderArticle(root, name)
18 | }
19 |
20 | }
21 |
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/toolchain/routes/RenderFeed.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import "cookie.engineer/structs"
4 | import "cookie.engineer/templates"
5 | import "bytes"
6 | import "os"
7 | import "strings"
8 |
9 | func RenderFeed(root string) bool {
10 |
11 | var result bool = false
12 |
13 | entries, err1 := os.ReadDir(root + "/weblog/articles")
14 |
15 | feed := structs.NewFeed()
16 |
17 | if err1 == nil {
18 |
19 | for _, entry := range entries {
20 |
21 | name := entry.Name()
22 |
23 | if strings.HasSuffix(name, ".md") {
24 |
25 | buffer, err2 := os.ReadFile(root + "/weblog/articles/"+name)
26 |
27 | if err2 == nil {
28 |
29 | document := structs.NewDocument(name[0:len(name)-3]+".html", string(buffer))
30 |
31 | if document.IsValid() {
32 | feed.AddDocument(document)
33 | }
34 |
35 | }
36 |
37 | }
38 |
39 | }
40 |
41 | }
42 |
43 | feed.Sort()
44 |
45 | var buffer bytes.Buffer
46 |
47 | if templates.Feed != nil {
48 |
49 | err2 := templates.Feed.Execute(&buffer, feed)
50 |
51 | if err2 == nil {
52 |
53 | err3 := os.WriteFile(root + "/weblog/feed.xml", buffer.Bytes(), 0666)
54 |
55 | if err3 == nil {
56 | result = true
57 | }
58 |
59 | }
60 |
61 | }
62 |
63 | return result
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/toolchain/routes/RenderIndex.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import "cookie.engineer/structs"
4 | import "cookie.engineer/templates"
5 | import "bytes"
6 | import "os"
7 | import "strings"
8 |
9 | func RenderIndex(root string) bool {
10 |
11 | var result bool = false
12 |
13 | entries, err1 := os.ReadDir(root + "/weblog/articles")
14 |
15 | index := structs.NewIndex()
16 |
17 | if err1 == nil {
18 |
19 | for _, entry := range entries {
20 |
21 | name := entry.Name()
22 |
23 | if strings.HasSuffix(name, ".md") {
24 |
25 | buffer, err2 := os.ReadFile(root + "/weblog/articles/"+name)
26 |
27 | if err2 == nil {
28 |
29 | document := structs.NewDocument(name[0:len(name)-3]+".html", string(buffer))
30 |
31 | if document.IsValid() {
32 | index.AddDocument(document)
33 | }
34 |
35 | }
36 |
37 | }
38 |
39 | }
40 |
41 | }
42 |
43 | index.Sort()
44 |
45 | var buffer bytes.Buffer
46 |
47 | if templates.Index != nil {
48 |
49 | err2 := templates.Index.Execute(&buffer, index)
50 |
51 | if err2 == nil {
52 |
53 | err3 := os.WriteFile(root + "/weblog/index.html", buffer.Bytes(), 0666)
54 |
55 | if err3 == nil {
56 | result = true
57 | }
58 |
59 | }
60 |
61 | }
62 |
63 | return result
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/toolchain/routes/ServeArticle.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import "net/http"
4 | import "strings"
5 |
6 | func ServeArticle(root string, response http.ResponseWriter, request *http.Request) {
7 |
8 | file := request.PathValue("file")
9 |
10 | if strings.HasSuffix(file, ".html") {
11 |
12 | result := RenderArticle(root, file)
13 |
14 | if result == true {
15 |
16 | ServeFile(root+"/weblog/articles", file, response, request)
17 |
18 | } else {
19 |
20 | response.Header().Set("Content-Type", "text/html")
21 | response.WriteHeader(http.StatusInternalServerError)
22 | response.Write([]byte("Syntax Error in Markdown Document"))
23 |
24 | }
25 |
26 | } else if strings.HasSuffix(file, ".md") {
27 | ServeFile(root+"/weblog/articles", file, response, request)
28 | } else {
29 | ServeFile(root+"/weblog/articles", file, response, request)
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/toolchain/routes/ServeArticleIndex.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import "encoding/json"
4 | import "net/http"
5 | import "os"
6 | import "strconv"
7 | import "strings"
8 |
9 | func ServeArticleIndex(root string, response http.ResponseWriter, request *http.Request) {
10 |
11 | if request.Method == http.MethodGet {
12 |
13 | entries, err1 := os.ReadDir(root + "/weblog/articles")
14 |
15 | if err1 == nil {
16 |
17 | var result []string
18 |
19 | for _, entry := range entries {
20 |
21 | name := entry.Name()
22 |
23 | if strings.HasSuffix(name, ".md") {
24 | result = append(result, name)
25 | }
26 |
27 | }
28 |
29 | buffer, err2 := json.MarshalIndent(result, "", "\t")
30 |
31 | if err2 == nil {
32 |
33 | response.Header().Set("Content-Type", "application/json")
34 | response.Header().Set("Content-Length", strconv.Itoa(len(buffer)))
35 | response.WriteHeader(http.StatusOK)
36 | response.Write(buffer)
37 |
38 | } else {
39 |
40 | response.Header().Set("Content-Type", "application/json")
41 | response.WriteHeader(http.StatusInternalServerError)
42 | response.Write([]byte{})
43 |
44 | }
45 |
46 | } else {
47 |
48 | response.Header().Set("Content-Type", "application/json")
49 | response.WriteHeader(http.StatusNotFound)
50 | response.Write([]byte{})
51 |
52 | }
53 |
54 | } else {
55 |
56 | response.Header().Set("Content-Type", "application/json")
57 | response.WriteHeader(http.StatusMethodNotAllowed)
58 | response.Write([]byte{})
59 |
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/toolchain/routes/ServeFile.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import "cookie.engineer/utils"
4 | import "net/http"
5 | import "os"
6 | import "strconv"
7 | import "strings"
8 |
9 | func ServeFile(root string, file string, response http.ResponseWriter, request *http.Request) {
10 |
11 | if request.Method == http.MethodGet {
12 |
13 | extension := file[strings.LastIndex(file, ".")+1:]
14 | buffer, err1 := os.ReadFile(root + "/" + file)
15 |
16 | if err1 == nil {
17 |
18 | content_type, ok := utils.MIME[extension]
19 |
20 | if ok == false {
21 | content_type = "application/octet-stream"
22 | }
23 |
24 | response.Header().Set("Content-Type", content_type)
25 | response.Header().Set("Content-Length", strconv.Itoa(len(buffer)))
26 | response.WriteHeader(http.StatusOK)
27 | response.Write(buffer)
28 |
29 | } else {
30 | utils.RespondWith(response, file, http.StatusNotFound)
31 | }
32 |
33 | } else {
34 | utils.RespondWith(response, file, http.StatusMethodNotAllowed)
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/toolchain/structs/Emojis.go:
--------------------------------------------------------------------------------
1 | package structs
2 |
3 | var Emojis map[string]string = map[string]string{
4 | "balloon": "🎈",
5 | "blue_book": "📘",
6 | "bomb": "💣",
7 | "book": "🕮",
8 | "bug": "🐛",
9 | "calendar": "📆",
10 | "castle": "🌍",
11 | "china": "🇨🇳",
12 | "compass": "🧭",
13 | "computer": "🖥️",
14 | "construction": "🚧",
15 | "cyclone": "🌀",
16 | "date": "📅",
17 | "eu": "🇪🇺",
18 | "gear": "⚙️",
19 | "ghost": "👻",
20 | "gift": "🎁",
21 | "globe": "🌍",
22 | "green_book": "📗",
23 | "joystick": "🕹️",
24 | "laptop": "💻",
25 | "mag": "🔍",
26 | "magnet": "🧲",
27 | "notebook": "📓",
28 | "orange_book": "📙",
29 | "pushpin": "📌",
30 | "rainbow": "🌈",
31 | "robot": "🤖",
32 | "rocket": "🚀",
33 | "russia": "🇷🇺",
34 | "satellite": "📡",
35 | "shit": "💩",
36 | "sparkles": "✨",
37 | "snowflake": "❄️",
38 | "tornado": "🌪️",
39 | "us": "🇺🇸",
40 | "zap": "⚡",
41 | }
42 |
--------------------------------------------------------------------------------
/toolchain/structs/Feed.go:
--------------------------------------------------------------------------------
1 | package structs
2 |
3 | import "sort"
4 | import "time"
5 |
6 | type Feed struct {
7 | Date string `json:"date"`
8 | Documents []*Document `json:"documents"`
9 | }
10 |
11 | func NewFeed() Feed {
12 |
13 | var feed Feed
14 |
15 | feed.Date = "Sat, 01 Jan 2000 00:00:00 UTC"
16 | feed.Documents = make([]*Document, 0)
17 |
18 | return feed
19 |
20 | }
21 |
22 | func (feed *Feed) AddDocument(value Document) {
23 |
24 | var document = &value
25 |
26 | if document.IsValid() {
27 |
28 | if document.Meta.Date != "" {
29 |
30 | date, _ := time.Parse(time.DateOnly, document.Meta.Date)
31 | feed_date, _ := time.Parse(time.RFC1123, feed.Date)
32 |
33 | if date.After(feed_date) {
34 | feed.Date = date.Format(time.RFC1123)
35 | }
36 |
37 | document.Meta.Date = date.Format(time.RFC1123)
38 |
39 | }
40 |
41 | feed.Documents = append(feed.Documents, document)
42 |
43 | }
44 |
45 | }
46 |
47 | func (feed *Feed) Sort() {
48 |
49 | sort.Slice(feed.Documents, func(a int, b int) bool {
50 |
51 | date_a, _ := time.Parse(time.RFC1123, feed.Documents[a].Meta.Date)
52 | date_b, _ := time.Parse(time.RFC1123, feed.Documents[b].Meta.Date)
53 |
54 | return date_a.After(date_b)
55 |
56 | })
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/toolchain/structs/Index.go:
--------------------------------------------------------------------------------
1 | package structs
2 |
3 | import "sort"
4 | import "time"
5 |
6 | type Index struct {
7 | Documents []*Document `json:"documents"`
8 | }
9 |
10 | func NewIndex() Index {
11 |
12 | var index Index
13 |
14 | index.Documents = make([]*Document, 0)
15 |
16 | return index
17 |
18 | }
19 |
20 | func (index *Index) AddDocument(value Document) {
21 |
22 | var document = &value
23 |
24 | if document.IsValid() {
25 | document.Count()
26 | index.Documents = append(index.Documents, document)
27 | }
28 |
29 | }
30 |
31 | func (index *Index) Sort() {
32 |
33 | sort.Slice(index.Documents, func(a int, b int) bool {
34 |
35 | date_a, _ := time.Parse(time.DateOnly, index.Documents[a].Meta.Date)
36 | date_b, _ := time.Parse(time.DateOnly, index.Documents[b].Meta.Date)
37 |
38 | return date_a.After(date_b)
39 |
40 | })
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/toolchain/structs/countWords.go:
--------------------------------------------------------------------------------
1 | package structs
2 |
3 | import "strings"
4 |
5 | func countWords(element *Element) int {
6 |
7 | var result int = 0
8 |
9 | if element.Text != "" {
10 |
11 | words := strings.Split(element.Text, " ")
12 |
13 | for w := 0; w < len(words); w++ {
14 | result++
15 | }
16 |
17 | }
18 |
19 | if len(element.Children) > 0 {
20 |
21 | for c := 0; c < len(element.Children); c++ {
22 | result += countWords(element.Children[c])
23 | }
24 |
25 | }
26 |
27 | return result
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/toolchain/structs/generateId.go:
--------------------------------------------------------------------------------
1 | package structs
2 |
3 | import "cookie.engineer/utils"
4 | import "strings"
5 |
6 | func generateId(element *Element) string {
7 |
8 | var texts []string
9 |
10 | if element.Text != "" {
11 |
12 | chunks := strings.Split(strings.TrimSpace(utils.ToASCII(element.Text)), "-")
13 |
14 | for c := 0; c < len(chunks); c++ {
15 |
16 | text := strings.TrimSpace(chunks[c])
17 |
18 | if len(text) > 0 {
19 | texts = append(texts, text)
20 | }
21 |
22 | }
23 |
24 | } else if len(element.Children) > 0 {
25 |
26 | for c := 0; c < len(element.Children); c++ {
27 |
28 | child := element.Children[c]
29 |
30 | if child.Type == "b" || child.Type == "code" || child.Type == "del" || child.Type == "em" || child.Type == "#text" {
31 |
32 | tmp := strings.TrimSpace(utils.ToASCIIName(child.Text))
33 |
34 | if strings.HasPrefix(tmp, "-") {
35 | tmp = tmp[1:]
36 | }
37 |
38 | if strings.HasSuffix(tmp, "-") {
39 | tmp = tmp[0 : len(tmp)-1]
40 | }
41 |
42 | chunks := strings.Split(tmp, "-")
43 |
44 | for c := 0; c < len(chunks); c++ {
45 |
46 | text := strings.TrimSpace(chunks[c])
47 |
48 | if len(text) > 0 {
49 | texts = append(texts, text)
50 | }
51 |
52 | }
53 |
54 | }
55 |
56 | }
57 |
58 | }
59 |
60 | var filtered []string
61 |
62 | if len(texts) > 0 {
63 |
64 | if utils.IsNumber(string(texts[0][0])) {
65 | texts = texts[1:]
66 | }
67 |
68 | for t := 0; t < len(texts); t++ {
69 |
70 | text := strings.ToLower(strings.TrimSpace(texts[t]))
71 |
72 | if text != "" {
73 | filtered = append(filtered, text)
74 | }
75 |
76 | }
77 |
78 | return strings.Join(filtered, "-")
79 |
80 | }
81 |
82 | return ""
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/toolchain/templates/Article.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | import _ "embed"
4 | import "text/template"
5 |
6 | var Article *template.Template
7 |
8 | //go:embed Article.tpl
9 | var embedded_Article []byte
10 |
11 | func init() {
12 |
13 | tpl, err := template.New("Article").Funcs(template.FuncMap{
14 | "RenderElement": RenderElement,
15 | "RenderElements": RenderElements,
16 | "RenderInteger": RenderInteger,
17 | "RenderStrings": RenderStrings,
18 | }).Parse(string(embedded_Article))
19 |
20 | if err == nil {
21 | Article = tpl
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/toolchain/templates/Feed.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | import _ "embed"
4 | import "text/template"
5 |
6 | var Feed *template.Template
7 |
8 | //go:embed Feed.tpl
9 | var embedded_Feed []byte
10 |
11 | func init() {
12 |
13 | tpl, err := template.New("Feed").Funcs(template.FuncMap{
14 | "RenderElement": RenderElement,
15 | "RenderElements": RenderElements,
16 | "RenderInteger": RenderInteger,
17 | "RenderStrings": RenderStrings,
18 | }).Parse(string(embedded_Feed))
19 |
20 | if err == nil {
21 | Feed = tpl
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/toolchain/templates/Feed.tpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Cookie Engineer's Web Log
5 | Web Log about Software Architecture and Automation
6 | Computers/Software/Internet/Automation/Robotics/Artificial Intelligence/Machine Learning
7 | Copyright 2019-2024 Cookie Engineer
8 | en-us
9 | {{.Date}}
10 | @cookiengineer
11 | {{.Date}}
12 |
13 | https://cookie.engineer/design/cookiengineer.png
14 | Cookie Engineer's Web Log
15 | https://cookie.engineer/weblog/index.html
16 | Web Log about Software Architecture and Automation
17 | 256
18 | 256
19 | {{range .Documents}}
20 | -
21 |
{{.Meta.Name}}
22 | {{.Meta.Crux}}
23 | https://cookie.engineer/weblog/articles/{{.File}}
24 | {{RenderStrings .Meta.Tags "/"}}
25 | {{.Meta.Date}}
26 | {{end}}
27 |
28 |
29 |
--------------------------------------------------------------------------------
/toolchain/templates/Index.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | import _ "embed"
4 | import "text/template"
5 |
6 | var Index *template.Template
7 |
8 | //go:embed Index.tpl
9 | var embedded_Index []byte
10 |
11 | func init() {
12 |
13 | tpl, err := template.New("Index").Funcs(template.FuncMap{
14 | "RenderElement": RenderElement,
15 | "RenderElements": RenderElements,
16 | "RenderInteger": RenderInteger,
17 | "RenderStrings": RenderStrings,
18 | }).Parse(string(embedded_Index))
19 |
20 | if err == nil {
21 | Index = tpl
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/toolchain/templates/RenderElement.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | import "cookie.engineer/structs"
4 |
5 | func RenderElement(element structs.Element, indent string) string {
6 | return element.Render(indent)
7 | }
8 |
--------------------------------------------------------------------------------
/toolchain/templates/RenderElements.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | import "cookie.engineer/structs"
4 |
5 | func RenderElements(elements []*structs.Element, indent string) string {
6 |
7 | var result string
8 |
9 | for e := 0; e < len(elements); e++ {
10 |
11 | tmp := elements[e].Render(indent)
12 |
13 | if e == 0 {
14 | result += tmp
15 | } else {
16 | result += " " + tmp
17 | }
18 |
19 | }
20 |
21 | return result
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/toolchain/templates/RenderInteger.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | import "strconv"
4 |
5 | func RenderInteger(number int) string {
6 | return strconv.Itoa(number)
7 | }
8 |
--------------------------------------------------------------------------------
/toolchain/templates/RenderStrings.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | import "strings"
4 |
5 | func RenderStrings(slice []string, separator string) string {
6 | return strings.Join(slice, separator)
7 | }
8 |
--------------------------------------------------------------------------------
/toolchain/utils/IsNumber.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | func IsNumber(value string) bool {
4 |
5 | var result bool = true
6 |
7 | for v := 0; v < len(value); v++ {
8 |
9 | character := string(value[v])
10 |
11 | if character >= "0" && character <= "9" {
12 | continue
13 | } else {
14 | result = false
15 | break
16 | }
17 |
18 | }
19 |
20 | return result
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/toolchain/utils/RespondWith.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "net/http"
4 | import "strings"
5 |
6 | func RespondWith(response http.ResponseWriter, file string, status int) {
7 |
8 | extension := file[strings.LastIndex(file, ".")+1:]
9 | content_type, ok := MIME[extension]
10 |
11 | if ok == false {
12 | content_type = "application/octet-stream"
13 | }
14 |
15 | response.Header().Set("Content-Type", content_type)
16 | response.WriteHeader(status)
17 | response.Write([]byte{})
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/toolchain/utils/ToASCII.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "encoding/json"
4 | import _ "embed"
5 | import "strings"
6 |
7 | //go:embed ToASCII.UTF8.json
8 | var embedded_utf8_table []byte
9 |
10 | var utf8_table map[string][]uint16
11 |
12 | func init() {
13 | json.Unmarshal(embedded_utf8_table, &utf8_table)
14 | }
15 |
16 | func lookup(character uint16) string {
17 |
18 | var found string
19 |
20 | for str, codes := range utf8_table {
21 |
22 | for c := 0; c < len(codes); c++ {
23 |
24 | if codes[c] == character {
25 | found = str
26 | break
27 | }
28 |
29 | }
30 |
31 | }
32 |
33 | return found
34 |
35 | }
36 |
37 | func ToASCII(value string) string {
38 |
39 | tmp := strings.TrimSpace(value)
40 |
41 | var filtered string
42 |
43 | for _, character := range tmp {
44 |
45 | var mapped = lookup(uint16(character))
46 |
47 | if mapped != "" {
48 | filtered += mapped
49 | }
50 |
51 | }
52 |
53 | return filtered
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/toolchain/utils/ToASCIIName.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "strings"
4 |
5 | func ToASCIIName(value string) string {
6 |
7 | tmp := ToASCII(value)
8 |
9 | var filtered string
10 | var last_was_dash bool = false
11 |
12 | for _, chunk := range tmp {
13 |
14 | if chunk == 32 || chunk == 45 || chunk == 58 || chunk == 59 || chunk == 95 {
15 |
16 | if last_was_dash == false {
17 | filtered += "-"
18 | last_was_dash = true
19 | }
20 |
21 | } else if chunk >= 33 && chunk <= 47 {
22 |
23 | // Do Nothing
24 |
25 | } else if chunk >= 48 && chunk <= 57 {
26 |
27 | // Digits
28 | filtered += string(chunk)
29 | last_was_dash = false
30 |
31 | } else if chunk >= 58 && chunk <= 64 {
32 |
33 | // Do Nothing
34 |
35 | } else if chunk >= 65 && chunk <= 90 {
36 |
37 | // Uppercase letters
38 | filtered += string(chunk)
39 | last_was_dash = false
40 |
41 | } else if chunk >= 91 && chunk <= 96 {
42 |
43 | // Do Nothing
44 |
45 | } else if chunk >= 97 && chunk <= 122 {
46 |
47 | // Lowercase letters
48 | filtered += string(chunk)
49 | last_was_dash = false
50 |
51 | } else if chunk >= 123 && chunk <= 126 {
52 |
53 | // Do Nothing
54 |
55 | }
56 |
57 | }
58 |
59 | if filtered != "-" {
60 | filtered = strings.TrimSpace(filtered)
61 | }
62 |
63 | return filtered
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/weblog/articles/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": false,
4 | "es6": true,
5 | "node": true
6 | },
7 | "extends": "eslint:recommended",
8 | "parserOptions": {
9 | "ecmaVersion": 2018,
10 | "sourceType": "module"
11 | },
12 | "overrides": [{
13 | "files": [ "*.mjs" ],
14 | "rules": {}
15 | }, {
16 | "files": [ "your-definition-of-privacy-is-wrong/prefs.js" ],
17 | "rules": {
18 | "no-undef": "off",
19 | "quotes": "off"
20 | }
21 | }],
22 | "rules": {
23 | "no-restricted-globals": [
24 | "error",
25 | { "name": "__dirname" },
26 | { "name": "__filename" },
27 | { "name": "Buffer" },
28 | { "name": "exports" },
29 | { "name": "module" },
30 | { "name": "process" },
31 | { "name": "require" },
32 | { "name": "TextDecoder" },
33 | { "name": "TextEncoder" },
34 | { "name": "URL" },
35 | { "name": "URLSearchParams" }
36 | ],
37 | "arrow-parens": [
38 | "error",
39 | "always"
40 | ],
41 | "indent": [
42 | "error",
43 | "tab"
44 | ],
45 | "linebreak-style": [
46 | "error",
47 | "unix"
48 | ],
49 | "quotes": [
50 | "error",
51 | "single"
52 | ],
53 | "semi": [
54 | "error",
55 | "always"
56 | ]
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/weblog/articles/android-privacy-guide/appwarden.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/android-privacy-guide/appwarden.jpg
--------------------------------------------------------------------------------
/weblog/articles/android-privacy-guide/osmand.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/android-privacy-guide/osmand.jpg
--------------------------------------------------------------------------------
/weblog/articles/android-privacy-guide/permission-manager-x.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/android-privacy-guide/permission-manager-x.jpg
--------------------------------------------------------------------------------
/weblog/articles/android-privacy-guide/rethinkdns.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/android-privacy-guide/rethinkdns.jpg
--------------------------------------------------------------------------------
/weblog/articles/android-privacy-guide/superfreezz.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/android-privacy-guide/superfreezz.jpg
--------------------------------------------------------------------------------
/weblog/articles/dji-drone-reset-guide/dji-spark-with-controller.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/dji-drone-reset-guide/dji-spark-with-controller.jpg
--------------------------------------------------------------------------------
/weblog/articles/gameboy-advance/gba-01-teardown.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/gameboy-advance/gba-01-teardown.jpg
--------------------------------------------------------------------------------
/weblog/articles/gameboy-advance/gba-02-cleanup.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/gameboy-advance/gba-02-cleanup.jpg
--------------------------------------------------------------------------------
/weblog/articles/gameboy-advance/gba-03-displaymod.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/gameboy-advance/gba-03-displaymod.jpg
--------------------------------------------------------------------------------
/weblog/articles/gameboy-advance/gba-04-ezflash-omega.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/gameboy-advance/gba-04-ezflash-omega.jpg
--------------------------------------------------------------------------------
/weblog/articles/i3-migration-guide/lxappearance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/i3-migration-guide/lxappearance.png
--------------------------------------------------------------------------------
/weblog/articles/implementers-guide-to-socks/client-manual.mjs:
--------------------------------------------------------------------------------
1 |
2 | // client-manual.mjs
3 | import net from 'net';
4 |
5 |
6 |
7 | const HANDSHAKE_REQUEST = [
8 | 0x05, // SOCKS version
9 | 0x02, // 2 Auth Methods are supported
10 | 0x00, // methods[0]: No Authentication Required
11 | 0x02 // methods[1]: Username/Password
12 | ];
13 |
14 | const CONNECTION_REQUEST = [
15 |
16 | 0x05, // SOCKS version
17 | 0x01, // CONNECT Command
18 | 0x00, // Reserved (due to SOCKS4 compatibility)
19 | 0x01, // IPv4 Address Type
20 |
21 | 0x01, // 1.3.3.7
22 | 0x03,
23 | 0x03,
24 | 0x07,
25 |
26 | 80 // HTTP
27 |
28 | ];
29 |
30 |
31 | let client = net.createConnection({
32 | host: '127.0.0.1',
33 | port: 1080
34 | }, () => {
35 |
36 | client.once('data', (response) => {
37 |
38 | console.log('Handshake Response Frame', response);
39 |
40 | if (response[0] === 0x05 && response[1] === 0x00) {
41 |
42 | client.once('data', (status) => {
43 | console.log('Connection Status Frame', status);
44 | });
45 |
46 | client.write(CONNECTION_REQUEST);
47 |
48 | }
49 |
50 | });
51 |
52 | client.write(HANDSHAKE_REQUEST);
53 |
54 | });
55 |
56 |
--------------------------------------------------------------------------------
/weblog/articles/implementers-guide-to-socks/client.mjs:
--------------------------------------------------------------------------------
1 | // client.mjs
2 | import net from 'net';
3 | import { SOCKS } from './SOCKS.mjs';
4 |
5 |
6 |
7 | // Chapter: SOCKS Client
8 | let client = new net.createConnection({
9 | host: 'localhost',
10 | port: 1080
11 | }, () => {
12 |
13 | let handshake = {
14 | headers: {
15 | 'auth': [ 'none' ]
16 | }
17 | };
18 |
19 | // Chapter: Handshake Request
20 | console.log('Send Handshake Request', handshake);
21 | SOCKS.send(client, handshake);
22 |
23 | });
24 |
25 | client.once('data', (response) => {
26 |
27 | client.allowHalfOpen = false;
28 | client.setTimeout(0);
29 | client.setNoDelay(true);
30 | client.setKeepAlive(true, 0);
31 |
32 | client.removeAllListeners('timeout');
33 | client.removeAllListeners('data');
34 |
35 | // Chapter: Handshake Response
36 | SOCKS.receive(client, response, (data) => {
37 |
38 | console.log('Receive Handshake Response', data);
39 |
40 | if (data.headers['@version'] === 0x05 && data.headers['auth'] === 'none') {
41 |
42 | // Chapter: Connection Status
43 | client.once('data', (status) => {
44 |
45 | SOCKS.receive(client, status, (data) => {
46 |
47 | console.log('Receive Connection Status', data);
48 |
49 | if (data.headers['@status'] === 'success') {
50 | console.log('Client would be ready to do a HTTP request to ' + data.payload.host + ':' + data.payload.port + ' now.');
51 | // TODO: client.write(HTTP_REQUEST);
52 | client.destroy();
53 | } else {
54 | console.error('Server responded with an Error: ' + data.headers['@status']);
55 | client.destroy();
56 | }
57 |
58 | });
59 |
60 | });
61 |
62 | setTimeout(() => {
63 |
64 | let request = {
65 | headers: {
66 | '@method': 'connect'
67 | },
68 | payload: {
69 | domain: 'cookie.engineer',
70 | port: 80 // HTTP
71 | }
72 | };
73 |
74 | // Chapter: Connection Request
75 | console.log('Send Connection Request', request);
76 | SOCKS.send(client, request);
77 |
78 | }, 1000);
79 |
80 | } else {
81 | client.destroy();
82 | }
83 |
84 | });
85 |
86 | SOCKS.receive(response);
87 |
88 | });
89 |
90 | client.on('error', () => {});
91 | client.on('close', () => {});
92 | client.on('timeout', () => client.destroy());
93 |
94 |
--------------------------------------------------------------------------------
/weblog/articles/intel-nuc-homeserver/fanless-intel-nuc-inside.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/intel-nuc-homeserver/fanless-intel-nuc-inside.jpg
--------------------------------------------------------------------------------
/weblog/articles/intel-nuc-homeserver/fanless-intel-nuc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/intel-nuc-homeserver/fanless-intel-nuc.jpg
--------------------------------------------------------------------------------
/weblog/articles/linux-assembly-part-4-arithmetic-operations.md:
--------------------------------------------------------------------------------
1 |
2 | ## Arithmetic Operations
3 |
4 | | Instruction | Description |
5 | | ADD dest, src | dest = dest + src |
6 | | SUB dest, src | dest = dest - src |
7 | | MUL reg | edx:eax = eax * reg |
8 | mul, add, etc
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/weblog/articles/linux-assembly/.gitignore:
--------------------------------------------------------------------------------
1 | /*.o
2 | /*.bin
3 |
--------------------------------------------------------------------------------
/weblog/articles/linux-assembly/calculator.asm:
--------------------------------------------------------------------------------
1 | section .data
2 | ; Define our numbers
3 | num1: equ 13
4 | num2: equ 37
5 |
6 | ; Define our messages
7 | msg1: db "Sum is correct!"
8 | msg2: db "Sum is incorrect!"
9 |
10 | section .text
11 | global _start
12 |
13 | _start:
14 |
15 | mov rax, num1
16 | mov rbx, num2
17 | add rax, rbx ; add(rax, rbx) stores the result in rax
18 |
19 | cmp rax, 50
20 | je .print_correct
21 | jmp .print_incorrect
22 |
23 | .print_correct:
24 |
25 | mov rax, 1
26 | mov rdi, 1
27 | mov rsi, msg1
28 | mov rdx, 15
29 | syscall
30 | jmp .exit_correct
31 |
32 | .print_incorrect:
33 |
34 | mov rax, 1
35 | mov rdi, 1
36 | mov rsi, msg2
37 | mov rdx, 17
38 | syscall
39 | jmp .exit_incorrect
40 |
41 | .exit_correct:
42 | mov rax, 60
43 | mov rdi, 0
44 | syscall
45 |
46 | .exit_incorrect:
47 | mov rax, 60
48 | mov rdi, 1
49 | syscall
50 |
--------------------------------------------------------------------------------
/weblog/articles/linux-assembly/hello-world.asm:
--------------------------------------------------------------------------------
1 | section .data
2 | msg db "Hello, World!"
3 |
4 | section .text
5 | global _start
6 |
7 | _start:
8 | mov rax, 1 ; syscall 1 "ksys_write(rdi, rsi, rdx)"
9 | mov rdi, 1 ; int 1 for standard output
10 | mov rsi, msg ; pointer to message
11 | mov rdx, 13 ; length of message
12 | syscall ; execute syscall stored in rax
13 |
14 | mov rax, 60 ; syscall 60 for "exit(rdi)"
15 | mov rdi, 0 ; int 0 for exit code
16 | syscall ; execute syscall stored in rax
17 |
--------------------------------------------------------------------------------
/weblog/articles/linux-assembly/stack.asm:
--------------------------------------------------------------------------------
1 |
2 | section .text
3 | global _start
4 |
5 | _start:
6 | ; set two registers for demonstration
7 | mov rax, 13
8 | mov rdx, 37
9 |
10 | ; rax stored at address 0 * 8
11 | ; increment rsp address to where the value of 13 is
12 | push rax
13 |
14 | ; rdx stored at address 1 * 8
15 | ; increment rsp address to where the value of 37 is
16 | push rdx
17 |
18 | ; set rax to the value of [rsp + 8], which is 13
19 | mov rax, [rsp + 8]
20 |
21 | cmp rax, 13
22 | je .success
23 | jmp .failure
24 |
25 | .success:
26 | mov rax, 60
27 | mov rdi, 0
28 | syscall
29 |
30 | .failure:
31 | mov rax, 60
32 | mov rdi, 1
33 | syscall
34 |
--------------------------------------------------------------------------------
/weblog/articles/maintenance-of-clearnets/first-time.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/maintenance-of-clearnets/first-time.jpg
--------------------------------------------------------------------------------
/weblog/articles/maintenance-of-clearnets/heist-attack.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/maintenance-of-clearnets/heist-attack.pdf
--------------------------------------------------------------------------------
/weblog/articles/maintenance-of-clearnets/maximum-security-prison.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/maintenance-of-clearnets/maximum-security-prison.jpg
--------------------------------------------------------------------------------
/weblog/articles/maintenance-of-clearnets/telephone-operator-lady.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/maintenance-of-clearnets/telephone-operator-lady.jpg
--------------------------------------------------------------------------------
/weblog/articles/mx518-repair-guide/01-mouse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/mx518-repair-guide/01-mouse.jpg
--------------------------------------------------------------------------------
/weblog/articles/mx518-repair-guide/02-topshell.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/mx518-repair-guide/02-topshell.jpg
--------------------------------------------------------------------------------
/weblog/articles/mx518-repair-guide/03-mousewheel.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/mx518-repair-guide/03-mousewheel.jpg
--------------------------------------------------------------------------------
/weblog/articles/mx518-repair-guide/04-components.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/mx518-repair-guide/04-components.jpg
--------------------------------------------------------------------------------
/weblog/articles/pacman-backup/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/pacman-backup/screenshot.png
--------------------------------------------------------------------------------
/weblog/articles/problems-with-web-browsers/firefox-cache-on-mobile-internet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/problems-with-web-browsers/firefox-cache-on-mobile-internet.png
--------------------------------------------------------------------------------
/weblog/articles/problems-with-web-browsers/firefox-network-connection-error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/problems-with-web-browsers/firefox-network-connection-error.png
--------------------------------------------------------------------------------
/weblog/articles/problems-with-web-browsers/firefox-network-protocol-error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/problems-with-web-browsers/firefox-network-protocol-error.png
--------------------------------------------------------------------------------
/weblog/articles/problems-with-web-browsers/firefox-network-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/problems-with-web-browsers/firefox-network-settings.png
--------------------------------------------------------------------------------
/weblog/articles/problems-with-web-browsers/stackoverflow-print-preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/problems-with-web-browsers/stackoverflow-print-preview.png
--------------------------------------------------------------------------------
/weblog/articles/problems-with-web-browsers/stealth-browser-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/problems-with-web-browsers/stealth-browser-settings.png
--------------------------------------------------------------------------------
/weblog/articles/synaptics-touchpad-on-linux/70-synaptics.conf:
--------------------------------------------------------------------------------
1 | Section "InputClass"
2 | Identifier "touchpad catchall"
3 | Driver "synaptics"
4 | MatchIsTouchpad "on"
5 | MatchDevicePath "/dev/input/event*"
6 | EndSection
7 |
8 | Section "InputClass"
9 | Identifier "touchpad ignore duplicates"
10 | MatchIsTouchpad "on"
11 | MatchOS "Linux"
12 | MatchDevicePath "/dev/input/mouse*"
13 | Option "Ignore" "on"
14 | EndSection
15 |
16 | Section "InputClass"
17 | Identifier "default clickpad buttons"
18 | MatchDriver "synaptics"
19 | Option "ClickPad" "0"
20 | Option "PalmDetect" "1"
21 | Option "TouchpadOff" "0"
22 | Option "MinSpeed" "2.0"
23 | Option "MaxSpeed" "2.0"
24 | Option "TapButton1" "1"
25 | Option "TapButton2" "3"
26 | Option "TapButton3" "2"
27 | Option "AreaLeftEdge" "0"
28 | Option "AreaRightEdge" "5112"
29 | Option "AreaTopEdge" "0"
30 | Option "AreaBottomEdge" "4832"
31 | Option "VertTwoFingerScroll" "1"
32 | Option "VertEdgeScroll" "0"
33 | Option "VertScrollDelta" "-111"
34 | Option "HorizTwoFingerScroll" "1"
35 | Option "HorizEdgeScroll" "0"
36 | Option "HorizScrollDelta" "-111"
37 | EndSection
38 |
39 | Section "InputClass"
40 | Identifier "disable clickpad buttons on Apple touchpads"
41 | MatchDriver "synaptics"
42 | MatchProduct "Apple|bcm5974"
43 | Option "SoftButtonAreas" "0 0 0 0 0 0 0 0"
44 | EndSection
45 |
--------------------------------------------------------------------------------
/weblog/articles/synaptics-touchpad-on-linux/lenovo-synaptics-touchpad.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/synaptics-touchpad-on-linux/lenovo-synaptics-touchpad.jpg
--------------------------------------------------------------------------------
/weblog/articles/your-definition-of-privacy-is-wrong/umatrix-usage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/articles/your-definition-of-privacy-is-wrong/umatrix-usage.png
--------------------------------------------------------------------------------
/weblog/design/editor/vera-mono.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/design/editor/vera-mono.woff
--------------------------------------------------------------------------------
/weblog/design/editor/vera-mono.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiengineer/cookie.engineer/a4ca598f85c421ea44fc5e24627ad512f74c2040/weblog/design/editor/vera-mono.woff2
--------------------------------------------------------------------------------
/weblog/design/index.css:
--------------------------------------------------------------------------------
1 |
2 | section#welcome h1 {
3 | display: block;
4 | margin: 160px 0px 0px 0px;
5 | padding: 0px;
6 | font-family: 'museo-sans-500';
7 | font-size: 40px;
8 | line-height: 48px;
9 | font-weight: 500;
10 | text-align: center;
11 | }
12 |
13 | section#weblog article ul {
14 | display: block;
15 | margin: 0px;
16 | padding: 1em 0px 0px 0px;
17 | list-style: none;
18 | }
19 |
20 | section#weblog article[data-result="false"] ul {
21 | display: none;
22 | }
23 |
24 | section#weblog article ul li b {
25 | display: inline-block;
26 | width: 8em;
27 | font-weight: 300;
28 | font-size: 16px;
29 | line-height: 20px;
30 | vertical-align: middle;
31 | }
32 |
33 | section#weblog article ul li a,
34 | section#weblot article ul li span {
35 | display: inline-block;
36 | width: calc(100% - 8em);
37 | font-size: 16px;
38 | line-height: 20px;
39 | vertical-align: middle;
40 | white-space: nowrap;
41 | text-overflow: ellipsis;
42 | overflow: hidden;
43 | }
44 |
45 |
46 |
47 | @media print {
48 |
49 | section#welcome {
50 | display: block;
51 | position: relative;
52 | width: 100vw;
53 | margin: 0px;
54 | padding: 0px;
55 | }
56 |
57 | section#welcome h1 {
58 | display: block;
59 | position: static;
60 | width: 100vw;
61 | height: 25vh;
62 | margin: 4em 0px 0px 0px;
63 | padding: 0px;
64 | font-size: 64px;
65 | line-height: 64px;
66 | text-align: center;
67 | vertical-align: middle;
68 | page-break-before: unset;
69 | page-break-after: unset;
70 | }
71 |
72 | section#welcome article {
73 | display: block;
74 | position: static;
75 | width: auto;
76 | margin: 6em 0px 0px 0px;
77 | padding: 0px;
78 | text-align: left;
79 | background: transparent;
80 | border-radius: 0px;
81 | break-before: auto;
82 | }
83 |
84 | section#weblog article,
85 | section#weblog article:nth-of-type(even) {
86 | display: block;
87 | position: static;
88 | width: 100vw;
89 | height: 25vh;
90 | margin: 0px;
91 | padding: 0px;
92 | }
93 |
94 | section#weblog article:nth-of-type(even) {
95 | page-break-after: unset;
96 | }
97 |
98 | }
99 |
100 |
--------------------------------------------------------------------------------
/weblog/design/layout/article.js:
--------------------------------------------------------------------------------
1 |
2 | (function(global) {
3 |
4 | global.addEventListener('DOMContentLoaded', () => {
5 |
6 | let hljs = global.hljs || null;
7 | if (hljs !== null) {
8 |
9 | let codes = Array.from(document.querySelectorAll('pre[class]'));
10 | if (codes.length > 0) {
11 |
12 | codes.forEach((code) => {
13 |
14 | let lang = code.className || null;
15 | if (lang === 'javascript') {
16 |
17 | setTimeout(() => {
18 |
19 | Array.from(code.querySelectorAll('span.hljs-built_in')).forEach((node) => {
20 |
21 | let text = node.innerHTML || '';
22 | if (text === 'console') {
23 | node.className += ' hljs-console';
24 | }
25 |
26 | });
27 |
28 | Array.from(code.querySelectorAll('span.hljs-keyword')).forEach((node) => {
29 |
30 | let text = node.innerHTML || '';
31 | if (text === 'let') {
32 | node.className += ' hljs-let';
33 | } else if (text === 'new') {
34 | node.className += ' hljs-new';
35 | } else if (text === 'function') {
36 | node.className += ' hljs-function';
37 | }
38 |
39 | });
40 |
41 | Array.from(code.querySelectorAll('span.hljs-literal')).forEach((node) => {
42 |
43 | let text = node.innerHTML || '';
44 | if (text === 'null') {
45 | node.className += ' hljs-null';
46 | }
47 |
48 | });
49 |
50 | }, 500);
51 |
52 | }
53 |
54 | if (lang !== 'plaintext') {
55 | hljs.highlightElement(code);
56 | }
57 |
58 | });
59 |
60 | }
61 |
62 | }
63 |
64 | }, true);
65 |
66 | })(typeof window !== 'undefined' ? window : this);
67 |
68 |
--------------------------------------------------------------------------------
/weblog/design/layout/highlight.css:
--------------------------------------------------------------------------------
1 |
2 | /* general */
3 | .hljs {}
4 | .hljs-built_in { color: #ff5f87 }
5 | .hljs-title.class_ { color: #ff5f87 }
6 | .hljs-class .hljs-title { color: #ff5f87 }
7 |
8 | .hljs-class { color: #ff5f87 }
9 | .hljs-function { color: #d78787 }
10 | .hljs-keyword { color: #ff5f87 }
11 | .hljs-literal { color: #32afe5 }
12 | .hljs-number { color: #ff005f }
13 | .hljs-params { color: #ffffff }
14 | .hljs-regexp { color: #5fd75f }
15 | .hljs-string { color: #5fd75f }
16 | .hljs-subst { color: #ffffff } /* unsure about this? */
17 | .hljs-symbol { color: #32afe5 }
18 | .hljs-title { color: #ffffff }
19 | .hljs-type { color: #d78787 }
20 |
21 | /* meta */
22 | .hljs-comment { color: #afafaf }
23 | .hljs-doctag { color: #afafaf }
24 | .hljs-meta { color: #d78787 }
25 | .hljs-meta .hljs-keyword { color: #ff5f87 }
26 | .hljs-meta .hljs-string { color: #5fd75f }
27 | .hljs-section { color: #ffffff }
28 | .hljs-tag { color: #d78787 }
29 | .hljs-name { color: #ff5f87 }
30 | .hljs-builtin-name { color: #ff5f87 }
31 | .hljs-attr { color: #d78787 }
32 | .hljs-attribute { color: #d78787 }
33 | .hljs-variable { color: #ffffff }
34 |
35 | /* markup */
36 | .hljs-bullet { color: #ffffff }
37 | .hljs-emphasis { font-style: italic }
38 | .hljs-formula { color: #ffffff }
39 | .hljs-link { text-decoration: underline }
40 | .hljs-quote { color: #afafaf }
41 | .hljs-strong { font-weight: bold }
42 |
43 | /* css */
44 | .hljs-selector-tag { color: #d78787 }
45 | .hljs-selector-id { color: #d78787 }
46 | .hljs-selector-class { color: #5fd75f }
47 | .hljs-selector-attr { color: #5fd75f }
48 | .hljs-selector-pseudo { color: #ffffff }
49 |
50 | /* templates */
51 |
52 | .hljs-template-tag { color: #d78787 }
53 | .hljs-template-variable { color: #ff5f87 }
54 |
55 | /* diff */
56 | .hljs-addition { background-color: #5faf5f }
57 | .hljs-deletion { background-color: #5f0000 }
58 |
59 |
60 |
61 | /* FIXES */
62 |
63 | pre.http { color: #5fd75f }
64 | pre.http .hljs-attribute { color: #ff5f87 }
65 |
66 | pre.javascript .hljs-attr { color: #ffffff }
67 | pre.javascript .hljs-console { color: #ffffff }
68 | pre.javascript .hljs-function { color: #d78787 }
69 | pre.javascript .hljs-let { color: #32afe5 }
70 | pre.javascript .hljs-new { color: #32afe5 }
71 | pre.javascript .hljs-null { color: #ff5f87 }
72 | pre.javascript .hljs-undefined { color: #ff5f87 }
73 |
74 |
--------------------------------------------------------------------------------
/weblog/editor.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Cookie Engineer's Crappy Web Log Editor
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------