Skip to content

Commit 6e1bd90

Browse files
authored
Merge pull request #106 from distributive/main
Flattened global penalty field to array instead of a mapping
2 parents 96dd8a6 + 47db473 commit 6e1bd90

13 files changed

+167
-87
lines changed

app/resources/api/v3/public/format_resource.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module Public
44
class Api::V3::Public::FormatResource < JSONAPI::Resource
55
immutable
66

7-
attributes :name, :active_snapshot_id, :snapshot_ids, :updated_at
7+
attributes :name, :active_snapshot_id, :snapshot_ids, :restriction_ids, :updated_at
88
attributes :active_card_pool_id, :active_restriction_id
99
key_type :string
1010

app/resources/api/v3/public/restriction_resource.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def verdicts
1717
{ 'banned': @model.banned_cards.pluck(:card_id),
1818
'restricted': @model.restricted_cards.pluck(:card_id),
1919
'universal_faction_cost': Hash[@model.universal_faction_cost_cards.pluck(:value, :card_id).group_by(&:first).map{ |k,a| [k,a.map(&:last)] }],
20-
'global_penalty': Hash[@model.global_penalty_cards.pluck(:value, :card_id).group_by(&:first).map{ |k,a| [k,a.map(&:last)] }],
20+
'global_penalty': @model.global_penalty_cards.pluck(:card_id),
2121
'points': Hash[@model.points_cards.pluck(:value, :card_id).group_by(&:first).map{ |k,a| [k,a.map(&:last)] }]
2222
}
2323
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class UpdateUnifiedRestrictionsToVersion4 < ActiveRecord::Migration[7.0]
2+
def change
3+
update_view :unified_restrictions, materialized: true, version: 4, revert_to_version: 3
4+
end
5+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class RemoveValueFromRestrictionsCardsGlobalPenalty < ActiveRecord::Migration[7.0]
2+
def change
3+
remove_column :restrictions_cards_global_penalty, :value
4+
end
5+
end

db/schema.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema[7.0].define(version: 2022_09_23_032558) do
13+
ActiveRecord::Schema[7.0].define(version: 2022_09_25_225117) do
1414
# These are extensions that must be enabled in order to support this database
1515
enable_extension "plpgsql"
1616

@@ -195,7 +195,6 @@
195195
create_table "restrictions_cards_global_penalty", id: false, force: :cascade do |t|
196196
t.text "restriction_id", null: false
197197
t.text "card_id", null: false
198-
t.integer "value", null: false
199198
t.datetime "created_at", null: false
200199
t.datetime "updated_at", null: false
201200
end
@@ -301,7 +300,10 @@
301300
ELSE false
302301
END AS is_restricted,
303302
COALESCE(restrictions_cards_points.value, 0) AS eternal_points,
304-
COALESCE(restrictions_cards_global_penalty.value, 0) AS global_penalty,
303+
CASE
304+
WHEN (restrictions_cards_global_penalty.restriction_id IS NOT NULL) THEN true
305+
ELSE false
306+
END AS has_global_penalty,
305307
COALESCE(restrictions_cards_universal_faction_cost.value, 0) AS universal_faction_cost
306308
FROM ((((((cards_cross_restrictions_and_snapshots
307309
JOIN card_pools_cards ON (((card_pools_cards.card_pool_id = cards_cross_restrictions_and_snapshots.card_pool_id) AND (card_pools_cards.card_id = (cards_cross_restrictions_and_snapshots.card_id)::text))))

db/views/unified_restrictions_v04.sql

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
WITH cards_cross_restrictions_and_snapshots AS (
2+
SELECT
3+
cards.id as card_id,
4+
restrictions.id as restriction_id,
5+
snapshots.id as snapshot_id,
6+
snapshots.format_id as format_id,
7+
snapshots.card_pool_id as card_pool_id,
8+
snapshots.date_start as snapshot_date_start
9+
FROM
10+
cards, restrictions JOIN snapshots ON restrictions.id = snapshots.restriction_id
11+
)
12+
SELECT
13+
cards_cross_restrictions_and_snapshots.format_id,
14+
cards_cross_restrictions_and_snapshots.card_pool_id,
15+
cards_cross_restrictions_and_snapshots.snapshot_id,
16+
cards_cross_restrictions_and_snapshots.snapshot_date_start,
17+
cards_cross_restrictions_and_snapshots.restriction_id,
18+
cards_cross_restrictions_and_snapshots.card_id,
19+
restrictions_cards_banned.restriction_id IS NOT NULL
20+
OR restrictions_cards_restricted.restriction_id IS NOT NULL
21+
OR restrictions_cards_points.restriction_id IS NOT NULL
22+
OR restrictions_cards_global_penalty.restriction_id IS NOT NULL
23+
OR restrictions_cards_universal_faction_cost.restriction_id IS NOT NULL
24+
as in_restriction,
25+
CASE WHEN restrictions_cards_banned.restriction_id IS NOT NULL THEN true ELSE false END AS is_banned,
26+
CASE WHEN restrictions_cards_restricted.restriction_id IS NOT NULL THEN true ELSE false END AS is_restricted,
27+
COALESCE(restrictions_cards_points.value, 0) AS eternal_points,
28+
CASE WHEN restrictions_cards_global_penalty.restriction_id IS NOT NULL THEN true ELSE false END AS has_global_penalty,
29+
COALESCE(restrictions_cards_universal_faction_cost.value, 0) AS universal_faction_cost
30+
FROM
31+
cards_cross_restrictions_and_snapshots
32+
JOIN card_pools_cards ON card_pools_cards.card_pool_id = cards_cross_restrictions_and_snapshots.card_pool_id
33+
AND card_pools_cards.card_id = cards_cross_restrictions_and_snapshots.card_id
34+
LEFT OUTER JOIN restrictions_cards_banned ON
35+
restrictions_cards_banned.restriction_id = cards_cross_restrictions_and_snapshots.restriction_id
36+
AND restrictions_cards_banned.card_id = cards_cross_restrictions_and_snapshots.card_id
37+
LEFT OUTER JOIN restrictions_cards_points ON
38+
restrictions_cards_points.restriction_id = cards_cross_restrictions_and_snapshots.restriction_id
39+
AND restrictions_cards_points.card_id = cards_cross_restrictions_and_snapshots.card_id
40+
LEFT OUTER JOIN restrictions_cards_global_penalty ON
41+
restrictions_cards_global_penalty.restriction_id = cards_cross_restrictions_and_snapshots.restriction_id
42+
AND restrictions_cards_global_penalty.card_id = cards_cross_restrictions_and_snapshots.card_id
43+
LEFT OUTER JOIN restrictions_cards_restricted ON
44+
restrictions_cards_restricted.restriction_id = cards_cross_restrictions_and_snapshots.restriction_id
45+
AND restrictions_cards_restricted.card_id = cards_cross_restrictions_and_snapshots.card_id
46+
LEFT OUTER JOIN restrictions_cards_universal_faction_cost ON
47+
restrictions_cards_universal_faction_cost.restriction_id = cards_cross_restrictions_and_snapshots.restriction_id
48+
AND restrictions_cards_universal_faction_cost.card_id = cards_cross_restrictions_and_snapshots.card_id
49+
;

lib/card_search_parser.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class CardSearchParser < Parslet::Parser
3131
str('faction') |
3232
str('format') |
3333
str('gains_subroutines') |
34-
str('global_penalty') |
34+
str('has_global_penalty') |
3535
str('illustrator') |
3636
str('in_restriction') |
3737
str('influence_cost') |

lib/card_search_query_builder.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class CardSearchQueryBuilder
66
'b',
77
'banlist',
88
'gains_subroutines',
9+
'has_global_penalty',
910
'in_restriction',
1011
'interrupt',
1112
'is_banned',
@@ -23,7 +24,6 @@ class CardSearchQueryBuilder
2324
'cost',
2425
'eternal_points',
2526
'g',
26-
'global_penalty',
2727
'h',
2828
'influence_cost',
2929
'l',
@@ -89,8 +89,8 @@ class CardSearchQueryBuilder
8989
'format' => 'unified_restrictions.format_id',
9090
'g' => 'cards.advancement_requirement',
9191
'gains_subroutines' => 'cards.gains_subroutines',
92-
'global_penalty' => 'unified_restrictions.global_penalty',
9392
'h' => 'cards.trash_cost',
93+
'has_global_penalty' => 'unified_restrictions.has_global_penalty',
9494
'in_restriction' => 'unified_restrictions.in_restriction',
9595
'influence_cost' => 'cards.influence_cost',
9696
'interrupt' => 'cards.interrupt',
@@ -128,7 +128,7 @@ class CardSearchQueryBuilder
128128
'card_pool' => :card_pool_cards,
129129
'card_subtype' => :card_subtypes,
130130
'eternal_points' => :unified_restrictions,
131-
'global_penalty' => :unified_restrictions,
131+
'has_global_penalty' => :unified_restrictions,
132132
'in_restriction' => :unified_restrictions,
133133
'is_banned' => :unified_restrictions,
134134
'is_restricted' => :unified_restrictions,
@@ -141,7 +141,7 @@ def initialize(query)
141141
@query = query
142142
@parse_error = nil
143143
@parse_tree = nil
144-
@left_joins = Set.new
144+
@left_joins = Set.new
145145
@where = ''
146146
@where_values = []
147147
begin
@@ -155,8 +155,8 @@ def initialize(query)
155155
constraints = []
156156
where = []
157157
# TODO(plural): build in explicit support for requirements
158-
# {is_banned,is_restricted,eternal_points,global_penalty,universal_faction_cost} all require restriction_id, would be good to have card_pool_id as well.
159-
# TODO(plural): build in explicit support for smart defaults, like restriction_id should imply is_banned = false. card_pool_id should imply the latest restriction list.
158+
# {is_banned,is_restricted,eternal_points,has_global_penalty,universal_faction_cost} all require restriction_id, would be good to have card_pool_id as well.
159+
# TODO(plural): build in explicit support for smart defaults, like restriction_id should imply is_banned = false. card_pool_id should imply the latest restriction list.
160160
@parse_tree[:fragments].each {|f|
161161
if f.include?(:search_term)
162162
keyword = f[:search_term][:keyword].to_s
@@ -180,7 +180,7 @@ def initialize(query)
180180
if !value.match?(/\A(\d+|x)\Z/i)
181181
@parse_error = 'Invalid value "%s" for integer field "%s"' % [value, keyword]
182182
return
183-
end
183+
end
184184
operator = ''
185185
if @@numeric_operators.include?(match_type)
186186
operator = @@numeric_operators[match_type]
@@ -192,7 +192,7 @@ def initialize(query)
192192
where << (value.downcase == 'x' ? -1 : value)
193193
else
194194
# String fields only support : and !, resolving to to {,NOT} LIKE %value%.
195-
# TODO(plural): consider ~ for regex matches.
195+
# TODO(plural): consider ~ for regex matches.
196196
operator = ''
197197
if @@string_operators.include?(match_type)
198198
operator = @@string_operators[match_type]
@@ -205,7 +205,7 @@ def initialize(query)
205205
end
206206
if @@term_to_left_join_map.include?(keyword)
207207
@left_joins << @@term_to_left_join_map[keyword]
208-
end
208+
end
209209
end
210210

211211
# bare/quoted words in the query are automatically mapped to stripped_title
@@ -214,7 +214,7 @@ def initialize(query)
214214
operator = value.start_with?('!') ? 'NOT LIKE' : 'LIKE'
215215
value = value.start_with?('!') ? value[1..] : value
216216
constraints << 'lower(cards.stripped_title) %s ?' % operator
217-
where << '%%%s%%' % value
217+
where << '%%%s%%' % value
218218
end
219219
}
220220
@where = constraints.join(' AND ')

lib/printing_search_parser.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class PrintingSearchParser < Parslet::Parser
3434
str('flavor') |
3535
str('format') |
3636
str('gains_subroutines') |
37-
str('global_penalty') |
37+
str('has_global_penalty') |
3838
str('illustrator') |
3939
str('in_restriction') |
4040
str('influence_cost') |

lib/printing_search_query_builder.rb

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class PrintingSearchQueryBuilder
66
'b',
77
'banlist',
88
'gains_subroutines',
9+
'has_global_penalty',
910
'in_restriction',
1011
'interrupt',
1112
'is_banned',
@@ -27,7 +28,6 @@ class PrintingSearchQueryBuilder
2728
'cost',
2829
'eternal_points',
2930
'g',
30-
'global_penalty',
3131
'h',
3232
'influence_cost',
3333
'l',
@@ -113,7 +113,7 @@ class PrintingSearchQueryBuilder
113113
'format' => 'unified_restrictions.format_id',
114114
'g' => 'cards.advancement_requirement',
115115
'gains_subroutines' => 'cards.gains_subroutines',
116-
'global_penalty' => 'unified_restrictions.global_penalty',
116+
'has_global_penalty' => 'unified_restrictions.has_global_penalty',
117117
'h' => 'cards.trash_cost',
118118
'i' => 'illustrators.name',
119119
'illustrator' => 'illustrators.name',
@@ -175,7 +175,7 @@ class PrintingSearchQueryBuilder
175175
'format' => :unified_restrictions,
176176
'g' => :card,
177177
'gains_subroutines' => :card,
178-
'global_penalty' => :unified_restrictions,
178+
'has_global_penalty' => :unified_restrictions,
179179
'h' => :card,
180180
'i' => :illustrators,
181181
'illustrator' => :illustrators,
@@ -216,7 +216,7 @@ def initialize(query)
216216
@query = query
217217
@parse_error = nil
218218
@parse_tree = nil
219-
@left_joins = Set.new
219+
@left_joins = Set.new
220220
@where = ''
221221
@where_values = []
222222
begin
@@ -230,8 +230,8 @@ def initialize(query)
230230
constraints = []
231231
where = []
232232
# TODO(plural): build in explicit support for requirements
233-
# {is_banned,is_restricted,eternal_points,global_penalty,universal_faction_cost} all require restriction_id, would be good to have card_pool_id as well.
234-
# TODO(plural): build in explicit support for smart defaults, like restriction_id should imply is_banned = false. card_pool_id should imply the latest restriction list.
233+
# {is_banned,is_restricted,eternal_points,has_global_penalty,universal_faction_cost} all require restriction_id, would be good to have card_pool_id as well.
234+
# TODO(plural): build in explicit support for smart defaults, like restriction_id should imply is_banned = false. card_pool_id should imply the latest restriction list.
235235
@parse_tree[:fragments].each {|f|
236236
if f.include?(:search_term)
237237
keyword = f[:search_term][:keyword].to_s
@@ -255,7 +255,7 @@ def initialize(query)
255255
if !value.match?(/\A(\d{4}-\d{2}-\d{2}|\d{8})\Z/)
256256
@parse_error = 'Invalid value "%s" for date field "%s" - only YYYY-MM-DD or YYYYMMDD are supported.' % [value, keyword]
257257
return
258-
end
258+
end
259259
operator = ''
260260
if @@date_operators.include?(match_type)
261261
operator = @@date_operators[match_type]
@@ -264,12 +264,12 @@ def initialize(query)
264264
return
265265
end
266266
constraints << '%s %s ?' % [@@term_to_field_map[keyword], operator]
267-
where << value
267+
where << value
268268
elsif @@numeric_keywords.include?(keyword)
269269
if !value.match?(/\A(\d+|x)\Z/i)
270270
@parse_error = 'Invalid value "%s" for integer field "%s"' % [value, keyword]
271271
return
272-
end
272+
end
273273
operator = ''
274274
if @@numeric_operators.include?(match_type)
275275
operator = @@numeric_operators[match_type]
@@ -281,7 +281,7 @@ def initialize(query)
281281
where << (value.downcase == 'x' ? -1 : value)
282282
else
283283
# String fields only support : and !, resolving to to {,NOT} LIKE %value%.
284-
# TODO(plural): consider ~ for regex matches.
284+
# TODO(plural): consider ~ for regex matches.
285285
operator = ''
286286
if @@string_operators.include?(match_type)
287287
operator = @@string_operators[match_type]
@@ -294,7 +294,7 @@ def initialize(query)
294294
end
295295
if @@term_to_left_join_map.include?(keyword)
296296
@left_joins << @@term_to_left_join_map[keyword]
297-
end
297+
end
298298
end
299299

300300
# bare/quoted words in the query are automatically mapped to stripped_title
@@ -303,7 +303,7 @@ def initialize(query)
303303
operator = value.start_with?('!') ? 'NOT LIKE' : 'LIKE'
304304
value = value.start_with?('!') ? value[1..] : value
305305
constraints << 'lower(cards.stripped_title) %s ?' % operator
306-
where << '%%%s%%' % value
306+
where << '%%%s%%' % value
307307
end
308308
}
309309
@where = constraints.join(' AND ')

lib/tasks/cards.rake

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,8 +570,7 @@ namespace :cards do
570570
cards.each do |card|
571571
global_penalty << RestrictionCardGlobalPenalty.new(
572572
restriction_id: r['id'],
573-
card_id: card,
574-
value: cost
573+
card_id: card
575574
)
576575
end
577576
end

0 commit comments

Comments
 (0)