automatic random mode is working

origin
steffen 5 years ago
parent 9c633da3ec
commit f1580d3713

@ -1,3 +1,3 @@
2020-03-09
- reverse funktioniert nicht immer

@ -1,3 +1,6 @@
2021-02-10:
- automatic mode with random destinations is working now
2021-01-31:
- automtic mode is improving, manual setting of destination
autoatic routing and moving the train to the destination.

@ -112,7 +112,7 @@ Block Blocks::GetBlockFromJSON(JSONParse *j) {
s = ""; j->GetValue("sensor_neg_1", &s);
strncpy (bl.s_neg_1, s.c_str(), REFERENCENAME_LEN);
printf ("%s:%d Sensor (%s ---> %s ---> %s\n", __FILE__, __LINE__, bl.s_pos_1, bl.s_center, bl.s_neg_1);
printf ("%s:%d block: %s flags: %d\n", __FILE__, __LINE__, bl.name, bl.flags);
return bl;
};
@ -211,6 +211,7 @@ int Blocks::SetLockedby (string blname, string lockedby, int lock_onoff) {
Block *bl = NULL;
JSONParse jp;
int res = -1;
int x, y;
debug (0, "Blocks:SetLockedby block:'%s' locked for '%s' locked:%d", blname.c_str(), lockedby.c_str(), lock_onoff);
@ -221,6 +222,12 @@ int Blocks::SetLockedby (string blname, string lockedby, int lock_onoff) {
else bl->lockedby[0] = 0;
jp.AddObject("block",_GetJSON(bl));
if(network) network->ChangeListPushToAll(jp.ToString());
x = -1; y = -1;
while (server->railways.FindReference(&x, &y, blname)) {
server->railways.SetLockedby(x, y, lockedby, lock_onoff);
}
res = 1;
}
else {

@ -288,11 +288,20 @@ int Locomotives::SetFunction(string name, int func, int value) {
int Locomotives::SetDestination (string name, string block, int direction) {
int i;
string way;
int blflags;
Lock();
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)\n", name.c_str(), block.c_str(), direction);
blflags = server->blocks.GetFlags(block);
if ((blflags & BLOCK_F_SHORT) && !(locomotives[i].flags & LOCO_F_SHORTTRAIN)) break;
if ((blflags & BLOCK_F_ENDSTATION) && !(locomotives[i].flags & LOCO_F_CANREVERSE)) break;
printf ("%s:%d blflags:%d locoflags:%d\n", __FILE__, __LINE__, blflags, locomotives[i].flags);
if (direction) snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "-:%s", block.c_str());
else snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "+:%s", block.c_str());
break;
@ -313,7 +322,7 @@ int Locomotives::SetAssign (string name, string block, int direction) {
debug (0, "Locomotives::SetAssign (Name:%s Block:%s Direction:%d)\n", name.c_str(), block.c_str(), direction);
if (locomotives[i].blockassign[0] != 0) // still locked unlock
server->blocks.SetLockedby(locomotives[i].blockassign, name, 0);
server->blocks.SetLockedby(locomotives[i].blockassign+2, name, 0);
if (direction) snprintf (locomotives[i].blockassign, REFERENCENAME_LEN, "-:%s", block.c_str());
else snprintf (locomotives[i].blockassign, REFERENCENAME_LEN, "+:%s", block.c_str());
@ -339,6 +348,21 @@ int Locomotives::SetAssign (string name, string block, int direction) {
}
int Locomotives::GetFlags(string name) {
int flags = -1;
int i;
Lock();
for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0)
if (name.compare(locomotives[i].name) == 0) {
flags = locomotives[i].flags;
}
UnLock();
return flags;
}
int Locomotives::Reset(string name) {
Railway rw;
int i;
@ -410,7 +434,7 @@ int Locomotives::SetAuto(string name) {
if (name.compare(locomotives[i].name) == 0) {
debug (0, "Locomotives::SetAuto (Name:%s)\n", name.c_str());
locomotives[i].flags |= LOCO_F_AUTO;
locomotives[i].auto_onroute = 0;
locomotives[i].flags &= ~LOCO_F_RANDOM;
break;
}
UnLock();
@ -573,6 +597,7 @@ int Locomotives::Loop() {
if (loco->flags & LOCO_F_REVERSE) reverse = -1;
else reverse = 1;
if (loco->flags & LOCO_F_AUTO) {
//
// only in automate do anything alone
@ -589,7 +614,37 @@ int Locomotives::Loop() {
// find way, if nothing found check if we can reverse direction
//
if (loco->auto_timenext.tv_sec == 0 || timer_get(&loco->auto_timenext) > LOCO_TO_TRYAGAIN) {
if (server->railways.FindWay(loco->blockassign, loco->blockdest, loco->name, &way)) {
debug (0, "* Loco Loop Search '%s' Reverse:%d", loco->name, reverse);;
if (loco->blockdest[0] == 0) {
if (loco->flags & LOCO_F_RANDOM)
if (server->railways.FindRandomWay(loco->blockassign, loco->name, &way)) {
size_t pos;
if ((pos = way.find(",b:", 1)) != string::npos) {
strncpy (loco->blocknext, way.substr(pos+3,string::npos).c_str(), REFERENCENAME_LEN);
strncpy (loco->auto_way, way.c_str(), WAYDATA_LEN);
if (server->railways.LockWay(way, loco->name) == 1) {
loco->auto_data = -1;
loco->auto_onroute = LOCO_OR_PREPARE;
}
else {
server->railways.UnLockWay(way, loco->name);
timer_start(&loco->auto_timenext);
}
}
}
else {
if (loco->blockassign[0] != 0 && (loco->flags & LOCO_F_CANREVERSE)) {
debug (0, "* Reverse Loco %s", loco->name);
if (loco->blockassign[0] == '-') loco->blockassign[0] = '+';
else if (loco->blockassign[0] == '+') loco->blockassign[0] = '-';
if (loco->flags & LOCO_F_REVERSE) loco->flags &= ~LOCO_F_REVERSE;
else loco->flags |= LOCO_F_REVERSE;
}
timer_start(&loco->auto_timenext);
}
}
else if (server->railways.FindWay(loco->blockassign, loco->blockdest, loco->name, &way)) {
size_t pos;
if ((pos = way.find(",b:", 1)) != string::npos) {
@ -599,11 +654,16 @@ int Locomotives::Loop() {
loco->auto_data = -1;
loco->auto_onroute = LOCO_OR_PREPARE;
}
else timer_start(&loco->auto_timenext);
else {
server->railways.UnLockWay(way, loco->name);
timer_start(&loco->auto_timenext);
}
}
}
else {
if (loco->blockassign[0] != 0 && (loco->flags & LOCO_F_CANREVERSE)) {
debug (0, "* Reverse Loco %s", loco->name);
if (loco->blockassign[0] == '-') loco->blockassign[0] = '+';
else if (loco->blockassign[0] == '+') loco->blockassign[0] = '-';
@ -640,7 +700,7 @@ int Locomotives::Loop() {
sensor = server->blocks.GetSensorPlus(block);
if (server->sensors.GetActive(sensor) == 1) { // entering block?
debug (0, "* Locomotive '%s' Enter Block '%s'", loco->name, loco->blocknext);
debug (0, "* Locomotive '%s' EnterBlock '%s'", loco->name, loco->blocknext);
// unlock old assigned block
if (loco->blockassign[0] != 0) {
server->blocks.SetLockedby((string)(loco->blockassign+2), loco->name, 0);
@ -662,7 +722,25 @@ int Locomotives::Loop() {
else {
// try to find new way
printf ("%s:%d LOCO_OR_ONTHEWAY try to find new way\n", __FILE__, __LINE__);
if (server->railways.FindWay(loco->blockassign, loco->blockdest, loco->name, &way)) {
if (loco->blockdest[0] == 0) {
if (loco->flags & LOCO_F_RANDOM)
if (server->railways.FindRandomWay(loco->blockassign, loco->name, &way)) {
size_t pos;
if ((pos = way.find(",b:", 1)) != string::npos) {
strncpy (loco->blocknext, way.substr(pos+3,string::npos).c_str(), REFERENCENAME_LEN);
strncpy (loco->auto_way, way.c_str(), WAYDATA_LEN);
if (server->railways.LockWay(way, loco->name) == 1) {
loco->auto_data = -1;
loco->auto_onroute = LOCO_OR_ENTERBLOCKNEXT;
}
else {
server->railways.UnLockWay(way, loco->name);
timer_start(&loco->auto_timenext);
}
}
}
}
else if (server->railways.FindWay(loco->blockassign, loco->blockdest, loco->name, &way)) {
size_t pos;
if ((pos = way.find(",b:", 1)) != string::npos) {
@ -688,7 +766,6 @@ int Locomotives::Loop() {
}
}
jp.Clear();
jp.AddObject("locomotive",_GetJSON(lnum));
if(network) network->ChangeListPushToAll(jp.ToString());
@ -710,10 +787,11 @@ int Locomotives::Loop() {
sensor = server->blocks.GetSensorMinus(block);
if (server->sensors.GetActive(sensor) == 1) {
debug (0, "Locomotives::Loop '%s' UnLockWay\n", loco->name);
debug (0, "Locomotives::Loop EnterBlockStop '%s' UnLockWay\n", loco->name);
SetSpeed(loco->name, 0);
loco->auto_onroute = LOCO_OR_STOPWAIT;
server->railways.UnLockWay(loco->auto_wayold, loco->name);
server->blocks.SetLockedby(loco->blockprev+2, loco->name, 0);
loco->auto_wayold[0] = 0;
jp.Clear();
jp.AddObject("locomotive",_GetJSON(lnum));
@ -740,7 +818,10 @@ int Locomotives::Loop() {
sensor = server->blocks.GetSensorMinus(block);
if (server->sensors.GetActive(sensor) == 1) {
debug (0, "Locomotives::Loop EnterBlockNext '%s' UnLockWay\n", loco->name);
server->railways.UnLockWay(loco->auto_wayold, loco->name);
server->blocks.SetLockedby(loco->blockprev+2, loco->name, 0);
loco->auto_wayold[0] = 0;
if (finish == 0) { // stop train if not finished

@ -105,6 +105,7 @@ class Locomotives {
int SetFunctionFromBus (string ifname, int addr, int func);
int SetDestination (string name, string block, int direction);
int SetAssign (string name, string block, int direction);
int GetFlags(string name);
int AutoCheckWaySingleStep(string way, string locname, int *data);
int Loop();

@ -502,6 +502,7 @@ int Railways::FindWay(string blockstart, string blockend, string lockedfor, stri
string lockedby;
int i, x ,y;
int found = 0;
int locoflags = server->locomotives.GetFlags(lockedfor);
// check blocklen
if (blockstart.length() <= 3 || blockend.length() <= 3) return 0;
@ -678,7 +679,11 @@ int Railways::FindWay(string blockstart, string blockend, string lockedfor, stri
// if block is off ignore it completly
else if (rpos->type == RAILWAY_BLOCK) {
printf ("%s:%d block found\n", __FILE__, __LINE__);
if (server->blocks.IsOff(rpos->name)) {
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)))) {
printf ("%s:%d block is off\n", __FILE__, __LINE__);
fd_pos.enterfrom = -1;
fd_pos.x = -1;
@ -743,6 +748,242 @@ int Railways::FindWay(string blockstart, string blockend, string lockedfor, stri
};
int Railways::FindRandomWay(string blockstart, string lockedfor, string *next) {
// direction 0 ... RIGHT and DOWN
// direction 1 ... LEFT and UP
struct s_findway_data fd_pos;
struct s_findway_data fd_tmp;
struct s_findway_data fd_start;
struct s_findway_data fd_end;
Railway *rpos, *rnext;
std::list<struct s_findway_data> fd_list;
struct s_findway_map *fd_data = NULL;
string lockedby;
int i, x ,y;
int found = 0;
int locoflags = server->locomotives.GetFlags(lockedfor);
debug (0, "Railway::FindRandomWay");
// 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;
fd_end.parma = fd_start.parma = -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;
fd_start.parma = 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<struct s_findway_data>::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);
fd_pos.parma++;
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_tmp.parma += 10; // 10 bad point for using the turnout
fd_list.push_back(fd_tmp);
fd_pos = NextPos(fd_pos, rpos->dir);
fd_pos.way += (string)",t:" + (string)rpos->name + (string)":0";
fd_pos.parma++;
}
else {
fd_tmp = NextPos(fd_pos, rpos->dir);
fd_tmp.way += (string)",t:" + (string)rpos->name + (string)":0";
fd_tmp.parma += 10; // 10 bad point for using the turnout
fd_list.push_back(fd_tmp);
fd_pos = NextPos(fd_pos, rpos->altdir);
fd_pos.way += (string)",t:" + (string)rpos->name + (string)":1";
fd_pos.parma++;
}
}
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);
fd_pos.parma++;
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)))) {
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());
int i;
i = 0;
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;
}
int Railways::LockWay (string way, string lockedby, int lockonoff) {
int res = 0;
size_t pos1, pos2;
@ -832,17 +1073,20 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) {
// do lock start and endpoint... unlock only start
if (pos.x == end.x && pos.y == end.y && r->type == RAILWAY_BLOCK) {
if (lockonoff == 1) {
UnLock();
server->blocks.SetLockedby(r->name, lockedby, 1);
strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
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) {
server->blocks.SetLockedby(r->name, lockedby, lockonoff);
UnLock();
if (lockonoff) 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());

@ -127,6 +127,7 @@ class Railways {
int FindReference(int *x, int *y, string name);
int FindWay(string blockstart, string blockend, string lockedfor, string *next);
int FindRandomWay(string blockstart, string lockedfor, string *next);
int LockWay (string way, string lockedby, int lockonoff);
int LockWay (string way, string lockedby) { return LockWay(way, lockedby, 1); };
int UnLockWay (string way, string lockedby) { return LockWay(way, lockedby, 0); };

@ -394,9 +394,13 @@ function blockdetail_getData() {
if (name) res.name = name.value;
if (flagoff.checked) res.flags |= BLOCK_F_OFF;
else res.flags &= ~BLOCK_F_OFF;
if (flagshort.checked) res.flags |= BLOCK_F_SHORT;
else res.flags &= ~BLOCK_F_SHORT;
if (flaglong.checked) res.flags |= BLOCK_F_LONG;
else res.flags &= ~BLOCK_F_LONG;
if (flagend.checked) res.flags |= BLOCK_F_ENDSTATION;
else res.flags &= ~BLOCK_F_ENDSTATION;
if (flagspeedlimit.checked) res.flags |= BLOCK_F_SPEEDLIMIT;
if (sensorLU) res.sensor_pos_1 = sensorLU.value;
if (sensorC) res.sensor_center = sensorC.value;

Loading…
Cancel
Save