backend stuff for ingredients and nutritions

This commit is contained in:
Aysegul Aydinlik 2025-12-04 14:41:45 +01:00
commit 88dc43613f
8 changed files with 296 additions and 0 deletions

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -0,0 +1,4 @@
package commons;
//should i do it or wait for lines for next week
public class RecipeIngredientTest {
}

View file

@ -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());
}
}

View file

@ -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<Ingredient, Long> {
List<Ingredient> findAllByOrderByNameAsc();
}

View file

@ -0,0 +1,11 @@
package server;
import commons.RecipeIngredient;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RecipeIngredientRepository extends JpaRepository<RecipeIngredient, Long> {
long countByIngredientId(long ingredientId);
void deleteByIngredientId(long ingredientId);
}