From 8e99f04d9cbc420176e6c28cbff30374dba7e03c Mon Sep 17 00:00:00 2001 From: twells46 Date: Sun, 25 Jan 2026 11:14:07 -0600 Subject: Initial commit --- src/App.css | 38 +++++++++++++++++++++++ src/App.test.tsx | 9 ++++++ src/App.tsx | 27 ++++++++++++++++ src/deconstruct.test.ts | 79 +++++++++++++++++++++++++++++++++++++++++++++++ src/deconstruct.ts | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ src/index.css | 13 ++++++++ src/index.tsx | 19 ++++++++++++ src/logo.svg | 1 + src/react-app-env.d.ts | 1 + src/reportWebVitals.ts | 15 +++++++++ src/setupTests.ts | 5 +++ 11 files changed, 289 insertions(+) create mode 100644 src/App.css create mode 100644 src/App.test.tsx create mode 100644 src/App.tsx create mode 100644 src/deconstruct.test.ts create mode 100644 src/deconstruct.ts create mode 100644 src/index.css create mode 100644 src/index.tsx create mode 100644 src/logo.svg create mode 100644 src/react-app-env.d.ts create mode 100644 src/reportWebVitals.ts create mode 100644 src/setupTests.ts (limited to 'src') diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..74b5e05 --- /dev/null +++ b/src/App.css @@ -0,0 +1,38 @@ +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .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; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/src/App.test.tsx b/src/App.test.tsx new file mode 100644 index 0000000..2a68616 --- /dev/null +++ b/src/App.test.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import App from './App'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..ddeffaf --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import logo from './logo.svg'; +import './App.css'; + +function App() { + return ( +
+
+ logo +

+ Edit src/App.tsx and save to reload. + I'm an alien! +

+ + Learn React + +
+
+ ); +} + +export default App; diff --git a/src/deconstruct.test.ts b/src/deconstruct.test.ts new file mode 100644 index 0000000..e374dd5 --- /dev/null +++ b/src/deconstruct.test.ts @@ -0,0 +1,79 @@ +import { SFItem, derive, add, BaseComponents, get } from './deconstruct'; + +test('base returns 1', () => { + const item: SFItem = { + name: 'Iron Ingot', + id: 'iron_ingot', + type: 'base' + }; + const expected = new Map([[item.id, 30]]); + expect(derive(item)).toMatchObject(expected); +}); + +test('add', () => { + const curr: BaseComponents = [['iron_ingot', 30]]; + const val = add(['iron_ingot', 10], curr); + const expected = [['iron_ingot', 40]]; + expect(val).toMatchObject(expected); +}); + +test('add2', () => { + const curr: BaseComponents = [['copper_ore', 10], ['iron_ingot', 30]]; + const val = add(['iron_ingot', 10], curr); + const expected = [['copper_ore', 10], ['iron_ingot', 40]]; + expect(val).toMatchObject(expected); +}); + +test('get undefined', () => { + const ITEMS: Array = [ + { + name: 'Iron Ingot', + id: 'iron_ingot', + type: 'base' + }, + ]; + const val = get('iron_plate', ITEMS); + const expected = undefined; + expect(val).toBe(expected); +}); + +test('get existing', () => { + const ITEMS: Array = [ + { + name: 'Iron Ingot', + id: 'iron_ingot', + type: 'base' + }, + ]; + const val = get('iron_ingot', ITEMS); + const expected = ITEMS[0]; + expect(val).toMatchObject(expected); +}); + +test('level 1', () => { + const item: SFItem = { + name: 'Iron Plate', + id: 'iron_plate', + type: 'derived', + recipe: { + in: [['iron_ingot', 30]], + out: 20 + } + }; + const expected = [['iron_ingot', 30]]; + expect(derive(item)).toMatchObject(expected); +}); + +test('level 2', () => { + const item: SFItem = { + name: 'Screw', + id: 'screw', + type: 'derived', + recipe: { + in: [['iron_rod', 10]], + out: 40 + } + }; + const expected = [['iron_ingot', 40]]; + expect(derive(item)).toMatchObject(expected); +}); diff --git a/src/deconstruct.ts b/src/deconstruct.ts new file mode 100644 index 0000000..3212645 --- /dev/null +++ b/src/deconstruct.ts @@ -0,0 +1,82 @@ +export type SFItem = { + name: string, + id: string, + type: 'base' | 'derived', + recipe: Recipe, +} + +export type BaseComponent = [string, number]; +export type BaseComponents = Array; + +export type Recipe = { + in: Array<[string, number]>, + out: number +}; + +const ITEMS: Array = [ + { + name: 'Iron Plate', + id: 'iron_plate', + type: 'base', + recipe: { + in: [['iron_ingot', 30]], + out: 20 + } + }, + { + name: 'Iron Rod', + id: 'iron_rod', + type: 'base', + recipe: { + in: [['iron_ingot', 15]], + out: 15 + } + }, + { + name: 'Screw', + id: 'screw', + type: 'derived', + recipe: { + in: [['iron_rod', 10]], + out: 40 + } + }, +]; + +export function get(id: string, items: Array): SFItem | undefined { + for (const item of items) { + if(item.id === id) { + return item; + } + } + return undefined; +} + +export function add(toAdd: BaseComponent, components: BaseComponents) { + for (const [i, val] of components.entries()) { + if (toAdd[0] === val[0]) { + components[i][1] += toAdd[1]; + return components; + } + } + return components.push(toAdd); +} + +function ratio(item: SFItem) { + const +} + +export function derive(item: SFItem): BaseComponents { + switch(item.type) { + case "derived": + let total = 0; + for (const input of item.recipe.in) { + const component = get(input[0], ITEMS); + if (component) { + total += input[1] * ratio(component); + } + } + case "base": + return [item.recipe.in[0]]; + } +} diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..ec2585e --- /dev/null +++ b/src/index.css @@ -0,0 +1,13 @@ +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; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..032464f --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; + +const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement +); +root.render( + + + +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/src/logo.svg b/src/logo.svg new file mode 100644 index 0000000..9dfc1c0 --- /dev/null +++ b/src/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts new file mode 100644 index 0000000..6431bc5 --- /dev/null +++ b/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts new file mode 100644 index 0000000..49a2a16 --- /dev/null +++ b/src/reportWebVitals.ts @@ -0,0 +1,15 @@ +import { ReportHandler } from 'web-vitals'; + +const reportWebVitals = (onPerfEntry?: ReportHandler) => { + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry); + getFID(onPerfEntry); + getFCP(onPerfEntry); + getLCP(onPerfEntry); + getTTFB(onPerfEntry); + }); + } +}; + +export default reportWebVitals; diff --git a/src/setupTests.ts b/src/setupTests.ts new file mode 100644 index 0000000..8f2609b --- /dev/null +++ b/src/setupTests.ts @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom'; -- cgit v1.2.3