Class: RankingSimpledb

Inherits:
Object
  • Object
show all
Defined in:
lib/ranking-simpledb.rb

Constant Summary collapse

@@db =
nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(access_key, secret_access_key, ranking_name, simple_db_endpoint = "sdb.ap-northeast-1.amazonaws.com", max_retries = 2) ⇒ RankingSimpledb

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



39
40
41
42
43
44
45
46
47
# File 'lib/ranking-simpledb.rb', line 39

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

Instance Attribute Details

#domainObject (readonly)

Returns the value of attribute domain.



4
5
6
# File 'lib/ranking-simpledb.rb', line 4

def domain
  @domain
end

Class Method Details

.score_str(score) ⇒ Object

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



10
11
12
13
14
15
16
# File 'lib/ranking-simpledb.rb', line 10

def self.score_str(score)
  if score.is_a? Integer
    sprintf("%012d",score)
  else
    score
  end
end

.to_id_score(score, u_id) ⇒ Object

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



22
23
24
# File 'lib/ranking-simpledb.rb', line 22

def self.to_id_score(score,u_id)
  sprintf("%s%012d",score_str(score),u_id)
end

.to_rec(u_id, score) ⇒ Object

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



30
31
32
33
# File 'lib/ranking-simpledb.rb', line 30

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

Instance Method Details

#delete(u_id) ⇒ Object

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



61
62
63
# File 'lib/ranking-simpledb.rb', line 61

def delete(u_id)
  @domain.items[u_id.to_s].delete
end

#my_list(list_num, u_id) ⇒ Object

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



149
150
151
152
# File 'lib/ranking-simpledb.rb', line 149

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) ⇒ Object

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のレコードも含める



136
137
138
139
140
141
142
143
# File 'lib/ranking-simpledb.rb', line 136

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) ⇒ Object

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のレコードも含める



118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/ranking-simpledb.rb', line 118

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) ⇒ Object

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



84
85
86
87
# File 'lib/ranking-simpledb.rb', line 84

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) ⇒ Object

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



68
69
70
71
# File 'lib/ranking-simpledb.rb', line 68

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) ⇒ Object

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



76
77
78
# File 'lib/ranking-simpledb.rb', line 76

def score_of_u_id(u_id)
  @domain.items[u_id.to_s].attributes["score"].values[0]
end

#to_list(list) ⇒ Object

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



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/ranking-simpledb.rb', line 159

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

#topObject

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



101
102
103
# File 'lib/ranking-simpledb.rb', line 101

def top
  to_list(@domain.items.where("id_score is not null").order(:id_score,:desc).limit(1))[0]
end

#top_list(list_num) ⇒ Object

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



109
110
111
# File 'lib/ranking-simpledb.rb', line 109

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) ⇒ Object

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



53
54
55
# File 'lib/ranking-simpledb.rb', line 53

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) ⇒ Object

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



93
94
95
# File 'lib/ranking-simpledb.rb', line 93

def user_num_of_score(score)
  @domain.items.where(:score => self.class.score_str(score)).count
end