using System;
using System.Collections.Generic;
using System.Globalization;
using System.Numerics;
using System.Text.RegularExpressions;
namespace AcDream.Core.Tests.Conformance;
///
/// A single retail find_cell_list pick captured via cdb (golden oracle).
/// is the seed/current cell at find_cell_list
/// entry; is the chosen containing cell
/// (retail *arg5 in CObjCell::find_cell_list @ 0x52b4e0 pc:308742).
///
public sealed record RetailCellPick(uint SeedCellId, Vector3 Position, uint PickedCellId);
/// Parser for the find-cell-list-capture.cdb log format.
public static class RetailTrace
{
private static readonly Regex Fcl = new(
@"^\[fcl\]\s+seed=0x(?[0-9A-Fa-f]{1,8})\s+" +
@"px=(?-?\d+(\.\d+)?)\s+py=(?-?\d+(\.\d+)?)\s+pz=(?-?\d+(\.\d+)?)\s+" +
@"picked=0x(?[0-9A-Fa-f]{1,8})\s*$",
RegexOptions.Compiled);
public static RetailCellPick? ParseFindCellList(string line)
{
if (string.IsNullOrEmpty(line)) return null;
var m = Fcl.Match(line);
if (!m.Success) return null;
var ci = CultureInfo.InvariantCulture;
return new RetailCellPick(
SeedCellId: Convert.ToUInt32(m.Groups["seed"].Value, 16),
Position: new Vector3(
float.Parse(m.Groups["px"].Value, ci),
float.Parse(m.Groups["py"].Value, ci),
float.Parse(m.Groups["pz"].Value, ci)),
PickedCellId: Convert.ToUInt32(m.Groups["picked"].Value, 16));
}
/// Parse a log, skipping every non-matching line (noise/banner/other BPs).
public static IReadOnlyList ParseAll(IEnumerable lines)
{
var list = new List();
foreach (var line in lines)
{
var rec = ParseFindCellList(line);
if (rec is not null) list.Add(rec);
}
return list;
}
}