Social Game Kit
Ruby on Railsアプリケーション向けのソーシャルゲーム機能を提供するgemです。 重み付き確率に基づくガチャ機能を実装しており、メモリ効率を考慮した設計になっています。
機能
- 重み付きガチャ機能
- 確率計算機能
- 単発・複数回ガチャ対応(10連ガチャ等)
インストール
Gemfileに以下を追加:
gem 'social-game-kit'その後、以下を実行:
bundle install要件
- Ruby 3.1.0以上
- Rails 6.0以上
- ActiveRecord
- ActiveSupport
使用方法
基本的な使用方法
require 'ssg'
# カードマスタデータ(ActiveRecordモデル)から抽選
cards = GachaCard.all
# エンジンの初期化
engine = SSG::Gacha::Engine.new(cards)
# 単発抽選
card = engine.draw
puts card.name # => "コモン" など
puts card.rarity # => "common"
# 複数回抽選(10連ガチャ)
results = engine.draw_multiple(10)
puts results.size # => 10
# 確率の計算
probabilities = engine.probabilities
# => {1=>70.0, 2=>25.0, 3=>4.0, 4=>1.0}Railsアプリケーションでの例
# app/models/gacha_card.rb
class GachaCard < ApplicationRecord
validates :name, :rarity, :weight, presence: true
validates :weight, numericality: { greater_than: 0 }
enum rarity: {
common: 0,
rare: 1,
super_rare: 2,
ultra_rare: 3
}
end
# app/controllers/gacha_controller.rb
class GachaController < ApplicationController
def draw
engine = SSG::Gacha::Engine.new(GachaCard.all)
@result = engine.draw
# ユーザーにカードを付与する処理など
current_user.gacha_cards << @result
render json: @result.json_format
end
def draw_multiple
count = params[:count].to_i.clamp(1, 10) # 最大10連
engine = SSG::Gacha::Engine.new(GachaCard.all)
@results = engine.draw_multiple(count)
current_user.gacha_cards.push(*@results)
render json: {
cards: @results.map(&:json_format)
}
end
def probabilities
engine = SSG::Gacha::Engine.new(GachaCard.all)
render json: engine.probabilities
end
endガチャカードモデルの例
# db/migrate/20240101000000_create_gacha_cards.rb
class CreateGachaCards < ActiveRecord::Migration[7.0]
def change
create_table :gacha_cards do |t|
t.string :name, null: false
t.string :rarity, null: false
t.integer :weight, null: false, default: 1
t.text :description
t.string :image_url
t.timestamps
end
add_index :gacha_cards, :rarity
add_index :gacha_cards, :weight
end
end
# db/seeds.rb
GachaCard.create!([
{ name: "コモンカード", rarity: :common, weight: 70 },
{ name: "レアカード", rarity: :rare, weight: 25 },
{ name: "スーパーレアカード", rarity: :super_rare, weight: 4 },
{ name: "ウルトラレアカード", rarity: :ultra_rare, weight: 1 }
])重み付き抽選アルゴリズム
このgemは累積重み方式を使用して、効率的にカードを抽選します。
アルゴリズムの説明
- 全カードの重みを合計(total_weight)
- 0〜total_weightの範囲でランダム値を生成
- 累積重みを計算しながら、ランダム値が該当する範囲のカードを選択
例
カードA: 重み70 (累積: 0-69)
カードB: 重み25 (累積: 70-94)
カードC: 重み4 (累積: 95-98)
カードD: 重み1 (累積: 99)
合計: 100
ランダム値75 → カードBを選択
APIリファレンス
SSG::Gacha::Engine
initialize(card_relation)
ActiveRecord::Relationを受け取ります。
engine = SSG::Gacha::Engine.new(GachaCard.all)draw
単発ガチャを実行し、カードを返します。
card = engine.drawdraw_multiple(count)
複数回ガチャを実行します。countは正の整数である必要があります。
cards = engine.draw_multiple(10) # 10連ガチャprobabilities
各カードの確率(パーセント)をハッシュで返します。
probs = engine.probabilities
# => {1=>70.0, 2=>25.0, 3=>4.0, 4=>1.0}SSG::Gacha::Result
ガチャ結果をラップするクラスです。
card
抽選されたカードオブジェクトを返します(読み取り専用)。
name
カード名を返します。
rarity
カードのレア度を返します。
json_format
カード情報をハッシュで返します(JSON化用)。
result = engine.draw
result.json_format
# => { card_id: 1, name: "コモン", rarity: "common" }メモリ効率について
このgemのprobabilitiesメソッドはハッシュを使用しており、実際に存在するカードのIDだけを保存します。
IDが飛び飛びの場合(例: 1-100と1000-10000)でも、間のIDのエントリは作成されません。
⚠️ 配列を使った場合の問題
# ❌ 配列を使った実装(メモリを大量に消費)
arr = []
arr[1000] = "value"
# インデックス0-999もメモリに確保されるこのgemはハッシュを使用することでこの問題を回避しています。
開発
リポジトリをクローンした後:
bundle installテストを実行:
bundle exec rspecコード品質をチェック:
bundle exec rubocop対話的なプロンプトで実験:
bin/consolegemをローカルにインストール:
bundle exec rake installテスト
このgemは包括的なテストスイートを含みます。
# 全テスト実行
bundle exec rake
# RSpecのみ実行
bundle exec rspec
# RuboCopのみ実行
bundle exec rubocop貢献
バグレポートやプルリクエストはGitHubで歓迎します。
https://github.com/NYUWAMOCHI/social-game-kit
ライセンス
このgemはMIT Licenseの下でオープンソースとして利用可能です。
詳細はLICENSE.txtを参照してください。