改了一亿个东西,修了一亿个 BUG
This commit is contained in:
148
ReplayAutoSaver.cs
Normal file
148
ReplayAutoSaver.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using AnotherReplayReader.ReplayFile;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace AnotherReplayReader
|
||||
{
|
||||
public static class ReplayAutoSaver
|
||||
{
|
||||
private static int _errorMessageCount = 0;
|
||||
|
||||
public static void SpawnAutoSaveReplaysTask(string replayFolderPath)
|
||||
{
|
||||
Task.Run(() => AutoSaveReplays(replayFolderPath));
|
||||
}
|
||||
|
||||
private static async Task AutoSaveReplays(string replayFolderPath)
|
||||
{
|
||||
const string ourPrefix = "自动保存";
|
||||
|
||||
// filename and last write time
|
||||
var previousFiles = new Dictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase);
|
||||
// filename and file size
|
||||
var lastReplays = new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var changed = (from fileName in Directory.GetFiles(replayFolderPath, "*.RA3Replay")
|
||||
let info = new FileInfo(fileName)
|
||||
where !info.Name.StartsWith(ourPrefix)
|
||||
where !previousFiles.ContainsKey(info.FullName) || previousFiles[info.FullName] != info.LastWriteTimeUtc
|
||||
select info).ToList();
|
||||
|
||||
foreach (var info in changed)
|
||||
{
|
||||
previousFiles[info.FullName] = info.LastWriteTimeUtc;
|
||||
}
|
||||
|
||||
var replays = changed.Select(info =>
|
||||
{
|
||||
Debug.Instance.DebugMessage += $"正在尝试检测已更改的文件:{info.FullName}\r\n";
|
||||
try
|
||||
{
|
||||
using var stream = info.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return new Replay(info.FullName, stream);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Instance.DebugMessage += $"自动保存录像/检测录像更改时发生错误:{e}\r\n";
|
||||
return null;
|
||||
}
|
||||
}).Where(replay => replay != null);
|
||||
|
||||
var newLastReplays = from replay in replays
|
||||
let threshold = Math.Abs((DateTime.UtcNow - replay.Date).TotalSeconds)
|
||||
let endDate = replay.Date.Add(replay.Length ?? TimeSpan.Zero)
|
||||
let endThreshold = Math.Abs((DateTime.UtcNow - endDate).TotalSeconds)
|
||||
where threshold < 40 || endThreshold < 40
|
||||
select replay;
|
||||
|
||||
var toBeChecked = newLastReplays.ToDictionary(replay => replay.Path, StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var savedLastReplay in lastReplays.Keys)
|
||||
{
|
||||
if (!toBeChecked.ContainsKey(savedLastReplay))
|
||||
{
|
||||
try
|
||||
{
|
||||
using var stream = File.Open(savedLastReplay, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
toBeChecked.Add(savedLastReplay, new Replay(savedLastReplay, stream));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Instance.DebugMessage += $"自动保存录像/检测录像更改时发生错误:{e}\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kv in toBeChecked)
|
||||
{
|
||||
Debug.Instance.DebugMessage += $"正在检测录像更改:{kv.Key}\r\n";
|
||||
var replay = kv.Value;
|
||||
if (lastReplays.TryGetValue(kv.Key, out var fileSize))
|
||||
{
|
||||
if (fileSize == replay.Size)
|
||||
{
|
||||
// skip if size is not changed
|
||||
Debug.Instance.DebugMessage += $"已跳过未更改的录像:{kv.Key}\r\n";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Debug.Instance.DebugMessage += $"将会自动保存已更改的录像:{kv.Key}\r\n";
|
||||
lastReplays[kv.Key] = replay.Size;
|
||||
|
||||
var date = replay.Date;
|
||||
|
||||
var playerString = $"{replay.NumberOfPlayingPlayers}名玩家";
|
||||
if (replay.NumberOfPlayingPlayers <= 2)
|
||||
{
|
||||
var playingPlayers = from player in replay.Players
|
||||
let faction = ModData.GetFaction(replay.Mod, player.FactionId)
|
||||
where faction.Kind != FactionKind.Observer
|
||||
select $"{player.PlayerName}({faction.Name})";
|
||||
playerString = playingPlayers.Aggregate(string.Empty, (x, y) => x + y);
|
||||
}
|
||||
|
||||
var dateString = $"{date.Year}{date.Month:D2}{date.Day:D2}_{date.Hour:D2}{date.Minute:D2}{date.Second:D2}";
|
||||
var destinationPath = Path.Combine(replayFolderPath, $"{ourPrefix}-{playerString}{dateString}.RA3Replay");
|
||||
try
|
||||
{
|
||||
File.Copy(replay.Path, destinationPath, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"复制文件({replay.Path} -> {destinationPath})失败:{e.Message}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var errorString = $"自动保存录像时出现错误:\r\n{e}\r\n";
|
||||
Debug.Instance.DebugMessage += errorString;
|
||||
if (Interlocked.Increment(ref _errorMessageCount) == 1)
|
||||
{
|
||||
_ = Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageBox.Show(errorString);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Decrement(ref _errorMessageCount);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay(10 * 1000).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user