Array Integer Logic - android

I have a game with progress chart and an array. I want to have a chart which the player can see its score in its last 5 games.
here's my code in my array
int[] Addition = { score1, score2, score3, score4, score5 };
if (score1 == 0) {
score1 = Game.score;
} else if (score1 != 0 && score2 == 0) {
score2 = 21;
} else if (score2 != 0 && score3 == 0) {
score3 = Game.score;
} else if (score3 != 0 && score4 == 0) {
score4 = Game.score;
} else if (score4 != 0 && score5 == 0) {
score5 = Game.score;
}
What is the problem on my logic? when it runs my first game score seems to be right. but when i play one more its just that the 1st element of the array is changing? where Am I wrong? btw please apologize my english. and I appreciate any suggestions and comments. thanks guys
:::UPDATE:::
here's my code now. Can someone check if my initialization is correct:
public class ProgressGraph extends Activity {
int[] Addition = { 0, 0, 0, 0, 0 };
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
openChart();
}
public void openChart() {
for (int i = 0; i < 5; i++) {
if (Addition[i] == 0) {
Addition[i] = Game.score;
break;
}
}

I would do something like this:
for(int i = Addition.length-1; i > 0; i--){
Addition[i] = Addition[i-1];
}
Addition[0] = Game.score;
This will mean that the most recent game will always be in position 0. If the user plays more than 5 games the oldest score gets replaced.
It also allows the user to be able to score 0.

This part of code seems to be good.
I think your score array is reset when you start the second game.
Did you try to print the scores array before the end of the second game ? Does the first score remain stored ?
Then I suggest you to use a loop like that (not tested):
for (int i = 0; i < 5; i++) {
if (score[i] == 0) {
score[i] = Game.score;
break;
}
}

Are you trying to move each old score down the list?
for (int i = 4; i > 0; i--) {
Addition[i] = Addition[i-1];
}
Addition[0] = Game.score;
In these code samples we've provided, the array values should be initialized to zero:
int[] Addition = { 0, 0, 0, 0, 0};

Taking into account your update.
- When you declare the array. The variable has a capital letter so it may have a conflict with a class. Replace Addition by addition.
With this code, if you start another activity, scores will be reset. You have to use Application extended class or SharedPreferences to save scores.

Related

Android Studio - App crash when using intent parameter

I have a function that 'crafts' products using two String parameters.
This is working fine when I put in hard coded strings like 'Wheel' & 'Car'.
But it makes my application crash if I try to put in the exact same strings but then provided by an intent.
I already tried to give in variable into the intent instead of a hard coded string. That did not work either.
Here is some part of the code. EDIT: Error log now included
productLeft = getIntent().getStringExtra("PRODUCT LEFT");
productRight = getIntent().getStringExtra("PRODUCT RIGHT");
public void craft(String product1, String product2) {
String[][] Products = factory.getProductList();
int i = 0;
while (finalProduct == "") {
int j;
for(j = 0; j < 3; j++){
if (product1 == Products[i][0] || product2 == Products[i][0]) {
if (product1 == Products[i][1] || product2 == Products[i][1]){
finalProduct = Products[i][2];
}
}
i++;
}
}
}
Problem is with the array index obviously. The array has only four elements and you are fetching index 4, probably in for loop with i variable. But then again I also do not see the role of j in that loop, can't tell without other parts of code.

Realm - Do not update if property equals

I am using realm for Android. I have the following code and it works but I was wondering if it is the best way to go about updating objects and if it would cause any performance issues.
Currently, I do not want to update an existing object if the status is set to processing.
List<WorkOrderObject> woList = new ArrayList<>();
for (int i = 0; i < openWorkOrders.size(); i++) {
if (!visnetawrap.isUserLoggedIn) {
return;
}
WorkOrderObject wo = visnetawrap.gsonClient.fromJson(openWorkOrders.get(i).toString(), WorkOrderObject.class);
WorkOrderObject currWO = realmThread.where(WorkOrderObject.class).equalTo("id", wo.getOrderRawId()).findFirst();
if (currWO != null) {
if (currWO.getOrderStatus().equals("Processing")) {
continue;
}
}
issueDateTime = AppUtils.formatTimestampToDateTime(wo.getOrderIssueDate());
issueDateString = issueDateTime.toLocalDateTime().toString("MM/dd/yyyy", Locale.US);
dueDateTime = AppUtils.formatTimestampToDateTime(wo.getOrderDueDate());
dueDateString = dueDateTime.toLocalDateTime().toString("MM/dd/yyyy", Locale.US);
if (!issueDateString.equals("") && !issueDateString.equals("00/00/0000") && issueDateTime.getYear() >= now.getYear() && !dueDateString.equals("") && !dueDateString.equals("00/00/0000") && dueDateTime.getYear() >= now.getYear()) {
//Log.d("dueDate", dueDateString);
woList.add(wo);
}
}
realmThread.beginTransaction();
realmThread.copyToRealmOrUpdate(woList);
realmThread.commitTransaction();
I think basically it is the same.
Since you are worried about performance here are ways you can improve.
private static String PROCESSING = "Processing";
private static String DATE_FORMAT = "MM/dd/yyyy";
private static String EMPTY_DATE = "00/00/0000";
public void betterMethod() {
List<WorkOrderObject> woList = new ArrayList<>(openWorkOrders.size());
//I think this code doesnot need to be inside loop.
if (!visnetawrap.isUserLoggedIn) {
return;
}
for (int i = 0, j = openWorkOrders.size(); i < j; i++) {
//Since you are using gson there are ways to convert JsonArray to list directly which is a better way than this
WorkOrderObject wo = visnetawrap.gsonClient.fromJson(openWorkOrders.get(i).toString(), WorkOrderObject.class);
WorkOrderObject currWO = realmThread.where(WorkOrderObject.class).equalTo("id", wo.getOrderRawId()).findFirst();
if (currWO != null && currWO.getOrderStatus().equals(PROCESSING)) { //Its cleanar way
continue;
}
issueDateTime = AppUtils.formatTimestampToDateTime(wo.getOrderIssueDate());
issueDateString = issueDateTime.toLocalDateTime().toString(DATE_FORMAT, Locale.US);
dueDateTime = AppUtils.formatTimestampToDateTime(wo.getOrderDueDate());
dueDateString = dueDateTime.toLocalDateTime().toString(DATE_FORMAT, Locale.US);
//I assume you have stripped out code where it needs string
//You can use TextUtils.isEmpty() or issueDateString.isEmpty() ,
// issueDateString.equals("") does is creates new String which is empty and compares issueDateString with it while above methods just check the
//length of string
if (!TextUtils.isEmpty(issueDateString) && !issueDateString.equals(EMPTY_DATE) && issueDateTime.getYear() >= now.getYear() && !TextUtils.isEmpty(dueDateString) && !dueDateString.equals(EMPTY_DATE) && dueDateTime.getYear() >= now.getYear()) {
//Log.d("dueDate", dueDateString);
woList.add(wo);
}
}
if (!woList.isEmpty()) {
realmThread.beginTransaction();
realmThread.copyToRealmOrUpdate(woList);
realmThread.commitTransaction();
}
}
For loop can be very large so conditional statement like currWO.getOrderStatus().equals("Processing") will create an new string and compares. It's better to initialize the string before and pass as above.
Converting JsonArray to List
Why instantiating arrays like new ArrayList<>(openWorkOrders.size()) and using for loop with list like for (int i = 0, j = openWorkOrders.size(); i < j; i++) {}
Streamlining Android Apps: Eliminating Code Overhead by Jake Wharton

MPAndroidChart with null values

I'm using the MPAndroidChart and am really enjoying it.
A 'little' need I have is that I can put null values to the 'entrys'. I'm monitoring the apache conections on servers of my system, and I would to see if they is down (where I put the null value) or if they just no conections (0).
I tried, but the Entry class don't accept 'null' as value showing the message: 'The constructor Entry(null, int) is undefined'
Thanks!
A possible solution for you could be to check weather the object you received is null, or not. If the object is null, you don't even create an Entry object instead of just setting it's value to null.
Example:
// array that contains the information you want to display
ConnectionHolder[] connectionHolders = ...;
ArrayList<Entry> entries = new ArrayList<Entry>();
int cnt = 0;
for(ConnectionHolder ch : connectionHolders) {
if(ch != null) entries.add(new Entry(ch.getNrOfConnections(), cnt));
else {
// do nothing
}
cnt++; // always increment
}
This would create e.g. a LineChart where no circles are drawn on indices where the ConnectionHolder object was null.
For a future release of the library, I will try to add the feature so that null values are supported.
My solution is to draw another DataSet with TRANSPARENT (or arbitrary) color:
- chart with fixed number of X values
- Y values are updated periodically
- boolean flag indicate transparent part (or another color)
private static final int SERIES_SIZE = 360;
int xIndex = -1;
float xIndexVal;
private LineChart chart;
private boolean currentFlag;
public void createChart(LineDataSet dataSet) {
LineData chartData = new LineData();
prepareDataSet(dataSet);
chartData.addDataSet(dataSet);
for (int i = 0; i < SERIES_SIZE; i++) {
chartData.addXValue("" /*+ i*/);
}
chart.setData(chartData);
}
private void prepareDataSet(LineDataSet dataSet, YAxis axis, int color) {
// configure set
}
public void update(Float val, boolean flag) {
List<ILineDataSet> dsl = chart.getData().getDataSets();
Log.d("chart", String.format("%s --- %d sets, index %d", descr, dsl.size(), xIndex));
if (xIndex == SERIES_SIZE - 1) {
// remove all entries at X index 0
for (int i = 0; i < chart.getData().getDataSetCount(); i++) {
Entry entry0 = chart.getData().getDataSetByIndex(i).getEntryForIndex(0);
if (entry0 != null && entry0.getXIndex() == 0) {
chart.getData().removeEntry(entry0, i);
Log.d("chart", String.format("entry 0 removed from dataset %d, %d entries in the set", i, chart.getData().getDataSetByIndex(i).getEntryCount()));
}
else {
Log.d("chart", String.format("all %d entries in the set kept", chart.getData().getDataSetByIndex(i).getEntryCount()));
}
}
// remove empty set, if any
for (Iterator<ILineDataSet> mit = dsl.iterator(); mit.hasNext(); ) {
if (mit.next().getEntryCount() == 0) {
mit.remove();
Log.d("chart", String.format("set removed, %d sets", dsl.size()));
}
}
// move all entries by -1
for (ILineDataSet ds : dsl) {
for (Entry entry : ((LineDataSet)ds).getYVals()) {
entry.setXIndex(entry.getXIndex() - 1);
}
}
}
else {
xIndex++;
}
if (currentFlag != flag) {
currentFlag = !currentFlag;
LineDataSet set = new LineDataSet(null, "");
prepareDataSet(set, chart.getAxisLeft(), currentFlag ? Color.TRANSPARENT : Color.BLUE);
chart.getData().addDataSet(set);
if (xIndex != 0) {
chart.getData().addEntry(new Entry(xIndexVal, xIndex - 1), dsl.size() - 1);
}
}
xIndexVal = val;
chart.getData().addEntry(new Entry(val, xIndex), dsl.size() - 1);
chart.notifyDataSetChanged();
chart.invalidate();
}

Order object by id in the same order as the ids list

I have list of integer IDs. Lets say this list is ArrayList<Integer> or int[], it doesn't matter. I have another ArrayList<Obj> that contains the objects with the same ids like in the first list, but they are ordered in different order.
I want to order the objects in the second list in the order as the ids in the first list.
EXAMPLE:
FIRST LIST: { 1, 5, 4, 8, 6 }
SECOND LIST: { Obj[id=5], Obj[id=8], Obj[id=6], Obj[id=1], Obj[id=4] }
RESULT LIST: { Obj[id=1], Obj[id=5], Obj[id=4], Obj[id=8], Obj[id=6] }
Can someone tell me an (efficient) way to do this?
I would suggest using a map:
Map<Integer, Obj> map = new HashMap<Integer, Obj>(secondList.size() * 2);
for (final Obj obj : secondList) {
map.put(obj.id, obj);
}
for (int i = 0; i < secondList.size(); i++) {
secondList.set(i, map.get(firstList.get(i)));
}
This runs in O(n), which IMHO is pretty much the best you can get.
A/ Create a matching id index list, such as:
1 -> 0
5 -> 1
4 -> 2
8 -> 3
6 -> 4
That's a reversed reference of your first list. It indicates the position of each id. A SparseIntArray is a good way of doing it:
SparseIntArray ref = new SparseIntArray();
for (int i = 0; i < firstList.size(); i++) {
ref.append(firstList.get(i), i);
}
Then you need to sort your second list using a Comparator that uses the id of the Object and the ref table:
Collections.sort(secondList, new Comparator<Obj>() {
public int compare(Obj t1, Obj t2) {
return ref.get(t1.id) - ref.get(t2.id);
}
});
I was in the middle of writing Etienne's answer when he posted it, so just for fun here's an O(N^2) solution with a smaller constant factor that doesn't create any objects:
int[] first = { 1, 5, 4, 8, 6 };
Obj[] second = { Obj[id=5], Obj[id=8], Obj[id=6], Obj[id=1], Obj[id=4] };
int i = 0;
while(i < second.length) {
int ind = -1;
for(int j=0;j<first.length;j+=1) {
if(first[j] == second[i].id) {
ind = j;
break;
}
}
if(ind == -1) break; //Bad news
if(ind == i) {
i += 1;
} else {
Obj temp = second[i];
second[i] = second[ind];
second[ind] = temp;
}
}
Obviously the creation of second[] is pseudocode, but the rest will work if the arrays are equal length. I think this will be a little bit faster than Etienne's for very small data sets, but you'd have to profile both answers.

Points changing rapidly

I like to make a game, but I get trouble with collecting points.
The purpose is to increase/decrease character point (charhop +1 or -1) whenever object 'face' is collided with injekBox, but the point just increase or decrease once then it return to the previous value.
The log also still print the value even if the object stop
I want to make the point change once if the 'face' collided with certain box, and will change again after collided with another box
char1.setHops(0);
public void onUpdate(final float pSecondsElapsed) {
if (char1.isJump()){
int rockPoint = char1.getPoints();
int maxBox = listBox.size();
int charHop = char1.getHops();
for (int j = 0; j < maxBox ; j++){
if (j == rockPoint){
j++;
}
Box injekBox = listBox.get(j);
if(injekBox.getRectangle().collidesWith(face)){
if(char1.isTurn()){
charHop++;
if (charHop == (maxBox - 1)){
char1.setTurn(false);
}
} else {
charHop--;
}
Log.i(this.toString(),"charHop: "+charHop);
injekBox.getRectangle().setColor(1, 0, 0);
} else {
injekBox.getRectangle().setColor(1, 1, 1);
}
}
}
}
Sorry for bad writing...
Thank you for attention :)
The scope of charHop is only within onUpdate. Once you leave that method, the contents of that variable is gone. You need the counterpart to char1.getHops()--something like char1.setHops(charHop);.

Categories

Resources