Commit 4966dc18 by Tuomas Riihimäki

Moar queue

1 parent 2c6396cb
......@@ -13,4 +13,10 @@ public interface QueueBeanLocal {
boolean isReserving(EventMap map, EventUser user);
Integer getQueuePosition(EventMap map, EventUser user);
boolean isQueueEnabled();
MapReservationQueueEntry remove(EventMap map, EventUser user);
}
package fi.codecrew.moya.beans;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
......@@ -23,11 +21,12 @@ import javax.ejb.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.facade.PlaceSlotFacade;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEventProperty;
import fi.codecrew.moya.model.LanEventPropertyKey;
import fi.codecrew.moya.model.map.MapReservationQueue;
import fi.codecrew.moya.model.PlaceSlot;
import fi.codecrew.moya.model.map.MapReservationQueueEntry;
/**
......@@ -42,10 +41,11 @@ public class QueueBean implements QueueBeanLocal {
* Default constructor.
*/
public QueueBean() {
// TODO Auto-generated constructor stub
mapqueues = new HashMap<>();
logger.info("Initialized2 QueueBean, {}", mapqueues);
}
private final Map<EventMap, MapQueue> mapqueues = new HashMap<>();
private final Map<Integer, MapQueue> mapqueues;
private int reservingSize = 4;
......@@ -104,7 +104,10 @@ public class QueueBean implements QueueBeanLocal {
}
}
}
queEntries.get(e).setSeenTime(new Date());
MapReservationQueueEntry que = queEntries.get(e);
if (que != null) {
que.setSeenTime(new Date());
}
return reserving.contains(e);
}
......@@ -131,9 +134,11 @@ public class QueueBean implements QueueBeanLocal {
if (!reserving.contains(user) && !queue.contains(user)) {
ret = new MapReservationQueueEntry();
queEntries.put(user, ret);
queue.offer(user);
boolean queStat = queue.offer(user);
logger.info("User {} not in queue, offer state {}", user, queStat);
} else {
ret = queEntries.get(user);
logger.info("User {} already in queue. Not entering again {}", user, ret);
}
}
return ret;
......@@ -145,7 +150,9 @@ public class QueueBean implements QueueBeanLocal {
if (reserving.contains(user)) {
ret = 0;
logger.info("User in reserving queue {}", user);
} else if (queue.contains(user)) {
ret = 1;
for (EventUser eu : queue) {
if (eu.equals(user)) {
......@@ -153,16 +160,31 @@ public class QueueBean implements QueueBeanLocal {
}
++ret;
}
logger.info("User is in queue {}, position {}", user, ret);
} else {
logger.info("Not in queue, while checking position");
}
logger.info("Got position {} for user {}", ret, user);
return ret;
}
public boolean isInQueue(EventUser user) {
return reserving.contains(user) || queue.contains(user);
}
public MapReservationQueueEntry getEntry(EventUser user) {
return queEntries.get(user);
}
}
@EJB
private EventBeanLocal eventbean;
private AtomicLong nextReservingTimeoutCheck = new AtomicLong();
@EJB
private PlaceSlotFacade slotfacade;
@Lock(LockType.READ)
@Override
public boolean isReserving(EventMap map, EventUser user) {
// If queue is not enabled, user can always reserve
if (!isQueueEnabled())
......@@ -201,22 +223,31 @@ public class QueueBean implements QueueBeanLocal {
}
private MapQueue getMapque(EventMap map) {
MapQueue ret = mapqueues.get(map);
if (ret == null) {
ret = new MapQueue();
mapqueues.put(map, ret);
if (map == null) {
return null;
}
MapQueue ret = mapqueues.get(map.getId());
if (ret == null) {
logger.info("getMapqueue, {}", mapqueues);
synchronized (mapqueues) {
ret = new MapQueue();
mapqueues.put(map.getId(), ret);
}
}
logger.info("returning queue {} for map {}", ret, map);
return ret;
}
@Lock(LockType.READ)
@Override
public Integer getQueuePosition(EventMap map, EventUser user)
{
return getMapque(map).getPosition(user);
}
@Lock(LockType.READ)
@Override
public boolean isQueueEnabled() {
boolean ret = false;
LanEventProperty mapque = eventbean.getProperty(LanEventPropertyKey.MAP_QUEUE);
......@@ -227,6 +258,7 @@ public class QueueBean implements QueueBeanLocal {
}
@Lock(LockType.READ)
@Override
public MapReservationQueueEntry remove(EventMap map, EventUser user) {
MapQueue queue = getMapque(map);
return queue.remove(user);
......@@ -235,8 +267,24 @@ public class QueueBean implements QueueBeanLocal {
@Override
@Lock(LockType.READ)
public MapReservationQueueEntry enterQueue(EventMap map, EventUser user) {
if (!isQueueEnabled()) {
return null;
}
MapQueue queue = getMapque(map);
return queue.enter(user);
MapReservationQueueEntry ret = null;
if (queue.isInQueue(user)) {
logger.info("User {} already in queue");
ret = queue.getEntry(user);
} else {
List<PlaceSlot> slots = slotfacade.findFreePlaceSlots(user, null);
logger.info("User {} not yet in queue. User has {} slots", user, slots.size());
if (!slots.isEmpty()) {
ret = queue.enter(user);
logger.info("Entered queue: {}", ret);
}
}
return ret;
}
}
......@@ -18,6 +18,7 @@
*/
package fi.codecrew.moya.facade;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
......@@ -27,6 +28,7 @@ import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.slf4j.Logger;
......@@ -67,11 +69,15 @@ public class PlaceSlotFacade extends IntegerPkGenericFacade<PlaceSlot> {
CriteriaQuery<PlaceSlot> q = cb.createQuery(PlaceSlot.class);
Root<PlaceSlot> root = q.from(PlaceSlot.class);
Path<Bill> bill = root.get(PlaceSlot_.bill);
q.where(cb.equal(bill.get(Bill_.user), user),
cb.isNotNull(bill.get(Bill_.paidDate)),
cb.isNull(root.get(PlaceSlot_.used)),
cb.equal(root.get(PlaceSlot_.product), product)
);
final List<Predicate> preds = new ArrayList<>();
preds.add(cb.equal(bill.get(Bill_.user), user));
preds.add(cb.isNotNull(bill.get(Bill_.paidDate)));
preds.add(cb.isNull(root.get(PlaceSlot_.used)));
if (product != null) {
preds.add(cb.equal(root.get(PlaceSlot_.product), product));
}
q.where(preds.toArray(new Predicate[preds.size()]));
return getEm().createQuery(q).getResultList();
}
......@@ -102,18 +108,15 @@ public class PlaceSlotFacade extends IntegerPkGenericFacade<PlaceSlot> {
q.where(cb.equal(root.get(PlaceSlot_.product), prod),
cb.or(cb.isNull(billexp),
cb.greaterThan(billexp, Calendar.getInstance())
),
),
cb.isNull(root.get(PlaceSlot_.place)),
cb.isNull(root.get(PlaceSlot_.used))
);
);
Long count = super.getSingleNullableResult(getEm().createQuery(q));
return count;
}
public Long totalSlotcount(Product prod) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Long> q = cb.createQuery(Long.class);
......
......@@ -35,14 +35,24 @@
<h:outputScript target="head" library="seatjs" name="d3-tip.js" />
<h:outputScript target="head" library="seatjs" name="seatmap.js" />
<h:outputStylesheet library="seatjs" name="placemap.css" />
<div style="margin: 5px;">
<h:form id="placeselectform">
<h:commandButton rendered="#{ajaxMapView.canUserBuy()}"
<p:commandButton rendered="#{ajaxMapView.canUserBuy()}"
value="#{i18n['mapView.buyPlaces']}"
action="#{ajaxMapView.buySelectedPlaces()}" />
action="#{ajaxMapView.buySelectedPlaces()}" ajax="false" />
</h:form>
</div>
<h:form>
<p:commandButton value="#{i18n['mapView.enterQueue']}"
action="#{ajaxMapView.enterQueue()}" ajax="false" />
</h:form>
queueEntry #{ajaxMapView.queueEntry} <br />
QueuePosition: #{ajaxMapView.queuePosition} <br />
Available places to select: #{ajaxMapView.placesLeftToSelect} <br />
<svg id="seatmap" style="margin: auto; border: 1px solid black;"
width="#{ajaxMapView.map.width}px"
height="#{ajaxMapView.map.height}px" />
......@@ -91,7 +101,7 @@
<h:outputLabel value="#{i18n['placeSelect.placesleft']}:" />
<h:outputText value="#{ajaxMapView.placesLeftToSelect}" />
</h:panelGrid>
</h:panelGrid>
......
......@@ -23,6 +23,7 @@ import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.model.map.MapReservationQueueEntry;
import fi.codecrew.moya.web.cdiview.GenericCDIView;
import fi.codecrew.moya.web.cdiview.user.UserView;
......@@ -34,8 +35,8 @@ public class AjaxMapView extends GenericCDIView {
*
*/
private static final long serialVersionUID = 8203589456357519480L;
@Inject
private PlaceView placeview;
// @Inject
// private PlaceView placeview;
private static final Logger logger = LoggerFactory.getLogger(AjaxMapView.class);;
private String testVal = "Testval1";
......@@ -67,6 +68,26 @@ public class AjaxMapView extends GenericCDIView {
initMap();
}
private Boolean queEnabled = null;
private MapReservationQueueEntry queueEntry;
public boolean isQueueEnabled() {
if (queEnabled == null)
queEnabled = quebean.isQueueEnabled();
return queEnabled;
}
public String enterQueue()
{
logger.info("Entering queue");
if (isQueueEnabled())
queueEntry = quebean.enterQueue(initMap(), permbean.getCurrentUser());
else {
logger.warn("QueueNot enabled. Not entering queue");
}
return null;
}
private EventMap initMap() {
if (map == null && mapId != null) {
map = placebean.findMap(mapId);
......@@ -83,9 +104,14 @@ public class AjaxMapView extends GenericCDIView {
}
}
}
return map;
}
public Integer getQueuePosition() {
return quebean.getQueuePosition(initMap(), permbean.getCurrentUser());
}
public Long getPlacesLeftToSelect() {
Long ret = placebean.selectablePlaceCount(initMap());
logger.debug("Got {} places left for map {}", ret, initMap());
......@@ -172,4 +198,12 @@ public class AjaxMapView extends GenericCDIView {
public void setContext(FacesContext context) {
this.context = context;
}
public MapReservationQueueEntry getQueueEntry() {
return queueEntry;
}
public void setQueueEntry(MapReservationQueueEntry queueEntry) {
this.queueEntry = queueEntry;
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!