Sean O
Sean O

Reputation: 236

How to find the greatest value among players uploaded data

I am trying to make a hi-score type of tool for my app, so I am playing around with some code and cannot figure out to search through multiple nodes to find the greatest value. The problem seems to be that the DataSnapshot reads the nodes as a HashMap and isn't having problem converting the values to an int. How can I read through the information (player name and player score), have the DataSnapshot identify the greatest value and set the TV to that value?

The code for what I have tried is below. I will also add a screenshot of how my firebase looks to make it visually easier to understand

My WriteToFirebase Activity

public void gFirebase(View view){

        int score = (int) (Math.random() * ((50)+1));
        Player p1 = new Player();
        p1.setName("Player 1");
        p1.setScore(score);

        DatabaseReference roofRef = FirebaseDatabase.getInstance().getReference();
        DatabaseReference gameInfoRef = roofRef.child("hiscore").child("player_name").push();

        gameInfoRef.setValue(p1);

    }

    public void lFirebase(View view){

        int score = (int) (Math.random() * ((50)+1));
        Player p2 = new Player();
        p2.setName("Player 2");
        p2.setScore(score);

        DatabaseReference roofRef = FirebaseDatabase.getInstance().getReference();
        DatabaseReference gameInfoRef = roofRef.child("hiscore").child("player_name").push();

        gameInfoRef.setValue(p2);

    }

    public void sFirebase(View view){

        int score = (int) (Math.random() * ((50)+1));
        Player p3 = new Player();
        p3.setName("Player 3");
        p3.setScore(score);

        DatabaseReference roofRef = FirebaseDatabase.getInstance().getReference();
        DatabaseReference gameInfoRef = roofRef.child("hiscore").child("player_name").push();

        gameInfoRef.setValue(p3);


    }

My ReadFromFirebase Activity

public void readFromFirebase(View view) {

        DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
        DatabaseReference hiscoreRef = rootRef.child("hiscore").child("player_name");
        ValueEventListener eventListener = new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                int hiscore = 0;
                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    int value = ds.getValue(Integer.class);
                    if (hiscore < value) {

                        hiscore = value;

                    }
                    Log.d("TAG", String.valueOf(hiscore));
                    ChangeMe.setText(hiscore);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }

        };
        hiscoreRef.addListenerForSingleValueEvent(eventListener);
}

The expected result is for the textview on my screen to change to the highest number in my Firebase system (The highest score)

JSON tree of my database

{
  "hiscore" : {
    "player_name" : {
      "-Lo0W8ks7WCEsrym5Qpl" : {
        "name" : "Player 3",
        "score" : 24
      },
      "-Lo0W92WqeUMdq_y7J8M" : {
        "name" : "Player 2",
        "score" : 42
      },
      "-Lo0W9KjzXE_XCU4K8MN" : {
        "name" : "Player 1",
        "score" : 43
      }
    }
  }
}

Upvotes: 0

Views: 68

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599946

You can use a Firebase query for this. That will make the server perform the check, instead of having to do this in your own code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference hiscoreRef = rootRef.child("hiscore").child("player_name");
Query hiscoreQuery = hiscoreRef.orderByChild("score").limitToLast(1);
hiscoreQuery.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        int hiscore = 0;
        for (DataSnapshot ds: dataSnapshot.getChildren()) {
            hiscore = ds.child("score").getValue(Integer.class);
        }
        Log.d("TAG", String.valueOf(hiscore));
        ChangeMe.setText(hiscore);
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        throw databaseError.toException(); // never ignore errors
    }

});

You may receive a warning about needing to define an index, in which case you can add this to your Firebase security rules:

"hiscore": {
  "player_name": {
    ".indexOn": "score"
  }
}

Upvotes: 1

Related Questions