Skip to content

Instantly share code, notes, and snippets.

@mikker
Created February 23, 2022 14:06
Show Gist options
  • Save mikker/87462de6acdc6d06989f9aadcf111b0e to your computer and use it in GitHub Desktop.
Save mikker/87462de6acdc6d06989f9aadcf111b0e to your computer and use it in GitHub Desktop.
Sorting the Invisible Friends
require_relative "sheet.rb"
require 'digest'
CURRENT_BLOCK = 12345
COMMUNITY_REACTIONS = 54321
def main
sheet = Sheet.new('Metadata/InvisibleFriends_Metadata.csv')
sheet.headers.concat(['Seed', 'Filename', 'SHA256'])
puts "Extending metadata"
sheet.each do |row|
padded_id = row["Number"].rjust(5, '0')
gif_path = "GIFs/INVISIBLE_FRIENDS_#{padded_id}.gif"
row["Seed"] = row["Number"]
row["Filename"] = gif_path
row["SHA256"] = shasum(gif_path)
print '.'
end
puts ""
sorted = sheet.dup
sorted.data.sort! { |a, b| a.fetch("SHA256") <=> b.fetch("SHA256") }
sorted.data.shuffle!(random: Random.new(CURRENT_BLOCK))
sorted.data.rotate!(COMMUNITY_REACTIONS)
sorted.each_with_index { |row, i| row['Number'] = i + 1 }
sorted.save("Metadata/enriched_and_sorted.csv")
combined_shasum = sorted.reduce("") { |str, row| str + row["SHA256"] }
provenance = Digest::SHA256.hexdigest(combined_shasum)
File.open('provenance.txt', 'w') { |f| f << provenance }
end
def shasum(path)
`shasum -a 256 "#{path}" | awk '{ print $1 }'`.chomp
end
main
require "csv"
class Sheet
include Enumerable
def initialize(path, **opts)
@path = path
@csv = CSV.read(path, headers: true, **opts)
@data = csv.map(&:to_h)
@headers = csv.first.headers
end
attr_accessor :data
attr_reader :csv, :headers, :dest
def each(&block)
data.each(&block)
end
def generate
each.reduce([headers.join(';')]) do |csv, row|
csv.push(headers.map { |h| row[h] }.join(';'))
end.join("\n")
end
def save(dest)
File.open(dest, 'w') do |f|
f << generate
end
end
end
if $0 == __FILE__
require "rubygems"
require "rspec"
require "fileutils"
RSpec.describe Sheet do
let(:sheet) do
<<-CSV
a,b,c
one,two,three
x,y,z
CSV
end
let(:path) { "test.csv" }
before do
File.open(path, "w") { |w| w << sheet }
end
subject do
Sheet.new(path)
end
it "loads sheet data" do
expect(subject.each.to_a).to(
eq(
[
{
"a" => "one",
"b" => "two",
"c" => "three"
},
{
"a" => "x",
"b" => "y",
"c" => "z"
}
]
)
)
end
it 'loads sheet headers' do
expect(subject.headers).to eq(%w[a b c])
end
it 'can regenerate' do
subject.data[0]['c'] = 'hello!'
expect(subject.generate).to eq(
<<-CSV
a,b,c
one,two,hello!
x,y,z
CSV
.chomp
)
end
it 'can add a header' do
subject.headers.push('more')
expect(subject.generate).to eq(
<<-CSV
a,b,c,more
one,two,three,
x,y,z,
CSV
.chomp
)
end
it "can't save a copy with a path" do
expect do
subject.save
end.to raise_error(ArgumentError)
end
it "can save a copy with a path" do
out_path = 'test-output.csv'
FileUtils.rm_rf(out_path)
subject.save(out_path)
expect(File.read(out_path)).to eq(
<<-CSV
a,b,c
one,two,three
x,y,z
CSV
.chomp
)
end
end
RSpec::Core::Runner.run([__FILE__])
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment