Skip to content

Instantly share code, notes, and snippets.

@hivehand
Last active August 18, 2025 19:31
Show Gist options
  • Select an option

  • Save hivehand/f99022751764f7d1f3f5e66094536ce3 to your computer and use it in GitHub Desktop.

Select an option

Save hivehand/f99022751764f7d1f3f5e66094536ce3 to your computer and use it in GitHub Desktop.
Extract the set of skills that each player has failed at least once in attempting to use.
#!/usr/bin/env ruby
# This script serves to extract the list of each character's failures.
# Using it requires a bit of brute force. You must:
# - View the entire log history as a single page in your browser.
# - Save just the raw text of the page to a file. (On a Mac, do a
# select-all and copy, followed by a `pbpaste` piped into a file.)
# - Open that file in an editor, and clip out _just_ the part
# between the current markers.
# After you've done all of that, you can run this script against the
# file to get a report of every skill each character experienced some
# kind of failure with.
require 'set'
def find_player_failures(filename)
# The set of outcomes that count as failures, for simple membership
# testing.
failures = Set['failure', 'fumble!']
# A Hash whose default key value is an empty set.
player_failures = Hash.new { |h, k| h[k] = Set.new }
File.open(filename) do |file|
while line = file.gets
# A new "action" section always starts with "<Character Name>:",
# and those are the *only* lines that end with colons, so start by
# finding the next one of those.
if line.chomp.end_with?(':')
name = file.gets.chomp
skill = file.gets.chomp
# Customized skills start with capital letters; regular ones
# don't. Filtering out the former spares Eric extra work. Now
# that we've added a valid custom skill, we'll have to
# fine-tune this for future rounds.
unless skill.match(/^[A-Z]/) || player_failures[name].include?(skill)
# Some entries have "regular" between the skill line and the
# outcome line; some don't. These following two lines are the simplest
# way to deal with that.
outcome = "regular"
outcome = file.gets.chomp until outcome != "regular"
player_failures[name].add(skill) if failures.include? outcome
end
end
end
end
player_failures
end
def present_player_failures(player_failures)
player_failures.each do |player, failures|
puts("#{player}:")
failures.to_a.sort.each { |failure| puts(" #{failure.capitalize}")}
puts
end
end
# ---
if ARGV.empty?
puts "Usage: list_failures <filename>"
exit 1
end
filename = ARGV[0]
unless File.exist?(filename)
puts "Error: File '#{filename}' not found"
exit 1
end
player_failures = find_player_failures(filename)
present_player_failures(player_failures)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment