diff --git a/Driver.cpp b/Driver.cpp index c134f670..488ec00d 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -11,7 +11,7 @@ http://mozilla.org/MPL/2.0/. Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others */ - +#include #include "system.hpp" #include "classes.hpp" #pragma hdrstop @@ -282,28 +282,70 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len) return false; }; +AnsiString TSpeedPos::GetName() +{ + if (iFlags & spTrack) // jeśli tor + return trTrack->NameGet(); + else if (iFlags & spEvent) // jeśli event + return evEvent->asName; +} + AnsiString TSpeedPos::TableText() { // pozycja tabelki prędkości if (iFlags & spEnabled) { // o ile pozycja istotna - if (iFlags & spTrack) // jeśli tor - return "Flags=#" + IntToHex(iFlags, 8) + ", Dist=" + FloatToStrF(fDist, ffFixed, 7, 1) + - ", Vel=" + AnsiString(fVelNext) + ", Track=" + trTrack->NameGet(); - else if (iFlags & spEvent) // jeśli event - return "Flags=#" + IntToHex(iFlags, 8) + ", Dist=" + FloatToStrF(fDist, ffFixed, 7, 1) + - ", Vel=" + AnsiString(fVelNext) + ", Event=" + evEvent->asName; + return "Flags=#" + IntToHex(iFlags, 8) + ", Dist=" + FloatToStrF(fDist, ffFixed, 7, 1) + + ", Vel=" + AnsiString(fVelNext) + ", Name=" + GetName(); + //if (iFlags & spTrack) // jeśli tor + // return "Flags=#" + IntToHex(iFlags, 8) + ", Dist=" + FloatToStrF(fDist, ffFixed, 7, 1) + + // ", Vel=" + AnsiString(fVelNext) + ", Track=" + trTrack->NameGet(); + //else if (iFlags & spEvent) // jeśli event + // return "Flags=#" + IntToHex(iFlags, 8) + ", Dist=" + FloatToStrF(fDist, ffFixed, 7, 1) + + // ", Vel=" + AnsiString(fVelNext) + ", Event=" + evEvent->asName; } return "Empty"; } -bool TSpeedPos::Set(TEvent *event, double dist) +bool TSpeedPos::IsProperSemaphor(TOrders order) +{ // sprawdzenie czy semafor jest zgodny z trybem jazdy + if (order < 0x40) // Wait_for_orders, Prepare_engine, Change_direction, Connect, Disconnect, Shunt + { + if (iFlags & (spSemaphor | spShuntSemaphor)) + return true; + else if (iFlags & spOutsideStation) + return true; + } + else if (order & Obey_train) + { + if (iFlags & spSemaphor) + return true; + } + return false; // true gdy zatrzymanie, wtedy nie ma po co skanować dalej +} + +bool TSpeedPos::Set(TEvent *event, double dist, TOrders order) { // zapamiętanie zdarzenia fDist = dist; iFlags = spEnabled | spEvent; // event+istotny evEvent = event; vPos = event->PositionGet(); // współrzędne eventu albo komórki pamięci (zrzutować na tor?) CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości - return fVelNext == 0.0; // true gdy zatrzymanie, wtedy nie ma po co skanować dalej + // zależnie od trybu sprawdzenie czy jest tutaj gdzieś semafor lub tarcza manewrowa + // jeśli wskazuje stop wtedy wystawiamy true jako koniec sprawdzania + // WriteLog("EventSet: Vel=" + AnsiString(fVelNext) + " iFlags=" + AnsiString(iFlags) + " order="+AnsiString(order)); + if (order < 0x40) // Wait_for_orders, Prepare_engine, Change_direction, Connect, Disconnect, Shunt + { + if (iFlags & (spSemaphor | spShuntSemaphor) && fVelNext == 0.0) + return true; + else if (iFlags & spOutsideStation) + return true; + } + else if (order & Obey_train) + { + if (iFlags & spSemaphor && fVelNext == 0.0) + return true; + } + return false; // true gdy zatrzymanie, wtedy nie ma po co skanować dalej }; void TSpeedPos::Set(TTrack *track, double dist, int flag) @@ -383,7 +425,8 @@ bool TController::TableNotFound(TEvent *e) void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) { // skanowanie trajektorii na odległość (fDistance) od (pVehicle) w kierunku przodu składu i // uzupełnianie tabelki - if (!iDirection) // kierunek pojazdu z napędem + // WriteLog("Starting TableTraceRoute"); + if (!iDirection) // kierunek pojazdu z napędem { // jeśli kierunek jazdy nie jest okreslony iTableDirection = 0; // czekamy na ustawienie kierunku } @@ -411,6 +454,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) } else { // kontynuacja skanowania od ostatnio sprawdzonego toru (w ostatniej pozycji zawsze jest tor) + // WriteLog("TableTraceRoute: check last track"); if (sSpeedTable[iLast].iFlags & spEndOfTable) // zatkanie { // jeśli zapełniła się tabelka if ((iLast + 1) % iSpeedTableSize == iFirst) // jeśli nadal jest zapełniona @@ -427,9 +471,23 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) } sSpeedTable[iLast].iFlags &= 0xBE; // kontynuować próby doskanowania } - //else if (VelNext == 0) - // return; // znaleziono semafor lub tor z prędkością zero i nie ma co dalej sprawdzać - //trzeba dalej sprawdzać, gdyż przy stopinfo potrafił zgubić semafor + // znaleziono semafor lub tarczę lub tor z prędkością zero + // trzeba sprawdzić czy to nadał semafor + // WriteLog("TableTraceRoute: check semaphor"); + // if (sSemNext) + // WriteLog(sSemNext->TableText()); + if (sSemNext && + sSemNext->fVelNext == + 0.0) // jeśli jest następny semafor to sprawdzamy czy to on nadał zero + { + // WriteLog("TableTraceRoute: "+sSemNext->TableText()); + if ((OrderCurrentGet() & Obey_train) && (sSemNext->iFlags & spSemaphor)) + return; + else if ((OrderCurrentGet() < 0x40) && + (sSemNext->iFlags & (spSemaphor | spShuntSemaphor | spOutsideStation))) + return; + } + pTrack = sSpeedTable[iLast].trTrack; // ostatnio sprawdzony tor if (!pTrack) return; // koniec toru, to nie ma co sprawdzać (nie ma prawa tak być) @@ -444,25 +502,49 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) } if (fCurrentDistance < fDistance) { // jeśli w ogóle jest po co analizować + // WriteLog("TableTraceRoute: checking next tracks"); --iLast; // jak coś się znajdzie, zostanie wpisane w tę pozycję, którą właśnie odczytano while (fCurrentDistance < fDistance) { if (pTrack != tLast) // ostatni zapisany w tabelce nie był jeszcze sprawdzony { // jeśli tor nie był jeszcze sprawdzany - if (pTrack) - WriteLog("TableTraceRoute: checking track " + pTrack->NameGet()); - if ((pEvent = CheckTrackEvent(fLastDir, pTrack)) != + if (pTrack) + WriteLog("TableTraceRoute: " + OwnerName() + " checking track " + + pTrack->NameGet()); + if ((pEvent = CheckTrackEvent(fLastDir, pTrack)) != NULL) // jeśli jest semafor na tym torze { // trzeba sprawdzić tabelkę, bo dodawanie drugi raz tego samego przystanku nie // jest korzystne if (TableNotFound(pEvent)) // jeśli nie ma if (TableAddNew()) { - WriteLog("TableTraceRoute: new event found " + pEvent->asName); - if (sSpeedTable[iLast].Set(pEvent, - fCurrentDistance)) // dodanie odczytu sygnału + WriteLog("TableTraceRoute: new event found " + pEvent->asName + " by " + + OwnerName()); + if (sSpeedTable[iLast].Set( + pEvent, fCurrentDistance, + OrderCurrentGet())) // dodanie odczytu sygnału + { fDistance = fCurrentDistance; // jeśli sygnał stop, to nie ma - // potrzeby dalej skanować + // potrzeby dalej skanować + sSemNext = &sSpeedTable[iLast]; + WriteLog("Signal stop. Next Semaphor ", false); + if (sSemNext) + WriteLog(sSemNext->GetName()); + else + WriteLog("none"); + } + else + { + if (sSpeedTable[iLast].IsProperSemaphor(OrderCurrentGet()) && + sSemNext == NULL) + sSemNext = + &sSpeedTable[iLast]; // sprawdzamy czy pierwszy na drodze + WriteLog("Signal forward. Next Semaphor ", false); + if (sSemNext) + WriteLog(sSemNext->GetName()); + else + WriteLog("none"); + } } } // event dodajemy najpierw, żeby móc sprawdzić, czy tor został dodany po // odczytaniu prędkości następnego @@ -615,17 +697,13 @@ void TController::TableCheck(double fDistance) int k = (iLast + 1) % iSpeedTableSize; // skanujemy razem z ostatnią pozycją for (int j = (i+1) % iSpeedTableSize; j != k; j = (j + 1) % iSpeedTableSize) { // kasowanie wszystkich rekordów za zmienioną zwrotnicą - if (sSpeedTable[j].iFlags & spTrack) - WriteLog("TableCheck: Delete from table: " + sSpeedTable[j].trTrack->NameGet()); - else if (sSpeedTable[j].iFlags & spEvent) - WriteLog("TableCheck: Delete from table: " + sSpeedTable[j].evEvent->asName); + WriteLog("TableCheck: Delete from table: " + sSpeedTable[j].GetName()); sSpeedTable[j].iFlags = 0; + if (&sSpeedTable[j] == sSemNext) + sSemNext = NULL; // przy kasowaniu tabelki zrzucamy także semafor } WriteLog("TableCheck: Delete entries OK."); - if (sSpeedTable[i].iFlags & spTrack) - WriteLog("TableCheck: New last element: " + sSpeedTable[i].trTrack->NameGet()); - else if (sSpeedTable[i].iFlags & spEvent) - WriteLog("TableCheck: New last element: " + sSpeedTable[i].evEvent->asName); + WriteLog("TableCheck: New last element: " + sSpeedTable[i].GetName()); iLast = i; // pokazujemy gdzie jest ostatni kawałek break; // nie kontynuujemy pętli, trzeba doskanować ciąg dalszy } @@ -681,6 +759,7 @@ void TController::TableCheck(double fDistance) } } sSpeedTable[iLast].Update(&pos, &dir, len); // aktualizacja ostatniego + // WriteLog("TableCheck: Upate last track. Dist=" + AnsiString(sSpeedTable[iLast].fDist)); if (sSpeedTable[iLast].fDist < fDistance) TableTraceRoute(fDistance, pVehicles[1]); // doskanowanie dalszego odcinka } @@ -968,6 +1047,20 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN else if (sSpeedTable[i].iFlags & spEvent) // W4 może się deaktywować { // jeżeli event, może być potrzeba wysłania komendy, aby ruszył //sprawdzanie eventów pasywnych miniętych + if (sSpeedTable[i].fDist < 0.0 && sSemNext == &sSpeedTable[i]) + { + WriteLog("TableUpdate: semaphor " + sSemNext->GetName() + " passed"); + sSemNext = NULL; // jeśli minęliśmy semafor od ograniczenia to go kasujemy ze + // zmiennej sprawdzającej dla skanowania w przód + } + if (sSpeedTable[i].fDist > 0.0 && !sSemNext && + sSpeedTable[i].IsProperSemaphor(OrderCurrentGet())) + { + sSemNext = &sSpeedTable[i]; // jeśli jest mienięty poprzedni semafor a wcześniej + // byl nowy to go dorzucamy do zmiennej, żeby cały + // czas widział najbliższy + WriteLog("TableUpdate: Next semaphor: " + sSemNext->GetName()); + } if (sSpeedTable[i].iFlags & spOutsideStation) { // jeśli W5, to reakcja zależna od trybu jazdy if (OrderCurrentGet() & Obey_train) @@ -1254,7 +1347,11 @@ void TController::TablePurger() { // jeśli jest to minięty (0x20) tor (0x03) do liczenia cięciw (0x80), a nie zwrotnica // (0x08) for (; k > 0; --k, i = (i + 1) % iSpeedTableSize) + { sSpeedTable[i] = sSpeedTable[(i + 1) % iSpeedTableSize]; // skopiowanie + if (&sSpeedTable[(i + 1) % iSpeedTableSize] == sSemNext) + sSemNext = &sSpeedTable[i]; // przeniesienie znacznika o semaforze + } WriteLog("Odtykacz usuwa pozycję"); iLast = (iLast - 1 + iSpeedTableSize) % iSpeedTableSize; // cofnięcie z zawinięciem return; @@ -1268,6 +1365,8 @@ void TController::TablePurger() for (j = -1, i = iFirst; k > 0; --k) { // przepisywanie rekordów iFirst..iLast na 0..k t[++j] = sSpeedTable[i]; + if (&sSpeedTable[i] == sSemNext) + sSemNext = &t[j]; // przeniesienie znacznika o semaforze i = (i + 1) % iSpeedTableSize; // kolejna pozycja mogą być zawinięta } iFirst = 0; // teraz będzie od zera @@ -1275,7 +1374,7 @@ void TController::TablePurger() delete[] sSpeedTable; // to już nie potrzebne sSpeedTable = t; // bo jest nowe iSpeedTableSize += 16; - // WriteLog("Tabelka powiększona do "+AnsiString(iSpeedTableSize)+" pozycji"); + WriteLog("Tabelka powiększona do "+AnsiString(iSpeedTableSize)+" pozycji"); }; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- @@ -1376,6 +1475,7 @@ TController::TController(bool AI, TDynamicObject *NewControll, bool InitPsyche, fLength = 0.0; fMass = 0.0; //[kg] eSignNext = NULL; // sygnał zmieniający prędkość, do pokazania na [F2] + sSemNext = NULL; // pierwszy semafor w przebiegu fShuntVelocity = 40; // domyślna prędkość manewrowa fStopTime = 0.0; // czas postoju przed dalszą jazdą (np. na przystanku) iDrivigFlags = moveStopPoint; // podjedź do W4 możliwie blisko @@ -3344,9 +3444,10 @@ bool TController::UpdateSituation(double dt) fBrakeDist = fBrakeDist + 2 * mvOccupied->Vel; // dla nastawienia G // koniecznie należy wydłużyć drogę na czas reakcji // double scanmax=(mvOccupied->Vel>0.0)?3*fDriverDist+fBrakeDist:10.0*fDriverDist; - double scanmax = (mvOccupied->Vel > 5.0) ? - 400 + fBrakeDist : - 30.0 * fDriverDist; // 1500m dla stojących pociągów; Ra 2015-01: przy + //double scanmax = (mvOccupied->Vel > 5.0) ? + // 400 + fBrakeDist : + // 30.0 * fDriverDist; // 1500m dla stojących pociągów; Ra 2015-01: przy + double scanmax = Max0R(400 + fBrakeDist, 1500); // dłuższej drodze skanowania AI jeździ spokojniej // 2. Sprawdzić, czy tabelka pokrywa założony odcinek (nie musi, jeśli jest STOP). // 3. Sprawdzić, czy trajektoria ruchu przechodzi przez zwrotnice - jeśli tak, to sprawdzić, @@ -4712,12 +4813,12 @@ void TController::OrdersDump() } }; -TOrders TController::OrderCurrentGet() +inline TOrders TController::OrderCurrentGet() { return OrderList[OrderPos]; } -TOrders TController::OrderNextGet() +inline TOrders TController::OrderNextGet() { return OrderList[OrderPos + 1]; } diff --git a/Driver.h b/Driver.h index 98cf1655..e62147a8 100644 --- a/Driver.h +++ b/Driver.h @@ -142,9 +142,11 @@ class TSpeedPos public: void Clear(); bool Update(vector3 *p, vector3 *dir, double &len); - bool Set(TEvent *e, double d); + bool Set(TEvent *e, double d, TOrders order = Wait_for_orders); void Set(TTrack *t, double d, int f); AnsiString TableText(); + AnsiString GetName(); + bool IsProperSemaphor(TOrders order = Wait_for_orders); }; //---------------------------------------------------------------------------- @@ -168,6 +170,7 @@ class TController double fLastVel; // prędkość na poprzednio sprawdzonym torze TTrack *tLast; // ostatni analizowany tor TEvent *eSignSkip; // można pominąć ten SBL po zatrzymaniu + TSpeedPos *sSemNext; // następny semafor na drodze zależny od trybu jazdy private: // parametry aktualnego składu double fLength; // długość składu (do wyciągania z ograniczeń) double fMass; // całkowita masa do liczenia stycznej składowej grawitacji @@ -321,8 +324,8 @@ class TController void JumpToFirstOrder(); void OrderPush(TOrders NewOrder); void OrderNext(TOrders NewOrder); - TOrders OrderCurrentGet(); - TOrders OrderNextGet(); + inline TOrders OrderCurrentGet(); + inline TOrders OrderNextGet(); bool CheckVehicles(TOrders user = Wait_for_orders); private: diff --git a/Logs.cpp b/Logs.cpp index 50a8a3b9..81b09292 100644 --- a/Logs.cpp +++ b/Logs.cpp @@ -33,14 +33,15 @@ void WriteConsoleOnly(const char *str, double value) // WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),endstring,strlen(endstring),&wr,NULL); } -void WriteConsoleOnly(const char *str) +void WriteConsoleOnly(const char *str, bool newline) { // printf("%n ffafaf /n",str); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY); DWORD wr = 0; WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), str, strlen(str), &wr, NULL); - WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), endstring, strlen(endstring), &wr, NULL); + if (newline) + WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), endstring, strlen(endstring), &wr, NULL); } void WriteLog(const char *str, double value) @@ -55,7 +56,7 @@ void WriteLog(const char *str, double value) } } }; -void WriteLog(const char *str) +void WriteLog(const char *str, bool newline) { if (str) { @@ -63,12 +64,14 @@ void WriteLog(const char *str) { if (!output.is_open()) output.open("log.txt", std::ios::trunc); - output << str << "\n"; + output << str; + if (newline) + output << "\n"; output.flush(); } // hunter-271211: pisanie do konsoli tylko, gdy nie jest ukrywana if (Global::iWriteLogEnabled & 2) - WriteConsoleOnly(str); + WriteConsoleOnly(str, newline); } }; void ErrorLog(const char *str) @@ -96,9 +99,9 @@ void ErrorLog(const AnsiString &asMessage) WriteLog(asMessage.c_str()); // do "log.txt" ewentualnie też } -void WriteLog(const AnsiString &str) +void WriteLog(const AnsiString &str, bool newline) { // Ra: wersja z AnsiString jest zamienna z Error() - WriteLog(str.c_str()); + WriteLog(str.c_str(), newline); }; //--------------------------------------------------------------------------- diff --git a/Logs.h b/Logs.h index 69c36c5f..53df811f 100644 --- a/Logs.h +++ b/Logs.h @@ -12,11 +12,11 @@ http://mozilla.org/MPL/2.0/. #include void WriteConsoleOnly(const char *str, double value); -void WriteConsoleOnly(const char *str); +void WriteConsoleOnly(const char *str, bool newline = true); void WriteLog(const char *str, double value); -void WriteLog(const char *str); +void WriteLog(const char *str, bool newline = true); void Error(const AnsiString &asMessage, bool box = true); void ErrorLog(const AnsiString &asMessage); -void WriteLog(const AnsiString &str); +void WriteLog(const AnsiString &str, bool newline = true); //--------------------------------------------------------------------------- #endif