diff --git a/package.json b/package.json index 01d33ad..45ac096 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,25 @@ { - "name": "vite-template-solid", - "version": "0.0.0", - "description": "", - "scripts": { - "start": "vite", - "dev": "vite", - "build": "vite build", - "serve": "vite preview" - }, - "license": "MIT", - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", - "eslint": "^8.52.0", - "solid-devtools": "^0.27.3", - "typescript": "^5.1.3", - "vite": "^4.3.9", - "vite-plugin-solid": "^2.7.0" - }, - "dependencies": { - "@solidjs/router": "^0.8.3", - "solid-js": "^1.7.6" - } + "name": "vite-template-solid", + "version": "0.0.0", + "description": "", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "vite build", + "serve": "vite preview" + }, + "license": "MIT", + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^6.9.0", + "@typescript-eslint/parser": "^6.9.0", + "eslint": "^8.52.0", + "solid-devtools": "^0.27.3", + "typescript": "^5.1.3", + "vite": "^4.3.9", + "vite-plugin-solid": "^2.7.0" + }, + "dependencies": { + "@solidjs/router": "^0.8.3", + "solid-js": "^1.7.6" + } } diff --git a/src/Navigation.tsx b/src/Navigation.tsx index bd86cf1..7556bff 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -8,6 +8,7 @@ const Navigation: Component = () => { String Reverse String Noise Lorem Ipsum + Convert Base ); }; diff --git a/src/index.tsx b/src/index.tsx index 14be359..610c23d 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -8,6 +8,8 @@ import StrLen from './pages/StrLen'; import StrRev from './pages/StrRev'; import StrNoise from './pages/StrNoise'; import LoremIpsum from './pages/LoremIpsum'; +import Convert from './pages/ConvertBase'; +import ConvertBase from './pages/ConvertBase'; const root = document.getElementById('root'); @@ -25,6 +27,7 @@ render(() => ( + ), root!); diff --git a/src/pages/ConvertBase.tsx b/src/pages/ConvertBase.tsx new file mode 100644 index 0000000..348fc23 --- /dev/null +++ b/src/pages/ConvertBase.tsx @@ -0,0 +1,102 @@ +import { Component, Setter, createEffect, createSignal, on } from 'solid-js'; + +import styles from './Page.module.css'; +import Navigation from '../Navigation'; + +function group(str: string, groupSize: number) { + const subs = []; + for (let i = 0; i < Math.ceil(str.length / groupSize); i++) { + let sub = str.slice(Math.max(0, str.length - i * groupSize - groupSize), str.length - i * groupSize); + while (sub.length < groupSize) sub = '0' + sub; + subs.push(sub); + } + + return subs.reverse().join(' '); +} + +function parse(value: string, base: number) { + return [...value].reduce((r, v) => r * BigInt(base) + BigInt(parseInt(v, base)), 0n); +} + +const ConvertBase: Component = () => { + const [error, setError] = createSignal(' '); + const [value, setValue] = createSignal(BigInt(0)); + const [decimal, setDecimal] = createSignal('0'); + const [binary, setBinary] = createSignal('0'); + const [binaryOctets, setBinaryOctet] = createSignal(true); + const [octal, setOctal] = createSignal('0'); + const [octalTriplets, setOctalTriplet] = createSignal(true); + const [hex, setHex] = createSignal('0'); + const [hexPairs, setHexPairs] = createSignal(true); + + function updateExcept(value: string, base: number, except: Setter) { + const raw = value.replaceAll(/ /g, ''); + + setError(''); + + if (base == 2) { // TODO: common validation method + if ([...raw].find(c => !['0', '1'].includes(c))) { + setError('Invalid binary number'); + return; + } + } else if (base == 8) { + if ([...raw].find(c => !['0', '1', '2', '3', '4', '5', '6', '7'].includes(c))) { + setError('Invalid octal number'); + return; + } + } else if (base == 10) { + if ([...raw].find(c => !['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].includes(c))) { + setError('Invalid decimal number'); + return; + } + } else if (base == 16) { + if ([...raw].find(c => !['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F'].includes(c))) { + setError('Invalid hex number'); + return; + } + } + + const num = parse(raw, base); + + setValue(num); + if (setDecimal != except) setDecimal(num.toString()); + if (setBinary != except) setBinary(binaryOctets() ? group(num.toString(2), 8) : num.toString(2)); + if (setOctal != except) setOctal(octalTriplets() ? group(num.toString(8), 3) : num.toString(8)); + if (setHex != except) setHex(hexPairs() ? group(num.toString(16), 2) : num.toString(16)); + } + + createEffect(on(binaryOctets, () => setBinary(binaryOctets() ? group(value().toString(2), 8) : value().toString(2)))); + createEffect(on(octalTriplets, () => setOctal(octalTriplets() ? group(value().toString(8), 3) : value().toString(8)))); + createEffect(on(hexPairs, () => setHex(hexPairs() ? group(value().toString(16), 2) : value().toString(16)))); + + return ( +
+

Convert

+

Bases

+ {error()} +

Decimal

+