"""Numerical teaching model: constant speed and instantaneous braking.

Python 3.10+, standard library only. No simulator engine, machine learning,
robot connection or hardware test. Distances in metres, times in seconds.
The delay calculation excludes physical braking distance.
"""
from math import isclose


def timed_distance(speed_m_s, duration_s):
    if speed_m_s < 0 or duration_s < 0:
        raise ValueError("This one-direction model requires nonnegative inputs")
    return speed_m_s * duration_s


def travel_time(distance_m, speed_m_s):
    if distance_m < 0 or speed_m_s <= 0:
        raise ValueError("Distance must be nonnegative and speed positive")
    return distance_m / speed_m_s


def stopping_position(target_m, positive_position_bias_m):
    # reported_position = actual_position + bias
    if not 0 <= positive_position_bias_m <= target_m:
        raise ValueError("Bias must be between zero and the target")
    return target_m - positive_position_bias_m


def main():
    nominal = timed_distance(0.20, 5.0)
    slower = timed_distance(0.18, 5.0)
    feedback_time = travel_time(1.0, 0.18)
    biased_stop = stopping_position(1.0, 0.02)
    delay_distance = timed_distance(0.20, 0.20)
    assert isclose(nominal, 1.0)
    assert isclose(slower, 0.9)
    assert isclose(1.0 - slower, 0.1)
    assert isclose(feedback_time, 50.0 / 9.0)
    assert isclose(biased_stop, 0.98)
    assert isclose(delay_distance, 0.04)
    assert timed_distance(0.0, 5.0) == 0.0
    try:
        travel_time(1.0, 0.0)
    except ValueError:
        pass
    else:
        raise AssertionError("Zero speed must not produce a finite travel time")
    print(f"Nominal timed travel: {nominal:.2f} m")
    print(f"Slower timed travel: {slower:.2f} m; shortfall: {1-slower:.2f} m")
    print(f"Ideal feedback travel time: {feedback_time:.2f} s")
    print(f"Positive 2 cm measurement bias: stop at {biased_stop:.2f} m")
    print(f"Extra travel during stop delay: {delay_distance:.2f} m")
    print("PASS all 8 numerical and boundary checks")


if __name__ == "__main__":
    main()
