improve achievement management and and views

This commit is contained in:
2021-08-24 20:53:32 +02:00
parent 39ebeea387
commit 2be44a89b8
18 changed files with 197 additions and 8 deletions

View File

@@ -0,0 +1,32 @@
# frozen_string_literal: true
class AchievementsController < ProtectedController
def index
@wow_achievement_categories = WowAchievementCategory.base_categories.order(display_order: :asc)
@wow_achievements = nil
@wow_last_completed_achievements = CompletedWowAchievement.where(
wow_character: current_user.wow_characters
).includes(:wow_character, wow_achievement: :wow_achievement_criterium).order(completed_timestamp: :desc).first(5)
@wow_achievement_category = nil
end
def show
@wow_achievement_category = WowAchievementCategory.find(params[:id])
@wow_achievement_categories = @wow_achievement_category.child_categories.order(display_order: :asc)
@wow_achievements = @wow_achievement_category.wow_achievements.includes(
wow_achievement_criterium: :child_criteria
).order(display_order: :asc)
end
end
# TODO
# Find a way to get the last achievement accomplished that were not already achievement by another character
# This will return all WowAchievement only completed by one character of the current user
# achievements = WowAchievement.joins(:completed_wow_achievements).where('completed_wow_achievements.wow_character_id': current_user.wow_characters).group(:id).having("count(completed_wow_achievements.id) < 2")
#
# This will return all the CompletedWowAchievement of the previous list
# completed_achievements = CompletedWowAchievement.where(wow_character: current_user.wow_characters, wow_achievement: achievements)
#
# The problem is that these completed_achivements all have a completed_timestamp at Thu, 01 Jan 1970 00:00:00.000000000 UTC +00:00
#
# It's probably required to use the WowAchievementCriterium to sort that

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
module AchievementsHelper
def achievement_completed(achievement_id, user)
CompletedWowAchievement.where(wow_achievement_id: achievement_id, wow_character: user.wow_characters).exists?
end
end

View File

@@ -19,4 +19,6 @@ class WowAchievement < ApplicationRecord
validates :name, presence: true
validates :achievement_id, presence: true, uniqueness: true
scope :base_achievements, -> { where(prerequisite_achievement: nil) }
end

View File

@@ -4,8 +4,16 @@ class WowAchievementCategory < ApplicationRecord
extend Mobility
translates :name
belongs_to :parent_category, class_name: 'WowAchievementCategory', optional: true
has_many :child_categories,
class_name: 'WowAchievementCategory',
foreign_key: 'parent_category_id',
dependent: :nullify,
inverse_of: :parent_category
has_many :wow_achievements, dependent: :destroy
validates :name, presence: true
validates :category_id, presence: true, uniqueness: true
scope :base_categories, -> { where(parent_category: nil) }
end

View File

@@ -11,6 +11,7 @@ class WowAchievementCriterium < ApplicationRecord
dependent: :destroy,
inverse_of: :parent_criterium
belongs_to :parent_criterium, class_name: 'WowAchievementCriterium', optional: true
has_many :completed_wow_achievement_criteria, dependent: :destroy
has_many :wow_characters, through: :completed_wow_achievement_criteria

View File

@@ -0,0 +1,76 @@
<div class="row">
<div class="col-3">
<div class="row">
<div class="col-12">
<% if wow_achievement_category %><h3> Achievement category: <%= wow_achievement_category.name %></h3><% end %>
<div class="d-grid gap-2">
<% wow_achievement_categories.each do |category| %>
<%= link_to category.name, "/#{locale}/achievements/#{category.id}", class: "btn btn-outline-dark" %>
<% end %>
</div>
</div>
</div>
<br />
<div class="row">
<div class="col-12">
<% if wow_achievement_category&.parent_category %>
<%= link_to "Back", "/#{locale}/achievements/#{wow_achievement_category.parent_category.id}", class: "btn btn-outline-dark" %>
<% elsif wow_achievement_category %>
<%= link_to "Back", "/#{locale}/achievements", class: "btn btn-outline-dark" %>
<% end %>
</div>
</div>
</div>
<% if wow_achievements %>
<div class="col-6">
<h3> Achievement:</h3>
<div class="d-grid gap-2">
<% wow_achievements.each do |achievement| %>
<div class="card">
<div class="card-header <% if achievement_completed(achievement.id, current_user) %>bg-success text-white<% else %>bg-secondary text-white<% end %>">
<%= achievement.name %><% if Rails.env.development? %> - ID: <%= achievement.achievement_id %><% end %>
</div>
<div class="card-body">
<p class="card-text">Description: <%= achievement.description %></p>
<p class="card-text">Criterium: <%= achievement&.wow_achievement_criterium&.description %></p>
<div class="row">
<% achievement&.wow_achievement_criterium&.child_criteria&.each do |criterium| %>
<div class="col-3">
<p class="card-text"><%= criterium&.description %></p>
</div>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<% elsif wow_last_completed_achievements %>
<div class="col-6">
<h3> Last achievement:</h3>
<div class="d-grid gap-2">
<% wow_last_completed_achievements.each do |achievement| %>
<div class="card">
<div class="card-header">
<%= achievement.wow_achievement.name %> - ID: <%= achievement.wow_achievement.achievement_id %>
</div>
<div class="card-body">
<p class="card-text">Description: <%= achievement.wow_achievement.description %></p>
<p class="card-text">Criterium: <%= achievement&.wow_achievement.wow_achievement_criterium&.description %></p>
<% if achievement&.wow_achievement.wow_achievement_criterium.child_criteria %>
<div class="row">
<% achievement&.wow_achievement.wow_achievement_criterium.child_criteria.each do |criterium| %>
<div class="col-3">
<p class="card-text"><%= criterium&.description %></p>
</div>
<% end %>
</div>
<% end %>
<p class="card-text">Completed by: <%= link_to achievement.wow_character.name, achievement.wow_character, data: { turbo: false } %></p>
</div>
</div>
<% end %>
</div>
</div>
<% end %>
</div>

View File

@@ -0,0 +1,5 @@
<h2>Achievement list</h2>
<%= turbo_frame_tag 'achievements' do %>
<%= render partial: 'achievements/achievements', locals: { wow_achievement_category: @wow_achievement_category, wow_achievement_categories: @wow_achievement_categories, wow_achievements: @wow_achievements, wow_last_completed_achievements: @wow_last_completed_achievements } %>
<% end %>

View File

@@ -0,0 +1,5 @@
<h2>Achievement list</h2>
<%= turbo_frame_tag 'achievements' do %>
<%= render partial: 'achievements/achievements', locals: { wow_achievement_category: @wow_achievement_category, wow_achievement_categories: @wow_achievement_categories, wow_achievements: @wow_achievements, wow_last_completed_achievements: nil } %>
<% end %>

View File

@@ -19,6 +19,9 @@
<li class="nav-item">
<a class="nav-link <%= 'active' if current_page?(rp_worlds_path) %>" aria-current="page" href="<%= rp_worlds_path %>"><%= t('layouts.navbar.worlds') %></a>
</li>
<li class="nav-item">
<a class="nav-link <%= 'active' if current_page?(achievements_path) %>" aria-current="page" href="<%= achievements_path %>"><%= t('layouts.navbar.achievements') %></a>
</li>
</ul>
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<%= render 'layouts/locales' %>

View File

@@ -18,7 +18,7 @@
<div class="col-7">
<div class="row">
<div class="col-6">
<%= render partial: 'wow_characters/reputations', locals: { standings: @wow_character.wow_standings.group_by { |standing| standing.wow_reputation.meta_wow_reputation_id }, meta_wow_reputations: @meta_wow_reputations } %>
<%= render partial: 'wow_characters/reputations', locals: { standings: @wow_character.wow_standings.group_by { |standing| standing.wow_reputation.meta_wow_reputation_id}, meta_wow_reputations: @meta_wow_reputations } %>
</div>
</div>
</div>

View File

@@ -17,6 +17,8 @@ class WowAchievementCategoriesWorker < WowSidekiqWorker
end
wow_category.save
WowAchievementCategoryDetailWorker.perform_async(wow_category.category_id) if wow_category.persisted?
end
end
end

View File

@@ -0,0 +1,21 @@
# frozen_string_literal: true
class WowAchievementCategoryDetailWorker < WowSidekiqWorker
def perform(category_id)
return unless (wow_achievement_category = WowAchievementCategory.find_by(category_id: category_id))
RBattlenet.set_options(locale: 'en_GB')
result = RBattlenet::Wow::AchievementCategory.find(category_id)
return unless result.status_code == 200
wow_achievement_category.is_guild_category = result.is_guild_category
wow_achievement_category.display_order = result.display_order
if result.parent_category
wow_achievement_category.parent_category = WowAchievementCategory.find_by(category_id: result.parent_category.id)
end
wow_achievement_category.save
end
end

View File

@@ -25,7 +25,11 @@ class WowAchievementDetailWorker < WowSidekiqWorker
wow_achievement.prerequisite_achievement = WowAchievement.find_by(achievement_id: result.prerequisite_achievement.id) if result.prerequisite_achievement
wow_achievement.wow_achievement_category = WowAchievementCategory.find_by(category_id: result.category.id) if result.category
wow_achievement.wow_achievement_criterium = find_or_create_wow_achievement_criterium(result.criteria) if result.criteria
wow_achievement.icon = RBattlenet::Wow::AchievementMedia.find(result.media.id).assets[0].value if result.media
if result.media
icon = RBattlenet::Wow::AchievementMedia.find(result.media.id)
wow_achievement.icon = icon.assets.first.value if icon.assets.first
end
wow_achievement.save
end
@@ -34,8 +38,10 @@ class WowAchievementDetailWorker < WowSidekiqWorker
wow_achievement_criterium = WowAchievementCriterium.find_or_initialize_by(criterium_id: criteria.id)
wow_achievement_criterium.amount = criteria.amount
locales.each do |locale|
Mobility.with_locale(locale[0]) { wow_achievement_criterium.description = criteria.description[locale[1]] }
if criteria.description
locales.each do |locale|
Mobility.with_locale(locale[0]) { wow_achievement_criterium.description = criteria.description[locale[1]] }
end
end
if criteria.operator
@@ -51,9 +57,13 @@ class WowAchievementDetailWorker < WowSidekiqWorker
wow_child_achievement_criterium = WowAchievementCriterium.find_or_initialize_by(criterium_id: child_criterium.id)
wow_child_achievement_criterium.parent_criterium = wow_achievement_criterium
wow_child_achievement_criterium.amount = child_criterium.amount
locales.each do |locale|
Mobility.with_locale(locale[0]) { wow_child_achievement_criterium.description = child_criterium.description[locale[1]] }
if child_criterium.description
locales.each do |locale|
Mobility.with_locale(locale[0]) { wow_child_achievement_criterium.description = child_criterium.description[locale[1]] }
end
end
wow_child_achievement_criterium.save
end

View File

@@ -40,7 +40,7 @@ class WowCharactersWorker < WowSidekiqWorker
WowCharacterDetailWorker.perform_async(wow_char.character_id)
WowCharacterPositionsWorker.perform_async(wow_char.character_id)
WowStandingWorker.perform_async(wow_char.character_id)
WowCharacterAchievementsWorker.perform_async(wow_char.character_id)
# WowCharacterAchievementsWorker.perform_async(wow_char.character_id)
end
end
end

View File

@@ -14,6 +14,7 @@ Rails.application.routes.draw do
resources :wow_mounts, only: [:index, :show]
resources :wow_pets, only: [:index, :show]
resources :wow_reputations, only: [:index, :show]
resources :achievements, only: [:index, :show]
resources :rp_worlds
end
end

View File

@@ -0,0 +1,5 @@
class AddWowAchievementCategorySelfJoin < ActiveRecord::Migration[6.1]
def change
add_reference :wow_achievement_categories, :parent_category, foreign_key: { to_table: :wow_achievement_categories }
end
end

View File

@@ -0,0 +1,6 @@
class AddColumnsToWowAchievementCategory < ActiveRecord::Migration[6.1]
def change
add_column :wow_achievement_categories, :is_guild_category, :boolean
add_column :wow_achievement_categories, :display_order, :integer
end
end

7
db/schema.rb generated
View File

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2021_08_15_130405) do
ActiveRecord::Schema.define(version: 2021_08_15_182820) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -118,7 +118,11 @@ ActiveRecord::Schema.define(version: 2021_08_15_130405) do
t.jsonb "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "parent_category_id"
t.boolean "is_guild_category"
t.integer "display_order"
t.index ["category_id"], name: "index_wow_achievement_categories_on_category_id", unique: true
t.index ["parent_category_id"], name: "index_wow_achievement_categories_on_parent_category_id"
end
create_table "wow_achievement_criteria", force: :cascade do |t|
@@ -531,6 +535,7 @@ ActiveRecord::Schema.define(version: 2021_08_15_130405) do
t.index ["wow_reputation_id"], name: "index_wow_standings_on_wow_reputation_id"
end
add_foreign_key "wow_achievement_categories", "wow_achievement_categories", column: "parent_category_id"
add_foreign_key "wow_achievement_criteria", "wow_achievement_criteria", column: "parent_criterium_id"
add_foreign_key "wow_achievements", "wow_achievements", column: "prerequisite_achievement_id"
add_foreign_key "wow_characters", "wow_geo_positions", column: "bind_position_id"