git_game_show 0.1.3 → 0.1.5

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