Separated Wafer-Counter

JsonElement instead of Request body
Attachment Class
Bump
Ready to test GetLastGroupIdWithValue
Changed to v4
This commit is contained in:
2024-05-21 12:40:20 -07:00
parent 5c9f0d1aff
commit 6317c385f6
38 changed files with 1231 additions and 476 deletions

View File

@ -0,0 +1 @@
[]

38
Wafer-Counter/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,38 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net8.0/OI.Metrology.Wafer.Counter.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
"uriFormat": "%s/swagger/index.html"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"preLaunchTask": "watch",
"processName": "OI.Metrology.Wafer.Counter.exe"
}
]
}

5
Wafer-Counter/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"cSpell.words": [
"Infineon"
]
}

163
Wafer-Counter/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,163 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/OI.Metrology.Wafer.Counter.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "buildTests",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/../Tests/OI.Metrology.Tests.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "testDebug",
"command": "dotnet",
"type": "process",
"args": [
"test",
"${workspaceFolder}/../Tests/OI.Metrology.Tests.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "testRelease",
"command": "dotnet",
"type": "process",
"args": [
"test",
"${workspaceFolder}/../Tests/OI.Metrology.Tests.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary",
"-c",
"Release"
],
"problemMatcher": "$msCompile"
},
{
"label": "Format",
"command": "dotnet",
"type": "process",
"args": [
"format",
"--report",
".vscode",
"--verbosity",
"detailed",
"--severity",
"warn"
],
"problemMatcher": "$msCompile"
},
{
"label": "Format-Whitespace",
"command": "dotnet",
"type": "process",
"args": [
"format",
"whitespace"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/OI.Metrology.Wafer.Counter.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary",
"--configuration",
"Release",
"--runtime",
"win-x64",
"--self-contained",
"-o",
"D:/web-sites/OI-Metrology/oo-8e5dd137-_______-OI-Metrology-Release/Wafer-Counter"
],
"problemMatcher": "$msCompile"
},
{
"label": "Publish AOT",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/OI.Metrology.Wafer.Counter.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary",
"--configuration",
"Release",
"--runtime",
"win-x64",
"-p:PublishAot=true",
"/property:GenerateFullPaths=true"
],
"problemMatcher": "$msCompile"
},
{
"label": "old-watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/OI.Metrology.Wafer.Counter.csproj"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"--launch-profile",
"http",
"run",
"--project",
"${workspaceFolder}/OI.Metrology.Wafer.Counter.csproj",
"--verbose"
],
"isBackground": true,
"dependsOn": [
"build"
],
"problemMatcher": {
"fileLocation": "relative",
"pattern": {
"regexp": "^([^\\s].*)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$",
"file": 1,
"location": 2,
"severity": 3,
"code": 4,
"message": 5
},
"background": {
"activeOnStart": true,
"beginsPattern": "^.*Shutdown requested.*",
"endsPattern": "^.*Application started.*"
}
}
}
]
}

View File

@ -0,0 +1,24 @@
using Microsoft.AspNetCore.Mvc;
using OI.Metrology.Shared.Models.Stateless;
namespace OI.Metrology.Wafer.Counter.ApiControllers;
[ApiController]
[Route("api/[controller]")]
public class AppSettingsController : ControllerBase, IAppSettingsController<ActionResult>
{
private readonly IAppSettingsRepository<Models.Binder.AppSettings> _AppSettingsRepository;
public AppSettingsController(IAppSettingsRepository<Models.Binder.AppSettings> AppSettingsRepository) =>
_AppSettingsRepository = AppSettingsRepository;
[HttpGet(nameof(IAppSettingsController<ActionResult>.Action.App))]
public ActionResult GetAppSettings() =>
Ok(_AppSettingsRepository.GetAppSettings());
[HttpGet(nameof(IAppSettingsController<ActionResult>.Action.DevOps))]
public ActionResult GetBuildNumberAndGitCommitSeven() =>
Ok(_AppSettingsRepository.GetBuildNumberAndGitCommitSeven());
}

View File

@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Mvc;
using OI.Metrology.Shared.Models.Stateless;
namespace OI.Metrology.Wafer.Counter.ApiControllers;
[Route("api/v1/file-share")]
public class FileShareController : Controller, IFileShareController<IResult>
{
private readonly IFileShareRepository _FileShareRepository;
public FileShareController(IFileShareRepository fileShareRepository) =>
_FileShareRepository = fileShareRepository;
[HttpGet("copy-file")]
public IResult CopyFile(string from, string to)
{
_FileShareRepository.CopyFile(from, to);
return Results.Ok();
}
[HttpGet("move-file")]
public IResult MoveFile(string from, string to)
{
_FileShareRepository.MoveFile(from, to);
return Results.Ok();
}
[HttpGet("file-write")]
public IResult FileWrite(string path, string contents)
{
_FileShareRepository.FileWrite(path, contents);
return Results.Ok();
}
}

View File

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Mvc;
using OI.Metrology.Shared.Models.Stateless;
namespace OI.Metrology.Wafer.Counter.ApiControllers;
[Route("api/v1/[controller]")]
public class WaferCounterController : Controller, IWaferCounterController<IActionResult>
{
private readonly IWaferCounterRepository _WaferCounterRepository;
public WaferCounterController(IWaferCounterRepository waferCounterRepository) =>
_WaferCounterRepository = waferCounterRepository;
[HttpGet("{waferSize}/last-quantity-and-slot-map")]
public IActionResult GetLastQuantityAndSlotMap(string area, string waferSize) =>
Json(_WaferCounterRepository.GetLastQuantityAndSlotMap(area, waferSize));
}

View File

@ -0,0 +1,27 @@
using System.Text.Json;
namespace OI.Metrology.Wafer.Counter.Models;
public record AppSettings(string BuildNumber,
string Company,
string EcCharacterizationSi,
string EcMesaFileShareCharacterizationSi,
string GitCommitSeven,
bool IsDevelopment,
bool IsStaging,
string MockRoot,
string MonAResource,
string MonASite,
string URLs,
string WaferCounterDestinationDirectory,
int WaferCounterTwoFileSecondsWait,
string WorkingDirectoryName)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,2 @@
[*.cs]
csharp_preserve_single_line_statements = true

View File

@ -0,0 +1,99 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace OI.Metrology.Wafer.Counter.Models.Binder;
public class AppSettings
{
public string? BuildNumber { get; set; }
public string? Company { get; set; }
public string? EcCharacterizationSi { get; set; }
public string? EcMesaFileShareCharacterizationSi { get; set; }
public string? GitCommitSeven { get; set; }
public bool? IsDevelopment { get; set; }
public bool? IsStaging { get; set; }
public string? MockRoot { get; set; }
public string? MonAResource { get; set; }
public string? MonASite { get; set; }
public string? URLs { get; set; }
public string? WaferCounterDestinationDirectory { get; set; }
public int? WaferCounterTwoFileSecondsWait { get; set; }
public string? WorkingDirectoryName { get; set; }
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
private static void PreVerify(IConfigurationRoot configurationRoot, AppSettings? appSettings)
{
if (appSettings?.Company is null)
{
List<string> paths = new();
foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers)
{
if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider)
continue;
if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider)
continue;
paths.Add(physicalFileProvider.Root);
}
throw new NotSupportedException($"Not found!{Environment.NewLine}{string.Join(Environment.NewLine, paths.Distinct())}");
}
}
private static Models.AppSettings Get(AppSettings? appSettings)
{
Models.AppSettings result;
if (appSettings is null) throw new NullReferenceException(nameof(appSettings));
if (appSettings.BuildNumber is null) throw new NullReferenceException(nameof(BuildNumber));
if (appSettings.Company is null) throw new NullReferenceException(nameof(Company));
if (appSettings.EcCharacterizationSi is null) throw new NullReferenceException(nameof(EcCharacterizationSi));
if (appSettings.EcMesaFileShareCharacterizationSi is null) throw new NullReferenceException(nameof(EcMesaFileShareCharacterizationSi));
if (appSettings.GitCommitSeven is null) throw new NullReferenceException(nameof(GitCommitSeven));
if (appSettings.IsDevelopment is null) throw new NullReferenceException(nameof(IsDevelopment));
if (appSettings.IsStaging is null) throw new NullReferenceException(nameof(IsStaging));
if (appSettings.MockRoot is null) throw new NullReferenceException(nameof(MockRoot));
if (appSettings.MonAResource is null) throw new NullReferenceException(nameof(MonAResource));
if (appSettings.MonASite is null) throw new NullReferenceException(nameof(MonASite));
if (appSettings.URLs is null) throw new NullReferenceException(nameof(URLs));
if (appSettings.WaferCounterDestinationDirectory is null) throw new NullReferenceException(nameof(WaferCounterDestinationDirectory));
if (appSettings.WaferCounterTwoFileSecondsWait is null) throw new NullReferenceException(nameof(WaferCounterTwoFileSecondsWait));
if (appSettings.WorkingDirectoryName is null) throw new NullReferenceException(nameof(WorkingDirectoryName));
result = new(appSettings.BuildNumber,
appSettings.Company,
appSettings.EcCharacterizationSi,
appSettings.EcMesaFileShareCharacterizationSi,
appSettings.GitCommitSeven,
appSettings.IsDevelopment.Value,
appSettings.IsStaging.Value,
appSettings.MockRoot,
appSettings.MonAResource,
appSettings.MonASite,
appSettings.URLs,
appSettings.WaferCounterDestinationDirectory,
appSettings.WaferCounterTwoFileSecondsWait.Value,
appSettings.WorkingDirectoryName);
return result;
}
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings result;
#pragma warning disable IL3050, IL2026
AppSettings? appSettings = configurationRoot.Get<AppSettings>();
#pragma warning restore IL3050, IL2026
PreVerify(configurationRoot, appSettings);
result = Get(appSettings);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(AppSettings))]
internal partial class BinderAppSettingsSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
<TargetFramework>net8.0</TargetFramework>
<UserSecretsId>2a0acd34-8f61-47a3-8818-73fa8fe04902</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.44" />
<PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="jQuery" Version="3.7.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.5" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.1" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\OI.Metrology.Shared.csproj" />
</ItemGroup>
</Project>

90
Wafer-Counter/Program.cs Normal file
View File

@ -0,0 +1,90 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting.WindowsServices;
using OI.Metrology.Wafer.Counter.Models;
using OI.Metrology.Wafer.Counter.Repository;
using OI.Metrology.Shared.Models.Stateless;
namespace OI.Metrology.Wafer.Counter;
public class Program
{
public static int Main(string[] args)
{
ILogger<Program>? logger = null;
WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args);
_ = webApplicationBuilder.Configuration.AddUserSecrets<Program>();
AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration);
if (string.IsNullOrEmpty(appSettings.Company))
throw new Exception("Company name must have a value!");
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
try
{
_ = webApplicationBuilder.Services.AddMemoryCache();
_ = webApplicationBuilder.Services.Configure<ApiBehaviorOptions>(options => options.SuppressModelStateInvalidFilter = true);
_ = webApplicationBuilder.Services.AddControllers();
_ = webApplicationBuilder.Services.AddDistributedMemoryCache();
AppSettingsRepository appSettingsRepository = new(appSettings);
_ = webApplicationBuilder.Services.AddHttpClient();
_ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
_ = webApplicationBuilder.Services.AddSingleton<IFileShareRepository, FileShareRepository>();
_ = webApplicationBuilder.Services.AddSingleton<IWaferCounterRepository, WaferCounterRepository>();
_ = webApplicationBuilder.Services.AddSingleton<IAppSettingsRepository<Models.Binder.AppSettings>>(_ => appSettingsRepository);
_ = webApplicationBuilder.Services.AddSwaggerGen();
_ = webApplicationBuilder.Services.AddSession(sessionOptions =>
{
sessionOptions.IdleTimeout = TimeSpan.FromSeconds(2000);
sessionOptions.Cookie.HttpOnly = true;
sessionOptions.Cookie.IsEssential = true;
}
);
if (WindowsServiceHelpers.IsWindowsService())
{
_ = webApplicationBuilder.Services.AddSingleton<IHostLifetime, WindowsServiceLifetime>();
_ = webApplicationBuilder.Logging.AddEventLog(settings =>
{
#pragma warning disable CA1416
if (string.IsNullOrEmpty(settings.SourceName))
settings.SourceName = webApplicationBuilder.Environment.ApplicationName;
#pragma warning restore
});
}
WebApplication webApplication = webApplicationBuilder.Build();
logger = webApplication.Services.GetRequiredService<ILogger<Program>>();
_ = webApplication.UseCors(corsPolicyBuilder => corsPolicyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
if (!webApplicationBuilder.Environment.IsDevelopment())
{
_ = webApplication.UseExceptionHandler("/Error");
_ = webApplication.UseHttpsRedirection();
_ = webApplication.UseHsts();
}
else
{
if (string.IsNullOrEmpty(appSettings.URLs))
{
Environment.ExitCode = -1;
webApplication.Lifetime.StopApplication();
}
_ = webApplication.UseSwagger();
_ = webApplication.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server V1"));
}
_ = webApplication.UseSession();
_ = webApplication.MapControllers();
logger.LogInformation("Starting Web Application");
webApplication.Run();
return 0;
}
catch (Exception ex)
{
try
{ logger?.LogCritical(ex, "Host terminated unexpectedly"); }
catch (Exception) { }
throw;
}
}
}

View File

@ -0,0 +1,31 @@
{
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5126",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7130;http://localhost:5126",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https-prod": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7130;http://localhost:5126",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production"
}
}
}
}

View File

@ -0,0 +1,40 @@
using OI.Metrology.Wafer.Counter.Models;
using OI.Metrology.Shared.Models.Stateless;
namespace OI.Metrology.Wafer.Counter.Repository;
public class AppSettingsRepository : IAppSettingsRepository<Models.Binder.AppSettings>
{
private readonly AppSettings _AppSettings;
public AppSettingsRepository(AppSettings appSettings) => _AppSettings = appSettings;
internal Models.Binder.AppSettings GetAppSettings()
{
Models.Binder.AppSettings result = new()
{
BuildNumber = _AppSettings.BuildNumber,
Company = _AppSettings.Company,
GitCommitSeven = _AppSettings.GitCommitSeven,
IsDevelopment = _AppSettings.IsDevelopment,
IsStaging = _AppSettings.IsStaging,
};
return result;
}
Models.Binder.AppSettings IAppSettingsRepository<Models.Binder.AppSettings>.GetAppSettings() => GetAppSettings();
internal string GetBuildNumberAndGitCommitSeven()
{
string result = string.Concat(_AppSettings.BuildNumber, '-', _AppSettings.GitCommitSeven);
return result;
}
string IAppSettingsRepository<Models.Binder.AppSettings>.GetBuildNumberAndGitCommitSeven() =>
GetBuildNumberAndGitCommitSeven();
void IAppSettingsRepository<Models.Binder.AppSettings>.VerifyConnectionStrings() =>
throw new NotImplementedException();
}

View File

@ -0,0 +1,99 @@
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Models.Stateless;
using System.Text.Json;
namespace OI.Metrology.Wafer.Counter.Repository;
public class FileShareRepository : IFileShareRepository
{
Uri IFileShareRepository.Append(Uri uri, params string[] paths) =>
new(paths.Aggregate(uri.AbsoluteUri, (current, path) =>
string.Format("{0}/{1}", current.TrimEnd('/'), path.TrimStart('/'))));
private Uri GetEndPoint(HttpClient httpClient, string method)
{
Uri result;
if (httpClient.BaseAddress is null)
throw new NullReferenceException(nameof(httpClient.BaseAddress));
IFileShareRepository fileShareRepository = this;
result = fileShareRepository.Append(httpClient.BaseAddress, "api", "v1", "file-share", method);
return result;
}
void IFileShareRepository.CopyFile(string from, string to)
{
string directory = Path.GetDirectoryName(to) ?? throw new NullReferenceException();
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
File.Copy(from, to);
}
void IFileShareRepository.MoveFile(string from, string to)
{
string directory = Path.GetDirectoryName(to) ?? throw new NullReferenceException();
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
if (File.Exists(to))
File.Move(to, $"{to}.{DateTime.Now.Ticks}.old");
File.Move(from, to);
}
void IFileShareRepository.FileWrite(string path, string contents)
{
string directory = Path.GetDirectoryName(path) ?? throw new NullReferenceException();
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
File.WriteAllText(path, contents);
}
void IFileShareRepository.CopyFile(HttpClient httpClient, string from, string to)
{
Uri uri = GetEndPoint(httpClient, "copy-file");
Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(uri);
httpResponseMessage.Wait();
if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK)
throw new Exception(httpResponseMessage.Result.StatusCode.ToString());
}
void IFileShareRepository.MoveFile(HttpClient httpClient, string from, string to)
{
Uri uri = GetEndPoint(httpClient, "move-file");
Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(uri);
httpResponseMessage.Wait();
if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK)
throw new Exception(httpResponseMessage.Result.StatusCode.ToString());
}
HttpResponseMessage IFileShareRepository.ReadFile(HttpClient httpClient, Uri uri)
{
HttpResponseMessage result;
Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(uri);
httpResponseMessage.Wait();
result = httpResponseMessage.Result;
return result;
}
List<NginxFileSystemSortable> IFileShareRepository.GetNginxFileSystemSortableCollection(HttpClient httpClient, Uri uri, string? endsWith)
{
List<NginxFileSystemSortable> results = new();
Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(uri);
httpResponseMessage.Wait();
if (httpResponseMessage.Result.StatusCode == System.Net.HttpStatusCode.OK)
{
FileShareRepository fileShareRepository = this;
Task<string> json = httpResponseMessage.Result.Content.ReadAsStringAsync();
json.Wait();
NginxFileSystem[]? nginxFileSystemCollection = JsonSerializer.Deserialize(json.Result, NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray);
List<NginxFileSystemSortable> nginxFileSystemSortableCollection = NginxFileSystemSortable.Convert(fileShareRepository, uri, nginxFileSystemCollection);
foreach (NginxFileSystemSortable nginxFileSystemSortable in nginxFileSystemSortableCollection.OrderByDescending(l => l.DateTime))
{
if (!string.IsNullOrEmpty(endsWith) && !nginxFileSystemSortable.Name.EndsWith(endsWith))
continue;
results.Add(nginxFileSystemSortable);
}
}
return results;
}
}

View File

@ -0,0 +1,186 @@
using OI.Metrology.Wafer.Counter.Models;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Repositories;
using System.Globalization;
namespace OI.Metrology.Wafer.Counter.Repository;
public class WaferCounterRepository : IWaferCounterRepository
{
private record Record(int Check,
int Total,
string? SlotMap);
private readonly string _MockRoot;
private readonly string _RepositoryName;
private readonly AppSettings _AppSettings;
private readonly IHttpClientFactory _HttpClientFactory;
private readonly IDbConnectionFactory _DBConnectionFactory;
private readonly IFileShareRepository _FileShareRepository;
public WaferCounterRepository(AppSettings appSettings, IDbConnectionFactory dbConnectionFactory, IHttpClientFactory httpClientFactory, IFileShareRepository fileShareRepository)
{
_AppSettings = appSettings;
_MockRoot = appSettings.MockRoot;
_HttpClientFactory = httpClientFactory;
_DBConnectionFactory = dbConnectionFactory;
_FileShareRepository = fileShareRepository;
_RepositoryName = nameof(WaferCounterRepository)[..^10];
}
private void MoveFile(string waferSizeDirectory, NginxFileSystemSortable nginxFileSystemSortable)
{
Calendar calendar = new CultureInfo("en-US").Calendar;
string from = Path.Combine(waferSizeDirectory, nginxFileSystemSortable.Name);
string weekOfYear = $"{nginxFileSystemSortable.DateTime:yyyy}_Week_{calendar.GetWeekOfYear(nginxFileSystemSortable.DateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}";
string to = Path.Combine(waferSizeDirectory, "Archive", weekOfYear, nginxFileSystemSortable.Name);
_FileShareRepository.MoveFile(from, to);
}
private static Record GetRecord(string line1, string line2)
{
Record result;
string? slotMap = string.IsNullOrEmpty(line2) || line2.Length != 8 ? null : line2.Substring(1, 1);
int check = slotMap == "1" ? 1 : 0;
#pragma warning disable IDE0057
int total = int.Parse(line1.Substring(1));
foreach (char item in line2.Substring(2))
#pragma warning restore IDE0057
{
switch (item)
{
case '0':
check += 0;
slotMap += "0000";
break;
case '1':
check += 1;
slotMap += "0001";
break;
case '2':
check += 1;
slotMap += "0010";
break;
case '3':
check += 2;
slotMap += "0011";
break;
case '4':
check += 1;
slotMap += "0100";
break;
case '5':
check += 2;
slotMap += "0101";
break;
case '6':
check += 2;
slotMap += "0110";
break;
case '7':
check += 3;
slotMap += "0111";
break;
case '8':
check += 1;
slotMap += "1000";
break;
case '9':
check += 2;
slotMap += "1001";
break;
case 'A':
check += 2;
slotMap += "1010";
break;
case 'B':
check += 3;
slotMap += "1011";
break;
case 'C':
check += 2;
slotMap += "1100";
break;
case 'D':
check += 3;
slotMap += "1101";
break;
case 'E':
check += 3;
slotMap += "1110";
break;
case 'F':
check += 4;
slotMap += "1111";
break;
default:
break;
}
}
result = new(check, total, slotMap);
return result;
}
private Uri GetWaferSizeUri(string area, string waferSize) =>
_FileShareRepository.Append(new Uri(_AppSettings.EcMesaFileShareCharacterizationSi), "WaferCounter", area, waferSize);
private string GetWaferSizeDirectory(string area, string waferSize, bool destination) =>
destination ? Path.Combine(_AppSettings.WaferCounterDestinationDirectory, area, waferSize) : Path.Combine(_AppSettings.EcCharacterizationSi, "WaferCounter", area, waferSize);
string? IWaferCounterRepository.GetSlotMap(string line1, string line2) =>
GetRecord(line1, line2).SlotMap;
private List<NginxFileSystemSortable> GetNginxFileSystemSortableCollection(HttpClient httpClient, Uri waferSizeUri)
{
List<NginxFileSystemSortable> results = new();
DateTime dateTime = DateTime.Now;
long ticks = dateTime.AddSeconds(_AppSettings.WaferCounterTwoFileSecondsWait).Ticks;
for (int i = 0; i < int.MaxValue; i++)
{
results = _FileShareRepository.GetNginxFileSystemSortableCollection(httpClient, waferSizeUri, ".wc");
if (results.Count > 0 || DateTime.Now.Ticks > ticks)
break;
Thread.Sleep(250);
}
return results;
}
private static WaferCounter GetLastQuantityAndSlotMap(string waferSize, HttpClient httpClient, NginxFileSystemSortable nginxFileSystemSortable)
{
WaferCounter result;
string text = string.Empty;
Task<string> value = httpClient.GetStringAsync(nginxFileSystemSortable.Uri);
value.Wait();
string[] lines = value.Result.Split("\r\n");
if (lines.Length <= 1)
throw new Exception("Incomplete file length!");
string[] segments = nginxFileSystemSortable.Name.Split('-');
Record record = GetRecord(lines[0], lines[1]);
string equipmentId = segments.Length <= 1 ? nginxFileSystemSortable.Name : segments[1].Split('.')[0];
if (string.IsNullOrEmpty(record.SlotMap) || record.SlotMap.Length != 25)
throw new Exception("Wrong length for slot-map!");
if (record.Total != record.Check)
throw new Exception($"Invalid {record.Total} != {record.Check}");
result = new(nginxFileSystemSortable.DateTime, nginxFileSystemSortable.DateTime.ToString("yyyy-MM-dd hh:mm tt"), $"WC{waferSize}{equipmentId}", text, record.Total, record.SlotMap);
return result;
}
WaferCounter IWaferCounterRepository.GetLastQuantityAndSlotMap(string area, string waferSize)
{
WaferCounter result;
Uri waferSizeUri = GetWaferSizeUri(area, waferSize);
HttpClient httpClient = _HttpClientFactory.CreateClient();
string waferSizeDirectory = GetWaferSizeDirectory(area, waferSize, destination: false);
List<NginxFileSystemSortable> nginxFileSystemSortableCollection = GetNginxFileSystemSortableCollection(httpClient, waferSizeUri);
if (nginxFileSystemSortableCollection.Count < 1)
throw new Exception("No files!");
result = GetLastQuantityAndSlotMap(waferSize, httpClient, nginxFileSystemSortableCollection[0]);
for (int i = 0; i < nginxFileSystemSortableCollection.Count; i++)
MoveFile(waferSizeDirectory, nginxFileSystemSortableCollection[i]);
return result;
}
}