private Pair GetBestQuestinPairByScore(IList <UserPairScoreNormalization> pairs)
        {
            var unbindedPair = pairs.OrderBy(p => p.UserScoreNormalization)
                               .ThenByDescending(p => p.TotalCommunityScore)
                               .ThenBy(p => p.RandomValue).FirstOrDefault();

            return(PairCache.Where(p => p.Id == unbindedPair.PairID).FirstOrDefault());
        }
        public async Task <ApiModels.QuestionBinding> GetQuestion(int userId, int userClientId, int dictionaryId, int questionTypeId)
        {
            //var dictionary = CacheProvider.Dictionaries.Where(d => d.Id == dictionaryId).FirstOrDefault();
            //if (dictionary == null)
            //throw new NullReferenceException(string.Format("Dictionary not exist with DictionaryID:{0}", dictionaryId));

            if (questionTypeId < 1 || questionTypeId > 2)
            {
                throw new ArgumentOutOfRangeException(string.Format("Invalid QuestionTypeID {0}", questionTypeId));
            }

            if (CacheProvider.Pairs.Count < 5)
            {
                throw new InvalidOperationException("Not enough pair for dictionary");
            }

            var unansweredQuestion = await GetUnansweredQuestion(userClientId, dictionaryId);



            var rankList = GetAllUserRanksByDictionaryId(userId, dictionaryId);

            var userRank = rankList.FirstOrDefault(r => r.UserId == userId);

            if (unansweredQuestion != null)
            {
                var unansweredPair = PairCache.Where(p => p.Id == unansweredQuestion.PairID).FirstOrDefault();
                var targetSoundEx  = unansweredPair.SoundEx1;
                if (unansweredQuestion.QuestionWordNumber == 2)
                {
                    targetSoundEx = unansweredPair.SoundEx2;
                }

                var wrongPairs = await GetWrongPairs(targetSoundEx, unansweredQuestion.QuestionWordNumber, dictionaryId, unansweredPair.Id);

                return(ModelFactory.ToQuestionBinding(unansweredQuestion, unansweredPair, wrongPairs, null));
            }

            var communityScore = await GetCommunityScore(userId, dictionaryId);

            var unbindPair = await GenerateUnpairQuestion(communityScore, dictionaryId);

            int numberOfWord = Convert.ToInt32(Math.Floor(new Random().NextDouble() * (3 - 1) + 1));

            var question = AddNewQuestionWithUnbindPair(unbindPair, userClientId, numberOfWord);

            await RefreshCaches(true);

            var wrongPairList = await GetWrongPairs(unbindPair.SoundEx1, numberOfWord, dictionaryId, unbindPair.Id);

            var questionBind = ModelFactory.ToQuestionBinding(question, unbindPair, wrongPairList, null);

            return(await Task.FromResult(questionBind));
        }
        private bool CheckAnswer(Question question, ApiModels.Answer answer)
        {
            var pair = PairCache.Where(p => p.Id == question.PairID).FirstOrDefault();

            if (question.QuestionWordNumber == 1)
            {
                return(string.Compare(pair.InLanguage2, answer.AnswerText, true) == 0);
            }
            else
            {
                return(string.Compare(pair.InLanguage1, answer.AnswerText, true) == 0);
            }
        }