# queries.ludic - what a panel draws: the step, the bar, the pace, and why it stopped export function update_state(update_st: UpdateState) -> int { return update_st.update__state } export function update_error(update_st: UpdateState) -> int { return update_st.update__err } export function update_busy(update_st: UpdateState) -> bool { return update_st.update__state != UPDATE_IDLE and update_st.update__state != UPDATE_FAILED } export function update_failed(update_st: UpdateState) -> bool { return update_st.update__state == UPDATE_FAILED } # checking and patching have no fraction to give: a panel's bar sweeps instead of filling export function update_working(update_st: UpdateState) -> bool { return update_st.update__state == UPDATE_CHECK or update_st.update__state == UPDATE_PATCH } # the package being fetched, checked or patched (0-based), its name, size and version export function update_index(update_st: UpdateState) -> int { return update_st.update__i } export function update_file(update_st: UpdateState) -> string { if update_st.update__files == null or update_st.update__i >= len(update_st.update__files) { return "" } return update_st.update__files[update_st.update__i] } export function update_file_size(update_st: UpdateState) -> int { if update_st.update__size == null or update_st.update__i >= len(update_st.update__size) { return 0 } return update_st.update__size[update_st.update__i] } export function update_version_at(update_st: UpdateState) -> string { if update_st.update__ver == null or update_st.update__i >= len(update_st.update__ver) { return "" } return update_st.update__ver[update_st.update__i] } # bytes of the package in flight, and of the whole plan export function update_file_received(update_st: UpdateState) -> int { if update_st.update__state != UPDATE_FETCH or update_st.update__h < 0 { return 0 } return UpdateNet.received(update_st.update__h) } export function update_received(update_st: UpdateState) -> int { return update_st.update__done_bytes + update_file_received(update_st) } # how far, 0..1000, over every byte of the plan (the file being checked counts as fetched) export function update_progress(update_st: UpdateState) -> int { if update_st.update__total_bytes <= 0 { return 0 } var got = update_st.update__done_bytes if update_st.update__state == UPDATE_FETCH { got = update_received(update_st) } if update_st.update__state == UPDATE_CHECK { got = update_st.update__done_bytes + update_st.update__size[update_st.update__i] } return min(1000, got / max(1, update_st.update__total_bytes / 1000)) } # seconds a check or a patch has been running export function update_step_seconds(update_st: UpdateState) -> int { return (UpdateWorld.now_ms() - update_st.update__step_t0) / 1000 } # seconds left at the eased pace; -1 until the pace is known export function update_eta_seconds(update_st: UpdateState) -> int { if update_st.update__state != UPDATE_FETCH or update_st.update__rate <= 0 { return -1 } return (update_st.update__total_bytes - update_received(update_st)) / update_st.update__rate + 1 } # every half second: the pace, eased so the estimate does not jump function update__rate_tick(update_st: mut UpdateState) -> void { if update_st.update__state != UPDATE_FETCH { return } let now = UpdateWorld.now_ms() let got = update_received(update_st) if update_st.update__rate_t < 0 { update_st.update__rate_t = now update_st.update__rate_bytes = got return } let ms = now - update_st.update__rate_t if ms < 500 { return } let per_s = (got - update_st.update__rate_bytes) / ms * 1000 if update_st.update__rate == 0 { update_st.update__rate = per_s } else { update_st.update__rate = (update_st.update__rate * 3 + per_s) / 4 } update_st.update__rate_t = now update_st.update__rate_bytes = got }