Skip to content

pedrocmart/leaderboard-service

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Leaderboard Service

Table of Contents


Description

Your task is to implement a service that maintains a "real-time" ranking of users playing a specific game.

Requirements:

  • Clients submit user scores when they achieve important milestones in the game 
  • Clients can submit absolute scores or relative scores, for example: {"user" :123, "total": 250}, or {"user": 456, "score": "+10"}, or {"user": 789, score: "-20"}
  • Any client can request the ranking at any time, using one of the following requests:
  • Absolute ranking, for example: Top100, Top200, Top500
  • Relative ranking, for instance: At100/3, meaning 3 users around position 100th of the ranking, that is positioned 97th, 98th, 99th, 100th, 101st, 102nd, 103rd

We propose that it have the following endpoints:

  • [POST] user/{user_id}/score
  • [GET] ranking?type=top100
  • [GET] ranking?type=At100/3

Technical requirements

  • We prefer you to develop the test in one of the main languages we use at SP (PHP or Golang) but if you don't feel comfortable enough with them, feel free to choose any other
  • Do not couple yourself to a specific framework, as the test is pretty simple we prefer to see how big is your knowledge of what goes under the hood
  • Do not use any database or external storage system, just keep the ranking in-memory (NB if you use a stateless language there's no need to keep this storage anywhere after the process dies)
  • The code must work and sort as specified in this document

Goals to evaluate

  • How you approach the project (we left some stuff  intentionally open, so you have to evaluate trade-offs and make some decisions)
  • How you design and architecture the system 
  • How you test and ensure the overall quality of the solution

Nice to have

  • Docker with docker-compose
  • Readme to explain how we can check the code
  • Testing with full code coverage or important code for you

Solution

Requirements to install

  • Go 1.18
  • Docker
  • docker-compose

Build for Local development

make local

Running Tests

make test


APIs

[POST] user/{user_id}/score

Since we can have two different submissions for the user (absolute or relative), the body must contain only one option, as described below:

Absolute Score:

Must be sent with the integer total. This will set the user's total score.

If the user_id sent didn't exist in the database, a new user will be created.

Example:

[POST] http://0.0.0.0:8894/user/1/score

[JSON Body]

{
    "total": 100
}

Relative Score:

Must be sent with the string score. This will add or subtracts from user's score, depending on the first character sent. The API only accepts score which starts with + or -.

The user can have a negative score.

If the user_id sent didn't exist in the database, a new user will be created.

Example:

[POST] http://0.0.0.0:8894/user/1/score

[JSON Body]

{
    "score": "+20"
}

Response:

For both scenarios, the response will be the same, in case of success. A JSON containing the user_id, and the current score.

{
    "user_id": 1,
    "score": 100
}

[GET] ranking?type={type}

In order to request the ranking, you need to set what kind of ranking do you want to see: absolute or relative. That said, the API will only accept the followin types as a parameter:

Absolute Ranking:

In this scenario, you must use the type top, followed by the number of users that you want in the ranking. The number must be greater than 0.

Example:

Below we define type as top3, meaning that we want the 3 top players from our ranking.

[GET] http://0.0.0.0:8894/ranking?type=top3

Response:

{
    "ranking": [
        {
            "position": 1,
            "user_id": 3,
            "score": 452
        },
        {
            "position": 2,
            "user_id": 2,
            "score": 101
        },
        {
            "position": 3,
            "user_id": 1,
            "score": 5
        }
    ]
}

Relative Ranking:

In this scenario, you must use the type at, followed by the position you want in the ranking, a /, and a number of users around that position. Both numbers must be greater than 0.

Example:

Below we define type as at10/2, meaning 2 users around position 10th of the ranking, that is positioned 8th, 9th, 10th, 11th, 12th.

[GET] http://0.0.0.0:8894/ranking?type=at10/2

Response:

{
    "ranking": [
        {
            "position": 7,
            "user_id": 12,
            "score": 34
        },
        {
            "position": 8,
            "user_id": 7,
            "score": 27
        },
        {
            "position": 9,
            "user_id": 9,
            "score": 24
        },
        {
            "position": 10,
            "user_id": 8,
            "score": 19
        },
        {
            "position": 11,
            "user_id": 4,
            "score": 2
        },
        {
            "position": 12,
            "user_id": 5,
            "score": -72
        }
    ]
}

Edge case: If you set your type as at1/3, you'll see the the top 1 user, and the 3 users next to her/him.


Environment Variables

ENV VAR DESCRIPTION DEFAULT
HOST service host 0.0.0.0
PORT service port 8884

Releases

No releases published

Packages

No packages published

Languages