Created
September 9, 2024 16:05
-
-
Save jjhiggz/3a26314f89ac1a3a94a8adcc955ac56e to your computer and use it in GitHub Desktop.
Multi Item Alignment Stuff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { buildMatrix } from "./build-matrix"; | |
describe("Build Matrix", () => { | |
it("Should turn my shit into matrix of rows", () => { | |
expect( | |
buildMatrix({ | |
// prettier-ignore | |
elements: [ | |
1/1, | |
1/3, 2/3, | |
1/4, 3/4, | |
4/5, 1/5, | |
1/4,1/4 | |
], | |
defaultWidth: 1 / 4, | |
getWidthAsDecimalFromElement: (el) => el, | |
}), | |
).toEqual( | |
// prettier-ignore | |
[ | |
[1], | |
[1/3, 2/3], | |
[1/4, 3/4], | |
[4/5, 1/5,], | |
[1/4, 1/4] | |
], | |
); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Builds a Matrix of widths, makes it much easier to get the last row from an array of elements | |
*/ | |
export const buildMatrix = <T>({ | |
elements, | |
defaultWidth, | |
getWidthAsDecimalFromElement, | |
}: { | |
elements: T[]; | |
defaultWidth: number; | |
getWidthAsDecimalFromElement: (input: T) => number | undefined; | |
}) => { | |
let matrix: number[][] = []; | |
let currRow: number[] = []; | |
let currRowWidth = 0; | |
for (let element of elements) { | |
const elWidth = getWidthAsDecimalFromElement(element) ?? defaultWidth; | |
const newCurrRowWidth = elWidth + currRowWidth; | |
if (newCurrRowWidth > 1) { | |
matrix.push(currRow); | |
currRowWidth = elWidth; | |
currRow = [elWidth]; | |
} else if (newCurrRowWidth === 1) { | |
currRow.push(elWidth); | |
matrix.push(currRow); | |
currRow = []; | |
currRowWidth = 0; | |
} else { | |
currRow.push(elWidth); | |
currRowWidth = newCurrRowWidth; | |
} | |
} | |
if (currRow.length > 0) { | |
matrix.push(currRow); | |
} | |
return matrix; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { MultiItemAlignment } from "@prisma/client"; | |
import { match } from "ts-pattern"; | |
import { Fractions } from "./fraction.utils"; | |
import { buildMatrix } from "~/components/Render/build-matrix"; | |
import { | |
getAllIntersectionsRightAligned, | |
getCenterAlignedIntersections, | |
} from "./get-intersecttions"; | |
/** | |
* Because we're only using right border to apply styles, | |
* We will need to create "ghost elements" next to things | |
* that need a left border | |
* This should only happen ever in the last row, hence this | |
* function | |
*/ | |
export const correctLastRow = <T, DefaultValue>({ | |
items, | |
defaultItemWidthAsDecimal, | |
getItemWidth, | |
generateValue, | |
alignment, | |
}: { | |
items: T[]; | |
defaultItemWidthAsDecimal: number; | |
getItemWidth: (item: T) => number | undefined; | |
generateValue: (fraction: number) => DefaultValue; | |
alignment: Exclude<MultiItemAlignment, "DEFAULT">; | |
}): (T | DefaultValue)[] => { | |
return match(alignment) | |
.with("CENTER", () => { | |
const matrix = buildMatrix({ | |
defaultWidth: defaultItemWidthAsDecimal, | |
elements: items, | |
getWidthAsDecimalFromElement: getItemWidth, | |
}); | |
const secondLastRow = (matrix.at(-2) ?? []).map( | |
Fractions.getClosestFraction, | |
); | |
const lastRow = (matrix.at(-1) ?? []).map(Fractions.getClosestFraction); | |
if (!lastRow) return items; | |
const lastRowWidth = Fractions.sumFrac(lastRow); | |
const ghostWidth = Fractions.fraq((1 - lastRowWidth.toNumber()) / 2); | |
if (ghostWidth.toNumber() === 0) return items; | |
const lastRowIntersections = getCenterAlignedIntersections([...lastRow]); | |
const secondLastRowIntersections = getCenterAlignedIntersections( | |
secondLastRow ?? [], | |
); | |
const firstIntersection = lastRowIntersections.at(0)?.reduce().toString(); | |
const isFirstValid = secondLastRowIntersections.some( | |
(fraction) => { | |
const cleaned = fraction.reduce().toString(); | |
return cleaned === firstIntersection; | |
}, | |
// .eq(lastRowIntersections.at(0)!), | |
); | |
const isLastValid = secondLastRowIntersections.some((fraction) => | |
fraction.eq(lastRowIntersections.at(-1)!), | |
); | |
const shouldDrawGhosts = isFirstValid && isLastValid; | |
const lastRowStuff = items.slice(items.length - lastRow.length); | |
const notLastRowStuff = items.slice(0, items.length - lastRow.length); | |
const ghostPlaceholder = shouldDrawGhosts | |
? [ | |
generateValue( | |
Fractions.getClosestFractionAsDecimal(ghostWidth.toNumber()), | |
), | |
] | |
: []; | |
return [ | |
...notLastRowStuff, | |
...ghostPlaceholder, | |
...lastRowStuff, | |
...ghostPlaceholder, | |
]; | |
}) | |
.with("LEFT", () => { | |
return items; | |
}) | |
.with("RIGHT", () => { | |
const matrix = buildMatrix({ | |
defaultWidth: defaultItemWidthAsDecimal, | |
elements: items, | |
getWidthAsDecimalFromElement: getItemWidth, | |
}); | |
const secondLastRow = (matrix.at(-2) ?? []).map( | |
Fractions.getClosestFraction, | |
); | |
const lastRow = (matrix.at(-1) ?? []).map(Fractions.getClosestFraction); | |
if (!lastRow) return items; | |
const lastRowWidth = Fractions.sumFrac(lastRow); | |
const ghostWidth = Fractions.fraq(1 - lastRowWidth.toNumber()); | |
if (ghostWidth.toNumber() === 0) return items; | |
const lastRowIntersections = getAllIntersectionsRightAligned([ | |
ghostWidth, | |
...lastRow, | |
]); | |
const secondLastRowIntersections = getAllIntersectionsRightAligned( | |
secondLastRow ?? [], | |
); | |
const shouldDrawGhosts = secondLastRowIntersections.some((fraction) => | |
fraction.eq(lastRowIntersections.at(0)!), | |
); | |
const lastRowStuff = items.slice(items.length - lastRow.length); | |
const notLastRowStuff = items.slice(0, items.length - lastRow.length); | |
const ghostPlaceholder = shouldDrawGhosts | |
? [ | |
generateValue( | |
Fractions.getClosestFractionAsDecimal(ghostWidth.toNumber()), | |
), | |
] | |
: []; | |
return [...notLastRowStuff, ...ghostPlaceholder, ...lastRowStuff]; | |
}) | |
.exhaustive(); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { range } from "remeda"; | |
import { getCalloutBorderIndeces } from "./get-callout-border-indeces"; | |
describe("getCalloutBorderIndeces", () => { | |
describe(`center`, () => { | |
it(`center 3X3 | |
<-----1/1------> | |
1/3 <-----2/3--> | |
1/4 <-----3/4--> | |
<----4/5---> 1/5 | |
1/4 1/4/ 1/4 1/4 | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
// prettier-ignore | |
elements: [ | |
1, | |
1/3, 2/3, | |
1/4, 3/4, | |
4/5, 1/5, | |
1/4, 1/4 | |
], | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: (w) => w, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([1, 3, 5, 7]); | |
}); | |
it(`center 3X3 | |
1/5 1/5 1/5 1/5 1/5 | |
1/5 | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
// prettier-ignore | |
elements: [ | |
.2, .2, .2, .2, .2 , | |
.4, .2, .4 | |
], | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: (e) => e, | |
defaultWidth: 0.2, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 2, 3, 5, 6]); | |
}); | |
it(`center 3X3 | |
o|o|o | |
o|o|o | |
o|o | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: range(0, 8), | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: () => undefined, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 3, 4, 6]); | |
}); | |
it(`center 3X3 | |
o|o|o | |
o|o|o | |
o|o|o | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: range(0, 9), | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: () => undefined, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 3, 4, 6, 7]); | |
}); | |
it(`3X3 with space on top | |
<->|o | |
o|o|o | |
o|o|o | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: [2 / 3, 1 / 3, 1 / 3, 1 / 3, 1 / 3, 1 / 3, 1 / 3, 1 / 3], | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 2, 3, 5, 6]); | |
}); | |
it(` 3X3 with space on top and in middle | |
<->|o | |
o|<-> | |
o|o|o | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: [2 / 3, undefined, undefined, 2 / 3, 2 / 3, 1 / 3], | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 2, 4]); | |
}); | |
it(`3X3 Staggered With One on End | |
<->|o | |
o|<-> | |
x o x | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: [2 / 3, undefined, undefined, 2 / 3, undefined], | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 2]); | |
}); | |
it(`3X3 Staggered With One on End | |
o|o|o|o | |
o|o|o|o | |
x|o|o|x | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: [2 / 3, undefined, undefined, 2 / 3, undefined], | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 2]); | |
}); | |
}); | |
it(`Would I be able to flag dummy elements to not do | |
o|o|o|o|o | |
o|o|o|o|o | |
<->|o|<-> | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
// prettier-ignore | |
elements: [ | |
1/5, 1/5, 1/5, 1/5, 1/5, | |
1/5, 1/5, 1/5, 1/5, 1/5, | |
2/5, 1/5, 2/5 | |
], | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 2, 3, 5, 6, 7, 8, 10, 11]); | |
}); | |
it(`Would I be able to flag dummy elements to not do | |
o|o|o|o|o | |
o|o|o|o|o | |
<->|o|<-> | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
// prettier-ignore | |
elements: [ | |
1/5, 1/5, 1/5, 1/5, 1/5, | |
1/5, 1/5, 1/5, 1/5, 1/5, | |
2/5, 1/5, 2/5 | |
], | |
elementAlignment: "CENTER", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 2, 3, 5, 6, 7, 8, 10, 11]); | |
}); | |
describe("left", () => { | |
it(`3X3 staggered with one on end | |
<->|o | |
o|<-> | |
o | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: [2 / 3, undefined, undefined, 2 / 3, undefined], | |
elementAlignment: "LEFT", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 2]); | |
}); | |
it(`Matching Uneven Rows | |
o|<-> | |
o|<-> | |
o| | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: [1 / 3, 2 / 3, 1 / 3, 2 / 3, 1 / 3], | |
elementAlignment: "LEFT", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 2, 4]); | |
}); | |
it(`one on end | |
o|o|o | |
o|o|o | |
o| | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: range(0, 7), | |
elementAlignment: "LEFT", | |
getWidthAsDecimalFromElement: () => undefined, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 3, 4, 6]); | |
}); | |
it(`4 -> 3 | |
o|o|o|o | |
o|o|o| | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: range(0, 7), | |
elementAlignment: "LEFT", | |
getWidthAsDecimalFromElement: () => undefined, | |
defaultWidth: 1 / 4, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 2, 4, 5, 6]); | |
}); | |
it(`4X 1/4 -> 2 -> 3/4 | |
o|o|o|o | |
o|o| | |
<----> | |
<---> | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: [1 / 4, 1 / 4, 1 / 4, 1 / 4, 1 / 4, 1 / 4, 4 / 4, 3 / 4], | |
elementAlignment: "LEFT", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 4, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 2, 4, 5]); | |
}); | |
it(` | |
o|o|o | |
o|o|o | |
o|o|o | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
elements: range(0, 9), | |
elementAlignment: "LEFT", | |
getWidthAsDecimalFromElement: () => undefined, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 3, 4, 6, 7]); | |
}); | |
it(` | |
<->|<->|<->|<->|<-> | |
<--->|<->|<->|<-> | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
// prettier-ignore | |
elements: [ | |
1/5, 1/5, 1/5, 1/5, 1/5, | |
1/4 ,1/5, 1/5, 1/5 | |
], | |
elementAlignment: "LEFT", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 2, 3, 5, 6, 7]); | |
}); | |
it(` | |
<->|<->|<->|<->|<-> | |
<->|<->|<->| | |
`, () => { | |
expect( | |
getCalloutBorderIndeces({ | |
// prettier-ignore | |
elements: [ | |
1/5, 1/5, 1/5, 1/5, 1/5, | |
1/5, 1/5, 1/5, | |
], | |
elementAlignment: "LEFT", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 3, | |
}).rightBorderIndices, | |
).toEqual([0, 1, 2, 3, 5, 6, 7]); | |
}); | |
}); | |
describe("RIGHT", () => { | |
it(` | |
o|o|o | |
o|o|o | |
o|o|o | |
`, () => { | |
const result = getCalloutBorderIndeces({ | |
elements: range(0, 9), | |
elementAlignment: "RIGHT", | |
getWidthAsDecimalFromElement: () => undefined, | |
defaultWidth: 1 / 3, | |
}); | |
expect(result.rightBorderIndices).toEqual([0, 1, 3, 4, 6, 7]); | |
expect(result.leftBorderIndices).toEqual([]); | |
}); | |
it(` | |
o|o|o|o | |
<->|<-> | |
o|o|o|o | |
`, () => { | |
const result = getCalloutBorderIndeces({ | |
elements: [ | |
1 / 4, | |
1 / 4, | |
1 / 4, | |
1 / 4, | |
1 / 2, | |
1 / 2, | |
1 / 4, | |
1 / 4, | |
1 / 4, | |
1 / 4, | |
], | |
elementAlignment: "RIGHT", | |
getWidthAsDecimalFromElement: (i) => i, | |
defaultWidth: 1 / 4, | |
}); | |
expect(result.rightBorderIndices).toEqual([0, 1, 2, 4, 6, 7, 8]); | |
}); | |
it(` | |
o|o|o | |
o|o|o | |
o|o | |
`, () => { | |
const result = getCalloutBorderIndeces({ | |
elements: range(0, 8), | |
elementAlignment: "RIGHT", | |
getWidthAsDecimalFromElement: () => undefined, | |
defaultWidth: 1 / 3, | |
}); | |
expect(result.rightBorderIndices).toEqual([0, 1, 3, 4, 6]); | |
expect(result.leftBorderIndices).toEqual([6]); | |
}); | |
}); | |
it(` | |
o|o|o|o|o | |
o|o|o | |
`, () => { | |
const result = getCalloutBorderIndeces({ | |
elements: range(0, 8), | |
elementAlignment: "RIGHT", | |
getWidthAsDecimalFromElement: () => undefined, | |
defaultWidth: 1 / 5, | |
}); | |
expect(result.rightBorderIndices).toEqual([0, 1, 2, 3, 5, 6]); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { MultiItemAlignment } from "@prisma/client"; | |
import { sum } from "remeda"; | |
import { match } from "ts-pattern"; | |
import { buildMatrix } from "./build-matrix"; | |
import { | |
getCenterAlignedIntersections, | |
getLeftAlignedIntersections, | |
} from "~/utils/get-intersecttions"; | |
import { Fractions } from "~/utils/fraction.utils"; | |
const areTwoRowsConsistent = (a: number[], b: number[]) => { | |
for (let i = 0; i < Math.max(a.length, b.length); i++) { | |
if (a[i] !== b[i]) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
type CReturnType = { | |
rightBorderIndices: number[]; | |
leftBorderIndices: number[]; | |
}; | |
/** | |
Determine the indexes of border-right separators | |
assuming that ghost elements are already added to the elements | |
*/ | |
export const getCalloutBorderIndeces = <T>({ | |
elements, | |
defaultWidth, | |
elementAlignment, | |
getWidthAsDecimalFromElement, | |
}: { | |
elements: T[]; | |
elementAlignment: Exclude<MultiItemAlignment, "DEFAULT">; | |
defaultWidth: number; | |
getWidthAsDecimalFromElement: (input: T) => number | undefined; | |
}): CReturnType => { | |
return match(elementAlignment) | |
.with("CENTER", () => { | |
const matrix = buildMatrix({ | |
elements, | |
getWidthAsDecimalFromElement, | |
defaultWidth, | |
}); | |
let rightBorderIndices: number[] = []; | |
let indexCount = 0; | |
let isStaggered = false; | |
for (let i = 0; i < matrix.length; i++) { | |
const row = matrix[i]!; | |
const prevRowToCompare = matrix[i - 1] ?? row; | |
// const isLastRow = i === matrix.length - 1; | |
const isRowFull = sum(row) === 1; | |
for (let j = 0; j < row.length; j++) { | |
const isLastInRow = j === row.length - 1; | |
const isOnlyInRow = row.length === 1; | |
if (isOnlyInRow) { | |
// Do nothing | |
} else if (!isLastInRow) { | |
rightBorderIndices.push(indexCount); | |
} else if (!isRowFull) { | |
// if (isLastInRow && !isStaggered) { | |
if (isLastInRow && !isStaggered) { | |
const lastRowIntersections = getCenterAlignedIntersections( | |
row.map(Fractions.fraq), | |
); | |
const secondLastRowIntersections = getCenterAlignedIntersections( | |
(matrix.at(i - 1) ?? []).map(Fractions.fraq), | |
); | |
const doEndsMatch = [ | |
lastRowIntersections.at(0), | |
lastRowIntersections.at(1), | |
].every((position) => { | |
return secondLastRowIntersections.some((intersection) => | |
intersection.eq(position ?? -1), | |
); | |
}); | |
console.log({ | |
doEndsMatch, | |
row, | |
lastRowIntersections, | |
secondLastRowIntersections, | |
}); | |
if (doEndsMatch) rightBorderIndices.push(indexCount); | |
} | |
} else if (isRowFull) { | |
if (j < row.length - 1) { | |
rightBorderIndices.push(indexCount); | |
} | |
} | |
indexCount++; | |
} | |
if (!areTwoRowsConsistent(row, prevRowToCompare)) { | |
isStaggered = true; | |
} | |
} | |
return { | |
rightBorderIndices: rightBorderIndices, | |
leftBorderIndices: [], | |
} satisfies CReturnType; | |
}) | |
.with("LEFT", () => { | |
const matrix = buildMatrix({ | |
elements, | |
getWidthAsDecimalFromElement, | |
defaultWidth, | |
}); | |
let rightIndices: number[] = []; | |
let indexCount = 0; | |
let isStaggered = false; | |
for (let i = 0; i < matrix.length; i++) { | |
const row = matrix[i]!; | |
const prevRowToCompare = matrix[i - 1] ?? row; | |
const isRowFull = sum(row) === 1; | |
for (let j = 0; j < row.length; j++) { | |
const isLastInRow = j === row.length - 1; | |
if (!isLastInRow) { | |
rightIndices.push(indexCount); | |
} else if (!isRowFull) { | |
console.log({ | |
row, | |
}); | |
const secondLastRowIntersections = getLeftAlignedIntersections( | |
(matrix.at(i - 1) ?? []).map(Fractions.fraq), | |
); | |
const lastRowIntersections = getLeftAlignedIntersections( | |
row.map(Fractions.fraq), | |
); | |
const shouldHaveRightBorderOnLast = secondLastRowIntersections.some( | |
(intersection) => lastRowIntersections.at(-1)?.eq(intersection), | |
); | |
if (isLastInRow && !isStaggered && shouldHaveRightBorderOnLast) { | |
rightIndices.push(indexCount); | |
} | |
} else if (isRowFull) { | |
if (j < row.length - 1) { | |
rightIndices.push(indexCount); | |
} | |
} | |
indexCount++; | |
} | |
if (!areTwoRowsConsistent(row, prevRowToCompare)) { | |
isStaggered = true; | |
} | |
} | |
return { | |
leftBorderIndices: [], | |
rightBorderIndices: rightIndices, | |
} satisfies CReturnType; | |
}) | |
.with("RIGHT", () => { | |
const matrix = buildMatrix({ | |
elements, | |
getWidthAsDecimalFromElement, | |
defaultWidth, | |
}); | |
let rightBorderIndices: number[] = []; | |
let leftBorderIndices: number[] = []; | |
let indexCount = 0; | |
for (let i = 0; i < matrix.length; i++) { | |
const row = matrix[i]!; | |
const isLastRow = i === matrix.length - 1; | |
const isRowFull = sum(row) === 1; | |
for (let j = 0; j < row.length; j++) { | |
const isLastInRow = j === row.length - 1; | |
if (j === 0 && isLastRow && !isRowFull) { | |
leftBorderIndices.push(indexCount); | |
} | |
if (!isLastInRow) { | |
rightBorderIndices.push(indexCount); | |
} else if (isRowFull) { | |
if (j < row.length - 1) { | |
rightBorderIndices.push(indexCount); | |
} | |
} | |
indexCount++; | |
} | |
} | |
return { | |
rightBorderIndices, | |
leftBorderIndices: leftBorderIndices, | |
} satisfies CReturnType; | |
}) | |
.exhaustive(); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { Fraction } from "fractions-math"; | |
import { reverse } from "remeda"; | |
import { Fractions } from "./fraction.utils"; | |
const { fraq } = Fractions; | |
/** | |
* Get's the intersections of a center aligned row of fractions | |
```ts | |
getCenterAlignedIntersections([1/4, 1/4, 1/4]) | |
// => [1/8, 3/8, 5/8, 7/8] | |
``` | |
Why? | |
```txt | |
|--------------------------- | |
| key | | |
| | | |
| <----> = 1/4 | | |
| || = wall | | |
| |-*.| = distance | | |
|__________________________| | |
``` | |
====EXAMPLE==== | |
```txt | |
Input: [1/4, 1/4, 1/4] | |
|| <----><----><----> || | |
|--| | |
--------| | |
--------------| | |
--------------------| | |
1/8, 3/8 , 5/8 7/8 | |
``` | |
*/ | |
export const getCenterAlignedIntersections = (input: Fraction[]) => { | |
let totalWidthOfParts = Fractions.sumFrac(input); | |
if (totalWidthOfParts.eq(1)) { | |
let totalWidth = fraq(0); | |
let intersections: Fraction[] = []; | |
for (let el of input.slice(0, input.length - 1)) { | |
totalWidth = totalWidth.add(el); | |
intersections.push(totalWidth); | |
} | |
return intersections; | |
} else { | |
const edgeSize = fraq(1).sub(totalWidthOfParts).div(2); | |
let totalWidth = edgeSize; | |
let intersections: Fraction[] = [totalWidth]; | |
for (let el of input) { | |
totalWidth = totalWidth.add(el); | |
intersections.push(totalWidth); | |
} | |
return intersections; | |
} | |
}; | |
/** | |
* Get's the intersections of a right aligned aligned row of fractions | |
```ts | |
getRightAlignedIntersections([1/4, 1/4, 1/4]) | |
// => [1/4, 2/4, 3/4] | |
``` | |
Why? | |
```txt | |
|--------------------------- | |
| key | | |
| | | |
| <----> = 1/4 | | |
| || = wall | | |
| |-*.| = distance | | |
|__________________________| | |
``` | |
====EXAMPLE==== | |
```txt | |
Input: [1/4, 1/4, 1/4] | |
|| <----><----><---->|| | |
|---| | |
----------| | |
----------------| | |
1/4, 2/4, 3/4 | |
``` | |
*/ | |
export const getAllIntersectionsRightAligned = (input: Fraction[]) => { | |
let totalWidth = Fractions.fraq(0); | |
let intersections: Fraction[] = []; | |
let one = Fractions.fraq(1); | |
for (let block of reverse(input)) { | |
totalWidth = totalWidth.add(block); | |
if (totalWidth.eq(1)) continue; | |
intersections.unshift(one.sub(totalWidth)); | |
} | |
return intersections; | |
}; | |
/** | |
* Get's the intersections of a left aligned aligned row of fractions | |
```ts | |
getLeftAlignedIntersections([1/4, 1/4, 1/4]) | |
// => [1/4, 2/4, 3/4] | |
``` | |
Why? | |
```txt | |
|--------------------------- | |
| key | | |
| | | |
| <----> = 1/4 | | |
| || = wall | | |
| |-*.| = distance | | |
|__________________________| | |
``` | |
====EXAMPLE==== | |
```txt | |
Input: [1/4, 1/4, 1/4] | |
||<----><----><----> || | |
|-----| | |
------------| | |
------------------| | |
1/4, 2/4, 3/4 | |
``` | |
*/ | |
export const getLeftAlignedIntersections = (input: Fraction[]) => { | |
let totalWidth = Fractions.fraq(0); | |
let intersections: Fraction[] = []; | |
for (let block of input) { | |
totalWidth = totalWidth.add(block); | |
if (totalWidth.eq(1)) continue; | |
intersections.push(totalWidth); | |
} | |
return intersections; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment