Java - Trying to make a timer - java

I'm trying to make a timer that goes from 15 minutes to 0 but my code doesn't work. Sorry if this is easy, I recently started learning.
package timer;
import java.util.Timer;
import java.util.TimerTask;
public class Timer {
int secondsLeft = 900;
int minutesLeft = secondsLeft/60;
int seconds2 = secondsLeft - minutesLeft * 60;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
secondsLeft--;
System.out.println("Time left : " + minutesLeft + ":" + seconds2 );
}
};
public void start() {
timer.scheduleAtFixedRate(task, 1000, 1000);
}
public static void main(String[] args) {
Timer timer = new Timer();
timer.start();
}
}

Your program is mostly written correctly, but you are not printing any changes. When the seconds count down, you need to convert existing total seconds to minutes and seconds.
You can do it several ways.
Method 1: Like you are doing it now, by
maintaining a total number of seconds. It requires two operators.
The division operator /
The remainder operator %
To get the minutes remaining, simply divide total seconds by 60. (totalSeconds / 60)
To get the seconds remaining in the current minute take the remainder (totalSeconds % 60)
Method 2: By maintaining separate values for minutes and seconds, where seconds is the number of seconds within the current minute.
define a int minutes field initialized to 15
define a int seconds field initialized to 0
When the timer task runs, you need to update those fields correctly. When the seconds reach 0
decrement the minutes and set the seconds to 59. Otherwise, just decrement the seconds.
When they both reach 0, you're done. So this requires some if clauses on your part.
Additional Recommendations
To retain the leading zeroes of minutes and seconds, you can use the following formatted print statement.
System.out.printf("Time left : %02d:%02d%n",minutesLeft, secondsLeft);
The %02d is the field width and the 0 means keep leading zeroes to fill out that field. To learn more about formatted printing, check out the Formatter class in the Java API.
And finally, please call you class something other than Timer. You are using a Timer class by that name already and even though it is in the same package it can be confusing.

Related

how to run a code 60 times per second in java

if I don't control the number of times per second my code executes, when I add a line, the program varies and I have to adjust the constants again. (translated by Google)
My code running out of control:
public builder(){
while(true)
stepEvent();
}
private void stepEvent() {
setOfActions();
repaint();
}
This is just one way to do it(it's very long but VERY precise - I recommend it for game development). In this case I'm using the run() method from the Runnable interface to execute the code.
public void run(){
long lastTime = System.nanoTime();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
while(true){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
the code you want to be executed
delta--;
}
}
}
Explanation Line by Line:
Basically, I store the current time in nanoseconds in lastTime. Then in ns I store 1/60th of a second in nanoseconds and create a variable delta.
After this, I go inside the infinite while loop(it doesn't have to be infinite) and store the current time in nanoseconds once again in now. This is to take into account the amount of time that took the computer to go from the lastTime declaration line to the while loop line.
After doing all this, I add to delta the difference of now and lastTime divided by the 1/60th of a second(ns) I mentioned. This means that every time delta is equal to 1, 1/60th of a second will have passed.
Right after this, I make lastTime be the same as now. In the while loop that comes afterwards I check if delta is equal or greater than 1 and then in there you should put all the code you want to be executed 60 times per second. Don't forget to substract 1 from delta so it doesn't loop endlessly.
Analyze the code thoroughly and see if you can understand it. If you can't, I'll clarify further. I insist that this is just one possible way to do it, but there are many more ways.
Note: In some cases, you will never even need delta, but it is very helpful for some purposes.
Credit for the code: Most of this code(at least where I got it & learned it) is extracted from TheCherno's Game Programming Series
Have a great day!
import java.util.Timer;
import java.util.TimerTask;
public class HelloWorld {
public static void main(String []args) {
// number of ms in 1/60 of a second
// there will be some rounding error here,
// not sure if that's acceptable for your use case
int ms = 1000 / 60;
Timer timer = new Timer();
timer.schedule(new SayHello(), 0, ms);
}
}
class SayHello extends TimerTask {
public void run() {
System.out.println("Hello World!");
}
}
Basically, you have to execute your stepEvent every 17 ms.
With the assumption you want to run sequentially, you could stop the execution during a defined period by using Thread.sleep(millis , nanos). In this case, we will stop the thread 17ms minus the stepEvent execution time (think to add condition to avoid negative value in sleep function)
long startedTime;
for(;;){
startedTime = System.currentTimeMillis();
stepEvent();
Thread.sleep(17 - System.currentTimeMillis() + startedTime);
}
Otherwise you can use the ScheduledExecutorService which allows you to schedule code to run periodically at fixed time intervals (or after a specified delay). In this case, you can execute your step at a fixed rate every 17ms.
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(YourClass::stepEvent, 0, 17, TimeUnit.MILLISECONDS);
You can also configure to use severals thread with Executors.newScheduledThreadPool

Method creating CountDownTimer objects

I'm kinda stuck with the following code. My goal is to create multiple CountDownTimer objects and start them after each other. The method looks like that:
private CountDownTimer setUpCountdown(int duration, int tick) {
// when tick is not set, set it to default 1 second
tick = (tick == 0 ? 1 : tick);
// convert seconds to milliseconds and set up the timer
CountDownTimer timer = new CountDownTimer(duration*1000, tick*1000) {
public void onTick(long millisUntilFinished) {
if (countdown != null) {
int timeRemaining = (int) (millisUntilFinished / 1000);
countdown.setText(String.valueOf(timeRemaining));
}
}
public void onFinish() {
// hide the countdown button and remove it from baseLayout. set the background of baseLayout back to black
countdown.setVisibility(View.INVISIBLE);
baseLayout.removeView(countdown);
baseLayout.setBackgroundColor(Color.BLACK);
}
};
return timer;
}
Then I create two timers:
CountDownTimer timer1 = setUpCountdown(8,1);
timer1.start();
CountDownTimer timer2 = setUpCountdown(5,1);
timer2.start();
When running the code the output for those values is: 4..3..2..1..3 when it should be 7..6...1 4...1 When I'm using 10 and 5 seconds as duration I get a single Countdown on the android device that counts from 10 to 5. It looks like the objects I'm creating are not really independent from each other or (kind of) use the same variables. Do you see what I'm doing wrong?
You are starting two timer at same time and displaying their values in single textView so you are able to see the value of only second timer 4..1 then the remaining values of timer with 8 sec will be displayed as 3..1
timer 7 6 5 4 3 2 1
// timer 2 will reset the values in text view, then after 1, you will see 3 2 1
timer 4 3 2 1
You can use Toast to verify the behavior or you have to use different TextViews to achieve the desired result or to achieve desired behavior, you can create and start the second timer from onFinish()

Mp3 player with timer in java [fast forward]

I'm making fast forward button in my Mp3 player. I wrote already code for this, but have problem how to implement timer to jump 5% forward? I mean when I press button timer should jump 5% forward of total long song. This is my fastForward method.
public void FastForward(){
try {
//songTotalLength = fis.available();
fis.skip((long) ((songTotalLength * 0.05)));
} catch (IOException e) {
e.printStackTrace();
}
}
And here is the button method:
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
bar+=5;
}
And this one is for timer:
private void setTime(float t) {
int mili = (int) (t / 1000);
int sec = (mili / 1000) % 60;
int min = (mili / 1000) / 60;
start.set(Calendar.MINUTE, 0);
start.set(Calendar.SECOND, 0);
end.set(Calendar.MINUTE, 0 + min);
end.set(Calendar.SECOND, 0 + sec);
timer = new javax.swing.Timer(1000, new TimerListener());
percent = (float)100/(min*60+sec);
}
You're already redundantly tracking progress in two variables fis and bar. For the sake of good design, use one of those to determine elapsed time rather than using yet another variable for the same purpose.
but have problem how to implement timer to jump 5% forward?
You seem to have mistaken the purpose of a Timer. According to the Timer class documentation, it:
Fires one or more ActionEvents at specified intervals.
So the timer is not meant to keep track of how much time has elapsed. It will simply invoke the actionPerformed(ActionEvent) method of your TimerListener once per second (every 1000 milliseconds) as you have it configured.
For a more complete answer, please post the code for your TimerListener class.
Notes
It seems that your setTime(float) method is meant to be called repeatedly, so this method should not be initializing the timer variable. Rather initialize the timer once and leave it alone to do its job.
I'm assuming you intended the supplied float parameter t to represent microseconds.
The float data type has only 7 digits of precision. This could be fine since you're interested only in minutes and seconds, otherwise float is only good for up to about four months of seconds before losing accuracy.
It seems like you wanted your button click handler to do this (increment bar sooner):
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
bar+=5; // increment bar before checking complete, and before setting progress
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
}

How to increment time every second in Libgdx

I try to add time to my game that will increment every second.
How to fix that?
I add my code below
float timer;
timer += delta;
if(timer<=delta+1000)//every one sec
{
time = time+1;
timePoint.setSentence(""+time/100);
timer = 0f;
}
as your note, delta is Gdx.graphics.getDeltaTime().
'time' is string.
but looks like the time increment slowly. means that when time already run about 1,5 sec,
'time' still increase 1.
I divide by 100 because if not it will increase more faster/sec,
i also use TimeUtils class from libgdx but it produced similar result.
Thanks before.
This should work. Note that time/100 results in 0 for 0-99 and 1 for 100-199. That's probably not the effect you wanted.
float timer;
timer += delta;
if (timer >= 1) {
time++;
timePoint.setSentence(""+time);
timer -= 1;
}
The problem was that you set the timer back to 0. If it was 1.1f for example (because the last delta was 0.1f), then you basically lose 100ms. Don't reset the timer to 0f, but decrease it by 1f instead.
I would do it like this:
float time = 0f;
In render:
time += delta;
timePoint.setSentence(Integer.toString((int)time));
delta is giving the ellapsed time in seconds, so for 30FPS it is 1/30 seconds. So you only need to add it to your time. To print the difference (i guess the setSentence is printing the text) you only need to cast it to int, so that it cuts the fraction digits.
Hope it helps.
EDIT: If you need the timer and the time variable somewhere you need to store them in 2 different variables.
For that i would do it like this:
float timer = 0f;
int time = 0;
And in render:
timer+=delta;
if (timer >= 1f) {
time++;
timePoint.setSentence(Integer.toString(time));
timer-=1f;
}
By doing this you are not loosing the few milli seconds you would loose if you reset the timer.
This means, that if timer goes from 0.99f to 1.05f in one renderloop and you reset the timer to 0f, you loose 0.05 seconds. If this happens every second you loose 1 second every 20 seconds (if i am not wrong^^)
Like in pure java:
Timer timer = new Timer();
timer.schedule(new incrementYourValue(), 0, 1000); //1000 is time in mili sec
//0 is the time waited before the beginning.
Had similar problem but for me using delta time was kinda overkill. Instead I used Libgdx Timer that "Executes tasks in the future on the main loop thread". Using Timer from java.util may cause Concurrency problems in libgdx.
import com.badlogic.gdx.utils.Timer;
public class Scheduler {
public Scheduler(Runnable runnable, float periodInSeconds) {
Timer timer = new Timer();
timer.scheduleTask(new Timer.Task() {
#Override
public void run() {
runnable.run();
}
}, 0, periodInSeconds);
}}
And usage:
new Scheduler(() -> updateSth(), 1f);

Java Gradually Decrease Number Until Target Reached Over Time

I am struggling a bit with a concept on how to implement some timings.
Basically, I need to write some code that will effectively perform a ramp-up to fire requests to a server.
To explain further, I need to fire requests to a server over the course of a 15 minute ramp-up period. After 15 minutes, a rate of 3 requests per second should be made. At the beginning of the ramp up period, we can start with (say) 1 request every 3 seconds. How it reaches the 3 request per second rate doesn't matter, but it should not reach this rate until 15 minutes.
What I need help with is implementing this as a timer. I need a function that will return the amount of time to wait before sending the next request.
So I have a loop like so:
Send request
Wait x amount of time (where x is returned by a function)
This happens until 15 minutes is reached, whereby the function always returns a value of 0.3 seconds (to achieve 3 requests per second - assumption is that requests take 0 seconds to send, but that's ok...)
The values provided are:
- Total ramp up time.
- Requests per second at the end of the ramp up time.
- Requests per second at the start of the ramp up time.
Any help would be appreciated.
Since you are not too concerned about the exact way the rate speeds up, you could choose the following assumptions:
Rate will increase linearly with time
Some approximations and rounding of the rate is fine, as long as we don't slow down
You are starting at time=0, and going to time=15
At time=0, your rate is (say) 1 every 3 seconds. At time=15, your rate is 1 every 0.3333 seconds
The total change from 0 to 15 is (3 - 0.3333=) 2.77777
Divide this by 15, you get 0.1777777. What this means is: if your rate fell by 0.177777 every second, you could start at 3 and end up at 0.3333
This is shown on a linear graph like this:
So, if you have a method that know how long (in seconds) since the start (x), you can compute what your current rate should be.
double computeRate(double secondsSinceStart)
{
return 3 * (-0.177777 * Math.floor(secondsSinceStart));
}
That computation is the number of seconds you have to wait.
Using a similar principle, you can assume a non-linear curve, or tweak it in other ways.
/**
* start is the moment the first request is sent (in ms)
* end is the moment, in which the targetDelta should be reached (in ms)
* targetDelta is the targeted period between two requests (0.3)
* initDelta is the initial delta (1.0)
*/
private int getWaitingPeriod(long start, long end, double targetDelta, double initDelta) {
double timePassed = (double) (System.currentTimeMillis() - start);
double progress = timePassed / (double) (end - start);
if(progress >= 1) return (int) (targetDelta * 1000);
return (int) ((targetDelta - (targetDelta - initDelta) * progress) * 1000);
}
Not tested, but is this what you are searching for?
edit: whoops, forgot converting seconds to ms.. Now tested, example:
long start = System.currentTimeMillis();
while(System.currentTimeMillis() < start + 10000) { //testing with 10 seconds
int wait = getWaitingPeriod(start, start + 10000, 1, 0.3);
System.out.println("waiting " + wait + "ms");
try {
Thread.sleep(wait);
} catch(InterruptedException ex) {}
}
You can start by creating a class that handles sending the requests if that's not already the case. Something like (this is more Object Oriented) :
public class RequestSender {
double startTime;
// ramp up time is in minutes
double rampUpTime;
boolean firstRequest;
int requestPerSecBeforeTime;
int requestPerSecAfterTime;
RequestSender(double rampUpTime, int requestPerSecBeforeTime, int requestPerSecAfterTime){
this.rampUpTime = rampUpTime;
this.requestPerSecAfterTime = requestPerSecAfterTime;
this.requestPerSecBeforeTime = requestPerSecAfterTime;
firstRequest=true;
}
public void sendRequest(){
if (firstRequest){
startTime = System.currentTimeMillis();
firstRequest = false;
}
// do stuff to send requests
}
public double getWaitTime(){
if ((System.currentTimeMillis() - startTime)/60000 > rampUpTime){
return 1/requestPerSecAfterTime;
}
else {
return 1/requestPerSecBeforeTime;
}
}
}
Then you can use this object in your code :
RequestSender rs = new RequestSender(15, 1, 3);
rs.sendRequest();
Thread.wait(rs.getWaitTime());

Categories