commit - 6f8321e65ea37dceb515d4d8e7af11429aed9cc8
commit + 6fa62bae5d2b8a1d41f16837a255b243f8f85ec3
blob - 0c47c893e2c60ff4baa66a37594da624fa88c0ff (mode 644)
blob + /dev/null
--- cmd/gedcom2errors/main.go
+++ /dev/null
-package main
-
-import (
- "bytes"
- "errors"
- "flag"
- "fmt"
- "github.com/iand/gedcom"
- "io/ioutil"
- "os"
- "regexp"
- "strings"
- "time"
-)
-
-const (
- OLDAGE = 99
- WEDDER = 3
- MAYDEC = 5
- YNGMAR = 20
- OLDMAR = 80
- LNGWDW = 80
- OLDUNM = 67
- FECMOM = 45
- OLDMOM = 55
- YNGMOM = 16
- CSPACE = 1
- CBSPAN = 1
-)
-
-type fn_person func(person *gedcom.IndividualRecord) bool
-type fn_family func(family *gedcom.FamilyRecord) bool
-
-func rule_I100(person *gedcom.IndividualRecord) bool {
- var birt_date, deat_date time.Time
- birt_date = eventDate(person, "BIRT")
- if birt_date.IsZero() {
- return true
- }
- deat_date = eventDate(person, "DEAT")
- if deat_date.Sub(birt_date) > OLDAGE {
- fmt.Println(deat_date, birt_date)
- return false
- }
-
- return true
-}
-
-func rule_I101(person *gedcom.IndividualRecord) bool {
- var birt_date, bap_date time.Time
- birt_date = eventDate(person, "BIRT")
- if birt_date.IsZero() {
- return true
- }
- bap_date = eventDate(person, "BAP")
- if bap_date.Sub(birt_date) > 0 {
- fmt.Println(birt_date, bap_date)
- return false
- }
-
- return true
-}
-
-func rule_I102(person *gedcom.IndividualRecord) bool {
- var birt_date, deat_date time.Time
- birt_date = eventDate(person, "BIRT")
- if birt_date.IsZero() {
- return true
- }
- deat_date = eventDate(person, "DEAT")
- if deat_date.Sub(birt_date) < 0 {
- fmt.Println(birt_date, deat_date)
- return false
- }
-
- return true
-}
-
-func rule_I103(person *gedcom.IndividualRecord) bool {
- var deat_date, buri_date time.Time
- deat_date = eventDate(person, "DEAT")
- if deat_date.IsZero() {
- return true
- }
- buri_date = eventDate(person, "BURI")
- if deat_date.Sub(buri_date) < 0 {
- fmt.Println(deat_date, buri_date)
- return false
- }
-
- return true
-}
-
-func rule_I104(person *gedcom.IndividualRecord) bool {
- var deat_date, bap_date time.Time
- deat_date = eventDate(person, "DEAT")
- if deat_date.IsZero() {
- return true
- }
- bap_date = eventDate(person, "BAP")
- if deat_date.Sub(bap_date) < 0 {
- fmt.Println(deat_date, bap_date)
- return false
- }
-
- return true
-}
-
-func rule_I105(person *gedcom.IndividualRecord) bool {
- var bap_date, buri_date time.Time
- bap_date = eventDate(person, "BAP")
- if bap_date.IsZero() {
- return true
- }
- buri_date = eventDate(person, "BURI")
- if bap_date.Sub(buri_date) < 0 {
- fmt.Println(buri_date, bap_date)
- return false
- }
-
- return true
-}
-
-func rule_I106(person *gedcom.IndividualRecord) bool {
- var buri_date, deat_date time.Time
- deat_date = eventDate(person, "DEAT")
- if deat_date.IsZero() {
- return true
- }
- buri_date = eventDate(person, "BURI")
- if deat_date.Sub(buri_date) > 0 {
- fmt.Println(buri_date, deat_date)
- return false
- }
-
- return true
-}
-
-func rule_I107(person *gedcom.IndividualRecord) bool {
- var bap_date, birt_date time.Time
- bap_date = eventDate(person, "BAP")
- if bap_date.IsZero() {
- return true
- }
- birt_date = eventDate(person, "BIRT")
- if bap_date.Sub(birt_date) >= 1 {
- fmt.Println(bap_date, birt_date)
- return false
- }
-
- return true
-}
-
-func rule_I108(person *gedcom.IndividualRecord) bool {
- var deat_date, buri_date time.Time
- deat_date = eventDate(person, "DEAT")
- if deat_date.IsZero() {
- return true
- }
- buri_date = eventDate(person, "BURI")
- if deat_date.Sub(buri_date) >= 1 {
- fmt.Println(deat_date, buri_date)
- return false
- }
-
- return true
-}
-
-func rule_I109(person *gedcom.IndividualRecord) bool {
- if person.Sex == "" {
- return false
- }
-
- return true
-}
-
-func rule_I110(person *gedcom.IndividualRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_I111(person *gedcom.IndividualRecord) bool {
- if len(person.Parents) > 1 {
- return false
- }
-
- return true
-}
-
-func rule_I112(person *gedcom.IndividualRecord) bool {
- if len(person.Family) == 0 {
- return false
- }
-
- return true
-}
-
-func rule_F100(family *gedcom.FamilyRecord) bool {
- if family.Husband == nil {
- return false
- }
- if family.Wife == nil {
- return false
- }
- if len(family.Child) == 0 {
- return false
- }
-
- return true
-}
-
-func rule_F101(family *gedcom.FamilyRecord) bool {
- if family.Husband == nil {
- return false
- }
- if family.Wife == nil {
- return false
- }
-
- return true
-}
-
-func rule_F102(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_F103(family *gedcom.FamilyRecord) bool {
- if family.Husband == nil {
- return false
- }
-
- return true
-}
-
-func rule_F104(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_F105(family *gedcom.FamilyRecord) bool {
- if family.Wife == nil {
- return false
- }
-
- return true
-}
-
-func rule_F106(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_F107(family *gedcom.FamilyRecord) bool {
- if len(family.Child) == 0 {
- return false
- }
-
- return true
-}
-
-func rule_F108(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_F109(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_F110(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M100(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M101(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M102(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M103(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M104(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M105(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M106(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M107(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M108(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M109(family *gedcom.FamilyRecord) bool {
- if family.Husband.Sex == family.Wife.Sex {
- return false
- }
-
- return true
-}
-
-func rule_M110(family *gedcom.FamilyRecord) bool {
- if family.Husband.Sex == "F" {
- return false
- }
-
- return true
-}
-
-func rule_M111(family *gedcom.FamilyRecord) bool {
- if family.Wife.Sex == "M" {
- return false
- }
-
- return true
-}
-
-func rule_M112(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M113(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M114(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_M115(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_P100(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_P101(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_P102(family *gedcom.FamilyRecord) bool {
- var mother_birt_date, child_birt_date time.Time
- mother_birt_date = eventDate(family.Wife, "BIRT")
- for _, child := range family.Child {
- child_birt_date = eventDate(child, "BIRT")
- if mother_birt_date.Sub(child_birt_date) < 0 {
- return false
- }
- }
-
- return true
-}
-
-func rule_P103(family *gedcom.FamilyRecord) bool {
- var mother_birt_date, child_birt_date time.Time
- mother_birt_date = eventDate(family.Wife, "BIRT")
- if mother_birt_date.IsZero() {
- return true
- }
- for _, child := range family.Child {
- child_birt_date = eventDate(child, "BIRT")
- if mother_birt_date.Sub(child_birt_date) < YNGMOM {
- fmt.Println(mother_birt_date, child_birt_date)
- return false
- }
- }
-
- return true
-}
-
-func rule_P104(family *gedcom.FamilyRecord) bool {
- var mother_deat_date, child_birt_date time.Time
- mother_deat_date = eventDate(family.Wife, "DEAT")
- if mother_deat_date.IsZero() {
- return true
- }
- for _, child := range family.Child {
- child_birt_date = eventDate(child, "BIRT")
- if mother_deat_date == child_birt_date {
- fmt.Println(mother_deat_date, child_birt_date)
- return false
- }
- }
-
- return true
-}
-
-func rule_P105(family *gedcom.FamilyRecord) bool {
- var father_deat_date, child_birt_date time.Time
- father_deat_date = eventDate(family.Husband, "DEAT")
- if father_deat_date.IsZero() {
- return true
- }
- for _, child := range family.Child {
- child_birt_date = eventDate(child, "BIRT")
- if father_deat_date == child_birt_date {
- fmt.Println(father_deat_date, child_birt_date)
- return false
- }
- }
-
- return true
-}
-
-func rule_P106(family *gedcom.FamilyRecord) bool {
- var father_surname []string
- var child_surname []string
- surname_re := regexp.MustCompile(`.+ /(.+)/`)
- for _, name := range family.Husband.Name {
- surname := surname_re.FindStringSubmatch(name.Name)
- if surname[1] != "" {
- father_surname = append(father_surname, surname[1])
- }
- }
- for _, child := range family.Child {
- for _, name := range child.Name {
- surname := surname_re.FindStringSubmatch(name.Name)
- if surname[1] != "" {
- child_surname = append(child_surname, surname[1])
- }
- }
- }
-
- for _, surname := range child_surname {
- if !contains(father_surname, surname) {
- fmt.Println(father_surname, surname)
- return false
- }
- }
-
- return true
-}
-
-func rule_C100(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_C101(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_C102(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_C103(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_C104(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func rule_C105(family *gedcom.FamilyRecord) bool {
- /* FIXME */
- return true
-}
-
-func eventDate(person *gedcom.IndividualRecord, eventTag string) time.Time {
- var date time.Time
- for _, event := range person.Event {
- if event.Tag == eventTag {
- date, _ = parse_date_string(event.Date)
- }
- }
-
- return date
-}
-
-func parse_date_string(date string) (time.Time, error) {
- // "2006-01-02T15:04:05.000Z"
- layout := "02 JAN 2006"
- t, err := time.Parse(layout, date)
- if err == nil {
- return t, nil
- }
-
- return time.Time{}, err
-}
-
-func contains(s []string, e string) bool {
- for _, a := range s {
- if a == e {
- return true
- }
- }
- return false
-}
-
-func PrintIndividualRecord(record *gedcom.IndividualRecord) {
- fmt.Printf("Person: %s", record.Xref)
- if len(record.Name) > 0 {
- fmt.Printf(" %s\n", record.Name[0].Name)
- } else {
- fmt.Printf("\n")
- }
-}
-
-func PrintFamilyRecord(record *gedcom.FamilyRecord) {
- fmt.Printf("Family %s\n", record.Xref)
-}
-
-func main() {
- /*
- persons born after they were married
- persons born after their children
- persons having similarly named children
- persons having an ancestral loop
-
- Persons Born After One of Their Parents Died
- Persons Born After One of Their Parents Was Buried
- Persons Baptized After Being Buried
- Persons Baptized After Being Married
- Persons Married After Being Buried
- Persons Baptized After They Died
- Persons Married After They Died
- Persons Died Before Children Were Born
- Persons Died After Being Buried
- Persons Buried Before Having Children
- Persons Baptized Past the Age of 5
- Persons Married Before the Age of 14
- Wives Married After the Age of 50
- Persons Living Past the Age of 100
- Persons at Least 30 Years Older Than Their Spouse
- Persons Having a Degree of Kinship of 4 or Less
- Persons Having a Non-biological Parent
- Persons Whose Birth Dates Could Not Be Estimated
- Persons with Invalid Dates
- Families Having Swapped Spouses
- */
-
- // rules are borrowed from gigatrees.com and lifelines
- person_rules := map[string]fn_person{
- "EI100: person's age at death is older than _oldage_": rule_I100,
- "EI101: person is baptized before birth": rule_I101,
- "EI102: person dies before birth": rule_I102,
- "EI103: person is buried before birth": rule_I103,
- "EI104: person dies before baptism": rule_I104,
- "EI105: person is buried before baptism": rule_I105,
- "EI106: person is buried before death": rule_I106,
- "EI107: person is baptised after birth year": rule_I107,
- "EI108: person is buried after death year": rule_I108,
- "EI109: person has unkown gender": rule_I109,
- "EI110: person has ambiguous gender": rule_I110,
- "EI111: person has multiple parentage": rule_I111,
- "EI112: person has no family pointers": rule_I112,
- }
-
- family_rules := map[string]fn_family{
- "EF100: family has no members": rule_F100,
- "EF101: family has no parents": rule_F101,
- "EF102: husband missing pointer to family": rule_F102,
- "EF103: family missing pointer to husband": rule_F103,
- "EF104: wife missing pointer to family": rule_F104,
- "EF105: family missing pointer to wife": rule_F105,
- "EF106: child missing pointer to family": rule_F106,
- "EF107: family missing pointer to child": rule_F107,
- "EF108: family has multiple husbands": rule_F108,
- "EF109: family has multiple wives": rule_F109,
- "EF110: child is in family multiple times": rule_F110,
- // marriage rules
- "EM100: person marries before birth": rule_M100,
- "EM101: person marries after death": rule_M101,
- "EM102: person has more than WEDDER spouses": rule_M102,
- "EM103: person marries someone more than MAYDEC years older": rule_M103,
- "EM104: person marries younger than YNGMAR": rule_M104,
- "EM105: person marries older than OLDMAR": rule_M105,
- "EM106: marriage out of order": rule_M106,
- "EM107: marriage before birth from previous marriage": rule_M107,
- "EM108: marriage after birth from subsequent marriage": rule_M108,
- "EM109: homosexual marriage": rule_M109,
- "EM110: person is a female husband": rule_M110,
- "EM111: person is a male wife": rule_M111,
- "EM112: person was a widow(er) longer than LNGWDW years": rule_M112,
- "EM113: person lived more than OLDUNM years and never married": rule_M113,
- "EM114: person has multiple marriages, this one with no spouse and no children": rule_M114,
- "EM115: person has same surname as spouse": rule_M115,
- // parentage rules
- "EP100: mother has more than FECMOM children": rule_P100,
- "EP101: mother is older than OLDMOM at time of birth of child": rule_P101,
- "EP102: child is born before mother": rule_P102,
- "EP103: mother is younger than YNGMOM at time of birth of child": rule_P103,
- "EP104: mother is dead at birth of child": rule_P104,
- "EP105: father is dead at birth of child": rule_P105,
- "EP106: child doesn't inherit father's surname": rule_P106,
- // children rules
- "EC100: child is born out of order with respect to a previous child": rule_C100,
- "EC101: child is born in the same year as a previous child": rule_C101,
- "EC102: child is born more than CSPACE years after previous child": rule_C102,
- "EC103: children's births span more than CBSPAN years": rule_C103,
- "EC104: child is born before parent's marriage": rule_C104,
- "EC105: child has same given name as sibling": rule_C105,
- }
-
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
- fmt.Fprintf(os.Stderr, "\nTool for checking of GEDCOM file for errors.")
- fmt.Fprintf(os.Stderr, "\n\nFlags:\n")
- flag.PrintDefaults()
- }
-
- var gedfile = flag.String("file", "", "GEDCOM filename")
- var ignorelist = flag.String("ignore", "", "rules ignore list")
- var verbose = flag.Bool("verbose", false, "verbose mode")
-
- flag.Parse()
-
- if *gedfile == "" {
- flag.Usage()
- os.Exit(1)
- }
-
- var ignores []string
- if len(*ignorelist) != 0 {
- ignores = strings.Split(*ignorelist, ",")
- fmt.Println("These rules are ignored:", ignores)
- }
-
- data, _ := ioutil.ReadFile(*gedfile)
- d := gedcom.NewDecoder(bytes.NewReader(data))
- g, _ := d.Decode()
-
- if *verbose {
- fmt.Printf("Found %d persons:\n\n", len(g.Individual))
- }
-
- found_errors := false
- for _, record := range g.Individual {
- for err_msg, fn := range person_rules {
- if contains(ignores, err_msg) {
- continue
- }
- if !fn(record) {
- fmt.Printf("%s", record.Xref)
- if len(record.Name) > 0 {
- fmt.Printf(" %s\n", record.Name[0].Name)
- } else {
- fmt.Printf("\n")
- }
- fmt.Println(errors.New(err_msg))
- found_errors = true
- }
- }
- }
-
- if *verbose {
- fmt.Printf("\nFound %d families:\n\n", len(g.Family))
- }
- for _, record := range g.Family {
- for err_msg, fn := range family_rules {
- if contains(ignores, err_msg) {
- continue
- }
- if !fn(record) {
- PrintFamilyRecord(record)
- fmt.Println(err_msg)
- found_errors = true
- }
- }
- }
-
- if found_errors {
- os.Exit(1)
- }
-}
blob - /dev/null
blob + 6f8effcc98ba58c6640857d2db328b188b2f4ce2 (mode 644)
--- /dev/null
+++ cmd/gedcom2errors/gedcom2errors.go
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "github.com/iand/gedcom"
+ "io/ioutil"
+ "os"
+ "regexp"
+ "strings"
+ "time"
+)
+
+const (
+ OLDAGE = 99
+ WEDDER = 3
+ MAYDEC = 5
+ YNGMAR = 20
+ OLDMAR = 80
+ LNGWDW = 80
+ OLDUNM = 67
+ FECMOM = 45
+ OLDMOM = 55
+ YNGMOM = 16
+ CSPACE = 1
+ CBSPAN = 1
+)
+
+type fn_person func(person *gedcom.IndividualRecord) bool
+type fn_family func(family *gedcom.FamilyRecord) bool
+
+func rule_I100(person *gedcom.IndividualRecord) bool {
+ var birt_date, deat_date time.Time
+ birt_date = eventDate(person, "BIRT")
+ if birt_date.IsZero() {
+ return true
+ }
+ deat_date = eventDate(person, "DEAT")
+ if deat_date.IsZero() {
+ return true
+ }
+ if deat_date.Sub(birt_date) > OLDAGE {
+ fmt.Println(deat_date, birt_date)
+ return false
+ }
+
+ return true
+}
+
+func rule_I101(person *gedcom.IndividualRecord) bool {
+ var birt_date, bap_date time.Time
+ birt_date = eventDate(person, "BIRT")
+ if birt_date.IsZero() {
+ return true
+ }
+ bap_date = eventDate(person, "BAP")
+ if bap_date.IsZero() {
+ return true
+ }
+ if bap_date.Sub(birt_date) > 0 {
+ fmt.Println(birt_date, bap_date)
+ return false
+ }
+
+ return true
+}
+
+func rule_I102(person *gedcom.IndividualRecord) bool {
+ var birt_date, deat_date time.Time
+ birt_date = eventDate(person, "BIRT")
+ if birt_date.IsZero() {
+ return true
+ }
+ deat_date = eventDate(person, "DEAT")
+ if deat_date.IsZero() {
+ return true
+ }
+ if deat_date.Sub(birt_date) < 0 {
+ fmt.Println(birt_date, deat_date)
+ return false
+ }
+
+ return true
+}
+
+func rule_I103(person *gedcom.IndividualRecord) bool {
+ var deat_date, buri_date time.Time
+ deat_date = eventDate(person, "DEAT")
+ if deat_date.IsZero() {
+ return true
+ }
+ buri_date = eventDate(person, "BURI")
+ if buri_date.IsZero() {
+ return true
+ }
+ if deat_date.Sub(buri_date) < 0 {
+ fmt.Println(deat_date, buri_date)
+ return false
+ }
+
+ return true
+}
+
+func rule_I104(person *gedcom.IndividualRecord) bool {
+ var deat_date, bap_date time.Time
+ deat_date = eventDate(person, "DEAT")
+ if deat_date.IsZero() {
+ return true
+ }
+ bap_date = eventDate(person, "BAP")
+ if bap_date.IsZero() {
+ return true
+ }
+ if deat_date.Sub(bap_date) < 0 {
+ fmt.Println(deat_date, bap_date)
+ return false
+ }
+
+ return true
+}
+
+func rule_I105(person *gedcom.IndividualRecord) bool {
+ var bap_date, buri_date time.Time
+ bap_date = eventDate(person, "BAP")
+ if bap_date.IsZero() {
+ return true
+ }
+ buri_date = eventDate(person, "BURI")
+ if buri_date.IsZero() {
+ return true
+ }
+ if bap_date.Sub(buri_date) < 0 {
+ fmt.Println(buri_date, bap_date)
+ return false
+ }
+
+ return true
+}
+
+func rule_I106(person *gedcom.IndividualRecord) bool {
+ var buri_date, deat_date time.Time
+ deat_date = eventDate(person, "DEAT")
+ if deat_date.IsZero() {
+ return true
+ }
+ buri_date = eventDate(person, "BURI")
+ if buri_date.IsZero() {
+ return true
+ }
+ if deat_date.Sub(buri_date) > 0 {
+ fmt.Println(buri_date, deat_date)
+ return false
+ }
+
+ return true
+}
+
+func rule_I107(person *gedcom.IndividualRecord) bool {
+ var bap_date, birt_date time.Time
+ bap_date = eventDate(person, "BAP")
+ if bap_date.IsZero() {
+ return true
+ }
+ birt_date = eventDate(person, "BIRT")
+ if birt_date.IsZero() {
+ return true
+ }
+ if bap_date.Sub(birt_date) >= 1 {
+ fmt.Println(bap_date, birt_date)
+ return false
+ }
+
+ return true
+}
+
+func rule_I108(person *gedcom.IndividualRecord) bool {
+ var deat_date, buri_date time.Time
+ deat_date = eventDate(person, "DEAT")
+ if deat_date.IsZero() {
+ return true
+ }
+ buri_date = eventDate(person, "BURI")
+ if buri_date.IsZero() {
+ return true
+ }
+ if deat_date.Sub(buri_date) >= 1 {
+ fmt.Println(deat_date, buri_date)
+ return false
+ }
+
+ return true
+}
+
+func rule_I109(person *gedcom.IndividualRecord) bool {
+ if person.Sex == "" {
+ return false
+ }
+
+ return true
+}
+
+func rule_I110(person *gedcom.IndividualRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_I111(person *gedcom.IndividualRecord) bool {
+ if len(person.Parents) > 1 {
+ return false
+ }
+
+ return true
+}
+
+func rule_I112(person *gedcom.IndividualRecord) bool {
+ if len(person.Family) == 0 {
+ return false
+ }
+
+ return true
+}
+
+func rule_F100(family *gedcom.FamilyRecord) bool {
+ if family.Husband == nil {
+ return false
+ }
+ if family.Wife == nil {
+ return false
+ }
+ if len(family.Child) == 0 {
+ return false
+ }
+
+ return true
+}
+
+func rule_F101(family *gedcom.FamilyRecord) bool {
+ if family.Husband == nil {
+ return false
+ }
+ if family.Wife == nil {
+ return false
+ }
+
+ return true
+}
+
+func rule_F102(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_F103(family *gedcom.FamilyRecord) bool {
+ if family.Husband == nil {
+ return false
+ }
+
+ return true
+}
+
+func rule_F104(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_F105(family *gedcom.FamilyRecord) bool {
+ if family.Wife == nil {
+ return false
+ }
+
+ return true
+}
+
+func rule_F106(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_F107(family *gedcom.FamilyRecord) bool {
+ if len(family.Child) == 0 {
+ return false
+ }
+
+ return true
+}
+
+func rule_F108(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_F109(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_F110(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M100(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M101(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M102(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M103(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M104(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M105(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M106(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M107(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M108(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M109(family *gedcom.FamilyRecord) bool {
+ if family.Husband.Sex == family.Wife.Sex {
+ return false
+ }
+
+ return true
+}
+
+func rule_M110(family *gedcom.FamilyRecord) bool {
+ if family.Husband.Sex == "F" {
+ return false
+ }
+
+ return true
+}
+
+func rule_M111(family *gedcom.FamilyRecord) bool {
+ if family.Wife.Sex == "M" {
+ return false
+ }
+
+ return true
+}
+
+func rule_M112(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M113(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M114(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_M115(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_P100(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_P101(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_P102(family *gedcom.FamilyRecord) bool {
+ var mother_birt_date, child_birt_date time.Time
+ mother_birt_date = eventDate(family.Wife, "BIRT")
+ for _, child := range family.Child {
+ child_birt_date = eventDate(child, "BIRT")
+ if mother_birt_date.Sub(child_birt_date) < 0 {
+ return false
+ }
+ }
+
+ return true
+}
+
+func rule_P103(family *gedcom.FamilyRecord) bool {
+ var mother_birt_date, child_birt_date time.Time
+ mother_birt_date = eventDate(family.Wife, "BIRT")
+ if mother_birt_date.IsZero() {
+ return true
+ }
+ for _, child := range family.Child {
+ child_birt_date = eventDate(child, "BIRT")
+ if child_birt_date.IsZero() {
+ continue
+ }
+ if mother_birt_date.Sub(child_birt_date) < YNGMOM {
+ fmt.Println(mother_birt_date, child_birt_date)
+ return false
+ }
+ }
+
+ return true
+}
+
+func rule_P104(family *gedcom.FamilyRecord) bool {
+ var mother_deat_date, child_birt_date time.Time
+ mother_deat_date = eventDate(family.Wife, "DEAT")
+ if mother_deat_date.IsZero() {
+ return true
+ }
+ for _, child := range family.Child {
+ child_birt_date = eventDate(child, "BIRT")
+ if child_birt_date.IsZero() {
+ continue
+ }
+ if mother_deat_date == child_birt_date {
+ fmt.Println(mother_deat_date, child_birt_date)
+ return false
+ }
+ }
+
+ return true
+}
+
+func rule_P105(family *gedcom.FamilyRecord) bool {
+ var father_deat_date, child_birt_date time.Time
+ father_deat_date = eventDate(family.Husband, "DEAT")
+ if father_deat_date.IsZero() {
+ return true
+ }
+ for _, child := range family.Child {
+ child_birt_date = eventDate(child, "BIRT")
+ if child_birt_date.IsZero() {
+ continue
+ }
+ if father_deat_date == child_birt_date {
+ fmt.Println(father_deat_date, child_birt_date)
+ return false
+ }
+ }
+
+ return true
+}
+
+func rule_P106(family *gedcom.FamilyRecord) bool {
+ var father_surname []string
+ var child_surname []string
+ surname_re := regexp.MustCompile(`.+ /(.+)/`)
+ for _, name := range family.Husband.Name {
+ surname := surname_re.FindStringSubmatch(name.Name)
+ if surname[1] != "" {
+ father_surname = append(father_surname, surname[1])
+ }
+ }
+ for _, child := range family.Child {
+ for _, name := range child.Name {
+ surname := surname_re.FindStringSubmatch(name.Name)
+ if surname[1] != "" {
+ child_surname = append(child_surname, surname[1])
+ }
+ }
+ }
+
+ for _, surname := range child_surname {
+ if !contains(father_surname, surname) {
+ fmt.Println(father_surname, surname)
+ return false
+ }
+ }
+
+ return true
+}
+
+func rule_C100(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_C101(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_C102(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_C103(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_C104(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func rule_C105(family *gedcom.FamilyRecord) bool {
+ /* FIXME */
+ return true
+}
+
+func eventDate(person *gedcom.IndividualRecord, eventTag string) time.Time {
+ var date time.Time
+ for _, event := range person.Event {
+ if event.Tag == eventTag {
+ date, _ = parse_date_string(event.Date)
+ }
+ }
+
+ return date
+}
+
+func parse_date_string(date string) (time.Time, error) {
+ // "2006-01-02T15:04:05.000Z"
+ layout := "02 JAN 2006"
+ t, err := time.Parse(layout, date)
+ if err == nil {
+ return t, nil
+ }
+
+ return time.Time{}, err
+}
+
+func contains(s []string, e string) bool {
+ for _, a := range s {
+ if a == e {
+ return true
+ }
+ }
+ return false
+}
+
+func PrintIndividualRecord(record *gedcom.IndividualRecord) {
+ fmt.Printf("Person (%s)", record.Xref)
+ if len(record.Name) > 0 {
+ fmt.Printf(" %s\n", record.Name[0].Name)
+ } else {
+ fmt.Printf("\n")
+ }
+}
+
+func PrintFamilyRecord(record *gedcom.FamilyRecord) {
+ fmt.Printf("Family (%s)\n", record.Xref)
+}
+
+func main() {
+ /*
+ persons born after they were married
+ persons born after their children
+ persons having similarly named children
+ persons having an ancestral loop
+
+ Persons Born After One of Their Parents Died
+ Persons Born After One of Their Parents Was Buried
+ Persons Baptized After Being Buried
+ Persons Baptized After Being Married
+ Persons Married After Being Buried
+ Persons Baptized After They Died
+ Persons Married After They Died
+ Persons Died Before Children Were Born
+ Persons Died After Being Buried
+ Persons Buried Before Having Children
+ Persons Baptized Past the Age of 5
+ Persons Married Before the Age of 14
+ Wives Married After the Age of 50
+ Persons Living Past the Age of 100
+ Persons at Least 30 Years Older Than Their Spouse
+ Persons Having a Degree of Kinship of 4 or Less
+ Persons Having a Non-biological Parent
+ Persons Whose Birth Dates Could Not Be Estimated
+ Persons with Invalid Dates
+ Families Having Swapped Spouses
+ */
+
+ // rules are borrowed from gigatrees.com and lifelines
+ person_rules := map[string]fn_person{
+ "EI100: person's age at death is older than _oldage_": rule_I100,
+ "EI101: person is baptized before birth": rule_I101,
+ "EI102: person dies before birth": rule_I102,
+ "EI103: person is buried before birth": rule_I103,
+ "EI104: person dies before baptism": rule_I104,
+ "EI105: person is buried before baptism": rule_I105,
+ "EI106: person is buried before death": rule_I106,
+ "EI107: person is baptised after birth year": rule_I107,
+ "EI108: person is buried after death year": rule_I108,
+ "EI109: person has unkown gender": rule_I109,
+ "EI110: person has ambiguous gender": rule_I110,
+ "EI111: person has multiple parentage": rule_I111,
+ "EI112: person has no family pointers": rule_I112,
+ }
+
+ family_rules := map[string]fn_family{
+ "EF100: family has no members": rule_F100,
+ "EF101: family has no parents": rule_F101,
+ "EF102: husband missing pointer to family": rule_F102,
+ "EF103: family missing pointer to husband": rule_F103,
+ "EF104: wife missing pointer to family": rule_F104,
+ "EF105: family missing pointer to wife": rule_F105,
+ "EF106: child missing pointer to family": rule_F106,
+ "EF107: family missing pointer to child": rule_F107,
+ "EF108: family has multiple husbands": rule_F108,
+ "EF109: family has multiple wives": rule_F109,
+ "EF110: child is in family multiple times": rule_F110,
+ // marriage rules
+ "EM100: person marries before birth": rule_M100,
+ "EM101: person marries after death": rule_M101,
+ "EM102: person has more than WEDDER spouses": rule_M102,
+ "EM103: person marries someone more than MAYDEC years older": rule_M103,
+ "EM104: person marries younger than YNGMAR": rule_M104,
+ "EM105: person marries older than OLDMAR": rule_M105,
+ "EM106: marriage out of order": rule_M106,
+ "EM107: marriage before birth from previous marriage": rule_M107,
+ "EM108: marriage after birth from subsequent marriage": rule_M108,
+ "EM109: homosexual marriage": rule_M109,
+ "EM110: person is a female husband": rule_M110,
+ "EM111: person is a male wife": rule_M111,
+ "EM112: person was a widow(er) longer than LNGWDW years": rule_M112,
+ "EM113: person lived more than OLDUNM years and never married": rule_M113,
+ "EM114: person has multiple marriages, this one with no spouse and no children": rule_M114,
+ "EM115: person has same surname as spouse": rule_M115,
+ // parentage rules
+ "EP100: mother has more than FECMOM children": rule_P100,
+ "EP101: mother is older than OLDMOM at time of birth of child": rule_P101,
+ "EP102: child is born before mother": rule_P102,
+ "EP103: mother is younger than YNGMOM at time of birth of child": rule_P103,
+ "EP104: mother is dead at birth of child": rule_P104,
+ "EP105: father is dead at birth of child": rule_P105,
+ "EP106: child doesn't inherit father's surname": rule_P106,
+ // children rules
+ "EC100: child is born out of order with respect to a previous child": rule_C100,
+ "EC101: child is born in the same year as a previous child": rule_C101,
+ "EC102: child is born more than CSPACE years after previous child": rule_C102,
+ "EC103: children's births span more than CBSPAN years": rule_C103,
+ "EC104: child is born before parent's marriage": rule_C104,
+ "EC105: child has same given name as sibling": rule_C105,
+ }
+
+ flag.Usage = func() {
+ fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+ fmt.Fprintf(os.Stderr, "\nTool for checking of GEDCOM file for errors.")
+ fmt.Fprintf(os.Stderr, "\n\nFlags:\n")
+ flag.PrintDefaults()
+ }
+
+ var gedfile = flag.String("file", "", "GEDCOM filename")
+ var ignorelist = flag.String("ignore", "", "rules ignore list")
+ var verbose = flag.Bool("verbose", false, "verbose mode")
+
+ flag.Parse()
+
+ if *gedfile == "" {
+ flag.Usage()
+ os.Exit(1)
+ }
+
+ var ignores []string
+ if len(*ignorelist) != 0 {
+ ignores = strings.Split(*ignorelist, ",")
+ fmt.Println("These rules are ignored:", ignores)
+ }
+
+ data, _ := ioutil.ReadFile(*gedfile)
+ d := gedcom.NewDecoder(bytes.NewReader(data))
+ g, _ := d.Decode()
+
+ if *verbose {
+ fmt.Printf("Found %d persons:\n\n", len(g.Individual))
+ }
+
+ found_errors := false
+ for _, record := range g.Individual {
+ for err_msg, fn := range person_rules {
+ if contains(ignores, err_msg) {
+ continue
+ }
+ if !fn(record) {
+ PrintIndividualRecord(record)
+ fmt.Println(err_msg)
+ found_errors = true
+ }
+ }
+ }
+
+ if *verbose {
+ fmt.Printf("\nFound %d families:\n\n", len(g.Family))
+ }
+ for _, record := range g.Family {
+ for err_msg, fn := range family_rules {
+ if contains(ignores, err_msg) {
+ continue
+ }
+ if !fn(record) {
+ PrintFamilyRecord(record)
+ fmt.Println(err_msg)
+ found_errors = true
+ }
+ }
+ }
+
+ if found_errors {
+ os.Exit(1)
+ }
+}
blob - /dev/null
blob + 7f3a50bfb07fd425b03931ab8817e87b282009bf (mode 644)
--- /dev/null
+++ cmd/gedcom2sql/gedcom2sql.go
+package main
+
+import (
+ "bytes"
+ "database/sql"
+ "flag"
+ "fmt"
+ "github.com/iand/gedcom"
+ _ "github.com/mattn/go-sqlite3"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func checkErr(err error) {
+ if err != nil {
+ panic(err)
+ }
+}
+
+const (
+ sql_table = `
+ DROP TABLE IF EXISTS famchild;
+ CREATE TABLE famchild (
+ famID varchar(40) NOT NULL DEFAULT '',
+ child varchar(40) NOT NULL DEFAULT '',
+ PRIMARY KEY (famID, child)
+ );
+
+ DROP TABLE IF EXISTS family;
+ CREATE TABLE family (
+ famID varchar(40) NOT NULL DEFAULT '',
+ husband varchar(40) DEFAULT NULL,
+ wife varchar(40) DEFAULT NULL,
+ marr_date varchar(255) DEFAULT NULL,
+ marr_plac varchar(255) DEFAULT NULL,
+ marr_sour varchar(255) DEFAULT NULL,
+ marb_date varchar(255) DEFAULT NULL,
+ marb_plac varchar(255) DEFAULT NULL,
+ marb_sour varchar(255) DEFAULT NULL,
+ PRIMARY KEY (famID)
+ );
+
+ DROP TABLE IF EXISTS person_st;
+ CREATE TABLE person_st (
+ persID varchar(40) NOT NULL DEFAULT '',
+ name varchar(255) DEFAULT NULL,
+ vorname varchar(255) DEFAULT NULL,
+ marname varchar(255) DEFAULT NULL,
+ sex char(1) DEFAULT NULL,
+ birt_date varchar(255) DEFAULT NULL,
+ birt_plac varchar(255) DEFAULT NULL,
+ birt_sour varchar(255) DEFAULT NULL,
+ taufe_date varchar(255) DEFAULT NULL,
+ taufe_plac varchar(255) DEFAULT NULL,
+ taufe_sour varchar(255) DEFAULT NULL,
+ deat_date varchar(255) DEFAULT NULL,
+ deat_plac varchar(255) DEFAULT NULL,
+ deat_sour varchar(255) DEFAULT NULL,
+ buri_date varchar(255) DEFAULT NULL,
+ buri_plac varchar(255) DEFAULT NULL,
+ buri_sour varchar(255) DEFAULT NULL,
+ occupation varchar(255) DEFAULT NULL,
+ occu_date varchar(255) DEFAULT NULL,
+ occu_plac varchar(255) DEFAULT NULL,
+ occu_sour varchar(255) DEFAULT NULL,
+ religion varchar(80) DEFAULT NULL,
+ confi_date varchar(255) DEFAULT NULL,
+ confi_plac varchar(255) DEFAULT NULL,
+ confi_sour varchar(255) DEFAULT NULL,
+ note longtext,
+ PRIMARY KEY (persID)
+ );
+ `
+)
+
+func InitDB(filepath string) *sql.DB {
+ db, err := sql.Open("sqlite3", filepath)
+ if err != nil {
+ panic(err)
+ }
+ if db == nil {
+ panic("db nil")
+ }
+ return db
+}
+
+func CreateTable(db *sql.DB) {
+ _, err := db.Exec(sql_table)
+ if err != nil {
+ panic(err)
+ }
+}
+
+func main() {
+
+ flag.Usage = func() {
+ fmt.Println("\ngedcom2sql is a tool for conversion of GEDCOM to SQLite.")
+ fmt.Println("\nUsage:")
+ flag.PrintDefaults()
+ }
+
+ var gedfile = flag.String("file", "", "GEDCOM filename")
+ var verbose = flag.Bool("verbose", false, "verbose mode")
+
+ flag.Parse()
+
+ if *gedfile == "" {
+ flag.Usage()
+ os.Exit(1)
+ }
+
+ /*
+ if len(g.Header.SourceSystem.Version) > 0 {
+ println(g.Header.SourceSystem.Version, g.Header.SourceSystem.Id)
+ }
+ if len(g.Header.SourceSystem.Id) > 0 {
+ println(g.Header.SourceSystem.Id)
+ }
+ */
+
+ var dbname = strings.TrimSuffix(*gedfile, filepath.Ext(*gedfile)) + ".sqlite"
+ db := InitDB(dbname)
+ defer db.Close()
+ CreateTable(db)
+
+ data, _ := ioutil.ReadFile(*gedfile)
+ d := gedcom.NewDecoder(bytes.NewReader(data))
+ g, _ := d.Decode()
+
+ if *verbose {
+ fmt.Println("\nPersons (Xref, Name, Sex):")
+ fmt.Println("--------------------------")
+ }
+ println("Found persons:", len(g.Individual))
+ for _, rec := range g.Individual {
+ if len(rec.Name) > 0 {
+ if *verbose {
+ fmt.Printf("%s, %s, %s\n", rec.Xref, rec.Name[0].Name, rec.Sex)
+ }
+ var birt_date, deat_date, buri_date string
+ var birt_plac, deat_plac, buri_plac string
+ for _, event := range rec.Event {
+ if *verbose {
+ fmt.Printf("\t%s, %s, %s\n", event.Tag, event.Date, event.Place.Name)
+ }
+ if event.Tag == "BIRT" {
+ birt_date = event.Date
+ birt_plac = event.Place.Name
+ }
+ if event.Tag == "DEAT" {
+ deat_date = event.Date
+ deat_plac = event.Place.Name
+ }
+ if event.Tag == "DEAT" {
+ buri_date = event.Date
+ buri_plac = event.Place.Name
+ }
+ }
+ stmt, err := db.Prepare("INSERT INTO person_st (persID, name, birt_date, birt_plac, deat_date, deat_plac, buri_date, buri_plac, sex) values(?, ?, ?, ?, ?, ?, ?, ?, ?)")
+ checkErr(err)
+ _, err = stmt.Exec(rec.Xref, rec.Name[0].Name, birt_date, birt_plac, deat_date, deat_plac, buri_date, buri_plac, rec.Sex)
+ checkErr(err)
+ }
+ }
+
+ if *verbose {
+ fmt.Println("\nFamilies (Xref, Husband, Wife):")
+ fmt.Println("-------------------------------")
+ }
+ println("Found families:", len(g.Family))
+ for _, rec := range g.Family {
+ if *verbose {
+ fmt.Printf("%s\n", rec.Xref)
+ fmt.Printf("%s, %s, %s\n", rec.Xref, rec.Husband.Xref, rec.Wife.Xref)
+ }
+ stmt, err := db.Prepare("INSERT INTO family (famID, husband, wife) values(?, ?, ?)")
+ checkErr(err)
+ _, err = stmt.Exec(rec.Xref, rec.Husband.Xref, rec.Wife.Xref)
+ checkErr(err)
+
+ for _, child := range rec.Child {
+ if *verbose {
+ fmt.Printf("\t%s, %s\n", rec.Xref, child.Xref)
+ }
+ stmt, err := db.Prepare("INSERT INTO famchild (famID, child) values(?, ?)")
+ checkErr(err)
+ _, err = stmt.Exec(rec.Xref, child.Xref)
+ checkErr(err)
+ }
+ }
+ println("Database path:", dbname)
+}
blob - 7f3a50bfb07fd425b03931ab8817e87b282009bf (mode 644)
blob + /dev/null
--- cmd/gedcom2sql/main.go
+++ /dev/null
-package main
-
-import (
- "bytes"
- "database/sql"
- "flag"
- "fmt"
- "github.com/iand/gedcom"
- _ "github.com/mattn/go-sqlite3"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
-)
-
-func checkErr(err error) {
- if err != nil {
- panic(err)
- }
-}
-
-const (
- sql_table = `
- DROP TABLE IF EXISTS famchild;
- CREATE TABLE famchild (
- famID varchar(40) NOT NULL DEFAULT '',
- child varchar(40) NOT NULL DEFAULT '',
- PRIMARY KEY (famID, child)
- );
-
- DROP TABLE IF EXISTS family;
- CREATE TABLE family (
- famID varchar(40) NOT NULL DEFAULT '',
- husband varchar(40) DEFAULT NULL,
- wife varchar(40) DEFAULT NULL,
- marr_date varchar(255) DEFAULT NULL,
- marr_plac varchar(255) DEFAULT NULL,
- marr_sour varchar(255) DEFAULT NULL,
- marb_date varchar(255) DEFAULT NULL,
- marb_plac varchar(255) DEFAULT NULL,
- marb_sour varchar(255) DEFAULT NULL,
- PRIMARY KEY (famID)
- );
-
- DROP TABLE IF EXISTS person_st;
- CREATE TABLE person_st (
- persID varchar(40) NOT NULL DEFAULT '',
- name varchar(255) DEFAULT NULL,
- vorname varchar(255) DEFAULT NULL,
- marname varchar(255) DEFAULT NULL,
- sex char(1) DEFAULT NULL,
- birt_date varchar(255) DEFAULT NULL,
- birt_plac varchar(255) DEFAULT NULL,
- birt_sour varchar(255) DEFAULT NULL,
- taufe_date varchar(255) DEFAULT NULL,
- taufe_plac varchar(255) DEFAULT NULL,
- taufe_sour varchar(255) DEFAULT NULL,
- deat_date varchar(255) DEFAULT NULL,
- deat_plac varchar(255) DEFAULT NULL,
- deat_sour varchar(255) DEFAULT NULL,
- buri_date varchar(255) DEFAULT NULL,
- buri_plac varchar(255) DEFAULT NULL,
- buri_sour varchar(255) DEFAULT NULL,
- occupation varchar(255) DEFAULT NULL,
- occu_date varchar(255) DEFAULT NULL,
- occu_plac varchar(255) DEFAULT NULL,
- occu_sour varchar(255) DEFAULT NULL,
- religion varchar(80) DEFAULT NULL,
- confi_date varchar(255) DEFAULT NULL,
- confi_plac varchar(255) DEFAULT NULL,
- confi_sour varchar(255) DEFAULT NULL,
- note longtext,
- PRIMARY KEY (persID)
- );
- `
-)
-
-func InitDB(filepath string) *sql.DB {
- db, err := sql.Open("sqlite3", filepath)
- if err != nil {
- panic(err)
- }
- if db == nil {
- panic("db nil")
- }
- return db
-}
-
-func CreateTable(db *sql.DB) {
- _, err := db.Exec(sql_table)
- if err != nil {
- panic(err)
- }
-}
-
-func main() {
-
- flag.Usage = func() {
- fmt.Println("\ngedcom2sql is a tool for conversion of GEDCOM to SQLite.")
- fmt.Println("\nUsage:")
- flag.PrintDefaults()
- }
-
- var gedfile = flag.String("file", "", "GEDCOM filename")
- var verbose = flag.Bool("verbose", false, "verbose mode")
-
- flag.Parse()
-
- if *gedfile == "" {
- flag.Usage()
- os.Exit(1)
- }
-
- /*
- if len(g.Header.SourceSystem.Version) > 0 {
- println(g.Header.SourceSystem.Version, g.Header.SourceSystem.Id)
- }
- if len(g.Header.SourceSystem.Id) > 0 {
- println(g.Header.SourceSystem.Id)
- }
- */
-
- var dbname = strings.TrimSuffix(*gedfile, filepath.Ext(*gedfile)) + ".sqlite"
- db := InitDB(dbname)
- defer db.Close()
- CreateTable(db)
-
- data, _ := ioutil.ReadFile(*gedfile)
- d := gedcom.NewDecoder(bytes.NewReader(data))
- g, _ := d.Decode()
-
- if *verbose {
- fmt.Println("\nPersons (Xref, Name, Sex):")
- fmt.Println("--------------------------")
- }
- println("Found persons:", len(g.Individual))
- for _, rec := range g.Individual {
- if len(rec.Name) > 0 {
- if *verbose {
- fmt.Printf("%s, %s, %s\n", rec.Xref, rec.Name[0].Name, rec.Sex)
- }
- var birt_date, deat_date, buri_date string
- var birt_plac, deat_plac, buri_plac string
- for _, event := range rec.Event {
- if *verbose {
- fmt.Printf("\t%s, %s, %s\n", event.Tag, event.Date, event.Place.Name)
- }
- if event.Tag == "BIRT" {
- birt_date = event.Date
- birt_plac = event.Place.Name
- }
- if event.Tag == "DEAT" {
- deat_date = event.Date
- deat_plac = event.Place.Name
- }
- if event.Tag == "DEAT" {
- buri_date = event.Date
- buri_plac = event.Place.Name
- }
- }
- stmt, err := db.Prepare("INSERT INTO person_st (persID, name, birt_date, birt_plac, deat_date, deat_plac, buri_date, buri_plac, sex) values(?, ?, ?, ?, ?, ?, ?, ?, ?)")
- checkErr(err)
- _, err = stmt.Exec(rec.Xref, rec.Name[0].Name, birt_date, birt_plac, deat_date, deat_plac, buri_date, buri_plac, rec.Sex)
- checkErr(err)
- }
- }
-
- if *verbose {
- fmt.Println("\nFamilies (Xref, Husband, Wife):")
- fmt.Println("-------------------------------")
- }
- println("Found families:", len(g.Family))
- for _, rec := range g.Family {
- if *verbose {
- fmt.Printf("%s\n", rec.Xref)
- fmt.Printf("%s, %s, %s\n", rec.Xref, rec.Husband.Xref, rec.Wife.Xref)
- }
- stmt, err := db.Prepare("INSERT INTO family (famID, husband, wife) values(?, ?, ?)")
- checkErr(err)
- _, err = stmt.Exec(rec.Xref, rec.Husband.Xref, rec.Wife.Xref)
- checkErr(err)
-
- for _, child := range rec.Child {
- if *verbose {
- fmt.Printf("\t%s, %s\n", rec.Xref, child.Xref)
- }
- stmt, err := db.Prepare("INSERT INTO famchild (famID, child) values(?, ?)")
- checkErr(err)
- _, err = stmt.Exec(rec.Xref, child.Xref)
- checkErr(err)
- }
- }
- println("Database path:", dbname)
-}
blob - 2eabf1fcdb2022410ae860d6658f462bb725d05a (mode 644)
blob + /dev/null
--- cmd/vis/main.go
+++ /dev/null
-/*
- * timenet
- * - http://vis.stanford.edu/papers/timenets
- * - http://vis.berkeley.edu/courses/cs294-10-sp10/wiki/images/f/f2/Family_Tree_Visualization_-_Final_Paper.pdf
- * timeline
- * - https://github.com/davorg/svg-timeline-genealogy
- * graphviz:
- * - https://github.com/adrienverge/familytreemaker
- * - https://github.com/vmiklos/ged2dot
- * - моя реализация
- * [GEPS 030: New Visualization Techniques](https://www.gramps-project.org/wiki/index.php/GEPS_030:_New_Visualization_Techniques)
- * [Geneaquilts](https://aviz.fr/geneaquilts/)
- * https://github.com/nicolaskruchten/genealogy
- */
-
-package main
-
-import (
- "github.com/ajstarks/svgo"
- "os"
-)
-
-func main() {
- width := 500
- height := 500
- canvas := svg.New(os.Stdout)
- canvas.Start(width, height)
- canvas.Circle(width/2, height/2, 100)
- canvas.Text(width/2, height/2, "Hello, SVG", "text-anchor:middle;font-size:30px;fill:white")
- canvas.End()
-}
blob - /dev/null
blob + 2eabf1fcdb2022410ae860d6658f462bb725d05a (mode 644)
--- /dev/null
+++ cmd/gedcom2timenet/gedcom2timenet.go
+/*
+ * timenet
+ * - http://vis.stanford.edu/papers/timenets
+ * - http://vis.berkeley.edu/courses/cs294-10-sp10/wiki/images/f/f2/Family_Tree_Visualization_-_Final_Paper.pdf
+ * timeline
+ * - https://github.com/davorg/svg-timeline-genealogy
+ * graphviz:
+ * - https://github.com/adrienverge/familytreemaker
+ * - https://github.com/vmiklos/ged2dot
+ * - моя реализация
+ * [GEPS 030: New Visualization Techniques](https://www.gramps-project.org/wiki/index.php/GEPS_030:_New_Visualization_Techniques)
+ * [Geneaquilts](https://aviz.fr/geneaquilts/)
+ * https://github.com/nicolaskruchten/genealogy
+ */
+
+package main
+
+import (
+ "github.com/ajstarks/svgo"
+ "os"
+)
+
+func main() {
+ width := 500
+ height := 500
+ canvas := svg.New(os.Stdout)
+ canvas.Start(width, height)
+ canvas.Circle(width/2, height/2, 100)
+ canvas.Text(width/2, height/2, "Hello, SVG", "text-anchor:middle;font-size:30px;fill:white")
+ canvas.End()
+}
blob - 1f99cfae42baf5597a80791abf7acb63e25a8163 (mode 644)
blob + /dev/null
--- cmd/vk2gedcom/main.go
+++ /dev/null
-/*
-
-Example: ./socialtree -id 233293686
-
-TreeWalk https://gist.github.com/abhat/71332461951830f9a0f5
-https://gist.github.com/zyxar/2317744
-https://golang.org/doc/play/tree.go
-https://github.com/alonsovidales/go_graph
-
-FIXME:
- id181554010 (зацикливается)
- id140022470 (зацикливается)
-
-*/
-
-package main
-
-import (
- "encoding/json"
- "flag"
- "fmt"
- "io/ioutil"
- "log"
- "net/http"
- "os"
- "strconv"
-)
-
-type RawResponse struct {
- Person []json.RawMessage `json:"response"`
-}
-
-type Person struct {
- ID int `json:"id"`
- FirstName string `json:"first_name"`
- LastName string `json:"last_name"`
- Sex int `json:"sex"`
- Bdate string `json:"bdate"`
- Photo_50 string `json:"photo_50"`
- Relation int `json:"relation"`
- Relatives []Relative `json:"relatives"`
- RelationPartner RelPartner `json:"relation_partner"`
- Generation int
-}
-
-type RelPartner struct {
- ID int `json:"id"`
- Name string `json:"name"`
-}
-
-type Relative struct {
- ID int `json:"id"` // идентификатор пользователя
- Type string `json:"type"` // тип родственной связи
- Name string `json:"name"` // имя родственника
-}
-
-func ValueInSlice(n int, list []int) bool {
- for _, i := range list {
- if i == n {
- return true
- }
- }
- return false
-}
-
-func process_person(person Person) []Person {
-
- var tree []Person
- var p Person
- if len(person.Relatives) != 0 {
- for _, r := range person.Relatives {
- p = Person{}
- log.Println(r.ID, r.Type, r.Name)
- id := strconv.Itoa(r.ID)
- if r.ID > 0 {
- log.Println("Person is in VK", id)
- p = get_profile(id)
- } else {
- log.Println("Person is absent in VK", id)
- p.FirstName = r.Name
- p.LastName = r.Name
- }
-
- switch r.Type {
- case "child":
- p.Generation = person.Generation - 1
- case "sibling":
- p.Generation = person.Generation
- case "parent":
- p.Generation = person.Generation + 1
- case "grandparent":
- p.Generation = person.Generation - 2
- case "grandchild":
- p.Generation = person.Generation + 2
- }
- tree = append(tree, p)
- process_person(p)
- }
- }
-
- relation := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
- if ValueInSlice(person.Relation, relation) {
- log.Println("no spouse")
- } else {
- p = Person{}
- id := strconv.Itoa(person.RelationPartner.ID)
- p = get_profile(id)
- tree = append(tree, p)
- process_person(p)
- }
-
- return tree
-}
-
-func get_profile(id string) Person {
-
- url := "https://api.vk.com/method/users.get?user_ids="
- url = url + id
- url = url + "&fields=first_name,last_name,photo_50,relatives,relation,bdate,sex&v=5.67"
-
- res, err := http.Get(url)
- if err != nil {
- panic(err.Error())
- }
-
- body, err := ioutil.ReadAll(res.Body)
- if err != nil {
- panic(err.Error())
- }
-
- var raw RawResponse
- err = json.Unmarshal(body, &raw)
- if err != nil {
- log.Fatal("Error parsing json: ", err)
- }
-
- var person Person
- err = json.Unmarshal(raw.Person[0], &person)
- if err != nil {
- log.Fatal("Error parsing json: ", err)
- }
-
- var sex string
- switch person.Sex {
- case 1:
- sex = "Ж"
- case 2:
- sex = "М"
- default:
- sex = "неизвестно"
- }
-
- log.Println(person.FirstName, person.LastName, sex, person.Bdate)
- log.Println("\t", person.Relatives)
-
- return person
-}
-
-func main() {
-
- flag.Usage = func() {
- fmt.Println("\nsocialtree is a tool for getting relations via VK.")
- fmt.Println("\nUsage:")
- flag.PrintDefaults()
- }
-
- var person_id = flag.String("id", "", "person id")
-
- flag.Parse()
-
- if *person_id == "" {
- flag.Usage()
- os.Exit(1)
- }
-
- var Tree []Person
-
- person := get_profile(*person_id)
- person.Generation = 0
- Tree = append(Tree, person)
- Tree = append(Tree, process_person(person)...) // new
-
- /*
- var p Person
- if len(person.Relatives) != 0 {
- for _, r := range person.Relatives {
- p = Person{}
- log.Println(r.ID, r.Type, r.Name)
- id := strconv.Itoa(r.ID)
- if r.ID > 0 {
- log.Println("Person is in VK", id)
- p = get_profile(id)
- } else {
- log.Println("Person is absent in VK", id)
- p.FirstName = r.Name
- p.LastName = r.Name
- }
-
- switch r.Type {
- case "child":
- p.Generation = person.Generation - 1
- case "sibling":
- p.Generation = person.Generation
- case "parent":
- p.Generation = person.Generation + 1
- case "grandparent":
- p.Generation = person.Generation - 2
- case "grandchild":
- p.Generation = person.Generation + 2
- }
- Tree = append(Tree, p)
- process_person(p)
- }
- }
-
- relation := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
- if ValueInSlice(person.Relation, relation) {
- log.Println("no spouse")
- } else {
- p = Person{}
- id := strconv.Itoa(person.RelationPartner.ID)
- p = get_profile(id)
- Tree = append(Tree, p)
- process_person(p)
- }
- */
-
- prettyJSON, err := json.MarshalIndent(Tree, "", " ")
- if err != nil {
- panic(err)
- }
- log.Println(string(prettyJSON))
-}
blob - /dev/null
blob + 1f99cfae42baf5597a80791abf7acb63e25a8163 (mode 644)
--- /dev/null
+++ cmd/vk2gedcom/vk2gedcom.go
+/*
+
+Example: ./socialtree -id 233293686
+
+TreeWalk https://gist.github.com/abhat/71332461951830f9a0f5
+https://gist.github.com/zyxar/2317744
+https://golang.org/doc/play/tree.go
+https://github.com/alonsovidales/go_graph
+
+FIXME:
+ id181554010 (зацикливается)
+ id140022470 (зацикливается)
+
+*/
+
+package main
+
+import (
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "strconv"
+)
+
+type RawResponse struct {
+ Person []json.RawMessage `json:"response"`
+}
+
+type Person struct {
+ ID int `json:"id"`
+ FirstName string `json:"first_name"`
+ LastName string `json:"last_name"`
+ Sex int `json:"sex"`
+ Bdate string `json:"bdate"`
+ Photo_50 string `json:"photo_50"`
+ Relation int `json:"relation"`
+ Relatives []Relative `json:"relatives"`
+ RelationPartner RelPartner `json:"relation_partner"`
+ Generation int
+}
+
+type RelPartner struct {
+ ID int `json:"id"`
+ Name string `json:"name"`
+}
+
+type Relative struct {
+ ID int `json:"id"` // идентификатор пользователя
+ Type string `json:"type"` // тип родственной связи
+ Name string `json:"name"` // имя родственника
+}
+
+func ValueInSlice(n int, list []int) bool {
+ for _, i := range list {
+ if i == n {
+ return true
+ }
+ }
+ return false
+}
+
+func process_person(person Person) []Person {
+
+ var tree []Person
+ var p Person
+ if len(person.Relatives) != 0 {
+ for _, r := range person.Relatives {
+ p = Person{}
+ log.Println(r.ID, r.Type, r.Name)
+ id := strconv.Itoa(r.ID)
+ if r.ID > 0 {
+ log.Println("Person is in VK", id)
+ p = get_profile(id)
+ } else {
+ log.Println("Person is absent in VK", id)
+ p.FirstName = r.Name
+ p.LastName = r.Name
+ }
+
+ switch r.Type {
+ case "child":
+ p.Generation = person.Generation - 1
+ case "sibling":
+ p.Generation = person.Generation
+ case "parent":
+ p.Generation = person.Generation + 1
+ case "grandparent":
+ p.Generation = person.Generation - 2
+ case "grandchild":
+ p.Generation = person.Generation + 2
+ }
+ tree = append(tree, p)
+ process_person(p)
+ }
+ }
+
+ relation := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
+ if ValueInSlice(person.Relation, relation) {
+ log.Println("no spouse")
+ } else {
+ p = Person{}
+ id := strconv.Itoa(person.RelationPartner.ID)
+ p = get_profile(id)
+ tree = append(tree, p)
+ process_person(p)
+ }
+
+ return tree
+}
+
+func get_profile(id string) Person {
+
+ url := "https://api.vk.com/method/users.get?user_ids="
+ url = url + id
+ url = url + "&fields=first_name,last_name,photo_50,relatives,relation,bdate,sex&v=5.67"
+
+ res, err := http.Get(url)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ body, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ var raw RawResponse
+ err = json.Unmarshal(body, &raw)
+ if err != nil {
+ log.Fatal("Error parsing json: ", err)
+ }
+
+ var person Person
+ err = json.Unmarshal(raw.Person[0], &person)
+ if err != nil {
+ log.Fatal("Error parsing json: ", err)
+ }
+
+ var sex string
+ switch person.Sex {
+ case 1:
+ sex = "Ж"
+ case 2:
+ sex = "М"
+ default:
+ sex = "неизвестно"
+ }
+
+ log.Println(person.FirstName, person.LastName, sex, person.Bdate)
+ log.Println("\t", person.Relatives)
+
+ return person
+}
+
+func main() {
+
+ flag.Usage = func() {
+ fmt.Println("\nsocialtree is a tool for getting relations via VK.")
+ fmt.Println("\nUsage:")
+ flag.PrintDefaults()
+ }
+
+ var person_id = flag.String("id", "", "person id")
+
+ flag.Parse()
+
+ if *person_id == "" {
+ flag.Usage()
+ os.Exit(1)
+ }
+
+ var Tree []Person
+
+ person := get_profile(*person_id)
+ person.Generation = 0
+ Tree = append(Tree, person)
+ Tree = append(Tree, process_person(person)...) // new
+
+ /*
+ var p Person
+ if len(person.Relatives) != 0 {
+ for _, r := range person.Relatives {
+ p = Person{}
+ log.Println(r.ID, r.Type, r.Name)
+ id := strconv.Itoa(r.ID)
+ if r.ID > 0 {
+ log.Println("Person is in VK", id)
+ p = get_profile(id)
+ } else {
+ log.Println("Person is absent in VK", id)
+ p.FirstName = r.Name
+ p.LastName = r.Name
+ }
+
+ switch r.Type {
+ case "child":
+ p.Generation = person.Generation - 1
+ case "sibling":
+ p.Generation = person.Generation
+ case "parent":
+ p.Generation = person.Generation + 1
+ case "grandparent":
+ p.Generation = person.Generation - 2
+ case "grandchild":
+ p.Generation = person.Generation + 2
+ }
+ Tree = append(Tree, p)
+ process_person(p)
+ }
+ }
+
+ relation := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
+ if ValueInSlice(person.Relation, relation) {
+ log.Println("no spouse")
+ } else {
+ p = Person{}
+ id := strconv.Itoa(person.RelationPartner.ID)
+ p = get_profile(id)
+ Tree = append(Tree, p)
+ process_person(p)
+ }
+ */
+
+ prettyJSON, err := json.MarshalIndent(Tree, "", " ")
+ if err != nil {
+ panic(err)
+ }
+ log.Println(string(prettyJSON))
+}