Exemple #1
0
 public AnswerLogView(answer_log a)
 {
     id          = a.id;
     create_time = a.create_time;
     uid         = a.uid;
     gid         = a.gid;
     pid         = a.pid;
     answer      = a.answer;
     status      = a.status;
 }
        public async Task CheckAnswer(Request request, Response response)
        {
            var userSession = await CheckAuth.Check(request, response, AuthLevel.Member, true);

            if (userSession == null)
            {
                return;
            }

            var requestJson = request.Json <CheckAnswerRequest>();

            //判断请求是否有效
            if (!Validation.Valid(requestJson, out string reason))
            {
                await response.BadRequest(reason);

                return;
            }

            var answerLogDb = DbFactory.Get <AnswerLog>();
            var answerLog   = new answer_log
            {
                create_time = DateTime.Now,
                uid         = userSession.uid,
                pid         = requestJson.pid,
                answer      = requestJson.answer
            };

            //取得该用户GID
            var groupBindDb   = DbFactory.Get <UserGroupBind>();
            var groupBindList = await groupBindDb.SelectAllFromCache();

            var groupBindItem = groupBindList.FirstOrDefault(it => it.uid == userSession.uid);

            if (groupBindItem == null)
            {
                answerLog.status = 5;
                await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                await response.BadRequest("未确定组队?");

                return;
            }

            var gid = groupBindItem.gid;

            answerLog.gid = gid;

            //取得进度
            var progressDb = DbFactory.Get <Progress>();
            var progress   = await progressDb.SimpleDb.AsQueryable().Where(it => it.gid == gid).FirstAsync();

            if (progress == null)
            {
                answerLog.status = 5;
                await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                await response.BadRequest("没有进度,请返回首页重新开始。");

                return;
            }

            var progressData = progress.data;

            if (progressData == null)
            {
                answerLog.status = 5;
                await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                await response.BadRequest("未找到可用存档,请联系管理员。");

                return;
            }

            //取出待判定题目
            var puzzleDb   = DbFactory.Get <Puzzle>();
            var puzzleList = await puzzleDb.SelectAllFromCache();

            //取出隐藏关键字
            var jumpKeyWords = puzzleList.Where(it => !string.IsNullOrEmpty(it.jump_keyword))
                               .GroupBy(it => it.jump_keyword.ToLower())
                               .ToDictionary(it => it.Key, it => it.First());

            if (jumpKeyWords.ContainsKey(requestJson.answer.ToLower()))
            {
                var jumpTarget = jumpKeyWords[requestJson.answer.ToLower()];

                answerLog.status = 6;
                await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                //回写存档
                progress.data.OpenedHidePuzzles.Add(jumpTarget.pid);
                await progressDb.SimpleDb.AsUpdateable(progress).IgnoreColumns(it => new { it.finish_time }).ExecuteCommandAsync();

                //返回
                await response.JsonResponse(200, new AnswerResponse
                {
                    status        = 3,
                    answer_status = 6,
                    message       = "好像发现了什么奇妙空间。",
                    location      = $"/puzzle/{jumpTarget.pid}"
                });

                return;
            }


            var puzzleItem = puzzleList.Where(it => it.pid == requestJson.pid).First();

            if (puzzleItem == null)
            {
                answerLog.status = 4;
                await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                await response.BadRequest("题目不存在或未解锁。");

                return;
            }

            //FinalMeta需存档可见
            if (puzzleItem.answer_type == 2)
            {
                if (!progressData.IsOpenPreFinal)
                {
                    answerLog.status = 4;
                    await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                    await response.BadRequest("题目不存在或未解锁。");

                    return;
                }
            }
            else if (puzzleItem.answer_type == 3)
            {
                if (!progressData.IsOpenFinalMeta)
                {
                    answerLog.status = 4;
                    await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                    await response.BadRequest("题目不存在或未解锁。");

                    return;
                }
            }
            //需判定题目组已开放或者题目本身作为隐藏题目开放
            else if (!progressData.NowOpenPuzzleGroups.Contains(puzzleItem.pgid) && !progressData.OpenedHidePuzzles.Contains(puzzleItem.pid))
            {
                answerLog.status = 4;
                await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                await response.BadRequest("题目不存在或未解锁。");

                return;
            }

            //取得最后一次错误答题记录
            var lastWrongTime   = DateTime.MinValue;
            var lastWrongAnswer = await answerLogDb.SimpleDb.AsQueryable().Where(it => it.gid == gid && it.status != 1 && it.status != 3 && it.status != 6)
                                  .OrderBy(it => it.create_time, OrderByType.Desc).FirstAsync();

            if (lastWrongAnswer != null)
            {
                lastWrongTime = lastWrongAnswer.create_time;
            }

            //判断是否在冷却时间内
            var coolTime = (DateTime.Now - lastWrongTime).TotalSeconds;

            if (coolTime <= Config.Config.Options.CooldownTime)
            {
                var remainTime = Config.Config.Options.CooldownTime - coolTime;
                answerLog.status = 3;
                await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                await response.JsonResponse(406, new AnswerResponse //使用 406 Not Acceptable 作为答案错误的专用返回码。若返回 200 OK 则为答案正确
                {
                    status                  = 1,
                    answer_status           = 3,
                    message                 = $"冷却中,还有 {remainTime:F0} 秒",
                    cooldown_remain_seconds = remainTime
                });

                return;
            }

            //判断答案是否正确
            if (!string.Equals(puzzleItem.answer, requestJson.answer, StringComparison.CurrentCultureIgnoreCase))
            {
                answerLog.status = 2;
                await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

                await response.JsonResponse(406, new AnswerResponse //使用 406 Not Acceptable 作为答案错误的专用返回码。若返回 200 OK 则为答案正确
                {
                    status        = 1,
                    answer_status = 2,
                    message       = "答案错误"
                });

                return;
            }

            //答案正确
            answerLog.status = 1;
            await answerLogDb.SimpleDb.AsInsertable(answerLog).ExecuteCommandAsync();

            //更新存档

            //若解出的题目是分区Meta,则标记为该分区完成
            if (puzzleItem.answer_type == 1)
            {
                progress.data.FinishedGroups.Add(puzzleItem.pgid);
            }

            //检查是否可以打开新区域
            var successMessage = "OK";

            var puzzleGroupDb  = DbFactory.Get <PuzzleGroup>();
            var nowPuzzleGroup = (await puzzleGroupDb.SelectAllFromCache()).Where(it => it.pgid == puzzleItem.pgid).First();

            if (nowPuzzleGroup != null && nowPuzzleGroup.is_hide == 0)      //只有非隐藏分区才可打开新区域
            {
                if (!progressData.UsedOpenGroups.Contains(puzzleItem.pgid)) //只有未开放过新区域的分组可以打开新区域
                {
                    if (progressData.NowOpenPuzzleGroups.Count <= 1)        //第一个分区,需完成分区meta
                    {
                        if (puzzleItem.answer_type == 1)
                        {
                            successMessage += " 成功解答出了Meta,好像有其他的区域开放了。";
                            progress.data.IsOpenNextGroup = true;
                            progress.data.UsedOpenGroups.Add(puzzleItem.pgid);
                        }
                    }
                    else //否则仅需完成本区域内半数题目(向上取整)
                    {
                        if (puzzleItem.answer_type == 1)
                        {
                            successMessage += " 成功解答出了Meta,可以开放下一个区域了。";
                            progress.data.IsOpenNextGroup = true;
                            progress.data.UsedOpenGroups.Add(puzzleItem.pgid);
                        }
                        else
                        {
                            var thisGroupPuzzleList = puzzleList.Where(it => it.pgid == puzzleItem.pgid).ToList();
                            var totalPuzzle         = thisGroupPuzzleList.Count;
                            var finishedPuzzle      = thisGroupPuzzleList.Where(it => progress.data.FinishedPuzzles.Contains(it.pid)).Count();

                            var halfNumber = totalPuzzle / 2;
                            if ((finishedPuzzle + 1) >= halfNumber)
                            {
                                successMessage += " 在这个分区已经解答了大多数问题,可以去下个区域看看了。";
                                progress.data.IsOpenNextGroup = true;
                                progress.data.UsedOpenGroups.Add(puzzleItem.pgid);
                            }
                        }
                    }
                }
            }

            if (!string.IsNullOrEmpty(puzzleItem.extend_content))
            {
                successMessage += " 好像发现了什么线索(请注意题目页面多出来的新内容)。";
            }

            //检查是否符合开放FinalMeta条件
            if (progress.data.NowOpenPuzzleGroups.Count >= Config.Config.Options.ShowFinalOpenGroups && progress.data.FinishedGroups.Count >= Config.Config.Options.ShowFinalGroups)
            {
                progress.data.IsOpenPreFinal = true;
            }
            if (puzzleItem.answer_type == 2)
            {
                progress.data.IsOpenFinalMeta = true;
            }

            //计算分数
            //时间分数为 1000 - (开赛以来的总时长 + 罚时)

            if (!progressData.FinishedPuzzles.Contains(puzzleItem.pid))
            {
                const double timeBaseScore = 1000d;
                var          timeSpanHours =
                    (DateTime.Now - Ccxc.Core.Utils.UnixTimestamp.FromTimestamp(Config.Config.Options.StartTime))
                    .TotalHours + progress.penalty;
                var timeScore = timeBaseScore - timeSpanHours;

                var puzzleFactor = 1.0d; //题目得分系数
                if (puzzleItem.answer_type == 1)
                {
                    puzzleFactor = 5.0d;
                }
                else if (puzzleItem.answer_type == 2)
                {
                    puzzleFactor = 10.0d;
                }
                else if (puzzleItem.answer_type == 3)
                {
                    puzzleFactor = 50.0d;
                }
                else if (puzzleItem.answer_type == 4)
                {
                    puzzleFactor = 0.0d;
                }

                if (progress.is_finish == 1)
                {
                    puzzleFactor *= 0.5; //完赛后继续答题题目分数减半
                }


                progress.score += timeScore * puzzleFactor; //累加本题分数
            }

            //本题目标记为已完成
            progress.data.FinishedPuzzles.Add(puzzleItem.pid);

            //回写存档

            //计算是否完赛
            if (puzzleItem.answer_type == 3)
            {
                progress.is_finish   = 1;
                progress.finish_time = DateTime.Now;

                await progressDb.SimpleDb.AsUpdateable(progress).ExecuteCommandAsync();
            }
            else
            {
                await progressDb.SimpleDb.AsUpdateable(progress).IgnoreColumns(it => new { it.finish_time }).ExecuteCommandAsync();
            }

            //返回回答正确
            await response.JsonResponse(200, new AnswerResponse
            {
                status        = 1,
                answer_status = 1,
                extend_flag   = string.IsNullOrEmpty(puzzleItem.extend_content) ? 0 : 16,
                message       = successMessage
            });
        }