How to Implement a "Timer"

How to implement a Timer class in Java?

I found out that there is a class in Android called Handler which can execute code with a delay. So I made use of this class to create a timer!

import android.os.Handler;
import android.support.annotation.NonNull;
import android.widget.TextView;

public class Timer implements Comparable<Timer> {
private Handler handler;
private boolean paused;
private TextView text;

private int minutes;
private int seconds;

private final Runnable timerTask = new Runnable () {
@Override
public void run() {
if (!paused) {
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
}

text.setText (Timer.this.toString ());
Timer.this.handler.postDelayed (this, 1000);
}
}
};

@Override
public String toString () {
if (Integer.toString (seconds).length () == 1) {
return minutes + ":0" + seconds;
} else {
return minutes + ":" + seconds;
}
}

public void startTimer () {
paused = false;
handler.postDelayed (timerTask, 1000);
}

public void stopTimer () {
paused = true;
}

public void resetTimer () {
stopTimer ();
minutes = 0;
seconds = 0;
text.setText (toString ());
}

public Timer (TextView text) {
this.text = text;
handler = new Handler ();
}

public Timer (TextView text, String parseString) {
this (text);
String[] splitString = parseString.split (":");
minutes = Integer.parseInt (splitString[0]);
seconds = Integer.parseInt (splitString[1]);
}

@Override
public int compareTo(@NonNull Timer another) {
int numberOfSeconds = seconds + minutes * 60;
int anotherNumberOfSeconds = another.seconds + another.minutes * 60;

return ((Integer)numberOfSeconds).compareTo (anotherNumberOfSeconds);
}
}

And it has a really simple interface. Very easy to use.

Implementing a timer in c++

If all you want is the time taken, chuck your timer. Ask what time it is when the user starts, store it, and subtract the start time from the time when the user finishes.

void game()
{
int s = 0 , m = 0;
char a[]="Computers";
char b[10];
time_t start = time(NULL); <<<< Modification here
while (strcmpi(a,b)!=0)
{
cout<<"Guess the word:";
gets(b);
}
cout<<"You got it correct!\n";
time _t taken = time(NULL) - start;
m = taken / 60; <<<< Modification here
s = taken % 60; <<<< Modification here
cout<<"Time taken : "<< m <<':'<<s<<endl;
}

If allowed by the assignment, consider replacing chars a and b with strings a and b. The user cannot overflow the string and wreak havoc on your program the way they can with char arrays and gets.

void game()
{
int s = 0 , m = 0;
std::string a ="Computers"; <<<< Modification here
std::string b; <<<< Modification here
time_t start = time(NULL);
do
{
cout<<"Guess the word:";
cin>> b; <<<< Modification here
} while (a != b); <<<< Modification here. No sense testing b before you read b
cout<<"You got it correct!\n";
time _t taken = time(NULL) - start;
m = taken / 60;
s = taken % 60;
cout<<"Time taken : "<< m <<':'<<s<<endl;
}

any help or idea on how to implement the timer functionality

No need for the for loop. The interval with an incrementing index takes care of that. Here's an example that will repeat or stop the interval once it's reached it's length - it's set for 3 seconds here in the example. Also note the fix in your arrow function () = { should be () => {.





//const value = await AsyncStorage.getItem('users'); 
//pub = JSON.parse(value);
let pub = [{'id': 1}, {'id': 2}, {'id': 3}, {'id': 4}, {'id': 7}, {'id': "F"}];
let id_index = 0,
repeat = true
const interval = setInterval(() => {
x = pub[id_index].id;
console.log('value of id >>', x);
if (id_index++ >= pub.length-1) {
if (repeat) id_index = 0; //reset
else clearInterval(interval)
}

}, 500)

// just in case you have to stop
// clearInterval(interval)

How can I implement a timer in a portable way in Jetpack Compose?

In Compose you can use LaunchedEffect - it's a side effect which is run on a coroutine scope, so you can use delay inside, like this:

var ticks by remember { mutableStateOf(0) }
LaunchedEffect(Unit) {
while(true) {
delay(1.seconds)
ticks++
}
}

How to implement a distributed countdown timer in Firebase

Many developers get stuck on this problem because they try to synchronize the countdown itself across all users. This is hard to keep in sync, and error prone. There is a much simpler approach however, and I've used this in many projects.

All each client needs to show its countdown timer are three things of fairly static information:

  1. The time that the question was posted, which is when the timer starts.
  2. The amount of time they need to count from that moment.
  3. The relative offset of the client to the central timer.

We're going to use the server time of the database for the first value, the second value is just coming from the hosts code, and the relative offset is a value that Firebase provides for us.

The code samples below are written in JavaScript for the web, but the same approach (and quite similar code) and be applied in iOS, Android and most other Firebase SDKs that implement realtime listeners.


Let's first write the starting time, and interval to the database. Ignoring security rules and validation, this can be as simple as:

const database = firebase.database();
const ref = database.ref("countdown");
ref.set({
startAt: ServerValue.TIMESTAMP,
seconds: 20
});

When we execute the above code, it writes the current time to the database, and that this is a 20 second countdown. Since we're writing the time with ServerValue.TIMESTAMP, the database will write the time on the server, so there's no chance if it being affected by the local time (or offset) of the host.


Now let's see how the other user's read this data. As usual with Firebase, we'll use an on() listener, which means our code is actively listening for when the data gets written:

ref.on("value", (snapshot) => {
...
});

When this ref.on(... code executes, it immediately reads the current value from the database and runs the callback. But it then also keeps listening for changes to the database, and runs the code again when another write happens.

So let's assume we're getting called with a new data snapshot for a countdown that has just started. How can we show an accurate countdown timer on all screens?

We'll first get the values from the database with:

ref.on("value", (snapshot) => {
const seconds = snapshot.val().seconds;
const startAt = snapshot.val().startAt;
...
});

We also need to estimate how much time there is between our local client, and the time on the server. The Firebase SDK estimates this time when it first connects to the server, and we can read it from .info/serverTimeOffset in the client:

const serverTimeOffset = 0;
database.ref(".info/serverTimeOffset").on("value", (snapshot) => { serverTimeOffset = snapshot.val() });
ref.on("value", (snapshot) => {
const seconds = snapshot.val().seconds;
const startAt = snapshot.val().startAt;

});

In a well running system, the serverTimeOffset is a positive value indicating our latency to the server (in milliseconds). But it may also be a negative value, if our local clock has an offset. Either way, we can use this value to show a more accurate countdown timer.

Next up we'll start an interval timer, which gets calls every 100ms or so:

const serverTimeOffset = 0;
database.ref(".info/serverTimeOffset").on("value", (snapshot) => { serverTimeOffset = snapshot.val() });
ref.on("value", (snapshot) => {
const seconds = snapshot.val().seconds;
const startAt = snapshot.val().startAt;
const interval = setInterval(() => {
...
}, 100)
});

Then every timer our interval expires, we're going to calculate the time that is left:

const serverTimeOffset = 0;
database.ref(".info/serverTimeOffset").on("value", (snapshot) => { serverTimeOffset = snapshot.val() });
ref.on("value", (snapshot) => {
const seconds = snapshot.val().seconds;
const startAt = snapshot.val().startAt;
const interval = setInterval(() => {
const timeLeft = (seconds * 1000) - (Date.now() - startAt - serverTimeOffset);
...
}, 100)
});

And then finally we log the remaining time, in a reasonable format and stop the timer if it has expired:

const serverTimeOffset = 0;
database.ref(".info/serverTimeOffset").on("value", (snapshot) => { serverTimeOffset = snapshot.val() });
ref.on("value", (snapshot) => {
const seconds = snapshot.val().seconds;
const startAt = snapshot.val().startAt;
const interval = setInterval(() => {
const timeLeft = (seconds * 1000) - (Date.now() - startAt - serverTimeOffset);
if (timeLeft < 0) {
clearInterval(interval);
console.log("0.0 left)";
}
else {
console.log(`${Math.floor(timeLeft/1000)}.${timeLeft % 1000}`);
}
}, 100)
});

There's definitely some cleanup left to do in the above code, for example when a new countdown starts while one is still in progress, but the overall approach works well and scales easily to thousands of users.



Related Topics



Leave a reply



Submit