Refactor QS408M and PDSF File Handlers

- Updated Detail class to include JsonSourceGenerationOptions and JsonSerializable attributes for source generation.
- Modified ProcessData class to utilize source generation context for Description deserialization.
- Renamed RowSourceGenerationContext to QS408MRowSourceGenerationContext for clarity.
- Updated Run class to use QS408MRunSourceGenerationContext for serialization.
- Enhanced Description class with source generation attributes.
- Refactored FileRead class to use source generation context for Description deserialization.
- Added new methods in ProcessDataStandardFormat for JSON element array extraction.
- Introduced new PDSF file handler classes: Body, Constant, FileRead, Footer, Header, Row, Run, and Site.
- Implemented logic for parsing and handling PDSF data structures.
- Added unit tests for PDSF processing to ensure functionality.
This commit is contained in:
2025-09-15 11:37:05 -07:00
parent 515df7ec37
commit d07755c3a0
29 changed files with 869 additions and 204 deletions

View File

@ -0,0 +1,106 @@
using System;
using System.Collections.ObjectModel;
namespace Adaptation.FileHandlers.pdsf;
#nullable enable
public class Header
{
public Header(string title, string recipe, string dateTime, string @operator, string batch, string cassette, bool usedLast, string wafer)
{
Title = title;
Recipe = recipe;
DateTime = dateTime;
Operator = @operator;
Batch = batch;
Cassette = cassette;
UsedLast = usedLast;
Wafer = wafer;
}
public string Title { get; }
public string Recipe { get; }
public string DateTime { get; }
public string Operator { get; }
public string Batch { get; }
public string Cassette { get; }
public bool UsedLast { get; }
public string Wafer { get; }
internal static Header Get() =>
new(string.Empty,
string.Empty,
string.Empty,
string.Empty,
string.Empty,
string.Empty,
false,
string.Empty);
internal static Header? Get(Constant constant, Header lastHeader, string text, int[] i)
{
Header? result;
// occasionally there are multiple blocks of details, get the last one as earlier ones may be aborted runs.
int index = text.LastIndexOf(constant.BioRad);
if (index > -1)
text = text.Substring(index);
if (string.IsNullOrEmpty(text))
result = null;
else
{
bool usedLast;
string recipe;
string title = Run.GetBefore(text, i, constant.Recipe);
string recipeAndDateTime = Run.GetToEOL(text, i);
if (recipeAndDateTime.Length < constant.TwoSpaces.Length)
recipe = recipeAndDateTime.Trim();
else if (!recipeAndDateTime.Contains(constant.TwoSpaces))
recipe = recipeAndDateTime.Substring(0, 25).Trim();
else
recipe = recipeAndDateTime.Split(new string[] { constant.TwoSpaces }, StringSplitOptions.None)[0].Trim();
string dateTime = recipeAndDateTime.Substring(recipe.Length).Trim();
if (dateTime.EndsWith(constant.Period))
dateTime = dateTime.Remove(dateTime.Length - 1, 1);
i[0] = Run.ScanPast(text, i, constant.Operator);
string @operator = Run.GetBefore(text, i, constant.Batch);
string batch = Run.GetToEOL(text, i);
i[0] = Run.ScanPast(text, i, constant.Cassette);
if (!text.Contains(constant.Cassette))
title = string.Empty;
string cassette = Run.GetBefore(text, i, constant.Wafer);
if (string.IsNullOrEmpty(batch))
{
i[0] = 0;
i[0] = Run.ScanPast(text, i, constant.Wafer);
}
string wafer = Run.GetToEOL(text, i);
_ = Run.GetToEOL(text, i);
_ = Run.GetToEOL(text, i);
if (string.IsNullOrEmpty(wafer))
throw new Exception(constant.WaferFieldIsMissing);
if (!string.IsNullOrEmpty(title))
usedLast = false;
else
{
title = lastHeader.Title;
recipe = lastHeader.Recipe;
@operator = lastHeader.Operator;
batch = lastHeader.Batch;
cassette = lastHeader.Cassette;
usedLast = true;
}
result = new(title: title,
recipe: recipe,
dateTime: dateTime,
@operator: @operator,
batch: batch,
cassette: cassette,
usedLast: usedLast,
wafer: wafer);
}
return result;
}
}