* Add advanced filters Adds new filters to search: * Full auto * Charge attack * Auto guard * Number of weapons (user-selectable now) * Number of summons * Number of characters * Maximum number of turns * Maximum number of buttons * Maximum clear time * User quality (No anonymous users) * Name quality (No untitled teams) * Remixes (Only show original teams) * Update advanced filter params * Add default to party counter cache
This commit is contained in:
parent
6fd5aa8c27
commit
6e81ffc7dd
4 changed files with 241 additions and 22 deletions
|
|
@ -8,6 +8,16 @@ module Api
|
|||
before_action :set, only: %w[update destroy]
|
||||
before_action :authorize, only: %w[update destroy]
|
||||
|
||||
MAX_CHARACTERS = 5
|
||||
MAX_SUMMONS = 8
|
||||
MAX_WEAPONS = 13
|
||||
|
||||
DEFAULT_MIN_CHARACTERS = 3
|
||||
DEFAULT_MIN_SUMMONS = 2
|
||||
DEFAULT_MIN_WEAPONS = 5
|
||||
|
||||
DEFAULT_MAX_CLEAR_TIME = 5400
|
||||
|
||||
def create
|
||||
party = Party.new
|
||||
party.user = current_user if current_user
|
||||
|
|
@ -73,12 +83,15 @@ module Api
|
|||
end
|
||||
|
||||
def index
|
||||
conditions = build_conditions(request.params)
|
||||
conditions = build_conditions
|
||||
|
||||
@parties = Party.joins(:weapons)
|
||||
.group('parties.id')
|
||||
.having('count(distinct grid_weapons.weapon_id) > 2')
|
||||
.where(conditions)
|
||||
.where(name_quality)
|
||||
.where(user_quality)
|
||||
.where(original)
|
||||
.order(created_at: :desc)
|
||||
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
|
||||
.each { |party| party.favorited = current_user ? party.is_favorited(current_user) : false }
|
||||
|
|
@ -99,11 +112,14 @@ module Api
|
|||
def favorites
|
||||
raise Api::V1::UnauthorizedError unless current_user
|
||||
|
||||
conditions = build_conditions(request.params)
|
||||
conditions = build_conditions
|
||||
conditions[:favorites] = { user_id: current_user.id }
|
||||
|
||||
@parties = Party.joins(:favorites)
|
||||
.where(conditions)
|
||||
.where(name_quality)
|
||||
.where(user_quality)
|
||||
.where(original)
|
||||
.order('favorites.created_at DESC')
|
||||
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
|
||||
.each { |party| party.favorited = party.is_favorited(current_user) }
|
||||
|
|
@ -127,20 +143,72 @@ module Api
|
|||
render_unauthorized_response if @party.user != current_user || @party.edit_key != edit_key
|
||||
end
|
||||
|
||||
def build_conditions(params)
|
||||
def build_conditions
|
||||
params = request.params
|
||||
|
||||
unless params['recency'].blank?
|
||||
start_time = (DateTime.current - params['recency'].to_i.seconds)
|
||||
.to_datetime.beginning_of_day
|
||||
end
|
||||
|
||||
min_characters_count = params['characters_count'].blank? ? DEFAULT_MIN_CHARACTERS : params['characters_count'].to_i
|
||||
min_summons_count = params['summons_count'].blank? ? DEFAULT_MIN_SUMMONS : params['summons_count'].to_i
|
||||
min_weapons_count = params['weapons_count'].blank? ? DEFAULT_MIN_WEAPONS : params['weapons_count'].to_i
|
||||
max_clear_time = params['max_clear_time'].blank? ? DEFAULT_MAX_CLEAR_TIME : params['max_clear_time'].to_i
|
||||
|
||||
{}.tap do |hash|
|
||||
hash[:element] = params['element'] unless params['element'].blank?
|
||||
# Basic filters
|
||||
hash[:element] = params['element'].to_i unless params['element'].blank?
|
||||
hash[:raid] = params['raid'] unless params['raid'].blank?
|
||||
hash[:created_at] = start_time..DateTime.current unless params['recency'].blank?
|
||||
hash[:weapons_count] = 5..13
|
||||
|
||||
# Advanced filters: Team parameters
|
||||
hash[:full_auto] = params['full_auto'].to_i unless params['full_auto'].blank? || params['full_auto'].to_i == -1
|
||||
hash[:auto_guard] = params['auto_guard'].to_i unless params['auto_guard'].blank? || params['auto_guard'].to_i == -1
|
||||
hash[:charge_attack] = params['charge_attack'].to_i unless params['charge_attack'].blank? || params['charge_attack'].to_i == -1
|
||||
|
||||
# Turn count of 0 will not be displayed, so disallow on the frontend or set default to 1
|
||||
# How do we do the same for button count since that can reasonably be 1?
|
||||
# hash[:turn_count] = params['turn_count'].to_i unless params['turn_count'].blank? || params['turn_count'].to_i <= 0
|
||||
# hash[:button_count] = params['button_count'].to_i unless params['button_count'].blank?
|
||||
# hash[:clear_time] = 0..max_clear_time
|
||||
|
||||
# Advanced filters: Object counts
|
||||
hash[:characters_count] = min_characters_count..MAX_CHARACTERS
|
||||
hash[:summons_count] = min_summons_count..MAX_SUMMONS
|
||||
hash[:weapons_count] = min_weapons_count..MAX_WEAPONS
|
||||
end
|
||||
end
|
||||
|
||||
def original
|
||||
"source_party_id IS NULL" unless request.params['original'].blank? || request.params['original'] == "false"
|
||||
end
|
||||
|
||||
def user_quality
|
||||
"user_id IS NOT NULL" unless request.params[:user_quality].blank? || request.params[:user_quality] == "false"
|
||||
end
|
||||
|
||||
def name_quality
|
||||
low_quality = [
|
||||
"Untitled",
|
||||
"Remix of Untitled",
|
||||
"Remix of Remix of Untitled",
|
||||
"Remix of Remix of Remix of Untitled",
|
||||
"Remix of Remix of Remix of Remix of Untitled",
|
||||
"Remix of Remix of Remix of Remix of Remix of Untitled",
|
||||
"無題",
|
||||
"無題のリミックス",
|
||||
"無題のリミックスのリミックス",
|
||||
"無題のリミックスのリミックスのリミックス",
|
||||
"無題のリミックスのリミックスのリミックスのリミックス",
|
||||
"無題のリミックスのリミックスのリミックスのリミックスのリミックス"
|
||||
]
|
||||
|
||||
joined_names = low_quality.map { |name| "'#{name}'" }.join(',')
|
||||
|
||||
"name NOT IN (#{joined_names})" unless request.params[:name_quality].blank? || request.params[:name_quality] == "false"
|
||||
end
|
||||
|
||||
def remixed_name(name)
|
||||
blanked_name = {
|
||||
en: name.blank? ? 'Untitled team' : name,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,16 @@ module Api
|
|||
before_action :set, except: %w[create check_email check_username]
|
||||
before_action :set_by_id, only: %w[info update]
|
||||
|
||||
MAX_CHARACTERS = 5
|
||||
MAX_SUMMONS = 8
|
||||
MAX_WEAPONS = 13
|
||||
|
||||
DEFAULT_MIN_CHARACTERS = 3
|
||||
DEFAULT_MIN_SUMMONS = 2
|
||||
DEFAULT_MIN_WEAPONS = 5
|
||||
|
||||
DEFAULT_MAX_CLEAR_TIME = 5400
|
||||
|
||||
def create
|
||||
user = User.new(user_params)
|
||||
|
||||
|
|
@ -44,11 +54,23 @@ module Api
|
|||
render_not_found_response('user')
|
||||
else
|
||||
|
||||
conditions = build_conditions(request.params)
|
||||
conditions = build_conditions
|
||||
conditions[:user_id] = @user.id
|
||||
|
||||
@parties = Party
|
||||
.where(conditions)
|
||||
.where(name_quality)
|
||||
.where(user_quality)
|
||||
.where(original)
|
||||
.order(created_at: :desc)
|
||||
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
|
||||
.each { |party| party.favorited = party.is_favorited(current_user) }
|
||||
|
||||
parties = Party
|
||||
.where(conditions)
|
||||
.where(name_quality)
|
||||
.where(user_quality)
|
||||
.where(original)
|
||||
.order(created_at: :desc)
|
||||
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
|
||||
.each do |party|
|
||||
|
|
@ -81,19 +103,72 @@ module Api
|
|||
|
||||
private
|
||||
|
||||
def build_conditions(params)
|
||||
def build_conditions
|
||||
params = request.params
|
||||
|
||||
unless params['recency'].blank?
|
||||
start_time = (DateTime.current - params['recency'].to_i.seconds)
|
||||
.to_datetime.beginning_of_day
|
||||
end
|
||||
|
||||
min_characters_count = params['characters_count'].blank? ? DEFAULT_MIN_CHARACTERS : params['characters_count'].to_i
|
||||
min_summons_count = params['summons_count'].blank? ? DEFAULT_MIN_SUMMONS : params['summons_count'].to_i
|
||||
min_weapons_count = params['weapons_count'].blank? ? DEFAULT_MIN_WEAPONS : params['weapons_count'].to_i
|
||||
max_clear_time = params['max_clear_time'].blank? ? DEFAULT_MAX_CLEAR_TIME : params['max_clear_time'].to_i
|
||||
|
||||
{}.tap do |hash|
|
||||
hash[:element] = params['element'] unless params['element'].blank?
|
||||
# Basic filters
|
||||
hash[:element] = params['element'].to_i unless params['element'].blank?
|
||||
hash[:raid] = params['raid'] unless params['raid'].blank?
|
||||
hash[:created_at] = start_time..DateTime.current unless params['recency'].blank?
|
||||
|
||||
# Advanced filters: Team parameters
|
||||
hash[:full_auto] = params['full_auto'].to_i unless params['full_auto'].blank? || params['full_auto'].to_i == -1
|
||||
hash[:auto_guard] = params['auto_guard'].to_i unless params['auto_guard'].blank? || params['auto_guard'].to_i == -1
|
||||
hash[:charge_attack] = params['charge_attack'].to_i unless params['charge_attack'].blank? || params['charge_attack'].to_i == -1
|
||||
|
||||
# Turn count of 0 will not be displayed, so disallow on the frontend or set default to 1
|
||||
# How do we do the same for button count since that can reasonably be 1?
|
||||
# hash[:turn_count] = params['turn_count'].to_i unless params['turn_count'].blank? || params['turn_count'].to_i <= 0
|
||||
# hash[:button_count] = params['button_count'].to_i unless params['button_count'].blank?
|
||||
# hash[:clear_time] = 0..max_clear_time
|
||||
|
||||
# Advanced filters: Object counts
|
||||
hash[:characters_count] = min_characters_count..MAX_CHARACTERS
|
||||
hash[:summons_count] = min_summons_count..MAX_SUMMONS
|
||||
hash[:weapons_count] = min_weapons_count..MAX_WEAPONS
|
||||
end
|
||||
end
|
||||
|
||||
def original
|
||||
"source_party_id IS NULL" unless params['original'].blank? || params['original'] == '0'
|
||||
end
|
||||
|
||||
def user_quality
|
||||
"user_id IS NOT NULL" unless params[:user_quality].nil? || params[:user_quality] == "0"
|
||||
end
|
||||
|
||||
def name_quality
|
||||
low_quality = [
|
||||
"Untitled",
|
||||
"Remix of Untitled",
|
||||
"Remix of Remix of Untitled",
|
||||
"Remix of Remix of Remix of Untitled",
|
||||
"Remix of Remix of Remix of Remix of Untitled",
|
||||
"Remix of Remix of Remix of Remix of Remix of Untitled",
|
||||
"無題",
|
||||
"無題のリミックス",
|
||||
"無題のリミックスのリミックス",
|
||||
"無題のリミックスのリミックスのリミックス",
|
||||
"無題のリミックスのリミックスのリミックスのリミックス",
|
||||
"無題のリミックスのリミックスのリミックスのリミックスのリミックス"
|
||||
]
|
||||
|
||||
joined_names = low_quality.map { |name| "'#{name}'" }.join(',')
|
||||
|
||||
"name NOT IN (#{joined_names})" unless params[:name_quality].nil? || params[:name_quality] == "0"
|
||||
end
|
||||
|
||||
# Specify whitelisted properties that can be modified.
|
||||
def set
|
||||
@user = User.where('username = ?', params[:id]).first
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
class AddDefaultToCounterCacheOnParties < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
change_column_default :parties, :characters_count, 0
|
||||
change_column_default :parties, :weapons_count, 0
|
||||
change_column_default :parties, :summons_count, 0
|
||||
end
|
||||
end
|
||||
97
db/schema.rb
97
db/schema.rb
|
|
@ -10,19 +10,62 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_03_15_103037) do
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_03_21_115930) 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 "character_charge_attacks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.uuid "character_id"
|
||||
t.string "name_en", null: false
|
||||
t.string "name_jp", null: false
|
||||
t.string "description_en", null: false
|
||||
t.string "description_jp", null: false
|
||||
t.integer "order", null: false
|
||||
t.string "form"
|
||||
t.uuid "effects", array: true
|
||||
t.index ["character_id"], name: "index_character_charge_attacks_on_character_id"
|
||||
end
|
||||
|
||||
create_table "character_skills", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.uuid "character_id"
|
||||
t.string "name_en", null: false
|
||||
t.string "name_jp", null: false
|
||||
t.string "description_en", null: false
|
||||
t.string "description_jp", null: false
|
||||
t.integer "type", null: false
|
||||
t.integer "position", null: false
|
||||
t.string "form"
|
||||
t.integer "cooldown", default: 0, null: false
|
||||
t.integer "lockout", default: 0, null: false
|
||||
t.integer "duration", array: true
|
||||
t.boolean "recast", default: false, null: false
|
||||
t.integer "obtained_at", default: 1, null: false
|
||||
t.uuid "effects", array: true
|
||||
t.index ["character_id"], name: "index_character_skills_on_character_id"
|
||||
end
|
||||
|
||||
create_table "character_support_skills", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.uuid "character_id"
|
||||
t.string "name_en", null: false
|
||||
t.string "name_jp", null: false
|
||||
t.string "description_en", null: false
|
||||
t.string "description_jp", null: false
|
||||
t.integer "position", null: false
|
||||
t.integer "obtained_at"
|
||||
t.boolean "emp", default: false, null: false
|
||||
t.boolean "transcendence", default: false, null: false
|
||||
t.uuid "effects", array: true
|
||||
t.index ["character_id"], name: "index_character_support_skills_on_character_id"
|
||||
end
|
||||
|
||||
create_table "characters", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.string "name_en"
|
||||
t.string "name_jp"
|
||||
|
|
@ -50,10 +93,26 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_15_103037) do
|
|||
t.integer "max_hp_ulb"
|
||||
t.integer "max_atk_ulb"
|
||||
t.integer "character_id", default: [], null: false, array: true
|
||||
t.string "nicknames_en", default: [], null: false, array: true
|
||||
t.string "nicknames_jp", default: [], null: false, array: true
|
||||
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|
|
||||
create_table "effects", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.string "name_en", null: false
|
||||
t.string "name_jp", null: false
|
||||
t.string "description_en", null: false
|
||||
t.string "description_jp", null: false
|
||||
t.integer "accuracy_value"
|
||||
t.string "accuracy_suffix"
|
||||
t.string "accuracy_comparator"
|
||||
t.jsonb "strength", array: true
|
||||
t.integer "healing_cap"
|
||||
t.boolean "duration_indefinite", default: false, null: false
|
||||
t.integer "duration_value"
|
||||
t.string "duration_unit"
|
||||
t.string "notes_en"
|
||||
t.string "notes_jp"
|
||||
end
|
||||
|
||||
create_table "favorites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
|
|
@ -74,12 +133,16 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_15_103037) do
|
|||
t.datetime "updated_at", null: false
|
||||
t.boolean "perpetuity", default: false, null: false
|
||||
t.integer "transcendence_step", default: 0, null: false
|
||||
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.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.boolean "skill0_enabled", default: true, null: false
|
||||
t.boolean "skill1_enabled", default: true, null: false
|
||||
t.boolean "skill2_enabled", default: true, null: false
|
||||
t.boolean "skill3_enabled", default: true, 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
|
||||
|
|
@ -94,6 +157,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_15_103037) do
|
|||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "transcendence_step", default: 0, null: false
|
||||
t.boolean "quick_summon", default: false, null: false
|
||||
t.index ["party_id"], name: "index_grid_summons_on_party_id"
|
||||
t.index ["summon_id"], name: "index_grid_summons_on_summon_id"
|
||||
end
|
||||
|
|
@ -155,12 +219,12 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_15_103037) do
|
|||
t.integer "proficiency2"
|
||||
t.string "row"
|
||||
t.boolean "master_level", default: false, null: false
|
||||
t.boolean "ultimate_mastery", default: false, null: 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.boolean "ultimate_mastery", default: false, null: false
|
||||
t.index ["base_job_id"], name: "index_jobs_on_base_job_id"
|
||||
end
|
||||
|
||||
|
|
@ -212,10 +276,9 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_15_103037) do
|
|||
t.text "description"
|
||||
t.uuid "raid_id"
|
||||
t.integer "element"
|
||||
t.integer "weapons_count"
|
||||
t.integer "weapons_count", default: 0
|
||||
t.uuid "job_id"
|
||||
t.integer "master_level"
|
||||
t.integer "ultimate_mastery"
|
||||
t.uuid "skill1_id"
|
||||
t.uuid "skill2_id"
|
||||
t.uuid "skill3_id"
|
||||
|
|
@ -229,10 +292,11 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_15_103037) do
|
|||
t.integer "turn_count"
|
||||
t.uuid "source_party_id"
|
||||
t.uuid "accessory_id"
|
||||
t.integer "characters_count"
|
||||
t.integer "summons_count"
|
||||
t.integer "characters_count", default: 0
|
||||
t.integer "summons_count", default: 0
|
||||
t.string "edit_key"
|
||||
t.uuid "local_id"
|
||||
t.integer "ultimate_mastery"
|
||||
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"
|
||||
|
|
@ -275,6 +339,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_15_103037) do
|
|||
t.boolean "xlb", default: false, null: false
|
||||
t.integer "max_atk_xlb"
|
||||
t.integer "max_hp_xlb"
|
||||
t.string "nicknames_en", default: [], null: false, array: true
|
||||
t.string "nicknames_jp", default: [], null: false, array: true
|
||||
t.index ["name_en"], name: "index_summons_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
||||
end
|
||||
|
||||
|
|
@ -329,6 +395,9 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_15_103037) do
|
|||
t.boolean "awakening", default: true, null: false
|
||||
t.boolean "limit", default: false, null: false
|
||||
t.boolean "ax", default: false, null: false
|
||||
t.integer "awakening_types", default: [], array: true
|
||||
t.string "nicknames_en", default: [], null: false, array: true
|
||||
t.string "nicknames_jp", default: [], null: false, array: true
|
||||
t.index ["name_en"], name: "index_weapons_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue