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.
- checksums.yaml +4 -4
- data/lib/git_game_show/cli.rb +175 -123
- data/lib/git_game_show/game_server.rb +610 -233
- data/lib/git_game_show/player_client.rb +307 -292
- data/lib/git_game_show/updater.rb +17 -17
- data/lib/git_game_show/version.rb +1 -1
- data/lib/git_game_show.rb +4 -4
- data/mini_games/date_ordering_quiz.rb +78 -21
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f8afebed41ed43c7d886a48c4de43fb6243d29a7b7e8be0655d4e5b1676208d
|
4
|
+
data.tar.gz: 7fdc45f5fe5526980daf719a228edfb058aa5648db0120902835036c383e7352
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 620bc18628354eb9b5910a6cf87eb8d998c82b8325d05fd64ebabfc752e8fa9b8897c32ead3823b41fda8c3f7c0d84d9633eae458345eb0a3581664a2d6e1aed
|
7
|
+
data.tar.gz: dd3c6f2276b3780fcdc9a228d9a7b51979ede0bc4b5dbaa851949727b184c2ea139a2cca11f46e70394bd6da141f552a642beaecf1f38cbeb8a978d682938f6f
|
data/lib/git_game_show/cli.rb
CHANGED
@@ -7,7 +7,7 @@ module GitGameShow
|
|
7
7
|
desc 'version', 'Display Git Game Show version'
|
8
8
|
def version
|
9
9
|
puts "Git Game Show version #{GitGameShow::VERSION}"
|
10
|
-
|
10
|
+
|
11
11
|
# Check for updates if the Updater class exists
|
12
12
|
GitGameShow::Updater.check_for_updates if defined?(GitGameShow::Updater)
|
13
13
|
end
|
@@ -15,12 +15,12 @@ module GitGameShow
|
|
15
15
|
desc '', 'Show welcome screen'
|
16
16
|
def welcome
|
17
17
|
display_welcome_screen
|
18
|
-
|
18
|
+
|
19
19
|
# Check for updates if the Updater class exists
|
20
20
|
GitGameShow::Updater.check_for_updates if defined?(GitGameShow::Updater)
|
21
21
|
|
22
22
|
prompt = TTY::Prompt.new
|
23
|
-
choice = prompt.select("
|
23
|
+
choice = prompt.select("", [
|
24
24
|
{name: "Host a new game", value: :host},
|
25
25
|
{name: "Join a game", value: :join},
|
26
26
|
{name: "Check for updates", value: :update},
|
@@ -38,7 +38,7 @@ module GitGameShow
|
|
38
38
|
current_version = GitGameShow::VERSION
|
39
39
|
puts "Current version: #{current_version}"
|
40
40
|
puts "Checking for updates..."
|
41
|
-
|
41
|
+
|
42
42
|
latest_version = GitGameShow::Updater.send(:fetch_latest_version)
|
43
43
|
if latest_version.nil?
|
44
44
|
puts "Unable to connect to RubyGems.org. Please check your internet connection."
|
@@ -47,7 +47,7 @@ module GitGameShow
|
|
47
47
|
else
|
48
48
|
puts "✓ You already have the latest version (#{current_version})!".colorize(:green)
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
# Return to welcome screen after checking
|
52
52
|
welcome
|
53
53
|
else
|
@@ -61,7 +61,7 @@ module GitGameShow
|
|
61
61
|
end
|
62
62
|
|
63
63
|
desc 'host [OPTIONS]', 'Host a new game session'
|
64
|
-
method_option :port, type: :numeric, default: GitGameShow::DEFAULT_CONFIG[:
|
64
|
+
method_option :port, type: :numeric, default: GitGameShow::DEFAULT_CONFIG[:internal_port],
|
65
65
|
desc: 'Port to run the server on'
|
66
66
|
method_option :password, type: :string,
|
67
67
|
desc: 'Optional password for players to join (auto-generated if not provided)'
|
@@ -100,29 +100,30 @@ module GitGameShow
|
|
100
100
|
end
|
101
101
|
|
102
102
|
# Clear the screen
|
103
|
-
|
103
|
+
display_ggs
|
104
104
|
|
105
105
|
# Ask user which IP to use
|
106
106
|
prompt = TTY::Prompt.new
|
107
107
|
ip_choices = []
|
108
|
-
ip_choices << {name: "Local
|
109
|
-
ip_choices << {name: "
|
110
|
-
ip_choices << {name: "
|
108
|
+
ip_choices << {name: "Local IP (#{local_ip})", value: {:type => :local, :ip => local_ip}} if !local_ip.empty?
|
109
|
+
ip_choices << {name: "External IP (#{external_ip})", value: {:type => :external, :ip => external_ip}} if external_ip
|
110
|
+
ip_choices << {name: "Automatic tunneling", value: {:type => :tunnel}}
|
111
111
|
ip_choices << {name: "Custom IP or hostname", value: {:type => :custom}}
|
112
112
|
|
113
113
|
# Format question with explanation
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
114
|
+
display_info_box(:info, "Network Setup", [
|
115
|
+
" • Local IP: Only for players on the same network",
|
116
|
+
" • External IP: For internet players",
|
117
|
+
" - requires router port forwarding",
|
118
|
+
" • Automatic tunneling: For internet players",
|
119
|
+
" - requires free account & authorization through ngrok",
|
120
|
+
" • Custom IP: For advanced users with specific network setup"
|
121
|
+
])
|
122
122
|
|
123
123
|
ip_choice = prompt.select("How should players connect to your game?", ip_choices)
|
124
124
|
|
125
125
|
# Handle different connection options
|
126
|
+
external_port = options[:port] || GitGameShow::DEFAULT_CONFIG[:internal_port]
|
126
127
|
case ip_choice[:type]
|
127
128
|
when :local, :external
|
128
129
|
ip = ip_choice[:ip]
|
@@ -130,14 +131,16 @@ module GitGameShow
|
|
130
131
|
ip = prompt.ask("Enter your IP address or hostname:", required: true)
|
131
132
|
when :tunnel
|
132
133
|
# Clear the screen and show informative message about ngrok
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
134
|
+
display_ggs
|
135
|
+
display_info_box(:info, "Ngrok Tunnel Setup", [
|
136
|
+
" The automatic tunneling option uses ngrok, a secure tunneling service.",
|
137
|
+
" This will allow players to connect from anywhere without port forwarding.",
|
138
|
+
" ",
|
139
|
+
" If you do not already have ngrok set up:",
|
140
|
+
" • The ngrok client will be downloaded and started automatically",
|
141
|
+
" • Instructions will be provided to set up a required free account on ngrok",
|
142
|
+
" • The tunnel will be established and the game will start"
|
143
|
+
])
|
141
144
|
|
142
145
|
# Check if ngrok is available
|
143
146
|
begin
|
@@ -267,18 +270,16 @@ module GitGameShow
|
|
267
270
|
auth_needed = auth_check.include?("auth") || auth_check.include?("authtoken") || auth_check.include?("ERR") || auth_check.include?("error")
|
268
271
|
|
269
272
|
if auth_needed
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
puts " 2. Get your authtoken from https://dashboard.ngrok.com/get-started/your-authtoken"
|
281
|
-
puts " 3. Enter your authtoken below"
|
273
|
+
display_ggs
|
274
|
+
display_info_box(:info, 'Ngrok Authorization Required', [
|
275
|
+
" Starting with ngrok v3, you need to create a free account and authorize ",
|
276
|
+
" to use TCP tunnels. This is a one-time setup. ",
|
277
|
+
" ",
|
278
|
+
" Steps to authorize ngrok: ",
|
279
|
+
" 1. Create a free account at https://ngrok.com/signup ",
|
280
|
+
" 2. Get an authtoken https://dashboard.ngrok.com/get-started/your-authtoken ",
|
281
|
+
" 3. Enter your authtoken below "
|
282
|
+
])
|
282
283
|
puts ""
|
283
284
|
|
284
285
|
prompt = TTY::Prompt.new
|
@@ -352,9 +353,7 @@ module GitGameShow
|
|
352
353
|
# Use the host with the ngrok-assigned port
|
353
354
|
ip = host
|
354
355
|
# Create a new port variable instead of modifying the frozen options hash
|
355
|
-
|
356
|
-
# Log the port change
|
357
|
-
puts "Ngrok assigned port: #{ngrok_port} (original port: #{options[:port]})"
|
356
|
+
external_port = port.to_i
|
358
357
|
|
359
358
|
tunnel_url = public_url
|
360
359
|
|
@@ -363,17 +362,22 @@ module GitGameShow
|
|
363
362
|
system("pkill -f ngrok > /dev/null 2>&1 || taskkill /F /IM ngrok.exe > /dev/null 2>&1")
|
364
363
|
end
|
365
364
|
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
365
|
+
display_ggs
|
366
|
+
|
367
|
+
# We need to handle the colorized content within the green box
|
368
|
+
content = [
|
369
|
+
" Your game is now accessible over the internet",
|
370
|
+
" The ngrok tunnel is running in the background:",
|
371
|
+
" ",
|
372
|
+
" ngrok ip: #{ip.ljust(57)}".colorize(:light_blue),
|
373
|
+
" ngrok port: #{external_port.to_s.ljust(57)}".colorize(:light_blue),
|
374
|
+
" ngrok public URL: #{public_url.ljust(57)}".colorize(:light_blue),
|
375
|
+
" ",
|
376
|
+
" DO NOT close the terminal window until your game is finished",
|
377
|
+
" The tunnel will automatically close when you exit the game"
|
378
|
+
]
|
379
|
+
|
380
|
+
display_info_box(:success, 'Ngrok tunnel established successfully!', content)
|
377
381
|
puts ""
|
378
382
|
puts "Press Enter to continue..."
|
379
383
|
gets
|
@@ -386,36 +390,30 @@ module GitGameShow
|
|
386
390
|
end
|
387
391
|
|
388
392
|
unless tunnel_url
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
puts " 3. Run this command: ngrok config add-authtoken <YOUR_TOKEN>"
|
402
|
-
puts " 4. Then restart the game and try tunneling again"
|
403
|
-
puts ""
|
393
|
+
display_ggs
|
394
|
+
display_info_box(:error, 'Tunnel setup failed!', [
|
395
|
+
" ngrok tunnel could not be established",
|
396
|
+
" Most common reason: Missing or invalid ngrok authentication token",
|
397
|
+
" Falling back to local IP (players will only be able to join locally)",
|
398
|
+
" ",
|
399
|
+
" Common solutions:",
|
400
|
+
" 1. Create a free account at https://ngrok.com/signup",
|
401
|
+
" 2. Get an authtoken https://dashboard.ngrok.com/get-started/your-authtoken",
|
402
|
+
" 3. Run this command: ngrok config add-authtoken <YOUR_TOKEN>",
|
403
|
+
" 4. Then restart the game and try tunneling again"
|
404
|
+
])
|
404
405
|
puts "Press Enter to continue with local IP..."
|
405
406
|
gets
|
406
407
|
|
407
408
|
ip = local_ip
|
408
409
|
end
|
409
410
|
rescue => e
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
puts "┃ • Falling back to local IP (players will only be able to join locally) ┃"
|
417
|
-
puts "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛"
|
418
|
-
puts ""
|
411
|
+
display_ggs
|
412
|
+
display_info_box(:error, 'Error setting up ngrok tunnel!', [
|
413
|
+
" An error occurred while trying to set up the ngrok tunnel",
|
414
|
+
" This is likely an authentication issue with ngrok",
|
415
|
+
" Falling back to local IP (players will only be able to join locally)"
|
416
|
+
])
|
419
417
|
puts "Error details: #{e.message}"
|
420
418
|
puts ""
|
421
419
|
puts "Press Enter to continue with local IP..."
|
@@ -425,16 +423,18 @@ module GitGameShow
|
|
425
423
|
end
|
426
424
|
end
|
427
425
|
|
428
|
-
#
|
429
|
-
#
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
426
|
+
# Now ask for the port (after network setup is complete)
|
427
|
+
# Skip if ngrok assigned a port already
|
428
|
+
unless ip_choice[:type] == :tunnel
|
429
|
+
internal_port = prompt.ask("Which port would you like to use?",
|
430
|
+
convert: :int,
|
431
|
+
default: GitGameShow::DEFAULT_CONFIG[:internal_port])
|
432
|
+
|
433
|
+
# Update the server's port
|
434
|
+
server.instance_variable_set(:@port, internal_port)
|
435
|
+
end
|
436
|
+
|
437
|
+
secure_link = "gitgame://#{ip}:#{external_port}/#{URI.encode_www_form_component(password)}"
|
438
438
|
|
439
439
|
# Start the server with the improved UI and pass the join link
|
440
440
|
server.start_with_ui(secure_link)
|
@@ -457,15 +457,15 @@ module GitGameShow
|
|
457
457
|
if secure_link.start_with?('gitgame://')
|
458
458
|
uri = URI.parse(secure_link.sub('gitgame://', 'http://'))
|
459
459
|
host = uri.host
|
460
|
-
port = uri.port || GitGameShow::DEFAULT_CONFIG[:
|
460
|
+
port = uri.port || GitGameShow::DEFAULT_CONFIG[:internal_port]
|
461
461
|
password = URI.decode_www_form_component(uri.path.sub('/', ''))
|
462
|
-
|
462
|
+
|
463
463
|
# Check if this is a secure (ngrok) connection from query params
|
464
464
|
is_secure = !uri.query.nil? && uri.query.include?('secure=')
|
465
465
|
else
|
466
466
|
# Legacy format - assume it's host:port
|
467
467
|
host, port = secure_link.split(':')
|
468
|
-
port ||= GitGameShow::DEFAULT_CONFIG[:
|
468
|
+
port ||= GitGameShow::DEFAULT_CONFIG[:internal_port]
|
469
469
|
password = options[:password]
|
470
470
|
is_secure = false
|
471
471
|
|
@@ -508,48 +508,64 @@ module GitGameShow
|
|
508
508
|
|
509
509
|
private
|
510
510
|
|
511
|
-
def
|
511
|
+
def display_ggs
|
512
512
|
clear_screen
|
513
|
+
lines = [
|
514
|
+
" ██████╗ ".colorize(:red) + " ██████╗ ".colorize(:green) + " █████╗".colorize(:blue),
|
515
|
+
"██╔════╝ ".colorize(:red) + " ██╔════╝ ".colorize(:green) + " ██╔═══╝".colorize(:blue),
|
516
|
+
"██║ ███╗".colorize(:red) + " ██║ ███╗".colorize(:green) + " ███████╗".colorize(:blue),
|
517
|
+
"██║ ██║".colorize(:red) + " ██║ ██║".colorize(:green) + " ╚════██║".colorize(:blue),
|
518
|
+
"╚██████╔╝".colorize(:red) + " ╚██████╔╝".colorize(:green) + " ██████╔╝".colorize(:blue),
|
519
|
+
" ╚═════╝ ".colorize(:red) + " ╚═════╝ ".colorize(:green) + " ╚═════╝ ".colorize(:blue),
|
520
|
+
]
|
521
|
+
lines.each { |line| puts line.center(120) }
|
522
|
+
end
|
513
523
|
|
514
|
-
|
515
|
-
|
516
|
-
puts "
|
517
|
-
puts "
|
518
|
-
puts "
|
519
|
-
puts "
|
520
|
-
|
521
|
-
puts "
|
522
|
-
|
523
|
-
puts "
|
524
|
-
puts "
|
525
|
-
puts "
|
526
|
-
puts "
|
527
|
-
|
528
|
-
puts "
|
529
|
-
puts "Test your team's Git knowledge with fun trivia games.\n\n"
|
524
|
+
def display_game_logo
|
525
|
+
clear_screen
|
526
|
+
puts (" ██████╗ ██╗████████╗".colorize(:red) + " ██████╗ █████╗ ███╗ ███╗███████╗".colorize(:green)).center(110)
|
527
|
+
puts ("██╔════╝ ██║╚══██╔══╝".colorize(:red) + " ██╔════╝ ██╔══██╗████╗ ████║██╔════╝".colorize(:green)).center(110)
|
528
|
+
puts ("██║ ███╗██║ ██║ ".colorize(:red) + " ██║ ███╗███████║██╔████╔██║█████╗ ".colorize(:green)).center(110)
|
529
|
+
puts ("██║ ██║██║ ██║ ".colorize(:red) + " ██║ ██║██╔══██║██║╚██╔╝██║██╔══╝ ".colorize(:green)).center(110)
|
530
|
+
puts ("╚██████╔╝██║ ██║ ".colorize(:red) + " ╚██████╔╝██║ ██║██║ ╚═╝ ██║███████╗".colorize(:green)).center(110)
|
531
|
+
puts (" ╚═════╝ ╚═╝ ╚═╝ ".colorize(:red) + " ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝".colorize(:green)).center(110)
|
532
|
+
|
533
|
+
puts (" █████╗ ██╗ ██╗ ██████╗ ██╗ ██╗".colorize(:blue)).center(95)
|
534
|
+
puts ("██╔═══╝ ██║ ██║██╔═══██╗██║ ██║".colorize(:blue)).center(95)
|
535
|
+
puts ("███████╗███████║██║ ██║██║ █╗ ██║".colorize(:blue)).center(95)
|
536
|
+
puts ("╚════██║██╔══██║██║ ██║██║███╗██║".colorize(:blue)).center(95)
|
537
|
+
puts ("██████╔╝██║ ██║╚██████╔╝╚███╔███╔╝".colorize(:blue)).center(95)
|
538
|
+
puts ("╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══╝╚══╝ ".colorize(:blue)).center(95)
|
530
539
|
end
|
531
540
|
|
532
|
-
def
|
533
|
-
|
541
|
+
def display_welcome_screen
|
542
|
+
display_game_logo
|
543
|
+
puts ""
|
544
|
+
display_info_box(:info, "Welcome to Git Game Show! version " + GitGameShow::VERSION, [
|
545
|
+
" Test your team's knowledge with fun mini games based on git commit history.",
|
546
|
+
"",
|
547
|
+
" Choose to host a new game or join an existing one."
|
548
|
+
])
|
549
|
+
end
|
534
550
|
|
535
|
-
|
536
|
-
|
537
|
-
convert: :int,
|
538
|
-
default: GitGameShow::DEFAULT_CONFIG[:rounds]) do |q|
|
539
|
-
q.validate(/^([1-9]|10)$/, "Please enter a number between 1 and 10")
|
540
|
-
end
|
541
|
-
port = prompt.ask("Which port would you like to use?",
|
542
|
-
convert: :int,
|
543
|
-
default: GitGameShow::DEFAULT_CONFIG[:port])
|
551
|
+
def prompt_for_host_options
|
552
|
+
prompt = TTY::Prompt.new
|
544
553
|
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
}
|
554
|
+
repo_path = prompt.ask("Enter the path to the Git repository (leave empty for current directory):", default: '.')
|
555
|
+
rounds = prompt.ask("How many rounds would you like to play? (1-10)",
|
556
|
+
convert: :int,
|
557
|
+
default: GitGameShow::DEFAULT_CONFIG[:rounds]) do |q|
|
558
|
+
q.validate(/^([1-9]|10)$/, "Please enter a number between 1 and 10")
|
551
559
|
end
|
552
560
|
|
561
|
+
# Call the host method with the provided options (password will be auto-generated)
|
562
|
+
# Port will be asked after network setup
|
563
|
+
invoke :host, [], {
|
564
|
+
repo_path: repo_path,
|
565
|
+
rounds: rounds
|
566
|
+
}
|
567
|
+
end
|
568
|
+
|
553
569
|
def prompt_for_join_options
|
554
570
|
prompt = TTY::Prompt.new
|
555
571
|
|
@@ -573,5 +589,41 @@ module GitGameShow
|
|
573
589
|
|
574
590
|
"#{adjectives.sample}-#{nouns.sample}-#{rand(100..999)}"
|
575
591
|
end
|
592
|
+
|
593
|
+
def display_info_box(kind, heading, content, width = 80)
|
594
|
+
# Set color based on the kind of box
|
595
|
+
color = case kind.to_sym
|
596
|
+
when :info
|
597
|
+
:light_blue
|
598
|
+
when :success
|
599
|
+
:green
|
600
|
+
when :error
|
601
|
+
:red
|
602
|
+
else
|
603
|
+
:light_blue
|
604
|
+
end
|
605
|
+
|
606
|
+
# Calculate border width - using 78 as in existing boxes
|
607
|
+
content_width = width - 2
|
608
|
+
|
609
|
+
# Create the box with borders and heading in the specified color
|
610
|
+
puts ("╭" + "─" * content_width + "╮").colorize(color)
|
611
|
+
puts "│#{heading.center(content_width)}│".colorize(color)
|
612
|
+
puts ("├" + "─" * content_width + "┤").colorize(color)
|
613
|
+
|
614
|
+
# Split content by lines and format each line
|
615
|
+
if content.is_a?(String)
|
616
|
+
content.each_line do |line|
|
617
|
+
puts "│".colorize(color) + "#{line.chomp}".ljust(content_width) + "│".colorize(color)
|
618
|
+
end
|
619
|
+
elsif content.is_a?(Array)
|
620
|
+
content.each do |line|
|
621
|
+
puts "│".colorize(color) + "#{line}".ljust(content_width) + "│".colorize(color)
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
puts ("╰" + "─" * content_width + "╯").colorize(color)
|
626
|
+
puts ""
|
627
|
+
end
|
576
628
|
end
|
577
629
|
end
|