Source code: com/eireneh/bible/control/map/LinkArray.java
1
2 package com.eireneh.bible.control.map;
3
4 import java.io.*;
5
6 import com.eireneh.util.*;
7 import com.eireneh.bible.passage.*;
8 import com.eireneh.bible.book.*;
9 import com.eireneh.bible.control.search.*;
10
11 /**
12 * LinkArray contains a set of links for each verse in the Bible.
13 * It is similar to a central margin reference data set, except that
14 * every verse is linked to a constant number of others, and the links
15 * have strengths.
16 *
17 * <table border='1' cellPadding='3' cellSpacing='0' width="100%">
18 * <tr><td bgColor='white'class='TableRowColor'><font size='-7'>
19 * Distribution Licence:<br />
20 * Project B is free software; you can redistribute it
21 * and/or modify it under the terms of the GNU General Public License,
22 * version 2 as published by the Free Software Foundation.<br />
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.<br />
27 * The License is available on the internet
28 * <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, by writing to
29 * <i>Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 * MA 02111-1307, USA</i>, Or locally at the Licence link below.<br />
31 * The copyright to this program is held by it's authors.
32 * </font></td></tr></table>
33 * @see <a href='http://www.eireneh.com/servlets/Web'>Project B Home</a>
34 * @see docs.Licence
35 * @author Joe Walker
36 * @version D0.I0.T0
37 */
38 public class LinkArray implements Serializable
39 {
40 /**
41 * Basic constructor
42 * @param bible The source of Bible data
43 */
44 public LinkArray(Bible bible) throws NoSuchVerseException, BookException, SearchException
45 {
46 this.bible = bible;
47 engine = new Matcher(bible);
48
49 cacheAll();
50 }
51
52 /**
53 * Fill up the link cache
54 */
55 public void cacheAll() throws NoSuchVerseException, BookException, SearchException
56 {
57 // Create the array of Nodes
58 for (int i=1; i<=Books.versesInBible(); i++)
59 {
60 getLinks(i);
61 }
62 }
63
64 /**
65 * Turn a PassageTally into an array of links.
66 * @param verse The verse to get a link for
67 * @return The array of links for the specified verse
68 */
69 public Link[] getLinks(int ord)
70 {
71 int index = ord - 1;
72 if (links[index] != null)
73 return links[index];
74
75 try
76 {
77 linked++;
78 Verse verse = new Verse(ord);
79
80 String text = bible.getText(new VerseRange(verse));
81 PassageTally tally = engine.bestMatch(text);
82
83 tally.setOrdering(PassageTally.ORDER_TALLY);
84 tally.trimVerses(LINKS_PER_VERSE);
85
86 // Check that the tally contains the first verse as first match
87 if (!tally.getVerseAt(0).equals(verse))
88 {
89 int miss_index = tally.getIndexOf(verse);
90 if (miss_index == -1) miss_index = 50;
91 miss_total += miss_index;
92 log.info(""+verse+" missed by "+miss_index+" average index="+getMatchScore()+" text="+text);
93 }
94
95 // Remove the original wherever it was
96 tally.remove(verse);
97
98 // Create the links for the tally
99 links[index] = new Link[LINKS_PER_VERSE];
100 for (int i=0; i<LINKS_PER_VERSE; i++)
101 {
102 try
103 {
104 Verse loop = tally.getVerseAt(i);
105 int strength = tally.getTallyOf(loop);
106
107 links[index][i] = new Link(loop.getOrdinal(), strength);
108 }
109 catch (ArrayIndexOutOfBoundsException ex)
110 {
111 links[index][i] = new Link(verse.getOrdinal(), 0);
112 }
113 }
114
115 return links[index];
116 }
117 catch (Exception ex)
118 {
119 throw new LogicError(ex);
120 }
121 }
122
123 /**
124 * What is the average index for a given match. This is a measure of
125 * how good the nest match algorithm is. The closer to zero the better
126 * @return The average match index
127 */
128 public float getMatchScore()
129 {
130 if (linked == 0)
131 return -1;
132
133 return ((float) (100 * miss_total)) / linked;
134 }
135
136 /**
137 * Debug for an array of Links
138 */
139 private static String debug(Link[] set)
140 {
141 StringBuffer buff = new StringBuffer();
142
143 for (int i=0; i<set.length; i++)
144 {
145 if (i != 0)
146 buff.append(", ");
147
148 buff.append(set[i].toString());
149 }
150
151 return buff.toString();
152 }
153
154 /** To make serialization work across new versions */
155 static final long serialVersionUID = -2354670272946948354L;
156
157 /** The total miss mark */
158 private transient int miss_total = 0;
159
160 /** The number of verses checked */
161 private transient int linked = 0;
162
163 /** The Bible that we search in */
164 private transient Bible bible;
165
166 /** The thing we use to generate matches */
167 private transient Matcher engine;
168
169 /** The number of links we record for each verse */
170 private static final int LINKS_PER_VERSE = 40;
171
172 /** The link data */
173 private Link[][] links = new Link[Books.versesInBible()][];
174
175 /** The log stream */
176 protected static Logger log = Logger.getLogger("control.map");
177 }