Time and waiting
A script that never sleeps hammers the game and gets itself noticed. These functions are there to space out what it does, and to tell what time it is.
Waiting
Ten functions, a single idea: suspend the script. They differ by the unit, and that is the most frequent source of error.
| Function | Unit | Example |
|---|---|---|
Sleep(n) | milliseconds | Sleep(500) waits half a second |
SleepMs(n) | milliseconds | the same one, under its other name |
SleepSec(n) | seconds | SleepSec(30) |
SleepMin(n) | minutes | SleepMin(5) |
SleepDur(d) | a duration | SleepDur(90 * time.Second) |
SleepRandMs(min, max) | milliseconds | drawn at random between the two |
SleepRandSec(min, max) | seconds | SleepRandSec(20, 40) |
SleepRandMin(min, max) | minutes | SleepRandMin(3, 8) waits from 3 to 8 minutes |
SleepRandHour(min, max) | hours | SleepRandHour(1, 3) |
SleepUntil(when) | until a given time | see below |
They all return one value, an error, which you can ignore without risk.
SleepSec(30)
SleepRandSec(20, 40) // prefer randomness: a regular interval is easy to spot
The SleepRandMin pitfall
SleepRandMin counts minutes. Some scripts coming from elsewhere passed it milliseconds, because on Ninja that is what it counted.
SleepRandMin(200, 800) // ✗ you wait from 3h20m to 13h20m
SleepRandMs(200, 800) // ✓ you wait from 200 to 800 milliseconds
Nothing will warn you: the script is simply sleeping, and you think it is stuck. The bot does write one line to the log the first time a script calls this function, with the duration it drew. If you read "437 minutes" there when you were expecting four hundred milliseconds, you have your culprit.
Sleeping until a given time
SleepUntil accepts two forms, a clock string or a date.
SleepUntil("03:30:00") // the next time it is 3:30
when, err = GetNextDatetimeAt(3, 30, 0) // returns TWO values
if err == nil { SleepUntil(when) } // never nest it inside SleepUntil(...)
Both forms "03:30:00" and "03:30" are accepted.
Do not nest GetNextDatetimeAt inside SleepUntil. GetNextDatetimeAt returns two values, the date and an error; written as a direct argument to another call, anko wraps them in a single slice, which SleepUntil cannot read. The script does not sleep, and the failure goes unnoticed if you did not pick up the error. See the first pitfall.
With a string, if the time has already gone by today, the wait targets the next day. A script that schedules its night at three in the morning while it is mid-afternoon waits for that night; it does not go backwards.
A wait can be interrupted
All these functions listen for the script being stopped. If you click Stop while the script is sleeping for eight hours, it stops right away: there is no waiting for the timer to run out. The same holds when the bot shuts down.
Telling the time
| Function | Returns | |
|---|---|---|
Now() | 1: a date | The present moment. |
GetTimestamp() | 1: an integer | The present moment in seconds since 1970. |
NowTimeString() | 1: a string | The current time, 15:04:05. |
Clock() | 3: hour, minute, second | |
Date() | 3: year, month, day | |
Weekday() | 1: an integer | The day of the week, Sunday being zero. |
Unix(sec, nsec) | 1: a date | Rebuilds a date from a timestamp. |
h, m, s = Clock() // three targets, not one
y, mo, d = Date()
if Weekday() == 0 { Print("Sunday") }
Clock and Date return three values. Written with a single target, they hand you a slice of three elements, and your comparisons fail silently. See the first pitfall.
Comparing and measuring
| Function | Returns | |
|---|---|---|
NowInTimeRange(start, end) | 1: a boolean | Tells you whether the current time is in the range. |
DurationBetweenTimeStrings(a, b) | 1: a duration | The gap between two clock times. |
MillisecondsBetweenTimeStrings(a, b) | 1: an integer | The same, in milliseconds. |
ShortDur(d) | 1: a string | Writes a duration readably, 2h15m. |
GetNextDatetimeAt(h, m, s) | 2: the date and an error | The next time it is that time of day. |
ParseNextDatetimeAt(s) | 2: the date and an error | The same, from "03:30:00". |
if NowInTimeRange("23:00:00", "07:00:00") {
Print("it is night") // the range crosses midnight, that is intended
}
For GetNextDatetimeAt, go back to the example above, in "Sleeping until a given time".
NowInTimeRange handles ranges that cross midnight: 23:00 to 07:00 reads as you would expect. It does not validate the time you hand it, though: "25:00:00" raises no error, it simply answers false. That is Ninja's behaviour, kept as is.