From 0b6ac1b733218927c2c69b8f9e2e4c15e9f7da78 Mon Sep 17 00:00:00 2001
From: fpeterfalvi <fpeterfalvi@gmail.com>
Date: Tue, 1 May 2018 17:36:12 +0200
Subject: [PATCH] Observer displays multiple choice questions

---
 .gitignore                                    |   1 +
 .../kvizclient/MultipleChoiceFragment.java    |  14 +-
 KvizObserver/pom.xml                          |   5 +
 KvizObserver/src/images/arrow_left.png        | Bin 0 -> 326 bytes
 KvizObserver/src/images/arrow_right.png       | Bin 0 -> 331 bytes
 KvizObserver/src/main/java/FontResizable.java |   3 +
 KvizObserver/src/main/java/Main.java          | 124 ++++++----
 .../java/MultipleChoiceQuestionPanel.java     | 213 ++++++++++++++++++
 .../src/main/java/model/PlayerAnswer.java     |  44 ++++
 .../java/onlab/kvizserver/GameActivity.java   |  27 ++-
 .../java/onlab/kvizserver/LobbyActivity.java  |   1 +
 .../java/onlab/kvizserver/ObserverHolder.java |  30 +++
 12 files changed, 406 insertions(+), 56 deletions(-)
 create mode 100644 KvizObserver/src/images/arrow_left.png
 create mode 100644 KvizObserver/src/images/arrow_right.png
 create mode 100644 KvizObserver/src/main/java/FontResizable.java
 create mode 100644 KvizObserver/src/main/java/MultipleChoiceQuestionPanel.java
 create mode 100644 KvizObserver/src/main/java/model/PlayerAnswer.java
 create mode 100644 KvizServer/app/src/main/java/onlab/kvizserver/ObserverHolder.java

diff --git a/.gitignore b/.gitignore
index effed22..e98a0ab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@
 /KvizServer/.idea/codeStyles/Project.xml
 /KvizServer/.idea/caches/build_file_checksums.ser
 /KvizClient/.idea/codeStyles/Project.xml
+/KvizClient/app/src/main/java/onlab/kvizclient/LobbyActivity.java.orig
diff --git a/KvizClient/app/src/main/java/onlab/kvizclient/MultipleChoiceFragment.java b/KvizClient/app/src/main/java/onlab/kvizclient/MultipleChoiceFragment.java
index ed230c6..09bfd7d 100644
--- a/KvizClient/app/src/main/java/onlab/kvizclient/MultipleChoiceFragment.java
+++ b/KvizClient/app/src/main/java/onlab/kvizclient/MultipleChoiceFragment.java
@@ -169,13 +169,15 @@ public class MultipleChoiceFragment extends Fragment {
             LinearLayout multipleChoiceFragmentLinearLayout = (LinearLayout) getView().findViewById(R.id.MultipleChoiceFragmentLinearLayout);
             for (int i=0;i<playerAnswers.size();i++) {
                 if (i != own_index) {
-                    final TextView playerAnswerTextView = new TextView(getActivity());
                     PlayerAnswer answer = playerAnswers.get(i);
-                    playerAnswerTextView.setText(answer.getPlayerName() + ": "
-                            + answers[answer.getValue()]);
-                    playerAnswerTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
-                    playerAnswerTextView.setPadding(20,30,20,0);
-                    multipleChoiceFragmentLinearLayout.addView(playerAnswerTextView);
+                    if (answer.getValue() > -1) {
+                        final TextView playerAnswerTextView = new TextView(getActivity());
+                        playerAnswerTextView.setText(answer.getPlayerName() + ": "
+                                + answers[answer.getValue()]);
+                        playerAnswerTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
+                        playerAnswerTextView.setPadding(20,30,20,0);
+                        multipleChoiceFragmentLinearLayout.addView(playerAnswerTextView);
+                    }
                 }
             }
         }
diff --git a/KvizObserver/pom.xml b/KvizObserver/pom.xml
index b6fbe3e..c1eafbe 100644
--- a/KvizObserver/pom.xml
+++ b/KvizObserver/pom.xml
@@ -66,6 +66,11 @@ The project was originally started in December 2002 by Arthur van Hoff at Strang
 			<version>3.3.1</version>
 			<scope>test</scope>
 		</dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.3</version>
+        </dependency>
 	</dependencies>
 	<build>
 		<resources>
diff --git a/KvizObserver/src/images/arrow_left.png b/KvizObserver/src/images/arrow_left.png
new file mode 100644
index 0000000000000000000000000000000000000000..725e7aab6412baf1527c2a98e9293f29423ab59e
GIT binary patch
literal 326
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE694rhB3_q?e>0w}C<n?rM45?szdy$)y$$-K2
zqPTPLiUb>b?llsLZ4*8w%oBci?+Ysf8fcg}QR!#;GS<6)#IAgf4mh9hXjot0_~$R{
zr|;q??#C-YIp_Bja~%CMU19&96Z-a_PWS)$wAtXlC5)~7|K88|Pp6?W%KQJUIa|*K
zR;3Kl@ZRdd<m?Rxm~=KUaO)gk;wFmu<2&o|fS3aAqpY98#ZSb?7VyJZA2{GF9#iK!
cG%tZd<fwREKxxGE$>Lx+Pgg&ebxsLQ0HV==K>z>%

literal 0
HcmV?d00001

diff --git a/KvizObserver/src/images/arrow_right.png b/KvizObserver/src/images/arrow_right.png
new file mode 100644
index 0000000000000000000000000000000000000000..35f1a1f72c8bc79d951bf0f8de9ffdbc61e05177
GIT binary patch
literal 331
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE694rhB3_q?e>0w}C6!LU&45?szdogzHAqEN7
zgYSQ>;Pz_TbGSd=!O>H7!tVknE9Jy;26XV?`rosqMy{XoH*Xa?QGfe$xcG_qScUrR
z#y{U}D@z;yTxI>VUF^jF8^$mR#?yP!vh^O^iECgLOK4<`NMIC;I8gNiiDPyC9h1%m
z25y}LOxzm|F!`~^gVey4Pp_0#_#ghnz3%74__`<4<$pefG3Wn(4r3yTLYR@aetKHl
zXFgYd`)A4A`CC3uE~~qA&L1Yoex4uQV+;q_?LL&(rZoP^2T6Il`njxgN@xNA_?Lph

literal 0
HcmV?d00001

diff --git a/KvizObserver/src/main/java/FontResizable.java b/KvizObserver/src/main/java/FontResizable.java
new file mode 100644
index 0000000..80e3877
--- /dev/null
+++ b/KvizObserver/src/main/java/FontResizable.java
@@ -0,0 +1,3 @@
+public interface FontResizable {
+    public void setFontSize(int fontSize);
+}
diff --git a/KvizObserver/src/main/java/Main.java b/KvizObserver/src/main/java/Main.java
index 46b73f5..3f0bb70 100644
--- a/KvizObserver/src/main/java/Main.java
+++ b/KvizObserver/src/main/java/Main.java
@@ -10,9 +10,6 @@ import java.net.InetAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
-import java.util.Scanner;
-import java.util.concurrent.Callable;
-import java.util.concurrent.FutureTask;
 
 import javax.jmdns.JmDNS;
 import javax.jmdns.ServiceEvent;
@@ -21,8 +18,12 @@ import javax.jmdns.ServiceListener;
 import javax.swing.*;
 import javax.swing.border.EmptyBorder;
 
+import com.google.gson.Gson;
+import model.PlayerAnswer;
 import model.ServerModel;
 
+import java.util.List;
+
 public class Main {
     
     private String TAG = "Client";
@@ -49,6 +50,7 @@ public class Main {
     private static JFrame frame;
     private static JPanel mainPanel;
     private static JPanel serverListPanel;
+    private static FontResizable actualFontResizable = null;
 
     private static class SampleListener implements ServiceListener {
         @Override
@@ -113,71 +115,65 @@ public class Main {
         threads = new ArrayList<Thread>();
 
         frame = new JFrame("KvizObserver");
-        mainPanel = new JPanel(new CardLayout());
+        mainPanel = new JPanel(new BorderLayout());
 
         JPanel observerNamePanel = new JPanel();
+        observerNamePanel.setBorder(new EmptyBorder(20, 20, 20, 20));
         observerNamePanel.setLayout(new BoxLayout(observerNamePanel, BoxLayout.Y_AXIS));
         JLabel observerNameLabel = new JLabel("Observer name:");
         observerNamePanel.add(observerNameLabel);
         JTextField observerNameTextField = new JTextField();
+        observerNameTextField.setMaximumSize(new Dimension(200, 100));
         observerNamePanel.add(observerNameTextField);
         JButton startSearchingButton = new JButton("Start searching servers");
         startSearchingButton.addActionListener(new StartSearchingButtonListener(observerNameTextField));
         observerNamePanel.add(startSearchingButton);
-        mainPanel.add(observerNamePanel, "OBSERVER_NAME_PANEL");
+        mainPanel.add(observerNamePanel);
 
         serverListPanel = new JPanel();
         serverListPanel.setLayout(new BoxLayout(serverListPanel, BoxLayout.Y_AXIS));
-        mainPanel.add(serverListPanel, "SERVER_LIST_PANEL");
+
+        JMenuItem fontSizeMenuItem = new JMenuItem("Font size");
+        fontSizeMenuItem.addActionListener(new setFontSizeButtonListener()); // adding listener
+        JMenu menu = new JMenu("Menu");
+        menu.add(fontSizeMenuItem);
+        JMenuBar bar = new JMenuBar();
+        bar.add(menu);
+        frame.setJMenuBar(bar);
 
         frame.add(mainPanel, BorderLayout.NORTH);
-        frame.setPreferredSize(new Dimension(300, 200));
+        frame.setPreferredSize(new Dimension(600, 400));
         frame.pack();
         frame.setLocationRelativeTo(null);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
 
-        //try {
-
-
-            //System.out.println("Set The ObserverName:");
-            //Scanner s = new Scanner(System.in);
-            //CLIENT_NAME = s.nextLine();
-
-            
-            // Create a JmDNS instance
-            //JmDNS jmdns = JmDNS.create(InetAddress.getLocalHost());
-            
-            
 
-            // Add a service listener
-            //jmdns.addServiceListener("_http._tcp.local.", new SampleListener());
 
-            // Wait a bit
-            //Thread.sleep(3000);
-            
-            //String msg = "";
-            
-            
-            /*Scanner s = new Scanner(System.in);
-            System.out.println("Type 'Connect' to Connect:");
-            msg = s.nextLine();
-            if(msg.equals("Connect"))
-            {
-                onConnect(0);
-            }
-            System.out.println("Type 'Disconnect' to Disconnect:");
-            msg = s.nextLine();
-            if(msg.equals("Disconnect"))
-            {
-                onDisconnect();
-            }*/
-        /*} catch (UnknownHostException e) {
-            System.out.println(e.getMessage());
-        } catch (IOException e) {
-            System.out.println(e.getMessage());*/
-        //}
-        
+        //teszteléshez
+        /*
+        PlayerAnswer pla = new PlayerAnswer("játékos");
+        pla.setValue(2);
+        pla.setTime(3.3);
+        PlayerAnswer pla2 = new PlayerAnswer("játékos2");
+        pla2.setValue(2);
+        pla2.setTime(3.3);
+        PlayerAnswer pla3 = new PlayerAnswer("játékos3");
+        pla3.setValue(2);
+        pla3.setTime(3.3);
+        List<PlayerAnswer> plalist = new ArrayList<>();
+        plalist.add(pla);
+        plalist.add(pla2);
+        plalist.add(pla3);
+        Gson gson = new Gson();
+        MultipleChoiceQuestionPanel mcqp = new MultipleChoiceQuestionPanel("Melyik a leghosszabb szó? Melyik? Melyik? Melyik? Melyik?", "alma",
+                "paradicsom", "görögdinnye", "őszibarack", gson.toJson(plalist), 1, -1);
+        actualFontResizable = mcqp;
+        mainPanel.removeAll();
+        mainPanel.add(mcqp);
+        mainPanel.revalidate();
+        mainPanel.repaint();
+        */
     }
 
     final static class StartSearchingButtonListener implements ActionListener {
@@ -187,8 +183,10 @@ public class Main {
         }
         public void actionPerformed(ActionEvent ae) {
             CLIENT_NAME = tf.getText();
-            CardLayout cl = (CardLayout)(mainPanel.getLayout());
-            cl.show(mainPanel, "SERVER_LIST_PANEL");
+            mainPanel.removeAll();
+            mainPanel.add(serverListPanel);
+            mainPanel.revalidate();
+            mainPanel.repaint();
 
             try {
                 // Create a JmDNS instance
@@ -260,6 +258,25 @@ public class Main {
         }
     }
 
+    static class setFontSizeButtonListener implements ActionListener {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            String s = (String) JOptionPane.showInputDialog(
+                    frame,
+                    "Font size: ",
+                    "Set font size",
+                    JOptionPane.PLAIN_MESSAGE,
+                    null,
+                    null,null);
+
+            if (s != null) {
+                actualFontResizable.setFontSize(Integer.parseInt(s));
+                System.out.println("Új betűméret: " + s);
+                return;
+            }
+        }
+    }
+
     class CommunicationThread implements Runnable {
 
         private ServerModel serverModel;
@@ -328,6 +345,17 @@ public class Main {
                                     exit = false;
                                     //majd
                                     break;
+                                case "questionMC":
+                                case "answerMC":
+                                    MultipleChoiceQuestionPanel mcqp = new MultipleChoiceQuestionPanel(params[1], params[2],
+                                            params[3], params[4], params[5], params[6], Integer.parseInt(params[7]),
+                                            Integer.parseInt(params[8]));
+                                    actualFontResizable = mcqp;
+                                    mainPanel.removeAll();
+                                    mainPanel.add(mcqp);
+                                    mainPanel.revalidate();
+                                    mainPanel.repaint();
+                                    break;
                                 case "Disconnect":
                                     break;
                                 default:
diff --git a/KvizObserver/src/main/java/MultipleChoiceQuestionPanel.java b/KvizObserver/src/main/java/MultipleChoiceQuestionPanel.java
new file mode 100644
index 0000000..c571ffa
--- /dev/null
+++ b/KvizObserver/src/main/java/MultipleChoiceQuestionPanel.java
@@ -0,0 +1,213 @@
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import javafx.scene.control.ProgressBar;
+import model.PlayerAnswer;
+
+import javax.imageio.ImageIO;
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+public class MultipleChoiceQuestionPanel extends JPanel implements FontResizable {
+
+    private static final String LEFT_ARROW_PATH = "src/images/arrow_left.png";
+    private static final String RIGHT_ARROW_PATH = "src/images/arrow_right.png";
+    private JProgressBar progressBar;
+
+    private static float fontSize = 60.0f;
+    private int arrowSize;
+
+    private String question;
+    private String answer1;
+    private String answer2;
+    private String answer3;
+    private String answer4;
+    private String playerAnswersString;
+    private int correctAnswer;
+    private int timeOut;
+
+    public MultipleChoiceQuestionPanel(String question, String answer1, String answer2, String answer3, String answer4,
+                                       String playerAnswersString, int correctAnswer, int timeOut) {
+        this.question = question;
+        this.answer1 = answer1;
+        this.answer2 = answer2;
+        this.answer3 = answer3;
+        this.answer4 = answer4;
+        this.playerAnswersString = playerAnswersString;
+        this.correctAnswer = correctAnswer;
+        this.timeOut = timeOut;
+
+        initialize();
+
+        if (timeOut > -1) {
+            ProgressBarThread pbt = new ProgressBarThread();
+            Thread progressBarThread = new Thread(pbt);
+            progressBarThread.start();
+        }
+
+    }
+
+    class ProgressBarThread implements Runnable {
+
+        private long startTime;
+
+        public ProgressBarThread() {
+            startTime = new Date().getTime();
+        }
+
+        @Override
+        public void run() {
+            long currentTime = new Date().getTime();
+            while (currentTime - startTime < timeOut) {
+
+                progressBar.setValue((int) (timeOut - currentTime + startTime));
+                try {
+                    Thread.sleep(20);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                currentTime = new Date().getTime();
+            }
+        }
+    }
+
+    private void initialize() {
+        this.removeAll();
+        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+        if (timeOut > -1) {
+            progressBar = new JProgressBar(0, timeOut);
+            this.add(progressBar);
+        }
+        JTextArea questionTextArea = new JTextArea(question);
+        questionTextArea.setBackground(this.getBackground());
+        questionTextArea.setBorder(new EmptyBorder(20,20,20,20));
+        questionTextArea.setEditable(false);
+        questionTextArea.setWrapStyleWord(true);
+        questionTextArea.setLineWrap(true);
+        Font bigFont = questionTextArea.getFont().deriveFont(fontSize);
+        questionTextArea.setFont(bigFont);
+        questionTextArea.setAlignmentX(Component.LEFT_ALIGNMENT);
+        this.add(questionTextArea);
+        JLabel[] answerLabels = new JLabel[4];
+        JLabel[] leftArrows = new JLabel[4];
+        JLabel[] rightArrows = new JLabel[4];
+        String[] answers = new String[4];
+        answers[0] = answer1;
+        answers[1] = answer2;
+        answers[2] = answer3;
+        answers[3] = answer4;
+        arrowSize = (int) (192 * fontSize / 200);
+        for (int i=0;i<4;i++) {
+            JPanel answerPanel = new JPanel(new FlowLayout());
+            answerPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+            leftArrows[i] = new JLabel();
+            leftArrows[i].setPreferredSize(new Dimension(arrowSize, arrowSize));
+            answerLabels[i] = new JLabel(answers[i]);
+            answerLabels[i].setFont(bigFont);
+            answerLabels[i].setMinimumSize(new Dimension((int) (10 * fontSize), (int) (1.1 * fontSize)));
+            answerLabels[i].setPreferredSize(new Dimension((int) (10 * fontSize), (int) (1.1 * fontSize)));
+            answerLabels[i].setMaximumSize(new Dimension((int) (10 * fontSize), (int) (1.1 * fontSize)));
+            answerLabels[i].setHorizontalAlignment(JLabel.CENTER);
+            rightArrows[i] = new JLabel();
+            rightArrows[i].setPreferredSize(new Dimension(arrowSize, arrowSize));
+            answerPanel.add(leftArrows[i]);
+            answerPanel.add(answerLabels[i]);
+            answerPanel.add(rightArrows[i]);
+            this.add(answerPanel);
+        }
+
+        Gson gson = new Gson();
+        Type collectionType = new TypeToken<Collection<PlayerAnswer>>(){}.getType();
+        Collection<PlayerAnswer> playerAnswerCollection = gson.fromJson(playerAnswersString, collectionType);
+        List<PlayerAnswer> playerAnswers = new ArrayList<PlayerAnswer>(playerAnswerCollection);
+
+        if (correctAnswer > -1) {
+            answerLabels[correctAnswer].setBackground(Color.GREEN);
+            answerLabels[correctAnswer].setOpaque(true);
+        }
+
+        if (playerAnswers.size() <= 2) {
+            int firstPlayerAnswer = playerAnswers.get(0).getValue();
+            if (firstPlayerAnswer > -1) {
+                try {
+                    BufferedImage img = null;
+                    img = ImageIO.read(new File(RIGHT_ARROW_PATH));
+                    img = resizeImage(img, arrowSize, arrowSize);
+                    ImageIcon icon = new ImageIcon(img);
+                    leftArrows[firstPlayerAnswer].setIcon(icon);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                if (firstPlayerAnswer != correctAnswer) {
+                    answerLabels[firstPlayerAnswer].setBackground(Color.RED);
+                    answerLabels[firstPlayerAnswer].setOpaque(true);
+                }
+            }
+            if (playerAnswers.size() == 2) {
+                int secondPlayerAnswer = playerAnswers.get(1).getValue();
+                if (secondPlayerAnswer > -1) {
+                    try {
+                        BufferedImage img = null;
+                        img = ImageIO.read(new File(LEFT_ARROW_PATH));
+                        img = resizeImage(img, arrowSize, arrowSize);
+                        ImageIcon icon = new ImageIcon(img);
+                        rightArrows[secondPlayerAnswer].setIcon(icon);
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                    if (firstPlayerAnswer != correctAnswer) {
+                        answerLabels[secondPlayerAnswer].setBackground(Color.RED);
+                        answerLabels[secondPlayerAnswer].setOpaque(true);
+                    }
+                }
+            }
+        }
+
+        if (playerAnswers.size() > 2) {
+            for (int i=0;i<playerAnswers.size();i++) {
+                JLabel playerAnswerLabel = new JLabel();
+                playerAnswerLabel.setFont(bigFont);
+                playerAnswerLabel.setMinimumSize(new Dimension((int) (10 * fontSize), (int) (1.1 * fontSize)));
+                playerAnswerLabel.setPreferredSize(new Dimension((int) (10 * fontSize), (int) (1.1 * fontSize)));
+                playerAnswerLabel.setMaximumSize(new Dimension((int) (10 * fontSize), (int) (1.1 * fontSize)));
+                playerAnswerLabel.setHorizontalAlignment(JLabel.CENTER);
+
+                PlayerAnswer answer = playerAnswers.get(i);
+                if (answer.getValue() > -1) {
+                    playerAnswerLabel.setText(answer.getPlayerName() + ": "
+                            + answers[answer.getValue()]);
+                    this.add(playerAnswerLabel);
+                }
+            }
+        }
+    }
+
+    public static BufferedImage resizeImage(BufferedImage img, int width, int height) {
+        Image tmp = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
+        BufferedImage dimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+
+        Graphics2D g2d = dimg.createGraphics();
+        g2d.drawImage(tmp, 0, 0, null);
+        g2d.dispose();
+
+        return dimg;
+    }
+
+
+    @Override
+    public void setFontSize(int fontSize) {
+        this.fontSize = (float) fontSize;
+        initialize();
+        this.revalidate();
+        this.repaint();
+    }
+
+}
diff --git a/KvizObserver/src/main/java/model/PlayerAnswer.java b/KvizObserver/src/main/java/model/PlayerAnswer.java
new file mode 100644
index 0000000..3706cf8
--- /dev/null
+++ b/KvizObserver/src/main/java/model/PlayerAnswer.java
@@ -0,0 +1,44 @@
+package model;
+
+public class PlayerAnswer {
+    private String playerName;
+    private int value = -1;
+    private double time = 0;
+    private boolean winner = false;
+
+    public PlayerAnswer(String playerName) {
+        this.playerName = playerName;
+    }
+
+    public String getPlayerName() {
+        return playerName;
+    }
+
+    public void setPlayerName(String playerName) {
+        this.playerName = playerName;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public void setValue(int value) {
+        this.value = value;
+    }
+
+    public double getTime() {
+        return time;
+    }
+
+    public void setTime(double time) {
+        this.time = time;
+    }
+
+    public boolean isWinner() {
+        return winner;
+    }
+
+    public void setWinner(boolean winner) {
+        this.winner = winner;
+    }
+}
diff --git a/KvizServer/app/src/main/java/onlab/kvizserver/GameActivity.java b/KvizServer/app/src/main/java/onlab/kvizserver/GameActivity.java
index 4df3b55..47272be 100644
--- a/KvizServer/app/src/main/java/onlab/kvizserver/GameActivity.java
+++ b/KvizServer/app/src/main/java/onlab/kvizserver/GameActivity.java
@@ -78,6 +78,11 @@ public class GameActivity extends AppCompatActivity implements GameControlFragme
                         new OutputStreamWriter(ClientHolder.get(i).getClientsocket().getOutputStream())), true);
                 outputs.add(output);
             }
+            for (int i=0;i<ObserverHolder.size();i++) {
+                PrintWriter output = new PrintWriter(new BufferedWriter(
+                        new OutputStreamWriter(ObserverHolder.get(i).getClientsocket().getOutputStream())), true);
+                outputs.add(output);
+            }
         } catch (IOException e) {
             e.printStackTrace();
         }
@@ -201,7 +206,7 @@ public class GameActivity extends AppCompatActivity implements GameControlFragme
         }
 
         String playerAnswersString = gson.toJson(playerAnswers);
-        for (int i=0;i<outputs.size();i++) {
+        for (int i=0;i<numberOfPlayers;i++) {
             gameControlFragment.displayAnswerOfPlayer(i,"The answer of " + playerAnswers[i].getPlayerName() + ": ");
             if (question.getType() == Question.MULTIPLE_CHOICE) {
                 String message = "questionMC##" + questionString + "##" + answers.get(0) + "##" + answers.get(1)
@@ -213,6 +218,14 @@ public class GameActivity extends AppCompatActivity implements GameControlFragme
                 new SendMessageToClientTask().execute(Integer.toString(i), message);
             }
         }
+        for (int i=numberOfPlayers;i<outputs.size();i++) { //observerek
+            if (question.getType() == Question.MULTIPLE_CHOICE) {
+                String message = "questionMC##" + questionString + "##" + answers.get(0) + "##" + answers.get(1)
+                        + "##" + answers.get(2) + "##" + answers.get(3) + "##" + playerAnswersString
+                        + "##-1##" + Integer.toString(timeLimit);
+                new SendMessageToClientTask().execute(Integer.toString(i), message);
+            }
+        }
 
             /*
             gameControlFragment.displayEndOfGame();
@@ -225,7 +238,7 @@ public class GameActivity extends AppCompatActivity implements GameControlFragme
     @Override
     public void correctAnswerButtonClicked() {
         gameControlFragment.setCorrectAnswerButtonEnabled(false);
-        for (int i=0;i<outputs.size();i++) {
+        for (int i=0;i<numberOfPlayers;i++) {
             if (answers.size() == 4) {
                 String playerAnswersString = gson.toJson(playerAnswers);
                 String message = "answerMC##" + questionString + "##" + answers.get(0) + "##" + answers.get(1)
@@ -240,6 +253,16 @@ public class GameActivity extends AppCompatActivity implements GameControlFragme
                 new SendMessageToClientTask().execute(Integer.toString(i), message);
             }
         }
+        for (int i=numberOfPlayers;i<outputs.size();i++) { //observerek
+            if (question.getType() == Question.MULTIPLE_CHOICE) {
+                String playerAnswersString = gson.toJson(playerAnswers);
+                String message = "answerMC##" + questionString + "##" + answers.get(0) + "##" + answers.get(1)
+                        + "##" + answers.get(2) + "##" + answers.get(3) + "##" + playerAnswersString
+                        + "##" + Integer.toString(correctAnswer) + "##-1";
+                new SendMessageToClientTask().execute(Integer.toString(i), message);
+            }
+        }
+
     }
 
     @Override
diff --git a/KvizServer/app/src/main/java/onlab/kvizserver/LobbyActivity.java b/KvizServer/app/src/main/java/onlab/kvizserver/LobbyActivity.java
index e5b0e92..2362d82 100644
--- a/KvizServer/app/src/main/java/onlab/kvizserver/LobbyActivity.java
+++ b/KvizServer/app/src/main/java/onlab/kvizserver/LobbyActivity.java
@@ -111,6 +111,7 @@ public class LobbyActivity extends AppCompatActivity {
                         commThread.interrupt();
                     }
                     ClientHolder.addAll(clients);
+                    ObserverHolder.addAll(observers);
                     Intent intent;
                     if (gameMode.equals("normal")) {
                         intent = new Intent(getApplicationContext(), GameActivity.class);
diff --git a/KvizServer/app/src/main/java/onlab/kvizserver/ObserverHolder.java b/KvizServer/app/src/main/java/onlab/kvizserver/ObserverHolder.java
new file mode 100644
index 0000000..b50edec
--- /dev/null
+++ b/KvizServer/app/src/main/java/onlab/kvizserver/ObserverHolder.java
@@ -0,0 +1,30 @@
+package onlab.kvizserver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import onlab.kvizserver.model.ClientModel;
+
+public class ObserverHolder {
+    private static List<ClientModel> observers = new ArrayList<>();
+
+    public static void add(ClientModel clientModel) {
+        observers.add(clientModel);
+    }
+
+    public static void remove(ClientModel clientModel) {
+        observers.remove(clientModel);
+    }
+
+    public static void addAll(List<ClientModel> observers) {
+        ObserverHolder.observers.addAll(observers);
+    }
+
+    public static ClientModel get(int index) {
+        return observers.get(index);
+    }
+
+    public static int size() {
+        return observers.size();
+    }
+}
-- 
GitLab