neck_ring_calculate.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. package crontab
  2. import (
  3. "fmt"
  4. "kpt-pasture/model"
  5. "math"
  6. "sort"
  7. "time"
  8. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  9. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  10. "gitee.com/xuyiping_admin/pkg/xerr"
  11. "go.uber.org/zap"
  12. )
  13. func (e *Entry) NeckRingCalculate() error {
  14. pastureList := e.FindPastureList()
  15. if pastureList == nil || len(pastureList) == 0 {
  16. return nil
  17. }
  18. if calculateIsRunning {
  19. return nil
  20. }
  21. defer func() {
  22. calculateIsRunning = false
  23. }()
  24. calculateIsRunning = true
  25. for _, pasture := range pastureList {
  26. if err := e.EntryUpdateActiveHabit(pasture.Id); err != nil {
  27. zaplog.Error("NeckRingCalculate", zap.Any("err", err), zap.Any("pasture", pasture))
  28. }
  29. zaplog.Info(fmt.Sprintf("NeckRingCalculate Success %d", pasture.Id))
  30. }
  31. return nil
  32. }
  33. func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
  34. // 获取这段执行数据内最大日期和最小日期
  35. xToday := &XToday{}
  36. systemConfigureList, err := e.GetSystemNeckRingConfigure(pastureId)
  37. if err != nil {
  38. return xerr.WithStack(err)
  39. }
  40. for _, v := range systemConfigureList {
  41. switch v.Name {
  42. case model.MaxHabit:
  43. xToday.LastMaxHabitId = v.Value
  44. case model.High:
  45. xToday.High = int32(v.Value)
  46. case model.Rumina:
  47. xToday.Rumina = int32(v.Value)
  48. case model.XRuminaDisc:
  49. xToday.XRuminaDisc = int32(v.Value)
  50. case model.XChangeDiscount:
  51. xToday.XChangeDiscount = int32(v.Value)
  52. case model.WeeklyActive:
  53. xToday.WeeklyActive = int32(v.Value)
  54. }
  55. }
  56. currMaxHabit := &model.NeckActiveHabit{}
  57. if err = e.DB.Model(new(model.NeckActiveHabit)).
  58. Where("id > ?", xToday.LastMaxHabitId).
  59. Where("pasture_id = ?", pastureId).
  60. Where("is_show = ?", pasturePb.IsShow_No).
  61. Order("id desc").
  62. First(currMaxHabit).Error; err != nil {
  63. return xerr.WithStack(err)
  64. }
  65. if currMaxHabit.Id <= 0 || currMaxHabit.Id <= xToday.LastMaxHabitId {
  66. return nil
  67. }
  68. xToday.CurrMaxHabitId = currMaxHabit.Id
  69. var processIds []int64
  70. // 更新活动滤波
  71. processIds, err = e.FirstFilterUpdate(pastureId, xToday)
  72. if err != nil {
  73. zaplog.Error("NeckRingCalculate", zap.Any("FirstFilterUpdate", err), zap.Any("xToday", xToday))
  74. }
  75. zaplog.Info("NeckRingCalculate", zap.Any("xToday", xToday), zap.Any("processIds", processIds))
  76. if len(processIds) <= 0 {
  77. return nil
  78. }
  79. if err = e.WeeklyUpdateActiveHabit(pastureId, processIds, xToday); err != nil {
  80. zaplog.Error("NeckRingCalculate", zap.Any("WeeklyUpdateActiveHabit", err), zap.Any("xToday", xToday))
  81. }
  82. if err = e.Before3DaysNeckActiveHabit(pastureId, processIds, xToday); err != nil {
  83. zaplog.Error("NeckRingCalculate", zap.Any("Before3DaysNeckActiveHabit", err), zap.Any("xToday", xToday))
  84. }
  85. // 二次更新滤波
  86. if err = e.SecondUpdateChangeFilter(pastureId, xToday); err != nil {
  87. zaplog.Error("NeckRingCalculate", zap.Any("SecondUpdateChangeFilter", err), zap.Any("xToday", xToday))
  88. }
  89. // 活动量校正系数和健康评分
  90. if err = e.FilterCorrectAndScoreUpdate(pastureId, processIds, xToday); err != nil {
  91. zaplog.Error("NeckRingCalculate", zap.Any("ActivityVolumeChanges", err), zap.Any("xToday", xToday))
  92. }
  93. if err = e.DB.Model(new(model.NeckActiveHabit)).
  94. Where("id IN (?)", processIds).
  95. Where("pasture_id = ?", pastureId).
  96. Where("is_show = ?", pasturePb.IsShow_No).
  97. Where("change_filter = ?", model.InitChangeFilter).
  98. Updates(map[string]interface{}{
  99. "change_filter": model.DefaultChangeFilter,
  100. "rumina_filter": model.DefaultRuminaFilter,
  101. "chew_filter": model.DefaultChewFilter,
  102. }).Error; err != nil {
  103. zaplog.Error("EntryUpdateActiveHabit", zap.Any("change_filter", err), zap.Any("xToday", xToday))
  104. }
  105. if err = e.DB.Model(new(model.NeckActiveHabit)).
  106. Where("id IN (?)", processIds).
  107. Where("pasture_id = ?", pastureId).
  108. Where("change_filter < ?", 0).
  109. Where("filter_correct < ?", model.DefaultFilterCorrect).
  110. Updates(map[string]interface{}{
  111. "filter_correct": model.DefaultFilterCorrect,
  112. }).Error; err != nil {
  113. zaplog.Error("EntryUpdateActiveHabit", zap.Any("filter_correct", err), zap.Any("xToday", xToday))
  114. }
  115. // 插入群体校正表
  116. if err = e.UpdateChangeAdJust(pastureId, xToday); err != nil {
  117. zaplog.Error("EntryUpdateActiveHabit", zap.Any("UpdateChangeAdJust", err), zap.Any("xToday", xToday))
  118. }
  119. // 更新所有的显示状态为否的记录为是
  120. if err = e.DB.Model(new(model.NeckActiveHabit)).
  121. Where("id IN (?)", processIds).
  122. Where("pasture_id = ?", pastureId).
  123. Update("is_show", pasturePb.IsShow_Ok).Error; err != nil {
  124. zaplog.Error("UpdateChangeAdJust-2", zap.Any("error", err), zap.Any("xToday", xToday))
  125. }
  126. sort.Slice(processIds, func(i, j int) bool {
  127. return processIds[i] > processIds[j]
  128. })
  129. // 更新日志
  130. if err = e.DB.Model(new(model.NeckRingConfigure)).
  131. Where("name = ?", model.MaxHabit).
  132. Where("pasture_id = ?", pastureId).
  133. Update("value", processIds[len(processIds)-1]).Error; err != nil {
  134. zaplog.Error("NeckRingCalculate", zap.Any("MaxHabit", err), zap.Any("xToday", xToday))
  135. }
  136. // 健康预警
  137. if err = e.HealthWarning(pastureId, processIds); err != nil {
  138. zaplog.Error("EntryUpdateActiveHabit", zap.Any("HealthWarning", err))
  139. }
  140. return nil
  141. }
  142. // FirstFilterUpdate 首次更新活动滤波
  143. func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) (processIds []int64, err error) {
  144. newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
  145. if err = e.DB.Model(new(model.NeckActiveHabit)).
  146. Where("id > ?", xToDay.LastMaxHabitId).
  147. Where("pasture_id = ?", pastureId).
  148. Where("is_show = ?", pasturePb.IsShow_No).
  149. Where("record_count = ?", model.DefaultRecordCount).
  150. Where(e.DB.Where("high >= ?", xToDay.High).Or("rumina >= ?", xToDay.Rumina)).
  151. Order("heat_date,neck_ring_number,frameid").
  152. Limit(int(defaultLimit)).
  153. Find(&newNeckActiveHabitList).Error; err != nil {
  154. return nil, xerr.WithStack(err)
  155. }
  156. // 活动量滤波
  157. for _, v := range newNeckActiveHabitList {
  158. // 过滤牛只未绑定的脖环的数据
  159. cowInfo := e.GetCowInfoByNeckRingNumber(v.PastureId, v.NeckRingNumber)
  160. if cowInfo == nil || cowInfo.Id <= 0 {
  161. if err = e.DB.Model(new(model.NeckActiveHabit)).
  162. Where("id = ?", v.Id).
  163. Where("pasture_id = ?", v.PastureId).
  164. Update("is_show", pasturePb.IsShow_Ok).Error; err != nil {
  165. zaplog.Error("EntryUpdateActiveHabit", zap.Any("error", err))
  166. }
  167. continue
  168. }
  169. frameId := v.Frameid
  170. heatDate := v.HeatDate
  171. if v.Frameid == 0 {
  172. frameId = 11
  173. heatDateParse, _ := time.Parse(model.LayoutDate2, heatDate)
  174. heatDate = heatDateParse.AddDate(0, 0, -1).Format(model.LayoutDate2)
  175. } else {
  176. frameId -= 1
  177. }
  178. firstFilterData := e.FindFirstFilter(pastureId, v.NeckRingNumber, heatDate, frameId)
  179. if v.FilterHigh > 0 {
  180. firstFilterData.FilterHigh = v.FilterHigh
  181. } else {
  182. if v.NeckRingNumber == firstFilterData.NeckRingNumber {
  183. firstFilterData.FilterHigh = int32(computeIfPositiveElse(float64(v.High), float64(firstFilterData.FilterHigh), 0.23, 0.77))
  184. } else {
  185. firstFilterData.FilterHigh = v.High
  186. }
  187. }
  188. if v.FilterRumina > 0 {
  189. firstFilterData.FilterRumina = v.FilterRumina
  190. } else {
  191. if v.NeckRingNumber == firstFilterData.NeckRingNumber {
  192. firstFilterData.FilterRumina = int32(computeIfPositiveElse(float64(v.Rumina), float64(firstFilterData.FilterRumina), 0.33, 0.67))
  193. } else {
  194. firstFilterData.FilterRumina = v.Rumina
  195. }
  196. }
  197. if v.FilterChew > 0 {
  198. firstFilterData.FilterChew = v.FilterChew
  199. } else {
  200. if v.NeckRingNumber == firstFilterData.NeckRingNumber {
  201. firstFilterData.FilterChew = int32(computeIfPositiveElse(float64(v.Rumina+v.Intake), float64(firstFilterData.FilterChew), 0.33, 0.67))
  202. } else {
  203. firstFilterData.FilterChew = v.Rumina + v.Intake
  204. }
  205. }
  206. processIds = append(processIds, v.Id)
  207. // 更新过滤值 // todo 记得更新胎次为牛只胎次,现在为了测试特意改成0
  208. if err = e.DB.Model(new(model.NeckActiveHabit)).
  209. Select("filter_high", "filter_rumina", "filter_chew", "cow_id", "lact", "calving_age", "ear_number").
  210. Where("id = ?", v.Id).
  211. Updates(map[string]interface{}{
  212. "filter_high": firstFilterData.FilterHigh,
  213. "filter_rumina": firstFilterData.FilterRumina,
  214. "filter_chew": firstFilterData.FilterChew,
  215. "cow_id": cowInfo.Id,
  216. "lact": 0,
  217. "calving_age": cowInfo.CalvingAge,
  218. "ear_number": cowInfo.EarNumber,
  219. }).Error; err != nil {
  220. zaplog.Error("FirstFilterUpdate",
  221. zap.Any("error", err),
  222. zap.Any("firstFilterData", firstFilterData),
  223. zap.Any("NeckActiveHabit", v),
  224. zap.Any("cowInfo", cowInfo),
  225. zap.Any("xToday", xToDay),
  226. )
  227. }
  228. }
  229. return processIds, nil
  230. }
  231. // WeeklyUpdateActiveHabit 时间点周平均值计算
  232. func (e *Entry) WeeklyUpdateActiveHabit(pastureId int64, processIds []int64, xToDay *XToday) (err error) {
  233. newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
  234. if err = e.DB.Model(new(model.NeckActiveHabit)).
  235. Where("id IN (?)", processIds).
  236. Order("heat_date,neck_ring_number,frameid").
  237. Find(&newNeckActiveHabitList).Error; err != nil {
  238. return xerr.WithStack(err)
  239. }
  240. for _, v := range newNeckActiveHabitList {
  241. // 前七天的
  242. weekHabitData := e.FindWeekHabitData(pastureId, v.NeckRingNumber, v.HeatDate, v.Frameid, xToDay)
  243. // 更新过滤值
  244. if err = e.DB.Model(new(model.NeckActiveHabit)).
  245. Select("week_high_habit", "week_rumina_habit", "week_chew_habit", "week_intake_habit", "week_inactive_habit").
  246. Where("id = ?", v.Id).
  247. Updates(map[string]interface{}{
  248. "week_high_habit": weekHabitData.WeekHighHabit,
  249. "week_rumina_habit": weekHabitData.WeekRuminaHabit,
  250. "week_chew_habit": weekHabitData.WeekChewHabit,
  251. "week_intake_habit": weekHabitData.WeekIntakeHabit,
  252. "week_inactive_habit": weekHabitData.WeekInactiveHabit,
  253. }).Error; err != nil {
  254. zaplog.Error("WeeklyUpdateActiveHabit",
  255. zap.Error(err),
  256. zap.Any("NeckActiveHabit", v),
  257. zap.Any("pastureId", pastureId),
  258. )
  259. }
  260. }
  261. if err = e.SumUpdateActiveHabit(pastureId, newNeckActiveHabitList, xToDay); err != nil {
  262. zaplog.Error("WeeklyUpdateActiveHabit",
  263. zap.Any("SumUpdateActiveHabit", err),
  264. zap.Any("newNeckActiveHabitList", newNeckActiveHabitList),
  265. zap.Any("pastureId", pastureId),
  266. )
  267. }
  268. if err = e.ActiveChange(pastureId, processIds, xToDay); err != nil {
  269. zaplog.Error("WeeklyUpdateActiveHabit",
  270. zap.Any("ActiveChange", err),
  271. zap.Any("processIds", processIds),
  272. zap.Any("xToDay", xToDay),
  273. zap.Any("pastureId", pastureId),
  274. )
  275. }
  276. return nil
  277. }
  278. // SumUpdateActiveHabit -- 累计24小时数值
  279. func (e *Entry) SumUpdateActiveHabit(pastureId int64, newNeckActiveHabitList []*model.NeckActiveHabit, xToDay *XToday) (err error) {
  280. for _, v := range newNeckActiveHabitList {
  281. sumHabitData := e.FindSumHabitData(pastureId, v.NeckRingNumber, v.HeatDate, v.Frameid, xToDay)
  282. // 更新过滤值
  283. if err = e.DB.Model(new(model.NeckActiveHabit)).
  284. Select("sum_rumina", "sum_intake", "sum_inactive", "sum_active", "sum_max_high", "sum_min_high", "sum_min_chew").
  285. Where("id = ?", v.Id).
  286. Updates(map[string]interface{}{
  287. "sum_rumina": sumHabitData.SumRumina,
  288. "sum_intake": sumHabitData.SumIntake,
  289. "sum_inactive": sumHabitData.SumInactive,
  290. "sum_active": sumHabitData.SumActive,
  291. "sum_max_high": sumHabitData.SumMaxHigh,
  292. "sum_min_high": sumHabitData.SumMinHigh,
  293. "sum_min_chew": sumHabitData.SumMinChew,
  294. }).Error; err != nil {
  295. zaplog.Error("WeeklyUpdateActiveHabit",
  296. zap.Any("err", err),
  297. zap.Any("NeckActiveHabit", v),
  298. zap.Any("pastureId", pastureId),
  299. )
  300. }
  301. }
  302. return err
  303. }
  304. // ActiveChange -- 变化百分比
  305. func (e *Entry) ActiveChange(pastureId int64, processIds []int64, xToDay *XToday) (err error) {
  306. newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
  307. if err = e.DB.Model(new(model.NeckActiveHabit)).
  308. Where("id IN (?)", processIds).
  309. Where("week_high_habit > ?", 0).
  310. Where(e.DB.Where("high >= ?", xToDay.High).Or("rumina >= ?", xToDay.Rumina)).
  311. Find(&newNeckActiveHabitList).Error; err != nil {
  312. return xerr.WithStack(err)
  313. }
  314. for _, v := range newNeckActiveHabitList {
  315. highDiff := v.FilterHigh - v.WeekHighHabit
  316. denominator := float64(v.WeekHigh)*0.6 + float64(v.WeekHighHabit)*0.2 + float64(xToDay.WeeklyActive)*0.2
  317. if highDiff > 0 {
  318. v.ChangeHigh = int32(math.Round((float64(highDiff) / denominator / float64(v.WeekHighHabit)) * 100))
  319. } else {
  320. v.ChangeHigh = int32(math.Round(float64(highDiff) / float64(v.WeekHighHabit) * 100))
  321. }
  322. if v.WeekRuminaHabit != 0 {
  323. v.ChangeRumina = int32(math.Round(float64(v.FilterRumina-v.WeekRuminaHabit) / float64(v.WeekRuminaHabit) * 100))
  324. }
  325. if v.WeekChewHabit != 0 {
  326. v.ChangeChew = int32(math.Round(float64(v.FilterChew-v.WeekChewHabit) / float64(v.WeekChewHabit) * 100))
  327. }
  328. // 更新过滤值
  329. if err = e.DB.Model(new(model.NeckActiveHabit)).
  330. Select("change_high", "change_rumina", "change_chew").
  331. Where("id = ?", v.Id).
  332. Updates(map[string]interface{}{
  333. "change_high": v.ChangeHigh,
  334. "change_rumina": v.ChangeRumina,
  335. "change_chew": v.ChangeChew,
  336. }).Error; err != nil {
  337. zaplog.Error("WeeklyUpdateActiveHabit",
  338. zap.Error(err),
  339. zap.Any("NeckActiveHabit", v),
  340. zap.Any("pastureId", pastureId),
  341. )
  342. }
  343. }
  344. return err
  345. }
  346. func (e *Entry) WeeklyUpdateActiveHabitOld(pastureId int64, newNeckActiveHabitList []*model.NeckActiveHabit, xToDay *XToday) (err error) {
  347. for _, v := range newNeckActiveHabitList {
  348. // 前七天的
  349. weekHabitData := e.FindWeekHabitData(pastureId, v.NeckRingNumber, v.HeatDate, v.Frameid, xToDay)
  350. highDiff := v.FilterHigh - weekHabitData.WeekHighHabit
  351. denominator := float64(v.WeekHigh)*0.6 + float64(weekHabitData.WeekHighHabit)*0.2 + float64(xToDay.WeeklyActive)*0.2
  352. if highDiff > 0 {
  353. v.ChangeHigh = int32(math.Round((float64(highDiff) / denominator) * 100))
  354. } else {
  355. v.ChangeHigh = int32(math.Round(float64(highDiff) / denominator * 100))
  356. }
  357. if weekHabitData.WeekRuminaHabit != 0 {
  358. v.ChangeRumina = int32(math.Round(float64(v.FilterRumina-weekHabitData.WeekRuminaHabit) / float64(weekHabitData.WeekRuminaHabit) * 100))
  359. } else {
  360. v.ChangeRumina = 0
  361. }
  362. if weekHabitData.WeekChewHabit != 0 {
  363. v.ChangeChew = int32(math.Round(float64(v.FilterChew-weekHabitData.WeekChewHabit) / float64(weekHabitData.WeekChewHabit) * 100))
  364. } else {
  365. v.ChangeChew = 0
  366. }
  367. sumHabitData := e.FindSumHabitData(pastureId, v.NeckRingNumber, v.HeatDate, v.Frameid, xToDay)
  368. // 更新过滤值
  369. if err = e.DB.Model(new(model.NeckActiveHabit)).
  370. Select(
  371. "week_high_habit", "week_rumina_habit", "week_chew_habit", "week_intake_habit", "week_inactive_habit",
  372. "sum_rumina", "sum_intake", "sum_inactive", "sum_active", "sum_max_high", "sum_min_high", "sum_min_chew",
  373. "change_high", "change_rumina", "change_chew", "before_three_sum_rumina", "before_three_sum_intake",
  374. ).Where("id = ?", v.Id).
  375. Updates(map[string]interface{}{
  376. "week_high_habit": weekHabitData.WeekHighHabit,
  377. "week_rumina_habit": weekHabitData.WeekRuminaHabit,
  378. "week_chew_habit": weekHabitData.WeekChewHabit,
  379. "week_intake_habit": weekHabitData.WeekIntakeHabit,
  380. "week_inactive_habit": weekHabitData.WeekInactiveHabit,
  381. "sum_rumina": sumHabitData.SumRumina,
  382. "sum_intake": sumHabitData.SumIntake,
  383. "sum_inactive": sumHabitData.SumInactive,
  384. "sum_active": sumHabitData.SumActive,
  385. "sum_max_high": sumHabitData.SumMaxHigh,
  386. "sum_min_high": sumHabitData.SumMinHigh,
  387. "sum_min_chew": sumHabitData.SumMinChew,
  388. "change_high": v.ChangeHigh,
  389. "change_rumina": v.ChangeRumina,
  390. "change_chew": v.ChangeChew,
  391. }).Error; err != nil {
  392. zaplog.Error("WeeklyUpdateActiveHabit",
  393. zap.Error(err),
  394. zap.Any("NeckActiveHabit", v),
  395. zap.Any("pastureId", pastureId),
  396. )
  397. }
  398. }
  399. return err
  400. }
  401. func (e *Entry) Before3DaysNeckActiveHabit(pastureId int64, processIds []int64, xToDay *XToday) (err error) {
  402. newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
  403. if err = e.DB.Model(new(model.NeckActiveHabit)).
  404. Where("id IN (?)", processIds).
  405. Order("heat_date,neck_ring_number,frameid").
  406. Find(&newNeckActiveHabitList).Error; err != nil {
  407. return xerr.WithStack(err)
  408. }
  409. for _, v := range newNeckActiveHabitList {
  410. before3DaysNeckActiveHabit := e.FindBefore3DaysNeckActiveHabit(pastureId, v.NeckRingNumber, v.HeatDate, v.Frameid)
  411. // 更新过滤值
  412. if err = e.DB.Model(new(model.NeckActiveHabit)).
  413. Select("before_three_sum_rumina", "before_three_sum_intake").
  414. Where("id = ?", v.Id).
  415. Updates(map[string]interface{}{
  416. "before_three_sum_rumina": before3DaysNeckActiveHabit.SumRumina,
  417. "before_three_sum_intake": before3DaysNeckActiveHabit.SumIntake,
  418. }).Error; err != nil {
  419. zaplog.Error("Before3DaysNeckActiveHabit",
  420. zap.Error(err),
  421. zap.Any("NeckActiveHabit", v),
  422. zap.Any("pastureId", pastureId),
  423. )
  424. }
  425. }
  426. return nil
  427. }
  428. // SecondUpdateChangeFilter 第二次更新变化趋势滤波
  429. func (e *Entry) SecondUpdateChangeFilter(pastureId int64, xToday *XToday) (err error) {
  430. newChangeFilterList := make([]*ChangeFilterData, 0)
  431. if err = e.DB.Model(new(model.NeckActiveHabit)).
  432. Select("id", "neck_ring_number", "change_high", "change_filter", "rumina_filter", "change_rumina",
  433. "chew_filter", "change_chew", "heat_date", "frameid", "IF(lact = 0, 0.8, 1) as xlc_dis_count").
  434. Where("id > ?", xToday.LastMaxHabitId).
  435. Where("heat_date >= ?", time.Now().AddDate(0, 0, -2).Format(model.LayoutDate2)).
  436. Where("pasture_id = ?", pastureId).
  437. Where("change_filter = ?", model.InitChangeFilter).
  438. Where("change_high > ?", MinChangeHigh).
  439. Order("neck_ring_number,heat_date,frameid").
  440. Limit(int(defaultLimit)).
  441. Find(&newChangeFilterList).Error; err != nil {
  442. return xerr.WithStack(err)
  443. }
  444. for _, v := range newChangeFilterList {
  445. secondFilterData := &SecondFilterData{}
  446. frameId := v.FrameId
  447. heatDate := v.HeatDate
  448. if v.FrameId == 0 {
  449. frameId = 11
  450. heatDateParse, _ := time.Parse(model.LayoutDate2, heatDate)
  451. heatDate = heatDateParse.AddDate(0, 0, -1).Format(model.LayoutDate2)
  452. } else {
  453. frameId -= 1
  454. }
  455. if err = e.DB.Model(new(model.NeckActiveHabit)).
  456. Select("neck_ring_number", "filter_high", "filter_rumina", "filter_chew").
  457. Where("neck_ring_number = ?", v.NeckRingNumber).
  458. Where("heat_date = ?", heatDate).
  459. Where("frameid = ?", frameId).
  460. First(&secondFilterData).Error; err != nil {
  461. zaplog.Error("EntryUpdateActiveHabit", zap.Any("FirstFilterUpdate", err))
  462. }
  463. if v.ChangeFilter > MinChangeFilter {
  464. secondFilterData.ChangeFilter = float64(v.ChangeFilter)
  465. } else {
  466. if v.NeckRingNumber == secondFilterData.NeckRingNumber {
  467. secondFilterData.ChangeFilter = secondFilterData.ChangeFilter*(1-(float64(xToday.XChangeDiscount)/10)*v.XlcDisCount) +
  468. math.Min(float64(v.ChangeHigh), secondFilterData.ChangeFilter+135)*(float64(xToday.XChangeDiscount)/10)*v.XlcDisCount
  469. } else {
  470. secondFilterData.ChangeFilter = 0
  471. }
  472. }
  473. if v.RuminaFilter > MinRuminaFilter {
  474. secondFilterData.RuminaFilter = float64(v.ChangeFilter)
  475. } else {
  476. if v.NeckRingNumber == secondFilterData.NeckRingNumber {
  477. discount := float64(xToday.XRuminaDisc) / 10 * v.XlcDisCount
  478. if math.Abs(float64(v.ChangeRumina)) > 60 {
  479. discount *= 0.5
  480. }
  481. secondFilterData.RuminaFilter = secondFilterData.RuminaFilter*(1-discount) + float64(v.ChangeRumina)*discount
  482. } else {
  483. secondFilterData.RuminaFilter = 0
  484. }
  485. }
  486. secondFilterData.RuminaFilter = math.Min(50, secondFilterData.RuminaFilter)
  487. if v.ChewFilter > MinChewFilter {
  488. secondFilterData.ChewFilter = float64(v.ChangeChew)
  489. } else {
  490. if v.NeckRingNumber == secondFilterData.NeckRingNumber {
  491. discount := float64(xToday.XRuminaDisc) / 10
  492. if math.Abs(float64(v.ChangeChew)) > 60 {
  493. discount *= 0.5
  494. }
  495. secondFilterData.ChewFilter = secondFilterData.ChewFilter*(1-discount) + float64(v.ChangeChew)*discount
  496. } else {
  497. secondFilterData.ChewFilter = 0
  498. }
  499. }
  500. secondFilterData.ChewFilter = math.Min(50, secondFilterData.ChewFilter)
  501. if err = e.DB.Model(new(model.NeckActiveHabit)).
  502. Select("change_filter", "rumina_filter", "chew_filter").
  503. Where("id = ?", v.Id).
  504. Updates(map[string]interface{}{
  505. "change_filter": secondFilterData.ChangeFilter,
  506. "rumina_filter": secondFilterData.RuminaFilter,
  507. "chew_filter": secondFilterData.ChewFilter,
  508. }).Error; err != nil {
  509. zaplog.Error("SecondUpdateChangeFilter-1", zap.Any("error", err), zap.Any("xToday", xToday))
  510. }
  511. }
  512. return nil
  513. }
  514. // FilterCorrectAndScoreUpdate 计算活动量变化趋势校正值(活跃度校正)和健康评分
  515. func (e *Entry) FilterCorrectAndScoreUpdate(pastureId int64, processIds []int64, xToday *XToday) error {
  516. beginDayDate := time.Now()
  517. before7DayDate := beginDayDate.AddDate(0, 0, -7).Format(model.LayoutDate2)
  518. before1DayDate := beginDayDate.AddDate(0, 0, -1).Format(model.LayoutDate2)
  519. neckActiveHabitList := make([]*model.NeckActiveHabit, 0)
  520. if err := e.DB.Model(new(model.NeckActiveHabit)).
  521. Where("id IN (?)", processIds).
  522. //Where("heat_date >= ?", before1DayDate).
  523. Where("pasture_id = ?", pastureId).
  524. Where(e.DB.Where("high > ?", xToday.High).Or("rumina > ?", xToday.Rumina)).
  525. Find(&neckActiveHabitList).Error; err != nil {
  526. zaplog.Error("ActivityVolumeChanges-1", zap.Any("error", err), zap.Any("xToday", xToday))
  527. return xerr.WithStack(err)
  528. }
  529. for _, v := range neckActiveHabitList {
  530. activityVolume := &ActivityVolume{}
  531. if err := e.DB.Model(new(model.NeckActiveHabit)).
  532. Select("neck_ring_number", "AVG(IF(change_filter>=60, 60, change_filter)) as avg_filter",
  533. "ROUND(STD(IF(change_filter>=60, 60, change_filter))) as std_filter", "COUNT(1) as nb").
  534. Where("heat_date BETWEEN ? AND ?", before7DayDate, before1DayDate).
  535. Where("pasture_id = ?", pastureId).
  536. Where(e.DB.Where("high > ?", xToday.High).Or("rumina >= ?", xToday.Rumina)).
  537. Where("active_time <= ?", beginDayDate.Add(-12*time.Hour).Format(model.LayoutTime)).
  538. Where("change_filter > ?", MinChangeFilter).
  539. Where("neck_ring_number = ?").
  540. Having("nb > ?", DefaultNb).
  541. First(&activityVolume).Error; err != nil {
  542. zaplog.Error("ActivityVolumeChanges-0", zap.Any("error", err), zap.Any("xToday", xToday))
  543. continue
  544. }
  545. if activityVolume != nil && activityVolume.NeckRingNumber != "" {
  546. filterCorrect := model.DefaultFilterCorrect - int(math.Floor(activityVolume.AvgFilter/3+float64(activityVolume.StdFilter)/2))
  547. // 活动量校正系数
  548. if err := e.DB.Model(new(model.NeckActiveHabit)).
  549. Where("id = ?", v.Id).
  550. Where("neck_ring_number = ?", v.NeckRingNumber).
  551. Update("filter_correct", filterCorrect).Error; err != nil {
  552. zaplog.Error("ActivityVolumeChanges-2", zap.Any("error", err), zap.Any("xToday", xToday))
  553. continue
  554. }
  555. }
  556. cowScore := calculateScore(v)
  557. if err := e.DB.Model(new(model.NeckActiveHabit)).
  558. Where("id = ?", v.Id).
  559. Update("score", cowScore).Error; err != nil {
  560. zaplog.Error("ActivityVolumeChanges-2", zap.Any("error", err), zap.Any("xToday", xToday))
  561. continue
  562. }
  563. }
  564. return nil
  565. }
  566. // UpdateChangeAdJust 更新群体校正数据
  567. func (e *Entry) UpdateChangeAdJust(pastureId int64, xToday *XToday) error {
  568. /*-- 插入群体校正表
  569. INSERT INTO data_bar_change(heatdate, frameid, intCurBar, intCurBarName, nb, highchange, changefilter)
  570. SELECT h.heatdate, h.frameid, c.intCurBar, c.intCurBarName, COUNT(*) nb, ROUND(AVG(h.highchange)) highchange, ROUND(AVG(h.changefilter) ) changefilter
  571. FROM h_activehabit h JOIN cow c ON h.intCowId=c.intCowId
  572. WHERE h.heatdate>=(CURDATE() -INTERVAL 1 DAY )
  573. GROUP BY h.heatdate, h.frameid, c.intCurBar
  574. ORDER BY h.heatdate, h.frameid, c.intCurBarName
  575. ON DUPLICATE KEY UPDATE nb = VALUES(nb), highchange = VALUES(highchange), changefilter = VALUES(changefilter);
  576. UPDATE h_activehabit h
  577. JOIN cow c ON h.intCowId=c.intCowId
  578. JOIN data_bar_change cg ON h.heatdate=cg.heatdate AND h.frameid=cg.frameid AND c.intCurBar=cg.intCurBar
  579. SET h.changeadjust=cg.changefilter
  580. WHERE h.id>xBeg_update_act_Id AND h.heatdate>=CURRENT_DATE() - INTERVAL 1 DAY AND ABS(cg.changefilter)>=10;
  581. */
  582. res := make([]*model.NeckRingBarChange, 0)
  583. oneDayAgo := time.Now().AddDate(0, 0, -1).Format(model.LayoutDate2)
  584. if err := e.DB.Table(fmt.Sprintf("%s as h", new(model.NeckActiveHabit).TableName())).
  585. Select("h.neck_ring_number,h.heat_date, h.frameid, c.pen_id, c.pen_name, COUNT(*) as nb, ROUND(AVG(h.change_high)) as change_high, ROUND(AVG(h.change_filter)) as change_filter").
  586. Joins("JOIN cow as c ON h.neck_ring_number = c.neck_ring_number").
  587. Where("h.pasture_id = ?", pastureId).
  588. Where("h.heat_date >= ?", oneDayAgo).
  589. Where("h.cow_id >= ?", 0).
  590. Where("h.cow_id >= ?", 0).
  591. Group("h.heat_date, h.frameid, c.pen_id").
  592. Order("h.heat_date, h.frameid, c.pen_name").
  593. Find(&res).Error; err != nil {
  594. return xerr.WithStack(err)
  595. }
  596. // todo ABS(cg.changefilter)>=10;
  597. for _, v := range res {
  598. if err := e.DB.Model(new(model.NeckActiveHabit)).
  599. Where("id > ?", xToday.LastMaxHabitId).
  600. Where("heat_date = ?", v.HeatDate).
  601. Where("frameid = ?", v.FrameId).
  602. Where("neck_ring_number = ?", v.NeckRingNumber).
  603. Update("change_adjust", v.ChangeHigh).Error; err != nil {
  604. zaplog.Error("UpdateChangeAdJust-1", zap.Any("error", err), zap.Any("xToday", xToday))
  605. }
  606. }
  607. return nil
  608. }