Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ are not the only possible solutions to these cases.
* [Number Challenges 🔢](src/test/java/pl/mperor/interview/tasks/challenge/NumberChallengeTest.java)
7. [Quiz Questions ❔](src/test/java/pl/mperor/interview/tasks/QuizQuestionsTest.java)
8. [Wolf 🐺 & Sheep 🐑](src/test/java/pl/mperor/interview/tasks/exception/WolfFullAndSheepWholeTest.java)
9. [Player Ranking System 🏆](src/test/java/pl/mperor/interview/tasks/ranking/PlayerRankingSystemTest.java)

## Sources 🔗

Expand Down
13 changes: 13 additions & 0 deletions src/main/java/pl/mperor/interview/tasks/ranking/Player.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package pl.mperor.interview.tasks.ranking;

import java.util.Comparator;

public record Player(String name, int score) implements Comparable<Player> {

@Override
public int compareTo(Player other) {
return Comparator.comparingInt(Player::score).reversed()
.thenComparing(Player::name)
.compare(this, other);
}
}
68 changes: 68 additions & 0 deletions src/main/java/pl/mperor/interview/tasks/ranking/Ranking.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package pl.mperor.interview.tasks.ranking;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;

class Ranking<T> {

private final TreeSet<T> items;

private Ranking(Comparator<T> comparator, T... varargs) {
this.items = new TreeSet<>(comparator);
items.addAll(Arrays.asList(varargs));
}

public void add(T item) {
items.add(item);
}

public void replace(Predicate<T> filter, T item) {
deleteIf(filter);
add(item);
}

public void deleteIf(Predicate<T> filter) {
items.removeIf(filter);
}

public T getLeader() {
return items.first();
}

public List<T> list() {
return items.stream().toList();
}

public static <T extends Comparable<T>> Ranking<T> of(T... varargs) {
return new Ranking<>(Comparable::compareTo, varargs);
}

public static <T> Ranking<T> of(Comparator<T> comparator, T... varargs) {
return new Ranking<>(comparator, varargs);
}

public String format(BiFunction<Integer, T, String> formatter) {
return format(formatter, Function.identity());
}

public <R> String format(BiFunction<Integer, T, String> formatter, Function<T, R> positionUniqueValueMapper) {
int counter = 0;
StringBuilder builder = new StringBuilder();
T previous = null;
for (T item : items) {
if (previous == null || !positionUniqueValueMapper.apply(item).equals(positionUniqueValueMapper.apply(previous))) {
counter++;
}
String formatted = formatter.apply(counter, item);
builder.append(formatted);
previous = item;
}
return builder.toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package pl.mperor.interview.tasks.ranking;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Objects;

/**
* Task: Player Ranking System 🏆
*
* <p><b>Description:</b>
* Your task is to develop a ranking system for players in a game using Java.
* The application should allow adding players, updating their scores, and displaying the ranking
* in a sorted manner based on their scores.
*
* <p><b>Requirements:</b>
* - Implement a `Player` class with attributes: `name` (String) and `score` (int).
* - Create a ranking system that maintains a collection of players and sorts them dynamically.
* - Implement methods for:
* - Adding a new player to the ranking.
* - Updating the score of an existing player.
* - Displaying the current ranking in descending order of scores.
*
* <p><b>Conditions:</b>
* - The ranking should always be sorted from the highest to the lowest score.
* - If a player's score is updated, their position in the ranking should be adjusted accordingly.
* - Player names should be unique.
*
* <p><b>Example:</b>
*
* <p>Given the following players:
* <pre>
* Player("Alice", 1200)
* Player("Bob", 1500)
* Player("Charlie", 1300)
* Player("Zeus", 1300)
* </pre>
* <p>
* The ranking should be displayed as:
* <pre>
* 1. Bob - 1500 pts
* 2. Charlie - 1300 pts
* 2. Zeus - 1300 pts
* 3. Alice - 1200 pts
* </pre>
* <p>
* If Alice's score is increased by 400 points, the updated ranking should be:
* <pre>
* 1. Alice - 1600 pts
* 2. Bob - 1500 pts
* 3. Charlie - 1300 pts
* 3. Zeus - 1300 pts
* </pre>
*
* <p><b>Additional Points:</b>
* - Use a suitable data structure (e.g., `TreeSet`, `PriorityQueue`, or `List`).
* - Consider optimizing performance for frequent updates.
* - Implement test cases to verify correct ranking behavior.
*
* <p><b>Expected Points:</b>
* - <b>Code Quality:</b> Is the code well-structured and easy to understand?
* - <b>Correctness:</b> Does the ranking update correctly after score changes?
* - <b>Performance:</b> Is the chosen data structure efficient for ranking operations?
*/
public class PlayerRankingSystemTest {

private Ranking<Player> ranking;

private Player bob;
private Player charlie;
private Player zeus;
private Player alice;

@BeforeEach
void setUp() {
bob = new Player("Bob", 1500);
charlie = new Player("Charlie", 1300);
zeus = new Player("Zeus", 1300);
alice = new Player("Alice", 1200);
ranking = Ranking.of(
alice,
bob,
charlie,
zeus
);
}

@Test
public void shouldReturnLeaderFromPlayerRanking() {
Assertions.assertEquals(bob, ranking.getLeader());
}

@Test
public void shouldDisplayRankingWithPlayers() {
var formatted = ranking.format((position, player) ->
"%d. %s - %d pts%n".formatted(position, player.name(), player.score()), Player::score);
System.out.println(formatted);
Assertions.assertLinesMatch("""
1. Bob - 1500 pts
2. Charlie - 1300 pts
2. Zeus - 1300 pts
3. Alice - 1200 pts
""".lines(), formatted.lines());
}

@Test
public void shouldAllowIncreasePlayerScore() {
alice = new Player(alice.name(), alice.score() + 400);
ranking.replace(player -> alice.name().equals(player.name()), alice);
Assertions.assertTrue(Objects.deepEquals(List.of(
alice,
bob,
charlie,
zeus
), ranking.list()));
}

}