|
|
@@ -24,9 +24,20 @@ interface LocalColumnAisleRule extends RowScopedRule {
|
|
|
|
|
|
interface LocalColumnShiftRule extends RowScopedRule {
|
|
|
startColumn: number
|
|
|
+ endColumn?: number
|
|
|
shiftCols: number
|
|
|
}
|
|
|
|
|
|
+interface ManualColumnOffsetRule extends RowScopedRule {
|
|
|
+ startColumn: number
|
|
|
+ endColumn?: number
|
|
|
+ offsetCols: number
|
|
|
+}
|
|
|
+
|
|
|
+interface ColumnCompactionRule extends RowScopedRule {
|
|
|
+ startColumn: number
|
|
|
+}
|
|
|
+
|
|
|
interface GlobalColumnAisleRule {
|
|
|
breakpoint: number
|
|
|
excludeRows?: readonly number[]
|
|
|
@@ -38,6 +49,8 @@ interface WarehouseLayoutRuleSet {
|
|
|
globalColumnAisles: readonly GlobalColumnAisleRule[]
|
|
|
localColumnAisles: readonly LocalColumnAisleRule[]
|
|
|
localColumnShifts: readonly LocalColumnShiftRule[]
|
|
|
+ manualColumnOffsets: readonly ManualColumnOffsetRule[]
|
|
|
+ columnCompactions: readonly ColumnCompactionRule[]
|
|
|
}
|
|
|
|
|
|
const scopedRows = <T extends object>(rows: readonly number[], rule: T): T & Pick<RowScopedRule, 'rows'> => ({
|
|
|
@@ -114,6 +127,10 @@ const FIRST_FLOOR_LOCAL_COLUMN_SHIFTS = [
|
|
|
startColumn: 0,
|
|
|
shiftCols: 1
|
|
|
}),
|
|
|
+ scopedRows([8, 11], {
|
|
|
+ startColumn: 8,
|
|
|
+ shiftCols: 1
|
|
|
+ }),
|
|
|
scopedRows([6, 13], {
|
|
|
startColumn: 5,
|
|
|
shiftCols: 1
|
|
|
@@ -132,11 +149,32 @@ const FIRST_FLOOR_LOCAL_COLUMN_SHIFTS = [
|
|
|
})
|
|
|
] as const
|
|
|
|
|
|
+const FIRST_FLOOR_MANUAL_COLUMN_OFFSETS = [
|
|
|
+ scopedRows([8, 11], {
|
|
|
+ startColumn: 13,
|
|
|
+ endColumn: 17,
|
|
|
+ offsetCols: -1
|
|
|
+ }),
|
|
|
+ scopedRows([8, 11], {
|
|
|
+ startColumn: 18,
|
|
|
+ endColumn: 18,
|
|
|
+ offsetCols: -1
|
|
|
+ })
|
|
|
+] as const
|
|
|
+
|
|
|
+const FIRST_FLOOR_COLUMN_COMPACTIONS = [
|
|
|
+ scopedRows([9, 10], {
|
|
|
+ startColumn: 11
|
|
|
+ })
|
|
|
+] as const
|
|
|
+
|
|
|
const FIRST_FLOOR_RULE_SET: WarehouseLayoutRuleSet = {
|
|
|
rowAisleBreakpoints: FIRST_FLOOR_ROW_AISLE_BREAKPOINTS,
|
|
|
globalColumnAisles: FIRST_FLOOR_GLOBAL_COLUMN_AISLES,
|
|
|
localColumnAisles: FIRST_FLOOR_LOCAL_COLUMN_AISLES,
|
|
|
- localColumnShifts: FIRST_FLOOR_LOCAL_COLUMN_SHIFTS
|
|
|
+ localColumnShifts: FIRST_FLOOR_LOCAL_COLUMN_SHIFTS,
|
|
|
+ manualColumnOffsets: FIRST_FLOOR_MANUAL_COLUMN_OFFSETS,
|
|
|
+ columnCompactions: FIRST_FLOOR_COLUMN_COMPACTIONS
|
|
|
}
|
|
|
|
|
|
const RULE_SETS_BY_LEVEL: Readonly<Record<number, WarehouseLayoutRuleSet>> = {
|
|
|
@@ -193,21 +231,39 @@ const sumLocalColumnShiftOffsets = (
|
|
|
rules: readonly LocalColumnShiftRule[]
|
|
|
) =>
|
|
|
rules.reduce((total, rule) => {
|
|
|
- if (matchesRowScope(parsedLocation.y, rule) && parsedLocation.x >= rule.startColumn) {
|
|
|
+ const matchedColumn = parsedLocation.x >= rule.startColumn
|
|
|
+ && (rule.endColumn === undefined || parsedLocation.x <= rule.endColumn)
|
|
|
+
|
|
|
+ if (matchesRowScope(parsedLocation.y, rule) && matchedColumn) {
|
|
|
return total + rule.shiftCols
|
|
|
}
|
|
|
|
|
|
return total
|
|
|
}, 0)
|
|
|
|
|
|
-const applyRuleSet = (
|
|
|
- currentPosition: WarehouseLayoutPosition,
|
|
|
+const sumManualColumnOffsets = (
|
|
|
+ parsedLocation: WarehouseLayoutParsedLocation,
|
|
|
+ rules: readonly ManualColumnOffsetRule[]
|
|
|
+) =>
|
|
|
+ rules.reduce((total, rule) => {
|
|
|
+ const matchedColumn = parsedLocation.x >= rule.startColumn
|
|
|
+ && (rule.endColumn === undefined || parsedLocation.x <= rule.endColumn)
|
|
|
+
|
|
|
+ if (matchesRowScope(parsedLocation.y, rule) && matchedColumn) {
|
|
|
+ return total + rule.offsetCols
|
|
|
+ }
|
|
|
+
|
|
|
+ return total
|
|
|
+ }, 0)
|
|
|
+
|
|
|
+const getBaseGridColOffset = (
|
|
|
parsedLocation: WarehouseLayoutParsedLocation,
|
|
|
ruleSet: WarehouseLayoutRuleSet
|
|
|
) => {
|
|
|
const columnShiftCount = sumLocalColumnShiftOffsets(parsedLocation, ruleSet.localColumnShifts)
|
|
|
const effectiveColumn = parsedLocation.x + columnShiftCount
|
|
|
- const gridColOffset =
|
|
|
+
|
|
|
+ return (
|
|
|
columnShiftCount +
|
|
|
sumGlobalColumnAisleOffsets(
|
|
|
parsedLocation.y,
|
|
|
@@ -215,6 +271,41 @@ const applyRuleSet = (
|
|
|
ruleSet.globalColumnAisles
|
|
|
) +
|
|
|
sumLocalColumnAisleOffsets(parsedLocation.y, effectiveColumn, ruleSet.localColumnAisles)
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+const sumColumnCompactionOffsets = (
|
|
|
+ parsedLocation: WarehouseLayoutParsedLocation,
|
|
|
+ ruleSet: WarehouseLayoutRuleSet
|
|
|
+) =>
|
|
|
+ ruleSet.columnCompactions.reduce((total, rule) => {
|
|
|
+ if (!matchesRowScope(parsedLocation.y, rule) || parsedLocation.x < rule.startColumn) {
|
|
|
+ return total
|
|
|
+ }
|
|
|
+
|
|
|
+ if (parsedLocation.x === rule.startColumn) {
|
|
|
+ return total - 1
|
|
|
+ }
|
|
|
+
|
|
|
+ const previousLocation: WarehouseLayoutParsedLocation = {
|
|
|
+ ...parsedLocation,
|
|
|
+ x: parsedLocation.x - 1
|
|
|
+ }
|
|
|
+ const previousGridCol = previousLocation.x + getBaseGridColOffset(previousLocation, ruleSet)
|
|
|
+ const currentGridCol = parsedLocation.x + getBaseGridColOffset(parsedLocation, ruleSet)
|
|
|
+
|
|
|
+ return total + (previousGridCol - currentGridCol)
|
|
|
+ }, 0)
|
|
|
+
|
|
|
+const applyRuleSet = (
|
|
|
+ currentPosition: WarehouseLayoutPosition,
|
|
|
+ parsedLocation: WarehouseLayoutParsedLocation,
|
|
|
+ ruleSet: WarehouseLayoutRuleSet
|
|
|
+) => {
|
|
|
+ const gridColOffset =
|
|
|
+ getBaseGridColOffset(parsedLocation, ruleSet) +
|
|
|
+ sumManualColumnOffsets(parsedLocation, ruleSet.manualColumnOffsets) +
|
|
|
+ sumColumnCompactionOffsets(parsedLocation, ruleSet)
|
|
|
const gridRowOffset = sumRowAisleOffsets(parsedLocation.y, ruleSet.rowAisleBreakpoints)
|
|
|
|
|
|
return {
|