PageRenderTime 29ms CodeModel.GetById 19ms app.highlight 9ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/chingu/high_score_list.rb

http://github.com/ippa/chingu
Ruby | 143 lines | 69 code | 15 blank | 59 comment | 8 complexity | c35df47bda2f516f8c5104fe486d8ac4 MD5 | raw file
Possible License(s): LGPL-2.1
  1#--
  2#
  3# Chingu -- OpenGL accelerated 2D game framework for Ruby
  4# Copyright (C) 2009 ippa / ippa@rubylicio.us
  5#
  6# This library is free software; you can redistribute it and/or
  7# modify it under the terms of the GNU Lesser General Public
  8# License as published by the Free Software Foundation; either
  9# version 2.1 of the License, or (at your option) any later version.
 10#
 11# This library is distributed in the hope that it will be useful,
 12# but WITHOUT ANY WARRANTY; without even the implied warranty of
 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 14# Lesser General Public License for more details.
 15#
 16# You should have received a copy of the GNU Lesser General Public
 17# License along with this library; if not, write to the Free Software
 18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 19#
 20#++
 21
 22module Chingu
 23  #
 24  # Highscore-class
 25  #
 26  # - Keeps a local YAML file with highscores, default highscores.yml in root game dir.
 27  # - Add, delete, clear highscores
 28  # - Iterate through highscores with simple HighScores#each
 29  #
 30  class HighScoreList
 31    attr_reader :file, :high_scores
 32    
 33    #
 34    # Create a new high score list with 0 entries
 35    #
 36    def initialize(options = {})
 37      @file = options[:file] || "high_score_list.yml"
 38      @size = options[:size] || 100
 39      @sort_on = options[:sort_on] || :score
 40      @high_scores = Array.new      
 41    end
 42    
 43    #
 44    # Create a new high score list and try to load content from :file-parameter
 45    # If no :file is given, HighScoreList tries to load from file "high_score_list.yml"
 46    #
 47    def self.load(options = {})
 48      require 'yaml'
 49      high_score_list = HighScoreList.new(options)
 50      high_score_list.load
 51      return high_score_list
 52    end
 53    
 54    #
 55    # Adda a new high score to the local file
 56    # 'data' is a hash of key/value-pairs that needs to contain at least the keys :name and :score
 57    # Returns the position it got in the list, with 1 beeing the first positions
 58    #
 59    def add(data)
 60      raise "No :name value in high score!"   if data[:name].nil?
 61      raise "No :score value in high score!"  if data[:score].nil?
 62      add_to_list(force_symbol_hash(data))
 63      save_to_file
 64      position_by_score(data[:score])
 65    end
 66    alias << add
 67    
 68    #
 69    # Returns the position of full data-hash data entry, used internally
 70    #
 71    def position_by_data(data)
 72      position = @high_scores.rindex(data)
 73      position += 1 if position
 74    end
 75          
 76    #
 77    # Returns the position 'score' would get in among the high scores:
 78    #   @high_score_list.position_by_score(999999999) # most likely returns 1 for the number one spot
 79    #   @high_score_list.position_by_score(1)         # most likely returns nil since no placement is found (didn't make it to the high scores)
 80    #
 81    def position_by_score(score)
 82      position = 1
 83      @high_scores.each do |high_score|
 84        return position   if score >= high_score[:score]
 85        position += 1
 86      end
 87      return nil
 88    end
 89    
 90    #
 91    # Load data from previously specified @file
 92    #
 93    def load
 94      @high_scores = YAML.load_file(@file)  if File.exists?(@file)
 95      @high_scores = @high_scores[0..@size]
 96    end
 97
 98    #
 99    # Direct access to invidual high scores
100    #
101    def [](index)
102      @high_scores[index]
103    end
104    
105    #
106    # Iterate through all high scores
107    #
108    def each
109      @high_scores.each { |high_score| yield high_score }
110    end
111    
112    def each_with_index
113      @high_scores.each_with_index { |high_score, index| yield high_score, index }
114    end
115
116    #
117    # Save high score data into previously specified @file
118    #
119    def save_to_file
120      require 'yaml'
121      File.open(@file, 'w') do |out|
122        YAML.dump(@high_scores, out)
123      end
124    end
125
126    private
127    
128    def add_to_list(data)
129      @high_scores.push(data)
130      @high_scores.sort! { |a, b| b[@sort_on] <=> a[@sort_on] }
131      @high_scores = @high_scores[0..@size]
132    end
133    
134    def force_symbol_hash(hash)
135      symbol_hash = {}
136      hash.each_pair do |key, value|
137        symbol_hash[key.to_sym] = value
138      end
139      return symbol_hash
140    end
141        
142  end
143end