diff --git a/server/block.cc b/server/block.cc index 88acb8d..e2e6e43 100644 --- a/server/block.cc +++ b/server/block.cc @@ -8,6 +8,7 @@ Blocks::Blocks () { changed = 0; blocks = (Block*) malloc(sizeof(Block)*SENSORS_MAX); max = BLOCKS_MAX; + last_blockidx = -1; }; Blocks::~Blocks() { @@ -31,19 +32,19 @@ int Blocks::UnLock() { } -JSONParse Blocks::_GetJSON(int idx) { +JSONParse Blocks::_GetJSON(Block *bl) { JSONParse json; JSONElement je; string s = ""; json.Clear(); - s = blocks[idx].name; json.AddObject("name", s); - json.AddObject("flags", blocks[idx].flags); - json.AddObject("lockedby", blocks[idx].lockedby); - json.AddObject("sensor_pos_1", blocks[idx].s_pos_1); - json.AddObject("sensor_center", blocks[idx].s_center); - json.AddObject("sensor_neg_1", blocks[idx].s_neg_1); + s = bl->name; json.AddObject("name", s); + json.AddObject("flags", bl->flags); + json.AddObject("lockedby", bl->lockedby); + json.AddObject("sensor_pos_1", bl->s_pos_1); + json.AddObject("sensor_center", bl->s_center); + json.AddObject("sensor_neg_1", bl->s_neg_1); return json; }; @@ -163,36 +164,115 @@ int Blocks::Delete(string name) { return 1; }; + // // thread will not be locked.. -int Blocks::SetOff(string name) { - int i; +int Blocks::SetOff(string blname) { + Block *bl = NULL; + JSONParse jp; - for (i = 0; i < max; i++) if (blocks[i].name[0] != 0) { - if (name.compare(blocks[i].name) == 0) { - changed = 1; - blocks[i].flags |= BLOCK_F_OFF; - printf ("%s:%d set block %s off", __FILE__, __LINE__, blocks[i].name); - break; - } + Lock(); + if ((bl = FindBlock(blname)) != NULL) { + changed = 1; + bl->flags |= BLOCK_F_OFF; + printf ("%s:%d set block %s off", __FILE__, __LINE__, bl->name); + + jp.AddObject("block",_GetJSON(bl)); + if(network) network->ChangeListPushToAll(jp.ToString()); + + UnLock(); + return 1; } + UnLock(); return 1; }; -int Blocks::Clear(string name) { - int i; +int Blocks::IsOff(string blname) { + // return -1 if not found, 0 on no lock, 1 on lock + Block *bl = NULL; + int res = -1; - for (i = 0; i < max; i++) if (blocks[i].name[0] != 0) { - if (name.compare(blocks[i].name) == 0) { - changed = 1; - blocks[i].flags &= ~BLOCK_F_OFF; - printf ("%s:%d clear block %s off", __FILE__, __LINE__, blocks[i].name); - break; + Lock(); + if ((bl = FindBlock(blname)) != NULL) { + if (bl->flags & BLOCK_F_OFF) res = 1; + else res = 0; + } + UnLock(); + + return res; +}; + + +int Blocks::SetLockedby (string blname, string lockedby, int lock_onoff) { + // return -1 if not found, 0 on no lock, 1 on lock + Block *bl = NULL; + JSONParse jp; + int res = -1; + + Lock(); + if ((bl = FindBlock(blname)) != NULL) { + if (lockedby.compare (bl->lockedby) == 0) res = 1; + else if (bl->lockedby[0] == 0) { + strncpy (bl->lockedby, lockedby.c_str(), REFERENCENAME_LEN); + jp.AddObject("block",_GetJSON(bl)); + if(network) network->ChangeListPushToAll(jp.ToString()); + res = 1; } + else res = 0; } + UnLock(); - return 1; + return res; +}; + + +string Blocks::GetLockedby (string blname) { + Block *bl = NULL; + string lb; + + Lock(); + if ((bl = FindBlock(blname)) != NULL) { + lb = bl->lockedby; + UnLock(); + return lb; + } + UnLock(); + + return ""; +}; + + +Block* Blocks::FindBlock(string name) { + Block *bl = NULL; + + if (last_blockidx >= 0 && last_blockidx < max) + if (name.compare (blocks[last_blockidx].name) == 0) + return &blocks[last_blockidx]; + + for (last_blockidx = 0; last_blockidx < max; last_blockidx++) { + if (name.compare (blocks[last_blockidx].name) == 0) + return &blocks[last_blockidx]; + } + + return bl; +}; + + +int Blocks::Clear(string name) { + Block *bl = NULL; + + Lock(); + if ((bl = FindBlock(name)) != NULL) { + changed = 1; + bl->flags &= ~BLOCK_F_OFF; + printf ("%s:%d clear block %s off", __FILE__, __LINE__, bl->name); + UnLock(); + return 1; + } + UnLock(); + + return 0; }; diff --git a/server/block.h b/server/block.h index 2b40d8a..91b6b0b 100644 --- a/server/block.h +++ b/server/block.h @@ -33,7 +33,11 @@ class Blocks { int UnLock(); // not thread safe - JSONParse _GetJSON(int idx); + JSONParse _GetJSON(Block *bl); + JSONParse _GetJSON(int idx) { return _GetJSON(&blocks[idx]); }; + + int last_blockidx; // to speed up things + Block* FindBlock(string name); public: Blocks(); ~Blocks(); @@ -48,7 +52,12 @@ class Blocks { void GetJSONAll(JSONParse *json); Block GetBlockFromJSON(JSONParse *j); - int SetOff(string name); + int SetOff(string blname); + int IsOff(string blname); + + int SetLockedby (string blname, string lockedby, int lock_onoff); + string GetLockedby (string blname); + int Clear(string name); }; diff --git a/server/locomotive.cc b/server/locomotive.cc index 24ae27e..4be910d 100644 --- a/server/locomotive.cc +++ b/server/locomotive.cc @@ -265,6 +265,7 @@ int Locomotives::SetFunction(string name, int func, int value) { int Locomotives::SetDestination (string name, string block, int direction) { int i; + string next; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) @@ -272,10 +273,14 @@ int Locomotives::SetDestination (string name, string block, int direction) { debug (0, "Locomotives::SetDestination (Name:%s Block:%s Direction:%d)\n", name.c_str(), block.c_str(), direction); if (direction) snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "-:%s", block.c_str()); else snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "+:%s", block.c_str()); + + server->railways.FindWay(locomotives[i].blockassign, locomotives[i].blockdest, locomotives[i].name, &next); + break; } UnLock(); + printf ("%s:%d %s ************** finish me **************\n", __FILE__, __LINE__, __FUNCTION__); return 1; } diff --git a/server/network.cc b/server/network.cc index c07f6db..87efa93 100644 --- a/server/network.cc +++ b/server/network.cc @@ -89,7 +89,7 @@ void Network::ThreadProcess() { gettimeofday (&tv, NULL); i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000; if (i > cycletime_max) cycletime_max = i; - if (i < 1000 && i > 0) usleep (100000 - i*1000); + if (i < 100 && i > 0) usleep (100000 - i*1000); gettimeofday (&tv, NULL); i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000; if (i > cyclelooptime_max) cyclelooptime_max = i; @@ -153,7 +153,6 @@ void Network::ChangeListPushToAll(string changes) { int Network::ServerLoop() { UNIX *u = NULL; - if (sockserver.IsData(10)) { u = sockserver.Accept(); clients.push_back(u); diff --git a/server/railway.cc b/server/railway.cc index 7bef599..c4bb5f9 100644 --- a/server/railway.cc +++ b/server/railway.cc @@ -37,6 +37,81 @@ int Railways::UnLock() { }; +// +// 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, parma: pos.parma }; // 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) @@ -319,7 +394,8 @@ void Railways::ClearLockedby(string name) { } -int Railways::FindReference(int *x, int *y, string name) { + +int Railways::_FindReference(int *x, int *y, string name) { int found = 0; if (x == NULL || y == NULL) return 0; if (*x < 0 || *y < 0) { @@ -327,7 +403,8 @@ int Railways::FindReference(int *x, int *y, string name) { *y = 0; } - Lock(); + 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)++; @@ -338,15 +415,269 @@ int Railways::FindReference(int *x, int *y, string name) { break; } } + if (found) break; } - UnLock(); + + printf ("%s:%d found (%d,%d)\n", __FILE__, __LINE__, *x, *y); if (*x < width && *y < height) return 1; else return 0; }; -int FindWay(string blockstart, string blockend, string lockedfor, string *next) { - 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"); +} + +// 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 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_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_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; if found next needs to be filled in + 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; + } + 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)\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_end.x, fd_end.y); + fd_pos.enterfrom = -1; + fd_pos.x = -1; + fd_pos.y = -1; + } + 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; + } + 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; + } + 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++; + } + + else if (rpos->type == RAILWAY_TURNOUT) { + fd_tmp = NextPos(fd_pos, rpos->altdir); + 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++; + fd_list.push_back(fd_tmp); + fd_pos = NextPos(fd_pos, rpos->dir); + 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); + + 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.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; + } + } + // + // 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; + } + else { + // lockedby = server->blocks.GetLockedby(rpos->name); + fd_pos = NextPos(fd_pos, rpos->dir); + fd_pos.parma++; + } + } + + else { // finished + printf ("%s:%d finished?\n", __FILE__, __LINE__); + fd_pos.enterfrom = -1; + fd_pos.x = -1; + fd_pos.y = -1; + } + } + 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 = ""; + UnLock(); + + free (fd_data); + + return found; }; diff --git a/server/railway.h b/server/railway.h index 328ee77..e5a71b4 100644 --- a/server/railway.h +++ b/server/railway.h @@ -40,7 +40,20 @@ enum { // | | | /| |\ | | | // +---+ +---+ +---+ +---+ // - +// Enter from +// 0 +// +---+ +// | | +// 3| |1 +// | | +// +---+ +// 2 +enum { + EF_NORTH = 0, + EF_EAST, + EF_SOUTH, + EF_WEST +}; struct s_Railway { int type; @@ -54,6 +67,17 @@ struct s_Railway { char lockedby[REFERENCENAME_LEN]; // element locked by locreference (only set by server, not by JSON/Webinterface) } typedef Railway; +struct s_findway_data { + int x; + int y; + int enterfrom; // enter field from clock view (0 = North, 3 = East... 6 ... 9) + int parma; +}; + +struct s_findway_map { + int e; // save entryfrom as (1 << entryfrom) + int score; +}; class Railways { private: @@ -70,6 +94,8 @@ class Railways { int GetRIdx(int x, int y); JSONParse _GetJSONRailway(int x, int y); void _New (int w, int h); + void DebugPrintFindWay(struct s_findway_map *fw); + int _FindReference(int *x, int *y, string name); public: Railways(); @@ -97,6 +123,8 @@ class Railways { int FindReference(int *x, int *y, string name); int FindWay(string blockstart, string blockend, string lockedfor, string *next); + + struct s_findway_data NextPos(struct s_findway_data pos, int dirtype); }; #endif diff --git a/server/server.cc b/server/server.cc index c063171..46f623d 100644 --- a/server/server.cc +++ b/server/server.cc @@ -105,7 +105,7 @@ void Server::ThreadProcess() { gettimeofday (&tv, NULL); i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000; if (i > cycletime_max) cycletime_max = i; - if (i < 25000 && i > 0) usleep (25000 - i*1000); + if (i < 25 && i > 0) usleep (25000 - i*1000); gettimeofday (&tv, NULL); i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000; if (i > cyclelooptime_max) cyclelooptime_max = i; diff --git a/server/server.h b/server/server.h index c1b1104..593084c 100644 --- a/server/server.h +++ b/server/server.h @@ -90,6 +90,7 @@ private: friend class Sensors; friend class Turnouts; friend class Blocks; + friend class Railways; public: ///////////////////////////////////////// // functions here are required to be thread save