git_game_show 0.1.8 → 0.1.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 719118cfd107443e62e4c5e91fe2ee425bf58d30b9c681df744e9e8fbc25f81d
4
- data.tar.gz: 80cb0a7b0f9653d33e0e58057eb9fc85df59757486e452c22de2ea3508a0bcb2
3
+ metadata.gz: 6dd69e30776e28d63d3fd20db47716c0e957dace72788a5e0479047fe8cbe708
4
+ data.tar.gz: cd8e8579ec722b25a67ffd1c8268f35a724dcf75cd863420ffebad9025f1ebf4
5
5
  SHA512:
6
- metadata.gz: 6ba0dec0a4e51517994a4c574cb1d1c738780e2a812a4d516fb53f18d46d9c08661ec924a67dbb228d4efffe360e0f47bebe804464fe7b83e10ad053a859da96
7
- data.tar.gz: acc62cb0dcaf6ae4d6249b8a1b4b5b6f03fc3d2d19016dc2f65a64991d31069b7b5b1786ff5c1566575c193473ba36d4ac3285385f46d74f81f30e6e21449a10
6
+ metadata.gz: 8874ab5bb9a8349e9b22926e8456fef2aa1ce4bcdaf1ca14b170d82d6e0491a68db6c576eda153b92fbca942efa1861dd44d139d1d57e709fe2853e5c2b36fe6
7
+ data.tar.gz: 37c9292edb46b4e3be1283efbd09b3762c504696a5d875a16c7d8a12fdbc68265319f40b4db992e0c4fd71d42bf420abcce75bd3e62402c741ba38e459c265a2
@@ -510,6 +510,7 @@ module GitGameShow
510
510
 
511
511
  def display_ggs
512
512
  clear_screen
513
+ puts ""
513
514
  lines = [
514
515
  " ██████╗ ".colorize(:red) + " ██████╗ ".colorize(:green) + " █████╗".colorize(:blue),
515
516
  "██╔════╝ ".colorize(:red) + " ██╔════╝ ".colorize(:green) + " ██╔═══╝".colorize(:blue),
@@ -543,7 +543,7 @@ module GitGameShow
543
543
 
544
544
  # Display a fun "Game Starting" animation
545
545
  box_width = 40
546
- puts "\n\n"
546
+ puts "\n"
547
547
  puts ("╭" + "─" * box_width + "╮").center(@game_width).colorize(:green)
548
548
  puts ("│" + "Game starting...".center(box_width) + "│").center(@game_width).colorize(:green)
549
549
  puts ("╰" + "─" * box_width + "╯").center(@game_width).colorize(:green)
@@ -600,8 +600,6 @@ module GitGameShow
600
600
  mini_game = data['mini_game']
601
601
  description = data['description']
602
602
 
603
- puts "\n\n"
604
-
605
603
  # Box is drawn with exactly 45 "━" characters for the top and bottom borders
606
604
  # The top and bottom including borders are 48 characters wide
607
605
  box_width = 42
@@ -610,6 +608,7 @@ module GitGameShow
610
608
  box_middle = "│#{"Round #{round_num} of #{total_rounds}".center(box_width - 2)}│".center(@game_width)
611
609
 
612
610
  # Output the box
611
+ puts "\n"
613
612
  puts box_top.colorize(:green)
614
613
  puts box_middle.colorize(:green)
615
614
  puts box_bottom.colorize(:green)
@@ -643,9 +642,6 @@ module GitGameShow
643
642
 
644
643
  # No need to reserve space for timer - it will be at the bottom of the screen
645
644
 
646
- # Display question header
647
- puts "\n"
648
-
649
645
  # Draw a simple box for the question header
650
646
  box_width = 42
651
647
  box_top = ("╭" + "─" * (box_width - 2) + "╮").center(@game_width)
@@ -653,6 +649,7 @@ module GitGameShow
653
649
  box_middle = "│#{"Question #{question_num} of #{total_questions}".center(box_width - 2)}│".center(@game_width)
654
650
 
655
651
  # Output the question box
652
+ puts "\n"
656
653
  puts box_top.colorize(:light_blue)
657
654
  puts box_middle.colorize(:light_blue)
658
655
  puts box_bottom.colorize(:light_blue)
@@ -867,8 +864,6 @@ module GitGameShow
867
864
  # Start with a clean screen
868
865
  clear_screen
869
866
 
870
- puts "\n"
871
-
872
867
  # Box is drawn with exactly 45 "━" characters for the top and bottom borders
873
868
  # The top and bottom including borders are 48 characters wide
874
869
  box_width = 40
@@ -877,6 +872,7 @@ module GitGameShow
877
872
  box_middle = "│#{'Round Results'.center(box_width)}│".center(@game_width)
878
873
 
879
874
  # Output the box
875
+ puts "\n"
880
876
  puts box_top.colorize(:light_blue)
881
877
  puts box_middle.colorize(:light_blue)
882
878
  puts box_bottom.colorize(:light_blue)
@@ -988,7 +984,7 @@ module GitGameShow
988
984
  clear_screen
989
985
 
990
986
  box_width = 40
991
- puts ""
987
+ puts "\n"
992
988
  puts ("╭" + "─" * box_width + "╮").center(@game_width).colorize(:yellow)
993
989
  puts "│#{'Scoreboard'.center(box_width)}┃".center(@game_width).colorize(:yellow)
994
990
  puts ("╰" + "─" * box_width + "╯").center(@game_width).colorize(:yellow)
@@ -1,4 +1,4 @@
1
1
  module GitGameShow
2
2
  # Current version of Git Game Show
3
- VERSION = "0.1.8"
3
+ VERSION = "0.1.9"
4
4
  end
@@ -1,4 +1,7 @@
1
1
  module GitGameShow
2
+ # Disable debug mode for normal operation
3
+ $FILE_QUIZ_DEBUG = false
4
+
2
5
  class FileQuiz < MiniGame
3
6
  self.name = "File Quiz"
4
7
  self.description = "Match the commit message to the right changed file!"
@@ -15,39 +18,54 @@ module GitGameShow
15
18
 
16
19
  def generate_questions(repo)
17
20
  begin
18
- # Get commits from the repo - based on similar approach as AuthorQuiz
19
- # Start by getting a larger number of commits to ensure enough variety
20
- commit_count = [self.class.questions_per_round * 10, 100].min
21
-
22
- # Get all commits
23
- commits = repo.log(commit_count).to_a
24
-
21
+ # Use the same approach as AuthorQuiz - get ALL commits using the helper method
22
+ commits = get_all_commits(repo)
23
+
24
+ # Check if we got any commits at all
25
+ if commits.nil? || commits.empty?
26
+ # Silently fall back to sample questions
27
+ return generate_sample_questions
28
+ end
29
+
25
30
  # Shuffle commits for better variety
26
31
  commits.shuffle!
27
-
32
+
28
33
  # Process commits to find ones with good file changes
29
34
  valid_commits = []
30
-
35
+
31
36
  commits.each do |commit|
32
37
  # Get changed files for this commit
33
38
  changed_files = []
34
-
39
+
35
40
  begin
36
- # Try to get the diff with previous commit
41
+ # Use standard Git methods instead of run_command (silently)
42
+
43
+ # Use git commands quietly without showing output
37
44
  if commit.parents.empty?
38
- # First commit - get the files directly
39
- diff_output = repo.lib.run_command('show', ['--name-only', '--pretty=format:', commit.sha])
40
- changed_files = diff_output.split("\n").reject(&:empty?)
45
+ # For first commit, get files directly
46
+ cmd = "cd #{repo.dir.path} && git show --name-only --pretty=format: #{commit.sha} 2>/dev/null"
47
+ diff_output = `#{cmd}`
41
48
  else
42
- # Regular commit with parent
43
- diff_output = repo.lib.run_command('diff', ['--name-only', "#{commit.sha}^", commit.sha])
44
- changed_files = diff_output.split("\n").reject(&:empty?)
49
+ # For normal commits with parents
50
+ cmd = "cd #{repo.dir.path} && git diff --name-only #{commit.sha}^ #{commit.sha} 2>/dev/null"
51
+ diff_output = `#{cmd}`
52
+
53
+ # If diff returns empty, try using show as fallback
54
+ if diff_output.strip.empty?
55
+ cmd = "cd #{repo.dir.path} && git show --name-only --pretty=format: #{commit.sha} 2>/dev/null"
56
+ diff_output = `#{cmd}`
57
+ end
45
58
  end
46
-
47
- # Skip if no files or too many files (probably a merge or refactoring)
59
+
60
+ # Parse the output to get changed files (quietly)
61
+ changed_files = diff_output.split("\n").reject(&:empty?)
62
+
63
+ # Skip if no files changed (can't create a question for this)
48
64
  next if changed_files.empty?
49
- next if changed_files.size > 8 # Skip large commits that likely changed multiple unrelated files
50
-
65
+
66
+ # Super relaxed - accept ANY commit with files that changed
67
+ # No more filtering by number of files
68
+
51
69
  # Create structure with relevant commit data
52
70
  valid_commits << {
53
71
  sha: commit.sha,
@@ -56,29 +74,31 @@ module GitGameShow
56
74
  date: commit.date,
57
75
  files: changed_files
58
76
  }
59
-
77
+
60
78
  # Once we have enough commits, we can stop
61
- break if valid_commits.size >= self.class.questions_per_round * 3
79
+ # Get more commits to have a better selection
80
+ break if valid_commits.size >= self.class.questions_per_round * 5
62
81
  rescue => e
63
- # Skip problematic commits
82
+ # Silently skip problematic commits
64
83
  next
65
84
  end
66
85
  end
67
-
68
- # If we couldn't find enough good commits, fall back to samples
69
- if valid_commits.size < self.class.questions_per_round
86
+
87
+ # Never fall back to samples as long as we have at least 1 valid commit
88
+ if valid_commits.empty?
89
+ # Silently fall back to sample questions if needed
70
90
  return generate_sample_questions
71
91
  end
72
-
92
+
73
93
  # Prioritize commits that modified interesting files (not just .gitignore etc.)
74
94
  prioritized_commits = valid_commits.sort_by do |commit|
75
95
  # Higher score = more interesting commit
76
96
  score = 0
77
-
97
+
78
98
  # Prioritize based on file types
79
99
  commit[:files].each do |file|
80
100
  ext = File.extname(file).downcase
81
-
101
+
82
102
  case ext
83
103
  when '.rb', '.js', '.py', '.java', '.tsx', '.jsx'
84
104
  score += 3 # Source code is most interesting
@@ -90,30 +110,33 @@ module GitGameShow
90
110
  score -= 1 # Less interesting files
91
111
  end
92
112
  end
93
-
113
+
94
114
  # Prioritize based on commit message length - longer messages are often more descriptive
95
115
  message_length = commit[:message].to_s.strip.length
96
116
  score += [message_length / 20, 5].min
97
-
117
+
98
118
  # Return negative score so highest scores come first in sort
99
119
  -score
100
120
  end
101
-
102
- # Select top commits for questions
103
- selected_commits = prioritized_commits.take(self.class.questions_per_round)
104
-
121
+
122
+ # Take as many commits as we need for questions
123
+ needed_commits = [self.class.questions_per_round, prioritized_commits.size].min
124
+ selected_commits = prioritized_commits.take(needed_commits)
125
+
105
126
  # Create questions from selected commits
106
127
  questions = []
107
-
128
+
108
129
  selected_commits.each do |commit|
109
130
  # Choose the most interesting file as the correct answer
110
- # (Sort by extension priority, then by path length to favor shorter paths)
111
131
  files = commit[:files]
112
-
132
+
133
+ # Skip if somehow we got a commit with no files
134
+ next if files.empty?
135
+
113
136
  # Score files by interestingness
114
137
  scored_files = files.map do |file|
115
138
  ext = File.extname(file).downcase
116
-
139
+
117
140
  # Start with base score by extension
118
141
  score = case ext
119
142
  when '.rb', '.js', '.py', '.java', '.tsx', '.jsx'
@@ -129,32 +152,33 @@ module GitGameShow
129
152
  else
130
153
  5 # Other files are neutral
131
154
  end
132
-
155
+
133
156
  # Shorter paths are usually more recognizable
134
157
  score -= [file.length / 10, 5].min
135
-
158
+
136
159
  # Prefer files in main directories (src, lib, app) over deeply nested ones
137
160
  if file.start_with?('src/', 'lib/', 'app/')
138
161
  score += 3
139
162
  end
140
-
163
+
141
164
  [file, score]
142
165
  end
143
-
166
+
144
167
  # Sort by score (highest first) and select most interesting file
145
- correct_file = scored_files.sort_by { |_, score| -score }.first[0]
146
-
168
+ scored_files.sort_by! { |_, score| -score }
169
+ correct_file = scored_files.first[0]
170
+
147
171
  # Get incorrect options from other commits
148
172
  other_files = []
149
173
  other_commits = selected_commits - [commit]
150
-
174
+
151
175
  # Collect files from other commits
152
176
  other_commits.each do |other_commit|
153
177
  other_commit[:files].each do |file|
154
178
  other_files << file unless files.include?(file)
155
179
  end
156
180
  end
157
-
181
+
158
182
  # If we don't have enough other files, use some from sample data
159
183
  if other_files.size < 3
160
184
  sample_files = [
@@ -164,19 +188,19 @@ module GitGameShow
164
188
  ]
165
189
  other_files += sample_files.reject { |f| files.include?(f) }
166
190
  end
167
-
191
+
168
192
  # Take up to 3 unique other files, prioritizing diverse ones
169
193
  other_files = other_files.uniq.sample(3)
170
-
194
+
171
195
  # Create options array with the correct answer and incorrect ones
172
196
  all_options = ([correct_file] + other_files).shuffle
173
-
197
+
174
198
  # Format the commit date nicely
175
199
  nice_date = commit[:date].strftime('%b %d, %Y') rescue "Unknown date"
176
-
200
+
177
201
  # Clean up commit message - take first line if multiple lines
178
202
  message = commit[:message].to_s.split("\n").first.strip
179
-
203
+
180
204
  # Format consistently with other mini-games
181
205
  questions << {
182
206
  question: "Which file was most likely changed in this commit?\n\n \"#{message}\"",
@@ -185,62 +209,66 @@ module GitGameShow
185
209
  correct_answer: correct_file
186
210
  }
187
211
  end
188
-
189
- # Final safety check - if we couldn't create enough questions, use samples
212
+
213
+ # If we still couldn't create enough questions, use a mix of real and samples
190
214
  if questions.size < self.class.questions_per_round
191
- return generate_sample_questions
215
+ # Add sample questions to fill the remaining slots (silently)
216
+ sample_questions = generate_sample_questions
217
+ remaining_slots = self.class.questions_per_round - questions.size
218
+ questions += sample_questions.take(remaining_slots)
192
219
  end
193
-
220
+
194
221
  return questions
195
222
  rescue => e
196
- # If anything fails, fall back to sample questions
223
+ # If anything fails, silently fall back to sample questions
197
224
  return generate_sample_questions
198
225
  end
199
226
  end
200
227
 
201
228
  def evaluate_answers(question, player_answers)
202
229
  results = {}
203
-
230
+
204
231
  player_answers.each do |player_name, answer_data|
205
232
  answered = answer_data[:answered] || false
206
233
  player_answer = answer_data[:answer]
207
234
  correct = player_answer == question[:correct_answer]
208
-
235
+
209
236
  points = correct ? 10 : 0
210
-
237
+
211
238
  # Bonus points for fast answers (if correct)
212
239
  if correct
213
240
  time_taken = answer_data[:time_taken] || 15
214
-
241
+
215
242
  if time_taken < 5
216
243
  points += 5
217
244
  elsif time_taken < 10
218
245
  points += 3
219
246
  end
220
247
  end
221
-
248
+
222
249
  results[player_name] = {
223
250
  answer: player_answer,
224
251
  correct: correct,
225
252
  points: points
226
253
  }
227
254
  end
228
-
255
+
229
256
  results
230
257
  end
231
258
 
232
259
  # Generate sample questions only used when no repository data is available
233
260
  def generate_sample_questions
261
+ # No debug message in production
234
262
  questions = []
235
263
 
236
264
  # Common file options
237
265
  common_files = [
238
266
  "src/main.js",
239
267
  "README.md",
240
- "lib/utils.js",
268
+ "lib/utils.js",
241
269
  "css/styles.css"
242
270
  ]
243
-
271
+
244
272
  # Common sample commit messages
245
273
  sample_messages = [
246
274
  "Update documentation with new API endpoints",
@@ -254,14 +282,14 @@ module GitGameShow
254
282
  self.class.questions_per_round.times do |i|
255
283
  # Use modulo to cycle through sample messages
256
284
  message = sample_messages[i % sample_messages.size]
257
-
285
+
258
286
  # Different correct answers for each question
259
287
  correct_file = common_files[i % common_files.size]
260
-
288
+
261
289
  # Options are all files with the correct one included
262
290
  all_options = common_files.shuffle
263
-
264
- # Create the question
291
+
292
+ # Create the question - clearly label as sample data
265
293
  questions << {
266
294
  question: "Which file was most likely changed in this commit?\n\n \"#{message} (SAMPLE)\"",
267
295
  commit_info: "sample#{i} (Demo Question)",
@@ -272,7 +300,5 @@ module GitGameShow
272
300
 
273
301
  questions
274
302
  end
275
-
276
- # No private methods needed anymore
277
303
  end
278
304
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git_game_show
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Paulson