git_game_show 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/git_game_show/cli.rb +70 -50
- data/lib/git_game_show/game_server.rb +1 -1
- data/lib/git_game_show/player_client.rb +192 -191
- data/lib/git_game_show/updater.rb +14 -14
- data/lib/git_game_show/version.rb +1 -1
- data/lib/git_game_show.rb +4 -4
- metadata +2 -2
@@ -5,7 +5,7 @@ require 'timeout'
|
|
5
5
|
module GitGameShow
|
6
6
|
class PlayerClient
|
7
7
|
attr_reader :host, :port, :password, :name, :secure
|
8
|
-
|
8
|
+
|
9
9
|
def initialize(host:, port:, password:, name:, secure: false)
|
10
10
|
@host = host
|
11
11
|
@port = port
|
@@ -18,45 +18,46 @@ module GitGameShow
|
|
18
18
|
@game_state = :lobby # :lobby, :playing, :ended
|
19
19
|
@current_timer_id = nil
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def connect
|
23
23
|
begin
|
24
24
|
client = self # Store reference to the client instance
|
25
|
-
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
25
|
+
|
26
|
+
# Check if the connection should use a secure protocol
|
27
|
+
# For ngrok TCP tunnels, we should use regular ws:// since ngrok tcp doesn't provide SSL termination
|
28
|
+
# Only use wss:// if the secure flag is explicitly set (for configured HTTPS endpoints)
|
29
|
+
protocol = if @secure
|
29
30
|
puts "Using secure WebSocket connection (wss://)".colorize(:cyan)
|
30
31
|
'wss'
|
31
32
|
else
|
32
33
|
'ws'
|
33
34
|
end
|
34
|
-
|
35
|
+
|
35
36
|
@ws = WebSocket::Client::Simple.connect("#{protocol}://#{host}:#{port}")
|
36
|
-
|
37
|
+
|
37
38
|
@ws.on :open do
|
38
39
|
puts "Connected to server".colorize(:green)
|
39
40
|
# Use the stored client reference
|
40
41
|
client.send_join_request
|
41
42
|
end
|
42
|
-
|
43
|
+
|
43
44
|
@ws.on :message do |msg|
|
44
45
|
client.handle_message(msg)
|
45
46
|
end
|
46
|
-
|
47
|
+
|
47
48
|
@ws.on :error do |e|
|
48
49
|
puts "Error: #{e.message}".colorize(:red)
|
49
50
|
end
|
50
|
-
|
51
|
+
|
51
52
|
@ws.on :close do |e|
|
52
53
|
puts "Connection closed (#{e.code}: #{e.reason})".colorize(:yellow)
|
53
54
|
exit(1)
|
54
55
|
end
|
55
|
-
|
56
|
+
|
56
57
|
# Keep the client running
|
57
58
|
loop do
|
58
59
|
sleep(1)
|
59
|
-
|
60
|
+
|
60
61
|
# Check if connection is still alive
|
61
62
|
if @ws.nil? || @ws.closed?
|
62
63
|
puts "Connection lost. Exiting...".colorize(:red)
|
@@ -67,7 +68,7 @@ module GitGameShow
|
|
67
68
|
puts "Failed to connect: #{e.message}".colorize(:red)
|
68
69
|
end
|
69
70
|
end
|
70
|
-
|
71
|
+
|
71
72
|
# Make these methods public so they can be called from the WebSocket callbacks
|
72
73
|
def send_join_request
|
73
74
|
send_message({
|
@@ -76,14 +77,14 @@ module GitGameShow
|
|
76
77
|
password: password
|
77
78
|
})
|
78
79
|
end
|
79
|
-
|
80
|
+
|
80
81
|
# Make public for WebSocket callback
|
81
82
|
def handle_message(msg)
|
82
83
|
begin
|
83
84
|
data = JSON.parse(msg.data)
|
84
|
-
|
85
|
+
|
85
86
|
# Remove debug print to reduce console noise
|
86
|
-
|
87
|
+
|
87
88
|
case data['type']
|
88
89
|
when MessageType::JOIN_RESPONSE
|
89
90
|
handle_join_response(data)
|
@@ -116,7 +117,7 @@ module GitGameShow
|
|
116
117
|
puts "Error processing message: #{e.message}".colorize(:red)
|
117
118
|
end
|
118
119
|
end
|
119
|
-
|
120
|
+
|
120
121
|
def handle_join_response(data)
|
121
122
|
if data['success']
|
122
123
|
@players = data['players'] # Get the full player list from server
|
@@ -126,22 +127,22 @@ module GitGameShow
|
|
126
127
|
exit(1)
|
127
128
|
end
|
128
129
|
end
|
129
|
-
|
130
|
+
|
130
131
|
def display_waiting_room
|
131
132
|
clear_screen
|
132
|
-
|
133
|
+
|
133
134
|
# Draw header with fancy box
|
134
135
|
terminal_width = `tput cols`.to_i rescue 80
|
135
136
|
terminal_height = `tput lines`.to_i rescue 24
|
136
|
-
|
137
|
+
|
137
138
|
# Create title box
|
138
139
|
puts "┏#{"━" * (terminal_width - 2)}┓".colorize(:green)
|
139
140
|
puts "┃#{" GIT GAME SHOW - WAITING ROOM ".center(terminal_width - 2)}┃".colorize(:green)
|
140
141
|
puts "┗#{"━" * (terminal_width - 2)}┛".colorize(:green)
|
141
|
-
|
142
|
+
|
142
143
|
# Left column width (2/3 of terminal) for main content
|
143
144
|
left_width = (terminal_width * 0.65).to_i
|
144
|
-
|
145
|
+
|
145
146
|
# Display instructions and welcome information
|
146
147
|
puts "\n"
|
147
148
|
puts " Welcome to Git Game Show!".colorize(:yellow)
|
@@ -155,41 +156,41 @@ module GitGameShow
|
|
155
156
|
puts "\n"
|
156
157
|
puts " 🔹 STATUS: Waiting for the host to start the game...".colorize(:light_yellow)
|
157
158
|
puts "\n"
|
158
|
-
|
159
|
+
|
159
160
|
# Draw player section in a box
|
160
161
|
player_box_width = terminal_width - 4
|
161
162
|
puts " ┏#{"━" * player_box_width}┓".colorize(:cyan)
|
162
163
|
puts " ┃#{" PLAYERS ".center(player_box_width)}┃".colorize(:cyan)
|
163
164
|
puts " ┗#{"━" * player_box_width}┛".colorize(:cyan)
|
164
|
-
|
165
|
+
|
165
166
|
# Display list of players in a nicer format
|
166
167
|
if @players.empty?
|
167
168
|
puts " (No other players yet)".colorize(:light_black)
|
168
169
|
else
|
169
170
|
# Calculate number of columns based on terminal width and name lengths
|
170
171
|
max_name_length = @players.map(&:length).max + 10 # Extra space for number and "(You)" text
|
171
|
-
|
172
|
+
|
172
173
|
# Add more spacing between players - increase padding from 4 to 10
|
173
174
|
column_width = max_name_length + 12 # More generous spacing
|
174
175
|
num_cols = [terminal_width / column_width, 3].min # Cap at 3 columns max
|
175
176
|
num_cols = 1 if num_cols < 1
|
176
|
-
|
177
|
+
|
177
178
|
# Use fewer columns for better spacing
|
178
179
|
if num_cols > 1 && @players.size > 6
|
179
180
|
# If we have many players, prefer fewer columns with more space
|
180
181
|
num_cols = [num_cols, 2].min
|
181
182
|
end
|
182
|
-
|
183
|
+
|
183
184
|
# Split players into rows for multi-column display
|
184
185
|
player_rows = @players.each_slice(((@players.size + num_cols - 1) / num_cols).ceil).to_a
|
185
|
-
|
186
|
+
|
186
187
|
puts "\n"
|
187
188
|
player_rows.each do |row_players|
|
188
189
|
row_str = " "
|
189
190
|
row_players.each_with_index do |player, idx|
|
190
191
|
col_idx = player_rows.index { |rp| rp.include?(player) }
|
191
192
|
player_num = col_idx * player_rows[0].length + idx + 1
|
192
|
-
|
193
|
+
|
193
194
|
# Apply different color for current player
|
194
195
|
if player == @name
|
195
196
|
row_str += "#{player_num}. #{player} (You)".colorize(:green).ljust(column_width)
|
@@ -202,30 +203,30 @@ module GitGameShow
|
|
202
203
|
puts ""
|
203
204
|
end
|
204
205
|
end
|
205
|
-
|
206
|
+
|
206
207
|
puts "\n"
|
207
208
|
puts " When the game starts, you'll see questions appear automatically.".colorize(:light_black)
|
208
209
|
puts " Get ready to test your Git knowledge!".colorize(:light_yellow)
|
209
210
|
puts "\n"
|
210
211
|
end
|
211
|
-
|
212
|
+
|
212
213
|
def clear_screen
|
213
214
|
# Reset cursor and clear entire screen
|
214
215
|
print "\033[H\033[2J" # Move to home position and clear screen
|
215
216
|
print "\033[3J" # Clear scrollback buffer
|
216
|
-
|
217
|
+
|
217
218
|
# Reserve bottom line for timer status
|
218
219
|
term_height = `tput lines`.to_i rescue 24
|
219
|
-
|
220
|
+
|
220
221
|
# Move to bottom of screen and clear status line
|
221
222
|
print "\e[#{term_height};1H"
|
222
223
|
print "\e[K"
|
223
224
|
print "\e[H" # Move cursor back to home position
|
224
|
-
|
225
|
+
|
225
226
|
STDOUT.flush
|
226
227
|
end
|
227
|
-
|
228
|
-
|
228
|
+
|
229
|
+
|
229
230
|
# Helper method to print a countdown timer status in the window title
|
230
231
|
# This doesn't interfere with the terminal content
|
231
232
|
def update_title_timer(seconds)
|
@@ -234,7 +235,7 @@ module GitGameShow
|
|
234
235
|
print "\033]0;Git Game Show - #{seconds} seconds remaining\007"
|
235
236
|
STDOUT.flush
|
236
237
|
end
|
237
|
-
|
238
|
+
|
238
239
|
# Super simple ordering implementation with minimal screen updates
|
239
240
|
def handle_ordering_question(options, question_text = nil)
|
240
241
|
# Create a copy of the options that we can modify
|
@@ -243,59 +244,59 @@ module GitGameShow
|
|
243
244
|
selected_index = nil
|
244
245
|
num_options = current_order.size
|
245
246
|
question_text ||= "Put these commits in chronological order (oldest to newest)"
|
246
|
-
|
247
|
+
|
247
248
|
# Extract question data if available
|
248
249
|
data = Thread.current[:question_data] || {}
|
249
250
|
question_number = data['question_number']
|
250
251
|
total_questions = data['total_questions']
|
251
|
-
|
252
|
+
|
252
253
|
# Draw the initial screen once
|
253
254
|
# system('clear') || system('cls')
|
254
|
-
|
255
|
+
|
255
256
|
# Draw question header once
|
256
257
|
if question_number && total_questions
|
257
258
|
puts "\n ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓".colorize(:cyan)
|
258
259
|
puts " ┃#{"QUESTION #{question_number} of #{total_questions}".center(45)}┃".colorize(:cyan)
|
259
260
|
puts " ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛".colorize(:cyan)
|
260
261
|
end
|
261
|
-
|
262
|
+
|
262
263
|
# Draw the main question text once
|
263
264
|
puts "\n #{question_text}".colorize(:light_blue)
|
264
265
|
puts " Put in order from oldest (1) to newest (#{num_options})".colorize(:light_blue)
|
265
|
-
|
266
|
+
|
266
267
|
# Draw instructions once
|
267
268
|
puts "\n INSTRUCTIONS:".colorize(:yellow)
|
268
269
|
puts " • Use ↑/↓ arrows to move cursor".colorize(:white)
|
269
270
|
puts " • Press ENTER to select/deselect an item to move".colorize(:white)
|
270
271
|
puts " • Selected items move with cursor when you press ↑/↓".colorize(:white)
|
271
272
|
puts " • Navigate to Submit and press ENTER when finished".colorize(:white)
|
272
|
-
|
273
|
+
|
273
274
|
# Draw the header for the list content once
|
274
275
|
puts "\n CURRENT ORDER:".colorize(:light_blue)
|
275
|
-
|
276
|
+
|
276
277
|
# Calculate where the list content starts on screen
|
277
278
|
content_start_line = question_number ? 15 : 12
|
278
|
-
|
279
|
+
|
279
280
|
# Draw the list content (this will be redrawn repeatedly)
|
280
281
|
draw_ordering_list(current_order, cursor_index, selected_index, content_start_line, num_options)
|
281
|
-
|
282
|
+
|
282
283
|
# Initialize variables
|
283
|
-
|
284
|
+
|
284
285
|
# Main interaction loop
|
285
286
|
loop do
|
286
287
|
# Read a single keypress
|
287
288
|
char = read_char
|
288
|
-
|
289
|
+
|
289
290
|
# Clear any message on this line
|
290
291
|
move_cursor_to(content_start_line + num_options + 2, 0)
|
291
292
|
print "\r\033[K"
|
292
|
-
|
293
|
+
|
293
294
|
# Check if the timer has expired
|
294
295
|
if @timer_expired
|
295
296
|
# If timer expired, just return the current ordering
|
296
297
|
return current_order
|
297
298
|
end
|
298
|
-
|
299
|
+
|
299
300
|
# Now char is an integer (ASCII code)
|
300
301
|
case char
|
301
302
|
when 13, 10 # Enter key (CR or LF)
|
@@ -317,7 +318,7 @@ module GitGameShow
|
|
317
318
|
# Move cursor up
|
318
319
|
if selected_index == cursor_index && cursor_index > 0
|
319
320
|
# Move the selected item up in the order
|
320
|
-
current_order[cursor_index], current_order[cursor_index - 1] =
|
321
|
+
current_order[cursor_index], current_order[cursor_index - 1] =
|
321
322
|
current_order[cursor_index - 1], current_order[cursor_index]
|
322
323
|
cursor_index -= 1
|
323
324
|
selected_index = cursor_index
|
@@ -328,7 +329,7 @@ module GitGameShow
|
|
328
329
|
when 66, 106, 115 # Down arrow (66='B'), j (106), s (115)
|
329
330
|
if selected_index == cursor_index && cursor_index < num_options - 1
|
330
331
|
# Move the selected item down in the order
|
331
|
-
current_order[cursor_index], current_order[cursor_index + 1] =
|
332
|
+
current_order[cursor_index], current_order[cursor_index + 1] =
|
332
333
|
current_order[cursor_index + 1], current_order[cursor_index]
|
333
334
|
cursor_index += 1
|
334
335
|
selected_index = cursor_index
|
@@ -337,34 +338,34 @@ module GitGameShow
|
|
337
338
|
cursor_index += 1
|
338
339
|
end
|
339
340
|
end
|
340
|
-
|
341
|
+
|
341
342
|
# Redraw just the list portion of the screen
|
342
343
|
draw_ordering_list(current_order, cursor_index, selected_index, content_start_line, num_options)
|
343
344
|
end
|
344
345
|
end
|
345
|
-
|
346
|
+
|
346
347
|
# Helper method to draw just the list portion of the ordering UI
|
347
348
|
def draw_ordering_list(items, cursor_index, selected_index, start_line, num_options)
|
348
349
|
# Clear the line above the list (was used for debugging)
|
349
350
|
debug_line = start_line - 1
|
350
351
|
move_cursor_to(debug_line, 0)
|
351
352
|
print "\r\033[K" # Clear debug line
|
352
|
-
|
353
|
+
|
353
354
|
# Move cursor to the start position for the list
|
354
355
|
move_cursor_to(start_line, 0)
|
355
|
-
|
356
|
+
|
356
357
|
# Clear all lines that will contain list items and the submit button
|
357
358
|
(num_options + 2).times do |i|
|
358
359
|
move_cursor_to(start_line + i, 0)
|
359
360
|
print "\r\033[K" # Clear current line without moving cursor
|
360
361
|
end
|
361
|
-
|
362
|
+
|
362
363
|
# Draw each item with appropriate highlighting
|
363
364
|
items.each_with_index do |item, idx|
|
364
365
|
# Calculate the line for this item
|
365
366
|
item_line = start_line + idx
|
366
367
|
move_cursor_to(item_line, 0)
|
367
|
-
|
368
|
+
|
368
369
|
if selected_index == idx
|
369
370
|
# Selected item (being moved)
|
370
371
|
print " → #{idx + 1}. #{item}".colorize(:light_green)
|
@@ -376,7 +377,7 @@ module GitGameShow
|
|
376
377
|
print " #{idx + 1}. #{item}".colorize(:white)
|
377
378
|
end
|
378
379
|
end
|
379
|
-
|
380
|
+
|
380
381
|
# Add the Submit option at the bottom
|
381
382
|
move_cursor_to(start_line + num_options, 0)
|
382
383
|
if cursor_index == num_options
|
@@ -384,27 +385,27 @@ module GitGameShow
|
|
384
385
|
else
|
385
386
|
print " Submit Answer".colorize(:white)
|
386
387
|
end
|
387
|
-
|
388
|
+
|
388
389
|
# Move cursor after the list
|
389
390
|
move_cursor_to(start_line + num_options + 1, 0)
|
390
|
-
|
391
|
+
|
391
392
|
# Ensure output is visible
|
392
393
|
STDOUT.flush
|
393
394
|
end
|
394
|
-
|
395
|
+
|
395
396
|
# Helper to position cursor at a specific row/column
|
396
397
|
def move_cursor_to(row, col)
|
397
398
|
print "\033[#{row};#{col}H"
|
398
399
|
end
|
399
|
-
|
400
|
+
|
400
401
|
# Simplified key input reader that uses numbers for arrow keys
|
401
402
|
def read_char
|
402
403
|
begin
|
403
404
|
system("stty raw -echo")
|
404
|
-
|
405
|
+
|
405
406
|
# Read a character
|
406
407
|
c = STDIN.getc
|
407
|
-
|
408
|
+
|
408
409
|
# Special handling for escape sequences
|
409
410
|
if c == "\e"
|
410
411
|
# Could be an arrow key - read more
|
@@ -434,14 +435,14 @@ module GitGameShow
|
|
434
435
|
return 27 # ESC key
|
435
436
|
end
|
436
437
|
end
|
437
|
-
|
438
|
+
|
438
439
|
# Just return the ASCII value for the key
|
439
440
|
return c.ord
|
440
441
|
ensure
|
441
442
|
system("stty -raw echo")
|
442
443
|
end
|
443
444
|
end
|
444
|
-
|
445
|
+
|
445
446
|
# Non-blocking key input reader that supports timeouts
|
446
447
|
def read_char_with_timeout
|
447
448
|
begin
|
@@ -449,10 +450,10 @@ module GitGameShow
|
|
449
450
|
if IO.select([STDIN], [], [], 0.1)
|
450
451
|
# Read a character
|
451
452
|
c = STDIN.getc
|
452
|
-
|
453
|
+
|
453
454
|
# Handle nil case (EOF)
|
454
455
|
return nil if c.nil?
|
455
|
-
|
456
|
+
|
456
457
|
# Special handling for escape sequences
|
457
458
|
if c == "\e"
|
458
459
|
# Could be an arrow key - read more
|
@@ -482,11 +483,11 @@ module GitGameShow
|
|
482
483
|
return 27 # ESC key
|
483
484
|
end
|
484
485
|
end
|
485
|
-
|
486
|
+
|
486
487
|
# Just return the ASCII value for the key
|
487
488
|
return c.ord
|
488
489
|
end
|
489
|
-
|
490
|
+
|
490
491
|
# No input available - return nil for timeout
|
491
492
|
return nil
|
492
493
|
rescue => e
|
@@ -494,17 +495,17 @@ module GitGameShow
|
|
494
495
|
return nil
|
495
496
|
end
|
496
497
|
end
|
497
|
-
|
498
|
+
|
498
499
|
# Helper method to display countdown using a status bar at the bottom of the screen
|
499
500
|
def update_countdown_display(seconds, original_seconds)
|
500
501
|
# Get terminal dimensions
|
501
502
|
term_height = `tput lines`.to_i rescue 24
|
502
|
-
|
503
|
+
|
503
504
|
# Calculate a simple progress bar
|
504
505
|
total_width = 30
|
505
506
|
progress_width = ((seconds.to_f / original_seconds) * total_width).to_i
|
506
507
|
remaining_width = total_width - progress_width
|
507
|
-
|
508
|
+
|
508
509
|
# Choose color based on time remaining
|
509
510
|
color = if seconds <= 5
|
510
511
|
:red
|
@@ -513,57 +514,57 @@ module GitGameShow
|
|
513
514
|
else
|
514
515
|
:green
|
515
516
|
end
|
516
|
-
|
517
|
+
|
517
518
|
# Create status bar with progress indicator
|
518
519
|
bar = "[#{"█" * progress_width}#{" " * remaining_width}]"
|
519
520
|
status_text = " ⏱️ Time remaining: #{seconds.to_s.rjust(2)} seconds ".colorize(color) + bar
|
520
|
-
|
521
|
+
|
521
522
|
# Save cursor position
|
522
523
|
print "\e7"
|
523
|
-
|
524
|
+
|
524
525
|
# Move to bottom of screen (status line)
|
525
526
|
print "\e[#{term_height};1H"
|
526
|
-
|
527
|
+
|
527
528
|
# Clear the line
|
528
529
|
print "\e[K"
|
529
|
-
|
530
|
+
|
530
531
|
# Print status bar at bottom of screen
|
531
532
|
print status_text
|
532
|
-
|
533
|
+
|
533
534
|
# Restore cursor position
|
534
535
|
print "\e8"
|
535
536
|
STDOUT.flush
|
536
537
|
end
|
537
|
-
|
538
|
+
|
538
539
|
def handle_game_start(data)
|
539
540
|
@game_state = :playing
|
540
541
|
@players = data['players']
|
541
542
|
@total_rounds = data['rounds']
|
542
|
-
|
543
|
+
|
543
544
|
clear_screen
|
544
|
-
|
545
|
+
|
545
546
|
# Display a fun "Game Starting" animation
|
546
547
|
puts "\n\n"
|
547
548
|
puts " ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓".colorize(:green)
|
548
549
|
puts " ┃ GAME STARTING... ┃".colorize(:green)
|
549
550
|
puts " ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛".colorize(:green)
|
550
551
|
puts "\n\n"
|
551
|
-
|
552
|
+
|
552
553
|
puts " Total rounds: #{@total_rounds}".colorize(:cyan)
|
553
554
|
puts " Players: #{@players.join(', ')}".colorize(:cyan)
|
554
555
|
puts "\n\n"
|
555
556
|
puts " Get ready for the first round!".colorize(:yellow)
|
556
557
|
puts "\n\n"
|
557
558
|
end
|
558
|
-
|
559
|
+
|
559
560
|
def handle_player_update(data)
|
560
561
|
# Update the players list
|
561
562
|
@players = data['players']
|
562
|
-
|
563
|
+
|
563
564
|
if @game_state == :lobby
|
564
565
|
# If we're in the lobby, refresh the waiting room UI with updated player list
|
565
566
|
display_waiting_room
|
566
|
-
|
567
|
+
|
567
568
|
# Show notification at the bottom
|
568
569
|
if data['type'] == 'player_joined'
|
569
570
|
puts "\n 🟢 #{data['name']} has joined the game".colorize(:green)
|
@@ -573,51 +574,51 @@ module GitGameShow
|
|
573
574
|
else
|
574
575
|
# During gameplay, just show a notification without disrupting the game UI
|
575
576
|
terminal_width = `tput cols`.to_i rescue 80
|
576
|
-
|
577
|
+
|
577
578
|
# Create a notification box that won't interfere with ongoing gameplay
|
578
579
|
puts "\n┏#{"━" * (terminal_width - 2)}┓".colorize(:cyan)
|
579
|
-
|
580
|
+
|
580
581
|
if data['type'] == 'player_joined'
|
581
582
|
puts "┃#{" 🟢 #{data['name']} has joined the game ".center(terminal_width - 2)}┃".colorize(:green)
|
582
583
|
else
|
583
584
|
puts "┃#{" 🔴 #{data['name']} has left the game ".center(terminal_width - 2)}┃".colorize(:yellow)
|
584
585
|
end
|
585
|
-
|
586
|
+
|
586
587
|
# Don't show all players during gameplay - can be too disruptive
|
587
588
|
# Just show the total count
|
588
589
|
puts "┃#{" Total players: #{data['players'].size} ".center(terminal_width - 2)}┃".colorize(:cyan)
|
589
590
|
puts "┗#{"━" * (terminal_width - 2)}┛".colorize(:cyan)
|
590
591
|
end
|
591
592
|
end
|
592
|
-
|
593
|
+
|
593
594
|
def handle_round_start(data)
|
594
595
|
clear_screen
|
595
|
-
|
596
|
+
|
596
597
|
# Draw a fancy round header
|
597
598
|
round_num = data['round']
|
598
599
|
total_rounds = data['total_rounds']
|
599
600
|
mini_game = data['mini_game']
|
600
601
|
description = data['description']
|
601
|
-
|
602
|
+
|
602
603
|
puts "\n\n"
|
603
|
-
|
604
|
+
|
604
605
|
# Box is drawn with exactly 45 "━" characters for the top and bottom borders
|
605
606
|
# The top and bottom including borders are 48 characters wide
|
606
607
|
box_top = " ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓"
|
607
608
|
box_bottom = " ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛"
|
608
|
-
|
609
|
+
|
609
610
|
# Get the text to center
|
610
611
|
round_text = "ROUND #{round_num} of #{total_rounds}"
|
611
|
-
|
612
|
+
|
612
613
|
# Find exact box width by measuring the top border
|
613
614
|
box_width = box_top.length # Should be 48 with Unicode characters
|
614
|
-
|
615
|
+
|
615
616
|
# The inner width is the box width minus the borders
|
616
617
|
inner_width = box_width - (" ┃".length + "┃".length)
|
617
|
-
|
618
|
+
|
618
619
|
# Simply use Ruby's built-in center method for reliable centering
|
619
620
|
box_middle = " ┃" + round_text.center(inner_width) + "┃"
|
620
|
-
|
621
|
+
|
621
622
|
# Output the box
|
622
623
|
puts box_top.colorize(:green)
|
623
624
|
puts box_middle.colorize(:green)
|
@@ -626,7 +627,7 @@ module GitGameShow
|
|
626
627
|
puts " Mini-game: #{mini_game}".colorize(:cyan)
|
627
628
|
puts " #{description}".colorize(:light_blue)
|
628
629
|
puts "\n"
|
629
|
-
|
630
|
+
|
630
631
|
# Count down to the start - don't sleep here as we're waiting for the server
|
631
632
|
# to send us the questions after a fixed delay
|
632
633
|
puts " Get ready for the first question...".colorize(:yellow)
|
@@ -634,99 +635,99 @@ module GitGameShow
|
|
634
635
|
puts " The host is controlling the timing of all questions.".colorize(:light_blue)
|
635
636
|
puts "\n\n"
|
636
637
|
end
|
637
|
-
|
638
|
+
|
638
639
|
def handle_question(data)
|
639
640
|
# Invalidate any previous timer
|
640
641
|
@current_timer_id = SecureRandom.uuid
|
641
|
-
|
642
|
+
|
642
643
|
# Clear the screen completely
|
643
644
|
clear_screen
|
644
|
-
|
645
|
+
|
645
646
|
question_num = data['question_number']
|
646
647
|
total_questions = data['total_questions']
|
647
648
|
question = data['question']
|
648
649
|
timeout = data['timeout']
|
649
|
-
|
650
|
+
|
650
651
|
# Store question data in thread-local storage for access in other methods
|
651
652
|
Thread.current[:question_data] = data
|
652
|
-
|
653
|
+
|
653
654
|
# No need to reserve space for timer - it will be at the bottom of the screen
|
654
|
-
|
655
|
+
|
655
656
|
# Display question header
|
656
657
|
puts "\n"
|
657
|
-
|
658
|
+
|
658
659
|
# Draw a simple box for the question header
|
659
660
|
box_top = " ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓"
|
660
661
|
box_bottom = " ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛"
|
661
662
|
question_text = "QUESTION #{question_num} of #{total_questions}"
|
662
663
|
inner_width = box_top.length - (" ┃".length + "┃".length)
|
663
664
|
box_middle = " ┃" + question_text.center(inner_width) + "┃"
|
664
|
-
|
665
|
+
|
665
666
|
# Output the question box
|
666
667
|
puts box_top.colorize(:cyan)
|
667
668
|
puts box_middle.colorize(:cyan)
|
668
669
|
puts box_bottom.colorize(:cyan)
|
669
670
|
puts "\n"
|
670
|
-
|
671
|
+
|
671
672
|
# Display question
|
672
673
|
puts " #{question}".colorize(:light_blue)
|
673
|
-
|
674
|
+
|
674
675
|
# Display commit info if available
|
675
676
|
if data['commit_info']
|
676
677
|
puts "\n Commit: #{data['commit_info']}".colorize(:yellow)
|
677
678
|
end
|
678
679
|
puts "\n"
|
679
|
-
|
680
|
+
|
680
681
|
# Create a unique timer ID for this question
|
681
682
|
timer_id = SecureRandom.uuid
|
682
683
|
@current_timer_id = timer_id
|
683
684
|
start_time = Time.now
|
684
685
|
end_time = start_time + timeout
|
685
|
-
|
686
|
+
|
686
687
|
# Static deadline info
|
687
688
|
puts " Deadline: #{end_time.strftime('%I:%M:%S %p')}".colorize(:light_blue)
|
688
689
|
puts "\n"
|
689
|
-
|
690
|
+
|
690
691
|
# Initialize remaining time for scoring
|
691
692
|
@time_remaining = timeout
|
692
|
-
|
693
|
+
|
693
694
|
# Update the timer display immediately
|
694
695
|
update_countdown_display(timeout, timeout)
|
695
|
-
|
696
|
+
|
696
697
|
# Variable to track if the timer has expired
|
697
698
|
@timer_expired = false
|
698
|
-
|
699
|
+
|
699
700
|
# Start countdown in a background thread with new approach
|
700
701
|
countdown_thread = Thread.new do
|
701
702
|
begin
|
702
703
|
remaining = timeout
|
703
|
-
|
704
|
+
|
704
705
|
while remaining > 0 && @current_timer_id == timer_id
|
705
706
|
# Update both window title and fixed position display
|
706
707
|
update_title_timer(remaining)
|
707
708
|
update_countdown_display(remaining, timeout)
|
708
|
-
|
709
|
+
|
709
710
|
# Sound alert when time is almost up (< 5 seconds)
|
710
711
|
if remaining < 5 && remaining > 0
|
711
712
|
print "\a" if remaining % 2 == 0 # Beep on even seconds
|
712
713
|
end
|
713
|
-
|
714
|
+
|
714
715
|
# Store time for scoring
|
715
716
|
@time_remaining = remaining
|
716
|
-
|
717
|
+
|
717
718
|
# Wait one second
|
718
719
|
sleep 1
|
719
720
|
remaining -= 1
|
720
721
|
end
|
721
|
-
|
722
|
+
|
722
723
|
# Final update when timer reaches zero
|
723
724
|
if @current_timer_id == timer_id
|
724
725
|
update_countdown_display(0, timeout)
|
725
|
-
|
726
|
+
|
726
727
|
# IMPORTANT: Send a timeout answer when time expires
|
727
728
|
# without waiting for user input
|
728
729
|
@timer_expired = true
|
729
|
-
|
730
|
+
|
730
731
|
# Clear the screen to break out of any prompt/UI state
|
731
732
|
clear_screen
|
732
733
|
|
@@ -753,7 +754,7 @@ module GitGameShow
|
|
753
754
|
# Silent failure for robustness
|
754
755
|
end
|
755
756
|
end
|
756
|
-
|
757
|
+
|
757
758
|
# Handle different question types - but wrap in a separate thread
|
758
759
|
# so that timeouts can interrupt the UI
|
759
760
|
input_thread = Thread.new do
|
@@ -786,7 +787,7 @@ module GitGameShow
|
|
786
787
|
end
|
787
788
|
end
|
788
789
|
end
|
789
|
-
|
790
|
+
|
790
791
|
# Wait for input but with timeout
|
791
792
|
answer = nil
|
792
793
|
begin
|
@@ -798,7 +799,7 @@ module GitGameShow
|
|
798
799
|
# If timeout occurs during join, kill the thread
|
799
800
|
input_thread.kill if input_thread.alive?
|
800
801
|
end
|
801
|
-
|
802
|
+
|
802
803
|
# Only send user answer if timer hasn't expired
|
803
804
|
unless @timer_expired
|
804
805
|
# Send answer back to server
|
@@ -808,47 +809,47 @@ module GitGameShow
|
|
808
809
|
answer: answer,
|
809
810
|
question_id: data['question_id']
|
810
811
|
})
|
811
|
-
|
812
|
+
|
812
813
|
puts "\n Answer submitted! Waiting for feedback...".colorize(:green)
|
813
814
|
end
|
814
|
-
|
815
|
+
|
815
816
|
# Stop the timer by invalidating its ID and terminating the thread
|
816
817
|
@current_timer_id = SecureRandom.uuid # Change timer ID to signal thread to stop
|
817
818
|
countdown_thread.kill if countdown_thread.alive? # Force kill the thread
|
818
|
-
|
819
|
+
|
819
820
|
# Reset window title
|
820
821
|
print "\033]0;Git Game Show\007"
|
821
|
-
|
822
|
+
|
822
823
|
# Clear the timer status line at bottom
|
823
824
|
term_height = `tput lines`.to_i rescue 24
|
824
825
|
print "\e7" # Save cursor position
|
825
826
|
print "\e[#{term_height};1H" # Move to bottom line
|
826
827
|
print "\e[K" # Clear line
|
827
828
|
print "\e8" # Restore cursor position
|
828
|
-
|
829
|
+
|
829
830
|
# The server will send ANSWER_FEEDBACK message right away, then we'll see feedback
|
830
831
|
end
|
831
|
-
|
832
|
+
|
832
833
|
# Handle immediate feedback after submitting an answer
|
833
834
|
def handle_answer_feedback(data)
|
834
835
|
# Invalidate any running timer and reset window title
|
835
836
|
@current_timer_id = SecureRandom.uuid
|
836
837
|
print "\033]0;Git Game Show\007" # Reset window title
|
837
|
-
|
838
|
+
|
838
839
|
# Clear the timer status line at bottom
|
839
840
|
term_height = `tput lines`.to_i rescue 24
|
840
841
|
print "\e7" # Save cursor position
|
841
842
|
print "\e[#{term_height};1H" # Move to bottom line
|
842
843
|
print "\e[K" # Clear line
|
843
844
|
print "\e8" # Restore cursor position
|
844
|
-
|
845
|
+
|
845
846
|
# Don't clear screen, just display the feedback under the question
|
846
847
|
# This keeps the context of the question while showing the result
|
847
|
-
|
848
|
+
|
848
849
|
# Add a visual separator
|
849
850
|
puts "\n #{"─" * 40}".colorize(:light_black)
|
850
851
|
puts "\n"
|
851
|
-
|
852
|
+
|
852
853
|
# Show immediate feedback
|
853
854
|
if data['answer'] == "TIMEOUT"
|
854
855
|
# Special handling for timeouts
|
@@ -859,7 +860,7 @@ module GitGameShow
|
|
859
860
|
# Correct answer
|
860
861
|
points_text = data['points'] > 0 ? " (+#{data['points']} points)" : ""
|
861
862
|
puts " ✅ CORRECT! Your answer was correct: #{data['answer']}#{points_text}".colorize(:green)
|
862
|
-
|
863
|
+
|
863
864
|
# Show bonus points details if applicable
|
864
865
|
if data['points'] > 10 # More than base points
|
865
866
|
bonus = data['points'] - 10
|
@@ -870,7 +871,7 @@ module GitGameShow
|
|
870
871
|
puts " ❌ INCORRECT! The correct answer was: #{data['correct_answer']}".colorize(:red)
|
871
872
|
puts " You answered: #{data['answer']} (0 points)".colorize(:yellow)
|
872
873
|
end
|
873
|
-
|
874
|
+
|
874
875
|
puts "\n Waiting for the round to complete. Please wait for the next question...".colorize(:light_blue)
|
875
876
|
end
|
876
877
|
|
@@ -879,43 +880,43 @@ module GitGameShow
|
|
879
880
|
# Invalidate any running timer and reset window title
|
880
881
|
@current_timer_id = SecureRandom.uuid
|
881
882
|
print "\033]0;Git Game Show - Round Results\007" # Reset window title with context
|
882
|
-
|
883
|
+
|
883
884
|
# Start with a clean screen
|
884
885
|
clear_screen
|
885
|
-
|
886
|
+
|
886
887
|
puts "\n"
|
887
|
-
|
888
|
+
|
888
889
|
# Box is drawn with exactly 45 "━" characters for the top and bottom borders
|
889
890
|
# The top and bottom including borders are 48 characters wide
|
890
891
|
box_top = " ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓"
|
891
892
|
box_bottom = " ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛"
|
892
|
-
|
893
|
+
|
893
894
|
# Get the text to center
|
894
895
|
result_text = "ROUND RESULTS"
|
895
|
-
|
896
|
+
|
896
897
|
# Find exact box width by measuring the top border
|
897
898
|
box_width = box_top.length # Should be 48 with Unicode characters
|
898
|
-
|
899
|
+
|
899
900
|
# The inner width is the box width minus 2 characters for the borders
|
900
901
|
inner_width = box_width - (" ┃".length + "┃".length)
|
901
|
-
|
902
|
+
|
902
903
|
# Simply use Ruby's built-in center method for reliable centering
|
903
904
|
box_middle = " ┃" + result_text.center(inner_width) + "┃"
|
904
|
-
|
905
|
+
|
905
906
|
# Output the box
|
906
907
|
puts box_top.colorize(:cyan)
|
907
908
|
puts box_middle.colorize(:cyan)
|
908
909
|
puts box_bottom.colorize(:cyan)
|
909
910
|
puts "\n"
|
910
|
-
|
911
|
+
|
911
912
|
# Show question again
|
912
913
|
puts " Question: #{data['question'][:question]}".colorize(:light_blue)
|
913
914
|
puts " Correct answer: #{data['correct_answer']}".colorize(:green)
|
914
|
-
|
915
|
+
|
915
916
|
puts "\n All player results:".colorize(:cyan)
|
916
|
-
|
917
|
+
|
917
918
|
# Debug data temporarily removed
|
918
|
-
|
919
|
+
|
919
920
|
# Handle results based on structure
|
920
921
|
if data['results'].is_a?(Hash)
|
921
922
|
data['results'].each do |player, result|
|
@@ -925,11 +926,11 @@ module GitGameShow
|
|
925
926
|
correct = result[:correct] || result['correct'] || false
|
926
927
|
answer = result[:answer] || result['answer'] || "No answer"
|
927
928
|
points = result[:points] || result['points'] || 0
|
928
|
-
|
929
|
+
|
929
930
|
status = correct ? "✓" : "✗"
|
930
931
|
points_str = "(+#{points} points)"
|
931
932
|
player_str = player == name ? "#{player} (You)" : player
|
932
|
-
|
933
|
+
|
933
934
|
player_output = " #{player_str.ljust(20)} #{points_str.ljust(15)} #{answer} #{status}"
|
934
935
|
if correct
|
935
936
|
puts player_output.colorize(:green)
|
@@ -945,14 +946,14 @@ module GitGameShow
|
|
945
946
|
# Fallback message if results isn't a hash
|
946
947
|
puts " No detailed results available".colorize(:yellow)
|
947
948
|
end
|
948
|
-
|
949
|
+
|
949
950
|
# Display current scoreboard
|
950
951
|
if data['scores']
|
951
952
|
puts "\n Current Standings:".colorize(:yellow)
|
952
953
|
data['scores'].each_with_index do |(player, score), index|
|
953
954
|
player_str = player == name ? "#{player} (You)" : player
|
954
955
|
rank = index + 1
|
955
|
-
|
956
|
+
|
956
957
|
# Add medal emoji for top 3
|
957
958
|
rank_display = case rank
|
958
959
|
when 1 then "🥇"
|
@@ -960,50 +961,50 @@ module GitGameShow
|
|
960
961
|
when 3 then "🥉"
|
961
962
|
else "#{rank}."
|
962
963
|
end
|
963
|
-
|
964
|
+
|
964
965
|
output = " #{rank_display} #{player_str.ljust(20)} #{score} points"
|
965
|
-
|
966
|
+
|
966
967
|
if player == name
|
967
|
-
puts output.colorize(:light_yellow)
|
968
|
+
puts output.colorize(:light_yellow)
|
968
969
|
else
|
969
970
|
puts output.colorize(:light_blue)
|
970
971
|
end
|
971
972
|
end
|
972
973
|
end
|
973
|
-
|
974
|
+
|
974
975
|
puts "\n Next question coming up automatically...".colorize(:yellow)
|
975
976
|
end
|
976
|
-
|
977
|
+
|
977
978
|
def handle_scoreboard(data)
|
978
979
|
# Invalidate any running timer and reset window title
|
979
980
|
@current_timer_id = SecureRandom.uuid
|
980
981
|
print "\033]0;Git Game Show - Scoreboard\007" # Reset window title with context
|
981
|
-
|
982
|
+
|
982
983
|
# Always start with a clean screen for the scoreboard
|
983
984
|
clear_screen
|
984
|
-
|
985
|
+
|
985
986
|
puts "\n"
|
986
987
|
puts " ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓".colorize(:yellow)
|
987
988
|
puts " ┃ SCOREBOARD ┃".colorize(:yellow)
|
988
989
|
puts " ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛".colorize(:yellow)
|
989
990
|
puts "\n"
|
990
|
-
|
991
|
+
|
991
992
|
# Get player positions
|
992
993
|
position = 1
|
993
994
|
last_score = nil
|
994
|
-
|
995
|
+
|
995
996
|
data['scores'].each do |player, score|
|
996
997
|
# Determine position (handle ties)
|
997
998
|
position = data['scores'].values.index(score) + 1 if last_score != score
|
998
999
|
last_score = score
|
999
|
-
|
1000
|
+
|
1000
1001
|
# Highlight current player
|
1001
1002
|
player_str = player == name ? "#{player} (You)" : player
|
1002
|
-
|
1003
|
+
|
1003
1004
|
# Format with position
|
1004
1005
|
position_str = "#{position}."
|
1005
1006
|
score_str = "#{score} points"
|
1006
|
-
|
1007
|
+
|
1007
1008
|
# Add emoji for top 3
|
1008
1009
|
case position
|
1009
1010
|
when 1
|
@@ -1019,28 +1020,28 @@ module GitGameShow
|
|
1019
1020
|
puts " #{position_str.ljust(5)} #{player_str.ljust(25)} #{score_str}"
|
1020
1021
|
end
|
1021
1022
|
end
|
1022
|
-
|
1023
|
+
|
1023
1024
|
puts "\n Next round coming up soon...".colorize(:cyan)
|
1024
1025
|
end
|
1025
|
-
|
1026
|
+
|
1026
1027
|
def handle_game_end(data)
|
1027
1028
|
# Invalidate any running timer and reset window title
|
1028
1029
|
@current_timer_id = SecureRandom.uuid
|
1029
1030
|
print "\033]0;Git Game Show - Game Over\007" # Reset window title with context
|
1030
|
-
|
1031
|
+
|
1031
1032
|
# Clear any timer status line at the bottom
|
1032
1033
|
term_height = `tput lines`.to_i rescue 24
|
1033
1034
|
print "\e7" # Save cursor position
|
1034
1035
|
print "\e[#{term_height};1H" # Move to bottom line
|
1035
1036
|
print "\e[K" # Clear line
|
1036
1037
|
print "\e8" # Restore cursor position
|
1037
|
-
|
1038
|
+
|
1038
1039
|
# Completely clear the screen
|
1039
1040
|
clear_screen
|
1040
1041
|
@game_state = :ended
|
1041
|
-
|
1042
|
+
|
1042
1043
|
winner = data['winner']
|
1043
|
-
|
1044
|
+
|
1044
1045
|
# ASCII trophy art
|
1045
1046
|
trophy = <<-TROPHY
|
1046
1047
|
___________
|
@@ -1053,7 +1054,7 @@ module GitGameShow
|
|
1053
1054
|
) (
|
1054
1055
|
_.' '._
|
1055
1056
|
TROPHY
|
1056
|
-
|
1057
|
+
|
1057
1058
|
puts "\n\n"
|
1058
1059
|
puts trophy.colorize(:yellow)
|
1059
1060
|
puts "\n"
|
@@ -1061,32 +1062,32 @@ module GitGameShow
|
|
1061
1062
|
puts " ┃ GAME OVER ┃".colorize(:green)
|
1062
1063
|
puts " ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛".colorize(:green)
|
1063
1064
|
puts "\n"
|
1064
|
-
|
1065
|
+
|
1065
1066
|
winner_is_you = winner == name
|
1066
1067
|
if winner_is_you
|
1067
1068
|
puts " 🎉 Congratulations! You won! 🎉".colorize(:light_yellow)
|
1068
1069
|
else
|
1069
1070
|
puts " Winner: #{winner}! 🏆".colorize(:light_yellow)
|
1070
1071
|
end
|
1071
|
-
|
1072
|
+
|
1072
1073
|
puts "\n Final Scores:".colorize(:cyan)
|
1073
|
-
|
1074
|
+
|
1074
1075
|
# Get player positions
|
1075
1076
|
position = 1
|
1076
1077
|
last_score = nil
|
1077
|
-
|
1078
|
+
|
1078
1079
|
data['scores'].each do |player, score|
|
1079
1080
|
# Determine position (handle ties)
|
1080
1081
|
position = data['scores'].values.index(score) + 1 if last_score != score
|
1081
1082
|
last_score = score
|
1082
|
-
|
1083
|
+
|
1083
1084
|
# Highlight current player
|
1084
1085
|
player_str = player == name ? "#{player} (You)" : player
|
1085
|
-
|
1086
|
+
|
1086
1087
|
# Format with position
|
1087
1088
|
position_str = "#{position}."
|
1088
1089
|
score_str = "#{score} points"
|
1089
|
-
|
1090
|
+
|
1090
1091
|
# Add emoji for top 3
|
1091
1092
|
case position
|
1092
1093
|
when 1
|
@@ -1102,11 +1103,11 @@ module GitGameShow
|
|
1102
1103
|
puts " #{position_str.ljust(5)} #{player_str.ljust(25)} #{score_str}"
|
1103
1104
|
end
|
1104
1105
|
end
|
1105
|
-
|
1106
|
+
|
1106
1107
|
puts "\n\n Thanks for playing Git Game Show!".colorize(:green)
|
1107
1108
|
puts " Waiting for the host to start a new game...".colorize(:cyan)
|
1108
1109
|
puts " Press Ctrl+C to exit, or wait for the next game".colorize(:light_black)
|
1109
|
-
|
1110
|
+
|
1110
1111
|
# Keep client ready to receive a new game start or reset message
|
1111
1112
|
@game_over_timer = Thread.new do
|
1112
1113
|
begin
|
@@ -1120,31 +1121,31 @@ module GitGameShow
|
|
1120
1121
|
end
|
1121
1122
|
end
|
1122
1123
|
end
|
1123
|
-
|
1124
|
+
|
1124
1125
|
# Add a special method to handle game reset notifications
|
1125
1126
|
def handle_game_reset(data)
|
1126
1127
|
# Stop the game over timer if it's running
|
1127
1128
|
@game_over_timer&.kill if @game_over_timer&.alive?
|
1128
|
-
|
1129
|
+
|
1129
1130
|
# Reset game state
|
1130
1131
|
@game_state = :lobby
|
1131
|
-
|
1132
|
+
|
1132
1133
|
# Clear any lingering state
|
1133
1134
|
@players = @players || [] # Keep existing players list if we have one
|
1134
|
-
|
1135
|
+
|
1135
1136
|
# Show the waiting room again
|
1136
1137
|
clear_screen
|
1137
1138
|
display_waiting_room
|
1138
|
-
|
1139
|
+
|
1139
1140
|
# Show a prominent message that we're back in waiting room mode
|
1140
1141
|
puts "\n 🔄 The game has been reset by the host. Waiting for a new game to start...".colorize(:cyan)
|
1141
1142
|
puts " You can play again or press Ctrl+C to exit.".colorize(:cyan)
|
1142
1143
|
end
|
1143
|
-
|
1144
|
+
|
1144
1145
|
def handle_chat(data)
|
1145
1146
|
puts "[#{data['sender']}]: #{data['message']}".colorize(:light_blue)
|
1146
1147
|
end
|
1147
|
-
|
1148
|
+
|
1148
1149
|
def send_message(message)
|
1149
1150
|
begin
|
1150
1151
|
@ws.send(message.to_json)
|
@@ -1153,4 +1154,4 @@ module GitGameShow
|
|
1153
1154
|
end
|
1154
1155
|
end
|
1155
1156
|
end
|
1156
|
-
end
|
1157
|
+
end
|