def validate_coverage(
    route,
    metric="node_coverage",
    max_gap_sec=3 * 60 * 60,
    min_node_coverage_percent=0.75,
):
    """
    Make sure there is sufficient coverage of the planned route with live data
    """
    if metric == "time":
        last_update, live = None, []
        for r in route:
            live += [l for l in r.get("updates", []) if l.get("eventTime")]
        for l in sorted(live, key=lambda l: l.get("eventTime")):
            if last_update is None:
                last_update = l.get("eventTime")
            if (l.get("eventTime") - last_update).total_seconds() > max_gap_sec:
                return False
            last_update = l.get("eventTime")
        if last_update is None:
            # Did not see any updates
            return False

    elif metric == "node_coverage":
        # Do not allow less than 75% node coverage with live data
        live_stations, planned_stations = [], []
        for r in route:
            live_stations += [
                l.get("stationId") for l in r.get("updates", []) if l.get("stationId")
            ]
            planned_stations += [
                p.get("stationId") for p in r.get("stations", []) if p.get("stationId")
            ]
        intersection = set(planned_stations).intersection(set(live_stations))
        if (
            float(len(intersection)) / float(len(set(planned_stations)))
            < min_node_coverage_percent
        ):
            return False
    return True