Extract event block diff logic

This commit is contained in:
Kurt 2019-06-18 18:10:48 -07:00
parent 3083b04223
commit 55d486af31
4 changed files with 166 additions and 91 deletions

View file

@ -0,0 +1,149 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static PKHeX.Core.MessageStrings;
namespace PKHeX.Core
{
/// <summary>
/// Calculates differences in the Event Blocks between two <see cref="SaveFile"/>.
/// </summary>
public class EventBlockDiff
{
public string Message { get; private set; }
public readonly List<int> SetFlags = new List<int>();
public readonly List<int> ClearedFlags = new List<int>();
public readonly List<string> WorkDiff = new List<string>();
private const int MAX_SAVEFILE_SIZE = 0x10_0000; // 1 MB
protected EventBlockDiff() { }
public EventBlockDiff(string f1, string f2)
{
if (!SanityCheckFiles(f1, f2))
return;
var s1 = SaveUtil.GetVariantSAV(f1);
var s2 = SaveUtil.GetVariantSAV(f2);
Diff(s1, s2);
}
public EventBlockDiff(SaveFile s1, SaveFile s2) => Diff(s1, s2);
protected bool SanityCheckFiles(string f1, string f2)
{
if (!File.Exists(f1))
{ Message = string.Format(MsgSaveNumberInvalid, 1); return false; }
if (!File.Exists(f2))
{ Message = string.Format(MsgSaveNumberInvalid, 2); return false; }
if (new FileInfo(f1).Length > MAX_SAVEFILE_SIZE)
{ Message = string.Format(MsgSaveNumberInvalid, 1); return false; }
if (new FileInfo(f2).Length > MAX_SAVEFILE_SIZE)
{ Message = string.Format(MsgSaveNumberInvalid, 2); return false; }
return true;
}
protected bool SanityCheckSaveInfo(SaveFile s1, SaveFile s2)
{
if (s1.GetType() != s2.GetType())
{ Message = string.Format(MsgSaveDifferentTypes, $"S1: {s1.GetType().Name}", $"S2: {s2.GetType().Name}"); return false; }
if (s1.Version != s2.Version)
{ Message = string.Format(MsgSaveDifferentVersions, $"S1: {s1.Version}", $"S2: {s2.Version}"); return false; }
return true;
}
protected virtual void Diff(SaveFile s1, SaveFile s2)
{
if (!SanityCheckSaveInfo(s1, s2))
return;
bool[] oldBits = s1.EventFlags;
bool[] newBits = s2.EventFlags;
var oldConst = s1.EventConsts;
var newConst = s2.EventConsts;
for (int i = 0; i < newBits.Length; i++)
{
if (oldBits[i] != newBits[i])
(newBits[i] ? SetFlags : ClearedFlags).Add(i);
}
for (int i = 0; i < newConst.Length; i++)
{
if (oldConst[i] != newConst[i])
WorkDiff.Add($"{i}: {oldConst[i]}->{newConst[i]}");
}
}
}
public class EventWorkDiff7b : EventBlockDiff
{
public readonly List<int> WorkChanged = new List<int>();
private SaveFile S1;
public EventWorkDiff7b(string f1, string f2)
{
if (!SanityCheckFiles(f1, f2))
return;
var s1 = SaveUtil.GetVariantSAV(f1);
var s2 = SaveUtil.GetVariantSAV(f2);
Diff(s1, s2);
}
public EventWorkDiff7b(SaveFile s1, SaveFile s2) => Diff(s1, s2);
protected override void Diff(SaveFile s1, SaveFile s2)
{
if (!SanityCheckSaveInfo(s1, s2))
return;
EventWorkUtil.DiffSavesFlag(((SAV7b)s1).EventWork, ((SAV7b)s2).EventWork, SetFlags, ClearedFlags);
EventWorkUtil.DiffSavesWork(((SAV7b)s1).EventWork, ((SAV7b)s2).EventWork, WorkChanged, WorkDiff);
S1 = s1;
}
public List<string> Summarize()
{
var ew = ((SAV7b)S1).EventWork;
var fOn = SetFlags.Select(z => new { Type = ew.GetFlagType(z, out var subIndex), Index = subIndex, Raw = z })
.Select(z => $"{z.Raw:0000}\t{true }\t{z.Index:0000}\t{z.Type}").ToArray();
var fOff = ClearedFlags.Select(z => new { Type = ew.GetFlagType(z, out var subIndex), Index = subIndex, Raw = z })
.Select(z => $"{z.Raw:0000}\t{false}\t{z.Index:0000}\t{z.Type}").ToArray();
var w = WorkChanged.Select((z, i) => new
{
Type = ew.GetWorkType(z, out var subIndex),
Index = subIndex,
Raw = z,
Text = WorkDiff[i]
}).ToArray();
var wt = w.Select(z => $"{z.Raw:000}\t{z.Text}\t{z.Index:000}\t{z.Type}").ToArray();
var list = new List<string> { "Flags: ON", "=========" };
list.AddRange(fOn);
if (SetFlags.Count == 0)
list.Add("None.");
list.Add("");
list.Add("Flags: OFF");
list.Add("==========");
list.AddRange(fOff);
if (ClearedFlags.Count == 0)
list.Add("None.");
list.Add("");
list.Add("Work:");
list.Add("=====");
if (WorkChanged.Count == 0)
list.Add("None.");
list.AddRange(wt);
return list;
}
}
}

View file

@ -73,11 +73,9 @@ namespace PKHeX.Core
/// <param name="after">Data after the event was triggered</param>
/// <param name="on">List of flags that were turned on</param>
/// <param name="off">List of flags that were turned off</param>
public static void DiffSavesFlag<T>(IEventWork<T> before, IEventWork<T> after, out IList<int> on, out IList<int> off)
public static void DiffSavesFlag<T>(IEventWork<T> before, IEventWork<T> after, List<int> on, List<int> off)
{
int max = before.MaxFlag;
on = new List<int>();
off = new List<int>();
for (int i = 0; i < max; i++)
{
var b = before.GetFlag(i);
@ -98,11 +96,9 @@ namespace PKHeX.Core
/// <param name="after">Data after the event was triggered</param>
/// <param name="changed"><see cref="EventVar.RawIndex"/> values that changed</param>
/// <param name="changes">Summary of the <see cref="EventWork{T}"/> value change</param>
public static void DiffSavesWork<T>(IEventWork<T> before, IEventWork<T> after, out IList<int> changed, out IList<string> changes)
public static void DiffSavesWork<T>(IEventWork<T> before, IEventWork<T> after, List<int> changed, List<string> changes)
{
int max = before.MaxWork;
changed = new List<int>();
changes = new List<string>();
for (int i = 0; i < max; i++)
{
var b = before.GetWork(i);

View file

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using PKHeX.Core;
@ -426,49 +425,24 @@ namespace PKHeX.WinForms
private void DiffSaves()
{
if (!File.Exists(TB_OldSAV.Text)) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 1)); return; }
if (!File.Exists(TB_NewSAV.Text)) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 2)); return; }
if (new FileInfo(TB_OldSAV.Text).Length > 0x100000) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 1)); return; }
if (new FileInfo(TB_NewSAV.Text).Length > 0x100000) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 2)); return; }
var s1 = SaveUtil.GetVariantSAV(TB_OldSAV.Text);
var s2 = SaveUtil.GetVariantSAV(TB_NewSAV.Text);
if (s1 == null) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 1)); return; }
if (s2 == null) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 2)); return; }
if (s1.GetType() != s2.GetType()) { WinFormsUtil.Alert(MsgSaveDifferentTypes, $"S1: {s1.GetType().Name}", $"S2: {s2.GetType().Name}"); return; }
if (s1.Version != s2.Version) { WinFormsUtil.Alert(MsgSaveDifferentVersions, $"S1: {s1.Version}", $"S2: {s2.Version}"); return; }
var tbIsSet = new List<int>();
var tbUnSet = new List<int>();
var result = new List<string>();
bool[] oldBits = s1.EventFlags;
bool[] newBits = s2.EventFlags;
var oldConst = s1.EventConsts;
var newConst = s2.EventConsts;
for (int i = 0; i < oldBits.Length; i++)
var diff = new EventBlockDiff(TB_OldSAV.Text, TB_NewSAV.Text);
if (diff.Message == null)
{
if (oldBits[i] != newBits[i])
(newBits[i] ? tbIsSet : tbUnSet).Add(i);
}
TB_IsSet.Text = string.Join(", ", tbIsSet.Select(z => $"{z:0000}"));
TB_UnSet.Text = string.Join(", ", tbUnSet.Select(z => $"{z:0000}"));
for (int i = 0; i < newConst.Length; i++)
{
if (oldConst[i] != newConst[i])
result.Add($"{i}: {oldConst[i]}->{newConst[i]}");
WinFormsUtil.Alert(diff.Message);
return;
}
if (result.Count == 0)
TB_IsSet.Text = string.Join(", ", diff.SetFlags.Select(z => $"{z:0000}"));
TB_UnSet.Text = string.Join(", ", diff.ClearedFlags.Select(z => $"{z:0000}"));
if (diff.WorkDiff.Count == 0)
{
WinFormsUtil.Alert("No Event Constant diff found.");
return;
}
if (DialogResult.Yes == WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Copy Event Constant diff to clipboard?"))
Clipboard.SetText(string.Join(Environment.NewLine, result));
Clipboard.SetText(string.Join(Environment.NewLine, diff.WorkDiff));
}
private static void Main_DragEnter(object sender, DragEventArgs e)

View file

@ -276,58 +276,14 @@ namespace PKHeX.WinForms
private void DiffSaves()
{
if (!File.Exists(TB_OldSAV.Text)) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 1)); return; }
if (!File.Exists(TB_NewSAV.Text)) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 2)); return; }
if (new FileInfo(TB_OldSAV.Text).Length > 0x100000) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 1)); return; }
if (new FileInfo(TB_NewSAV.Text).Length > 0x100000) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 2)); return; }
var s1 = SaveUtil.GetVariantSAV(TB_OldSAV.Text);
var s2 = SaveUtil.GetVariantSAV(TB_NewSAV.Text);
if (s1 == null) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 1)); return; }
if (s2 == null) { WinFormsUtil.Alert(string.Format(MsgSaveNumberInvalid, 2)); return; }
if (s1.GetType() != s2.GetType()) { WinFormsUtil.Alert(MsgSaveDifferentTypes, $"S1: {s1.GetType().Name}", $"S2: {s2.GetType().Name}"); return; }
if (s1.Version != s2.Version) { WinFormsUtil.Alert(MsgSaveDifferentVersions, $"S1: {s1.Version}", $"S2: {s2.Version}"); return; }
EventWorkUtil.DiffSavesFlag(((SAV7b)s1).EventWork, ((SAV7b)s2).EventWork, out var on, out var off);
EventWorkUtil.DiffSavesWork(((SAV7b)s1).EventWork, ((SAV7b)s2).EventWork, out var changed, out var changes);
var ew = ((SAV7b) s1).EventWork;
var fOn = on.Select(z => new {Type = ew.GetFlagType(z, out var subIndex), Index = subIndex, Raw = z})
.Select(z => $"{z.Raw:0000}\t{true }\t{z.Index:0000}\t{z.Type}").ToArray();
var fOff = off.Select(z => new {Type = ew.GetFlagType(z, out var subIndex), Index = subIndex, Raw = z})
.Select(z => $"{z.Raw:0000}\t{false}\t{z.Index:0000}\t{z.Type}").ToArray();
var w = changed.Select((z, i) => new
var diff7b = new EventWorkDiff7b(TB_OldSAV.Text, TB_NewSAV.Text);
if (diff7b.Message != null)
{
Type = ew.GetWorkType(z, out var subIndex),
Index = subIndex,
Raw = z,
Text = changes[i]
}).ToArray();
var wt = w.Select(z => $"{z.Raw:000}\t{z.Text}\t{z.Index:000}\t{z.Type}").ToArray();
WinFormsUtil.Alert(diff7b.Message);
return;
}
var list = new List<string> {"Flags: ON", "========="};
list.AddRange(fOn);
if (on.Count == 0)
list.Add("None.");
list.Add("");
list.Add("Flags: OFF");
list.Add("==========");
list.AddRange(fOff);
if (off.Count == 0)
list.Add("None.");
list.Add("");
list.Add("Work:");
list.Add("=====");
if (changes.Count == 0)
list.Add("None.");
list.AddRange(wt);
RTB_Diff.Lines = list.ToArray();
RTB_Diff.Lines = diff7b.Summarize().ToArray();
}
private static void Main_DragEnter(object sender, DragEventArgs e)