Skip to content

Commit

Permalink
Overhaul Tastings (#158)
Browse files Browse the repository at this point in the history
This adds a new tag categorization and flavor profile mechanic. Current tags will get ported over at some point, but for now itll create a new set of fixtures for selection.

Additionaly it adds color selection to tastings, and changes a number of related things, including the tasting cards.
  • Loading branch information
dcramer authored Apr 17, 2024
1 parent 2756ebf commit 89dd61a
Show file tree
Hide file tree
Showing 53 changed files with 5,761 additions and 464 deletions.
264 changes: 264 additions & 0 deletions apps/cli/src/commands/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
import program from "@peated/cli/program";
import { db } from "@peated/server/db";
import { tags } from "@peated/server/db/schema";
import type { FlavorProfile, TagCategory } from "@peated/server/types";

const TAGS: Record<TagCategory, string[]> = {
cereal: [
"barley sugar",
"biscuity",
"oatmeal",
"grains",
"malted barley",
"rye",
"wheat",
"corn",
"fresh hay",
"bread",
],
fruity: [
"acidic",
"green apple",
"lemon zest",
"fresh berries",
"citrus",
"lime",
"ripe peach",
"juicy pear",
"mellow apricot",
"soft cherry",
"ripe melon",
"banana",
"apple pie",
"stewed fruits",
],
floral: [
"light floral",
"soft floral",
"lavender",
"fresh flowers",
"green leaves",
"heather",
"delicate herbs",
],
peaty: [
"alcohol burn",
"light smoke",
"gentle peat",
"smoked herbs",
"peat moss",
"earthy peat",
"smoked wood",
"balanced smoke",
"intense smoke",
"heavy iodine",
"tar",
"burnt rubber",
"creosote",
"smoked meat",
"charred oak",
"deep peat",
],
feinty: [
"old books",
"antique leather",
"tobacco",
"earthiness",
"soft musk",
"aged sherry",
"library books",
"tobacco leaf",
],
sulphury: ["burnt matches", "gunpowder"],
woody: [
"anise",
"baking spices",
"nutmeg",
"old oak",
"polished wood",
"vanilla bean",
"creamy oak",
"maple syrup",
"butterscotch",
"ripe apples",
"toasted almonds",
"oak spices",
"juicy pears",
"antique wood",
"oak",
"sherry",
],
winey: [
"luxurious sherry",
"dark chocolate",
"walnut",
"coffee beans",
"date",
"currants",
"rich prunes",
"dried figs",
"raisins",
"fruit cake",
],
};

const PROFILES: Record<FlavorProfile, string[]> = {
young_spritely: [
"green apple",
"lemon zest",
"fresh berries",
"citrus",
"grass",
"lime",
"light floral",
"sparkling",
],
sweet_fruit_mellow: [
"cake",
"candy",
"ripe peach",
"juicy pear",
"mellow apricot",
"soft cherry",
"barley sugar",
"marmalade",
"ripe melon",
"banana",
],
spicy_sweet: [
"anise",
"baking spices",
"cinnamon",
"sweet ginger",
"vanilla",
"caramel",
"honey",
"rich nutmeg",
"warm clove",
"spiced cake",
],
spicy_dry: [
"bitter",
"fiery",
"dry pepper",
"herbal notes",
"crisp ginger",
"subtle oak",
"cardamom",
"sandalwood",
"black tea",
"tobacco leaf",
],
deep_rich_dried_fruit: [
"dried figs",
"raisins",
"rich prunes",
"luxurious sherry",
"dark chocolate",
"walnut",
"coffee beans",
"date",
],
old_dignified: [
"balanced",
"antique leather",
"old oak",
"tobacco",
"polished wood",
"earthiness",
"soft musk",
"aged sherry",
"library books",
],
light_delicate: [
"acidic",
"clean",
"soft floral",
"lavender",
"green leaves",
"light honey",
"almond",
"heather",
"fresh hay",
"delicate herbs",
],
juicy_oak_vanilla: [
"butter",
"vanilla bean",
"creamy oak",
"maple syrup",
"butterscotch",
"ripe apples",
"toasted almonds",
"oak spices",
"juicy pears",
],
oily_coastal: [
"ethanol",
"seaweed",
"oily texture",
"salt spray",
"maritime air",
"briny notes",
"clam",
"oyster",
"fishing net",
],
lightly_peated: [
"ethanol",
"light smoke",
"gentle peat",
"fresh mineral",
"smoked herbs",
"bonfire embers",
"peat moss",
"autumn leaves",
"grilled citrus",
],
peated: [
"earthy peat",
"smoked wood",
"balanced smoke",
"leather",
"campfire",
"black pepper",
"wet stones",
"forest floor",
],
heavily_peated: [
"alcohol burn",
"fiery",
"intense smoke",
"heavy iodine",
"tar",
"burnt rubber",
"creosote",
"smoked meat",
"charred oak",
"deep peat",
],
};

const subcommand = program.command("data");

subcommand.command("load-default-tags").action(async (options) => {
Object.entries(TAGS).forEach(async ([categoryName, tagList]) => {
await db.transaction(async (tx) => {
for (const tagName of tagList) {
console.log(`Registering tag ${tagName}`);
await tx
.insert(tags)
.values({
name: tagName,
tagCategory: categoryName as TagCategory,
flavorProfiles: Object.entries(PROFILES)
.filter(([profileName, tagList]) => tagList.includes(tagName))
.map<FlavorProfile>(
([profileName]) => profileName as FlavorProfile,
),
})
.onConflictDoNothing();
}
});
});
});
1 change: 1 addition & 0 deletions apps/cli/src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./bottles";
export * from "./data";
export * from "./db";
export * from "./entities";
export * from "./mocks";
Expand Down
43 changes: 43 additions & 0 deletions apps/server/migrations/0092_parched_kat_farrell.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
DO $$ BEGIN
CREATE TYPE "category" AS ENUM('blend', 'bourbon', 'rye', 'single_grain', 'single_malt', 'single_pot_still', 'spirit');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

DO $$ BEGIN
CREATE TYPE "flavor_profile" AS ENUM('young_spritely', 'sweet_fruit_mellow', 'spicy_sweet', 'spicy_dry', 'deep_rich_dried_fruit', 'old_dignified', 'light_delicate', 'juicy_oak_vanilla', 'oily_coastal', 'lightly_peated', 'peated', 'heavily_peated');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

DO $$ BEGIN
CREATE TYPE "object_type" AS ENUM('bottle', 'comment', 'entity', 'tasting', 'toast', 'follow');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

DO $$ BEGIN
CREATE TYPE "tag_category" AS ENUM('cereal', 'fruity', 'floral', 'peaty', 'feinty', 'sulphury', 'woody', 'winey');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

CREATE TABLE IF NOT EXISTS "bottle_flavor_profile" (
"bottle_id" bigint NOT NULL,
"flavor_profile" "flavor_profile" NOT NULL,
"count" integer DEFAULT 0 NOT NULL,
CONSTRAINT "bottle_flavor_profile_bottle_id_flavor_profile_pk" PRIMARY KEY("bottle_id","flavor_profile")
);

CREATE TABLE IF NOT EXISTS "tag" (
"name" varchar(64) PRIMARY KEY NOT NULL,
"synonyms" varchar(64)[] DEFAULT '{}' NOT NULL,
"tag_category" "tag_category" NOT NULL,
"flavor_profile" flavor_profile[] DEFAULT '{}' NOT NULL
);

DO $$ BEGIN
ALTER TABLE "bottle_flavor_profile" ADD CONSTRAINT "bottle_flavor_profile_bottle_id_bottle_id_fk" FOREIGN KEY ("bottle_id") REFERENCES "bottle"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
1 change: 1 addition & 0 deletions apps/server/migrations/0093_robust_beast.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE "tasting" ADD COLUMN "color" integer;
Loading

0 comments on commit 89dd61a

Please sign in to comment.