chenluhua1980
2026-01-07 7e0e199c4adc819b5784f689de98b8569025ed53
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#pragma once
 
#include <chrono>
#include <map>
#include <string>
 
class CConfiguration;
 
enum class ProductionShiftType : int {
    Day = 1,
    Night = 2
};
 
struct ProductionShiftWindow {
    ProductionShiftType type{ ProductionShiftType::Day };
    std::chrono::system_clock::time_point start{};
    std::chrono::system_clock::time_point end{};
    std::string startLocal;   // "YYYY-MM-DD HH:MM:SS"
    std::string endLocal;     // "YYYY-MM-DD HH:MM:SS"
    std::string startUtcIso;  // "YYYY-MM-DDTHH:MM:SSZ"
    std::string endUtcIso;    // "YYYY-MM-DDTHH:MM:SSZ"
};
 
struct ProductionOutputSummary {
    long long pairsTotal = 0;        // "对数"
    long long pairsPass = 0;
    long long pairsFail = 0;
    long long pairsNoResult = 0;
    double yield = 0.0;              // pairsPass / (pairsPass + pairsFail), 0 if denom==0
 
    // Average takt time derived from glass_log.t_start/t_end (per pair, seconds)
    double avgTaktSeconds = 0.0;
    long long taktSamplePairs = 0;
};
 
struct ProductionAlarmSummary {
    int alarmsTriggered = 0;         // start_time within shift window
    int alarmsOverlapping = 0;       // overlaps shift window (including active)
    double downtimeMinutes = 0.0;    // overlap minutes (best-effort)
    std::map<int, int> bySeverity;   // severity_level -> count (overlapping)
};
 
struct ProductionTransferSummary {
    int transfersFinished = 0;        // end_time within shift window
    std::map<std::string, int> byStatus;
    double avgCreateToEndSeconds = 0.0;
};
 
struct ProductionShiftSummary {
    ProductionShiftWindow window;
    ProductionOutputSummary output;
    ProductionAlarmSummary alarms;
    ProductionTransferSummary transfers;
};
 
class ProductionStats {
public:
    static bool GetCurrentShiftWindow(CConfiguration& config, ProductionShiftWindow& outWindow);
    static bool ComputeCurrentShiftSummary(CConfiguration& config, ProductionShiftSummary& outSummary);
    static void LogCurrentShiftSummary(CConfiguration& config);
 
    // Computes "current shift" and its adjacent other shift, so UI can always show Day+Night numbers.
    // - If current is Day: day=current day shift, night=previous night shift.
    // - If current is Night: night=current night shift, day=previous day shift.
    static bool ComputeDayNightSummaries(CConfiguration& config, ProductionShiftSummary& outDay, ProductionShiftSummary& outNight);
};