AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[Func] ETA - Estimated time of arrival

 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
animeaime



Joined: 04 Nov 2008
Posts: 1045

PostPosted: Sat Apr 11, 2009 5:50 pm    Post subject: [Func] ETA - Estimated time of arrival Reply with quote

Functions: ETA and helper functions

Description
  • ETA returns a formatted time for the estimated finish time of a loop, file download, etc.
  • Supports tracking multiple ETAs simultaneously
  • Supports pausing (and resuming) an ETA timer


Download
ETA.zip

Requirements
None



Functions
ETA_Start(ByRef PreviousTime, ByRef TimeTaken, ByRef TimerIndex = 0)
Initializes values to be used by ETA.

Parameters
PreviousTime - variable to store the previous time (the "Timer" variable)
TimeTaken - variable to store how long the timer has been running so far
TimerIndex - variable to store the timer index (initializes it to 0)



ETA(CurrentValue, TotalValue, ByRef PreviousTime, ByRef TimeTaken)
Returns the estimated finish time given the specified current value, total value, previous time, and time taken; updates PreviousTime and TimeTaken accordingly.

ReturnValue
A formatted string represing the estimated finish time.

Format
If ETA is less than a minute:
0:ss

If ETA is less than an hour (but more than a minute):
m:ss

Else:
h:mm:ss

Remarks
CurrentValue and TotalValue must be positive numbers - either can be a decimal.

Supports percentages by specifing 100 for TotalValue and the percentage for CurrentValue.

Can be used to show the ETA for a file download. Specify the file size (in bytes) for TotalValue and the size (in bytes) already downloaded for CurrentValue.



ETA_Stop(ByRef PreviousTime, ByRef TimeTaken)
1) Stops the specified timer
2) Updates TimeTaken (if the timer was previously running, and not paused)
3) Sets PreviousTime to -2, to signify the timer is stopped (see example 2 below, for use)
4) Returns TimeTaken (in seconds)

Note: Although this function is not required to be called, it can be used to store the time taken (in seconds) for the timer into a variable. Additionally, this function sets PreviousTime to -2, to signify the timer is stopped - this allows an easy check to see if the timer is stopped (see example 2 below).

Note: Do not call this function if you intend to start the timer back up - instead, call ETA_Pause.



ETA_Pause(ByRef PreviousTime, ByRef TimeTaken)
1) Pauses the specified timer. Does nothing if the timer was already paused (or stopped).
2) Updates TimeTaken
3) Sets PreviousTime to -1, to signify the timer is paused (see example 2 below, for use)



ETA_Resume(ByRef PreviousTime)
Resumes the specified Timer. Does nothing if the timer wasn't paused.



Code
Code:
;for all functions, PreviousTime is the "timer" - the previous time is stored

/*
calculates ETA
(supports "pausing")

returns the formatted ETA
*/
ETA(CurrentValue, TotalValue, ByRef PreviousTime, ByRef TimeTaken)
{
    /*
    values MUST start at 0 and have a constant step
    (CurrentValue or TotalValue can be a decimal value)


    e.g.

    A_Index (in a loop),
    percentages (TotalValue = 100),
    file download (use bytes for values),
    etc.
    */

    /*
    Derivation of formula

    ETA = TimeRequired - TimeTaken

    TimeTaken / CurrentValue = TimeRequired / TotalValue
    TimeRequired = TimeTaken / CurrentValue * TotalValue
    TimeRequired - TimeTaken = TimeTaken / CurrentValue * TotalValue - TimeTaken
    ETA = TimeTaken * (TotalValue / CurrentValue - 1)
    */

    if (PreviousTime >= 0)
    {
        ;timer is not "paused" and not stopped
       
        TimeTaken += A_TickCount - PreviousTime
        PreviousTime := A_TickCount
    }

    ;divide by 1000 to convert from milliseconds to seconds
    ETA := round(TimeTaken * (TotalValue - CurrentValue) / CurrentValue / 1000)

    ;ETA is less than a minute
    if (ETA < 60)
        return "0:" . (ETA < 10 ? "0" : "") . ETA

    seconds := mod(ETA, 60)
    ETA //= 60


    ;ETA is less than an hour
    if (ETA < 60)
        return ETA ":" . (seconds < 10 ? "0" : "") . seconds

    minutes := mod(ETA, 60)
    ETA //= 60


    ;else, ETA is greater than an hour
    return ETA ":" . (minutes < 10 ? "0" : "") . minutes
        . ":" . (seconds < 10 ? "0" : "") . seconds
}

;initializes a Timer
;pass variables to use for each the
;   previous time, time taken, and timer index (optional)
ETA_Start(ByRef PreviousTime, ByRef TimeTaken, ByRef TimerIndex = 0)
{
    PreviousTime := A_TickCount
    TimeTaken := 0
    TimerIndex := 0
}

;"stops" an ETA timer
;(use ETA_Pause if you plan to continue the timer later)
;updates TimeTaken, and returns this value (in seconds)
;sets PreviousTime to -2, to signify the time is done
ETA_Stop(ByRef PreviousTime, ByRef TimeTaken)
{
    ;only if timer is "ticking"
    if (PreviousTime >= 0)
        TimeTaken += A_TickCount - PreviousTime
       
    PreviousTime := -2
   
    return round(TimeTaken / 1000)
}

;"pauses" an ETA timer
ETA_Pause(ByRef PreviousTime, ByRef TimeTaken)
{
    ;already paused (or stopped)
    if (PreviousTime < 0)
        return

    TimeTaken += A_TickCount - PreviousTime
    PreviousTime := -1
}

;"resumes" a "paused" ETA timer
ETA_Resume(ByRef PreviousTime)
{
    ;you don't need to pass TimeTaken, because the time taken doesn't increase
    ;(since the timer was paused)

    ;wasn't paused
    if (PreviousTime != -1)
        return

    PreviousTime := A_TickCount
}


Example 1
Code:
#SingleInstance Force
#NoEnv

;initialize an ETA timer
ETA_Start(Timer1, Timer1Time)

;loops for about 15 seconds
LoopCount := 150

Loop, %LoopCount%
{
    Sleep, 100
    ToolTip, % ETA(A_Index, LoopCount, Timer1, Timer1Time)
}


Example 2
Code:
#SingleInstance Force
#NoEnv

;each loop loops for about 5 seconds (4 loops = 20 seconds)
LoopCount := 50


;initialize an ETA timer
ETA_Start(Timer1, Timer1Time, Index1)

;Store the total count
TotalValue1 := 4 * LoopCount


;initialize an ETA timer
ETA_Start(Timer2, Timer2Time, Index2)

;Store the total count
TotalValue2 := 2 * LoopCount


Loop, %LoopCount%
{
    Sleep, 100
   
    ;store pause state
    isPaused1 := (Timer1 = -1) ? " (Paused)" : ""
    isPaused2 := (Timer2 = -1) ? " (Paused)" : ""
   
    ;stores done state
    isDone1 := (Timer1 = -2) ? " (Done)" : ""
    isDone2 := (Timer2 = -2) ? " (Done)" : ""

    ;increase indexes
    Index1++
    Index2++
       
    ToolTip, % "Loop #1`n`n"
        . "Timer1: " ETA(Index1, TotalValue1, Timer1, Timer1Time) . "`n"
        . isDone1 . isPaused1
        . "Timer2: " ETA(Index2, TotalValue2, Timer2, Timer2Time)
        . isDone2 . isPaused2
}

;pause Timer2
ETA_Pause(Timer2, Timer2Time)

Loop, %LoopCount%
{
    Sleep, 100

    ;store pause state
    isPaused1 := (Timer1 = -1) ? " (Paused)" : ""
    isPaused2 := (Timer2 = -1) ? " (Paused)" : ""

    ;stores done state
    isDone1 := (Timer1 = -2) ? " (Done)" : ""
    isDone2 := (Timer2 = -2) ? " (Done)" : ""

    ;increase indexes
    Index1++
    ;don't increase Index2 (Timer2 is paused)

    ToolTip, % "Loop #2`n`n"
        . "Timer1: " ETA(Index1, TotalValue1, Timer1, Timer1Time) . "`n"
        . isDone1 . isPaused1
        . "Timer2: " ETA(Index2, TotalValue2, Timer2, Timer2Time)
        . isDone2 . isPaused2
}

;resume Timer2
ETA_Resume(Timer2)

Loop, %LoopCount%
{
    Sleep, 100

    ;store pause state
    isPaused1 := (Timer1 = -1) ? " (Paused)" : ""
    isPaused2 := (Timer2 = -1) ? " (Paused)" : ""

    ;stores done state
    isDone1 := (Timer1 = -2) ? " (Done)" : ""
    isDone2 := (Timer2 = -2) ? " (Done)" : ""

    ;increase indexes
    Index1++
    Index2++

    ToolTip, % "Loop #3`n`n"
        . "Timer1: " ETA(Index1, TotalValue1, Timer1, Timer1Time) . "`n"
        . isDone1 . isPaused1
        . "Timer2: " ETA(Index2, TotalValue2, Timer2, Timer2Time)
        . isDone2 . isPaused2
}

/*
Timer2 is done

calling ETA_Stop is not required;
   it can be used to store the "total time required" into a variable.
*/
TotalTime2 := ETA_Stop(Timer2, Timer2Time)

Loop, %LoopCount%
{
    Sleep, 100

    ;store pause state
    isPaused1 := (Timer1 = -1) ? " (Paused)" : ""
    isPaused2 := (Timer2 = -1) ? " (Paused)" : ""

    ;stores done state
    isDone1 := (Timer1 = -2) ? " (Done)" : ""
    isDone2 := (Timer2 = -2) ? " (Done)" : ""

    ;increase indexes
    Index1++
    ;don't increase Index2 (Timer2 is already finished)
   
    ToolTip, % "Loop #4`n`n"
        . "Timer1: " ETA(Index1, TotalValue1, Timer1, Timer1Time) . "`n"
        . isDone1 . isPaused1
        . "Timer2: " ETA(Index2, TotalValue2, Timer2, Timer2Time)
        . isDone2 . isPaused2
}

;Timer1 is done
TotalTime1 := ETA_Stop(Timer1, Timer1Time)

ToolTip

MsgBox, % "Timer1 took " TotalTime1 " seconds.`n"
    . "Timer2 took " TotalTime2 " seconds."




How to use
Extract the zip's contents to a library folder for automatic inclusion - StdLib compliant.

A copy of the above examples can be found in the "Func Examples" folder.

Download ETA function
_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group