From 88dc43613fca20d25f9821341a67702dd2cdabb3 Mon Sep 17 00:00:00 2001 From: Aysegul Aydinlik Date: Thu, 4 Dec 2025 14:41:45 +0100 Subject: [PATCH 1/4] backend stuff for ingredients and nutritions --- commons/src/main/java/commons/Ingredient.java | 51 ++++++++++++ .../main/java/commons/RecipeIngredient.java | 78 +++++++++++++++++++ commons/src/main/java/commons/Unit.java | 44 +++++++++++ .../src/test/java/commons/IngredientTest.java | 36 +++++++++ .../java/commons/RecipeIngredientTest.java | 4 + commons/src/test/java/commons/UnitTest.java | 61 +++++++++++++++ .../java/server/IngredientRepository.java | 11 +++ .../server/RecipeIngredientRepository.java | 11 +++ 8 files changed, 296 insertions(+) create mode 100644 commons/src/main/java/commons/Ingredient.java create mode 100644 commons/src/main/java/commons/RecipeIngredient.java create mode 100644 commons/src/main/java/commons/Unit.java create mode 100644 commons/src/test/java/commons/IngredientTest.java create mode 100644 commons/src/test/java/commons/RecipeIngredientTest.java create mode 100644 commons/src/test/java/commons/UnitTest.java create mode 100644 server/src/main/java/server/IngredientRepository.java create mode 100644 server/src/main/java/server/RecipeIngredientRepository.java diff --git a/commons/src/main/java/commons/Ingredient.java b/commons/src/main/java/commons/Ingredient.java new file mode 100644 index 0000000..743fd20 --- /dev/null +++ b/commons/src/main/java/commons/Ingredient.java @@ -0,0 +1,51 @@ +package commons; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + + + +@Entity +public class Ingredient { + + //I don't like magic numbers + // online it says nutrition are this much kcal per gram + public static final double KCAL_PER_GRAM_PROTEIN = 4.0; + public static final double KCAL_PER_GRAM_CARBS = 4.0; + public static final double KCAL_PER_GRAM_FAT= 9.0; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public long id; + + public String name; + + public double proteinPer100g; + public double fatPer100g; + public double carbsPer100g; + + @SuppressWarnings("unused") + protected Ingredient() { + // for object mapper says sebastian + } + + public Ingredient(String name, + double proteinPer100g, + double fatPer100g, + double carbsPer100g) { + this.name = name; + this.proteinPer100g = proteinPer100g; + this.fatPer100g = fatPer100g; + this.carbsPer100g = carbsPer100g; + } + + public double kcalPer100g() { + return proteinPer100g * KCAL_PER_GRAM_PROTEIN + + carbsPer100g * KCAL_PER_GRAM_CARBS + + fatPer100g * KCAL_PER_GRAM_FAT; + } +} + + diff --git a/commons/src/main/java/commons/RecipeIngredient.java b/commons/src/main/java/commons/RecipeIngredient.java new file mode 100644 index 0000000..f9062a6 --- /dev/null +++ b/commons/src/main/java/commons/RecipeIngredient.java @@ -0,0 +1,78 @@ +package commons; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; + +@Entity +public class RecipeIngredient { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + public Long id; + + @ManyToOne(optional = false) + @JoinColumn(name = "recipe_id") + public Recipe recipe; + + @ManyToOne(optional = false) + @JoinColumn(name = "ingredient_id") + public Ingredient ingredient; + + public double amount; + + // store the unit name in the database + public String unitName; + + @SuppressWarnings("unused") + protected RecipeIngredient() { + // for sebastian + } + + public RecipeIngredient(Recipe recipe, //which recipe + Ingredient ingredient, // which ingredient + double amount, // the amount + String unitName) { //gram liter etc + //store it im tha field + this.recipe = recipe; + this.ingredient = ingredient; + this.amount = amount; + this.unitName = unitName; + } + + // Convert unitName to Unit object so java can read it + public Unit getUnit() { + return switch (unitName) { + case "GRAM" -> Unit.GRAM; + case "KILOGRAM" -> Unit.KILOGRAM; + case "MILLILITER" -> Unit.MILLILITER; + case "LITER" -> Unit.LITER; + case "TABLESPOON" -> Unit.TABLESPOON; + case "TEASPOON" -> Unit.TEASPOON; + case "CUP" -> Unit.CUP; + case "PIECE" -> Unit.PIECE; + + case "PINCH" -> Unit.PINCH; + case "HANDFUL" -> Unit.HANDFUL; + case "TO_TASTE" -> Unit.TO_TASTE; + + default -> null; + }; + } + + public boolean isInformal() { + Unit unit = getUnit(); + return unit != null && !unit.isFormal(); + } + + public double amountInBaseUnit() { + Unit unit = getUnit(); + if (unit == null || !unit.isFormal() || unit.conversionFactor <= 0) { + return 0.0; + } + return amount * unit.conversionFactor; + } +} diff --git a/commons/src/main/java/commons/Unit.java b/commons/src/main/java/commons/Unit.java new file mode 100644 index 0000000..fe38bf2 --- /dev/null +++ b/commons/src/main/java/commons/Unit.java @@ -0,0 +1,44 @@ +package commons; + +//what is a record class and why is it recommended +public final class Unit { + + //formal units + //weight units + public static final Unit GRAM = new Unit("GRAM", true, 1.0); + public static final Unit KILOGRAM = new Unit("KILOGRAM", true, 1000.0); + + //volume units + public static final Unit MILLILITER = new Unit("MILLILITER",true, 1.0); + public static final Unit LITER = new Unit("LITER", true, 1000.0); + public static final Unit TABLESPOON = new Unit("TABLESPOON",true, 15.0); + public static final Unit TEASPOON = new Unit("TEASPOON", true, 5.0); + public static final Unit CUP = new Unit("CUP", true, 240.0); + + //piece should be a formal unit to converse for portions like 3eggs can become 1,5 eggs this way + public static final Unit PIECE = new Unit("PIECE", true, 1.0); + + //informal units + public static final Unit PINCH = new Unit("PINCH", false, 0.0); + public static final Unit HANDFUL = new Unit("HANDFUL", false, 0.0); + public static final Unit TO_TASTE = new Unit("TO_TASTE", false, 0.0); + + public final String name; + public final boolean formal; + public final double conversionFactor; + + private Unit(String name, boolean formal, double conversionFactor) { + this.name = name; + this.formal = formal; + this.conversionFactor = conversionFactor; + } + + public boolean isFormal() { + return formal; + } + + @Override + public String toString() { + return name; + } +} diff --git a/commons/src/test/java/commons/IngredientTest.java b/commons/src/test/java/commons/IngredientTest.java new file mode 100644 index 0000000..7f4ceb1 --- /dev/null +++ b/commons/src/test/java/commons/IngredientTest.java @@ -0,0 +1,36 @@ +package commons; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class IngredientTest { + + @Test + void checkConstructorIngredient() { + Ingredient sugar = new Ingredient("Sugar", 0.0, 0.0, 100.0); + + assertEquals("Sugar", sugar.name); + assertEquals(0.0 , sugar.proteinPer100g); + assertEquals(0.0, sugar.fatPer100g); + assertEquals(100.0, sugar.carbsPer100g); + assertEquals(0L, sugar.id); + } + + @Test + void checkConstructorIngredientIfEverything0() { + Ingredient water = new Ingredient("Water", 0.0, 0.0, 0.0); + + assertEquals(0.0, water.kcalPer100g()); + + } + + @Test + void checkConstructorIngredientIfEverything100() { + Ingredient test = new Ingredient("Test", 10.0, 5.0, 20.0); + + double expectedKcal = 165.0; + assertEquals(expectedKcal, test.kcalPer100g()); + } +} + diff --git a/commons/src/test/java/commons/RecipeIngredientTest.java b/commons/src/test/java/commons/RecipeIngredientTest.java new file mode 100644 index 0000000..b2d989a --- /dev/null +++ b/commons/src/test/java/commons/RecipeIngredientTest.java @@ -0,0 +1,4 @@ +package commons; +//should i do it or wait for lines for next week +public class RecipeIngredientTest { +} diff --git a/commons/src/test/java/commons/UnitTest.java b/commons/src/test/java/commons/UnitTest.java new file mode 100644 index 0000000..3d09edb --- /dev/null +++ b/commons/src/test/java/commons/UnitTest.java @@ -0,0 +1,61 @@ +package commons; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class UnitTest { + + @Test + void formalUnitMarkedFormal(){ + assertTrue(Unit.GRAM.isFormal()); + assertTrue(Unit.KILOGRAM.isFormal()); + assertTrue(Unit.LITER.isFormal()); + assertTrue(Unit.CUP.isFormal()); + assertTrue(Unit.MILLILITER.isFormal()); + assertTrue(Unit.PIECE.isFormal()); + assertTrue(Unit.TABLESPOON.isFormal()); + assertTrue(Unit.TEASPOON.isFormal()); + + } + + @Test + void informalUnitAreNotFormal() { + assertFalse(Unit.PINCH.isFormal()); + assertFalse(Unit.HANDFUL.isFormal()); + assertFalse(Unit.TO_TASTE.isFormal()); + } + + @Test + void conversionIsCorrect() { + assertEquals(1.0, Unit.GRAM.conversionFactor); + assertEquals(1000.0, Unit.KILOGRAM.conversionFactor); + assertEquals(1000.0, Unit.LITER.conversionFactor); + assertEquals(240.0, Unit.CUP.conversionFactor); + assertEquals(1.0, Unit.MILLILITER.conversionFactor); + assertEquals(1.0, Unit.PIECE.conversionFactor); + assertEquals(15.0, Unit.TABLESPOON.conversionFactor); + assertEquals(5.0, Unit.TEASPOON.conversionFactor); + + assertEquals(0.0, Unit.PINCH.conversionFactor); + assertEquals(0.0, Unit.HANDFUL.conversionFactor); + assertEquals(0.0, Unit.TO_TASTE.conversionFactor); + + } + + @Test + void toStringReturnsName(){ + assertEquals("GRAM", Unit.GRAM.toString()); + assertEquals("KILOGRAM", Unit.KILOGRAM.toString()); + assertEquals("LITER", Unit.LITER.toString()); + assertEquals("CUP", Unit.CUP.toString()); + assertEquals("MILLILITER", Unit.MILLILITER.toString()); + assertEquals("PIECE", Unit.PIECE.toString()); + assertEquals("TABLESPOON", Unit.TABLESPOON.toString()); + assertEquals("TEASPOON", Unit.TEASPOON.toString()); + + assertEquals("PINCH", Unit.PINCH.toString()); + assertEquals("HANDFUL", Unit.HANDFUL.toString()); + assertEquals("TO_TASTE", Unit.TO_TASTE.toString()); + } +} diff --git a/server/src/main/java/server/IngredientRepository.java b/server/src/main/java/server/IngredientRepository.java new file mode 100644 index 0000000..fe3a155 --- /dev/null +++ b/server/src/main/java/server/IngredientRepository.java @@ -0,0 +1,11 @@ +package server; + +import commons.Ingredient; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface IngredientRepository extends JpaRepository { + List findAllByOrderByNameAsc(); +} + diff --git a/server/src/main/java/server/RecipeIngredientRepository.java b/server/src/main/java/server/RecipeIngredientRepository.java new file mode 100644 index 0000000..9ebbb12 --- /dev/null +++ b/server/src/main/java/server/RecipeIngredientRepository.java @@ -0,0 +1,11 @@ +package server; + +import commons.RecipeIngredient; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RecipeIngredientRepository extends JpaRepository { + + long countByIngredientId(long ingredientId); + + void deleteByIngredientId(long ingredientId); +} From 78e7f90024c4f9ebaf005d629f57991acd980b16 Mon Sep 17 00:00:00 2001 From: Aysegul Aydinlik Date: Thu, 4 Dec 2025 15:41:43 +0100 Subject: [PATCH 2/4] backend stuff for ingredients and nutritions AND FIXED MAGIC NUMBERS --- commons/src/main/java/commons/Unit.java | 36 +++++++++++++------ .../src/test/java/commons/IngredientTest.java | 30 ++++++++++------ commons/src/test/java/commons/UnitTest.java | 35 ++++++++++++------ 3 files changed, 69 insertions(+), 32 deletions(-) diff --git a/commons/src/main/java/commons/Unit.java b/commons/src/main/java/commons/Unit.java index fe38bf2..5233121 100644 --- a/commons/src/main/java/commons/Unit.java +++ b/commons/src/main/java/commons/Unit.java @@ -3,25 +3,39 @@ package commons; //what is a record class and why is it recommended public final class Unit { + + //stupid magic numbers + private static final double GRAMS = 1.0; + private static final double KILOGRAMS = 1000.0; + private static final double MILLILITERS = 1.0; + private static final double LITERS = 1000.0; + private static final double TABLESPOONS = 15.0; + private static final double TEASPOONS = 5.0; + private static final double CUPS = 240.0; + private static final double PIECES = 1.0; + + private static final double NoMeaningfulValue = 0.0; + + //formal units //weight units - public static final Unit GRAM = new Unit("GRAM", true, 1.0); - public static final Unit KILOGRAM = new Unit("KILOGRAM", true, 1000.0); + public static final Unit GRAM = new Unit("GRAM", true, GRAMS); + public static final Unit KILOGRAM = new Unit("KILOGRAM", true, KILOGRAMS ); //volume units - public static final Unit MILLILITER = new Unit("MILLILITER",true, 1.0); - public static final Unit LITER = new Unit("LITER", true, 1000.0); - public static final Unit TABLESPOON = new Unit("TABLESPOON",true, 15.0); - public static final Unit TEASPOON = new Unit("TEASPOON", true, 5.0); - public static final Unit CUP = new Unit("CUP", true, 240.0); + public static final Unit MILLILITER = new Unit("MILLILITER",true, MILLILITERS); + public static final Unit LITER = new Unit("LITER", true, LITERS); + public static final Unit TABLESPOON = new Unit("TABLESPOON",true, TABLESPOONS); + public static final Unit TEASPOON = new Unit("TEASPOON", true, TEASPOONS); + public static final Unit CUP = new Unit("CUP", true, CUPS); //piece should be a formal unit to converse for portions like 3eggs can become 1,5 eggs this way - public static final Unit PIECE = new Unit("PIECE", true, 1.0); + public static final Unit PIECE = new Unit("PIECE", true, PIECES); //informal units - public static final Unit PINCH = new Unit("PINCH", false, 0.0); - public static final Unit HANDFUL = new Unit("HANDFUL", false, 0.0); - public static final Unit TO_TASTE = new Unit("TO_TASTE", false, 0.0); + public static final Unit PINCH = new Unit("PINCH", false, NoMeaningfulValue); + public static final Unit HANDFUL = new Unit("HANDFUL", false, NoMeaningfulValue); + public static final Unit TO_TASTE = new Unit("TO_TASTE", false, NoMeaningfulValue); public final String name; public final boolean formal; diff --git a/commons/src/test/java/commons/IngredientTest.java b/commons/src/test/java/commons/IngredientTest.java index 7f4ceb1..aeae121 100644 --- a/commons/src/test/java/commons/IngredientTest.java +++ b/commons/src/test/java/commons/IngredientTest.java @@ -6,31 +6,41 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class IngredientTest { + // === Meaningful constants === + private static final double ZERO = 0.0; + private static final double HUNDRED = 100.0; + + private static final double PROTEIN_10 = 10.0; + private static final double FAT_5 = 5.0; + private static final double CARBS_20 = 20.0; + + private static final double EXPECTED_KCAL_165 = 165.0; + + @Test void checkConstructorIngredient() { - Ingredient sugar = new Ingredient("Sugar", 0.0, 0.0, 100.0); + Ingredient sugar = new Ingredient("Sugar", ZERO, ZERO, HUNDRED); assertEquals("Sugar", sugar.name); - assertEquals(0.0 , sugar.proteinPer100g); - assertEquals(0.0, sugar.fatPer100g); - assertEquals(100.0, sugar.carbsPer100g); + assertEquals(ZERO, sugar.proteinPer100g); + assertEquals(ZERO, sugar.fatPer100g); + assertEquals(HUNDRED, sugar.carbsPer100g); assertEquals(0L, sugar.id); } @Test void checkConstructorIngredientIfEverything0() { - Ingredient water = new Ingredient("Water", 0.0, 0.0, 0.0); - - assertEquals(0.0, water.kcalPer100g()); + Ingredient water = new Ingredient("Water", ZERO, ZERO, ZERO); + assertEquals(ZERO, water.kcalPer100g()); } @Test void checkConstructorIngredientIfEverything100() { - Ingredient test = new Ingredient("Test", 10.0, 5.0, 20.0); + Ingredient test = new Ingredient("Test", PROTEIN_10, FAT_5, CARBS_20); - double expectedKcal = 165.0; - assertEquals(expectedKcal, test.kcalPer100g()); + assertEquals(EXPECTED_KCAL_165, test.kcalPer100g()); } } + diff --git a/commons/src/test/java/commons/UnitTest.java b/commons/src/test/java/commons/UnitTest.java index 3d09edb..8d7f06f 100644 --- a/commons/src/test/java/commons/UnitTest.java +++ b/commons/src/test/java/commons/UnitTest.java @@ -6,6 +6,19 @@ import static org.junit.jupiter.api.Assertions.*; class UnitTest { + //stupid magic numbers + private static final double GRAMS = 1.0; + private static final double KILOGRAMS = 1000.0; + private static final double MILLILITERS = 1.0; + private static final double LITERS = 1000.0; + private static final double TABLESPOONS = 15.0; + private static final double TEASPOONS = 5.0; + private static final double CUPS = 240.0; + private static final double PIECES = 1.0; + + private static final double NoMeaningfulValue = 0.0; + + @Test void formalUnitMarkedFormal(){ assertTrue(Unit.GRAM.isFormal()); @@ -28,18 +41,18 @@ class UnitTest { @Test void conversionIsCorrect() { - assertEquals(1.0, Unit.GRAM.conversionFactor); - assertEquals(1000.0, Unit.KILOGRAM.conversionFactor); - assertEquals(1000.0, Unit.LITER.conversionFactor); - assertEquals(240.0, Unit.CUP.conversionFactor); - assertEquals(1.0, Unit.MILLILITER.conversionFactor); - assertEquals(1.0, Unit.PIECE.conversionFactor); - assertEquals(15.0, Unit.TABLESPOON.conversionFactor); - assertEquals(5.0, Unit.TEASPOON.conversionFactor); + assertEquals(GRAMS, Unit.GRAM.conversionFactor); + assertEquals(KILOGRAMS, Unit.KILOGRAM.conversionFactor); + assertEquals(LITERS, Unit.LITER.conversionFactor); + assertEquals(CUPS, Unit.CUP.conversionFactor); + assertEquals(MILLILITERS, Unit.MILLILITER.conversionFactor); + assertEquals(PIECES, Unit.PIECE.conversionFactor); + assertEquals(TABLESPOONS, Unit.TABLESPOON.conversionFactor); + assertEquals(TEASPOONS, Unit.TEASPOON.conversionFactor); - assertEquals(0.0, Unit.PINCH.conversionFactor); - assertEquals(0.0, Unit.HANDFUL.conversionFactor); - assertEquals(0.0, Unit.TO_TASTE.conversionFactor); + assertEquals(NoMeaningfulValue, Unit.PINCH.conversionFactor); + assertEquals(NoMeaningfulValue, Unit.HANDFUL.conversionFactor); + assertEquals(NoMeaningfulValue, Unit.TO_TASTE.conversionFactor); } From f9262d4046cfafcabf0e67f95a5f5889ecc337e1 Mon Sep 17 00:00:00 2001 From: Aysegul Aydinlik Date: Fri, 5 Dec 2025 00:12:53 +0100 Subject: [PATCH 3/4] backend stuff for ingredients and nutritions AND FIXED MAGIC NUMBERS and fixed stevens and oskars problems --- commons/src/main/java/commons/Ingredient.java | 9 ++++++++- commons/src/main/java/commons/RecipeIngredient.java | 6 ++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/commons/src/main/java/commons/Ingredient.java b/commons/src/main/java/commons/Ingredient.java index 743fd20..f224f2f 100644 --- a/commons/src/main/java/commons/Ingredient.java +++ b/commons/src/main/java/commons/Ingredient.java @@ -1,12 +1,12 @@ package commons; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; - @Entity public class Ingredient { @@ -20,10 +20,17 @@ public class Ingredient { @GeneratedValue(strategy = GenerationType.AUTO) public long id; + @Column(name = "name", nullable = false, unique = true) public String name; + + @Column(name = "protein", nullable = false) public double proteinPer100g; + + @Column(name = "fat", nullable = false) public double fatPer100g; + + @Column(name = "carbs", nullable = false) public double carbsPer100g; @SuppressWarnings("unused") diff --git a/commons/src/main/java/commons/RecipeIngredient.java b/commons/src/main/java/commons/RecipeIngredient.java index f9062a6..c94d8dd 100644 --- a/commons/src/main/java/commons/RecipeIngredient.java +++ b/commons/src/main/java/commons/RecipeIngredient.java @@ -14,10 +14,12 @@ public class RecipeIngredient { @GeneratedValue(strategy = GenerationType.IDENTITY) public Long id; + // which recipe is used @ManyToOne(optional = false) @JoinColumn(name = "recipe_id") public Recipe recipe; + //which ingredient is used @ManyToOne(optional = false) @JoinColumn(name = "ingredient_id") public Ingredient ingredient; @@ -35,12 +37,12 @@ public class RecipeIngredient { public RecipeIngredient(Recipe recipe, //which recipe Ingredient ingredient, // which ingredient double amount, // the amount - String unitName) { //gram liter etc + String unit) { //gram liter etc //store it im tha field this.recipe = recipe; this.ingredient = ingredient; this.amount = amount; - this.unitName = unitName; + this.unitName = unit; } // Convert unitName to Unit object so java can read it From 1c9ff190ead9b463ac83ad79f024665e5f1073cb Mon Sep 17 00:00:00 2001 From: Aysegul Aydinlik Date: Fri, 5 Dec 2025 00:30:12 +0100 Subject: [PATCH 4/4] backend stuff for ingredients and nutritions AND FIXED MAGIC NUMBERS and fixed stevens and oskarsss problems --- commons/src/main/java/commons/RecipeIngredient.java | 7 ++----- commons/src/main/java/commons/Unit.java | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/commons/src/main/java/commons/RecipeIngredient.java b/commons/src/main/java/commons/RecipeIngredient.java index c94d8dd..36488d9 100644 --- a/commons/src/main/java/commons/RecipeIngredient.java +++ b/commons/src/main/java/commons/RecipeIngredient.java @@ -65,14 +65,11 @@ public class RecipeIngredient { }; } - public boolean isInformal() { - Unit unit = getUnit(); - return unit != null && !unit.isFormal(); - } + public double amountInBaseUnit() { Unit unit = getUnit(); - if (unit == null || !unit.isFormal() || unit.conversionFactor <= 0) { + if (unit == null || unit.isFormal() || unit.conversionFactor <= 0) { return 0.0; } return amount * unit.conversionFactor; diff --git a/commons/src/main/java/commons/Unit.java b/commons/src/main/java/commons/Unit.java index 5233121..05c174e 100644 --- a/commons/src/main/java/commons/Unit.java +++ b/commons/src/main/java/commons/Unit.java @@ -51,6 +51,10 @@ public final class Unit { return formal; } + public boolean isInformal() { + return !formal; + } //for oskar + @Override public String toString() { return name;