// Package util provide some utility fun package util import ( "fmt" "modelRT/orm" ) type CalculationResult struct { BaseValue float64 Changes []float64 Size int BaseType string // "normal", "warning", "edge" Message string } func ProcessMeasurements(measurements []orm.Measurement) map[string]CalculationResult { results := make(map[string]CalculationResult, len(measurements)) for _, measurement := range measurements { // 检查 DataSource 是否存在且 type 为 1 if measurement.DataSource == nil { continue } // 检查 type 是否为 1 dataType, typeExists := measurement.DataSource["type"] if !typeExists { continue } // 类型断言,处理不同的数字类型 var typeValue int switch v := dataType.(type) { case int: typeValue = v case float64: typeValue = int(v) case int64: typeValue = int(v) default: continue } if typeValue != 1 { continue } // 获取 io_address ioAddressRaw, ioExists := measurement.DataSource["io_address"] if !ioExists { continue } ioAddress, ok := ioAddressRaw.(map[string]any) if !ok { continue } station, _ := ioAddress["station"].(string) device, _ := ioAddress["device"].(string) channel, _ := ioAddress["channel"].(string) result := fmt.Sprintf("%s:%s:phasor:%s", station, device, channel) if measurement.EventPlan == nil { continue } causeValue, causeExist := measurement.EventPlan["cause"] if !causeExist { continue } causeMap, ok := causeValue.(map[string]any) if !ok { continue } calResult, err := calculateBaseValueEnhanced(causeMap) if err != nil { continue } calResult.Size = measurement.Size results[result] = calResult } return results } func calculateBaseValueEnhanced(data map[string]any) (CalculationResult, error) { result := CalculationResult{} if edge, exists := data["edge"]; exists { value, err := calculateEdgeValue(edge) if err != nil { return result, err } if edge == "raising" { result.Changes = []float64{1.0} } else { result.Changes = []float64{0.0} } result.BaseValue = value result.BaseType = "TI" result.Message = "边沿触发基准值" return result, nil } hasUpDown := HasKeys(data, "up", "down") hasUpUpDownDown := HasKeys(data, "upup", "downdown") result.BaseType = "TE" switch { case hasUpDown && hasUpUpDownDown: value, err := calculateAverage(data, "up", "down") if err != nil { return result, err } result.BaseValue = value result.Changes, err = calculateChanges(data, value, false, 4) if err != nil { return result, err } result.Message = "上下限基准值(忽略预警上上下下限)" return result, nil case hasUpDown: value, err := calculateAverage(data, "up", "down") if err != nil { return result, err } result.BaseValue = value result.Changes, err = calculateChanges(data, value, false, 2) if err != nil { return result, err } result.Message = "上下限基准值" return result, nil case hasUpUpDownDown: value, err := calculateAverage(data, "upup", "downdown") if err != nil { return result, err } result.BaseValue = value result.Changes, err = calculateChanges(data, value, true, 2) if err != nil { return result, err } result.Message = "上上下下限基准值" return result, nil default: return result, fmt.Errorf("不支持的数据结构: %v", data) } } func calculateAverage(data map[string]any, key1, key2 string) (float64, error) { val1, err := getFloatValue(data, key1) if err != nil { return 0, err } val2, err := getFloatValue(data, key2) if err != nil { return 0, err } return (val1 + val2) / 2.0, nil } func calculateChanges(data map[string]any, baseValue float64, maxLimt bool, limitNum int) ([]float64, error) { results := make([]float64, 0, limitNum) switch limitNum { case 2: var key1, key2 string if maxLimt { key1 = "upup" key2 = "downdown" } else { key1 = "up" key2 = "down" } val1, err := getFloatValue(data, key1) if err != nil { return nil, err } results = append(results, val1-baseValue) val2, err := getFloatValue(data, key2) if err != nil { return nil, err } results = append(results, val2-baseValue) case 4: key1 := "up" key2 := "down" key3 := "upup" key4 := "downdown" val1, err := getFloatValue(data, key1) if err != nil { return nil, err } results = append(results, val1-baseValue) val2, err := getFloatValue(data, key2) if err != nil { return nil, err } results = append(results, val2-baseValue) val3, err := getFloatValue(data, key3) if err != nil { return nil, err } results = append(results, val3-baseValue) val4, err := getFloatValue(data, key4) if err != nil { return nil, err } results = append(results, val4-baseValue) } return results, nil } func getFloatValue(data map[string]any, key string) (float64, error) { value, exists := data[key] if !exists { return 0, fmt.Errorf("缺少必需的键:%s", key) } switch v := value.(type) { case float64: return v, nil case int: return float64(v), nil case float32: return float64(v), nil default: return 0, fmt.Errorf("键 %s 的值类型错误,期望数字类型,得到 %T", key, value) } } func HasKeys(data map[string]any, keys ...string) bool { for _, key := range keys { if _, exists := data[key]; !exists { return false } } return true } func calculateEdgeValue(edge any) (float64, error) { edgeStr, ok := edge.(string) if !ok { return 0, fmt.Errorf("edge 字段类型错误,期望 string,得到 %T", edge) } switch edgeStr { case "raising": return 1.0, nil case "falling": return 0.0, nil default: return 0, fmt.Errorf("不支持的 edge 值: %s", edgeStr) } }