special_award.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "sort"
  6. "time"
  7. "go-common/app/interface/main/growup/model"
  8. "go-common/library/ecode"
  9. "go-common/library/log"
  10. xtime "go-common/library/time"
  11. )
  12. const (
  13. ceilings = 50000
  14. rule = 1
  15. detail = 3
  16. question = 5
  17. answer = 6
  18. )
  19. // GetAwardUpStatus get award up status
  20. func (s *Service) GetAwardUpStatus(c context.Context, awardID, mid int64) (status *model.AwardUpStatus, err error) {
  21. joined, err := s.isJoined(c, mid, awardID)
  22. if err != nil {
  23. return
  24. }
  25. fans, err := s.getUpFans(c, mid)
  26. if err != nil {
  27. return
  28. }
  29. status = &model.AwardUpStatus{
  30. Joined: joined,
  31. Qualified: checkQualification(fans),
  32. }
  33. return
  34. }
  35. // GetWinningRecord get winning record
  36. func (s *Service) GetWinningRecord(c context.Context, mid int64) (rs []*model.WinningRecord, err error) {
  37. awardIDs, err := s.dao.GetAwardJoinRecord(c, mid)
  38. if err != nil {
  39. return
  40. }
  41. if len(awardIDs) == 0 {
  42. return
  43. }
  44. as := make([]int64, 0)
  45. for awardID := range awardIDs {
  46. as = append(as, awardID)
  47. }
  48. awards, err := s.dao.JoinedSpecialAwards(c, as)
  49. if err != nil {
  50. return
  51. }
  52. sort.Slice(awards, func(i, j int) bool {
  53. return awards[i].CycleStart < awards[j].CycleStart
  54. })
  55. // am map[award_id]prize_id
  56. am, err := s.dao.AwardIDsByWinner(c, mid)
  57. if err != nil {
  58. return
  59. }
  60. now := time.Now().Unix()
  61. rs = make([]*model.WinningRecord, 0)
  62. for _, award := range awards {
  63. // in selection
  64. if now > int64(award.CycleEnd) && award.OpenStatus == 1 {
  65. rs = append(rs, &model.WinningRecord{
  66. AwardID: award.AwardID,
  67. AwardName: award.AwardName,
  68. State: 2,
  69. })
  70. continue
  71. }
  72. // finished
  73. if award.OpenStatus == 2 {
  74. wr := &model.WinningRecord{
  75. AwardID: award.AwardID,
  76. AwardName: award.AwardName,
  77. }
  78. if prizeID, ok := am[award.AwardID]; ok {
  79. wr.PrizeID = prizeID
  80. wr.State = 1
  81. }
  82. rs = append(rs, wr)
  83. }
  84. }
  85. return
  86. }
  87. // GetWinningPoster get prize winning poster
  88. func (s *Service) GetWinningPoster(c context.Context, mid int64, awardID, prizeID int64) (poster *model.Poster, err error) {
  89. accs, err := s.dao.AccountInfos(c, []int64{mid})
  90. if err != nil {
  91. return
  92. }
  93. if len(accs) <= 0 {
  94. return
  95. }
  96. award, err := s.dao.GetAwardSchedule(c, awardID)
  97. if err != nil {
  98. return
  99. }
  100. // am map[award_id]division_name
  101. names, err := s.dao.DivisionName(c, mid)
  102. if err != nil {
  103. return
  104. }
  105. bonus, err := s.dao.AwardBonus(c, awardID, prizeID)
  106. if err != nil {
  107. return
  108. }
  109. poster = &model.Poster{
  110. AwardName: award.AwardName,
  111. Nickname: accs[mid].Nickname,
  112. Face: accs[mid].Face,
  113. PrizeName: fmt.Sprintf("最佳%s新秀奖", names[awardID]),
  114. Date: award.CycleEnd.Time().Format("2006-01"),
  115. Bonus: bonus,
  116. }
  117. return
  118. }
  119. // JoinAward sign up award
  120. func (s *Service) JoinAward(c context.Context, mid int64, awardID int64) (err error) {
  121. joined, err := s.isJoined(c, mid, awardID)
  122. if err != nil {
  123. return
  124. }
  125. if joined {
  126. err = ecode.GrowupSpecialAwardJoined
  127. return
  128. }
  129. fans, err := s.getUpFans(c, mid)
  130. if err != nil {
  131. return
  132. }
  133. if !checkQualification(fans) {
  134. err = ecode.GrowupSpecialAwardUnqualified
  135. return
  136. }
  137. _, err = s.dao.AddToAwardRecord(c, mid, awardID)
  138. return
  139. }
  140. // if fans count >= ceilings, no qualification
  141. func checkQualification(fans int64) bool {
  142. return fans < ceilings
  143. }
  144. // if joined special award
  145. func (s *Service) isJoined(c context.Context, mid, awardID int64) (joined bool, err error) {
  146. count, err := s.dao.JoinedCount(c, mid, awardID)
  147. if err != nil {
  148. return
  149. }
  150. joined = count != 0
  151. return
  152. }
  153. // AwardList award_id: award_name
  154. func (s *Service) AwardList(c context.Context) (as []*model.SimpleSpecialAward, err error) {
  155. as, err = s.dao.PastAwards(c)
  156. if err != nil {
  157. return
  158. }
  159. sort.Slice(as, func(i, j int) bool {
  160. return as[i].CycleStart < as[j].CycleStart
  161. })
  162. return
  163. }
  164. // Winners get winners by award id
  165. func (s *Service) Winners(c context.Context, awardID int64) (as []*model.Account, err error) {
  166. mids, err := s.dao.GetWinners(c, awardID)
  167. if err != nil {
  168. return
  169. }
  170. infos, err := s.dao.AccountInfos(c, mids)
  171. if err != nil {
  172. return
  173. }
  174. for _, mid := range mids {
  175. a := &model.Account{Mid: mid}
  176. as = append(as, a)
  177. if info, ok := infos[mid]; ok {
  178. a.Name = info.Nickname
  179. a.Face = info.Face
  180. }
  181. }
  182. return
  183. }
  184. // AwardDetail get award detail include schedule & resource
  185. func (s *Service) AwardDetail(c context.Context, awardID int64) (data map[string]interface{}, err error) {
  186. schedule, err := s.dao.GetAwardSchedule(c, awardID)
  187. if err != nil {
  188. return
  189. }
  190. // rs map[resource_type]map[index]content
  191. rs, err := s.dao.GetResources(c, awardID)
  192. if err != nil {
  193. return
  194. }
  195. qas := make([]*model.QA, len(rs[question]))
  196. for i := 0; i < len(rs[question]); i++ {
  197. qas[i] = &model.QA{}
  198. }
  199. res := map[string]interface{}{
  200. "qa": qas,
  201. "rule": "",
  202. "detail": "",
  203. }
  204. for rt, cs := range rs {
  205. if rt == rule {
  206. res["rule"] = cs[1]
  207. }
  208. if rt == detail {
  209. res["detail"] = cs[1]
  210. }
  211. if rt == question || rt == answer {
  212. for index, content := range cs {
  213. if index < 0 || index > len(qas) {
  214. continue
  215. }
  216. qa := qas[index-1]
  217. if rt == question {
  218. qa.Question = content
  219. }
  220. if rt == answer {
  221. qa.Answer = content
  222. }
  223. }
  224. }
  225. }
  226. data = map[string]interface{}{
  227. "schedule": schedule,
  228. "resource": res,
  229. }
  230. return
  231. }
  232. // SpecialAwardInfo special award info
  233. func (s *Service) SpecialAwardInfo(c context.Context, mid int64) (data map[string]interface{}, err error) {
  234. var (
  235. nowTime = xtime.Time(time.Now().Unix())
  236. winRecord []string
  237. upStates []*model.UpAwardState
  238. )
  239. awards, nowAward, nextAward, err := s.getRecentSpecialAward(c, nowTime)
  240. if err != nil {
  241. log.Error("s.getRecentSpecialAward error(%v)", err)
  242. return
  243. }
  244. if mid > 0 {
  245. winRecord, err = s.getAwardWinRecord(c, mid, awards)
  246. if err != nil {
  247. log.Error("s.getAwardWinRecord error(%v)", err)
  248. return
  249. }
  250. upStates, err = s.getUpAwardState(c, mid, awards)
  251. if err != nil {
  252. log.Error("s.getUpAwardState error(%v)", err)
  253. return
  254. }
  255. }
  256. data = map[string]interface{}{
  257. "win_record": winRecord,
  258. "now": nowAward,
  259. "next": nextAward,
  260. "up_states": upStates,
  261. }
  262. return
  263. }
  264. // get now and next special award
  265. func (s *Service) getRecentSpecialAward(c context.Context, nowTime xtime.Time) (awards []*model.SpecialAward, nowAward, nextAward *model.SpecialAward, err error) {
  266. awards, err = s.dao.GetSpecialAwards(c)
  267. if err != nil {
  268. log.Error("s.dao.GetSpecialAwards error(%v)", err)
  269. return
  270. }
  271. sort.Slice(awards, func(i, j int) bool {
  272. return awards[i].CycleStart < awards[j].CycleStart
  273. })
  274. for i := 0; i < len(awards); i++ {
  275. if awards[i].CycleStart <= nowTime && awards[i].CycleEnd >= nowTime {
  276. nowAward = awards[i]
  277. } else if awards[i].CycleStart > nowTime {
  278. nextAward = awards[i]
  279. break
  280. }
  281. }
  282. if nowAward != nil {
  283. nowAward.Duration = int64(nowAward.CycleEnd - nowTime)
  284. nowAward.Divisions, err = s.dao.GetSpecialAwardDivision(c, nowAward.AwardID)
  285. if err != nil {
  286. return
  287. }
  288. }
  289. if nextAward != nil {
  290. nextAward.Duration = int64(nextAward.CycleStart - nowTime)
  291. nextAward.Divisions, err = s.dao.GetSpecialAwardDivision(c, nextAward.AwardID)
  292. if err != nil {
  293. return
  294. }
  295. }
  296. return
  297. }
  298. func (s *Service) getAwardWinRecord(c context.Context, mid int64, awards []*model.SpecialAward) (awardNames []string, err error) {
  299. awardIDs, err := s.dao.GetAwardWinRecord(c, mid)
  300. if err != nil {
  301. log.Error("s.dao.GetAwardWinRecord error(%v)", err)
  302. return
  303. }
  304. awardNames = make([]string, 0)
  305. for i := len(awards) - 1; i >= 0; i-- {
  306. if awardIDs[awards[i].AwardID] {
  307. awardNames = append(awardNames, awards[i].AwardName)
  308. }
  309. }
  310. return
  311. }
  312. func (s *Service) getUpAwardState(c context.Context, mid int64, awards []*model.SpecialAward) (upStates []*model.UpAwardState, err error) {
  313. upStates = make([]*model.UpAwardState, 0)
  314. now := xtime.Time(time.Now().Unix())
  315. awardIDs, err := s.dao.GetAwardJoinRecord(c, mid)
  316. if err != nil {
  317. log.Error("s.dao.GetAwardJoinRecord error(%v)", err)
  318. return
  319. }
  320. winIDs, err := s.dao.GetAwardWinRecord(c, mid)
  321. if err != nil {
  322. log.Error("s.dao.GetAwardWinRecord error(%v)", err)
  323. return
  324. }
  325. for i := 0; i < len(awards); i++ {
  326. upState := &model.UpAwardState{AwardName: awards[i].AwardName}
  327. date := awards[i].AnnounceDate.Time()
  328. doubleCreativeStart := time.Date(date.Year(), date.Month()+1, 15, 0, 0, 0, 0, time.Local)
  329. doubleCreativeEnd := doubleCreativeStart.AddDate(0, 0, 14)
  330. if now > awards[i].CycleEnd && now <= awards[i].AnnounceDate && awardIDs[awards[i].AwardID] { // 评选中
  331. upState.State = 1
  332. } else if now > awards[i].AnnounceDate && now < xtime.Time(doubleCreativeStart.Unix()) && winIDs[awards[i].AwardID] { // 双倍即将开始
  333. upState.State = 2
  334. } else if now >= xtime.Time(doubleCreativeStart.Unix()) && now <= xtime.Time(doubleCreativeEnd.Unix()) && winIDs[awards[i].AwardID] { // 双倍中
  335. upState.State = 3
  336. }
  337. if upState.State != 0 {
  338. upStates = append(upStates, upState)
  339. }
  340. }
  341. return
  342. }