/// <summary> /// 抽奖/兑奖 /// </summary> /// <param name="user"></param> /// <param name="request"></param> /// <param name="requestAborted"></param> /// <returns></returns> public async Task <ResponseMessage <GiftInfo> > ConsumableScoreAsync(UserInfo user, ConsumableScoreRequest request, CancellationToken requestAborted) { var response = new ResponseMessage <GiftInfo>(); var periodGift = await _giftStore.GetPeriodGifts().Where(w => w.PeriodId == request.PeriodId).FirstOrDefaultAsync(); if (periodGift == null || periodGift.Enabled == false) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "当前赛季奖品暂未开放"; return(response); } //抽奖 if (request.ConsumableType == 1) { var giftInfoList = await _giftStore.GetGiftInfos().Where(w => !w.IsDelete && w.PeriodId == request.PeriodId).ToListAsync(); if (!giftInfoList.Any()) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "没有奖品可供抽取"; return(response); } var scoreInfo = await _allocateStore.GetScoreInfos().Where(w => !w.IsDelete && w.PeriodId == request.PeriodId && w.UserId == user.Id).FirstOrDefaultAsync(); if (scoreInfo == null) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "未查询到您的积分信息"; return(response); } if (scoreInfo.ConsumableScore < periodGift.Score) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "您的可消费K币不足,赶紧去赚点K币吧"; return(response); } //总几率 var sumOdds = giftInfoList.Sum(s => s.Odds); if (sumOdds > 1000) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "奖品设置异常,请联系管理员。"; return(response); } var giftList = giftInfoList.Where(w => w.Number != 0).ToList();//排除抽完的奖品 if (!giftList.Any()) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "所有奖品已被抽取/兑换完,请等待新奖品上架吧。"; return(response); } //将奖品ID和中奖率放在数组中,并从小到大排序 var prizeList = giftList.Select(s => new { Prize = s.Id, Change = s.Odds }).OrderBy(o => o.Change).ToList(); //将中奖率累加,放到字典里 var prizeDictionary = new Dictionary <string, int>(); for (var i = 0; i < giftList.Count; i++) { var allChange = 0; for (var j = 0; j <= i; j++) { allChange += prizeList[j].Change; } prizeDictionary.Add(prizeList[i].Prize, allChange); } //产生一个1-1000的随机数 var rd = new Random(); var rdChange = rd.Next(1, 1001); //找第一个大于随机值的奖项,如果中途有奖品抽完了,找不到到大于随机值的奖项,就直接取几率最大 var giftResult_Id = prizeDictionary.FirstOrDefault(j => j.Value >= rdChange).Key ?? prizeDictionary.LastOrDefault().Key; var giftInfo = giftInfoList.FirstOrDefault(fi => fi.Id == giftResult_Id); if (giftInfo.Number > 0) { giftInfo.Number -= 1; } //事务保存 using (var trans = await _transaction.BeginTransaction()) { try { //事务里面重新查一次 scoreInfo = await _allocateStore.GetScoreInfos().Where(w => !w.IsDelete && w.PeriodId == request.PeriodId && w.UserId == user.Id).FirstOrDefaultAsync(); if (scoreInfo == null) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "未查询到您的积分信息"; return(response); } scoreInfo.ConsumableScore = scoreInfo.ConsumableScore - periodGift.Score; await _allocateStore.UpdateScoreInfo(scoreInfo, requestAborted); await _giftStore.UpdateGift(giftInfo, requestAborted); //添加抽奖动态 await _dynamicHelper.AddDynamicContent( DynamicType.RandomGift, request.PeriodId, giftInfo.Id, null, null, user.UserName, user.GroupName, user.Id, giftInfo.Name, periodGift.Score, null, null ); trans.Commit(); } catch (Exception e) { trans.Rollback(); throw new Exception("保存事务失败", e); } } response.Extension = giftInfo; } //兑奖 else if (request.ConsumableType == 2) { var scoreInfo = await _allocateStore.GetScoreInfos().Where(w => !w.IsDelete && w.PeriodId == request.PeriodId && w.UserId == user.Id).FirstOrDefaultAsync(); if (scoreInfo == null) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "未查询到您的积分信息"; return(response); } var giftInfo = await _giftStore.GetGiftInfos().Where(w => !w.IsDelete && w.PeriodId == request.PeriodId && w.Number != 0 && w.Id == request.GiftId).FirstOrDefaultAsync(); if (giftInfo == null) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "兑换奖品不存在"; return(response); } if (!giftInfo.IsGet) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = $"兑换奖品{giftInfo.Name}不运行直接兑换"; return(response); } if (scoreInfo.ConsumableScore < giftInfo.GetScore) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "您的可消费K币不足,赶紧去赚点K币吧"; return(response); } if (giftInfo.Number == 0) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "奖品数量不足不能直接兑换"; return(response); } if (giftInfo.Number > 0) { giftInfo.Number -= 1; } //事务保存 using (var trans = await _transaction.BeginTransaction()) { try { //事务里面重新查一次 scoreInfo = await _allocateStore.GetScoreInfos().Where(w => !w.IsDelete && w.PeriodId == request.PeriodId && w.UserId == user.Id).FirstOrDefaultAsync(); if (scoreInfo == null) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "未查询到您的积分信息"; trans.Rollback(); return(response); } scoreInfo.ConsumableScore = scoreInfo.ConsumableScore - giftInfo.GetScore; await _allocateStore.UpdateScoreInfo(scoreInfo, requestAborted); await _giftStore.UpdateGift(giftInfo, requestAborted); //添加直接兑换动态 await _dynamicHelper.AddDynamicContent( DynamicType.GetGift, request.PeriodId, giftInfo.Id, null, null, user.UserName, user.GroupName, user.Id, giftInfo.Name, periodGift.Score, null, null ); trans.Commit(); } catch (Exception e) { trans.Rollback(); throw new Exception("保存事务失败", e); } } response.Extension = giftInfo; } else { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "ConsumableType参数错误"; return(response); } // 触发个人信息变化 await _sendClientMessageManager.SendInfos(new List <Dto.Common.SendClientType>() { Dto.Common.SendClientType.User, Dto.Common.SendClientType.Dynamic }); return(response); }
public async Task <ResponseMessage <GiftInfo> > ConsumableScore(Models.UserInfo user, [FromBody] ConsumableScoreRequest request) { Logger.Trace($"用户{user?.UserName ?? ""}({user?.Id ?? ""})抽奖,请求参数为:\r\n" + JsonHelper.ToJson(request)); var response = new ResponseMessage <GiftInfo>(); if (!ModelState.IsValid) { response.Code = ResponseCodeDefines.ModelStateInvalid; response.Message = "模型验证失败" + ModelState.GetAllErrors(); Logger.Warn("抽奖模型验证失败:\r\n{0}", response.Message ?? ""); return(response); } var prefixs = new string[] { "ConsumableScore" }; var key = "ConsumableScore"; try { // 防止同时中奖,兑奖,数量不够。所以这里是一个一个来 await _cache.LockSubmit(prefixs, key, "ConsumableScore", HttpContext.RequestAborted); response = await _giftManager.ConsumableScoreAsync(user, request, HttpContext.RequestAborted); } catch (Exception e) { response.Code = ResponseCodeDefines.ServiceError; response.Message = e.Message; Logger.Error($"用户{user?.UserName ?? ""}({user?.Id ?? ""})抽奖,报错:{e.Message}\r\n{e.StackTrace}"); } finally { // 成功失败都要移除 await _cache.UnlockSubmit(prefixs, key); } return(response); }