public async Task <string> GetQuestionAPITokenAsync(BiblePathsCoreDbContext context) { string TokenString = "No API Token Found"; // Find the most recent token for this user QuizQuestionStat TokenStat = new QuizQuestionStat(); try { TokenStat = await context.QuizQuestionStats.Where(T => T.QuizUserId == this.Id && T.EventType == (int)QuizQuestion.QuestionEventType.QuestionAPIToken) .OrderByDescending(T => T.EventWritten).Take(1).SingleAsync(); } catch { // We'll take any exceptions to indicate we couldn't find a Token return(TokenString); } TokenString = "API Token Expired"; TimeSpan TimeSinceTokenCreated = (TimeSpan)(DateTime.Now - TokenStat.EventWritten); if (TimeSinceTokenCreated.TotalHours < 24) { TokenString = TokenStat.EventData; } return(TokenString); }
public static async Task <List <SelectListItem> > GetPathSelectListAsync(BiblePathsCoreDbContext context) { List <SelectListItem> PathSelectList = new List <SelectListItem>(); List <Path> Paths = await context.Paths .Where(P => P.IsDeleted == false && P.IsPublished == true) .OrderBy(P => P.StepCount) .ToListAsync(); // Add a Default entry PathSelectList.Add(new SelectListItem { Text = "Select a Bible Path", Value = 0.ToString() }); // Add our BookLists first foreach (Path path in Paths) { PathSelectList.Add(new SelectListItem { Text = path.Name + " - " + path.StepCount + " Steps", Value = path.Id.ToString() }); } return(PathSelectList); }
public async Task <bool> AddBookNameAsync(BiblePathsCoreDbContext context, string bibleId) { // Get BookName BookName = await BibleBook.GetBookNameAsync(context, bibleId, BookNumber); return(true); }
public async Task <QuizQuestion> GetNextQuizQuestionFromBookAsync(BiblePathsCoreDbContext context, string bibleId, int BookNumber) { QuizQuestion ReturnQuestion = new QuizQuestion(); BibleBook Book = new BibleBook(); int SelectedChapter = 0; try { Book = await context.BibleBooks.Where(B => B.BibleId == bibleId && B.BookNumber == BookNumber).FirstAsync(); } catch { // This is the couldn't find the book scenario. ReturnQuestion.QuestionSelected = false; return(ReturnQuestion); } // Ok we've got our Book... now which chapter? pick a random one Random rand = new Random(); if (Book.Chapters.HasValue == true) { SelectedChapter = rand.Next(Book.Chapters.Value) + 1; // Rand will return an int >= 0 and < Book.Chapters, so we add 1 since Chapters are 1 based. } else { // Somethings badly wrong with this Book it has not chapters ReturnQuestion.QuestionSelected = false; return(ReturnQuestion); } return(await GetNextQuizQuestionFromBookAndChapterAsync(context, bibleId, BookNumber, SelectedChapter)); }
public async Task <bool> CheckAPITokenAsync(BiblePathsCoreDbContext context, string Token) { // Find the most recent token for this user QuizQuestionStat TokenStat = new QuizQuestionStat(); try { TokenStat = await context.QuizQuestionStats.Where(T => T.QuizUserId == this.Id && T.EventType == (int)QuizQuestion.QuestionEventType.QuestionAPIToken) .OrderByDescending(T => T.EventWritten).Take(1).SingleAsync(); } catch { // We'll take any exceptions to indicate we couldn't find a Token return(false); } TimeSpan TimeSinceTokenCreated = (TimeSpan)(DateTime.Now - TokenStat.EventWritten); if (TimeSinceTokenCreated.TotalHours < 24) { string TokenString = TokenStat.EventData; if (TokenString.Trim() == Token.Trim()) { // this is the only success case. return(true); } } return(false); }
public async Task <bool> RegisterReadEventsAsync(BiblePathsCoreDbContext context, bool FullPathRead = false) { // there are two scenarios we should register events for // 1. If this is the second step in a path we register a Read, this avoids false reads for accidental clicks. // 2. If this is the final step in the path we register a Finished if ((Position > 14 && Position < 21) || FullPathRead) // by some fluke second step may be between 15 and 20... { if (Path == null) { context.Entry(this).Reference(s => s.Path).Load(); } _ = await Path.RegisterEventAsync(context, EventType.PathStarted, null); } if (this.FWStepId == 0 || FullPathRead) // this is the last step { if (Path == null) { context.Entry(this).Reference(s => s.Path).Load(); } _ = await Path.RegisterEventAsync(context, EventType.PathCompleted, null); // Now we need to increment Read Count... context.Attach(Path).State = EntityState.Modified; Path.Reads++; await context.SaveChangesAsync(); } return(true); }
public static async Task <BibleBook> GetBookAndChapterByNameAsync(BiblePathsCoreDbContext context, string BibleId, string BookName, int ChapterNum) { BibleBook PBEBook = new BibleBook(); try { PBEBook = await context.BibleBooks.Where(B => B.BibleId == BibleId && B.Name == BookName) .SingleAsync(); } catch { return(null); } // TODO: This is not ideal, we should be simply be deleting rather than soft deleting these // So that a simple ANY would work vs. having to retrieve all of these. List <QuizBookList> BookLists = await context.QuizBookLists .Include(L => L.QuizBookListBookMaps) .Where(L => L.IsDeleted == false) .ToListAsync(); await PBEBook.AddPBEBookPropertiesAsync(context, ChapterNum, null, BookLists); return(PBEBook); }
private async Task <bool> AddPrevNextChapters(BiblePathsCoreDbContext context, string BibleId) { PrevChapter = Chapter - 1; NextChapter = Chapter + 1; NextChapter = (await context.BibleChapters.Where(c => c.BibleId == BibleId && c.BookNumber == BookNumber && c.ChapterNumber == NextChapter).AnyAsync()) ? NextChapter : 0; return(true); }
public static async Task <IList <BibleBook> > GetPBEBooksAsync(BiblePathsCoreDbContext context, string BibleId) { IList <BibleBook> PBEBooks = await context.BibleBooks .Include(B => B.BibleChapters) .Where(B => B.BibleId == BibleId) .ToListAsync(); // Querying for Question counts for each Book/Chapter gets expensive let's grab all of them // and pass them around for counting. List <QuizQuestion> Questions = await context.QuizQuestions .Where(Q => (Q.BibleId == BibleId || Q.BibleId == null) && Q.IsDeleted == false) .ToListAsync(); // TODO: This is not ideal, we should be simply be deleting rather than soft deleting these // So that a simple ANY would work vs. having to retrieve all of these. List <QuizBookList> BookLists = await context.QuizBookLists .Include(L => L.QuizBookListBookMaps) .Where(L => L.IsDeleted == false) .ToListAsync(); foreach (BibleBook Book in PBEBooks) { await Book.AddPBEBookPropertiesAsync(context, null, Questions, BookLists); } return(PBEBooks); }
public async Task <bool> RedistributeStepsAsync(BiblePathsCoreDbContext context) { int DefaultInterval = 10; int NextPosition = 10; // Build a list of all steps in the path after "FromPosition", then iterate // Through this list and re-position the remaining nodes if necessary. try { List <PathNode> pathNodes = await context.PathNodes.Where(N => N.PathId == Id).OrderBy(L => L.Position).ToListAsync(); foreach (PathNode node in pathNodes) { if (node.Position != NextPosition) { context.Attach(node); node.Position = NextPosition; await context.SaveChangesAsync(); } NextPosition += DefaultInterval; } } catch { return(false); } return(true); }
public async Task <QuizQuestion> GetNextQuizQuestionFromBookListAsync(BiblePathsCoreDbContext context, string bibleId, int BookListId) { QuizQuestion ReturnQuestion = new QuizQuestion(); QuizBookList BookList = new QuizBookList(); int SelectedBookNumber = 0; try { BookList = await context.QuizBookLists.Include(L => L.QuizBookListBookMaps).Where(L => L.Id == BookListId).FirstAsync(); } catch { // This is the couldn't find BookList scenario, ReturnQuestion.QuestionSelected = false; return(ReturnQuestion); } // Ok we've got our BookList Now... so which Book? Random rand = new Random(); if (BookList.QuizBookListBookMaps.Count > 0) { List <QuizBookListBookMap> Books = BookList.QuizBookListBookMaps.ToList(); int BIndex = rand.Next(0, BookList.QuizBookListBookMaps.Count); // Rand will return an int >= 0 and < bookMaps.Count, which works with a zero based array right? SelectedBookNumber = Books[BIndex].BookNumber; } return(await GetNextQuizQuestionFromBookAsync(context, bibleId, SelectedBookNumber)); }
public async Task <List <BibleWordIndex> > GetVerseIndicesByWordAsync(BiblePathsCoreDbContext context, string BibleId, string KeyWord) { // To add a bit more random to this we'll randomize between ascending and descending. Random random = new Random(); int RandOrder = random.Next(0, 2); List <BibleWordIndex> WordReferences = new List <BibleWordIndex>(); if (RandOrder == 1) { WordReferences = await context.BibleWordIndices.Where(W => W.BibleId == BibleId && W.Word.Contains(KeyWord)) .OrderBy(W => W.RandomInt) .Take(25) .ToListAsync(); } else { WordReferences = await context.BibleWordIndices.Where(W => W.BibleId == BibleId && W.Word.Contains(KeyWord)) .OrderByDescending(W => W.RandomInt) .Take(25) .ToListAsync(); } return(WordReferences); }
public async Task <QuizQuestion> GetNextQuizQuestionAsync(BiblePathsCoreDbContext context, string bibleId) { QuizQuestion ReturnQuestion = new QuizQuestion { QuestionSelected = false }; // Template Scenario if (PredefinedQuiz > 0) { ReturnQuestion = await GetNextQuizQuestionFromTemplateAsync(context, bibleId); return(ReturnQuestion); } // BookList Scenario if (BookNumber >= Bible.MinBookListID) { ReturnQuestion = await GetNextQuizQuestionFromBookListAsync(context, bibleId, BookNumber); return(ReturnQuestion); } // Book Scenario if (BookNumber > 0 && BookNumber < Bible.MinBookListID) { ReturnQuestion = await GetNextQuizQuestionFromBookAsync(context, bibleId, BookNumber); return(ReturnQuestion); } return(ReturnQuestion); }
// PopulatePBEQuestionAndBookInfoAsync is expensive as it builds a new PBE Book everytime, we don't want to call this often. public async Task <bool> PopulatePBEQuestionAndBookInfoAsync(BiblePathsCoreDbContext context) { // BibleId may not be set on every question, particularly old ones, so default it. if (BibleId == null) { BibleId = Bible.DefaultPBEBibleId; } BibleBook PBEBook = await BibleBook.GetPBEBookAndChapterAsync(context, BibleId, BookNumber, Chapter); if (PBEBook == null) { return(false); } if (Chapter == Bible.CommentaryChapter) { IsCommentaryQuestion = true; BookName = PBEBook.CommentaryTitle; } else { IsCommentaryQuestion = false; BookName = PBEBook.Name; } PBEQuestion = GetPBEQuestionText(); TimeLimit = (Points * 5) + 20; return(true); }
public async Task <bool> GetRelatedPathsAsync(BiblePathsCoreDbContext context) { InRelatedPaths = false; List <Path> relatedPaths = new List <Path>(); // Return all PathNodes or Steps that contain this verse. // EF CORE 5 Will contain Filtered Includes we can simplify when it releases. List <PathNode> RelatedSteps = await context.PathNodes .Include(N => N.Path) .Where(N => N.BookNumber == BookNumber && N.Chapter == Chapter && N.StartVerse <= Verse && N.EndVerse >= Verse) .ToListAsync(); foreach (PathNode relatedStep in RelatedSteps) { if (relatedStep.Path.IsDeleted == false && relatedStep.Path.IsPublished == true) { InRelatedPaths = true; // We only add a path object on the EndVerse, and only if it hasn'be already been added. if (relatedStep.EndVerse == Verse && relatedPaths.Contains(relatedStep.Path) == false) { _ = await relatedStep.Path.AddCalculatedPropertiesAsync(context); relatedPaths.Add(relatedStep.Path); } } } RelatedPaths = relatedPaths; return(true); }
public async Task <bool> AddQuizPropertiesAsync(BiblePathsCoreDbContext context, string bibleId) { bool retval = true; // If we're using a Template we'll use that name, otherwise well use // a Book or Booklist name. if (PredefinedQuiz > 0) // Template Scenario { PredefinedQuiz Template = await context.PredefinedQuizzes.FindAsync(PredefinedQuiz); if (Template != null) { BookOrTemplateName = Template.QuizName; } else { BookOrTemplateName = "Unknown"; } } else { BookOrTemplateName = await BibleBook.GetBookorBookListNameAsync(context, bibleId, BookNumber); } QuestionNumber = QuestionsAsked + 1; CalculateQuizStats(); return(retval); }
public async Task <bool> ValidateBookChapterAsync(BiblePathsCoreDbContext context, string BibleId) { if (await context.BibleVerses.Where(v => v.BibleId == BibleId && v.BookNumber == BookNumber && v.Chapter == Chapter).AnyAsync()) { return(true); } return(false); }
public async Task <bool> AddCalculatedPropertiesAsync(BiblePathsCoreDbContext context) { _ = await AddFirstStepIdAsync(context); LengthInMinutes = GetLengthInMinutesString(); PathLink = "https://www.BiblePaths.Net/Paths/" + Name; return(true); }
public async Task <bool> AddLegalNoteAsync(BiblePathsCoreDbContext context, string BibleId) { Bible Bible = await context.Bibles.FindAsync(BibleId); Bible.HydrateBible(); LegalNote = Bible.LegalNote; return(true); }
public static async Task <bool> ListNameAlreadyExistsStaticAsync(BiblePathsCoreDbContext context, string CheckName) { if (await context.QuizBookLists.Where(l => l.BookListName.ToLower() == CheckName.ToLower()).AnyAsync()) { return(true); } return(false); }
public async Task <bool> AddBookNameAsync(BiblePathsCoreDbContext context, string bibleId) { // Get BookName BibleBook Book = await context.BibleBooks.Where(B => B.BibleId == bibleId && B.BookNumber == BookNumber).FirstAsync(); BookName = Book.Name; return(true); }
public async Task <List <SelectListItem> > GetKeyWordSelectListAsync(BiblePathsCoreDbContext context, PathNode CurrentStep) { List <SelectListItem> KeyWordSelectList = new List <SelectListItem>(); // Find all the unique words in our Curent Step Hashtable UniqueWords = new Hashtable(); StringBuilder StepText = new StringBuilder(); foreach (BibleVerse Verse in CurrentStep.Verses) { StepText.Append(Verse.Text + " "); } String text = StepText.ToString(); var punctuation = text.Where(Char.IsPunctuation).Distinct().ToArray(); var words = text.Split().Select(x => x.Trim(punctuation)); foreach (string word in words) { if (word.Length > 2 && !UniqueWords.ContainsKey(word)) { int occurs = 0; try { BibleNoiseWord noiseWord = await context.BibleNoiseWords.Where(w => w.NoiseWord == word).FirstAsync(); if (noiseWord.IsNoise == true) { occurs = 0; } else { occurs = noiseWord.Occurs; } } catch { // Assume we couldn't find the word in our NoiseWord List occurs = 0; } UniqueWords.Add(word, occurs); } } // Now iterate our HasthTable adding only non-noise words // that occur more than 10 times in the whole bible foreach (string UniqueWord in UniqueWords.Keys) { if ((int)UniqueWords[UniqueWord] > 10) { KeyWordSelectList.Add(new SelectListItem { Text = UniqueWord, Value = UniqueWord }); } } return(KeyWordSelectList); }
public async Task <bool> AddGenericStepPropertiesAsync(BiblePathsCoreDbContext context, string BibleId) { _ = await AddBookNameAsync(context, BibleId); _ = await AddLegalNoteAsync(context, BibleId); _ = await AddPrevNextChapters(context, BibleId); return(true); }
// This one is expensive we shouldn't use this one if we can avoid. public async Task <int> GetQuestionCountAsync(BiblePathsCoreDbContext context) { return(await context.QuizQuestions .Where(Q => Q.BookNumber == BookNumber && Q.Chapter == Chapter && Q.EndVerse == Verse && (Q.BibleId == BibleId || Q.BibleId == null) && Q.IsDeleted == false) .CountAsync()); }
public async Task <int> GetPathVerseCountAsync(BiblePathsCoreDbContext context) { int retVal = 0; List <PathNode> pathNodes = await context.PathNodes.Where(N => N.PathId == Id).ToListAsync(); foreach (PathNode node in pathNodes) { retVal += (node.EndVerse - node.StartVerse + 1); } return(retVal); }
public async Task <bool> AddPathStepPropertiesAsync(BiblePathsCoreDbContext context) { // Calculate Step Number StepNumber = (int)Position / 10; // Add Fwd and Back Steps _ = await AddFwdBackStepAsync(context); // Add PathName and StepCount _ = await AddPathPropertiesAsync(context); return(true); }
public async Task <List <BibleVerse> > GetPathVersesAsync(BiblePathsCoreDbContext context, String BibleId) { List <BibleVerse> returnVerses = new List <BibleVerse>(); List <PathNode> pathNodes = await context.PathNodes.Where(N => N.PathId == Id).OrderBy(P => P.Position).ToListAsync(); foreach (PathNode node in pathNodes) { returnVerses.AddRange(await context.BibleVerses .Where(v => v.BibleId == BibleId && v.BookNumber == node.BookNumber && v.Chapter == node.Chapter && v.Verse >= node.StartVerse && v.Verse <= node.EndVerse) .ToListAsync()); } return(returnVerses); }
public static async Task <string> GetBookorBookListNameAsync(BiblePathsCoreDbContext context, string bibleId, int BookNumber) { // BookList scenario if (BookNumber >= Bible.MinBookListID) { return((await context.QuizBookLists.Where(L => L.Id == BookNumber).Select(L => new { L.BookListName }).FirstAsync()).BookListName); } else { // Get BookName return(await BibleBook.GetBookNameAsync(context, bibleId, BookNumber)); } }
public async Task <string> GetValidBibleIdAsync(BiblePathsCoreDbContext context, string BibleId) { string RetVal = Bible.DefaultPBEBibleId; if (BibleId != null) { if (await context.Bibles.Where(B => B.Id == BibleId).AnyAsync()) { RetVal = BibleId; } } return(RetVal); }
public bool IsInBooklist(BiblePathsCoreDbContext context, List <QuizBookList> BookLists) { // We need to determine whether any of the non-deleted BookLists contains our Book. foreach (QuizBookList list in BookLists) { if (list.QuizBookListBookMaps.Where(B => B.BookNumber == BookNumber).Any()) { return(true); } } return(false); }