Merge branch 'main' into jedmund/skill-data-modeling

# Conflicts:
#	db/schema.rb
This commit is contained in:
Justin Edmund 2025-03-06 19:18:48 -08:00
commit 7879cccf23
5 changed files with 830 additions and 469 deletions

View file

@ -27,6 +27,8 @@ module Api
6 => 5 6 => 5
}.freeze }.freeze
before_action :ensure_admin_role, only: %i[weapons summons characters]
## ##
# Processes an import request. # Processes an import request.
# #
@ -49,9 +51,9 @@ module Api
end end
unless raw_params['deck'].is_a?(Hash) && unless raw_params['deck'].is_a?(Hash) &&
raw_params['deck'].key?('pc') && raw_params['deck'].key?('pc') &&
raw_params['deck'].key?('npc') raw_params['deck'].key?('npc')
Rails.logger.error "[IMPORT] Deck data incomplete or missing." Rails.logger.error '[IMPORT] Deck data incomplete or missing.'
return render json: { error: 'Invalid deck data' }, status: :unprocessable_content return render json: { error: 'Invalid deck data' }, status: :unprocessable_content
end end
@ -68,8 +70,111 @@ module Api
render json: { error: e.message }, status: :unprocessable_content render json: { error: e.message }, status: :unprocessable_content
end end
def weapons
Rails.logger.info '[IMPORT] Checking weapon gamedata input...'
body = parse_request_body
return unless body
weapon = Weapon.find_by(granblue_id: body['id'])
unless weapon
Rails.logger.error "[IMPORT] Weapon not found with ID: #{body['id']}"
return render json: { error: 'Weapon not found' }, status: :not_found
end
lang = params[:lang]
unless %w[en jp].include?(lang)
Rails.logger.error "[IMPORT] Invalid language: #{lang}"
return render json: { error: 'Invalid language' }, status: :unprocessable_content
end
begin
weapon.update!(
"game_raw_#{lang}" => body.to_json
)
render json: { message: 'Weapon gamedata updated successfully' }, status: :ok
rescue StandardError => e
Rails.logger.error "[IMPORT] Failed to update weapon gamedata: #{e.message}"
render json: { error: e.message }, status: :unprocessable_content
end
end
def summons
Rails.logger.info '[IMPORT] Checking summon gamedata input...'
body = parse_request_body
return unless body
summon = Summon.find_by(granblue_id: body['id'])
unless summon
Rails.logger.error "[IMPORT] Summon not found with ID: #{body['id']}"
return render json: { error: 'Summon not found' }, status: :not_found
end
lang = params[:lang]
unless %w[en jp].include?(lang)
Rails.logger.error "[IMPORT] Invalid language: #{lang}"
return render json: { error: 'Invalid language' }, status: :unprocessable_content
end
begin
summon.update!(
"game_raw_#{lang}" => body.to_json
)
render json: { message: 'Summon gamedata updated successfully' }, status: :ok
rescue StandardError => e
Rails.logger.error "[IMPORT] Failed to update summon gamedata: #{e.message}"
render json: { error: e.message }, status: :unprocessable_content
end
end
##
# Updates character gamedata from JSON blob.
#
# @return [void] Renders JSON response with success or error message.
def characters
Rails.logger.info '[IMPORT] Checking character gamedata input...'
body = parse_request_body
return unless body
character = Character.find_by(granblue_id: body['id'])
unless character
Rails.logger.error "[IMPORT] Character not found with ID: #{body['id']}"
return render json: { error: 'Character not found' }, status: :not_found
end
lang = params[:lang]
unless %w[en jp].include?(lang)
Rails.logger.error "[IMPORT] Invalid language: #{lang}"
return render json: { error: 'Invalid language' }, status: :unprocessable_content
end
begin
character.update!(
"game_raw_#{lang}" => body.to_json
)
render json: { message: 'Character gamedata updated successfully' }, status: :ok
rescue StandardError => e
Rails.logger.error "[IMPORT] Failed to update character gamedata: #{e.message}"
render json: { error: e.message }, status: :unprocessable_content
end
end
private private
##
# Ensures the current user has admin role (role 9).
# Renders an error if the user is not an admin.
#
# @return [void]
def ensure_admin_role
return if current_user&.role == 9
Rails.logger.error "[IMPORT] Unauthorized access attempt by user #{current_user&.id}"
render json: { error: 'Unauthorized' }, status: :unauthorized
end
## ##
# Reads and parses the raw JSON request body. # Reads and parses the raw JSON request body.
# #

251
app/services/dataminer.rb Normal file
View file

@ -0,0 +1,251 @@
# frozen_string_literal: true
class Dataminer
include HTTParty
BOT_UID = '39094985'
GAME_VERSION = '1741068713'
base_uri 'https://game.granbluefantasy.jp'
format :json
HEADERS = {
'Accept' => 'application/json, text/javascript, */*; q=0.01',
'Accept-Language' => 'en-US,en;q=0.9',
'Accept-Encoding' => 'gzip, deflate, br, zstd',
'Content-Type' => 'application/json',
'DNT' => '1',
'Origin' => 'https://game.granbluefantasy.jp',
'Referer' => 'https://game.granbluefantasy.jp/',
'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',
'X-Requested-With' => 'XMLHttpRequest'
}.freeze
attr_reader :page, :cookies, :logger, :debug
def initialize(page:, access_token:, wing:, midship:, t: 'dummy', debug: false)
@page = page
@cookies = {
access_gbtk: access_token,
wing: wing,
t: t,
midship: midship
}
@debug = debug
setup_logger
end
def fetch
timestamp = Time.now.to_i * 1000
response = self.class.post(
"/#{page}?_=#{timestamp}&t=#{timestamp}&uid=#{BOT_UID}",
headers: HEADERS.merge(
'Cookie' => format_cookies,
'X-VERSION' => GAME_VERSION
)
)
raise AuthenticationError if auth_failed?(response)
response
end
def fetch_character(granblue_id)
timestamp = Time.now.to_i * 1000
url = "/archive/npc_detail?_=#{timestamp}&t=#{timestamp}&uid=#{BOT_UID}"
body = {
special_token: nil,
user_id: BOT_UID,
kind_name: '0',
attribute: '0',
event_id: nil,
story_id: nil,
style: 1,
character_id: granblue_id
}
response = fetch_detail(url, body)
update_game_data('Character', granblue_id, response) if response
response
end
def fetch_weapon(granblue_id)
timestamp = Time.now.to_i * 1000
url = "/archive/weapon_detail?_=#{timestamp}&t=#{timestamp}&uid=#{BOT_UID}"
body = {
special_token: nil,
user_id: BOT_UID,
kind_name: '0',
attribute: '0',
event_id: nil,
story_id: nil,
weapon_id: granblue_id
}
response = fetch_detail(url, body)
update_game_data('Weapon', granblue_id, response) if response
response
end
def fetch_summon(granblue_id)
timestamp = Time.now.to_i * 1000
url = "/archive/summon_detail?_=#{timestamp}&t=#{timestamp}&uid=#{BOT_UID}"
body = {
special_token: nil,
user_id: BOT_UID,
kind_name: '0',
attribute: '0',
event_id: nil,
story_id: nil,
summon_id: granblue_id
}
response = fetch_detail(url, body)
update_game_data('Summon', granblue_id, response) if response
response
end
# Public batch processing methods
def fetch_all_characters(only_missing: false)
process_all_records('Character', only_missing: only_missing)
end
def fetch_all_weapons(only_missing: false)
process_all_records('Weapon', only_missing: only_missing)
end
def fetch_all_summons(only_missing: false)
process_all_records('Summon', only_missing: only_missing)
end
private
def format_cookies
cookies.map { |k, v| "#{k}=#{v}" }.join('; ')
end
def auth_failed?(response)
return true if response.code != 200
begin
parsed = JSON.parse(response.body)
parsed.is_a?(Hash) && parsed['auth_status'] == 'require_auth'
rescue JSON::ParserError
true
end
end
def setup_logger
@logger = ::Logger.new($stdout)
@logger.level = debug ? ::Logger::DEBUG : ::Logger::INFO
@logger.formatter = proc do |severity, _datetime, _progname, msg|
case severity
when 'DEBUG'
debug ? "#{msg}\n" : ''
else
"#{msg}\n"
end
end
# Suppress SQL logs in non-debug mode
return if debug
ActiveRecord::Base.logger.level = ::Logger::INFO if defined?(ActiveRecord::Base)
end
def fetch_detail(url, body)
logger.debug "\n=== Request Details ==="
logger.debug "URL: #{url}"
logger.debug 'Headers:'
logger.debug HEADERS.merge(
'Cookie' => format_cookies,
'X-VERSION' => GAME_VERSION
).inspect
logger.debug 'Body:'
logger.debug body.to_json
logger.debug '===================='
response = self.class.post(
url,
headers: HEADERS.merge(
'Cookie' => format_cookies,
'X-VERSION' => GAME_VERSION
),
body: body.to_json
)
logger.debug "\n=== Response Details ==="
logger.debug "Response code: #{response.code}"
logger.debug 'Response headers:'
logger.debug response.headers.inspect
logger.debug 'Raw response body:'
logger.debug response.body.inspect
begin
logger.debug 'Parsed response body (if JSON):'
logger.debug JSON.parse(response.body).inspect
rescue JSON::ParserError => e
logger.debug "Could not parse as JSON: #{e.message}"
end
logger.debug '======================'
raise AuthenticationError if auth_failed?(response)
JSON.parse(response.body)
end
def update_game_data(model_name, granblue_id, response_data)
return unless response_data.is_a?(Hash)
model = Object.const_get(model_name)
record = model.find_by(granblue_id: granblue_id)
if record
record.update(game_raw_en: response_data)
logger.debug "Updated #{model_name} #{granblue_id}"
else
logger.warn "#{model_name} with granblue_id #{granblue_id} not found in database"
end
rescue StandardError => e
logger.error "Error updating #{model_name} #{granblue_id}: #{e.message}"
end
def process_all_records(model_name, only_missing: false)
model = Object.const_get(model_name)
scope = model
scope = scope.where(game_raw_en: nil) if only_missing
total = scope.count
success_count = 0
error_count = 0
logger.info "Starting to fetch #{total} #{model_name.downcase}s#{' (missing data only)' if only_missing}..."
scope.find_each do |record|
logger.info "\nProcessing #{model_name} #{record.granblue_id} (#{success_count + error_count + 1}/#{total})"
response = case model_name
when 'Character'
fetch_character(record.granblue_id)
when 'Weapon'
fetch_weapon(record.granblue_id)
when 'Summon'
fetch_summon(record.granblue_id)
end
success_count += 1
logger.debug "Successfully processed #{model_name} #{record.granblue_id}"
sleep(1)
rescue StandardError => e
error_count += 1
logger.error "Error processing #{model_name} #{record.granblue_id}: #{e.message}"
end
logger.info "\nProcessing complete!"
logger.info "Total: #{total}"
logger.info "Successful: #{success_count}"
logger.info "Failed: #{error_count}"
end
class AuthenticationError < StandardError; end
end

View file

@ -20,6 +20,9 @@ Rails.application.routes.draw do
get 'version', to: 'api#version' get 'version', to: 'api#version'
post 'import', to: 'import#create' post 'import', to: 'import#create'
post 'import/weapons', to: 'import#weapons'
post 'import/summons', to: 'import#summons'
post 'import/characters', to: 'import#characters'
get 'users/info/:id', to: 'users#info' get 'users/info/:id', to: 'users#info'

View file

@ -1,7 +0,0 @@
class AddWikiRawToCharacters < ActiveRecord::Migration[8.0]
def change
add_column :characters, :wiki_raw, :text
add_column :characters, :game_raw_en, :text
add_column :characters, :game_raw_jp, :text
end
end

View file

@ -10,523 +10,532 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_02_18_025315) do ActiveRecord::Schema[8.0].define(version: 20_250_301_143_956) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "btree_gin" enable_extension 'btree_gin'
enable_extension "pg_catalog.plpgsql" enable_extension 'pg_catalog.plpgsql'
enable_extension "pg_stat_statements" enable_extension 'pg_stat_statements'
enable_extension "pg_trgm" enable_extension 'pg_trgm'
enable_extension "pgcrypto" enable_extension 'pgcrypto'
create_table "app_updates", primary_key: "updated_at", id: :datetime, force: :cascade do |t| create_table 'app_updates', primary_key: 'updated_at', id: :datetime, force: :cascade do |t|
t.string "update_type", null: false t.string 'update_type', null: false
t.string "version" t.string 'version'
end end
create_table "awakenings", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'awakenings', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "name_en", null: false t.string 'name_en', null: false
t.string "name_jp", null: false t.string 'name_jp', null: false
t.string "slug", null: false t.string 'slug', null: false
t.string "object_type", null: false t.string 'object_type', null: false
t.integer "order", default: 0, null: false t.integer 'order', default: 0, null: false
end end
create_table "characters", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'characters', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "name_en" t.string 'name_en'
t.string "name_jp" t.string 'name_jp'
t.string "granblue_id" t.string 'granblue_id'
t.integer "rarity" t.integer 'rarity'
t.integer "element" t.integer 'element'
t.integer "proficiency1" t.integer 'proficiency1'
t.integer "proficiency2" t.integer 'proficiency2'
t.integer "gender" t.integer 'gender'
t.integer "race1" t.integer 'race1'
t.integer "race2" t.integer 'race2'
t.boolean "flb", default: false, null: false t.boolean 'flb', default: false, null: false
t.integer "min_hp" t.integer 'min_hp'
t.integer "max_hp" t.integer 'max_hp'
t.integer "max_hp_flb" t.integer 'max_hp_flb'
t.integer "min_atk" t.integer 'min_atk'
t.integer "max_atk" t.integer 'max_atk'
t.integer "max_atk_flb" t.integer 'max_atk_flb'
t.integer "base_da" t.integer 'base_da'
t.integer "base_ta" t.integer 'base_ta'
t.float "ougi_ratio" t.float 'ougi_ratio'
t.float "ougi_ratio_flb" t.float 'ougi_ratio_flb'
t.boolean "special", default: false, null: false t.boolean 'special', default: false, null: false
t.boolean "ulb", default: false, null: false t.boolean 'ulb', default: false, null: false
t.integer "max_hp_ulb" t.integer 'max_hp_ulb'
t.integer "max_atk_ulb" t.integer 'max_atk_ulb'
t.integer "character_id", default: [], null: false, array: true t.integer 'character_id', default: [], null: false, array: true
t.string "wiki_en", default: "", null: false t.string 'wiki_en', default: '', null: false
t.date "release_date" t.date 'release_date'
t.date "flb_date" t.date 'flb_date'
t.date "ulb_date" t.date 'ulb_date'
t.string "wiki_ja", default: "" t.string 'wiki_ja', default: ''
t.string "gamewith", default: "" t.string 'gamewith', default: ''
t.string "kamigame", default: "" t.string 'kamigame', default: ''
t.string "nicknames_en", default: [], null: false, array: true t.string 'nicknames_en', default: [], null: false, array: true
t.string "nicknames_jp", default: [], null: false, array: true t.string 'nicknames_jp', default: [], null: false, array: true
t.index ["granblue_id"], name: "index_characters_on_granblue_id" t.text 'wiki_raw'
t.index ["name_en"], name: "index_characters_on_name_en", opclass: :gin_trgm_ops, using: :gin t.text 'game_raw_en'
t.text 'game_raw_jp'
t.index ['granblue_id'], name: 'index_characters_on_granblue_id'
t.index ['name_en'], name: 'index_characters_on_name_en', opclass: :gin_trgm_ops, using: :gin
end end
create_table "data_migrations", primary_key: "version", id: :string, force: :cascade do |t| create_table 'data_migrations', primary_key: 'version', id: :string, force: :cascade do |t|
end end
create_table "data_versions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'data_versions', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "filename", null: false t.string 'filename', null: false
t.datetime "imported_at", null: false t.datetime 'imported_at', null: false
t.index ["filename"], name: "index_data_versions_on_filename", unique: true t.index ['filename'], name: 'index_data_versions_on_filename', unique: true
end end
create_table "favorites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'favorites', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "user_id" t.uuid 'user_id'
t.uuid "party_id" t.uuid 'party_id'
t.datetime "created_at", null: false t.datetime 'created_at', null: false
t.datetime "updated_at", null: false t.datetime 'updated_at', null: false
t.index ["party_id"], name: "index_favorites_on_party_id" t.index ['party_id'], name: 'index_favorites_on_party_id'
t.index ["user_id"], name: "index_favorites_on_user_id" t.index ['user_id'], name: 'index_favorites_on_user_id'
end end
create_table "gacha", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'gacha', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.boolean "premium" t.boolean 'premium'
t.boolean "classic" t.boolean 'classic'
t.boolean "flash" t.boolean 'flash'
t.boolean "legend" t.boolean 'legend'
t.boolean "valentines" t.boolean 'valentines'
t.boolean "summer" t.boolean 'summer'
t.boolean "halloween" t.boolean 'halloween'
t.boolean "holiday" t.boolean 'holiday'
t.string "drawable_type" t.string 'drawable_type'
t.uuid "drawable_id" t.uuid 'drawable_id'
t.index ["drawable_id"], name: "index_gacha_on_drawable_id", unique: true t.index ['drawable_id'], name: 'index_gacha_on_drawable_id', unique: true
t.index ["drawable_type", "drawable_id"], name: "index_gacha_on_drawable" t.index %w[drawable_type drawable_id], name: 'index_gacha_on_drawable'
end end
create_table "gacha_rateups", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'gacha_rateups', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "gacha_id" t.uuid 'gacha_id'
t.string "user_id" t.string 'user_id'
t.decimal "rate" t.decimal 'rate'
t.datetime "created_at", default: -> { "CURRENT_TIMESTAMP" }, null: false t.datetime 'created_at', default: -> { 'CURRENT_TIMESTAMP' }, null: false
t.index ["gacha_id"], name: "index_gacha_rateups_on_gacha_id" t.index ['gacha_id'], name: 'index_gacha_rateups_on_gacha_id'
end end
create_table "grid_characters", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'grid_characters', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "party_id" t.uuid 'party_id'
t.uuid "character_id" t.uuid 'character_id'
t.integer "uncap_level" t.integer 'uncap_level'
t.integer "position" t.integer 'position'
t.datetime "created_at", null: false t.datetime 'created_at', null: false
t.datetime "updated_at", null: false t.datetime 'updated_at', null: false
t.boolean "perpetuity", default: false, null: false t.boolean 'perpetuity', default: false, null: false
t.integer "transcendence_step", default: 0, null: false t.integer 'transcendence_step', default: 0, null: false
t.jsonb "ring1", default: {"modifier"=>nil, "strength"=>nil}, null: false t.jsonb 'ring1', default: { 'modifier' => nil, 'strength' => nil }, null: false
t.jsonb "ring2", default: {"modifier"=>nil, "strength"=>nil}, null: false t.jsonb 'ring2', default: { 'modifier' => nil, 'strength' => nil }, null: false
t.jsonb "ring3", default: {"modifier"=>nil, "strength"=>nil}, null: false t.jsonb 'ring3', default: { 'modifier' => nil, 'strength' => nil }, null: false
t.jsonb "ring4", default: {"modifier"=>nil, "strength"=>nil}, null: false t.jsonb 'ring4', default: { 'modifier' => nil, 'strength' => nil }, null: false
t.jsonb "earring", default: {"modifier"=>nil, "strength"=>nil}, null: false t.jsonb 'earring', default: { 'modifier' => nil, 'strength' => nil }, null: false
t.uuid "awakening_id" t.uuid 'awakening_id'
t.integer "awakening_level", default: 1 t.integer 'awakening_level', default: 1
t.index ["awakening_id"], name: "index_grid_characters_on_awakening_id" t.index ['awakening_id'], name: 'index_grid_characters_on_awakening_id'
t.index ["character_id"], name: "index_grid_characters_on_character_id" t.index ['character_id'], name: 'index_grid_characters_on_character_id'
t.index ["party_id", "position"], name: "index_grid_characters_on_party_id_and_position" t.index %w[party_id position], name: 'index_grid_characters_on_party_id_and_position'
t.index ["party_id"], name: "index_grid_characters_on_party_id" t.index ['party_id'], name: 'index_grid_characters_on_party_id'
end end
create_table "grid_summons", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'grid_summons', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "party_id" t.uuid 'party_id'
t.uuid "summon_id" t.uuid 'summon_id'
t.integer "uncap_level" t.integer 'uncap_level'
t.boolean "main" t.boolean 'main'
t.boolean "friend" t.boolean 'friend'
t.integer "position" t.integer 'position'
t.datetime "created_at", null: false t.datetime 'created_at', null: false
t.datetime "updated_at", null: false t.datetime 'updated_at', null: false
t.integer "transcendence_step", default: 0, null: false t.integer 'transcendence_step', default: 0, null: false
t.boolean "quick_summon", default: false t.boolean 'quick_summon', default: false
t.index ["party_id", "position"], name: "index_grid_summons_on_party_id_and_position" t.index %w[party_id position], name: 'index_grid_summons_on_party_id_and_position'
t.index ["party_id"], name: "index_grid_summons_on_party_id" t.index ['party_id'], name: 'index_grid_summons_on_party_id'
t.index ["summon_id"], name: "index_grid_summons_on_summon_id" t.index ['summon_id'], name: 'index_grid_summons_on_summon_id'
end end
create_table "grid_weapons", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'grid_weapons', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "party_id" t.uuid 'party_id'
t.uuid "weapon_id" t.uuid 'weapon_id'
t.uuid "weapon_key1_id" t.uuid 'weapon_key1_id'
t.uuid "weapon_key2_id" t.uuid 'weapon_key2_id'
t.integer "uncap_level" t.integer 'uncap_level'
t.boolean "mainhand" t.boolean 'mainhand'
t.integer "position" t.integer 'position'
t.datetime "created_at", null: false t.datetime 'created_at', null: false
t.datetime "updated_at", null: false t.datetime 'updated_at', null: false
t.uuid "weapon_key3_id" t.uuid 'weapon_key3_id'
t.integer "ax_modifier1" t.integer 'ax_modifier1'
t.float "ax_strength1" t.float 'ax_strength1'
t.integer "ax_modifier2" t.integer 'ax_modifier2'
t.float "ax_strength2" t.float 'ax_strength2'
t.integer "element" t.integer 'element'
t.integer "awakening_level", default: 1, null: false t.integer 'awakening_level', default: 1, null: false
t.uuid "awakening_id" t.uuid 'awakening_id'
t.integer "transcendence_step", default: 0 t.integer 'transcendence_step', default: 0
t.string "weapon_key4_id" t.string 'weapon_key4_id'
t.index ["awakening_id"], name: "index_grid_weapons_on_awakening_id" t.index ['awakening_id'], name: 'index_grid_weapons_on_awakening_id'
t.index ["party_id", "position"], name: "index_grid_weapons_on_party_id_and_position" t.index %w[party_id position], name: 'index_grid_weapons_on_party_id_and_position'
t.index ["party_id"], name: "index_grid_weapons_on_party_id" t.index ['party_id'], name: 'index_grid_weapons_on_party_id'
t.index ["weapon_id"], name: "index_grid_weapons_on_weapon_id" t.index ['weapon_id'], name: 'index_grid_weapons_on_weapon_id'
t.index ["weapon_key1_id"], name: "index_grid_weapons_on_weapon_key1_id" t.index ['weapon_key1_id'], name: 'index_grid_weapons_on_weapon_key1_id'
t.index ["weapon_key2_id"], name: "index_grid_weapons_on_weapon_key2_id" t.index ['weapon_key2_id'], name: 'index_grid_weapons_on_weapon_key2_id'
t.index ["weapon_key3_id"], name: "index_grid_weapons_on_weapon_key3_id" t.index ['weapon_key3_id'], name: 'index_grid_weapons_on_weapon_key3_id'
end end
create_table "guidebooks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'guidebooks', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "granblue_id", null: false t.string 'granblue_id', null: false
t.string "name_en", null: false t.string 'name_en', null: false
t.string "name_jp", null: false t.string 'name_jp', null: false
t.string "description_en", null: false t.string 'description_en', null: false
t.string "description_jp", null: false t.string 'description_jp', null: false
t.datetime "created_at", default: -> { "CURRENT_TIMESTAMP" }, null: false t.datetime 'created_at', default: -> { 'CURRENT_TIMESTAMP' }, null: false
end end
create_table "job_accessories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'job_accessories', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "job_id" t.uuid 'job_id'
t.string "name_en", null: false t.string 'name_en', null: false
t.string "name_jp", null: false t.string 'name_jp', null: false
t.string "granblue_id", null: false t.string 'granblue_id', null: false
t.integer "rarity" t.integer 'rarity'
t.date "release_date" t.date 'release_date'
t.integer "accessory_type" t.integer 'accessory_type'
t.index ["job_id"], name: "index_job_accessories_on_job_id" t.index ['job_id'], name: 'index_job_accessories_on_job_id'
end end
create_table "job_skills", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'job_skills', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "job_id" t.uuid 'job_id'
t.string "name_en", null: false t.string 'name_en', null: false
t.string "name_jp", null: false t.string 'name_jp', null: false
t.string "slug", null: false t.string 'slug', null: false
t.integer "color", null: false t.integer 'color', null: false
t.boolean "main", default: false t.boolean 'main', default: false
t.boolean "sub", default: false t.boolean 'sub', default: false
t.boolean "emp", default: false t.boolean 'emp', default: false
t.integer "order" t.integer 'order'
t.boolean "base", default: false t.boolean 'base', default: false
t.index ["job_id"], name: "index_job_skills_on_job_id" t.index ['job_id'], name: 'index_job_skills_on_job_id'
end end
create_table "jobs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'jobs', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "name_en" t.string 'name_en'
t.string "name_jp" t.string 'name_jp'
t.integer "proficiency1" t.integer 'proficiency1'
t.integer "proficiency2" t.integer 'proficiency2'
t.string "row" t.string 'row'
t.boolean "master_level", default: false, null: false t.boolean 'master_level', default: false, null: false
t.integer "order" t.integer 'order'
t.uuid "base_job_id" t.uuid 'base_job_id'
t.string "granblue_id" t.string 'granblue_id'
t.boolean "accessory", default: false t.boolean 'accessory', default: false
t.integer "accessory_type", default: 0 t.integer 'accessory_type', default: 0
t.boolean "ultimate_mastery", default: false, null: false t.boolean 'ultimate_mastery', default: false, null: false
t.index ["base_job_id"], name: "index_jobs_on_base_job_id" t.index ['base_job_id'], name: 'index_jobs_on_base_job_id'
end end
create_table "oauth_access_grants", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'oauth_access_grants', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "resource_owner_id", null: false t.uuid 'resource_owner_id', null: false
t.uuid "application_id", null: false t.uuid 'application_id', null: false
t.string "token", null: false t.string 'token', null: false
t.integer "expires_in", null: false t.integer 'expires_in', null: false
t.text "redirect_uri", null: false t.text 'redirect_uri', null: false
t.datetime "created_at", precision: nil, null: false t.datetime 'created_at', precision: nil, null: false
t.datetime "revoked_at", precision: nil t.datetime 'revoked_at', precision: nil
t.string "scopes" t.string 'scopes'
t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true t.index ['token'], name: 'index_oauth_access_grants_on_token', unique: true
end end
create_table "oauth_access_tokens", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'oauth_access_tokens', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "resource_owner_id" t.uuid 'resource_owner_id'
t.uuid "application_id" t.uuid 'application_id'
t.string "token", null: false t.string 'token', null: false
t.string "refresh_token" t.string 'refresh_token'
t.integer "expires_in" t.integer 'expires_in'
t.datetime "revoked_at", precision: nil t.datetime 'revoked_at', precision: nil
t.datetime "created_at", precision: nil, null: false t.datetime 'created_at', precision: nil, null: false
t.string "scopes" t.string 'scopes'
t.string "previous_refresh_token", default: "", null: false t.string 'previous_refresh_token', default: '', null: false
t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true t.index ['refresh_token'], name: 'index_oauth_access_tokens_on_refresh_token', unique: true
t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id" t.index ['resource_owner_id'], name: 'index_oauth_access_tokens_on_resource_owner_id'
t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true t.index ['token'], name: 'index_oauth_access_tokens_on_token', unique: true
end end
create_table "oauth_applications", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'oauth_applications', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "name", null: false t.string 'name', null: false
t.string "uid", null: false t.string 'uid', null: false
t.string "secret", null: false t.string 'secret', null: false
t.text "redirect_uri", null: false t.text 'redirect_uri', null: false
t.string "scopes", default: "", null: false t.string 'scopes', default: '', null: false
t.datetime "created_at", null: false t.datetime 'created_at', null: false
t.datetime "updated_at", null: false t.datetime 'updated_at', null: false
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true t.index ['uid'], name: 'index_oauth_applications_on_uid', unique: true
end end
create_table "parties", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'parties', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "user_id" t.uuid 'user_id'
t.string "shortcode" t.string 'shortcode'
t.datetime "created_at", null: false t.datetime 'created_at', null: false
t.datetime "updated_at", null: false t.datetime 'updated_at', null: false
t.boolean "extra", default: false, null: false t.boolean 'extra', default: false, null: false
t.string "name" t.string 'name'
t.text "description" t.text 'description'
t.uuid "raid_id" t.uuid 'raid_id'
t.integer "element" t.integer 'element'
t.integer "weapons_count", default: 0 t.integer 'weapons_count', default: 0
t.uuid "job_id" t.uuid 'job_id'
t.integer "master_level" t.integer 'master_level'
t.uuid "skill1_id" t.uuid 'skill1_id'
t.uuid "skill2_id" t.uuid 'skill2_id'
t.uuid "skill3_id" t.uuid 'skill3_id'
t.uuid "skill0_id" t.uuid 'skill0_id'
t.boolean "full_auto", default: false, null: false t.boolean 'full_auto', default: false, null: false
t.boolean "auto_guard", default: false, null: false t.boolean 'auto_guard', default: false, null: false
t.boolean "charge_attack", default: true, null: false t.boolean 'charge_attack', default: true, null: false
t.integer "clear_time", default: 0, null: false t.integer 'clear_time', default: 0, null: false
t.integer "button_count" t.integer 'button_count'
t.integer "chain_count" t.integer 'chain_count'
t.integer "turn_count" t.integer 'turn_count'
t.uuid "source_party_id" t.uuid 'source_party_id'
t.uuid "accessory_id" t.uuid 'accessory_id'
t.integer "characters_count", default: 0 t.integer 'characters_count', default: 0
t.integer "summons_count", default: 0 t.integer 'summons_count', default: 0
t.string "edit_key" t.string 'edit_key'
t.uuid "local_id" t.uuid 'local_id'
t.integer "ultimate_mastery" t.integer 'ultimate_mastery'
t.uuid "guidebook3_id" t.uuid 'guidebook3_id'
t.uuid "guidebook1_id" t.uuid 'guidebook1_id'
t.uuid "guidebook2_id" t.uuid 'guidebook2_id'
t.boolean "auto_summon", default: false t.boolean 'auto_summon', default: false
t.boolean "remix", default: false, null: false t.boolean 'remix', default: false, null: false
t.integer "visibility", default: 1, null: false t.integer 'visibility', default: 1, null: false
t.integer "preview_state", default: 0, null: false t.integer 'preview_state', default: 0, null: false
t.datetime "preview_generated_at" t.datetime 'preview_generated_at'
t.string "preview_s3_key" t.string 'preview_s3_key'
t.index ["accessory_id"], name: "index_parties_on_accessory_id" t.index ['accessory_id'], name: 'index_parties_on_accessory_id'
t.index ["created_at"], name: "index_parties_on_created_at" t.index ['created_at'], name: 'index_parties_on_created_at'
t.index ["element"], name: "index_parties_on_element" t.index ['element'], name: 'index_parties_on_element'
t.index ["guidebook1_id"], name: "index_parties_on_guidebook1_id" t.index ['guidebook1_id'], name: 'index_parties_on_guidebook1_id'
t.index ["guidebook2_id"], name: "index_parties_on_guidebook2_id" t.index ['guidebook2_id'], name: 'index_parties_on_guidebook2_id'
t.index ["guidebook3_id"], name: "index_parties_on_guidebook3_id" t.index ['guidebook3_id'], name: 'index_parties_on_guidebook3_id'
t.index ["job_id"], name: "index_parties_on_job_id" t.index ['job_id'], name: 'index_parties_on_job_id'
t.index ["preview_generated_at"], name: "index_parties_on_preview_generated_at" t.index ['preview_generated_at'], name: 'index_parties_on_preview_generated_at'
t.index ["preview_state"], name: "index_parties_on_preview_state" t.index ['preview_state'], name: 'index_parties_on_preview_state'
t.index ["raid_id"], name: "index_parties_on_raid_id" t.index ['raid_id'], name: 'index_parties_on_raid_id'
t.index ["shortcode"], name: "index_parties_on_shortcode" t.index ['shortcode'], name: 'index_parties_on_shortcode'
t.index ["skill0_id"], name: "index_parties_on_skill0_id" t.index ['skill0_id'], name: 'index_parties_on_skill0_id'
t.index ["skill1_id"], name: "index_parties_on_skill1_id" t.index ['skill1_id'], name: 'index_parties_on_skill1_id'
t.index ["skill2_id"], name: "index_parties_on_skill2_id" t.index ['skill2_id'], name: 'index_parties_on_skill2_id'
t.index ["skill3_id"], name: "index_parties_on_skill3_id" t.index ['skill3_id'], name: 'index_parties_on_skill3_id'
t.index ["source_party_id"], name: "index_parties_on_source_party_id" t.index ['source_party_id'], name: 'index_parties_on_source_party_id'
t.index ["user_id"], name: "index_parties_on_user_id" t.index ['user_id'], name: 'index_parties_on_user_id'
t.index ["visibility", "created_at"], name: "index_parties_on_visibility_created_at" t.index %w[visibility created_at], name: 'index_parties_on_visibility_created_at'
t.index ["weapons_count", "characters_count", "summons_count"], name: "index_parties_on_counters" t.index %w[weapons_count characters_count summons_count], name: 'index_parties_on_counters'
end end
create_table "pg_search_documents", force: :cascade do |t| create_table 'pg_search_documents', force: :cascade do |t|
t.text "content" t.text 'content'
t.string "granblue_id" t.string 'granblue_id'
t.string "name_en" t.string 'name_en'
t.string "name_jp" t.string 'name_jp'
t.integer "element" t.integer 'element'
t.string "searchable_type" t.string 'searchable_type'
t.uuid "searchable_id" t.uuid 'searchable_id'
t.datetime "created_at", null: false t.datetime 'created_at', null: false
t.datetime "updated_at", null: false t.datetime 'updated_at', null: false
t.index ["searchable_type", "searchable_id"], name: "index_pg_search_documents_on_searchable" t.index %w[searchable_type searchable_id], name: 'index_pg_search_documents_on_searchable'
end end
create_table "pghero_query_stats", force: :cascade do |t| create_table 'pghero_query_stats', force: :cascade do |t|
t.text "database" t.text 'database'
t.text "user" t.text 'user'
t.text "query" t.text 'query'
t.bigint "query_hash" t.bigint 'query_hash'
t.float "total_time" t.float 'total_time'
t.bigint "calls" t.bigint 'calls'
t.datetime "captured_at", precision: nil t.datetime 'captured_at', precision: nil
t.index ["database", "captured_at"], name: "index_pghero_query_stats_on_database_and_captured_at" t.index %w[database captured_at], name: 'index_pghero_query_stats_on_database_and_captured_at'
end end
create_table "raid_groups", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'raid_groups', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "name_en", null: false t.string 'name_en', null: false
t.string "name_jp", null: false t.string 'name_jp', null: false
t.integer "difficulty" t.integer 'difficulty'
t.integer "order", null: false t.integer 'order', null: false
t.integer "section", default: 1, null: false t.integer 'section', default: 1, null: false
t.boolean "extra", default: false, null: false t.boolean 'extra', default: false, null: false
t.boolean "hl", default: true, null: false t.boolean 'hl', default: true, null: false
t.boolean "guidebooks", default: false, null: false t.boolean 'guidebooks', default: false, null: false
end end
create_table "raids", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'raids', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "name_en" t.string 'name_en'
t.string "name_jp" t.string 'name_jp'
t.integer "level" t.integer 'level'
t.integer "element" t.integer 'element'
t.string "slug" t.string 'slug'
t.uuid "group_id" t.uuid 'group_id'
end end
create_table "sparks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'sparks', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "user_id", null: false t.string 'user_id', null: false
t.string "guild_ids", null: false, array: true t.string 'guild_ids', null: false, array: true
t.integer "crystals", default: 0 t.integer 'crystals', default: 0
t.integer "tickets", default: 0 t.integer 'tickets', default: 0
t.integer "ten_tickets", default: 0 t.integer 'ten_tickets', default: 0
t.string "target_type" t.string 'target_type'
t.bigint "target_id" t.bigint 'target_id'
t.datetime "updated_at", default: -> { "CURRENT_TIMESTAMP" }, null: false t.datetime 'updated_at', default: -> { 'CURRENT_TIMESTAMP' }, null: false
t.string "target_memo" t.string 'target_memo'
t.index ["target_type", "target_id"], name: "index_sparks_on_target" t.index %w[target_type target_id], name: 'index_sparks_on_target'
t.index ["user_id"], name: "index_sparks_on_user_id", unique: true t.index ['user_id'], name: 'index_sparks_on_user_id', unique: true
end end
create_table "summons", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'summons', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "name_en" t.string 'name_en'
t.string "name_jp" t.string 'name_jp'
t.string "granblue_id" t.string 'granblue_id'
t.integer "rarity" t.integer 'rarity'
t.integer "element" t.integer 'element'
t.string "series" t.string 'series'
t.boolean "flb", default: false, null: false t.boolean 'flb', default: false, null: false
t.boolean "ulb", default: false, null: false t.boolean 'ulb', default: false, null: false
t.integer "max_level", default: 100, null: false t.integer 'max_level', default: 100, null: false
t.integer "min_hp" t.integer 'min_hp'
t.integer "max_hp" t.integer 'max_hp'
t.integer "max_hp_flb" t.integer 'max_hp_flb'
t.integer "max_hp_ulb" t.integer 'max_hp_ulb'
t.integer "min_atk" t.integer 'min_atk'
t.integer "max_atk" t.integer 'max_atk'
t.integer "max_atk_flb" t.integer 'max_atk_flb'
t.integer "max_atk_ulb" t.integer 'max_atk_ulb'
t.boolean "subaura", default: false, null: false t.boolean 'subaura', default: false, null: false
t.boolean "limit", default: false, null: false t.boolean 'limit', default: false, null: false
t.boolean "transcendence", default: false, null: false t.boolean 'transcendence', default: false, null: false
t.integer "max_atk_xlb" t.integer 'max_atk_xlb'
t.integer "max_hp_xlb" t.integer 'max_hp_xlb'
t.integer "summon_id" t.integer 'summon_id'
t.date "release_date" t.date 'release_date'
t.date "flb_date" t.date 'flb_date'
t.date "ulb_date" t.date 'ulb_date'
t.string "wiki_en", default: "" t.string 'wiki_en', default: ''
t.string "wiki_ja", default: "" t.string 'wiki_ja', default: ''
t.string "gamewith", default: "" t.string 'gamewith', default: ''
t.string "kamigame", default: "" t.string 'kamigame', default: ''
t.date "transcendence_date" t.date 'transcendence_date'
t.string "nicknames_en", default: [], null: false, array: true t.string 'nicknames_en', default: [], null: false, array: true
t.string "nicknames_jp", default: [], null: false, array: true t.string 'nicknames_jp', default: [], null: false, array: true
t.index ["granblue_id"], name: "index_summons_on_granblue_id" t.text 'wiki_raw'
t.index ["name_en"], name: "index_summons_on_name_en", opclass: :gin_trgm_ops, using: :gin t.text 'game_raw_en'
t.text 'game_raw_jp'
t.index ['granblue_id'], name: 'index_summons_on_granblue_id'
t.index ['name_en'], name: 'index_summons_on_name_en', opclass: :gin_trgm_ops, using: :gin
end end
create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'users', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "email" t.string 'email'
t.string "password_digest" t.string 'password_digest'
t.string "username" t.string 'username'
t.integer "granblue_id" t.integer 'granblue_id'
t.datetime "created_at", null: false t.datetime 'created_at', null: false
t.datetime "updated_at", null: false t.datetime 'updated_at', null: false
t.string "picture", default: "gran" t.string 'picture', default: 'gran'
t.string "language", default: "en", null: false t.string 'language', default: 'en', null: false
t.boolean "private", default: false, null: false t.boolean 'private', default: false, null: false
t.string "element", default: "water", null: false t.string 'element', default: 'water', null: false
t.integer "gender", default: 0, null: false t.integer 'gender', default: 0, null: false
t.string "theme", default: "system", null: false t.string 'theme', default: 'system', null: false
t.integer "role", default: 1, null: false t.integer 'role', default: 1, null: false
end end
create_table "weapon_awakenings", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'weapon_awakenings', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.uuid "weapon_id", null: false t.uuid 'weapon_id', null: false
t.uuid "awakening_id", null: false t.uuid 'awakening_id', null: false
t.index ["awakening_id"], name: "index_weapon_awakenings_on_awakening_id" t.index ['awakening_id'], name: 'index_weapon_awakenings_on_awakening_id'
t.index ["weapon_id"], name: "index_weapon_awakenings_on_weapon_id" t.index ['weapon_id'], name: 'index_weapon_awakenings_on_weapon_id'
end end
create_table "weapon_keys", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'weapon_keys', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "name_en" t.string 'name_en'
t.string "name_jp" t.string 'name_jp'
t.integer "slot" t.integer 'slot'
t.integer "group" t.integer 'group'
t.integer "order" t.integer 'order'
t.string "slug" t.string 'slug'
t.integer "granblue_id" t.integer 'granblue_id'
t.integer "series", default: [], null: false, array: true t.integer 'series', default: [], null: false, array: true
end end
create_table "weapons", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table 'weapons', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
t.string "name_en" t.string 'name_en'
t.string "name_jp" t.string 'name_jp'
t.string "granblue_id" t.string 'granblue_id'
t.integer "rarity" t.integer 'rarity'
t.integer "element" t.integer 'element'
t.integer "proficiency" t.integer 'proficiency'
t.boolean "flb", default: false, null: false t.boolean 'flb', default: false, null: false
t.boolean "ulb", default: false, null: false t.boolean 'ulb', default: false, null: false
t.integer "max_level", default: 100, null: false t.integer 'max_level', default: 100, null: false
t.integer "max_skill_level", default: 10, null: false t.integer 'max_skill_level', default: 10, null: false
t.integer "min_hp" t.integer 'min_hp'
t.integer "max_hp" t.integer 'max_hp'
t.integer "max_hp_flb" t.integer 'max_hp_flb'
t.integer "max_hp_ulb" t.integer 'max_hp_ulb'
t.integer "min_atk" t.integer 'min_atk'
t.integer "max_atk" t.integer 'max_atk'
t.integer "max_atk_flb" t.integer 'max_atk_flb'
t.integer "max_atk_ulb" t.integer 'max_atk_ulb'
t.boolean "extra", default: false, null: false t.boolean 'extra', default: false, null: false
t.integer "ax_type" t.integer 'ax_type'
t.boolean "limit", default: false, null: false t.boolean 'limit', default: false, null: false
t.boolean "ax", default: false, null: false t.boolean 'ax', default: false, null: false
t.integer "max_awakening_level" t.integer 'max_awakening_level'
t.date "release_date" t.date 'release_date'
t.date "flb_date" t.date 'flb_date'
t.date "ulb_date" t.date 'ulb_date'
t.string "wiki_en", default: "" t.string 'wiki_en', default: ''
t.string "wiki_ja", default: "" t.string 'wiki_ja', default: ''
t.string "gamewith", default: "" t.string 'gamewith', default: ''
t.string "kamigame", default: "" t.string 'kamigame', default: ''
t.string "nicknames_en", default: [], null: false, array: true t.string 'nicknames_en', default: [], null: false, array: true
t.string "nicknames_jp", default: [], null: false, array: true t.string 'nicknames_jp', default: [], null: false, array: true
t.boolean "transcendence", default: false t.boolean 'transcendence', default: false
t.date "transcendence_date" t.date 'transcendence_date'
t.string "recruits" t.string 'recruits'
t.integer "series" t.integer 'series'
t.integer "new_series" t.integer 'new_series'
t.index ["granblue_id"], name: "index_weapons_on_granblue_id" t.text 'wiki_raw'
t.index ["name_en"], name: "index_weapons_on_name_en", opclass: :gin_trgm_ops, using: :gin t.text 'game_raw_en'
t.index ["recruits"], name: "index_weapons_on_recruits" t.text 'game_raw_jp'
t.index ['granblue_id'], name: 'index_weapons_on_granblue_id'
t.index ['name_en'], name: 'index_weapons_on_name_en', opclass: :gin_trgm_ops, using: :gin
t.index ['recruits'], name: 'index_weapons_on_recruits'
end end
add_foreign_key "favorites", "parties" add_foreign_key 'favorites', 'parties'
add_foreign_key "favorites", "users" add_foreign_key 'favorites', 'users'
add_foreign_key "grid_characters", "awakenings" add_foreign_key 'grid_characters', 'awakenings'
add_foreign_key "grid_characters", "characters" add_foreign_key 'grid_characters', 'characters'
add_foreign_key "grid_characters", "parties" add_foreign_key 'grid_characters', 'parties'
add_foreign_key "grid_summons", "parties" add_foreign_key 'grid_summons', 'parties'
add_foreign_key "grid_summons", "summons" add_foreign_key 'grid_summons', 'summons'
add_foreign_key "grid_weapons", "awakenings" add_foreign_key 'grid_weapons', 'awakenings'
add_foreign_key "grid_weapons", "parties" add_foreign_key 'grid_weapons', 'parties'
add_foreign_key "grid_weapons", "weapon_keys", column: "weapon_key3_id" add_foreign_key 'grid_weapons', 'weapon_keys', column: 'weapon_key3_id'
add_foreign_key "grid_weapons", "weapons" add_foreign_key 'grid_weapons', 'weapons'
add_foreign_key "oauth_access_grants", "oauth_applications", column: "application_id" add_foreign_key 'oauth_access_grants', 'oauth_applications', column: 'application_id'
add_foreign_key "oauth_access_tokens", "oauth_applications", column: "application_id" add_foreign_key 'oauth_access_tokens', 'oauth_applications', column: 'application_id'
add_foreign_key "parties", "guidebooks", column: "guidebook1_id" add_foreign_key 'parties', 'guidebooks', column: 'guidebook1_id'
add_foreign_key "parties", "guidebooks", column: "guidebook2_id" add_foreign_key 'parties', 'guidebooks', column: 'guidebook2_id'
add_foreign_key "parties", "guidebooks", column: "guidebook3_id" add_foreign_key 'parties', 'guidebooks', column: 'guidebook3_id'
add_foreign_key "parties", "job_accessories", column: "accessory_id" add_foreign_key 'parties', 'job_accessories', column: 'accessory_id'
add_foreign_key "parties", "job_skills", column: "skill0_id" add_foreign_key 'parties', 'job_skills', column: 'skill0_id'
add_foreign_key "parties", "job_skills", column: "skill1_id" add_foreign_key 'parties', 'job_skills', column: 'skill1_id'
add_foreign_key "parties", "job_skills", column: "skill2_id" add_foreign_key 'parties', 'job_skills', column: 'skill2_id'
add_foreign_key "parties", "job_skills", column: "skill3_id" add_foreign_key 'parties', 'job_skills', column: 'skill3_id'
add_foreign_key "parties", "jobs" add_foreign_key 'parties', 'jobs'
add_foreign_key "parties", "parties", column: "source_party_id" add_foreign_key 'parties', 'parties', column: 'source_party_id'
add_foreign_key "parties", "raids" add_foreign_key 'parties', 'raids'
add_foreign_key "parties", "users" add_foreign_key 'parties', 'users'
add_foreign_key "raids", "raid_groups", column: "group_id", name: "raids_group_id_fkey" add_foreign_key 'raids', 'raid_groups', column: 'group_id', name: 'raids_group_id_fkey'
add_foreign_key "weapon_awakenings", "awakenings" add_foreign_key 'weapon_awakenings', 'awakenings'
add_foreign_key "weapon_awakenings", "weapons" add_foreign_key 'weapon_awakenings', 'weapons'
end end