mirror of
https://gitlab.com/walljm/dynamicbible.git
synced 2025-07-25 16:29:49 -04:00
DynamicBibleUtility - Adding Strong's numbers to geolocation data.
This commit is contained in:
parent
b67e52950a
commit
274cecb598
@ -65,9 +65,11 @@
|
||||
</Compile>
|
||||
<Compile Include="Geolocation\BibleBook.cs" />
|
||||
<Compile Include="Geolocation\BibleLocationIndexByName.cs" />
|
||||
<Compile Include="Geolocation\BibleLocationIndexByStrongsNumbers.cs" />
|
||||
<Compile Include="Geolocation\BibleLocationIndexByVerse.cs" />
|
||||
<Compile Include="Geolocation\BibleLocationReference.cs" />
|
||||
<Compile Include="Geolocation\BibleVerseReference.cs" />
|
||||
<Compile Include="Geolocation\LocationNameToStrongsNumberLookup.cs" />
|
||||
<Compile Include="Geolocation\OpenBibleDotInfoLocationParser.cs" />
|
||||
<Compile Include="Helpers.cs" />
|
||||
<Compile Include="Index.cs" />
|
||||
|
@ -7,8 +7,8 @@ namespace DynamicBibleUtility.Geolocation
|
||||
/// </summary>
|
||||
public class BibleLocationIndexByName
|
||||
{
|
||||
/// <summary>A mapping of location names to full location data.</summary>
|
||||
public IDictionary<string, BibleLocationReference> NameToLocationLookup = new Dictionary<string, BibleLocationReference>();
|
||||
/// <summary>A mapping of location names to full location data (in the JSON format).</summary>
|
||||
public IDictionary<string, dynamic> NameToLocationLookup = new Dictionary<string, dynamic>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates the index from the provided locations.
|
||||
@ -24,7 +24,20 @@ namespace DynamicBibleUtility.Geolocation
|
||||
// The information currently isn't useful without these coordinates.
|
||||
if (location.HasGeographicCoordinates)
|
||||
{
|
||||
NameToLocationLookup[location.Name] = location;
|
||||
// Since the location data needs to be converted to JSON in different
|
||||
// scenarios with different properties serialized, there's not an easy
|
||||
// way to simply mark which fields should/shouldn't be serialized in
|
||||
// all situations. While a custom JSON converter could be used,
|
||||
// creating a dynamic object here seemed simpler. In this scenario,
|
||||
// the name doesn't need to be included in the member data since
|
||||
// it already serves as the key in the lookup.
|
||||
NameToLocationLookup[location.Name] = new
|
||||
{
|
||||
sn = location.StrongsNumbers,
|
||||
lat = location.Latitude,
|
||||
lon = location.Longitude,
|
||||
vss = location.VerseReferenceStrings
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DynamicBibleUtility.Geolocation
|
||||
{
|
||||
/// <summary>
|
||||
/// An index of Bible location data by Strong's numbers.
|
||||
///
|
||||
/// Strong's numbers tend to be more useful for lookups in the Dynamic Bible app
|
||||
/// due to how they're integrated into the rest of the app and can help more clearly
|
||||
/// define a particular location.
|
||||
///
|
||||
/// This class maintains a simple lookup of Strong's numbers to location names
|
||||
/// in addition to a lookup that includes the full location data.
|
||||
/// </summary>
|
||||
public class BibleLocationIndexByStrongsNumbers
|
||||
{
|
||||
/// <summary>
|
||||
/// A mapping of Strong's numbers to normalized location names.
|
||||
/// A Strong's number may refer to multiple locations.
|
||||
/// </summary>
|
||||
public IDictionary<string, List<string>> StrongsNumberToLocationNameLookup = new Dictionary<string, List<string>>();
|
||||
/// <summary>
|
||||
/// A mapping of Strong's numbers to full location data (in JSON format).
|
||||
/// A Strong's number may refer to multiple locations.
|
||||
/// </summary>
|
||||
public IDictionary<string, List<dynamic>> StrongsNumberToLocationLookup = new Dictionary<string, List<dynamic>>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates the index from the provided locations.
|
||||
/// </summary>
|
||||
/// <param name="locations">The locations to put in the index.</param>
|
||||
/// <exception cref="System.NullReferenceException">Thrown if the locations are null.</exception>
|
||||
public BibleLocationIndexByStrongsNumbers(IEnumerable<BibleLocationReference> locations)
|
||||
{
|
||||
// INDEX THE LOCATIONS BY STRONG'S NUMBERS.
|
||||
foreach (var location in locations)
|
||||
{
|
||||
// DON'T INDEX THE LOCATION IF IT HAS GEOGRAPHIC COORDINATES.
|
||||
// The information currently isn't useful without these coordinates.
|
||||
if (!location.HasGeographicCoordinates)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// DON'T INDEX THE LOCATION IF IT DOESN'T HAVE ANY STRONG'S NUMBERS.
|
||||
bool location_has_strongs_numbers = location.StrongsNumbers.Any();
|
||||
if (!location_has_strongs_numbers)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// INDEX THE LOCATION BY STRONG'S NUMBERS.
|
||||
foreach (string strongs_number in location.StrongsNumbers)
|
||||
{
|
||||
// MAKE SURE EXISTING COLLECTIONS EXIST FOR THE STRONG'S NUMBER.
|
||||
bool strongs_number_exists_in_index = StrongsNumberToLocationLookup.ContainsKey(strongs_number);
|
||||
if (!strongs_number_exists_in_index)
|
||||
{
|
||||
StrongsNumberToLocationNameLookup[strongs_number] = new List<string>();
|
||||
StrongsNumberToLocationLookup[strongs_number] = new List<dynamic>();
|
||||
}
|
||||
|
||||
// CONVERT THE LOCATION TO JSON FORMAT.
|
||||
// Since the location data needs to be converted to JSON in different
|
||||
// scenarios with different properties serialized, there's not an easy
|
||||
// way to simply mark which fields should/shouldn't be serialized in
|
||||
// all situations. While a custom JSON converter could be used,
|
||||
// creating a dynamic object here seemed simpler. In this scenario,
|
||||
// the Strong's number doesn't need to be included in the member data
|
||||
// since it already serves as the key in the lookup.
|
||||
dynamic converted_location = new
|
||||
{
|
||||
name = location.Name,
|
||||
lat = location.Latitude,
|
||||
lon = location.Longitude,
|
||||
vss = location.VerseReferenceStrings
|
||||
};
|
||||
|
||||
// INDEX THE LOCATION BY STRONG'S NUMBER.
|
||||
// Indices with just the location name and full location data are maintained.
|
||||
StrongsNumberToLocationNameLookup[strongs_number].Add(location.Name);
|
||||
StrongsNumberToLocationLookup[strongs_number].Add(converted_location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,35 +6,27 @@ namespace DynamicBibleUtility.Geolocation
|
||||
{
|
||||
/// <summary>
|
||||
/// A location mentioned in the Bible, with geographic coordinates and verse references.
|
||||
///
|
||||
/// Attributes are used to control serialization to minimize the amount of JSON that
|
||||
/// gets serialized.
|
||||
/// </summary>
|
||||
public class BibleLocationReference
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the location.
|
||||
/// Ignored for serialization since the name is more useful separately
|
||||
/// as a key for a property in a JavaScript object, rather than
|
||||
/// being duplicated again in the serialized data.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
/// <summary>The name of the location.</summary>
|
||||
public string Name = "";
|
||||
/// <summary>
|
||||
/// Any Strong's numbers for the location name, if available.
|
||||
/// Includes an 'H' prefix for Hebrew and a 'G' prefix for Greek before the actual numbers.
|
||||
/// </summary>
|
||||
public IEnumerable<string> StrongsNumbers = new List<string>();
|
||||
/// <summary>The latitude of the location, if available.</summary>
|
||||
[JsonProperty("lat")]
|
||||
public double? Latitude = null;
|
||||
/// <summary>The longitude of the location, if available.</summary>
|
||||
[JsonProperty("lon")]
|
||||
public double? Longitude = null;
|
||||
/// <summary>References to verses that mention the location.</summary>
|
||||
[JsonIgnore]
|
||||
public IEnumerable<BibleVerseReference> VerseReferences = new List<BibleVerseReference>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets references to verses that mention the location, in their short string form
|
||||
/// as used by the Dynamic Bible app.
|
||||
/// </summary>
|
||||
[JsonProperty("vss")]
|
||||
public IEnumerable<string> VerseReferenceStrings
|
||||
{
|
||||
get
|
||||
@ -46,9 +38,7 @@ namespace DynamicBibleUtility.Geolocation
|
||||
|
||||
/// <summary>
|
||||
/// True if this location information has full geographic coordinates; false otherwise.
|
||||
/// Marked such that it doesn't get serialized to JSON.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public bool HasGeographicCoordinates
|
||||
{
|
||||
get
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DynamicBibleUtility.Geolocation
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,8 @@ namespace DynamicBibleUtility.Geolocation
|
||||
/// Creative Commons Attribution license (see
|
||||
/// https://www.openbible.info/geo/ and
|
||||
/// https://creativecommons.org/licenses/by/4.0/).
|
||||
///
|
||||
/// Strong's numbers are added using <see cref="LocationNameToStrongsNumberLookup"/>.
|
||||
/// </summary>
|
||||
public class OpenBibleDotInfoLocationParser
|
||||
{
|
||||
@ -32,6 +34,8 @@ namespace DynamicBibleUtility.Geolocation
|
||||
/// <exception cref="Exception">Thrown if a parsing error occurs.</exception>
|
||||
public static IEnumerable<BibleLocationReference> Parse(string filepath)
|
||||
{
|
||||
List<string> locations_without_normalized_names = new List<string>();
|
||||
|
||||
// READ THE ENTIRE GEOLOCATION DATA FILE.
|
||||
// It is small enough to store completely in memory.
|
||||
string[] geolocation_input_file_lines = File.ReadAllLines(filepath);
|
||||
@ -81,6 +85,9 @@ namespace DynamicBibleUtility.Geolocation
|
||||
string verse_references_csv_list = current_line_fields[VERSE_REFERENCES_INDEX];
|
||||
location.VerseReferences = ParseVerseReferences(verse_references_csv_list);
|
||||
|
||||
// ADD STRONG'S NUMBERS REFERENCES TO THE LOCATION.
|
||||
location.StrongsNumbers = LocationNameToStrongsNumberLookup.GetStrongsNumbers(location.Name);
|
||||
|
||||
// ADD THE LOCATION INFORMATION FOR RETURNING.
|
||||
locations.Add(location);
|
||||
}
|
||||
|
@ -689,12 +689,13 @@ namespace DynamicBibleUtility
|
||||
UpdateStatus($"Parsed {locations.Count()} locations.\n");
|
||||
|
||||
// CREATE MORE USEFUL INDICES FOR THE LOCATIONS.
|
||||
// Indexing by name and verse references is useful for quick lookups
|
||||
// in the Dynamic Bible app.
|
||||
// Indexing in these different ways is useful for quick lookups in the Dynamic Bible app.
|
||||
BibleLocationIndexByName locations_by_name = new BibleLocationIndexByName(locations);
|
||||
UpdateStatus($"Finished indexing locations by name.\n");
|
||||
BibleLocationIndexByVerse locations_by_verse = new BibleLocationIndexByVerse(locations);
|
||||
UpdateStatus($"Finished indexing locations by verse.\n");
|
||||
BibleLocationIndexByStrongsNumbers locations_by_strongs_numbers = new BibleLocationIndexByStrongsNumbers(locations);
|
||||
UpdateStatus($"Finished indexing locations by Strong's numbers.\n");
|
||||
|
||||
// WRITE OUT THE GEOLOCATION DATA TO JSON FORMAT.
|
||||
const string LOCATIONS_BY_NAME_JSON_FILENAME = "locations_by_name.json";
|
||||
@ -702,14 +703,20 @@ namespace DynamicBibleUtility
|
||||
File.WriteAllText(LOCATIONS_BY_NAME_JSON_FILENAME, locations_by_name_in_json);
|
||||
UpdateStatus($"Wrote locations by name to {LOCATIONS_BY_NAME_JSON_FILENAME} in current working directory.\n");
|
||||
|
||||
const string LOCATIONS_BY_VERSE_JSON_FILENAME = "locations_by_verse.json";
|
||||
string locations_by_verse_in_json = JSON.ToJSON(locations_by_verse.VerseToLocationNameLookup);
|
||||
File.WriteAllText(LOCATIONS_BY_VERSE_JSON_FILENAME, locations_by_verse_in_json);
|
||||
UpdateStatus($"Wrote locations by verse to {LOCATIONS_BY_VERSE_JSON_FILENAME} in current working directory.\n");
|
||||
const string LOCATION_NAMES_BY_VERSE_JSON_FILENAME = "location_names_by_verse.json";
|
||||
string location_names_by_verse_in_json = JSON.ToJSON(locations_by_verse.VerseToLocationNameLookup);
|
||||
File.WriteAllText(LOCATION_NAMES_BY_VERSE_JSON_FILENAME, location_names_by_verse_in_json);
|
||||
UpdateStatus($"Wrote location names by verse to {LOCATION_NAMES_BY_VERSE_JSON_FILENAME} in current working directory.\n");
|
||||
|
||||
/// TODO(Jacob): Add Strong's numbers to the location data (with JavaScript property name of 'sn')
|
||||
/// and create a lookup based on Strong's numbers. This would be more useful in the context of
|
||||
/// the Dynamic Bible app.
|
||||
const string LOCATION_NAMES_BY_STRONGS_NUMBER = "location_names_by_strongs.json";
|
||||
string location_names_by_strongs_number_in_json = JSON.ToJSON(locations_by_strongs_numbers.StrongsNumberToLocationNameLookup);
|
||||
File.WriteAllText(LOCATION_NAMES_BY_STRONGS_NUMBER, location_names_by_strongs_number_in_json);
|
||||
UpdateStatus($"Wrote location names by Strong's number to {LOCATION_NAMES_BY_STRONGS_NUMBER} in current working directory.\n");
|
||||
|
||||
const string LOCATIONS_BY_STRONGS_NUMBER = "locations_by_strongs.json";
|
||||
string locations_by_strongs_number_in_json = JSON.ToJSON(locations_by_strongs_numbers.StrongsNumberToLocationLookup);
|
||||
File.WriteAllText(LOCATIONS_BY_STRONGS_NUMBER, locations_by_strongs_number_in_json);
|
||||
UpdateStatus($"Wrote locations by Strong's number to {LOCATIONS_BY_STRONGS_NUMBER} in current working directory.\n");
|
||||
|
||||
// INFORM THE USER THAT CREATING THE GEOLOCATION JSON FILES IS COMPLETE.
|
||||
UpdateStatus("Done.\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user