I am trying to take the average of multiple sharedpreference values in Android, but I can't seem to get it to work.
Here is the code that is "suppose" to caluclate the average:
if(amountOfMphValues > 1)
{
for(int i = 0; prefs.getInt(MPH_VALUE + i, 0) != 0; i++)
{
averageMphArray.add(prefs.getInt(MPH_VALUE + i, 0));
}
Iterator<Integer> iterator = averageMphArray.iterator();
int averageValue = 0;
while(iterator.hasNext())
{
averageValue = averageValue + iterator.next().intValue();
}
if(averageMphArray.size() > 0)
{
saveUserPrefs(AVERAGE_MPH, averageValue / averageMphArray.size());
}
}
SOLVED:
Ok, I got it to work. In the for loop, the i variable needed to start at 1 instead of 0, since my sharedpreferences started at 1.
Fixed version for whoever needs it:
for(int i = 1; prefs.getInt(MPH_VALUE + i, 0) != 0; i++)
{
averageMphArray.add(prefs.getInt(MPH_VALUE + i, 0));
}
Related
I'm trying to build a bar chart to show daily data of the week using MPAndroidChart. the data is shown localized so they're arranged depending on the first day of the week (Monday or Sunday). Some data get duplicated and added to several bars and some are show in wrong bars. I've been trying to solve this for a week and had no luck.
This is how I process data:
List<String> dailyIncomes = new ArrayList<>(7);
List<String> dailyExpenses = new ArrayList<>(7);
for (int x = 0; x < 7; x++) {
dailyIncomes.add("0");
dailyExpenses.add("0");
}
for (int i = 0; i < transactionsList.size(); i++) {
TransactionItem currentTransaction = transactionsList.get(i);
DateTimeHandler dateTimeHandler = new DateTimeHandler(currentTransaction.getUserDate()); //my own class to get day, week or year
int transactionYear = dateTimeHandler.getYear();
int transactionWeek = dateTimeHandler.getWeekOfYear();
int transactionDay = dateTimeHandler.getDayOfWeek();
if (transactionWeek == week && transactionYear == year) {
for (int d = 0; d < 7; d++) {
if (d + 1 == transactionDay) {
if (weekFields.getFirstDayOfWeek().getValue() == 7) {
if (transactionDay == 7) {
if (currentTransaction.getPrefix().equals("+")) {
double dailyTotal = Double.parseDouble(dailyIncomes.get(0)) + currentTransaction.getAmountValue();
dailyIncomes.add(0, "" + dailyTotal);
} else {
double dailyTotal = Double.parseDouble(dailyExpenses.get(0)) + currentTransaction.getAmountValue();
dailyExpenses.add(0, "" + dailyTotal);
}
} else {
if (currentTransaction.getPrefix().equals("+")) {
double dailyTotal = Double.parseDouble(dailyIncomes.get(d + 1)) + currentTransaction.getAmountValue();
dailyIncomes.add(d + 1, "" + dailyTotal);
} else {
double dailyTotal = Double.parseDouble(dailyExpenses.get(d + 1)) + currentTransaction.getAmountValue();
dailyExpenses.add(d + 1, "" + dailyTotal);
}
}
} else {
if (currentTransaction.getPrefix().equals("+")) {
double dailyTotal = Double.parseDouble(dailyIncomes.get(d)) + currentTransaction.getAmountValue();
dailyIncomes.add(d, "" + dailyTotal);
} else {
double dailyTotal = Double.parseDouble(dailyExpenses.get(d)) + currentTransaction.getAmountValue();
dailyExpenses.add(d, "" + dailyTotal);
}
}
}
}
}
}
WeeklyReport weeklyReport = new WeeklyReport(.....,dailyIncomes, dailyExpenses,....);
//to load next cards
weekCount++;
if (this.week == 1) {
yearCount++;
this.year = this.year - yearCount;
}
this.week = LocalDate.now()
.minusYears(yearCount)
.minusWeeks(weekCount)
.get(weekFields.weekOfWeekBasedYear());
weeklyReportList.add(weeklyReport);
adapter.submitList(weeklyReportList);
adapter.notifyItemInserted(adapter.getItemCount() + 1);
How I set data to the chart:
List<BarEntry> dailyDetails = new ArrayList<>();
for (int i = 0; i < 7; i++)
dailyDetails.add(new BarEntry(
(float) i, new float[]{
Float.parseFloat(weeklyReport.getDailyIncomes().get(i)),
Float.parseFloat(weeklyReport.getDailyExpenses().get(i))
}));
BarDataSet dailyDetailsSet = new BarDataSet(dailyDetails, "");
String[] labels = {context.getString(R.string.incomes), context.getString(R.string.expenses)};
//add x axis labels (days of week)
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int firstDay = weekFields.getFirstDayOfWeek().getValue();
Log.i(TAG, "first day: " + firstDay);
final List<String> xLabels = new ArrayList<>();
for (int x = 0; x < 7; x++)
xLabels.add("DAY");
if (firstDay == 7) {
xLabels.add(0, LocalDate.now().with(DayOfWeek.of(7)).getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.getDefault()));
for (int z = 1; z < 7; z++)
xLabels.add(z, LocalDate.now().with(DayOfWeek.of(z)).getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.getDefault()));
} else
for (int y = 0; y < 7; y++)
xLabels.add(LocalDate.now().with(DayOfWeek.of(y + 1)).getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.getDefault()));
dailyDetailsSet.setStackLabels(labels);
BarData data = new BarData(dailyDetailsSet);
chartView.setData(data);
chartView.getXAxis().setValueFormatter(new IndexAxisValueFormatter() {
#Override
public String getFormattedValue(float value) {
return xLabels.get((int) value);
}
});
chartView.invalidate();
The chart looks like this:
I already tried using switch statements instead of loops but no luck. I'm sure that the data is accurate because there are some other charts like budget and monthly reports and nothing's wrong with them. It must be some silly mistake and I've been trying to fix this for three days but there's always something wrong.
Could someone help me and point out what I'm doing wrong? I'd appreciate it so much. Thanks. (Sorry if there's bad English)
Please ask me if you need to see more of the code.
With same instance of 'interpreter' score is getting increased for same image until it reaches at some saturation.
Interpreter tflite = new Interpreter(loadModelFile(context));
Create Instance for ImageClassifier and use the same instance to classify Frame and run inference for the same image.
ImageClassifier(Activity activity) throws IOException {
tflite = new Interpreter(loadModelFile(activity));
labelList = loadLabelList(activity);
imgData =
ByteBuffer.allocateDirect(
DIM_BATCH_SIZE
* getImageSizeX()
* getImageSizeY()
* DIM_PIXEL_SIZE
* getNumBytesPerChannel());
imgData.order(ByteOrder.nativeOrder());
filterLabelProbArray = new float[FILTER_STAGES][getNumLabels()];
Log.d(TAG, "Created a Tensorflow Lite Image Classifier.");
}
Classifies a frame for the same image. Same image can be picked up from the Sd card.
private void classifyImage() {
if (classifier == null || getActivity() == null || cameraDevice == null) {
showToast("Uninitialized Classifier or invalid context.");
return;
}
String imgPath = "/storage/emulated/0/DCIM/test.jpg";
Log.d("Image Path is %s", imgPath);
Bitmap bitmap = BitmapFactory.decodeFile(imgPath);
Bitmap newbitmap = Bitmap.createScaledBitmap(bitmap, 299, 299, false);
String textToShow = classifier.classifyFrame(newbitmap);
bitmap.recycle();
showToast(textToShow);
}
classifyFrame() Method of ImageClassifier.java
String classifyFrame(Bitmap bitmap) {
if (tflite == null) {
Log.e(TAG, "Image classifier has not been initialized; Skipped.");
return "Uninitialized Classifier.";
}
convertBitmapToByteBuffer(bitmap);
// Here's where the magic happens!!!
long startTime = SystemClock.uptimeMillis();
runInference();
long endTime = SystemClock.uptimeMillis();
Log.d(TAG, "Timecost to run model inference: " + Long.toString(endTime - startTime));
// Smooth the results across frames.
applyFilter();
// Print the results.
String textToShow = printTopKLabels();
textToShow = Long.toString(endTime - startTime) + "ms" + textToShow;
return textToShow;
}
applyFilter() method of ImageClassifier.java
void applyFilter() {
int numLabels = getNumLabels();
// Low pass filter `labelProbArray` into the first stage of the filter.
for (int j = 0; j < numLabels; ++j) {
filterLabelProbArray[0][j] +=
FILTER_FACTOR * (getProbability(j) - filterLabelProbArray[0][j]);
}
// Low pass filter each stage into the next.
for (int i = 1; i < FILTER_STAGES; ++i) {
for (int j = 0; j < numLabels; ++j) {
filterLabelProbArray[i][j] +=
FILTER_FACTOR * (filterLabelProbArray[i - 1][j] - filterLabelProbArray[i][j]);
}
}
// Copy the last stage filter output back to `labelProbArray`.
for (int j = 0; j < numLabels; ++j) {
setProbability(j, filterLabelProbArray[FILTER_STAGES - 1][j]);
}
}
Prints top-K labels, to be shown in UI as the results.
private String printTopKLabels() {
for (int i = 0; i < getNumLabels(); ++i) {
sortedLabels.add(
new AbstractMap.SimpleEntry<>(labelList.get(i), getNormalizedProbability(i)));
if (sortedLabels.size() > RESULTS_TO_SHOW) {
sortedLabels.poll();
}
}
String textToShow = "";
final int size = sortedLabels.size();
for (int i = 0; i < size; ++i) {
Map.Entry<String, Float> label = sortedLabels.poll();
textToShow = String.format("\n%s: %4.2f", label.getKey(), label.getValue()) + textToShow;
}
return textToShow;
}
At the first time when application gets launched score the image classification is 0.06 and then again if we called classifyImage() on some event click score gets increased to 0.13 and with same process it keeps increasing until it reached to 0.86(saturation).
I am not sure why its happening but it happened for both type of TfLite models inceptionV3 and MobileNet.
The results are filtered by the applyFilter method. It is a simple low pass filter, so the scores gradually arrive at their medium-term average. Comment out the call to applyFilter and it should respond instantly, but maybe too jittery for some applications.
I want to create an Eddittext to type in currency values with 2 decimals from left to right. If there´s no value it shows 0.00, and as the user types the text should change acording to these rules:
I´ve tried getting it done using TextWatcher like in a similar question but I couldnt get it done as it kept calling TextWatcher after updating the text.
I finally got it working just as I wanted using a TextWatcher with this code, hope it helps someone:
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if ((count - before) > 0) {
String text = s.toString().replace(',', '.');
text = text.replace("..", ".");
if (text.equals(".")) {
text = "0,00";
amount_field.setText(text);
amount_field.setSelection(2);
} else {
int counter = 0;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == '.') {
counter++;
if (counter > 1) {
break;
}
}
}
if (counter > 1) {
StringBuilder sb = new StringBuilder(text);
sb.deleteCharAt(start);
amount_field.setText(sb.toString().replace('.', ','));
amount_field.setSelection(start);
} else {
Float value = Float.valueOf(text);
String result = String.format("%.2f", value);
amount_field.setText(result.replace('.', ','));
if (start != result.length()) {
amount_field.setSelection(start + 1);
} else {
amount_field.setSelection(start);
}
}
}
}
}
Try this:
String yourStringToPutIntoTextView = String.format("%.2f", YourFloat);
Here an example:
List<Float> listTestValue = new ArrayList<Float>();
listTestValue.add(new Float(10));
listTestValue.add(new Float(10.10));
listTestValue.add(new Float(1010));
listTestValue.add(new Float(0));
listTestValue.add(new Float(0.9));
listTestValue.add(new Float(.12));
listTestValue.add(new Float(0.01));
for(Float f : listTestValue)
{
String s = String.format("%.2f", f);
System.out.println(s);
}
If you have noInput format string with f = 0, like this:
String noInput = String.format("%.2f", (float)0);
Note that the values must be Float!
Output:
10,00
10,10
1010,00
0,00
0,90
0,12
0,01
I'm querying my calendar and showing all events result.
When i'm trying to parse the value CalendarContract.Events.DURATION i'm getting a RFC2445 string format.
For example i'm getting "P15M" which I know it's 15 minutes meeting.
After digging on the internet on how to parse RFC2445 I've found some google jar here
But is there any static class to parse those format?
Compiling a jar and using it only for 1 function it's not that nice...
Thanks for the help
I have had the same problem as you, dug around and found the following useful snippet somewhere. I refactored it a bit, so it will be more readable. hope it helps!
public static long RFC2445ToMilliseconds(String str)
{
if(str == null || str.isEmpty())
throw new IllegalArgumentException("Null or empty RFC string");
int sign = 1;
int weeks = 0;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
int len = str.length();
int index = 0;
char c;
c = str.charAt(0);
if (c == '-')
{
sign = -1;
index++;
}
else if (c == '+')
index++;
if (len < index)
return 0;
c = str.charAt(index);
if (c != 'P')
throw new IllegalArgumentException("Duration.parse(str='" + str + "') expected 'P' at index="+ index);
index++;
c = str.charAt(index);
if (c == 'T')
index++;
int n = 0;
for (; index < len; index++)
{
c = str.charAt(index);
if (c >= '0' && c <= '9')
{
n *= 10;
n += ((int)(c-'0'));
}
else if (c == 'W')
{
weeks = n;
n = 0;
}
else if (c == 'H')
{
hours = n;
n = 0;
}
else if (c == 'M')
{
minutes = n;
n = 0;
}
else if (c == 'S')
{
seconds = n;
n = 0;
}
else if (c == 'D')
{
days = n;
n = 0;
}
else if (c == 'T')
{
}
else
throw new IllegalArgumentException ("Duration.parse(str='" + str + "') unexpected char '" + c + "' at index=" + index);
}
long factor = 1000 * sign;
long result = factor * ((7*24*60*60*weeks)
+ (24*60*60*days)
+ (60*60*hours)
+ (60*minutes)
+ seconds);
return result;
}
In while loop of cursor
String duration = "your duration";
try {
Duration d = new Duration();
d.parse(duration);
endMillis = startMillis + d.getMillis();
if (debug)
Log.d(TAG, "startMillis! " + startMillis);
if (debug)
Log.d(TAG, "endMillis! " + endMillis);
if (endMillis < startMillis) {
continue;
}
} catch (DateException e) {
if (debug)
Log.d(TAG, "duration:" + e.toString());
continue;
}
The class Duration is and also refer line number 1487. there is parsing logic , you just need to include duration class in your source code and parse as in try block.
I hope it helps
I want to generate random number in two field between range 1-8 and also field sum should be less than 9.
what I've done done till now
for (int i; i <= 6; i++) {
fieldOne = rand.nextInt(9 - 5) + 5;
fieldTwo = rand.nextInt(9 - 5) + 5;
fieldSum = fieldOne + fieldTwo;
System.out.print(fieldSum); // should be < 9 and not repetition
}
but fieldSum become greater then 9 so How it is control this condition?
And Sequence should be random should not repeat 2 or more time.
rand.nextInt(9-5) won't calculate a random number between 5 and 8, it will make the operation 9 minus 5 and then will calculate rand.nextInt(4).
To calculate a random number between 5 and 8 you have to do something like this:
Random r = new Random();
for (int i = 0; i < 10; i++) {
int rand1 = r.nextInt(4) + 5;
int rand2 = r.nextInt(4) + 5;
int result = rand1 + rand2;
Log.v("", "" + result);
}
The problem is that result can't be < than 9 because you are summing two numbers that are => 5 so the lower result you can get is 10.
Edit for a solution with no repetition:
private List<Integer> rdmNumList = new ArrayList<Integer>();
private final int leftLimitRange = 1;
private final int rightLimitRange = 10;
private final int numOfIteration = 10;
public void generateNumList() {
for (int i = leftLimitRange; i <= rightLimitRange; i++) {
this.rdmNumList.add(num);
}
}
public int getRandomNumer() {
Random r = new Random();
int rNum = r.nextInt(rdmNumList.size());
int result = this.rdmNumList.get(rNum);
this.rdmNumList.remove(rNum);
return result;
}
public void test() {
this.generateNumList();
if(this.numOfIteration <= ((this.rightLimitRange - this.leftLimitRange + 1))) {
for (int i = 0; i < this.numOfIteration; i++) {
Log.v("Debug Output", String.valueOf(this.getRandomNumer()));
}
}
}
Note: this is efficient only with small range of number
This code works but it's far from being good. You should find some other solution by yourself. This answer will help you find your way
Maybe try this --> random.nextInt()%9; another way Get random nuber with random.nextInt(9).
Try,
fieldSum=(fieldOne+fieldTwo)%9;
This will def