+ ##################
+ # Instance methods
+ #
+
+ # an array of player IDs; [gps+123, foo+234, ...]
+ attr_reader :keys
+
+ # matrix holds games # where player i (row index) beats player j (column index).
+ # The row and column indexes match with the keys.
+ attr_reader :matrix
+
+ def initialize(keys, matrix)
+ @keys = keys
+ @matrix = matrix
+ end
+
+ ##
+ # Returns the size of the keys/matrix
+ #
+ def size
+ if @keys
+ @keys.size
+ else
+ nil
+ end
+ end
+
+ ##
+ # Removes a delete_index'th player and returns a new object.
+ #
+ def delete_row(delete_index)
+ copied_cols = []
+ (0...size).each do |i|
+ next if i == delete_index
+ row = @matrix.get_row(i) # get_row returns a copy of the row
+ row.delete_at(delete_index)
+ copied_cols << row
+ end
+ new_matrix = Matrix[*copied_cols]
+ new_keys = @keys.clone
+ new_keys.delete_at(delete_index)
+ return WinLossMatrix.new(new_keys, new_matrix)
+ end
+
+ ##
+ # Removes players in a rows; [1,3,5]
+ #
+ def delete_rows(rows)
+ obj = self
+ rows.sort.reverse.each do |index|
+ obj = obj.delete_row(index)
+ end
+ obj
+ end
+
+ ##
+ # Removes players who do not pass a criteria to be rated, and returns a new object.
+ #
+ def filter
+ $stderr.puts @keys.inspect if $DEBUG
+ $stderr.puts @matrix.inspect if $DEBUG
+ delete = []
+ (0...size).each do |i|
+ row = @matrix.row(i)
+ col = @matrix.col(i)
+ win = row.sum
+ loss = col.sum
+ if win < 1 || loss < 1 || win + loss < $GAMES_LIMIT
+ delete << i