@jetta/blocks-allocator 0.2.0 → 0.2.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jetta/blocks-allocator",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-0",
4
4
  "description": "Blocks wall allocation library",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -46,7 +46,7 @@
46
46
  "@jetta/lp-framework": "2.1.0-6",
47
47
  "@jetta/number-compare": "^3.0.2-4",
48
48
  "@jetta/stacking-constraints": "^1.1.0",
49
- "@jetta/tie-ratio-block-creator-core": "1.2.2-3",
49
+ "@jetta/tie-ratio-block-creator-core": "1.2.2-5",
50
50
  "@jetta/z-intersected-block-creator": "^0.0.1-42",
51
51
  "@jettacargo/single-item-block-creator-core": "2.0.1-0",
52
52
  "@jettacargo/spiral-block-creator-core": "2.1.2",
@@ -0,0 +1,28 @@
1
+ const Block_Filter_Interface = require('../../space_and_block_chooser/blocks_filters/Block_Filter_Interface')
2
+ const Cargo_Profile = require('../../models/Cargo_Profile')
3
+ const filter_out_mixed_height_tie_ratio = require('./filter_out_mixed_height_tie_ratio')
4
+ const has_stocked_same_height_tie_ratio = require('./has_stocked_same_height_tie_ratio')
5
+
6
+ /**
7
+ * Post-selection filter: prefer same-height tie-ratio over mixed-height when stock allows.
8
+ */
9
+ module.exports = class Same_Height_Tie_Ratio_Filter extends Block_Filter_Interface
10
+ {
11
+ static run(filter_data)
12
+ {
13
+ if (!Cargo_Profile.prefer_same_height_tie_ratio_slots())
14
+ {
15
+ return filter_data.block_list
16
+ }
17
+
18
+ if (!has_stocked_same_height_tie_ratio(
19
+ filter_data.block_list,
20
+ filter_data.item_list || []
21
+ ))
22
+ {
23
+ return filter_data.block_list
24
+ }
25
+
26
+ return filter_out_mixed_height_tie_ratio(filter_data.block_list)
27
+ }
28
+ }
@@ -0,0 +1,20 @@
1
+ const is_tie_ratio_block = require('./is_tie_ratio_block')
2
+
3
+ /**
4
+ * Drops mixed-height tie-ratio blocks; keeps same-height tie-ratio and non-tie-ratio.
5
+ * @param {Array<object>} block_list
6
+ * @returns {Array<object>}
7
+ */
8
+ function filter_out_mixed_height_tie_ratio(block_list)
9
+ {
10
+ return block_list.filter((block) =>
11
+ {
12
+ if (!is_tie_ratio_block(block))
13
+ {
14
+ return true
15
+ }
16
+ return block.is_slots_of_same_measure()
17
+ })
18
+ }
19
+
20
+ module.exports = filter_out_mixed_height_tie_ratio
@@ -0,0 +1,40 @@
1
+ const is_tie_ratio_block = require('./is_tie_ratio_block')
2
+ const max_tie_ratio_slot_count = require('./max_tie_ratio_slot_count')
3
+ const tie_ratio_block_has_shape_stock = require('./tie_ratio_block_has_shape_stock')
4
+
5
+ /**
6
+ * True when a same-height tie-ratio at the max slot count has enough shape stock.
7
+ * Smaller same-height partials must not hide larger mixed walls.
8
+ * @param {Array<object>} block_list
9
+ * @param {Array<object>} item_list
10
+ * @returns {boolean}
11
+ */
12
+ function has_stocked_same_height_tie_ratio(block_list, item_list)
13
+ {
14
+ const target_slot_count = max_tie_ratio_slot_count(block_list)
15
+
16
+ if (target_slot_count === 0)
17
+ {
18
+ return false
19
+ }
20
+
21
+ for (const block of block_list)
22
+ {
23
+ if (!is_tie_ratio_block(block) || !block.is_slots_of_same_measure())
24
+ {
25
+ continue
26
+ }
27
+ if (block.get_slot_list().length !== target_slot_count)
28
+ {
29
+ continue
30
+ }
31
+ if (tie_ratio_block_has_shape_stock(block, item_list))
32
+ {
33
+ return true
34
+ }
35
+ }
36
+
37
+ return false
38
+ }
39
+
40
+ module.exports = has_stocked_same_height_tie_ratio
@@ -0,0 +1,12 @@
1
+ /**
2
+ * True when the block reports itself as a tie-ratio block.
3
+ * Probe objects without the method are not tie-ratio blocks.
4
+ * @param {object} block
5
+ * @returns {boolean}
6
+ */
7
+ function is_tie_ratio_block(block)
8
+ {
9
+ return typeof block.is_tie_ratio_block === 'function' && block.is_tie_ratio_block()
10
+ }
11
+
12
+ module.exports = is_tie_ratio_block
@@ -0,0 +1,24 @@
1
+ const is_tie_ratio_block = require('./is_tie_ratio_block')
2
+
3
+ /**
4
+ * Returns the largest slot count among tie-ratio blocks in the list.
5
+ * @param {Array<object>} block_list
6
+ * @returns {number}
7
+ */
8
+ function max_tie_ratio_slot_count(block_list)
9
+ {
10
+ let maximum = 0
11
+
12
+ for (const block of block_list)
13
+ {
14
+ if (!is_tie_ratio_block(block))
15
+ {
16
+ continue
17
+ }
18
+ maximum = Math.max(maximum, block.get_slot_list().length)
19
+ }
20
+
21
+ return maximum
22
+ }
23
+
24
+ module.exports = max_tie_ratio_slot_count
@@ -0,0 +1,113 @@
1
+ const { cube_map_function } = require('../../Blocks_Preparation/Cube_Map_Function')
2
+
3
+ /**
4
+ * Builds required shape amounts from a block's slots.
5
+ * @param {object} block
6
+ * @returns {Map<string, number>}
7
+ */
8
+ function build_required_shapes(block)
9
+ {
10
+ const required_shapes = new Map()
11
+ for (const slot of block.get_slot_list())
12
+ {
13
+ const shape_hash = cube_map_function(slot)
14
+ required_shapes.set(shape_hash, (required_shapes.get(shape_hash) || 0) + 1)
15
+ }
16
+ return required_shapes
17
+ }
18
+
19
+ /**
20
+ * Builds available shape amounts (amount counted once per SKU per unique rotation hash).
21
+ * @param {Array<object>} item_list
22
+ * @returns {Map<string, number>}
23
+ */
24
+ function build_available_shapes(item_list)
25
+ {
26
+ const available_shapes = new Map()
27
+ for (const item of item_list)
28
+ {
29
+ const unique_shape_hashes = new Set()
30
+ for (const rotated_item of item.get_all_rotated_options())
31
+ {
32
+ unique_shape_hashes.add(cube_map_function(rotated_item))
33
+ }
34
+ const item_amount = item.get_amount()
35
+ for (const shape_hash of unique_shape_hashes)
36
+ {
37
+ available_shapes.set(
38
+ shape_hash,
39
+ (available_shapes.get(shape_hash) || 0) + item_amount
40
+ )
41
+ }
42
+ }
43
+ return available_shapes
44
+ }
45
+
46
+ /**
47
+ * Counts units that can form any required shape (once per SKU).
48
+ * @param {Map<string, number>} required_shapes
49
+ * @param {Array<object>} item_list
50
+ * @returns {number}
51
+ */
52
+ function count_capable_item_amount(required_shapes, item_list)
53
+ {
54
+ let capable_amount = 0
55
+
56
+ for (const item of item_list)
57
+ {
58
+ const amount = item.get_amount()
59
+ if (amount <= 0)
60
+ {
61
+ continue
62
+ }
63
+ const can_form = item.get_all_rotated_options().some((rotated_item) =>
64
+ required_shapes.has(cube_map_function(rotated_item)))
65
+ if (can_form)
66
+ {
67
+ capable_amount += amount
68
+ }
69
+ }
70
+
71
+ return capable_amount
72
+ }
73
+
74
+ /**
75
+ * True when remaining item_list stock can fill the block.
76
+ * Combines total capable units with per-shape availability so rotation
77
+ * double-counting cannot keep a stale same-height five-slot alive.
78
+ * @param {object} block
79
+ * @param {Array<object>} item_list
80
+ * @returns {boolean}
81
+ */
82
+ function tie_ratio_block_has_shape_stock(block, item_list)
83
+ {
84
+ const required_shapes = build_required_shapes(block)
85
+ if (required_shapes.size === 0)
86
+ {
87
+ return false
88
+ }
89
+
90
+ let total_required = 0
91
+ for (const required_amount of required_shapes.values())
92
+ {
93
+ total_required += required_amount
94
+ }
95
+
96
+ if (count_capable_item_amount(required_shapes, item_list) < total_required)
97
+ {
98
+ return false
99
+ }
100
+
101
+ const available_shapes = build_available_shapes(item_list)
102
+ for (const [shape_hash, required_amount] of required_shapes)
103
+ {
104
+ if ((available_shapes.get(shape_hash) || 0) < required_amount)
105
+ {
106
+ return false
107
+ }
108
+ }
109
+
110
+ return true
111
+ }
112
+
113
+ module.exports = tie_ratio_block_has_shape_stock
@@ -362,6 +362,21 @@ class Cargo_Profile
362
362
  return str_to_bool(this.#instance[key], false)
363
363
  }
364
364
 
365
+ /**
366
+ * Prefer same-height tie-ratio blocks over mixed-height when both fit.
367
+ * Default true when omitted.
368
+ * @returns {boolean}
369
+ */
370
+ static prefer_same_height_tie_ratio_slots()
371
+ {
372
+ if (Cargo_Profile.#instance === null)
373
+ {
374
+ return true
375
+ }
376
+ const key = 'allocation.blocks.prefer_same_height_tie_ratio_slots'
377
+ return str_to_bool(this.#instance[key], true)
378
+ }
379
+
365
380
  static tie_ratio_allocate_remainder_as_partial_blocks()
366
381
  {
367
382
  if (Cargo_Profile.#instance === null)
@@ -1,9 +1,11 @@
1
1
  const Blocks_Bigger_Than_Space_Filter = require('./Blocks_Bigger_Than_Space_Filter')
2
2
  const Tie_Ratio_Orientation_Filter = require('../../../Allocation_Optimization/tie_ratio/Tie_Ratio_Orientation_Filter')
3
3
  const Tie_Ratio_Vertical_Stack_Filter = require('../../../Allocation_Optimization/tie_ratio/Tie_Ratio_Vertical_Stack_Filter')
4
+ const Same_Height_Tie_Ratio_Filter = require('../../../Allocation_Optimization/tie_ratio/Same_Height_Tie_Ratio_Filter')
4
5
 
5
6
  module.exports = [
6
7
  Blocks_Bigger_Than_Space_Filter,
7
8
  Tie_Ratio_Orientation_Filter,
8
- Tie_Ratio_Vertical_Stack_Filter
9
- ]
9
+ Tie_Ratio_Vertical_Stack_Filter,
10
+ Same_Height_Tie_Ratio_Filter
11
+ ]