From 2df7d6e0324d8ce04fd0c320da70978eb984c3f5 Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Sat, 23 Dec 2023 17:20:09 +0100 Subject: [PATCH] LockWay and UnLockWay is working with split blocks now. --- server/locomotive.cc | 52 +++++-- server/locomotive.h | 1 - server/railway.cc | 341 +++++++++++-------------------------------- 3 files changed, 126 insertions(+), 268 deletions(-) diff --git a/server/locomotive.cc b/server/locomotive.cc index 0a875b1..1bb47a7 100644 --- a/server/locomotive.cc +++ b/server/locomotive.cc @@ -303,8 +303,6 @@ int Locomotives::SetDestination (string name, string block, int direction) { for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (name.compare(locomotives[i].name) == 0) { - debug (0, "Locomotives::SetDestination (Name:%s Block:%s Direction:%d)", name.c_str(), block.c_str(), direction); - blflags = server->blocks.GetFlags(block); if ((blflags & BLOCK_F_SHORT) && !(locomotives[i].flags & LOCO_F_SHORTTRAIN) && !(blflags & BLOCK_F_SPLIT)) break; if ((blflags & BLOCK_F_ENDSTATION) && !(locomotives[i].flags & LOCO_F_CANREVERSE)) break; @@ -313,6 +311,21 @@ int Locomotives::SetDestination (string name, string block, int direction) { if (direction) snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "-:%s", block.c_str()); else snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "+:%s", block.c_str()); + + // + // check if it is a split block and a long train + if (!(locomotives[i].flags & LOCO_F_SHORTTRAIN) && (blflags & BLOCK_F_SPLIT)) { + if ((locomotives[i].blockdest[0] == '+' && (blflags & BLOCK_F_SPLITPOS)) || + (locomotives[i].blockdest[0] == '-' && !(blflags & BLOCK_F_SPLITPOS)) ) { + strncpy (locomotives[i].blockdest+2 + , server->blocks.GetSecondBlock(locomotives[i].blockdest+2).c_str() + , REFERENCENAME_LEN-2); + } + } + + debug (0, "Locomotives::SetDestination (Name:%s Block:%s Direction:%d) -> Final:%s" + , name.c_str(), block.c_str(), direction, locomotives[i].blockdest); + break; } UnLock(); @@ -738,7 +751,6 @@ void::Locomotives::SendUpdate (Locomotive *loc) { int Locomotives::Loco_SearchAndLock(Locomotive *loco) { string way; - // // try to find and prepare(lock) a new way. // nothing found check if we can reverse direction, this will be done only @@ -851,6 +863,7 @@ int Locomotives::Loco_OnRoute(Locomotive *loco) { int dir_reverse = 0; char *tmpc = NULL; string way; + int blockflags; // FIXME: move this code to the block class -> we will need a better code for multiple sensors // @@ -878,21 +891,30 @@ int Locomotives::Loco_OnRoute(Locomotive *loco) { // assignment <-- next, the assignment has to be checked // against long trains and split blocks // check if we need to clear dest + strncpy (loco->blockprev, loco->blockassign, REFERENCENAME_LEN); tmpc = strstr (loco->blocknext, ",b:"); - if (tmpc) { - strncpy (loco->blockassign, tmpc+3, REFERENCENAME_LEN); - strncpy (loco->blockassignsplit, loco->blocknext, REFERENCENAME_LEN); - } - else { - strncpy (loco->blockassign, loco->blocknext, REFERENCENAME_LEN); - loco->blockassignsplit[0] = 0; + if (tmpc) strncpy (loco->blockassign, tmpc+3, REFERENCENAME_LEN); + else strncpy (loco->blockassign, loco->blocknext, REFERENCENAME_LEN); + + // + // check if it is a split block and a long train + blockflags = server->blocks.GetFlags(loco->blockassign+2); + if (!(loco->flags & LOCO_F_SHORTTRAIN) && (blockflags & BLOCK_F_SPLIT)) { + if ((loco->blockassign[0] == '+' && (blockflags & BLOCK_F_SPLITPOS)) || + (loco->blockassign[0] == '-' && !(blockflags & BLOCK_F_SPLITPOS)) ) { + strncpy (loco->blockassign+2 + , server->blocks.GetSecondBlock(loco->blockassign+2).c_str() + , REFERENCENAME_LEN-2); + } } + strncpy (loco->auto_wayold, loco->auto_way, WAYDATA_LEN); loco->auto_way[0] = 0; loco->blocknext[0] = 0; - debug (0, "Locomotive::Loop Loco:'%s' Prev:'%s' Assign:'%s' AssignSplit:'%s' Next:'%s'", - loco->name, loco->blockprev, loco->blockassign, loco->blockassignsplit, loco->blocknext); + + debug (0, "Locomotive::Loco_OnRoute Loco:'%s' Prev:'%s' Assign:'%s' Next:'%s'", + loco->name, loco->blockprev, loco->blockassign, loco->blocknext); // if (Loco_SearchAndLock(loco) == 1) { @@ -1045,9 +1067,9 @@ int Locomotives::Loop() { // // only in automate do anything alone // - debug (0, "* Locomotives::Loop (%s:%d) Loco:%s auto_onroute:%d assign:'%s' assignsplit:'%s' next:'%s' prev:'%s' dest:'%s' way:'%s' wayold:'%s'" - , __FILE__, __LINE__, loco->name, loco->auto_onroute, loco->blockassign, loco->blockassignsplit - , loco->blocknext, loco->blockprev, loco->blockdest, loco->auto_way, loco->auto_wayold); +// debug (0, "* Locomotives::Loop (%s:%d) Loco:%s auto_onroute:%d assign:'%s' next:'%s' prev:'%s' dest:'%s' way:'%s' wayold:'%s'" +// , __FILE__, __LINE__, loco->name, loco->auto_onroute, loco->blockassign +// , loco->blocknext, loco->blockprev, loco->blockdest, loco->auto_way, loco->auto_wayold); if (loco->blockassign[0] == 0) { debug (0, "%s:%d Locomotive [%s] not assigned to any block. Set Mode to Man", __FILE__, __LINE__, loco->name); diff --git a/server/locomotive.h b/server/locomotive.h index e5077f9..bfd78cc 100644 --- a/server/locomotive.h +++ b/server/locomotive.h @@ -56,7 +56,6 @@ struct s_Locomotive { int speed; // current speed int64_t func; // function enabled ... light... char blockassign[REFERENCENAME_LEN]; // currently assigned block [+BLOCKREFNAME ... -BLOCKREFNAME] - char blockassignsplit[REFERENCENAME_LEN]; // if assigned block is a split block, save full way. char blocknext[REFERENCENAME_LEN]; // next block to go to char blockprev[REFERENCENAME_LEN]; // prev block (mostly assigned block char blockdest[REFERENCENAME_LEN]; // destination block diff --git a/server/railway.cc b/server/railway.cc index 4421c81..51a8684 100644 --- a/server/railway.cc +++ b/server/railway.cc @@ -503,10 +503,8 @@ string Railways::GetDestBlock(int locoflags, string blockend) { blockp = server->blocks.GetSecondBlock(blockn); } - if (blockend[0] == '+') blockend = "+:" + blockn; - else blockend = "-:" + blockp; - - block = blockend; + if (blockend[0] == '+') block = "+:" + blockn; + else block = "-:" + blockp; } else { block = blockend; @@ -642,13 +640,13 @@ int Railways::FindWay(string org_blockstart, string org_blockend, string lockedf } else if (fd_pos.enterfrom >= 0 && fd_end.x == fd_pos.x && fd_pos.y == fd_end.y && fd_pos.enterfrom == fd_end.enterfrom) { // destination found - debug (0, "Railway::FindWay %s:%d found way.", __FILE__, __LINE__); found = 1; *next = fd_pos.way + ",b:" + blockend; fd_pos.enterfrom = -1; fd_pos.x = -1; fd_pos.y = -1; fd_pos.way = ""; + debug (0, "Railway::FindWay %s:%d found way. [%s]", __FILE__, __LINE__, next->c_str()); } else if (fd_pos.enterfrom >= 0 && fd_start.x == fd_pos.x && fd_start.y == fd_pos.y && fd_start.enterfrom == fd_pos.enterfrom) { // start found @@ -890,215 +888,6 @@ int Railways::FindRandomWay(string blockstart, string lockedfor, string *next) { debug (0, "Railway::FindRandomWay - disabled for now - needs to be rewritten"); return 0; -/* - // check blocklen - if (blockstart.length() <= 3) return 0; - - // allocate and clear memory for checked data - fd_data = (struct s_findway_map *) malloc (sizeof(struct s_findway_map) * width * height); - if (fd_data == NULL) { - printf ("%s:%d (%s) FATAL ERROR: could not allocate enough memory\n", __FILE__, __LINE__, __FUNCTION__); - exit (1); - } - memset (fd_data, 0x0, sizeof(struct s_findway_map) * width*height); - - // - // find start and endpoint mark on fd_data, also startpoint to fd_list - fd_end.x = fd_start.x = -1; - fd_end.y = fd_start.y = -1; - fd_end.enterfrom = fd_start.enterfrom = -1; - - if (FindReference(&fd_start.x, &fd_start.y, blockstart.substr(2, string::npos))) { - if (Get(fd_start.x, fd_start.y).dir == 1) { - if (blockstart[0] == '+') fd_start.enterfrom = 0; - else fd_start.enterfrom = 2; - } - else { - if (blockstart[0] == '+') fd_start.enterfrom = 3; - else fd_start.enterfrom = 1; - } - fd_start.way = "b:" + blockstart; - fd_data[GetRIdx(fd_start.x, fd_start.y)].e = (1 << fd_start.enterfrom); - fd_data[GetRIdx(fd_start.x, fd_start.y)].score = 1; - } - else { - debug (0, "Railway::FindRandomWay could not find startblock (%s).", blockstart.c_str()); - free (fd_data); - return 0; - } - - fd_pos = NextPos(fd_start, Get(fd_start.x, fd_start.y).dir); - Lock(); - - // - // loop through the map to find all possible ways to the destination - // this will be done in respect of lockedby blocks and ways. - // - while ((fd_list.size() > 0 || fd_pos.enterfrom >= 0) && found == 0) { - // DebugPrintFindWay(fd_data); - if (fd_pos.enterfrom < 0) { - std::list::iterator iter; - - iter = fd_list.begin(); - if (iter != fd_list.end()) { - fd_pos = *iter; - fd_list.pop_front(); - // printf ("get from stack (%d,%d)\n", fd_pos.x, fd_pos.y); - } - } - - // printf ("%s:%d fd_start (%d,%d) enterfrom:%d\n", __FILE__, __LINE__, fd_start.x, fd_start.y, fd_start.enterfrom); - // printf ("%s:%d fd_end (%d,%d) enterfrom:%d\n", __FILE__, __LINE__, fd_end.x, fd_end.y, fd_end.enterfrom); - // printf ("%s:%d fd_pos (%d,%d) enterfrom:%d\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_pos.enterfrom); - if (fd_pos.enterfrom < 0 && fd_pos.enterfrom > 3) { - fd_pos.enterfrom = -1; - fd_pos.x = -1; - fd_pos.y = -1; - fd_pos.way = ""; - } - else if (fd_pos.enterfrom >= 0 && fd_start.x == fd_pos.x && fd_start.y == fd_pos.y && fd_start.enterfrom == fd_pos.enterfrom) { - // start found - fd_pos.enterfrom = -1; - fd_pos.x = -1; - fd_pos.y = -1; - fd_pos.way = ""; - } - else if (fd_data[GetRIdx(fd_pos.x, fd_pos.y)].e & (1 << fd_pos.enterfrom)) { - // old entry found - fd_pos.enterfrom = -1; - fd_pos.x = -1; - fd_pos.y = -1; - fd_pos.way = ""; - } - else if (fd_pos.enterfrom >= 0) { - rpos = &railways[GetRIdx(fd_pos.x, fd_pos.y)]; - fd_data[GetRIdx(fd_pos.x, fd_pos.y)].e |= (1 << fd_pos.enterfrom); - - if (rpos->type == RAILWAY_NORMAL || rpos->type == RAILWAY_SENSOR) { - fd_pos = NextPos(fd_pos, rpos->dir); - rnext = &railways[GetRIdx(fd_pos.x, fd_pos.y)]; - if (rnext->lockedby[0] != 0) { - fd_pos.enterfrom = -1; - fd_pos.x = -1; - fd_pos.y = -1; - fd_pos.way = ""; - } - } - - else if (rpos->type == RAILWAY_TURNOUT) { - // random turn or no turn - if ((rand() & 1) == 1) { - fd_tmp = NextPos(fd_pos, rpos->altdir); - fd_tmp.way += (string)",t:" + (string)rpos->name + (string)":1"; - fd_list.push_back(fd_tmp); - fd_pos = NextPos(fd_pos, rpos->dir); - fd_pos.way += (string)",t:" + (string)rpos->name + (string)":0"; - } - else { - fd_tmp = NextPos(fd_pos, rpos->dir); - fd_tmp.way += (string)",t:" + (string)rpos->name + (string)":0"; - fd_list.push_back(fd_tmp); - fd_pos = NextPos(fd_pos, rpos->altdir); - fd_pos.way += (string)",t:" + (string)rpos->name + (string)":1"; - } - } - - else if (rpos->type == RAILWAY_CONNECTOR) { - int found = 0; - - x = -1; - y = -1; - while (found == 0 && _FindReference(&x, &y, rpos->name) == 1) { - if (fd_pos.x != x || fd_pos.y != y) { - fd_pos.oldx = fd_pos.x; - fd_pos.oldy = fd_pos.y; - fd_pos.oldenterfrom = fd_pos.enterfrom; - fd_pos.x = x; - fd_pos.y = y; - rpos = &railways[GetRIdx(fd_pos.x, fd_pos.y)]; - fd_pos = NextPos(fd_pos, rpos->dir); - found = 1; - break; - } - } - - if (found == 0) { - fd_pos.enterfrom = -1; - fd_pos.x = -1; - fd_pos.y = -1; - fd_pos.way = ""; - } - } - // - // if block is off ignore it completly - else if (rpos->type == RAILWAY_BLOCK) { - int blflags = server->blocks.GetFlags(rpos->name); - - if ((server->blocks.IsOff(rpos->name) || - ((blflags & BLOCK_F_ENDSTATION) && !(locoflags & LOCO_F_CANREVERSE)) || - ((blflags & BLOCK_F_SHORT) && !(locoflags & LOCO_F_SHORTTRAIN)) || - ((blflags & BLOCK_F_ONLYCARGO) && !(locoflags & LOCO_F_CARGO)) || - ((blflags & BLOCK_F_ONLYPASSENGER) && (locoflags & LOCO_F_CARGO)))) { - fd_pos.enterfrom = -1; - fd_pos.x = -1; - fd_pos.y = -1; - fd_pos.way = ""; - } - else { - // lockedby = server->blocks.GetLockedby(rpos->name); - lockedby = server->blocks.GetLockedby(rpos->name); - if (lockedby.length() == 0 || lockedby.compare(lockedfor) == 0) { - if (fd_pos.enterfrom == 0 || fd_pos.enterfrom == 3) - fd_pos.way += (string)",b:+:" + (string)rpos->name; - else fd_pos.way += (string)",b:-:" + (string)rpos->name; - - *next = fd_pos.way + ",b:" + (string)rpos->name; - fd_pos.enterfrom = -1; - fd_pos.x = -1; - fd_pos.y = -1; - fd_pos.way = ""; - found = 1; - } - else { - fd_pos.enterfrom = -1; - fd_pos.x = -1; - fd_pos.y = -1; - fd_pos.way = ""; - } - } - } - - else { // finished nothing more to check - fd_pos.enterfrom = -1; - fd_pos.x = -1; - fd_pos.y = -1; - fd_pos.way = ""; - } - } - } - - if (found == 0) *next = ""; - else { - // - // next = "b:+blockname,t:name:0,t:name:1,b:-blockname" - debug (0, "* Random Temp Next: %s", next->c_str()); - size_t npos; - if ((npos = next->find(",b:")) != string::npos) { - *next = next->substr(0, next->find(",", npos+1)); - debug (0, "* Random next: '%s' found", next->c_str()); - } - else { - // nothing found? - debug (0, "* Random Nothing Found next: '%s' but no next block?", next->c_str()); - *next = ""; - } - } - UnLock(); - - free (fd_data); - - return found; -*/ } @@ -1114,11 +903,11 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) { struct s_findway_data start; struct s_findway_data end; struct s_findway_data pos; - string startblock, startblock2, endblock, endblock2; + string startblock, startblock2, startblockfinal, endblock, endblock2,endblockfinal; Railway *r; int finished = 0; JSONParse jp; - int locoflags = 0; + int locoflags = server->locomotives.GetFlags(lockedby); int blockendflags = 0; int blockstartflags = 0; @@ -1139,7 +928,6 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) { // // take care of split blocks and long trains. // if the second block is not needed endblock2 will remain empty - locoflags = server->locomotives.GetFlags(lockedby); blockendflags = server->blocks.GetFlags(endblock.substr(2, string::npos)); if (!(locoflags & LOCO_F_SHORTTRAIN) && (blockendflags & BLOCK_F_SPLIT)) endblock2 = server->blocks.GetSecondBlock(endblock.substr(2, string::npos)); @@ -1154,7 +942,23 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) { // // find start position // - if (FindReference(&start.x, &start.y, startblock.substr(2,string::npos))) { + if (startblock2.length() > 0) { + if ((startblock[0] == '+' && !(blockstartflags & BLOCK_F_SPLITPOS)) || + (startblock[0] == '-' && (blockstartflags & BLOCK_F_SPLITPOS)) ) { + startblockfinal = startblock2; + } + else { + startblockfinal = startblock.substr(2, string::npos); + } + } + else { + startblockfinal = startblock.substr(2, string::npos); + } + + + // + // retrieve final start position, in case of split blocks + if (FindReference(&start.x, &start.y, startblockfinal)) { if (Get(start.x, start.y).dir == 1) { if (startblock[0] == '+') start.enterfrom = 0; else start.enterfrom = 2; @@ -1170,24 +974,51 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) { } // - // find end position. Long trains and Split blocks is being taken care of in - // the Findwaypart. - // when unlocking we are not unlocking the way between these blocks. - if (FindReference(&end.x, &end.y, endblock.substr(2,string::npos))) { - if (Get(end.x, end.y).dir == 1) { - if (endblock[0] == '+') end.enterfrom = 0; - else end.enterfrom = 2; + // find end position + // + + // + // retrieve final end position, in case of split blocks + if (endblock2.length() > 0) { + if (lockonoff) { + if ((endblock[0] == '+' && (blockendflags & BLOCK_F_SPLITPOS)) || + (endblock[0] == '-' && !(blockendflags & BLOCK_F_SPLITPOS)) ) { + endblockfinal = endblock2; + } + else { + endblockfinal = endblock.substr(2, string::npos); + } } else { - if (endblock[0] == '+') end.enterfrom = 3; - else end.enterfrom = 1; + if ((endblock[0] == '-' && (blockendflags & BLOCK_F_SPLITPOS)) || + (endblock[0] == '+' && !(blockendflags & BLOCK_F_SPLITPOS)) ) { + endblockfinal = endblock2; + } + else { + endblockfinal = endblock.substr(2, string::npos); + } } } else { - debug (0, "Railway::FindWay could not find end (%s).", endblock.c_str()); + endblockfinal = endblock.substr(2, string::npos); + } + + // get the final end position + if (!FindReference(&end.x, &end.y, endblockfinal)) { + debug (0, "Railway::FindWay could not find endblock (%s).", endblockfinal.c_str()); return 0; } + + if (Get(end.x, end.y).dir == 1) { + if (endblock[0] == '+') end.enterfrom = 0; + else end.enterfrom = 2; + } + else { + if (endblock[0] == '+') end.enterfrom = 3; + else end.enterfrom = 1; + } + printf ("%s:%d LockWay Way:'%s' start [%d,%d -> %d] to [%d,%d -> %d] LockOnOff:%d\n", __FILE__, __LINE__, way.c_str(), start.x, start.y, start.enterfrom, end.x, end.y, end.enterfrom, lockonoff); @@ -1215,24 +1046,27 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) { } // lock start and endpoint... unlock only start - if ((pos.x == end.x && pos.y == end.y) || (r->type == RAILWAY_BLOCK && - ((endblock.compare(r->name) == 0) || - (endblock2.length() > 0 && endblock2.compare(r->name) == 0)))) { - if (lockonoff == 1) { + if (r->type == RAILWAY_BLOCK) { + if ((strcmp(endblock.c_str()+2,r->name) == 0) || (endblock2.length() > 0 && (endblock2.compare(r->name) == 0))) { + UnLock(); + if (lockonoff) { + strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN); + server->blocks.SetLockedby(r->name, lockedby, lockonoff); + } + Lock(); + } + else if ((strcmp(startblock.c_str()+2, r->name) == 0) || (startblock2.length() > 0 && (startblock2.compare(r->name) == 0))) { UnLock(); - server->blocks.SetLockedby(r->name, lockedby, 1); - strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN); + server->blocks.SetLockedby(r->name, lockedby, lockonoff); + if (lockonoff) strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN); + else r->lockedby[0] = 0; Lock(); - jp.Clear(); - jp.AddObject("railway",_GetJSONRailway(pos.x, pos.y)); - if(network) network->ChangeListPushToAll(jp.ToString()); } - } - else if (pos.x == start.x && pos.y == start.y && r->type == RAILWAY_BLOCK) { - UnLock(); - if (lockonoff) server->blocks.SetLockedby(r->name, lockedby, lockonoff); - if (lockonoff) strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN); - Lock(); + else { + debug (0, "*** ERROR *** RailWay BLOCK not start and end (r->name:%s) startblock:%s [%s] endblock:%s [%s]" + , r->name, startblock.c_str(), startblock2.c_str(), endblock.c_str(), endblock2.c_str()); + server->PowerOnOff(0); + } jp.Clear(); jp.AddObject("railway",_GetJSONRailway(pos.x, pos.y)); if(network) network->ChangeListPushToAll(jp.ToString()); @@ -1287,18 +1121,21 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) { return 0; } + // + // in case this turnout is not in the way list. It is might in between the splitblocks if (way.substr(curwaypos+2, pos1-curwaypos-2).compare(r->name) != 0) { - debug (0, "LockWay turnout '%s' not on Way '%s' we should on '%s'", r->name, way.c_str(), way.substr(curwaypos+2, pos1-curwaypos-2).c_str()); - UnLock(); - return 0; + int d = server->turnouts.Get(r->name); + debug (0, "LockWay tournout %s in between start or endblock? Active: %d", r->name, d); + pos = NextPos(pos, d ? r->altdir : r->dir); } + else { + if (way[pos1+1] == '0') pos = NextPos(pos, r->dir); + else pos = NextPos(pos, r->altdir); - if (way[pos1+1] == '0') pos = NextPos(pos, r->dir); - else pos = NextPos(pos, r->altdir); - - // next turnout? - curwaypos = way.find(",t:", curwaypos); - if (curwaypos != string::npos) curwaypos++; + // next turnout? + curwaypos = way.find(",t:", curwaypos); + if (curwaypos != string::npos) curwaypos++; + } } else if (r->type == RAILWAY_CONNECTOR) {