diff --git a/app/db/src/app/common/bible-reference.spec.ts b/app/db/src/app/common/bible-reference.spec.ts index 69abffb5..85197baf 100644 --- a/app/db/src/app/common/bible-reference.spec.ts +++ b/app/db/src/app/common/bible-reference.spec.ts @@ -1,6 +1,11 @@ -import { BibleReference } from './bible-reference'; +import { BibleReference, Overlap } from './bible-reference'; describe('Reference', () => { + it('Should parse the reference: Gen 1-2', () => { + const ref = new BibleReference('Gen 1-2').toString(); + expect(ref).toBe('Genesis 1:1 - 2:25'); + }); + it('Should parse the reference: Gen 1:1', () => { const ref = new BibleReference('Gen 1:1').toString(); expect(ref).toBe('Genesis 1:1'); @@ -11,11 +16,6 @@ describe('Reference', () => { expect(ref).toBe('Genesis 1:1 - 11'); }); - it('Should parse the reference: Gen 1-2', () => { - const ref = new BibleReference('Gen 1-2').toString(); - expect(ref).toBe('Genesis 1:1 - 2:*'); - }); - it('Should parse the reference: John 3:16', () => { const ref = new BibleReference('John 3:16').toString(); expect(ref).toBe('John 3:16'); @@ -23,7 +23,7 @@ describe('Reference', () => { it('Should parse the reference: John 3-6', () => { const ref = new BibleReference('Jn 3-6').toString(); - expect(ref).toBe('John 3:1 - 6:*'); + expect(ref).toBe('John 3:1 - 6:71'); }); it('Should parse the reference: 1 Corinthians 3:5-6:5', () => { @@ -266,17 +266,8 @@ describe('Reference', () => { it('Should parse the references: ' + bk.abbr, () => { const book = BibleReference.parseBook(bk.abbr); expect(book.name).toBe(bk.actual); - for (let i = 1; i <= book.lastChapter; i++) { - expect(new BibleReference(bk.abbr + ' ' + i).toString()).toBe( - bk.actual + ' ' + i + ':1 - *' - ); - } for (let i = 1; i < book.lastChapter; i++) { - expect( - new BibleReference(bk.abbr + ' ' + i + '-' + (i + 1)).toString() - ).toBe(bk.actual + ' ' + i + ':1 - ' + (i + 1) + ':*'); - expect( new BibleReference( bk.abbr + ' ' + i + ':3-' + (i + 1) + ':6' @@ -304,3 +295,33 @@ describe('Reference', () => { }); } }); + +describe('Reference Overlap Detection', () => { + // it('Different books dont overlap', () => { + // const leftRf = new BibleReference('Gen 1:1-5'); + // const rightRef = new BibleReference('Exodus 1:3-7'); + // + // expect(BibleReference.overlap(leftRf, rightRef)).toBe(Overlap.None); + // }); + // + // it('Different chapters dont overlap', () => { + // const leftRef = new BibleReference('Gen 1:1-5'); + // const rightRef = new BibleReference('Gen 2:1-5'); + // + // expect(BibleReference.overlap(leftRef, rightRef)).toBe(Overlap.None); + // }); + // + // it('Detects Left intersects the front of Right', () => { + // const leftRef = new BibleReference('Gen 1:1-5'); + // const rightRef = new BibleReference('Gen 1:4-5'); + // + // expect(BibleReference.overlap(leftRef, rightRef)).toBe(Overlap.Intersect); + // }); + + it('Detects Right intersects the front of left', () => { + const leftRef = new BibleReference('Gen 1:7-10'); + const rightRef = new BibleReference('Gen 1:5-8'); + + expect(BibleReference.overlap(leftRef, rightRef)).toBe(Overlap.Intersect); + }); +}); \ No newline at end of file diff --git a/app/db/src/app/common/bible-reference.ts b/app/db/src/app/common/bible-reference.ts index be95c56d..2f21e35c 100644 --- a/app/db/src/app/common/bible-reference.ts +++ b/app/db/src/app/common/bible-reference.ts @@ -3,6 +3,8 @@ // Jason@walljm.com // www.walljm.com // Jeremy@marzhillstudios.com // jeremy.marzhillstudios.com +import { NONE_TYPE } from '@angular/compiler'; + class StringUtils { public static trim(str: string): string { return str.replace(/^\s+|\s+$/g, ''); @@ -17,23 +19,29 @@ class StringUtils { } } +export enum Overlap { + Intersect, + Subset, + None, +} + export class BibleReference { constructor(reference: string) { this.Section = { book: null, start: { - chapter: '', - verse: '', + chapter: 0, + verse: 0, }, end: { - chapter: '', - verse: '', + chapter: 0, + verse: 0, }, }; this.ref = reference.toLowerCase().trim(); this.parseReference(); - if (this.Section.end.chapter === '') { + if (this.Section.end.chapter === 0) { this.Section.end.chapter = this.Section.start.chapter; } if ( @@ -42,11 +50,11 @@ export class BibleReference { ) { this.Section.end.verse = this.Section.start.verse; } - if (this.Section.start.verse === '') { - this.Section.start.verse = '1'; + if (this.Section.start.verse === 0) { + this.Section.start.verse = 1; } - if (this.Section.end.verse === '') { - this.Section.end.verse = '*'; + if (this.Section.end.verse === 0) { + this.Section.end.verse = this.Section.book.chapters[this.Section.end.chapter]; } } @@ -1866,9 +1874,9 @@ export class BibleReference { // get the starting book, chapter, verse let ref = section.book.name .concat(' ') - .concat(section.start.chapter) + .concat(section.start.chapter.toString()) .concat(':') - .concat(section.start.verse); + .concat(section.start.verse.toString()); if ( section.start.chapter === section.end.chapter && @@ -1881,14 +1889,14 @@ export class BibleReference { section.start.chapter === section.end.chapter && section.start.verse !== section.end.verse ) { - return ref.concat(' - ').concat(section.end.verse); + return ref.concat(' - ').concat(section.end.verse.toString()); } ref = ref.concat(' - '); - ref = ref.concat(section.end.chapter).concat(':'); + ref = ref.concat(section.end.chapter.toString()).concat(':'); - return ref.concat(section.end.verse); + return ref.concat(section.end.verse.toString()); } public static bookName(booknum: number): Book { @@ -1909,22 +1917,54 @@ export class BibleReference { return new BibleReference(`${book} ${keyArray[1]}:${keyArray[2]}`); } + public static overlap(leftRef: BibleReference, rightRef: BibleReference): Overlap { + if (leftRef.Section.book !== rightRef.Section.book) { + // either of the above means we are not overlapping + console.log("Not same book"); + return Overlap.None; + } + + if (leftRef.Section.end.chapter === rightRef.Section.start.chapter) { + console.log("Same chapter"); + console.log("Left Section", leftRef.Section); + console.log("Right Section", rightRef.Section); + if ((leftRef.Section.end.verse > rightRef.Section.start.verse) + || (rightRef.Section.end.verse > leftRef.Section.start.verse)) { + console.log("Overlap detected"); + return Overlap.Intersect; + } + } + console.log("Default case"); + return Overlap.None; + } + + public static mergeReference(ref1: BibleReference, ref2: BibleReference) { + // eliminate based on book first. + if (ref1.Section.book != ref2.Section.book) { + // either of the above mean we are not overlapping + return null; + } + // detect overlaps from end + // detect embedded + return null; + } + private parseReference() { this.parseKeyReference(); if (this.ref.length === 0) { return; } this.parseBook(false); - this.parseFirstNum(false); + this.parseChapter(false); const foundFirstVerse = this.ref.search(/:.*-/) !== -1; - this.maybeParseSecondNum(false); + this.maybeParseVerse(false); this.maybeParseRangeSep(); const foundSecondBook = this.ref.search(/\w\s+\d/i) !== -1; this.maybeParseBook(true); - this.maybeParseFirstNumOrVerse(foundSecondBook, foundFirstVerse, true); - this.maybeParseSecondNum(true); + this.maybeParseChapterOrVerse(foundSecondBook, foundFirstVerse, true); + this.maybeParseVerse(true); } // we're trying to parse references in the form of 41:2:3 @@ -1937,12 +1977,12 @@ export class BibleReference { this.Section.book = fbook; const fch = parts[1]; - this.Section.end.chapter = fch; - this.Section.start.chapter = fch; + this.Section.end.chapter = parseInt(fch, 10); + this.Section.start.chapter = parseInt(fch, 10); const fv = parts[2]; - this.Section.end.verse = fv; - this.Section.start.verse = fv; + this.Section.end.verse = parseInt(fv, 10); + this.Section.start.verse = parseInt(fv, 10); this.ref = ''; } @@ -1959,7 +1999,7 @@ export class BibleReference { this.Section.book = BibleReference.parseBook(fbook); } - private parseFirstNum(isEnd: boolean) { + private parseChapter(isEnd: boolean) { let thing = this.Section.start; if (isEnd) { thing = this.Section.end; @@ -1967,27 +2007,29 @@ export class BibleReference { this.ref = StringUtils.ltrim(this.ref); let found = false; + let chapter = ''; for (let i = 0; i <= this.ref.length; i++) { const c = this.ref.charAt(i); // Grab characters until we hit a non digit. if ('0'.charAt(0) <= c && c <= '9'.charAt(0)) { found = true; - thing.chapter = thing.chapter.concat(c); + chapter = chapter.concat(c); } else { // if the chapter is longer than 3 digits it's an error - if (thing.chapter.length > 3) { - this.errAcc = 'Chapter too long"' + thing.chapter + '".'; + if (chapter.length > 3) { + this.errAcc = 'Chapter too long"' + chapter + '".'; return; } else if (!found) { this.errAcc = 'No chapter found' + this.ref; } this.ref = this.ref.slice(i); + thing.chapter = parseInt(chapter, 10); return; } } } - private parseSecondNum(skipColon?: boolean, isEnd?: boolean) { + private parseVerse(skipColon?: boolean, isEnd?: boolean) { let thing = this.Section.start; if (isEnd) { thing = this.Section.end; @@ -2001,21 +2043,23 @@ export class BibleReference { this.ref = this.ref.slice(1); } this.ref = StringUtils.ltrim(this.ref.toLowerCase()); + let verse = ''; if (this.ref[0] === '*') { - thing.verse = '*'; + thing.verse = 0; this.ref = this.ref.slice(1); return; } for (let i = 0; i <= this.ref.length; i++) { const c = this.ref.charAt(i); if ('0'.charAt(0) <= c && c <= '9'.charAt(0)) { - thing.verse = thing.verse.concat(c); + verse = verse.concat(c); } else { - if (thing.verse.length > 3) { + if (verse.length > 3) { this.errAcc = 'Verse too long "' + thing.verse + '".'; return; } this.ref = this.ref.slice(i); + thing.verse = verse === '' ? 0 : parseInt(verse, 10); return; } } @@ -2029,13 +2073,13 @@ export class BibleReference { }); } - private maybeParseSecondNum(isEnd?: boolean) { + private maybeParseVerse(isEnd?: boolean) { return this.maybeDo(() => { - this.parseSecondNum(false, isEnd); + this.parseVerse(false, isEnd); }); } - private maybeParseFirstNumOrVerse( + private maybeParseChapterOrVerse( foundSecondBook: boolean, foundFirstVerse: boolean, isEnd: boolean @@ -2043,9 +2087,9 @@ export class BibleReference { const self = this; return this.maybeDo(() => { if (self.ref.search(/:/) !== -1 || foundSecondBook || !foundFirstVerse) { - self.parseFirstNum(isEnd); + self.parseChapter(isEnd); } - self.parseSecondNum(true, isEnd); + self.parseVerse(true, isEnd); }); } @@ -2088,6 +2132,6 @@ export interface Section { } export interface Location { - chapter: string; - verse: string; + chapter: number; + verse: number; } diff --git a/app/db/src/app/services/app.service.ts b/app/db/src/app/services/app.service.ts index 58c1b749..8dfaa6ac 100644 --- a/app/db/src/app/services/app.service.ts +++ b/app/db/src/app/services/app.service.ts @@ -74,52 +74,52 @@ const initialState: AppState = { type AppAction = | { - type: 'GET_SAVED_PAGE'; - pageId: string; - } + type: 'GET_SAVED_PAGE'; + pageId: string; + } | { - type: 'UPDATE_SAVED_PAGES'; - savedPages: SavedPage[]; - } + type: 'UPDATE_SAVED_PAGES'; + savedPages: SavedPage[]; + } | { - type: 'ADD_CARD_TO_SAVED_PAGE'; - card: CardItem; - pageId: string; - } + type: 'ADD_CARD_TO_SAVED_PAGE'; + card: CardItem; + pageId: string; + } | { - type: 'ADD_CARD'; - card: CardItem; - nextToItem: CardItem; - } + type: 'ADD_CARD'; + card: CardItem; + nextToItem: CardItem; + } | { - type: 'UPDATE_CARD'; - newCard: CardItem; - oldCard: CardItem; - } + type: 'UPDATE_CARD'; + newCard: CardItem; + oldCard: CardItem; + } | { - type: 'REMOVE_CARD'; - card: CardItem; - } + type: 'REMOVE_CARD'; + card: CardItem; + } | { - type: 'UPDATE_ERROR'; - error: Error; - } + type: 'UPDATE_ERROR'; + error: Error; + } | { - type: 'UPDATE_FONT_SIZE'; - size: number; - } + type: 'UPDATE_FONT_SIZE'; + size: number; + } | { - type: 'UPDATE_FONT_FAMILY'; - cardFont: string; - } + type: 'UPDATE_FONT_FAMILY'; + cardFont: string; + } | { - type: 'UPDATE_AUTOCOMPLETE'; - words: string[]; - } + type: 'UPDATE_AUTOCOMPLETE'; + words: string[]; + } | { - type: 'UPDATE_DISPLAY_SETTINGS'; - settings: DisplaySettings; - }; + type: 'UPDATE_DISPLAY_SETTINGS'; + settings: DisplaySettings; + }; function reducer(state: AppState, action: AppAction): AppState { // somtimes the state is null. lets not complain if that happens. @@ -762,17 +762,7 @@ export class AppService extends createStateService(reducer, initialState) { // figure out the start verse. if (j === 0) { - if (section.start.verse.indexOf('*') !== -1) { - // you sometimes use this as a shortcut to the last verse - // replace the * with the last verse - // e.g jn 1:* - 3:4 - - // update the section and the ref. - section.start.verse = chapters[j].vss.length.toString(); - result.ref = BibleReference.toString(section); - } else { - start = parseInt(section.start.verse, 10); - } + start = section.start.verse; } else { start = 1; } @@ -786,7 +776,7 @@ export class AppService extends createStateService(reducer, initialState) { // get the verses requested. const tvs = chapters[j].vss.length; - if (end === '*' || parseInt(end, 10) > tvs) { + if (end === '*' || end > tvs) { end = tvs; }