Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package hu.bme.iit.quiz.endpoint; import hu.bme.iit.quiz.model.Quiz; import hu.bme.iit.quiz.model.User; import hu.bme.iit.quiz.util.EndpointUtil; import hu.bme.iit.quiz.xml.Question; import hu.bme.iit.quiz.xml.QuestionOption; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.inject.Singleton; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import org.apache.log4j.Logger; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONStringer; @Singleton @ServerEndpoint(value = "/pollendpoint/{presentationID}") public class PollEndpoint { private static final Logger logger = Logger.getLogger(PollEndpoint.class); private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>()); // <presentationID, quiz> pattern: a user only can have one quiz in active phase private static Map<Integer, QuizRoom> quizzesInOngoingPhase = Collections .synchronizedMap(new HashMap<Integer, QuizRoom>()); // <SESSIONid, USERKEY> private static Map<String, String> userSessions = Collections.synchronizedMap(new HashMap<String, String>()); //userkey []questionNum[1]selectedoptionnum private static Map<String, Integer[]> userAnswers = Collections .synchronizedMap(new HashMap<String, Integer[]>()); @OnMessage public String onMessage(String jMessage, Session session, @PathParam("presentationID") Integer presentationID) { logger.debug("onMessage websocket event: " + jMessage); JSONObject message = new JSONObject(jMessage); try { logger.debug("onMessage type: " + message.getString("type")); switch (message.getString("type")) { case "JOIN": joinRoom(session, presentationID, message.getString("userkey")); break; case "START": if (isQuizOwner(presentationID, session)) { sendQuizQestion(session, presentationID, message.getString("userkey"), 0); } break; case "NEXT": if (isQuizOwner(presentationID, session)) { sendQuizQestion(session, presentationID, message.getString("userkey"), message.getInt("questionID")); } break; case "SHOWCORRECT": if (isQuizOwner(presentationID, session)) { sendActualQestionCorrection(session, presentationID, message.getString("userkey")); } break; case "ANSWER": setUserAnswer(session, presentationID, message.getString("userkey"), message.getInt("optionNum")); break; default: logger.warn("Websocket SWITCH drive in default case."); break; } } catch (JSONException e) { logger.error(e); } return null; } @OnOpen public void onOpen(final Session session, @PathParam("presentationID") Integer presentationID) { logger.debug("onOpen websocket event id: " + session.getId()); peers.add(session); if (!quizzesInOngoingPhase.containsKey(presentationID)) { QuizRoom newQuizRoom = new QuizRoom(presentationID); quizzesInOngoingPhase.put(presentationID, newQuizRoom); newQuizRoom.initQuizPresentation(); } } @OnClose public void onClose(Session peer, @PathParam("presentationID") Integer presentationID) { logger.debug("onClose from client: " + peer.getId() + " presid: " + presentationID); quizzesInOngoingPhase.get(presentationID).removeFollower(userSessions.get(peer.getId())); userSessions.remove(peer.getId()); peers.remove(peer); EndpointUtil.sendUpdateToAll(peers, createFollowersUpdateString(presentationID)); } private void joinRoom(Session session, Integer presentationID, String userkey) { userSessions.put(session.getId(), userkey); if (isQuizOwner(presentationID, session)) { quizzesInOngoingPhase.get(presentationID).setOwnerPeer(session); } quizzesInOngoingPhase.get(presentationID).addFollower(userkey); EndpointUtil.sendUpdateToAll(peers, createFollowersUpdateString(presentationID)); //If quiz is ongoing logger.debug("ActualQuestionAtJoin: " + quizzesInOngoingPhase.get(presentationID).getActualQuestion()); if (quizzesInOngoingPhase.get(presentationID).getActualQuestion() > -1) { EndpointUtil.sendUpdateToPeer(session, createQuizQuestionUpdateString(presentationID, quizzesInOngoingPhase.get(presentationID).getActualQuestion())); } } private void sendQuizQestion(Session session, Integer presentationID, String userkey, Integer questionID) { logger.debug("sendQuizQestion function start: " + session.getId()); quizzesInOngoingPhase.get(presentationID).setActualQuestion(questionID); EndpointUtil.sendUpdateToAll(peers, createQuizQuestionUpdateString(presentationID, questionID)); for (String secretkey : quizzesInOngoingPhase.get(presentationID).getFollowers().keySet()) { this.storeUserAnswer(presentationID, secretkey, -1); } EndpointUtil.sendUpdateToPeer(quizzesInOngoingPhase.get(presentationID).getOwnerPeer(), createUserAnswerUpdateString(presentationID)); logger.debug("sendQuizQestion function finish: " + session.getId()); } private void setUserAnswer(Session session, Integer presentationID, String userkey, int answerNum) { logger.debug("setUserAnswer function start"); this.storeUserAnswer(presentationID, userkey, answerNum); EndpointUtil.sendUpdateToPeer(quizzesInOngoingPhase.get(presentationID).getOwnerPeer(), createUserAnswerUpdateString(presentationID)); } private void storeUserAnswer(Integer presentationID, String userkey, int answerNum) { if (!userAnswers.containsKey(userkey)) { Integer[] answers = new Integer[quizzesInOngoingPhase.get(presentationID).getQuizData().getContent() .getQuestion().size()]; userAnswers.put(userkey, answers); } Integer[] answers = userAnswers.get(userkey); answers[quizzesInOngoingPhase.get(presentationID).getActualQuestion()] = answerNum; userAnswers.put(userkey, answers); } private void sendActualQestionCorrection(Session session, Integer presentationID, String string) { List<QuestionOption> questionOptions = quizzesInOngoingPhase.get(presentationID).getQuizData().getContent() .getQuestion().get(quizzesInOngoingPhase.get(presentationID).getActualQuestion()) .getQuestionContent().getQuestionOption(); int i = 0; List<Integer> corrects = new ArrayList<Integer>(); for (QuestionOption option : questionOptions) { if (option.isIsCorrect()) { corrects.add(i); } i++; } EndpointUtil.sendUpdateToAll(peers, createQuizCorrectionString(corrects)); } private boolean isQuizOwner(Integer presentationID, Session peer) { return quizzesInOngoingPhase.get(presentationID).getQuizPresentation().getOwner().getSecretkey() .equalsIgnoreCase(userSessions.get(peer.getId())); } private String createFollowersUpdateString(Integer presentationID) { JSONStringer creator = new JSONStringer(); creator.object().key("type").value("FOLLOWERSUPDATE").key("followers").array(); Map<String, User> users = quizzesInOngoingPhase.get(presentationID).getFollowers(); for (String key : users.keySet()) { User user = users.get(key); creator.object().key("username").value(user.getLogin()).endObject(); } creator.endArray().endObject(); return creator.toString(); } private String createQuizQuestionUpdateString(Integer presentationID, Integer questionID) { logger.debug("sendQuizQestion createQuizQuestionUpdateString start: questionID: " + questionID); JSONStringer creator = new JSONStringer(); Question question = quizzesInOngoingPhase.get(presentationID).getQuestionData(questionID); creator.object().key("type").value("QUESTION").key("questionTitle").value(question.getQuestionTitle()) .key("questionID").value(questionID).key("questionBody").value(question.getQuestionBody()) .key("options").array(); for (QuestionOption option : question.getQuestionContent().getQuestionOption()) { creator.object().key("optionBody").value(option.getQuestionOptionBody()).endObject(); } creator.endArray().endObject(); logger.debug("sendQuizQestion createQuizQuestionUpdateString finish"); return creator.toString(); } private String createUserAnswerUpdateString(Integer presentationID) { JSONStringer creator = new JSONStringer(); QuizRoom quiz = quizzesInOngoingPhase.get(presentationID); creator.object().key("type").value("ANSWERUPDATE").key("answers").array(); for (String secretkey : userAnswers.keySet()) { User user = EndpointUtil.getUserByKey(secretkey); creator.object().key("username").value(user.getLogin()).key("selected").value( userAnswers.get(secretkey)[quizzesInOngoingPhase.get(presentationID).getActualQuestion()]) .endObject(); } creator.endArray().endObject(); return creator.toString(); } private String createQuizCorrectionString(List<Integer> corrects) { JSONStringer creator = new JSONStringer(); creator.object().key("type").value("CORRECTION").key("corrects").array(); for (Integer correct : corrects) { creator.object().key("optionID").value(correct).endObject(); } creator.endArray().endObject(); return creator.toString(); } }