Merge main into gbf-wiki

This commit is contained in:
Justin Edmund 2023-07-16 02:07:33 -07:00
commit 32f4c27637
183 changed files with 5188 additions and 2756 deletions

2
.gitignore vendored
View file

@ -44,3 +44,5 @@ config/application.yml
.idea/* .idea/*
.vscode/* .vscode/*
/config/credentials/production.key

View file

@ -71,12 +71,16 @@ end
group :development do group :development do
gem 'listen' gem 'listen'
gem 'rubocop'
gem 'solargraph' gem 'solargraph'
gem 'spring' gem 'spring'
gem 'spring-commands-rspec' gem 'spring-commands-rspec'
end end
group :tools do
gem 'squasher', '>= 0.6.0'
gem 'rubocop'
end
group :test do group :test do
gem 'api_matchers' gem 'api_matchers'
gem 'byebug' gem 'byebug'

View file

@ -304,6 +304,7 @@ GEM
actionpack (>= 5.2) actionpack (>= 5.2)
activesupport (>= 5.2) activesupport (>= 5.2)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
squasher (0.7.2)
stringio (3.0.4) stringio (3.0.4)
thor (1.2.1) thor (1.2.1)
tilt (2.0.11) tilt (2.0.11)
@ -362,6 +363,7 @@ DEPENDENCIES
spring spring
spring-commands-rspec spring-commands-rspec
sprockets-rails sprockets-rails
squasher (>= 0.6.0)
will_paginate (~> 3.3) will_paginate (~> 3.3)
RUBY VERSION RUBY VERSION

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
module Api
module V1
class AwakeningBlueprint < ApiBlueprint
field :name do |w|
{
en: w.name_en,
ja: w.name_jp
}
end
fields :slug, :object_type, :order
end
end
end

View file

@ -63,6 +63,12 @@ module Api
ougi_ratio_flb: w.ougi_ratio_flb ougi_ratio_flb: w.ougi_ratio_flb
} }
end end
field :awakenings do
Awakening.where(object_type: 'Character').map do |a|
AwakeningBlueprint.render_as_hash(a)
end
end
end end
end end
end end

View file

@ -18,6 +18,7 @@ module Api
end end
field :awakening do |c| field :awakening do |c|
<<<<<<< HEAD
c.awakening c.awakening
end end
@ -34,6 +35,31 @@ module Api
rings rings
end end
field :aetherial_mastery, if: lambda { |_fn, obj, _opt|
!obj.earring['modifier'].nil?
} do |c|
c.earring
=======
{
type: AwakeningBlueprint.render_as_hash(c.awakening),
level: c.awakening_level
}
>>>>>>> main
end
field :over_mastery, if: lambda { |_fn, obj, _opt|
!obj.ring1['modifier'].nil? && !obj.ring2['modifier'].nil?
} do |c|
rings = []
rings.push(c.ring1) unless c.ring1['modifier'].nil?
rings.push(c.ring2) unless c.ring2['modifier'].nil?
rings.push(c.ring3) unless c.ring3['modifier'].nil?
rings.push(c.ring4) unless c.ring4['modifier'].nil?
rings
end
field :aetherial_mastery, if: lambda { |_fn, obj, _opt| field :aetherial_mastery, if: lambda { |_fn, obj, _opt|
!obj.earring['modifier'].nil? !obj.earring['modifier'].nil?
} do |c| } do |c|

View file

@ -9,7 +9,11 @@ module Api
end end
view :nested do view :nested do
<<<<<<< HEAD
fields :main, :friend, :position, :uncap_level, :transcendence_step fields :main, :friend, :position, :uncap_level, :transcendence_step
=======
fields :main, :friend, :position, :quick_summon, :uncap_level, :transcendence_step
>>>>>>> main
association :summon, name: :object, blueprint: SummonBlueprint association :summon, name: :object, blueprint: SummonBlueprint
end end

View file

@ -32,9 +32,9 @@ module Api
end end
end end
field :awakening, if: ->(_field_name, w, _options) { w.weapon.awakening } do |w| field :awakening, if: ->(_field_name, w, _options) { w.awakening_id } do |w|
{ {
type: w.awakening_type, type: AwakeningBlueprint.render_as_hash(w.awakening),
level: w.awakening_level level: w.awakening_level
} }
end end

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
module Api
module V1
class GuidebookBlueprint < ApiBlueprint
field :name do |book|
{
en: book.name_en,
ja: book.name_jp
}
end
field :description do |book|
{
en: book.description_en,
ja: book.description_jp
}
end
fields :granblue_id
end
end
end

View file

@ -17,7 +17,13 @@ module Api
] ]
end end
<<<<<<< HEAD
fields :granblue_id, :row, :ml, :order fields :granblue_id, :row, :ml, :order
=======
fields :granblue_id, :row, :order,
:master_level, :ultimate_mastery,
:accessory, :accessory_type
>>>>>>> main
end end
end end
end end

View file

@ -33,15 +33,25 @@ module Api
end end
view :minimal do view :minimal do
fields :name, :element, :shortcode, :favorited, :extra, fields :name, :element, :shortcode, :favorited, :remix,
:full_auto, :clear_time, :auto_guard, :created_at, :updated_at :extra, :full_auto, :clear_time, :auto_guard, :auto_summon,
:created_at, :updated_at
field :guidebooks do |p|
{
'1' => !p.guidebook1.nil? ? GuidebookBlueprint.render_as_hash(p.guidebook1) : nil,
'2' => !p.guidebook2.nil? ? GuidebookBlueprint.render_as_hash(p.guidebook2) : nil,
'3' => !p.guidebook3.nil? ? GuidebookBlueprint.render_as_hash(p.guidebook3) : nil
}
end
field :remix do |p| field :remix do |p|
p.is_remix p.is_remix
end end
association :raid, association :raid,
blueprint: RaidBlueprint blueprint: RaidBlueprint,
view: :full
association :job, association :job,
blueprint: JobBlueprint blueprint: JobBlueprint
@ -68,9 +78,18 @@ module Api
include_view :characters include_view :characters
include_view :job_skills include_view :job_skills
<<<<<<< HEAD
association :accessory, association :accessory,
blueprint: JobAccessoryBlueprint blueprint: JobAccessoryBlueprint
fields :description, :charge_attack, :button_count, :turn_count, :chain_count fields :description, :charge_attack, :button_count, :turn_count, :chain_count
=======
fields :local_id, :description, :charge_attack,
:button_count, :turn_count, :chain_count,
:master_level, :ultimate_mastery
association :accessory,
blueprint: JobAccessoryBlueprint
>>>>>>> main
association :source_party, association :source_party,
blueprint: PartyBlueprint, blueprint: PartyBlueprint,
@ -86,6 +105,11 @@ module Api
include_view :preview include_view :preview
end end
view :created do
include_view :full
fields :edit_key
end
view :destroyed do view :destroyed do
fields :name, :description, :created_at, :updated_at fields :name, :description, :created_at, :updated_at
end end

View file

@ -3,14 +3,21 @@
module Api module Api
module V1 module V1
class RaidBlueprint < ApiBlueprint class RaidBlueprint < ApiBlueprint
field :name do |raid| view :nested do
{ field :name do |raid|
en: raid.name_en, {
ja: raid.name_jp en: raid.name_en,
} ja: raid.name_jp
}
end
fields :slug, :level, :element
end end
fields :slug, :level, :group, :element view :full do
include_view :nested
association :group, blueprint: RaidGroupBlueprint, view: :flat
end
end end
end end
end end

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
module Api
module V1
class RaidGroupBlueprint < ApiBlueprint
view :flat do
field :name do |group|
{
en: group.name_en,
ja: group.name_jp
}
end
fields :difficulty, :order, :section, :extra, :guidebooks, :hl
end
view :full do
include_view :flat
association :raids, blueprint: RaidBlueprint, view: :full
end
end
end
end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Api
module V1
class SearchBlueprint < Blueprinter::Base
identifier :searchable_id
fields :searchable_type, :granblue_id, :name_en, :name_jp, :element
end
end
end

View file

@ -11,8 +11,8 @@ module Api
end end
fields :granblue_id, :element, :proficiency, fields :granblue_id, :element, :proficiency,
:max_level, :max_skill_level, :limit, :rarity, :max_level, :max_skill_level, :max_awakening_level, :limit, :rarity,
:series, :ax, :ax_type, :awakening :series, :ax, :ax_type
field :uncap do |w| field :uncap do |w|
{ {
@ -38,6 +38,12 @@ module Api
max_atk_ulb: w.max_atk_ulb max_atk_ulb: w.max_atk_ulb
} }
end end
field :awakenings, if: lambda { |_fn, obj, _opt| obj.awakenings.length.positive? } do |w|
w.awakenings.map do |a|
AwakeningBlueprint.render_as_hash(a)
end
end
end end
end end
end end

View file

@ -10,7 +10,7 @@ module Api
} }
end end
fields :slug, :series, :slot, :group, :order fields :granblue_id, :slug, :series, :slot, :group, :order
end end
end end
end end

View file

@ -50,6 +50,12 @@ module Api
@current_user @current_user
end end
def edit_key
@edit_key ||= request.headers['X-Edit-Key'] if request.headers['X-Edit-Key']
@edit_key
end
# Set the response content-type # Set the response content-type
def content_type(content_type) def content_type(content_type)
response.headers['Content-Type'] = content_type response.headers['Content-Type'] = content_type

View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Api
module V1
class CharactersController < Api::V1::ApiController
before_action :set
def show
render json: CharacterBlueprint.render(@character)
end
private
def set
@character = Character.where(granblue_id: params[:id]).first
end
end
end
end

View file

@ -7,7 +7,11 @@ module Api
before_action :find_party, only: :create before_action :find_party, only: :create
before_action :set, only: %i[update destroy] before_action :set, only: %i[update destroy]
<<<<<<< HEAD
before_action :check_authorization, only: %i[update destroy] before_action :check_authorization, only: %i[update destroy]
=======
before_action :authorize, only: %i[create update destroy]
>>>>>>> main
before_action :find_incoming_character, only: :create before_action :find_incoming_character, only: :create
before_action :find_current_characters, only: :create before_action :find_current_characters, only: :create
@ -135,17 +139,33 @@ module Api
render_unauthorized_response if current_user && (party.user != current_user) render_unauthorized_response if current_user && (party.user != current_user)
end end
<<<<<<< HEAD
def check_authorization def check_authorization
render_unauthorized_response if @character.party.user != current_user render_unauthorized_response if @character.party.user != current_user
=======
def authorize
# Create
unauthorized_create = @party && (@party.user != current_user || @party.edit_key != edit_key)
unauthorized_update = @character && @character.party && (@character.party.user != current_user || @character.party.edit_key != edit_key)
render_unauthorized_response if unauthorized_create || unauthorized_update
>>>>>>> main
end end
# Specify whitelisted properties that can be modified. # Specify whitelisted properties that can be modified.
def character_params def character_params
params.require(:character).permit(:id, :party_id, :character_id, :position, params.require(:character).permit(:id, :party_id, :character_id, :position,
:uncap_level, :transcendence_step, :perpetuity, :uncap_level, :transcendence_step, :perpetuity,
<<<<<<< HEAD
ring1: %i[modifier strength], ring2: %i[modifier strength], ring1: %i[modifier strength], ring2: %i[modifier strength],
ring3: %i[modifier strength], ring4: %i[modifier strength], ring3: %i[modifier strength], ring4: %i[modifier strength],
earring: %i[modifier strength], awakening: %i[type level]) earring: %i[modifier strength], awakening: %i[type level])
=======
:awakening_id, :awakening_level,
ring1: %i[modifier strength], ring2: %i[modifier strength],
ring3: %i[modifier strength], ring4: %i[modifier strength],
earring: %i[modifier strength])
>>>>>>> main
end end
def resolve_params def resolve_params

View file

@ -3,12 +3,21 @@
module Api module Api
module V1 module V1
class GridSummonsController < Api::V1::ApiController class GridSummonsController < Api::V1::ApiController
<<<<<<< HEAD
before_action :set, only: %w[update destroy] before_action :set, only: %w[update destroy]
attr_reader :party, :incoming_summon attr_reader :party, :incoming_summon
before_action :find_party, only: :create before_action :find_party, only: :create
before_action :find_incoming_summon, only: :create before_action :find_incoming_summon, only: :create
=======
attr_reader :party, :incoming_summon
before_action :set, only: %w[update update_uncap_level update_quick_summon]
before_action :find_party, only: :create
before_action :find_incoming_summon, only: :create
before_action :authorize, only: %i[create update update_uncap_level update_quick_summon destroy]
>>>>>>> main
def create def create
# Create the GridSummon with the desired parameters # Create the GridSummon with the desired parameters
@ -24,10 +33,72 @@ module Api
def update def update
@summon.attributes = summon_params @summon.attributes = summon_params
<<<<<<< HEAD
return render json: GridSummonBlueprint.render(@summon, view: :nested, root: :grid_summon) if @summon.save return render json: GridSummonBlueprint.render(@summon, view: :nested, root: :grid_summon) if @summon.save
render_validation_error_response(@character) render_validation_error_response(@character)
=======
return render json: GridSummonBlueprint.render(@summon, view: :nested, root: :grid_summon) if @summon.save
render_validation_error_response(@character)
end
def update_uncap_level
summon = @summon.summon
max_uncap_level = if summon.flb && !summon.ulb && !summon.xlb
4
elsif summon.ulb && !summon.xlb
5
elsif summon.xlb
6
else
3
end
greater_than_max_uncap = summon_params[:uncap_level].to_i > max_uncap_level
can_be_transcended = summon.xlb && summon_params[:transcendence_step] && summon_params[:transcendence_step]&.to_i&.positive?
uncap_level = if greater_than_max_uncap || can_be_transcended
max_uncap_level
else
summon_params[:uncap_level]
end
transcendence_step = if summon.xlb && summon_params[:transcendence_step]
summon_params[:transcendence_step]
else
0
end
@summon.update!(
uncap_level: uncap_level,
transcendence_step: transcendence_step
)
return unless @summon.persisted?
render json: GridSummonBlueprint.render(@summon, view: :nested, root: :grid_summon)
end
def update_quick_summon
return if [4, 5, 6].include?(@summon.position)
quick_summons = @summon.party.summons.select(&:quick_summon)
quick_summons.each do |summon|
summon.update!(quick_summon: false)
end
@summon.update!(quick_summon: summon_params[:quick_summon])
return unless @summon.persisted?
quick_summons -= [@summon]
summons = [@summon] + quick_summons
render json: GridSummonBlueprint.render(summons, view: :nested, root: :summons)
>>>>>>> main
end end
def save_summon(summon) def save_summon(summon)
@ -42,6 +113,7 @@ module Api
output = render_grid_summon_view(summon) output = render_grid_summon_view(summon)
render json: output, status: :created render json: output, status: :created
<<<<<<< HEAD
end end
def handle_conflict(summon) def handle_conflict(summon)
@ -56,24 +128,39 @@ module Api
output = render_grid_summon_view(conflict_summon, old_position) output = render_grid_summon_view(conflict_summon, old_position)
render json: output render json: output
=======
>>>>>>> main
end end
def update_uncap_level def handle_conflict(summon)
summon = GridSummon.find(summon_params[:id]) conflict_summon = summon.conflicts(party)
return unless conflict_summon.summon.id == incoming_summon.id
render_unauthorized_response if current_user && (summon.party.user != current_user) old_position = conflict_summon.position
conflict_summon.position = summon_params[:position]
<<<<<<< HEAD
summon.uncap_level = summon_params[:uncap_level] summon.uncap_level = summon_params[:uncap_level]
summon.transcendence_step = 0 summon.transcendence_step = 0
return unless summon.save! return unless summon.save!
=======
return unless conflict_summon.save
>>>>>>> main
render json: GridSummonBlueprint.render(summon, view: :nested, root: :grid_summon) output = render_grid_summon_view(conflict_summon, old_position)
render json: output
end end
def destroy def destroy
<<<<<<< HEAD
render_unauthorized_response if @summon.party.user != current_user render_unauthorized_response if @summon.party.user != current_user
return render json: GridSummonBlueprint.render(@summon, view: :destroyed) if @summon.destroy return render json: GridSummonBlueprint.render(@summon, view: :destroyed) if @summon.destroy
=======
summon = GridSummon.find_by('id = ?', params[:id])
render_unauthorized_response if summon.party.user != current_user
return render json: GridSummonBlueprint.render(summon, view: :destroyed) if summon.destroy
>>>>>>> main
end end
private private
@ -90,18 +177,40 @@ module Api
def render_grid_summon_view(grid_summon, conflict_position = nil) def render_grid_summon_view(grid_summon, conflict_position = nil)
GridSummonBlueprint.render(grid_summon, view: :nested, GridSummonBlueprint.render(grid_summon, view: :nested,
<<<<<<< HEAD
root: :grid_summon, root: :grid_summon,
meta: { replaced: conflict_position }) meta: { replaced: conflict_position })
end end
def set def set
@summon = GridSummon.where('id = ?', params[:id]).first @summon = GridSummon.where('id = ?', params[:id]).first
=======
root: :grid_summon,
meta: { replaced: conflict_position })
end
def authorize
# Create
unauthorized_create = @party && (@party.user != current_user || @party.edit_key != edit_key)
unauthorized_update = @summon && @summon.party && (@summon.party.user != current_user || @summon.party.edit_key != edit_key)
render_unauthorized_response if unauthorized_create || unauthorized_update
end
def set
@summon = GridSummon.find_by('id = ?', summon_params[:id])
>>>>>>> main
end end
# Specify whitelisted properties that can be modified. # Specify whitelisted properties that can be modified.
def summon_params def summon_params
<<<<<<< HEAD
params.require(:summon).permit(:id, :party_id, :summon_id, :position, :main, :friend, :uncap_level, params.require(:summon).permit(:id, :party_id, :summon_id, :position, :main, :friend, :uncap_level,
:transcendence_step) :transcendence_step)
=======
params.require(:summon).permit(:id, :party_id, :summon_id, :position, :main, :friend,
:quick_summon, :uncap_level, :transcendence_step)
>>>>>>> main
end end
end end
end end

View file

@ -3,12 +3,17 @@
module Api module Api
module V1 module V1
class GridWeaponsController < Api::V1::ApiController class GridWeaponsController < Api::V1::ApiController
<<<<<<< HEAD
before_action :set, except: %w[create update_uncap_level] before_action :set, except: %w[create update_uncap_level]
=======
>>>>>>> main
attr_reader :party, :incoming_weapon attr_reader :party, :incoming_weapon
before_action :set, except: %w[create update_uncap_level]
before_action :find_party, only: :create before_action :find_party, only: :create
before_action :find_incoming_weapon, only: :create before_action :find_incoming_weapon, only: :create
before_action :authorize, only: %i[create update destroy]
def create def create
# Create the GridWeapon with the desired parameters # Create the GridWeapon with the desired parameters
@ -183,6 +188,14 @@ module Api
@weapon = GridWeapon.where('id = ?', params[:id]).first @weapon = GridWeapon.where('id = ?', params[:id]).first
end end
def authorize
# Create
unauthorized_create = @party && (@party.user != current_user || @party.edit_key != edit_key)
unauthorized_update = @weapon && @weapon.party && (@weapon.party.user != current_user || @weapon.party.edit_key != edit_key)
render_unauthorized_response if unauthorized_create || unauthorized_update
end
# Specify whitelisted properties that can be modified. # Specify whitelisted properties that can be modified.
def weapon_params def weapon_params
params.require(:weapon).permit( params.require(:weapon).permit(
@ -190,7 +203,7 @@ module Api
:position, :mainhand, :uncap_level, :element, :position, :mainhand, :uncap_level, :element,
:weapon_key1_id, :weapon_key2_id, :weapon_key3_id, :weapon_key1_id, :weapon_key2_id, :weapon_key3_id,
:ax_modifier1, :ax_modifier2, :ax_strength1, :ax_strength2, :ax_modifier1, :ax_modifier2, :ax_strength1, :ax_strength2,
:awakening_type, :awakening_level :awakening_id, :awakening_level
) )
end end

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
module Api
module V1
class GuidebooksController < Api::V1::ApiController
def all
render json: GuidebookBlueprint.render(Guidebook.all)
end
end
end
end

View file

@ -3,7 +3,8 @@
module Api module Api
module V1 module V1
class JobsController < Api::V1::ApiController class JobsController < Api::V1::ApiController
before_action :set, only: %w[update_job update_job_skills] before_action :set, only: %w[update_job update_job_skills destroy_job_skill]
before_action :authorize, only: %w[update_job update_job_skills destroy_job_skill]
def all def all
render json: JobBlueprint.render(Job.all) render json: JobBlueprint.render(Job.all)
@ -79,6 +80,12 @@ module Api
render json: PartyBlueprint.render(@party, view: :jobs) if @party.save! render json: PartyBlueprint.render(@party, view: :jobs) if @party.save!
end end
def destroy_job_skill
position = job_params[:skill_position].to_i
@party["skill#{position}_id"] = nil
render json: PartyBlueprint.render(@party, view: :jobs) if @party.save
end
private private
def merge_skills_with_existing_skills( def merge_skills_with_existing_skills(
@ -149,7 +156,7 @@ module Api
def mismatched_skill(job, skill) def mismatched_skill(job, skill)
mismatched_main = (skill.job.id != job.id) && skill.main && !skill.sub mismatched_main = (skill.job.id != job.id) && skill.main && !skill.sub
mismatched_emp = (skill.job.id != job.id) && skill.emp mismatched_emp = (skill.job.id != job.id && skill.job.base_job.id != job.base_job.id) && skill.emp
mismatched_base = skill.job.base_job && (job.row != 'ex2' || skill.job.base_job.id != job.base_job.id) && skill.base mismatched_base = skill.job.base_job && (job.row != 'ex2' || skill.job.base_job.id != job.base_job.id) && skill.base
if %w[4 5 ex2].include?(job.row) if %w[4 5 ex2].include?(job.row)
@ -165,6 +172,10 @@ module Api
end end
end end
def authorize
render_unauthorized_response if @party.user != current_user || @party.edit_key != edit_key
end
def set def set
@party = Party.where('id = ?', params[:id]).first @party = Party.where('id = ?', params[:id]).first
end end
@ -175,7 +186,8 @@ module Api
:skill0_id, :skill0_id,
:skill1_id, :skill1_id,
:skill2_id, :skill2_id,
:skill3_id :skill3_id,
:skill_position
) )
end end
end end

View file

@ -6,27 +6,25 @@ module Api
before_action :set_from_slug, before_action :set_from_slug,
except: %w[create destroy update index favorites] except: %w[create destroy update index favorites]
before_action :set, only: %w[update destroy] before_action :set, only: %w[update destroy]
before_action :authorize, only: %w[update destroy]
MAX_CHARACTERS = 5
MAX_SUMMONS = 8
MAX_WEAPONS = 13
DEFAULT_MIN_CHARACTERS = 3
DEFAULT_MIN_SUMMONS = 2
DEFAULT_MIN_WEAPONS = 5
DEFAULT_MAX_CLEAR_TIME = 5400
def create def create
party = Party.new party = Party.new
party.user = current_user if current_user party.user = current_user if current_user
party.attributes = party_params if party_params party.attributes = party_params if party_params
# unless party_params.empty?
# party.attributes = party_params
#
# # TODO: Extract this into a different method
# job = Job.find(party_params['job_id']) if party_params['job_id'].present?
# if job
# job_skills = JobSkill.where(job: job.id, main: true)
# job_skills.each_with_index do |skill, index|
# party["skill#{index}_id"] = skill.id
# end
# end
# end
if party.save! if party.save!
return render json: PartyBlueprint.render(party, view: :full, root: :party), return render json: PartyBlueprint.render(party, view: :created, root: :party),
status: :created status: :created
end end
@ -40,19 +38,16 @@ module Api
end end
def update def update
render_unauthorized_response if @party.user != current_user
@party.attributes = party_params.except(:skill1_id, :skill2_id, :skill3_id) @party.attributes = party_params.except(:skill1_id, :skill2_id, :skill3_id)
# TODO: Validate accessory with job # TODO: Validate accessory with job
return render json: PartyBlueprint.render(@party, view: :full, root: :party) if @party.save! return render json: PartyBlueprint.render(@party, view: :full, root: :party) if @party.save
render_validation_error_response(@party) render_validation_error_response(@party)
end end
def destroy def destroy
render_unauthorized_response if @party.user != current_user
return render json: PartyBlueprint.render(@party, view: :destroyed, root: :checkin) if @party.destroy return render json: PartyBlueprint.render(@party, view: :destroyed, root: :checkin) if @party.destroy
end end
@ -61,24 +56,30 @@ module Api
new_party.attributes = { new_party.attributes = {
user: current_user, user: current_user,
name: remixed_name(@party.name), name: remixed_name(@party.name),
source_party: @party source_party: @party,
remix: true
} }
new_party.local_id = party_params[:local_id] if !party_params.nil?
if new_party.save if new_party.save
render json: PartyBlueprint.render(new_party, view: :full, root: :party, render json: PartyBlueprint.render(new_party, view: :created, root: :party),
meta: { remix: true }) status: :created
else else
render_validation_error_response(new_party) render_validation_error_response(new_party)
end end
end end
def index def index
conditions = build_conditions(request.params) conditions = build_conditions
@parties = Party.joins(:weapons) @parties = Party.joins(:weapons)
.group('parties.id') .group('parties.id')
.having('count(distinct grid_weapons.weapon_id) > 2') .having('count(distinct grid_weapons.weapon_id) > 2')
.where(conditions) .where(conditions)
.where(name_quality)
.where(user_quality)
.where(original)
.order(created_at: :desc) .order(created_at: :desc)
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE) .paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
.each { |party| party.favorited = current_user ? party.is_favorited(current_user) : false } .each { |party| party.favorited = current_user ? party.is_favorited(current_user) : false }
@ -99,11 +100,14 @@ module Api
def favorites def favorites
raise Api::V1::UnauthorizedError unless current_user raise Api::V1::UnauthorizedError unless current_user
conditions = build_conditions(request.params) conditions = build_conditions
conditions[:favorites] = { user_id: current_user.id } conditions[:favorites] = { user_id: current_user.id }
@parties = Party.joins(:favorites) @parties = Party.joins(:favorites)
.where(conditions) .where(conditions)
.where(name_quality)
.where(user_quality)
.where(original)
.order('favorites.created_at DESC') .order('favorites.created_at DESC')
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE) .paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
.each { |party| party.favorited = party.is_favorited(current_user) } .each { |party| party.favorited = party.is_favorited(current_user) }
@ -123,20 +127,76 @@ module Api
private private
def build_conditions(params) def authorize
render_unauthorized_response if @party.user != current_user || @party.edit_key != edit_key
end
def build_conditions
params = request.params
unless params['recency'].blank? unless params['recency'].blank?
start_time = (DateTime.current - params['recency'].to_i.seconds) start_time = (DateTime.current - params['recency'].to_i.seconds)
.to_datetime.beginning_of_day .to_datetime.beginning_of_day
end end
min_characters_count = params['characters_count'].blank? ? DEFAULT_MIN_CHARACTERS : params['characters_count'].to_i
min_summons_count = params['summons_count'].blank? ? DEFAULT_MIN_SUMMONS : params['summons_count'].to_i
min_weapons_count = params['weapons_count'].blank? ? DEFAULT_MIN_WEAPONS : params['weapons_count'].to_i
max_clear_time = params['max_clear_time'].blank? ? DEFAULT_MAX_CLEAR_TIME : params['max_clear_time'].to_i
{}.tap do |hash| {}.tap do |hash|
hash[:element] = params['element'] unless params['element'].blank? # Basic filters
hash[:element] = params['element'].to_i unless params['element'].blank?
hash[:raid] = params['raid'] unless params['raid'].blank? hash[:raid] = params['raid'] unless params['raid'].blank?
hash[:created_at] = start_time..DateTime.current unless params['recency'].blank? hash[:created_at] = start_time..DateTime.current unless params['recency'].blank?
hash[:weapons_count] = 5..13
# Advanced filters: Team parameters
hash[:full_auto] = params['full_auto'].to_i unless params['full_auto'].blank? || params['full_auto'].to_i == -1
hash[:auto_guard] = params['auto_guard'].to_i unless params['auto_guard'].blank? || params['auto_guard'].to_i == -1
hash[:charge_attack] = params['charge_attack'].to_i unless params['charge_attack'].blank? || params['charge_attack'].to_i == -1
# Turn count of 0 will not be displayed, so disallow on the frontend or set default to 1
# How do we do the same for button count since that can reasonably be 1?
# hash[:turn_count] = params['turn_count'].to_i unless params['turn_count'].blank? || params['turn_count'].to_i <= 0
# hash[:button_count] = params['button_count'].to_i unless params['button_count'].blank?
# hash[:clear_time] = 0..max_clear_time
# Advanced filters: Object counts
hash[:characters_count] = min_characters_count..MAX_CHARACTERS
hash[:summons_count] = min_summons_count..MAX_SUMMONS
hash[:weapons_count] = min_weapons_count..MAX_WEAPONS
end end
end end
def original
"source_party_id IS NULL" unless request.params['original'].blank? || request.params['original'] == "false"
end
def user_quality
"user_id IS NOT NULL" unless request.params[:user_quality].blank? || request.params[:user_quality] == "false"
end
def name_quality
low_quality = [
"Untitled",
"Remix of Untitled",
"Remix of Remix of Untitled",
"Remix of Remix of Remix of Untitled",
"Remix of Remix of Remix of Remix of Untitled",
"Remix of Remix of Remix of Remix of Remix of Untitled",
"無題",
"無題のリミックス",
"無題のリミックスのリミックス",
"無題のリミックスのリミックスのリミックス",
"無題のリミックスのリミックスのリミックスのリミックス",
"無題のリミックスのリミックスのリミックスのリミックスのリミックス"
]
joined_names = low_quality.map { |name| "'#{name}'" }.join(',')
"name NOT IN (#{joined_names})" unless request.params[:name_quality].blank? || request.params[:name_quality] == "false"
end
def remixed_name(name) def remixed_name(name)
blanked_name = { blanked_name = {
en: name.blank? ? 'Untitled team' : name, en: name.blank? ? 'Untitled team' : name,
@ -173,6 +233,8 @@ module Api
params.require(:party).permit( params.require(:party).permit(
:user_id, :user_id,
:local_id,
:edit_key,
:extra, :extra,
:name, :name,
:description, :description,
@ -185,11 +247,15 @@ module Api
:skill3_id, :skill3_id,
:full_auto, :full_auto,
:auto_guard, :auto_guard,
:auto_summon,
:charge_attack, :charge_attack,
:clear_time, :clear_time,
:button_count, :button_count,
:turn_count, :turn_count,
:chain_count :chain_count,
:guidebook1_id,
:guidebook2_id,
:guidebook3_id
) )
end end
end end

View file

@ -4,7 +4,11 @@ module Api
module V1 module V1
class RaidsController < Api::V1::ApiController class RaidsController < Api::V1::ApiController
def all def all
render json: RaidBlueprint.render(Raid.all) render json: RaidBlueprint.render(Raid.all, view: :full)
end
def groups
render json: RaidGroupBlueprint.render(RaidGroup.all, view: :full)
end end
end end
end end

View file

@ -3,6 +3,49 @@
module Api module Api
module V1 module V1
class SearchController < Api::V1::ApiController class SearchController < Api::V1::ApiController
TRIGRAM = {
trigram: {
threshold: 0.3
}
}.freeze
TSEARCH_WITH_PREFIX = {
tsearch: {
prefix: true,
dictionary: 'simple'
}
}.freeze
def all
locale = search_params[:locale] || 'en'
case locale
when 'en'
results = search_all_en
when 'ja'
results = search_all_ja
end
render json: SearchBlueprint.render(results, root: :results)
end
def search_all_en
PgSearch.multisearch_options = { using: TRIGRAM }
results = PgSearch.multisearch(search_params[:query]).limit(10)
if (results.length < 5) && (search_params[:query].length >= 2)
PgSearch.multisearch_options = { using: TSEARCH_WITH_PREFIX }
results = PgSearch.multisearch(search_params[:query]).limit(10)
end
results
end
def search_all_ja
PgSearch.multisearch_options = { using: TSEARCH_WITH_PREFIX }
PgSearch.multisearch(search_params[:query]).limit(10)
end
def characters def characters
filters = search_params[:filters] filters = search_params[:filters]
locale = search_params[:locale] || 'en' locale = search_params[:locale] || 'en'
@ -24,7 +67,7 @@ module Api
characters = if search_params[:query].present? && search_params[:query].length >= 2 characters = if search_params[:query].present? && search_params[:query].length >= 2
if locale == 'ja' if locale == 'ja'
Character.jp_search(search_params[:query]).where(conditions) Character.ja_search(search_params[:query]).where(conditions)
else else
Character.en_search(search_params[:query]).where(conditions) Character.en_search(search_params[:query]).where(conditions)
end end
@ -62,7 +105,7 @@ module Api
weapons = if search_params[:query].present? && search_params[:query].length >= 2 weapons = if search_params[:query].present? && search_params[:query].length >= 2
if locale == 'ja' if locale == 'ja'
Weapon.jp_search(search_params[:query]).where(conditions) Weapon.ja_search(search_params[:query]).where(conditions)
else else
Weapon.en_search(search_params[:query]).where(conditions) Weapon.en_search(search_params[:query]).where(conditions)
end end
@ -95,7 +138,7 @@ module Api
summons = if search_params[:query].present? && search_params[:query].length >= 2 summons = if search_params[:query].present? && search_params[:query].length >= 2
if locale == 'ja' if locale == 'ja'
Summon.jp_search(search_params[:query]).where(conditions) Summon.ja_search(search_params[:query]).where(conditions)
else else
Summon.en_search(search_params[:query]).where(conditions) Summon.en_search(search_params[:query]).where(conditions)
end end
@ -140,17 +183,34 @@ module Api
# Perform the query # Perform the query
skills = if search_params[:query].present? && search_params[:query].length >= 2 skills = if search_params[:query].present? && search_params[:query].length >= 2
JobSkill.method("#{locale}_search").call(search_params[:query]) JobSkill.joins(:job)
.method("#{locale}_search").call(search_params[:query])
.where(conditions) .where(conditions)
.where(job: job.id, main: false) .where(job: job.id, main: false)
.or( .or(
JobSkill.method("#{locale}_search").call(search_params[:query]) JobSkill.joins(:job)
.method("#{locale}_search").call(search_params[:query])
.where(conditions) .where(conditions)
.where(sub: true) .where(sub: true)
.where.not(job: job.id) .where.not(job: job.id)
) )
.or(
JobSkill.joins(:job)
.method("#{locale}_search").call(search_params[:query])
.where(conditions)
.where(job: { base_job: job.base_job.id }, emp: true)
.where.not(job: job.id)
)
.or(
JobSkill.joins(:job)
.method("#{locale}_search").call(search_params[:query])
.where(conditions)
.where(job: { base_job: job.base_job.id }, base: true)
.where.not(job: job.id)
)
else else
JobSkill.all JobSkill.all
.joins(:job)
.where(conditions) .where(conditions)
.where(job: job.id, main: false) .where(job: job.id, main: false)
.or( .or(
@ -165,6 +225,13 @@ module Api
.where(job: job.base_job.id, base: true) .where(job: job.base_job.id, base: true)
.where.not(job: job.id) .where.not(job: job.id)
) )
.or(
JobSkill.all
.where(conditions)
.joins(:job)
.where(job: { base_job: job.base_job.id }, emp: true)
.where.not(job: job.id)
)
end end
count = skills.length count = skills.length
@ -179,6 +246,26 @@ module Api
}) })
end end
def guidebooks
# Perform the query
books = if search_params[:query].present? && search_params[:query].length >= 2
Guidebook.method("#{locale}_search").call(search_params[:query])
else
Guidebook.all
end
count = books.length
paginated = books.paginate(page: search_params[:page], per_page: SEARCH_PER_PAGE)
render json: GuidebookBlueprint.render(paginated,
root: :results,
meta: {
count: count,
total_pages: total_pages(count),
per_page: SEARCH_PER_PAGE
})
end
private private
def total_pages(count) def total_pages(count)

View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Api
module V1
class SummonsController < Api::V1::ApiController
before_action :set
def show
render json: SummonBlueprint.render(@summon)
end
private
def set
@summon = Summon.where(granblue_id: params[:id]).first
end
end
end
end

View file

@ -8,6 +8,16 @@ module Api
before_action :set, except: %w[create check_email check_username] before_action :set, except: %w[create check_email check_username]
before_action :set_by_id, only: %w[info update] before_action :set_by_id, only: %w[info update]
MAX_CHARACTERS = 5
MAX_SUMMONS = 8
MAX_WEAPONS = 13
DEFAULT_MIN_CHARACTERS = 0
DEFAULT_MIN_SUMMONS = 0
DEFAULT_MIN_WEAPONS = 0
DEFAULT_MAX_CLEAR_TIME = 5400
def create def create
user = User.new(user_params) user = User.new(user_params)
@ -43,12 +53,14 @@ module Api
if @user.nil? if @user.nil?
render_not_found_response('user') render_not_found_response('user')
else else
conditions = build_conditions
conditions = build_conditions(request.params)
conditions[:user_id] = @user.id conditions[:user_id] = @user.id
parties = Party parties = Party
.where(conditions) .where(conditions)
.where(name_quality)
.where(user_quality)
.where(original)
.order(created_at: :desc) .order(created_at: :desc)
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE) .paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
.each do |party| .each do |party|
@ -81,26 +93,85 @@ module Api
private private
def build_conditions(params) def build_conditions
params = request.params
unless params['recency'].blank? unless params['recency'].blank?
start_time = (DateTime.current - params['recency'].to_i.seconds) start_time = (DateTime.current - params['recency'].to_i.seconds)
.to_datetime.beginning_of_day .to_datetime.beginning_of_day
end end
min_characters_count = params['characters_count'].blank? ? DEFAULT_MIN_CHARACTERS : params['characters_count'].to_i
min_summons_count = params['summons_count'].blank? ? DEFAULT_MIN_SUMMONS : params['summons_count'].to_i
min_weapons_count = params['weapons_count'].blank? ? DEFAULT_MIN_WEAPONS : params['weapons_count'].to_i
max_clear_time = params['max_clear_time'].blank? ? DEFAULT_MAX_CLEAR_TIME : params['max_clear_time'].to_i
{}.tap do |hash| {}.tap do |hash|
hash[:element] = params['element'] unless params['element'].blank? # Basic filters
hash[:element] = params['element'].to_i unless params['element'].blank?
hash[:raid] = params['raid'] unless params['raid'].blank? hash[:raid] = params['raid'] unless params['raid'].blank?
hash[:created_at] = start_time..DateTime.current unless params['recency'].blank? hash[:created_at] = start_time..DateTime.current unless params['recency'].blank?
# Advanced filters: Team parameters
hash[:full_auto] = params['full_auto'].to_i unless params['full_auto'].blank? || params['full_auto'].to_i == -1
hash[:auto_guard] = params['auto_guard'].to_i unless params['auto_guard'].blank? || params['auto_guard'].to_i == -1
hash[:charge_attack] = params['charge_attack'].to_i unless params['charge_attack'].blank? || params['charge_attack'].to_i == -1
# Turn count of 0 will not be displayed, so disallow on the frontend or set default to 1
# How do we do the same for button count since that can reasonably be 1?
# hash[:turn_count] = params['turn_count'].to_i unless params['turn_count'].blank? || params['turn_count'].to_i <= 0
# hash[:button_count] = params['button_count'].to_i unless params['button_count'].blank?
# hash[:clear_time] = 0..max_clear_time
# Advanced filters: Object counts
hash[:characters_count] = min_characters_count..MAX_CHARACTERS
hash[:summons_count] = min_summons_count..MAX_SUMMONS
hash[:weapons_count] = min_weapons_count..MAX_WEAPONS
end
end
def original
unless params.key?('original') || params['original'].blank? || params['original'] == '0'
"source_party_id IS NULL"
end
end
def user_quality
unless params.key?('user_quality') || params[:user_quality].nil? || params[:user_quality] == "0"
"user_id IS NOT NULL"
end
end
def name_quality
low_quality = [
"Untitled",
"Remix of Untitled",
"Remix of Remix of Untitled",
"Remix of Remix of Remix of Untitled",
"Remix of Remix of Remix of Remix of Untitled",
"Remix of Remix of Remix of Remix of Remix of Untitled",
"無題",
"無題のリミックス",
"無題のリミックスのリミックス",
"無題のリミックスのリミックスのリミックス",
"無題のリミックスのリミックスのリミックスのリミックス",
"無題のリミックスのリミックスのリミックスのリミックスのリミックス"
]
joined_names = low_quality.map { |name| "'#{name}'" }.join(',')
unless params.key?('name_quality') || params[:name_quality].nil? || params[:name_quality] == "0"
"name NOT IN (#{joined_names})"
end end
end end
# Specify whitelisted properties that can be modified. # Specify whitelisted properties that can be modified.
def set def set
@user = User.where('username = ?', params[:id]).first @user = User.find_by('lower(username) = ?', params[:id].downcase)
end end
def set_by_id def set_by_id
@user = User.where('id = ?', params[:id]).first @user = User.find_by('id = ?', params[:id])
end end
def user_params def user_params

View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Api
module V1
class WeaponsController < Api::V1::ApiController
before_action :set
def show
render json: WeaponBlueprint.render(@weapon)
end
private
def set
@weapon = Weapon.where(granblue_id: params[:id]).first
end
end
end
end

View file

@ -20,7 +20,6 @@ module Api
end end
def to_hash def to_hash
ap @data
{ {
message: message, message: message,
code: code, code: code,

15
app/models/awakening.rb Normal file
View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
class Awakening < ApplicationRecord
def weapon_awakenings
WeaponAwakening.where(awakening_id: id)
end
def weapons
weapon_awakenings.map(&:weapon)
end
def awakening
AwakeningBlueprint
end
end

View file

@ -3,6 +3,16 @@
class Character < ApplicationRecord class Character < ApplicationRecord
include PgSearch::Model include PgSearch::Model
multisearchable against: %i[name_en name_jp],
additional_attributes: lambda { |character|
{
name_en: character.name_en,
name_jp: character.name_jp,
granblue_id: character.granblue_id,
element: character.element
}
}
pg_search_scope :en_search, pg_search_scope :en_search,
against: :name_en, against: :name_en,
using: { using: {
@ -11,7 +21,7 @@ class Character < ApplicationRecord
} }
} }
pg_search_scope :jp_search, pg_search_scope :ja_search,
against: :name_jp, against: :name_jp,
using: { using: {
tsearch: { tsearch: {

2
app/models/gacha.rb Normal file
View file

@ -0,0 +1,2 @@
class Gacha < ApplicationRecord
end

View file

@ -1,12 +1,13 @@
# frozen_string_literal: true # frozen_string_literal: true
class GridCharacter < ApplicationRecord class GridCharacter < ApplicationRecord
belongs_to :awakening, optional: true
belongs_to :party, belongs_to :party,
counter_cache: :characters_count, counter_cache: :characters_count,
inverse_of: :characters inverse_of: :characters
validates_presence_of :party validates_presence_of :party
validate :awakening_level, on: :update validate :validate_awakening_level, on: :update
validate :transcendence, on: :update validate :transcendence, on: :update
validate :validate_over_mastery_values, on: :update validate :validate_over_mastery_values, on: :update
validate :validate_aetherial_mastery_value, on: :update validate :validate_aetherial_mastery_value, on: :update
@ -22,11 +23,12 @@ class GridCharacter < ApplicationRecord
set perpetuity: false set perpetuity: false
end end
def awakening_level # Add awakening before the model saves
return if awakening.nil? before_save :add_awakening
errors.add(:awakening, 'awakening level too low') if awakening['level'] < 1 def validate_awakening_level
errors.add(:awakening, 'awakening level too high') if awakening['level'] > 9 errors.add(:awakening, 'awakening level too low') if awakening_level < 1
errors.add(:awakening, 'awakening level too high') if awakening_level > 9
end end
def transcendence def transcendence
@ -84,6 +86,12 @@ class GridCharacter < ApplicationRecord
private private
def add_awakening
if self.awakening.nil?
self.awakening = Awakening.where(slug: "character-balanced").sole
end
end
def check_value(property, type) def check_value(property, type)
# Input format # Input format
# { ring1: { atk: 300 } } # { ring1: { atk: 300 } }

View file

@ -10,9 +10,13 @@ class GridWeapon < ApplicationRecord
belongs_to :weapon_key2, class_name: 'WeaponKey', foreign_key: :weapon_key2_id, optional: true belongs_to :weapon_key2, class_name: 'WeaponKey', foreign_key: :weapon_key2_id, optional: true
belongs_to :weapon_key3, class_name: 'WeaponKey', foreign_key: :weapon_key3_id, optional: true belongs_to :weapon_key3, class_name: 'WeaponKey', foreign_key: :weapon_key3_id, optional: true
belongs_to :awakening, optional: true
validate :compatible_with_position, on: :create validate :compatible_with_position, on: :create
validate :no_conflicts, on: :create validate :no_conflicts, on: :create
before_save :is_mainhand
##### Amoeba configuration ##### Amoeba configuration
amoeba do amoeba do
nullify :ax_modifier1 nullify :ax_modifier1
@ -71,4 +75,13 @@ class GridWeapon < ApplicationRecord
# Check if the grid weapon conflicts with any of the other grid weapons in the party # Check if the grid weapon conflicts with any of the other grid weapons in the party
errors.add(:series, 'must not conflict with existing weapons') unless conflicts(party).nil? errors.add(:series, 'must not conflict with existing weapons') unless conflicts(party).nil?
end end
# Checks if the weapon should be a mainhand before saving the model
def is_mainhand
if self.position == -1
self.mainhand = true
else
self.mainhand = false
end
end
end end

37
app/models/guidebook.rb Normal file
View file

@ -0,0 +1,37 @@
# frozen_string_literal: true
class Guidebook < ApplicationRecord
alias eql? ==
include PgSearch::Model
pg_search_scope :en_search,
against: :name_en,
using: {
tsearch: {
prefix: true,
dictionary: 'simple'
}
}
pg_search_scope :ja_search,
against: :name_jp,
using: {
tsearch: {
prefix: true,
dictionary: 'simple'
}
}
def blueprint
GuidebookBlueprint
end
def display_resource(book)
book.name_en
end
def ==(other)
self.class == other.class && granblue_id === other.granblue_id
end
end

View file

@ -1,7 +1,20 @@
# frozen_string_literal: true # frozen_string_literal: true
class Job < ApplicationRecord class Job < ApplicationRecord
include PgSearch::Model
belongs_to :party belongs_to :party
has_many :skills, class_name: 'JobSkill'
multisearchable against: %i[name_en name_jp],
additional_attributes: lambda { |job|
{
name_en: job.name_en,
name_jp: job.name_jp,
granblue_id: job.granblue_id,
element: 0
}
}
belongs_to :base_job, belongs_to :base_job,
foreign_key: 'base_job_id', foreign_key: 'base_job_id',

View file

@ -16,7 +16,7 @@ class JobSkill < ApplicationRecord
} }
} }
pg_search_scope :jp_search, pg_search_scope :ja_search,
against: :name_jp, against: :name_jp,
using: { using: {
tsearch: { tsearch: {

View file

@ -10,7 +10,8 @@ class Party < ApplicationRecord
has_many :derivative_parties, has_many :derivative_parties,
class_name: 'Party', class_name: 'Party',
foreign_key: :source_party_id, foreign_key: :source_party_id,
inverse_of: :source_party inverse_of: :source_party,
dependent: :nullify
belongs_to :user, optional: true belongs_to :user, optional: true
belongs_to :raid, optional: true belongs_to :raid, optional: true
@ -41,6 +42,21 @@ class Party < ApplicationRecord
class_name: 'JobSkill', class_name: 'JobSkill',
optional: true optional: true
belongs_to :guidebook1,
foreign_key: 'guidebook1_id',
class_name: 'Guidebook',
optional: true
belongs_to :guidebook2,
foreign_key: 'guidebook2_id',
class_name: 'Guidebook',
optional: true
belongs_to :guidebook3,
foreign_key: 'guidebook3_id',
class_name: 'Guidebook',
optional: true
has_many :characters, has_many :characters,
foreign_key: 'party_id', foreign_key: 'party_id',
class_name: 'GridCharacter', class_name: 'GridCharacter',
@ -59,12 +75,17 @@ class Party < ApplicationRecord
dependent: :destroy, dependent: :destroy,
inverse_of: :party inverse_of: :party
has_many :favorites has_many :favorites, dependent: :destroy
before_create :set_shortcode before_create :set_shortcode
before_create :set_edit_key
##### Amoeba configuration ##### Amoeba configuration
amoeba do amoeba do
set weapons_count: 0
set characters_count: 0
set summons_count: 0
nullify :description nullify :description
nullify :shortcode nullify :shortcode
@ -75,11 +96,12 @@ class Party < ApplicationRecord
##### ActiveRecord Validations ##### ActiveRecord Validations
validate :skills_are_unique validate :skills_are_unique
validate :guidebooks_are_unique
attr_accessor :favorited attr_accessor :favorited
def is_favorited(user) def is_favorited(user)
user.favorite_parties.include? self user.favorite_parties.include? self if user
end end
def is_remix def is_remix
@ -100,6 +122,12 @@ class Party < ApplicationRecord
self.shortcode = random_string self.shortcode = random_string
end end
def set_edit_key
if !self.user
self.edit_key = Digest::SHA1.hexdigest([Time.now, rand].join)
end
end
def random_string def random_string
num_chars = 6 num_chars = 6
o = [('a'..'z'), ('A'..'Z'), (0..9)].map(&:to_a).flatten o = [('a'..'z'), ('A'..'Z'), (0..9)].map(&:to_a).flatten
@ -119,4 +147,17 @@ class Party < ApplicationRecord
errors.add(:job_skills, 'must be unique') errors.add(:job_skills, 'must be unique')
end end
def guidebooks_are_unique
guidebooks = [guidebook1, guidebook2, guidebook3].compact
return if guidebooks.uniq.length == guidebooks.length
guidebooks.each_with_index do |book, index|
next if index.zero?
errors.add(:"guidebook#{index + 1}", 'must be unique') if guidebooks[0...index].include?(book)
end
errors.add(:guidebooks, 'must be unique')
end
end end

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class Raid < ApplicationRecord class Raid < ApplicationRecord
belongs_to :group, class_name: 'RaidGroup', foreign_key: :group_id
def blueprint def blueprint
RaidBlueprint RaidBlueprint
end end

9
app/models/raid_group.rb Normal file
View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class RaidGroup < ApplicationRecord
has_many :raids, class_name: 'Raid', foreign_key: :group_id
def blueprint
RaidGroupBlueprint
end
end

View file

@ -3,6 +3,16 @@
class Summon < ApplicationRecord class Summon < ApplicationRecord
include PgSearch::Model include PgSearch::Model
multisearchable against: %i[name_en name_jp],
additional_attributes: lambda { |summon|
{
name_en: summon.name_en,
name_jp: summon.name_jp,
granblue_id: summon.granblue_id,
element: summon.element
}
}
pg_search_scope :en_search, pg_search_scope :en_search,
against: :name_en, against: :name_en,
using: { using: {
@ -11,7 +21,7 @@ class Summon < ApplicationRecord
} }
} }
pg_search_scope :jp_search, pg_search_scope :ja_search,
against: :name_jp, against: :name_jp,
using: { using: {
tsearch: { tsearch: {

View file

@ -3,6 +3,16 @@
class Weapon < ApplicationRecord class Weapon < ApplicationRecord
include PgSearch::Model include PgSearch::Model
multisearchable against: %i[name_en name_jp],
additional_attributes: lambda { |weapon|
{
name_en: weapon.name_en,
name_jp: weapon.name_jp,
granblue_id: weapon.granblue_id,
element: weapon.element
}
}
pg_search_scope :en_search, pg_search_scope :en_search,
against: :name_en, against: :name_en,
using: { using: {
@ -11,7 +21,7 @@ class Weapon < ApplicationRecord
} }
} }
pg_search_scope :jp_search, pg_search_scope :ja_search,
against: :name_jp, against: :name_jp,
using: { using: {
tsearch: { tsearch: {
@ -20,6 +30,9 @@ class Weapon < ApplicationRecord
} }
} }
has_many :weapon_awakenings
has_many :awakenings, through: :weapon_awakenings
def blueprint def blueprint
WeaponBlueprint WeaponBlueprint
end end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
class WeaponAwakening < ApplicationRecord
belongs_to :weapon
belongs_to :awakening
def weapon
Weapon.find(weapon_id)
end
def awakening
Awakening.find(awakening_id)
end
end

27
bin/squasher Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'squasher' is installed as part of a gem, and
# this file is here to facilitate running it.
#
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
bundle_binstub = File.expand_path("bundle", __dir__)
if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end
require "rubygems"
require "bundler/setup"
load Gem.bin_path("squasher", "squasher")

View file

@ -1 +1 @@
d2FydGGNzmcDxx3yD8kWlU7vquTJA/QHjPxZhjcoV65DZYU2JgRZSwL+zzE+Vl4bfXtkHKXhyI821y2DvcCtFpHPmNuUncmvmt+jq9mkrK1KuQts9FLshzw1JdCDioGr+JUmMmb55nPChtHUTnd+eW7BXi9KfBtogA9vDlkEG47epYKv0Wn99ziOP/fyvIPVC+nRtUePHQvDAqIENK7doHDKoDhNkhYbCNwH8Xa+F+kZNVKMgpyoCkNDPg10NyUhub7rHBEX41xGeluZVGAkG6HsBB1XNHAkyCQroBKh/XTHZ4brCTeaoJHL3W+/nwZrRDnBVWl7p6lh17JGgfmTzx/oNBqk/FJHR9lfAdkh/msrqpl5YlnsB9nY6vmjEEX4epylGYWDndoo0INYLawOZp1xFgQFedPb7ZU5--f6jX9dWlDgeyy6gd--nHpeshtZQBL1eBzNeocBoA== Fxc8acnxWOFdt+zwWoACR/fskFH2+ZY5izq5cHf8pnGDKRSoI7QYm0h8RwevJtRUvUJQsJ+ja/xzbTYxNC4ABRSBe06lXwHJuCnt5YtR+4l+NiFnS76kGzSfhlfhmvPLtSdfTVRfhRib1vrz7E38jM1pcc2QBkzCxyaoZRu3X65U+gc7EqTjOsg8wpTjJwvfTXW9gkFNwFSen3nOSytewYDcivwUjr/3NUAONKHn4rNhBN3UJiNgOSCGj77Xx60E0Q95CidbkgExcyKAIMMsQgLKGhQRr9yUGxdshMuhA3JhVQSyvtd+jX8PmNX3FQusQIg7YUCh/WpiKo3aimZLQYY2n7lbfeSLpwuishjn138GAxe59Wgm1JhKN4xAkcAq54Q9d4AGFnu/IphMhv1TO03CqnwX1BbfY142--n8Fil7/q3W/SrENe--J31ORG+51iIo29fjiZU3Uw==

View file

@ -8,7 +8,7 @@
Rails.application.config.middleware.insert_before 0, Rack::Cors do Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do allow do
if Rails.env.production? if Rails.env.production?
origins %w[app.granblue.team hensei-web-production.up.railway.app] origins %w[granblue.team app.granblue.team hensei-web-production.up.railway.app]
else else
origins %w[staging.granblue.team 127.0.0.1:1234] origins %w[staging.granblue.team 127.0.0.1:1234]
end end

View file

@ -3,12 +3,12 @@
# Add new inflection rules using the following format. Inflections # Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different # are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default: # locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect| ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, "\\1en" # inflect.plural /^(ox)$/i, "\\1en"
# inflect.singular /^(ox)en/i, "\\1" # inflect.singular /^(ox)en/i, "\\1"
# inflect.irregular "person", "people" # inflect.irregular "person", "people"
# inflect.uncountable %w( fish sheep ) inflect.uncountable %w( gacha )
# end end
# These inflection rules are supported but not enabled by default: # These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect| # ActiveSupport::Inflector.inflections(:en) do |inflect|

View file

@ -11,6 +11,9 @@ Rails.application.routes.draw do
resources :grid_weapons, only: %i[update destroy] resources :grid_weapons, only: %i[update destroy]
resources :grid_characters, only: %i[update destroy] resources :grid_characters, only: %i[update destroy]
resources :grid_summons, only: %i[update destroy] resources :grid_summons, only: %i[update destroy]
resources :weapons, only: :show
resources :characters, only: :show
resources :summons, only: :show
resources :favorites, only: [:create] resources :favorites, only: [:create]
get 'version', to: 'api#version' get 'version', to: 'api#version'
@ -23,14 +26,17 @@ Rails.application.routes.draw do
put 'parties/:id/jobs', to: 'jobs#update_job' put 'parties/:id/jobs', to: 'jobs#update_job'
put 'parties/:id/job_skills', to: 'jobs#update_job_skills' put 'parties/:id/job_skills', to: 'jobs#update_job_skills'
delete 'parties/:id/job_skills', to: 'jobs#destroy_job_skill'
post 'check/email', to: 'users#check_email' post 'check/email', to: 'users#check_email'
post 'check/username', to: 'users#check_username' post 'check/username', to: 'users#check_username'
post 'search', to: 'search#all'
post 'search/characters', to: 'search#characters' post 'search/characters', to: 'search#characters'
post 'search/weapons', to: 'search#weapons' post 'search/weapons', to: 'search#weapons'
post 'search/summons', to: 'search#summons' post 'search/summons', to: 'search#summons'
post 'search/job_skills', to: 'search#job_skills' post 'search/job_skills', to: 'search#job_skills'
post 'search/guidebooks', to: 'search#guidebooks'
get 'jobs', to: 'jobs#all' get 'jobs', to: 'jobs#all'
@ -38,7 +44,10 @@ Rails.application.routes.draw do
get 'jobs/:id/skills', to: 'job_skills#job' get 'jobs/:id/skills', to: 'job_skills#job'
get 'jobs/:id/accessories', to: 'job_accessories#job' get 'jobs/:id/accessories', to: 'job_accessories#job'
get 'guidebooks', to: 'guidebooks#all'
get 'raids', to: 'raids#all' get 'raids', to: 'raids#all'
get 'raids/groups', to: 'raids#groups'
get 'weapon_keys', to: 'weapon_keys#all' get 'weapon_keys', to: 'weapon_keys#all'
post 'characters', to: 'grid_characters#create' post 'characters', to: 'grid_characters#create'
@ -53,6 +62,7 @@ Rails.application.routes.draw do
post 'summons', to: 'grid_summons#create' post 'summons', to: 'grid_summons#create'
post 'summons/update_uncap', to: 'grid_summons#update_uncap_level' post 'summons/update_uncap', to: 'grid_summons#update_uncap_level'
post 'summons/update_quick_summon', to: 'grid_summons#update_quick_summon'
delete 'summons', to: 'grid_summons#destroy' delete 'summons', to: 'grid_summons#destroy'
delete 'favorites', to: 'favorites#destroy' delete 'favorites', to: 'favorites#destroy'

View file

@ -1,20 +0,0 @@
# frozen_string_literal: true
class MigrateAxTypeToAx < ActiveRecord::Migration[6.1]
def up
Weapon.all.each do |weapon|
if weapon.ax_type > 0
weapon.ax = true
elsif weapon.ax_type == 0
weapon.ax = false
weapon.ax_type = nil
end
weapon.save
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

View file

@ -1,21 +0,0 @@
# frozen_string_literal: true
class SetFlbToFalseOnSummons < ActiveRecord::Migration[6.1]
def up
Summon.all.each do |summon|
if summon.flb.nil?
summon.flb = false
summon.save
end
if summon.ulb.nil?
summon.ulb = false
summon.save
end
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
class MigrateAwakeningTypeToNewAwakeningType < ActiveRecord::Migration[7.0]
def up
GridWeapon.all.each do |weapon|
if weapon.awakening_type&.positive? && weapon.awakening_type <= 3
slug = if weapon.awakening_type == 1
'weapon-atk'
elsif weapon.awakening_type == 2
'weapon-def'
elsif weapon.awakening_type == 3
'weapon-special'
end
new_awakening = Awakening.find_by(slug: slug)
weapon.awakening_id = new_awakening.id
weapon.save!
end
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

View file

@ -0,0 +1,30 @@
# frozen_string_literal: true
class MigrateCharacterAwakeningTypeToNewAwakeningType < ActiveRecord::Migration[7.0]
def up
GridCharacter.all.each do |character|
slug = if character['awakening']['type'] == 0
'character-balanced'
elsif character['awakening']['type'] == 1
'character-atk'
elsif character['awakening']['type'] == 2
'character-def'
elsif character['awakening']['type'] == 3
'character-multi'
else
'character-balanced'
end
new_awakening = Awakening.find_by(slug: slug)
character.awakening_id = new_awakening.id
character.awakening_level = character['awakening']['level']
character.save!(validate: false)
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
class PopulateRemixFlagOnParties < ActiveRecord::Migration[7.0]
def up
Party.find_each do |party|
party.update(remix: party.source_party_id.present?)
end
end
def down
Party.find_each do |party|
party.update(remix: false)
end
end
end

View file

@ -1 +1 @@
DataMigrate::Data.define(version: 20230102235227) DataMigrate::Data.define(version: 20230702035600)

View file

@ -1,5 +0,0 @@
class EnablePgcryptoExtension < ActiveRecord::Migration[5.0]
def change
enable_extension 'pgcrypto'
end
end

View file

@ -1,12 +0,0 @@
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.string :email, :unique => true
t.string :password_digest
t.string :username, :unique => true
t.integer :granblue_id, :unique => true
t.timestamps
end
end
end

View file

@ -1,28 +0,0 @@
class CreateWeapons < ActiveRecord::Migration[6.0]
def change
create_table :weapons, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.string :name_en
t.string :name_jp
t.string :granblue_id
t.integer :rarity
t.integer :element
t.integer :proficiency
t.string :series
t.boolean :flb
t.boolean :ulb
t.integer :max_level
t.integer :max_skill_level
t.integer :min_hp
t.integer :max_hp
t.integer :max_hp_flb
t.integer :max_hp_ulb
t.integer :min_atk
t.integer :max_atk
t.integer :max_atk_flb
t.integer :max_atk_ulb
end
end
end

View file

@ -1,11 +0,0 @@
class CreateParties < ActiveRecord::Migration[6.0]
def change
create_table :parties, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :user, type: :uuid
t.string :shortcode
t.timestamps
end
end
end

View file

@ -1,17 +0,0 @@
class CreateGridWeapons < ActiveRecord::Migration[6.0]
def change
create_table :grid_weapons, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :party, type: :uuid
t.references :weapon, type: :uuid
t.references :weapon_key1, class_name: 'WeaponKey', type: :uuid
t.references :weapon_key2, class_name: 'WeaponKey', type: :uuid
t.integer :uncap_level
t.boolean :mainhand
t.integer :position
t.timestamps
end
end
end

View file

@ -1,13 +0,0 @@
class CreateWeaponKeys < ActiveRecord::Migration[6.0]
def change
create_table :weapon_keys, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.string :name_en
t.string :name_jp
t.integer :series
t.integer :type
t.timestamps
end
end
end

View file

@ -1,70 +0,0 @@
# frozen_string_literal: true
class CreateDoorkeeperTables < ActiveRecord::Migration[6.0]
def change
create_table :oauth_applications, id: :uuid do |t|
t.string :name, null: false
t.string :uid, null: false
t.string :secret, null: false
t.text :redirect_uri, null: false
t.string :scopes, null: false, default: ''
t.timestamps null: false
end
add_index :oauth_applications, :uid, unique: true
create_table :oauth_access_grants, id: :uuid do |t|
t.uuid :resource_owner_id, null: false
t.uuid :application_id, null: false
t.string :token, null: false
t.integer :expires_in, null: false
t.text :redirect_uri, null: false
t.datetime :created_at, null: false
t.datetime :revoked_at
t.string :scopes
end
add_index :oauth_access_grants, :token, unique: true
add_foreign_key(
:oauth_access_grants,
:oauth_applications,
column: :application_id
)
create_table :oauth_access_tokens, id: :uuid do |t|
t.uuid :resource_owner_id
t.uuid :application_id
# If you use a custom token generator you may need to change this column
# from string to text, so that it accepts tokens larger than 255
# characters. More info on custom token generators in:
# https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
#
# t.text :token, null: false
t.string :token, null: false
t.string :refresh_token
t.integer :expires_in
t.datetime :revoked_at
t.datetime :created_at, null: false
t.string :scopes
# If there is a previous_refresh_token column,
# refresh tokens will be revoked after a related access token is used.
# If there is no previous_refresh_token column,
# previous tokens are revoked as soon as a new access token is created.
# Comment out this line if you'd rather have refresh tokens
# instantly revoked.
t.string :previous_refresh_token, null: false, default: ""
end
add_index :oauth_access_tokens, :token, unique: true
add_index :oauth_access_tokens, :resource_owner_id
add_index :oauth_access_tokens, :refresh_token, unique: true
add_foreign_key(
:oauth_access_tokens,
:oauth_applications,
column: :application_id
)
end
end

View file

@ -1,26 +0,0 @@
class CreateSummons < ActiveRecord::Migration[6.0]
def change
create_table :summons, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.string :name_en
t.string :name_jp
t.string :granblue_id
t.integer :rarity
t.integer :element
t.string :series
t.boolean :flb
t.boolean :ulb
t.integer :max_level
t.integer :min_hp
t.integer :max_hp
t.integer :max_hp_flb
t.integer :max_hp_ulb
t.integer :min_atk
t.integer :max_atk
t.integer :max_atk_flb
t.integer :max_atk_ulb
end
end
end

View file

@ -1,15 +0,0 @@
class CreateGridSummons < ActiveRecord::Migration[6.0]
def change
create_table :grid_summons, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :party, type: :uuid
t.references :summon, type: :uuid
t.integer :uncap_level
t.boolean :main
t.boolean :friend
t.integer :position
t.timestamps
end
end
end

View file

@ -1,32 +0,0 @@
class CreateCharacters < ActiveRecord::Migration[6.0]
def change
create_table :characters, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.string :name_en
t.string :name_jp
t.string :granblue_id
t.integer :rarity
t.integer :element
t.integer :proficiency1
t.integer :proficiency2
t.integer :gender
t.integer :race1
t.integer :race2
t.boolean :flb
t.boolean :max_level
t.integer :min_hp
t.integer :max_hp
t.integer :max_hp_flb
t.integer :min_atk
t.integer :max_atk
t.integer :max_atk_flb
t.integer :base_da
t.integer :base_ta
t.float :ougi_ratio
t.float :ougi_ratio_flb
end
end
end

View file

@ -1,13 +0,0 @@
class CreateGridCharacters < ActiveRecord::Migration[6.0]
def change
create_table :grid_characters do |t|
t.references :party, type: :uuid
t.references :character, type: :uuid
t.integer :uncap_level
t.integer :position
t.timestamps
end
end
end

View file

@ -1,5 +0,0 @@
class AddExtraToParty < ActiveRecord::Migration[6.1]
def change
add_column :parties, :extra, :boolean, :default => false, :null => false
end
end

View file

@ -1,5 +0,0 @@
class AddExtraToWeapons < ActiveRecord::Migration[6.1]
def change
add_column :weapons, :extra, :boolean, :default => false, :null => false
end
end

View file

@ -1,5 +0,0 @@
class AddSubauraToSummons < ActiveRecord::Migration[6.1]
def change
add_column :summons, :subaura, :boolean, :default => false, :null => false
end
end

View file

@ -1,5 +0,0 @@
class AddLimitsToWeapons < ActiveRecord::Migration[6.1]
def change
add_column :weapons, :limit, :integer
end
end

View file

@ -1,5 +0,0 @@
class AddLimitsToSummons < ActiveRecord::Migration[6.1]
def change
add_column :summons, :limit, :integer
end
end

View file

@ -1,13 +0,0 @@
class AddDefaultToLbOnWeapons < ActiveRecord::Migration[6.1]
def change
def self.up
change_column :weapons, :flb, :boolean, default: false
change_column :weapons, :ulb, :boolean, default: false
end
def self.down
change_column :weapons, :flb, :boolean, default: nil
change_column :weapons, :ulb, :boolean, default: nil
end
end
end

View file

@ -1,5 +0,0 @@
class AddAxToWeapons < ActiveRecord::Migration[6.1]
def change
add_column :weapons, :ax, :integer
end
end

View file

@ -1,10 +0,0 @@
class AddSpecialToCharacters < ActiveRecord::Migration[6.1]
def up
add_column :characters, :special, :boolean, :default => false
change_column_null :characters, :special, false
end
def down
remove_column :characters, :special, :boolean
end
end

View file

@ -1,15 +0,0 @@
class AddUlbToCharacters < ActiveRecord::Migration[6.1]
def up
add_column :characters, :ulb, :boolean, :default => false
add_column :characters, :max_hp_ulb, :integer
add_column :characters, :max_atk_ulb, :integer
change_column_null :characters, :ulb, false
change_column_null :characters, :flb, false
end
def down
remove_column :characters, :ulb, :boolean
remove_column :characters, :max_hp_ulb, :integer
remove_column :characters, :max_atk_ulb, :integer
end
end

View file

@ -1,5 +0,0 @@
class RemoveMaxLevelFromCharacters < ActiveRecord::Migration[6.1]
def change
remove_column :characters, :max_level, :boolean
end
end

View file

@ -1,5 +0,0 @@
class AddUuidToGridCharacter < ActiveRecord::Migration[6.1]
def change
add_column :grid_characters, :uuid, :uuid, default: "gen_random_uuid()", null: false
end
end

View file

@ -1,10 +0,0 @@
class ChangeGridCharacterIdToUuid < ActiveRecord::Migration[6.1]
def change
change_table :grid_characters do |t|
t.remove :id
t.rename :uuid, :id
end
execute "ALTER TABLE grid_characters ADD PRIMARY KEY (id);"
end
end

View file

@ -1,13 +0,0 @@
class AddDetailsToParty < ActiveRecord::Migration[6.1]
def change
create_table :raids, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.string :name_en
t.string :name_jp
t.integer :level
end
add_column :parties, :name, :string
add_column :parties, :description, :text
add_reference :parties, :raids, index: true
end
end

View file

@ -1,5 +0,0 @@
class AddGroupToRaids < ActiveRecord::Migration[6.1]
def change
add_column :raids, :group, :integer
end
end

View file

@ -1,6 +0,0 @@
class FixRaidAssociationOnParties < ActiveRecord::Migration[6.1]
def change
add_column :parties, :raid_id, :uuid
remove_column :parties, :raids_id, :bigint
end
end

View file

@ -1,5 +0,0 @@
class AddElementToRaids < ActiveRecord::Migration[6.1]
def change
add_column :raids, :element, :integer
end
end

View file

@ -1,5 +0,0 @@
class AddElementToParties < ActiveRecord::Migration[6.1]
def change
add_column :parties, :element, :integer
end
end

View file

@ -1,9 +0,0 @@
class CreateFavorites < ActiveRecord::Migration[6.1]
def change
create_table :favorites, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
t.references :user, type: :uuid
t.references :party, type: :uuid
t.timestamps
end
end
end

View file

@ -1,5 +0,0 @@
class ChangeWeaponSeriesToNumber < ActiveRecord::Migration[6.1]
def change
change_column :weapons, :series, 'integer USING CAST(element AS integer)'
end
end

View file

@ -1,6 +0,0 @@
class RemoveTimestampsFromWeaponKeys < ActiveRecord::Migration[6.1]
def change
remove_column :weapon_keys, :created_at, :datetime
remove_column :weapon_keys, :updated_at, :datetime
end
end

View file

@ -1,5 +0,0 @@
class AddSubTypeToWeaponKeys < ActiveRecord::Migration[6.1]
def change
add_column :weapon_keys, :subtype, :integer
end
end

View file

@ -1,5 +0,0 @@
class AddWeaponKey3ToGridWeapons < ActiveRecord::Migration[6.1]
def change
add_reference :grid_weapons, :weapon_key3, type: :uuid, foreign_key: { to_table: :weapon_keys }
end
end

View file

@ -1,8 +0,0 @@
class AddAxToGridWeapons < ActiveRecord::Migration[6.1]
def change
add_column :grid_weapons, :ax_modifier1, :integer
add_column :grid_weapons, :ax_strength1, :float
add_column :grid_weapons, :ax_modifier2, :integer
add_column :grid_weapons, :ax_strength2, :float
end
end

View file

@ -1,5 +0,0 @@
class AddElementToGridWeapons < ActiveRecord::Migration[6.1]
def change
add_column :grid_weapons, :element, :integer
end
end

View file

@ -1,5 +0,0 @@
class AddPerpetuityToGridCharacters < ActiveRecord::Migration[6.1]
def change
add_column :grid_characters, :perpetuity, :boolean
end
end

View file

@ -1,6 +0,0 @@
class RenameTypeAndSubTypeInWeaponKeys < ActiveRecord::Migration[6.1]
def change
rename_column :weapon_keys, :type, :slot
rename_column :weapon_keys, :subtype, :group
end
end

View file

@ -1,5 +0,0 @@
class AddOrderToWeaponKeys < ActiveRecord::Migration[6.1]
def change
add_column :weapon_keys, :order, :integer
end
end

View file

@ -1,7 +0,0 @@
class AddFieldsToUser < ActiveRecord::Migration[6.1]
def change
add_column :users, :picture, :string
add_column :users, :language, :string
add_column :users, :private, :boolean
end
end

View file

@ -1,7 +0,0 @@
class AddDefaultValuesToUser < ActiveRecord::Migration[6.1]
def change
change_column :users, :picture, :string, :default => "gran"
change_column :users, :language, :string, :default => "en"
change_column :users, :private, :boolean, :default => false
end
end

View file

@ -1,6 +0,0 @@
class AddNotNullableToUser < ActiveRecord::Migration[6.1]
def change
change_column :users, :language, :string, :default => "en", :null => false
change_column :users, :private, :boolean, :default => false, :null => false
end
end

View file

@ -1,5 +0,0 @@
class AddElementToUser < ActiveRecord::Migration[6.1]
def change
add_column :users, :element, :string, :default => "water", :null => false
end
end

View file

@ -1,5 +0,0 @@
class AddSlugToRaids < ActiveRecord::Migration[6.1]
def change
add_column :raids, :slug, :string
end
end

View file

@ -1,7 +0,0 @@
class AddGinIndexToWeapons < ActiveRecord::Migration[6.1]
def change
enable_extension "pg_trgm"
enable_extension "btree_gin"
add_index :weapons, :name_en, using: :gin, opclass: :gin_trgm_ops
end
end

View file

@ -1,6 +0,0 @@
class AddGinIndexToSummonsAndCharacters < ActiveRecord::Migration[6.1]
def change
add_index :summons, :name_en, using: :gin, opclass: :gin_trgm_ops
add_index :characters, :name_en, using: :gin, opclass: :gin_trgm_ops
end
end

Some files were not shown because too many files have changed in this diff Show more