123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815 |
- using System.Threading.Tasks;
- using System;
- using Wicture.DbRESTFul.Infrastructure.Repository;
- using System.Linq;
- using Newtonsoft.Json.Linq;
- using System.Collections.Generic;
- using System.Data;
- using Wicture.DbRESTFul.Cache;
- using System.Security.Cryptography.X509Certificates;
- using Newtonsoft.Json;
- using System.Runtime.Intrinsics.X86;
- using JiaZhiQuan.Common.Models.VO;
- using JiaZhiQuan.Common.Models.PO;
- namespace JiaZhiQuan.Common
- {
- public static partial class RepositoryExtension
- {
- public class ActivityCzdTaskRecord
- {
- public int id { get; set; }
- public long userId { get; set; }
- public int betPoints { get; set; }
- public int betType { get; set; }
- public DateTime createAt { get; set; }
- public int gainPoints { get; set; }
- public int gameResult { get; set; }
- }
- public class ActivityCzdMockModel
- {
- public int fallUsers { get; set; }
- public int riseUsers { get; set; }
- public int points { get; set; }
- public DateTime execTime { get; set; }
- }
- public static async Task<List<int>> GetCzdPointListByContract(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, int contractId)
- {
- var key = CacheKeys.ActivityCzdPointList(contractId);
- var list = await cacheProvider.Get<List<int>>(key);
- if (list == null)
- {
- list = (await repository.QuerySingleOrDefaultAsync<string>($"select pointsList from n_activity_czd_contract where id={contractId}") ?? string.Empty)
- .Split(',', StringSplitOptions.RemoveEmptyEntries)
- .Select(e => int.Parse(e)).ToList();
- await cacheProvider.Set(key, list, CacheKeys.ActivityCzdPointListCacheSecs);
- }
- return list;
- }
- /// <summary>
- /// 获取随机人数和随机价值币
- /// </summary>
- /// <param name="minCount">包含</param>
- /// <param name="maxCount">包含</param>
- /// <param name="mode">0 双方都加同样的,2 仅跌的,1 仅涨的</param>
- public static async Task<bool> GenerateActivityCzdMockData(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, int contractId, int taskId, int minCount, int maxCount, int minutes, int mode = 0)
- {
- var pointsArr = await repository.GetCzdPointListByContract(cacheProvider, contractId);
- if (pointsArr.Count == 0) return false;
- var rand = new Random();
- var count = rand.Next(minCount, maxCount + 1);
- if (count == 0) return true;
- var list = new List<ActivityCzdMockModel>();
- var maxBatch = Math.Min(count, 10);
- for (var i = 0; i < count; i++)
- {
- var time = DateTime.Now.AddMinutes(rand.NextDouble() * minutes);
- var batch = rand.Next(1, maxBatch + 1);
- var model = new ActivityCzdMockModel { execTime = time };
- if (mode == 2 || mode == 0)
- {
- model.fallUsers = batch;
- }
- if (mode == 1 || mode == 0)
- {
- model.riseUsers = batch;
- }
- for (var j = 0; j < batch; j++)
- {
- model.points += pointsArr[rand.Next(Math.Min(3, pointsArr.Count))];
- }
- if (mode == 0)
- {
- model.points *= 2;
- }
- list.Add(model);
- i += batch - 1;
- }
- await repository.QueryAsync<dynamic>($"insert into n_activity_czd_mock_action (taskId, fallUsers, riseUsers, points, execTime, createAt) values ({taskId}, @fallUsers, @riseUsers, @points, @execTime, now())", list, null, null, false);
- return true;
- }
- /// <summary>
- /// 结束某一个任务
- /// </summary>
- /// <param name="contractId">合约组编号</param>
- /// <param name="date">yyyy-MM-dd</param>
- /// <param name="contractResult">1 涨 2 跌 3 平</param>
- public static async Task<bool> EndActivityCzdTask(this DbRESTFulRepository repository, int contractId, string date, int contractResult)
- {
- var task = await repository.QuerySingleOrDefaultAsync<dynamic>($"select t.id, t.activityId, t.contractId, c.contractName, t.date from n_activity_czd_task as t left join n_activity_czd_contract as c on t.contractId=c.id where t.contractId={contractId} and t.date='{date}' and t.contractResult=0");
- if (task == null) return false;
- // 判断是否是最新的已结束的任务
- var isNewTask = (await repository.QuerySingleOrDefaultAsync<int>(
- $"select id from n_activity_czd_task where id>{task.id} and contractResult>0 limit 1")) == 0;
- var activityId = task.activityId;
- var activityName =
- await repository.QuerySingleOrDefaultAsync<string>(
- $"select title from n_activity where id={activityId}");
- var pointChangeDescription = $"活动奖励-{activityName}";
- var allRecords = (await repository.QueryAsync<ActivityCzdTaskRecord>($"select id, userId, betType, betPoints, createAt from n_activity_czd_task_records where taskId={task.id}")).ToList();
- var risePoints = 0;
- var fallPoints = 0;
- foreach (var record in allRecords)
- {
- // 跌
- if (record.betType == 2)
- {
- fallPoints += record.betPoints;
- }
- // 涨
- else
- {
- risePoints += record.betPoints;
- }
- }
- var platformTotalPoints = 0; // 平台所出价值币
- var totalWinPoints = 0; // 赢方总获取的价值币(不记成本)
- int totalPoints = contractResult == 2 ? risePoints : fallPoints; // 瓜分总价值币
- int totalWinBetPoints = contractResult == 2 ? fallPoints : risePoints; // 赢方总投注价值币
- var rate = totalWinBetPoints > 0 ? (double)totalPoints / totalWinBetPoints : 0;
- var winUserIds = new List<long>();
- foreach (var record in allRecords)
- {
- var win = (record.betType == 2 && contractResult == 2) || (record.betType != 2 && contractResult != 2);
- record.gameResult = win ? 1 : 2;
- if (win)
- {
- var p = (int)Math.Floor(rate * record.betPoints);
- if (p < 20) p = 20;
- totalWinPoints += p;
- record.gainPoints = record.betPoints + p;
- winUserIds.Add(record.userId);
- }
- else
- {
- record.gainPoints = 0;
- }
- }
- platformTotalPoints = totalWinPoints - totalPoints;
- var updateRecords = allRecords.Select(e =>
- {
- return new
- {
- e.id,
- e.gainPoints,
- e.gameResult,
- };
- }).ToList();
- var updateStats = allRecords.Select(e =>
- {
- return new
- {
- e.userId,
- e.createAt,
- win = e.gameResult == 1 ? 1 : 0,
- points = e.gainPoints - e.betPoints,
- };
- }).ToList();
- var pointsRecords = allRecords.Where(e => e.gainPoints > 0).Select(e =>
- {
- return new
- {
- e.userId,
- points = e.gainPoints,
- };
- }).ToList();
- var execCount = 0;
- var taskEndTime = ((DateTime)task.date).ToString("yyyy-MM-dd 15:00:00");
- using var conn = repository.ConnectionManager.GetConnection(false);
- conn.Open();
- var trans = conn.BeginTransaction();
- try
- {
- execCount = await repository.QuerySingleOrDefaultAsync<int>($"update n_activity_czd_task set contractResult={contractResult}, extraPoints={platformTotalPoints} where id={task.id} and contractResult=0; select row_count() as count;", null, conn, trans);
- if (execCount > 0)
- {
- await repository.QueryAsync<dynamic>("update n_activity_czd_task_records set gainPoints=@gainPoints, remind=1, gameResult=@gameResult where id=@id and gameResult=0;", updateRecords, conn, trans);
- if (isNewTask)
- {
- await repository.QueryAsync<dynamic>(@$"update n_activity_czd_task_statistic set
- winTimes=winTimes+@win, continuousTimes=(case @win when 1 then continuousTimes+1 else 0 end),
- totalEarnPoints=totalEarnPoints+@points, lastJoinAt=(case @createAt<lastJoinAt when 1 then lastJoinAt else @createAt end),
- latestWinAt=(case @win when 1 then (case latestWinAt<'{taskEndTime}' when 1 then '{taskEndTime}' else latestWinAt end) else latestWinAt end) where contractId={contractId} and userId=@userId", updateStats, conn, trans);
- // 如果将其他未参与用户的连中次数设置成-1
- await repository.QueryAsync<dynamic>($"update n_activity_czd_task_statistic set continuousTimes=0 where contractId={contractId} [and userId not in @userIds]", new { userIds = winUserIds.Count > 0 ? winUserIds : null }, conn, trans);
- }
- else
- {
- await repository.QueryAsync<dynamic>(@$"update n_activity_czd_task_statistic set
- winTimes=winTimes+@win,
- totalEarnPoints=totalEarnPoints+@points, lastJoinAt=(case @createAt<lastJoinAt when 1 then lastJoinAt else @createAt end),
- latestWinAt=(case @win when 1 then (case latestWinAt<'{taskEndTime}' when 1 then '{taskEndTime}' else latestWinAt end) else latestWinAt end) where contractId={contractId} and userId=@userId", updateStats, conn, trans);
- }
- // 给用户添加价值币
- if (pointsRecords.Count > 0)
- {
- await repository.QueryAsync<dynamic>($"insert into n_user_points_record(userId, points, `way`, extra, description, createAt, createAtDate) values(@userId, @points, 'ACTIVITY', '{activityId}', '{pointChangeDescription}', now(), now())", pointsRecords, conn, trans);
- await repository.QueryAsync<dynamic>($"update n_user_statistic set points=points+@points where userId=@userId", pointsRecords, conn, trans);
- }
- }
- trans.Commit();
- }
- catch (Exception ex)
- {
- trans.Rollback();
- throw ex;
- }
- if (execCount > 0 && !isNewTask)
- {
- // 更新用户的连中次数,最多50次
- var taskIds = (await repository.QueryAsync<int>(
- $"select id from n_activity_czd_task where contractId={contractId} and contractResult>0 order by id desc limit 50",
- null, conn)).ToList();
- // 查询出所有参与记录
- var records =
- (await repository.QueryAsync<dynamic>(
- $"select taskId, userId from n_activity_czd_task_records where taskId in @taskIds and gameResult=1",
- new { taskIds })).ToList();
- // 按人进行统计
- var userIdCountMap = new Dictionary<long, int>();
- var completedUserIds = new HashSet<long>();
- var first = true;
- foreach (var taskId in taskIds)
- {
- var uids = records.Where(e => e.taskId == taskId).Select(e => (long)e.userId).ToHashSet();
- if (first)
- {
- records.ForEach(e =>
- {
- if (!userIdCountMap.ContainsKey(e.userId))
- {
- userIdCountMap.Add(e.userId, uids.Contains(e.userId) ? 1 : 0);
- }
- });
- first = false;
- }
- else
- {
- userIdCountMap.Keys.ForEach(uid =>
- {
- if (completedUserIds.Contains(uid)) return;
- if (uids.Contains(uid) && userIdCountMap.ContainsKey(uid) && userIdCountMap[uid] != 0) userIdCountMap[uid]++;
- else completedUserIds.Add(uid);
- });
- }
- }
- // 更新记录
- if (userIdCountMap.Count > 0)
- {
- var query = userIdCountMap.Select(e => new { userId = e.Key, count = e.Value }).ToList();
- await repository.QueryAsync<dynamic>(
- $"update n_activity_czd_task_statistic set continuousTimes=@count where contractId={contractId} and userId=@userId",
- query, conn, null, false);
- }
- }
- return execCount > 0;
- }
- /// <summary>
- /// 根据给定变更的奖励任务编号列表来更新活动的报名状态
- /// </summary>
- private static async Task UpdateActivitySignupState(this DbRESTFulRepository repository,
- List<int> rewardIds, IDbConnection conn)
- {
- var rewards = (await repository.QueryAsync<dynamic>(
- "select id, activityId, name, requirement, signupLimit from n_activity_reward where id in @ids and signupLimit>0", new
- {
- ids = rewardIds
- }, conn)).ToList();
- if (rewards.Count == 0) return;
- var allActivityIds = rewards.Select(e => (int)e.activityId).Distinct().ToList();
- rewardIds = rewards.Select(e => (int)e.id).ToList();
- var completeStat = (await repository.QueryAsync<dynamic>(
- @"select rewardId, count(1) as count from n_activity_reward_user_state
- where rewardId in @rewardIds and state in(0, 1) group by rewardId",
- new { rewardIds }, conn)).ToList();
- if (completeStat.Count == 0) return;
- var cannotSignupActivityIds = new HashSet<int>();
- var updateRecords = new List<dynamic>();
- rewards.ForEach(p =>
- {
- if (cannotSignupActivityIds.Contains(p.activityId)) return;
- var existStat = completeStat.FirstOrDefault(e => e.rewardId == p.id);
- if (existStat == null) return;
- if (existStat.count >= p.signupLimit)
- {
- cannotSignupActivityIds.Add(p.activityId);
- updateRecords.Add(new
- {
- p.name,
- p.activityId,
- p.requirement,
- existStat.count,
- p.signupLimit
- });
- }
- });
- var canSignupActivityIds = allActivityIds.Where(i => !cannotSignupActivityIds.Contains(i)).ToList();
- var activityInfos = (await repository.QueryAsync<dynamic>("select id, signupState, signupCount, signupStartAt, signupEndAt from n_activity where id in @ids", new
- {
- ids = allActivityIds
- }, conn)).ToList();
- // 过滤掉当前不可报名的活动编号,不可报名的无需更新
- var validCannotSignupActivityIds = cannotSignupActivityIds
- .Where(i => !activityInfos.Any(a => a.id == i && a.signupState == 1)).ToList();
- if (validCannotSignupActivityIds.Count > 0)
- {
- await repository.QueryAsync<dynamic>(
- $"update n_activity set signupState=1 where id in @ids", new
- {
- ids = validCannotSignupActivityIds
- }, conn, null, false);
- await repository.QueryAsync<dynamic>($"insert into n_activity_signup_state_change(activityId, `event`, createAt) values (@activityId, @eventTxt, now())", validCannotSignupActivityIds.Select(
- i =>
- {
- var r = updateRecords.First(r => r.activityId == i);
- var name = string.IsNullOrEmpty(r.name)
- ? $"邀请{r.requirement}人"
- : r.name;
- return new
- {
- activityId = i,
- eventTxt = $"停止报名(原因:任务\"{name}\"完成人数{r.count}达到上限)"
- };
- }));
- }
- if (canSignupActivityIds.Count > 0)
- {
- var now = DateTime.Now;
- var needCheckSignupLimitActivityIds = new List<int>();
- // 过滤掉当前可报名的活动编号,可报名的无需更新
- var validCanSignupActivityIds = canSignupActivityIds.Where(i =>
- {
- var activityInfo = activityInfos.FirstOrDefault(a => a.id == i);
- if (activityInfo == null) return false;
- // 忽略非不可报名状态
- if (activityInfo.signupState != 1) return false;
- // 如果时间不满足或者自定义报名人数不满足 也忽略
- if (activityInfo.signupStartAt > now || activityInfo.signupEndAt < now) return false;
- if (activityInfo.signupCount == 0) return false;
- if (activityInfo.signupCount > 0) needCheckSignupLimitActivityIds.Add(i);
- return true;
- }).ToList();
- // 进一步统计报名人数并判断是否满足
- if (needCheckSignupLimitActivityIds.Count > 0)
- {
- // 查出活动当前报名人数
- var userCountStat = (await repository.QueryAsync<dynamic>(
- "select activityId, count(1) as count from n_activity_signup_records where activityId in @activityIds and state=1",
- new { activityIds = needCheckSignupLimitActivityIds }, conn)).ToList();
- validCanSignupActivityIds = validCanSignupActivityIds.Where(i =>
- {
- var activityInfo = activityInfos.First(a => a.id == i);
- var userCount = userCountStat.FirstOrDefault(s => s.activityId == i)?.count ?? 0;
- return activityInfo.signupCount > userCount;
- }).ToList();
- }
- if (validCanSignupActivityIds.Count > 0)
- {
- await repository.QueryAsync<dynamic>(
- $"update n_activity set signupState=0 where id in @ids", new
- {
- ids = validCanSignupActivityIds
- }, conn, null, false);
- await repository.QueryAsync<dynamic>($"insert into n_activity_signup_state_change(activityId, `event`, createAt) values (@activityId, @eventTxt, now())", validCanSignupActivityIds.Select(
- i => new
- {
- activityId = i,
- eventTxt = "开始报名"
- }));
- }
- }
- }
- /// <summary>
- /// 更新邀请好友活动的统计值(各活动任务完成状态/排行数据)
- /// </summary>
- public static async Task UpdateActivityYqhyStatBySingleUser(this DbRESTFulRepository repository, long userId, IDbConnection conn)
- {
- // 如果邀请好友活动未超出领取时间,才需要更新排名数据
- var needUpdateActivities = (await repository.QueryAsync<dynamic>(
- @"select id, startTime, endTime, config, signupEnabled, rewardRule,hotValue
- from n_activity where state=1 and type='yqhy' and startTime<now() and (latestReceiveTime is null or latestReceiveTime>now())",
- null, conn)).ToList();
- if (needUpdateActivities.Count == 0) return;
- //更新热度值
- List<ActivityHotVO> activityInfos = needUpdateActivities.Where(a => (DateTime)a.endTime >= DateTime.Now && (int)a.signupEnabled == 0).Select(e => new ActivityHotVO
- {
- id = e.id,
- userId = userId,
- oldHotValue = e.hotValue,
- signupEnabled = (int)e.signupEnabled
- }).ToList();
- //活动参与热度记录
- await AddActivityHotRecords(repository, activityInfos, conn);
- var activityIds = needUpdateActivities.Where(e => e.signupEnabled == 1).Select(e => (int)e.id).ToList();
- var signupTimeDic = new Dictionary<int, DateTime>();
- // 如果启用报名的,则需要过滤掉未报名活动
- if (activityIds.Count > 0)
- {
- var validActivityInfos = (await repository.QueryAsync<dynamic>(
- $"select activityId, createAt from n_activity_signup_records where activityId in @activityIds and userId={userId} and state=1",
- new
- {
- activityIds
- }, conn)).ToList();
- validActivityInfos.ForEach(e =>
- {
- signupTimeDic[(int)e.activityId] = (DateTime)e.createAt;
- });
- var validActivityIds = validActivityInfos.Select(e => (int)e.activityId).ToList();
- needUpdateActivities = needUpdateActivities
- .Where(e => activityIds.All(i => i != e.id) || validActivityIds.Any(i => i == e.id))
- .ToList();
- }
- if (needUpdateActivities.Count == 0) return;
- var typedActivitiesDic = new Dictionary<int, ActivityYqhyConfig>();
- var activitiesDic = new Dictionary<int, dynamic>();
- var allRewardIds = new List<int>();
- var minTime = DateTime.MaxValue;
- var maxTime = DateTime.MinValue;
- var now = DateTime.Now;
- foreach (var activity in needUpdateActivities)
- {
- var config = JsonConvert.DeserializeObject<ActivityYqhyConfig>((string)activity.config);
- typedActivitiesDic[activity.id] = config;
- activitiesDic[activity.id] = activity;
- allRewardIds.AddRange(config.rewardIds);
- if (activity.startTime < minTime) minTime = activity.startTime;
- if (activity.endTime > maxTime) maxTime = activity.endTime;
- }
- // 统计此用户此期间所有的有效的邀请记录
- var records = (await repository.QueryAsync<dynamic>(
- $"select createAt, activeAt, hasProfit from n_user_invitation_record where userId={userId} and state=1 and invalid=0 and (createAt>=@minTime and createAt<=@maxTime) and (activeAt>=@minTime and activeAt<=@maxTime)",
- new { minTime, maxTime }, conn)).ToList();
- // 统计不同活动用户成功邀请次数
- var countDic = new Dictionary<int, int>();
- var lastCompletedTime = new Dictionary<int, DateTime>();
- records.ForEach(r =>
- {
- needUpdateActivities.ForEach(a =>
- {
- var aid = (int)a.id;
- var config = typedActivitiesDic[aid];
- var startTime = a.startTime;
- if (signupTimeDic.ContainsKey(aid) && signupTimeDic[aid] > startTime)
- {
- startTime = signupTimeDic[aid];
- }
- // 如果配置不允许获利邀请计入且当前条目是获利,则不计入
- if ((!config.ignoreProfit || r.hasProfit == 0) && (a.endTime == null || a.endTime >= r.activeAt) && startTime <= r.activeAt)
- {
- if (countDic.ContainsKey(aid))
- {
- countDic[aid]++;
- }
- else
- {
- countDic[aid] = 1;
- }
- if (!lastCompletedTime.ContainsKey(aid) || lastCompletedTime[aid] < r.activeAt)
- {
- lastCompletedTime[aid] = r.activeAt;
- }
- }
- });
- });
- // 更新奖励状态记录
- if (allRewardIds.Count > 0)
- {
- var completed = new List<dynamic>();
- var uncompleted = new List<int>();
- // 查出所有活动的奖励配置
- var rewards = await repository.QueryAsync<dynamic>(
- "select id, activityId, requirement from n_activity_reward where id in @ids and invalid=0 order by displayOrder asc",
- new { ids = allRewardIds }, conn);
- // 用于设置仅发最后一个任务的奖励
- var activityIdHashSet = new HashSet<int>();
- // 检测各活动用户奖励是否达标
- rewards.ForEach(r =>
- {
- int requirement = int.Parse(r.requirement);
- int aid = (int)r.activityId;
- var activityInfo = activitiesDic[aid];
- var count = countDic.ContainsKey(aid) ? countDic[aid] : 0;
- var time = lastCompletedTime.ContainsKey(aid) ? lastCompletedTime[aid] : now;
- if (requirement <= count)
- {
- // 如果活动设置的是只能领取最后奖励,则需要将除最高任务的其他任务设置成未达成
- if (activityInfo.rewardRule == 1)
- {
- if (!activityIdHashSet.Contains(aid))
- {
- completed.Add(new
- {
- rewardId = r.id,
- r.activityId,
- latestCompleteAt = time
- });
- activityIdHashSet.Add(aid);
- }
- else
- {
- uncompleted.Add(r.id);
- }
- }
- else
- {
- completed.Add(new
- {
- rewardId = r.id,
- r.activityId,
- latestCompleteAt = time
- });
- }
- }
- else
- {
- uncompleted.Add(r.id);
- }
- });
- if (completed.Count > 0)
- {
- await repository.QueryAsync<dynamic>(@$"insert into n_activity_reward_user_state
- (userId, rewardId, activityId, state, latestCompleteAt) values
- ({userId}, @rewardId, @activityId, 0, @latestCompleteAt)
- ON DUPLICATE KEY update state=if(state=-1, 0, state), latestCompleteAt=if(state=-1, @latestCompleteAt, latestCompleteAt)",
- completed, conn, null, false);
- }
- if (uncompleted.Count > 0)
- {
- await repository.QueryAsync<dynamic>(@$"update n_activity_reward_user_state
- set state=-1 where userId={userId} and rewardId in @ids and state=0", new { ids = uncompleted }, conn, null, false);
- }
- }
- if (countDic.Count > 0)
- {
- // 更新排行数据
- var rankingdata = countDic.Select(e => new
- {
- activityId = e.Key,
- score = e.Value,
- lastRecordTime = lastCompletedTime.ContainsKey(e.Key) ? lastCompletedTime[e.Key] : now
- });
- await repository.QueryAsync<dynamic>($@"insert into n_activity_ranking
- (activityId, userId, score, lastRecordTime) values
- (@activityId, {userId}, @score, @lastRecordTime)
- ON DUPLICATE KEY update score=@score, lastRecordTime=@lastRecordTime", rankingdata, conn, null, false);
- }
- // 更新报名状态
- if (allRewardIds.Count > 0)
- {
- await repository.UpdateActivitySignupState(allRewardIds, conn);
- }
- }
- /// <summary>
- /// 更新每日话题活动的统计值(各活动任务完成状态/排行数据)
- /// </summary>
- public static async Task UpdateActivityMrhtStatBySinglePost(this DbRESTFulRepository repository, long postId,
- IDbConnection conn)
- {
- // 如果每日话题活动未超出领取时间,才需要更新排名数据
- var needUpdateActivities = (await repository.QueryAsync<dynamic>(
- "select id, startTime, endTime, config, signupEnabled, rewardRule,hotValue from n_activity where type='mrht' and state=1 and startTime<now() and (latestReceiveTime is null or latestReceiveTime>now())",
- null, conn)).ToList();
- if (needUpdateActivities.Count == 0) return;
- var postInfo = await repository.QuerySingleOrDefaultAsync<dynamic>($"select userId, categoryType, originalTopicNames, createAt from n_post where id={postId}", null, conn);
- if (postInfo == null) return;
- var userId = (long)postInfo.userId;
- //更新热度值
- List<ActivityHotVO> activityInfos = needUpdateActivities.Where(a => (DateTime)a.endTime >= DateTime.Now && (int)a.signupEnabled == 0).Select(e => new ActivityHotVO
- {
- id = e.id,
- userId = userId,
- oldHotValue = e.hotValue,
- signupEnabled = (int)e.signupEnabled
- }).ToList();
- //活动参与热度记录
- await AddActivityHotRecords(repository, activityInfos, conn);
- {
- var activityIds = needUpdateActivities.Where(e => e.signupEnabled == 1).Select(e => (int)e.id).ToList();
- // 如果启用报名的,则需要过滤掉未报名活动
- if (activityIds.Count > 0)
- {
- var validActivityIds = (await repository.QueryAsync<int>(
- $"select activityId from n_activity_signup_records where activityId in @activityIds and userId={userId} and state=1",
- new
- {
- activityIds
- }, conn)).ToList();
- needUpdateActivities = needUpdateActivities
- .Where(e => !activityIds.Contains(e.id) || validActivityIds.Contains(e.id))
- .ToList();
- }
- }
- if (needUpdateActivities.Count == 0) return;
- var topicNames = ((string)postInfo.originalTopicNames).Split('\n', StringSplitOptions.RemoveEmptyEntries);
- if (topicNames.Length == 0) return;
- var topicIds = (await repository.QueryAsync<int>("select id from n_topic where title in @names",
- new { names = topicNames }, conn)).ToList();
- if (topicIds.Count == 0) return;
- var createDate = ((DateTime)postInfo.createAt).Date;
- // 筛选出此文章话题相关的所有活动
- needUpdateActivities = needUpdateActivities.Where(e =>
- {
- var config = JsonConvert.DeserializeObject<ActivityMrhtConfig>((string)e.config);
- if (config.topics == null) return false;
- var validTopicId = config.topics.LastOrDefault(i => i.date.Date <= createDate && i.topicId > 0)
- ?.topicId ?? 0;
- return validTopicId > 0 && topicIds.Contains(validTopicId);
- }).ToList();
- if (needUpdateActivities.Count == 0) return;
- var relativeActivityIds = needUpdateActivities.Select(e => e.id).ToList();
- // 找出此用户在所有有效每日话题中的活动记录
- var allRelativeRecords = (await repository.QueryAsync<dynamic>(
- $"select activityId, `date`, topicId, postId, createAt from n_activity_mrht_records where userId={userId} and state=1 and activityId in @activityIds",
- new { activityIds = relativeActivityIds }, conn)).ToList();
- if (allRelativeRecords.Count == 0) return;
- // 查出相关活动的奖励配置列表
- var rewards = (await repository.QueryAsync<dynamic>(
- "select id, activityId, requirement, displayOrder from n_activity_reward where activityId in @activityIds and invalid=0 order by displayOrder asc",
- new { activityIds = relativeActivityIds }, conn))
- .Select(e => new { e.id, e.activityId, requirement = int.Parse(e.requirement), e.displayOrder }).ToList();
- if (rewards.Count == 0) return;
- // 查出已达成和未达成的任务
- var completedRecords =
- (await repository.QueryAsync<dynamic>(
- $"select rewardId, latestCompleteAt from n_activity_reward_user_state where userId={userId} and rewardId in @rewardIds and state in (0, 1)",
- new { rewardIds = rewards.Select(e => e.id) }, conn)).ToList();
- var completed = completedRecords.Select(e => (int)e.rewardId).ToList();
- var uncompleted = rewards.Where(e => !completed.Contains(e.id));
- var insertRecords = new List<dynamic>(); // 待插入或更新的达成记录(除去了最高任务奖励类型)
- var singleRewardInsertRecords = new List<dynamic>(); // 待插入或更新的达成记录(仅包含最高任务奖励类型)
- // 判断达成情况
- uncompleted.ForEach(e =>
- {
- var curActivityRecords = allRelativeRecords.Where(i => i.activityId == e.activityId).ToList();
- // 查出此任务所有的完成的记录数量
- var dates = curActivityRecords.Select(i => i.date).Distinct().OrderBy(d => d).ToList();
- var count = dates.Count;
- if (count >= e.requirement && e.requirement > 0)
- {
- // 达成活动的日期
- var date = dates[e.requirement - 1];
- // 找出达成的那天最早的发布时间
- var latestCompleteAt = curActivityRecords.Where(i => i.date == date).Select(i => i.date).Min();
- // 添加到更新列表中
- insertRecords.Add(new { rewardId = e.id, e.activityId, latestCompleteAt });
- }
- });
- // 如果活动设置的是只能领取最后奖励,则需要将除最高任务的其他任务设置成未达成
- var singleRewardActivityList = needUpdateActivities.Where(e => e.rewardRule == 1).ToList();
- if (singleRewardActivityList.Count > 0)
- {
- var set = new HashSet<int>();
- rewards.ForEach(e =>
- {
- if (singleRewardActivityList.All(a => a.id != e.activityId)) return;
- var existRecord = completedRecords.FirstOrDefault(r => r.rewardId == e.id);
- if (existRecord == null) existRecord = insertRecords.FirstOrDefault(r => r.rewardId == e.id);
- if (existRecord == null) return;
- if (set.Contains(e.activityId)) return;
- set.Add(e.activityId);
- singleRewardInsertRecords.Add(new
- {
- rewardId = e.id,
- e.activityId,
- existRecord.latestCompleteAt
- });
- });
- // 先在更新列表中移除只领一个奖励的任务
- insertRecords = insertRecords.Where(e => singleRewardActivityList.All(a => a.id != e.activityId))
- .ToList();
- }
- // 更新此用户所有有效的每日话题活动总参与次数
- var rankingdata = new List<dynamic>();
- allRelativeRecords.GroupBy(e => e.activityId).ForEach(group =>
- {
- var activityId = group.Key;
- var list = group.ToList();
- var sgroup = list.GroupBy(i => i.date);
- var count = sgroup.Count();
- var minTime = sgroup.OrderBy(m => m.Key).Last().First().createAt;
- rankingdata.Add(new
- {
- activityId,
- score = count,
- lastRecordTime = minTime
- });
- });
- List<int> validUpdatedRecordIds = new List<int>();
- if (insertRecords.Count > 0)
- {
- await repository.QueryAsync<dynamic>(@$"insert into n_activity_reward_user_state
- (userId, rewardId, activityId, state, latestCompleteAt) values
- ({userId}, @rewardId, @activityId, 0, @latestCompleteAt)
- ON DUPLICATE KEY update state=if(state=-1, 0, state), latestCompleteAt=if(state=-1, @latestCompleteAt, latestCompleteAt)",
- insertRecords, conn, null, false);
- validUpdatedRecordIds.AddRange(insertRecords.Select(e => (int)e.rewardId));
- }
- if (singleRewardActivityList.Count > 0)
- {
- // 如果活动设置的是只能领取最后奖励,先重置非达成的状态,然后再插入或更新达成的状态
- var activityIds = singleRewardActivityList.Select(a => a.id);
- dynamic rewardIds = singleRewardInsertRecords.Count > 0
- ? singleRewardInsertRecords.Select(e => e.rewardId)
- : null;
- await repository.QueryAsync<dynamic>(
- $"update n_activity_reward_user_state set state=-1 where activityId in @activityIds and userId={userId} [and rewardId not in @rewardIds]", new
- {
- activityIds,
- rewardIds
- }, conn, null, false);
- if (singleRewardInsertRecords.Count > 0)
- {
- await repository.QueryAsync<dynamic>(@$"insert into n_activity_reward_user_state
- (userId, rewardId, activityId, state, latestCompleteAt) values
- ({userId}, @rewardId, @activityId, 0, @latestCompleteAt)
- ON DUPLICATE KEY update state=if(state=-1, 0, state), latestCompleteAt=if(state=-1, @latestCompleteAt, latestCompleteAt)",
- singleRewardInsertRecords, conn, null, false);
- validUpdatedRecordIds.AddRange(singleRewardInsertRecords.Select(e => (int)e.rewardId));
- }
- }
- if (rankingdata.Count > 0)
- {
- await repository.QueryAsync<dynamic>($@"insert into n_activity_ranking
- (activityId, userId, score, lastRecordTime) values
- (@activityId, {userId}, @score, @lastRecordTime)
- ON DUPLICATE KEY update score=@score, lastRecordTime=@lastRecordTime", rankingdata, conn, null, false);
- }
- // 更新报名状态
- if (validUpdatedRecordIds.Count > 0)
- {
- await repository.UpdateActivitySignupState(validUpdatedRecordIds, conn);
- }
- }
- /// <summary>
- /// 活动参与热度记录
- /// </summary>
- /// <param name="repository"></param>
- /// <param name="userId"></param>
- /// <param name="hotInfos"></param>
- /// <param name="conn"></param>
- /// <returns></returns>
- public static async Task AddActivityHotRecords(this DbRESTFulRepository repository, List<ActivityHotVO> hotInfos, IDbConnection conn)
- {
- if (hotInfos != null && hotInfos.Count > 0)
- {
- //所有活动id
- var ids = hotInfos.Select(s => s.id);
- //该用户已经参与活动已经加过热度了
- var activityIds = await repository.QueryAsync<int>(
- $"select activityId from n_activity_hot_records where activityId in @ids and userId=@userId limit 1", new { ids, hotInfos[0].userId },
- conn, null, false);
- if (activityIds != null && activityIds.Count() > 0)
- {
- hotInfos = hotInfos.Where(s => !activityIds.ToList().Contains(s.id)).ToList();
- }
- if (hotInfos != null && hotInfos.Count > 0)
- {
- //报名:每个账号报名成功时,随机加1~10;
- //热度:每个账号完成每个活动的第1次任务时,随机加5~15
- hotInfos.ForEach(item => { item.addHotValue = item.signupEnabled == 1 ? new Random().Next(1, 10) : new Random().Next(5, 15); });
- await repository.QueryAsync<dynamic>(
- "update n_activity set hotValue=hotValue+@addHotValue where id=@id;", hotInfos,
- conn, null, false);
- await repository.QueryAsync<dynamic>(
- $@"insert into n_activity_hot_records(activityId,userId, oldHotValue,addHotValue, createAt)
- values (@id,@userId, @oldHotValue,@addHotValue, now())", hotInfos, conn, null, false);
- }
- }
- }
- }
- }
|