• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

project-slippi / slippi-js / 4382534950

pending completion
4382534950

Pull #123

github

GitHub
Merge d5ddd09c4 into cd8177915
Pull Request #123: [PR] Correctly Calculate Winners for Timeout

642 of 818 branches covered (78.48%)

Branch coverage included in aggregate %.

62 of 62 new or added lines in 3 files covered. (100.0%)

1785 of 2108 relevant lines covered (84.68%)

110070.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

58.97
/src/utils/getWinners.ts
1
import type { GameEndType, GameStartType, PlacementType, PostFrameUpdateType } from "../types";
2
import { GameEndMethod } from "../types";
11✔
3
import { exists } from "./exists";
11✔
4

5
export function getWinners(
11✔
6
  gameEnd: GameEndType,
7
  settings: Pick<GameStartType, "players" | "isTeams">,
8
  finalPostFrameUpdates: PostFrameUpdateType[],
9
): PlacementType[] {
10
  const { placements, gameEndMethod, lrasInitiatorIndex } = gameEnd;
3✔
11
  const { players, isTeams } = settings;
3✔
12

13
  if (gameEndMethod === GameEndMethod.NO_CONTEST || gameEndMethod === GameEndMethod.UNRESOLVED) {
3✔
14
    // The winner is the person who didn't LRAS
15
    if (exists(lrasInitiatorIndex) && players.length === 2) {
1✔
16
      const winnerIndex = players.find(({ playerIndex }) => playerIndex !== lrasInitiatorIndex)?.playerIndex;
2!
17
      if (exists(winnerIndex)) {
1✔
18
        return [
1✔
19
          {
20
            playerIndex: winnerIndex,
21
            position: 0,
22
          },
23
        ];
24
      }
25
    }
26

27
    return [];
×
28
  }
29

30
  if (gameEndMethod === GameEndMethod.TIME && players.length === 2) {
2!
31
    const nonFollowerUpdates = finalPostFrameUpdates.filter((pfu) => !pfu.isFollower);
×
32
    if (nonFollowerUpdates.length !== players.length) {
×
33
      return [];
×
34
    }
35

36
    const p1 = nonFollowerUpdates[0]!;
×
37
    const p2 = nonFollowerUpdates[1]!;
×
38
    if (p1.stocksRemaining! > p2.stocksRemaining!) {
×
39
      return [{ playerIndex: p1.playerIndex!, position: 0 }];
×
40
    } else if (p2.stocksRemaining! > p1.stocksRemaining!) {
×
41
      return [{ playerIndex: p2.playerIndex!, position: 0 }];
×
42
    }
43

44
    const p1Health = Math.trunc(p1.percent!);
×
45
    const p2Health = Math.trunc(p2.percent!);
×
46
    if (p1Health < p2Health) {
×
47
      return [{ playerIndex: p1.playerIndex!, position: 0 }];
×
48
    } else if (p2Health < p1Health) {
×
49
      return [{ playerIndex: p2.playerIndex!, position: 0 }];
×
50
    }
51

52
    // If stocks and percents were tied, no winner
53
    return [];
×
54
  }
55

56
  const firstPosition = placements.find((placement) => placement.position === 0);
4✔
57
  if (!firstPosition) {
2!
58
    return [];
×
59
  }
60

61
  const winningTeam = players.find(({ playerIndex }) => playerIndex === firstPosition.playerIndex)?.teamId ?? null;
4!
62
  if (isTeams && exists(winningTeam)) {
2✔
63
    return placements.filter((placement) => {
1✔
64
      const teamId = players.find(({ playerIndex }) => playerIndex === placement.playerIndex)?.teamId ?? null;
10!
65
      return teamId === winningTeam;
4✔
66
    });
67
  }
68

69
  return [firstPosition];
1✔
70
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc