commit 6fa62bae5d2b8a1d41f16837a255b243f8f85ec3 from: Sergey Bronnikov date: Sat Nov 02 13:57:48 2019 UTC Переименование commit - 6f8321e65ea37dceb515d4d8e7af11429aed9cc8 commit + 6fa62bae5d2b8a1d41f16837a255b243f8f85ec3 blob - 0c47c893e2c60ff4baa66a37594da624fa88c0ff (mode 644) blob + /dev/null --- cmd/gedcom2errors/main.go +++ /dev/null @@ -1,705 +0,0 @@ -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 @@ -0,0 +1,735 @@ +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 @@ -0,0 +1,194 @@ +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 @@ -1,194 +0,0 @@ -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 @@ -1,31 +0,0 @@ -/* - * 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 @@ -0,0 +1,31 @@ +/* + * 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 @@ -1,233 +0,0 @@ -/* - -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 @@ -0,0 +1,233 @@ +/* + +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)) +}