github.com/LanderTome/numerologyCalculator@v1.0.2/README.md (about) 1 [![Build Status](https://www.travis-ci.com/LanderTome/numerologyCalculator.svg?branch=master)](https://www.travis-ci.com/LanderTome/numerologyCalculator) 2 [![Go Report Card](https://goreportcard.com/badge/github.com/LanderTome/numerologyCalculator)](https://goreportcard.com/report/github.com/LanderTome/numerologyCalculator) 3 [![codecov](https://codecov.io/gh/LanderTome/numerologyCalculator/branch/master/graph/badge.svg?token=UH32UC6AQ0)](https://codecov.io/gh/LanderTome/numerologyCalculator) 4 [![Go Reference](https://pkg.go.dev/badge/github.com/LanderTome/numerologyCalculator.svg)](https://pkg.go.dev/github.com/LanderTome/numerologyCalculator) 5 6 Proof of concept: [https://numerology.mysticalriver.com](https://numerology.mysticalriver.com) 7 8 ## About the Project 9 10 Using either Pythagorean or Chaldean number systems, this calculator does various common numerological name and date 11 calculations: 12 13 - Destiny / Expression 14 - Soul's Urge / Heart's Desire 15 - Personality 16 - Hidden Passions 17 - Karmic Lessons 18 - Life Path 19 20 The truly unique aspect of this package, however, is that it also provides methods to search for either names or dates 21 that satisfy various numerological criteria. This is useful if one is trying to find a name for a baby, or a wedding 22 date that has the desirable numerological properties. 23 24 The way that it does this is using a precomputed table of names with corresponding numerological properties. This allows 25 the table to be searched for specific names that satisfy given constraints. This method is surprisingly efficient. A 26 database of 100,000 names with all the necessary pre-calculations is only 13.5 MB and searches take only hundredths of a 27 second. 28 29 This calculator does not provide any numerological interpretations as part of the package. Just the raw numbers. 30 31 See additional documentation at [pkg.go.dev.](https://pkg.go.dev/github.com/LanderTome/numerologyCalculator) 32 33 ## Getting Started 34 35 `go get "github.com/LanderTome/numerologyCalculator"` 36 37 ### Important numerological concepts 38 39 When doing a name calculation there are three properties that need to be specified that affect the calculation output: 40 41 1. Number System 42 2. Master Numbers 43 3. Reduce Words 44 45 The `Number System` is either one of the two most common systems that are used to assign numbers to the letters of 46 alphabet; Pythagorean and Chaldean. 47 48 The `Master Numbers` are numbers that are considered to have special numerological importance, and are treated in 49 differently in calculations. The most commonly cited master numbers 11, 22, and 33. However, some consider ALL repeated 50 numbers to be special, ex. 44, 55, 66, etc. The master numbers that one wants to use can be customized. 51 52 When `Reduce Words` is true, the calculation process sums and reduces each name individually before summing and reducing 53 those results. When it is false, all the parts of a name are summed and reduced together. The most common way is to sum 54 and reduce each name individually. 55 56 ### Name calculations 57 58 Start a name calculation with the `Name` function. 59 60 ```go 61 package main 62 63 import "github.com/LanderTome/numerologyCalculator/numerology" 64 65 func main() { 66 numberSystem := numerology.Pythagorean 67 masterNumbers := []int{11, 22, 33} 68 reduceWords := true 69 name := numerology.Name("John Doe", numberSystem, masterNumbers, reduceWords) 70 } 71 ``` 72 73 The returned struct is now the basis for calculating the numerological properties of the given name. 74 75 Now the various numerological numbers can be calculated by calling the various methods. 76 77 ```go 78 result := name.Full() 79 destiny := name.Destiny() // alias for name.Full() 80 expression := name.Expression() // alias for name.Full() 81 82 result := name.Vowels() 83 soulsUrge := name.SoulsUrge() // alias for name.Vowels() 84 heartsDesire := name.HeartsDesire() // alias for name.Vowels() 85 86 result := name.Consonants() 87 personality := name.Personality() // alias for name.Consonants() 88 89 hiddenPassions := name.HiddenPassions() 90 karmicLessons := name.KarmicLessons() 91 ``` 92 93 `Full, Vowels, and Consonants` are used instead of the common numerological terms because there are sometimes multiple 94 acceptable terms, and it can make is easier to understand which calculation is being done because you know what letters 95 of the name are being used. 96 97 Aliases for the above methods are provided for convenience. 98 99 The returned `NumerologicalResult` struct contains information about the calculation. `Value` is the final reduced 100 numerological number. 101 `ReduceSteps` is a slice of numbers that are the numerological values at each stage of the final reducing. `Breakdown` 102 contains the calculated values for each letter and each name that are used as the basis of the calculations. 103 104 `NumerologicalResult` has a method `Debug()` that returns a multiline string that contains a simplistic breakdown of the 105 calculation steps. It can be used to visualize the conversion. 106 107 ```go 108 package main 109 110 import "github.com/LanderTome/numerologyCalculator/numerology" 111 112 func main() { 113 numberSystem := numerology.Pythagorean 114 masterNumbers := []int{11, 22, 33} 115 reduceWords := true 116 name := numerology.Name("Janet Audrey Doe", numberSystem, masterNumbers, reduceWords) 117 personality := name.Consonants() 118 println(personality.Debug()) 119 } 120 121 Output: 122 J a n e t 123 1 · 5 · 2 = 8 124 A u d r e y 125 · · 4 9 · 7 = 20 = 2 126 D o e 127 4 · · = 4 128 Reduce: 14 = 5 129 ``` 130 131 ### Searching names 132 133 Where this calculator stands apart from other ones is in its ability to search for names that match given numerological 134 criteria. The idea is to scan a database of names, and find ones that, when combined with given names, have the 135 numerological properties that are specified. This task can be done with brute force methods, but several tricks as 136 utilized here to filter out names that we know won't work before actually querying the database. 137 138 ```go 139 package main 140 141 import "github.com/LanderTome/numerologyCalculator/numerology" 142 143 func main() { 144 numberSystem := numerology.Pythagorean 145 masterNumbers := []int{11, 22, 33} 146 reduceWords := true 147 name := numerology.Name("Jane ? Doe", numberSystem, masterNumbers, reduceWords) 148 searchOpts := numerology.NameSearchOpts{ 149 Count: 10, 150 Offset: 0, 151 Seed: 0, 152 Database: "sqlite://test_names.db", 153 Dictionary: "usa_census", 154 Gender: numerology.Female, 155 Sort: numerology.CommonSort, 156 Full: []int{1, 8, -13}, 157 Vowels: []int{4, 5, 6}, 158 Consonants: []int{5}, 159 HiddenPassions: nil, 160 KarmicLessons: nil, 161 } 162 results, offset, err := name.Search(searchOpts) 163 } 164 ``` 165 166 `NameSearchOpts` contains the necessary information to do the search. `Count` is the number of results to return in each 167 batch. 168 `Offset` is used to return the next batch of results. `Seed` is used for generating the "random" sort results. The seed 169 needs to be known if batching through random results in order to keep the results consistent. `Dictionary` is the name 170 of the table in the database that will be searched. *The included test files are from the US Census.* `Gender` allows 171 the names to be filtered by gender, so the results will be more male or female sounding. `Database` 172 is the database connection string that connects to the database that has the table to be searched. 173 174 Numerological properties: `Full`, `Vowels`, `Consonants`, 175 `HiddenPassions`, and `KarmicLessons`. These are all slices of integers that specify what criteria we want. Positive 176 numbers are numbers that are acceptable. Negative numbers are numbers that are to be excluded. A common use for negative 177 numbers would be to exclude, what are referred to as, Karmic Debt numbers 178 (13, 14, 16, 17). By specifying `[]int{-13, -14, -16, -19}`, the search results will not include names with those 179 numbers. 180 181 The return consists of a slice of `NameNumerology` results, an offset number that indicates where the next batch of 182 results should begin, and any errors messages that occur. To get the next batch use the given offset number in 183 the `NameSearchOpts`. 184 185 ### Date calculations 186 187 Date calculation are done with the `Date` function. 188 189 ```go 190 package main 191 192 import "github.com/LanderTome/numerologyCalculator/numerology" 193 194 func main() { 195 dt := numerology.NewDate(2021, 1, 1) 196 masterNumbers := []int{11, 22, 33} 197 date := numerology.Date(dt, masterNumbers) 198 } 199 ``` 200 201 The available methods for date numerology are `Event()` and 202 `LifePath()`. 203 204 ```go 205 event := name.Event() 206 lifePath := name.LifePath() 207 ``` 208 209 The only real difference between an event calculation and a life path calculation is that life path takes master numbers 210 into account. The returned `NumerologicalResult` similar to that which is returned by the `Name` methods. 211 212 ### Searching dates 213 214 The calculator is able to search for dates with specific numerological criteria. Unlike the name search, there are no 215 clever optimizations to this process. It simply loops through each date, and checks that it meets the criteria. Usually, 216 the search space for dates is only a few hundred days, so this does not significantly impact performance. 217 218 Life Path numbers have to do with one's date of birth so searching does not make a lot of sense because it is quite 219 difficult to control when someone is born. Searching dates is better suited for finding ideal wedding or event dates. 220 221 ```go 222 package main 223 224 import "github.com/LanderTome/numerologyCalculator/numerology" 225 226 func main() { 227 dt := numerology.NewDate(2021, 1, 1) 228 masterNumbers := []int{11, 22, 33} 229 date := numerology.Date(dt, masterNumbers) 230 231 searchOpts := numerology.DateSearchOpts{ 232 Count: 10, 233 Offset: 0, 234 Match: []int{3, 6}, 235 MonthsForward: 12, 236 Dow: []int{numerology.Friday, numerology.Saturday}, 237 LifePath: false, 238 } 239 results, offset := date.Search(searchOpts) 240 } 241 ``` 242 243 `DateSearchOpts` contains the necessary information to do the search. `Count` is the number of results to return in each 244 batch. 245 `Offset` is used to return the next batch of results. `Match` 246 contains the numerological numbers to find. Positive numbers indicate numbers that are acceptable, and Negative numbers 247 indicate numbers that will be avoided. `MonthsForward` is the number of months to search. It does not necessarily make 248 sense to search 5 years out for a wedding that you want to have in 1 or 2 years. 249 `Dow` are days of the week that you want results on. This helps if you are only interested in events that occur on 250 particular days; like weekends. `LifePath` indicates whether the dates should take Master Numbers into account. 251 252 ## Creating the Database 253 254 Before using the name search functionality, a database needs to be created and populated. 255 256 ```go 257 package main 258 259 import "github.com/LanderTome/numerologyCalculator/numerology" 260 261 func main() { 262 dsn := "sqlite://file::memory:" // Example for testing 263 namesDir := "test_names" 264 if err := numerology.CreateDatabase(dsn, namesDir); err != nil { 265 println(err.Error()) 266 } 267 } 268 ``` 269 270 ### Connecting to database 271 272 DSN (data source name) is the connection string for the database to use. This library uses [Gorm](https://gorm.io) for 273 the database connection. It currently supports MySQL, PostgreSQL, and SQLite, however it is anticipated that SQLite 274 would be the most common backend used. Go package [xo/dburl](https://github.com/xo/dburl) is used for dsn validation, so 275 it is useful to look at the documentation there to see acceptable connection string formats. 276 277 *The database connection is exposed in a package var `numerology.DB`. It could theoretically be used to manually attach 278 a custom Gorm backend, although this feature is untested.* 279 280 ### Source files 281 282 #### CSV structure 283 284 Each csv file needs to have three columns, however **NO HEADERS**. 285 286 The columns are *name*, *gender*, *popularity*. 287 288 ```csv 289 Mary,F,100 290 Michael,M,98 291 John,M,95 292 Susan,F,94 293 ``` 294 295 The popularity field is used so that names are sorted by how common they are. Often census compilations include 296 information like this. It is useful to be able to sort by how common a name is because some names that people give their 297 children are simply bizarre, and it becomes hard to sift through quality names without some control of that. 298 299 *In order to save space in the database, the raw popularity numbers are not stored. They are simply used to order the 300 names before putting them in the database. Once there, the inserted order of the database is used to establish 301 popularity.* 302 303 #### Directory layout 304 305 The database is populated by names coming from one or more CSV files based on a particular directory layout. 306 307 ``` 308 baseDir\ 309 ├── table1\ 310 │ ├── file1.csv 311 │ └── file2.csv 312 └── table2\ 313 ├── file1.csv 314 └── file2.csv 315 ``` 316 317 The folder names within the `baseDir` will be used as table names in the database. The names in each csv file in the 318 table directory will be iterated in ascending order and aggregated before being added to the database. 319 320 *Multiple csv files can be used when inserting into the database. The original source of names was a yearly compilation 321 of USA Census names. They consisted of the popularity of each name for each year from past to present. The names are 322 weighted so that current popularity is valued higher than older popularity. As the CSV files are iterated, the 323 popularity is summed up with a weighted scale based on how many files there are.* 324 325 ## Other notes 326 327 ### Is 'Y' a consonant or a vowel? 328 329 One problem that often comes up when doing name numerology is that sometimes the letter 'Y' is treated as a consonant, 330 and sometimes it is treated like a vowel. How to handle these situations is, unfortunately, not so straightforward for 331 an algorithm. The obvious answer is that 'Y' is a consonant when it is used as a consonant in a word, and a vowel when 332 used as a vowel. But how does one know the difference? 333 334 In the English language, every word can be broken down in to syllables. The rule is that each syllable must have a 335 vowel. That means that when there is a syllable with no obvious vowels, but there is a 'Y', the 'Y' is treated like a 336 vowel. 337 338 Take a name like Sydney. The syllables would be `Syd` and `ney`. In 339 `Syd`, there is no vowel, so the 'Y' functions as a vowel. However, in 340 `ney`, the 'E' is the vowel, so the 'Y' defaults to a consonant. 341 342 This idea is pretty easy to grasp, but turns out it is hard to program because there is no good algorithm for separating 343 words (especially names) into syllables. You essentially need a dictionary of the English language (and perhaps others, 344 as well) because there are different ways to pronounce similarly written words. This is even more difficult for names 345 because great liberties are often taken with their pronunciation. 346 347 One route is the use machine learning, and train it to deduce the syllable structure of words. This is a lot of work and 348 overhead for a solution that won't really even be 100% accurate anyway. 349 350 Some numerology calculators allow for special characters to signify when to treat 'Y' differently. Something 351 like `S*yndey` would use the * symbol to denote that the following 'Y' should be a vowel instead of a consonant. This is 352 difficult for this library because in order to search it needs to precompute a table of names. In order to do that, the 353 value of 'Y' needs to be picked ahead of time and in a consistent way. Arbitrarily choosing the value of a 'Y' could 354 lead to inconsistent name results. 355 356 Luckily, the 'Y' situation does not come up very often, and there are several rules-of-thumb that can be used to pick 357 the right value most of the time. This is what this library does, however, it does mean that names with 'Y' ought to be 358 looked at with extra scrutiny. 359 360 ### Transliteration of non-ASCII characters 361 362 The Pythagorean and Chaldean numbers systems are defined for the Latin alphabet A-Z. Of course, some languages have 363 characters that do not fit into this alphabet. The general consensus is to transliterate those characters to Latin 364 equivalent characters. This is easy for some characters such as ä, é, or ñ. However, some others are not so easy or 365 obvious; ex. 张. 366 367 Most calculators just ignore these characters, but we can do better. This library includes a Go 368 package [mozillazg/go-unidecode](https://github.com/mozillazg/go-unidecode) 369 that is inspired by a Python port of a well-known Perl package `Text::Unidecode`. The author of the Perl package has 370 some excellent [information](https://interglacial.com/~sburke/tpj/as_html/tpj22.html) 371 on the difficulties of transliterating languages. It is worth the read in order to understand the limitations of the 372 automatic conversion. 373 374 When in doubt, manual transliteration to ASCII characters is recommended. 375 376 ### Unknown Characters 377 378 Even with transliteration of alphabetic characters, it is inevitable that names pop up that have symbols or emojis or 379 other weird characters. What should a calculator do in this situation? Symbols do not have numerological value, so it 380 seems like there are two solutions: 1) Error on unknown characters or 2) Give them a zero value. 381 382 Returning an error does not seem quite appropriate because sometimes you want to use strange characters in a name, and 383 purposefully ignore them. Commonly occurring characters of this sort are spaces, dashes, apostrophes, and periods. It is 384 not unusual to have a hyphenated name or to include an apostrophe in a name like in A'isha. 385 386 If someone had a name like 'Crazy! Smith', we could force them to drop the exclamation point to do the calculation, or 387 we could allow it and just give it no value. That way it calculates with no extra work, and the symbols are reflected as 388 part of the name. 389 390 The problem with just zeroing out characters is that if someone does not know that a character is being interpreted as 391 an unknown character then they won't be able to know if the numerological calculation is what they expect. Perhaps 392 someone expects that 393 `$amuel $mith` is similar enough to `Samuel Smith` that it is automatically converted. 394 395 The compromise used here is that unknown characters are processed just fine, albeit with a zero value, and all unknown 396 characters are stored with the name and can be checked with the `UnknownCharacters()` 397 method.