fix: materialize stationary yutong daily mileage
This commit is contained in:
@@ -69,6 +69,7 @@ type AppendResult struct {
|
||||
SamplesSkippedMissingFields int
|
||||
SamplesSkippedMissingVIN int
|
||||
SamplesSkippedMissingMileage int
|
||||
SamplesRecoveredStationary int
|
||||
SamplesSkippedNonMileageFrame int
|
||||
SamplesSkippedNonPositiveMileage int
|
||||
SamplesSkippedMissingTime int
|
||||
@@ -282,6 +283,19 @@ func (w *Writer) AppendWithResult(ctx context.Context, env envelope.FrameEnvelop
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
var stationaryCandidate *SourceMileageSample
|
||||
if len(samples) == 0 && hasSource && result.SamplesSkippedMissingMileage > 0 {
|
||||
sample, candidate, recovered, recoverErr := w.stationaryCarryForward(ctx, env, identity)
|
||||
if recoverErr != nil {
|
||||
return result, recoverErr
|
||||
}
|
||||
if recovered {
|
||||
samples = []MetricSample{sample}
|
||||
stationaryCandidate = &candidate
|
||||
result.SamplesFound++
|
||||
result.SamplesRecoveredStationary++
|
||||
}
|
||||
}
|
||||
for _, sample := range samples {
|
||||
if !hasSource {
|
||||
result.SamplesSkippedMissingSource++
|
||||
@@ -293,8 +307,12 @@ func (w *Writer) AppendWithResult(ctx context.Context, env envelope.FrameEnvelop
|
||||
continue
|
||||
}
|
||||
candidate := SourceMileageSampleFromMetric(sample, identity)
|
||||
if err := w.applyRealtimeBaseline(ctx, &candidate); err != nil {
|
||||
return result, err
|
||||
if stationaryCandidate != nil {
|
||||
candidate = *stationaryCandidate
|
||||
} else {
|
||||
if err := w.applyRealtimeBaseline(ctx, &candidate); err != nil {
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
projectDaily := w.shouldProjectDailyMileage(sample)
|
||||
if projectDaily {
|
||||
@@ -316,6 +334,47 @@ func (w *Writer) AppendWithResult(ctx context.Context, env envelope.FrameEnvelop
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (w *Writer) stationaryCarryForward(ctx context.Context, env envelope.FrameEnvelope, identity SourceIdentity) (MetricSample, SourceMileageSample, bool, error) {
|
||||
if env.Protocol != envelope.ProtocolYutongMQTT || strings.TrimSpace(env.VIN) == "" {
|
||||
return MetricSample{}, SourceMileageSample{}, false, nil
|
||||
}
|
||||
location, ok := telemetry.LocationProjectionForProtocol(env.Protocol, env.Fields)
|
||||
if !ok || location.SpeedKMH == nil || *location.SpeedKMH != 0 {
|
||||
return MetricSample{}, SourceMileageSample{}, false, nil
|
||||
}
|
||||
eventMS, _, ok := envelope.NormalizedEventTimeMSWithReason(env)
|
||||
if !ok {
|
||||
return MetricSample{}, SourceMileageSample{}, false, nil
|
||||
}
|
||||
eventTime := time.UnixMilli(eventMS).In(w.loc)
|
||||
sample := MetricSample{
|
||||
VIN: strings.TrimSpace(env.VIN),
|
||||
Protocol: env.Protocol,
|
||||
StatDate: eventTime.Format("2006-01-02"),
|
||||
EventTime: eventTime,
|
||||
SourceKey: SourceKeyForSource(env.Protocol, env.Phone, env.DeviceID, identity.SourceIP, identity.SourceKind, identity.SourceCode),
|
||||
Phone: strings.TrimSpace(env.Phone),
|
||||
DeviceID: strings.TrimSpace(env.DeviceID),
|
||||
SourceEndpoint: strings.TrimSpace(env.SourceEndpoint),
|
||||
PlatformName: strings.TrimSpace(env.PlatformName),
|
||||
}
|
||||
candidate := SourceMileageSampleFromMetric(sample, identity)
|
||||
baseline, found, err := w.previousBaseline(ctx, candidate)
|
||||
if err != nil || !found || baseline.LatestTotalKM <= 0 || baseline.LatestEventTime.IsZero() {
|
||||
return MetricSample{}, SourceMileageSample{}, false, err
|
||||
}
|
||||
sample.TotalMileageKM = baseline.LatestTotalKM
|
||||
candidate = SourceMileageSampleFromMetric(sample, identity)
|
||||
candidate.FirstTotalKM = baseline.LatestTotalKM
|
||||
candidate.LatestTotalKM = baseline.LatestTotalKM
|
||||
candidate.DailyKM = 0
|
||||
candidate.FirstEventTime = baseline.LatestEventTime
|
||||
candidate.LatestEventTime = eventTime
|
||||
candidate.QualityStatus = QualityOK
|
||||
candidate.QualityReason = QualityReasonStationaryCarry
|
||||
return sample, candidate, true, nil
|
||||
}
|
||||
|
||||
func (w *Writer) writeMileageSample(ctx context.Context, sample MetricSample, candidate SourceMileageSample, projectDaily bool) error {
|
||||
if projectDaily {
|
||||
if beginner, ok := w.exec.(txBeginner); ok {
|
||||
|
||||
Reference in New Issue
Block a user