def track_progress(
    measure: MeasureProgress,
    target: MetricProgress,
    interval_check: float,
    capture_maybe: Optional[CaptureProgress] = None
) -> None:
    """
    Tracks progress against a certain end condition of the simulation (for instance, a certain duration on the simulated
    clock), reporting this progress as the simulation chugs along. Stops the simulation once the target has been
    reached. By default, the progress is reported as printout on standard output, in a manner that works best for
    digital terminals.
    """

    def measure_to_target() -> MeasureComparison:
        return list(zip(measure(), target))

    def is_finished(progress: MeasureComparison) -> bool:
        return all(p >= t for p, t in progress)

    capture = capture_maybe or capture_print()
    rt_started = now_real()
    while True:
        advance(interval_check)

        rt_elapsed = now_real() - rt_started
        progress = measure_to_target()
        ratio_progress_min = min(m / t for m, t in progress)
        if ratio_progress_min == 0.0:
            rt_total_projected = inf
        else:
            rt_total_projected = rt_elapsed / ratio_progress_min
        capture(ratio_progress_min, rt_total_projected - rt_elapsed, progress)

        if is_finished(progress):
            stop()
            break
Tracks progress against a certain end condition of the simulation (for instance, a certain duration on the simulated
    clock), reporting this progress as the simulation chugs along. Stops the simulation once the target has been
    reached. By default, the progress is reported as printout on standard output, in a manner that works best for
    digital terminals.