diff --git a/StarterNG.Tests/ConsistCrewTests.cs b/StarterNG.Tests/ConsistCrewTests.cs index 839086b..5e6dcd5 100644 --- a/StarterNG.Tests/ConsistCrewTests.cs +++ b/StarterNG.Tests/ConsistCrewTests.cs @@ -123,6 +123,39 @@ public class ConsistCrewTests Assert.Equal(eDriverType.Headdriver, loco.Cars[0].DriverType); } + [Fact] + public void A_unit_staffed_at_the_head_has_its_driver_in_cab_1_of_the_first_car() + { + var unit = Unit("ep07-001", "ep07-002"); + + _consist.Staff(unit, 0); + + Assert.Equal(eDriverType.Headdriver, unit.Cars[0].DriverType); + Assert.Equal(eDriverType.Nobody, unit.Cars[1].DriverType); + } + + [Fact] + public void A_driver_in_cab_2_moves_into_the_last_car_of_a_unit() + { + var loco = Add("ep07-001", 0); + loco.Cars[0].DriverType = eDriverType.Reardriver; + loco.Driver = eDriverType.Reardriver; + var unit = Unit("ep07-001", "ep07-002"); + + _consist.Replace(0, unit); + + Assert.Equal(eDriverType.Nobody, unit.Cars[0].DriverType); + Assert.Equal(eDriverType.Reardriver, unit.Cars[1].DriverType); + Assert.Equal(eDriverType.Reardriver, unit.Driver); + } + + private ConsistItem Unit(params string[] skins) => + new() + { + Cars = skins.Select(skin => _consist.MakeDynamic(_catalog.TextureForSkin(skin)!, null)).ToList(), + Grouped = true + }; + private ConsistItem Add(string skin, int at) { var item = Item(skin); diff --git a/StarterNG/Domain/Consist.cs b/StarterNG/Domain/Consist.cs index 4009545..7112afd 100644 --- a/StarterNG/Domain/Consist.cs +++ b/StarterNG/Domain/Consist.cs @@ -274,16 +274,36 @@ public sealed class Consist : IReadOnlyList } // The crew lives on the cars - they are what is shown and exported - and the - // card only mirrors it. + // card only mirrors it. A unit has one crew, in the car that has the cab. private static void Crew(ConsistItem item, eDriverType crew) { if (item.Cars.Count == 0) return; - item.Cars[0].DriverType = crew; + foreach (var car in item.Cars) + car.DriverType = eDriverType.Nobody; + CrewCar(item, crew).DriverType = crew; item.Driver = crew; } + /// + /// Where a unit's crew sits: cab 1 is at the front of its first car and cab 2 + /// at the back of its last - the ET42-A has only cab 1, the ET42-B only cab 2. + /// The unit's own order, so turning it round takes the cabs along. + /// + public static Dynamic CrewCar(ConsistItem item, eDriverType crew) => + crew == eDriverType.Reardriver ? item.Cars[^1] : item.Cars[0]; + + /// Puts the crew into the unit, in the car its cab is in. + public void SetCrew(ConsistItem item, eDriverType crew) + { + Crew(item, crew); + if (ReferenceEquals(Selected, item)) + SyncStartingVehicle(); + Raise(); + AppServices.Current.State.NotifyChanged(); + } + private bool IsPowered(ConsistItem item) => item.Cars.Count > 0 && _db.TextureFor(item.Cars[0].DataFolder, item.Cars[0].SkinFile, item.Cars[0].MmdFile) is { } texture && VehicleInfo.IsPoweredCategory(VehicleInfo.CategoryOf(texture)); @@ -400,22 +420,14 @@ public sealed class Consist : IReadOnlyList _items.Reverse(first, last - first + 1); } - public void CycleDriver(ConsistItem item) - { - var car = ActiveCar(item); - car.DriverType = car.DriverType switch + public void CycleDriver(ConsistItem item) => + SetCrew(item, item.Driver switch { eDriverType.Nobody => eDriverType.Headdriver, eDriverType.Headdriver => eDriverType.Reardriver, eDriverType.Reardriver => eDriverType.Passenger, _ => eDriverType.Nobody - }; - item.Driver = UnitDriver(item.Cars); - if (ReferenceEquals(Selected, item)) - SyncStartingVehicle(); - Raise(); - AppServices.Current.State.NotifyChanged(); - } + }); public void Split(ConsistItem item) { diff --git a/StarterNG/Views/Depot/VehicleCards.cs b/StarterNG/Views/Depot/VehicleCards.cs index a43d2cc..22a8dbd 100644 --- a/StarterNG/Views/Depot/VehicleCards.cs +++ b/StarterNG/Views/Depot/VehicleCards.cs @@ -612,9 +612,7 @@ public sealed class VehicleCards private void PaintDriverButton(Button btn, ConsistItem item) { - var type = ReferenceEquals(item, _consist.Selected) && item.Cars.Count > 1 - ? _consist.ActiveCar(item).DriverType - : item.Driver; + var type = item.Driver; (string glyph, string color) = type switch { diff --git a/StarterNG/Views/Depot/VehicleDetails.cs b/StarterNG/Views/Depot/VehicleDetails.cs index d185269..a64c3d8 100644 --- a/StarterNG/Views/Depot/VehicleDetails.cs +++ b/StarterNG/Views/Depot/VehicleDetails.cs @@ -262,17 +262,16 @@ public sealed class VehicleDetails } /// - /// The vehicle's own settings. Every write path is unchanged: crew and wagon number - /// go through the unit's active car, the coolant flag to its first car only. + /// The vehicle's own settings: the crew is the unit's and sits where its cab is, + /// the wagon number goes through the unit's active car, the coolant flag to its + /// first car only. /// private Control BuildVehicleSection(ConsistItem item) { var driver = new ComboBox { FontSize = 12, MinWidth = 0 }; foreach (string key in new[] { "DriverHead", "DriverRear", "DriverPassenger", "DriverNobody" }) driver.Items.Add(new ComboBoxItem { Content = App.Loc[key] }); - var crewCar = _consist.ActiveCar(item); - - driver.SelectedIndex = crewCar.DriverType switch + driver.SelectedIndex = item.Driver switch { eDriverType.Headdriver => 0, eDriverType.Reardriver => 1, @@ -288,14 +287,9 @@ public sealed class VehicleDetails 2 => eDriverType.Passenger, _ => eDriverType.Nobody }; - if (picked == crewCar.DriverType) return; + if (picked == item.Driver) return; - crewCar.DriverType = picked; - item.Driver = Consist.UnitDriver(item.Cars); - if (ReferenceEquals(_consist.Selected, item)) - _consist.SyncStartingVehicle(); - _redraw(); - AppServices.Current.State.NotifyChanged(); + _consist.SetCrew(item, picked); }; driver.MinWidth = 0; driver.HorizontalAlignment = HorizontalAlignment.Stretch;