/* * 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.memory; import gwap.action.ActionBean; import gwap.action.TaggingBean; import gwap.model.GameRound; import gwap.model.Tag; import gwap.model.action.Selection; import gwap.model.action.Tagging; import gwap.model.resource.ArtResource; import gwap.tools.ArtResourceFrequency; import gwap.tools.TagSemantics; import java.util.ArrayList; import java.util.List; import org.jboss.seam.Component; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Out; import org.jboss.seam.annotations.Scope; import org.jboss.seam.faces.FacesMessages; import org.jboss.seam.log.Log; @Name("gwapGameMemorySharedGame") @Scope(ScopeType.CONVERSATION) public class SharedGame extends gwap.game.SharedGame<Player> { @In private Player gwapGameMemoryPlayer; @Logger private Log log; @In private FacesMessages facesMessages; @In(create=true) private ActionBean actionBean; @In(create=true) @Out(scope=ScopeType.CONVERSATION) private TaggingBean taggingBean; //List of tags that is shown in view List<Tag> tags=new ArrayList<Tag>(); //List of descriptions, including those generated from questions List<Tagging> descriptions=new ArrayList<Tagging>(); private int wrongGuesses; List<ArtResourceFrequency> freq=new ArrayList<ArtResourceFrequency>(); List<Question> questions=new ArrayList<Question>(); List<Question> answers=new ArrayList<Question>(); private boolean allowDescriptions=true; private boolean allowQuestions=true; private boolean clusteringMode=false; private boolean alternatingMode=false; private int alternatingModeTurn=0; private ResourceGridBean resourceGridBean; private List<GameRound> gameRounds=new ArrayList<GameRound>(); private GameRound gameRound; private ArtResource resource; public boolean isCompatible(gwap.game.SharedGame game) { if (!game.getLanguage().equals(getLanguage())) return false; if (game instanceof SharedGame) { SharedGame g=(SharedGame)game; return g.getAllowDescriptions() == allowDescriptions && g.getAllowQuestions() == allowQuestions && g.getAlternatingMode() == alternatingMode && g.getRoundCount() == getRoundCount() && g.getRoundLength() == getRoundLength() && g.getMoveMode() == getMoveMode(); } else return false; } public boolean getAllowDescriptions() { return allowDescriptions; } public boolean isClusteringMode() { return clusteringMode; } public void setClusteringMode(boolean clusteringMode) { this.clusteringMode = clusteringMode; } public void setAllowDescriptions(boolean allowDescriptions) { this.allowDescriptions = allowDescriptions; } public void setAllowQuestions(boolean allowQuestions) { this.allowQuestions = allowQuestions; } public boolean getAllowQuestions() { return allowQuestions; } public boolean getAlternatingMode() { return alternatingMode; } public void setAlternatingMode(boolean alternatingMode) { this.alternatingMode=alternatingMode; } public boolean getDisableEditQuestion() { return resourceGridBean.getGoal()==null || (alternatingMode && alternatingModeTurn!=1); } public boolean getDisableAnswerQuestion() { return resourceGridBean.getGoal()==null || (alternatingMode && alternatingModeTurn!=2); } public boolean getDisableEditDescription() { return resourceGridBean.getGoal()==null || (alternatingMode && alternatingModeTurn!=0); } public int getAlternatingModeTurn() { return alternatingModeTurn; } public void doMove() { move(); gwapGameMemoryPlayer.signalAll("moves"); } public synchronized String getHeading(boolean isGuesser) { if (isGuesser) { if (resourceGridBean.isNoGoal()) return "game.memory.guesser_wait"; else { if (alternatingMode) { if (alternatingModeTurn==0) return "game.memory.guesser_description_wait"; else if (alternatingModeTurn==1) return "game.memory.guesser_description_ask"; else return "game.memory.guesser_description_answer"; } else return "game.memory.guesser_description"; } } else { if (resourceGridBean.isNoGoal()) return "game.memory.describer_select"; else { if (alternatingMode) { if (alternatingModeTurn==0) return "game.memory.describer_description"; else if (alternatingModeTurn==1) return "game.memory.describer_wait"; else return "game.memory.describer_answer"; } else return "game.memory.describer_description"; } } } public void setAlternatingModeTurn(int turn) { alternatingModeTurn=turn; gwapGameMemoryPlayer.signalAll("edit"); } public void addQuestion(String question, int round) { if (alternatingMode) { if (alternatingModeTurn!=1) return; } if (checkRound(round)) return; question=question.toLowerCase(); if (TagSemantics.wordCount(question)>3) { facesMessages.add("#{messages['taggingBean.tooManyWordsInTag']}"); return; } for (Question q : answers) { if (q.getQuestion().getName().toLowerCase().equals(question)) { facesMessages.add("#{messages['taggingBean.tagExistsAlready']}"); return; } } if (alternatingMode) { setAlternatingModeTurn(2); gwapGameMemoryPlayer.signalAll("shakeheading"); } Tag tag=taggingBean.findOrCreateTag(question); if (tag!=null) { Question q=new Question(tag); questions.add(q); answers.add(q); } } public void removeQuestion(Question question) { if (alternatingMode) { if (alternatingModeTurn!=2) return; setAlternatingModeTurn(0); gwapGameMemoryPlayer.signalAll("shakeheading"); } doMove(); questions.remove(question); } public List<Question> getQuestions() { return questions; } public List<Question> getAnswers() { return answers; } public void TESTsetFreq(List<ArtResourceFrequency> f) { freq=f; } public double TESTgetFreq(ArtResource res) { for (ArtResourceFrequency r : freq) { if (r.getResource()==res) return r.getCount(); } return 0; } public ResourceGridBean getResourceGridBean() { return resourceGridBean; } public SharedGame() { resourceGridBean=(ResourceGridBean)Component.getInstance("resourceGridBean"); setScore(0); // gameSessionBean=(GameSessionBean)Component.getInstance("gameSessionBean"); // gameSessionBean.startGameSession("memory"); } public List<Tag> getDescription() { return tags; } public List<Tagging> getDescriptions() { return descriptions; } public void sendTag(Tag tag, int round) { if (checkRound(round)) return; tags.add(tag); } public void sendDescription(Tagging description, int round) { if (checkRound(round)) return; if (alternatingMode) { if (alternatingModeTurn!=0) return; setAlternatingModeTurn(1); gwapGameMemoryPlayer.signalAll("shakeheading"); } doMove(); descriptions.add(description); resource.getTaggings().add(description); tags.add(description.getTag()); } public void addDescription(Tagging t) { resource.getTaggings().add(t); descriptions.add(t); } private ArtResource cloneResource(ArtResource resource) { ArtResource result=new ArtResource(); result.setArtist(resource.getArtist()); result.setTitles(resource.getTitles()); result.setDateCreated(resource.getDateCreated()); result.setUrl(resource.getUrl()); return result; } public synchronized void startNewRound() { try { //Start new round (replay previous round if partner is Ai and Player is guesser) resourceGridBean.updateResourceGridBean(gwapGameMemoryPlayer.getPartner().isAi() && gwapGameMemoryPlayer.isGuesser(), isClusteringMode()); } catch (Exception e) { log.info("Error starting new round: #0", e.getMessage()); return; } int number=1; if (gameRound!=null) { number=gameRound.getNumber()+1; } gameRound=new GameRound(); gameRounds.add(gameRound); resource=cloneResource(resourceGridBean.getGoal()); gameRound.getResources().add(resource); gameRound.setNumber(number); newGoal(); gwapGameMemoryPlayer.signalAll("images"); gwapGameMemoryPlayer.addNotifierAll("tags"); gwapGameMemoryPlayer.addNotifierAll("edit"); if (allowQuestions) gwapGameMemoryPlayer.addNotifierAll("questions"); wrongGuesses=0; log.info("Players signalled"); } private void newGoal() { descriptions.clear(); tags.clear(); questions.clear(); answers.clear(); alternatingModeTurn=0; } public List<GameRound> getGameRounds() { return gameRounds; } public void resourceClicked(ArtResource res, int round) { resourceClicked(res, round, gwapGameMemoryPlayer); } public synchronized void resourceClicked(ArtResource res, int round, Player player) { if (checkRound(round)) return; /*if (isRoundCompleted()) { newRound(); return; }*/ if (res==null) return; //Guesser if (player.isGuesser()) { if (resourceGridBean.getGoal()!=null) { int scoreDelta=0; if (resourceGridBean.isSelected(res)) //Player has ventured a guess { Selection selection=(Selection)Component.getInstance("selection"); selection.setResource(res); if (alternatingMode) { if (alternatingModeTurn==1) setAlternatingModeTurn(0); gwapGameMemoryPlayer.signalAll("shakeheading"); doMove(); } if (resourceGridBean.isGoal(res)) { selection.setCorrect(true); resourceGridBean.removeGoalResource(); int rCnt=resourceGridBean.getResourceCount(); scoreDelta=(9-rCnt)*10; //Factor between 1.0 and 0.0 // 1.0 = No wrong guesses // 0.0 = 1/3 rCnt wrong guesses if (rCnt>0) //Should always be the case { double weight=Math.max(0.3-(double)wrongGuesses/rCnt, 0.0)/0.3; if (!player.isAi()) actionBean.updateRatings(descriptions, (0.5+0.05*rCnt)*weight); } newGoal(); player.addNotifierAll("clearResource"); player.addNotifierAll("edit"); player.addNotifierAll("shakeheading"); wrongGuesses=0; if (resourceGridBean.getResourceCount()==1) newRound(); } else { int rCnt=resourceGridBean.getResourceCount(); selection.setCorrect(false); //actionBean.updateDescriptions(descriptions, -1.0/rCnt); wrongGuesses++; scoreDelta=-(10-rCnt)*11; player.addNotifier("shakeheading"); } actionBean.performAction(selection, player.getGameRound()); setScore(getScore()+scoreDelta); gameRound.setScore((int)getRoundScore()); resourceGridBean.setSelected(null); player.signalPartner("images"); player.signalAll("tags"); player.signalAll("score"); } else resourceGridBean.setSelected(res); } } //Describer else { if (resourceGridBean.getGoal()==null) { resourceGridBean.setGoal(res); resource=cloneResource(resourceGridBean.getGoal()); gameRound.getResources().add(resource); player.addNotifierAll("newResource"); player.signalPartner("edit"); player.signalAll("shakeheading"); } else player.signal("shakeheading"); } } }