I work with two Bluetooth beacons and two Philips Hue lights. I have a JSON file which contains the beacon UUID for each region and the light IDs:
{
"features":
[
{
"iot_identifier" : "1",
"iot_beacon_uuid" : "E2C56DB5-DFFB-48D2-B060-D0F5A71096E1"
},
{
"iot_identifier" : "2",
"iot_beacon_uuid" : "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"
}
]
}
I also have a string in my code which displays the current region UUID. It changes when I enter the other region.
This is my code to control the two lights after reading in the JSON:
List<Feature> listFeatures; //Features from JSON file
int count = listFeatures.size();
for(int i=0; i<count; i++){
// Here I have the UUID (not elegant, but does its work)
String regionString = beaconManager.getMonitoredRegions().toString();
String regionUUID = regionString.substring(6, 43).toUpperCase();
// Here I get the JSON properties for each feature
String iotIdentifierString = listFeatures.get(i).getIotIdentifier();
String iotBeaconUuid = listFeatures.get(i).getIotBeaconUuid();
// need this value as double to associate the JSON-ID with the Hue light ID
double iotIdentifierDouble = Double.parseDouble(iotIdentifierString);
if( /* anything */ ){
// get the light with the ID of the current JSON feature
String lightId = hueLightObjects.getFeatures().get(i).getIotIdentifier();
final PHLight light = bridge.getResourceCache().getLights().get(lightId);
// control the lights, turn on/off
}
}
So the "regionUUID" string changes whenever I switch the region. Currently I am always able to control both lights, no matter in which region I am.
What I am looking for is a way to only control the light that has the current beacon UUID in the JSON file.
Something like:
For regionUUID.equals(iot_beacon_uuid), only control the light with the ID in the feature where regionUUID equals the iot_beacon_uuid.
If I change the region, then I only want to control the other light in the other feature where this statement is true again.
Could someone help me with this?
First of all I believe that your question can be more shorter something like ( A Minimal, Complete, and Verifiable example)
So when I am in the region where the minor ID = 1, I only want to select the lamps, where the property "Minor_ID" is also 1
Your code can achieve that in your case it's depend on how you using it after retrieving process.
But you can do that with current way too:
for (int i=0; i<count; i++) {
if(selectedLamp == iotIdentifierDouble ){
//do what you wish
}
}
Related
I am trying to extract a Map of headers (position of the header + text in the header) from a list of inputs. I have mapped the inputs to the header (or group) they belong in. I need a function that's more or less like distinctor distinctUntilChangedbut where I can obtain the position where the text changed.
So far I have this:
Observable.from(inputs)
.map(this::getSectionTitle) // Maps the inputs into the Header string
.distinct();
which obviously return a list of the headers. In case it wasn't clear I need the list of headers linked to the position where they should be placed.
Alternatively I can also accept a function in F# of type List<String> -> Set<(Int*String)>for example.
Edit:
This is the function I want to move from impeartive to a functionl approach:
for (int i = 0; i < inputs.size(); i++) {
Input pu = inputs.get(i);
String header = getSectionTitle(pu);
if (!mHeaders.containsValue(header)) {
mHeaders.put(i + mHeaders.size(), header);
}
}
Edit 2:
Example of an input/output
["a","a","a","b","b","c"] -> [("a",0),("b",3),("c",5)]
You could use something like this
Observable.from(inputs)
.map(this::getSectionTitle) // Maps the inputs into the Header string
.zipWith(Observable.range(0, 1000), Pair::create) // This is a weak point of the solution as you should know max number of emissions as if it exceeds the number in range, it will stop emitting ..
.distinctUntilChanged(pair -> pair.first) // keySelector function tells the operator what is the value object upon which it should determine whether it was changed
.map(pair -> /* Map to your desired format */)
The pair corresponds to an item which has changed and the order number, in which it was emitted...
EDIT: Instead of Observable.range() you can use timer with scan operator. You should not rely on direct emissions from timer observable as there is no guarantee that it will be a continuous sequence, therefore a scan operator.
Observable.interval(1, TimeUnit.MILLISECONDS)
.scan(0L, (index, emittedValue) -> index++)
I'm using the speech recognizer to get a voice input from the user, it returns an array of 5 strings which I pass to this method
public int analyzeTag(ArrayList<String> voiceResults,Editor editor, Context context){
for (String match : voiceResults) {
Log.d(TAG, match);
if (match.equalsIgnoreCase(context.getResources().getString(R.string.first_tag))){
editor.append(context.getResources().getString(R.string.first_tag));
return 1;
}
else if (match.equalsIgnoreCase(context.getResources().getString(R.string.second_tag))){
editor.append(context.getResources().getString(R.string.second_tag));
return 1;
}
//etc....(huge list of tags)
//Some tags might also have acceptable variations, example:
else if (match.equalsIgnoreCase("img") || match.equalsIgnoreCase("image")
{
editor.append("img"); //the string to append is always taken from the first variation
}
}
return 0;
}
This method compares the results with a list of tags, the tag list will be pretty big with hundreds of tags so I would like to find the most efficient way to do this operation.
I need help with:
1.Is my way of comparing results the most efficient? Is there a better way? (from the user experience perspective, I don't want users waiting a long time to get a result).
The voice input will be a big part of my app so this method will be called quite often
2.I have a long list of tags, obviously the if(), elseIf() route is gonna be quite repetitive, is there a way to iterate this? Considering the fact that some tags might have variations (even more than 1)and that the variation 1 ("img") will be the same for everyone, but other variations will be locale/language sensitive example: "image" for english users "immagini" for italian users etc.
Text appended to the editor will be always taken from the first variation
How about puting tags in a StringArray and then iterate though the array ?
String[] tags = context.getResources().getStringArray(R.array.tags);
for (String match : voiceResults) {
for (int index = 0; index < tags.length; index++ ) {
if (match.equalsIgnoreCase(tags[index]) {
editor.append(tags[index]);
}
}
}
Here's the doc on StringArray
I've seen many people do similar to this in order to get the last word of a String:
String test = "This is a sentence";
String lastWord = test.substring(test.lastIndexOf(" ")+1);
I would like to do similar but get the last few words after the last int, it can't be hard coded as the number could be anything and the amount of words after the last int could also be unlimited. I'm wondering whether there is a simple way to do this as I want to avoid using Patterns and Matchers again due to using them earlier on in this method to receive a similar effect.
Thanks in advance.
I would like to get the last few words after the last int.... as the number could be anything and the amount of words after the last int could also be unlimited.
Here's a possible suggestion. Using Array#split
String str = "This is 1 and 2 and 3 some more words .... foo bar baz";
String[] parts = str.split("\\d+(?!.*\\d)\\s+");
And now parts[1] holds all words after the last number in the string.
some more words .... foo bar baz
What about this one:
String test = "a string with a large number 1312398741 and some words";
String[] parts = test.split();
for (int i = 1; i < parts.length; i++)
{
try
{
Integer.parseInt(parts[i])
}
catch (Exception e)
{
// this part is not a number, so lets go on...
continue;
}
// when parsing succeeds, the number was reached and continue has
// not been called. Everything behind 'i' is what you are looking for
// DO YOUR STUFF with parts[i+1] to parts[parts.length] here
}
i have some problems extracting strings
i am making a multiple choice with 4 choices (e.g. as buttons), with the choices by referencing to the filename. The file (i.e. the question) is a png and the filename is Number-Q01AZ7BZ8CZ9DZ10ANZ8.png. These png are put under assets folder.
Set<String> regions = regionsMap.keySet(); // get Set of regions
// loop through each region
for (String region : regions)
{
if (regionsMap.get(region)) // if region is enabled
{
// get a list of all flag image files in this region
String[] paths = assets.list(region);
for (String path : paths)
fileNameList.add(path.replace(".png", ""));
} // end if
} // end for
String fileName = fileNameList.get(randomIndex);
if (!quizCountriesList.contains(fileName))
{
quizCountriesList.add(fileName); // add the file to the list
String nextImageName = quizCountriesList.remove(0);
correctAnswer = nextImageName; // update the correct answer
int AZ = correctAnswer.indexOf("AZ");
int BZ = correctAnswer.indexOf("BZ");
int CZ = correctAnswer.indexOf("CZ");
int DZ = correctAnswer.indexOf("DZ");
int ANZ = correctAnswer.indexOf("ANZ");
String choiceA = null;
String choiceB = null;
String choiceC = null;
String choiceD = null;
choiceA = correctAnswer.substring( (AZ+2), (BZ) );
choiceB = correctAnswer.substring( (BZ+2), (CZ) );
choiceC = correctAnswer.substring( (CZ+2), (DZ) );
choiceD = correctAnswer.substring( (DZ+2), (ANZ) );
The logcat is as follows:
11-09 21:14:08.495: E/AndroidRuntime(25905): FATAL EXCEPTION: main
11-09 21:14:08.495: E/AndroidRuntime(25905): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.trial.quizgame/com.trial.quizgame.QuizGame}: java.lang.StringIndexOutOfBoundsException: length=15; regionStart=1; regionLength=-2
11-09 21:14:08.495: E/AndroidRuntime(25905): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1967)
I have tried to set the buttons as .setText(correctAnswer) and it will correctly show as Number-Q01AZ7BZ8CZ9DZ10ANZ8, so the top part of getting the String for "correctAnswer" should be ok. The problem left at extracting strings, yet BZ must be at a position behind AZ, so as CZ behind BZ, etc:
From the logcat the regionLength is -2? How could I handle this?
I would like it to be for Q01, choice A=7, B=8, C=9, D=10 and ANZ=8
thanks in advance for your advice!
Your assumption on the strings value is wrong. This code, if AZ, BZ, CZ, DZ, ANZ is present, should run with no error.
Either run debugger as advised in comments, or use android logcat to provide some debugging context. android.utils.Log.d("APP", String.format("AZ=%d", AZ));
How you store your data is not a big deal. You can tune it for days... You could create xml files that contain the name of the image, and the four possible answers... You can use the underscore approach, you can stay with your current one. Til it is only used by you, it doesn't really matter. You should just keep it simple. More complex => more chance for bugs...
So I'd advise reading about debugging and logging instead of refining the way you store the information... Storing it in the filename, that's a smart idea, quick and efficient, an ideal hack...
I can obtain the phone number from an incoming call or from a sms message. unfortunately, in case of the SMS there might be the country code in it. So, basically I need to obtain the plain phone number, without country code, in order to compare it with existing numbers in Contacts.
If you want to compare phone numbers you can always use the
PhoneNumberUtils.compare(number1, number2);
or
PhoneNumberUtils.compare(context, number1, number2);
Then you don't have to worry about the country code, it will just compare the numbers from the reversed order and see if they match (enough for callerID purposes at least).
fast untested approach (AFAIK phone numbers have 10 digits):
// As I said, AFAIK phone numbers have 10 digits... (at least here in Mexico this is true)
int digits = 10;
// the char + is always at first.
int plus_sign_pos = 0;
// Always send the number to this function to remove the first n digits (+1,+52, +520, etc)
private String removeCountryCode(String number) {
if (hasCountryCode(number)) {
// +52 for MEX +526441122345, 13-10 = 3, so we need to remove 3 characters
int country_digits = number.length() - digits;
number = number.substring(country_digits);
}
return number;
}
// Every country code starts with + right?
private boolean hasCountryCode(String number) {
return number.charAt(plus_sign_pos) == '+'; // Didn't String had contains() method?...
}
then you just call these functions