public async Task <IActionResult> CreateQuiz([FromBody][Bind("Topic", "Category", "Description", "ImagePath", "Questions")] Quiz quiz) { if (quiz.Id != 0) { return(BadRequest("Invalid ID")); } quiz.Category = QuizUtil.CategoryFromIndex(int.TryParse(quiz.Category, out var i) ? i : (int?)null); if (quiz.Category == null) { return(BadRequest("Invalid category!")); } if (!QuizUtil.QuestionsValid(quiz.Questions)) { return(BadRequest("Invalid question format!")); } if (!ModelState.IsValid) { return(BadRequest("Invalid quiz format!")); } quiz.OwnerUsername = _um.GetUserName(User); _db.Add(quiz); await _db.SaveChangesAsync(); var user = await _um.GetUserAsync(User); user.MyQuizzes.Add(quiz); await _um.UpdateAsync(user); return(Ok()); }
public async Task <IActionResult> UpdateQuiz([FromBody][Bind("Topic", "Category", "Description", "ImagePath", "Questions")] Quiz quizForm) { if (!ModelState.IsValid) { return(BadRequest("Model state not valid!")); } var quiz = await _db.Quizzes .Where(q => q.Id == quizForm.Id) .Include(q => q.Questions) .FirstOrDefaultAsync(); if (quiz == null) { return(BadRequest("Quiz not found!")); } if (quiz.OwnerId != _um.GetUserId(User)) { return(BadRequest("You are not the owner of this quiz!")); } if (!QuizUtil.QuestionsValid(quiz.Questions)) { return(BadRequest("Question format not valid!")); } if (await _db.QuizzesTaken.AnyAsync(q => q.Quiz == quiz)) { return(BadRequest("You cannot edit this quiz because someone has already taken it. You can however delete it, and create a new.")); } try { if (quizForm.Category != quiz.Category) { quiz.Category = QuizUtil.CategoryFromIndex(int.TryParse(quiz.Category, out var i) ? i : (int?)null); if (quiz.Category == null) { return(BadRequest("Invalid category!")); } } quiz.Topic = quizForm.Topic; quiz.Description = quizForm.Description; quiz.ImagePath = quizForm.ImagePath; _db.Questions.RemoveRange(quiz.Questions); quiz.Questions = quizForm.Questions; await _db.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { return(BadRequest("Woopsie! Database error! :(")); } return(Ok()); }
public async Task <IActionResult> CheckAnswer(int?quizId, int?questionId, char guessAlternative) { if (quizId == null || questionId == null || guessAlternative == 0) { return(BadRequest()); } var question = await _db.Questions.FindAsync(questionId); if (question == null) { return(BadRequest()); } var userId = _um.GetUserId(User); var xpGained = 0; var bonus = 0; // If user is authorized if (userId != null) { var user = await _db.Users .Include(u => u.QuestionsTaken) .Include(u => u.QuizzesTaken) .Include(u => u.MyQuizzes) .SingleOrDefaultAsync(u => u.Id == userId); // Check if user has answered this question before if (!user.QuestionsTaken.Exists(q => q.QuestionId == questionId)) { // Check answer by alternative var answeredCorrectly = guessAlternative == question.CorrectAlternative; var timer = DateTime.Now - user.LastQuestionStarted; var timerSec = (int)Math.Round(timer.TotalSeconds); var isOwner = user.MyQuizzes.Any(q => q.Id == quizId); // If answered within time frame if (answeredCorrectly && timerSec >= 0 && timerSec <= 15 && !isOwner) { xpGained = QuizUtil.XpGainedFromQuestion(question.Difficulty); bonus = (int)(xpGained * (((15f - timerSec) / 15f * 100f) / 100f)); AddExperience(user, xpGained + bonus); } AddQuestionTaken(user, question, answeredCorrectly, xpGained, bonus, timer, guessAlternative); } // Check if all the questions of the quiz has been answered UpdateQuizTaken(user, quizId, questionId); } return(Ok(new { correctAlternative = question.CorrectAlternative, xpGained, bonus })); }
/// <summary> /// バインドします。 /// </summary> public override void Bind(QuizModel model) { // キーボードのバインド var keyboardButtons = keyboardBase.GetComponentsInChildren <Button>().ToList(); var deleteButton = keyboardButtons.Find(x => x.name == DeleteButtonObjectName); { // 入力ボタン foreach (var button in keyboardButtons.Where(x => x.name != DeleteButtonObjectName)) { button.OnClickAsObservable().Subscribe(_ => { var text = button.GetComponentInChildren <Text>(); _input.Value = QuizUtil.Convert($"{Input}{text.text}", WordEnum); }).AddTo(button); } // 削除ボタン deleteButton.OnClickAsObservable().Subscribe(_ => { if (!string.IsNullOrEmpty(Input)) { if (Input.Length >= 8) { _input.Value = Input.Substring(0, 7); } else { _input.Value = Input.Substring(0, Input.Length - 1); } } }).AddTo(deleteButton); } // 入力文字列の反映 _input.Subscribe(input => { for (int index = 0; index < TypingTexts.Count && index < input.Length; index++) { TypingTexts[index].text = input[index].ToString(); } for (int index = input.Length; index < TypingTexts.Count; index++) { TypingTexts[index].text = string.Empty; } }).AddTo(this); // OKボタン okButton.OnClickAsObservable().Subscribe(_ => { var answer = new string(Input.Take(8).ToArray()); model.PushAnswer(answer); }).AddTo(okButton); }
/// <summary> /// スコアを変更します。 /// </summary> public void ChangeScore(int before, int after) { if (before < after) { var upScore = after - before; this.score.text = $"<color=yellow>(+{upScore})</color>{after}点"; } else { this.score.text = $"{after}点"; } var rank = QuizUtil.GetQuizRank(after); this.rank.text = rank.ToString(); var rankRatio = QuizUtil.GetRankRatio(after); nextRankBackground.fillAmount = rankRatio; }
private static async Task AddRandomQuizzes(int amount) { // Get questions from open trivia DB API for (var i = 0; i < amount; i++) { dynamic randomQuestion = await GetObjectFromApi("https://opentdb.com/", "api.php?amount=10"); if (randomQuestion == null || randomQuestion.response_code != 0) { continue; } var apiQuestions = new List <Question>(); foreach (var q in randomQuestion.results) { if (q == null) { continue; } // TODO: Should strings be json stringified? string text = HttpUtility.HtmlDecode((string)q.question); string qType = q.type; string qDifficulty = q.difficulty; string answer = HttpUtility.HtmlDecode((string)q.correct_answer); Question question; if (qType == "multiple") { string[] alternatives = { answer, HttpUtility.HtmlDecode((string)q.incorrect_answers[0]), HttpUtility.HtmlDecode((string)q.incorrect_answers[1]), HttpUtility.HtmlDecode((string)q.incorrect_answers[2]) }; var alt = JsonConvert.SerializeObject(alternatives); question = new Question("multiple_choice", text, alt, answer, 'A', qDifficulty, ""); } else { question = new Question("true_false", text, null, answer, answer == "true" ? 'T' : 'F', qDifficulty, null); } apiQuestions.Add(question); await _db.Questions.AddRangeAsync(question); await _db.SaveChangesAsync(); } string randomName = Path.GetRandomFileName().Replace(".", ""); string category = HttpUtility.HtmlDecode(QuizUtil.CategoryFromIndex(_ran.Next(0, 23))); var ranUser = await _db.Users.Skip(_ran.Next(0, _db.Users.Count())).FirstAsync(); var quiz = new Quiz(ranUser, apiQuestions, category, randomName, "Description", "easy") { ImagePath = "/images/logo_transparent_notxt.png", Upvotes = _ran.Next(0, 500), Views = _ran.Next(0, 50000) }; await _db.Quizzes.AddRangeAsync(quiz); await _db.SaveChangesAsync(); } }
/// <summary> /// 残り回答時間ゲージを設定します。 /// </summary> public void SetSlider(Format format, float value) { Slider.value = value; SliderImage.color = QuizUtil.GetSliderColor(format, value); }
/// <summary> /// HomeMenuのバインダー /// </summary> public override void Bind(SceneModel model) { // 第○問目 var quizModel = model.FindModel <QuizModel>(); quizModel.OnChangeCount.Subscribe(count => { this.CurrentQuiz = quizModel.CurrentQuiz; SetQuiz(count); ElapsedSeconds = 0.0f; }); // 解答送信 quizModel.OnPushAnswer.Subscribe(answer => { // 正誤判定&スコア計算 var isCorrect = CurrentQuiz.CorrectAnswer == answer; if (isCorrect) { var answerTime = QuizConfig.LimitSeconds - ElapsedSeconds; var score = QuizUtil.GetScore(CurrentQuiz, answerTime, false); // TODO:マニアック判定 quizModel.Score += score; } else { scorePanel.ChangeScore(quizModel.Score, quizModel.Score); } GeLogger.Debug($"your answer is {answer}. correctAnswer is {CurrentQuiz.CorrectAnswer}"); // 正誤表示 scorePanel.ActivateFalsehoodObject(isCorrect); // 画面のリセット questionPanel.Reset(); answerPanel.Reset(CurrentQuiz); // 次の問題へ sentenceCount = 0; quizModel.QuizCount++; }).AddTo(this); // 解答部分のバインド answerPanel.Bind(model); // 回答時間 this.UpdateAsObservable().Subscribe(_ => { ElapsedSeconds += Time.deltaTime; var value = 1 - Mathf.Clamp01(ElapsedSeconds / QuizConfig.LimitSeconds); questionPanel.SetSlider(CurrentQuiz.Format, value); if (ElapsedSeconds >= QuizConfig.LimitSeconds) { quizModel.PushAnswer("時間切れ"); } }); // 問題文の表示 Observable.Interval(TimeSpan.FromSeconds(QuizConfig.SentenceInterval)).Subscribe(_ => { questionPanel.ViewSentence(CurrentQuiz, ref sentenceCount); }).AddTo(this); // スコア変更 quizModel.OnChangeScore.Buffer(2, 1).Subscribe(scores => { var before = scores[0]; var after = scores[1]; scorePanel.ChangeScore(before, after); }).AddTo(this); }
public async Task <IActionResult> GetQuizList(string username, int page, int size, string type, int?categoryIndex, string difficulty, string orderBy, string search) { if (page < 1 || (size > 20 || size < 0)) { return(BadRequest()); } switch (type) { case "history" when username != null: { var query = await _um.Users .Where(u => u.UserName == username) .SelectMany(q => q.QuizzesTaken) .Include(q => q.Quiz).ToListAsync(); var entries = query.Skip((page - 1) * size).Take(size).ToList(); var pages = (int)Math.Ceiling(decimal.Divide(query.Count, size)); var authUsername = _um.GetUserName(User); var showSummary = authUsername != null && authUsername == username; return(Ok(new { entries, pages, showSummary })); } case "quizzesBy" when username != null: { var query = await _db.Quizzes.Where(q => q.OwnerUsername == username).ToListAsync(); var entries = query.Skip((page - 1) * size).Take(size).ToList(); var pages = (int)Math.Ceiling(decimal.Divide(query.Count, size)); var authUsername = _um.GetUserName(User); var canEdit = authUsername != null && authUsername == username; return(Ok(new { entries, pages, canEdit })); } case "search": { var category = QuizUtil.CategoryFromIndex(categoryIndex); var query = await _db.Quizzes.ToListAsync(); // If category and difficulty is defined, filter the query if (category != null) { query = query.Where(q => q.Category == category).ToList(); } else if (difficulty != null) { query = query.Where(q => q.Difficulty == difficulty).ToList(); } if (search != null) { var searchArr = Regex.Split(search.ToLower(), @"\s+").Where(s => s != string.Empty); var queryUserName = query.Where(q => searchArr.Any(q.OwnerUsername.ToLower().Contains)).ToList(); var queryDescription = query.Where(q => searchArr.Any(q.Description.ToLower().Contains)).ToList(); var queryCategory = query.Where(q => searchArr.Any(q.Category.ToLower().Contains)).ToList(); var queryTopic = query.Where(q => searchArr.Any(q.Topic.ToLower().Contains)).ToList(); List <Quiz> searchList = new List <Quiz>(); searchList.AddRange(queryTopic); searchList.AddRange(queryUserName); searchList.AddRange(queryDescription); searchList.AddRange(queryCategory); query = searchList.Distinct().ToList(); } if (orderBy != null) { if (orderBy == "views") { query = query.OrderByDescending(q => q.Views).ToList(); } else if (orderBy == "upvotes") { query = query.OrderByDescending(q => q.Upvotes).ToList(); } else if (orderBy == "recent") { query = query.OrderByDescending(q => q.CreationDate).ToList(); } } var entries = query.Skip((page - 1) * size).Take(size).ToList(); var pages = (int)Math.Ceiling(decimal.Divide(query.Count, size)); return(Ok(new { entries, pages })); } default: return(BadRequest("Type not found!")); } }
/// <summary> /// 初期化を行います。 /// </summary> public override void Initialize(QuizEntity quiz) { Reset(); WordEnum = QuizUtil.GetWordEnum(quiz.CorrectAnswer); }