-
-
Save gshutler/3028862 to your computer and use it in GitHub Desktop.
File-based score data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'digest' | |
require 'json' | |
require 'fileutils' | |
$leaderboard_count = 5 | |
$user_count = 200000 | |
def username(i) | |
Digest::SHA1.hexdigest(i.to_s) | |
end | |
def create_file(*parts) | |
file = File.join(parts) | |
FileUtils.mkdir_p File.dirname(file) | |
FileUtils.touch file | |
end | |
(1..$leaderboard_count).map do |lb| | |
Thread.new do | |
(1..$user_count).map do |i| | |
name = username(i) | |
data = {:points => i * lb} | |
# Support scores up to 999,999,999,999,999,999,999,999. | |
score_str = data[:points].to_s.rjust(24, '0') | |
# Support users submitting one score per second. | |
time_str = Time.now.utc.strftime('%Y%m%d%H%M%S') | |
# Create user records in the style: | |
# | |
# temp/users/xxxx/xxxx/xxxx/xxxx/xxxx/xxxx/xxxx/xxxx/xxxx/xxxx/GAME/SCORE-TIME | |
# | |
# This allows us to easily get an individual's best scores without having | |
# too many users in any one directory. | |
create_file 'temp', 'users', name.scan(/.{4}/), lb.to_s, "#{score_str}-#{time_str}" | |
# Create leaderboard records in the style: | |
# | |
# temp/leaderboard/GAME/xxx/xxx/xxx/xxx/xxx/xxx/xxx/xxx/TIME-USER | |
# | |
# This allows us to easily get the highest scores for a given game and | |
# filter them easily by time. | |
create_file 'temp', 'leaderboard', lb.to_s, score_str.scan(/.{3}/), "#{time_str}-#{name}" | |
end | |
end | |
end.each(&:join) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'benchmark' | |
require 'fileutils' | |
require 'json' | |
# Users 40 characters | |
# Scores 24 characters | |
MONTH_AGO = (Time.now.utc - (60*60*24*28)).strftime('%Y%m%d%H%M%S') | |
WEEK_AGO = (Time.now.utc - (60*60*24*7)).strftime('%Y%m%d%H%M%S') | |
SCOREBOARD_SIZE = 10 | |
PRINT = false | |
def get_leaderboards(root) | |
cache_file = File.join 'cache', root | |
if File.exist?(cache_file) and File.mtime(root) < File.mtime(cache_file) | |
puts "Using cache file #{cache_file}" if PRINT | |
return JSON.parse IO.read(cache_file) | |
end | |
leaderboards = determine_leaderboards root | |
puts "Writing cache file #{cache_file}" if PRINT | |
FileUtils.mkdir_p File.dirname(cache_file) | |
File.write(cache_file, leaderboards.to_json) | |
leaderboards | |
end | |
def determine_leaderboards(root) | |
all_time = [] | |
past_month = [] | |
past_week = [] | |
# Do a depth-first traversal of the directory structure, diving into the | |
# highest named directory first as that will contain the highest possible | |
# scores. | |
Dir["#{root}/*"].sort.reverse.each do |dir| | |
Dir["#{dir}/*"].sort.reverse.each do |dir| | |
Dir["#{dir}/*"].sort.reverse.each do |dir| | |
Dir["#{dir}/*"].sort.reverse.each do |dir| | |
Dir["#{dir}/*"].sort.reverse.each do |dir| | |
Dir["#{dir}/*"].sort.reverse.each do |dir| | |
Dir["#{dir}/*"].sort.reverse.each do |dir| | |
Dir["#{dir}/*"].sort.reverse.each do |file| | |
# Inspect each file and add it to the appropriate leaderboard | |
# lists. | |
all_time << file if all_time.length < SCOREBOARD_SIZE | |
past_month << file if past_month.length < SCOREBOARD_SIZE and file > MONTH_AGO | |
past_week << file if past_week.length < SCOREBOARD_SIZE and file > WEEK_AGO | |
# If all the leaderboards are filled return early. | |
return all_time, past_month, past_week if past_week.length == SCOREBOARD_SIZE | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
# Return whatever scores we have managed to collect. | |
return all_time, past_month, past_week | |
end | |
Benchmark.bmbm do |bm| | |
bm.report 'leaderboards' do | |
(1..5).each do |lb| | |
puts "Getting leaderboards for #{lb}" if PRINT | |
lb_dir = File.join('temp', 'leaderboard', lb.to_s) | |
all_time, past_month, past_week = get_leaderboards lb_dir | |
next unless PRINT | |
puts 'All Time' | |
puts '--------' | |
all_time.each { |s| puts s } | |
puts '' | |
puts 'Past month' | |
puts '----------' | |
past_month.each { |s| puts s } | |
puts '' | |
puts 'Past week' | |
puts '---------' | |
past_week.each { |s| puts s } | |
puts '' | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment