1

I want to get game high scores for the top 10 users and display them in a table view.

leaderboards
 CQVudhI2OjTfNbqWOWi2T1DTWKw2
 HIGH-SCORE: 23
 PLAYER-NAME: Russell
 REACTION-TIME: .9
 SWIPES: 12

 F9IbjpVSE8g5YN3PX0sdhSNGULJ3
 HIGH-SCORE: 29
 PLAYER-NAME: Clayton
 REACTION-TIME: .87
 SWIPES: 22

 HDIHCUSJDHCJHZKSHJXH
 HIGH-SCORE: 89
 PLAYER-NAME: Damien
 REACTION-TIME: .77
 SWIPES: 32

 jdhsjdbwkjsdkahnkdnk232j3j2
 HIGH-SCORE: 43
 PLAYER-NAME: Christopher
 REACTION-TIME: .99
 SWIPES: 32

In the table view I wish to splay the name and the score of the 10 highest scorers.

any help would be appreciated. Thanks

KENdi
  • 7,576
  • 2
  • 16
  • 31

3 Answers3

3

Firebase does not offer any way to reverse the sort order via a query. However, if you store your scores as negative values, then it's super easy.

Here's a structure

scores
  score_0
     amt: -20
  score_1
     amt: -10
  score_2
     amt: -12
  score_3
     amt: -1
  score_4
     amt: -22

and then the code that reads the top three 'high' scores of 22, followed by 20 and 12

    let scoresRef = self.ref.child("scores")
    let queryRef = scoresRef.queryOrdered(byChild: "amt").queryLimited(toFirst: 3)

    queryRef.observeSingleEvent(of: .value, with: { snapshot in   
        for child in snapshot.children {
            let snap = child as! DataSnapshot
            print(snap.value)
        }
    })

and the output

Optional({
    amt = "-22";
})
Optional({
    amt = "-20";
})
Optional({
    amt = "-12";
})

and of course, if there's a limited number of scores, they could be read into an array and sorted as well.

For completeness and if you don't want to store scores as negative values, here's how that would work.

    let scoresRef = self.ref.child("scores")
    let queryRef = scoresRef.queryOrdered(byChild: "amt").queryLimited(toLast: 3)

    queryRef.observeSingleEvent(of: .value, with: { snapshot in

        var scoresArray = [Int]()

        for child in snapshot.children {
            let snap = child as! DataSnapshot
            let score = snap.childSnapshot(forPath: "amt")
            scoresArray.append(score.value as! Int)
        }

        scoresArray = scoresArray.reversed()
        print(scoresArray)
    })

The above code reads in the three highest values via queryLimited(toLast) which are 12, 20 and 22 and populates an array. The array can be reversed which sorts descending 22, 20 and 12.

A final option is to read them in as 12, 22, 20 but insert each amt into the array at position 0. So 12 would be at index 0, then 22 would be at index 0 and 12 would be at index 1 etc.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Jay
  • 34,438
  • 18
  • 52
  • 81
  • Thanks for the help everyone! What I did was to do a querylimted(tolast 10) this was I got the 10 higest scores and then added that to an array and reversed it. Is that considered good enough code ? – russsell phillips Jul 18 '17 at 02:10
  • @russsellphillips If it works, is stable and easy to maintain then absolutely yes, it's good enough! If my answer helped, please accept it so it can help others as well! – Jay Jul 18 '17 at 12:03
0

I think you have to load all your Databae into an array of structs first, filter your array into the new array (how to do this, check here) and than represent it on the tableView. By the way, if you are only starting with Firebase I highly recommend you to read this tutorial. I hope my answer was useful :)

Oleg Blanutsa
  • 82
  • 1
  • 6
0

Here is another way to do it and you can save some code. Instead of using append when retrieving from firebase use insert( newObject, at: 0).

In the code you can se I replaced:

scoresArray.append()

for

scoresArray.insert( score, at: 0)

Full code:

var scoresArray = [Int]()
let scoresRef = self.ref.child("leaderboards")
let queryRef = scoresRef.queryOrdered(byChild: "HIGH-SCORE").queryLimited(toLast: 10)

queryRef.observeSingleEvent(of: .value, with: { snapshot in
  
  for child in snapshot.children {
    let snap = child as! DataSnapshot
    let score = snap.childSnapshot(forPath: "HIGH-SCORE").value as! Int
    scoresArray.insert( score, at: 0)
  }

})

Initially I got this answer from here: https://www.youtube.com/watch?v=4y_NLkYT6NU

Cristian
  • 62
  • 4