/*
* This file is part of gwap, an open platform for games with a purpose
*
* Copyright (C) 2013
* Project play4science
* Lehr- und Forschungseinheit für Programmier- und Modellierungssprachen
* Ludwig-Maximilians-Universität München
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gwap.game;
import gwap.ResourceBean;
import gwap.action.TaggingBean;
import gwap.model.GameRound;
import gwap.model.action.Action;
import gwap.model.action.Tagging;
import gwap.model.action.TaggingCorrection;
import gwap.model.resource.ArtResource;
import gwap.wrapper.MatchingTag;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.Query;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
/**
* This is the backing bean for one game session. It handles all actions that
* can be executed during a game session. The game session itself is organized
* in a business process.
*
* @author Christoph Wieser
*/
@Name("gameSessionBean")
@Scope(ScopeType.CONVERSATION)
public class GameSessionBean extends AbstractGameSessionBean {
private static final int MAXIMUM_RETRY_LOAD_NEW_RESOURCE = 5;
private static final long serialVersionUID = 1L;
@In(create=true) private TaggingBean taggingBean;
@In private ResourceBean resourceBean;
@In(create=true) private ArtResource resource;
@In(create=true) private GameRoundScoringBean gameRoundScoringBean;
private Map<Integer, List<MatchingTag>> recommendedTags = new HashMap<Integer, List<MatchingTag>>();
@Override
public void startGameSession() {
startGameSession("imageLabeler");
}
@Override
protected void loadNewResource() {
resourceBean.updateResource();
// check if person already played with this resource in the last 6 months
Query q = entityManager.createNamedQuery("artResource.hasBeenPlayedSince");
q.setParameter("person", person);
Calendar monthsAgo = GregorianCalendar.getInstance();
monthsAgo.add(Calendar.MONTH, -6);
q.setParameter("startDate", monthsAgo.getTime());
q.setParameter("resource", resourceBean.getResource());
int emergencyStop = MAXIMUM_RETRY_LOAD_NEW_RESOURCE;
while (((Number)q.getSingleResult()).longValue() > 0 && emergencyStop > 0) {
log.info("Load new resource because user already played with #0", resourceBean.getResource());
resourceBean.updateResource();
q.setParameter("resource", resourceBean.getResource());
emergencyStop--;
}
}
public String recommendTag() {
if (!roundExpired()) {
Tagging tagging = taggingBean.recommendTag(resource, false);
if (tagging.getTag() == null) {
log.info("Could not add tag to gameround as it is invalid.");
} else {
List<Action> actions = gameRound.getActions();
actions.add(tagging);
log.info("Added #0 to game round", tagging.getTag().getName());
}
recommendedTags.put(gameRound.getNumber(), taggingBean.getRecommendedTags());
return null;
} else {
//facesMessages.add("#{messages['game.round.expired']}");
return "next";
}
}
public void acceptTagCorrection(String originalTag, String correctedTag) {
log.info("Correcting tag from #0 to #1", originalTag, correctedTag);
MatchingTag correctedMatchingTag = taggingBean.correctTag(originalTag, correctedTag);
if (correctedMatchingTag != null) {
correctedMatchingTag.setTagCorrectionCompleted(true);
updateScore(correctedMatchingTag);
}
}
public void rejectTagCorrection(String originalTag, String correctedTag) {
log.info("Reject tag correction from #0 to #1", originalTag, correctedTag);
MatchingTag matchingTag = taggingBean.getMatchingTag(originalTag);
matchingTag.setAlternativeTags(null);
matchingTag.setTagCorrectionCompleted(true);
TaggingCorrection taggingCorrection = new TaggingCorrection();
initializeAction(taggingCorrection);
taggingCorrection.setOriginalTag(taggingBean.findOrCreateTag(originalTag));
taggingCorrection.setCorrectedTag(taggingBean.findOrCreateTag(correctedTag));
taggingCorrection.setAccepted(false);
entityManager.persist(taggingCorrection);
}
@Override
public void endRound() {
gameRound.getResources().add(resource);
super.endRound();
}
@Observer("updateScore")
public void updateScore(MatchingTag newlyMatchedTag) {
gameRoundScoringBean.updateScore(resource, newlyMatchedTag);
currentRoundScore = taggingBean.getCurrentScore();
}
public List<MatchingTag> getTagsForRound(GameRound gameRound) {
Integer roundNr = gameRound.getNumber();
if (roundNr != null)
return recommendedTags.get(roundNr);
else
return null;
}
}