Better merging logic handle the cross chapter case

This commit is contained in:
Jeremy Wall 2020-08-07 21:16:22 -04:00
parent 80be335d2b
commit 8ed0da3c1d
2 changed files with 120 additions and 22 deletions

View File

@ -353,4 +353,58 @@ describe('Reference Overlap Detection', () => {
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Subset)).toEqual(new BibleReference('Gen 1:1-10'));
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.None)).toBeNull();
});
it('Detects Left chapter Overlaps right chapter', () => {
const leftRef = new BibleReference('Gen 1:1-2:5');
const rightRef = new BibleReference('Gen 2:1-10');
expect(BibleReference.overlap(leftRef, rightRef)).toBe(Overlap.Intersect);
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Intersect)).toEqual(new BibleReference('Gen 1:1-2:10'));
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Subset)).toBeNull();
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.None)).toBeNull();
});
it('Detects Right chapter Overlaps Left chapter', () => {
const leftRef = new BibleReference('Gen 2:1-10');
const rightRef = new BibleReference('Gen 1:1-2:5');
expect(BibleReference.overlap(leftRef, rightRef)).toBe(Overlap.Intersect);
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Intersect)).toEqual(new BibleReference('Gen 1:1-2:10'));
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Subset)).toBeNull();
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.None)).toBeNull();
});
it('Detects discontinuous chapters', () => {
const leftRef = new BibleReference('Gen 2:6-10');
const rightRef = new BibleReference('Gen 1:1-2:5');
expect(BibleReference.overlap(leftRef, rightRef)).toBe(Overlap.None);
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Intersect)).toBeNull();
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Subset)).toBeNull();
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.None)).toBeNull();
});
it('Detects left side embedded chapters', () => {
const leftRef = new BibleReference('Gen 1:1-2:5');
const rightRef = new BibleReference('Gen 1:1-3:1');
expect(BibleReference.overlap(leftRef, rightRef)).toBe(Overlap.Subset);
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Intersect).toString()).toEqual(
new BibleReference('Gen 1:1-3:1').toString()
);
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Subset)).toEqual(new BibleReference('Gen 1:1-3:1'));
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.None)).toBeNull();
});
it('Detects right side embedded chapters', () => {
const leftRef = new BibleReference('Gen 1:1-3:1');
const rightRef = new BibleReference('Gen 1:1-2:5');
expect(BibleReference.overlap(leftRef, rightRef)).toBe(Overlap.Subset);
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Intersect).toString()).toEqual(
new BibleReference('Gen 1:1-3:1').toString()
);
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.Subset)).toEqual(new BibleReference('Gen 1:1-3:1'));
expect(BibleReference.mergeReference(leftRef, rightRef, Overlap.None)).toBeNull();
});
});

View File

@ -1885,6 +1885,13 @@ export class BibleReference {
return this.Books[booknum];
}
public static locationToIndex(book: number, loc: Location): number {
let ref = book * 100000000;
ref = ref + loc.chapter * 10000;
ref = ref + loc.verse;
return ref;
}
static formatReferenceKey(
book: number | string,
chapter: number | string,
@ -1899,29 +1906,40 @@ export class BibleReference {
return new BibleReference(`${book} ${keyArray[1]}:${keyArray[2]}`);
}
static overlap(leftRef: BibleReference, rightRef: BibleReference): Overlap {
public static overlap(
leftRef: BibleReference,
rightRef: BibleReference
): Overlap {
if (leftRef.section.book !== rightRef.section.book) {
// either of the above means we are not overlapping
return Overlap.None;
}
if (leftRef.section.start.chapter === rightRef.section.end.chapter) {
if (leftRef.section.start.verse >= rightRef.section.start.verse) {
if (leftRef.section.end.verse <= rightRef.section.end.verse) {
return Overlap.Subset;
}
return Overlap.Intersect;
} else if (rightRef.section.start.verse > leftRef.section.start.verse) {
if (rightRef.section.end.verse < leftRef.section.end.verse) {
return Overlap.Subset;
}
return Overlap.Intersect;
}
let leftStartIndex = leftRef.startIndex();
let leftEndIndex = leftRef.endIndex();
let rightStartIndex = rightRef.startIndex();
let rightEndIndex = rightRef.endIndex();
if (
// left is subset of right
(leftStartIndex >= rightStartIndex && leftEndIndex <= rightEndIndex) ||
// right is subset of left
(rightStartIndex >= leftStartIndex && rightEndIndex <= leftEndIndex)
) {
return Overlap.Subset;
}
if (
// left overlaps the right
(leftEndIndex >= rightStartIndex && leftEndIndex <= rightEndIndex) ||
// right overlaps the left
(rightEndIndex >= leftStartIndex && rightEndIndex <= leftEndIndex)
) {
return Overlap.Intersect;
}
return Overlap.None;
}
static mergeReference(
public static mergeReference(
ref1: BibleReference,
ref2: BibleReference,
strategy: Overlap
@ -1950,18 +1968,30 @@ export class BibleReference {
ref1.section.start.chapter <= ref2.section.start.chapter
? ref1.section.start.chapter
: ref2.section.start.chapter;
mergedRef.section.start.verse =
ref1.section.start.verse <= ref2.section.start.verse
? ref1.section.start.verse
: ref2.section.start.verse;
if (ref1.section.start.chapter < ref2.section.start.chapter) {
mergedRef.section.start.verse = ref1.section.start.verse;
} else if (ref2.section.start.chapter < ref1.section.start.chapter) {
mergedRef.section.start.verse = ref2.section.start.verse;
} else {
mergedRef.section.start.verse =
ref1.section.start.verse <= ref2.section.start.verse
? ref1.section.start.verse
: ref2.section.start.verse;
}
mergedRef.section.end.chapter =
ref1.section.end.chapter >= ref2.section.end.chapter
? ref1.section.end.chapter
: ref2.section.end.chapter;
mergedRef.section.end.verse =
ref1.section.end.verse >= ref2.section.end.verse
? ref1.section.end.verse
: ref2.section.end.verse;
if (ref1.section.end.chapter > ref2.section.end.chapter) {
mergedRef.section.end.verse = ref1.section.end.verse;
} else if (ref2.section.end.chapter > ref1.section.end.chapter) {
mergedRef.section.end.verse = ref2.section.end.verse;
} else {
mergedRef.section.end.verse =
ref1.section.end.verse >= ref2.section.end.verse
? ref1.section.end.verse
: ref2.section.end.verse;
}
return mergedRef;
}
@ -2136,6 +2166,20 @@ export class BibleReference {
// get the starting book, chapter, verse
return BibleReference.toString(this.section);
}
public startIndex(): Number {
return BibleReference.locationToIndex(
this.section.book.bookNumber,
this.section.start
);
}
public endIndex(): Number {
return BibleReference.locationToIndex(
this.section.book.bookNumber,
this.section.end
);
}
}
class StringUtils {