chiark / gitweb /
New resolution arrangements; before move predict() call into resolve_motioncheck
authorian <ian>
Sun, 27 Jul 2008 20:25:46 +0000 (20:25 +0000)
committerian <ian>
Sun, 27 Jul 2008 20:25:46 +0000 (20:25 +0000)
hostside/resolve.c

index 6a29ab77a25d99236c979ea615dfe570bead49a2..dc093bcb87698d1a47803d6cabcf69c0785432f5 100644 (file)
@@ -382,12 +382,22 @@ static int resolve_complete_main(void) {
 /*---------- heads and tails of trains, final placement ----------*/
 
 #define resfin_ours mark1
-#define resfin_done mark2
 
 typedef struct {
+  Distance hardallow, min, max;
+  int hardwhy;
+  Segment *lastdetect, *hardend;
+} FindEndConstraint;
+
+typedef struct {
+  TrackAdvanceContext tc; /* first! */
+  TrackLocation t;
   Train *train;
-  Segment *furthest;
-  int extraspace;
+  Segment *startpoint;
+  Distance atlastdetect;
+  Segment *lastdetect;
+  FindEndConstraint constraints[2];
+  int problems, rear;
 } FindEndUserContext;
 
 static int findends_getmovpos(TrackLocation *t, TrackAdvanceContext *c,
@@ -395,75 +405,125 @@ static int findends_getmovpos(TrackLocation *t, TrackAdvanceContext *c,
   const char *pn= t->seg->i->pname;
   if (t->seg->motion) *use_io= movpos_change_intent(t->seg->motion);
   if (*use_io<0) {
-    DPRINTF(resolving,ends, " getmovpos %s fails\n", pn);
-    t->seg->resfin_done= 0;
-    return -1;
+    DPRINTF(resolving,ends, "   getmovpos %s fails\n", pn);
+    return 'm';
   }
-  DPRINTF(resolving,ends, " getmovpos %s -> %d\n", pn, *use_io);
+  DPRINTF(resolving,ends, "   getmovpos %s -> %d\n", pn, *use_io);
   return 0;
 }
 
-static int segdist(Segment *seg) {
-  TrackLocation t;
+static int constraint_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
+                             MovPosComb *mpc, const TrackLocation *before) {
   int r;
-  MovPosComb mpc;
-  
-  t.seg= seg;
-  mpc= seg->movposcomb;
+  FindEndUserContext *u= (void*)c;
   
-  r= findends_getmovpos(&t,0,&mpc);
-  assert(!r);  assert(mpc >= 0);
-  return seg->i->poscombs[mpc].dist;
-}
-
-static void ends_callback_debug(const char *what, TrackLocation *t,
-                               struct TrackAdvanceContext *c) {
-  DPRINTF(resolving,ends, "  %s"
-         " %s%s dist=%d det=%d ours=%d done=%d owner=%s home=%s\n",
-         what, t->backwards?"-":"", t->seg->i->pname, c->distance,
+  DPRINTF(resolving,ends, "  constraint_nextseg %c"
+         " %s%s dist=INF-%d det=%d ours=%d owner=%s home=%s\n",
+         "fr"[u->rear],
+         t->backwards?"-":"", t->seg->i->pname,
+         TL_DIST_INF - c->distance,
          t->seg->res_detect,
          t->seg->resfin_ours,
-         t->seg->resfin_done,
          t->seg->owner ? t->seg->owner->pname : "-",
          t->seg->home ?  t->seg->home->pname  : "-");
-}
 
-static int findhead_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
-                           MovPosComb *mpc_io, const TrackLocation *before) {
-  FindEndUserContext *u= c->u;
+  if (!t->seg->resfin_ours) return 'o';
+  r= findends_getmovpos(t,0,mpc);  if (r) return r;
 
-  ends_callback_debug("findhead_nextseg",t,c);
+  const SegPosCombInfo *pci= &t->seg->i->poscombs[*mpc];
 
-  if (!t->seg->resfin_ours || t->seg->resfin_done) return -1;
-  u->furthest= t->seg;
-  t->seg->tr_backwards= t->backwards;
-  t->seg->resfin_done= 1;
-
-  if (!t->seg->res_detect) {
-    u->train->plan_lookahead_nsegs= 1;
-    u->extraspace= 0;
-    return -1;
+  if (before) {
+    if (t->seg == u->startpoint) return 'l';
+    const SegmentLinkInfo *rlink= &pci->link[!t->backwards];
+    if (before->seg != &segments[rlink->next]) return 'm';
+  }
+  if (t->seg->res_detect) {
+    u->atlastdetect= c->distance;
+    u->lastdetect= t->seg;
   }
-  u->train->foredetect= t->seg;
   return 0;
 }
 
-static int walkback_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
-                           MovPosComb *mpc_io, const TrackLocation *before) {
-  ends_callback_debug("walkback_nextseg",t,c);
+static int constraint_trackend(TrackLocation *t,
+                              struct TrackAdvanceContext *c) {
+  return 'e';
+}
 
-  if (!t->seg->resfin_ours) return -1;
-  t->seg->tr_backwards= !t->backwards;
-  t->seg->resfin_done= 1;
-  return 0;
+static void end_startpoint(FindEndUserContext *u) {
+  int r;
+
+  u->tc.distance= TL_DIST_INF;
+  u->tc.nextseg= constraint_nextseg;
+  u->tc.getmovpos= findends_getmovpos;
+  u->tc.trackend= constraint_trackend;
+  u->tc.u= 0;
+
+  r= trackloc_set_exactinto(&u->t, &u->tc,
+                           u->startpoint, u->startpoint->tr_backwards,
+                           0);
+  assert(!r);
+}
+
+static void end_constraints(FindEndUserContext *u) {
+  FindEndConstraint lim;
+  Train *tra= u->train;
+  int r;
+
+  end_startpoint(u);
+  u->tc.distance= TL_DIST_INF;
+
+  u->lastdetect= 0;
+  u->atlastdetect= -1;
+
+  if (u->rear) {
+    r= trackloc_reverse_exact(&u->t,&u->tc);
+    assert(!r);
+  }
+
+  FindEndConstraint *cons= &u->constraints[u->rear];
+
+  cons->hardwhy= trackloc_advance(&u->t,&u->tc);
+  
+  assert(cons->hardwhy);
+  assert(u->lastdetect);
+  assert(u->atlastdetect >= 0);
+
+  Distance nose= MARGIN_NOSE +
+    ((tra->backwards ^ u->rear) ? tra->head : tra->tail);
+
+  lim.min= TL_DIST_INF - u->atlastdetect;
+  lim.max= (TL_DIST_INF - u->tc.distance) - nose;
+
+  if (!u->rear) {
+    cons->min= lim.min;
+    cons->max= lim.max;
+  } else {
+    cons->max= -lim.min + tra->detectable;
+    cons->min= -lim.max + tra->detectable;
+  }
+  cons->lastdetect= u->lastdetect;
+  cons->hardend= u->t.seg;
+
+  if (cons->min > cons->max) {
+    ouprintf("resolution implausible %s %s overhang %d %d\n",
+            cons->lastdetect->i->pname, tra->pname,
+            cons->min - cons->max, nose);
+    u->problems++;
+  }
+
+  DPRINTF(resolving,ends, " lims %c hardwhy=%c %s,%s lim=%d..%d out=%d..%d\n",
+         "fr"[u->rear], cons->hardwhy,
+         cons->lastdetect->i->pname, u->t.seg->i->pname,
+         lim.min, lim.max, cons->min, cons->max);
 }
 
 static int resolve_complete_ends_train(Train *tra) {
   SEG_IV;
-  TrackLocation t;
-  TrackAdvanceContext tc;
   FindEndUserContext u;
-  Segment *startpoint;
+  const SegPosCombInfo *pci;
+  struct timeval tnow;
+  ErrorCode ec;
+  int r, DP;
 
   switch (tra->resolution) {
   case RR_H: break;
@@ -472,91 +532,87 @@ static int resolve_complete_ends_train(Train *tra) {
   default: abort();
   }
 
-  DPRINTF(resolving,ends, "%s %c\n",
-         tra->pname, RESOLUTION_CHARS[tra->resolution]);
+  DPRINTF1(resolving,ends, "%s %c",
+          tra->pname, RESOLUTION_CHARS[tra->resolution]);
 
-  startpoint= 0;
+  memset(&u,0,sizeof(u));
+  u.startpoint= 0;
   
   FOR_SEGMENT(seg,NOOP,NOOP) {
-    seg->resfin_done= 0;
     seg->resfin_ours= tra ==
       (tra->resolution==RR_H ? seg->home : seg->owner);
-    if (seg->resfin_ours && seg->res_detect)
-      startpoint= seg;
+    if (!seg->resfin_ours) continue;
+    DPRINTF2(" %s%s", seg->tr_backwards?"-":"", seg->i->pname);
+    if (seg->res_detect) {
+      DPRINTF2("*");
+      u.startpoint= seg;
+    }
   }
-
-  assert(startpoint);
-
-  t.seg= startpoint;
-  t.remain= 0;
-  t.backwards= t.seg->tr_backwards ^ tra->backwards;
-
-  tra->backwards= 0;
-  tra->plan_lookahead_nsegs= 0;
-
-  tc.distance= TL_DIST_INF;
-  tc.nextseg= findhead_nextseg;
-  tc.getmovpos= findends_getmovpos;
-  tc.trackend= 0;
-  tc.u= &u;
+  assert(u.startpoint);
+  DPRINTF2("\n");
+
+  /* There are four pieces of information we have:
+   * The rearmost detection, the rearmost end of ownership
+   * the foremost detection, the foremost end of ownership
+   *
+   * From each we compute a range of locations.  These are
+   * in the form of a minimum and maximum distance of the
+   * foredetect ahead of 0 into the startpoint.
+   */
 
   u.train= tra;
-  u.extraspace= MARGIN_NOSE + tra->head;
-  u.furthest= 0;
-
-  DPRINTF(resolving,ends, " start=%s%s es=%d\n",
-         t.backwards?"-":"", t.seg->i->pname, u.extraspace);
-
-  trackloc_advance(&t,&tc);
+  for (u.rear=0; u.rear<2; u.rear++)
+    end_constraints(&u);
 
-  DPRINTF(resolving,ends, " es=%d furthest=%s fd=%s%s fd.dist=%d\n",
-         u.extraspace, u.furthest->i->pname,
-         tra->foredetect->tr_backwards?"-":"", tra->foredetect->i->pname,
-         segdist(tra->foredetect));
+  Distance wrongness;
 
-  tra->maxinto= segdist(tra->foredetect) - u.extraspace;
-  if (tra->maxinto < 0) {
-    ouprintf("resolution mispositioned head %s %s %d\n",
-            tra->pname, tra->foredetect->i->pname, -tra->maxinto);
-    return 1;
+  if ((wrongness= u.constraints[0].min - u.constraints[1].max) > 0) {
+    for (u.rear=1; u.rear>0; u.rear--)
+      ouprintf("resolution implausible %s %s over-detect %d\n",
+              u.constraints[u.rear].lastdetect->i->pname,
+              tra->pname, wrongness);
+    u.problems++;
   }
-  tra->uncertainty= tra->maxinto;
+  if ((wrongness= u.constraints[1].min - u.constraints[0].max) > 0) {
+    for (u.rear=1; u.rear>0; u.rear--)
+      ouprintf("resolution implausible %s %s cramped %d\n",
+              u.constraints[u.rear].hardend->i->pname,
+              tra->pname, wrongness);
+    u.problems++;
+  }
+
+  int min= MIN(u.constraints[0].min, u.constraints[1].min);
+  int max= MIN(u.constraints[0].max, u.constraints[1].max);
+  DPRINTF(resolving,ends, " lims a %d..%d problems=%d\n",
+         min, max, u.problems);
 
-  t.seg= tra->foredetect;
-  t.remain= 0;
-  t.backwards= !tra->foredetect->tr_backwards;
+  if (u.problems)
+    return u.problems;
   
-  tc.distance= tra->detectable + tra->tail + MARGIN_NOSE;
-  tc.nextseg= walkback_nextseg;
+  assert(min <= max);
+  assert(max > 0); /* startpoint is detected so foredet is there or later */
 
-  trackloc_advance(&t,&tc);
+  /* Now we just need to turn this into the canonical format. */
 
-  DPRINTF(resolving,ends, " maxi=%d unc=%d;"
-         " remaining distance=%d\n",
-         tra->maxinto, tra->uncertainty, tc.distance);
+  end_startpoint(&u);
 
-  if (tc.distance) {
-    tra->uncertainty -= tc.distance;
-    if (tra->uncertainty < 0) {
-      ouprintf("resolution mispositioned tail %s %s %d\n",
-              tra->pname, t.seg->i->pname, -tra->uncertainty);
-      return 1;
-    }
-  }
+  u.tc.distance= max;
+  r= trackloc_advance(&u.t, &u.tc);  assert(!r);
 
-  FOR_SEG {
-    if (seg->owner == tra)
-      seg->owner= 0;
+  tra->foredetect= u.t.seg;
+  tra->foredetect->tr_backwards= u.t.backwards;
 
-    if (seg->resfin_done) {
-      seg->owner= tra;
-      seg->resfin_done= 0;
-      seg->det_ignore= 1;
-    }
-  }
+  r= trackloc_getlink(&u.t, &u.tc, &pci,0,0);  assert(!r);
+  tra->maxinto= pci->dist - u.t.remain;
+  tra->uncertainty= max - min;
 
   report_train_position(tra);
-  report_train_ownerships(tra, t.seg, 1);
+
+  mgettimeofday(&tnow);
+  tra->plan_lookahead_nsegs= INT_MAX;
+  ec= predict(tra,tnow, PREDF_OLDPLAN, 0,0, 0,
+             0,(char*)"resolution confirmation");
+  assert(!ec);
 
   return 0;
 }