BAS file parsing

This commit is contained in:
bird_egop
2026-05-13 02:53:42 +03:00
parent 9e651a60ce
commit aa02309f2d
3 changed files with 114 additions and 116 deletions
+86
View File
@@ -0,0 +1,86 @@
using Common;
namespace ParkanPlayground;
public record BasContours(InnerContour[] Inner, OuterContour[] Outer);
public record InnerContour(Vector3[] Points, uint[] Nums1, uint[] Nums2);
public record OuterContour(Vector3[] Points);
public static class BasParser
{
public static BasContours ReadFile(string path)
{
using FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
return ReadFile(fs);
}
public static BasContours ReadFile(Stream fs)
{
var innerContourCount = fs.ReadUInt32LittleEndian();
InnerContour[] innerContours = new InnerContour[innerContourCount];
for (var i = 0; i < innerContourCount; i++)
{
var pointCount = fs.ReadUInt32LittleEndian();
Vector3[] points = new Vector3[pointCount + 1];
for (var j = 0; j < pointCount + 1; j++)
{
var x = fs.ReadFloatLittleEndian();
var y = fs.ReadFloatLittleEndian();
var z = fs.ReadFloatLittleEndian();
points[j] = new Vector3(x, y, z);
}
uint[] nums1 = new uint[pointCount];
// batch 1
for (var j = 0; j < pointCount; j++)
{
var num = fs.ReadUInt32LittleEndian();
nums1[j] = num;
}
uint[] nums2 = new uint[pointCount];
// batch 2
for (var j = 0; j < pointCount; j++)
{
var num = fs.ReadUInt32LittleEndian();
nums2[j] = num;
}
innerContours[i] = new InnerContour(points, nums1, nums2);
}
var outerContourCount = fs.ReadUInt32LittleEndian();
OuterContour[] outerContours = new OuterContour[outerContourCount];
for (var i = 0; i < outerContourCount; i++)
{
var pointCount = fs.ReadUInt32LittleEndian();
Vector3[] points = new Vector3[pointCount + 1];
for (var j = 0; j < pointCount + 1; j++)
{
var x = fs.ReadFloatLittleEndian();
var y = fs.ReadFloatLittleEndian();
var z = fs.ReadFloatLittleEndian();
points[j] = new Vector3(x, y, z);
}
outerContours[i] = new OuterContour(points);
}
BasContours contours = new BasContours(innerContours, outerContours);
return contours;
}
}
+1 -61
View File
@@ -1,63 +1,3 @@
using ResTreeLib;
using Common;
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var trfPath = Directory.EnumerateFiles(@"C:\Program Files (x86)\Nikita\Iron Strategy\MISSIONS\SCRIPTS", "*.trf").First();
var nodes = ResTreeParser.Parse(trfPath);
var active = nodes.Where(n => !string.IsNullOrWhiteSpace(n.ShortName) && (n.Node.ResearchCost > 0 || n.Node.ResearchTime > 0)).ToList();
Console.WriteLine($"active={active.Count}");
Analyze("X from Cost", active.Select(n => (A:n.Node.ResearchCost, B:n.Node.ViewPosX, Name:n.ShortName, Idx:n.Index)).ToList());
Analyze("Y from Time", active.Select(n => (A:n.Node.ResearchTime, B:n.Node.ViewPosY, Name:n.ShortName, Idx:n.Index)).ToList());
Console.WriteLine();
Console.WriteLine("Largest |Y-Time| (active):");
foreach (var n in active.OrderByDescending(n => Math.Abs(n.Node.ViewPosY - n.Node.ResearchTime)).Take(20))
{
Console.WriteLine($"idx={n.Index,3} {n.ShortName,-12} T={n.Node.ResearchTime,6:0.##} Y={n.Node.ViewPosY,6:0.##} d={n.Node.ViewPosY-n.Node.ResearchTime,6:0.##}");
}
Console.WriteLine();
Console.WriteLine("Largest |X-Cost| (active):");
foreach (var n in active.OrderByDescending(n => Math.Abs(n.Node.ViewPosX - n.Node.ResearchCost)).Take(20))
{
Console.WriteLine($"idx={n.Index,3} {n.ShortName,-12} C={n.Node.ResearchCost,6:0.##} X={n.Node.ViewPosX,6:0.##} d={n.Node.ViewPosX-n.Node.ResearchCost,6:0.##}");
}
static void Analyze(string title, List<(float A, float B, string Name, int Idx)> data)
{
float meanA = data.Average(x => x.A);
float meanB = data.Average(x => x.B);
float cov=0, varA=0;
foreach (var d in data)
{
var da = d.A - meanA;
var db = d.B - meanB;
cov += da*db;
varA += da*da;
}
float slope = varA == 0 ? 0 : cov / varA;
float intercept = meanB - slope*meanA;
float mae = data.Average(d => Math.Abs((slope*d.A + intercept) - d.B));
float rmse = MathF.Sqrt(data.Average(d => MathF.Pow((slope*d.A + intercept) - d.B,2)));
float corr = Corr(data.Select(x=>x.A).ToArray(), data.Select(x=>x.B).ToArray());
Console.WriteLine($"{title}: corr={corr:0.###}, slope={slope:0.###}, intercept={intercept:0.###}, MAE={mae:0.###}, RMSE={rmse:0.###}");
}
static float Corr(float[] a, float[] b)
{
if (a.Length != b.Length || a.Length == 0) return 0;
var ma = a.Average();
var mb = b.Average();
float top=0, aa=0, bb=0;
for(int i=0;i<a.Length;i++)
{
var da=a[i]-ma; var db=b[i]-mb;
top += da*db; aa += da*da; bb += db*db;
}
if (aa<=0||bb<=0) return 0;
return top / MathF.Sqrt(aa*bb);
}