Skip to content

Commit 31b8263

Browse files
authored
Merge pull request #6 from Heroes-Profile/PreMatch
Prematch integration
2 parents be165e4 + bce2d20 commit 31b8263

13 files changed

+319
-10
lines changed

Heroesprofile.Uploader.Common.Test/ManagerTests.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public async Task InitialFilesStartInOrder()
6666
}
6767
});
6868

69-
manager.Start(new NoNewFilesMonitor(), new MockAnalizer(), uploadTester);
69+
manager.Start(new NoNewFilesMonitor(), new PreMatchNoNewFilesMonitor(), new MockAnalizer(), uploadTester);
7070
await done;
7171
}
7272

@@ -106,7 +106,7 @@ public async Task InitialFilesEndInorder() {
106106
}
107107
});
108108

109-
manager.Start(new NoNewFilesMonitor(), new MockAnalizer(), uploadTester);
109+
manager.Start(new NoNewFilesMonitor(), new PreMatchNoNewFilesMonitor(), new MockAnalizer(), uploadTester);
110110
await done;
111111
}
112112

@@ -131,7 +131,7 @@ public async Task AllInitialFilesProcessed()
131131
}
132132
});
133133

134-
manager.Start(new NoNewFilesMonitor(), new MockAnalizer(), uploadTester);
134+
manager.Start(new NoNewFilesMonitor(), new PreMatchNoNewFilesMonitor(), new MockAnalizer(), uploadTester);
135135
var finished = await Task.WhenAny(Task.Delay(4000), done.Task);
136136
await finished;
137137
Assert.AreEqual(3, uploadsSeen);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace Heroesprofile.Uploader.Common.Test
6+
{
7+
public partial class ManagerTests
8+
{
9+
private class PreMatchNoNewFilesMonitor : PreMatchIMonitor
10+
{
11+
public event EventHandler<EventArgs<string>> TempReplayCreated;
12+
public event EventHandler<EventArgs<string>> StormSaveCreated;
13+
public event EventHandler<EventArgs<string>> TempBattleLobbyCreated;
14+
public void Start() { }
15+
public void Stop() { }
16+
}
17+
}
18+
}

Heroesprofile.Uploader.Common/Heroesprofile.Uploader.Common.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<Configurations>Debug;Release</Configurations>
66
<AssemblyName>Heroesprofile.Uploader.Common</AssemblyName>
77
<RootNamespace>Heroesprofile.Uploader.Common</RootNamespace>
8+
<Version>1.0.4</Version>
89
</PropertyGroup>
910

1011
<ItemGroup>

Heroesprofile.Uploader.Common/Manager.cs

+170-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@
1313
using System.Diagnostics;
1414
using Heroes.ReplayParser;
1515
using System.Collections.Concurrent;
16+
using System.Net.Http;
17+
using Newtonsoft.Json;
18+
using MpqBattlelobby = Heroes.ReplayParser.MPQFiles.StandaloneBattleLobbyParser;
19+
using MpqHeader = Heroes.ReplayParser.MPQFiles.MpqHeader;
20+
using MpqAttributeEvents = Heroes.ReplayParser.MPQFiles.ReplayAttributeEvents;
21+
using MpqDetails = Heroes.ReplayParser.MPQFiles.ReplayDetails;
22+
//using MpqGameEvents = Heroes.ReplayParser.MPQFiles.ReplayGameEvents;
23+
using MpqInitData = Heroes.ReplayParser.MPQFiles.ReplayInitData;
24+
//using MpqMessageEvents = Heroes.ReplayParser.MPQFiles.ReplayMessageEvents;
25+
//using MpqResumableEvents = Heroes.ReplayParser.MPQFiles.ReplayResumableEvents;
26+
using MpqTrackerEvents = Heroes.ReplayParser.MPQFiles.ReplayTrackerEvents;
27+
using Statistics = Heroes.ReplayParser.Statistics;
28+
//using GameEventType = Heroes.ReplayParser.MPQFiles.GameEventType;
29+
1630

1731
namespace Heroesprofile.Uploader.Common
1832
{
@@ -36,9 +50,12 @@ public class Manager : INotifyPropertyChanged
3650
private IUploader _uploader;
3751
private IAnalyzer _analyzer;
3852
private IMonitor _monitor;
53+
private PreMatchIMonitor _prematch_monitor;
3954

4055
public event PropertyChangedEventHandler PropertyChanged;
4156

57+
private int prematch_id = 0;
58+
public bool PreMatchPage { get; set; }
4259
private string _status = "";
4360
/// <summary>
4461
/// Current uploader status
@@ -91,7 +108,7 @@ public Manager(IReplayStorage storage)
91108
/// <summary>
92109
/// Start uploading and watching for new replays
93110
/// </summary>
94-
public async void Start(IMonitor monitor, IAnalyzer analyzer, IUploader uploader)
111+
public async void Start(IMonitor monitor, PreMatchIMonitor prematch_monitor, IAnalyzer analyzer, IUploader uploader)
95112
{
96113
if (_initialized) {
97114
return;
@@ -101,19 +118,116 @@ public async void Start(IMonitor monitor, IAnalyzer analyzer, IUploader uploader
101118
_uploader = uploader;
102119
_analyzer = analyzer;
103120
_monitor = monitor;
121+
_prematch_monitor = prematch_monitor;
104122

105123
var replays = ScanReplays();
106124
Files.AddRange(replays);
107125
replays.Where(x => x.UploadStatus == UploadStatus.None).Reverse().Map(x => processingQueue.Add(x));
108126

127+
128+
109129
_monitor.ReplayAdded += async (_, e) => {
110130
await EnsureFileAvailable(e.Data, 3000);
111131
var replay = new ReplayFile(e.Data);
112132
Files.Insert(0, replay);
113133
processingQueue.Add(replay);
134+
if (PreMatchPage) {
135+
_prematch_monitor.Start();
136+
}
114137
};
115138
_monitor.Start();
116139

140+
141+
_prematch_monitor.TempBattleLobbyCreated += async (_, e) => {
142+
if (PreMatchPage) {
143+
prematch_id = 0;
144+
_prematch_monitor.Stop();
145+
Thread.Sleep(1000);
146+
var tmpPath = Path.GetTempFileName();
147+
await SafeCopy(e.Data, tmpPath, true);
148+
byte[] bytes = System.IO.File.ReadAllBytes(tmpPath);
149+
Replay replay = MpqBattlelobby.Parse(bytes);
150+
await runPreMatch(replay);
151+
}
152+
};
153+
_prematch_monitor.Start();
154+
155+
156+
/*
157+
_prematch_monitor.StormSaveCreated += async (_, e) => {
158+
var tmpPath = Path.GetTempFileName();
159+
await SafeCopy(e.Data, tmpPath, true);
160+
var replay = new Replay();
161+
162+
MpqHeader.ParseHeader(replay, e.Data);
163+
164+
using (var archive = new Foole.Mpq.MpqArchive(tmpPath)) {
165+
archive.AddListfileFilenames();
166+
167+
168+
//Gets Players
169+
MpqDetails.Parse(replay, DataParser.GetMpqFile(archive, "save.details"), true);
170+
171+
//Gets which Heroes each player played
172+
if (archive.FileExists("replay.attributes.events")) {
173+
MpqAttributeEvents.Parse(replay, DataParser.GetMpqFile(archive, "replay.attributes.events"));
174+
}
175+
176+
177+
//Get Game Mode
178+
if (archive.FileExists("save.initData")) {
179+
MpqInitData.Parse(replay, DataParser.GetMpqFile(archive, "save.initData"));
180+
}
181+
182+
////Fails
183+
//
184+
//if (archive.FileExists("replay.game.events")) {
185+
// MpqGameEvents.Parse(DataParser.GetMpqFile(archive, "replay.game.events"), replay.Players, replay.ReplayBuild, replay.ReplayVersionMajor, false);
186+
//}
187+
//
188+
//
189+
190+
//
191+
//
192+
////Not Needed
193+
//
194+
//if (archive.FileExists("replay.message.events")) {
195+
// MpqMessageEvents.Parse(replay, DataParser.GetMpqFile(archive, "replay.message.events"));
196+
//}
197+
//
198+
//
199+
////Fails
200+
//
201+
//if (archive.FileExists("replay.resumable.events")) {
202+
// MpqResumableEvents.Parse(replay, DataParser.GetMpqFile(archive, "replay.resumable.events"));
203+
//}
204+
205+
206+
207+
for (int i = 0; i < replay.Players.Length; i++) {
208+
replay.Players[i].Talents = new Talent[7];
209+
for (int j = 0; j < replay.Players[i].Talents.Length; j++) {
210+
replay.Players[i].Talents[j] = new Talent();
211+
}
212+
}
213+
214+
if (archive.FileExists("replay.tracker.events")) {
215+
replay.TrackerEvents = MpqTrackerEvents.Parse(DataParser.GetMpqFile(archive, "replay.tracker.events"));
216+
}
217+
218+
219+
Statistics.Parse(replay);
220+
221+
}
222+
223+
224+
await updatePreMatch(replay);
225+
};
226+
*/
227+
//_prematch_monitor.Start();
228+
229+
230+
117231
_analyzer.MinimumBuild = await _uploader.GetMinimumBuild();
118232

119233
for (int i = 0; i < MaxThreads; i++) {
@@ -127,6 +241,42 @@ public void Stop()
127241
processingQueue.CompleteAdding();
128242
}
129243

244+
private async Task runPreMatch(Replay replayData)
245+
{
246+
HttpClient client = new HttpClient();
247+
var values = new Dictionary<string, string>
248+
{
249+
{ "data", JsonConvert.SerializeObject(replayData.Players) },
250+
};
251+
252+
var content = new FormUrlEncodedContent(values);
253+
254+
var response = await client.PostAsync("https://www.heroesprofile.com/PreMatch/", content);
255+
256+
var responseString = await response.Content.ReadAsStringAsync();
257+
258+
259+
prematch_id = Convert.ToInt32(responseString);
260+
261+
System.Diagnostics.Process.Start("https://www.heroesprofile.com/PreMatch/Results/?prematchID=" + prematch_id);
262+
}
263+
264+
private async Task updatePreMatch(Replay replayData)
265+
{
266+
HttpClient client = new HttpClient();
267+
var values = new Dictionary<string, string>
268+
{
269+
{ "prematch_id", prematch_id.ToString() },
270+
{ "game_type", replayData.GameMode.ToString() },
271+
{ "game_map", replayData.Map.ToString() },
272+
{ "data", JsonConvert.SerializeObject(replayData.Players) },
273+
};
274+
275+
var content = new FormUrlEncodedContent(values);
276+
277+
var response = await client.PostAsync("https://www.heroesprofile.com/PreMatch/Update", content);
278+
}
279+
130280
private async Task UploadLoop()
131281
{
132282
while (await processingQueue.OutputAvailableAsync()) {
@@ -248,5 +398,24 @@ private bool ShouldDelete(ReplayFile file, Replay replay)
248398
DeleteAfterUpload.HasFlag(DeleteFiles.StormLeague) && replay.GameMode == GameMode.StormLeague
249399
);
250400
}
401+
private static async Task SafeCopy(string source, string dest, bool overwrite)
402+
{
403+
var watchdog = 10;
404+
var retry = false;
405+
do {
406+
try {
407+
File.Copy(source, dest, overwrite);
408+
retry = false;
409+
}
410+
catch (Exception ex) {
411+
Debug.WriteLine($"Failed to copy ${source} to ${dest}. Counter at ${watchdog} CAUSED BY ${ex}");
412+
if (watchdog <= 0) {
413+
throw;
414+
}
415+
retry = true;
416+
}
417+
await Task.Delay(1000);
418+
} while (watchdog-- > 0 && retry);
419+
}
251420
}
252421
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Heroesprofile.Uploader.Common
5+
{
6+
public interface PreMatchIMonitor
7+
{
8+
event EventHandler<EventArgs<string>> TempBattleLobbyCreated;
9+
event EventHandler<EventArgs<string>> StormSaveCreated;
10+
void Start();
11+
void Stop();
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using NLog;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace Heroesprofile.Uploader.Common
10+
{
11+
public class PreMatchMonitor : PreMatchIMonitor
12+
{
13+
private static Logger _log = LogManager.GetCurrentClassLogger();
14+
protected readonly string BattleLobbyTempPath = Path.Combine(Path.GetTempPath(), @"Heroes of the Storm\");
15+
protected readonly string StormSavePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"Heroes of the Storm\Accounts");
16+
protected FileSystemWatcher _battlelobby_watcher;
17+
protected FileSystemWatcher _stormsave_watcher;
18+
19+
/// <summary>
20+
/// Fires when a new replay file is found
21+
/// </summary>
22+
public event EventHandler<EventArgs<string>> TempBattleLobbyCreated;
23+
public event EventHandler<EventArgs<string>> StormSaveCreated;
24+
protected virtual void OnBattleLobbyAdded(string path)
25+
{
26+
_log.Debug($"Detected new temp prematch replay: {path}");
27+
TempBattleLobbyCreated?.Invoke(this, new EventArgs<string>(path));
28+
}
29+
30+
protected virtual void OnStormSaveAdded(string path)
31+
{
32+
_log.Debug($"Detected new StormSave replay: {path}");
33+
StormSaveCreated?.Invoke(this, new EventArgs<string>(path));
34+
}
35+
36+
/// <summary>
37+
/// Starts watching filesystem for new replays. When found raises <see cref="TempReplayCreated"/> event.
38+
/// </summary>
39+
public void Start()
40+
{
41+
if (_battlelobby_watcher == null) {
42+
System.IO.Directory.CreateDirectory(BattleLobbyTempPath);
43+
_battlelobby_watcher = new FileSystemWatcher() {
44+
Path = BattleLobbyTempPath,
45+
Filter = "*.battlelobby",
46+
IncludeSubdirectories = true
47+
};
48+
_battlelobby_watcher.Changed += (o, e) => OnBattleLobbyAdded(e.FullPath);
49+
}
50+
_battlelobby_watcher.EnableRaisingEvents = true;
51+
52+
if (_stormsave_watcher == null) {
53+
_stormsave_watcher = new FileSystemWatcher() {
54+
Path = StormSavePath,
55+
Filter = "*.StormSave",
56+
IncludeSubdirectories = true
57+
};
58+
_stormsave_watcher.Created += (o, e) => OnStormSaveAdded(e.FullPath);
59+
}
60+
_stormsave_watcher.EnableRaisingEvents = true;
61+
62+
_log.Debug($"Started watching for new stormsave replays");
63+
}
64+
65+
/// <summary>
66+
/// Stops watching filesystem for new replays
67+
/// </summary>
68+
public void Stop()
69+
{
70+
if (_battlelobby_watcher != null) {
71+
_battlelobby_watcher.EnableRaisingEvents = false;
72+
}
73+
74+
if (_stormsave_watcher != null) {
75+
_stormsave_watcher.EnableRaisingEvents = false;
76+
}
77+
_log.Debug($"Stopped watching for new replays");
78+
}
79+
}
80+
}

Heroesprofile.Uploader.Windows/App.config

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
<setting name="UploadToHotslogs" serializeAs="String">
3939
<value>False</value>
4040
</setting>
41+
<setting name="DeleteAfterUpload" serializeAs="String">
42+
<value>None</value>
43+
</setting>
4144
<setting name="Theme" serializeAs="String">
4245
<value>MetroDark</value>
4346
</setting>
@@ -47,6 +50,9 @@
4750
<setting name="ApplicationVersion" serializeAs="String">
4851
<value />
4952
</setting>
53+
<setting name="PreMatchPage" serializeAs="String">
54+
<value>False</value>
55+
</setting>
5056
</Heroesprofile.Uploader.Windows.Properties.Settings>
5157
</userSettings>
5258

0 commit comments

Comments
 (0)