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(); } }
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(); } }
internal static void ResetAllCardsSimple() { using (CitizenEntities db = new CitizenEntities()) { List<Card> allCards = db.Cards.ToList(); foreach (Card card in allCards) { card.Score = 0d; } db.SaveChanges(); } }
internal static void RemoveCardSimple(Guid guid) { using (CitizenEntities db = new CitizenEntities()) { Card card = db.Cards.Where(c => c.CardId == guid).First(); card.Score = -1d; db.SaveChanges(); } }
public static void UpdateCard(string englishText, string chineseText, Guid cardId) { using (CitizenEntities db = new CitizenEntities()) { if (cardId == Guid.Empty) // new card to add { Card newCard = new Card() { CardId = Guid.NewGuid(), EnglishText = englishText, ChineseText = chineseText, Score = 0d }; db.AddToCards(newCard); } else { Card card = db.Cards.Where(c => c.CardId == cardId).First(); card.ChineseText = chineseText; card.EnglishText = englishText; } db.SaveChanges(); } }
public static List<Card> SearchCards(string word) { List<Card> result = new List<Card>(); using (CitizenEntities db = new CitizenEntities()) { result = db.Cards.Where(c => c.EnglishText.Contains(word) || c.ChineseText.Contains(word)).ToList(); } return result; }
public static Card GetNextCardSimple(int? goToNum) { using (CitizenEntities db = new CitizenEntities()) { // if goToNum is provided, ignore the score. if (goToNum != null) { string startWith = goToNum.ToString() + "."; var q2 = db.Cards.Where(c => c.EnglishText.StartsWith(startWith)); if (q2.Count() != 1) return null; else return q2.First(); } else { // Only THREE types of score in simple mode: // 0 - never touched // -0.5 - in progress // -1 - removed, don't show var query = db.Cards.Where(c => c.Score == -0.5); if (query.Count() > 0) return query.First(); else { query = db.Cards.Where(c => c.Score == 0); if (query.Count() > 0) { Card card = query.First(); card.Score = -0.5d; db.SaveChanges(); return card; } else return null; } } } }