class RankingSimpledb

Attributes

domain[R]

Public Class Methods

new(access_key,secret_access_key,ranking_name, simple_db_endpoint = "sdb.ap-northeast-1.amazonaws.com",max_retries = 2) click to toggle source

create domain domain(tableみたいなもの)を作成

# File lib/ranking-simpledb.rb, line 38
def initialize(access_key,secret_access_key,ranking_name,
               simple_db_endpoint = "sdb.ap-northeast-1.amazonaws.com",max_retries = 2)
  unless @@db
    AWS.config({ :access_key_id => access_key, :secret_access_key => secret_access_key,
               :simple_db_endpoint => simple_db_endpoint,:max_retries => max_retries})
    @@db = AWS::SimpleDB.new()
  end
  @domain = @@db.domains.create(ranking_name)
end
score_str(score) click to toggle source

change integer score to string score スコアの文字列化(文字列比較の場合に整数順になるようゼロパディング)

# File lib/ranking-simpledb.rb, line 9
def self.score_str(score)
  if score.is_a? Integer
    sprintf("%012d",score)
  else
    score
  end
end
to_id_score(score,u_id) click to toggle source

score + user_id for sort スコア+ユーザIDの文字列化(同じスコアの場合はユーザIDが大きい順に並べるため)

# File lib/ranking-simpledb.rb, line 21
def self.to_id_score(score,u_id)
  sprintf("%s%012d",score_str(score),u_id)
end
to_rec(u_id,score) click to toggle source

formatize for items itemsにセットするレコード形式を作成

# File lib/ranking-simpledb.rb, line 29
def self.to_rec(u_id,score)
  str_score = score_str(score)
  {"score" => score_str(score),"id_score" => to_id_score(score,u_id)}
end

Public Instance Methods

delete(u_id) click to toggle source

delete ranking data specified by u_id 指定したレコードの削除

# File lib/ranking-simpledb.rb, line 60
def delete(u_id)
  @domain.items[u_id.to_s].delete
end
my_list(list_num,u_id) click to toggle source

return list_num recored near u_id’s score. include u_id score. list_num数分、指定したユーザとそれ以下のユーザのランキングを取得。

# File lib/ranking-simpledb.rb, line 148
def my_list(list_num,u_id)
  score = score_of_u_id(u_id)
  next_list(list_num,self.class.to_id_score(score,u_id),true)
end
next_list(list_num,id_score,inc=false) click to toggle source

return list_num record above id_score. if inc is true, include specified id_score_record. use for paginate. list_num数分、指定したスコア+ユーザIDよりも下にいるランキングを取得。incがtrueの場合は、指定したid_scoreのレコードも含める

# File lib/ranking-simpledb.rb, line 135
def next_list(list_num,id_score,inc=false)
  if inc
    clause = "id_score <= \"#{id_score}\""
  else
    clause = "id_score < \"#{id_score}\""
  end
  to_list(@domain.items.where(clause).order(:id_score,:desc).limit(list_num))
end
prev_list(list_num,id_score,inc=false) click to toggle source

return list_num record above id_score. if inc is true, include specified id_score_record. use for paginate. list_num数分、指定したスコア+ユーザIDよりも上にいるランキングを取得。incがtrueの場合は、指定したid_scoreのレコードも含める

# File lib/ranking-simpledb.rb, line 117
def prev_list(list_num,id_score,inc=false)
  if inc
    clause = "id_score >= \"#{id_score}\""
  else
    clause = "id_score > \"#{id_score}\""
  end
  items = @domain.items.where(clause).order(:id_score,:asc).limit(list_num).to_a
  if items.count < list_num
    return top_list(list_num)
  end
  to_list(items.reverse)
end
rank_by_score(score) click to toggle source

rank by score 指定したスコアの順位

# File lib/ranking-simpledb.rb, line 83
def rank_by_score(score)
  return @domain.items.count + 1 unless score
  @domain.items.where("score > \"#{self.class.score_str(score)}\"").count + 1
end
rank_of_u_id(u_id) click to toggle source

rank of u_id 指定したユーザIDの順位

# File lib/ranking-simpledb.rb, line 67
def rank_of_u_id(u_id)
  score = score_of_u_id(u_id)
  rank_by_score(score)
end
score_of_u_id(u_id) click to toggle source

score of u_id 指定したユーザIDのスコア

# File lib/ranking-simpledb.rb, line 75
def score_of_u_id(u_id)
  @domain.items[u_id.to_s].attributes["score"].values[0]
end
to_list(list) click to toggle source

change format of item_record [{“u_id”=>user id,“rank”=>rank,score“=>score,”id_score“=>score+u_id(zero padding)}, …] SimpleDBに登録したレコードを{”u_id“=>ユーザID,”rank“=>順位,”score“=>スコア,”id_score“=>スコア+ユーザID} のフォーマットの配列に変換。

# File lib/ranking-simpledb.rb, line 158
def to_list(list)
  records = []
  list.each{|elm|
    attrs = {}
    elm.attributes.each_value{|k,v| attrs[k] = v}
    attrs["u_id"] = elm.name.to_i
    records.push(attrs)
  }
  return [] if records.count == 0
  prev_score = records[0]["score"].to_i
  rank = rank_by_score(prev_score)
  count = user_num_of_score(prev_score)
  first_flg = true
  records.each do|entry|
    score = entry["score"].to_i
    id_score = entry["id_score"]
    if score != prev_score
      rank = count + rank
      count = 1
      prev_score = score
      first_flg = false
    else
      unless first_flg
        count += 1
      end
    end
    entry["score"] = score
    entry["rank"] = rank
  end
  records
end
top() click to toggle source

return ranking top recored 一番高いスコアのランキング情報

# File lib/ranking-simpledb.rb, line 100
def top
  to_list(@domain.items.where("id_score is not null").order(:id_score,:desc).limit(1))[0]
end
top_list(list_num) click to toggle source

top (list_num) list. スコアが高い順にlist_num数分表示

# File lib/ranking-simpledb.rb, line 108
def top_list(list_num)
  to_list(@domain.items.where("id_score is not null").order(:id_score,:desc).limit(list_num))
end
upsert(u_id,score) click to toggle source

update ranking data. if u_id does not exist, create new data. if u_id exists in ranking, override new score 同じ主キーがあった場合は、自動的に書き換えられる

# File lib/ranking-simpledb.rb, line 52
def upsert(u_id,score)
  @domain.items.create(u_id.to_s,self.class.to_rec(u_id,score))
end
user_num_of_score(score) click to toggle source

number of user in the score. same score user. 指定したスコアにいる人数(同位タイ)

# File lib/ranking-simpledb.rb, line 92
def user_num_of_score(score)
  @domain.items.where(:score => self.class.score_str(score)).count
end