@@ -11,65 +11,124 @@ def initialize(order_qty, order_item)
11
11
end
12
12
13
13
def optimal ( product )
14
+ puts "Quantity: #{ order_qty } "
14
15
pack_qtys = [ ]
15
16
@order_item . packs ( product ) . each { |p | pack_qtys << [ p . qty , p . price ] }
17
+ puts "Packs: #{ pack_qtys } "
16
18
17
- whole_packs = whole_packs ( pack_qtys , [ ] , order_qty )
19
+ # Get Exact matches
20
+ exact_matches = [ ]
21
+ pack_qtys . sort { |a , b | b <=> a } . each do |p , v |
22
+ next unless ( order_qty / p ) * p == order_qty
23
+ exact_matches << [ order_qty / p , p , v ]
24
+ end
25
+ # puts exact_matches
18
26
19
- return whole_packs [ 0 ] if whole_packs [ 1 ] . zero?
27
+ # Check for the optimim price
28
+ price_check = [ ]
29
+ exact_matches . each do |x , y , z |
30
+ val = ( x * z )
20
31
21
- total_packs = left_over_items ( pack_qtys , whole_packs [ 0 ] , whole_packs [ 1 ] )
32
+ price_check << [ x , y , z , val ]
33
+ end
34
+ # puts price_check
22
35
23
- total_packs [ 0 ]
24
- end
36
+ numbers = price_check . select { |x | x [ 3 ] } . map
25
37
26
- def present_line ( packs )
27
- sub_total = [ ]
28
- sub_item = [ ]
29
- packs . each do |k , v , i |
30
- sub_total << k * i
31
- sub_item << "#{ k } x #{ v } packs @ #{ i } "
38
+ # Get Part matches
39
+ partial_matches = [ ]
40
+ pack_qtys . sort { |a , b | b <=> a } . each do |p , v |
41
+ partial_matches << [ order_qty / p , p , v ]
42
+ end
43
+ puts "partial: #{ partial_matches } "
44
+
45
+ # Top up part matches
46
+ exact_partial = [ ]
47
+ partial_matches . each do |x , y , z |
48
+ val = order_qty - ( x * y )
49
+ puts "VAL: #{ val } "
50
+ pack_qtys . detect do |a |
51
+ # To be optimised: a.include?(val) does not cooperate with Money
52
+ if a [ 0 ] == val || a [ 0 ] * 3 == val
53
+ exact_partial << [ x , y , z ]
54
+ exact_partial << [ val / a [ 0 ] , a [ 0 ] , a [ 1 ] ]
55
+ end
56
+ end
32
57
end
58
+ puts "exact partial: #{ exact_partial } "
33
59
34
- @line_total = sub_total . inject ( 0 ) { |sum , x | sum + x }
60
+ # Check for the optimim partial price
61
+ partial_price_check = [ ]
62
+ exact_partial . each do |x , y , z |
63
+ val = ( x * z )
35
64
36
- sub_item . each { |s | s }
37
- end
65
+ partial_price_check << [ x , y , z , val ]
66
+ end
67
+ # puts partial_price_check
38
68
39
- def presenter_line_total
40
- @line_total
41
- end
69
+ partial_numbers = partial_price_check . select { |x | x [ 3 ] } . map
42
70
43
- private
71
+ partial_price_array = [ ]
72
+ partial_numbers . each do |f |
73
+ partial_price_array << f
74
+ end
75
+ # puts partial_price_array
44
76
45
- def whole_packs ( pack_qtys , packs , left_over_qty )
46
- pack_qtys . sort { |a , b | b <=> a } . each do |p , v |
47
- volume = left_over_qty . to_f / p
77
+ puts "Exact Match: #{ exact_matches } "
78
+ # Array for best price line: 1x 9pk @16 = $16
79
+ puts "Best Exact Price: #{ numbers . min } "
80
+ puts "Partial Match: #{ exact_partial } "
81
+ puts "Best Partial Price: #{ partial_price_array } "
48
82
49
- next unless volume >= 1
83
+ return calculate_best ( numbers , partial_price_array ) unless price_check . empty?
50
84
51
- left_over_qty -= volume . to_int * p
85
+ calculate_best ( numbers . min , partial_price_array )
86
+ end
52
87
53
- packs << [ volume . to_int , p , v ]
88
+ def calculate_best ( exact , partial )
89
+ if exact . nil?
90
+ puts "\n This is it #{ partial } "
91
+ return partial
54
92
end
55
93
56
- [ packs , left_over_qty ]
57
- end
94
+ if partial . empty?
95
+ puts "\n This is it #{ exact } "
96
+ return exact
97
+ end
58
98
59
- def left_over_items ( pack_qtys , packs , left_over_qty )
60
- pack_qtys . sort { |a , b | a <=> b } . each do |p , v |
61
- break if left_over_qty . zero?
99
+ sub_total = [ ]
100
+ partial . each do |_x , _y , _z , val |
101
+ sub_total << val
102
+ end
62
103
63
- next unless left_over_qty <= p
104
+ # Find total cost of sub_items
105
+ line_total = sub_total . inject ( :+ )
64
106
65
- packs . map { |a | a [ 0 ] += 1 if a [ 1 ] . to_i == p }
66
- left_over_qty = 0
107
+ # Return array of the cheapest line
108
+ if [ exact . min [ 3 ] , line_total ] . min == line_total
109
+ puts "\n This is it #{ partial } "
110
+ return partial
111
+ end
67
112
68
- next if packs . detect { |a | a [ 1 ] == p }
113
+ puts "\n This is it #{ exact } " if [ exact . min [ 3 ] , line_total ] . min == exact
114
+ exact
115
+ end
69
116
70
- packs << [ 1 , p , v ]
117
+ def present_line ( packs )
118
+ puts "pACKS: #{ packs } "
119
+ sub_total = [ ]
120
+ sub_item = [ ]
121
+ packs . each do |k , v , i |
122
+ sub_total << k * i
123
+ sub_item << "#{ k } x #{ v } packs @ #{ i } "
71
124
end
72
125
73
- [ packs , left_over_qty ]
126
+ @line_total = sub_total . inject ( :+ )
127
+
128
+ sub_item . each { |s | s }
129
+ end
130
+
131
+ def presenter_line_total
132
+ @line_total
74
133
end
75
134
end
0 commit comments