Ready to test Max RDS

This commit is contained in:
2022-10-03 11:08:24 -07:00
parent 466057022d
commit 617a4989e2
30 changed files with 5747 additions and 167 deletions

View File

@ -82,6 +82,8 @@ public class ExportController : Controller
ModelState.AddModelError("Exception", ex.Message);
string errorMessage = $"Error exporting: {ex}";
_Logger.LogError(message: errorMessage);
MonIn monIn = MonIn.GetInstance();
_ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Warning);
}
}
return View("Index", model);

View File

@ -4,18 +4,21 @@ using OI.Metrology.Archive.Models;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.ViewModels;
using System;
using System.Collections.Generic;
using IO = System.IO;
namespace OI.Metrology.Archive.Controllers;
public class PagesController : Controller
{
private readonly IMetrologyRepo _Repo;
private readonly bool _IsTestDatabase;
private readonly IRdsMaxRepo _RdsMaxRepo;
private readonly IMetrologyRepo _MetrologyRepo;
public PagesController(AppSettings appSettings, IMetrologyRepo repo)
public PagesController(AppSettings appSettings, IMetrologyRepo metrologyRepo, IRdsMaxRepo rdsMaxRepo)
{
_Repo = repo;
_RdsMaxRepo = rdsMaxRepo;
_MetrologyRepo = metrologyRepo;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
}
@ -33,7 +36,8 @@ public class PagesController : Controller
[HttpGet]
[Route("/AwaitingDispo")]
[Route("/Metrology/AwaitingDispo")]
public IActionResult AwaitingDispo() => View();
public IActionResult AwaitingDispo() =>
View();
[HttpGet]
[Route("/RunInfo")]
@ -48,7 +52,7 @@ public class PagesController : Controller
};
if (headerid > 0)
{
m.HeaderAttachmentID = _Repo.GetHeaderAttachmentID(tooltypeid, headerid);
m.HeaderAttachmentID = _MetrologyRepo.GetHeaderAttachmentID(tooltypeid, headerid);
}
return View(m);
}
@ -56,11 +60,13 @@ public class PagesController : Controller
[HttpGet]
[Route("/RunHeaders")]
[Route("/Metrology/RunHeaders")]
public IActionResult RunHeaders() => View();
public IActionResult RunHeaders() =>
View();
[HttpGet]
[Route("/Crash")]
public IActionResult Crash() => throw new Exception("Test unhandled exception");
public IActionResult Crash() =>
throw new Exception("Test unhandled exception");
[HttpGet]
[Route("/Step1")]
@ -72,33 +78,48 @@ public class PagesController : Controller
_ = IO.Directory.CreateDirectory(directory);
string[] model = new string[] { mod, equipment, layer, zone, rds, initials };
if (!string.IsNullOrEmpty(initials))
IO.File.WriteAllLines(IO.Path.Combine(directory, $"{DateTime.Now.Ticks}.rsv"), model);
IO.File.WriteAllLines(IO.Path.Combine(directory, $"{DateTime.Now.Ticks}-{initials}.rsv"), model);
return View(model);
}
[HttpGet]
[Route("/Step2")]
[Route("/Metrology/Step2")]
public IActionResult Step2(string mod) => View(new string[] { mod });
public IActionResult Step2(string mod) =>
View(new string[] { mod });
[HttpGet]
[Route("/Step3")]
[Route("/Metrology/Step3")]
public IActionResult Step3(string mod, string equipment) => View(new string[] { mod, equipment });
public IActionResult Step3(string mod, string equipment) =>
View(new string[] { mod, equipment });
[HttpGet]
[Route("/Step4")]
[Route("/Metrology/Step4")]
public IActionResult Step4(string mod, string equipment, string layer) => View(new string[] { mod, equipment, layer });
public IActionResult Step4(string mod, string equipment, string layer) =>
View(new string[] { mod, equipment, layer });
[HttpGet]
[Route("/Step5")]
[Route("/Metrology/Step5")]
public IActionResult Step5(string mod, string equipment, string layer, string zone) => View(new string[] { mod, equipment, layer, zone });
public IActionResult Step5(string mod, string equipment, string layer, string zone) =>
View(new string[] { mod, equipment, layer, zone });
[HttpGet]
[Route("/Step6")]
[Route("/Metrology/Step6")]
public IActionResult Step6(string mod, string equipment, string layer, string zone, string rds) => View(new string[] { mod, equipment, layer, zone, rds });
public IActionResult Step6(string mod, string equipment, string layer, string zone, string rds) =>
View(new string[] { mod, equipment, layer, zone, rds });
[HttpGet]
[Route("/RdsMax")]
[Route("/Metrology/RdsMax")]
public IActionResult RdsMax()
{
Shared.DataModels.RDS.Max[] collection = _RdsMaxRepo.GetMaxRDS();
List<string[]> results = _RdsMaxRepo.Convert(collection);
return View(results);
}
}

View File

@ -18,11 +18,26 @@ public class AppSettings
public string MonAResource { init; get; }
public string MonASite { init; get; }
public string OIExportPath { init; get; }
public string Oi2SqlConnectionString { init; get; }
public string URLs { init; get; }
public string WorkingDirectoryName { init; get; }
[JsonConstructor]
public AppSettings(string apiLoggingContentTypes, string apiLoggingPathPrefixes, string apiLogPath, string attachmentPath, string buildNumber, string company, string connectionString, string gitCommitSeven, string inboundApiAllowedIPList, string monAResource, string monASite, string oiExportPath, string urls, string workingDirectoryName)
public AppSettings(string apiLoggingContentTypes,
string apiLoggingPathPrefixes,
string apiLogPath,
string attachmentPath,
string buildNumber,
string company,
string connectionString,
string gitCommitSeven,
string inboundApiAllowedIPList,
string monAResource,
string monASite,
string oi2SqlConnectionString,
string oiExportPath,
string urls,
string workingDirectoryName)
{
ApiLoggingContentTypes = apiLoggingContentTypes;
ApiLoggingPathPrefixes = apiLoggingPathPrefixes;
@ -35,6 +50,7 @@ public class AppSettings
InboundApiAllowedIPList = inboundApiAllowedIPList;
MonAResource = monAResource;
MonASite = monASite;
Oi2SqlConnectionString = oi2SqlConnectionString;
OIExportPath = oiExportPath;
URLs = urls;
WorkingDirectoryName = workingDirectoryName;

View File

@ -20,6 +20,7 @@ public class AppSettings
[Display(Name = "Inbound Api Allowed IP List"), Required] public string InboundApiAllowedIPList { get; set; }
[Display(Name = "MonA Resource"), Required] public string MonAResource { get; set; }
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
[Display(Name = "Oi 2 Sql Connection String"), Required] public string Oi2SqlConnectionString { get; set; }
[Display(Name = "OI Export Path"), Required] public string OIExportPath { get; set; }
[Display(Name = "URLs"), Required] public string URLs { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
@ -47,6 +48,7 @@ public class AppSettings
appSettings.InboundApiAllowedIPList,
appSettings.MonAResource,
appSettings.MonASite,
appSettings.Oi2SqlConnectionString,
appSettings.OIExportPath,
appSettings.URLs,
appSettings.WorkingDirectoryName);

View File

@ -0,0 +1,31 @@
namespace OI.Metrology.Archive.Models.Binder;
public class Max
{
#pragma warning disable
public string reactor_type { get; set; }
public int reactor { get; set; }
public string ls_id { get; set; }
public string zone { get; set; }
public string load_lock_side { get; set; }
public int rds_no { get; set; }
public string ps_no { get; set; }
public string recipe_name { get; set; }
public int recipe_no { get; set; }
public string spec_type { get; set; }
public string spec_thick_mtool { get; set; }
public string spec_thick_mrecipe { get; set; }
public string spec_res_mtool { get; set; }
public string spec_res_mrecipe { get; set; }
public string spec_cres_mtool { get; set; }
public string spec_cres_mrecipe { get; set; }
public int ci_no { get; set; }
public string spec_clean_tool { get; set; }
public int? mv_no { get; set; }
public string scan_tool { get; set; }
public string spec_surfscan_recipe { get; set; }
public int? spec_ss_samp_qty { get; set; }
}

View File

@ -70,6 +70,7 @@ public class Program
_ = webApplicationBuilder.Services.AddScoped<IAttachmentsService, AttachmentsService>();
_ = webApplicationBuilder.Services.AddScoped<IInboundDataService, InboundDataService>();
_ = webApplicationBuilder.Services.AddScoped<IMetrologyRepo, MetrologyRepo>();
_ = webApplicationBuilder.Services.AddScoped<IRdsMaxRepo, RdsMaxRepo>();
_ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>();
_ = webApplicationBuilder.Services.AddSwaggerGen();
_ = webApplicationBuilder.Services.AddSession(sessionOptions =>

View File

@ -25,7 +25,8 @@ public class MetrologyRepo : IMetrologyRepo
private DbConnection GetDbConnection() => _DBConnectionFactory.GetDbConnection();
protected DbProviderFactory GetDbProviderFactory(IDbConnection conn) => DbProviderFactories.GetFactory(conn.GetType().Namespace);
protected DbProviderFactory GetDbProviderFactory(IDbConnection conn) =>
DbProviderFactories.GetFactory(conn.GetType().Namespace);
public bool IsTestDatabase()
{

View File

@ -0,0 +1,286 @@
using Microsoft.Extensions.Caching.Memory;
using OI.Metrology.Shared.DataModels.RDS;
using OI.Metrology.Shared.Repositories;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
namespace OI.Metrology.Archive.Repositories;
public class RdsMaxRepo : IRdsMaxRepo
{
private readonly IMemoryCache _Cache;
private readonly Models.AppSettings _AppSettings;
public RdsMaxRepo(Models.AppSettings appSettings, IMemoryCache memoryCache)
{
_Cache = memoryCache;
_AppSettings = appSettings;
}
protected void CacheItem(string key, object v)
{
System.Diagnostics.Debug.WriteLine("CacheItem: " + key);
_ = _Cache.Set(key, v, new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(1)));
}
private static string GetMaxRdsSql()
{
StringBuilder result = new();
_ = result.Append(" select ").
Append(" rt.reactor_type ").
Append(" , rr.reactor ").
Append(" , rt.ls_id ").
Append(" , rt.zone ").
Append(" , rr.load_lock_side ").
Append(" , rr.rds_no ").
Append(" , rt.ps_no ").
Append(" , rr.recipe_name ").
Append(" , rr.recipe_no ").
Append(" , rr.spec_type ").
Append(" , rt.spec_thick_mtool ").
Append(" , rt.spec_thick_mrecipe ").
Append(" , rt.spec_res_mtool ").
Append(" , rt.spec_res_mrecipe ").
Append(" , rt.spec_cres_mtool ").
Append(" , rt.spec_cres_mrecipe ").
Append(" , ci.ci_no ").
Append(" , ci.spec_clean_tool ").
Append(" , cr.mv_no ").
Append(" , cr.scan_tool ").
Append(" , cr.spec_surfscan_recipe ").
Append(" , cr.spec_ss_samp_qty ").
Append(" from ( ").
Append(" select rds_no ").
Append(" from lsl2sql.dbo.react_run qa ").
Append(" inner join ( ").
Append(" select max(qb.rds_no) max_rds_no, qb.reactor ").
Append(" from lsl2sql.dbo.react_run qb ").
Append(" where qb.load_sig != '' ").
Append(" and qb.load_sig_dtm > @load_sig_dtm ").
Append(" group by qb.reactor ").
Append(" ) qb ").
Append(" on qa.rds_no = qb.max_rds_no ").
Append(" ) as qc ").
Append(" inner join lsl2sql.dbo.react_run rr ").
Append(" on qc.rds_no = rr.rds_no ").
Append(" left join [lsl2sql].[dbo].[rds_test] rt ").
Append(" on rr.rds_no = rt.rds_no ").
Append(" left join [lsl2sql].[dbo].[clean_insp] ci ").
Append(" on rr.rds_no = ci.rds_no ").
Append(" and ci.stage = 'LWI' ").
Append(" left join [lsl2sql].[dbo].[clean_insp_scan_results] cr ").
Append(" on ci.ci_no = cr.ci_no ").
Append(" order by ").
Append(" rr.reactor ").
Append(" , rt.ls_id ").
Append(" , rt.zone ").
Append(" for json path ");
return result.ToString();
}
private string GetMaxRDSJson(string commandText)
{
StringBuilder result = new();
try
{
using DbConnection dbConnection = SqlClientFactory.Instance.CreateConnection();
dbConnection.ConnectionString = _AppSettings.Oi2SqlConnectionString;
dbConnection.Open();
using DbCommand dbCommand = dbConnection.CreateCommand();
dbCommand.CommandText = commandText;
using DbDataReader reader = dbCommand.ExecuteReader(CommandBehavior.SequentialAccess);
while (reader.Read())
_ = result.Append(reader.GetString(0));
dbConnection.Close();
}
catch (Exception)
{ }
return result.ToString();
}
public Max[] GetMaxRDS()
{
Max[] cached;
string cacheKey = "GetMaxRDS";
if (_Cache.TryGetValue(cacheKey, out cached))
return cached;
string loadSigDTM = DateTime.Now.AddDays(-90).ToString("yyyy-MM-dd 00:00:00.000");
string sql = GetMaxRdsSql();
string commandText = sql.Replace("@load_sig_dtm", $"'{loadSigDTM}'");
string json = GetMaxRDSJson(commandText);
Max[] r = System.Text.Json.JsonSerializer.Deserialize<Max[]>(json);
CacheItem(cacheKey, r);
return r;
}
private static Dictionary<int, List<Max>> GetReactorToRecords(Max[] collection)
{
Dictionary<int, List<Max>> results = new();
foreach (Max max in collection)
{
if (!results.ContainsKey(max.Reactor))
results.Add(max.Reactor, new());
results[max.Reactor].Add(max);
}
return results;
}
private static (string[], int[], int[], int[]) GetDistinct(Max[] collection)
{
List<string> layerCollection = new();
List<int> comboCollection = new();
List<int> zoneCollection = new();
List<int> cleanCollection = new();
foreach (Max max in collection)
{
if (!string.IsNullOrEmpty(max.LsId) && max.LsId[0] == 'L' && !layerCollection.Contains(max.LsId))
layerCollection.Add(max.LsId);
if (!string.IsNullOrEmpty(max.LsId) && max.LsId[0] != 'L' && int.TryParse(max.LsId, out int comboCheck) && !comboCollection.Contains(comboCheck))
comboCollection.Add(comboCheck);
if (!string.IsNullOrEmpty(max.Zone) && int.TryParse(max.Zone, out int zoneCheck) && !zoneCollection.Contains(zoneCheck))
zoneCollection.Add(zoneCheck);
if (max.MvNo.HasValue && !cleanCollection.Contains(max.MvNo.Value))
cleanCollection.Add(max.MvNo.Value);
}
return new(layerCollection.OrderBy(l => l).ToArray(), comboCollection.OrderBy(l => l).ToArray(), zoneCollection.OrderBy(l => l).ToArray(), cleanCollection.OrderBy(l => l).ToArray());
}
private static Max[] GetLayerZoneCollection(Dictionary<string, List<(string, Max)>> layerZoneToCollection)
{
Max[] results;
List<(string Sort, Max Max)> collection = new();
foreach (KeyValuePair<string, List<(string, Max)>> keyValuePair in layerZoneToCollection)
collection.AddRange(keyValuePair.Value);
results = (from l in collection orderby l.Sort select l.Max).ToArray();
return results;
}
private static Max[] GetLayerZoneCollection(string[] layerCollection, int[] comboCollection, int[] zoneCollection, List<Max> collection)
{
Max[] results;
string key;
string sort;
string distinct;
List<string> distinctCollection = new();
Dictionary<string, List<(string, Max)>> layerZoneToCollection = new();
foreach (string layer in layerCollection)
{
layerZoneToCollection.Add(string.Concat(layer, '.'), new());
foreach (int zone in zoneCollection)
layerZoneToCollection.Add(string.Concat(layer, '.', zone), new());
}
foreach (int combo in comboCollection)
{
layerZoneToCollection.Add(string.Concat(combo, '.'), new());
foreach (int zone in zoneCollection)
layerZoneToCollection.Add(string.Concat(combo, '.', zone), new());
}
foreach (Max max in collection)
{
if (string.IsNullOrEmpty(max.LsId))
continue;
sort = string.Concat(max.LsId.PadLeft(2, 'Z'), '.', max.Zone);
key = string.Concat(max.LsId, '.', max.Zone);
distinct = string.Concat(max.LsId, '\t', max.Zone, '\t', max.LoadLockSide, '\t', max.RdsNo, '\t', max.PsNo, '\t', max.RecipeName, '\t', max.SpecType, '\t', max.SpecThickMtool, '\t', max.SpecThickMrecipe, '\t', max.SpecResMtool, '\t', max.SpecResMrecipe, '\t', max.SpecCresMtool, '\t', max.SpecCresMrecipe);
if (distinctCollection.Contains(distinct))
continue;
distinctCollection.Add(distinct);
layerZoneToCollection[key].Add(new(sort, max));
}
results = GetLayerZoneCollection(layerZoneToCollection);
return results;
}
private static Max[] GetCleanCollection(Dictionary<int, List<(int, Max)>> layerZoneToCollection)
{
Max[] results;
List<(int Sort, Max Max)> collection = new();
foreach (KeyValuePair<int, List<(int, Max)>> keyValuePair in layerZoneToCollection)
collection.AddRange(keyValuePair.Value);
results = (from l in collection orderby l.Sort select l.Max).ToArray();
return results;
}
private static Max[] GetCleanCollection(int[] cleanCollection, List<Max> collection)
{
Max[] results;
int key;
string distinct;
List<string> distinctCollection = new();
Dictionary<int, List<(int, Max)>> cleanToCollection = new();
foreach (int clean in cleanCollection)
cleanToCollection.Add(clean, new());
foreach (Max max in collection)
{
if (max.MvNo is null)
continue;
key = max.MvNo.Value;
distinct = string.Concat(max.MvNo, '\t', max.ScanTool, '\t', max.SpecSurfscanRecipe, '\t', max.SpecSsSampQty);
if (distinctCollection.Contains(distinct))
continue;
distinctCollection.Add(distinct);
cleanToCollection[key].Add(new(key, max));
}
results = GetCleanCollection(cleanToCollection);
return results;
}
public List<string[]> Convert(Max[] collection)
{
List<string[]> results = new();
string[] row;
Max[] cleanCollectionB;
List<string> res = new();
Max[] layerZoneCollection;
List<string> clean = new();
List<string> thick = new();
List<string> centerRes = new();
StringBuilder stringBuilder = new();
_ = stringBuilder.Append($"Reactor\tReactorType\tRDS\tPSN\tName\tSpecType\tRes\tThick\tCenter Res\tClean");
row = stringBuilder.ToString().Split('\t');
results.Add(row);
Dictionary<int, List<Max>> reactorToRecords = GetReactorToRecords(collection);
(string[] layerCollection, int[] comboCollection, int[] zoneCollection, int[] cleanCollection) = GetDistinct(collection);
foreach (KeyValuePair<int, List<Max>> reactorToRecord in reactorToRecords)
{
res.Clear();
clean.Clear();
thick.Clear();
centerRes.Clear();
_ = stringBuilder.Clear();
foreach (Max max in reactorToRecord.Value)
{
_ = stringBuilder.Append($"R{max.Reactor}\t{max.ReactorType}\t{max.RdsNo}\t{max.PsNo}\t{max.RecipeName}\t{max.SpecType}\t");
break;
}
layerZoneCollection = GetLayerZoneCollection(layerCollection, comboCollection, zoneCollection, reactorToRecord.Value);
foreach (Max max in layerZoneCollection)
{
res.Add(string.Concat(max.LsId, '.', max.Zone, " - ", max.SpecResMtool, " {", max.SpecResMrecipe, '}'));
thick.Add(string.Concat(max.LsId, '.', max.Zone, " - ", max.SpecThickMtool, " {", max.SpecThickMrecipe, '}'));
centerRes.Add(string.Concat(max.LsId, '.', max.Zone, " - ", max.SpecCresMtool, " {", max.SpecCresMrecipe, '}'));
}
_ = stringBuilder.Append($"{string.Join("<br />", res.ToArray())}\t");
_ = stringBuilder.Append($"{string.Join("<br />", thick.ToArray())}\t");
_ = stringBuilder.Append($"{string.Join("<br />", centerRes.ToArray())}\t");
cleanCollectionB = GetCleanCollection(cleanCollection, reactorToRecord.Value);
foreach (Max max in cleanCollectionB)
clean.Add(string.Concat(max.MvNo, " - {", max.SpecSurfscanRecipe, "} [", max.SpecSsSampQty, "] ", max.ScanTool));
_ = stringBuilder.Append($"{string.Join("<br />", clean.ToArray())}");
row = stringBuilder.ToString().Split('\t');
results.Add(row);
}
return results;
}
}

View File

@ -12,6 +12,12 @@ public class SQLDbConnectionFactory : IDbConnectionFactory
public SQLDbConnectionFactory(AppSettings appSettings) => _AppSettings = appSettings;
public SQLDbConnectionFactory(string json)
{
AppSettings appSettings = System.Text.Json.JsonSerializer.Deserialize<AppSettings>(json);
_AppSettings = appSettings;
}
public DbConnection GetDbConnection()
{
DbProviderFactories.RegisterFactory(

View File

@ -0,0 +1,43 @@
@model System.Collections.Generic.List<string[]>
@{
ViewData["Title"] = "Max RDS per Reactor with Recipes";
}
<style>
html,
body {
height: 100%;
}
div.container-fluid {
height: 90%;
}
#HeaderGrid,
#FieldsGrid {
font-size: 12px;
}
.FieldTitle {
font-weight: bold;
}
</style>
<h4>Max RDS per Reactor with Recipes</h4>
<table border="1" style="width:100%">
@foreach (string[] row in Model)
{
<tr>
@foreach (string column in row)
{
<td>@Html.Raw(column)</td>
}
</tr>
}
</table>
<script>
$(document).ready(function () {
});
</script>

View File

@ -19,6 +19,7 @@
"InboundApiAllowedIPList": "",
"MonAResource": "OI_Metrology_Archive_IFX",
"MonASite": "auc",
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [

View File

@ -19,6 +19,7 @@
"InboundApiAllowedIPList": "",
"MonAResource": "OI_Metrology_Archive_EC",
"MonASite": "auc",
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [