Trading card city builder game?

add card frequencies data to pack banners

+150 -38
+43 -7
generated/schema.sql
··· 237 237 238 238 239 239 -- 240 + -- Name: pack_banner_cards; Type: TABLE; Schema: public; Owner: - 241 + -- 242 + 243 + CREATE TABLE public.pack_banner_cards ( 244 + pack_banner_id text NOT NULL, 245 + card_type_id text NOT NULL, 246 + frequency integer NOT NULL, 247 + CONSTRAINT pack_banner_cards_frequency_check CHECK ((frequency > 0)) 248 + ); 249 + 250 + 251 + -- 252 + -- Name: TABLE pack_banner_cards; Type: COMMENT; Schema: public; Owner: - 253 + -- 254 + 255 + COMMENT ON TABLE public.pack_banner_cards IS 'Lists relative frequencies of cards available to be pulled from each banner.'; 256 + 257 + 258 + -- 240 259 -- Name: pack_banners; Type: TABLE; Schema: public; Owner: - 241 260 -- 242 261 ··· 534 553 535 554 536 555 -- 556 + -- Name: pack_banner_cards pack_banner_cards_pkey; Type: CONSTRAINT; Schema: public; Owner: - 557 + -- 558 + 559 + ALTER TABLE ONLY public.pack_banner_cards 560 + ADD CONSTRAINT pack_banner_cards_pkey PRIMARY KEY (pack_banner_id, card_type_id); 561 + 562 + 563 + -- 537 564 -- Name: pack_banners pack_banners_pkey; Type: CONSTRAINT; Schema: public; Owner: - 538 565 -- 539 566 ··· 611 638 612 639 ALTER TABLE ONLY public.tiles 613 640 ADD CONSTRAINT tiles_pkey PRIMARY KEY (id); 614 - 615 - 616 - -- 617 - -- Name: accounts_id_case_insensitive; Type: INDEX; Schema: public; Owner: - 618 - -- 619 - 620 - CREATE UNIQUE INDEX accounts_id_case_insensitive ON public.accounts USING btree (lower((id)::text)); 621 641 622 642 623 643 -- ··· 729 749 730 750 ALTER TABLE ONLY public.fields 731 751 ADD CONSTRAINT fields_account_id_fkey FOREIGN KEY (account_id) REFERENCES public.accounts(id) ON UPDATE CASCADE ON DELETE CASCADE; 752 + 753 + 754 + -- 755 + -- Name: pack_banner_cards pack_banner_cards_card_type_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - 756 + -- 757 + 758 + ALTER TABLE ONLY public.pack_banner_cards 759 + ADD CONSTRAINT pack_banner_cards_card_type_id_fkey FOREIGN KEY (card_type_id) REFERENCES public.card_types(id) ON UPDATE CASCADE ON DELETE RESTRICT; 760 + 761 + 762 + -- 763 + -- Name: pack_banner_cards pack_banner_cards_pack_banner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - 764 + -- 765 + 766 + ALTER TABLE ONLY public.pack_banner_cards 767 + ADD CONSTRAINT pack_banner_cards_pack_banner_id_fkey FOREIGN KEY (pack_banner_id) REFERENCES public.pack_banners(id) ON UPDATE CASCADE ON DELETE CASCADE; 732 768 733 769 734 770 --
+4
main.rs
··· 1 + '\u{1234}' 2 + '\n' 3 + ' ' 4 + '"'
+16
migrations/committed/000013.sql
··· 1 + --! Previous: sha1:88d84bf5c81b47ff8aadf93f93569e2d9a478495 2 + --! Hash: sha1:6899eea812121a36fcdc877f6c5c8111b43e6fd7 3 + 4 + DROP TABLE IF EXISTS pack_banner_cards; 5 + 6 + CREATE TABLE pack_banner_cards ( 7 + pack_banner_id TEXT NOT NULL REFERENCES pack_banners (id) ON DELETE CASCADE ON UPDATE CASCADE, 8 + card_type_id TEXT NOT NULL REFERENCES card_types (id) ON DELETE RESTRICT ON UPDATE CASCADE, 9 + frequency INT NOT NULL CHECK (frequency > 0), 10 + PRIMARY KEY (pack_banner_id, card_type_id) 11 + ); 12 + 13 + COMMENT ON TABLE pack_banner_cards IS 'Lists relative frequencies of cards available to be pulled from each banner.'; 14 + 15 + -- Extraneous index after changing type to CITEXT 16 + DROP INDEX IF EXISTS accounts_id_case_insensitive;
+3
seeds/card_sets.tri
··· 1 + export card_set 2 + 3 + rule card_set("base", "2026-01-01T00:00:00Z")
+7
seeds/card_types.tri
··· 1 + import "./species.tri" use species 2 + import "./tile_types.tri" use tile_type 3 + 4 + export card_type 5 + 6 + rule card_type(species_id, card_set_id, "citizen") <- species(species_id, card_set_id) 7 + rule card_type(tile_type_id, card_set_id, "tile") <- tile_type(tile_type_id, card_set_id, _, _, _)
+12
seeds/pack_banners.tri
··· 1 + import "./card_types.tri" use card_type 2 + 3 + export pack_banner, pack_banner_card 4 + 5 + rule pack_banner("default", "2026-01-01T00:00:00Z", "2026-01-01T00:00:00Z") 6 + 7 + rule pack_banner("base-standard", "2026-01-01T00:00:00Z", unit) 8 + 9 + rule pack_banner_card("base-standard", card_type_id, 3) <- card_type(card_type_id, "base", "tile") 10 + rule pack_banner_card("base-standard", card_type_id, 1) <- card_type(card_type_id, "base", "citizen") 11 + 12 + rule pack_banner("halloween-2026", "2026-10-01T00:00:00Z", "2026-10-31T23:59:59Z")
+54 -20
seeds/seed.tri
··· 2 2 import "trilogy:array" use fold, map, zip 3 3 import "trilogy:string" use replace_all, trim, join 4 4 5 + import "./card_sets.tri" use card_set 6 + import "./card_types.tri" use card_type 5 7 import "./resources.tri" use resource 6 8 import "./species.tri" use species, species_needs 7 9 import "./tile_types.tri" use tile_type, tile_type_consumes, tile_type_produces 8 - 9 - func uncurry f (a:b) = f a b 10 - func flip f a b = f b a 10 + import "./pack_banners.tri" use pack_banner, pack_banner_card 11 11 12 12 func escape_single_quotes value = replace_all "'" "''" value 13 13 ··· 26 26 func escape_each a:b = "${sql_escape a}, ${escape_each b}" 27 27 func escape_each v = "${sql_escape v}" 28 28 29 - func sql [prefix, ..segments] interpolations = 30 - segments 31 - |> zip (map sql_escape interpolations) 32 - |> map (uncurry (<>)) 33 - |> fold (flip (<>)) prefix 29 + func sql [prefix, ..segments] [interpolation, ..rest] = prefix <> sql_escape interpolation <> sql segments rest 30 + func sql [prefix] [] = prefix 34 31 35 32 rule optional_species(unit) 36 33 rule optional_species(value) <- species(value) 37 34 38 35 proc main!() { 36 + let card_sets_values = 'values([id:release_date for card_set(id, release_date)]) 37 + 39 38 let resources_values = 'values([id for resource(id)]) 40 39 41 40 let card_types_values = 'values([ 42 - ..[species_id:"citizen" for species(species_id)], 43 - ..[tile_type_id:"tile" for tile_type(tile_type_id, _, _, _)] 41 + card_type_id:card_set_id:card_class 42 + for card_type(card_type_id, card_set_id, card_class) 43 + ]) 44 + 45 + let pack_banners_values = 'values([ 46 + pack_banner_id:start_at:end_at 47 + for pack_banner(pack_banner_id, start_at, end_at) 44 48 ]) 45 49 46 - let species_values = 'values([id for species(id)]) 50 + let pack_banner_cards_values = 'values([ 51 + pack_banner_id:card_type_id:frequency 52 + for pack_banner_card(pack_banner_id, card_type_id, frequency) 53 + ]) 54 + 55 + let species_values = 'values([id for species(id, _)]) 47 56 let species_needs_values = 'values([ 48 57 species_id:resource_id:quantity 49 58 for species_needs(species_id, resource_id, quantity) 50 - and species(^species_id) 59 + and species(^species_id, _) 51 60 and resource(^resource_id) 52 61 ]) 53 62 let tile_types_values = 'values([ 54 63 id:category:houses:employs 55 - for tile_type(id, category, houses, employs) 64 + for tile_type(id, _, category, houses, employs) 56 65 ]) 57 66 let tile_type_consumes_values = 'values([ 58 67 tile_type_id:resource_id:quantity 59 68 for tile_type_consumes(tile_type_id, resource_id, quantity) 60 - and tile_type(^tile_type_id, _, _, _) 69 + and tile_type(^tile_type_id, _, _, _, _) 61 70 and resource(^resource_id) 62 71 ]) 63 72 let tile_type_produces_values = 'values([ 64 73 tile_type_id:resource_id:quantity 65 74 for tile_type_produces(tile_type_id, resource_id, quantity) 66 - and tile_type(^tile_type_id, _, _, _) 75 + and tile_type(^tile_type_id, _, _, _, _) 67 76 and resource(^resource_id) 68 77 ]) 69 78 70 79 println!(trim $sql" 80 + BEGIN; 81 + 71 82 INSERT INTO resources (id) 72 83 ${resources_values} 73 84 ON CONFLICT DO NOTHING; 74 85 75 - INSERT INTO card_types (id, class) 86 + INSERT INTO card_sets (id, release_date) 87 + ${card_sets_values} 88 + ON CONFLICT (id) DO UPDATE 89 + SET release_date = EXCLUDED.release_date; 90 + 91 + INSERT INTO card_types (id, card_set_id, class) 76 92 ${card_types_values} 77 - ON CONFLICT (id) DO UPDATE SET class = EXCLUDED.class; 93 + ON CONFLICT (id) DO UPDATE 94 + SET class = EXCLUDED.class, 95 + card_set_id = EXCLUDED.card_set_id; 78 96 79 97 INSERT INTO species (id) 80 98 ${species_values} 81 99 ON CONFLICT DO NOTHING; 82 100 101 + INSERT INTO pack_banners (id, start_date, end_date) 102 + ${pack_banners_values} 103 + ON CONFLICT (id) DO UPDATE 104 + SET start_date = EXCLUDED.start_date, 105 + end_date = EXCLUDED.end_date; 106 + 107 + INSERT INTO pack_banner_cards (pack_banner_id, card_type_id, frequency) 108 + ${pack_banner_cards_values} 109 + ON CONFLICT (pack_banner_id, card_type_id) DO UPDATE 110 + SET frequency = EXCLUDED.frequency; 111 + 83 112 INSERT INTO species_needs (species_id, resource_id, quantity) 84 113 ${species_needs_values} 85 - ON CONFLICT (species_id, resource_id) DO UPDATE SET quantity = EXCLUDED.quantity; 114 + ON CONFLICT (species_id, resource_id) DO UPDATE 115 + SET quantity = EXCLUDED.quantity; 86 116 87 117 INSERT INTO tile_types (id, category, houses, employs) 88 118 ${tile_types_values} ··· 93 123 94 124 INSERT INTO tile_type_consumes (tile_type_id, resource_id, quantity) 95 125 ${tile_type_consumes_values} 96 - ON CONFLICT (tile_type_id, resource_id) DO UPDATE SET quantity = EXCLUDED.quantity; 126 + ON CONFLICT (tile_type_id, resource_id) DO UPDATE 127 + SET quantity = EXCLUDED.quantity; 97 128 98 129 INSERT INTO tile_type_produces (tile_type_id, resource_id, quantity) 99 130 ${tile_type_produces_values} 100 - ON CONFLICT (tile_type_id, resource_id) DO UPDATE SET quantity = EXCLUDED.quantity; 131 + ON CONFLICT (tile_type_id, resource_id) DO UPDATE 132 + SET quantity = EXCLUDED.quantity; 133 + 134 + COMMIT; 101 135 ") 102 136 }
+3 -3
seeds/species.tri
··· 1 1 export species, species_needs 2 2 3 - rule species("rabbit") 4 - rule species("cat") 5 - rule species("bird") 3 + rule species("rabbit", "base") 4 + rule species("cat", "base") 5 + rule species("bird", "base") 6 6 7 7 rule species_needs("rabbit", "salad", 1) 8 8 rule species_needs("cat", "bread", 1)
+8 -8
seeds/tile_types.tri
··· 1 1 export tile_type, tile_type_consumes, tile_type_produces 2 2 3 - rule tile_type("cat-colony", "residential", 3, 0) 3 + rule tile_type("cat-colony", "base", "residential", 3, 0) 4 4 5 - rule tile_type("rabbit-warren", "residential", 3, 0) 5 + rule tile_type("rabbit-warren", "base", "residential", 3, 0) 6 6 7 - rule tile_type("bird-nest", "residential", 3, 0) 7 + rule tile_type("bird-nest", "base", "residential", 3, 0) 8 8 9 - rule tile_type("water-well", "source", 0, 1) 9 + rule tile_type("water-well", "base", "source", 0, 1) 10 10 rule tile_type_produces("water-well", "water", 10) 11 11 12 12 rule farm("carrot") 13 13 rule farm("tomato") 14 14 rule farm("lettuce") 15 15 rule farm("grain") 16 - rule tile_type(resource <> "-farm", "production", 0, 3) <- farm(resource) 16 + rule tile_type(resource <> "-farm", "base", "production", 0, 3) <- farm(resource) 17 17 rule tile_type_produces(resource <> "-farm", resource, 5) <- farm(resource) 18 18 19 - rule tile_type("flour-mill", "production", 0, 2) 19 + rule tile_type("flour-mill", "base", "production", 0, 2) 20 20 rule tile_type_consumes("flour-mill", "grain", 1) 21 21 rule tile_type_produces("flour-mill", "flour", 10) 22 22 23 - rule tile_type("bread-bakery", "amenity", 0, 2) 23 + rule tile_type("bread-bakery", "base", "amenity", 0, 2) 24 24 rule tile_type_consumes("bread-bakery", "flour", 3) 25 25 rule tile_type_consumes("bread-bakery", "water", 2) 26 26 rule tile_type_produces("bread-bakery", "bread", 5) 27 27 28 - rule tile_type("salad-shop", "amenity", 0, 2) 28 + rule tile_type("salad-shop", "base", "amenity", 0, 2) 29 29 rule tile_type_consumes("salad-shop", "tomato", 1) 30 30 rule tile_type_consumes("salad-shop", "lettuce", 1) 31 31 rule tile_type_consumes("salad-shop", "carrot", 1)