Snapshot of a couple things.

Fixed some parsing bugs with tests.
The beginnings of reference overlap detection.
This commit is contained in:
Jeremy Wall 2020-08-06 22:11:42 -04:00
parent eb862a580a
commit f537f515f5
3 changed files with 156 additions and 101 deletions

View File

@ -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);
});
});

View File

@ -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;
}

View File

@ -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;
}