1
1
package com .kamisarau .shopsimulation .service .impl ;
2
2
3
+ import com .google .common .collect .ImmutableList ;
3
4
import com .kamisarau .shopsimulation .model .Category ;
4
5
import com .kamisarau .shopsimulation .model .Product ;
5
6
import com .kamisarau .shopsimulation .model .Shelf ;
12
13
import org .springframework .beans .factory .annotation .Autowired ;
13
14
import org .springframework .stereotype .Service ;
14
15
15
- import java .util .ArrayList ;
16
- import java .util .List ;
16
+ import java .util .* ;
17
+ import java .util .stream . Collectors ;
17
18
18
19
@ Service
19
20
@ Slf4j
@@ -22,18 +23,20 @@ public class MerchandiseServiceImpl implements MerchandiseService {
22
23
private StorageService storageService ;
23
24
private ShelfService shelfService ;
24
25
25
-
26
- //TODO add try catch blocks to prevent NoProductFound crash
26
+ //TODO add try catch blocks to prevent NoProductFound crash
27
27
@ Autowired
28
- public MerchandiseServiceImpl (WrappedProductService wrappedProductService , StorageService storageService , ShelfService shelfService ) {
28
+ public MerchandiseServiceImpl (WrappedProductService wrappedProductService ,
29
+ StorageService storageService , ShelfService shelfService ) {
29
30
this .wrappedProductService = wrappedProductService ;
30
31
this .storageService = storageService ;
31
32
this .shelfService = shelfService ;
32
33
}
33
34
34
35
@ Override
35
36
public boolean isProductBiggerThanShelf (WrappedProduct product , Shelf shelf ) {
36
- log .info ("Checking if product is bigger than shelf size: {}" , shelf .getHeight () * shelf .getWidth () < product .getHeight () * product .getWidth ());
37
+ log .info ("Checking if product is bigger than shelf size: {}" ,
38
+ (shelf .getHeight () * shelf .getWidth () < product .getHeight () * product .getWidth ()) ||
39
+ (shelf .getWidth () < product .getWidth ()) || (shelf .getHeight () < product .getHeight ()));
37
40
38
41
if (shelf .getHeight () * shelf .getWidth () < product .getHeight () * product .getWidth ()) {
39
42
return true ;
@@ -44,16 +47,10 @@ public boolean isProductBiggerThanShelf(WrappedProduct product, Shelf shelf) {
44
47
@ Override
45
48
public boolean storeOnShelf (WrappedProduct product , Shelf shelf ) {
46
49
47
- if (product .getWidth () < product .getHeight ()) {
48
- log .info ("Rotating product: {} so the width: {} wiil be bigger than height: {}" , product .getName (), product .getWidth (), product .getHeight ());
49
-
50
- int temp = product .getWidth ();
51
- product .setWidth (product .getHeight ());
52
- product .setHeight (temp );
53
- }
50
+ rotateProduct (product );
54
51
55
52
if (isProductBiggerThanShelf (product , shelf )) {
56
- log .warn ("Given product is bigger than shelf size, exiting ..." );
53
+ log .warn ("Given product is bigger than shelf size, bringing back ..." );
57
54
58
55
return false ;
59
56
}
@@ -65,43 +62,18 @@ public boolean storeOnShelf(WrappedProduct product, Shelf shelf) {
65
62
return true ;
66
63
}
67
64
68
- List <WrappedProduct > copyWithNewItem = new ArrayList <>(shelf .getProducts ());
69
- copyWithNewItem .add (product );
70
- log .debug ("Creting the copy: {} of products on the shelf: {}" , copyWithNewItem , shelf );
71
-
72
- int x = 1 ;
73
- int y = 1 ;
74
- int shelfLevel = 0 ;
75
-
76
- for (WrappedProduct storedItem : copyWithNewItem ) {
77
-
78
- log .debug ("Shelflevel is: {}" , shelfLevel );
79
-
80
- if (shelf .getHeight () < shelfLevel + storedItem .getHeight ()) {
81
- log .debug ("Product: {} doesnt fit, exiting..." , storedItem );
82
- return false ;
83
- }
84
-
85
- if (shelf .getWidth () + 1 < x + storedItem .getWidth ()) {
86
- log .debug ("Moving position to the {}, {}" , 1 , shelfLevel );
87
- y = shelfLevel ;
88
- x = 1 ;
89
- }
65
+ List <WrappedProduct > copyWithNewItem = ImmutableList .<WrappedProduct >builder ()
66
+ .addAll (shelf .getProducts ())
67
+ .add (product ).build ();
90
68
91
- if (storedItem .getHeight () > shelfLevel - y ) {
92
- log .debug ("Setting shelflevel to: {}" , y + storedItem .getHeight ());
93
- shelfLevel = y + storedItem .getHeight ();
94
- }
69
+ log .debug ("Creting the copy: {} of products on the shelf: {}" , copyWithNewItem , shelf .getId ());
95
70
96
- log .debug ("Setting final position on: {}, {}" , x , y );
97
- storedItem .setX (x );
98
- storedItem .setY (y );
99
-
100
- x += storedItem .getWidth ();
71
+ if (doShelfAlgorithm (shelf , copyWithNewItem ).isEmpty ()) {
72
+ return false ;
101
73
}
102
74
103
75
shelfService .storeProduct (copyWithNewItem , shelf );
104
- log .info ("Shelf: {} has: {} products" , shelf , shelf .getProducts ().size ());
76
+ log .info ("Shelf: {} has: {} products" , shelf . getId () , shelf .getProducts ().size ());
105
77
log .info ("Shelf index is: {}%" , getShelfCapacityIndex (shelf ));
106
78
return true ;
107
79
}
@@ -149,6 +121,8 @@ public WrappedProduct prepare(Product product) {
149
121
150
122
@ Override
151
123
public Product prepare (WrappedProduct wrappedProduct ) {
124
+ wrappedProductService .remove (wrappedProduct );
125
+
152
126
return new Product ()
153
127
.setName (wrappedProduct .getName ())
154
128
.setHeight (wrappedProduct .getHeight ())
@@ -161,4 +135,63 @@ private double getShelfCapacityIndex(Shelf shelf) {
161
135
162
136
return sumOfProductsParams / (shelf .getHeight () * shelf .getWidth ()) * 100 ;
163
137
}
138
+
139
+ private void rotateProduct (WrappedProduct product ) {
140
+ if (product .getWidth () < product .getHeight ()) {
141
+ log .info ("Rotating product: {} so the width: {} wiil be bigger than height: {}" ,
142
+ product .getName (), product .getWidth (), product .getHeight ());
143
+
144
+ int temp = product .getWidth ();
145
+ product .setWidth (product .getHeight ());
146
+ product .setHeight (temp );
147
+ }
148
+ }
149
+
150
+ /**
151
+ * NFDH (Next Fit Decreasing High) packing algorithm
152
+ *
153
+ * @param shelf shelf to use as storage to calculate wether products fit or not
154
+ * @param products list of products to store
155
+ * <p>
156
+ * x,y - bottom-left point of the product to be set after its located on the shelf
157
+ * @return null if one of the products doesn't fit
158
+ */
159
+ private List <WrappedProduct > doShelfAlgorithm (Shelf shelf , List <? extends WrappedProduct > products ) {
160
+ List <WrappedProduct > productsWithSortedHeight = products .stream ()
161
+ .sorted (Comparator .comparingInt (WrappedProduct ::getHeight ).reversed ())
162
+ .collect (Collectors .toList ());
163
+
164
+ int x = 1 ;
165
+ int y = 1 ;
166
+ int shelfLevel = 0 ;
167
+
168
+ for (WrappedProduct storedItem : productsWithSortedHeight ) {
169
+
170
+ log .debug ("Shelflevel is: {}" , shelfLevel );
171
+
172
+ if (shelf .getHeight () < shelfLevel + storedItem .getHeight ()) {
173
+ log .debug ("Product: {} doesnt fit, exiting..." , storedItem );
174
+ return Collections .emptyList ();
175
+ }
176
+
177
+ if (shelf .getWidth () + 1 < x + storedItem .getWidth ()) {
178
+ log .debug ("Moving position to the {}, {}" , 1 , shelfLevel );
179
+ y = shelfLevel ;
180
+ x = 1 ;
181
+ }
182
+
183
+ if (storedItem .getHeight () > shelfLevel - y ) {
184
+ log .debug ("Setting shelflevel to: {}" , y + storedItem .getHeight ());
185
+ shelfLevel = y + storedItem .getHeight ();
186
+ }
187
+
188
+ log .debug ("Setting final position on: {}, {}" , x , y );
189
+ storedItem .setX (x );
190
+ storedItem .setY (y );
191
+
192
+ x += storedItem .getWidth ();
193
+ }
194
+
195
+ return productsWithSortedHeight ;
196
+ }
164
197
}
0 commit comments