public void CreateBoatTest() { var apiBoat = DefaultBoat(); var boatEntity = BoatData.CreateBoat(apiBoat); Assert.IsTrue(boatEntity.Identifier != 0, $"Failed to create boat {apiBoat.BuilderName} {apiBoat.ModelYear} {apiBoat.Model} "); }
/// <summary> /// Tries to load everything from the saved data directory /// </summary> /// <param name="objects">Reference list to store the loaded objects in</param> public void TryLoadAll(ref List <DataObject> objects) { if (!Directory.Exists(directory)) { return; } objects.AddRange(LoadFiles(directory + "/Members", (readData) => { var res = new MemberData( dataController, readData[1], long.Parse(readData[2]), readData[3], readData[4] ); return(res); })); objects.AddRange(LoadFiles(directory + "/Boats", (readData) => { var res = new BoatData( dataController, readData[1], long.Parse(readData[2]), (MemberData)dataController.RetrieveByID(readData[3]), int.Parse(readData[4]), (BoatType)Enum.Parse(typeof(BoatType), readData[5]) ); return(res); })); }
public void Setup(BoatData boat) { _boatData = boat; _boat = boat.Boat; nameText.text = boat.boatName; _rect = transform as RectTransform; }
/// <summary> /// Tries to load everything from the saved data directory /// </summary> /// <param name="objects">Reference list to store the loaded objects in</param> public void TryLoadAll(ref List <DataObject> objects) { if (!Directory.Exists(directory)) { return; } objects.AddRange(LoadFiles(directory + "/Members", (readData) => { var res = new MemberData(dataController, readData[1], long.Parse(readData[2])); res.Name = readData[3]; res.PersonalNumber = readData[4]; return(res); })); objects.AddRange(LoadFiles(directory + "/Boats", (readData) => { var res = new BoatData(dataController, readData[1], long.Parse(readData[2])); var owner = (MemberData)dataController.RetrieveByID(readData[3]); owner.RegisterBoat(res); res.Length = int.Parse(readData[4]); res.BoatType = (BoatType)Enum.Parse(typeof(BoatType), readData[5]); return(res); })); }
private Boat UpdateBoat(Boat apiBoat) { var boatEntity = BoatData.UpdateBoat(apiBoat); Assert.IsNotNull(boatEntity.Identifier, "UpdateBoat Failed. Identifier is null"); return(boatEntity); }
public void GetBoatTest() { var apiBoat = DefaultBoat(); var boatEntity = BoatData.CreateBoat(apiBoat); var boat = BoatData.GetBoatbyId(boatEntity.Identifier); Assert.IsNotNull(boat.BuilderName, $"No boat is retrieved"); }
/// <summary> /// Initializes a new instance of the <see cref="Boat" /> class. /// </summary> /// <param name="boatData">The boat data.</param> public Boat(BoatData boatData) { StartNumber = boatData.BibNumber; Club = boatData.TitleShort; Comment = ""; Status = BoatStatus.None; Visibility = Visibility.Visible; }
public void CreateAndUpdateBoatTest() { var apiBoat = DefaultBoat(); var boatEntity = BoatData.CreateBoat(apiBoat); boatEntity.Model = "ChangedModel"; var updatedBoat = UpdateBoat(boatEntity); Assert.IsTrue(boatEntity.Identifier == updatedBoat.Identifier, $"UpdateBoat failed. Id's {boatEntity.Identifier}!={updatedBoat.Identifier }"); Assert.IsTrue("ChangedModel" == updatedBoat.Model, $"UpdateBoat failed. OriginalModel!={updatedBoat.Model}"); }
public void SetBoatData(string targetID, string ownerID, int length, BoatType type) { BoatData bd = (BoatData)RetrieveByID(targetID); if (ownerID != null) { ((MemberData)RetrieveByID(ownerID)).RegisterBoat(bd); } bd.Length = length; bd.BoatType = type; fileController.SaveToFile(bd); }
public void CreateAndDeleteBoatTest() { Boat apiBoat = null; apiBoat = DefaultBoat(); var boatEntity = BoatData.CreateBoat(apiBoat); BoatData.DeleteBoatbyId(boatEntity.Identifier); var boat = BoatData.GetBoatbyId(boatEntity.Identifier); Assert.IsNull(boat, $"The boat is not deleted"); }
public async Task <IHttpActionResult> GetBoat(int boatId) { var result = await Task <Boat> .Run(() => BoatData.GetBoatbyId(boatId)); if (result != null) { return(Ok(result)); } else { return(Content(HttpStatusCode.NotFound, $"No boat is available for the boatId provided")); } }
public async Task <IHttpActionResult> GetBoat() { var result = await Task <Boats> .Run(() => BoatData.GetBoats()); if (result != null) { return(Ok(result)); } else { return(Content(HttpStatusCode.NotFound, $"No Boats available")); } }
public void GetAllBoatTest() { var boat1 = DefaultBoat(); var boatEntity = BoatData.CreateBoat(boat1); Assert.IsNotNull(boatEntity, $"CreateBoat failed."); var boat2 = DefaultAdditionalBoat(); var boatEntityAdditional = BoatData.CreateBoat(boat2); Assert.IsNotNull(boatEntityAdditional, $"CreateBoat failed."); var boats = BoatData.GetBoats(); Assert.IsTrue(boats.BoatCollection.Count > 0, $"All boats are not retrieved"); }
public async Task <IHttpActionResult> PutBoat(Boat boat) { if (boat.Identifier == 0) { return(Content(HttpStatusCode.BadRequest, $"Identifier should be provided")); } var result = await Task <Boat> .Run(() => BoatData.UpdateBoat(boat)); if (result != null) { return(Ok(result)); } else { return(Content(HttpStatusCode.NotFound, $"No boat is available for the Identifier provided")); } }
public async Task <IHttpActionResult> PostBoat(Boat boat) { if (boat.Identifier != 0) { return(Content(HttpStatusCode.BadRequest, $"Identifier should be null")); } var result = await Task <Boat> .Run(() => BoatData.CreateBoat(boat)); if (result != null) { return(Ok(result)); } else { return(Content(HttpStatusCode.BadRequest, $"Not able to add the boat")); } }
public void Setup(BoatData boat, float scale = 0.0028f) // TODO magic number for mini map size { _boatData = boat; _boat = boat.Boat; _boatTransform = boat.Boat.transform; _rect = transform as RectTransform; _scale = scale; var p = _boatData.livery.primaryColor; p.a = 1f; primary.color = p; var t = _boatData.livery.trimColor; t.a = 1f; secondary.color = t; _playerCount = RaceManager.RaceData.boatCount; }
private void AddButton_OnClick(object sender, RoutedEventArgs e) { string id = IdInput.Text.ToUpperInvariant(); if (!int.TryParse(WeightInput.Text, out int weight)) { DoError(); } if (!int.TryParse(SpeedInput.Text, out int speed)) { DoError(); } if (!int.TryParse(UniqueInput.Text, out int unique)) { DoError(); } var data = new BoatData { Type = HarborHelper.RegisteredBoatTypes[(string)TypeCombo.SelectedValue].FullName, Prefix = template.IdentityCode.First(), Code = id, TopSpeed = speed, Weight = weight, Characteristic = unique }; try { var newBoat = Boat.FromData(data); control.AddBoat(newBoat); Close(); } catch { DoError(); } }
/// <summary> /// Helper function for reading BoatData to a human-readable string /// </summary> /// <param name="data"></param> /// <param name="displayMode"></param> /// <returns></returns> string BoatToString(BoatData data, ListDisplayMode displayMode) { var owner = data.Owner; return($"ID: {data.ID}, {data.Length}m {data.BoatType}, " + (owner == null ? "ownerless" :$" owned by {owner.Name} (ID: {owner.ID})")); }
/// <summary> /// Shows a context-sensitive menu for listing, viewing, creating, editing, or deleting boats /// </summary> /// <param name="dataMode"></param> /// <param name="selectedID"></param> void ShowBoatMenu(DataMode dataMode, string selectedID = null) { Console.Clear(); string selected = selectedID; BoatData selectedData = null; if (dataMode != DataMode.Create) { if (selected == null) { selected = SelectBoat($"Please select the boat whose details you wish to {(dataMode == DataMode.View?"view":"edit")}:\n"); } selectedData = (BoatData)DataController.RetrieveByID(selected); } switch (dataMode) { case DataMode.Create: case DataMode.Edit: { Dictionary <string, object> arguments = new Dictionary <string, object>(); var owner = SelectMember("Please select the owner to register the new boat on\n"); arguments.Add("owner", owner); Console.Write("Specify length of vessel in metre (m):"); arguments.Add("length", int.Parse(Console.ReadLine())); var boatType = Enum.Parse(typeof(BoatType), ListSelection <string>("Please specify type of vessel", Enum.GetNames(typeof(BoatType)).ToList <object>())); arguments.Add("boat-type", boatType); if (dataMode == DataMode.Create) { DataController.CreateData(typeof(BoatData), arguments); } else { DataController.ChangeData(selected, arguments); } break; } case DataMode.View: { Console.Clear(); Console.Write( $"Boat ID: {selectedData.ID}\n" + $"Time of creation: {selectedData.Timestamp}\n\n" + $"Length: {selectedData.Length} metre\n" + $"Type: {selectedData.BoatType}\n" + (selectedData.Owner == null ? $"Owner: Owner not found\n" : $"Owner: {selectedData.Owner.Name} (M-ID: {selectedData.Owner.ID})\n")); Console.WriteLine("\nPress E to edit this - Press D to delete this - Any else to return to main menu..."); var key = Console.ReadKey().Key; switch (key) { case ConsoleKey.E: ShowBoatMenu(DataMode.Edit, selected); break; case ConsoleKey.D: ShowDeleteConfirmation(selected); break; default: return; } break; } } }
/// <summary> /// Loads the data from database. /// </summary> private void LoadDataFromDb() { // Event-Id aus den Einstellungen holen var eventId = Properties.Settings.Default.EventId; using (var db = new AquariusDataContext(Properties.Settings.Default.ConnectionString)) { // Test-Zugriff auf DB try { var test = db.Events.ToList(); } catch (Exception ex) { MessageBox.Show("Fehler beim Datenbank-Zugriff! Verbindung zur Datenbank und Connection String in den Einstellungen prüfen.\r\n\r\nDetails:\r\n\r\n" + ex.ToString()); return; } var dbData = GlobalData.Instance; // Veranstaltungen laden var dbEvents = db.Events; dbData.EventsData = dbEvents.Select(e => new EventData() { Id = e.Event_ID, Title = e.Event_Title }).ToList(); if (dbData.EventsData.SingleOrDefault(ed => ed.Id == eventId) == null) { MessageBox.Show("Veranstaltung nicht gefunden! Veranstaltung in den Einstellungen auswählen und Programm neu starten!"); return; } // Altersklassen einlesen var dbAgeClasses = db.AgeClasses.ToDictionary(ac => ac.AgeClass_ID, ac => ac); // Bootsklassen einlesen var dbBoatClasses = db.BoatClasses.ToDictionary(bc => bc.BoatClass_ID, bc => bc); // Ausschreibung einlesen var dbOffers = db.Offers.Where(o => o.Offer_Event_ID_FK == eventId).ToDictionary(o => o.Offer_ID, o => o); // Wettkämpfe einlesen var dbCompetions = db.Comps.Where(c => (c.Comp_Event_ID_FK == eventId) && c.Comp_DateTime != null).OrderBy(c => c.Comp_DateTime); // Boote einlesen (Entries sind Boote, in jedem Boot sitzt eine Mannschaft) // (gruppiert nach Meldung) var dbEntries = db.Entries.Where(e => e.Entry_Event_ID_FK == eventId).GroupBy(ee => ee.Entry_Race_ID_FK).ToDictionary(ee => ee.Key, ee => ee.Select(x => x).ToList()); // Mannschaften einlesen // (gruppiert nach dem Boot, in dem sie sitzt) var dbCrews = db.Crews.GroupBy(c => c.Crew_Entry_ID_FK).ToDictionary(c => c.Key, c => c.Select(x => x).ToList()); // Ruderer einlesen var dbAthlets = db.Athlets.ToDictionary(a => a.Athlet_ID, a => a); // Vereine einlesen var dbClubs = db.Clubs.ToDictionary(c => c.Club_ID, c => c); // Mappings Boot (!) <-> Verein var dbEntryLabels = db.EntryLabels.ToDictionary(el => el.EL_ID, el => el); // Labels für Boote (!) var dbLabels = db.Labels.ToDictionary(l => l.Label_ID, l => l); // Rennen tauchen mehrfach auf, falls es z. B. mehrere Leistungsgruppen gibt. // Da die Läufe aber ggf. noch nicht eingeteilt sind, lassen sich die Personen nicht // den einzelnen Rennen/Läufen zuweisen. // Derartig mehrfach vorkommende Rennen werden daher zu einem Rennen zusammengefasst: var competitionGroups = dbCompetions.GroupBy(c => c.Comp_Race_ID_FK).ToList(); #region Wettkämpfe durchgehen dbData.RacesData = new List <RaceData>(); foreach (var competionGroup in competitionGroups) { _ = dbOffers.TryGetValue((int)competionGroup.Key, out var offer); _ = dbAgeClasses.TryGetValue(offer.Offer_AgeClass_ID_FK, out var ageClass); _ = dbBoatClasses.TryGetValue(offer.Offer_BoatClass_ID_FK, out var boatClass); var isChildrenRace = (ageClass.AgeClass_MaxAge <= 14); bool isLightweightRace = (offer.Offer_IsLightweight); var isCoxedRace = (boatClass.BoatClass_Coxed == 1); // Entscheiden, ob man das Rennen übernehmen muss var raceOk = false; if (isLightweightRace) { raceOk = true; // alle Leichtgewichtsrennen müssen zur Waage } if (isCoxedRace && !isChildrenRace) { raceOk = true; // gesteuerte Rennen, die keine Kinderrennen sind, müssen zur Waage } if (raceOk) { // Rennzeit ist die Zeit des ersten Rennens dieser Gruppe var raceTime = (DateTime)competionGroup.Select(x => x).OrderBy(c => c.Comp_DateTime).First().Comp_DateTime; #region Gewichte bestimmen var maxSingleWeight = new Weight(ageClass.AgeClass_LW_UpperLimit, true); var maxAverageWeight = new Weight(ageClass.AgeClass_LW_AvgLimit, true); var minCoxWeight = new Weight(ageClass.AgeClass_LW_CoxLowerLimit, true); var maxAdditionalCoxWeight = new Weight(ageClass.AgeClass_LW_CoxTolerance, true); // wenn es kein gesteuertes Rennen ist, dann interessiert das Gewicht des Steuermanns nicht if (!isCoxedRace) { minCoxWeight.Value = null; } // bei Kinderrennen interessiert das Gewicht des Steuermanns ebenfalls nicht if (isChildrenRace) { minCoxWeight.Value = null; } // bei Einer-Rennen kein Mannschaftsdurchschnittsgewicht if (boatClass.BoatClass_NumRowers == 1) { maxAverageWeight.Value = null; } // Wenn es kein Leichgewichtsrennen ist, dann interessieren auch die Gewichte der Ruderer nicht if (!isLightweightRace) { maxSingleWeight.Value = null; maxAverageWeight.Value = null; } #endregion // Rennen definieren und hinzufügen var newRace = new RaceData() { Id = offer.Offer_ID, RaceNumber = offer.Offer_RaceNumber, ShortTitle = offer.Offer_ShortLabel, LongTitle = offer.Offer_LongLabel, DateTime = raceTime, IsChildrenRace = isChildrenRace, IsCoxedRace = isCoxedRace, NumberOfRowers = boatClass.BoatClass_NumRowers, IsLightweightRace = isLightweightRace, MaxSingleWeight = maxSingleWeight, MaxAverageWeight = maxAverageWeight, MinCoxWeight = minCoxWeight, MaxAdditionalCoxWeight = maxAdditionalCoxWeight }; dbData.RacesData.Add(newRace); // zum aktuellen Rennen die Boote hinzufügen newRace.BoatsData = new List <BoatData>(); _ = dbEntries.TryGetValue(offer.Offer_ID, out var entries); if (entries != null) { foreach (var entry in entries) { // das Label für das Boot (!) (z. B. "Renngemeinschaft ...") bestimmen var titleShort = "?"; var titleLong = "?"; var entryLabel = dbEntryLabels.Values.FirstOrDefault(el => el.EL_Entry_ID_FK == entry.Entry_ID); if (entryLabel != null) { dbLabels.TryGetValue(entryLabel.EL_Label_ID_FK, out var label); titleShort = label?.Label_Short; titleLong = label?.Label_Long; } var newBoat = new BoatData() { TitleShort = titleShort, TitleLong = titleLong, BibNumber = (byte)entry.Entry_Bib, Canceled = (entry.Entry_CancelValue > 0) }; newRace.BoatsData.Add(newBoat); // Zum aktuellen Boot die Mannschaft hinzufügen newBoat.Rowers = new List <RowerData>(); _ = dbCrews.TryGetValue(entry.Entry_ID, out var crew); #region Sonderbehandlung der Crew für den Fall, dass es Ummeldungen gibt // TODO: Es ist nicht ganz klar, woran man Ummeldungen erkennt, bzw. woran // man erkennt, welches das alte, und welches das neue Crewmitglied // ist. Auf jeden Falls stehen beiden in der DB drin. if (crew != null) { // Gruppieren nach dem Sitzplatz var crewByPos = crew.GroupBy(c => c.Crew_Pos).ToList(); // Crew-Liste löschen und neu füllen crew = new List <Crew>(); foreach (var item in crewByPos) { // die Ruderer für die aktuelle Sitzposition sortiert nach DB-ID // TODO: Ist DB-ID wirklich das richtige ??? var rowersOnCurrentPos = item.Select(x => x).OrderBy(x => x.Crew_ID); crew.Add(rowersOnCurrentPos.Last()); } } #endregion if (crew != null) { // Crew durchgehen und ins Boot platzieren foreach (var crewMember in crew) { dbAthlets.TryGetValue(crewMember.Crew_Athlete_ID_FK, out var athlet); dbClubs.TryGetValue((int)athlet.Athlet_Club_ID_FK, out var club); if ((athlet != null) && (club != null)) { var newRower = new RowerData() { Id = athlet.Athlet_ID, ClubTitleLong = club.Club_Name, ClubTitleShort = club.Club_Abbr, LastName = athlet.Athlet_LastName, FirstName = athlet.Athlet_FirstName, DateOfBirth = athlet.Athlet_DOB, Gender = (athlet.Athlet_Gender == 'M') ? Gender.Male : Gender.Female }; if (crewMember.Crew_IsCox) { // es handelt sich um den Steuermann newBoat.Cox = newRower; } else { // normaler Ruderer newBoat.Rowers.Add(newRower); } } else { // Fehler: Ruderer oder Verein nicht gefunden Tools.LogErrorNoMessageBox("Warnung: Ruderer oder kein Verein zu Crew nicht gefunden. Rennen ", offer.Offer_RaceNumber, offer.Offer_ShortLabel); } } } else { // Fehler: keine Mannschaft für das Boot gefunden Tools.LogErrorNoMessageBox("Warnung: Mannschaft zu Rennen nicht gefunden. Rennen ", offer.Offer_RaceNumber, offer.Offer_ShortLabel); } } } // Boote sortieren nach Startnummer newRace.BoatsData = newRace.BoatsData.OrderBy(b => b.BibNumber).ToList(); } } #endregion #region Ruderer anhand der ermittelten Rennen bestimmen var newRowers = new List <RowerData>(); foreach (var raceData in dbData.RacesData) { foreach (var boatData in raceData.BoatsData) { // Ruderer hinzufügen foreach (var rowerData in boatData.Rowers) { if (!newRowers.Any(r => r.Id == rowerData.Id)) { newRowers.Add(rowerData); } } // Steuermann hinzufügen if (boatData.Cox != null) { if (!newRowers.Any(r => r.Id == boatData.Cox.Id)) { newRowers.Add(boatData.Cox); } } } } dbData.RowersData = newRowers.OrderBy(r => r.LastName).ThenBy(r => r.FirstName).ToList(); #endregion // Rennen sortieren nach Startzeit dbData.RacesData = dbData.RacesData.OrderBy(r => r.DateTime).ToList(); } }
/// <summary> /// Sets the boat status. /// </summary> /// <param name="boat">The boat.</param> public void SetBoatStatus(RaceData raceData, BoatData boatData, UserControls.Race race, UserControls.Boat boat) { if (boatData.Canceled) { // Boot ist abgemeldet boat.Comment = "Boot abgemeldet!"; boat.Status = UserControls.BoatStatus.BoatOk; boat.Canceled = true; // Wenn das Boot abgemeldet ist, dann ist es egal, ob die einzelnen Ruderer darin zum Wiegen da waren oder nicht. // Diese Ruderer sollen dann nicht als zu schwer oder fehlend angezeigt werden, sondern als in Ordnung. var rowsers = boat.Rowers.Where(r => new[] { UserControls.RowerStatus.TooLate, UserControls.RowerStatus.WeightNotOk }.Contains(r.Status)); foreach (var rower in rowsers) { rower.Status = UserControls.RowerStatus.WaitingForTimeWindow; } return; } // Im UserControl ("boat") sind Ruderer und Steuermann in einer gemeinsamen Liste enthalten // und lassen sich nur durch das Type-Attribut des jeweiligen Eintrags unterscheiden var rowersWithoutCox = boat.Rowers.Where(r => r.Type == UserControls.RowerType.Rower); // Prüfen ob das Boot vollständig besetzt ist if (raceData.NumberOfRowers != rowersWithoutCox.Count()) { boat.Comment = "Anzahl der Ruderer passt nicht zur Bootsklasse!"; boat.Status = UserControls.BoatStatus.BoatNok; return; } // Prüfen ob der Steuermann da ist if (raceData.IsCoxedRace && (boat.Rowers.Count(r => r.Type == UserControls.RowerType.Cox) != 1)) { boat.Comment = "Steuermann fehlt!"; boat.Status = UserControls.BoatStatus.BoatNok; return; } // Durchschnittsgewicht wird berechnet, wenn es mehr als einen Ruderer gibt und // wenn mindestens schon von einem Ruderer das Gewicht vorliegt. var calculateAverageWeight = (rowersWithoutCox.Count() > 1) && (rowersWithoutCox?.Any(r => r.WeightInfo != null) == true); // Durchschnittsgewicht wird auf Richtigkeit geprüft, wenn ein Sollwert vorhanden ist var checkAverageWeightOk = calculateAverageWeight && (raceData.MaxAverageWeight?.Value != null) && (raceData.MaxAverageWeight.Value > 0); float averageWeight = 0; boat.AverageWeight = ""; if (checkAverageWeightOk) { // Durschnittsgewicht berechnen var count = 0; foreach (var rower in rowersWithoutCox) { if (rower.WeightInfo != null) { averageWeight += (float)rower.WeightInfo; count++; } } if (count == 0) { averageWeight = 0; } else { averageWeight = averageWeight / count; boat.AverageWeight = $"(ø {averageWeight} kg)"; } if (checkAverageWeightOk) { } } // Reihenfolge beachten! if (boat?.Rowers?.Any(r => r.Status == UserControls.RowerStatus.WeightNotOk) == true) { // es gibt Ruderer, bei denen das Gewicht nicht passt boat.Status = UserControls.BoatStatus.BoatNok; } else if (boat?.Rowers?.Any(r => r.Status == UserControls.RowerStatus.TooLate) == true) { // Es gibt Ruderer, die das Wiegen verpasst haben boat.Status = UserControls.BoatStatus.BoatNok; } else if (boat?.Rowers?.Any(r => r.Status == UserControls.RowerStatus.WaitingForTimeWindow) == true) { // Es gibt Ruderer ohne Gewicht, für die es noch zu früh zum Wiegen ist boat.Status = UserControls.BoatStatus.WaitingForTimeWindow; } else if (boat?.Rowers?.Any(r => r.Status == UserControls.RowerStatus.WaitingInsideTimeWindow) == true) { // Es gibt Ruderer ohne Gewicht, die jetzt zum wiegen dran wären boat.Status = UserControls.BoatStatus.WaitingInsideTimeWindow; } else if (boat.Rowers.All(r => r.Status == UserControls.RowerStatus.WeightOk)) { // alle Ruderer sind einzeln OK, jetzt muss noch das Durschnittsgewicht stimmen if (checkAverageWeightOk) { boat.Status = (averageWeight <= raceData.MaxAverageWeight.Value) ? UserControls.BoatStatus.BoatOk : UserControls.BoatStatus.BoatNok; } else { // Durschnittsgewicht interessiert nicht boat.Status = UserControls.BoatStatus.BoatOk; } } // Zusatzgewicht bestimmen var cox = boat.Rowers.SingleOrDefault(r => r.Type == UserControls.RowerType.Cox); if (cox != null) { // es gibt einen Steuermann if (cox.WeightInfo != null) { // es gibt ein Gewicht für den Steuermann if (raceData.MinCoxWeight.IsSpecified()) { // Sollgewicht für Steuermann vorhanden var weight = (float)cox.WeightInfo; var additionalWeight = raceData.MinCoxWeight.Value - weight; if (additionalWeight > 0) { // Steuermann ist zu leicht boat.Comment = $"Zusatzgewicht für Steuermann! => {additionalWeight:0.0} kg"; } } } } }