]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java
[XVSM] Delivery in progress, Delivery done updates in UIs, Delivery logic
[pub/jan/sbc.git] / src / main / java / at / ac / tuwien / sbc / valesriegler / xvsm / WaiterXVSM.java
1 package at.ac.tuwien.sbc.valesriegler.xvsm;
2
3 import at.ac.tuwien.sbc.valesriegler.common.OrderId;
4 import at.ac.tuwien.sbc.valesriegler.common.Util;
5 import at.ac.tuwien.sbc.valesriegler.types.*;
6 import at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceAction;
7 import at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceListener;
8 import org.mozartspaces.core.MzsConstants.RequestTimeout;
9 import org.mozartspaces.core.MzsCoreException;
10 import org.mozartspaces.core.TransactionReference;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import java.io.Serializable;
15 import java.util.Arrays;
16 import java.util.List;
17
18 public class WaiterXVSM extends AbstractXVSMConnector {
19     private static final Logger log = LoggerFactory.getLogger(WaiterXVSM.class);
20     private final int waiterId;
21
22     public WaiterXVSM(int waiterId, int port) {
23         super(port);
24
25         this.waiterId = waiterId;
26
27         freeTablesContainer = useContainer(Util.FREE_TABLES);
28         assignTableContainer = useContainer(Util.ASSIGN_TABLE);
29         takeOrderContainer = useContainer(Util.TAKE_ORDER);
30         orderTakenContainer = useContainer(Util.ORDER_TAKEN);
31         deliveryOrderTakenContainer = useContainer(Util.DELIVERY_ORDER_TAKEN);
32         preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
33         prepareDeliveryPizzasContainer = useContainer(Util.PREPARE_DELIVERY_PIZZAS);
34         orderDeliveredContainer = useContainer(Util.ORDER_COMPLETE);
35         preparedPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
36         paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST);
37         paymentDoneContainer = useContainer(Util.PAYMENT_DONE);
38         tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED);
39         pizzeriaInfoContainer = useContainer(Util.PIZZERIA_INFO);
40         phoneCallsContainer = useContainer(Util.PHONE_CALLS);
41         preparedDeliveryPizzasContainer = useContainer(Util.DELIVER_DELIVERY_PIZZAS);
42         deliverDeliveryOrderContainer = useContainer(Util.DELIVER_DELIVERY_ORDER);
43         pizzeriaGroupContainer = useContainer(Util.PIZZERIA_GROUP);
44         pizzeriaTableContainer = useContainer(Util.PIZZERIA_TABLE);
45         pizzeriaDeliveryContainer = useContainer(Util.PIZZERIA_DELIVERY);
46     }
47
48     public void listenForPhoneOrders() {
49         SpaceListener phoneListener = getDefaultBuilder().setCref(phoneCallsContainer).setLookaround(true).setSpaceAction(new SpaceAction() {
50             @Override
51             public void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
52                 final List<DeliveryGroupData> phoneOrders = castEntries(entries);
53
54                 for (DeliveryGroupData phoneOrder : phoneOrders) {
55                     final int id = phoneOrder.getId();
56                     final DeliveryGroupData template = new DeliveryGroupData(id);
57                     final String errorMsg = String.format("There was phone call with id %d. Another waiter already responded!", id);
58
59                     final TransactionReference tx = getDefaultTransaction();
60                     try {
61                         // Get the the delete lock so that only one waiter can answer this particular phone call
62                         takeMatchingEntity(template, phoneCallsContainer, tx, RequestTimeout.DEFAULT, errorMsg);
63
64                         final DeliveryGroupData group = takeMatchingEntity(template, pizzeriaDeliveryContainer, tx, RequestTimeout.DEFAULT, errorMsg);
65                         group.setWaiterIdOfOrder(WaiterXVSM.this.waiterId);
66                         final Order order = group.getOrder();
67                         group.setDeliveryStatus(DeliveryStatus.ORDERED);
68
69                         updatePizzeriaOrderNumber(order, tx);
70
71                         // send the order as a whole to the space
72                         final List<DeliveryGroupData> groupsWhoHaveOrdered = Arrays.asList(group);
73                         sendItemsToContainer(groupsWhoHaveOrdered,
74                                 deliveryOrderTakenContainer, RequestTimeout.ZERO, tx);
75                         sendItemsToContainer(groupsWhoHaveOrdered,
76                                 pizzeriaDeliveryContainer, RequestTimeout.ZERO, tx);
77                         sendItemsToContainer(order.getOrderedPizzas(),
78                                 prepareDeliveryPizzasContainer, RequestTimeout.ZERO, tx);
79                         capi.commitTransaction(tx);
80
81                         log.info("Waiter has taken a phone delivery call!");
82                     } catch (Exception e) {
83                     }
84                 }
85
86             }
87         }).createSpaceListenerImpl();
88     }
89
90     public void listenForFreeTable() {
91         SpaceListener listener = getDefaultBuilder().setCref(freeTablesContainer).setSpaceAction(new SpaceAction() {
92
93             @Override
94             public void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
95
96                 List<Table> tables = castEntries(entries);
97
98                 for (Table table : tables) {
99
100                     TransactionReference tx = getDefaultTransaction();
101
102                     // Acquire a lock for the free table in the
103                     // FreeTableContainer
104                     int id = table.getId();
105
106                     Table tableTemplate = new Table(id);
107                     try {
108                         Table lockedFreeTable = takeMatchingEntity(tableTemplate,
109                                 freeTablesContainer, tx, RequestTimeout.DEFAULT,
110                                 String.format("There was no free table found with id %d", id));
111                         takeMatchingEntityIfItExists(tableTemplate, pizzeriaTableContainer, tx, RequestTimeout.DEFAULT);
112
113                         GroupData groupTemplate = new GroupData();
114                         GroupData lockedGroup = takeMatchingEntity(groupTemplate,
115                                 assignTableContainer, tx, RequestTimeout.DEFAULT,
116                                 "There is no group waiting for a table at the moment");
117                         takeMatchingEntityIfItExists(lockedGroup, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
118
119                         assignGroupToTable(lockedGroup, lockedFreeTable, tx);
120                     } catch (Exception e) {
121 //                                              log.info(e.getMessage());
122                     }
123                 }
124             }
125         }).createSpaceListenerImpl();
126     }
127
128
129     public void listenForNewGuests() {
130         SpaceListener listener = getDefaultBuilder().setLookaround(true).setCref(assignTableContainer).setSpaceAction(new SpaceAction() {
131
132             @Override
133             public void onEntriesWritten(List<? extends Serializable> entries)
134                     throws Exception {
135                 log.info("New guest groups have arrived");
136
137                 List<GroupData> groups = castEntries(entries);
138
139                 for (GroupData group : groups) {
140
141                     TransactionReference tx = getDefaultTransaction();
142
143                     // Acquire a lock for the group in the
144                     // AssignTableContainer
145                     String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
146
147                     try {
148                         final GroupData templateGroup = new GroupData(group.getId());
149                         GroupData lockedGroup = takeMatchingEntity(
150                                 templateGroup,
151                                 assignTableContainer, tx,
152                                 RequestTimeout.DEFAULT, groupNotFound);
153                         takeMatchingEntityIfItExists(templateGroup, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
154                         // Acquire a lock for one free table in the
155                         // TablesContainer
156                         String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
157                         final Table freeTable = new Table(null);
158                         freeTable.setFree(true);
159                         Table lockedFreeTable = takeMatchingEntity(freeTable, freeTablesContainer, tx, RequestTimeout.DEFAULT,
160                                 noFreeTable);
161                         takeMatchingEntityIfItExists(lockedFreeTable, pizzeriaTableContainer, tx, RequestTimeout.DEFAULT);
162
163                         assignGroupToTable(lockedGroup, lockedFreeTable, tx);
164                     } catch (Exception e) {
165 //                                              log.info(e.getMessage());
166                     }
167                 }
168             }
169         }).createSpaceListenerImpl();
170     }
171
172     public void listenForPaymentRequest() {
173         SpaceListener paymentListener = getDefaultBuilder().setCref(paymentRequestContainer).setSpaceAction(new SpaceAction() {
174
175             @Override
176             public void onEntriesWritten(List<? extends Serializable> entries)
177                     throws Exception {
178
179                 List<GroupData> groups = castEntries(entries);
180
181                 for (GroupData groupData : groups) {
182                     TransactionReference tx = getDefaultTransaction();
183                     GroupData entity = new GroupData(groupData.getId());
184                     entity.setState(GroupState.PAY);
185
186                     // Acquire the lock so that another waiter can't do the same
187                     // thing!
188                     String paymentRequestTakenByOtherWaiter = String.format(
189                             "The payment request for group %d was already taken by an other waiter!",
190                             groupData.getId());
191                     try {
192                         takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
193                         GroupData group = takeMatchingEntity(entity, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT, "Cannot get paying group!");
194                         group.setPayingWaiter(waiterId);
195                         group.setState(GroupState.GONE);
196
197                         final Table tableTemplate = new Table(null);
198                         tableTemplate.setGroupId(group.getId());
199                         final Table table = takeMatchingEntity(tableTemplate, pizzeriaTableContainer, tx, RequestTimeout.DEFAULT, "Table was not found!");
200                         table.setGroupId(-1);
201                         final List<Table> tables = Arrays.asList(table);
202                         sendItemsToContainer(tables, pizzeriaTableContainer, RequestTimeout.DEFAULT, tx);
203                         sendItemsToContainer(tables, freeTablesContainer, RequestTimeout.DEFAULT, tx);
204
205                         final List<GroupData> groupsPayed = Arrays.asList(group);
206                         sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.DEFAULT, tx);
207                         sendItemsToContainer(groupsPayed, pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
208
209                         capi.commitTransaction(tx);
210                     } catch (Exception e) {
211                                                 log.info(e.getMessage());
212                     }
213                 }
214             }
215         }).createSpaceListenerImpl();
216     }
217
218     public void listenForOrderRequests() {
219         SpaceListener ordersListener = getDefaultBuilder().setCref(takeOrderContainer).setSpaceAction(new SpaceAction() {
220
221             @Override
222             public void onEntriesWritten(List<? extends Serializable> entries)
223                     throws Exception {
224
225                 List<GroupData> groups = castEntries(entries);
226
227                 for (GroupData groupData : groups) {
228
229                     TransactionReference tx = getDefaultTransaction();
230                     GroupData entity = new GroupData(groupData.getId());
231                     entity.setState(GroupState.SITTING);
232
233                     try {
234                         // Acquire the lock so that another waiter can't do the same thing!
235                         String orderTakenByOtherWaiter = String.format(
236                                 "The order for group %d was already taken by an other waiter!",
237                                 groupData.getId());
238                         takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
239                         GroupData group = takeMatchingEntityIfItExists(entity, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
240
241                         group.setOrderWaiter(waiterId);
242                         group.setState(GroupState.ORDERED);
243                         Order order = group.getOrder();
244                         order.setStatus(OrderStatus.ORDERED);
245
246                         /*  get the id of the last order of the pizzeria and set the order accordingly and
247                             update the space */
248                         updatePizzeriaOrderNumber(order, tx);
249
250                         // send the order as a whole to the space
251                         final List<GroupData> groupsWhoHaveOrdered = Arrays.asList(group);
252                         sendItemsToContainer(groupsWhoHaveOrdered,
253                                 orderTakenContainer, RequestTimeout.ZERO, tx);
254                         sendItemsToContainer(groupsWhoHaveOrdered,
255                                 pizzeriaGroupContainer, RequestTimeout.ZERO, tx);
256                         sendItemsToContainer(order.getOrderedPizzas(),
257                                 preparePizzasContainer, RequestTimeout.ZERO, tx);
258                         capi.commitTransaction(tx);
259
260                         log.info("Waiter has taken order from group {}",
261                                 group.getId());
262                     } catch (Exception e) {
263 //                                              log.info(e.getMessage());
264                     }
265                 }
266             }
267         }).createSpaceListenerImpl();
268     }
269
270     public void listenForPreparedPizzas() {
271         /**
272          * A waiter gets informed when a new pizza is complete. He takes the
273          * orderId of the pizza and looks up the corresponding order from which
274          * he gets the number of necessary pizzas of the order. He then tries to
275          * fetch all pizzas with the corresponding orderId and compares the
276          * number of those pizzas with the number of necessary pizzas. If all
277          * pizzas of an order are complete he then delivers them!
278          */
279         SpaceListener preparedPizzasListener = getDefaultBuilder().setLookaround(true).setCref(preparedPizzasContainer).setSpaceAction(new SpaceAction() {
280
281             @Override
282             public void onEntriesWritten(List<? extends Serializable> entries)
283                     throws Exception {
284                 log.info("NEW PIZZAS ARRived");
285
286                 List<Pizza> pizzas = castEntries(entries);
287
288                 for (Pizza pizza : pizzas) {
289                     int orderId = pizza.getOrderId();
290                     Order order = new Order();
291                     order.setId(orderId);
292
293                     TransactionReference tx = getDefaultTransaction();
294
295                     try {
296                         GroupData entity = new GroupData();
297                         entity.setState(GroupState.ORDERED);
298                         entity.setOrder(order);
299
300                         takeMatchingEntity(entity,
301                                 orderTakenContainer, tx, RequestTimeout.DEFAULT,
302                                 "Another waiter just checks if the order is complete");
303                         GroupData groupData = takeMatchingEntityIfItExists(entity,
304                                 pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
305                         int groupId = groupData.getId();
306                         int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
307
308                         Pizza pizzaTemplate = new Pizza();
309                         pizzaTemplate.setOrderId(orderId);
310
311                         List<Pizza> pizzasOfOrder = takeMatchingEntities(
312                                 pizzaTemplate, preparedPizzasContainer, tx,
313                                 RequestTimeout.DEFAULT,
314                                 "Cannot take the pizzas from the preparedPizzasContainer");
315
316                         final List<GroupData> groupsWithCompleteOrder = Arrays.asList(groupData);
317                         if (pizzasOfOrder.size() == numberOfPizzas) {
318                             groupData.setServingWaiter(waiterId);
319                             groupData.setState(GroupState.EATING);
320                             groupData.getOrder().setStatus(OrderStatus.DELIVERED);
321                             sendItemsToContainer(groupsWithCompleteOrder,
322                                     orderDeliveredContainer, RequestTimeout.DEFAULT,
323                                     tx);
324                             sendItemsToContainer(groupsWithCompleteOrder,
325                                     pizzeriaGroupContainer, RequestTimeout.DEFAULT,
326                                     tx);
327
328                             capi.commitTransaction(tx);
329                         } else {
330                             log.info("Not yet all pizzas prepared! Order with id "
331                                     + orderId + " has " + numberOfPizzas
332                                     + " pizzas, but only " + pizzasOfOrder.size()
333                                     + " pizzas are ready by now!");
334                             capi.rollbackTransaction(tx);
335                         }
336                     } catch (NullPointerException e) {
337
338                     } catch (Exception e) {
339                         capi.rollbackTransaction(tx);
340                     }
341                 }
342             }
343         }).createSpaceListenerImpl();
344     }
345
346     public void listenForPreparedDeliveryPizzas() {
347         /**
348          * A waiter gets informed when a new pizza is complete. He takes the
349          * orderId of the pizza and looks up the corresponding order from which
350          * he gets the number of necessary pizzas of the order. He then tries to
351          * fetch all pizzas with the corresponding orderId and compares the
352          * number of those pizzas with the number of necessary pizzas. If all
353          * pizzas of an order are complete he then delivers them!
354          */
355         SpaceListener preparedPizzasListener = getDefaultBuilder().setCref(preparedDeliveryPizzasContainer).setLookaround(true).setSpaceAction(new SpaceAction() {
356
357             @Override
358             public void onEntriesWritten(List<? extends Serializable> entries)
359                     throws Exception {
360
361                 List<Pizza> pizzas = castEntries(entries);
362
363                 for (Pizza pizza : pizzas) {
364                     int orderId = pizza.getOrderId();
365                     Order order = new Order();
366                     order.setId(orderId);
367
368                     TransactionReference tx = getDefaultTransaction();
369
370                     try {
371                         DeliveryGroupData entity = new DeliveryGroupData();
372                         entity.setDeliveryStatus(null);
373                         entity.setOrder(order);
374
375                         takeMatchingEntity(entity,
376                                 deliveryOrderTakenContainer, tx, RequestTimeout.DEFAULT,
377                                 "Another driver just checks if the delivery order is complete");
378                         DeliveryGroupData groupData = takeMatchingEntity(entity,
379                                 pizzeriaDeliveryContainer, tx, RequestTimeout.DEFAULT,
380                                 "Waiter cannot take the delivery order from Space!");
381                         int groupId = groupData.getId();
382                         int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
383
384                         Pizza pizzaTemplate = new Pizza();
385                         pizzaTemplate.setOrderId(orderId);
386
387                         List<Pizza> pizzasOfOrder = takeMatchingEntities(
388                                 pizzaTemplate, preparedDeliveryPizzasContainer, tx,
389                                 RequestTimeout.DEFAULT,
390                                 "Cannot take the pizzas from the preparedDeliveryPizzasContainer");
391
392                         if (pizzasOfOrder.size() == numberOfPizzas) {
393                             final List<DeliveryGroupData> groupsWithCompleteOrder = Arrays.asList(groupData);
394                             sendItemsToContainer(groupsWithCompleteOrder,
395                                     deliverDeliveryOrderContainer, RequestTimeout.DEFAULT,
396                                     tx);
397                             sendItemsToContainer(groupsWithCompleteOrder,
398                                     pizzeriaDeliveryContainer, RequestTimeout.DEFAULT,
399                                     tx);
400
401                             capi.commitTransaction(tx);
402                         } else {
403                             log.info("Not yet all pizzas prepared! Order with id "
404                                     + orderId + " has " + numberOfPizzas
405                                     + " pizzas, but only " + pizzasOfOrder.size()
406                                     + " pizzas are ready by now!");
407                             capi.rollbackTransaction(tx);
408                         }
409                     } catch (NullPointerException e) {
410
411                     } catch (Exception e) {
412                         capi.rollbackTransaction(tx);
413                     }
414                 }
415             }
416         }).createSpaceListenerImpl();
417     }
418
419
420     private void assignGroupToTable(GroupData lockedGroup,
421                                     Table lockedFreeTable, TransactionReference tx)
422             throws MzsCoreException {
423         // The new group sits down at the table
424         lockedFreeTable.setGroupId(lockedGroup.getId());
425
426         // The new group now wants to order
427         lockedGroup.setState(GroupState.SITTING);
428         lockedGroup.setTable(lockedFreeTable);
429         lockedGroup.setTableWaiter(waiterId);
430
431         final List<Table> freeTables = Arrays.asList(lockedFreeTable);
432         sendItemsToContainer(freeTables,
433                 pizzeriaTableContainer, RequestTimeout.ZERO, tx);
434         sendItemsToContainer(freeTables,
435                 tableAssignedContainer, RequestTimeout.ZERO, tx);
436         sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
437                 RequestTimeout.ZERO, tx);
438         sendItemsToContainer(Arrays.asList(lockedGroup), pizzeriaGroupContainer,
439                 RequestTimeout.ZERO, tx);
440
441         try {
442             capi.commitTransaction(tx);
443             log.info("Assigned table to group with groupId {}",
444                     lockedGroup.getId());
445         } catch (Exception e) {
446             log.info("Assigning a table to group with groupId {} failed",
447                     lockedGroup.getId());
448             log.info(e.getMessage());
449         }
450     }
451
452     private void updatePizzeriaOrderNumber(Order order, TransactionReference tx) throws MzsCoreException {
453     /*  get the id of the last order of the pizzeria and set the order accordingly and
454         update the space */
455         final OrderId orderId = takeMatchingEntity(new OrderId(null), pizzeriaInfoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
456         final int id = orderId.getId();
457         final int nextId = id + 1;
458         order.setId(nextId);
459         final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
460         for (PizzaOrder orderedPizza : orderedPizzas) {
461             orderedPizza.setOrderId(nextId);
462         }
463         sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);
464     }
465 }