Пример #1
0
        public void Read_MatchOnOurServer_ReturnsCorrectStatistics()
        {
            var demo = new Demo {
                FilePath = Path.Combine("TestData", @"auto0-20210103-190414-139014994-de_dust2-honigbiene_vs_waldfrosch.dem")
            };

            //Setting minimum number of rounds & players to 0 (different than during runtime) to allow reading this smaller demo file
            var demoReader = new DemoReader(new Match {
                Demo = demo
            }, 0, 0);

            demoReader.ReadHeader();
            demoReader.Read();

            Assert.Equal(0, demoReader.Match.CTScore);
            Assert.Equal(3, demoReader.Match.TScore);

            var expectedStatisticsAlex = demoReader.Match.PlayerResults.Single(x => x.SteamID == 76561198011775117);

            Assert.Equal(1, expectedStatisticsAlex.Kills);
            Assert.Equal(0, expectedStatisticsAlex.Deaths);
            Assert.Equal(3, expectedStatisticsAlex.Rounds);
            Assert.Equal(1, expectedStatisticsAlex.OneKill);
            Assert.Equal(1.096, expectedStatisticsAlex.HLTVScore);

            var expectedStatisticsFlo = demoReader.Match.PlayerResults.Single(x => x.SteamID == 76561197973591119);

            Assert.Equal(-1, expectedStatisticsFlo.Kills);
            Assert.Equal(2, expectedStatisticsFlo.Deaths);
            Assert.Equal(3, expectedStatisticsFlo.Rounds);
            Assert.Equal(0.091, expectedStatisticsFlo.HLTVScore);
        }
Пример #2
0
        public MainWindow()
        {
            InitializeComponent();

            m_Reader = Task.Run(() =>
            {
                var stream = File.Open("demos/cp_process_final.dem", FileMode.Open, FileAccess.Read);
                return(DemoReader.FromStream(stream));
            });

            m_Reader.ContinueWith(lastTask =>
            {
                lastTask.Result.Events.NewTick.Add(Events_NewTick);
                lastTask.Result.Events.NewTick.Add(UpdatePlayerStatuses);
                lastTask.Result.Events.NewTick.Add(UpdatePlayerPositions);

                lastTask.Result.Events.NewTick.Add(UpdateRocketPositions);

                lastTask.Result.Events.TempEntityCreated.Add(TempEntCreated);

                lastTask.Result.Events.GameEvent.Add(GameEventTriggered);

                progress.Dispatcher.Invoke(() => progress.Maximum = lastTask.Result.Header.m_PlaybackTicks.Value);

                lastTask.Result.SimulateDemo();
            });
        }
Пример #3
0
        public void Read_GameIsRestartedAfterMatchStarted_DoesNotCountEventsBeforeRealMatchStart()
        {
            var demo = new Demo {
                FilePath = Path.Combine("TestData", @"auto0-20210102-204730-1247575572-de_mirage-honigbiene_vs_waldfrosch.dem")
            };
            var demoReader = new DemoReader(new Match {
                Demo = demo
            });

            demoReader.ReadHeader();
            demoReader.Read();

            Assert.Equal(15, demoReader.Match.CTScore);
            Assert.Equal(15, demoReader.Match.TScore);

            var expectedStatisticsForSteamId = new List <MatchStatistics>
            {
                new MatchStatistics {
                    SteamID = 76561197984050254, Kills = 26, Deaths = 24, Rounds = 30
                },
                new MatchStatistics {
                    SteamID = 76561197973591119, Kills = 24, Deaths = 27, Rounds = 30
                },
                new MatchStatistics {
                    SteamID = 76561197978519504, Kills = 21, Deaths = 22, Rounds = 30
                },
                new MatchStatistics {
                    SteamID = 76561198011775117, Kills = 21, Deaths = 18, Rounds = 30
                },
                new MatchStatistics {
                    SteamID = 76561198011654217, Kills = 15, Deaths = 23, Rounds = 30
                },
                new MatchStatistics {
                    SteamID = 76561199045573415, Kills = 37, Deaths = 19, Rounds = 30
                },
                new MatchStatistics {
                    SteamID = 76561198258023370, Kills = 25, Deaths = 19, Rounds = 30
                },
                new MatchStatistics {
                    SteamID = 76561197995643389, Kills = 21, Deaths = 23, Rounds = 30
                },
                new MatchStatistics {
                    SteamID = 76561198031200891, Kills = 17, Deaths = 21, Rounds = 30
                },
                new MatchStatistics {
                    SteamID = 76561198053826525, Kills = 14, Deaths = 25, Rounds = 30
                }
            };

            foreach (var playerResult in demoReader.Match.PlayerResults)
            {
                var expected = expectedStatisticsForSteamId.Single(x => x.SteamID == playerResult.SteamID);
                Assert.Equal(expected.Kills, playerResult.Kills);
                Assert.Equal(expected.Deaths, playerResult.Deaths);
                Assert.Equal(expected.Rounds, playerResult.Rounds);
            }
        }
Пример #4
0
        public static void Run()
        {
            DefaultObservable <User>    observable = new DefaultObservable <User>();
            AbstractTaskObserver <User> observer   = new DemoTaskObserver();
            IReader <User> reader = new DemoReader();
            var            runner = new ObserverTaskRunner <User>(observable, observer, reader);

            // 开始运行
            runner.Run();
        }
Пример #5
0
        private void Demo(IProgress <string> progress)
        {
            progress.Report("Start");
            progress.Report($"Reading demo files from \"{Settings.DemosFolderPath}\" folder");

            var demoFileRepository = new DemoFileRepository(new MongoRepositoryFactory(new ConnectionStringFactory()));
            var demoRepository     = new BaseRepository(new MongoRepositoryFactory(new ConnectionStringFactory()));

            var demoReader = new DemoReader(Settings.DemosFolderPath, demoFileRepository, demoRepository,
                                            Config.CreateMapper(), progress);

            demoReader.Start(Settings.TimerInterval);
        }
Пример #6
0
        public void Read_OnlyFourRounds_CorrectStatistics()
        {
            var demo = new Demo {
                FilePath = Path.Combine("TestData", @"auto0-20201222-213144-349508145-de_inferno-honigbiene_vs_waldfrosch.dem")
            };
            var demoReader = new DemoReader(new Match {
                Demo = demo
            }, 0, 0);

            demoReader.ReadHeader();
            demoReader.Read();

            Assert.Equal(2, demoReader.Match.CTScore);
            Assert.Equal(2, demoReader.Match.TScore);
            Assert.Equal(4, demoReader.Match.Rounds);

            var expectedStatisticsForSteamId = new List <MatchStatistics>
            {
                new MatchStatistics {
                    SteamID = 76561198011775117, Kills = 1, Deaths = 3, Rounds = 4, OneKill = 0, TwoKill = 1
                },
                new MatchStatistics {
                    SteamID = 76561197984050254, Kills = 1, Deaths = 4, Rounds = 4, OneKill = 1
                },
                new MatchStatistics {
                    SteamID = 76561198053826525, Kills = -1, Deaths = 4, Rounds = 4
                },
                new MatchStatistics {
                    SteamID = 76561199045573415, Kills = 8, Deaths = 1, Rounds = 4, OneKill = 2, TwoKill = 0, ThreeKill = 2
                },
                new MatchStatistics {
                    SteamID = 76561197973591119, Kills = 0, Deaths = 2, Rounds = 4
                },
                new MatchStatistics {
                    SteamID = 76561198258023370, Kills = -1, Deaths = 2, Rounds = 4, OneKill = 1
                }
            };

            foreach (var playerResult in demoReader.Match.PlayerResults)
            {
                var expected = expectedStatisticsForSteamId.Single(x => x.SteamID == playerResult.SteamID);
                Assert.Equal(expected.Kills, playerResult.Kills);
                Assert.Equal(expected.Deaths, playerResult.Deaths);
                Assert.Equal(expected.Rounds, playerResult.Rounds);
                Assert.Equal(expected.OneKill, playerResult.OneKill);
                Assert.Equal(expected.TwoKill, playerResult.TwoKill);
                Assert.Equal(expected.ThreeKill, playerResult.ThreeKill);
                Assert.Equal(expected.FourKill, playerResult.FourKill);
                Assert.Equal(expected.FiveKill, playerResult.FiveKill);
            }
        }
Пример #7
0
        public void Parse_MatchHasDifferentNumberOfRoundsPreset_ThrowsInconsistentStatistics()
        {
            var demo = new Demo {
                FilePath = Path.Combine("TestData", @"auto0-20210103-190414-139014994-de_dust2-honigbiene_vs_waldfrosch.dem")
            };
            var match = new Match {
                Demo = demo, Rounds = 6
            };

            //Setting minimum number of rounds & players to 0 (different than during runtime) to allow reading this smaller demo file
            var demoReader = new DemoReader(match, 0, 0);

            Assert.Throws <InconsistentStatisticsException>(() => demoReader.Parse());
        }
Пример #8
0
        public void Read_GameOnOurServer_ReturnsCorrectScores(string demoFileName, int CTScore, int TScore)
        {
            var demo = new Demo {
                FilePath = Path.Combine("TestData", demoFileName)
            };

            var demoReader = new DemoReader(new Match {
                Demo = demo
            }, 0, 0);

            var match = demoReader.Parse();

            Assert.Equal(CTScore, match.CTScore);
            Assert.Equal(TScore, match.TScore);
        }
Пример #9
0
        public void ProcessNewMatches(object state)
        {
            var newMatches         = new List <Match>();
            var blacklistedMatches = new List <Match>();
            var newDemoFiles       = Directory.EnumerateFiles(myDemoWatchFolder).Where(x => x.EndsWith(".dem"));

            myLogger.LogDebug($"Found {newDemoFiles.Count()} new demo files in the watch folder");

            var demoBackuper = new DemoBackuper(myLoggerFactory.CreateLogger <DemoBackuper>());

            foreach (var demoFile in newDemoFiles)
            {
                var match = new Match {
                    Demo = new Demo {
                        FilePath = demoFile
                    }, Date = File.GetCreationTime(demoFile)
                };

                try
                {
                    using var demoReader = new DemoReader(match);
                    demoReader.ReadHeader();
                    demoReader.Read();
                    match = demoReader.Match;
                    myLogger.LogTrace($"Finished analyzing demo file {Path.GetFileName(demoFile)}");
                    newMatches.Add(match);
                }
                catch (DemoReaderException e)
                {
                    match.Id     += Guid.NewGuid().ToString();
                    match.Demo.Id = match.Id;
                    myLogger.LogWarning($"Analyzing demo from watch folder ({Path.GetFileName(demoFile)}) failed: {e.Message}. Adding to repository (id: {match.Id}) without stats -> blacklisted.");
                    match.PlayerResults.Clear();
                    match.CTScore = -1;
                    match.TScore  = -1;
                    blacklistedMatches.Add(match);
                }

                BackupDemo(match.Demo, demoBackuper);
            }

            using var scope = myScopeFactory.CreateScope();
            myLogger.LogTrace($"Getting match repository to add {newMatches.Count} new matches and blacklist {blacklistedMatches.Count} demos.");
            var matchRepository = scope.ServiceProvider.GetRequiredService <MatchRepository>();

            matchRepository.AddMatchesAndSave(newMatches);
            matchRepository.AddMatchesAndSave(blacklistedMatches);
        }
Пример #10
0
        public void Read_MatchMakingGame_ReturnsCorrectMatchType(string demoFileName, CompetitiveMatchType expectedMatchType)
        {
            var demo = new Demo {
                FilePath = Path.Combine("TestData", demoFileName)
            };

            var demoReader = new DemoReader(new Match {
                Demo = demo
            }, 0, 0);

            var match = demoReader.Parse();

            foreach (var matchStatistics in match.PlayerResults)
            {
                Assert.Equal(expectedMatchType, matchStatistics.MatchType);
            }
        }
Пример #11
0
        public void Read_MatchMakingGame_ReturnsCorrectPlayerHighestAndLowestHLTV(string demoFileName, string highestHLTVPlayerSteamId, string lowestHLTVPlayerSteamId)
        {
            var demo = new Demo {
                FilePath = Path.Combine("TestData", demoFileName)
            };

            var demoReader = new DemoReader(new Match {
                Demo = demo
            }, 0, 0);

            var match = demoReader.Parse();

            var orderedByDescendingHLTV = match.PlayerResults.OrderByDescending(x => x.HLTVScore);

            Assert.Equal(long.Parse(highestHLTVPlayerSteamId), orderedByDescendingHLTV.First().SteamID);
            Assert.Equal(long.Parse(lowestHLTVPlayerSteamId), orderedByDescendingHLTV.Last().SteamID);
        }
Пример #12
0
        static void Main(string[] args)
        {
            using (var stream = File.Open(@"D:\Steam\steamapps\common\Team Fortress 2\tf\demos\testdemo.dem", FileMode.Open, FileAccess.Read))
            {
                Console.WriteLine("Parsing test demo file...");

                DateTime   start  = DateTime.Now;
                DemoReader reader = DemoReader.FromStream(stream);
                DateTime   end    = DateTime.Now;

                Console.WriteLine("Finished parsing test demo file in {0:N1}ms.", (end - start).TotalMilliseconds);

                reader.SimulateDemo();

                Console.WriteLine("Finished simulating demo.");
                Console.ReadLine();
            }
        }
Пример #13
0
        public void Read_GameIsRestartedAfterMatchStarted_DoesNotCountRoundsBeforeRealMatchStart()
        {
            var demo = new Demo {
                FilePath = Path.Combine("TestData", @"auto0-20210102-225615-1235223714-de_dust2-honigbiene_vs_waldfrosch.dem")
            };
            var demoReader = new DemoReader(new Match {
                Demo = demo
            });

            demoReader.ReadHeader();
            demoReader.Read();

            Assert.Equal(30, demoReader.Match.Rounds);
            foreach (var player in demoReader.Match.PlayerResults)
            {
                Assert.Equal(30, player.Rounds);
            }
        }
Пример #14
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="LocalDemo" /> class.
        /// </summary>
        /// <param name="path">The path to the demo file.</param>
        /// <param name="version">The version of the demo.</param>
        public LocalDemo(string path, GameType version)
        {
            Path    = path;
            Version = version;

            try
            {
                using (var stream = Open())
                {
                    var reader = new DemoReader(stream, Version);

                    var config = reader.ReadConfiguration();

                    config.TryGetValue("mapname", out var map);
                    config.TryGetValue("fs_game", out var mod);
                    config.TryGetValue("g_gametype", out var gameType);
                    config.TryGetValue("sv_hostname", out var server);
                    config.TryGetValue("sv_referencedIwdNames", out var iwdNames);
                    config.TryGetValue("sv_referencedFFNames", out var ffNames);

                    if (!string.IsNullOrWhiteSpace(mod) && mod.ToLower().StartsWith("mods/"))
                    {
                        mod = mod.Substring(5);
                    }

                    Map      = map;
                    Mod      = mod;
                    GameType = gameType;
                    Server   = server;
                    IWDs     = iwdNames == null ? new string[0] : iwdNames.Split(' ');
                    FFs      = ffNames == null
                        ? new string[0]
                        : ffNames.Split(' ').Select(ff =>
                    {
                        // Change path of usermaps files to full paths.
                        // e.g. usermaps/mp_caen2_load -> usermaps/mp_caen2/mp_caen2_load

                        if (!ff.StartsWith("usermaps/mp_"))
                        {
                            return(ff);
                        }

                        var mapName = ff.Split('/').Last();
                        if (mapName.EndsWith("_load"))
                        {
                            mapName = mapName.Substring(0, mapName.Length - 5);
                            return(string.Format("usermaps/{0}/{0}_load", mapName));
                        }

                        return(string.Format("usermaps/{0}/{0}", mapName));
                    });
                }
            }
            catch (Exception)
            {
                Map          = "???";
                Mod          = "???";
                GameType     = "???";
                Server       = "File corrupted!";
                IWDs         = new string[0];
                FFs          = new string[0];
                _isCorrupted = true;
            }
        }
Пример #15
0
        private void ProcessNewMatches(GameCoordinatorClient gameCoordinatorClient, ShareCodeRepository shareCodeRepository, MatchRepository matchRepository)
        {
            var newSharingCodes = shareCodeRepository.GetRetryableBatch(5);

            if (!newSharingCodes.Any())
            {
                return;
            }

            myLogger.LogDebug($"Retrieved {newSharingCodes.Count} new sharing codes: {string.Join(", ", newSharingCodes.Select(x => x.Code))}");
            var newMatches     = new List <Match>();
            var demoDownloader = new DemoDownloader(myLoggerFactory.CreateLogger <DemoDownloader>());
            var demoBackuper   = new DemoBackuper(myLoggerFactory.CreateLogger <DemoBackuper>());

            foreach (var sharingCode in newSharingCodes)
            {
                var demo = CreateNewDemoForShareCode(sharingCode);

                try
                {
                    var match = gameCoordinatorClient.GetMatchInfo(demo);
                    myLogger.LogTrace($"Got match details for sharing code {sharingCode.Code}");

                    match.Demo.FilePath = demoDownloader.DownloadAndDecompressDemo(match.Demo.DownloadURL);
                    myLogger.LogTrace($"Downloaded and decompressed demo file for sharing code {sharingCode.Code}");

                    using var demoReader = new DemoReader(match, 0, 0);
                    match = demoReader.Parse();

                    myLogger.LogTrace($"Finished analyzing demo file for sharing code {sharingCode.Code}");
                    newMatches.Add(match);
                }
                catch (GameCoordinatorException)
                {
                    myLogger.LogWarning($"Couldn't get download url for sharing code {sharingCode.Code}. See previous logs/exceptions for explanation. Continuing.");
                    continue;
                }
                catch (DemoDownloaderException exception)
                {
                    myLogger.LogWarning($"Demo downloading or decompressing failed: {exception.Message} for sharing code {sharingCode.Code}.");
                    continue;
                }
                catch (DemoReaderException e)
                {
                    myLogger.LogWarning($"Analyzing demo for share code {sharingCode.Code} failed: {e.Message}");
                    demo.State = DemoState.ParseFailure;
                    continue;
                }
                finally
                {
                    TryBackupDemo(demo, demoBackuper);
                }
            }

            myLogger.LogDebug($"Downloaded and analyzed {newMatches.Count} new matches (from {newSharingCodes.Count} new sharing codes).");
            myLogger.LogTrace($"Saving {newMatches.Count} new matches to repository.");

            var successfullySavedMatches = matchRepository.AddMatchesAndSave(newMatches);

            shareCodeRepository.RemoveCodes(successfullySavedMatches.Select(x => x.Demo.ShareCode));
        }
Пример #16
0
 public DemoAdapter(ILogger <DemoAdapter> logger)
 {
     this.logger = logger;
     this.state  = new DemoMachineState();
     this.reader = new DemoReader();
 }