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; #nullable disable public class RdsMaxRepo : IRdsMaxRepo { private readonly IMemoryCache _MemoryCache; private readonly Models.AppSettings _AppSettings; public RdsMaxRepo(Models.AppSettings appSettings, IMemoryCache memoryCache) { _MemoryCache = memoryCache; _AppSettings = appSettings; } public RdsMaxRepo(string json, IMemoryCache memoryCache) { _MemoryCache = memoryCache; Models.AppSettings appSettings = System.Text.Json.JsonSerializer.Deserialize(json); _AppSettings = appSettings; } protected void CacheItem(string key, object v) { System.Diagnostics.Debug.WriteLine("CacheItem: " + key); _ = _MemoryCache.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(" , rr.wo_no "). Append(" , rr.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(" , 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(" and rr.ps_no = rt.ps_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 (_MemoryCache.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(json); CacheItem(cacheKey, r); return r; } private static Dictionary> GetReactorToRecords(Max[] collection) { Dictionary> 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 layerCollection = new(); List comboCollection = new(); List zoneCollection = new(); List 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> layerZoneToCollection) { Max[] results; List<(string Sort, Max Max)> collection = new(); foreach (KeyValuePair> 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 collection) { Max[] results; string key; string sort; string distinct; List distinctCollection = new(); Dictionary> 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> layerZoneToCollection) { Max[] results; List<(int Sort, Max Max)> collection = new(); foreach (KeyValuePair> 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 collection) { Max[] results; int key; string distinct; List distinctCollection = new(); Dictionary> 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 Convert(Max[] collection) { List results = new(); string[] row; Max[] cleanCollectionB; List res = new(); Max[] layerZoneCollection; List clean = new(); List thick = new(); List centerRes = new(); StringBuilder stringBuilder = new(); _ = stringBuilder.Append($"Reactor\tReactorType\tWO\tRDS\tPSN\tName\tSpecType\tRes\tThick\tCenter Res\tScan"); row = stringBuilder.ToString().Split('\t'); results.Add(row); Dictionary> reactorToRecords = GetReactorToRecords(collection); (string[] layerCollection, int[] comboCollection, int[] zoneCollection, int[] cleanCollection) = GetDistinct(collection); foreach (KeyValuePair> 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.WoNo}\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("
", res.ToArray())}\t"); _ = stringBuilder.Append($"{string.Join("
", thick.ToArray())}\t"); _ = stringBuilder.Append($"{string.Join("
", 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("
", clean.ToArray())}"); row = stringBuilder.ToString().Split('\t'); results.Add(row); } return results; } }