private String nextSiteId() {
    // TODO: replace this linear search with binary search
    double r = random.nextDouble();
    for (Map.Entry<String, Double> entry : siteWeights.entrySet()) {
      if (r < entry.getValue()) {
        return entry.getKey();
      }
    }
    // Unreachable if siteWeights is created correctly; checking sum(weights)=1 should prevent this.
    throw new RuntimeException("Unexpected problem randomly selecting a siteId");
  }