Guest User

Untitled

a guest
Jul 9th, 2018
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 17.99 KB | None | 0 0
  1. package server;
  2.  
  3. import java.nio.charset.Charset;
  4. import java.util.ArrayList;
  5. import java.util.HashMap;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Random;
  9. import java.util.Timer;
  10. import java.util.TimerTask;
  11. import java.util.concurrent.BlockingQueue;
  12. import java.util.concurrent.ExecutorService;
  13. import java.util.concurrent.Executors;
  14. import java.util.concurrent.LinkedBlockingQueue;
  15.  
  16. import org.apache.commons.mail.DefaultAuthenticator;
  17. import org.apache.commons.mail.Email;
  18. import org.apache.commons.mail.EmailException;
  19. import org.apache.commons.mail.SimpleEmail;
  20. import org.jboss.netty.channel.Channel;
  21. import org.jboss.netty.channel.group.DefaultChannelGroup;
  22. import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
  23. import org.jboss.netty.util.internal.ConcurrentHashMap;
  24.  
  25. import quiz.shared.LoginResponseType;
  26. import quiz.shared.LoginType;
  27. import quiz.shared.MessageType;
  28. import server.SocketEventObject;
  29. import server.SocketEventType;
  30. import server.dto.Forgot;
  31. import server.dto.InRoom;
  32. import server.dto.IncomingMessageType;
  33. import server.dto.Login;
  34. import server.dto.MessageFromUser;
  35. import server.dto.MessageToUser;
  36. import server.dto.ResponseLoginMsg;
  37. import server.dto.Round;
  38. import server.dto.Top;
  39. import server.dto.UserNumInRoom;
  40. import server.dto.WinningMessage;
  41. import server.entity.Question;
  42. import server.entity.User;
  43. import server.game.Room;
  44.  
  45. import com.google.gson.Gson;
  46. import com.google.gson.GsonBuilder;
  47.  
  48. public final class ReadQueueHandler  {
  49.  
  50.     static int maxUsersInRoom = 20;
  51.     static int votePersent = 50;
  52.     private final Charset charset = Charset.forName("UTF-8");
  53.  
  54.  
  55.     public static final HashMap<Integer, Integer> numOfCharsShowedInAnswer = new HashMap<Integer, Integer>();
  56.     static {
  57.         int v = 0;
  58.         for (int i = 0; i < 31; i++) {
  59.  
  60.             if (i > 2 && i % 2 != 0)
  61.                 v += 1;
  62.             numOfCharsShowedInAnswer.put(i, v);
  63.         }
  64.     }
  65.  
  66.     // key -> indifierName
  67.     private ConcurrentHashMap<String, Room> rooms;
  68.     private ConcurrentHashMap<String, DefaultChannelGroup> groups;
  69.     // лун -> Channel->getId()
  70.     private ConcurrentHashMap<Integer, User> users;
  71.     public Gson gson;
  72.     private Mng mng;
  73.  
  74.     // Очередь с вопросами
  75.     private QuestionsQueue questionQueue;
  76.  
  77.     private final BlockingQueue<SocketEventObject> socketEventObjectQueue;
  78.     private final ExecutorService threadPool;
  79.     private int threadPoolSize;
  80.     private boolean isActive = true;
  81.  
  82.     public ReadQueueHandler(int threadPoolSize) {
  83.         this.threadPoolSize = threadPoolSize;
  84.         this.threadPool = Executors.newFixedThreadPool(threadPoolSize);
  85.        
  86.     //
  87.        
  88.         this.socketEventObjectQueue = new LinkedBlockingQueue<SocketEventObject>();
  89.  
  90.         this.rooms = new ConcurrentHashMap<String, Room>();
  91.         this.groups = new ConcurrentHashMap<String, DefaultChannelGroup>();
  92.         this.users = new ConcurrentHashMap<Integer, User>();
  93.  
  94.         this.gson = new Gson();
  95.         this.mng = new Mng();
  96.         // инициализируем очередь(сразу заполнится 100 вопросами)
  97.         this.questionQueue = new QuestionsQueue(this.mng);
  98.  
  99.         //runRoundTimer();
  100.  
  101.     }
  102.  
  103.  
  104.     private void runMainLogic(){
  105.         SocketEventObject socketEventObject;
  106.         try {
  107.             socketEventObject = socketEventObjectQueue.take();
  108.  
  109.             System.out.println("TYPE: " + socketEventObject.getType());
  110.            
  111.             String jsonAsString = (String) socketEventObject
  112.             .getObject();
  113.             System.out.println("MSG: " + jsonAsString);
  114.            
  115.             System.out.println("socketEventObject.getType(): " + socketEventObject.getType());
  116.            
  117.             switch (socketEventObject.getType()) {
  118.            
  119.             case SocketEventType.CONNECTED:
  120.  
  121.                 Channel channel = socketEventObject.getChannel();
  122.                 System.out.println("CONNECTED CHANNEL ID: "
  123.                         + channel.getId());
  124.                 break;
  125.             case SocketEventType.DISCONNEDCED:
  126.                 disconnectedProcceed(socketEventObject);
  127.                 break;
  128.             case SocketEventType.MESSAGE:
  129.  
  130.                 System.out.println("SocketEventType.MESSAGE:" + (String) socketEventObject.getObject());
  131.  
  132.                 IncomingMessageType msg = gson.fromJson(jsonAsString,
  133.                         IncomingMessageType.class);
  134.                 switch (msg.getMessageType()) {
  135.                 case MessageType.LOGIN:
  136.                     System.out.println("LOGIN PROCCEED");
  137.                     loginProcceed(socketEventObject);
  138.                     break;
  139.                 case MessageType.MESSAGE:
  140.                     messageProcceed(socketEventObject);
  141.                     break;
  142.                 case MessageType.VOTE:
  143.                     voteProcceed(socketEventObject);
  144.                     break;
  145.                 case MessageType.TOP:
  146.                     topProcceed(socketEventObject);
  147.                     break;
  148.                 case MessageType.INROOM:
  149.                     inRoomProcceed(socketEventObject);
  150.                     break;
  151.                 case MessageType.FORGOT:
  152.                     forgotProcceed(socketEventObject);
  153.                     break;
  154.                 default:
  155.                     break;
  156.                 }
  157.                 break;
  158.             }
  159.         } catch (InterruptedException e) {
  160.             e.printStackTrace();
  161.         } catch (EmailException e) {
  162.             e.printStackTrace();
  163.         }
  164.     }
  165.  
  166.     private void forgotProcceed(SocketEventObject socketEventObject) throws EmailException {
  167.        
  168.         Forgot forgot = gson.fromJson(
  169.         (String) socketEventObject.getObject(), Forgot.class);
  170.         User user = getuserByEmail(forgot.getEmail());
  171.         if (user != null) {
  172.            
  173.             String tempBodyMail = new String("Your Username is: " + user.getName() + "\n" + "Your password is: " + user.getPassword()
  174.                     + "\n" + "Current experience: " + user.getExp() + "\n \n" + "Trivi Online, Welcome Back");
  175.            
  176.             String bodyEmail = new String(tempBodyMail.getBytes(charset), charset);
  177.            
  178.             Email email = new SimpleEmail();
  179.             email.setHostName("smtp.gmail.com");
  180.             email.setCharset("UTF-8");
  181.             email.setSmtpPort(587);
  182.             email.setAuthenticator(new DefaultAuthenticator("noreply@triviapp.net",
  183.                     "!qazxsw2"));
  184.             email.setTLS(true);
  185.             email.setFrom("noreply@triviapp.net");
  186.             email.setSubject("Recovery Password - Trivi Online");
  187.             email.setMsg(bodyEmail);
  188.             email.addTo(user.getEmail());
  189.             email.send();
  190.         }
  191.     }
  192.  
  193.     private void runRoundTimer() {
  194.  
  195.         Timer timer = new java.util.Timer();
  196.         TimerTask task = new TimerTask() {
  197.             public void run() {
  198.                 System.out.println("run timer");
  199.                
  200.                 System.out.println("Rooms: " + rooms.size());
  201.                 System.out.println("Users: " + users.size());
  202.                 System.out.println("Groups: " + groups.size());
  203.                 for(Map.Entry<String, DefaultChannelGroup> entry : groups.entrySet()) {
  204.                     System.out.println("Group(" + entry.getKey()+ ") size: " + entry.getValue().size());
  205.                 }  
  206.                
  207.                 for (Map.Entry<String, Room> entry : rooms.entrySet()) {
  208.                     String indifier = entry.getKey();
  209.                     Room room = entry.getValue();
  210.                     DefaultChannelGroup group = getGroupByIndifierName(indifier);
  211.                     if (((System.currentTimeMillis() / 1000) - room.roundStart) > 30
  212.                             && group.size() > 0) {
  213.                         System.out.println("fireNewRound");
  214.                         fireNewRound(room, group,true);
  215.                     }
  216.                 }
  217.             }
  218.         };
  219.         timer.scheduleAtFixedRate(task, 0, 30000);
  220.     }
  221.  
  222.     private void inRoomProcceed(SocketEventObject socketEventObject) {
  223.  
  224.         User user = getUserByChannelId(socketEventObject.getChannel().getId());
  225.         String indifierName = user.getIndifierName();
  226.  
  227.         DefaultChannelGroup channelGroup = getGroupByIndifierName(indifierName);
  228.  
  229.         ArrayList<User> users = new ArrayList<User>();
  230.         for (Channel ch : channelGroup) {
  231.             users.add(getUserByChannelId(ch.getId()));
  232.         }
  233.  
  234.         InRoom inRoom = new InRoom(users);
  235.         sendToUserExplisit(socketEventObject.getChannel(), inRoom, true);
  236.     }
  237.  
  238.     private void topProcceed(SocketEventObject socketEventObject) {
  239.  
  240.         DefaultChannelGroup group = getGroupByUserChannelId(socketEventObject
  241.                 .getChannel().getId());
  242.  
  243.         List<User> users = mng.ds.find(User.class).order("-exp").limit(20)
  244.                 .asList();
  245.  
  246.         Top top = new Top(users);
  247.         sendToUserExplisit(socketEventObject.getChannel(), top, true);
  248.     }
  249.  
  250.     private void fireNewRound(Room room, DefaultChannelGroup group) {
  251.         room.resetVote();
  252.         room.setQuestionWithTime(getQuestion());
  253.         sendToGroup(group, getRoundDTO(room));
  254.     }
  255.    
  256.     private void fireNewRound(Room room, DefaultChannelGroup group, Boolean lastAnswer) {
  257.         String answer = room.getQuestion().getAnswer();
  258.        
  259.         room.resetVote();
  260.         room.setQuestionWithTime(getQuestion());
  261.         Round round = getRoundDTO(room);
  262.         round.setLastAnswer(answer);
  263.         sendToGroup(group, round);
  264.     }
  265.  
  266.     private boolean isVoteFired(int usersInRoom, int usersVotedNum) {
  267.         if (usersInRoom == 0)
  268.             return false;
  269.  
  270.         if (((usersVotedNum * 100) / usersInRoom) > votePersent)
  271.             return true;
  272.         return false;
  273.     }
  274.  
  275.     private void voteProcceed(SocketEventObject socketEventObject) {
  276.         Room room = getRoomByUserChannelId(socketEventObject.getChannel()
  277.                 .getId());
  278.         DefaultChannelGroup group = getGroupByUserChannelId(socketEventObject
  279.                 .getChannel().getId());
  280.  
  281.         int votesNum = room.incVote();
  282.         if (isVoteFired(group.size(), votesNum)) {
  283.             fireNewRound(room, group,true);
  284.         }
  285.     }
  286.  
  287.     private User getUserByChannelId(int channelId) {
  288.         return users.get(channelId);
  289.     }
  290.  
  291.     private Room getRoomByUserChannelId(int channelId) {
  292.         User user = getUserByChannelId(channelId);
  293.         return getRoomByIndifierName(user.getIndifierName());
  294.     }
  295.  
  296.     private Room getRoomByIndifierName(String indifierName) {
  297.         return rooms.get(indifierName);
  298.     }
  299.  
  300.     private DefaultChannelGroup getGroupByIndifierName(String indifierName) {
  301.         return groups.get(indifierName);
  302.     }
  303.  
  304.     private DefaultChannelGroup getGroupByUserChannelId(int channelId) {
  305.         User user = getUserByChannelId(channelId);
  306.         return getGroupByIndifierName(user.getIndifierName());
  307.     }
  308.  
  309.     private boolean checkForRightAnswer(Room room, String answer) {
  310.         if (room.getQuestion().getAnswer().toLowerCase().trim()
  311.                 .equals(answer.toLowerCase().trim())) {
  312.             return true;
  313.         }
  314.         return false;
  315.     }
  316.  
  317.     private int getExp(Room room, int numOfOpenedChars) {
  318.         int returnExp = (int) Math.round(10 - 0.1 * ((100 / room.getQuestion()
  319.                 .getAnswer().length()) * numOfOpenedChars));
  320.         System.out.println("Открытых букв в слове " + numOfOpenedChars);
  321.  
  322.         System.out.println("Дали экспу " + returnExp);
  323.         return returnExp;
  324.     }
  325.  
  326.     private void sendToUserExplisit(Channel channel, Object msg, boolean b) {
  327.         Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
  328.                 .create();
  329.         sendToUser(channel, gson.toJson(msg), true);
  330.     }
  331.  
  332.     private void messageProcceed(SocketEventObject socketEventObject) {
  333.  
  334.         MessageFromUser messageFromUser = gson.fromJson(
  335.                 (String) socketEventObject.getObject(), MessageFromUser.class);
  336.  
  337.         User user = getUserByChannelId(socketEventObject.getChannel().getId());
  338.         Room room = getRoomByIndifierName(user.getIndifierName());
  339.         DefaultChannelGroup group = getGroupByIndifierName(user
  340.                 .getIndifierName());
  341.  
  342.         sendToGroup(
  343.                 group,
  344.                 new MessageToUser(user.getName(), messageFromUser.getMessage()),
  345.                 socketEventObject.getChannel());
  346.         if (checkForRightAnswer(room, messageFromUser.getMessage())) {
  347.  
  348.             if (room.getLocked().compareAndSet(false, true)) {
  349.  
  350.                 String answer = room.getQuestion().getAnswer();
  351.                 fireNewRound(room, group);
  352.                 room.getLocked().set(false);
  353.  
  354.                 int exp = getExp(room, messageFromUser.getNumOfChars());
  355.                 sendToGroup(group, new WinningMessage(user.getName(), answer, exp));
  356.  
  357.                 getUserByChannelId(socketEventObject.getChannel().getId())
  358.                         .addExp(exp);
  359.             }
  360.         }
  361.     }
  362.  
  363.     private void disconnectedProcceed(SocketEventObject socketEventObject) {
  364.  
  365.         User user = users.get(socketEventObject.getChannel().getId());
  366.         if (user != null) {
  367.  
  368.             DefaultChannelGroup channelGroup = getGroupByIndifierName(user
  369.                     .getIndifierName());
  370.             channelGroup.remove(socketEventObject.getChannel());
  371.  
  372.             users.remove(socketEventObject.getChannel().getId());
  373.             mng.ds.save(user);
  374.         }
  375.     }
  376.  
  377.     private void sendToUser(Channel channel, Object object) {
  378.         sendToUser(channel, gson.toJson(object), true);
  379.     }
  380.  
  381.     private void sendToUser(Channel channel, String object, boolean b) {
  382.         if (channel.getPipeline().get("wsdecoder") != null) {
  383.             System.out.println("sending to ws");
  384.             channel.write(new TextWebSocketFrame(object));
  385.         } else {
  386.             System.out.println("sending to socket");
  387.             channel.write(object);
  388.         }
  389.     }
  390.  
  391.     private void sendToGroup(DefaultChannelGroup channelGroup, Object object) {
  392.  
  393.         for (Channel ch : channelGroup) {
  394.             sendToUser(ch, object);
  395.         }
  396.     }
  397.  
  398.     private void sendToGroup(DefaultChannelGroup channelGroup, String object,
  399.             boolean b) {
  400.  
  401.         for (Channel ch : channelGroup) {
  402.             sendToUser(ch, object, b);
  403.         }
  404.     }
  405.  
  406.     private void sendToGroup(DefaultChannelGroup group,
  407.             MessageToUser messageToUser, Channel channel) {
  408.  
  409.         for (Channel ch : group) {
  410.             if (!ch.equals(channel))
  411.                 sendToUser(ch, messageToUser);
  412.         }
  413.     }
  414.  
  415.     private void loginProcceed(SocketEventObject socketEventObject) {
  416.  
  417.         Login login = gson.fromJson((String) socketEventObject.getObject(),
  418.                 Login.class);
  419.         User user = getUserByUserName(login.getUsername());
  420.  
  421.         ResponseLoginMsg responseLoginMsg = getLoginResponse(login,
  422.                 (user == null) ? false : true, user);
  423.         sendToUser(socketEventObject.getChannel(), responseLoginMsg);
  424.  
  425.         System.out.println("loginProcceed before if");
  426.         System.out.println("responseLoginMsg.getType(): " + responseLoginMsg.getType());
  427.         System.out.println("LoginResponseType.OK: " + LoginResponseType.OK);
  428.        
  429.         if (responseLoginMsg.getType() == LoginResponseType.OK) {
  430.  
  431.             System.out.println("loginProcceed after if");
  432.            
  433.             if (user == null) {
  434.                 user = new User(login.getUsername(), login.getPassword(),login.getEmail().toLowerCase());
  435.                 mng.ds.save(user);
  436.             }
  437.  
  438.             System.out.println("user must exists!: " + user.getName());
  439.             addNewUser(user, socketEventObject.getChannel());
  440.             Room room = rooms.get(user.getIndifierName());
  441.             Round round = getRoundDTO(room);
  442.  
  443.             sendToUser(socketEventObject.getChannel(), round);
  444.         }
  445.     }
  446.  
  447.     private User getUserByUserName(String username) {
  448.         return mng.ds.find(User.class).field("username").containsIgnoreCase(username).get();
  449.     }
  450.    
  451.     private User getuserByEmail(String email) {
  452.         return mng.ds.find(User.class).field("email").equal(email.toLowerCase()).get();
  453.     }
  454.  
  455.     private ResponseLoginMsg getLoginResponse(Login login, boolean userExists,
  456.             User user) {
  457.  
  458.         ResponseLoginMsg response = new ResponseLoginMsg(
  459.                 LoginResponseType.USERNOTEXIST);
  460.  
  461.         if (!login.getUsername().isEmpty()) {
  462.  
  463.             String username = login.getUsername().toLowerCase();
  464.             String password = login.getPassword().toLowerCase();
  465.  
  466.             switch (login.getType()) {
  467.             case LoginType.NEWUSER:
  468.                 if (userExists == false && getuserByEmail(login.getEmail())==null) {
  469.                     response = new ResponseLoginMsg(LoginResponseType.OK);
  470.                 } else {
  471.                     response = new ResponseLoginMsg(LoginResponseType.USEREXIST);
  472.                 }
  473.                 break;
  474.             case LoginType.EXISTUSER:
  475.                 if (userExists == true && user.getPassword().toLowerCase().equals(password.toLowerCase())) {
  476.                     response = new ResponseLoginMsg(LoginResponseType.OK);
  477.                 } else {
  478.                     response = new ResponseLoginMsg(
  479.                             LoginResponseType.USERNOTEXIST);
  480.                 }
  481.                 break;
  482.             case LoginType.FACEBOOK:
  483.                 response = new ResponseLoginMsg(LoginResponseType.OK);
  484.                 break;
  485.             }
  486.         }
  487.         return response;
  488.     }
  489.  
  490.     private void addNewUser(User user, Channel channel) {
  491.         String indifierName = getRoomWithMinGroup();
  492.         if (indifierName == null) {
  493.             indifierName = allocateNewRoom();
  494.         }
  495.  
  496.         addUserToChannelGroup(indifierName, channel);
  497.         user.setIndifierName(indifierName);
  498.         users.put(channel.getId(), user);
  499.         fireSendUserNumInGroup(indifierName);
  500.     }
  501.  
  502.     private void fireSendUserNumInGroup(String indifierName) {
  503.         DefaultChannelGroup channelGroup = getGroupByIndifierName(indifierName);
  504.         sendToGroup(channelGroup, new UserNumInRoom(channelGroup.size()));
  505.     }
  506.  
  507.     private void addUserToChannelGroup(String indifierName, Channel channel) {
  508.         DefaultChannelGroup channelGroup = groups.get(indifierName);
  509.         channelGroup.add(channel);
  510.     }
  511.  
  512.     // index of room and group
  513.     private String allocateNewRoom() {
  514.  
  515.         String channelName = createChannelGroup();
  516.         Room room = createRoom();
  517.         rooms.put(channelName, room);
  518.         return channelName;
  519.     }
  520.  
  521.     private String createChannelGroup() {
  522.  
  523.         String channelName = (new Long(System.currentTimeMillis())).toString();
  524.         DefaultChannelGroup channelGroup = new DefaultChannelGroup(channelName);
  525.         groups.put(channelName, channelGroup);
  526.         return channelName;
  527.     }
  528.  
  529.     private String getRoomWithMinGroup() {
  530.  
  531.         for (DefaultChannelGroup cg : groups.values()) {
  532.             if (cg.size() < maxUsersInRoom) {
  533.                 return cg.getName();
  534.             }
  535.         }
  536.         return null;
  537.     }
  538.  
  539.     private void removeGroup(DefaultChannelGroup channelGroup) {
  540.         groups.remove(channelGroup);
  541.         channelGroup.close();
  542.     }
  543.  
  544.     private Room createRoom() {
  545.         Room room = new Room();
  546.         room.setQuestion(getQuestion());
  547.         return room;
  548.     }
  549.  
  550.     private Question getQuestion() {
  551.         // очередь из n вопросов
  552.         // Random random = new Random();
  553.         // Question question = new Question();
  554.         Question question = questionQueue.getNextQuestion();
  555.         System.out.println("QUESTIOn:" + question.getQuestion());
  556.         // question.setQuestion("question_"
  557.         // + new Integer(random.nextInt()).toString());
  558.         // question.setAnswer("answer" + new
  559.         // Integer(random.nextInt()).toString());
  560.         return question;
  561.     }
  562.  
  563.     public void addEventObject(Channel channel, Object object, int type) {
  564.         System.out.println("addEventObject: " + object.toString());
  565.         socketEventObjectQueue
  566.                 .add(new SocketEventObject(channel, object, type));
  567.         runMainLogic();
  568.     }
  569.  
  570.     private Round getRoundDTO(Room room) {
  571.  
  572.         Question q = room.getQuestion();
  573.         Round round = new Round();
  574.         round.setAnswer(getAnswerMap(q.getAnswer()));
  575.         round.setQuestion(q.getQuestion() + "( " + q.getAnswer() + ")");
  576.         round.setCharsNum(q.getAnswer().length());
  577.         return round;
  578.     }
  579.  
  580.     private Map<Integer, String> getAnswerMap(String answer) {
  581.  
  582.         int answerLength = answer.length();
  583.         int numOfChars = numOfCharsShowedInAnswer.get(answerLength);
  584.  
  585.         Random random = new Random();
  586.  
  587.         Map<Integer, String> tmp = new HashMap<Integer, String>();
  588.         int count = 0;
  589.         do {
  590.             int rnd = (random.nextInt(answerLength));
  591.             if (!tmp.containsKey(rnd)) {
  592.                 count++;
  593.                 tmp.put(rnd, (new Character(answer.charAt(rnd))).toString());
  594.             }
  595.         } while (count < (numOfChars));
  596.  
  597.         return tmp;
  598.     }
  599. }
Add Comment
Please, Sign In to add comment