Jay McGavren's Journal

2010-04-16

Name the Top X of All Time - go!

A friend asked for a quick script to help him sort a top-50 list of games. Here’s what I threw together:

#!/usr/bin/env ruby

# rank.rb - Rank a list of items, two at a time.

# Copyright (c) 2010 Jay McGavren
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


require 'fileutils'
require 'curses'

file_name = ARGV[0] or fail "Usage: #{__FILE__} filename.txt"

def random_index(list)
  rand(list.length)
end

def write_store(name, entries)
  File.open(name, 'w+') do |file|
    file.puts(entries)
  end
end

def read_store(name)
  entries = []
  File.open(name) do |file|
    entries = file.readlines
  end
  entries
end

entries = read_store(file_name)

Curses.noecho
Curses.init_screen
Curses.stdscr.keypad(true)

loop do
  # Pick 2 random items.
  indices = [0, 0]
  while (indices[0] == indices[1]) do
    indices = [random_index(entries), random_index(entries)]
  end
  indices.sort!
  # Present them.
  Curses.setpos(0, 0)
  Curses.addstr(<<-EOD)
    Which is better?
    1. #{entries[indices[0]]}
    2. #{entries[indices[1]]}
    3. Exit
  EOD
  begin
    result = nil
    until ([?1, ?2, ?3].include?(result)) do
      result = Curses.getch
    end
    case result
    # Higher one chosen?
    when ?1
      # Do nothing.
    # Otherwise:
    when ?2
      # Swap them.
      entries[indices[0]], entries[indices[1]] = entries[indices[1]], entries[indices[0]]
    # Exit chosen?
    when ?3
      # Exit loop.
      break
    else
      fail "wtf?"
    end
  end
  write_store("#{file_name}.bak", entries)
end

# Save.
FileUtils.mv("#{file_name}.bak", file_name)

Curses.close_screen

It picks two entries at random, and swaps their positions if you choose the later one as your favorite. Lather, rinse, repeat. Like a bubble sort without adjacent items.

Curses? Well, it was the quickest way to get Ruby to respond to a single keypress. And since you’re going to be making a lot of entries, I didn’t want you to have to hit Enter after every one.

So here you see my list of artists with 5-star songs, originally in alphabetical order, but with my favorites starting to bubble to the top:

  • 10,000 Maniacs
  • Enigma
  • Boom Boom Satellites
  • Alpha
  • Amon Tobin
  • Aphex Twin
  • Barenaked Ladies
  • Arovane
  • Audioslave
  • Boards of Canada
  • Massive Attack
  • Red Snapper
  • Tipper
  • Beach Flea
  • Cake
  • Ben Folds Five
  • Counting Crows
  • Propellerheads
  • Billy Joel
  • The Smashing Pumpkins
  • Lemon Jelly
  • Fatboy Slim
  • Boards Of Canada
  • Shpongle
  • Bola
  • Coldplay
  • Weekend Players
  • Boulderdash
  • Buckethead
  • Crunch
  • Ulrich Schnauss
  • Basement Jaxx
  • µ-Ziq
  • Dol-lop
  • Chicane
  • Depeche Mode
  • Clint Mansell
  • Train
  • Boom Bip
  • Bent
  • Creed
  • Beck
  • Cujo
  • DJ Cam
  • Röyksopp
  • Daft Punk
  • Red Hot Chili Peppers
  • Death Cab for Cutie
  • Plaid
  • Deftones
  • Delarosa & Asora
  • Christian Kleine
  • Caviar
  • Third Eye Blind
  • Duncan Sheik
  • E.S. Posthumus
  • Eat Static
  • The Crystal Method
  • 3 Doors Down
  • Blind Melon
  • Fluke
  • Hive
  • BT
  • Loden
  • Goldie
  • Groove Armada
  • Hexstatic
  • R.E.M.
  • Hybrid
  • Bush
  • Sugar Ray
  • Jay McGavren
  • Single Cell Orchestra
  • Kenji Kawai
  • LFO
  • Saru
  • Sarah McLachlan
  • Arkarna
  • Prefuse 73
  • James Bong
  • Lusine ICL
  • Banco de Gaia
  • Mighty Dub Cats
  • Mike & Rich
  • The Cranberries
  • Natalie Merchant
  • Orbital
  • P.M. Dawn
  • Clue to Kalo
  • Pearl Jam
  • Photek
  • Deep Forest
  • Polygon Window
  • Portishead
  • Loess
  • Prince
  • Proem
  • Billie Myers
  • Freaky Chakra
  • Dave Matthews Band
  • Global Communication
  • Roni Size & Reprazent
  • DJ Krush
  • Moby
  • Blessid Union of Souls
  • Londonbeat
  • Savath & Savalas
  • Seal
  • The Chemical Brothers
  • Shantel
  • Genesis
  • Jimpster
  • Elton John
  • The Wiseguys
  • Living Colour
  • Stone Temple Pilots
  • Janet Jackson
  • Talvin Singh
  • Blackwatch & Greed
  • Squarepusher
  • Soundgarden
  • The Dust Brothers
  • The Postal Service
  • The Prodigy
  • Seb & Lo-tec
  • Spring Heel Jack
  • Dot Allison
  • Isao Tomita
  • Patchwork
  • Bôa
  • A Man Called Adam
  • wunsch/demmin
  • Chicago

Been meaning to write something like this for a while, and my friend’s request was just the final nudge. Hopefully this will help others looking for something similar.

comments powered by Disqus