Skip to content

Commit f0dbd1d

Browse files
committed
Verbose scheme output for VersificationDetector
When passing the system property 'versificationdetector.verboseschemes' with either 'all' or a comma separated list of schemes as value, print more details about a versification match (of this schema). For normal versification detector, print a list of all verses that are missing or extra. For versification counts detector, print number of chapters and verses for every book included.
1 parent 33379bc commit f0dbd1d

File tree

2 files changed

+71
-10
lines changed

2 files changed

+71
-10
lines changed

biblemulticonverter/src/main/java/biblemulticonverter/tools/AbstractVersificationDetector.java

+54-6
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,25 @@
55
import java.util.Arrays;
66
import java.util.BitSet;
77
import java.util.Collection;
8+
import java.util.Comparator;
9+
import java.util.EnumMap;
810
import java.util.EnumSet;
11+
import java.util.HashMap;
912
import java.util.HashSet;
1013
import java.util.List;
1114
import java.util.Map;
15+
import java.util.Map.Entry;
1216
import java.util.Set;
17+
import java.util.regex.Matcher;
18+
import java.util.regex.Pattern;
1319

1420
import biblemulticonverter.data.Bible;
1521
import biblemulticonverter.data.Book;
1622
import biblemulticonverter.data.BookID;
1723
import biblemulticonverter.data.Chapter;
1824
import biblemulticonverter.data.FormattedText;
1925
import biblemulticonverter.data.FormattedText.Visitor;
26+
import biblemulticonverter.data.Utils;
2027
import biblemulticonverter.data.Verse;
2128
import biblemulticonverter.data.VerseRange;
2229
import biblemulticonverter.data.VirtualVerse;
@@ -32,13 +39,15 @@ public void doExport(Bible bible, String... exportArgs) throws Exception {
3239
Set<String> totalVerses = new HashSet<String>();
3340
boolean includeXref = exportArgs.length > 0 && exportArgs[0].equals("-xref");
3441
Set<BookID> usedBooks = EnumSet.noneOf(BookID.class);
42+
Map<BookID,String> bookAbbrMap = new EnumMap<>(BookID.class);
3543
XrefCountVisitor xcv = includeXref ? new XrefCountVisitor(schemes, totalVerses, usedBooks) : null;
3644
int usedArgCount = (includeXref ? 1 : 0);
3745
boolean limitBooks = exportArgs.length > usedArgCount && exportArgs[usedArgCount].equals("-limitBooks");
3846

3947
// fill missing verses
4048
for (Book book : bible.getBooks()) {
4149
usedBooks.add(book.getId());
50+
bookAbbrMap.put(book.getId(), book.getAbbr());
4251
for (int cc = 0; cc < book.getChapters().size(); cc++) {
4352
Chapter chapter = book.getChapters().get(cc);
4453
if (includeXref && chapter.getProlog() != null) {
@@ -76,13 +85,14 @@ public void doExport(Bible bible, String... exportArgs) throws Exception {
7685

7786
// print them
7887
System.out.print("Best match: ");
79-
int totalVerseCount = totalVerses.size();
80-
printScheme(schemes[0], totalVerseCount);
88+
String verboseSchemasProperty = System.getProperty("versificationdetector.verboseschemes", "");
89+
Set<String> verboseSchemes = verboseSchemasProperty == null ? null : new HashSet<>(Arrays.asList(verboseSchemasProperty.split(", *")));
90+
printScheme(schemes[0], totalVerses, verboseSchemes, bookAbbrMap);
8191

8292
System.out.println();
8393
System.out.println("Other options:");
8494
for (int i = 1; i < Math.min(11, schemes.length); i++) {
85-
printScheme(schemes[i], totalVerseCount);
95+
printScheme(schemes[i], totalVerses, verboseSchemes, bookAbbrMap);
8696
if (schemes[i].missingChapters.size() > schemes[0].missingChapters.size() + 2 ||
8797
schemes[i].missingVerses.size() > schemes[0].missingVerses.size() + 5)
8898
break;
@@ -96,7 +106,7 @@ public void doExport(Bible bible, String... exportArgs) throws Exception {
96106
boolean found = false;
97107
for (VersificationScheme scheme : schemes) {
98108
if (scheme.getName().equals(exportArgs[i])) {
99-
printScheme(scheme, totalVerseCount);
109+
printScheme(scheme, totalVerses, verboseSchemes, bookAbbrMap);
100110
found = true;
101111
break;
102112
}
@@ -134,13 +144,51 @@ protected boolean useTitleAsVerseZero() {
134144
return false;
135145
}
136146

137-
private void printScheme(VersificationScheme scheme, int totalVerseCount) {
147+
private void printScheme(VersificationScheme scheme, Set<String> totalVerses, Set<String> verboseSchemes, Map<BookID, String> bookAbbrMap) {
138148
if (scheme.getMissingChapters().size() > 0)
139149
System.out.println(scheme.getName() + " (Missing chapters+verses: " + scheme.getMissingChapters().size() + "+" + scheme.getMissingVerses().size() + " " + scheme.getMissingChapters() + " " + scheme.getMissingVerses());
140150
else if (scheme.getMissingVerses().size() > 0)
141151
System.out.println(scheme.getName() + " (Missing verses: " + scheme.getMissingVerses().size() + " " + scheme.getMissingVerses() + ")");
142152
else
143-
System.out.println(scheme.getName() + " (All verses covered, and " + (scheme.getVerseCount() - totalVerseCount) + " more)");
153+
System.out.println(scheme.getName() + " (All verses covered, and " + (scheme.getVerseCount() - totalVerses.size()) + " more)");
154+
if (verboseSchemes != null && (verboseSchemes.contains(scheme.getName()) || verboseSchemes.contains("all"))) {
155+
Set<String> coveredVerses = new HashSet<>();
156+
for (Entry<BookID, BitSet[]> entry : scheme.coveredBooks.entrySet()) {
157+
String bookAbbr = bookAbbrMap.getOrDefault(entry.getKey(), entry.getKey().getOsisID());
158+
for (int cnum = 1; cnum <= entry.getValue().length; cnum++) {
159+
BitSet verses = entry.getValue()[cnum - 1];
160+
for (int vnum = verses.nextSetBit(0); vnum != -1; vnum = verses.nextSetBit(vnum + 1)) {
161+
coveredVerses.add(bookAbbr + " " + cnum + ":" + vnum);
162+
}
163+
}
164+
}
165+
List<String> bookAbbrOrder = new ArrayList<>(bookAbbrMap.values());
166+
printVerbose("\t-", totalVerses, coveredVerses, bookAbbrOrder);
167+
printVerbose("\t+", coveredVerses, totalVerses, bookAbbrOrder);
168+
}
169+
}
170+
171+
private void printVerbose(String prefix, Set<String> verseList, Set<String> removeList, List<String> bookAbbrOrder) {
172+
List<String> list = new ArrayList<>(verseList);
173+
list.removeAll(removeList);
174+
Map<String, int[]> sortKey = new HashMap<>();
175+
Pattern ptn = Pattern.compile("(" + Utils.BOOK_ABBR_REGEX + ") ([0-9]+):([0-9]+)");
176+
for (String verse : list) {
177+
Matcher m = ptn.matcher(verse);
178+
if (!m.matches())
179+
throw new RuntimeException("Invalid verse reference: " + verse);
180+
String abbr = m.group(1);
181+
int aidx = bookAbbrOrder.indexOf(abbr);
182+
if (aidx == 0) {
183+
aidx = bookAbbrOrder.size();
184+
bookAbbrOrder.add(abbr);
185+
}
186+
sortKey.put(verse, new int[] { aidx, Integer.parseInt(m.group(2)), Integer.parseInt(m.group(3)) });
187+
}
188+
list.sort(Comparator.comparing(v -> sortKey.get(v), Comparator.<int[], Integer> comparing(a -> a[0]).thenComparing(a -> a[1]).thenComparing(a -> a[2])));
189+
for (String verse : list) {
190+
System.out.println(prefix + verse);
191+
}
144192
}
145193

146194
public static final class VersificationScheme implements Comparable<VersificationScheme> {

biblemulticonverter/src/main/java/biblemulticonverter/tools/VersificationCountsDetector.java

+17-4
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,13 @@ public void doExport(Bible bible, String... exportArgs) throws Exception {
9696

9797
// print them
9898
System.out.print("Best match: ");
99-
printScheme(counts[0], totalVerseCount);
99+
String verboseSchemasProperty = System.getProperty("versificationdetector.verboseschemes", "");
100+
Set<String> verboseSchemes = verboseSchemasProperty == null ? null : new HashSet<>(Arrays.asList(verboseSchemasProperty.split(", *")));
101+
printScheme(counts[0], totalVerseCount, verboseSchemes);
100102
System.out.println();
101103
System.out.println("Other options:");
102104
for (int i = 1; i < Math.min(11, counts.length); i++) {
103-
printScheme(counts[i], totalVerseCount);
105+
printScheme(counts[i], totalVerseCount, verboseSchemes);
104106
}
105107

106108
// print selected schemes
@@ -111,7 +113,7 @@ public void doExport(Bible bible, String... exportArgs) throws Exception {
111113
boolean found = false;
112114
for (VersificationCounts c : counts) {
113115
if (c.getName().equals(exportArgs[i])) {
114-
printScheme(c, totalVerseCount);
116+
printScheme(c, totalVerseCount, verboseSchemes);
115117
found = true;
116118
break;
117119
}
@@ -131,7 +133,7 @@ protected void countVerse(Map<BookID, int[]> bibleCounts, Set<String> totalVerse
131133
bookCounts[0]++;
132134
}
133135

134-
private void printScheme(VersificationCounts counts, int totalVerseCount) {
136+
private void printScheme(VersificationCounts counts, int totalVerseCount, Set<String> verboseSchemes) {
135137
List<String> missingInfo = new ArrayList<String>();
136138
if (counts.missingBooks > 0 || counts.missingChapters > 0 || counts.missingVerses > 0) {
137139
for (BookID bid : counts.bibleCounts.keySet()) {
@@ -156,6 +158,17 @@ private void printScheme(VersificationCounts counts, int totalVerseCount) {
156158
} else {
157159
System.out.println(counts.getName() + " (All verses covered, and " + (counts.verseCount - totalVerseCount) + " more)");
158160
}
161+
if (verboseSchemes != null && (verboseSchemes.contains(counts.getName()) || verboseSchemes.contains("all"))) {
162+
EnumSet<BookID> books = EnumSet.noneOf(BookID.class);
163+
books.addAll(counts.bibleCounts.keySet());
164+
books.addAll(counts.coveredCounts.keySet());
165+
int[] noVerses = new int[2];
166+
for (BookID bid : books) {
167+
int[] bInfo = counts.bibleCounts.getOrDefault(bid, noVerses);
168+
int[] cInfo = counts.coveredCounts.getOrDefault(bid, noVerses);
169+
System.out.println("\t" + bid.getOsisID() + ": " + cInfo[0] + "c[" + String.format("%+d", cInfo[0] - bInfo[0]) + "], " + cInfo[1] + "v[" + String.format("%+d", cInfo[1] - bInfo[1]) + "]");
170+
}
171+
}
159172
}
160173

161174
public static final class VersificationCounts implements Comparable<VersificationCounts> {

0 commit comments

Comments
 (0)