From d32e22ee2b7aceda57163b42ca9e9deaeae72afd Mon Sep 17 00:00:00 2001 From: mehbark Date: Mon, 17 Apr 2023 00:24:30 -0400 Subject: [PATCH] wow --- package.json | 83 ++++++++++---------- public/index.html | 44 ++++++----- public/manifest.json | 46 +++++------ src/App.css | 42 +++++----- src/App.tsx | 81 +++++++++++++++----- src/DaveHash.tsx | 177 +++++++++++++++++++++++++++++++++++++++++++ src/index.css | 75 ++++++++++++++++-- 7 files changed, 413 insertions(+), 135 deletions(-) create mode 100644 src/DaveHash.tsx diff --git a/package.json b/package.json index 7130fa3..9954703 100644 --- a/package.json +++ b/package.json @@ -1,43 +1,44 @@ { - "name": "davehash", - "version": "0.1.0", - "private": true, - "dependencies": { - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^13.5.0", - "@types/jest": "^27.5.2", - "@types/node": "^16.18.23", - "@types/react": "^18.0.35", - "@types/react-dom": "^18.0.11", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-scripts": "5.0.1", - "typescript": "^4.9.5", - "web-vitals": "^2.1.4" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } + "name": "davehash", + "homepage": "davehash/", + "version": "0.1.0", + "private": true, + "dependencies": { + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "@types/jest": "^27.5.2", + "@types/node": "^16.18.23", + "@types/react": "^18.0.35", + "@types/react-dom": "^18.0.11", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "5.0.1", + "typescript": "^4.9.5", + "web-vitals": "^2.1.4" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } } diff --git a/public/index.html b/public/index.html index aa069f2..9907a3c 100644 --- a/public/index.html +++ b/public/index.html @@ -1,21 +1,18 @@ - - - - - - - - - - - React App - - - -
- - + --> diff --git a/public/manifest.json b/public/manifest.json index 080d6c7..39039b7 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,25 +1,25 @@ { - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" + "short_name": "davehash", + "name": "davehash", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": "./davehash/", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" } diff --git a/src/App.css b/src/App.css index 74b5e05..011d8a0 100644 --- a/src/App.css +++ b/src/App.css @@ -1,38 +1,38 @@ .App { - text-align: center; + text-align: center; + display: inline-block; } .App-logo { - height: 40vmin; - pointer-events: none; + height: 40vmin; + pointer-events: none; } @media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } + .App-logo { + animation: App-logo-spin infinite 20s linear; + } } .App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; + background-color: white; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + /* justify-content: center; */ + font-size: 14px; } .App-link { - color: #61dafb; + color: #61dafb; } @keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } } diff --git a/src/App.tsx b/src/App.tsx index a53698a..8357b14 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,26 +1,65 @@ -import React from 'react'; -import logo from './logo.svg'; -import './App.css'; +import React, { useState } from "react"; +import "./App.css"; +import DaveHash, { hashes, HashFn, ShowHashDesc } from "./DaveHash"; function App() { - return ( -
-
- logo -

- Edit src/App.tsx and save to reload. -

- - Learn React - -
-
- ); + let [name, setName] = useState(""); + let [yVowel, setYVowel] = useState(true); + let [size, setSize] = useState(10); + let [hash_fn, setHashFn] = useState(() => hashes[0].fn); + + return ( +
+ setName(e.target.value)} value={name}> +
+

Y is a vowel:

+ setYVowel(!yVowel)} + > +
+
+

Sylladex size:

+ { + let new_size = parseInt(e.target.value, 10); + return setSize(new_size == new_size ? new_size : 0); + }} + value={size} + width="10vw" + > +
+
( +
setHashFn(() => h.fn)} + className={ + `${h.fn}` == `${hash_fn}` ? "active-hash-fn" : "" + } + > + +
+ ))} + >
+
+ +
+ ); } +// TODO: more hash functions (configurable) and, like, an actual sylladex thingy (optional detect collisions) + export default App; diff --git a/src/DaveHash.tsx b/src/DaveHash.tsx new file mode 100644 index 0000000..5bcd046 --- /dev/null +++ b/src/DaveHash.tsx @@ -0,0 +1,177 @@ +import { Fragment } from "react"; + +export default function DaveHash({ + text, + y_vowel = false, + sylladex_size = 10, + hash_fn = basic_hash, +}: { + text: string; + y_vowel?: boolean; + sylladex_size?: number; + hash_fn?: HashFn; +}): JSX.Element { + let letters = text.toUpperCase().split(""); + let math_result = ( + {math({ letters, y_vowel, sylladex_size, hash_fn })} + ); + // children.push(); + let letters__ = ( +
+ + {math_result} +
+ ); + + return letters__; +} + +function Word({ + letters, + y_vowel, + hash_fn, +}: { + letters: string[]; + y_vowel: boolean; + hash_fn: HashFn; +}): JSX.Element { + let children = letters.map((letter, i) => ( + {Letter({ letter, y_vowel, hash_fn })} + )); + return ; +} + +function math({ + letters, + y_vowel, + sylladex_size, + hash_fn, +}: { + letters: string[]; + y_vowel: boolean; + sylladex_size: number; + hash_fn: HashFn; +}): string { + let nums: number[] = letters + .filter(is_letter) + .map(l => hash_fn(l, y_vowel).value); + let sum = nums.reduce((a, b) => a + b, 0); + + return `(${ + nums.length > 0 ? nums.join("+") : 0 + } = ${sum}%${sylladex_size} = ${sum % sylladex_size})`; +} + +type HashResult = { color: Color; value: number }; +// prettier-ignore +type AsciiLetter = + | "A" | "B" | "C" | "D" | "E" + | "F" | "G" | "H" | "I" | "J" + | "K" | "L" | "M" | "N" | "O" + | "P" | "Q" | "R" | "S" | "T" + | "U" | "V" | "W" | "X" | "Y" + | "Z"; +export type HashFn = (_: AsciiLetter, y_vowel: boolean) => HashResult; +type Color = string; +type HashLetterAssoc = [AsciiLetter, Color, number]; + +type HashInfo = { fn: HashFn; bla: HashLetterAssoc[] }; + +function Letter({ + letter, + y_vowel, + hash_fn, +}: { + letter: string; + y_vowel: boolean; + hash_fn: HashFn; +}): JSX.Element { + return is_letter(letter) ? ( + {letter} + ) : ( + {letter} + ); +} + +const basic_hash: HashFn = (l, y_vowel) => + is_vowel(l, y_vowel) + ? { color: "red", value: 1 } + : { color: "blue", value: 2 }; + +function is_vowel(letter: AsciiLetter, y_vowel: boolean): boolean { + let vowels = "aeiou".split(""); + if (y_vowel) { + vowels.push("y"); + } + return !vowels.every(v => v != letter.toLowerCase()); +} + +function is_letter(letter: string): letter is AsciiLetter { + let letters = "QWERTYUIOPASDFGHJKLZXCVBNM".split(""); + return !letters.every(v => v != letter); +} + +const reversed_hash: HashFn = (l, y_vowel) => + !is_vowel(l, y_vowel) + ? { color: "red", value: 1 } + : { color: "blue", value: 2 }; + +export function ShowHashDesc({ bla }: { bla: HashLetterAssoc[] }): JSX.Element { + return ( +
( + {ShowHashLetterAssoc({ hla })} + ))} + >
+ ); +} + +function ShowHashLetterAssoc({ hla }: { hla: HashLetterAssoc }): JSX.Element { + return ( +

+ {hla[0].toUpperCase()}= + {hla[2]}; +

+ ); +} + +const scrabble_hash: HashFn = (l, _) => { + // prettier-ignore + let dict = { + A: 1, B: 3, C: 3, D: 2, E: 1, + F: 4, G: 2, H: 4, I: 1, J: 8, + K: 5, L: 1, M: 3, N: 1, O: 1, + P: 3, Q: 10, R: 1, S: 1, T: 1, + U: 1, V: 4, W: 4, X: 8, Y: 4, + Z: 10, + }; + return { color: "#05d000", value: dict[l] }; +}; + +export const hashes: HashInfo[] = [ + { + fn: basic_hash, + bla: [ + ["C", "blue", 2], + ["V", "red", 1], + ], + }, + { + fn: reversed_hash, + bla: [ + ["C", "red", 1], + ["V", "blue", 2], + ], + }, + { + fn: scrabble_hash, + bla: "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + .split("") + .map(l => [ + l as AsciiLetter, + "#05d000", + scrabble_hash(l as AsciiLetter, false).value, + ]), + }, +]; diff --git a/src/index.css b/src/index.css index ec2585e..2951f4f 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1,72 @@ body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + margin: 0; + font-family: "Courier New", Courier, monospace; + font-weight: bold; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + white-space: pre; +} + +#root { + margin-top: 5vh; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + monospace; +} + +.vowel { + color: red; +} + +.consonant { + color: blue; +} + +.davehash { + font-size: 14px; + display: flex; +} + +* { + margin: 0; + max-width: 100vw; + max-height: 100vh; +} + +body { + overflow: hidden; +} + +.space { + width: 0.75rem; +} + +.hash-desc { + display: block; + cursor: pointer; + width: 40vmin; + margin-left: auto; + margin-right: auto; + /* text-overflow: ellipsis; */ + overflow: hidden; + text-align: left; + /* max-height: 17px; */ +} + +.hash-letter-assoc { + display: inline-block; +} + +/* .hash-letter-assoc::after { + content: " "; +} */ + +.active-hash-fn { + background-color: #e7e7e7; +} + +input[type="checkbox"] { + cursor: pointer; }