Прогноз можно сделать инертным.
По событию обновления прогресса (очередной чанк загрузился) скачкообразно меняется значение ожидаемого конца
finish_forecast
.
Переменная
finish_forecast_display
это прогнозируемый момент окончания для показа. Исходя из него и
текущего времени плавно обновляем индикатор прогресса.
Чтобы не было дерганий,
finish_forecast_display
обновляем не мгновенно, а раз в фикс. интервал времени (раз в 200 ms) двигаем его в сторону текущего значения
finish_forecast
на дельту, пропорциональную расстоянию - чем ближе, тем медленнее. Тут важна регулярность этих интервалов обновления дисплея.
Так скорость прогресс-бара будет плавно ускоряться или замедляться, но скачков не будет.
Похожий эффект в 2D использовал в
эмуляции полёта насекомого. Там случайная точка задаёт цель, к которой стремится муха. В примере, правда, не сама муха, а перед ней ещё несколько звеньев невидимой цепочки преследования. Но принцип тот же:
C ---> N . . . . . . . . . . . T
T - только что заданный новый момент окончания процесса
total * time_passed / current_progress
C - показываем прогресс бар исходя из этого ожидаемого момента конца всего процесса
N - в следующем "кадре" С примет значение N.
N = C + (T - C) / 100