Alejandro Ozai
Alejandro Ozai

Reputation: 71

Top 10 Scores using JavaScript

This is my first time asking a question here. I'm new to JavaScript and I'm trying learn it by making a game. I have 5 players, each with a scoreHistory array. How do I sort through all the player's scores, and display only the top 10? Since there are only 5 players, some players should be displayed multiple times if they have many high scores.

 const Data = [
{
    username: 'spidey2016',
    email: '[email protected]',
    password: 'maryJane123',
    firstName: 'Peter',
    lastName: 'Parker',
    scoreHistory: [500, 2300, 1000, 900, 3000],
},
{
    username: 'bbanner45',
    email: '[email protected]',
    password: 'berttyRoss456',
    firstName: 'Bruce',
    lastName: 'Banner',
    scoreHistory: [1000, 3500, 800, 2000, 3100],
},
{
    username: 'weirdo100',
    email: '[email protected]',
    password: 'chritinePalmer789',
    firstName: 'Stephen',
    lastName: 'Strange',
    scoreHistory: [2000, 700, 1000, 1000, 500],
},
{
    username: 'merchantOfDeath',
    email: '[email protected]',
    password: 'pepperPotts123',
    firstName: 'Tony',
    lastName: 'Stark',
    scoreHistory: [3000, 2500, 1000, 3100, 800],
},
{
    username: 'hammerGod',
    email: '[email protected]',
    password: 'janeFoster456',
    firstName: 'Thor',
    lastName: 'Odinson',
    scoreHistory: [500, 900, 1100, 2500, 2900],
},

]

export default Data;

What I've been able to do is sort through my data and get each player's top score and sort them from highest to lowest. But, I realized that some players have multiple high scores and should be displayed multiple times.

import React from 'react';
import { connect } from 'react-redux'

// hard code list of high scores - top 10

const HighScores = (props) => {
    return (
        <div>
            <h1>High Scores</h1>
            <table className="table table-striped">
                <thead>
                    <tr>
                        <th>#</th>
                        <th>Username</th>
                        <th>High Score</th>
                    </tr>
                </thead>
                <tbody>                   
                    {props.user.sort((a, b) => Math.max(...b.scoreHistory) - Math.max(...a.scoreHistory)).map((user, index) => //sort through all players based on their top scores them display them in order top to last
                        <tr key={index}>
                            <th>{index + 1}</th>
                            <td>{user.username}</td>
                            <td>{Math.max(...user.scoreHistory)}</td>
                        </tr>
                    )}
                </tbody>
            </table>

        </div>
    );
}

const mapStateToProps = state => ({
    user: state.users,
    allScores: state.allScores
})

export default connect(mapStateToProps)(HighScores);

Upvotes: 3

Views: 1021

Answers (4)

Nina Scholz
Nina Scholz

Reputation: 386730

You could take a staged approach and take all scores and the names and sort this array and take the top ten items.

var data = [{ username: 'spidey2016', email: '[email protected]', password: 'maryJane123', firstName: 'Peter', lastName: 'Parker', scoreHistory: [500, 2300, 1000, 900, 3000] }, { username: 'bbanner45', email: '[email protected]', password: 'berttyRoss456', firstName: 'Bruce', lastName: 'Banner', scoreHistory: [1000, 3500, 800, 2000, 3100] }, { username: 'weirdo100', email: '[email protected]', password: 'chritinePalmer789', firstName: 'Stephen', lastName: 'Strange', scoreHistory: [2000, 700, 1000, 1000, 500] }, { username: 'merchantOfDeath', email: '[email protected]', password: 'pepperPotts123', firstName: 'Tony', lastName: 'Stark', scoreHistory: [3000, 2500, 1000, 3100, 800] }, { username: 'hammerGod', email: '[email protected]', password: 'janeFoster456', firstName: 'Thor', lastName: 'Odinson', scoreHistory: [500, 900, 1100, 2500, 2900] }],
    top10 = data
        .reduce((r, { username, scoreHistory }) => r.concat(
            scoreHistory.map(score => ({ username, score }))
        ), [])
        .sort(({ score: a }, { score: b }) => b - a)
        .slice(0, 10);

console.log(top10);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Tomasz Bubała
Tomasz Bubała

Reputation: 2153

This is how you can do it:

  1. Create an array of objects, each { player: username, score: score }
  2. Sort array and slice it to find top 5

const data = [
{
    username: 'spidey2016',
    email: '[email protected]',
    password: 'maryJane123',
    firstName: 'Peter',
    lastName: 'Parker',
    scoreHistory: [500, 2300, 1000, 900, 3000],
},
{
    username: 'bbanner45',
    email: '[email protected]',
    password: 'berttyRoss456',
    firstName: 'Bruce',
    lastName: 'Banner',
    scoreHistory: [1000, 3500, 800, 2000, 3100],
},
{
    username: 'weirdo100',
    email: '[email protected]',
    password: 'chritinePalmer789',
    firstName: 'Stephen',
    lastName: 'Strange',
    scoreHistory: [2000, 700, 1000, 1000, 500],
},
{
    username: 'merchantOfDeath',
    email: '[email protected]',
    password: 'pepperPotts123',
    firstName: 'Tony',
    lastName: 'Stark',
    scoreHistory: [3000, 2500, 1000, 3100, 800],
},
{
    username: 'hammerGod',
    email: '[email protected]',
    password: 'janeFoster456',
    firstName: 'Thor',
    lastName: 'Odinson',
    scoreHistory: [500, 900, 1100, 2500, 2900],
},

]

const scores = data.map(player => {
  return player.scoreHistory.map(score => {
    return {
      player: player.username,
      score,
    }
  })
}).flat()

const highestScores = scores.sort((a, b) => b.score - a.score).slice(0, 5)

const list = document.querySelector('.top-scores')

highestScores.forEach(({ player, score }) => {
  const el = document.createElement("li")
  el.innerText = `${player} ${score}`
  list.appendChild(el)
})
<ul class="top-scores">
</ul>

Upvotes: 0

Patric
Patric

Reputation: 1627

One way you can achieve this is like this:

First you create a new array scores, consisting of (score, player) pairs:

let scores = [];
Data.forEach(entry => {
    entry.scoreHistory.forEach(score => {
      scores.push({score:score, player:entry.username});
    });
});

Then you sort this array descending by score

scores.sort((a, b) => b.score - a.score);

And now you only need to iterate over your top 10 and print the output:

for (let i = 0; i < 10; i++) {
    console.log(scores[i]);
}

Upvotes: 0

Treycos
Treycos

Reputation: 7492

Seems like a school exercise. Here are the steps you need to implement :

First, map every score in your players score histories to the following object :

{
    username: String,
    score: Number
}

You can achieve this by using the map function
Then flatten your array by either deconstructing your data or using flat / concat

Finally, you can use sort to sort out the biggest score with each object also indicating the name of the player who did it

Upvotes: 0

Related Questions