| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 | package modelimport (	"fmt"	"kpt-pasture/util"	"math"	"strconv"	"strings"	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow")const (	InitChangeFilter     = -10000	DefaultChangeFilter  = -99	DefaultRuminaFilter  = -99	DefaultChewFilter    = -99	DefaultFilterCorrect = 100	DefaultWeeklyActive  = 1500	DefaultRecordCount   = 6	LowActivity          = 62	MiddleActivity       = 80)type NeckActiveHabit struct {	Id                   int64                 `json:"id"`	PastureId            int64                 `json:"pastureId"`	NeckRingNumber       string                `json:"neckRingNumber"`	CowId                int64                 `json:"cowId"`	EarNumber            string                `json:"earNumber"`	Lact                 int32                 `json:"lact"`	CalvingAge           int32                 `json:"calvingAge"`	PenId                int32                 `json:"penId"`	ActiveTime           string                `json:"activeTime"`	Frameid              int32                 `json:"frameid"`	HeatDate             string                `json:"heatDate"`	Rumina               int32                 `json:"rumina"`	Intake               int32                 `json:"intake"`	Inactive             int32                 `json:"inactive"`	Gasp                 int32                 `json:"gasp"`	Other                int32                 `json:"other"`	High                 int32                 `json:"high"`	Active               int32                 `json:"active"`	FilterHigh           int32                 `json:"filterHigh"`	FilterRumina         int32                 `json:"filterRumina"`	FilterChew           int32                 `json:"filterChew"`	WeekHigh             int32                 `json:"weekHigh"`	HighHabit            int32                 `json:"highHabit"`	RuminaHabit          int32                 `json:"ruminaHabit"`	IntakeHabit          int32                 `json:"intakeHabit"`	ChewHabit            int32                 `json:"chewHabit"`	InactiveHabit        int32                 `json:"inactiveHabit"`	OtherHabit           int32                 `json:"otherHabit"`	ChangeHigh           int32                 `json:"changeHigh"`	ChangeRumina         int32                 `json:"changeRumina"`	ChangeChew           int32                 `json:"changeChew"`	ChangeAdjust         int32                 `json:"changeAdjust"`	ChangeFilter         int32                 `json:"changeFilter"`	RuminaFilter         int32                 `json:"ruminaFilter"`	ChewFilter           int32                 `json:"chewFilter"`	FilterCorrect        int32                 `json:"filterCorrect"`	SumRumina            int32                 `json:"sumRumina"`	SumIntake            int32                 `json:"sumIntake"`	SumInactive          int32                 `json:"sumInactive"`	SumActive            int32                 `json:"sumActive"`	SumMinHigh           int32                 `json:"sumMinHigh"`	SumMaxHigh           int32                 `json:"sumMaxHigh"`	SumMinChew           int32                 `json:"SumMinChew"`	BeforeThreeSumRumina int32                 `json:"beforeThreeSumRumina"`	BeforeThreeSumIntake int32                 `json:"beforeThreeSumIntake"`	Score                int32                 `json:"score"`	IsShow               pasturePb.IsShow_Kind `json:"isShow"`	Cft                  float32               `json:"cft"`	Voltage              int32                 `json:"voltage"`	RecordCount          int32                 `json:"recordCount"`	FirmwareVersion      int32                 `json:"firmwareVersion"`	CreatedAt            int64                 `json:"createdAt"`	UpdatedAt            int64                 `json:"updatedAt"`}func (n *NeckActiveHabit) UnShardTableName() string {	return "neck_active_habit"}/*func (n *NeckActiveHabit) TableName() string {	return fmt.Sprintf("%s_%06d", n.UnShardTableName(), n.PastureId)}*/func (n *NeckActiveHabit) TableName() string {	return "neck_active_habit"}func (n *NeckActiveHabit) SumAvg() {	n.Rumina = n.Rumina / n.RecordCount * n.RecordCount	n.Inactive = n.Inactive / n.RecordCount * n.RecordCount	n.Active = n.Active / n.RecordCount * n.RecordCount	n.Intake = n.Intake / n.RecordCount * n.RecordCount	n.Other = n.Other / n.RecordCount * n.RecordCount	n.Gasp = n.Gasp / n.RecordCount * n.RecordCount	n.High = n.High / n.RecordCount * n.RecordCount}func (n *NeckActiveHabit) UpdateIsShowOk() {	n.IsShow = pasturePb.IsShow_Ok}func NewNeckActiveHabit(data *NeckRingOriginalMerge) *NeckActiveHabit {	return &NeckActiveHabit{		PastureId:       data.PastureId,		Frameid:         data.XframeId,		HeatDate:        data.ActiveDate,		NeckRingNumber:  data.NeckRingNumber,		Active:          data.Active,		Gasp:            data.Gasp,		High:            data.High,		Inactive:        data.Inactive,		Intake:          data.Intake,		Other:           data.Other,		Rumina:          data.Rumina,		IsShow:          data.IsShow,		WeekHigh:        DefaultWeeklyActive,		ChangeFilter:    InitChangeFilter,		FilterCorrect:   InitChangeFilter,		RuminaFilter:    InitChangeFilter,		ChewFilter:      InitChangeFilter,		ActiveTime:      fmt.Sprintf("%s %02d:00:00", data.ActiveDate, data.XframeId*2+1),		RecordCount:     data.RecordCount,		FirmwareVersion: data.FirmwareVersion,		Voltage:         data.Voltage,	}}type NeckActiveHabitSlice []*NeckActiveHabitfunc (n NeckActiveHabitSlice) Len() int      { return len(n) }func (n NeckActiveHabitSlice) Swap(i, j int) { n[i], n[j] = n[j], n[i] }func (n NeckActiveHabitSlice) Less(i, j int) bool {	if n[i].HeatDate != n[j].HeatDate {		return n[i].HeatDate < n[j].HeatDate	}	return n[i].Frameid < n[j].Frameid}func (n NeckActiveHabitSlice) ToPB(curveName string) *CowBehaviorCurveData {	res := &CowBehaviorCurveData{		OriginalDateList: make([]int32, 0),		ChangeDateList:   make([]int32, 0),		SumDateList:      make([]int32, 0),		DateTimeList:     make([]string, 0),		EstrusList:       make(map[pasturePb.EstrusLevel_Kind][]string),		EventList:        make([]*pasturePb.CowEvent, 0),		EventMap:         make(map[pasturePb.EventType_Kind]string),		RuminaChange:     make([]int32, 0),		IQR1:             make([]int32, 0),		IQR3:             make([]int32, 0),	}	initFrameId := int32(0)	dateFrameMap := make(map[string][]int32)	for _, v := range n {		if dateFrameMap[v.HeatDate] == nil {			initFrameId = 0			dateFrameMap[v.HeatDate] = make([]int32, 0)		}		// 补全结尾不够的数据		if initFrameId == 0 && len(res.DateTimeList) > 0 {			lastDateTime := res.DateTimeList[len(res.DateTimeList)-1]			lastDatePare := strings.Split(lastDateTime, " ")			if len(lastDatePare) == 2 {				lastDay := lastDatePare[0]				lastHourStr := lastDatePare[1]				lastHour, _ := strconv.ParseInt(lastHourStr, 10, 64)				maxHour := util.ExpectedFrameIDs[len(util.ExpectedFrameIDs)-1]				xframeId := int32(lastHour-1)/2 + 1				if xframeId != maxHour {					for ; xframeId <= maxHour; xframeId++ {						res.DateTimeList = append(res.DateTimeList, fmt.Sprintf("%s %02d", lastDay, util.ExpectedFrameIDs[xframeId]*2+1))						res.OriginalDateList = append(res.OriginalDateList, 0)						res.ChangeDateList = append(res.ChangeDateList, 0)						res.SumDateList = append(res.SumDateList, 0)						res.RuminaChange = append(res.RuminaChange, 0)						res.SumChewList = append(res.SumChewList, 0)					}				}			}		}		expectedFrameId := util.ExpectedFrameIDs[initFrameId]		if expectedFrameId != v.Frameid {			maxFrameId := int32(math.Abs(float64(expectedFrameId - v.Frameid)))			for ; expectedFrameId < maxFrameId; expectedFrameId++ {				res.DateTimeList = append(res.DateTimeList, fmt.Sprintf("%s %02d", v.HeatDate, util.ExpectedFrameIDs[expectedFrameId]*2+1))				res.OriginalDateList = append(res.OriginalDateList, 0)				res.ChangeDateList = append(res.ChangeDateList, 0)				res.SumDateList = append(res.SumDateList, 0)				res.RuminaChange = append(res.RuminaChange, 0)				res.SumChewList = append(res.SumChewList, 0)			}			initFrameId = expectedFrameId		}		// 格式化为到小时的字符串		parsedTime, _ := util.TimeParseLocal(LayoutTime, v.ActiveTime)		hourStr := parsedTime.Format(LayoutHour)		res.DateTimeList = append(res.DateTimeList, hourStr)		switch curveName {		case "active": // 活动量			changeDateList := v.ChangeFilter * v.FilterCorrect / 100			if changeDateList == DefaultChangeFilter {				changeDateList = 0			}			res.OriginalDateList = append(res.OriginalDateList, v.High)			res.ChangeDateList = append(res.ChangeDateList, changeDateList)			res.RuminaChange = append(res.RuminaChange, v.RuminaFilter)		case "rumina": // 反刍			res.OriginalDateList = append(res.OriginalDateList, v.Rumina)			res.ChangeDateList = append(res.ChangeDateList, v.RuminaFilter)			res.SumDateList = append(res.SumDateList, v.SumRumina)			res.SumChewList = append(res.SumChewList, v.SumRumina+v.SumIntake)		case "intake": // 采食			res.OriginalDateList = append(res.OriginalDateList, v.Intake)			res.SumDateList = append(res.SumDateList, v.SumIntake)			res.SumChewList = append(res.SumChewList, v.SumRumina+v.SumIntake)		case "inactive": // 休息			res.OriginalDateList = append(res.OriginalDateList, v.Inactive)			res.SumDateList = append(res.SumDateList, v.SumInactive)		case "chew": // 咀嚼			res.OriginalDateList = append(res.OriginalDateList, v.Rumina+v.Intake)			res.ChangeDateList = append(res.ChangeDateList, v.ChewFilter)			res.SumDateList = append(res.SumDateList, v.SumRumina+v.SumIntake)		case "immobility": // 静止			res.OriginalDateList = append(res.OriginalDateList, 120-v.Active)			res.SumDateList = append(res.SumDateList, 60*24-v.SumActive)		}		initFrameId++	}	return res}func (n NeckActiveHabitSlice) ToPB2(dataBetween []string, groupNeckActiveHabitList []*NeckActiveHabit) *pasturePb.CowBehaviorRateData {	data := &pasturePb.CowBehaviorRateData{		DateTime:     dataBetween,		RuminaRate:   make([]float32, 0),		IntakeRate:   make([]float32, 0),		InactiveRate: make([]float32, 0),		GaspRate:     make([]float32, 0),	}	neckActiveHabitMap := make(map[string]*NeckActiveHabit)	for _, v := range n {		if v.HeatDate == "" {			continue		}		if _, ok := neckActiveHabitMap[v.HeatDate]; !ok {			neckActiveHabitMap[v.HeatDate] = v		}	}	groupNeckActiveHabitMap := make(map[string]*NeckActiveHabit)	for _, v := range groupNeckActiveHabitList {		if v.HeatDate == "" {			continue		}		if _, ok := groupNeckActiveHabitMap[v.HeatDate]; !ok {			groupNeckActiveHabitMap[v.HeatDate] = v		}	}	for _, t := range dataBetween {		ruminaRate, intakeRate, inactiveRate, gaspRate := float32(0), float32(0), float32(0), float32(0)		if v, ok := neckActiveHabitMap[t]; ok {			sum := v.Rumina + v.Intake + v.Inactive + v.Gasp			if sum > 0 {				// 保留小数点后两位				ruminaRate = float32(math.Round(float64(v.Rumina)/float64(sum)*100) / 100)				intakeRate = float32(math.Round(float64(v.Intake)/float64(sum)*100) / 100)				inactiveRate = float32(math.Round(float64(v.Inactive)/float64(sum)*100) / 100)				gaspRate = float32(math.Round(float64(v.Gasp)/float64(sum)*100) / 100)			}		}		data.RuminaRate = append(data.RuminaRate, ruminaRate)		data.IntakeRate = append(data.IntakeRate, intakeRate)		data.InactiveRate = append(data.InactiveRate, inactiveRate)		data.GaspRate = append(data.GaspRate, gaspRate)		groupRuminaRate, groupIntakeRate, groupInactiveRate, groupGaspRate := float32(0), float32(0), float32(0), float32(0)		if v, ok := groupNeckActiveHabitMap[t]; ok {			groupSum := v.Rumina + v.Intake + v.Inactive + v.Gasp			if groupSum > 0 {				// 保留小数点后两位				groupRuminaRate = float32(math.Round(float64(v.Rumina)/float64(groupSum)*100) / 100)				groupIntakeRate = float32(math.Round(float64(v.Intake)/float64(groupSum)*100) / 100)				groupInactiveRate = float32(math.Round(float64(v.Inactive)/float64(groupSum)*100) / 100)				groupGaspRate = float32(math.Round(float64(v.Gasp)/float64(groupSum)*100) / 100)			}		}		data.GroupRuminaRate = append(data.GroupRuminaRate, groupRuminaRate)		data.GroupIntakeRate = append(data.GroupIntakeRate, groupIntakeRate)		data.GroupInactiveRate = append(data.GroupInactiveRate, groupInactiveRate)		data.GroupGaspRate = append(data.GroupGaspRate, groupGaspRate)	}	return data}type MaxHabitIdModel struct {	Id int64 `json:"id"`}type WeeklyActiveModel struct {	CowId    int64  `json:"cow_id"`	HeatDate string `json:"heat_date"`	Nb       int32  `json:"nb"`	High     int32  `json:"high"`}type NeckRingErrorModel struct {	CowId   int64	Nb      int32	Nba     int32	Voltage int32}
 |