neck_ring_calculate.go 21 KB

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