You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Modelbahn/server/railway.cc

963 lines
24 KiB

#include "modelbahn.h"
#include "server.h"
#include "debug.h"
Railways::Railways() {
debug (0, "* Railways Constructor");
height = 0;
width = 0;
railways = NULL;
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
changed = 0;
};
Railways::~Railways() {
if (railways) free (railways);
height = 0;
width = 0;
};
//
// thread protection: lock
int Railways::Lock() {
if (pthread_mutex_lock(&mtx) == 0) return 1;
else return 0;
};
//
// thread protection: unlock
int Railways::UnLock() {
if (pthread_mutex_unlock(&mtx) == 0) return 1;
else return 0;
};
//
// data must be mutex looked before use
struct s_findway_data Railways::NextPos(struct s_findway_data pos, int dirtype) {
struct s_findway_data np = { x: -1, y: -1, enterfrom: -1, oldx: pos.x, oldy:pos.y,
oldenterfrom: pos.enterfrom, parma: pos.parma,
way: pos.way }; // newpos
if (dirtype == 1) {
if (pos.enterfrom == EF_NORTH) {
np.x = pos.x;
np.y = pos.y + 1 ;
np.enterfrom = EF_NORTH;
} else if (pos.enterfrom == EF_SOUTH) {
np.x = pos.x;
np.y = pos.y - 1;
np.enterfrom = EF_SOUTH;
}
}
else if (dirtype == 2) {
if (pos.enterfrom == EF_WEST) {
np.x = pos.x + 1;
np.y = pos.y;
np.enterfrom = EF_WEST;
} else if (pos.enterfrom == EF_EAST) {
np.x = pos.x - 1;
np.y = pos.y;
np.enterfrom = EF_EAST;
}
}
else if (dirtype == 3) {
if (pos.enterfrom == EF_WEST) {
np.x = pos.x;
np.y = pos.y - 1;
np.enterfrom = EF_SOUTH;
} else if (pos.enterfrom == EF_NORTH){
np.x = pos.x - 1;
np.y = pos.y;
np.enterfrom = EF_EAST;
}
}
else if (dirtype == 4) {
if (pos.enterfrom == EF_NORTH) {
np.x = pos.x + 1;
np.y = pos.y;
np.enterfrom = EF_WEST;
} else if (pos.enterfrom == EF_EAST){
np.x = pos.x;
np.y = pos.y - 1;
np.enterfrom = EF_SOUTH;
}
}
else if (dirtype == 5) {
if (pos.enterfrom == EF_SOUTH) {
np.x = pos.x + 1;
np.y = pos.y;
np.enterfrom = EF_WEST;
} else if (pos.enterfrom == EF_EAST){
np.x = pos.x;
np.y = pos.y + 1;
np.enterfrom = EF_NORTH;
}
}
else if (dirtype == 6) {
if (pos.enterfrom == EF_WEST) {
np.x = pos.x;
np.y = pos.y + 1;
np.enterfrom = EF_NORTH;
} else if (pos.enterfrom == EF_SOUTH){
np.x = pos.x - 1;
np.y = pos.y;
np.enterfrom = EF_EAST;
}
}
return np;
};
//
// return index inside the array (clip to boundery)
int Railways::GetRIdx(int x, int y) {
int _x, _y;
if (x < 0) _x = 0;
else if (x >= width) _x = width-1;
else _x = x;
if (y < 0) _y = 0;
else if (y >= height) _y = height-1;
else _y = y;
return (_x + _y * width);
};
//
// return JSON strign with the Railway data
// not thread safe !!!!
JSONParse Railways::_GetJSONRailway(int x, int y) {
JSONParse json;
JSONElement je;
int idx = GetRIdx(x,y);
string text = "";
json.Clear();
json.AddObject("x", x);
json.AddObject("y", y);
json.AddObject("dir", railways[idx].dir);
json.AddObject("altdir", railways[idx].altdir);
json.AddObject("type", railways[idx].type);
json.AddObject("maxspeed", railways[idx].maxspeed);
json.AddObject("flags", railways[idx].flags);
text = railways[idx].lockedby;
json.AddObject("lockedby", text);
text = railways[idx].name;
json.AddObject("name", text);
return json;
};
//
// return JSON strign with the Railway data
// thread safe.
JSONParse Railways::GetJSONRailway(int x, int y) {
JSONParse json;
Lock();
json = _GetJSONRailway(x, y);
UnLock();
return json;
};
Railway Railways::GetRailwayFromJSON(JSONParse *j) {
string text;
Railway r = {
type: RAILWAY_NOTHING,
x: 0,
y: 0,
dir: 0,
altdir: 0,
maxspeed: -1,
flags: 0,
name: { 0 }
};
r.name[0] = 0;
r.lockedby[0] = 0;
j->GetValueInt("x", &r.x);
j->GetValueInt("y", &r.y);
j->GetValueInt("dir", &r.dir);
j->GetValueInt("altdir", &r.altdir);
j->GetValueInt("type", &r.type);
j->GetValueInt("maxspeed", &r.maxspeed);
j->GetValueInt("flags", &r.flags);
j->GetValue("name", &text);
strncpy (r.name, text.c_str(), REFERENCENAME_LEN);
j->GetValue("lockedby", &text);
strncpy (r.lockedby, text.c_str(), REFERENCENAME_LEN);
return r;
};
//
// return some data about the railway/tracks
//
JSONParse Railways::GetJSONTrack() {
JSONParse json;
JSONParse jsondata;
JSONElement je;
json.Clear();
json.AddObject("height", height);
json.AddObject("width", width);
return json;
};
//
// change railway
// return 1 on change
int Railways::Change(Railway *rw) {
int x, y;
int result = 1;
JSONParse json;
if (rw == NULL) return 0;
Lock();
if (rw->x < 0 || rw->x >= width) result = 0;
else if (rw->y < 0 || rw->y >= height) result = 0;
else if (rw->dir < 0 || rw->dir > 6) result = 0;
else {
changed = true;
result = 1;
if (rw->dir == 0) rw->type == RAILWAY_NOTHING;
//
// need to delete?
if (rw->type == RAILWAY_NOTHING) {
Railway *r = &railways[GetRIdx(rw->x, rw->y)];
r->type = RAILWAY_NOTHING;
r->dir = 0;
r->altdir = 0;
r->flags = 0;
r->maxspeed = 0;
r->x = rw->x;
r->y = rw->y;
r->name[0] = 0;
r->lockedby[0] = 0;
}
//
// add normal railway
else if (rw->type == RAILWAY_NORMAL) {
railways[GetRIdx(rw->x, rw->y)] = *rw;
}
//
// add normal railway
else if (rw->type < RAILWAY_MAX) {
railways[GetRIdx(rw->x, rw->y)] = *rw;
}
else {
debug (DEBUG_INFO, "%s:%d add unknown %d,%d dir(%d) type:%d", __FILE__, __LINE__, rw->x, rw->y, rw->dir, rw->type);
}
}
UnLock();
return result;
};
//
// redefine the size of the track, keep data
void Railways::SetSize (int neww, int newh) {
Railway *rarray = railways;
int ow = width;
int oh = height;
int x, y;
debug (0, "* Railways::SetSize (%d, %d)", neww, newh);
Lock();
//
// old values saved during call up of the function, create new array for the railways data
railways = NULL;
_New (neww, newh);
//
// copy old data
for (x = 0; x < ow && x < width; x++)
for (y = 0; y < oh && x < height; y++)
railways[x + y * width] = rarray[x + y * oh];
free (rarray);
UnLock();
};
void Railways::_New (int neww, int newh) {
int x, y;
debug (0, "* Railways New");
//
// clip to minimum and maximum sizes
if (neww < RAILWAYS_MIN_WIDTH) width = RAILWAYS_MIN_WIDTH;
else if (neww > RAILWAYS_MAX_WIDTH) width = RAILWAYS_MAX_WIDTH;
else width = neww;
if (newh < RAILWAYS_MIN_HEIGHT) width = RAILWAYS_MIN_HEIGHT;
else if (newh > RAILWAYS_MAX_HEIGHT) width = RAILWAYS_MAX_HEIGHT;
else height = newh;
//
// if memory is already allocated free it first
if (railways != NULL) free (railways);
//
// allocate memory and reset memory
railways = (Railway*) malloc (sizeof (Railway) * width * height);
for (x = 0; x < width; x++) for (y = 0; y < height; y++) {
Railway *r = &railways[GetRIdx(x, y)];
r->type = RAILWAY_NOTHING;
r->dir = 0;
r->altdir = 0;
r->flags = 0;
r->maxspeed = 0;
r->x = x;
r->y = y;
r->name[0] = 0;
r->lockedby[0] = 0;
}
};
void Railways::New (int neww, int newh) {
Lock();
_New (neww, newh);
UnLock();
};
//
// append all data to the givin jasonobject
void Railways::GetJSONAll(JSONParse *json) {
int x, y;
if (json == NULL) return;
Lock();
json->AddObject("track", GetJSONTrack());
for (y = 0; y < height; y++)
for (x = 0; x < width; x++)
if (railways[GetRIdx(x, y)].type != RAILWAY_NOTHING) {
json->AddObject("railway", _GetJSONRailway(x, y));
}
UnLock();
}
//
// get railway element
// thread safe
Railway Railways::Get(int x, int y) {
Railway r;
Lock();
r = railways[GetRIdx(x, y)];
UnLock();
return r;
};
void Railways::ClearLockedby(string name) {
int x, y;
JSONParse jp;
Lock();
for (x = 0; x < width; x++)
for (y = 0; y < height; y++) {
if (name.compare(railways[GetRIdx(x,y)].lockedby) == 0) {
railways[GetRIdx(x,y)].lockedby [0] = 0;
changed = 1;
jp.AddObject("railway",_GetJSONRailway(x,y));
if(network) network->ChangeListPushToAll(jp.ToString());
}
}
UnLock();
}
int Railways::_FindReference(int *x, int *y, string name) {
int found = 0;
if (x == NULL || y == NULL) return 0;
if (*x < 0 || *y < 0) {
*x = 0;
*y = 0;
}
printf ("%s:%d find reference (%d,%d,%s)\n", __FILE__, __LINE__, *x, *y, name.c_str());
for (; found == 0 && *y < height; (*y)++) {
if (*x >= width) *x = 0;
else (*x)++;
for (; found == 0 && *x < width; (*x)++) {
if (strncmp (railways[GetRIdx(*x, *y)].name, name.c_str(), REFERENCENAME_LEN) == 0) {
found = 1;
break;
}
}
if (found) break;
}
printf ("%s:%d found (%d,%d)\n", __FILE__, __LINE__, *x, *y);
if (*x < width && *y < height) return 1;
else return 0;
};
int Railways::FindReference(int *x, int *y, string name) {
int res;
Lock();
res = _FindReference (x, y, name);
UnLock();
return res;
};
void Railways::DebugPrintFindWay(struct s_findway_map *fw) {
string c;
int x, y;
int idx;
char chr;
printf (" ");
for (x = 0; x < width && x < 80; x++)
printf ("%c", (char) ((x % 10) + '0'));
printf ("\n");
for (y = 0; y < height && y < 40; y++) {
printf ("%c ", (char) ((y % 10) + '0'));
for (x = 0; x < width && x < 80; x++) {
idx = GetRIdx(x, y);
if (railways[idx].dir == 1) c = "";
if (railways[idx].dir == 2) c = "";
if (railways[idx].dir == 3) c = "";
if (railways[idx].dir == 4) c = "";
if (railways[idx].dir == 5) c = "";
if (railways[idx].dir == 6) c = "";
if (railways[idx].type == RAILWAY_CROSSING) c = "+";
if (railways[idx].type == RAILWAY_TURNOUT) c = "t";
if (railways[idx].type == RAILWAY_CONNECTOR) c = "";
if (railways[idx].type == RAILWAY_BLOCK && railways[idx].dir == 1) c = "";
if (railways[idx].type == RAILWAY_BLOCK && railways[idx].dir == 2) c = "";
if (fw != NULL) {
if ((fw[idx].e & 15) > 0) {
chr = (char)('0' + (fw[idx].e & 15));
if (chr > '9') chr = chr - ('0' + 10) + 'A';
c = chr;
}
else if (fw[idx].e != 0) {
c = "?";
printf ("---%d---", fw[idx].e);
}
}
printf ("%s", c.c_str());
c = " ";
}
printf ("\n");
}
for (x = 0; x < width && x < 80; x++)
printf ("%c", (char) ((x % 10) + '0'));
printf ("\n");
printf ("Debug Finished\n");
}
/////////////////////////////////////////////////////////////////////
//
// FindWay: will be in two phases to decide where to go and how
// 1. check all possible ways in respect of (out of service blocks)
// 2.
// return 0 if no way found
int Railways::FindWay(string blockstart, string blockend, 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;
// check blocklen
if (blockstart.length() <= 3 || blockend.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::FindWay could not find startblock (%s).", blockstart.c_str());
free (fd_data);
return 0;
}
if (FindReference(&fd_end.x, &fd_end.y, blockend.substr(2, string::npos))) {
if (Get(fd_end.x, fd_end.y).dir == 1) {
if (blockend[0] == '+') fd_end.enterfrom = 0;
else fd_end.enterfrom = 2;
}
else {
if (blockend[0] == '+') fd_end.enterfrom = 3;
else fd_end.enterfrom = 1;
}
fd_end.way = blockend;
fd_data[GetRIdx(fd_end.x, fd_end.y)].e = (1 << fd_end.enterfrom);
}
else {
debug (0, "Railway::FindWay could not find endblock (%s).", blockend.c_str());
free (fd_data);
return 0;
}
fd_pos = NextPos(fd_start, Get(fd_start.x, fd_start.y).dir);
// fd_list.push_back(fd_pos);
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_end.x == fd_pos.x && fd_pos.y == fd_end.y && fd_pos.enterfrom == fd_end.enterfrom) {
// destination found
printf ("%s:%d destination found fd_pos (%d,%d) fd_end (%d,%d) next:%s\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_end.x, fd_end.y, fd_pos.way.c_str());
found = 1;
*next = fd_pos.way + ",b:" + blockend;
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
printf ("%s:%d start found fd_pos (%d,%d) fd_start (%d,%d)\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_start.x, fd_start.y);
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
printf ("old entry found (%d,%d)\n", fd_pos.x, fd_pos.y);
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) {
printf ("%s:%d railway is locked by %s\n", __FILE__, __LINE__, rnext->lockedby);
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
fd_pos.way = "";
}
}
else if (rpos->type == RAILWAY_TURNOUT) {
fd_tmp = NextPos(fd_pos, rpos->altdir);
fd_tmp.way += (string)",t:" + (string)rpos->name + (string)":1";
printf ("%s:%d turnout dir:%d altdir:%d fd_pos (%d,%d -> %d) fd_tmp (%d,%d -> %d)\n", __FILE__, __LINE__, rpos->dir, rpos->altdir, fd_pos.x, fd_pos.y, fd_pos.enterfrom, fd_tmp.x, fd_tmp.y, fd_tmp.enterfrom);
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++;
printf ("%s:%d turnout fd_newpos (%d,%d -> %d)\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_pos.enterfrom);
}
else if (rpos->type == RAILWAY_CONNECTOR) {
int found = 0;
printf ("%s:%d connector found Reference:'%s'\n", __FILE__, __LINE__, rpos->name);
x = -1;
y = -1;
while (found == 0 && _FindReference(&x, &y, rpos->name) == 1) {
if (fd_pos.x != x || fd_pos.y != y) {
printf ("%s:%d found %d,%d\n", __FILE__, __LINE__, x, 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) {
printf ("%s:%d block found\n", __FILE__, __LINE__);
if (server->blocks.IsOff(rpos->name)) {
printf ("%s:%d block is off\n", __FILE__, __LINE__);
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) {
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;
fd_pos = NextPos(fd_pos, rpos->dir);
fd_pos.parma++;
}
else {
printf ("%s:%d block is locked by %s\n", __FILE__, __LINE__, lockedby.c_str());
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
fd_pos.way = "";
}
}
}
else { // finished
printf ("%s:%d finished?\n", __FILE__, __LINE__);
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
fd_pos.way = "";
}
}
printf ("%s:%d fd_pos (%d,%d) enterfrom:%d\n\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_pos.enterfrom);
}
if (found == 0) *next = "";
else {
//
// next = "b:+blockname,t:name:0,t:name:1,b:-blockname"
printf ("Temp Next: %s\n", 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));
printf ("%s:%d next: '%s' found\n", __FILE__, __LINE__, next->c_str());
}
else {
// nothing found?
printf ("%s:%d next: '%s' but no next block?\n", __FILE__, __LINE__, 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;
size_t curwaypos;
struct s_findway_data start;
struct s_findway_data end;
struct s_findway_data pos;
string startblock, endblock;
Railway *r;
int finished = 0;
JSONParse jp;
debug (0, "* LockWay Way:'%s' for '%s'", way.c_str(), lockedby.c_str());
end.x = start.x = -1;
end.y = start.y = -1;
end.enterfrom = start.enterfrom = -1;
end.parma = start.parma = -1;
if ((pos1 = way.find("b:", 0)) == string::npos) return 0;
if ((pos2 = way.find(",", pos1+1)) == string::npos) return 0;
startblock = way.substr (pos1+2, pos2-pos1-2);
if ((pos1 = way.find(",b:", 0)) == string::npos) return 0;
if ((pos2 = way.find(",", pos1+1)) == string::npos) endblock = way.substr (pos1+3, pos2);
else endblock = way.substr (pos1+3, pos2-pos1-3);
// printf ("%s:%d LockWay Way: '%s' Startblock: '%s' Endblock: '%s'\n", __FILE__, __LINE__, way.c_str(),
// startblock.c_str(), endblock.c_str());
if (FindReference(&start.x, &start.y, startblock.substr(2,string::npos))) {
if (Get(start.x, start.y).dir == 1) {
if (startblock[0] == '+') start.enterfrom = 0;
else start.enterfrom = 2;
}
else {
if (startblock[0] == '+') start.enterfrom = 3;
else start.enterfrom = 1;
}
}
else {
debug (0, "Railway::LockWay could not find start (%s).", startblock.c_str());
return 0;
}
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;
}
else {
if (endblock[0] == '+') end.enterfrom = 3;
else end.enterfrom = 1;
}
}
else {
debug (0, "Railway::FindWay could not find end (%s).", endblock.c_str());
return 0;
}
printf ("%s:%d LockWay Way:'%s' start [%d,%d -> %d] to [%d,%d -> %d]\n", __FILE__, __LINE__, way.c_str(),
start.x, start.y, start.enterfrom, end.x, end.y, end.enterfrom);
//
// lock way depending on Way
Lock();
pos.x = start.x;
pos.y = start.y;
pos.enterfrom = start.enterfrom;
curwaypos = 0; // position in string // find first turnout
curwaypos = way.find(",t:", curwaypos);
if (curwaypos != string::npos) curwaypos++;
finished = 0;
do {
r = &railways[GetRIdx(pos.x, pos.y)];
printf ("LockWay Position [%d,%d] Name:%s LockedBy:'%s'\n", pos.x, pos.y, r->name, r->lockedby);
// check if railway is free or locked by me
if (r->lockedby[0] != 0 && lockedby.compare(r->lockedby) != 0) {
debug (0, "LockWay: Railway currently locked by '%s'.", r->lockedby);
UnLock();
return 0;
}
// do lock start and endpoint... unlock only start
if (pos.x == end.x && pos.y == end.y && r->type == RAILWAY_BLOCK) {
if (lockonoff == 1) {
server->blocks.SetLockedby(r->name, lockedby, 1);
strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
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);
if (lockonoff) strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
else r->lockedby[0] = 0;
jp.Clear();
jp.AddObject("railway",_GetJSONRailway(pos.x, pos.y));
if(network) network->ChangeListPushToAll(jp.ToString());
}
else {
if (lockonoff) strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
else r->lockedby[0] = 0;
jp.Clear();
jp.AddObject("railway",_GetJSONRailway(pos.x, pos.y));
if(network) network->ChangeListPushToAll(jp.ToString());
}
if ((pos.x == end.x && pos.y == end.y) || pos.x < 0 || pos.y < 0 || pos.x >= width || pos.y >= height) {
finished = 1;
break;
}
// go to next position
if (r->type == RAILWAY_TURNOUT) {
if (curwaypos == string::npos) { // we should have a turnout
debug (0, "LockWay turnout '%s' not on Way '%s'", r->name, way.c_str());
UnLock();
return 0;
}
pos1 = way.find(":", curwaypos+2);
if (pos1 == string::npos) {
debug (0, "LockWay turnout could not find parameter 'active'" );
UnLock();
return 0;
}
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;
}
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++;
}
else if (r->type == RAILWAY_CONNECTOR) {
int found = 0;
int x, y;
printf ("%s:%d connector found Reference:'%s'\n", __FILE__, __LINE__, r->name);
x = -1;
y = -1;
while (found == 0 && _FindReference(&x, &y, r->name) == 1) {
if (pos.x != x || pos.y != y) {
printf ("%s:%d found %d,%d\n", __FILE__, __LINE__, x, y);
pos.oldx = pos.x;
pos.oldy = pos.y;
pos.oldenterfrom = pos.enterfrom;
pos.x = x;
pos.y = y;
r = &railways[GetRIdx(pos.x, pos.y)];
pos = NextPos(pos, r->dir);
pos.parma++;
found = 1;
break;
}
}
if (found == 0) {
debug (0, "LockWay connector '%s' did not find second end.", r->name );
UnLock();
return 0;
}
}
else if (r->type == RAILWAY_BLOCK || r->type == RAILWAY_SENSOR || r->type == RAILWAY_NORMAL) {
pos = NextPos(pos, r->dir);
}
} while (finished == 0);
if (pos.x == end.x && pos.y == end.y) res = 1;
UnLock();
return res;
};
int Railways::SetLockedby (int x, int y, string name, int locked) {
int res = 1;
Railway *r;
JSONParse jp;
if (x < 0 || y < 0 || x >= width || y >= height) return 0;
Lock();
r = &railways[GetRIdx(x,y)];
if (r->lockedby[0] != 0)
if (name.compare(r->lockedby) != 0) res = 0;
if (res) {
if (locked) strncpy (r->lockedby, name.c_str(), REFERENCENAME_LEN);
else r->lockedby[0] = 0;
if (railways[GetRIdx(x, y)].type != RAILWAY_NOTHING) {
jp.AddObject("railway", _GetJSONRailway(x, y));
if(network) network->ChangeListPushToAll(jp.ToString());
}
}
UnLock();
return res;
};