From c4a27208b9ca92154e2c73893869beaf95b8ccad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Fri, 14 Jul 2023 17:25:01 +0200 Subject: [PATCH] feat: implement environment score (resolve #2) --- README.md | 58 ++++++++++------- cli/pom.xml | 4 +- lib/pom.xml | 4 +- .../mensascraper/lib/KITMensaScraper.java | 64 +++++++++++++++++-- .../aifb/atks/mensascraper/lib/MensaMeal.java | 31 +++++++++ .../lib/KITMensaScraperIntegrationTest.java | 3 + .../mensascraper/lib/KITMensaScraperTest.java | 19 ++++-- pom.xml | 2 +- 8 files changed, 145 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index bce550d..1776801 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Scrapes [KIT Mensa Speiseplan](https://www.sw-ka.de/en/hochschulgastronomie/spei * [x] Line * [x] Nutrients * [x] Additives -* [ ] Environment Score +* [x] Environment Score ## API Documentation JavaDoc available [here](https://docs.muetsch.io/kit-mensa-scraper/edu/kit/aifb/atks/KITMensaScraper.html). @@ -32,29 +32,39 @@ public static void main(String[]args) { ### Output ``` -MensaMeal(name=Pasta in Tomatensoße mit Speck, Peperoncini und Reibekäse, line=LINIE_1, price=3.2, type=PORK, kcal=943.0, proteins=32.0, carbs=85.0, sugar=5.0, fat=51.0, saturated=19.0, salt=4.0) -MensaMeal(name=Pasta in Tomaten - Broccolisoße mit Reibekäse, line=LINIE_1, price=3.2, type=VEGETARIAN, kcal=856.0, proteins=27.0, carbs=91.0, sugar=11.0, fat=39.0, saturated=7.0, salt=4.0) -MensaMeal(name=Mini Frühlingsrollen mit Sweet Chili Soße und Mienudeln, line=LINIE_2, price=3.8, type=VEGAN, kcal=1147.0, proteins=23.0, carbs=144.0, sugar=22.0, fat=52.0, saturated=6.0, salt=2.0) -MensaMeal(name=Reispfanne mit Rindfleisch und Balkangemüse, line=LINIE_3, price=3.35, type=BEEF, kcal=721.0, proteins=39.0, carbs=86.0, sugar=7.0, fat=22.0, saturated=4.0, salt=4.0) -MensaMeal(name=Blattsalat, line=LINIE_3, price=0.9, type=VEGAN, kcal=106.0, proteins=0.0, carbs=3.0, sugar=3.0, fat=9.0, saturated=0.0, salt=2.0) -MensaMeal(name=Hausgemachte Gnocchi in Bechamelsoße mit Chorizo, line=LINIE_4, price=3.5, type=PORK, kcal=1121.0, proteins=22.0, carbs=132.0, sugar=8.0, fat=55.0, saturated=19.0, salt=6.0) -MensaMeal(name=Hausgemachte Gnocchi in Tomatensoße mit Champignons, line=LINIE_4, price=3.2, type=VEGAN, kcal=1241.0, proteins=24.0, carbs=162.0, sugar=19.0, fat=54.0, saturated=4.0, salt=11.0) -MensaMeal(name=Blattsalat, line=LINIE_4, price=0.9, type=VEGAN, kcal=106.0, proteins=0.0, carbs=3.0, sugar=3.0, fat=9.0, saturated=0.0, salt=2.0) -MensaMeal(name=Aktion "Afrika Senegal" Thiebouyapp mit Rindfleisch, line=LINIE_5, price=4.15, type=BEEF, kcal=464.0, proteins=33.0, carbs=72.0, sugar=10.0, fat=2.0, saturated=0.0, salt=0.0) -MensaMeal(name=Blattsalat, line=LINIE_5, price=0.9, type=VEGAN, kcal=106.0, proteins=0.0, carbs=3.0, sugar=3.0, fat=9.0, saturated=0.0, salt=2.0) -MensaMeal(name=Ananasquark, line=LINIE_5, price=0.85, type=VEGETARIAN, kcal=122.0, proteins=15.0, carbs=13.0, sugar=13.0, fat=0.0, saturated=0.0, salt=0.0) -MensaMeal(name=Schweine- und Hähnchenschnitzel, vegetarische Leckereien, Salatbuffet und Pommes - alles zur Wahl zu einem Preis, line=SCHNITZELBAR, price=1.05, type=PORK, kcal=837.0, proteins=32.0, carbs=62.0, sugar=8.0, fat=49.0, saturated=5.0, salt=3.0) -MensaMeal(name=Ananasquark, line=SCHNITZELBAR, price=0.85, type=VEGETARIAN, kcal=122.0, proteins=15.0, carbs=13.0, sugar=13.0, fat=0.0, saturated=0.0, salt=0.0) -MensaMeal(name=Hamburger Buffet Preis je 100 g, line=LINIE_6, price=1.05, type=BEEF, kcal=597.0, proteins=33.0, carbs=55.0, sugar=7.0, fat=25.0, saturated=10.0, salt=4.0) -MensaMeal(name=Salatbuffet mit frischer Rohkost, Blattsalate und ausgemachten Dressings, Preis je 100 g, line=LINIE_6, price=1.0, type=VEGAN, kcal=0.0, proteins=0.0, carbs=0.0, sugar=0.0, fat=0.0, saturated=0.0, salt=0.0) -MensaMeal(name=Reine Kalbsbratwurst mit Currysoße, line=KOERIWERK, price=2.1, type=BEEF, kcal=527.0, proteins=11.0, carbs=35.0, sugar=32.0, fat=37.0, saturated=13.0, salt=5.0) -MensaMeal(name=Vegane Tofu-Bratwurst mit Currysoße, line=KOERIWERK, price=2.1, type=VEGAN, kcal=556.0, proteins=26.0, carbs=37.0, sugar=34.0, fat=32.0, saturated=3.0, salt=4.0) -MensaMeal(name=koerifrites, line=KOERIWERK, price=1.3, type=VEGAN, kcal=0.0, proteins=0.0, carbs=0.0, sugar=0.0, fat=0.0, saturated=0.0, salt=0.0) -MensaMeal(name=Geflügelfrikadelle mit Brötchen, line=CAFETERIA, price=2.8, type=NONE, kcal=0.0, proteins=0.0, carbs=0.0, sugar=0.0, fat=0.0, saturated=0.0, salt=0.0) -MensaMeal(name=Pizza alla bolognese - Pizza mit Rinderhackfleisch, Lauch und roten Zwiebeln, line=PIZZAWERK, price=4.55, type=BEEF, kcal=1134.0, proteins=62.0, carbs=138.0, sugar=7.0, fat=34.0, saturated=16.0, salt=6.0) -MensaMeal(name=Pizza Funghi - frische Champignons, Frühlingszwiebeln, line=PIZZAWERK, price=4.35, type=VEGETARIAN, kcal=1121.0, proteins=47.0, carbs=138.0, sugar=5.0, fat=40.0, saturated=16.0, salt=6.0) -MensaMeal(name=Pizza Funghi vegan - frische Champignons, Frühlingszwiebeln und vegane Käsealternative, line=PIZZAWERK, price=4.35, type=VEGAN, kcal=999.0, proteins=25.0, carbs=156.0, sugar=6.0, fat=28.0, saturated=10.0, salt=6.0) -MensaMeal(name=Pizza Margherita vegetarisch - frische Tomaten, Mozzarella, Basilikumpesto, line=PIZZAWERK, price=4.05, type=NONE, kcal=1229.0, proteins=53.0, carbs=139.0, sugar=8.0, fat=49.0, saturated=20.0, salt=7.0) +MensaMeal(name=Scharfe Sombrero - Reispfanne mit Hackfleisch, Gemüse und Tomatensoße, line=LINIE_1, price=3.2, type=BEEF, kcal=737.0, proteins=40.0, carbs=109.0, sugar=7.0, fat=14.0, saturated=3.0, salt=3.0, scoreCo2=1, scoreWater=3, scoreAnimals=3, scoreRainforest=1, co2Emissions=4021.0, waterConsumption=8.78, additives=[Se, We]) +MensaMeal(name=Scharfe Sombrero - Reispfanne mit knusprigen Gemüse Crossini und Tomatensoße, line=LINIE_1, price=3.2, type=VEGETARIAN, kcal=851.0, proteins=26.0, carbs=136.0, sugar=22.0, fat=20.0, saturated=4.0, salt=3.0, scoreCo2=2, scoreWater=3, scoreAnimals=1, scoreRainforest=3, co2Emissions=666.0, waterConsumption=13.7, additives=[ML, Se, So, We]) +MensaMeal(name=Sellerieschnitzel mit Ratatouille und Ofenkartoffel, line=LINIE_2, price=3.5, type=VEGAN, kcal=716.0, proteins=13.0, carbs=73.0, sugar=13.0, fat=38.0, saturated=3.0, salt=4.0, scoreCo2=3, scoreWater=3, scoreAnimals=1, scoreRainforest=2, co2Emissions=777.0, waterConsumption=11.79, additives=[Se, We]) +MensaMeal(name=Veganes Tagesdessert, line=LINIE_2, price=1.05, type=VEGAN, kcal=0.0, proteins=0.0, carbs=0.0, sugar=0.0, fat=0.0, saturated=0.0, salt=0.0, scoreCo2=0, scoreWater=0, scoreAnimals=0, scoreRainforest=0, co2Emissions=0.0, waterConsumption=0.0, additives=[]) +MensaMeal(name=Spätzle-Pilz-Pfanne, line=LINIE_3, price=2.95, type=VEGETARIAN, kcal=510.0, proteins=17.0, carbs=41.0, sugar=2.0, fat=29.0, saturated=13.0, salt=2.0, scoreCo2=3, scoreWater=3, scoreAnimals=1, scoreRainforest=1, co2Emissions=462.0, waterConsumption=4.54, additives=[1, Di, Ei, We]) +MensaMeal(name=Blattsalat Gurkensalat, line=LINIE_3, price=0.9, type=VEGAN, kcal=116.0, proteins=1.0, carbs=5.0, sugar=5.0, fat=9.0, saturated=0.0, salt=2.0, scoreCo2=2, scoreWater=3, scoreAnimals=3, scoreRainforest=3, co2Emissions=230.0, waterConsumption=1.27, additives=[Sn]) +MensaMeal(name=Creme Sahne - Karamellgeschmack, line=LINIE_3, price=0.85, type=VEGETARIAN, kcal=197.0, proteins=5.0, carbs=25.0, sugar=19.0, fat=8.0, saturated=5.0, salt=0.0, scoreCo2=1, scoreWater=3, scoreAnimals=1, scoreRainforest=1, co2Emissions=347.0, waterConsumption=7.67, additives=[1, ML]) +MensaMeal(name=Vollkornpenne in fruchtiger Tomatensoße mit Chorizo, line=LINIE_4, price=3.5, type=PORK, kcal=828.0, proteins=26.0, carbs=80.0, sugar=12.0, fat=42.0, saturated=14.0, salt=7.0, scoreCo2=2, scoreWater=3, scoreAnimals=1, scoreRainforest=1, co2Emissions=893.0, waterConsumption=16.23, additives=[1, 2, 3, 5, Se, We]) +MensaMeal(name=Vollkornpenne in heller veganer Soja-Kräutersoße mit Erbsen, line=LINIE_4, price=3.2, type=VEGAN, kcal=672.0, proteins=22.0, carbs=87.0, sugar=5.0, fat=22.0, saturated=9.0, salt=10.0, scoreCo2=3, scoreWater=3, scoreAnimals=3, scoreRainforest=1, co2Emissions=281.0, waterConsumption=4.1, additives=[1, Se, So, We]) +MensaMeal(name=Blattsalat Gurkensalat, line=LINIE_4, price=0.9, type=VEGAN, kcal=116.0, proteins=1.0, carbs=5.0, sugar=5.0, fat=9.0, saturated=0.0, salt=2.0, scoreCo2=2, scoreWater=3, scoreAnimals=3, scoreRainforest=3, co2Emissions=230.0, waterConsumption=1.27, additives=[Sn]) +MensaMeal(name=Creme Sahne - Karamellgeschmack, line=LINIE_4, price=0.85, type=VEGETARIAN, kcal=197.0, proteins=5.0, carbs=25.0, sugar=19.0, fat=8.0, saturated=5.0, salt=0.0, scoreCo2=1, scoreWater=3, scoreAnimals=1, scoreRainforest=1, co2Emissions=347.0, waterConsumption=7.67, additives=[1, ML]) +MensaMeal(name=Paniertes Alaska Seelachsfilet mit Kräuterdip, line=LINIE_5, price=3.95, type=MSC, kcal=791.0, proteins=34.0, carbs=31.0, sugar=5.0, fat=58.0, saturated=5.0, salt=2.0, scoreCo2=2, scoreWater=3, scoreAnimals=1, scoreRainforest=3, co2Emissions=919.0, waterConsumption=11.62, additives=[Fi, ML, Sn, We]) +MensaMeal(name=Blattsalat Gurkensalat, line=LINIE_5, price=0.9, type=VEGAN, kcal=116.0, proteins=1.0, carbs=5.0, sugar=5.0, fat=9.0, saturated=0.0, salt=2.0, scoreCo2=2, scoreWater=3, scoreAnimals=3, scoreRainforest=3, co2Emissions=230.0, waterConsumption=1.27, additives=[Sn]) +MensaMeal(name=Kaisergemüse, line=LINIE_5, price=0.9, type=VEGAN, kcal=91.0, proteins=3.0, carbs=7.0, sugar=6.0, fat=4.0, saturated=2.0, salt=1.0, scoreCo2=2, scoreWater=3, scoreAnimals=3, scoreRainforest=3, co2Emissions=136.0, waterConsumption=1.44, additives=[1, Se]) +MensaMeal(name=Creme Sahne - Karamellgeschmack, line=LINIE_5, price=0.85, type=VEGETARIAN, kcal=197.0, proteins=5.0, carbs=25.0, sugar=19.0, fat=8.0, saturated=5.0, salt=0.0, scoreCo2=1, scoreWater=3, scoreAnimals=1, scoreRainforest=1, co2Emissions=347.0, waterConsumption=7.67, additives=[1, ML]) +MensaMeal(name=hausgemachter Kartoffelsalat, line=LINIE_5, price=0.85, type=VEGAN, kcal=290.0, proteins=4.0, carbs=35.0, sugar=2.0, fat=13.0, saturated=1.0, salt=1.0, scoreCo2=3, scoreWater=3, scoreAnimals=3, scoreRainforest=3, co2Emissions=104.0, waterConsumption=1.09, additives=[Se, Sn]) +MensaMeal(name=Linsensuppe, line=LINIE_5, price=0.55, type=VEGAN, kcal=176.0, proteins=5.0, carbs=14.0, sugar=1.0, fat=9.0, saturated=0.0, salt=1.0, scoreCo2=3, scoreWater=2, scoreAnimals=3, scoreRainforest=3, co2Emissions=95.0, waterConsumption=10.76, additives=[Se, We]) +MensaMeal(name=Schweine- und Hähnchenschnitzel, vegetarische Leckereien, Salatbuffet und Pommes - alles zur Wahl zu einem Preis, line=SCHNITZELBAR, price=1.05, type=PORK, kcal=837.0, proteins=32.0, carbs=62.0, sugar=8.0, fat=49.0, saturated=5.0, salt=3.0, scoreCo2=1, scoreWater=2, scoreAnimals=1, scoreRainforest=1, co2Emissions=2435.0, waterConsumption=62.83, additives=[4, 5, Ei, Hf, ML, Se, Sn, So, We]) +MensaMeal(name=Creme Sahne - Karamellgeschmack, line=SCHNITZELBAR, price=0.85, type=VEGETARIAN, kcal=197.0, proteins=5.0, carbs=25.0, sugar=19.0, fat=8.0, saturated=5.0, salt=0.0, scoreCo2=1, scoreWater=3, scoreAnimals=1, scoreRainforest=1, co2Emissions=347.0, waterConsumption=7.67, additives=[1, ML]) +MensaMeal(name=Verschiedene Desserts im Portionsbecher, line=SCHNITZELBAR, price=0.65, type=NONE, kcal=123.0, proteins=1.0, carbs=20.0, sugar=16.0, fat=3.0, saturated=2.0, salt=0.0, scoreCo2=2, scoreWater=3, scoreAnimals=1, scoreRainforest=1, co2Emissions=259.0, waterConsumption=5.9, additives=[1, Ei, GEL, ML, We]) +MensaMeal(name=Heute Geschlossen, line=LINIE_6, price=1.05, type=NONE, kcal=0.0, proteins=0.0, carbs=0.0, sugar=0.0, fat=0.0, saturated=0.0, salt=0.0, scoreCo2=0, scoreWater=0, scoreAnimals=0, scoreRainforest=0, co2Emissions=0.0, waterConsumption=0.0, additives=[]) +MensaMeal(name=Spätausgabe 14:00 bis 14:30 an der Linie 2 Info zum Speisenangebot direkt an der Ausgabe, line=UNKNOWN, price=3.2, type=NONE, kcal=0.0, proteins=0.0, carbs=0.0, sugar=0.0, fat=0.0, saturated=0.0, salt=0.0, scoreCo2=0, scoreWater=0, scoreAnimals=0, scoreRainforest=0, co2Emissions=0.0, waterConsumption=0.0, additives=[]) +MensaMeal(name=Reine Kalbsbratwurst mit Currysoße, line=KOERIWERK, price=2.1, type=BEEF, kcal=527.0, proteins=11.0, carbs=35.0, sugar=32.0, fat=37.0, saturated=13.0, salt=5.0, scoreCo2=1, scoreWater=3, scoreAnimals=1, scoreRainforest=1, co2Emissions=1491.0, waterConsumption=9.62, additives=[Se, Sn]) +MensaMeal(name=Vegane Tofu - Bratwurst mit Currysoße, line=KOERIWERK, price=2.1, type=VEGAN, kcal=556.0, proteins=26.0, carbs=37.0, sugar=34.0, fat=32.0, saturated=3.0, salt=4.0, scoreCo2=3, scoreWater=3, scoreAnimals=3, scoreRainforest=1, co2Emissions=298.0, waterConsumption=5.84, additives=[Ma, Se, Sn, So, We]) +MensaMeal(name=koerifrites, line=KOERIWERK, price=1.3, type=VEGAN, kcal=737.0, proteins=7.0, carbs=67.0, sugar=0.0, fat=47.0, saturated=8.0, salt=2.0, scoreCo2=1, scoreWater=3, scoreAnimals=3, scoreRainforest=3, co2Emissions=1805.0, waterConsumption=3.86, additives=[]) +MensaMeal(name=Hähnchenschnitzel mit Brötchen, line=CAFETERIA, price=2.8, type=NONE, kcal=0.0, proteins=0.0, carbs=0.0, sugar=0.0, fat=0.0, saturated=0.0, salt=0.0, scoreCo2=0, scoreWater=0, scoreAnimals=0, scoreRainforest=0, co2Emissions=0.0, waterConsumption=0.0, additives=[1, 3, Ge, We]) +MensaMeal(name=Börek mit Spinatfüllung, line=CAFETERIA, price=2.0, type=VEGAN, kcal=0.0, proteins=0.0, carbs=0.0, sugar=0.0, fat=0.0, saturated=0.0, salt=0.0, scoreCo2=0, scoreWater=0, scoreAnimals=0, scoreRainforest=0, co2Emissions=0.0, waterConsumption=0.0, additives=[2, 3, 4, Se, So, We]) +MensaMeal(name=Pizza alla bolognese - Pizza mit Rinderhackfleisch, Lauch und roten Zwiebeln, line=PIZZAWERK, price=4.55, type=BEEF, kcal=1134.0, proteins=62.0, carbs=138.0, sugar=7.0, fat=34.0, saturated=16.0, salt=6.0, scoreCo2=1, scoreWater=3, scoreAnimals=2, scoreRainforest=1, co2Emissions=3351.0, waterConsumption=32.68, additives=[ML, We]) +MensaMeal(name=Pizza Mykonos - Hirtenkäse, Paprika, Oliven, rote Zwiebeln und Mais, line=PIZZAWERK, price=4.45, type=VEGETARIAN, kcal=1124.0, proteins=51.0, carbs=140.0, sugar=8.0, fat=38.0, saturated=19.0, salt=7.0, scoreCo2=2, scoreWater=3, scoreAnimals=1, scoreRainforest=3, co2Emissions=1116.0, waterConsumption=39.48, additives=[8, ML, We]) +MensaMeal(name=Pizza Mykonos vegan - Paprika, Oliven, rote Zwiebeln, vegane Käsealternative und Mais, line=PIZZAWERK, price=4.45, type=VEGAN, kcal=936.0, proteins=24.0, carbs=159.0, sugar=9.0, fat=20.0, saturated=9.0, salt=6.0, scoreCo2=3, scoreWater=3, scoreAnimals=3, scoreRainforest=3, co2Emissions=401.0, waterConsumption=22.16, additives=[1, 8, We]) +MensaMeal(name=Pizza Margherita vegetarisch - frische Tomaten, Mozzarella, Basilikumpesto, line=PIZZAWERK, price=4.05, type=NONE, kcal=1232.0, proteins=53.0, carbs=139.0, sugar=8.0, fat=49.0, saturated=20.0, salt=7.0, scoreCo2=2, scoreWater=2, scoreAnimals=1, scoreRainforest=1, co2Emissions=1251.0, waterConsumption=63.69, additives=[2, Ei, LAB, ML, We]) +MensaMeal(name=Pizza Margherita vegan - frische Tomaten, vegane Käsealternative, Basilikumpesto, line=PIZZAWERK, price=4.05, type=VEGAN, kcal=1123.0, proteins=25.0, carbs=158.0, sugar=8.0, fat=40.0, saturated=12.0, salt=6.0, scoreCo2=3, scoreWater=2, scoreAnimals=3, scoreRainforest=3, co2Emissions=470.0, waterConsumption=59.77, additives=[1, We]) +MensaMeal(name=Insalata piccola - kleiner Blattsalat mit Tomate, Gurke und Ei, line=PIZZAWERK, price=1.8, type=VEGETARIAN, kcal=117.0, proteins=9.0, carbs=2.0, sugar=2.0, fat=7.0, saturated=2.0, salt=0.0, scoreCo2=2, scoreWater=3, scoreAnimals=1, scoreRainforest=1, co2Emissions=233.0, waterConsumption=4.58, additives=[Ei]) ``` ## Build diff --git a/cli/pom.xml b/cli/pom.xml index f42cef2..f77ed54 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -7,7 +7,7 @@ edu.kit.aifb.atks mensascraper - 1.1.5 + 1.2.0 edu.kit.aifb.atks.mensascraper @@ -20,7 +20,7 @@ edu.kit.aifb.atks.mensascraper lib - [1.1.0,) + [1.2.0,) com.google.code.gson diff --git a/lib/pom.xml b/lib/pom.xml index bd18ebb..274cd0d 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -7,12 +7,12 @@ edu.kit.aifb.atks mensascraper - 1.1.5 + 1.2.0 edu.kit.aifb.atks.mensascraper lib - 1.1.5 + 1.2.0 mensascraper-lib jar diff --git a/lib/src/main/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraper.java b/lib/src/main/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraper.java index e9ad010..d203afe 100644 --- a/lib/src/main/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraper.java +++ b/lib/src/main/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraper.java @@ -43,6 +43,7 @@ public KITMensaScraper() { /** * Create new scraper instance and control caching behavior. + * * @param noCache Whether to cache per-day meal menus. If {@code true}, requesting meals for same canteen and same day will only result in one fetch operation. */ public KITMensaScraper(boolean noCache) { @@ -52,8 +53,9 @@ public KITMensaScraper(boolean noCache) { /** * Fetch list of meals for a given canteen and given day. Currently, only "Mensa am Adenauerring" is supported. Note that you cannot request data for past days. + * * @param location Which canteen (aka. Mensa) to request meals for. - * @param day Which date to request meals for. Must be larger or equal than today ({@code LocalDate.now()}). Usually, only data for the upcoming 5 weeks is available. + * @param day Which date to request meals for. Must be larger or equal than today ({@code LocalDate.now()}). Usually, only data for the upcoming 5 weeks is available. * @return List of meals or empty list if no data is available. * @throws MensaScraperException Thrown if requested date is invalid or if anything else went wrong while downloading and parsing the menu. */ @@ -136,14 +138,15 @@ private static List parseSingleLine(Element el) { MensaMeal currentMeal = null; for (Element mealRow : mealRows) { - final boolean isNutrition = mealRow.selectXpath("./td[1]").hasClass("nutrition_facts_row"); + final boolean isDetailsSection = mealRow.selectXpath("./td[1]").hasClass("nutrition_facts_row"); - if (isNutrition) { - // parse nutrition info - // nutrition info always comes second, after the meal entry + if (isDetailsSection) { + // nutrition info, etc. always comes second, after the meal entry if (currentMeal == null) { throw new MensaScraperException("got nutrition table without preceding meal"); } + + // parse nutrition info currentMeal.setKcal(parseKcal(mealRow)); currentMeal.setProteins(parseProteins(mealRow)); currentMeal.setCarbs(parseCarbs(mealRow)); @@ -151,6 +154,14 @@ private static List parseSingleLine(Element el) { currentMeal.setFat(parseFat(mealRow)); currentMeal.setSaturated(parseSaturated(mealRow)); currentMeal.setSalt(parseSalt(mealRow)); + + // parse environment scores + currentMeal.setScoreCo2(parseScoreCo2(mealRow)); + currentMeal.setScoreWater(parseScoreWater(mealRow)); + currentMeal.setScoreAnimals(parseScoreAnimalWelfare(mealRow)); + currentMeal.setScoreRainforest(parseScoreRainforest(mealRow)); + currentMeal.setCo2Emissions(parseCo2Emissions(mealRow)); + currentMeal.setWaterConsumption(parseWaterConsumption(mealRow)); } else { // parse meal info currentMeal = new MensaMeal(); @@ -239,7 +250,50 @@ private static float parseNutrient(Element el, String key) { return Float.parseFloat(nutriText); } + private static short parseScoreCo2(Element el) { + final String ratingText = el.selectXpath(".//div[contains(@class, 'co2_bewertung')]/div[1]").attr("data-rating"); + return !ratingText.isEmpty() ? Short.parseShort(ratingText) : 0; + } + + private static short parseScoreWater(Element el) { + final String ratingText = el.selectXpath(".//div[contains(@class, 'wasser_bewertung')]/div[1]").attr("data-rating"); + return !ratingText.isEmpty() ? Short.parseShort(ratingText) : 0; + } + + private static short parseScoreAnimalWelfare(Element el) { + final String ratingText = el.selectXpath(".//div[contains(@class, 'tierwohl')]/div[1]").attr("data-rating"); + return !ratingText.isEmpty() ? Short.parseShort(ratingText) : 0; + } + + private static short parseScoreRainforest(Element el) { + final String ratingText = el.selectXpath(".//div[contains(@class, 'regenwald')]/div[1]").attr("data-rating"); + return !ratingText.isEmpty() ? Short.parseShort(ratingText) : 0; + } + + private static float parseCo2Emissions(Element el) { + final String emissionsText = el.selectXpath(".//div[contains(@class, 'co2_bewertung')]/div[3]").text() + .replaceAll("[^0-9,]+", "") + .replaceAll(",", ".") + .strip(); + return !emissionsText.isEmpty() ? Float.parseFloat(emissionsText) : 0; + } + + private static float parseWaterConsumption(Element el) { + final String consumptionText = el.selectXpath(".//div[contains(@class, 'wasser_bewertung')]/div[3]").text() + .replaceAll("[^0-9,]+", "") + .replaceAll(",", ".") + .strip(); + return !consumptionText.isEmpty() ? Float.parseFloat(consumptionText) : 0; + } + private static List cloneMeals(List meals) { return meals.stream().map(MensaMeal::copy).collect(Collectors.toList()); } + + private static void allowFail(Runnable r) { + try { + r.run(); + } catch (RuntimeException ignored) { + } + } } diff --git a/lib/src/main/java/edu/kit/aifb/atks/mensascraper/lib/MensaMeal.java b/lib/src/main/java/edu/kit/aifb/atks/mensascraper/lib/MensaMeal.java index e6a828a..a030e79 100644 --- a/lib/src/main/java/edu/kit/aifb/atks/mensascraper/lib/MensaMeal.java +++ b/lib/src/main/java/edu/kit/aifb/atks/mensascraper/lib/MensaMeal.java @@ -73,6 +73,36 @@ public class MensaMeal implements Serializable, Cloneable { */ private float salt; + /** + * Rating of emitted CO2 emissions of this meal (1-3 stars). + */ + private short scoreCo2; + + /** + * Rating of water consumption of this meal (1-3 stars). + */ + private short scoreWater; + + /** + * Animal welfare rating of this meal (1-3 stars). + */ + private short scoreAnimals; + + /** + * Rainforest friendliness score of this meal (1-3 stars). + */ + private short scoreRainforest; + + /** + * CO2 emissions of this meal in grams. + */ + private float co2Emissions; + + /** + * Water consumption of this meal in liters. + */ + private float waterConsumption; + /** * List of additives / ingredients / allergens. * See List of allergens. @@ -83,6 +113,7 @@ public class MensaMeal implements Serializable, Cloneable { /** * Create a deep-copy of this object. + * * @return Deep-copy of this object. */ public MensaMeal copy() { diff --git a/lib/src/test/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraperIntegrationTest.java b/lib/src/test/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraperIntegrationTest.java index 5e6349b..e08717e 100644 --- a/lib/src/test/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraperIntegrationTest.java +++ b/lib/src/test/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraperIntegrationTest.java @@ -40,6 +40,9 @@ void testFetchMealsLive() { assertTrue(result.stream().anyMatch(m -> !m.getAdditives().isEmpty())); assertTrue(result.stream().anyMatch(m -> m.getPrice() > 0f)); assertTrue(result.stream().anyMatch(m -> m.getKcal() > 0f)); + assertTrue(result.stream().anyMatch(m -> m.getScoreCo2() > 0f)); + assertTrue(result.stream().anyMatch(m -> m.getCo2Emissions() > 0f)); + assertTrue(result.stream().anyMatch(m -> m.getWaterConsumption() > 0f)); assertTrue(result.stream().anyMatch(m -> !m.getLine().equals(MensaLine.UNKNOWN))); assertTrue(result.stream().anyMatch(m -> !m.getType().equals(MensaMealType.NONE))); } diff --git a/lib/src/test/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraperTest.java b/lib/src/test/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraperTest.java index e384cde..e6df9ed 100644 --- a/lib/src/test/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraperTest.java +++ b/lib/src/test/java/edu/kit/aifb/atks/mensascraper/lib/KITMensaScraperTest.java @@ -63,20 +63,27 @@ void testFetchMeals() throws IOException, InterruptedException { assertEquals("kw=19", captor1.getValue().uri().getQuery()); assertEquals(32, tuesday.size()); - assertEquals(32, wednesday.size()); assertEquals(tuesday.size(), tuesday.stream().distinct().count()); - assertEquals(wednesday.size(), wednesday.stream().distinct().count()); assertEquals("Mini Frühlingsrollen mit Sweet Chili Soße und Mienudeln", tuesday.get(2).getName()); - assertEquals("Hausgemachte Gnocchi in Bechamelsoße mit Chorizo", tuesday.get(6).getName()); // bold + normal font - assertEquals(3, tuesday.get(2).getAdditives().size()); assertEquals("Sa", tuesday.get(2).getAdditives().get(0)); assertEquals(3.8f, tuesday.get(2).getPrice()); - assertEquals(3.5f, tuesday.get(6).getPrice()); assertEquals(1147.0f, tuesday.get(2).getKcal()); - assertEquals(1121.0f, tuesday.get(6).getKcal()); assertEquals(23.0f, tuesday.get(2).getProteins()); + assertEquals(2, tuesday.get(0).getScoreCo2()); + assertEquals(3, tuesday.get(0).getScoreWater()); + assertEquals(1, tuesday.get(0).getScoreAnimals()); + assertEquals(3, tuesday.get(0).getScoreRainforest()); + assertEquals(857f, tuesday.get(0).getCo2Emissions()); + assertEquals(21.61f, tuesday.get(0).getWaterConsumption()); + assertEquals(3, tuesday.get(2).getAdditives().size()); assertEquals(MensaLine.LINIE_2, tuesday.get(2).getLine()); assertEquals(MensaMealType.VEGAN, tuesday.get(2).getType()); + + assertEquals(32, wednesday.size()); + assertEquals(wednesday.size(), wednesday.stream().distinct().count()); + assertEquals("Hausgemachte Gnocchi in Bechamelsoße mit Chorizo", tuesday.get(6).getName()); // bold + normal font + assertEquals(3.5f, tuesday.get(6).getPrice()); + assertEquals(1121.0f, tuesday.get(6).getKcal()); } @Test diff --git a/pom.xml b/pom.xml index f42966c..21626cc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ edu.kit.aifb.atks mensascraper - 1.1.5 + 1.2.0 pom