saul / demofile

Node.js library for parsing Counter-Strike: Global Offensive demo files
https://demofile.dev
MIT License
485 stars 53 forks source link

Error on count rounds and player stats #135

Closed basmoura closed 3 years ago

basmoura commented 4 years ago

Describe the bug When I get the player stats like Kills, Deaths, Assists, and MPVs, some data differs from the game's scoreboard. The same happens with the rounds. My last demos, for example, the final result is 15x11 instead of 16x11.

Code to reproduce

// get score for ct and tr
  demoFile.gameEvents.on("round_officially_ended", e => {
      const teams = demoFile.teams;
      const terrorists = teams[2];
      const cts = teams[3];

      gameData.rounds = terrorists.score + cts.score
      gameData.tr_score = terrorists.score
      gameData.ct_score = cts.score
    });
// get player data
  demoFile.gameEvents.on("round_end", e => {
    let roundNumber = demoFile.gameRules.roundsPlayed - 1;
    let players = demoFile.players.map(p => p.userId)
    let player = ""
    let playerData = {}

    for (p of players) {
      player = demoFile.entities.getByUserId(p)

      if (player.steam64Id === '0') { continue; }

      playerData = {
        steam_id: player.steam64Id,
        player: player.name,
        kills: player.kills,
        assists: player.assists,
        deaths: player.deaths,
        mvps: player.mvps,
        score: player.score,
        side: ''
      }

      if (gameData.players.some(p => p.steam_id === player.steam64Id)) {
        let playerFound = gameData.players.find(p => p.steam_id === player.steam64Id)

        if (player.kills > playerFound.kills || player.deaths > playerFound.deaths || player.assists > playerFound.assists || player.mvps > playerFound.mvps) {
          gameData.players = gameData.players.filter(p => p.steam_id != player.steam64Id)
          gameData.players.push(playerData)
        }
      } else {
        gameData.players.push(playerData)
      }
    }

Expected behaviour The results for score should be 16x11 instead of 15x11 and the player stats differs from scoreboard

master117 commented 4 years ago

Demo files are very often missing events. You have to interpolate them in some way. There is nothing this library can do to fix this. The same happens with demoinfo and c# demoinfo.

saul commented 4 years ago

If this also happens with demoinfo, unfortunately there's nothing we can do here.

lucasreppewelander commented 4 years ago

@basmoura I don't think they are missing events, just that the score updates after the next round, which means a GOTV pro game is often closed before the new score have updated, take a look at this screenshot where I thought that I was missing the last round too.

Skärmavbild 2020-02-15 kl  14 57 07

but I actually got the player_death events for the last round too, only that the score on the teams entity hasn't updated before the GOTV was shut down.

let roundNumber = 1;
demoFile.gameEvents.on('player_death', e => {
    const attacker = demo.entities.getByUserId(e.attacker);
    const victim = demo.entities.getByUserId(e.userid);
    const weapon = e.weapon;
    console.log(roundNumber, ':', attacker.name, 'killed', victim.name, 'with', weapon);
});

demoFile.gameEvents.on('round_officially_ended', e => {
    roundNumber += 1;

    const teams = demoFile.teams;
    const terrorists = teams[2];
    const cts = teams[3];

    const rounds = terrorists.score + cts.score
    const tr_score = terrorists.score
    const ct_score = cts.score

    console.log(`ROUND NUMBER: ${rounds}`)
    console.log(`CT : ${ct_score} vs T : ${tr_score}`);
    console.log('\n');
});

demoFile.on('end', e => {
    console.log('CALLED END on demo');
});
saul commented 4 years ago

Instead of incrementing round count on round end, why not do it on round start (and start at 0)? Then you can treat the demo ending as end of the final round

ghost commented 4 years ago

Do you have idea for fix? (final score 16:0)

Code

let roundNumber = 1;

demoFile.gameEvents.on("round_start", e => {
    roundNumber += 1;

    const teams = demoFile.teams;
    const terrorists = teams[2];
    const cts = teams[3];

    const rounds = terrorists.score + cts.score
    const tr_score = terrorists.score
    const ct_score = cts.score

    console.log(`ROUND NUMBER: ${rounds}`)
    console.log(`CT : ${ct_score} vs T : ${tr_score}`);
    console.log('\n');
});

Output

ROUND NUMBER: 0
CT : 0 vs T : 0

ROUND NUMBER: 0
CT : 0 vs T : 0

ROUND NUMBER: 1
CT : 0 vs T : 1

ROUND NUMBER: 2
CT : 0 vs T : 2

ROUND NUMBER: 3
CT : 0 vs T : 3

ROUND NUMBER: 4
CT : 0 vs T : 4

ROUND NUMBER: 5
CT : 0 vs T : 5

ROUND NUMBER: 6
CT : 0 vs T : 6

ROUND NUMBER: 7
CT : 0 vs T : 7

ROUND NUMBER: 8
CT : 0 vs T : 8

ROUND NUMBER: 9
CT : 0 vs T : 9

ROUND NUMBER: 10
CT : 0 vs T : 10

ROUND NUMBER: 11
CT : 0 vs T : 11

ROUND NUMBER: 12
CT : 0 vs T : 12

ROUND NUMBER: 13
CT : 0 vs T : 13

ROUND NUMBER: 14
CT : 0 vs T : 14

ROUND NUMBER: 15
CT : 0 vs T : 15
saul commented 4 years ago

See my previous comment - you're not treating the demo ending as the end of the final round

ghost commented 4 years ago

See my previous comment - you're not treating the demo ending as the end of the final round

What should I put instead of round_start ?

saul commented 4 years ago

Something like:

let roundNumber = 1;

function logScores() {
  const teams = demoFile.teams;
  const terrorists = teams[2];
  const cts = teams[3];

  const rounds = terrorists.score + cts.score;
  const tr_score = terrorists.score;
  const ct_score = cts.score;

  console.log(`ROUND NUMBER: ${rounds}`);
  console.log(`CT : ${ct_score} vs T : ${tr_score}`);
  console.log("\n");
}

demoFile.gameEvents.on("round_start", (e) => {
  roundNumber += 1;
  logScores();
});

demoFile.on("end", (e) => {
  if (e.error) {
    console.error("Error during parsing:", e.error);
  } else {
    logScores();
  }
  console.log("Finished.");
});
ghost commented 4 years ago

Something like:

let roundNumber = 1;

function logScores() {
  const teams = demoFile.teams;
  const terrorists = teams[2];
  const cts = teams[3];

  const rounds = terrorists.score + cts.score;
  const tr_score = terrorists.score;
  const ct_score = cts.score;

  console.log(`ROUND NUMBER: ${rounds}`);
  console.log(`CT : ${ct_score} vs T : ${tr_score}`);
  console.log("\n");
}

demoFile.gameEvents.on("round_start", (e) => {
  roundNumber += 1;
  logScores();
});

demoFile.on("end", (e) => {
  if (e.error) {
    console.error("Error during parsing:", e.error);
  } else {
    logScores();
  }
  console.log("Finished.");
});

Genius thanks it's work :)