MPAndroidChart stacked bar chart shows wrong/duplicated values - android

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.

Related

Filter number from Array of string and get the index of last two greater number in android

I have a ArrayList that has value like [Value,Sum3,121,data8input,in:21::7,7.00,9.01] and I want to extract only number as the output should be like this [3,121,8,21,7,7.00,9.01] and then have to rearrange ascending and then get the index of last two number as result will be [21,121].
My tried code below,
for (int i = 0; i < arrayString.size(); i++) {
Pattern p = Pattern.compile("-?\\d+(,\\d+)*?\\.?\\d+?");
List<String> numbers = new ArrayList<String>();
Matcher m = p.matcher(arrayString.get(i).getvalue);
numbers.addAll(m);
for (int j = 0; j < numbers.size(); j++) {
Log.d("REMEMBERFILTER", allCollection.get(i).getTextValue());
}
}
}
do something like this, though it is not exactly memory efficient as I am using another list.
ArrayList<String> tempList = new ArrayList<>();
for (int i = 0; i < yourArrayList.size(); i++) {
tempList.add(yourArrayList.get(i).replaceAll("[^0-9]", ""));
}
//Arrange in ascending order
Collections.sort(tempList);
//Also try to remove those indexes which has only letters with
tempList.removeAll(Arrays.asList("", null));
for (int i = 0; i < tempList.size(); i++) {
Log.d("+++++++++", "" + tempList.get(i));
}
//You can get the last two or any element by get method of list by //list.size()-1 and list.size()-2 so on
This is a way to do it, finalArray has the 2 numbers you want:
String[] str = new String[] {"Value", "Sum3", "121", "data8input", "in:21::7", "7.00,9.01"};
StringBuilder longStringBuilder = new StringBuilder();
for (String s : str) {
longStringBuilder.append(s).append(" ");
}
String longString = longStringBuilder.toString();
String onlyNumbers = " " + longString.replaceAll("[^0-9.]", " ") + " ";
onlyNumbers = onlyNumbers.replaceAll(" \\. ", "").trim();
while (onlyNumbers.indexOf(" ") > 0) {
onlyNumbers = onlyNumbers.replaceAll(" ", " ");
}
String[] array = onlyNumbers.split(" ");
Double[] doubleArray = new Double[array.length];
for (int i = 0; i < array.length; i++) {
try {
doubleArray[i] = Double.parseDouble(array[i]);
} catch (NumberFormatException e) {
e.printStackTrace();
doubleArray[i] = 0.0;
}
}
Arrays.sort(doubleArray);
int numbersCount = doubleArray.length;
Double[] finalArray;
if (numbersCount >= 2) {
finalArray = new Double[]{doubleArray[numbersCount - 2], doubleArray[numbersCount - 1]};
} else if (numbersCount == 1) {
finalArray = new Double[]{ doubleArray[0]};
} else {
finalArray = new Double[]{};
}
for (Double number : finalArray) {
System.out.println(number);
}

Parse CalendarContract.Events.DURATION values

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

Taking the average of multiple sharedpreferences in Android?

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));
}

String Equation parser issue

I'm coding a method that solve various kind of equation. Now I want that the method receives a String equation that could be in the forms:
ax^2+bx+c=0
or
*ax^2+c=0*
or
bx+c=0
etc. and the order shouldn't matter.
My problem is: How could I parse the equation according the "x" grade?
The eq could contains more values of the same grade for example 2x^2+4x^2+3x+8=2 (max grade x^3).
My method should assign the a value to double a[] if on the left or on the right of a there is x^2, double b[], if on the left or on the right there is x, and double c[] if there isn't any x variable near the value (and should change the value sign if the therms is after the =).
Convert a String number in a double is simple but I don't know how I could disassemble the input String according the x grade as described.
Tested for -2x + 3x^2 - 2 + 3x = 3 - 2x^2
public Double[] parseEquation(String equation)
{
Log.d(TAG, "equation: " + equation);
// Remove all white spaces
equation = equation.replaceAll("[ ]", "");
// Get the left and right sides of =
String[] sides = equation.split("[=]"); // should be of size 2
boolean leftNegative = false;
boolean rightNegative = false;
if (sides.length != 2)
{
// There is no = or more than one = signs.
}
else
{
// if sides i starts with + remove the +
// if - we remove and put it back later
for (int i = 0; i < 2; i++)
{
if (sides[i].charAt(0) == '+')
{
sides[i] = sides[i].substring(1);
}
}
if (sides[0].charAt(0) == '-')
{
leftNegative = true;
sides[0] = sides[0].substring(1);
}
if (sides[1].charAt(0) == '-')
{
rightNegative = true;
sides[1] = sides[1].substring(1);
}
}
Log.d(TAG, "left side:" + sides[0] + " right side: " + sides[1]);
// Terms without signs need to find out later
String[] leftTerms = sides[0].split("[+-]");
String[] rightTerms = sides[1].split("[+-]");
int length = leftTerms[0].length();
if (leftNegative)
{
leftTerms[0] = "-" + leftTerms[0];
}
// put in the minus sign for the rest of the terms
for (int i = 1; i < leftTerms.length; i++)
{
Log.d(TAG, "length = " + length + " " + sides[0].charAt(length));
if (sides[0].charAt(length) == '-')
{
leftTerms[i] = "-" + leftTerms[i];
length += leftTerms[i].length();
}
else
{
length += leftTerms[i].length() + 1;
}
}
length = rightTerms[0].length();
if (rightNegative)
{
rightTerms[0] = "-" + rightTerms[0];
}
for (int i = 1; i < rightTerms.length; i++)
{
Log.d(TAG, "length = " + length + " " + sides[1].charAt(length));
if (sides[1].charAt(length) == '-')
{
rightTerms[i] = "-" + rightTerms[i];
length += rightTerms[i].length();
}
else
{
length += rightTerms[i].length() + 1;
}
}
// Now we put all the factors and powers in a list
List<ContentValues> leftLists = new ArrayList<ContentValues>();
// left side
for (int i = 0; i < leftTerms.length; i++)
{
Log.d(TAG, "leftTerm: " + leftTerms[i]);
ContentValues contentValues = new ContentValues();
int indexOfX = leftTerms[i].indexOf('x');
if (indexOfX == -1)
{
// no x mean a constant term
contentValues.put("factor", leftTerms[i]);
contentValues.put("power", "0");
}
else
{
int indexOfHat = leftTerms[i].indexOf('^');
if (indexOfHat == -1)
{
// no hat mean power = 1
contentValues.put("power", "1");
String factor = leftTerms[i].substring(0, indexOfX).trim();
contentValues.put("factor", factor);
}
else
{
String power = leftTerms[i].substring(indexOfX + 2).trim();
String factor = leftTerms[i].substring(0, indexOfX).trim();
contentValues.put("factor", factor);
contentValues.put("power", power);
}
}
Log.d(TAG, contentValues.toString());
leftLists.add(contentValues);
}
List<ContentValues> rightLists = new ArrayList<ContentValues>();
for (int i = 0; i < rightTerms.length; i++)
{
Log.d(TAG, "rightTerm: " + rightTerms[i]);
ContentValues contentValues = new ContentValues();
int indexOfX = rightTerms[i].indexOf('x');
if (indexOfX == -1)
{
// no hat mean a constant term
contentValues.put("factor", rightTerms[i]);
contentValues.put("power", "0");
}
else
{
int indexOfHat = rightTerms[i].indexOf('^');
if (indexOfHat == -1)
{
// no hat mean power = 1
contentValues.put("power", "1");
String factor = rightTerms[i].substring(0, indexOfX).trim();
contentValues.put("factor", factor);
}
else
{
String power = rightTerms[i].substring(indexOfX + 2).trim();
String factor = rightTerms[i].substring(0, indexOfX).trim();
contentValues.put("factor", factor);
contentValues.put("power", power);
}
}
Log.d(TAG, contentValues.toString());
rightLists.add(contentValues);
}
// Now add the factors with same powers.
// Suppose we solve for cubic here the end result will be
// 4 terms constant, x, x^2 and x^3
// Declare a double array of dim 4 the first will hold constant
// the second the x factor etc...
// You can allow arbitrary power by looping through the lists and get the max power
Double[] result = new Double[]{0.0, 0.0, 0.0, 0.0};
for (ContentValues c : leftLists)
{
switch (c.getAsInteger("power"))
{
case 0:
//Log.d(TAG, "power = 0, factor = " + c.toString());
result[0] += c.getAsDouble("factor");
break;
case 1:
result[1] += c.getAsDouble("factor");
break;
case 2:
result[2] += c.getAsDouble("factor");
break;
case 3:
result[3] += c.getAsDouble("factor");
break;
}
}
for (ContentValues c : rightLists)
{
switch (c.getAsInteger("power"))
{
case 0:
//Log.d(TAG, "power = 0, factor = " + c.toString());
result[0] -= c.getAsDouble("factor");
break;
case 1:
result[1] -= c.getAsDouble("factor");
break;
case 2:
result[2] -= c.getAsDouble("factor");
break;
case 3:
result[3] -= c.getAsDouble("factor");
break;
}
}
Log.d(TAG, "constant term = " + result[0] + ", x^1 = " + result[1]
+ ", x^2 = " + result[2] + ", x^3 = " + result[3]);
return result;
}
If you weren't limited by Android, I'd suggest using a lexer and parser. These are code generators, so they can work anywhere the base language works, but they tend to produce bloated code. Android might not appreciate that.

JSON remove special characters

I want to do the replication between Android sqlite & MS SQL server.That Time i want to take Tables values from Databse.
This is my JSON
{
"Table1":[
{
"BusinessUnit":"MASS",
"ProductCode":"SLD0201",
"Description":"Lou Difan C.Blue 12"3- Commode",
"Description2":"301 0201"
},
{
"BusinessUnit":"MASS",
"ProductCode":"SLN0502",
"Description":"Lou Napoli I"vory- Cistern",
"Description2":"2011 0502"
},
{
"BusinessUnit":"MASS",
"ProductCode":"LDMBL6H",
"Description":"Dortek Taper Bullet Handle 6"5 serr ",
"Description2":"Taper Bullet Ha"
}
],
"Table2":[
{
"chk":6,
"currentchk":1
}
]
}
In Here JSON Description column value contain "(double quotation) .If we check http://jsonformatter.curiousconcept.com/ , it show error.Its a Invalid JSON.
WCF service I have converted DataSet to JSON. Some table column contain special charters.
I converted like this :
public String ConverTableToJson(DataSet dsDownloadJson,int currentSplit)
{
StringBuilder Sb = new StringBuilder();
String result = "";
int start = 0;
int end =500;
int chk = 0;
int currentChk = currentSplit;
if (dsDownloadJson.Tables.Count > 0)
{
Sb.Append("{");
foreach (DataTable dt in dsDownloadJson.Tables)
{
DataTable dtDownloadJson = dt;
string[] StrDc = new string[dtDownloadJson.Columns.Count];
string HeadStr = string.Empty;
double total = dtDownloadJson.Rows.Count;
Console.WriteLine("--1--" + dtDownloadJson.Rows.Count);
if (dtDownloadJson.Rows.Count < 500)
{
end = dtDownloadJson.Rows.Count;
}
if (chk == 0)
{
if (dtDownloadJson.Rows.Count > 500)
{
if ((dtDownloadJson.Rows.Count / 500) == 0)
{
chk = dtDownloadJson.Rows.Count / 500;
}
else
{
chk = dtDownloadJson.Rows.Count / 500 + 1;
}
}
else
{
chk = 1;
}
currentChk = 1;
}
else
{
currentChk = currentChk + 1;
start = currentChk * 500;
end = start + 500;
currentChk = chk;
}
Sb.Append("\"" + dtDownloadJson.TableName + "1\" : [");
if (dtDownloadJson.Rows.Count > 0)
{
for (int i = 0; i < dtDownloadJson.Columns.Count; i++)
{
StrDc[i] = dtDownloadJson.Columns[i].Caption;
HeadStr += "\"" + StrDc[i] + "\" : \"" + StrDc[i] + i.ToString() + "¾" + "\",";
}
if (HeadStr.Length > 0)
{
HeadStr = HeadStr.Substring(0, HeadStr.Length - 1);
Console.WriteLine("--2--" + start);
Console.WriteLine("--3--" + end);
for (int i = start; i < end; i++)
{
string TempStr = HeadStr;
Sb.Append("{");
for (int j = 0; j < dtDownloadJson.Columns.Count; j++)
{
TempStr = TempStr.Replace(dtDownloadJson.Columns[j] + j.ToString() + "¾", dtDownloadJson.Rows[i][j].ToString());
TempStr = TempStr.Replace(""", '\"');
}
Sb.Append(TempStr + "},");
}
Sb = new StringBuilder(Sb.ToString().Substring(0, Sb.ToString().Length - 1));
}
}
else
{
}
Sb.Append("],");
if (chk > 1)
{
Sb.Append("\"Table2\": [{\"chk\": " + chk + ", \"currentchk\": " + currentChk + " }]");
}
else
{
Sb.Append("\"Table2\": [{\"chk\": " + chk + ", \"currentchk\": " + currentChk + " }]");
}
}
// Sb = new StringBuilder(Sb.ToString().Substring(0, Sb.ToString().Length - 1));
Sb.Append("}");
return Sb.ToString();
}
else
{
return "0";
}
}
My problem is removing special charters OR How to allow special characters.?
Please help me anybody...
You shouldn't use a StringBuilder to convert an object to a JSON string. Use the JsonConverter class in JayRock JSON library and it takes care of Serialising/Deserialising Json for you (including escaping)
try to use inbuilt json serialization
public static string Serialize<T>(T obj)
{
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new
System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, obj);
string retVal = Encoding.Default.GetString(ms.ToArray());
ms.Dispose();
return retVal;
}

Categories

Resources