# Review PR #265 — AI on up gradients: hold a train coming to a stand, start on the train brake Autor: @pwarszawski · base: `master` (zbudowany na #264 → #263 → #187, #262) · przyrost: `Driver.cpp/.h`, ~+150/−5 https://github.com/MaSzyna-EU07/maszyna/pull/265 **Werdykt: Request changes — ryzyko dla sprzęgów i stan `bUphillStart`** > Recenzja dotyczy tylko przyrostu ponad #264 (interdiff policzony lokalnie). ## Podsumowanie 1. **Zatrzymanie pod górę:** hamulec zespolony zaciągany zanim samo wzniesienie zatrzyma pociąg; bez luzowania poniżej 10 km/h (`uphill_stop_hold()`); bez „dociągania” gdy hamulec już działa (`uphill_brake_committed()`); hamulec lokomotywy < 3 km/h i natychmiast przy staczaniu. 2. **Ruszanie pod górę** (`control_uphill_start()`): hamulec zespolony zostaje, lokomotywa odhamowana (dodatkowy + odluźniacz), moc podawana przeciw zahamowanemu składowi; zwolnienie hamulca gdy Ft > 1.1 × siła z pochylenia, pociąg ruszy, albo po 45 s. Wyniki bardzo dobre: staczanie po zatrzymaniu 51 → 0, ruszanie ze staczaniem 7/62 → 0/155. ## Uwagi blokujące 1. **Pełna moc przeciw zahamowanemu składowi przez 10–18 s.** Opis sam to przyznaje („still applies full power at once”). Dla ciężkich towarów to klasyczny przepis na zerwanie sprzęgu (por. dyskusję w #187 i fix #255). Proszę o: - statystykę maks. sił w sprzęgach podczas ruszania (base vs PR) dla najcięższych składów (ET42 + 30 wagonów, ET41 + 25), - albo ograniczenie mocy do wartości potrzebnej na utrzymanie (np. do ~1.1–1.2 × `holdingforce`) dopóki `bUphillStart`. 2. **`bUphillStart` może utknąć na `true`.** Flaga jest resetowana tylko w `control_uphill_start()`, wołanym z `control_tractive_force()`. Jeśli AI zostanie wyłączone w trakcie ruszania (Shift+Q / Q, a po #231 także z menu), flaga zostaje, a w `determine_consist_state()` `heldforstart` dalej: - ignoruje niezluzowane hamulce przy ustalaniu `Ready`, - zeruje `fReady`. Proszę resetować `bUphillStart` przy przejęciu sterowania przez gracza / zmianie rozkazu / `OrderCurrentGet()`, a w `determine_consist_state()` warunkować to dodatkowo `AIControllFlag`. 3. **`Ready` ignoruje *każde* hamowanie** podczas ruszania (także `vehicle->Fb > 10 kN`, np. zaciągnięty hamulec ręczny wagonu albo niezluzowany wagon z innego powodu). Przez 45 s AI będzie ciągnąć przeciw nim. Lepiej ignorować tylko hamulec zespolony (`b_on|b_hld` przy zaciągniętym kranie), a `Fb` od hamulca ręcznego/postojowego nadal blokować. ## Pozostałe uwagi 4. **Niespójne progi pochylenia:** `-0.005` (`uphill_stop_hold`, lokomotywa przy staczaniu), `-0.01` (`control_uphill_start`), `-0.025` (`uphill_brake_committed`, #187), `-0.05` (staczanie w `control_braking_force`). Proszę o nazwane stałe i krótkie uzasadnienie różnic. 5. **Odluźniacz przy ruszaniu a #263.** Po #263 odluźniacz ESt3 opróżnia ZS ~23 s zamiast ~6 s — czy pomiary „10–18 s pulling against the brake” były robione już z nowym odluźniaczem (stos sugeruje, że tak — proszę potwierdzić)? 6. **Złożoność (Sonar S3776/S134/S1067):** warunek `independentbrakeapply` w `control_braking_force()` ma 9 członów z mieszanym `&&`/`||` — wydzielić do `bool should_hold_on_independent_brake(double velocity) const`. 7. **`break` w `DecBrake()`** — działa, bo jesteśmy w `switch`, ale przy dwóch nowych `break` przed właściwą logiką czytelniej byłoby jedno wczesne wyjście z komentarzem. 8. `fUphillStartTime` mierzony `ElapsedTime` — przy pauzie/przyspieszeniu czasu OK, ale 45 s powinno być stałą nazwaną (`uphill_start_timeout`). 9. **Kolejność merge:** całego stosu #187 → #262 → #263 → #264 → #265 — zaproponuję maintainerom zmergować to w jednym oknie po kolei, z rebase każdego PR po poprzednim, żeby CI/Sonar liczyły tylko przyrost.