From 258da22b4a645a9c10dac4172768e1c934985c86 Mon Sep 17 00:00:00 2001 From: talhaahsan Date: Mon, 23 Jun 2025 04:48:16 +0000 Subject: [PATCH 1/4] WIP narrative insert text API support --- app/controllers/cards_controller.rb | 1 + app/resources/card_resource.rb | 1 + app/resources/printing_resource.rb | 4 +- .../20250623035203_add_narrative_to_cards.rb | 5 + ...5759_update_unified_cards_to_version_10.rb | 8 + ..._update_unified_printings_to_version_12.rb | 8 + db/schema.rb | 5 +- db/views/unified_cards_v10.sql | 436 ++++++++++++++++ db/views/unified_printings_v12.sql | 479 ++++++++++++++++++ lib/tasks/cards.rake | 1 + 10 files changed, 946 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20250623035203_add_narrative_to_cards.rb create mode 100644 db/migrate/20250623035759_update_unified_cards_to_version_10.rb create mode 100644 db/migrate/20250623035928_update_unified_printings_to_version_12.rb create mode 100644 db/views/unified_cards_v10.sql create mode 100644 db/views/unified_printings_v12.sql diff --git a/app/controllers/cards_controller.rb b/app/controllers/cards_controller.rb index 89b0379..2933e90 100644 --- a/app/controllers/cards_controller.rb +++ b/app/controllers/cards_controller.rb @@ -5,6 +5,7 @@ class CardsController < ApplicationController def index add_total_stat(params) cards = CardResource.all(params) + debugger respond_with(cards) end diff --git a/app/resources/card_resource.rb b/app/resources/card_resource.rb index bcd44e4..a26ee22 100644 --- a/app/resources/card_resource.rb +++ b/app/resources/card_resource.rb @@ -59,6 +59,7 @@ class CardResource < ApplicationResource # rubocop:disable Metrics/ClassLength end attribute :card_set_names, :array_of_strings attribute :designed_by, :string + attribute :narrative_text, :string attribute :printings_released_by, :array_of_strings attribute :pronouns, :string attribute :pronunciation_approximation, :string diff --git a/app/resources/printing_resource.rb b/app/resources/printing_resource.rb index dede357..9e8af95 100644 --- a/app/resources/printing_resource.rb +++ b/app/resources/printing_resource.rb @@ -77,6 +77,7 @@ class PrintingResource < ApplicationResource # rubocop:disable Metrics/ClassLeng end attribute :card_set_names, :array_of_strings attribute :designed_by, :string + attribute :narrative_text, :string attribute :released_by, :string attribute :printings_released_by, :array_of_strings attribute :pronouns, :string @@ -186,7 +187,8 @@ def images(id, face_index = nil) 'tiny' => "#{url_prefix}/tiny/#{id}#{face_suffix}.jpg", 'small' => "#{url_prefix}/small/#{id}#{face_suffix}.jpg", 'medium' => "#{url_prefix}/medium/#{id}#{face_suffix}.jpg", - 'large' => "#{url_prefix}/large/#{id}#{face_suffix}.jpg" + 'large' => "#{url_prefix}/large/#{id}#{face_suffix}.jpg", + 'narrative' => "#{url_prefix}/large/#{id}#{face_suffix}-narrative.jpg" } } end diff --git a/db/migrate/20250623035203_add_narrative_to_cards.rb b/db/migrate/20250623035203_add_narrative_to_cards.rb new file mode 100644 index 0000000..ec6677a --- /dev/null +++ b/db/migrate/20250623035203_add_narrative_to_cards.rb @@ -0,0 +1,5 @@ +class AddNarrativeToCards < ActiveRecord::Migration[7.2] + def change + add_column :cards, :narrative_text, :string + end +end diff --git a/db/migrate/20250623035759_update_unified_cards_to_version_10.rb b/db/migrate/20250623035759_update_unified_cards_to_version_10.rb new file mode 100644 index 0000000..fa73f18 --- /dev/null +++ b/db/migrate/20250623035759_update_unified_cards_to_version_10.rb @@ -0,0 +1,8 @@ +class UpdateUnifiedCardsToVersion10 < ActiveRecord::Migration[7.2] + def change + update_view :unified_cards, + version: 10, + revert_to_version: 9, + materialized: true + end +end diff --git a/db/migrate/20250623035928_update_unified_printings_to_version_12.rb b/db/migrate/20250623035928_update_unified_printings_to_version_12.rb new file mode 100644 index 0000000..299ff70 --- /dev/null +++ b/db/migrate/20250623035928_update_unified_printings_to_version_12.rb @@ -0,0 +1,8 @@ +class UpdateUnifiedPrintingsToVersion12 < ActiveRecord::Migration[7.2] + def change + update_view :unified_printings, + version: 12, + revert_to_version: 11, + materialized: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 9362d5d..c6ac02f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2025_01_05_055917) do +ActiveRecord::Schema[7.2].define(version: 2025_06_23_035928) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -144,6 +144,7 @@ t.string "pronunciation_approximation" t.string "pronunciation_ipa" t.string "layout_id", default: "normal", null: false + t.string "narrative_text" t.index ["card_type_id"], name: "index_cards_on_card_type_id" t.index ["faction_id"], name: "index_cards_on_faction_id" t.index ["side_id"], name: "index_cards_on_side_id" @@ -594,6 +595,7 @@ c.influence_limit, c.memory_cost, c.minimum_deck_size, + c.narrative_text, c.pronouns, c.pronunciation_approximation, c.pronunciation_ipa, @@ -913,6 +915,7 @@ c.link_provided, c.memory_cost, c.mu_provided, + c.narrative_text, c.num_printed_subroutines, c.on_encounter_effect, c.performs_trace, diff --git a/db/views/unified_cards_v10.sql b/db/views/unified_cards_v10.sql new file mode 100644 index 0000000..a8dca55 --- /dev/null +++ b/db/views/unified_cards_v10.sql @@ -0,0 +1,436 @@ +WITH card_cycles_summary AS ( + SELECT c.id, + ARRAY_AGG( + cc.id + ORDER BY cc.date_release DESC + ) as card_cycle_ids, + ARRAY_AGG( + cc.name + ORDER BY cc.date_release DESC + ) as card_cycle_names + FROM cards c + JOIN printings p ON c.id = p.card_id + JOIN card_sets cs ON p.card_set_id = cs.id + JOIN card_cycles cc ON cc.id = cs.card_cycle_id + GROUP BY c.id +), +printing_releasers AS ( + SELECT card_id, + ARRAY_AGG( + DISTINCT released_by + ORDER BY released_by + ) as releasers + FROM printings + GROUP BY card_id +), +card_sets_summary AS ( + SELECT c.id, + ARRAY_AGG( + cs.id + ORDER BY cs.date_release DESC + ) as card_set_ids, + ARRAY_AGG( + cs.name + ORDER BY cs.date_release DESC + ) as card_set_names + FROM cards c + JOIN printings p ON c.id = p.card_id + JOIN card_sets cs ON p.card_set_id = cs.id + GROUP BY c.id +), +card_subtype_ids AS ( + SELECT card_id, + ARRAY_AGG( + card_subtype_id + ORDER BY 1 + ) as card_subtype_ids + FROM cards_card_subtypes + GROUP BY card_id +), +card_subtype_names AS ( + SELECT ccs.card_id, + -- lower used for filtering + ARRAY_AGG( + LOWER(cs.name) + ORDER BY LOWER(cs.name) + ) as lower_card_subtype_names, + -- proper case used for display + ARRAY_AGG( + cs.name + ORDER BY cs.name + ) as card_subtype_names + FROM cards_card_subtypes ccs + JOIN card_subtypes cs ON ccs.card_subtype_id = cs.id + GROUP BY ccs.card_id +), +card_printing_ids AS ( + SELECT card_id, + ARRAY_AGG( + id + ORDER BY date_release DESC + ) as printing_ids + FROM printings + GROUP BY card_id +), +card_release_dates AS ( + SELECT card_id, + MIN(date_release) as date_release + FROM printings + GROUP BY card_id +), +card_restriction_ids AS ( + SELECT card_id, + ARRAY_AGG( + restriction_id + ORDER BY restriction_id + ) as restriction_ids + FROM unified_restrictions + WHERE in_restriction + GROUP BY 1 +), +restrictions_banned_summary AS ( + SELECT card_id, + ARRAY_AGG( + restriction_id + ORDER BY restriction_id + ) as restrictions_banned + FROM restrictions_cards_banned + GROUP BY card_id +), +restrictions_global_penalty_summary AS ( + SELECT card_id, + ARRAY_AGG( + restriction_id + ORDER BY restriction_id + ) as restrictions_global_penalty + FROM restrictions_cards_global_penalty + GROUP BY card_id +), +restrictions_points_summary AS ( + SELECT card_id, + ARRAY_AGG( + CONCAT(restriction_id, '=', CAST (value AS text)) + ORDER BY CONCAT(restriction_id, '=', CAST (value AS text)) + ) as restrictions_points + FROM restrictions_cards_points + GROUP BY card_id +), +restrictions_restricted_summary AS ( + SELECT card_id, + ARRAY_AGG( + restriction_id + ORDER BY restriction_id + ) as restrictions_restricted + FROM restrictions_cards_restricted + GROUP BY card_id +), +restrictions_universal_faction_cost_summary AS ( + SELECT card_id, + ARRAY_AGG( + CONCAT(restriction_id, '=', CAST (value AS text)) + ORDER BY CONCAT(restriction_id, '=', CAST (value AS text)) + ) as restrictions_universal_faction_cost + FROM restrictions_cards_universal_faction_cost + GROUP BY card_id +), +format_ids AS ( + SELECT cpc.card_id, + ARRAY_AGG( + DISTINCT s.format_id + ORDER BY s.format_id + ) as format_ids + FROM card_pools_cards cpc + JOIN snapshots s ON cpc.card_pool_id = s.card_pool_id + GROUP BY cpc.card_id +), +card_pool_ids AS ( + SELECT cpc.card_id, + ARRAY_AGG( + DISTINCT s.card_pool_id + ORDER BY s.card_pool_id + ) as card_pool_ids + FROM card_pools_cards cpc + JOIN snapshots s ON cpc.card_pool_id = s.card_pool_id + GROUP BY cpc.card_id +), +snapshot_ids AS ( + SELECT cpc.card_id, + ARRAY_AGG( + DISTINCT s.id + ORDER BY s.id + ) as snapshot_ids + FROM card_pools_cards cpc + JOIN snapshots s ON cpc.card_pool_id = s.card_pool_id + GROUP BY cpc.card_id +), +subtypes_for_faces AS ( + SELECT cf.card_id, + cf.face_index, + ARRAY_AGG( + cs.card_subtype_id + ORDER BY cs.card_subtype_id + ) as card_subtype_ids + FROM card_faces AS cf + LEFT JOIN card_faces_card_subtypes AS cs USING (card_id, face_index) + GROUP BY cf.card_id, + cf.face_index +), +faces AS ( + SELECT cf.card_id, + ARRAY_AGG( + cf.face_index + ORDER BY cf.face_index + ) AS face_index, + ARRAY_AGG( + cf.base_link + ORDER BY cf.face_index + ) AS base_link, + ARRAY_AGG( + cf.display_subtypes + ORDER BY cf.face_index + ) AS display_subtypes, + ARRAY_AGG( + COALESCE(cs.card_subtype_ids, ARRAY []::text []) + ORDER BY cs.face_index + ) AS card_subtype_ids, + ARRAY_AGG( + cf.stripped_text + ORDER BY cf.face_index + ) AS stripped_text, + ARRAY_AGG( + cf.stripped_title + ORDER BY cf.face_index + ) AS stripped_title, + ARRAY_AGG( + cf.text + ORDER BY cf.face_index + ) AS text, + ARRAY_AGG( + cf.title + ORDER BY cf.face_index + ) AS title + FROM card_faces AS cf + LEFT JOIN subtypes_for_faces AS cs ON cf.card_id = cs.card_id + AND cf.face_index = cs.face_index + GROUP BY cf.card_id +), +unified AS ( + SELECT c.id as id, + c.title, + c.stripped_title, + c.card_type_id, + c.side_id, + c.faction_id, + c.advancement_requirement, + c.agenda_points, + c.base_link, + c.cost, + c.deck_limit, + c.influence_cost, + c.influence_limit, + c.memory_cost, + c.minimum_deck_size, + c.narrative_text, + c.pronouns, + c.pronunciation_approximation, + c.pronunciation_ipa, + c.strength, + c.stripped_text, + c.text, + c.trash_cost, + c.is_unique, + c.display_subtypes, + c.attribution, + c.created_at, + c.updated_at, + c.additional_cost, + c.advanceable, + c.gains_subroutines, + c.interrupt, + c.link_provided, + c.mu_provided, + c.num_printed_subroutines, + c.on_encounter_effect, + c.performs_trace, + c.recurring_credits_provided, + c.rez_effect, + c.trash_ability, + COALESCE(csi.card_subtype_ids, ARRAY []::text []) as card_subtype_ids, + COALESCE( + csn.lower_card_subtype_names, + ARRAY []::text [] + ) as lower_card_subtype_names, + COALESCE(csn.card_subtype_names, ARRAY []::text []) as card_subtype_names, + p.printing_ids, + ARRAY_LENGTH(p.printing_ids, 1) AS num_printings, + ccs.card_cycle_ids, + ccs.card_cycle_names, + css.card_set_ids, + css.card_set_names, + COALESCE(r.restriction_ids, ARRAY []::text []) as restriction_ids, + r.restriction_ids IS NOT NULL as in_restriction, + COALESCE(r_b.restrictions_banned, ARRAY []::text []) as restrictions_banned, + COALESCE( + r_g_p.restrictions_global_penalty, + ARRAY []::text [] + ) as restrictions_global_penalty, + COALESCE(r_p.restrictions_points, ARRAY []::text []) as restrictions_points, + COALESCE(r_r.restrictions_restricted, ARRAY []::text []) as restrictions_restricted, + COALESCE( + r_u_f_c.restrictions_universal_faction_cost, + ARRAY []::text [] + ) as restrictions_universal_faction_cost, + COALESCE(f.format_ids, ARRAY []::text []) as format_ids, + COALESCE(cpc.card_pool_ids, ARRAY []::text []) as card_pool_ids, + COALESCE(s.snapshot_ids, ARRAY []::text []) as snapshot_ids, + crd.date_release, + c.designed_by, + pr.releasers as printings_released_by, + c.layout_id + FROM cards c + JOIN card_printing_ids p ON c.id = p.card_id + JOIN card_cycles_summary ccs ON c.id = ccs.id + JOIN card_sets_summary css ON c.id = css.id + INNER JOIN printing_releasers pr ON c.id = pr.card_id + LEFT JOIN card_subtype_ids csi ON c.id = csi.card_id + LEFT JOIN card_subtype_names csn ON c.id = csn.card_id + LEFT JOIN card_restriction_ids r ON c.id = r.card_id + LEFT JOIN restrictions_banned_summary r_b ON c.id = r_b.card_id + LEFT JOIN restrictions_global_penalty_summary r_g_p ON c.id = r_g_p.card_id + LEFT JOIN restrictions_points_summary r_p ON c.id = r_p.card_id + LEFT JOIN restrictions_restricted_summary r_r ON c.id = r_r.card_id + LEFT JOIN restrictions_universal_faction_cost_summary r_u_f_c ON c.id = r_u_f_c.card_id + LEFT JOIN format_ids f ON c.id = f.card_id + LEFT JOIN card_pool_ids cpc ON c.id = cpc.card_id + LEFT JOIN snapshot_ids s ON c.id = s.card_id + LEFT JOIN card_release_dates crd ON c.id = crd.card_id + GROUP BY c.id, + c.title, + c.stripped_title, + c.card_type_id, + c.side_id, + c.faction_id, + c.advancement_requirement, + c.agenda_points, + c.base_link, + c.cost, + c.deck_limit, + c.influence_cost, + c.influence_limit, + c.layout_id, + c.memory_cost, + c.minimum_deck_size, + c.strength, + c.stripped_text, + c.text, + c.trash_cost, + c.is_unique, + c.display_subtypes, + c.attribution, + c.created_at, + c.updated_at, + c.additional_cost, + c.advanceable, + c.gains_subroutines, + c.interrupt, + c.link_provided, + c.mu_provided, + c.num_printed_subroutines, + c.on_encounter_effect, + c.performs_trace, + c.recurring_credits_provided, + c.rez_effect, + c.trash_ability, + csi.card_subtype_ids, + csn.lower_card_subtype_names, + csn.card_subtype_names, + p.printing_ids, + ccs.card_cycle_ids, + ccs.card_cycle_names, + css.card_set_ids, + css.card_set_names, + r.restriction_ids, + r_b.restrictions_banned, + r_g_p.restrictions_global_penalty, + r_p.restrictions_points, + r_r.restrictions_restricted, + r_u_f_c.restrictions_universal_faction_cost, + f.format_ids, + cpc.card_pool_ids, + s.snapshot_ids, + crd.date_release, + pr.releasers +) +SELECT u.id, + u.title, + u.stripped_title, + u.card_type_id, + u.side_id, + u.faction_id, + u.advancement_requirement, + u.agenda_points, + u.base_link, + u.cost, + u.deck_limit, + u.influence_cost, + u.influence_limit, + u.memory_cost, + u.minimum_deck_size, + u.pronouns, + u.pronunciation_approximation, + u.pronunciation_ipa, + u.strength, + u.stripped_text, + u.text, + u.trash_cost, + u.is_unique, + u.display_subtypes, + u.attribution, + u.created_at, + u.updated_at, + u.additional_cost, + u.advanceable, + u.gains_subroutines, + u.interrupt, + u.link_provided, + u.mu_provided, + u.num_printed_subroutines, + u.on_encounter_effect, + u.performs_trace, + u.recurring_credits_provided, + u.rez_effect, + u.trash_ability, + u.card_subtype_ids, + u.lower_card_subtype_names, + u.card_subtype_names, + u.printing_ids, + u.num_printings, + u.card_cycle_ids, + u.card_cycle_names, + u.card_set_ids, + u.card_set_names, + u.restriction_ids, + u.in_restriction, + u.restrictions_banned, + u.restrictions_global_penalty, + u.restrictions_points, + u.restrictions_restricted, + u.restrictions_universal_faction_cost, + u.format_ids, + u.card_pool_ids, + u.snapshot_ids, + u.date_release, + u.designed_by, + u.printings_released_by, + u.layout_id, + COALESCE(ARRAY_LENGTH(faces.face_index, 1), 0) as num_extra_faces, + faces.face_index as face_indices, + faces.base_link AS faces_base_link, + faces.display_subtypes AS faces_display_subtypes, + faces.card_subtype_ids AS faces_card_subtype_ids, + faces.stripped_text AS faces_stripped_text, + faces.stripped_title AS faces_stripped_title, + faces.text AS faces_text, + faces.title AS faces_title +FROM unified u + LEFT JOIN faces ON u.id = faces.card_id; diff --git a/db/views/unified_printings_v12.sql b/db/views/unified_printings_v12.sql new file mode 100644 index 0000000..14086af --- /dev/null +++ b/db/views/unified_printings_v12.sql @@ -0,0 +1,479 @@ +WITH card_cycles_summary AS ( + SELECT c.id, + ARRAY_AGG( + cc.id + ORDER BY cc.date_release DESC + ) as card_cycle_ids, + ARRAY_AGG( + cc.name + ORDER BY cc.date_release DESC + ) as card_cycle_names + FROM cards c + JOIN printings p ON c.id = p.card_id + JOIN card_sets cs ON p.card_set_id = cs.id + JOIN card_cycles cc ON cc.id = cs.card_cycle_id + GROUP BY c.id +), +card_sets_summary AS ( + SELECT c.id, + ARRAY_AGG( + cs.id + ORDER BY cs.date_release DESC + ) as card_set_ids, + ARRAY_AGG( + cs.name + ORDER BY cs.date_release DESC + ) as card_set_names + FROM cards c + JOIN printings p ON c.id = p.card_id + JOIN card_sets cs ON p.card_set_id = cs.id + GROUP BY c.id +), +card_subtype_ids AS ( + SELECT card_id, + ARRAY_AGG( + card_subtype_id + ORDER BY 1 + ) as card_subtype_ids + FROM cards_card_subtypes + GROUP BY card_id +), +card_subtype_names AS ( + SELECT ccs.card_id, + -- lower used for filtering + ARRAY_AGG( + LOWER(cs.name) + ORDER BY LOWER(cs.name) + ) as lower_card_subtype_names, + -- proper case used for display + ARRAY_AGG( + cs.name + ORDER BY cs.name + ) as card_subtype_names + FROM cards_card_subtypes ccs + JOIN card_subtypes cs ON ccs.card_subtype_id = cs.id + GROUP BY ccs.card_id +), +card_printing_ids AS ( + SELECT card_id, + ARRAY_AGG( + id + ORDER BY date_release DESC + ) as printing_ids + FROM printings + GROUP BY card_id +), +printing_releasers AS ( + SELECT card_id, + ARRAY_AGG( + DISTINCT released_by + ORDER BY released_by + ) as releasers + FROM printings + GROUP BY card_id +), +illustrators AS ( + SELECT ip.printing_id, + ARRAY_AGG( + ip.illustrator_id + ORDER BY ip.illustrator_id + ) as illustrator_ids, + ARRAY_AGG( + i.name + ORDER BY i.name + ) as illustrator_names + FROM illustrators_printings ip + JOIN illustrators i ON ip.illustrator_id = i.id + GROUP BY ip.printing_id +), +card_restriction_ids AS ( + SELECT card_id, + ARRAY_AGG( + restriction_id + ORDER BY restriction_id + ) as restriction_ids + FROM unified_restrictions + WHERE in_restriction + GROUP BY 1 +), +restrictions_banned_summary AS ( + SELECT card_id, + ARRAY_AGG( + restriction_id + ORDER BY restriction_id + ) as restrictions_banned + FROM restrictions_cards_banned + GROUP BY card_id +), +restrictions_global_penalty_summary AS ( + SELECT card_id, + ARRAY_AGG( + restriction_id + ORDER BY restriction_id + ) as restrictions_global_penalty + FROM restrictions_cards_global_penalty + GROUP BY card_id +), +restrictions_points_summary AS ( + SELECT card_id, + ARRAY_AGG( + CONCAT(restriction_id, '=', CAST (value AS text)) + ORDER BY CONCAT(restriction_id, '=', CAST (value AS text)) + ) as restrictions_points + FROM restrictions_cards_points + GROUP BY card_id +), +restrictions_restricted_summary AS ( + SELECT card_id, + ARRAY_AGG( + restriction_id + ORDER BY restriction_id + ) as restrictions_restricted + FROM restrictions_cards_restricted + GROUP BY card_id +), +restrictions_universal_faction_cost_summary AS ( + SELECT card_id, + ARRAY_AGG( + CONCAT(restriction_id, '=', CAST (value AS text)) + ORDER BY CONCAT(restriction_id, '=', CAST (value AS text)) + ) as restrictions_universal_faction_cost + FROM restrictions_cards_universal_faction_cost + GROUP BY card_id +), +format_ids AS ( + SELECT cpc.card_id, + ARRAY_AGG( + DISTINCT s.format_id + ORDER BY s.format_id + ) as format_ids + FROM card_pools_cards cpc + JOIN snapshots s ON cpc.card_pool_id = s.card_pool_id + GROUP BY cpc.card_id +), +card_pool_ids AS ( + SELECT cpc.card_id, + ARRAY_AGG( + DISTINCT s.card_pool_id + ORDER BY s.card_pool_id + ) as card_pool_ids + FROM card_pools_cards cpc + JOIN snapshots s ON cpc.card_pool_id = s.card_pool_id + GROUP BY cpc.card_id +), +snapshot_ids AS ( + SELECT cpc.card_id, + ARRAY_AGG( + DISTINCT s.id + ORDER BY s.id + ) as snapshot_ids + FROM card_pools_cards cpc + JOIN snapshots s ON cpc.card_pool_id = s.card_pool_id + GROUP BY cpc.card_id +), +subtypes_for_faces AS ( + SELECT cf.card_id, + cf.face_index, + ARRAY_AGG( + cs.card_subtype_id + ORDER BY cs.card_subtype_id + ) as card_subtype_ids + FROM card_faces AS cf + LEFT JOIN card_faces_card_subtypes AS cs USING (card_id, face_index) + GROUP BY cf.card_id, + cf.face_index +), +faces_for_cards AS ( + SELECT cf.card_id, + ARRAY_AGG( + cf.face_index + ORDER BY cf.face_index + ) AS face_index, + ARRAY_AGG( + cf.base_link + ORDER BY cf.face_index + ) AS base_link, + ARRAY_AGG( + cf.display_subtypes + ORDER BY cf.face_index + ) AS display_subtypes, + ARRAY_AGG( + COALESCE(cs.card_subtype_ids, ARRAY []::text []) + ORDER BY cs.face_index + ) AS card_subtype_ids, + ARRAY_AGG( + cf.stripped_text + ORDER BY cf.face_index + ) AS stripped_text, + ARRAY_AGG( + cf.stripped_title + ORDER BY cf.face_index + ) AS stripped_title, + ARRAY_AGG( + cf.text + ORDER BY cf.face_index + ) AS text, + ARRAY_AGG( + cf.title + ORDER BY cf.face_index + ) AS title + FROM card_faces AS cf + LEFT JOIN subtypes_for_faces AS cs ON cf.card_id = cs.card_id + AND cf.face_index = cs.face_index + GROUP BY cf.card_id +), +faces_for_printings AS ( + SELECT pf.printing_id, + ARRAY_AGG( + pf.face_index + ORDER BY pf.face_index + ) AS face_index, + ARRAY_AGG( + pf.copy_quantity + ORDER BY pf.face_index + ) AS copy_quantity, + ARRAY_AGG( + pf.flavor + ORDER BY pf.face_index + ) AS flavor + FROM printing_faces pf + GROUP BY pf.printing_id +), +combined_face_indexes AS ( + SELECT cf.card_id, + cf.face_index, + p.id AS printing_id, + NULL as val, + NULL::int as int_val + FROM card_faces AS cf + INNER JOIN printings AS p ON cf.card_id = p.card_id + UNION + DISTINCT + SELECT c.id AS card_id, + pf.face_index, + pf.printing_id, + NULL as val, + NULL::int as int_val + FROM printing_faces AS pf + INNER JOIN printings p ON pf.printing_id = p.id + INNER JOIN cards AS c ON c.id = p.card_id +), +faces_fallback AS ( + SELECT card_id, + printing_id, + COUNT(*) AS num_extra_faces, + ARRAY_AGG( + face_index + ORDER BY face_index + ) AS face_index, + ARRAY_AGG( + val + ORDER BY face_index + ) AS dummy_vals, + ARRAY_AGG( + int_val + ORDER BY face_index + ) AS dummy_int_vals + FROM combined_face_indexes + GROUP BY card_id, + printing_id +), +unified AS ( + SELECT p.id, + p.card_id, + cc.id as card_cycle_id, + cc.name as card_cycle_name, + p.card_set_id, + cs.name as card_set_name, + p.flavor, + p.display_illustrators, + p.position, + p.position_in_set, + p.quantity, + p.date_release, + p.created_at, + p.updated_at, + c.additional_cost, + c.advanceable, + c.advancement_requirement, + c.agenda_points, + c.base_link, + c.card_type_id, + c.cost, + c.faction_id, + c.gains_subroutines, + c.influence_cost, + c.interrupt, + c.is_unique, + c.link_provided, + c.memory_cost, + c.mu_provided, + c.narrative_text, + c.num_printed_subroutines, + c.on_encounter_effect, + c.performs_trace, + c.pronouns, + c.pronunciation_approximation, + c.pronunciation_ipa, + c.recurring_credits_provided, + c.side_id, + c.strength, + c.stripped_text, + c.stripped_title, + c.trash_ability, + c.trash_cost, + COALESCE(csi.card_subtype_ids, ARRAY []::text []) as card_subtype_ids, + COALESCE( + csn.lower_card_subtype_names, + ARRAY []::text [] + ) as lower_card_subtype_names, + COALESCE(csn.card_subtype_names, ARRAY []::text []) as card_subtype_names, + cp.printing_ids, + p.id = cp.printing_ids [1] AS is_latest_printing, + ARRAY_LENGTH(cp.printing_ids, 1) AS num_printings, + COALESCE(ccs.card_cycle_ids, ARRAY []::text []) as card_cycle_ids, + COALESCE(ccs.card_cycle_names, ARRAY []::text []) as card_cycle_names, + COALESCE(css.card_set_ids, ARRAY []::text []) as card_set_ids, + COALESCE(css.card_set_names, ARRAY []::text []) as card_set_names, + COALESCE(i.illustrator_ids, ARRAY []::text []) as illustrator_ids, + COALESCE(i.illustrator_names, ARRAY []::text []) as illustrator_names, + COALESCE(r.restriction_ids, ARRAY []::text []) as restriction_ids, + r.restriction_ids IS NOT NULL as in_restriction, + COALESCE(r_b.restrictions_banned, ARRAY []::text []) as restrictions_banned, + COALESCE( + r_g_p.restrictions_global_penalty, + ARRAY []::text [] + ) as restrictions_global_penalty, + COALESCE(r_p.restrictions_points, ARRAY []::text []) as restrictions_points, + COALESCE(r_r.restrictions_restricted, ARRAY []::text []) as restrictions_restricted, + COALESCE( + r_u_f_c.restrictions_universal_faction_cost, + ARRAY []::text [] + ) as restrictions_universal_faction_cost, + COALESCE(f.format_ids, ARRAY []::text []) as format_ids, + COALESCE(cpc.card_pool_ids, ARRAY []::text []) as card_pool_ids, + COALESCE(s.snapshot_ids, ARRAY []::text []) as snapshot_ids, + c.attribution, + c.deck_limit, + c.display_subtypes, + c.influence_limit, + c.minimum_deck_size, + c.rez_effect, + c.text, + c.title, + c.layout_id, + c.designed_by, + p.released_by, + pr.releasers as printings_released_by + FROM printings p + INNER JOIN cards c ON p.card_id = c.id + JOIN card_cycles_summary ccs ON c.id = ccs.id + JOIN card_sets_summary css ON c.id = css.id + INNER JOIN card_sets cs ON p.card_set_id = cs.id + INNER JOIN card_cycles cc ON cs.card_cycle_id = cc.id + LEFT JOIN card_subtype_ids csi ON c.id = csi.card_id + LEFT JOIN card_subtype_names csn ON c.id = csn.card_id + INNER JOIN card_printing_ids cp ON p.card_id = cp.card_id + INNER JOIN printing_releasers pr ON p.card_id = pr.card_id + LEFT JOIN illustrators i ON p.id = i.printing_id + LEFT JOIN card_restriction_ids r ON p.card_id = r.card_id + LEFT JOIN restrictions_banned_summary r_b ON p.card_id = r_b.card_id + LEFT JOIN restrictions_global_penalty_summary r_g_p ON p.card_id = r_g_p.card_id + LEFT JOIN restrictions_points_summary r_p ON p.card_id = r_p.card_id + LEFT JOIN restrictions_restricted_summary r_r ON p.card_id = r_r.card_id + LEFT JOIN restrictions_universal_faction_cost_summary r_u_f_c ON p.card_id = r_u_f_c.card_id + LEFT JOIN format_ids f ON p.card_id = f.card_id + LEFT JOIN card_pool_ids cpc ON p.card_id = cpc.card_id + LEFT JOIN snapshot_ids s ON p.card_id = s.card_id +) +SELECT u.id, + u.card_id, + u.card_cycle_id, + u.card_cycle_name, + u.card_set_id, + u.card_set_name, + u.flavor, + u.display_illustrators, + u.position, + u.position_in_set, + u.quantity, + u.date_release, + u.created_at, + u.updated_at, + u.additional_cost, + u.advanceable, + u.advancement_requirement, + u.agenda_points, + u.base_link, + u.card_type_id, + u.cost, + u.faction_id, + u.gains_subroutines, + u.influence_cost, + u.interrupt, + u.is_unique, + u.link_provided, + u.memory_cost, + u.mu_provided, + u.num_printed_subroutines, + u.on_encounter_effect, + u.performs_trace, + u.pronouns, + u.pronunciation_approximation, + u.pronunciation_ipa, + u.recurring_credits_provided, + u.side_id, + u.strength, + u.stripped_text, + u.stripped_title, + u.trash_ability, + u.trash_cost, + u.card_subtype_ids, + u.lower_card_subtype_names, + u.card_subtype_names, + u.printing_ids, + u.is_latest_printing, + u.num_printings, + u.card_cycle_ids, + u.card_cycle_names, + u.card_set_ids, + u.card_set_names, + u.illustrator_ids, + u.illustrator_names, + u.restriction_ids, + u.in_restriction, + u.restrictions_banned, + u.restrictions_global_penalty, + u.restrictions_points, + u.restrictions_restricted, + u.restrictions_universal_faction_cost, + u.format_ids, + u.card_pool_ids, + u.snapshot_ids, + u.attribution, + u.deck_limit, + u.display_subtypes, + u.influence_limit, + u.minimum_deck_size, + u.rez_effect, + u.text, + u.title, + u.designed_by, + u.released_by, + u.printings_released_by, + u.layout_id, + COALESCE(ff.num_extra_faces, 0) AS num_extra_faces, + ff.face_index as face_indices, + COALESCE(cf.base_link, ff.dummy_vals) AS faces_base_link, + COALESCE(cf.display_subtypes, ff.dummy_vals) AS faces_display_subtypes, + COALESCE(cf.card_subtype_ids, ff.dummy_vals) AS faces_card_subtype_ids, + COALESCE(cf.stripped_text, ff.dummy_vals) AS faces_stripped_text, + COALESCE(cf.stripped_title, ff.dummy_vals) AS faces_stripped_title, + COALESCE(cf.text, ff.dummy_vals) AS faces_text, + COALESCE(cf.title, ff.dummy_vals) AS faces_title, + COALESCE(pf.copy_quantity, ff.dummy_int_vals) AS faces_copy_quantity, + COALESCE(pf.flavor, ff.dummy_vals) AS faces_flavor +FROM unified AS u + LEFT JOIN faces_for_cards AS cf ON u.card_id = cf.card_id + LEFT JOIN faces_for_printings AS pf ON u.id = pf.printing_id + LEFT JOIN faces_fallback AS ff ON u.id = ff.printing_id; diff --git a/lib/tasks/cards.rake b/lib/tasks/cards.rake index b7ba46c..348cbf2 100644 --- a/lib/tasks/cards.rake +++ b/lib/tasks/cards.rake @@ -103,6 +103,7 @@ namespace :cards do influence_limit: card['influence_limit'], memory_cost: card['memory_cost'], minimum_deck_size: card['minimum_deck_size'], + narrative_text: card['narrative_text'], pronouns: card['pronouns'], pronunciation_approximation: card['pronunciation_approx'], pronunciation_ipa: card['pronunciation_ipa'], From e8e8bd83e30a0e3e841149c76ca312a911019b4d Mon Sep 17 00:00:00 2001 From: talhaahsan Date: Mon, 23 Jun 2025 17:29:50 +0000 Subject: [PATCH 2/4] re-migrate and it works --- app/controllers/cards_controller.rb | 1 - db/schema.rb | 2 ++ db/views/unified_cards_v10.sql | 1 + db/views/unified_printings_v12.sql | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/cards_controller.rb b/app/controllers/cards_controller.rb index 2933e90..89b0379 100644 --- a/app/controllers/cards_controller.rb +++ b/app/controllers/cards_controller.rb @@ -5,7 +5,6 @@ class CardsController < ApplicationController def index add_total_stat(params) cards = CardResource.all(params) - debugger respond_with(cards) end diff --git a/db/schema.rb b/db/schema.rb index c6ac02f..b12ac26 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -677,6 +677,7 @@ u.influence_limit, u.memory_cost, u.minimum_deck_size, + u.narrative_text, u.pronouns, u.pronunciation_approximation, u.pronunciation_ipa, @@ -1014,6 +1015,7 @@ u.memory_cost, u.mu_provided, u.num_printed_subroutines, + u.narrative_text, u.on_encounter_effect, u.performs_trace, u.pronouns, diff --git a/db/views/unified_cards_v10.sql b/db/views/unified_cards_v10.sql index a8dca55..804f2cf 100644 --- a/db/views/unified_cards_v10.sql +++ b/db/views/unified_cards_v10.sql @@ -376,6 +376,7 @@ SELECT u.id, u.influence_limit, u.memory_cost, u.minimum_deck_size, + u.narrative_text, u.pronouns, u.pronunciation_approximation, u.pronunciation_ipa, diff --git a/db/views/unified_printings_v12.sql b/db/views/unified_printings_v12.sql index 14086af..677dcc6 100644 --- a/db/views/unified_printings_v12.sql +++ b/db/views/unified_printings_v12.sql @@ -416,6 +416,7 @@ SELECT u.id, u.memory_cost, u.mu_provided, u.num_printed_subroutines, + u.narrative_text, u.on_encounter_effect, u.performs_trace, u.pronouns, From e3ed0a6fd60000e4ac0d1c762fba1d2058142078 Mon Sep 17 00:00:00 2001 From: talhaahsan Date: Mon, 23 Jun 2025 17:34:16 +0000 Subject: [PATCH 3/4] lint bump --- db/migrate/20250623035203_add_narrative_to_cards.rb | 2 ++ .../20250623035759_update_unified_cards_to_version_10.rb | 8 +++++--- ...250623035928_update_unified_printings_to_version_12.rb | 8 +++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/db/migrate/20250623035203_add_narrative_to_cards.rb b/db/migrate/20250623035203_add_narrative_to_cards.rb index ec6677a..0953c67 100644 --- a/db/migrate/20250623035203_add_narrative_to_cards.rb +++ b/db/migrate/20250623035203_add_narrative_to_cards.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddNarrativeToCards < ActiveRecord::Migration[7.2] def change add_column :cards, :narrative_text, :string diff --git a/db/migrate/20250623035759_update_unified_cards_to_version_10.rb b/db/migrate/20250623035759_update_unified_cards_to_version_10.rb index fa73f18..9b03ba6 100644 --- a/db/migrate/20250623035759_update_unified_cards_to_version_10.rb +++ b/db/migrate/20250623035759_update_unified_cards_to_version_10.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + class UpdateUnifiedCardsToVersion10 < ActiveRecord::Migration[7.2] def change update_view :unified_cards, - version: 10, - revert_to_version: 9, - materialized: true + version: 10, + revert_to_version: 9, + materialized: true end end diff --git a/db/migrate/20250623035928_update_unified_printings_to_version_12.rb b/db/migrate/20250623035928_update_unified_printings_to_version_12.rb index 299ff70..486323a 100644 --- a/db/migrate/20250623035928_update_unified_printings_to_version_12.rb +++ b/db/migrate/20250623035928_update_unified_printings_to_version_12.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + class UpdateUnifiedPrintingsToVersion12 < ActiveRecord::Migration[7.2] def change update_view :unified_printings, - version: 12, - revert_to_version: 11, - materialized: true + version: 12, + revert_to_version: 11, + materialized: true end end From 2e1fba566c0a95eef15bb7681d1b330be85e2865 Mon Sep 17 00:00:00 2001 From: talhaahsan Date: Mon, 23 Jun 2025 17:36:28 +0000 Subject: [PATCH 4/4] lint bump2 --- db/migrate/20250623035203_add_narrative_to_cards.rb | 2 +- db/migrate/20250623035759_update_unified_cards_to_version_10.rb | 2 +- .../20250623035928_update_unified_printings_to_version_12.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/db/migrate/20250623035203_add_narrative_to_cards.rb b/db/migrate/20250623035203_add_narrative_to_cards.rb index 0953c67..dc6d678 100644 --- a/db/migrate/20250623035203_add_narrative_to_cards.rb +++ b/db/migrate/20250623035203_add_narrative_to_cards.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class AddNarrativeToCards < ActiveRecord::Migration[7.2] +class AddNarrativeToCards < ActiveRecord::Migration[7.2] # rubocop:disable Style/Documentation def change add_column :cards, :narrative_text, :string end diff --git a/db/migrate/20250623035759_update_unified_cards_to_version_10.rb b/db/migrate/20250623035759_update_unified_cards_to_version_10.rb index 9b03ba6..6cf5256 100644 --- a/db/migrate/20250623035759_update_unified_cards_to_version_10.rb +++ b/db/migrate/20250623035759_update_unified_cards_to_version_10.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class UpdateUnifiedCardsToVersion10 < ActiveRecord::Migration[7.2] +class UpdateUnifiedCardsToVersion10 < ActiveRecord::Migration[7.2] # rubocop:disable Style/Documentation def change update_view :unified_cards, version: 10, diff --git a/db/migrate/20250623035928_update_unified_printings_to_version_12.rb b/db/migrate/20250623035928_update_unified_printings_to_version_12.rb index 486323a..02c3305 100644 --- a/db/migrate/20250623035928_update_unified_printings_to_version_12.rb +++ b/db/migrate/20250623035928_update_unified_printings_to_version_12.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class UpdateUnifiedPrintingsToVersion12 < ActiveRecord::Migration[7.2] +class UpdateUnifiedPrintingsToVersion12 < ActiveRecord::Migration[7.2] # rubocop:disable Style/Documentation def change update_view :unified_printings, version: 12,