In processing (which is based on java), the draw method is constantly being executed as long as the program is running. I'm trying to measure for how long the condition in the if statement was true.
I have a if statement:
if (matrix [3][5]== 3) {
System.out.println("Closed");
}
else {
System.out.println("Opened");
}
The value of matrix [3][5]changes dynamically (I use Reactivision, and based on some markers position, this value will change). When I run the program, the condition is false so I'll have:
opened
opened
...
opened
and then the condition will be true so it will print:
closed
closed
etc
Before eventually turning back to opened.
I want to measure for how long the condition was true and printed closed, and when it changes, for how long it stayed opened etc: for each lapse of time it returned opened or closed, I want to know for how long.
I started a timer in my setup:
void setup () {
startTime = System.nanoTime();
}
that I could end in the if statement:
if (matrix [3][5]== 3) {
System.out.println("Closed");
long estimatedTime = System.nanoTime() - startTime;
System.out.println("Was opened for"+ estimatedTime);
}
So I would know for how long it's been opened. But how can I make it start again to make it measure now for how long it's closed, then opened etc back and forth ?
I can't figure this out
You can set a new start time in the else branch. And you should set an extra flag indication the last state.
if (matrix [3][5]== 3) {
System.out.println("Closed");
if (isOpen)
{
isOpen=false;
System.out.println("Runtime: " + (System.nanoTime() - startTime));
}
}
else {
if (!isOpen)
{
startTime=System.nanoTime();
isOpen = true;
System.out.println("Opened");
}
}
Something this way. The result depends on the switch frequency. "System.nanoTime()" may return the same time for different calls.
You're on the right track. You can use the nanoTime() or millis() functions to record the start time, and then simply use that same function to record the current time. Subtract the start time from the current time to get your elapsed time.
Here's an example that keeps track of how much time has elapsed since the user clicked:
int start;
void setup(){
size(200, 100);
start = millis();
}
void draw(){
background(0);
int now = millis();
int elapsed = now - start;
text("Elapsed: " + elapsed, 25, 25);
}
void mouseClicked(){
start = millis();
}
Try to repeat your setup() logic in else:
boolean flag = true;// opened is true.
if (matrix[3][5] == 3) {
if (flag) {
long estimatedTime = System.nanoTime() - startTime;
System.out.println("Was opened for" + estimatedTime);
startTime = System.nanoTime();
flag = false;
}
System.out.println("Closed");// or place in the nested if to be less verbose.
} else {
if (!flag) {
long estimatedTime = System.nanoTime() - startTime;
System.out.println("Was closed for" + estimatedTime);
startTime = System.nanoTime();
flag = true;
}
System.out.println("Opened");
}
GL!
You can keep 2 fields in class, where you want to measure a time of opened status as below:
private Long startOpenedStatus=null;
private Long endOpenedStatus=null;
private int[][] matrix=new int[5][5];
public void yourMethod(){
//...
if (matrix [3][5]== 3) {
stopMeasure();
System.out.println("Closed");
}
else {
startMeasure();
System.out.println("Opened");
}
//...
}
/** take time of start opened status, takes only one (first time method fire) in opened session */
private void startMeasure(){
if(startOpenedStatus==null){
//reset time of end the opened status
endOpenedStatus=null;
startOpenedStatus=new GregorianCalendar().getTimeInMillis();//returns actual time in miliseconds for start of opened status
}
}
/** take time of end opened status, takes only one time in closed session*/
private void stopMeasure(){
if(endOpenedStatus==null){
endOpenedStatus=new GregorianCalendar().getTimeInMillis();//returns actual time in miliseconds for end of opened Status
long timeInMilis=endOpenedStatus-startOpenedStatus; //this is interwal between end and start of time (in miliseconds)
System.out.println("opened status was for "+ timeInMilis+" in miliseconds");
System.out.println("opened status was for "+reaclculateToSeconds(timeInMilis)+" in seconds");
startOpenedStatus=null;
}
}
private BigDecimal reaclculateToSeconds(long timeInMiliseconds){
BigDecimal timeInSeconds=new BigDecimal(timeInMiliseconds).divide(new BigDecimal(1000), MathContext.DECIMAL128);
return timeInSeconds.round(new MathContext(3));
}
I think your best bet would be to keep track of the current "state" (open/closed) and reset your startTime when the "state" changes. I haven't tried the following but hopefully it starts you off in the right direction.
First you'd have to define a "lastState" String variable (probably same place you define "startTime" and initialize it in your setup. If you know the initial state, set it to that. I just used "NotSet" as an example.
void setup () {
startTime = System.nanoTime();
lastState = "NotSet";
}
Then you would need a method that compare the current state to the last state and output the elapsed time if there is a state change.
private static void logElapsed (String currentState) {
if(!lastState.Equals(currentState)) {
// state has changed so output the elapsed time and set the lastState to the currentState
long estimatedTime = System.nanoTime() - startTime;
// reset the startTime to keep track of the elapsed time of the new state
startTime = System.nanoTime();
// Output how long the last state
System.out.println("Was " + lastState + " for "+ estimatedTime);
// reset the lastState to the current state
lastState = currentState;
}
}
Finally, you would just need to call it from within your if/else block.
if (matrix [3][5]== 3) {
System.out.println("Closed");
logElapsed("Closed");
}
else {
System.out.println("Opened");
logElapsed("Opened");
}
Related
In my platforming game, I have a swing timer that ticks the following method every 17 milliseconds. It is here that I run the various events that I need to run. My plan was to sleep the timer for 1 second whenever the player died.
My problem is that I don't really have a firm understanding of how to sleep a swing timer. Every example that I look at involves using a Thread which is not what I am doing. When I do the following I get a IllegalMonitorStateException error.
public void actionPerformed(ActionEvent e)
{
if (!louis.isDead)
{
if (louis.right)
{
louis.moveR();
}
if (louis.left)
{
louis.moveL();
}
if (!louis.left && !louis.right)
louis.friction();
louis.gravity();
louis.checkCol(charMap, mapX, mapY);
mapX -= louis.moveX();
mapY -= louis.moveY();
louis.checkDeath(charMap, mapX, mapY);
}
else
{
try {
time.wait(1000);
} catch (InterruptedException e1) {e1.printStackTrace();}
mapX = initMapX;
mapY = initMapY;
louis = new Player(spawnX, spawnY);
}
repaint();
}
Thanks in advance
My problem is that I don't really have a firm understanding of how to sleep a swing timer.
You don't. You don't sleep anything in Swing, not unless you want to put your entire GUI asleep. Instead why not simply record the start time, check the elapsed time with each tick, and then activate whatever code you want activated when the elapsed time is greater than your cut-off?
Not sure what you're trying to do, but perhaps something in this sort of range (code not tested)
private static final long TOTAL_DEATH_TIME = 1000L; // total time of your delay
private long deathInitTime = -1L; // start time of death throes
public void actionPerformed(ActionEvent e) {
if (!louis.isDead) {
// .... etc... unchanged from your code
} else {
// he's dead
if (deathInitTime < 0) {
// if dead but just now dead, initialize deathInitTime
deathInitTime = System.currentTimeMillis();
} else {
// he's been dead
// check how long he's been dead
long deathTime = System.currentTimeMillis() - deathInitTime;
if (deathTime > TOTAL_DEATH_TIME) {
// if he's been dead long enough, call this code
mapX = initMapX;
mapY = initMapY;
louis = new Player(spawnX, spawnY);
deathInitTime = -1L; // and re-initialize deathInitTime
}
}
}
repaint();
}
I want to see if the user completed a certain task in one second. I know that there are several ways to get time elapsed, but I am wondering what the most accurate way would be for this scenario. I want to get time elapsed ever since a certain time. For example, register a timer, and refer back to it later:
User does something
I check if user completed task in the one second timer
User does something again
I check if the user completed the task within the same one second timer that was running before. If not, make timer null.
User does something again
I check if user completed the task within one second timer. If not, make timer null.
I want to basically have one timer that runs for one second, as the user completes various tasks. After every task, I check whether or not the timer is still going. I don't want to use countdowntimer for this, as it is not accurate enough for one second. What method can I use for this?
Use System.currentTimeMillis() or System.nanoTime(), if you need a nanosecond precision. I guess, System.currentTimeMillis() precision should be enough for your case.
Record a timestamp just before starting a task, then just after completing a task and task a difference.
Check this answer for explanation which method is better suits for you.
Use System.nanoTime() if you want the highest precission. System.currentTimeMillis() should work for you too though.
This method provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes) - no guarantees are made except that the resolution is at least as good as that of currentTimeMillis().
Just implement a simple timer using either of these methods.
private static final class Timer {
private long start;
private long end;
static double toSeconds(long nanos) {
return nanos / 1000000000.0;
}
void start() {
end = -1;
start = System.nanoTime();
}
double getCurrent() {
return toSeconds(System.nanoTime() - start);
}
double stop() {
end = System.nanoTime();
return toSeconds(end - start);
}
boolean isRunning() {
return end == -1;
}
}
public static void main(String[] args) {
Timer timer = new Timer();
timer.start();
doSomething();
if (timer.getCurrent() > 1.0) {
double time = timer.stop();
System.out.println("User completed task 1 in " + time);
}
doSomething();
if (timer.isRunning() && timer.getCurrent() > 1.0) {
double time = timer.stop();
System.out.println("User completed task 1 & 2 in " + time);
}
doSomething();
if (timer.isRunning() && timer.getCurrent() > 1.0) {
double time = timer.stop();
System.out.println("User completed task 1 & 2 & 3 in " + time);
}
System.out.println("All tasks finished");
}
I have a thread that runs while a condition is false. For each second it is false, then it will add 1 second to the time, then return that time. My problem is that at the end of the code, it returns no output, that is, no integer variable is returned to output.
Note: For this program, assume that the user correctly guesses the number, and win is true.
Edit: Code execute() has been added to the while win = false
Thread thread = new Thread() {
public int run(boolean win){
int time = 0;
while(win == false) {
try {
time++;
Thread.sleep(1000);
}
catch(Exception e) {
}
}
return time;
}
};
public void execute() {
thread.start();
}
This thread continues to increase while win is false, then returns the value of time when win is true.
public void userGuessNumber() {
boolean win = false
[...] // Options Menu Code - timer should not increment for this section
while(win == false) {
execute();
if(guess == number) {
win = true;
}
[...] // Do some code
}
}
Win is true when user guesses a number correctly. That is when the thread should stop incrementing. Then below is when the method outputs the time:
public void outputInfo() {
System.out.print("The time it had taken to guess the number: ");
execute();
}
Edited Code: I have added execute() in the while loop; my logic is that I want the thread to begin counting only when the user starts guessing a number. The execute() statement in the outputInfo method, I intend to print the number generated from time when the thread was running, but I believe this could be semantically incorrect.
execute is a method that runs the thread code, but for some reason the output it empty, and returns nothing.
Instead, I want it to return the number of the time that has elapsed before win reached true.
This really isn't the proper use of a thread. Multithreading should be used for event handling or having long background processes such as a download.
You can easily just track the time by using System.currentTimeMillis(), assigning it to a variable and you'll be able to get the difference of time in milliseconds. If you want it in seconds, just divide by 1000.
Here's a snippet:
public void userGuessNumber() {
boolean win = false
[...] // Options Menu Code - timer should not increment for this section
long guessNumberStarted = System.currentTimeMillis();
int timeElapsed = 0;
while (!win) {
if (guess == number) {
win = true;
timeElapsed = (int)(System.currentTimeMillis() - guessNumberStarted) / 1000;
}
}
[...] // Do some code
}
Not only is the code shortened, you don't have any unneeded code running in the background, and you can calculate the amount of time that passed with more accuracy, given that you make the variable a double or a long.
I'd like to create MIDI clock which works basically like a normal clock. It simply ticks and counts its ticks. Now I have read quite a few times that Thread.sleep() isn't accurate at all. So correcting it every every few cycles ensures that it is stable in the long term?
My Clock Class
public class Clock implements Runnable {
long beatsPassed = 0;
double bpm = 120; // default
double beatLength; // default
boolean running = false;
Clock(int bpm) {
this.bpm = bpm;
this.beatLength = 60.0 / bpm;
this.running = true;
}
public void run() {
int beatLengthInMS = (int) (this.beatLength * 1000);
long baseTime = System.currentTimeMillis();
// long corrected = 1;
try {
while (running) {
// check delay every 9 beats
// mod == 0 lets it the first time through which causes a negative timeout
if (this.beatsPassed % 10 == 9) {
// corrected = (System.currentTimeMillis() - baseTime) - (beatLengthInMS * 9);
Thread.sleep(beatLengthInMS + ((System.currentTimeMillis() - baseTime) - (beatLengthInMS * 9)));
baseTime = System.currentTimeMillis();
} else {
Thread.sleep(beatLengthInMS);
}
this.beatsPassed++;
// System.out.println(corrected);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Now I have measured actually quite steady times. It always adds about 6-9ms.
Am I forgetting something fundamental or is my approach wrong? Also great would be if you could tell me a more performant way to this?
The simplest approach (apart from using Timer, there are AFAIK two of them in the JDK) is a method
void sleepUntil(long absoluteTime) throw InterruptedException {
while (true) {
long now = System.currentTimeMillis();
if (now >= absoluteTime) break;
Thread.sleep(absoluteTime - now);
}
}
The loop is used because of spurious wakeups (which may never occur in practice, but better safe than sorry). The absoluteTime gets computed in advance (basically, you only look at the current time at the very beginning).
I am working on a drawing application, using Java and Swing. It has a constant update loop that runs constantly, as long as a boolean variable is set to true. The loop is located inside a thread.
It works fine, but now I want the loop to only run at certain times (only when the mouse is pressed), and otherwise not run. (Thus not wasting memory for nothing).
To stop the loop, I can simply set that variable to false. But my question is, how can I restart the loop after stopping it? Setting that variable back to true will not restart the loop. What would be a good way to do this?
EDIT: My (a little simplified) loop:
public void run(){
int TICKS_PER_SECOND = 50;
int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
int MAX_FRAMESKIP = 10;
long next_game_tick = System.currentTimeMillis();
int loops;
boolean app_is_running = true;
while( app_is_running ) {
loops = 0;
while( System.currentTimeMillis() > next_game_tick && loops < MAX_FRAMESKIP) {
update();
next_game_tick += SKIP_TICKS;
loops++;
}
repaint();
}
}
Use Object.wait to suspend the thread when it isn't running. Have another thread call Object.notify to wake it up from its sleep.
To execute the thread body once every FRAME_RATE ms while being controllable by an externally defined Boolean, the run method could be structured as such:
public void run()
{
long delay;
long frameStart = System.currentTimeMillis();
// INSERT YOUR INITIALIZATION CODE HERE
try
{
while (true)
{
if (active) // Boolean defined outside of thread
{
// INSERT YOUR LOOP CODE HERE
}
frameStart += FRAME_RATE;
delay = frameStart - System.currentTimeMillis();
if (delay > 0)
{
Thread.sleep(delay);
}
}
}
catch (InterruptedException exception) {}
}
Additionally, if you want to eliminate the slight overhead of the constantly running loop (for a mostly inactive thread), the Boolean in the while loop could be replaced with a Semaphore object:
while (true)
{
semaphore.acquire(); // Semaphore defined outside thread with 1 permit
// INSERT YOUR LOOP CODE HERE
semaphore.release();
frameStart += FRAME_RATE;
delay = frameStart - System.currentTimeMillis();
if (delay > 0)
{
Thread.sleep(delay);
}
}
To stop the loop externally use semaphore.acquire(); to restart it use semaphore.release().