Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
fulcanelly committed Jan 9, 2024
1 parent 91e9a95 commit abf9504
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 52 deletions.
19 changes: 9 additions & 10 deletions src/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as R from 'ramda'
//import { buildModelOfState } from './nothing';
import { debugEntry, drawShuntWire } from './circuit'
import { Cell, findByPosition, getConnectedTo, getOppositeIndex, NotCell, PinCell, PinIndex, PinInfo, Position, State, updateCellsNToActuall, WireCell } from './model';
import { buildPath, isMatch } from './utils'
import { buildLens, buildPath, isMatch } from './utils'


// needed for rotation
Expand Down Expand Up @@ -96,13 +96,9 @@ export function getNearWithTouchingIndex(pos: Position): Array<{ position: Posit
.map(([position, touching]) => ({ position, touching } as { position: Position, touching: PinIndex }))
}

let cellsLens = R.lensPath(
buildPath(_ => _.cells)
)

const valueLens = R.lensPath(
buildPath(_ => _.value))
let cellsLens = buildLens<State>().cells._()

const valueLens = buildLens<PinInfo>().value!._()

//toPins :: Cell -> State -> Pins

Expand Down Expand Up @@ -132,8 +128,11 @@ export type Datasheet = {

// ========================

export const actualStatePoweredLens = R.lensPath(
buildPath(_ => _.actual.state.powered))

// buildLens<PinCell>().actual.state.

export const actualStatePoweredLens = buildLens<PinCell>().actual.state.powered?._()!


export const notDatasheet = {
pattern: {
Expand All @@ -149,7 +148,7 @@ export const notDatasheet = {

toPins(cell: NotCell) {
const pins = this.pinInfo.map(it => {
if (it.type == 'output') {
if (it.type === 'output') {
return R.set(valueLens, Boolean(cell.state.powered), it)
} else {
return it
Expand Down
28 changes: 28 additions & 0 deletions src/mege.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@


// taken from https://dev.to/lucianbc/union-type-merging-in-typescript-9al

export type Subtract<A, C> = A extends C ? never : A;
export type NonCommonKeys<T extends object> = Subtract<AllKeys<T>, CommonKeys<T>>;

export type CommonKeys<T extends object> = keyof T;

export type AllKeys<T> = T extends any ? keyof T : never;


export type Merge<T extends object> = {
[k in CommonKeys<T>]: PickTypeOf<T, k>;
} &
{
[k in NonCommonKeys<T>]?: PickTypeOf<T, k>;
};

export type PickType<T, K extends AllKeys<T>> = T extends { [k in K]?: any }
? T[K]
: never;

export type PickTypeOf<T, K extends string | number | symbol> = K extends AllKeys<T>
? PickType<T, K>
: never;


8 changes: 4 additions & 4 deletions src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,18 +151,18 @@ function getWire(pinCells: PinCell[]): [Wire | null, PinCell []] {
getConnectedTo(rest, queue.shift()!)
.forEach(cell => {
//group by
if (cell.found.actual.cellType == 'wire') {
if (cell.found.actual.cellType === 'wire') {
wire.cells.push(cell.found)
queue.push(cell.found)
rest = R.without(wire.cells, pinCells)
} else {
wire.inputs.push({
pinIndex: (cell.touching) as PinIndex,
position: cell.position
})
}

})

rest = R.without(wire.cells, rest)
}

return [wire, R.without(wire.cells, pinCells)]
Expand All @@ -172,7 +172,7 @@ function getWire(pinCells: PinCell[]): [Wire | null, PinCell []] {
export function findWires(tiles: PinCell[]): [Wire[], PinCell[]] {
//todo .filter wire
let wires: Wire[] = []
while (tiles.find(p => p.actual.cellType == 'wire')) {
while (tiles.find(p => p.actual.cellType === 'wire')) {
let [wire, tilesUpd] = getWire(tiles)
tiles = tilesUpd
if (wire) {
Expand Down
62 changes: 26 additions & 36 deletions src/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import * as R from 'ramda'
import { updateState } from './engine'
import { Cell, NotCell, Position, State, WireCell } from './model'
import { buildPath } from './utils'
import { buildLens, buildPath } from './utils'

export const genericWire: Cell = {
cellType: 'wire',
Expand Down Expand Up @@ -64,7 +64,7 @@ export function initState(): State {
}

//TODO
type Action = {
export type Action = {
type: string
[rest: string]: any
}
Expand Down Expand Up @@ -123,33 +123,28 @@ export function sendToggleEditing(dispatch: React.Dispatch<Action>) {
})
}

export function handleTileHover(state: State, action: Action) {
export function handleTileHover(state: State, action: Action): State {
return R.set(
R.lensPath(['hovered']), action.pos, state)
}

function handleSelectTool(state, action: Action) {
let selectedIndexLens = R.lensPath(
buildPath(_ => _.selected.index))
export const stateLens = buildLens<State>

let selectedEntryLens = R.lensPath(
buildPath(_ => _.selected.entry))

return R.set(
selectedEntryLens, action.entry, R.set(
selectedIndexLens, action.index, state))
function handleSelectTool(state: State, action: Action): State {
return R.pipe(
R.set(stateLens().selected.entry._(), action.entry),
R.set(stateLens().selected.index._(), action.index))
(state)
}

export function handleToggleEditing(state: State, action: Action) {
const modeEditingLens = R.lensPath(
buildPath(_ => _.mode.editing)
)
export function handleToggleEditing(state: State, action: Action): State {
const modeEditingLens = buildLens<State>().mode.editing._()

let lastEditingState = R.view(modeEditingLens, state)
return R.set(modeEditingLens, !lastEditingState, state)
}

export function handleTileClick(state: State, action: Action) {
export function handleTileClick(state: State, action: Action): State {
if (!state.mode.editing) {
return state
}
Expand All @@ -160,10 +155,10 @@ export function handleTileClick(state: State, action: Action) {
}

//void is special tile type so it means remove current tile
if (state.selected.entry.cellType == 'void') {
if (state.selected.entry.cellType === 'void') {
const cells = [
...state.cells.filter(
item => JSON.stringify(item.position) != JSON.stringify(action.pos)
item => JSON.stringify(item.position) !== JSON.stringify(action.pos)
)
]

Expand All @@ -183,7 +178,7 @@ export function handleTileClick(state: State, action: Action) {
// genDebugCellFor(action.pos),
// ...genDebugCellsFor(action.pos),
...state.cells.filter(
item => JSON.stringify(item.position) != JSON.stringify(action.pos)
item => JSON.stringify(item.position) !== JSON.stringify(action.pos)
)
]

Expand All @@ -194,12 +189,12 @@ export function handleTileClick(state: State, action: Action) {
}


function handleMouseWheelEditing(state: State, action: Action) {
function handleMouseWheelEditing(state: State, action: Action): State {
if (state.hovered) {
//find needed cell
const cell = state.cells.find(
item => JSON.stringify(state.hovered)
== JSON.stringify(item.position)
=== JSON.stringify(item.position)
)

//get index of found cell
Expand All @@ -210,8 +205,8 @@ function handleMouseWheelEditing(state: State, action: Action) {
}

//get lens
let rotationLens = R.lensPath(
buildPath(_ => _.cells[index].state.rotation)
let rotationLens = R.lensPath<State, number>(
buildPath<State>(_ => _.cells[index].state.rotation)
)

let mutation = (x) =>
Expand All @@ -223,16 +218,13 @@ function handleMouseWheelEditing(state: State, action: Action) {
return state
}

export function handleMouseWheel(state: State, action: Action) {
export function handleMouseWheel(state: State, action: Action): State {

if (state.mode.editing) {
return handleMouseWheelEditing(state, action)
} else {
const deltaY = action.deltaY

const fieldScaleLens = R.lensPath(
buildPath(_ => _.field.scale)
)
const fieldScaleLens = buildLens<State>().field.scale._()

const getNewScale = () => {
let currentScale = state.field.scale
Expand All @@ -250,12 +242,10 @@ export function handleMouseWheel(state: State, action: Action) {

}

export function handleShiftChange(state: State, action: Action) {
export function handleShiftChange(state: State, action: Action): State {
if (state.mode.editing) return state

const fieldStateLens = R.lensPath(
buildPath(_ => _.field.shift)
)
const fieldStateLens = buildLens<State>().field.shift._()

const oldShift = R.view(fieldStateLens, state)

Expand All @@ -272,7 +262,7 @@ export function handleCellsUpdate(state: State, action: Action): State {
return updateState(state)
}

export function defaultReducer(state: State, action: Action) {
export function defaultReducer(state: State, action: Action): State {
const template = {
tile_click: handleTileClick,
edit: handleToggleEditing,
Expand All @@ -285,6 +275,6 @@ export function defaultReducer(state: State, action: Action) {

return Object.entries(template)
.map(([event, handler]) => ({event, handler}))
.find(pair => pair.event == action.type)
?.handler(state, action)
.find(pair => pair.event === action.type)
?.handler(state, action)!
}
30 changes: 28 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@

import * as R from 'ramda'
import { Position, State } from './model'
import { Action } from './reducer'
import { Merge } from './mege'

//**
// *
// * @param {*} handler
// * @returns
// */
type ProxyType = {[key: string]: ProxyType }

type rec = Record<string, any>

type ProxyType<T extends rec> = { [K in keyof Merge<T>]-?: ProxyType<T[K]> }


/**
Expand All @@ -22,7 +28,7 @@ type ProxyType = {[key: string]: ProxyType }
* @param {(proxy: Proxy) => Proxy} handler
*
*/
export function buildPath(handler: (proxy: ProxyType) => ProxyType): (string | number)[] {
export function buildPath<T extends rec>(handler: (proxy: ProxyType<T>) => any): (string | number)[] {
let path: Array<string | number> = []
let proxy = new Proxy(path, {
get(target, string: string, recv) {
Expand All @@ -34,6 +40,26 @@ export function buildPath(handler: (proxy: ProxyType) => ProxyType): (string | n
return path.map(item => isNaN(item as any) ? item : Number(item))
}

type LensBuilderProxyType<T extends rec, StartType>
= { [K in keyof Merge<T>]: LensBuilderProxyType<T[K], StartType> }
& {
_: () => R.Lens<StartType, T>
}


export function buildLens<T extends rec>(): LensBuilderProxyType<T, T> {
let path: Array<string> = [];
let proxy = new Proxy({}, {
get(target, prop, receiver) {
if (prop === '_') {
return () => R.lensPath(path);
}
path.push(prop as string);
return proxy;
}
});
return proxy as LensBuilderProxyType<T, T>;
}


export function isMatch(pattern: any, object: any): boolean {
Expand Down

0 comments on commit abf9504

Please sign in to comment.