Is it possible to determine wether two rigth-unbounded intervals (intervals with one boundary at infinity) overlap or not?
I've tried this (and other similar variations):
Instant now = new Instant(new Date().getTime());
Interval i2 = new Interval(now, (ReadableInstant) null);
Interval i1 = new Interval(now, (ReadableInstant) null);
boolean overlapping = i2.overlaps(i1);
But according to the docs, using null as a second parameter means "now" instead of "infinity".
EDIT: I've found this answer in the mailing list, so it seems to be impossible with Joda. I am now looking for alternative implementations.
If both intervals start at t = -∞ , or if both intervals end at t = +∞, they will always overlap, regardless of the start date.
If interval A starts at t = -∞ and interval B ends at t = +∞, they overlap iff
A.start > B.start.
Hacky solution:
/**
* Checks if two (optionally) unbounded intervals overlap each other.
* #param aBeginn
* #param aEnde
* #param bBeginn
* #param bEnde
* #return
*/
public boolean checkIfOverlap(LocalDate aBeginn,LocalDate aEnde, LocalDate bBeginn,LocalDate bEnde){
if(aBeginn == null){
//set the date to the past if null
aBeginn = LocalDate.now().minusYears(300);
}
if(aEnde == null){
aEnde = LocalDate.now().plusYears(300);
}
if(bBeginn == null){
bBeginn = LocalDate.now().minusYears(300);
}
if(bEnde == null){
bEnde = LocalDate.now().plusYears(300);
}
if(aBeginn != null && aEnde != null && bBeginn != null && bEnde != null){
Interval intervalA = new Interval(aBeginn.toDateTimeAtStartOfDay(),aEnde.toDateTimeAtStartOfDay());
Interval intervalB = new Interval(bBeginn.toDateTimeAtStartOfDay(),bEnde.toDateTimeAtStartOfDay());
if(intervalA.overlaps(intervalB)){
return true;
}
} else{
return false;
}
return false;
}
I'd recommend using a Range<DateTime> (from Guava), which should provide all the construction options and comparison functions you need.
Range<DateTime> r1= Range.atLeast(DateTime.now());
Range<DateTime> r2 = Range.atLeast(DateTime.now());
boolean overlap = r1.isConnected(r2) && !r1.intersection(r2).isEmpty();
Related
Well, am working on a java project which requires input from the user. I realised that if the user press the backspace when there are no characters in the field, a window warning sound is heard. How can I stop this please. My system is windows 10 if at all the behavior may be different on different platforms. Thank you.
behavior may be different on different platforms.
Yes, the behaviour can be different because it is controlled by the LAF, so you should not really be changing it.
But to understand how Swing works you need to understand that Swing uses an Action provided by the DefaultEditorKit to provide the editing functions of text components.
Following is the code for the current "delete previous character" Action (taken from the DefaultEditKit):
/*
* Deletes the character of content that precedes the
* current caret position.
* #see DefaultEditorKit#deletePrevCharAction
* #see DefaultEditorKit#getActions
*/
static class DeletePrevCharAction extends TextAction {
/**
* Creates this object with the appropriate identifier.
*/
DeletePrevCharAction() {
super(DefaultEditorKit.deletePrevCharAction);
}
/**
* The operation to perform when this action is triggered.
*
* #param e the action event
*/
public void actionPerformed(ActionEvent e) {
JTextComponent target = getTextComponent(e);
boolean beep = true;
if ((target != null) && (target.isEditable())) {
try {
Document doc = target.getDocument();
Caret caret = target.getCaret();
int dot = caret.getDot();
int mark = caret.getMark();
if (dot != mark) {
doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
beep = false;
} else if (dot > 0) {
int delChars = 1;
if (dot > 1) {
String dotChars = doc.getText(dot - 2, 2);
char c0 = dotChars.charAt(0);
char c1 = dotChars.charAt(1);
if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
c1 >= '\uDC00' && c1 <= '\uDFFF') {
delChars = 2;
}
}
doc.remove(dot - delChars, delChars);
beep = false;
}
} catch (BadLocationException bl) {
}
}
if (beep) {
UIManager.getLookAndFeel().provideErrorFeedback(target);
}
}
}
If you don't like the beep then you would need to create your own custom Action to remove the beep sound. (ie. don't provide the error feedback). Once you customize the Action you can than change a single text field using:
textField.getActionMap().put(DefaultEditorKit.deletePrevCharAction, new MyDeletePrevCharAction());
Or you can change all text fields using:
ActionMap am = (ActionMap)UIManager.get("TextField.actionMap");
am.put(DefaultEditorKit.deletePrevCharAction, new MyDeletePrevCharAction());
I found recently the default renderable sort function in LibGDX wasn't quite up to my needs. (see; Draw order changes strangely as camera moves? )
Essentially a few objects rendered in front when they should render behind.
Fortunately, the renderables in question always have a guarantied relationship. The objects are attached to eachother so when one moves the other moves. One object can be seen as being literally "pinned" to the other, so always in front.
This gave me the idea that if I specified a "z-index" (int) and "groupname" (String) for each object, I could manually take over the draw order, and for things with the same groupname, ensure they are positioned next to eachother in the list, in the order specified by the z-index. (low to high)
//For example an array of renderables like
0."testgroup2",11
1."testgroup",20
2."testgroup2",10
3.(no zindex attribute)
4."testgroup",50
//Should sort to become
0."testgroup",20
1."testgroup",50
2.(no zindex attribute)
3."testgroup2",10
4."testgroup2",11
// assuming the object2 in testgroup2 are closer to the camera, the one without a index second closest, and the rest furthest<br>
//(It is assumed that things within the same group wont be drastically different distances)
I implemented a sort system in libgdx to do this as followed;
/**
* The goal of this sorter is to sort the renderables the same way LibGDX would do normally (in DefaultRenderableSorter)<br>
* except if they have a ZIndex Attribute.<br>
* A Zindex attribute provides a groupname string and a number.<br>
* Renderables with the attribute are placed next to others of the same group, with the order within the group determined by the number<br>
*
* For example an array of renderables like;<br><br>
* 0."testgroup",20<br>
* 1."testgroup2",10<br>
* 2.(no zindex attribute)<br>
* 3."testgroup",50<br>
* <br>Should become;<br><br>
* 0."testgroup",20<br>
* 1."testgroup",50<br>
* 2.(no zindex attribute)<br>
* 3."testgroup2",10<br>
* <br>
* assuming the object in testgroup2 is closer to the camera, the one without a index second closest, and the rest furthest<br>
* (It is assumed that things within the same group wont be drastically different distances)<br>
*
* #param camera - the camera in use to determine normal sort order when we cant place in a existing group
* #param resultList - an array of renderables to change the order of
*/
private void customSorter(Camera camera, Array<Renderable> resultList) {
//make a copy of the list to sort. (This is probably a bad start)
Array <Renderable> renderables = new Array <Renderable> (resultList);
//we work by clearing and rebuilding the Renderables array (probably not a good method)
resultList.clear();
//loop over the copy we made
for (Renderable o1 : renderables) {
//depending of if the Renderable as a ZIndexAttribute or not, we sort it differently
//if it has one we do the following....
if (o1.material.has(ZIndexAttribute.ID)){
//get the index and index group name of it.
int o1Index = ((ZIndexAttribute)o1.material.get(ZIndexAttribute.ID)).zIndex;
String o1GroupName = ((ZIndexAttribute)o1.material.get(ZIndexAttribute.ID)).group;
//setup some variables
boolean placementFound = false; //Determines if a placement was found for this renderable (this happens if it comes across another with the same groupname)
int defaultPosition = -1; //if it doesn't find another renderable with the same groupname, this will be its position in the list. Consider this the "natural" position based on distance from camera
//start looping over all objects so far in the results (urg, told you this was probably not a good method)
for (int i = 0; i < resultList.size; i++) {
//first get the renderable and its ZIndexAttribute (null if none found)
Renderable o2 = resultList.get(i);
ZIndexAttribute o2szindex = ((ZIndexAttribute)o2.material.get(ZIndexAttribute.ID));
if (o2szindex!=null){
//if the renderable we are comparing too has a zindex, then we get its information
int o2index = o2szindex.zIndex;
String o2groupname = o2szindex.group;
//if its in the same group as o1, then we start the processing of placing them nexto eachother
if (o2groupname.equals(o1GroupName)){
//we either place it in front or behind based on zindex
if (o1Index<o2index){
//if lower z-index then behind it
resultList.insert(i, o1);
placementFound = true;
break;
}
if (o1Index>o2index){
//if higher z-index then it should go in front UNLESS there is another of this group already there too
//in which case we just continue (which will cause this to fire again on the next renderable in the inner loop)
if (resultList.size>(i+1)){
Renderable o3 = resultList.get(i+1);
ZIndexAttribute o3szindex = ((ZIndexAttribute)o3.material.get(ZIndexAttribute.ID));
if (o3szindex!=null){
String o3groupname = o3szindex.group;
if (o3groupname!=null && o3groupname.equals(o1GroupName)){
//the next element is also a renderable with the same groupname, so we loop and test that one instead
continue;
}
}
}
// Gdx.app.log("zindex", "__..placeing at:"+(i+1));
//else we place after the current one
resultList.insert(i+1, o1);
placementFound = true;
break;
}
}
}
//if no matching groupname found we need to work out a default placement.
int placement = normalcompare(o1, o2); //normal compare is the compare function in DefaultRenderableSorter.
if (placement>0){
//after then we skip
//(we are waiting till we are either under something or at the end
} else {
//if placement is before, then we remember this position as the default (but keep looking as there still might be matching groupname, which should take priority)
defaultPosition = i;
//break; //break out the loop
}
}
//if we have checked all the renderables positioned in the results list, and none were found with matching groupname
//then we use the defaultposition to insert it
if (!placementFound){
//Gdx.app.log("zindex", "__no placement found using default which is:"+defaultPosition);
if (defaultPosition>-1){
resultList.insert(defaultPosition, o1);
} else {
resultList.add(o1);
}
}
continue;
}
//...(breath out)...
//ok NOW we do placement for things that have no got a ZIndexSpecified
boolean placementFound = false;
//again, loop over all the elements in results
for (int i = 0; i < resultList.size; i++) {
Renderable o2 = resultList.get(i);
//if not we compare by default to place before/after
int placement = normalcompare(o1, o2);
if (placement>0){
//after then we skip
//(we are waiting till we are either under something or at the end)
continue;
} else {
//before
resultList.insert(i, o1);
placementFound = true;
break; //break out the loop
}
}
//if no placement found we go at the end by default
if (!placementFound){
resultList.add(o1);
};
} //go back to check the next element in the incomeing list of renderables (that is, the copy we made at the start)
//done
}
//Copy of the default sorters compare function
//;
private Camera camera;
private final Vector3 tmpV1 = new Vector3();
private final Vector3 tmpV2 = new Vector3();
public int normalcompare (final Renderable o1, final Renderable o2) {
final boolean b1 = o1.material.has(BlendingAttribute.Type) && ((BlendingAttribute)o1.material.get(BlendingAttribute.Type)).blended;
final boolean b2 = o2.material.has(BlendingAttribute.Type) && ((BlendingAttribute)o2.material.get(BlendingAttribute.Type)).blended;
if (b1 != b2) return b1 ? 1 : -1;
// FIXME implement better sorting algorithm
// final boolean same = o1.shader == o2.shader && o1.mesh == o2.mesh && (o1.lights == null) == (o2.lights == null) &&
// o1.material.equals(o2.material);
o1.worldTransform.getTranslation(tmpV1);
o2.worldTransform.getTranslation(tmpV2);
final float dst = (int)(1000f * camera.position.dst2(tmpV1)) - (int)(1000f * camera.position.dst2(tmpV2));
final int result = dst < 0 ? -1 : (dst > 0 ? 1 : 0);
return b1 ? -result : result;
}
As far as I can tell my customSorter function produces the order I want - the renderables now look like they are drawn in the right order.
However, this also seems like a hackjob, and I am sure my sorting algorithm is horrendously inefficient.
I would like advice on how to either;
a) Improve my own algorithm, especially in regards to any quirks to bare in mind when doing cross-platform LibGDX development (ie, array types, memory management in regards to android/web etc)
b) Alternative more efficient solutions having a similar "z index override" of the normal draw-order sorting.
Notes;
. The grouping is necessary. This is because while things are firmly stuck relatively to eachother within a group, groups themselves can also move about in front/behind eachother. (but not between). This makes it tricky to do a "global" override of the draw order, rather then a local one per group.
. If it helps, I can add/change the zindexattribute object in any way.
. I am thinking somehow "pre-storeing" each group of objects in a array could help things, but not 100% sure how.
First of all do never copy a list if not needed. The list with renderables could be really huge since it also could contain resources. Copying will be very very slow. If you need something local and you need performance try to make it final since it can improve the performance.
So a simple approach would be the default sorting of Java. You need to implement a Comperator for your class for example the Class with z index could look like this:
public class MyRenderable {
private float z_index;
public MyRenderable(float i)
{
z_index = i;
}
public float getZ_index() {
return z_index;
}
public void setZ_index(float z_index) {
this.z_index = z_index;
}
}
If you want a faster sort since your list wont change that much on runtime you could implement a insertion sort since it does a faster job if the list is kind of presorted. If it is not pre sorted it does take longer but in general it should only be the first sort call where it is alot disordered in your case.
private void sortList(ArrayList<MyRenderable> array) {
// double starttime = System.nanoTime();
for (int i = 1; i < array.size(); i++) {
final MyRenderable temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).getZ_index() < temp.getZ_index()) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
// System.out.println("Time taken: " + (System.nanoTime() - starttime));
}
To use this method you simply call it with your Array
sortList(renderbales);
In your case you need to take care of the ones that do not have a Z index. Maybe you could give them a 0 since they'll get sorted at the right position(i guess). Else you can use the given methods in z case and the regular in no z case as you do already.
After the conversation in the comments. I dont think it is a good idea to push everything into one list. It's hard to sort and would be very slow. A better approach would be a list of groups. Since you want to have groups, programm a group. Do not use String names, use IDs or types (way more easy to sort and it doesn't really matter). So a simple group would be this:
public class Group{
//think about privates and getters or methods to add things which also checks some conditions and so on
public int groupType;
public ArrayList<MyRenderable> renderables;
}
And now all your groups into a list. (this contains all your renderbales then)
ArrayList<Group> allRenderables = new ArrayList<>();
Last but not least sort the groups and sort the renderables. Since i dont think that your group ids/names will change on runtime, sort them once or even use a SortedSet instead of a ArrayList. But basically the whole sorting looks like this:
for(Group g: allRenderables)
sortRenderables(g.renderables); //now every group is sorted
//now sort by group names
sortGroup(allRenderables);
With the following insertionsorts as shown above
public static void sortRenderables(ArrayList<MyRenderable> array) {
for (int i = 1; i < array.size(); i++) {
final MyRenderable temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).getZ_index() < temp.getZ_index()) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
}
public static void sortGroup(ArrayList<Group> array) {
for (int i = 1; i < array.size(); i++) {
final Group temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).groupType < temp.groupType) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
}
I am attempting to get the device's current battery level with the following:
Intent batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
Log.i(LOG_FILTER, "Battery level = " + (level*100)/scale);
// error check values
if (level == -1 || scale == -1) {
return -1;
} else {
return (level * 100) / scale;
}
The code seems to work and has never failed me, but I am getting a warning:
Method invocation 'batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)' may produce 'java.lang.NullPointerException'
This may never actually affect my application but as there is an end product depending on it, I am wondering, how might I accommodate this potential issue?
Is there a way to reorganize the above to achieve the same result (obtaining the battery's current state of charge)?
The Javadoc for registerReceiver states:
* #return The first sticky intent found that matches <var>filter</var>,
* or null if there are none.
So there is the potential that this will return you a null event. You already handle the case where the values are invalid ((level == -1 || scale == -1)), so I would recommend that you just check whether the intent is null, and return that value early:
if (batteryIntent == null) {
return -1;
}
I would throw a try/catch around it because you know it could throw the error, and then you can handle it appropriately if/when it ever does occur.
try {
//your code here
} catch (NullPointerException e) {
//handle the error here, maybe return -1?
}
I have list of Joda-Time intervals
List<Interval> intervals = new ArrayList<Interval>();
and another Joda-Time interval (search time interval), like on the picture below.
I need to write Java function that finds the holes in time and returns List<Interval> with the red intervals.
Building up on fge's response - the following version actually handles both cases (when the big interval is larger than the extremes of the intervals being searched over + the case when the big interval is in fact smaller ... or smaller on one side)
you can see the full code along with the tests at https://github.com/erfangc/JodaTimeGapFinder.git
public class DateTimeGapFinder {
/**
* Finds gaps on the time line between a list of existing {#link Interval}
* and a search {#link Interval}
*
* #param existingIntervals
* #param searchInterval
* #return The list of gaps
*/
public List<Interval> findGaps(List<Interval> existingIntervals, Interval searchInterval) {
List<Interval> gaps = new ArrayList<Interval>();
DateTime searchStart = searchInterval.getStart();
DateTime searchEnd = searchInterval.getEnd();
if (hasNoOverlap(existingIntervals, searchInterval, searchStart, searchEnd)) {
gaps.add(searchInterval);
return gaps;
}
// create a sub-list that excludes interval which does not overlap with
// searchInterval
List<Interval> subExistingList = removeNoneOverlappingIntervals(existingIntervals, searchInterval);
DateTime subEarliestStart = subExistingList.get(0).getStart();
DateTime subLatestStop = subExistingList.get(subExistingList.size() - 1).getEnd();
// in case the searchInterval is wider than the union of the existing
// include searchInterval.start => earliestExisting.start
if (searchStart.isBefore(subEarliestStart)) {
gaps.add(new Interval(searchStart, subEarliestStart));
}
// get all the gaps in the existing list
gaps.addAll(getExistingIntervalGaps(subExistingList));
// include latestExisting.stop => searchInterval.stop
if (searchEnd.isAfter(subLatestStop)) {
gaps.add(new Interval(subLatestStop, searchEnd));
}
return gaps;
}
private List<Interval> getExistingIntervalGaps(List<Interval> existingList) {
List<Interval> gaps = new ArrayList<Interval>();
Interval current = existingList.get(0);
for (int i = 1; i < existingList.size(); i++) {
Interval next = existingList.get(i);
Interval gap = current.gap(next);
if (gap != null)
gaps.add(gap);
current = next;
}
return gaps;
}
private List<Interval> removeNoneOverlappingIntervals(List<Interval> existingIntervals, Interval searchInterval) {
List<Interval> subExistingList = new ArrayList<Interval>();
for (Interval interval : existingIntervals) {
if (interval.overlaps(searchInterval)) {
subExistingList.add(interval);
}
}
return subExistingList;
}
private boolean hasNoOverlap(List<Interval> existingIntervals, Interval searchInterval, DateTime searchStart, DateTime searchEnd) {
DateTime earliestStart = existingIntervals.get(0).getStart();
DateTime latestStop = existingIntervals.get(existingIntervals.size() - 1).getEnd();
// return the entire search interval if it does not overlap with
// existing at all
if (searchEnd.isBefore(earliestStart) || searchStart.isAfter(latestStop)) {
return true;
}
return false;
}
}
A quick look at the Interval API gives this (UNTESTED):
// SUPPOSED: the big interval is "bigInterval"; the list is "intervals"
// Intervals returned
List<Interval> ret = new ArrayList<>();
Interval gap, current, next;
// First, compute the gaps between the elements in the list
current = intervals.get(0);
for (int i = 1; i < intervals.size(); i++) {
next = intervals.get(i);
gap = current.gap(next);
if (gap != null)
ret.add(gap);
current = next;
}
// Now, compute the time difference between the starting time of the first interval
// and the starting time of the "big" interval; add it at the beginning
ReadableInstant start, end;
start = bigInterval.getStart();
end = intervals.get(0).getStart();
if (start.isBefore(end))
ret.add(0, new Interval(start, end));
//
// finally, append the time difference between the ending time of the last interval
// and the ending time of the "big" interval
// next still contains the last interval
start = next.getEnd();
end = bigInterval.getEnd();
if (start.isBefore(end))
ret.add(new Interval(start, end));
return ret;
The answer by fge seems to be correct, though I've not run that untested code.
The term "gap" seems to be a more common term for what you are calling "holes".
See this answer by Katja Christiansen, which makes good use of the gap method on the Interval class.
Interval gapInterval = interval_X.gap( interval_Y );
// … Test for null to see whether or a gap exists.
If there is a non-zero duration between them, you get a new Interval object returned. If the intervals overlap or abut, then null is returned. Note that the Interval class also offers the methods overlap and abuts if you are interested in those particular conditions.
Of course your collection of Interval objects must be sorted for this to work.
I want to do an operation like this : if the given float numbers are like 1.0 , 2.0 , 3.0 , I want to save them to database as integer (1,2,3 ), if they are like 1.1 , 2.1 , ,3.44 , I save them as float. what's the best solution for this problem using java ? The corresponding field in database is type of varchar.
Just try int i = (int) f;.
EDIT : I see the point in the question. This code might work :
int i = (int) f;
String valToStore = (i == f) ? String.valueOf(i) : String.valueOf(f);
String result = "0";
if (floatVar == Math.floor(floatVar)) {
result = Integer.toString((int) floatVar);
} else {
result = Float.toString(floatVar);
}
The if-clause checks whether the number is a whole number - i.e. if it is equal to the result of rounding it down to the closest whole value.
But this is very odd requirement indeed, and perhaps you should reconsider the need for such a thing.
Seems like you want to save Floats with no trailing numbers as Integers, while saving those with significant trailing numbers as Floats. I would rather just save it all as Float to the DB, but it's your question so here's my answer:
/**
* Method to determine if trailing numbers are significant or not. Significant
* here means larger than 0
*
* #param fFloat
* #return
*/
public static boolean isTrailingSignificant(Float fFloat)
{
int iConvertedFloat = fFloat.intValue();// this drops trailing numbers
// checks if difference is 0
return ((fFloat - iConvertedFloat) > 0);
}
This is how you would use this method:
Number oNumToSave = null;
if (isTrailingSignificant(fFloat))
{
// save float value as is
oNumToSave = fFloat;
}
else
{
// save as int
oNumToSave = fFloat.intValue();// drops trailing numbers
}
After that, you can do the database operation using the variable oNumToSave.
Not sure this is the best solution, but you can try to write a method like this :
String convertToString(Float f) {
if (f.toString().endsWith(".0"))
return f.intValue().toString();
else
return f.toString();
}
Kotlin:
val mAmount = 3.0
val intAmount = mAmount.toInt()
val amountToDisplay = if (intAmount.compareTo(mAmount) == 0) intAmount.toString() else java.lang.String.valueOf(mAmount)