
namespace dhrg {

void routing_test() {
  N = 8;

  rogueviz::vdata.resize(N);
  for(int i=0; i<N; i++) rogueviz::vdata[i].edges.clear();

  vector<int> parents(N, -1);
  for(int i=1; i<N; i++) parents[i] = rand() % i;
  vector<vector<int> > graph(N);
  for(int i=0; i<N; i++) {
    for(int j=0; j<i; j++)
      if(i == parents[j] || j == parents[i] || rand() % 100 < 10) {
        graph[i].push_back(j), graph[j].push_back(i);
        auto ei = new rogueviz::edgeinfo(&rogueviz::default_edgetype);
        ei->i = i; ei->j = j;
        rogueviz::addedge0(i, j, ei);
        }
    }

  // prepare_pairs(N, [&] (int i) { return graph[i]; } );
  prepare_pairs();

  println(hlog, "graph = ", graph);
  println(hlog, actual);

  vector<hyperpoint> coord(N);
  for(int i=0; i<N; i++) coord[i][0] = rand() % 1000, coord[i][1] = rand() % 1000;
  auto hdist = [&] (int i, int j) { 
    int dx = coord[i][0] - coord[j][0];
    int dy = coord[i][1] - coord[j][1];
    return dx * dx + dy * dy;
    };
  println(hlog, "coord = ", coord);

  bool repeat = false;
  set<int> seen;
  for(int i=0; i<N; i++) for(int j=0; j<i; j++) {
    int d = hdist(i, j);
    if(seen.count(d)) repeat = true;
    seen.insert(d);
    repeat = false;
    }
  if(repeat) return;

  iddata result;
  for(int goal=0; goal<gr_N; goal++) {
    greedy_routing_to(result, goal, hdist);
    }

  iddata result2;
  for(int m=0; m<2; m++) {
    for(int j=0; j<N; j++) for(int i=0; i<N; i++) if(i != j) {
      if(m == 0) result2.tot++;
      int at = i, steps = 0;
      while(at != j && steps < N) {
        int best = at, bestdist = m ? 999999999 : hdist(at, j);
        for(int k: graph[at]) {
          if(hdist(k, j) < bestdist) {
            bestdist = hdist(k, j); best = k;
            }
          }
        at = best; steps++;
        }

      if(at == j) {
        // println(hlog, "from ", i, " to ", j, ": ", steps, " vs ", actual[i][j]);
        (m?result2.msuc:result2.suc)++;
        (m?result2.meff:result2.eff) += actual[i][j] * 1. / steps;
        (m?result2.mroutedist:result2.routedist) += steps * 1. / actual[i][j];
        }
      // else println(hlog, "from ", i, " to ", j, ": failure");
      }
    }

  for(int i=0; i<N; i++) for(int j=0; j<i; j++) println(hlog, tie(i, j), " : ", hdist(i, j));

  auto chk = [] (bool b, string s) {
    return s + (b ? " OK " : " XX ");
    };

  println(hlog, tie(result.tot, result.suc, result.routedist, result.eff));
  println(hlog, tie(result2.tot, result2.suc, result2.routedist, result2.eff));

  bool b1, b2, b3, b4;

  println(hlog, 
    chk(result.tot == result2.tot, "TOT") + 
    chk(result.suc == result2.suc, "OSUC") + 
    chk(result.msuc == result2.msuc, "MSUC") + 
    chk(b1 = abs(result.eff - result2.eff) < 1e-6, "OEFF") + 
    chk(b2 = abs(result.meff - result2.meff) < 1e-6 , "MEFF") +
    chk(b3 = abs(result.routedist - result2.routedist) < 1e-6, "OSF") + 
    chk(b4 = abs(result.mroutedist - result2.mroutedist) < 1e-6, "MSF")
    );

  if(!b3 || !b1 || !b2 || !b4) exit(1);
  }

void routing_tests() {
  for(int i=0; i<1000000; i++) routing_test();
  }

}
