Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## What is it?

In the git game, you guess who made a commit to your team's repo based on their commit message:
In the git game, you guess who made a commit to your team's repo based on their commit message:

![](https://cloud.githubusercontent.com/assets/21294/6428030/ba13a98c-bf60-11e4-92fa-ae25302e9a84.png)

Expand All @@ -13,7 +13,7 @@ The goal is to get the longest streak! (It's harder than you think...)
- [Download the `git-game` executable](https://github.com/jsomers/git-game/releases/tag/1.2)
- Put it somewhere on your PATH (like /usr/local/bin)
- Then, in any git repository, run `git game`
- (If you'd like, you can select a subset of commits, for example, `git game --after={2014-08-08}`. For more options, see [http://gitref.org/inspect/](http://gitref.org/inspect/).)
- (If you'd like, you can select a subset of commits, for example, `git game --after={2014-08-08}`. For more options, see [Git - git-log documentation](https://git-scm.com/docs/git-log).)

## Requirements

Expand Down
138 changes: 80 additions & 58 deletions git-game
Original file line number Diff line number Diff line change
@@ -1,116 +1,138 @@
#!/usr/bin/ruby
# frozen_string_literal: true

require 'English'

longest_streak = streak = 0
difficulty = :normal

# -- Exit gracefully --
Signal.trap("INT") {
Signal.trap('INT') do
puts "\nLongest streak: #{longest_streak}"
exit 0
}
end

def print_header
puts "----------------------------------------------------------"
puts " THE GIT GAME "
puts "----------------------------------------------------------"
puts "Welcome! The goal of the git game is to guess committers"
puts "based on their commit messages.\n\n"
puts <<~TXT
----------------------------------------------------------
THE GIT GAME
----------------------------------------------------------
Welcome! The goal of the git game is to guess committers
based on their commit messages.

TXT
end

def print_help
puts "----------------------------------------------------------"
puts " USAGE "
puts "----------------------------------------------------------"
puts "git game [extra git log options]"
puts "EX: git game --after={2014-08-08}"
puts "(This script already uses --no-merges and --pretty."
puts "For more valid options see: http://gitref.org/inspect/)"
puts <<~TXT
----------------------------------------------------------
USAGE
----------------------------------------------------------
git game [options]

Flags:
-h Show this help message
--hard Opt into a challenge (git game classic)

Extra options can be passed directly to git log:

EX: git game --after={2014-08-08}
(This script already uses --no-merges and --pretty.
For more valid options see: https://git-scm.com/docs/git-log)
TXT
end

def print_commit_preview(sha, difficulty)
details_args = {
normal: "--pretty='(%ar)%n%B' --shortstat",
hard: "--pretty='(%ar)%n%B' --no-patch"
}[difficulty]

puts `git show #{sha} #{details_args}`
puts "\n\n"
end

# -- Usage Text --
if ARGV.count > 0 && (input = ARGV.shift) == 'help'
# -- Command line options --
used_args = []
if ARGV.include?('help') ||
ARGV.include?('--help') ||
ARGV.include?('-h')
print_header
print_help
exit 0
elsif ARGV.include?('--hard')
used_args << '--hard'
difficulty = :hard
end

# -- Parse commits --
COMMIT_DELIMITER = "XXXCOMMITXXX"
FIELD_DELIMITER = "|||"

commit_format = ["%an", "%ar", "%B"].join(FIELD_DELIMITER)

raw_commits = `git log --no-merges --pretty="#{COMMIT_DELIMITER}#{commit_format}" #{input if input}`.split("#{COMMIT_DELIMITER}")
commits = []
raw_commits.each do |c|
next if c.strip.empty?

fields = c.split(FIELD_DELIMITER)
commits << {:author => fields[0], :date => fields[1], :message => fields[2]}
end

committers = commits.map { |c| c[:author] }.compact.uniq
input = ARGV.reject { |arg| used_args.include?(arg) }.join(' ')
ARGV.clear

# -- Fetch Repository Info --
commit_shas = `git log --no-merges --pretty=%H -z #{input}`
.split("\0")
.shuffle
exit $CHILD_STATUS.exitstatus unless $CHILD_STATUS.success?
committers = `git log --no-merges --pretty=%aN | sort -u`
.split("\n")
.map(&:strip)

# -- Show welcome message --
system('clear')

print_header
puts "You're playing in a repo with #{commits.size} commits and #{committers.size}"
puts "You're playing in a repo with #{commit_shas.size} commits and #{committers.size}"
puts "distinct committers.\n\n"

committers.each do |committer|
puts committer
end

puts "Ready? PRESS ENTER TO START PLAYING (Ctrl-C to quit)"

puts 'Ready? PRESS ENTER TO START PLAYING (Ctrl-C to quit)'
gets

system('clear')

# -- Game loop --
NUM_CHOICE = 4

loop do
commit = commits.shuffle.pop
message = commit[:message]
author = commit[:author]

next if message.nil? || message.empty? || author.nil? || author.empty?
commit_shas.each do |sha|
print_commit_preview(sha, difficulty)

puts "(#{commit[:date]})\n"
puts "#{message.strip}\n\n"
puts

choices = committers.sample(NUM_CHOICE)
if !choices.include?(author)
choices.pop
choices.push author
end
author = `git show #{sha} --pretty=%aN --no-patch`.strip
choices = [author]
choices += committers.reject do |name|
name == author
end.sample(NUM_CHOICE - 1)
choices.shuffle!

choices.each_with_index do |name, index|
puts "[#{index + 1}] #{name}"
end

print "Who wrote it (current streak: #{streak})? "

guess = gets.strip

while guess.empty? || !guess.to_i.between?(1, NUM_CHOICE)
guess = nil
until guess.to_i.between?(1, NUM_CHOICE)
print "Who wrote it (current streak: #{streak})? "
guess = gets.strip
end

if choices[guess.to_i - 1] == author
streak += 1
puts "Got it!"
puts 'Got it!'
else
streak = 0
puts "Actually, it was #{author}."
end

longest_streak = [longest_streak, streak].max

sleep 1
puts "\nEnter to go to next question"
gets
system('clear')
end

puts <<~TXT
Congratulations! There are no more commits in this repo!

Longest streak: #{longest_streak}
TXT
exit 0