From 8435545bec914c8b7a49857343c39b77a806aeba Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sun, 3 Mar 2024 18:16:37 +0100 Subject: [PATCH] =?UTF-8?q?Tests=20mit=20Prozentualer=20Umverteilung=20bei?= =?UTF-8?q?=20der=20St=C3=A4rke?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CocktailWeb/GeneralSettings.cs | 2 +- CocktailWeb/Pages/CocktailView.razor | 131 ++++++++++++++----- CocktailWeb/{ => _Docs}/Notizen.txt | 0 CocktailWeb/_Docs/ProzentualeVerteilung.xlsx | Bin 0 -> 10592 bytes 4 files changed, 98 insertions(+), 35 deletions(-) rename CocktailWeb/{ => _Docs}/Notizen.txt (100%) create mode 100644 CocktailWeb/_Docs/ProzentualeVerteilung.xlsx diff --git a/CocktailWeb/GeneralSettings.cs b/CocktailWeb/GeneralSettings.cs index dd1bfe2..34af356 100644 --- a/CocktailWeb/GeneralSettings.cs +++ b/CocktailWeb/GeneralSettings.cs @@ -2,8 +2,8 @@ { public class GeneralSettings { - public int MaxAllowedUploadSizeInMB { get; set; } = 10; + public string ImageUploadDir { get; set; } = "images"; public string SerialPort { get; set; } = "COM5"; diff --git a/CocktailWeb/Pages/CocktailView.razor b/CocktailWeb/Pages/CocktailView.razor index 144f853..9fe1ad2 100644 --- a/CocktailWeb/Pages/CocktailView.razor +++ b/CocktailWeb/Pages/CocktailView.razor @@ -31,15 +31,30 @@ else
Stärke
-
- - - - - - - -
+ @if (!UseNewIntensityCalc) + { +
+ + + + + + + +
+ } + else + { +
+ + + + + + + +
+ }

@if (ErrorMessage != null) @@ -48,12 +63,12 @@ else @ErrorMessage } - @if(CocktailCode != null) + @if (CocktailCode != null) { - } + } @@ -120,6 +135,8 @@ else private int DrinkIntensity = 0; + private bool UseNewIntensityCalc = false; + private string? ErrorMessage; private string? CocktailCode; @@ -181,6 +198,9 @@ else } + /// + /// Erstellt den für die Arduino-Steuerung erforderlichen Code + /// private void CreateCocktailCode() { CocktailCode = null; @@ -196,50 +216,93 @@ else if (Filler.Type == Filler.FillerType.Pump) { line = $"P{Filler.Pos}={Zutat.Menge}"; - } else if (Filler.Type == Filler.FillerType.Pourer) + } + else if (Filler.Type == Filler.FillerType.Pourer) { line = $"F{Filler.Pos}={Zutat.Menge}"; } lines.Add(line); } - lines.Add("ZIEL"); - CocktailCode = String.Join("\r\n", lines.ToArray()); + lines.Add("ZIEL"); + CocktailCode = String.Join("\r\n", lines.ToArray()); } /// - /// Setzt die Alkoholintensität + /// Setzt die Alkoholintensität und berechnet die Mengen für ModifiedCocktail entsprechend neu /// /// Zugabe/Abzug von Alkohol in Prozent private void SetIntensity(int intensity) { DrinkIntensity = intensity; - if (ModifiedCocktail != null && SelectedCocktail != null) + if (ModifiedCocktail == null || SelectedCocktail == null) return; + + foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen) { - - foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen) + int OriginalMenge = SelectedCocktail.Cocktailflaschen.First(scf => scf.Id == cf.Id).Menge; + if (cf.Flasche.Alkoholisch) { - int OriginalMenge = SelectedCocktail.Cocktailflaschen.First(scf => scf.FlascheID == cf.FlascheID).Menge; - if (cf.Flasche.Alkoholisch) - { - cf.Menge = OriginalMenge + (OriginalMenge * intensity / 100); - } - else - { - cf.Menge = OriginalMenge - (OriginalMenge * intensity / 100); - } + cf.Menge = OriginalMenge + (OriginalMenge * intensity / 100); } - - // Durch das anteilige Umrechnen ändert sich die Gesamtmenge, daher passen wir die Mengen nochmal an - int AktGesMenge = ModifiedCocktail.Cocktailflaschen.Sum(cf => cf.Menge); - int OrigMenge = SelectedCocktail.Cocktailflaschen.Sum(cf => cf.Menge); - foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen) + else { - cf.Menge = (int)((float)cf.Menge / AktGesMenge * OrigMenge); + cf.Menge = OriginalMenge - (OriginalMenge * intensity / 100); } - } + // Durch das anteilige Umrechnen ändert sich die Gesamtmenge, daher passen wir die Mengen nochmal an + int AktGesMenge = ModifiedCocktail.Cocktailflaschen.Sum(cf => cf.Menge); + int OrigMenge = SelectedCocktail.Cocktailflaschen.Sum(cf => cf.Menge); + foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen) + { + cf.Menge = (int)((float)cf.Menge / AktGesMenge * OrigMenge); + } + } + + + // ToDo: Ggf. noch Rundungsfehler drin oder wirklich noch grobe Fehler in der Mathematik.. Gesamtmenge passt irgendwie nicht. + /// + /// Ändert die Alkoholintensität basierend auf den Prozentwerten anstatt der Menge + /// + /// Intensitätslevel (z.B. -1, 0, 1,2 ...) + private void SetIntensityPercentual(int intensitylevel) + { + DrinkIntensity = intensitylevel; + if (ModifiedCocktail == null || SelectedCocktail == null) return; + int DivideParts = 4; // Gibt an, in wieviele Teile die nicht-alkoholische Gesamtmenge aufgeteilt wird. Sollte mindestens 1 oder 2 mehr als das Max.Intensitätslevel sein + float IncreasePerLevel_pct; // Gibt an, um welchen Anteil in % die alkoholischen Getränke steigen. + + float SumAlcoholic_ml = SelectedCocktail.Cocktailflaschen.Where(cf => cf.Flasche.Alkoholisch).Sum(cf => cf.Menge); // Summe in ml der Alkoholhaltigen Zutaten + float SumNonAlcoholic_ml = SelectedCocktail.Cocktailflaschen.Where(cf => !cf.Flasche.Alkoholisch).Sum(cf => cf.Menge); // Summe in ml der Alkoholfreien Zutaten + float SumTotal = SumAlcoholic_ml + SumNonAlcoholic_ml; + float SumAlcoholic_pct = SumAlcoholic_ml / SumTotal * 100; //Prozentwert an alkoholhaltigen Zutaten + float SumNonAlcoholic_pct = SumNonAlcoholic_ml / SumTotal * 100; //Prozentwert an alkoholhaltigen Zutaten + float SumBasis_ml = intensitylevel >= 0 ? SumNonAlcoholic_ml : SumAlcoholic_ml; // Wenn Intensität > 0, dann ist Summenbasis nichtalkoholisch, ansonsten alkoholisch + if (intensitylevel >= 0) + { + /// Wenn alkoholhaltiges 30% ausmacht, teilen wir den Rest (alkoholfreis, 70%) durch die o.g. DivideParts, damit wir wissen um wieviel Prozent pro Stufe wir erhöhen können + IncreasePerLevel_pct = SumNonAlcoholic_pct / DivideParts; + } + else + { + // Cocktail abschwächen, daher teilen wir in die andere Richtung auf + IncreasePerLevel_pct = SumAlcoholic_pct / DivideParts; + } + + + foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen) + { + float OrigMenge = SelectedCocktail.Cocktailflaschen.First(f => f.Id == cf.Id).Menge; + // Herausfinden, wieviel Prozent die Zutat in ihrem Bereich (Alkoholisch/Nichtalkoholisch) ausmacht + float ZutatIncrease_pct = IncreasePerLevel_pct / SumBasis_ml * cf.Menge; + float ZutatMenge_pct = (float)OrigMenge / SumTotal * 100; + // Neue Menge in Prozent: ZutatMenge_pct + ZutatIncrease_pct + if (!cf.Flasche.Alkoholisch ^ intensitylevel < 0 ) + { + ZutatIncrease_pct *= -1; + } + cf.Menge = (int)Math.Round(OrigMenge / ZutatMenge_pct * (ZutatMenge_pct + (ZutatIncrease_pct * intensitylevel)), 0, MidpointRounding.AwayFromZero); + } } diff --git a/CocktailWeb/Notizen.txt b/CocktailWeb/_Docs/Notizen.txt similarity index 100% rename from CocktailWeb/Notizen.txt rename to CocktailWeb/_Docs/Notizen.txt diff --git a/CocktailWeb/_Docs/ProzentualeVerteilung.xlsx b/CocktailWeb/_Docs/ProzentualeVerteilung.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..3dd2e09a57b4969ce0c5ed924c259ba22713ca9b GIT binary patch literal 10592 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 Q9Z&(L5GUB8`t|nz0EIvzivR!s literal 0 HcmV?d00001