ruslanmv commited on
Commit
0bcd8e4
·
1 Parent(s): cdfb731

First version

Browse files
Files changed (5) hide show
  1. app.py +78 -16
  2. requirements.txt +1 -0
  3. static/script.js +41 -9
  4. templates/client.html +3 -0
  5. templates/host.html +8 -3
app.py CHANGED
@@ -1,17 +1,20 @@
1
  from flask import Flask, render_template, request
2
  from flask_socketio import SocketIO, emit, join_room, leave_room
 
 
 
3
  import random
4
 
5
  app = Flask(__name__)
6
  app.config['SECRET_KEY'] = 'your_secret_key'
7
  socketio = SocketIO(app)
8
 
9
- # Store questions and participants
10
  questions = [
11
- {"question": "What is the capital of France?", "options": ["Paris", "London", "Berlin", "Rome"]},
12
- {"question": "What is the largest planet?", "options": ["Earth", "Mars", "Jupiter", "Saturn"]}
13
  ]
14
- current_question = {"index": 0, "answers": {}}
 
15
  participants = {}
16
 
17
  @app.route('/')
@@ -29,32 +32,58 @@ def host():
29
  @socketio.on('join')
30
  def on_join(data):
31
  username = data['username']
32
- participants[request.sid] = username
 
33
  join_room('quiz')
34
- emit('update_participants', participants, room='quiz')
35
- print(f"{username} joined the quiz.")
36
 
37
  @socketio.on('disconnect')
38
  def on_leave():
39
  if request.sid in participants:
40
- username = participants[request.sid]
41
  leave_room('quiz')
42
  del participants[request.sid]
43
- emit('update_participants', participants, room='quiz')
44
  print(f"{username} left the quiz.")
45
 
46
- @socketio.on('request_question')
47
- def send_question():
 
 
48
  index = current_question['index']
49
- question = questions[index]
50
- emit('new_question', question, room=request.sid)
 
51
 
52
  @socketio.on('submit_answer')
53
  def receive_answer(data):
54
- username = participants.get(request.sid, "Unknown")
55
  answer = data['answer']
56
  current_question['answers'][username] = answer
57
- emit('update_results', current_question['answers'], room='quiz')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  @socketio.on('next_question')
60
  def next_question():
@@ -62,9 +91,42 @@ def next_question():
62
  current_question['answers'] = {}
63
  if current_question['index'] < len(questions):
64
  question = questions[current_question['index']]
 
65
  emit('new_question', question, room='quiz')
66
  else:
67
- emit('quiz_end', room='quiz')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  if __name__ == '__main__':
70
  socketio.run(app, debug=True)
 
1
  from flask import Flask, render_template, request
2
  from flask_socketio import SocketIO, emit, join_room, leave_room
3
+ import matplotlib.pyplot as plt
4
+ import base64
5
+ from io import BytesIO
6
  import random
7
 
8
  app = Flask(__name__)
9
  app.config['SECRET_KEY'] = 'your_secret_key'
10
  socketio = SocketIO(app)
11
 
 
12
  questions = [
13
+ {"question": "What is the capital of France?", "options": ["Paris", "London", "Berlin", "Rome"], "correct": "Paris"},
14
+ {"question": "What is the largest planet?", "options": ["Earth", "Mars", "Jupiter", "Saturn"], "correct": "Jupiter"}
15
  ]
16
+ initial_questions = questions.copy() # Keep a copy of the original questions to reset later
17
+ current_question = {"index": 0, "answers": {}, "started": False}
18
  participants = {}
19
 
20
  @app.route('/')
 
32
  @socketio.on('join')
33
  def on_join(data):
34
  username = data['username']
35
+ user_id_number = random.randint(1000, 9999) # Generate a unique ID for the user
36
+ participants[request.sid] = {"user_id_number": user_id_number, "username": username, "score": 0}
37
  join_room('quiz')
38
+ emit('update_participants', {"participants": participants, "count": len(participants)}, room='quiz')
39
+ print(f"{username} (ID: {user_id_number}) joined the quiz.")
40
 
41
  @socketio.on('disconnect')
42
  def on_leave():
43
  if request.sid in participants:
44
+ username = participants[request.sid]["username"]
45
  leave_room('quiz')
46
  del participants[request.sid]
47
+ emit('update_participants', {"participants": participants, "count": len(participants)}, room='quiz')
48
  print(f"{username} left the quiz.")
49
 
50
+ @socketio.on('start_quiz')
51
+ def start_quiz():
52
+ reset_quiz() # Reset the quiz state before starting
53
+ current_question['started'] = True
54
  index = current_question['index']
55
+ if index < len(questions):
56
+ question = questions[index]
57
+ emit('new_question', question, room='quiz')
58
 
59
  @socketio.on('submit_answer')
60
  def receive_answer(data):
61
+ username = participants[request.sid]["username"]
62
  answer = data['answer']
63
  current_question['answers'][username] = answer
64
+ if len(current_question['answers']) == len(participants):
65
+ emit('all_answers_received', room='quiz')
66
+
67
+ @socketio.on('check_answers')
68
+ def check_answers():
69
+ index = current_question['index']
70
+ if index < len(questions):
71
+ question = questions[index]
72
+ correct_answer = question['correct']
73
+ results = {
74
+ "question": question["question"],
75
+ "answers": current_question["answers"],
76
+ "correct_answer": correct_answer
77
+ }
78
+
79
+ # Generate the chart and encode it as base64
80
+ chart_base64 = generate_chart(current_question["answers"], question["options"])
81
+ emit('display_results', {"results": results, "chart": chart_base64}, room='quiz')
82
+
83
+ # Update scores based on user_id_number
84
+ for sid, participant in participants.items():
85
+ if current_question['answers'].get(participant["username"]) == correct_answer:
86
+ participants[sid]["score"] += 1
87
 
88
  @socketio.on('next_question')
89
  def next_question():
 
91
  current_question['answers'] = {}
92
  if current_question['index'] < len(questions):
93
  question = questions[current_question['index']]
94
+ emit('clear_results', room='quiz') # Clear previous results and plot
95
  emit('new_question', question, room='quiz')
96
  else:
97
+ final_results = calculate_final_results()
98
+ emit('quiz_end', final_results, room='quiz')
99
+
100
+ @socketio.on('restart_quiz')
101
+ def restart_quiz():
102
+ reset_quiz()
103
+ emit('quiz_reset', room='quiz')
104
+
105
+ def generate_chart(answers, options):
106
+ counts = [list(answers.values()).count(option) for option in options]
107
+ plt.figure(figsize=(6, 4))
108
+ plt.bar(options, counts)
109
+ plt.xlabel('Options')
110
+ plt.ylabel('Number of Votes')
111
+ plt.title('Results')
112
+ buf = BytesIO()
113
+ plt.savefig(buf, format='png')
114
+ buf.seek(0)
115
+ chart_base64 = base64.b64encode(buf.read()).decode('utf-8')
116
+ buf.close()
117
+ plt.close()
118
+ return chart_base64
119
+
120
+ def calculate_final_results():
121
+ results = {participant["username"]: participant["score"] for participant in participants.values()}
122
+ return results
123
+
124
+ def reset_quiz():
125
+ global questions, current_question
126
+ questions = initial_questions.copy()
127
+ current_question = {"index": 0, "answers": {}, "started": False}
128
+ for participant in participants.values():
129
+ participant["score"] = 0
130
 
131
  if __name__ == '__main__':
132
  socketio.run(app, debug=True)
requirements.txt CHANGED
@@ -1,2 +1,3 @@
1
  Flask
2
  flask-socketio
 
 
1
  Flask
2
  flask-socketio
3
+ matplotlib
static/script.js CHANGED
@@ -4,13 +4,21 @@ let username;
4
  function joinQuiz() {
5
  username = document.getElementById('username').value;
6
  socket.emit('join', { username: username });
 
 
 
7
  document.getElementById('quiz-content').style.display = 'block';
8
- socket.emit('request_question');
9
  }
10
 
 
 
 
 
11
  socket.on('new_question', (data) => {
 
12
  document.getElementById('question-text').innerText = data.question;
13
- const options = data.options.map((opt, index) =>
14
  `<button onclick="submitAnswer('${opt}')" class="btn btn-secondary">${opt}</button>`
15
  ).join('');
16
  document.getElementById('options').innerHTML = options;
@@ -20,18 +28,42 @@ function submitAnswer(answer) {
20
  socket.emit('submit_answer', { answer: answer });
21
  }
22
 
 
 
 
 
 
 
 
 
23
  function nextQuestion() {
24
  socket.emit('next_question');
25
  }
26
 
27
- socket.on('update_results', (data) => {
28
- let resultsText = '';
29
- for (let user in data) {
30
- resultsText += `<p>${user}: ${data[user]}</p>`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
- document.getElementById('results').innerHTML = resultsText;
33
  });
34
 
35
- socket.on('quiz_end', () => {
36
- alert('Quiz has ended!');
 
 
37
  });
 
4
  function joinQuiz() {
5
  username = document.getElementById('username').value;
6
  socket.emit('join', { username: username });
7
+ document.getElementById('username').style.display = 'none';
8
+ document.querySelector('button').style.display = 'none';
9
+ document.getElementById('logged-user').textContent = username;
10
  document.getElementById('quiz-content').style.display = 'block';
11
+ document.getElementById('waiting-message').style.display = 'block';
12
  }
13
 
14
+ socket.on('update_participants', (data) => {
15
+ document.getElementById('participant-count').textContent = data.count;
16
+ });
17
+
18
  socket.on('new_question', (data) => {
19
+ document.getElementById('waiting-message').style.display = 'none';
20
  document.getElementById('question-text').innerText = data.question;
21
+ const options = data.options.map((opt) =>
22
  `<button onclick="submitAnswer('${opt}')" class="btn btn-secondary">${opt}</button>`
23
  ).join('');
24
  document.getElementById('options').innerHTML = options;
 
28
  socket.emit('submit_answer', { answer: answer });
29
  }
30
 
31
+ function startQuiz() {
32
+ socket.emit('start_quiz');
33
+ }
34
+
35
+ function checkAnswers() {
36
+ socket.emit('check_answers');
37
+ }
38
+
39
  function nextQuestion() {
40
  socket.emit('next_question');
41
  }
42
 
43
+ function restartQuiz() {
44
+ socket.emit('restart_quiz');
45
+ }
46
+
47
+ socket.on('display_results', (data) => {
48
+ const img = `<img src="data:image/png;base64,${data.chart}" alt="Results Chart" />`;
49
+ const resultText = `<p>Correct Answer: ${data.results.correct_answer}</p>`;
50
+ document.getElementById('results').innerHTML = img + resultText;
51
+ });
52
+
53
+ socket.on('clear_results', () => {
54
+ document.getElementById('results').innerHTML = '';
55
+ });
56
+
57
+ socket.on('quiz_end', (finalResults) => {
58
+ let resultHtml = '<h3>Final Results</h3>';
59
+ for (let user in finalResults) {
60
+ resultHtml += `<p>${user}: ${finalResults[user]} correct answers</p>`;
61
  }
62
+ document.getElementById('results').innerHTML = resultHtml;
63
  });
64
 
65
+ socket.on('quiz_reset', () => {
66
+ document.getElementById('results').innerHTML = '';
67
+ document.getElementById('question-text').innerText = '';
68
+ document.getElementById('options').innerHTML = '';
69
  });
templates/client.html CHANGED
@@ -12,8 +12,11 @@
12
  <input type="text" id="username" placeholder="Enter your name" class="form-control">
13
  <button onclick="joinQuiz()" class="btn btn-primary mt-2">Join</button>
14
  <div id="quiz-content" style="display: none;">
 
 
15
  <h3 id="question-text"></h3>
16
  <div id="options"></div>
 
17
  </div>
18
  </div>
19
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
 
12
  <input type="text" id="username" placeholder="Enter your name" class="form-control">
13
  <button onclick="joinQuiz()" class="btn btn-primary mt-2">Join</button>
14
  <div id="quiz-content" style="display: none;">
15
+ <h3>Logged in as: <span id="logged-user"></span></h3>
16
+ <h3 id="waiting-message" style="display: none;">Waiting for the Host...</h3>
17
  <h3 id="question-text"></h3>
18
  <div id="options"></div>
19
+ <div id="results" class="mt-4"></div>
20
  </div>
21
  </div>
22
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
templates/host.html CHANGED
@@ -9,9 +9,14 @@
9
  <body>
10
  <div class="container">
11
  <h2>Quiz Host</h2>
12
- <button onclick="nextQuestion()" class="btn btn-success">Next Question</button>
13
- <h3 id="question-text"></h3>
14
- <div id="results"></div>
 
 
 
 
 
15
  </div>
16
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
17
  <script src="/static/script.js"></script>
 
9
  <body>
10
  <div class="container">
11
  <h2>Quiz Host</h2>
12
+ <p>Participants connected: <span id="participant-count">0</span></p>
13
+ <button onclick="startQuiz()" class="btn btn-success">Start Quiz</button>
14
+ <button onclick="checkAnswers()" class="btn btn-primary mt-2">Check Answers</button>
15
+ <button onclick="nextQuestion()" class="btn btn-secondary mt-2">Next Question</button>
16
+ <button onclick="restartQuiz()" class="btn btn-danger mt-2">Start New Quiz</button>
17
+ <h3 id="question-text" class="mt-4"></h3>
18
+ <div id="options" class="mt-2"></div>
19
+ <div id="results" class="mt-4"></div>
20
  </div>
21
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
22
  <script src="/static/script.js"></script>