Limit uses of a function in a period of time (android) - java

I want to limit the calls to a function within one day.
The problem is I'm a bit confused of how to use the Date and Calendar classes...
private int usesLeft //Set every day to the number of uses
private void function() {
if(usesLeft > 0) {
//Function's body...
}
usesLeft--;
}
I need to find out when a new day starts in order to reset the usesLeft variable.

Well I found a solution...
The better side of this solution is that the user can't "cheat" because then he'll lose activity days (If my analysis of the code behavior is right).
if(lastDayActive < (int)Math.floor(System.currentTimeMillis()/86400000)) {
usesLeft = 100;
//Initializes the day value
lastDayActive = (int)Math.floor(System.currentTimeMillis()/86400000);
}
If there's any way to prevent the user from manually changing the date and therefore gaining more uses I'd really like to hear about it.

Related

Java, TDD True when not equals?

for some reason while testing this method during a lesson in class we found an issue we couldn't understand. When writing System.out.println(); for some reason it passes?. Can someone explain why this is happening?
public class Zones {
public ZoneId getZoneId(String input) {
if (input.equalsIgnoreCase("Stockholm")) {
return ZoneId.of("Europe/Stockholm");
}
else if (input.equalsIgnoreCase("Shanghai")) {
return ZoneId.of("Asia/Shanghai");
} else if (input.equalsIgnoreCase("Toronto")) {
return ZoneId.of("America/Toronto");
}
else if (input.equalsIgnoreCase("Hamburg")) {
return ZoneId.of("Europe/Berlin");
}
else return null;
}
public LocalDateTime getZoneTime(ZoneId zoneId) {
LocalDateTime lt = LocalDateTime.now(zoneId);
return lt;
}
}
private Zones z = new Zones();
#Test
public void getZoneTimeTest () {
System.out.println(z.getZoneTime(zIDToronto).getNano() );
System.out.println(LocalDateTime.now(zIDToronto).getNano() );
assertTrue(z.getZoneTime(zIDToronto).getNano() == LocalDateTime.now(zIDToronto).getNano());
}
Finally had some time to investigate this deeper.
I started experimenting and found after a while, that is in fact not the presence of System.out.println that influenced the result, but the fact that you instantiate 2 LocalDateTime instances before it.
Digging deeper, into the code of LocalDateTime, and the SystemClock (to which it delegates), I found that the sub milli precision was achieved by a call to the native call jdk.internal.misc.VM#getNanoTimeAdjustment.
That last call is OS specific. I experimented a bit with it and found that it doesn't return values linearly, as it gets called in a loop (assuming my loop ran fairly regularly).
So I decided to run some code to map the returned nano values.
I made this sampling code :
Clock clock = Clock.systemDefaultZone();
int samples = 1_000;
LocalDateTime[] instants = new LocalDateTime[samples];
int k = 0;
for (int i = 0; i < samples; i++) {
instants[i] = LocalDateTime.now(clock);
for (int j = 0; j < 10000; j++) {
k = j % 2;
}
}
wrote the values to a file, and then mapped the nano differences vs the first value into a graph :
As you can see this graph (of 1000 values) makes intermittent leaps. This is obviously in part due to precision restriction of the underlying system. But wat struck me is that the first two values consistently were different. It's as if upon regular access the OS system starts caching the value for a while (possibly to avoid strain on the system resources).
But the result it seems is that you set yourself up for getting the same value on the 3rd and 4th call (unless enough time has passed).
That would explain why your test passes with, and fails without those prior instantiations.
As an aside, for unit tests you don't want to rely on a system clock. Make sure your business code gets it's time from an injected Clock instance. Then you can inject a custom clock for tests, and test whether your code will run on a DST changeover date or on a leap day without having to wait several months.
The test involves race condition and passes (sometimes) because of the timing and adding statements changes the timing and therefore test outcome.
The condition that is checked in the assertion basically is the equality of the nanoseconds parts of two date-times taken one after another in succession.
Given that by default System.currentTimeMillis() is used internally by LocalDateTime.now and it has at most millisecond precision the check will succeed if the second sequence of invocations to get the number of nanoseconds is quick enough (that is the actual sequence of calls leading to invocation of System.currentTimeMillis finished within the same millisecond as the first).
When you invoke the functions used to obtain the value of nanosecond before the actual assertion the corresponding classes are loaded, the code of corresponding methods get into the CPU caches etc. This makes the second pair of calls to get the number of nanoseconds run much quicker.

JFreeChart TimeSeries array exception

this is my first question here ever, and I would appreciate if you can help me.
Since the code I have is way too large to post here, I'll try to describe what my problem is in short.
So, I have made TimeSeries array within my class and array list from where I get values for time series:
private TimeSeries[] seriesArray = new TimeSeries[10];
ArrayList<TempClass> valuesFromArrayList = new ArrayList<>();
I need to make TimeSeries array, because I want to be able to show multiple timeseries graphs. Using only one TimeSeries and addOrUpdate method isn't what I want because then values get mixed when I create more graphs. So, I add values like this:
for(int i = 0; i < valuesFromArrayList.size(); i++)
{
TempClass obj = (TempClass) valuesFromArrayList.get(i);
int timeStamp = obj.getTimeStamp();
int hrsDiff;
int minsDiff;
int secsDiff;
hrsDiff = timeStamp / 3600;
timeStamp = timeStamp - hrsDiff * 3600;
minsDiff = timeStamp / 60;
timeStamp = timeStamp - minsDiff * 60;
secsDiff = timeStamp;
seriesArray[Integer.parseInt(comboBoxValue) - 1].add(new Second(secsDiff, minsDiff, hrsDiff, day, month, year), Math.abs(obj.getValue()));
}
What this part of code does is that it reads values and timestamps from ArrayList I created. There is comboBox where user can choose which timeSeries array index will be in graph. So, if user chooses value 9 from comboBox, timeSeries from index 8 will be chosen and plotted on graph. TimeStamp is simply number of seconds that passed since 00:00:00 at day when values were taken.
TempClass is defined as:
class TempClass
{
private int timeStamp;
private double value;
public TempClass(int a, double b)
{
timeStamp = a;
value = b;
}
public int getTimeStamp()
{
return timeStamp;
}
public double getValue()
{
return value;
}
public void setValue(double val)
{
value = val;
}
}
The problem I have is that when I try to make second (2nd) graph, that is another index of TimeSeries array, I get message:
You are attempting to add an observation for the time period Thu Apr 30 00:00:00 CEST 2015 but the series already contains an observation for that time period. Duplicates are not permitted. Try using the addOrUpdate() method.
I don't want to use addOrUpdate method, I need add method. Values in ArrayList I use to put values into timeSeries are fine, I am 300% sure. I already checked input from comboBox value and it gives correct values.
I have no explanation other that for some reason, even if array index is changed, data I want to write into the series goes to the old series (that is, to the series at the old index). In other words, it seems like even if I change index of array, it keeps writing into the old array index!
It's like equivalent to this (I know this sounds crazy but that is basically what I am getting):
int[] array = new int[5];
array[0] = 1;
array[1] = 2;
System.out.println(array[0]);
And the output I get is
2
This is something I have never heard of before, and I have code similar to this I wrote here in two other places, and in that two places it goes just fine, but in this third place I keep getting that exception.
Is this some kind of bug in JVM?
Does somebody know what this could be?
I don't know too much about TimeSeries, but after skimming the docs about it it says:
"The time series will ensure that (a) all data items have the same
type of period (for example, Day) and (b) that each period appears at
most one time in the series."
Link to Docs
I'm guessing the error is pretty straight forward or a misuse of TimeSeries. It looks like you are simply adding a duplicate date and that the constraints of TimeSeries don't allow that.
You may wish to consider writing a custom class that has the functionality you want. Yet again, I don't know much about TimeSeries, but I hope this helped a little.
Your for loop will always overwrite the value with an index of 0 on seriesArray.
What I mean is, the first time it will write to [0]
The second it will write to [0] then [1]
Is this intended?
I have not looked at the docs too much, but the message says 'the series already contains an observation for that time period.' I think that loop is not doing what you want it to do.

Combining Human Time with Computer Time into Synthetic Time

I am trying to write a high data rate UDP streaming interface simulator/tester in Java 8 to a realtime machine that has a very accurate time processor card. Every message has a time field in it and this field is in microseconds resolution. The interface relies on the high resolution time processor for packet ordering. The interface relies on the high precision time card which I don't have and need to simulate out of the equation. I figured I could get away with using something like this:
TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
It does work but after running for extended periods of time I found UDP bites me because I send a couple hundred packets out of order with the same exact time stamp and the other side of the interface can't tell that the packets it received were out of order. The interface is tolerant of this to an extent but this isn't really an issue on the real system with the high precision clocks.
To mitigate this I have added a sense of synthetic microseconds to my currentTimeMillis() as follows:
class TimeFactory {
private long prev;
private long incr;
public long now() {
final long now = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
long synthNow = now;
if(now == prev) {
if(incr < 999) {
incr += 1;
}
synthNow += incr;
} else {
incr = 0;
}
prev = now;
return synthNow;
}
}
Has anyone ever dealt with synthetic time like this? Is there any other way to tighten this code up or even a better way to handle this (using nanoTime somehow)? If I ever did send more then 999 packets would it be safe to increment into the milliseconds range (ie: increment + 1000 or more)? It looks like I am getting around ~10-15ms difference between currentTimeMillis() calls but I'm sure this is very system dependent.
In case anyone is interested here is what I ended up with to work around the lack of a high resolution system clock. It will give me a synthetic microseconds counter that increments until either System.currentTimeMillis() returns an updated value or you have called this 999 times. In practice I have only seen a maximum of ~500 increments. It doesn't look like I will have worry about spilling into the millisecond range.
I'm still open to other more realistic result alternatives.
public class SyntheticMicrosClock extends Clock {
private final ZoneId zone;
private long prev;
private long incr;
SyntheticMicrosClock (ZoneId zone) {
this.zone = zone;
}
#Override
public ZoneId getZone() {
return zone;
}
#Override
public Clock withZone(ZoneId zone) {
if (zone.equals(this.zone)) { // intentional NPE
return this;
}
return new SyntheticMicrosClock(zone);
}
public long micros() {
final long now = TimeUnit.MILLISECONDS.toMicros(millis());
long synthNow = now;
if(now == prev) {
if(incr < 999) {
incr += 1;
}
synthNow += incr;
} else {
incr = 0;
}
prev = now;
return synthNow;
}
#Override
public long millis() {
return System.currentTimeMillis();
}
#Override
public Instant instant() {
return Instant.ofEpochSecond(0, micros());
}
}
To use it I inject my synthetic Clock where I need it. Ex:
Clock synthClock = Inject or new SynthClock(ZoneOffset.UTC);
Instant.now(synthClock);
Do you need a timestamp or just a high resolution increasing number that it time based? If so, you might be able to use System.nanoTime.
There were issues with this call in early JVM's/OS' but they seem to have been addressed (see first answer here).
Of course there's that odd chance that it might loop around on you. Don't know what kind of flexibility you have with your protocol, but there should be ways to deal with that.
Building on what #Bill suggested, you have 200+ years of resolution with nanoTime, so why not store nanoTime on init, currentTimeMillis on init, then add the difference of nanoTime and initNanoTime to initCurrentTimeMillis to get an augmented, high-precision timestamp? Once you detect clock skew between this augmented clock and the real one over 100ms, or so, you can reinit.

Checking which date comes first?

It seems logical that there should be some simple method to check which DatePicker object comes first but I can't find done.
// so if you had two objects
final DatePicker start_datepicker = (DatePicker)findViewById(R.id.DatePickerStart);
final DatePicker end_datepicker = (DatePicker)findViewById(R.id.DatePickerEnd);
// I was thinking something along the lines of:
if (end_datepicker > start_datepicker) {
// something
}
// or is there something like
if (end_datepicker.isLarger(start_datepicker)) {
// Something
}
Is this possible or does anyone know of something simple along these lines to compare to dates?
A DatePicker is a UI widget for displaying a date. You don't set it by assignment (as in your code) but by calling it's init method. Typically you would then track the date using an OnDateChangedListener. Nevertheless, you can compare the current dates displayed on two such widgets with something like this:
/** Returns a number <0, 0, or >0 when dp1 displays a date <, =, or > dp2. */
public int compare(DatePicker dp1, DatePicker dp2) {
int compare = dp1.getYear() - dp2.getYear();
if (compare == 0) {
compare = dp1.getMonth() - dp2.getMonth();
if (compare == 0) {
compare = dp1.getDay() - dp2.getDay();
}
}
return compare;
}
You should take the resulting values from the date pickers and convert them to Date objects which will then allow you to easily compare the values rather than going the route of writing your own Comparator that relies on the UI component.
I actually wrote a Java class specifically to handle this situation for Android. Feel free to use it and include it in your app! It's documented, as well.
Date has before() and after() methods.. just for that.

Programming exercise?

I got this exercise, is not a homework, I just trying to solve:
We manage a farm with horses that have
to work on the field.
A horse has
a name,
a maximum amount of
working hours per week,
the amount
of hours actually worked and
a field to indicate if she is lazy or
hard-working.
All the attributes of the Horse class
are private and they have no setters.
Initial values are passed through the
constructor.
The Horse class has a method to add
one hour of actual work. That method
is called every hour (that the horse
works). At the begin of the next week,
we reset that counter to 0, by calling
another method taking no parameter.
A lazy horse cannot work more than 34
hours/week, while a hard-working horse
can work up to 80 hours.
Code a Horse class that is shielded
against wrong working hours data.
Your main method will create an horse
and call its methods, but the data
must never be corrupted, ie. the
working hour limits must be respected.
For example, a lazy horse's maximum
hours cannot be set above 34 and the
number of hours worked cannot be
greater than the maximum.
If the Horse class detects an attempts
to set incorrect data, the data
remains unchanged (and you print a
message to help you debugging).
Example of correct data:
Name: "Blacky"
lazy: no
max hours / week = 70
actual hours this week = 61
Name: "Sultan"
lazy: yes
max hours / week = 30
actual hours this week = 1
Example of corrupted data (your code should make such a situation impossible to reach)
Name: "Georges"
lazy: yes
max hours / week = 50 (wrong because lazy horses work max 34h/week)
actual hours this week = 51 (wrong because 51 > 50).
This is my code:
public class Horse {
private String name;
private int maximumAmount;
private int amountWorked;
private boolean isLazy;
public Horse(String name, int maximumAmount, int amountWorked, boolean lasyOrHardworking) {
this.name = name;
this.maximumAmount = maximumAmount;
this.amountWorked = amountWorked;
this.isLazy = lasyOrHardworking;
}
void everyHour(){
amountWorked = amountWorked + 1;
System.out.println(amountWorked);
if((isLazy == true)&&(amountWorked <= 34)){
resetToZero();
}
if((isLazy == false)&&(amountWorked <= 80)){
resetToZero();
}
}
void resetToZero(){
this.amountWorked = 0;
}
}
and my main class
public class MainHorse {
public static void main(String args[]){
Horse one = new Horse("Blacky", 34,35,true);
one.everyHour();
}
}
my question is how can I get that my method everyhour do the reset method, and in general, what is wrong in my code?
I hoper you can help me
My question is how can I get that my
method every hour do the reset method,
and in general, what is wrong in my
code?
Try to come up with something with java.util.Timer
Minor details:
Typos and spelling inconsistencies will come back to bite you someday (less likely in Java than in languages that do not require explicit declaration), you should stick to one correct spelling of the word "lazy".
this.isLazy = lasyOrHardworking;
Why not use isLazy in the parameter as well, instead of lasyOrHardworking
this.isLazy = isLazy;
I think bool == true isn't adding any value, this looks better to me:
if(isLazy && (amountWorked <= 34))
I think what you are doing wrong is calling resetToZero() from inside the everyHour() function.
I would have every hour return a bool to indicate success or failure. If failure, it doesn't increment the horse's amount worked, but prints the debug message. The main code could then check to see if it is violating the horses limits. The main code would also call resetToZero when the week ended.
You're not supposed to go back to zero, just not to increase the hoursworked. Also, if this isn't homework, you have some freedom, so I would not have independent variables for max hours and lazy - that just gives you an opportunity to get them out of sync. I would use named constants for maxLazyhours and maxHardworkinghours.
Then have a function called IncrementHours that just says
if (lazy && hours < maxLazyhours) || hours < maxHardworkinghours)
hours++;
It's simpler, right?

Categories

Resources