using System; using System.Collections.Generic; using ILSOS_CCW_H52A.Sequences; using ILSOS_CCW_H52A.Data; namespace ILSOS_CCW_H52A.Data { // 물리 지그 번호 (0-based enum, 1-based 변환: (eJigNo)(jigNo - 1)) public enum eJigNo { Jig1, Jig2, Jig3, Jig4, Jig5, Jig6, Jig7, Jig8, Jig9, Jig10, Jig11, Jig12, Jig13, Jig14, Jig15, Jig16, } /// /// Dictionary<eJigNo, JigInfo> 상속으로 물리 지그 번호 직접 접근과 /// 파이프라인 단계 접근을 동시에 지원하는 셀 스케줄러. /// /// - 물리 지그 접근: scheduler[eJigNo.Jig5] /// - 파이프라인 접근: scheduler.Prefetch1, scheduler.Prefetch2 /// /// 3단계 파이프라인: Prefetch2 → Prefetch1 → ReportTarget /// Prefetch2 : 셀 정보 수신 완료, 스캐너 리스트 업로드 전 /// Prefetch1 : 업로드 완료, 실행 중 — EncoderMonitor 감시 + 완료 체크 대상 /// ReportTarget: 완료, 보고 대기 /// /// Shift()는 Prefetch2→Prefetch1만 전진. GC 할당 없음. /// Prefetch1 ← Prefetch2 ← this[nextJig] /// public class CellInfoScheduler : Dictionary { public JigInfo Prefetch2 { get; private set; } // 전전 셀: 셀 정보 수신, 업로드 전 public JigInfo Prefetch1 { get; private set; } // 전 셀: 업로드 완료, 실행 중 / 완료 체크 대상 /// 현재 보고 대상 JigInfo (CheckScannerListComplete에서 지정, 보고 완료 후 null) public JigInfo ReportTarget { get; set; } // 재시작 보존용 독립 슬롯 — Reset()에서 건드리지 않음 private readonly JigInfo _pendingSlot = new JigInfo(); // 재시작 전 미완료 보고 슬롯 (유효 시 non-null) public JigInfo PendingComplete => HasPendingComplete ? _pendingSlot : null; // 재시작 보존 보고가 있는지 public bool HasPendingComplete => _pendingSlot.IsCanExist && !_pendingSlot.ReportComplete; // 현재 활성 보고 슬롯 — 재시작 pending 우선 public JigInfo ActiveReportSlot => HasPendingComplete ? _pendingSlot : ReportTarget; // 보고가 필요한 상태인지 (정상 + 재시작 모두 포함) public bool HasReport => HasPendingComplete || (ReportTarget != null && !ReportTarget.ReportComplete); public CellInfoScheduler() { foreach (eJigNo no in Enum.GetValues(typeof(eJigNo))) Add(no, new JigInfo()); } // 1-based jigNo (_WeldingJigNo 등) → 0-based eJigNo 변환 편의 인덱서 public JigInfo this[int jigNo] { get => base[(eJigNo)(jigNo - 1)]; } // Reset() 전에 호출 — 미완료 보고가 있으면 보류 슬롯(_pendingSlot)에 복사하여 보존. public void SavePendingComplete() { if (ReportTarget != null && ReportTarget.IsCanExist && ReportTarget.WeldComplete && !ReportTarget.ReportComplete) _pendingSlot.CopyFrom(ReportTarget); } // 보고 완료 처리 — ReportTarget 마킹 및 _pendingSlot 클리어. // GetReportCellResult_SeqResult 성공 시 호출. public void CompleteReport() { ReportTarget?.SetReportComplete(true); ReportTarget = null; _pendingSlot.Clear(); } /// /// Prefetch2→Prefetch1 한 칸 전진. GC 할당 없음. /// 새 Prefetch2 슬롯은 Clear 후 반환 — 호출자가 셀 정보를 채워야 한다. /// /// 새 Prefetch2로 지정할 물리 지그 (eJigNo) public void Shift(eJigNo nextJig) { Prefetch1 = Prefetch2; Prefetch2 = this[nextJig]; Prefetch2.Clear(); } /// /// 전체 초기화 (AutoRun 시작 시 호출). /// SavePendingComplete() 호출 후 이 메서드를 호출할 것. /// _pendingSlot은 재시작 보고 보존을 위해 건드리지 않음. /// public void Reset() { foreach (var info in Values) info.Clear(); Prefetch2 = null; Prefetch1 = null; ReportTarget = null; // _pendingSlot: SavePendingComplete()가 복사해 둔 데이터를 유지 } /// /// 스케줄러 자체는 Clear 할 수 없도록 함 /// public new void Clear() { Reset(); } } }