示例#1
0
        public static void AddAttempt(Guid cardId, bool result)
        {
            // scoring
            double score = 0d;
            DateTime now = DateTime.Now;
            Attempt lastAttempt = new Attempt();
            using (CitizenEntities db = new CitizenEntities())
            {
                if (db.Attempts.Where(a => a.Card.CardId == cardId).Count() > 0)
                {
                    lastAttempt = db.Attempts.Where(a => a.Card.CardId == cardId).OrderByDescending(a => a.CreateDate).First();
                }
                else lastAttempt = null;

                if (lastAttempt != null)
                {
                    double minSinceLast = (now - lastAttempt.CreateDate).TotalMinutes;
                    if (minSinceLast <= 0) throw new Exception("New attempt CreateDate happened before last attempt. Impossible!!");
                    if (result)
                        score = 1d - (1d / (Math.Log(minSinceLast + 9d, 10d)));
                    else score = -(1d / (Math.Log(minSinceLast + 9d, 10d)));
                }
                // update card, and insert new attempt.
                Card card = db.Cards.Where(c => c.CardId == cardId).First();
                if (score > 0d) card.Score = Math.Max(card.Score, score);
                if (score < 0d) card.Score = Math.Min(card.Score, score);
                else card.Score = 0d;
                card.Attempts.Add(new Attempt() { AttemptId = Guid.NewGuid(), Card = card, CreateDate = now, Result = result });
                db.SaveChanges();
            }
        }
示例#2
0
        public static Card GetNextCard()
        {
            // first fetch:
            // - have attempt(s), but less than 3; and
            // - no attempt in last 1 min; and
            // - not in last 5 attempts
            using (CitizenEntities db = new CitizenEntities())
            {
                List<Guid> temp1 = (from a in db.Attempts
                                    group a by a.Card.CardId into g
                                    where g.Count() > 0 && g.Count() < 4
                                    select g.Key).ToList();
                if (temp1.Count != 0)
                {
                    DateTime oneMinBack = DateTime.Now.AddMinutes(-1);
                    List<Guid> temp2 = (from a in db.Attempts
                                        where a.CreateDate > oneMinBack
                                        select a.Card.CardId).ToList();
                    List<Guid> temp3 = (from a in db.Attempts
                                        orderby a.CreateDate descending
                                        select a.Card.CardId).Take(5).ToList();
                    List<Guid> temp4 = (from t in temp1
                                        where !temp2.Contains(t) && !temp3.Contains(t)
                                        select t).ToList();
                    if (temp4.Count != 0)
                    {
                        Random ran = new Random();
                        Guid picked = temp4[ran.Next(temp4.Count)];
                        return db.Cards.Where(c => c.CardId == picked).First();
                    }
                }

                // second fetch:
                // - no attempt in last 5 mins
                // - no frequent correct ones
                //      - has 2+ correct attempts in the past 1 day; or
                //      - has 5+ correct attempts in the past 1 week
                // - if last attempt correct, pick from score<=0; otherwise, pick from score>0.
                //      - if no last attempt, do not pay attention to score.
                // - if found, pick the one has min(|score|)
                DateTime now = DateTime.Now;
                DateTime fiveMinBack = now.AddMinutes(-5);
                DateTime oneDayBack = now.AddDays(-1);
                DateTime oneWeekBack = now.AddDays(-7);
                List<Card> temp5 = (from c in db.Cards
                                    where c.Attempts.Where(a => a.CreateDate > fiveMinBack).Count() == 0
                                    select c).ToList();
                if (temp5.Count == 0) return null;

                List<Guid> frequentCorrectDay = (from a in db.Attempts
                                                 where a.CreateDate > oneDayBack && a.Result == true
                                                 group a by a.Card.CardId into g
                                                 where g.Count() >= 2
                                                 select g.Key).ToList();
                List<Guid> frequentCorrectWeek = (from a in db.Attempts
                                                  where a.CreateDate > oneWeekBack && a.Result == true
                                                  group a by a.Card.CardId into g
                                                  where g.Count() >= 5
                                                  select g.Key).ToList();
                temp5 = temp5.Where(c => !frequentCorrectDay.Contains(c.CardId) && !frequentCorrectWeek.Contains(c.CardId)).ToList();

                Attempt lastAttempt = new Attempt();
                if (db.Attempts.Count() != 0) lastAttempt = db.Attempts.OrderByDescending(a => a.CreateDate).First();
                else lastAttempt = null;
                List<Card> temp6 = new List<Card>();
                if (lastAttempt != null)
                {
                    if (lastAttempt.Result) temp6 = temp5.Where(c => c.Score <= 0).ToList();
                    else temp6 = temp5.Where(c => c.Score > 0).ToList();
                }
                if (temp6.Count == 0) temp6 = temp5;

                return (from t in temp6
                        orderby Math.Abs(t.Score)
                        select t).First();
            }
        }