> For the complete documentation index, see [llms.txt](https://k0ssek-scripts.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://k0ssek-scripts.gitbook.io/docs/scripts/dart-game/skill-and-elo.md).

# Skill & Elo

XP, levels and how the rating is calculated.

Every player has a level, an XP total, a best score and an Elo rating. All of them are saved in the `darts_stats` table and shown in the lobby.

## XP

XP is awarded when a match ends, for everything the player did in that match.

| Setting         | Default | Awarded for                               |
| --------------- | ------- | ----------------------------------------- |
| `XpPerWin`      | 80      | Winning the match                         |
| `XpPerThrow`    | 2       | Each dart thrown, whatever it scored      |
| `XpPerBullseye` | 25      | Each bullseye (the inner bull, 50 points) |

```lua
Config.Skill = {
    MaxLevel          = 50,
    XpPerWin          = 80,
    XpPerThrow        = 2,
    XpPerBullseye     = 25,
    MinSwayMultiplier = 0.3,
}
```

Example: a player who threw 24 darts, hit 2 bullseyes and won the match gets 24 x 2 + 2 x 25 + 80 = 178 XP.

Other resources can award XP too, with the [`AddPlayerXP`](/docs/scripts/dart-game/exports.md) export.

## Levels

A player starts at level 1 and reaches a level when their total XP is at least `floor(100 x level^1.5)`.

| Level | Total XP needed |
| ----- | --------------- |
| 2     | 282             |
| 5     | 1,118           |
| 10    | 3,162           |
| 20    | 8,944           |
| 30    | 16,431          |
| 40    | 25,298          |
| 50    | 35,355          |

`MaxLevel` is the last level. XP keeps adding up after it.

### What a level does

A higher level means less sway while aiming. The level multiplier goes in a straight line from 1.0 at level 1 to `MinSwayMultiplier` at `MaxLevel`:

```
sway = Config.AimZone.BaseSway x difficulty swayMultiplier x level multiplier
```

With the defaults, a level 50 player has 30% of the sway of a level 1 player.

### Tuning

* Raise `MinSwayMultiplier` (for example to `0.5`) to keep the game harder for high-level players.
* Lower `XpPerWin` and `XpPerThrow` to slow levelling down.
* Lower `Config.AimZone.BaseSway` to make aiming easier for everyone.

## Best Score

Best Score is the most points a player has scored in a single turn, across all their matches. With three darts per turn the highest possible value is 180.

A dart that busts in Reach Zero scores nothing, so it adds nothing to the turn.

## Elo

The rating changes only when a match ends with exactly two players in it. Solo matches and matches with three or more players give XP but leave the rating alone.

The new rating is shown in the lobby panel as soon as the match ends.

```lua
Config.Elo = {
    Default = 1000,
    KFactor = {
        beginner     = 48,
        intermediate = 32,
        experienced  = 16,
    },
}
```

### K-factor

The K-factor sets how many points one match can move a rating. It depends on how many games the player has played:

| Games played  | K-factor            |
| ------------- | ------------------- |
| Fewer than 10 | `beginner` (48)     |
| 10 to 49      | `intermediate` (32) |
| 50 or more    | `experienced` (16)  |

New players move quickly to the rating that fits them; experienced players have a steadier rating.

### Formula

```
expectedWinner = 1 / (1 + 10^((loserElo - winnerElo) / 400))
expectedLoser  = 1 - expectedWinner

newWinnerElo = winnerElo + winnerK x (1 - expectedWinner)
newLoserElo  = loserElo  - loserK  x expectedLoser
```

Results are rounded down, and a rating never goes below 100.

## The darts\_stats table

| Column          | Description                                     |
| --------------- | ----------------------------------------------- |
| `identifier`    | The player's framework identifier (primary key) |
| `player_name`   | Name the player last played under               |
| `level`         | Current level                                   |
| `xp`            | Total XP                                        |
| `games_played`  | Matches finished                                |
| `games_won`     | Matches won                                     |
| `highest_score` | Best Score: most points scored in a single turn |
| `elo`           | Current rating                                  |

A row is created the first time a player's stats are needed, and updated at the end of every match.
