February 2023 Update (#48)
This commit is contained in:
parent
2c9b15857c
commit
06f8d28874
66 changed files with 1550 additions and 349 deletions
4
Gemfile
4
Gemfile
|
|
@ -5,6 +5,7 @@ gem 'bootsnap'
|
|||
gem 'pg'
|
||||
gem 'rack-cors'
|
||||
gem 'rails'
|
||||
gem 'sprockets-rails'
|
||||
|
||||
# A Ruby Web Server Built For Concurrency
|
||||
gem 'puma'
|
||||
|
|
@ -46,6 +47,9 @@ gem 'will_paginate', '~> 3.3'
|
|||
# Migrate and update data alongside your database structure.
|
||||
gem 'data_migrate'
|
||||
|
||||
# A ruby gem to allow the copying of ActiveRecord objects and their associated children, configurable with a DSL on the model
|
||||
gem 'amoeba'
|
||||
|
||||
group :doc do
|
||||
gem 'apipie-rails'
|
||||
gem 'sdoc'
|
||||
|
|
|
|||
151
Gemfile.lock
151
Gemfile.lock
|
|
@ -1,77 +1,79 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
actioncable (7.0.4.1)
|
||||
actionpack (= 7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activestorage (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
actionmailbox (7.0.4.1)
|
||||
actionpack (= 7.0.4.1)
|
||||
activejob (= 7.0.4.1)
|
||||
activerecord (= 7.0.4.1)
|
||||
activestorage (= 7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
actionview (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
actionmailer (7.0.4.1)
|
||||
actionpack (= 7.0.4.1)
|
||||
actionview (= 7.0.4.1)
|
||||
activejob (= 7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (7.0.4)
|
||||
actionview (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
actionpack (7.0.4.1)
|
||||
actionview (= 7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
rack (~> 2.0, >= 2.2.0)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actiontext (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activestorage (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
actiontext (7.0.4.1)
|
||||
actionpack (= 7.0.4.1)
|
||||
activerecord (= 7.0.4.1)
|
||||
activestorage (= 7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
actionview (7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
activejob (7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
activejob (7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
activerecord (7.0.4)
|
||||
activemodel (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
activestorage (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
activemodel (7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
activerecord (7.0.4.1)
|
||||
activemodel (= 7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
activestorage (7.0.4.1)
|
||||
actionpack (= 7.0.4.1)
|
||||
activejob (= 7.0.4.1)
|
||||
activerecord (= 7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (7.0.4)
|
||||
activesupport (7.0.4.1)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
amazing_print (1.4.0)
|
||||
amoeba (3.2.0)
|
||||
activerecord (>= 4.2.0)
|
||||
api_matchers (0.6.2)
|
||||
activesupport (>= 3.2.5)
|
||||
nokogiri (>= 1.5.2)
|
||||
rspec (>= 3.1)
|
||||
apipie-rails (0.9.0)
|
||||
apipie-rails (0.9.1)
|
||||
actionpack (>= 5.0)
|
||||
activesupport (>= 5.0)
|
||||
ast (2.4.2)
|
||||
|
|
@ -122,7 +124,7 @@ GEM
|
|||
gemoji (4.0.1)
|
||||
gemoji-parser (1.3.1)
|
||||
gemoji (>= 2.1.0)
|
||||
globalid (1.0.0)
|
||||
globalid (1.0.1)
|
||||
activesupport (>= 5.0)
|
||||
i18n (1.12.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
|
|
@ -132,13 +134,13 @@ GEM
|
|||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
listen (3.7.1)
|
||||
listen (3.8.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
loofah (2.19.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.8.0)
|
||||
mail (2.8.0.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
net-imap
|
||||
net-pop
|
||||
|
|
@ -159,7 +161,7 @@ GEM
|
|||
net-smtp (0.3.3)
|
||||
net-protocol
|
||||
nio4r (2.5.8)
|
||||
nokogiri (1.13.10)
|
||||
nokogiri (1.14.0)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
oj (3.13.23)
|
||||
|
|
@ -170,38 +172,38 @@ GEM
|
|||
pg_search (2.3.6)
|
||||
activerecord (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
psych (5.0.1)
|
||||
psych (5.0.2)
|
||||
stringio
|
||||
puma (6.0.2)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.6.2)
|
||||
rack (2.2.5)
|
||||
rack (2.2.6.2)
|
||||
rack-cors (1.1.1)
|
||||
rack (>= 2.0.0)
|
||||
rack-test (2.0.2)
|
||||
rack (>= 1.3)
|
||||
rails (7.0.4)
|
||||
actioncable (= 7.0.4)
|
||||
actionmailbox (= 7.0.4)
|
||||
actionmailer (= 7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
actiontext (= 7.0.4)
|
||||
actionview (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activemodel (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activestorage (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
rails (7.0.4.1)
|
||||
actioncable (= 7.0.4.1)
|
||||
actionmailbox (= 7.0.4.1)
|
||||
actionmailer (= 7.0.4.1)
|
||||
actionpack (= 7.0.4.1)
|
||||
actiontext (= 7.0.4.1)
|
||||
actionview (= 7.0.4.1)
|
||||
activejob (= 7.0.4.1)
|
||||
activemodel (= 7.0.4.1)
|
||||
activerecord (= 7.0.4.1)
|
||||
activestorage (= 7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.0.4)
|
||||
railties (= 7.0.4.1)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.4.4)
|
||||
rails-html-sanitizer (1.5.0)
|
||||
loofah (~> 2.19, >= 2.19.1)
|
||||
railties (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
railties (7.0.4.1)
|
||||
actionpack (= 7.0.4.1)
|
||||
activesupport (= 7.0.4.1)
|
||||
method_source
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
|
|
@ -213,7 +215,7 @@ GEM
|
|||
ffi (~> 1.0)
|
||||
rdoc (6.5.0)
|
||||
psych (>= 4.0.0)
|
||||
regexp_parser (2.6.1)
|
||||
regexp_parser (2.6.2)
|
||||
responders (3.0.1)
|
||||
actionpack (>= 5.0)
|
||||
railties (>= 5.0)
|
||||
|
|
@ -226,10 +228,10 @@ GEM
|
|||
rspec-mocks (~> 3.12.0)
|
||||
rspec-core (3.12.0)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-expectations (3.12.1)
|
||||
rspec-expectations (3.12.2)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-mocks (3.12.1)
|
||||
rspec-mocks (3.12.3)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-rails (6.0.1)
|
||||
|
|
@ -243,20 +245,20 @@ GEM
|
|||
rspec-support (3.12.0)
|
||||
rspec_junit_formatter (0.6.0)
|
||||
rspec-core (>= 2, < 4, != 2.12.0)
|
||||
rubocop (1.42.0)
|
||||
rubocop (1.43.0)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.1.2.1)
|
||||
parser (>= 3.2.0.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.24.1, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 3.0)
|
||||
unicode-display_width (>= 2.4.0, < 3.0)
|
||||
rubocop-ast (1.24.1)
|
||||
parser (>= 3.1.1.0)
|
||||
ruby-progressbar (1.11.0)
|
||||
sdoc (2.5.0)
|
||||
sdoc (2.6.0)
|
||||
rdoc (>= 5.0)
|
||||
shoulda-matchers (5.3.0)
|
||||
activesupport (>= 5.2.0)
|
||||
|
|
@ -281,16 +283,23 @@ GEM
|
|||
thor (~> 1.0)
|
||||
tilt (~> 2.0)
|
||||
yard (~> 0.9, >= 0.9.24)
|
||||
spring (4.1.0)
|
||||
spring (4.1.1)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
sprockets (4.2.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (>= 2.2.4, < 4)
|
||||
sprockets-rails (3.4.2)
|
||||
actionpack (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
sprockets (>= 3.0.0)
|
||||
stringio (3.0.4)
|
||||
thor (1.2.1)
|
||||
tilt (2.0.11)
|
||||
timeout (0.3.1)
|
||||
tzinfo (2.0.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.4.0)
|
||||
unicode-display_width (2.4.2)
|
||||
webrick (1.7.0)
|
||||
websocket-driver (0.7.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
|
|
@ -305,6 +314,7 @@ PLATFORMS
|
|||
|
||||
DEPENDENCIES
|
||||
amazing_print
|
||||
amoeba
|
||||
api_matchers
|
||||
apipie-rails
|
||||
awesome_nested_set
|
||||
|
|
@ -338,6 +348,7 @@ DEPENDENCIES
|
|||
solargraph
|
||||
spring
|
||||
spring-commands-rspec
|
||||
sprockets-rails
|
||||
will_paginate (~> 3.3)
|
||||
|
||||
RUBY VERSION
|
||||
|
|
|
|||
0
app/assets/config/manifest.js
Normal file
0
app/assets/config/manifest.js
Normal file
|
|
@ -14,6 +14,10 @@ module Api
|
|||
field :errors, if: ->(_field_name, _error, options) { options.key?(:exception) } do |_, options|
|
||||
options[:exception]
|
||||
end
|
||||
|
||||
field :errors, if: ->(_field_name, object, options) { options.key?(:errors) } do |_, options|
|
||||
options[:errors]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,11 +11,33 @@ module Api
|
|||
view :nested do
|
||||
fields :position, :uncap_level, :perpetuity
|
||||
|
||||
field :transcendence_step, if: lambda { |_fn, obj, _opt|
|
||||
obj.character.ulb
|
||||
} do |c|
|
||||
c.transcendence_step
|
||||
end
|
||||
|
||||
field :awakening do |c|
|
||||
{
|
||||
type: c.awakening_type,
|
||||
level: c.awakening_level
|
||||
}
|
||||
c.awakening
|
||||
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|
|
||||
!obj.earring['modifier'].nil?
|
||||
} do |c|
|
||||
c.earring
|
||||
end
|
||||
|
||||
association :character, name: :object, blueprint: CharacterBlueprint
|
||||
|
|
@ -25,6 +47,10 @@ module Api
|
|||
include_view :nested
|
||||
association :party, blueprint: PartyBlueprint, view: :minimal
|
||||
end
|
||||
|
||||
view :destroyed do
|
||||
fields :position, :created_at, :updated_at
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ module Api
|
|||
class GridSummonBlueprint < ApiBlueprint
|
||||
view :uncap do
|
||||
association :party, blueprint: PartyBlueprint, view: :minimal
|
||||
fields :position, :uncap_level
|
||||
fields :position, :uncap_level, :transcendence_step
|
||||
end
|
||||
|
||||
view :nested do
|
||||
fields :main, :friend, :position, :uncap_level
|
||||
fields :main, :friend, :position, :uncap_level, :transcendence_step
|
||||
association :summon, name: :object, blueprint: SummonBlueprint
|
||||
end
|
||||
|
||||
|
|
@ -17,6 +17,10 @@ module Api
|
|||
include_view :nested
|
||||
association :party, blueprint: PartyBlueprint, view: :minimal
|
||||
end
|
||||
|
||||
view :destroyed do
|
||||
fields :main, :friend, :position, :created_at, :updated_at
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ module Api
|
|||
include_view :nested
|
||||
association :party, blueprint: PartyBlueprint, view: :minimal
|
||||
end
|
||||
|
||||
view :destroyed do
|
||||
fields :mainhand, :position, :created_at, :updated_at
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
20
app/blueprints/api/v1/job_accessory_blueprint.rb
Normal file
20
app/blueprints/api/v1/job_accessory_blueprint.rb
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V1
|
||||
class JobAccessoryBlueprint < ApiBlueprint
|
||||
field :name do |skill|
|
||||
{
|
||||
en: skill.name_en,
|
||||
ja: skill.name_jp
|
||||
}
|
||||
end
|
||||
|
||||
association :job,
|
||||
name: :job,
|
||||
blueprint: JobBlueprint
|
||||
|
||||
fields :granblue_id, :rarity, :release_date
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -17,7 +17,7 @@ module Api
|
|||
]
|
||||
end
|
||||
|
||||
fields :row, :ml, :order
|
||||
fields :granblue_id, :row, :ml, :order, :accessory, :accessory_type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@ module Api
|
|||
fields :name, :element, :shortcode, :favorited, :extra,
|
||||
:full_auto, :clear_time, :auto_guard, :created_at, :updated_at
|
||||
|
||||
field :remix do |p|
|
||||
p.is_remix
|
||||
end
|
||||
|
||||
association :raid,
|
||||
blueprint: RaidBlueprint
|
||||
|
||||
|
|
@ -64,13 +68,30 @@ module Api
|
|||
include_view :characters
|
||||
include_view :job_skills
|
||||
|
||||
fields :description, :charge_attack, :button_count, :turn_count, :chain_count
|
||||
fields :local_id, :description, :charge_attack, :button_count, :turn_count, :chain_count
|
||||
|
||||
association :accessory,
|
||||
blueprint: JobAccessoryBlueprint
|
||||
|
||||
association :source_party,
|
||||
blueprint: PartyBlueprint,
|
||||
view: :minimal
|
||||
|
||||
# TODO: This should probably be paginated
|
||||
association :remixes,
|
||||
blueprint: PartyBlueprint,
|
||||
view: :collection
|
||||
end
|
||||
|
||||
view :collection do
|
||||
include_view :preview
|
||||
end
|
||||
|
||||
view :created do
|
||||
include_view :full
|
||||
fields :edit_key
|
||||
end
|
||||
|
||||
view :destroyed do
|
||||
fields :name, :description, :created_at, :updated_at
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ module Api
|
|||
field :uncap do |w|
|
||||
{
|
||||
flb: w.flb,
|
||||
ulb: w.ulb
|
||||
ulb: w.ulb,
|
||||
xlb: w.xlb
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -24,7 +25,8 @@ module Api
|
|||
min_hp: w.min_hp,
|
||||
max_hp: w.max_hp,
|
||||
max_hp_flb: w.max_hp_flb,
|
||||
max_hp_ulb: w.max_hp_ulb
|
||||
max_hp_ulb: w.max_hp_ulb,
|
||||
max_hp_xlb: w.max_hp_xlb
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -33,7 +35,8 @@ module Api
|
|||
min_atk: w.min_atk,
|
||||
max_atk: w.max_atk,
|
||||
max_atk_flb: w.max_atk_flb,
|
||||
max_atk_ulb: w.max_atk_ulb
|
||||
max_atk_ulb: w.max_atk_ulb,
|
||||
max_atk_xlb: w.max_atk_xlb
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
9
app/blueprints/api/v1/update_blueprint.rb
Normal file
9
app/blueprints/api/v1/update_blueprint.rb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V1
|
||||
class UpdateBlueprint < Blueprinter::Base
|
||||
fields :version, :update_type, :updated_at
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -36,6 +36,11 @@ module Api
|
|||
respond_to :json
|
||||
|
||||
##### Methods
|
||||
# Returns the latest update
|
||||
def version
|
||||
render json: UpdateBlueprint.render_as_json(AppUpdate.last)
|
||||
end
|
||||
|
||||
# Assign the current user if the Doorkeeper token isn't nil, then
|
||||
# update the current user's last seen datetime and last IP address
|
||||
# before returning
|
||||
|
|
@ -45,6 +50,12 @@ module Api
|
|||
@current_user
|
||||
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
|
||||
def content_type(content_type)
|
||||
response.headers['Content-Type'] = content_type
|
||||
|
|
|
|||
19
app/controllers/api/v1/characters_controller.rb
Normal file
19
app/controllers/api/v1/characters_controller.rb
Normal 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
|
||||
|
|
@ -6,6 +6,8 @@ module Api
|
|||
attr_reader :party, :incoming_character, :current_characters
|
||||
|
||||
before_action :find_party, only: :create
|
||||
before_action :set, only: %i[update destroy]
|
||||
before_action :authorize, only: %i[create update destroy]
|
||||
before_action :find_incoming_character, only: :create
|
||||
before_action :find_current_characters, only: :create
|
||||
|
||||
|
|
@ -19,16 +21,15 @@ module Api
|
|||
conflict_view = render_conflict_view(conflict_characters, incoming_character, character_params[:position])
|
||||
render json: conflict_view
|
||||
else
|
||||
# Replace the grid character in the position if it is already filled
|
||||
# Destroy the grid character in the position if it is already filled
|
||||
if GridCharacter.where(party_id: party.id, position: character_params[:position]).exists?
|
||||
character = GridCharacter.where(party_id: party.id, position: character_params[:position]).limit(1)[0]
|
||||
character.character_id = incoming_character.id
|
||||
character.destroy
|
||||
end
|
||||
|
||||
# Otherwise, create a new grid character
|
||||
else
|
||||
# Then, create a new grid character
|
||||
character = GridCharacter.create!(character_params.merge(party_id: party.id,
|
||||
character_id: incoming_character.id))
|
||||
end
|
||||
|
||||
if character.save!
|
||||
grid_character_view = render_grid_character_view(character)
|
||||
|
|
@ -37,6 +38,20 @@ module Api
|
|||
end
|
||||
end
|
||||
|
||||
def update
|
||||
mastery = {}
|
||||
%i[ring1 ring2 ring3 ring4 earring awakening].each do |key|
|
||||
value = character_params.to_h[key]
|
||||
mastery[key] = value unless value.nil?
|
||||
end
|
||||
|
||||
@character.attributes = character_params.merge(mastery)
|
||||
|
||||
return render json: GridCharacterBlueprint.render(@character, view: :full) if @character.save
|
||||
|
||||
render_validation_error_response(@character)
|
||||
end
|
||||
|
||||
def resolve
|
||||
incoming = Character.find(resolve_params[:incoming])
|
||||
conflicting = resolve_params[:conflicting].map { |id| GridCharacter.find(id) }
|
||||
|
|
@ -70,13 +85,17 @@ module Api
|
|||
render_unauthorized_response if current_user && (character.party.user != current_user)
|
||||
|
||||
character.uncap_level = character_params[:uncap_level]
|
||||
character.transcendence_step = character_params[:transcendence_step]
|
||||
return unless character.save!
|
||||
|
||||
render json: GridCharacterBlueprint.render(character, view: :nested, root: :grid_character)
|
||||
end
|
||||
|
||||
# TODO: Implement removing characters
|
||||
def destroy; end
|
||||
def destroy
|
||||
render_unauthorized_response if @character.party.user != current_user
|
||||
return render json: GridCharacterBlueprint.render(@character, view: :destroyed) if @character.destroy
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
@ -103,6 +122,10 @@ module Api
|
|||
end.flatten
|
||||
end
|
||||
|
||||
def set
|
||||
@character = GridCharacter.find(params[:id])
|
||||
end
|
||||
|
||||
def find_incoming_character
|
||||
@incoming_character = Character.find(character_params[:character_id])
|
||||
end
|
||||
|
|
@ -112,10 +135,25 @@ module Api
|
|||
render_unauthorized_response if current_user && (party.user != current_user)
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
# Specify whitelisted properties that can be modified.
|
||||
def character_params
|
||||
params.require(:character).permit(:id, :party_id, :character_id, :position, :uncap_level, :conflicting,
|
||||
:incoming)
|
||||
params.require(:character).permit(:id, :party_id, :character_id, :position,
|
||||
:uncap_level, :transcendence_step, :perpetuity,
|
||||
ring1: %i[modifier strength], ring2: %i[modifier strength],
|
||||
ring3: %i[modifier strength], ring4: %i[modifier strength],
|
||||
earring: %i[modifier strength], awakening: %i[type level])
|
||||
end
|
||||
|
||||
def resolve_params
|
||||
params.require(:resolve).permit(:position, :incoming, conflicting: [])
|
||||
end
|
||||
|
||||
def render_conflict_view(conflict_characters, incoming_character, incoming_position)
|
||||
|
|
@ -129,10 +167,6 @@ module Api
|
|||
def render_grid_character_view(grid_character)
|
||||
GridCharacterBlueprint.render(grid_character, view: :nested)
|
||||
end
|
||||
|
||||
def resolve_params
|
||||
params.require(:resolve).permit(:position, :incoming, conflicting: [])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,12 +3,34 @@
|
|||
module Api
|
||||
module V1
|
||||
class GridSummonsController < Api::V1::ApiController
|
||||
attr_reader :party, :incoming_summon
|
||||
|
||||
before_action :set, only: %w[update destroy]
|
||||
before_action :find_party, only: :create
|
||||
before_action :find_incoming_summon, only: :create
|
||||
before_action :authorize, only: %i[create update destroy]
|
||||
|
||||
def create
|
||||
party = Party.find(summon_params[:party_id])
|
||||
canonical_summon = Summon.find(summon_params[:summon_id])
|
||||
# Create the GridSummon with the desired parameters
|
||||
summon = GridSummon.new
|
||||
summon.attributes = summon_params.merge(party_id: party.id, summon_id: incoming_summon.id)
|
||||
|
||||
render_unauthorized_response if current_user && (party.user != current_user)
|
||||
if summon.validate
|
||||
save_summon(summon)
|
||||
else
|
||||
handle_conflict(summon)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@summon.attributes = summon_params
|
||||
|
||||
return render json: GridSummonBlueprint.render(@summon, view: :nested, root: :grid_summon) if @summon.save
|
||||
|
||||
render_validation_error_response(@character)
|
||||
end
|
||||
|
||||
def save_summon(summon)
|
||||
if (grid_summon = GridSummon.where(
|
||||
party_id: party.id,
|
||||
position: summon_params[:position]
|
||||
|
|
@ -16,8 +38,24 @@ module Api
|
|||
GridSummon.destroy(grid_summon.id)
|
||||
end
|
||||
|
||||
summon = GridSummon.create!(summon_params.merge(party_id: party.id, summon_id: canonical_summon.id))
|
||||
render json: GridSummonBlueprint.render(summon, view: :nested), status: :created if summon.save!
|
||||
return unless summon.save
|
||||
|
||||
output = render_grid_summon_view(summon)
|
||||
render json: output, status: :created
|
||||
end
|
||||
|
||||
def handle_conflict(summon)
|
||||
conflict_summon = summon.conflicts(party)
|
||||
ap conflict_summon
|
||||
return unless conflict_summon.summon.id == incoming_summon.id
|
||||
|
||||
old_position = conflict_summon.position
|
||||
conflict_summon.position = summon_params[:position]
|
||||
|
||||
return unless conflict_summon.save
|
||||
|
||||
output = render_grid_summon_view(conflict_summon, old_position)
|
||||
render json: output
|
||||
end
|
||||
|
||||
def update_uncap_level
|
||||
|
|
@ -26,19 +64,52 @@ module Api
|
|||
render_unauthorized_response if current_user && (summon.party.user != current_user)
|
||||
|
||||
summon.uncap_level = summon_params[:uncap_level]
|
||||
summon.transcendence_step = 0
|
||||
|
||||
return unless summon.save!
|
||||
|
||||
render json: GridSummonBlueprint.render(summon, view: :nested, root: :grid_summon)
|
||||
end
|
||||
|
||||
# TODO: Implement removing summons
|
||||
def destroy; end
|
||||
def destroy
|
||||
render_unauthorized_response if @summon.party.user != current_user
|
||||
return render json: GridSummonBlueprint.render(@summon, view: :destroyed) if @summon.destroy
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_incoming_summon
|
||||
@incoming_summon = Summon.find_by(id: summon_params[:summon_id])
|
||||
end
|
||||
|
||||
def find_party
|
||||
# BUG: I can create grid weapons even when I'm not logged in on an authenticated party
|
||||
@party = Party.find(summon_params[:party_id])
|
||||
render_unauthorized_response if current_user && (party.user != current_user)
|
||||
end
|
||||
|
||||
def render_grid_summon_view(grid_summon, conflict_position = nil)
|
||||
GridSummonBlueprint.render(grid_summon, view: :nested,
|
||||
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.where('id = ?', params[:id]).first
|
||||
end
|
||||
|
||||
# Specify whitelisted properties that can be modified.
|
||||
def summon_params
|
||||
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)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@
|
|||
module Api
|
||||
module V1
|
||||
class GridWeaponsController < Api::V1::ApiController
|
||||
before_action :set, except: %w[create update_uncap_level destroy]
|
||||
|
||||
attr_reader :party, :incoming_weapon
|
||||
|
||||
before_action :set, except: %w[create update_uncap_level]
|
||||
before_action :find_party, only: :create
|
||||
before_action :find_incoming_weapon, only: :create
|
||||
before_action :authorize, only: %i[create update destroy]
|
||||
|
||||
def create
|
||||
# Create the GridWeapon with the desired parameters
|
||||
|
|
@ -40,7 +40,11 @@ module Api
|
|||
|
||||
weapon = GridWeapon.create!(party_id: party.id, weapon_id: incoming.id,
|
||||
position: resolve_params[:position], uncap_level: uncap_level)
|
||||
render json: GridWeaponBlueprint.render(weapon, view: :nested), status: :created if weapon.save!
|
||||
|
||||
if weapon.save
|
||||
view = render_grid_weapon_view(weapon, resolve_params[:position])
|
||||
render json: view, status: :created
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
|
|
@ -55,8 +59,10 @@ module Api
|
|||
render json: GridWeaponBlueprint.render(@weapon, view: :nested) if @weapon.update(weapon_params)
|
||||
end
|
||||
|
||||
# TODO: Implement removing characters
|
||||
def destroy; end
|
||||
def destroy
|
||||
render_unauthorized_response if @weapon.party.user != current_user
|
||||
return render json: GridCharacterBlueprint.render(@weapon, view: :destroyed) if @weapon.destroy
|
||||
end
|
||||
|
||||
def update_uncap_level
|
||||
weapon = GridWeapon.find(weapon_params[:id])
|
||||
|
|
@ -177,6 +183,15 @@ module Api
|
|||
@weapon = GridWeapon.where('id = ?', params[:id]).first
|
||||
end
|
||||
|
||||
def authorize
|
||||
# Create
|
||||
ap @party
|
||||
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.
|
||||
def weapon_params
|
||||
params.require(:weapon).permit(
|
||||
|
|
|
|||
12
app/controllers/api/v1/job_accessories_controller.rb
Normal file
12
app/controllers/api/v1/job_accessories_controller.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V1
|
||||
class JobAccessoriesController < Api::V1::ApiController
|
||||
def job
|
||||
accessories = JobAccessory.where('job_id = ?', params[:id])
|
||||
render json: JobAccessoryBlueprint.render(accessories)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -4,6 +4,7 @@ module Api
|
|||
module V1
|
||||
class JobsController < Api::V1::ApiController
|
||||
before_action :set, only: %w[update_job update_job_skills]
|
||||
before_action :authorize, only: %w[update_job update_job_skills]
|
||||
|
||||
def all
|
||||
render json: JobBlueprint.render(Job.all)
|
||||
|
|
@ -63,8 +64,7 @@ module Api
|
|||
new_skill_ids = new_skill_keys.map { |key| job_params[key] }
|
||||
new_skill_ids.map do |id|
|
||||
skill = JobSkill.find(id)
|
||||
raise Api::V1::IncompatibleSkillError.new(job: @party.job, skill: skill) if mismatched_skill(@party.job,
|
||||
skill)
|
||||
raise Api::V1::IncompatibleSkillError.new(job: @party.job, skill: skill) if mismatched_skill(@party.job, skill)
|
||||
end
|
||||
|
||||
positions = extract_positions_from_keys(new_skill_keys)
|
||||
|
|
@ -154,7 +154,11 @@ module Api
|
|||
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)
|
||||
true if mismatched_emp || mismatched_base || mismatched_main
|
||||
if skill.base && !mismatched_base
|
||||
false
|
||||
else
|
||||
true if mismatched_emp || mismatched_main
|
||||
end
|
||||
elsif mismatched_emp || mismatched_main
|
||||
true
|
||||
else
|
||||
|
|
@ -162,6 +166,10 @@ module Api
|
|||
end
|
||||
end
|
||||
|
||||
def authorize
|
||||
render_unauthorized_response if @party.user != current_user || @party.edit_key != edit_key
|
||||
end
|
||||
|
||||
def set
|
||||
@party = Party.where('id = ?', params[:id]).first
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,14 +6,12 @@ module Api
|
|||
before_action :set_from_slug,
|
||||
except: %w[create destroy update index favorites]
|
||||
before_action :set, only: %w[update destroy]
|
||||
before_action :authorize, only: %w[update destroy]
|
||||
|
||||
def create
|
||||
party = Party.new(shortcode: random_string)
|
||||
party = Party.new
|
||||
party.user = current_user if current_user
|
||||
|
||||
if party_params
|
||||
party.attributes = party_params
|
||||
end
|
||||
party.attributes = party_params if party_params
|
||||
|
||||
# unless party_params.empty?
|
||||
# party.attributes = party_params
|
||||
|
|
@ -29,7 +27,7 @@ module Api
|
|||
# end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
|
|
@ -43,20 +41,37 @@ module Api
|
|||
end
|
||||
|
||||
def update
|
||||
render_unauthorized_response if @party.user != current_user
|
||||
|
||||
@party.attributes = party_params.except(:skill1_id, :skill2_id, :skill3_id)
|
||||
|
||||
# TODO: Validate accessory with job
|
||||
|
||||
return render json: PartyBlueprint.render(@party, view: :full, root: :party) if @party.save!
|
||||
|
||||
render_validation_error_response(@party)
|
||||
end
|
||||
|
||||
def destroy
|
||||
render_unauthorized_response if @party.user != current_user
|
||||
return render json: PartyBlueprint.render(@party, view: :destroyed, root: :checkin) if @party.destroy
|
||||
end
|
||||
|
||||
def remix
|
||||
new_party = @party.amoeba_dup
|
||||
new_party.attributes = {
|
||||
user: current_user,
|
||||
name: remixed_name(@party.name),
|
||||
source_party: @party
|
||||
}
|
||||
|
||||
new_party.local_id = party_params[:local_id] if !party_params.nil?
|
||||
|
||||
if new_party.save
|
||||
render json: PartyBlueprint.render(new_party, view: :full, root: :party,
|
||||
meta: { remix: true })
|
||||
else
|
||||
render_validation_error_response(new_party)
|
||||
end
|
||||
end
|
||||
|
||||
def index
|
||||
conditions = build_conditions(request.params)
|
||||
|
||||
|
|
@ -108,6 +123,10 @@ module Api
|
|||
|
||||
private
|
||||
|
||||
def authorize
|
||||
render_unauthorized_response if @party.user != current_user || @party.edit_key != edit_key
|
||||
end
|
||||
|
||||
def build_conditions(params)
|
||||
unless params['recency'].blank?
|
||||
start_time = (DateTime.current - params['recency'].to_i.seconds)
|
||||
|
|
@ -122,15 +141,31 @@ module Api
|
|||
end
|
||||
end
|
||||
|
||||
def random_string
|
||||
num_chars = 6
|
||||
o = [('a'..'z'), ('A'..'Z'), (0..9)].map(&:to_a).flatten
|
||||
(0...num_chars).map { o[rand(o.length)] }.join
|
||||
def remixed_name(name)
|
||||
blanked_name = {
|
||||
en: name.blank? ? 'Untitled team' : name,
|
||||
ja: name.blank? ? '無名の編成' : name
|
||||
}
|
||||
|
||||
if current_user
|
||||
case current_user.language
|
||||
when 'en'
|
||||
"Remix of #{blanked_name[:en]}"
|
||||
when 'ja'
|
||||
"#{blanked_name[:ja]}のリミックス"
|
||||
end
|
||||
else
|
||||
"Remix of #{blanked_name[:en]}"
|
||||
end
|
||||
end
|
||||
|
||||
def set_from_slug
|
||||
@party = Party.where('shortcode = ?', params[:id]).first
|
||||
if @party
|
||||
@party.favorited = current_user && @party ? @party.is_favorited(current_user) : false
|
||||
else
|
||||
render_not_found_response('party')
|
||||
end
|
||||
end
|
||||
|
||||
def set
|
||||
|
|
@ -138,13 +173,18 @@ module Api
|
|||
end
|
||||
|
||||
def party_params
|
||||
return unless params[:party].present?
|
||||
|
||||
params.require(:party).permit(
|
||||
:user_id,
|
||||
:local_id,
|
||||
:edit_key,
|
||||
:extra,
|
||||
:name,
|
||||
:description,
|
||||
:raid_id,
|
||||
:job_id,
|
||||
:accessory_id,
|
||||
:skill0_id,
|
||||
:skill1_id,
|
||||
:skill2_id,
|
||||
|
|
@ -156,7 +196,7 @@ module Api
|
|||
:button_count,
|
||||
:turn_count,
|
||||
:chain_count
|
||||
) if params[:party].present?
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
19
app/controllers/api/v1/summons_controller.rb
Normal file
19
app/controllers/api/v1/summons_controller.rb
Normal 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
|
||||
|
|
@ -40,7 +40,9 @@ module Api
|
|||
end
|
||||
|
||||
def show
|
||||
render_not_found_response('user') unless @user
|
||||
if @user.nil?
|
||||
render_not_found_response('user')
|
||||
else
|
||||
|
||||
conditions = build_conditions(request.params)
|
||||
conditions[:user_id] = @user.id
|
||||
|
|
@ -65,6 +67,7 @@ module Api
|
|||
per_page: COLLECTION_PER_PAGE
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
def check_email
|
||||
render json: EmptyBlueprint.render_as_json(nil, email: params[:email], availability: true)
|
||||
|
|
|
|||
19
app/controllers/api/v1/weapons_controller.rb
Normal file
19
app/controllers/api/v1/weapons_controller.rb
Normal 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
|
||||
5
app/models/app_update.rb
Normal file
5
app/models/app_update.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AppUpdate < ApplicationRecord
|
||||
|
||||
end
|
||||
|
|
@ -1,7 +1,78 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class GridCharacter < ApplicationRecord
|
||||
belongs_to :party
|
||||
belongs_to :party,
|
||||
counter_cache: :characters_count,
|
||||
inverse_of: :characters
|
||||
validates_presence_of :party
|
||||
|
||||
validate :awakening_level, on: :update
|
||||
validate :transcendence, on: :update
|
||||
validate :validate_over_mastery_values, on: :update
|
||||
validate :validate_aetherial_mastery_value, on: :update
|
||||
validate :over_mastery_attack_matches_hp, on: :update
|
||||
|
||||
##### Amoeba configuration
|
||||
amoeba do
|
||||
set ring1: { modifier: nil, strength: nil }
|
||||
set ring2: { modifier: nil, strength: nil }
|
||||
set ring3: { modifier: nil, strength: nil }
|
||||
set ring4: { modifier: nil, strength: nil }
|
||||
set earring: { modifier: nil, strength: nil }
|
||||
set perpetuity: false
|
||||
end
|
||||
|
||||
def awakening_level
|
||||
return if awakening.nil?
|
||||
|
||||
errors.add(:awakening, 'awakening level too low') if awakening['level'] < 1
|
||||
errors.add(:awakening, 'awakening level too high') if awakening['level'] > 9
|
||||
end
|
||||
|
||||
def transcendence
|
||||
errors.add(:transcendence_step, 'character has no transcendence') if transcendence_step.positive? && !character.ulb
|
||||
errors.add(:transcendence_step, 'transcendence step too high') if transcendence_step > 5 && character.ulb
|
||||
errors.add(:transcendence_step, 'transcendence step too low') if transcendence_step.negative? && character.ulb
|
||||
end
|
||||
|
||||
def over_mastery_attack
|
||||
errors.add(:ring1, 'invalid value') unless ring1['modifier'].nil? || atk_values.include?(ring1['strength'])
|
||||
end
|
||||
|
||||
def over_mastery_hp
|
||||
return if ring2['modifier'].nil?
|
||||
|
||||
errors.add(:ring2, 'invalid value') unless hp_values.include?(ring2['strength'])
|
||||
end
|
||||
|
||||
def over_mastery_attack_matches_hp
|
||||
return if ring1[:modifier].nil? && ring2[:modifier].nil?
|
||||
|
||||
return if ring2[:strength] == (ring1[:strength] / 2)
|
||||
|
||||
errors.add(:over_mastery,
|
||||
'over mastery attack and hp values do not match')
|
||||
end
|
||||
|
||||
def validate_over_mastery_values
|
||||
[ring1, ring2, ring3, ring4].each_with_index do |ring, index|
|
||||
next if ring['modifier'].nil?
|
||||
|
||||
modifier = over_mastery_modifiers[ring['modifier']]
|
||||
check_value({ "ring#{index}": { ring[modifier] => ring['strength'] } },
|
||||
'over_mastery')
|
||||
end
|
||||
end
|
||||
|
||||
def validate_aetherial_mastery_value
|
||||
return if earring['modifier'].nil?
|
||||
|
||||
return unless earring['modifier'].positive?
|
||||
|
||||
modifier = aetherial_mastery_modifiers[earring['modifier']].to_sym
|
||||
check_value({ "earring": { modifier => earring['strength'] } },
|
||||
'aetherial_mastery')
|
||||
end
|
||||
|
||||
def character
|
||||
Character.find(character_id)
|
||||
|
|
@ -10,4 +81,132 @@ class GridCharacter < ApplicationRecord
|
|||
def blueprint
|
||||
GridCharacterBlueprint
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_value(property, type)
|
||||
# Input format
|
||||
# { ring1: { atk: 300 } }
|
||||
|
||||
key = property.keys.first
|
||||
modifier = property[key].keys.first
|
||||
|
||||
return if modifier.nil?
|
||||
|
||||
case type
|
||||
when 'over_mastery'
|
||||
errors.add(key, 'invalid value') unless over_mastery_values.include?(key['strength'])
|
||||
when 'aetherial_mastery'
|
||||
errors.add(key, 'value too low') if aetherial_mastery_values[modifier][:min] > self[key]['strength']
|
||||
errors.add(key, 'value too high') if aetherial_mastery_values[modifier][:max] < self[key]['strength']
|
||||
end
|
||||
end
|
||||
|
||||
def over_mastery_modifiers
|
||||
{
|
||||
1 => 'atk',
|
||||
2 => 'hp',
|
||||
3 => 'debuff_success',
|
||||
4 => 'skill_cap',
|
||||
5 => 'ca_dmg',
|
||||
6 => 'ca_cap',
|
||||
7 => 'stamina',
|
||||
8 => 'enmity',
|
||||
9 => 'crit',
|
||||
10 => 'da',
|
||||
11 => 'ta',
|
||||
12 => 'def',
|
||||
13 => 'heal',
|
||||
14 => 'debuff_resist',
|
||||
15 => 'dodge'
|
||||
}
|
||||
end
|
||||
|
||||
def over_mastery_values
|
||||
{
|
||||
atk: [300, 600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000],
|
||||
hp: [150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500],
|
||||
debuff_success: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
skill_cap: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
ca_dmg: [10, 12, 14, 16, 18, 20, 22, 24, 27, 30],
|
||||
ca_cap: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
crit: [10, 12, 14, 16, 18, 20, 22, 24, 27, 30],
|
||||
enmity: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
stamina: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
def: [6, 7, 8, 9, 10, 12, 14, 16, 18, 20],
|
||||
heal: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30],
|
||||
debuff_resist: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
dodge: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
da: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
ta: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
}
|
||||
end
|
||||
|
||||
def aetherial_mastery_modifiers
|
||||
{
|
||||
1 => 'da',
|
||||
2 => 'ta',
|
||||
3 => 'ele_atk',
|
||||
4 => 'ele_resist',
|
||||
5 => 'stamina',
|
||||
6 => 'enmity',
|
||||
7 => 'supplemental',
|
||||
8 => 'crit',
|
||||
9 => 'counter_dodge',
|
||||
10 => 'counter_dmg'
|
||||
}
|
||||
end
|
||||
|
||||
def aetherial_mastery_values
|
||||
{
|
||||
da: {
|
||||
min: 10,
|
||||
max: 17
|
||||
},
|
||||
ta: {
|
||||
min: 5,
|
||||
max: 12
|
||||
},
|
||||
ele_atk: {
|
||||
min: 15,
|
||||
max: 22
|
||||
},
|
||||
ele_resist: {
|
||||
min: 5,
|
||||
max: 12
|
||||
},
|
||||
stamina: {
|
||||
min: 5,
|
||||
max: 12
|
||||
},
|
||||
enmity: {
|
||||
min: 5,
|
||||
max: 12
|
||||
},
|
||||
supplemental: {
|
||||
min: 5,
|
||||
max: 12
|
||||
},
|
||||
crit: {
|
||||
min: 18,
|
||||
max: 35
|
||||
},
|
||||
counter_dodge: {
|
||||
min: 5,
|
||||
max: 12
|
||||
},
|
||||
counter_dmg: {
|
||||
min: 10,
|
||||
max: 17
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def atk_values
|
||||
[300, 600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000]
|
||||
end
|
||||
|
||||
def hp_values
|
||||
[150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class GridSummon < ApplicationRecord
|
||||
belongs_to :party
|
||||
belongs_to :party,
|
||||
counter_cache: :summons_count,
|
||||
inverse_of: :summons
|
||||
validates_presence_of :party
|
||||
|
||||
validate :compatible_with_position, on: :create
|
||||
validate :no_conflicts, on: :create
|
||||
|
||||
def summon
|
||||
Summon.find(summon_id)
|
||||
|
|
@ -10,4 +16,29 @@ class GridSummon < ApplicationRecord
|
|||
def blueprint
|
||||
GridSummonBlueprint
|
||||
end
|
||||
|
||||
# Returns conflicting summons if they exist
|
||||
def conflicts(party)
|
||||
return unless summon.limit
|
||||
|
||||
party.summons.find do |grid_summon|
|
||||
return unless grid_summon.id
|
||||
grid_summon if summon.id == grid_summon.summon.id
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Validates whether there is a conflict with the party
|
||||
def no_conflicts
|
||||
# Check if the grid summon conflicts with any of the other grid summons in the party
|
||||
errors.add(:series, 'must not conflict with existing summons') unless conflicts(party).nil?
|
||||
end
|
||||
|
||||
# Validates whether the summon can be added to the desired position
|
||||
def compatible_with_position
|
||||
return unless [4, 5].include?(position.to_i) && !summon.subaura
|
||||
|
||||
errors.add(:position, 'must have subaura for position')
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
class GridWeapon < ApplicationRecord
|
||||
belongs_to :party,
|
||||
counter_cache: :weapons_count
|
||||
counter_cache: :weapons_count,
|
||||
inverse_of: :weapons
|
||||
validates_presence_of :party
|
||||
|
||||
belongs_to :weapon_key1, class_name: 'WeaponKey', foreign_key: :weapon_key1_id, optional: true
|
||||
belongs_to :weapon_key2, class_name: 'WeaponKey', foreign_key: :weapon_key2_id, optional: true
|
||||
|
|
@ -11,6 +13,16 @@ class GridWeapon < ApplicationRecord
|
|||
validate :compatible_with_position, on: :create
|
||||
validate :no_conflicts, on: :create
|
||||
|
||||
before_save :is_mainhand
|
||||
|
||||
##### Amoeba configuration
|
||||
amoeba do
|
||||
nullify :ax_modifier1
|
||||
nullify :ax_modifier2
|
||||
nullify :ax_strength1
|
||||
nullify :ax_strength2
|
||||
end
|
||||
|
||||
# Helper methods
|
||||
def blueprint
|
||||
GridWeaponBlueprint
|
||||
|
|
@ -29,6 +41,8 @@ class GridWeapon < ApplicationRecord
|
|||
return unless weapon.limit
|
||||
|
||||
party.weapons.find do |party_weapon|
|
||||
return unless party_weapon.id
|
||||
|
||||
id_match = weapon.id == party_weapon.id
|
||||
series_match = weapon.series == party_weapon.weapon.series
|
||||
both_opus_or_draconic = weapon.opus_or_draconic? && party_weapon.weapon.opus_or_draconic?
|
||||
|
|
@ -59,4 +73,13 @@ class GridWeapon < ApplicationRecord
|
|||
# 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?
|
||||
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
|
||||
|
|
|
|||
37
app/models/job_accessory.rb
Normal file
37
app/models/job_accessory.rb
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class JobAccessory < ApplicationRecord
|
||||
include PgSearch::Model
|
||||
|
||||
belongs_to :job
|
||||
|
||||
pg_search_scope :en_search,
|
||||
against: :name_en,
|
||||
using: {
|
||||
tsearch: {
|
||||
prefix: true,
|
||||
dictionary: 'simple'
|
||||
}
|
||||
}
|
||||
|
||||
pg_search_scope :jp_search,
|
||||
against: :name_jp,
|
||||
using: {
|
||||
tsearch: {
|
||||
prefix: true,
|
||||
dictionary: 'simple'
|
||||
}
|
||||
}
|
||||
|
||||
def blueprint
|
||||
JobAccessoryBlueprint
|
||||
end
|
||||
|
||||
def display_resource(skill)
|
||||
skill.name_en
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
self.class == other.class && id == other.id
|
||||
end
|
||||
end
|
||||
|
|
@ -2,10 +2,25 @@
|
|||
|
||||
class Party < ApplicationRecord
|
||||
##### ActiveRecord Associations
|
||||
belongs_to :source_party,
|
||||
class_name: 'Party',
|
||||
foreign_key: :source_party_id,
|
||||
optional: true
|
||||
|
||||
has_many :derivative_parties,
|
||||
class_name: 'Party',
|
||||
foreign_key: :source_party_id,
|
||||
inverse_of: :source_party
|
||||
|
||||
belongs_to :user, optional: true
|
||||
belongs_to :raid, optional: true
|
||||
belongs_to :job, optional: true
|
||||
|
||||
belongs_to :accessory,
|
||||
foreign_key: 'accessory_id',
|
||||
class_name: 'JobAccessory',
|
||||
optional: true
|
||||
|
||||
belongs_to :skill0,
|
||||
foreign_key: 'skill0_id',
|
||||
class_name: 'JobSkill',
|
||||
|
|
@ -29,20 +44,36 @@ class Party < ApplicationRecord
|
|||
has_many :characters,
|
||||
foreign_key: 'party_id',
|
||||
class_name: 'GridCharacter',
|
||||
dependent: :destroy
|
||||
dependent: :destroy,
|
||||
inverse_of: :party
|
||||
|
||||
has_many :weapons,
|
||||
foreign_key: 'party_id',
|
||||
class_name: 'GridWeapon',
|
||||
dependent: :destroy
|
||||
dependent: :destroy,
|
||||
inverse_of: :party
|
||||
|
||||
has_many :summons,
|
||||
foreign_key: 'party_id',
|
||||
class_name: 'GridSummon',
|
||||
dependent: :destroy
|
||||
dependent: :destroy,
|
||||
inverse_of: :party
|
||||
|
||||
has_many :favorites
|
||||
|
||||
before_create :set_shortcode
|
||||
before_create :set_edit_key
|
||||
|
||||
##### Amoeba configuration
|
||||
amoeba do
|
||||
nullify :description
|
||||
nullify :shortcode
|
||||
|
||||
include_association :characters
|
||||
include_association :weapons
|
||||
include_association :summons
|
||||
end
|
||||
|
||||
##### ActiveRecord Validations
|
||||
validate :skills_are_unique
|
||||
|
||||
|
|
@ -52,12 +83,36 @@ class Party < ApplicationRecord
|
|||
user.favorite_parties.include? self
|
||||
end
|
||||
|
||||
def is_remix
|
||||
self.source_party != nil
|
||||
end
|
||||
|
||||
def remixes
|
||||
Party.where(source_party_id: self.id)
|
||||
end
|
||||
|
||||
def blueprint
|
||||
PartyBlueprint
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_shortcode
|
||||
self.shortcode = random_string
|
||||
end
|
||||
|
||||
def set_edit_key
|
||||
if !self.user
|
||||
self.edit_key = Digest::SHA1.hexdigest([Time.now, rand].join)
|
||||
end
|
||||
end
|
||||
|
||||
def random_string
|
||||
num_chars = 6
|
||||
o = [('a'..'z'), ('A'..'Z'), (0..9)].map(&:to_a).flatten
|
||||
(0...num_chars).map { o[rand(o.length)] }.join
|
||||
end
|
||||
|
||||
def skills_are_unique
|
||||
skills = [skill0, skill1, skill2, skill3].compact
|
||||
|
||||
|
|
|
|||
11
bin/rails
11
bin/rails
|
|
@ -1,9 +1,4 @@
|
|||
#!/usr/bin/env ruby
|
||||
begin
|
||||
load File.expand_path('../spring', __FILE__)
|
||||
rescue LoadError => e
|
||||
raise unless e.message.include?('spring')
|
||||
end
|
||||
APP_PATH = File.expand_path('../config/application', __dir__)
|
||||
require_relative '../config/boot'
|
||||
require 'rails/commands'
|
||||
APP_PATH = File.expand_path("../config/application", __dir__)
|
||||
require_relative "../config/boot"
|
||||
require "rails/commands"
|
||||
|
|
|
|||
9
bin/rake
9
bin/rake
|
|
@ -1,9 +1,4 @@
|
|||
#!/usr/bin/env ruby
|
||||
begin
|
||||
load File.expand_path('../spring', __FILE__)
|
||||
rescue LoadError => e
|
||||
raise unless e.message.include?('spring')
|
||||
end
|
||||
require_relative '../config/boot'
|
||||
require 'rake'
|
||||
require_relative "../config/boot"
|
||||
require "rake"
|
||||
Rake.application.run
|
||||
|
|
|
|||
24
bin/setup
24
bin/setup
|
|
@ -1,33 +1,33 @@
|
|||
#!/usr/bin/env ruby
|
||||
require 'fileutils'
|
||||
require "fileutils"
|
||||
|
||||
# path to your application root.
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
APP_ROOT = File.expand_path("..", __dir__)
|
||||
|
||||
def system!(*args)
|
||||
system(*args) || abort("\n== Command #{args} failed ==")
|
||||
end
|
||||
|
||||
FileUtils.chdir APP_ROOT do
|
||||
# This script is a way to setup or update your development environment automatically.
|
||||
# This script is idempotent, so that you can run it at anytime and get an expectable outcome.
|
||||
# This script is a way to set up or update your development environment automatically.
|
||||
# This script is idempotent, so that you can run it at any time and get an expectable outcome.
|
||||
# Add necessary setup steps to this file.
|
||||
|
||||
puts '== Installing dependencies =='
|
||||
system! 'gem install bundler --conservative'
|
||||
system('bundle check') || system!('bundle install')
|
||||
puts "== Installing dependencies =="
|
||||
system! "gem install bundler --conservative"
|
||||
system("bundle check") || system!("bundle install")
|
||||
|
||||
# puts "\n== Copying sample files =="
|
||||
# unless File.exist?('config/database.yml')
|
||||
# FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
|
||||
# unless File.exist?("config/database.yml")
|
||||
# FileUtils.cp "config/database.yml.sample", "config/database.yml"
|
||||
# end
|
||||
|
||||
puts "\n== Preparing database =="
|
||||
system! 'bin/rails db:prepare'
|
||||
system! "bin/rails db:prepare"
|
||||
|
||||
puts "\n== Removing old logs and tempfiles =="
|
||||
system! 'bin/rails log:clear tmp:clear'
|
||||
system! "bin/rails log:clear tmp:clear"
|
||||
|
||||
puts "\n== Restarting application server =="
|
||||
system! 'bin/rails restart'
|
||||
system! "bin/rails restart"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
require_relative 'boot'
|
||||
require_relative "boot"
|
||||
|
||||
require "rails"
|
||||
# Pick the frameworks you want:
|
||||
|
|
@ -7,10 +7,11 @@ require "active_job/railtie"
|
|||
require "active_record/railtie"
|
||||
require "active_storage/engine"
|
||||
require "action_controller/railtie"
|
||||
# require "action_mailer/railtie"
|
||||
# require "action_mailbox/engine"
|
||||
require "action_text/engine"
|
||||
require "action_view/railtie"
|
||||
require "action_cable/engine"
|
||||
# require "sprockets/railtie"
|
||||
require "rails/test_unit/railtie"
|
||||
|
||||
# Require the gems listed in Gemfile, including any gems
|
||||
|
|
@ -22,10 +23,13 @@ module HenseiApi
|
|||
# Initialize configuration defaults for originally generated Rails version.
|
||||
config.load_defaults 7.0
|
||||
|
||||
# Settings in config/environments/* take precedence over those specified here.
|
||||
# Application configuration can go into files in config/initializers
|
||||
# -- all .rb files in that directory are automatically loaded after loading
|
||||
# the framework and any gems in your application.
|
||||
# Configuration for the application, engines, and railties goes here.
|
||||
#
|
||||
# These settings can be overridden in specific environments using the files
|
||||
# in config/environments, which are processed later.
|
||||
#
|
||||
# config.time_zone = "Central Time (US & Canada)"
|
||||
# config.eager_load_paths << Rails.root.join("extras")
|
||||
|
||||
# Only loads a smaller set of middleware suitable for API only apps.
|
||||
# Middleware like session, flash, cookies can be added back manually.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
||||
|
||||
require 'bundler/setup' # Set up gems listed in the Gemfile.
|
||||
require 'bootsnap/setup' # Speed up boot time by caching expensive operations.
|
||||
require "bundler/setup" # Set up gems listed in the Gemfile.
|
||||
require "bootsnap/setup" # Speed up boot time by caching expensive operations.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Load the Rails application.
|
||||
require_relative 'application'
|
||||
require_relative "application"
|
||||
|
||||
# Initialize the Rails application.
|
||||
Rails.application.initialize!
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
require "active_support/core_ext/integer/time"
|
||||
|
||||
Rails.application.configure do
|
||||
config.after_initialize do
|
||||
ActiveRecord::Base.logger = Rails.logger.clone
|
||||
ActiveRecord::Base.logger.level = Logger::INFO
|
||||
end
|
||||
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
config.hosts << "grid-api.ngrok.io"
|
||||
config.hosts << "staging-api.granblue.team"
|
||||
|
||||
# In the development environment your application's code is reloaded on
|
||||
# every request. This slows down response time but is perfect for development
|
||||
# In the development environment your application's code is reloaded any time
|
||||
# it changes. This slows down response time but is perfect for development
|
||||
# since you don't have to restart the web server when you make code changes.
|
||||
config.cache_classes = false
|
||||
|
||||
|
|
@ -18,12 +15,15 @@ Rails.application.configure do
|
|||
# Show full error reports.
|
||||
config.consider_all_requests_local = true
|
||||
|
||||
# Enable server timing
|
||||
config.server_timing = true
|
||||
|
||||
# Enable/disable caching. By default caching is disabled.
|
||||
# Run rails dev:cache to toggle caching.
|
||||
if Rails.root.join('tmp', 'caching-dev.txt').exist?
|
||||
if Rails.root.join("tmp/caching-dev.txt").exist?
|
||||
config.cache_store = :memory_store
|
||||
config.public_file_server.headers = {
|
||||
'Cache-Control' => "public, max-age=#{2.days.to_i}"
|
||||
"Cache-Control" => "public, max-age=#{2.days.to_i}"
|
||||
}
|
||||
else
|
||||
config.action_controller.perform_caching = false
|
||||
|
|
@ -31,30 +31,30 @@ Rails.application.configure do
|
|||
config.cache_store = :null_store
|
||||
end
|
||||
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
|
||||
# Store uploaded files on the local file system (see config/storage.yml for options).
|
||||
config.active_storage.service = :local
|
||||
|
||||
# Don't care if the mailer can't send.
|
||||
# config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
# config.action_mailer.perform_caching = false
|
||||
|
||||
# Print deprecation notices to the Rails logger.
|
||||
config.active_support.deprecation = :log
|
||||
|
||||
# Raise exceptions for disallowed deprecations.
|
||||
config.active_support.disallowed_deprecation = :raise
|
||||
|
||||
# Tell Active Support which deprecation messages to disallow.
|
||||
config.active_support.disallowed_deprecation_warnings = []
|
||||
|
||||
# Raise an error on page load if there are pending migrations.
|
||||
config.active_record.migration_error = :page_load
|
||||
|
||||
# Highlight code that triggered database queries in logs.
|
||||
config.active_record.verbose_query_logs = true
|
||||
|
||||
|
||||
# Raises error for missing translations.
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
# config.i18n.raise_on_missing_translations = true
|
||||
|
||||
# Use an evented file watcher to asynchronously detect changes in source code,
|
||||
# routes, locales, etc. This feature depends on the listen gem.
|
||||
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
|
||||
# Annotate rendered view with file names.
|
||||
# config.action_view.annotate_rendered_view_with_filenames = true
|
||||
|
||||
# Uncomment if you wish to allow Action Cable access from any origin.
|
||||
# config.action_cable.disable_request_forgery_protection = true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
require "active_support/core_ext/integer/time"
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
|
|
@ -13,40 +15,38 @@ Rails.application.configure do
|
|||
# Full error reports are disabled and caching is turned on.
|
||||
config.consider_all_requests_local = false
|
||||
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
|
||||
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
|
||||
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
|
||||
# config.require_master_key = true
|
||||
|
||||
# Disable serving static files from the `/public` folder by default since
|
||||
# Apache or NGINX already handles this.
|
||||
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
|
||||
config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
|
||||
# config.action_controller.asset_host = 'http://assets.example.com'
|
||||
# config.asset_host = "http://assets.example.com"
|
||||
|
||||
# Specifies the header that your server uses for sending files.
|
||||
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
|
||||
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
|
||||
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
|
||||
# config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX
|
||||
|
||||
# Store uploaded files on the local file system (see config/storage.yml for options).
|
||||
config.active_storage.service = :local
|
||||
|
||||
# Mount Action Cable outside main process or domain.
|
||||
# config.action_cable.mount_path = nil
|
||||
# config.action_cable.url = 'wss://example.com/cable'
|
||||
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
|
||||
# config.action_cable.url = "wss://example.com/cable"
|
||||
# config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]
|
||||
|
||||
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
||||
# config.force_ssl = true
|
||||
|
||||
# Use the lowest log level to ensure availability of diagnostic information
|
||||
# when problems arise.
|
||||
config.log_level = :debug
|
||||
# Include generic and useful information about system operation, but avoid logging too much
|
||||
# information to avoid inadvertent exposure of personally identifiable information (PII).
|
||||
config.log_level = :info
|
||||
|
||||
# Prepend all log lines with the following tags.
|
||||
config.log_tags = [ :request_id ]
|
||||
config.log_tags = [:request_id]
|
||||
|
||||
# Use a different cache store in production.
|
||||
# config.cache_store = :mem_cache_store
|
||||
|
|
@ -55,25 +55,19 @@ Rails.application.configure do
|
|||
# config.active_job.queue_adapter = :resque
|
||||
# config.active_job.queue_name_prefix = "hensei_api_production"
|
||||
|
||||
# config.action_mailer.perform_caching = false
|
||||
|
||||
# Ignore bad email addresses and do not raise email delivery errors.
|
||||
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||
# config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Send deprecation notices to registered listeners.
|
||||
config.active_support.deprecation = :notify
|
||||
# Don't log any deprecations.
|
||||
config.active_support.report_deprecations = false
|
||||
|
||||
# Use default logging formatter so that PID and timestamp are not suppressed.
|
||||
config.log_formatter = ::Logger::Formatter.new
|
||||
|
||||
# Use a different logger for distributed setups.
|
||||
# require 'syslog/logger'
|
||||
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
|
||||
# require "syslog/logger"
|
||||
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")
|
||||
|
||||
if ENV["RAILS_LOG_TO_STDOUT"].present?
|
||||
logger = ActiveSupport::Logger.new(STDOUT)
|
||||
|
|
@ -83,25 +77,4 @@ Rails.application.configure do
|
|||
|
||||
# Do not dump schema after migrations.
|
||||
config.active_record.dump_schema_after_migration = false
|
||||
|
||||
# Inserts middleware to perform automatic connection switching.
|
||||
# The `database_selector` hash is used to pass options to the DatabaseSelector
|
||||
# middleware. The `delay` is used to determine how long to wait after a write
|
||||
# to send a subsequent read to the primary.
|
||||
#
|
||||
# The `database_resolver` class is used by the middleware to determine which
|
||||
# database is appropriate to use based on the time delay.
|
||||
#
|
||||
# The `database_resolver_context` class is used by the middleware to set
|
||||
# timestamps for the last write to the primary. The resolver uses the context
|
||||
# class timestamps to determine how long to wait before reading from the
|
||||
# replica.
|
||||
#
|
||||
# By default Rails will store a last write timestamp in the session. The
|
||||
# DatabaseSelector middleware is designed as such you can define your own
|
||||
# strategy for connection switching and pass that into the middleware through
|
||||
# these configuration options.
|
||||
# config.active_record.database_selector = { delay: 2.seconds }
|
||||
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
|
||||
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
require "active_support/core_ext/integer/time"
|
||||
|
||||
# The test environment is used exclusively to run your application's
|
||||
# test suite. You never need to work with it otherwise. Remember that
|
||||
# your test database is "scratch space" for the test suite and is wiped
|
||||
|
|
@ -6,18 +8,18 @@
|
|||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
config.cache_classes = false
|
||||
config.action_view.cache_template_loading = true
|
||||
# Turn false under Spring and add config.action_view.cache_template_loading = true.
|
||||
config.cache_classes = true
|
||||
|
||||
# Do not eager load code on boot. This avoids loading your whole application
|
||||
# just for the purpose of running a single test. If you are using a tool that
|
||||
# preloads Rails for running tests, you may have to set it to true.
|
||||
config.eager_load = false
|
||||
# Eager loading loads your whole application. When running a single test locally,
|
||||
# this probably isn't necessary. It's a good idea to do in a continuous integration
|
||||
# system, or in some way before deploying your code.
|
||||
config.eager_load = ENV["CI"].present?
|
||||
|
||||
# Configure public file server for tests with Cache-Control for performance.
|
||||
config.public_file_server.enabled = true
|
||||
config.public_file_server.headers = {
|
||||
'Cache-Control' => "public, max-age=#{1.hour.to_i}"
|
||||
"Cache-Control" => "public, max-age=#{1.hour.to_i}"
|
||||
}
|
||||
|
||||
# Show full error reports and disable caching.
|
||||
|
|
@ -34,16 +36,18 @@ Rails.application.configure do
|
|||
# Store uploaded files on the local file system in a temporary directory.
|
||||
config.active_storage.service = :test
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# Tell Action Mailer not to deliver emails to the real world.
|
||||
# The :test delivery method accumulates sent emails in the
|
||||
# ActionMailer::Base.deliveries array.
|
||||
config.action_mailer.delivery_method = :test
|
||||
|
||||
# Print deprecation notices to the stderr.
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
# Raise exceptions for disallowed deprecations.
|
||||
config.active_support.disallowed_deprecation = :raise
|
||||
|
||||
# Tell Active Support which deprecation messages to disallow.
|
||||
config.active_support.disallowed_deprecation_warnings = []
|
||||
|
||||
# Raises error for missing translations.
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
# config.i18n.raise_on_missing_translations = true
|
||||
|
||||
# Annotate rendered view with file names.
|
||||
# config.action_view.annotate_rendered_view_with_filenames = true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ Rails.application.config.middleware.insert_before 0, Rack::Cors do
|
|||
if Rails.env.production?
|
||||
origins %w[app.granblue.team hensei-web-production.up.railway.app]
|
||||
else
|
||||
origins %w[127.0.0.1:1234 grid.ngrok.io]
|
||||
origins %w[staging.granblue.team 127.0.0.1:1234]
|
||||
end
|
||||
|
||||
resource '*',
|
||||
resource "*",
|
||||
headers: :any,
|
||||
methods: %i[get post put patch delete options head]
|
||||
methods: [:get, :post, :put, :patch, :delete, :options, :head]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Configure sensitive parameters which will be filtered from the log file.
|
||||
Rails.application.config.filter_parameters += [:password]
|
||||
# Configure parameters to be filtered from the log file. Use this to limit dissemination of
|
||||
# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
|
||||
# notations and behaviors.
|
||||
Rails.application.config.filter_parameters += [
|
||||
:passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
|
||||
]
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
# are locale specific, and you may define rules for as many different
|
||||
# locales as you wish. All of these examples are active by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.plural /^(ox)$/i, '\1en'
|
||||
# inflect.singular /^(ox)en/i, '\1'
|
||||
# inflect.irregular 'person', 'people'
|
||||
# inflect.plural /^(ox)$/i, "\\1en"
|
||||
# inflect.singular /^(ox)en/i, "\\1"
|
||||
# inflect.irregular "person", "people"
|
||||
# inflect.uncountable %w( fish sheep )
|
||||
# end
|
||||
|
||||
# These inflection rules are supported but not enabled by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.acronym 'RESTful'
|
||||
# inflect.acronym "RESTful"
|
||||
# end
|
||||
|
|
|
|||
135
config/initializers/new_framework_defaults_7_0.rb
Normal file
135
config/initializers/new_framework_defaults_7_0.rb
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
#
|
||||
# This file eases your Rails 7.0 framework defaults upgrade.
|
||||
#
|
||||
# Uncomment each configuration one by one to switch to the new default.
|
||||
# Once your application is ready to run with all new defaults, you can remove
|
||||
# this file and set the `config.load_defaults` to `7.0`.
|
||||
#
|
||||
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
|
||||
# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
|
||||
|
||||
# `button_to` view helper will render `<button>` element, regardless of whether
|
||||
# or not the content is passed as the first argument or as a block.
|
||||
# Rails.application.config.action_view.button_to_generates_button_tag = true
|
||||
|
||||
# `stylesheet_link_tag` view helper will not render the media attribute by default.
|
||||
# Rails.application.config.action_view.apply_stylesheet_media_default = false
|
||||
|
||||
# Change the digest class for the key generators to `OpenSSL::Digest::SHA256`.
|
||||
# Changing this default means invalidate all encrypted messages generated by
|
||||
# your application and, all the encrypted cookies. Only change this after you
|
||||
# rotated all the messages using the key rotator.
|
||||
#
|
||||
# See upgrading guide for more information on how to build a rotator.
|
||||
# https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html
|
||||
# Rails.application.config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256
|
||||
|
||||
# Change the digest class for ActiveSupport::Digest.
|
||||
# Changing this default means that for example Etags change and
|
||||
# various cache keys leading to cache invalidation.
|
||||
# Rails.application.config.active_support.hash_digest_class = OpenSSL::Digest::SHA256
|
||||
|
||||
# Don't override ActiveSupport::TimeWithZone.name and use the default Ruby
|
||||
# implementation.
|
||||
# Rails.application.config.active_support.remove_deprecated_time_with_zone_name = true
|
||||
|
||||
# Calls `Rails.application.executor.wrap` around test cases.
|
||||
# This makes test cases behave closer to an actual request or job.
|
||||
# Several features that are normally disabled in test, such as Active Record query cache
|
||||
# and asynchronous queries will then be enabled.
|
||||
# Rails.application.config.active_support.executor_around_test_case = true
|
||||
|
||||
# Define the isolation level of most of Rails internal state.
|
||||
# If you use a fiber based server or job processor, you should set it to `:fiber`.
|
||||
# Otherwise the default of `:thread` if preferable.
|
||||
# Rails.application.config.active_support.isolation_level = :thread
|
||||
|
||||
# Set both the `:open_timeout` and `:read_timeout` values for `:smtp` delivery method.
|
||||
# Rails.application.config.action_mailer.smtp_timeout = 5
|
||||
|
||||
# The ActiveStorage video previewer will now use scene change detection to generate
|
||||
# better preview images (rather than the previous default of using the first frame
|
||||
# of the video).
|
||||
# Rails.application.config.active_storage.video_preview_arguments =
|
||||
# "-vf 'select=eq(n\\,0)+eq(key\\,1)+gt(scene\\,0.015),loop=loop=-1:size=2,trim=start_frame=1' -frames:v 1 -f image2"
|
||||
|
||||
# Automatically infer `inverse_of` for associations with a scope.
|
||||
# Rails.application.config.active_record.automatic_scope_inversing = true
|
||||
|
||||
# Raise when running tests if fixtures contained foreign key violations
|
||||
# Rails.application.config.active_record.verify_foreign_keys_for_fixtures = true
|
||||
|
||||
# Disable partial inserts.
|
||||
# This default means that all columns will be referenced in INSERT queries
|
||||
# regardless of whether they have a default or not.
|
||||
# Rails.application.config.active_record.partial_inserts = false
|
||||
|
||||
# Protect from open redirect attacks in `redirect_back_or_to` and `redirect_to`.
|
||||
# Rails.application.config.action_controller.raise_on_open_redirects = true
|
||||
|
||||
# Change the variant processor for Active Storage.
|
||||
# Changing this default means updating all places in your code that
|
||||
# generate variants to use image processing macros and ruby-vips
|
||||
# operations. See the upgrading guide for detail on the changes required.
|
||||
# The `:mini_magick` option is not deprecated; it's fine to keep using it.
|
||||
# Rails.application.config.active_storage.variant_processor = :vips
|
||||
|
||||
# Enable parameter wrapping for JSON.
|
||||
# Previously this was set in an initializer. It's fine to keep using that initializer if you've customized it.
|
||||
# To disable parameter wrapping entirely, set this config to `false`.
|
||||
# Rails.application.config.action_controller.wrap_parameters_by_default = true
|
||||
|
||||
# Specifies whether generated namespaced UUIDs follow the RFC 4122 standard for namespace IDs provided as a
|
||||
# `String` to `Digest::UUID.uuid_v3` or `Digest::UUID.uuid_v5` method calls.
|
||||
#
|
||||
# See https://guides.rubyonrails.org/configuring.html#config-active-support-use-rfc4122-namespaced-uuids for
|
||||
# more information.
|
||||
# Rails.application.config.active_support.use_rfc4122_namespaced_uuids = true
|
||||
|
||||
# Change the default headers to disable browsers' flawed legacy XSS protection.
|
||||
# Rails.application.config.action_dispatch.default_headers = {
|
||||
# "X-Frame-Options" => "SAMEORIGIN",
|
||||
# "X-XSS-Protection" => "0",
|
||||
# "X-Content-Type-Options" => "nosniff",
|
||||
# "X-Download-Options" => "noopen",
|
||||
# "X-Permitted-Cross-Domain-Policies" => "none",
|
||||
# "Referrer-Policy" => "strict-origin-when-cross-origin"
|
||||
# }
|
||||
|
||||
|
||||
# ** Please read carefully, this must be configured in config/application.rb **
|
||||
# Change the format of the cache entry.
|
||||
# Changing this default means that all new cache entries added to the cache
|
||||
# will have a different format that is not supported by Rails 6.1 applications.
|
||||
# Only change this value after your application is fully deployed to Rails 7.0
|
||||
# and you have no plans to rollback.
|
||||
# When you're ready to change format, add this to `config/application.rb` (NOT this file):
|
||||
# config.active_support.cache_format_version = 7.0
|
||||
|
||||
|
||||
# Cookie serializer: 2 options
|
||||
#
|
||||
# If you're upgrading and haven't set `cookies_serializer` previously, your cookie serializer
|
||||
# is `:marshal`. The default for new apps is `:json`.
|
||||
#
|
||||
# Rails.application.config.action_dispatch.cookies_serializer = :json
|
||||
#
|
||||
#
|
||||
# To migrate an existing application to the `:json` serializer, use the `:hybrid` option.
|
||||
#
|
||||
# Rails transparently deserializes existing (Marshal-serialized) cookies on read and
|
||||
# re-writes them in the JSON format.
|
||||
#
|
||||
# It is fine to use `:hybrid` long term; you should do that until you're confident *all* your cookies
|
||||
# have been converted to JSON. To keep using `:hybrid` long term, move this config to its own
|
||||
# initializer or to `config/application.rb`.
|
||||
#
|
||||
# Rails.application.config.action_dispatch.cookies_serializer = :hybrid
|
||||
#
|
||||
#
|
||||
# If your cookies can't yet be serialized to JSON, keep using `:marshal` for backward-compatibility.
|
||||
#
|
||||
# If you have configured the serializer elsewhere, you can remove this section of the file.
|
||||
#
|
||||
# See https://guides.rubyonrails.org/action_controller_overview.html#cookies for more information.
|
||||
|
|
@ -8,13 +8,21 @@ Rails.application.routes.draw do
|
|||
namespace :v1 do
|
||||
resources :parties, only: %i[index create update destroy]
|
||||
resources :users, only: %i[create update show]
|
||||
resources :grid_weapons, only: [:update]
|
||||
resources :grid_weapons, only: %i[update destroy]
|
||||
resources :grid_characters, 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]
|
||||
|
||||
get 'version', to: 'api#version'
|
||||
|
||||
get 'users/info/:id', to: 'users#info'
|
||||
|
||||
get 'parties/favorites', to: 'parties#favorites'
|
||||
get 'parties/:id', to: 'parties#show'
|
||||
post 'parties/:id/remix', to: 'parties#remix'
|
||||
|
||||
put 'parties/:id/jobs', to: 'jobs#update_job'
|
||||
put 'parties/:id/job_skills', to: 'jobs#update_job_skills'
|
||||
|
|
@ -31,6 +39,7 @@ Rails.application.routes.draw do
|
|||
|
||||
get 'jobs/skills', to: 'job_skills#all'
|
||||
get 'jobs/:id/skills', to: 'job_skills#job'
|
||||
get 'jobs/:id/accessories', to: 'job_accessories#job'
|
||||
|
||||
get 'raids', to: 'raids#all'
|
||||
get 'weapon_keys', to: 'weapon_keys#all'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
class ChangeAwakeningTypeDefaultValue < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
change_column :grid_characters, :awakening_type, :integer, null: false, default: 1
|
||||
end
|
||||
end
|
||||
22
db/migrate/20230107121520_change_mastery_columns_to_jsonb.rb
Normal file
22
db/migrate/20230107121520_change_mastery_columns_to_jsonb.rb
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
class ChangeMasteryColumnsToJsonb < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
# Remove old columns
|
||||
remove_column :grid_characters, :ring_modifier1, :integer
|
||||
remove_column :grid_characters, :ring_modifier2, :integer
|
||||
remove_column :grid_characters, :ring_modifier3, :integer
|
||||
remove_column :grid_characters, :ring_modifier4, :integer
|
||||
remove_column :grid_characters, :ring_strength1, :integer
|
||||
remove_column :grid_characters, :ring_strength2, :integer
|
||||
remove_column :grid_characters, :ring_strength3, :integer
|
||||
remove_column :grid_characters, :ring_strength4, :integer
|
||||
remove_column :grid_characters, :earring_modifier, :integer
|
||||
remove_column :grid_characters, :earring_strength, :integer
|
||||
|
||||
# Add new columns
|
||||
add_column :grid_characters, :ring1, :jsonb, default: { modifier: nil, strength: nil }
|
||||
add_column :grid_characters, :ring2, :jsonb, default: { modifier: nil, strength: nil }
|
||||
add_column :grid_characters, :ring3, :jsonb, default: { modifier: nil, strength: nil }
|
||||
add_column :grid_characters, :ring4, :jsonb, default: { modifier: nil, strength: nil }
|
||||
add_column :grid_characters, :earring, :jsonb, default: { modifier: nil, strength: nil }
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
class ChangeAwakeningColumnsToJsonb < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
# Remove old columns
|
||||
remove_column :grid_characters, :awakening_type, :integer
|
||||
remove_column :grid_characters, :awakening_level, :integer
|
||||
|
||||
# Add new column
|
||||
add_column :grid_characters, :awakening, :jsonb, default: { type: 1, level: 1 }
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
class MakeMasteryColumnsNotNullable < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
change_column :grid_characters, :ring1, :jsonb, null: false
|
||||
change_column :grid_characters, :ring2, :jsonb, null: false
|
||||
change_column :grid_characters, :ring3, :jsonb, null: false
|
||||
change_column :grid_characters, :ring4, :jsonb, null: false
|
||||
change_column :grid_characters, :earring, :jsonb, null: false
|
||||
change_column :grid_characters, :awakening, :jsonb, null: false
|
||||
end
|
||||
end
|
||||
7
db/migrate/20230108150956_add_source_party_to_parties.rb
Normal file
7
db/migrate/20230108150956_add_source_party_to_parties.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
class AddSourcePartyToParties < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
change_table(:parties) do |t|
|
||||
t.references :source_party, type: :uuid, foreign_key: { to_table: 'parties' }
|
||||
end
|
||||
end
|
||||
end
|
||||
6
db/migrate/20230123035602_add_max_hpatkxlb_to_summon.rb
Normal file
6
db/migrate/20230123035602_add_max_hpatkxlb_to_summon.rb
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class AddMaxHpatkxlbToSummon < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :summons, :max_atk_xlb, :integer
|
||||
add_column :summons, :max_hp_xlb, :integer
|
||||
end
|
||||
end
|
||||
5
db/migrate/20230123055508_add_granblue_id_to_jobs.rb
Normal file
5
db/migrate/20230123055508_add_granblue_id_to_jobs.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
class AddGranblueIdToJobs < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :jobs, :granblue_id, :string
|
||||
end
|
||||
end
|
||||
14
db/migrate/20230124000252_create_job_accessories.rb
Normal file
14
db/migrate/20230124000252_create_job_accessories.rb
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
class CreateJobAccessories < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :job_accessories, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
|
||||
t.references :job, type: :uuid
|
||||
|
||||
t.string :name_en, null: false, unique: true
|
||||
t.string :name_jp, null: false, unique: true
|
||||
t.string :granblue_id, null: false, unique: true
|
||||
|
||||
t.integer :rarity
|
||||
t.date :release_date
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
class AddAccessoryTypeToJobAccessories < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :job_accessories, :accessory_type, :integer
|
||||
end
|
||||
end
|
||||
7
db/migrate/20230124100823_add_accessory_id_to_party.rb
Normal file
7
db/migrate/20230124100823_add_accessory_id_to_party.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
class AddAccessoryIdToParty < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
change_table(:parties) do |t|
|
||||
t.references :accessory, type: :uuid, foreign_key: { to_table: 'job_accessories' }
|
||||
end
|
||||
end
|
||||
end
|
||||
8
db/migrate/20230126030358_add_updates_table.rb
Normal file
8
db/migrate/20230126030358_add_updates_table.rb
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
class AddUpdatesTable < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :app_updates, id: false do |t|
|
||||
t.string :update_type, null: false
|
||||
t.datetime :updated_at, null: false, unique: true, primary_key: true
|
||||
end
|
||||
end
|
||||
end
|
||||
5
db/migrate/20230126040207_add_version_to_app_updates.rb
Normal file
5
db/migrate/20230126040207_add_version_to_app_updates.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
class AddVersionToAppUpdates < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :app_updates, :version, :string
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
class AddCharacterAndSummonCountsToParty < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :parties, :characters_count, :integer
|
||||
add_column :parties, :summons_count, :integer
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
class AddAccessoryAndTypeToJobs < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :jobs, :accessory, :boolean, default: false unless column_exists?(:jobs, :accessory)
|
||||
add_column :jobs, :accessory_type, :integer, default: 0 unless column_exists?(:jobs, :accessory_type)
|
||||
end
|
||||
end
|
||||
5
db/migrate/20230131082521_add_edit_key_to_parties.rb
Normal file
5
db/migrate/20230131082521_add_edit_key_to_parties.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
class AddEditKeyToParties < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :parties, :edit_key, :string, unique: true, null: true
|
||||
end
|
||||
end
|
||||
5
db/migrate/20230131084343_add_local_id_to_parties.rb
Normal file
5
db/migrate/20230131084343_add_local_id_to_parties.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
class AddLocalIdToParties < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :parties, :local_id, :uuid, null: true, unique: true
|
||||
end
|
||||
end
|
||||
58
db/schema.rb
58
db/schema.rb
|
|
@ -10,12 +10,18 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_01_03_180458) do
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_01_31_084343) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "btree_gin"
|
||||
enable_extension "pg_trgm"
|
||||
enable_extension "pgcrypto"
|
||||
enable_extension "plpgsql"
|
||||
enable_extension "timescaledb"
|
||||
|
||||
create_table "app_updates", primary_key: "updated_at", id: :datetime, force: :cascade do |t|
|
||||
t.string "update_type", null: false
|
||||
t.string "version"
|
||||
end
|
||||
|
||||
create_table "characters", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.string "name_en"
|
||||
|
|
@ -47,9 +53,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_03_180458) do
|
|||
t.index ["name_en"], name: "index_characters_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
||||
end
|
||||
|
||||
create_table "data_migrations", primary_key: "version", id: :string, force: :cascade do |t|
|
||||
end
|
||||
|
||||
create_table "favorites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.uuid "user_id"
|
||||
t.uuid "party_id"
|
||||
|
|
@ -67,19 +70,13 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_03_180458) do
|
|||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.boolean "perpetuity", default: false, null: false
|
||||
t.integer "awakening_type", default: 0, null: false
|
||||
t.integer "awakening_level", default: 1, null: false
|
||||
t.integer "transcendence_step", default: 0, null: false
|
||||
t.integer "ring_modifier1"
|
||||
t.float "ring_strength1"
|
||||
t.integer "ring_modifier2"
|
||||
t.float "ring_strength2"
|
||||
t.integer "ring_modifier3"
|
||||
t.float "ring_strength3"
|
||||
t.integer "ring_modifier4"
|
||||
t.float "ring_strength4"
|
||||
t.integer "earring_modifier"
|
||||
t.float "earring_strength"
|
||||
t.jsonb "ring1", 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 "ring4", default: {"modifier"=>nil, "strength"=>nil}, null: false
|
||||
t.jsonb "earring", default: {"modifier"=>nil, "strength"=>nil}, null: false
|
||||
t.jsonb "awakening", default: {"type"=>1, "level"=>1}, null: false
|
||||
t.index ["character_id"], name: "index_grid_characters_on_character_id"
|
||||
t.index ["party_id"], name: "index_grid_characters_on_party_id"
|
||||
end
|
||||
|
|
@ -118,6 +115,20 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_03_180458) do
|
|||
t.integer "awakening_level", default: 1, null: false
|
||||
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_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_key3_id"], name: "index_grid_weapons_on_weapon_key3_id"
|
||||
end
|
||||
|
||||
create_table "job_accessories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.uuid "job_id"
|
||||
t.string "name_en", null: false
|
||||
t.string "name_jp", null: false
|
||||
t.string "granblue_id", null: false
|
||||
t.integer "rarity"
|
||||
t.date "release_date"
|
||||
t.integer "accessory_type"
|
||||
t.index ["job_id"], name: "index_job_accessories_on_job_id"
|
||||
end
|
||||
|
||||
create_table "job_skills", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
|
|
@ -143,6 +154,9 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_03_180458) do
|
|||
t.boolean "ml", default: false
|
||||
t.integer "order"
|
||||
t.uuid "base_job_id"
|
||||
t.string "granblue_id"
|
||||
t.boolean "accessory", default: false
|
||||
t.integer "accessory_type", default: 0
|
||||
t.index ["base_job_id"], name: "index_jobs_on_base_job_id"
|
||||
end
|
||||
|
||||
|
|
@ -208,11 +222,19 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_03_180458) do
|
|||
t.integer "button_count"
|
||||
t.integer "chain_count"
|
||||
t.integer "turn_count"
|
||||
t.uuid "source_party_id"
|
||||
t.uuid "accessory_id"
|
||||
t.integer "characters_count"
|
||||
t.integer "summons_count"
|
||||
t.string "edit_key"
|
||||
t.uuid "local_id"
|
||||
t.index ["accessory_id"], name: "index_parties_on_accessory_id"
|
||||
t.index ["job_id"], name: "index_parties_on_job_id"
|
||||
t.index ["skill0_id"], name: "index_parties_on_skill0_id"
|
||||
t.index ["skill1_id"], name: "index_parties_on_skill1_id"
|
||||
t.index ["skill2_id"], name: "index_parties_on_skill2_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 ["user_id"], name: "index_parties_on_user_id"
|
||||
end
|
||||
|
||||
|
|
@ -246,6 +268,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_03_180458) do
|
|||
t.boolean "subaura", default: false, null: false
|
||||
t.boolean "limit", default: false, null: false
|
||||
t.boolean "xlb", default: false, null: false
|
||||
t.integer "max_atk_xlb"
|
||||
t.integer "max_hp_xlb"
|
||||
t.index ["name_en"], name: "index_summons_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
||||
end
|
||||
|
||||
|
|
@ -314,11 +338,13 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_03_180458) do
|
|||
add_foreign_key "jobs", "jobs", column: "base_job_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 "parties", "job_accessories", column: "accessory_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: "skill2_id"
|
||||
add_foreign_key "parties", "job_skills", column: "skill3_id"
|
||||
add_foreign_key "parties", "jobs"
|
||||
add_foreign_key "parties", "parties", column: "source_party_id"
|
||||
add_foreign_key "parties", "raids"
|
||||
add_foreign_key "parties", "users"
|
||||
end
|
||||
|
|
|
|||
41
lib/tasks/download_all_images.rake
Normal file
41
lib/tasks/download_all_images.rake
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
namespace :granblue do
|
||||
def _progress_reporter(count:, total:, result:, bar_len: 40, multi: true)
|
||||
filled_len = (bar_len * count / total).round
|
||||
status = File.basename(result)
|
||||
percents = (100.0 * count / total).round(1)
|
||||
bar = '=' * filled_len + '-' * (bar_len - filled_len)
|
||||
|
||||
if !multi
|
||||
print("[#{bar}] #{percents}% ...#{' ' * 14}#{status}\n")
|
||||
else
|
||||
print "\n"
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Downloads images for the given object type at the given size'
|
||||
task :download_all_images, %i[object size] => :environment do |_t, args|
|
||||
require 'open-uri'
|
||||
|
||||
filename = "export/#{args[:object]}-#{args[:size]}.txt"
|
||||
count = `wc -l #{filename}`.split.first.to_i
|
||||
|
||||
path = "#{Rails.root}/download/#{args[:object]}-#{args[:size]}"
|
||||
FileUtils.mkdir_p(path) unless Dir.exist?(path)
|
||||
|
||||
puts "Downloading #{count} images from #{args[:object]}-#{args[:size]}.txt..."
|
||||
if File.exist?(filename)
|
||||
File.readlines(filename).each_with_index do |line, i|
|
||||
download = URI.parse(line.strip).open
|
||||
download_URI = "#{path}/#{download.base_uri.to_s.split('/')[-1]}"
|
||||
if File.exist?(download_URI)
|
||||
puts "Skipping #{line}"
|
||||
else
|
||||
IO.copy_stream(download, "#{path}/#{download.base_uri.to_s.split('/')[-1]}")
|
||||
_progress_reporter(count: i, total: count, result: download_URI, bar_len: 40, multi: false)
|
||||
end
|
||||
rescue StandardError => e
|
||||
puts "#{e}: #{line}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -12,29 +12,120 @@ namespace :granblue do
|
|||
end
|
||||
end
|
||||
|
||||
desc 'Exports a list of character URLs for a given size'
|
||||
task :download_images, %i[object size] => :environment do |_t, args|
|
||||
require 'open-uri'
|
||||
def build_weapon_url(id, size)
|
||||
# Set up URL
|
||||
base_url = 'http://gbf.game-a.mbga.jp/assets/img/sp/assets/weapon'
|
||||
extension = '.jpg'
|
||||
|
||||
filename = "export/#{args[:object]}-#{args[:size]}.txt"
|
||||
count = `wc -l #{filename}`.split.first.to_i
|
||||
directory = 'ls' if size.to_s == 'main'
|
||||
directory = 'm' if size.to_s == 'grid'
|
||||
directory = 's' if size.to_s == 'square'
|
||||
|
||||
path = "#{Rails.root}/download/#{args[:object]}-#{args[:size]}"
|
||||
FileUtils.mkdir_p(path) unless Dir.exist?(path)
|
||||
"#{base_url}/#{directory}/#{id}#{extension}"
|
||||
end
|
||||
|
||||
puts "Downloading #{count} images from #{args[:object]}-#{args[:size]}.txt..."
|
||||
if File.exist?(filename)
|
||||
File.readlines(filename).each_with_index do |line, i|
|
||||
download = URI.parse(line.strip).open
|
||||
def build_summon_url(id, size)
|
||||
# Set up URL
|
||||
base_url = 'http://gbf.game-a.mbga.jp/assets/img/sp/assets/summon'
|
||||
extension = '.jpg'
|
||||
|
||||
directory = 'party_main' if size.to_s == 'main'
|
||||
directory = 'party_sub' if size.to_s == 'grid'
|
||||
directory = 's' if size.to_s == 'square'
|
||||
|
||||
"#{base_url}/#{directory}/#{id}#{extension}"
|
||||
end
|
||||
|
||||
def build_chara_url(id, size)
|
||||
# Set up URL
|
||||
base_url = 'http://gbf.game-a.mbga.jp/assets/img/sp/assets/npc'
|
||||
extension = '.jpg'
|
||||
|
||||
directory = 'f' if size.to_s == 'main'
|
||||
directory = 'm' if size.to_s == 'grid'
|
||||
directory = 's' if size.to_s == 'square'
|
||||
|
||||
"#{base_url}/#{directory}/#{id}#{extension}"
|
||||
end
|
||||
|
||||
def download_images(url, size, path)
|
||||
begin
|
||||
download = URI.parse(url).open
|
||||
download_URI = "#{path}/#{download.base_uri.to_s.split('/')[-1]}"
|
||||
if File.exist?(download_URI)
|
||||
puts "Skipping #{line}"
|
||||
puts "\tSkipping #{size}\t#{url}"
|
||||
else
|
||||
puts "\tDownloading #{size}\t#{url}..."
|
||||
IO.copy_stream(download, "#{path}/#{download.base_uri.to_s.split('/')[-1]}")
|
||||
_progress_reporter(count: i, total: count, result: download_URI, bar_len: 40, multi: false)
|
||||
end
|
||||
rescue StandardError => e
|
||||
puts "#{e}: #{line}"
|
||||
rescue OpenURI::HTTPError
|
||||
puts "\t404 returned\t#{url}"
|
||||
end
|
||||
end
|
||||
|
||||
def download_chara_images(id)
|
||||
sizes = %w[main grid square]
|
||||
|
||||
url = {
|
||||
'main': build_chara_url(id, 'main'),
|
||||
'grid': build_chara_url(id, 'grid'),
|
||||
'square': build_chara_url(id, 'square')
|
||||
}
|
||||
|
||||
puts "Character #{id}"
|
||||
sizes.each do |size|
|
||||
path = "#{Rails.root}/download/character-#{size}"
|
||||
download_images(url[size.to_sym], size, path)
|
||||
end
|
||||
end
|
||||
|
||||
def download_weapon_images(id)
|
||||
sizes = %w[main grid square]
|
||||
|
||||
url = {
|
||||
'main': build_weapon_url(id, 'main'),
|
||||
'grid': build_weapon_url(id, 'grid'),
|
||||
'square': build_weapon_url(id, 'square')
|
||||
}
|
||||
|
||||
puts "Weapon #{id}"
|
||||
sizes.each do |size|
|
||||
path = "#{Rails.root}/download/weapon-#{size}"
|
||||
download_images(url[size.to_sym], size, path)
|
||||
end
|
||||
end
|
||||
|
||||
def download_summon_images(id)
|
||||
sizes = %w[main grid square]
|
||||
|
||||
url = {
|
||||
'main': build_summon_url(id, 'main'),
|
||||
'grid': build_summon_url(id, 'grid'),
|
||||
'square': build_summon_url(id, 'square')
|
||||
}
|
||||
|
||||
puts "Summon #{id}"
|
||||
sizes.each do |size|
|
||||
path = "#{Rails.root}/download/character-#{size}"
|
||||
download_images(url[size.to_sym], size, path)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Downloads images for the given Granblue_IDs'
|
||||
task :download_images, %i[object] => :environment do |_t, args|
|
||||
object = args[:object]
|
||||
list = args.extras
|
||||
|
||||
list.each do |id|
|
||||
if object == 'character'
|
||||
download_chara_images("#{id}_01")
|
||||
download_chara_images("#{id}_02")
|
||||
download_chara_images("#{id}_03")
|
||||
download_chara_images("#{id}_04")
|
||||
elsif object == 'weapon'
|
||||
download_weapon_images(id)
|
||||
elsif object == 'summon'
|
||||
download_summon_images(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
42
lib/tasks/export_accessories.rake
Normal file
42
lib/tasks/export_accessories.rake
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
namespace :granblue do
|
||||
namespace :export do
|
||||
def build_url(id, type, size)
|
||||
# Set up URL
|
||||
base_url = 'https://prd-game-a-granbluefantasy.akamaized.net/assets_en/img/sp/assets'
|
||||
extension = '.jpg'
|
||||
|
||||
directory = 'm' if size.to_s == 'grid'
|
||||
directory = 's' if size.to_s == 'square'
|
||||
|
||||
"#{base_url}/#{type}/#{directory}/#{id}#{extension}"
|
||||
end
|
||||
|
||||
desc 'Exports a list of accessories for a given size'
|
||||
task :accessory, [:size] => :environment do |_t, args|
|
||||
# Set up options
|
||||
size = args[:size]
|
||||
|
||||
Dir.glob("#{Rails.root}/app/models/job_accessory.rb").each { |file| require file }
|
||||
|
||||
# Set up filepath
|
||||
dir = "#{Rails.root}/export/"
|
||||
filename = "#{dir}/accessory-#{size}.txt"
|
||||
FileUtils.mkdir(dir) unless Dir.exist?(dir)
|
||||
|
||||
# Write to file
|
||||
File.open(filename, 'w') do |f|
|
||||
JobAccessory.all.each do |w|
|
||||
if w.accessory_type === 1
|
||||
f.write("#{build_url(w.granblue_id.to_s, "shield", size)} \n")
|
||||
elsif w.accessory_type === 2
|
||||
f.write("#{build_url(w.granblue_id.to_s, "familiar", size)} \n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# CLI output
|
||||
count = `wc -l #{filename}`.split.first.to_i
|
||||
puts "Wrote #{count} job accessory URLs for \"#{size}\" size"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -32,7 +32,18 @@ namespace :granblue do
|
|||
Rake::Task['granblue:export:summon'].invoke('square')
|
||||
Rake::Task['granblue:export:summon'].reenable
|
||||
|
||||
puts 'Exported 9 files'
|
||||
# Run job tasks
|
||||
Rake::Task['granblue:export:job'].invoke
|
||||
Rake::Task['granblue:export:job'].reenable
|
||||
|
||||
# Run job accessory tasks
|
||||
Rake::Task['granblue:export:accessory'].invoke('grid')
|
||||
Rake::Task['granblue:export:accessory'].reenable
|
||||
|
||||
Rake::Task['granblue:export:accessory'].invoke('square')
|
||||
Rake::Task['granblue:export:accessory'].reenable
|
||||
|
||||
puts 'Exported 12 files'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
33
lib/tasks/export_job.rake
Normal file
33
lib/tasks/export_job.rake
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
namespace :granblue do
|
||||
namespace :export do
|
||||
def build_job_icon_url(id)
|
||||
# Set up URL
|
||||
base_url = 'https://prd-game-a-granbluefantasy.akamaized.net/assets_en/img/sp/ui/icon/job'
|
||||
extension = '.png'
|
||||
|
||||
"#{base_url}/#{id}#{extension}"
|
||||
end
|
||||
|
||||
desc 'Exports a list of weapon URLs for a given size'
|
||||
task :job do |_t, _args|
|
||||
# Include weapon model
|
||||
Dir.glob("#{Rails.root}/app/models/job.rb").each { |file| require file }
|
||||
|
||||
# Set up filepath
|
||||
dir = "#{Rails.root}/export/"
|
||||
filename = "#{dir}/job-icon.txt"
|
||||
FileUtils.mkdir(dir) unless Dir.exist?(dir)
|
||||
|
||||
# Write to file
|
||||
File.open(filename, 'w') do |f|
|
||||
Job.all.each do |w|
|
||||
f.write("#{build_job_icon_url(w.granblue_id.to_s)} \n")
|
||||
end
|
||||
end
|
||||
|
||||
# CLI output
|
||||
count = `wc -l #{filename}`.split.first.to_i
|
||||
puts "Wrote #{count} job URLs for icon size"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -36,6 +36,11 @@ namespace :granblue do
|
|||
f.write("#{build_summon_url("#{s.granblue_id}_02",
|
||||
size)} \n")
|
||||
end
|
||||
|
||||
if s.xlb
|
||||
f.write("#{build_summon_url("#{s.granblue_id}_03",
|
||||
size)} \n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue