From 6aaa49e29279ee83a69a6c46e1f1febaaa7ea62d Mon Sep 17 00:00:00 2001 From: shmueldabomb441 Date: Tue, 1 Nov 2022 02:53:40 -0400 Subject: [PATCH 1/7] Fix serious mistake in documentation --- node_diff.go | 138 +++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 70 deletions(-) diff --git a/node_diff.go b/node_diff.go index 79bb9a6..c1e471f 100644 --- a/node_diff.go +++ b/node_diff.go @@ -2,29 +2,29 @@ // // CompareNodes recursively compares two nodes. For example: // -// 0 INDI @P3@ | 0 INDI @P4@ -// 1 NAME John /Smith/ | 1 NAME J. /Smith/ -// 1 BIRT | 1 BIRT -// 2 DATE 3 SEP 1943 | 2 DATE Abt. Sep 1943 -// 1 DEAT | 1 BIRT -// 2 PLAC England | 2 DATE 3 SEP 1943 -// 1 BIRT | 1 DEAT -// 2 DATE Abt. Oct 1943 | 2 DATE Aft. 2001 -// | 2 PLAC Surry, England +// 0 INDI @P3@ | 0 INDI @P4@ +// 1 NAME John /Smith/ | 1 NAME J. /Smith/ +// 1 BIRT | 1 BIRT +// 2 DATE 3 SEP 1943 | 2 DATE Abt. Sep 1943 +// 1 DEAT | 1 BIRT +// 2 PLAC England | 2 DATE 3 SEP 1943 +// 1 BIRT | 1 DEAT +// 2 DATE Abt. Oct 1943 | 2 DATE Aft. 2001 +// | 2 PLAC Surry, England // // Produces a *NodeDiff than can be rendered with the String method: // -// LR 0 INDI @P3@ -// L 1 NAME John /Smith/ -// LR 1 BIRT -// L 2 DATE Abt. Oct 1943 -// LR 2 DATE 3 SEP 1943 -// R 2 DATE Abt. Sep 1943 -// LR 1 DEAT -// L 2 PLAC England -// R 2 DATE Aft. 2001 -// R 2 PLAC Surry, England -// R 1 NAME J. /Smith/ +// LR 0 INDI @P3@ +// L 1 NAME John /Smith/ +// LR 1 BIRT +// L 2 DATE Abt. Oct 1943 +// LR 2 DATE 3 SEP 1943 +// R 2 DATE Abt. Sep 1943 +// LR 1 DEAT +// L 2 PLAC England +// R 2 DATE Aft. 2001 +// R 2 PLAC Surry, England +// R 1 NAME J. /Smith/ package gedcom import ( @@ -54,10 +54,10 @@ import ( // considered to be equal because the BirthNode.Equals regards all BirthNodes as // equal (see specific documentation for a complete explanation): // -// BIRT | BIRT | BIRT -// DATE 3 SEP 1943 | DATE 3 SEP 1943 | PLAC England -// BIRT | PLAC England | DATE 3 SEP 1943 -// PLAC England | | BIRT +// BIRT | BIRT | BIRT +// DATE 3 SEP 1943 | DATE 3 SEP 1943 | PLAC England +// BIRT | PLAC England | DATE 3 SEP 1943 +// PLAC England | | BIRT // // However, the semantics of Equals is quite different for other types of nodes. // For example ResidenceNodes are considered equal only if they have the same @@ -92,7 +92,7 @@ type NodeDiff struct { // If you need to be sure the root node are the equal after the comparison, you // can use (this is also nil safe): // -// d.Left.Equals(d.Right) +// d.Left.Equals(d.Right) // // The algorithm to perform the diff is actually very simple: // @@ -110,15 +110,15 @@ type NodeDiff struct { // // Here are two individuals that have slightly different data: // -// 0 INDI @P3@ | 0 INDI @P4@ -// 1 NAME John /Smith/ | 1 NAME J. /Smith/ -// 1 BIRT | 1 BIRT -// 2 DATE 3 SEP 1943 | 2 DATE Abt. Sep 1943 -// 1 DEAT | 1 BIRT -// 2 PLAC England | 2 DATE 3 SEP 1943 -// 1 BIRT | 1 DEAT -// 2 DATE Abt. Oct 1943 | 2 DATE Aft. 2001 -// | 2 PLAC Surry, England +// 0 INDI @P3@ | 0 INDI @P4@ +// 1 NAME John /Smith/ | 1 NAME J. /Smith/ +// 1 BIRT | 1 BIRT +// 2 DATE 3 SEP 1943 | 2 DATE Abt. Sep 1943 +// 1 DEAT | 1 BIRT +// 2 PLAC England | 2 DATE 3 SEP 1943 +// 1 BIRT | 1 DEAT +// 2 DATE Abt. Oct 1943 | 2 DATE Aft. 2001 +// | 2 PLAC Surry, England // // In this case both of the root nodes are different (because of the different // pointer values). The returned left and right will have the respective root @@ -126,18 +126,17 @@ type NodeDiff struct { // // Here is the output, rendered with NodeDiff.String(): // -// LR 0 INDI @P3@ -// L 1 NAME John /Smith/ -// LR 1 BIRT -// L 2 DATE Abt. Oct 1943 -// LR 2 DATE 3 SEP 1943 -// R 2 DATE Abt. Sep 1943 -// LR 1 DEAT -// L 2 PLAC England -// R 2 DATE Aft. 2001 -// R 2 PLAC Surry, England -// R 1 NAME J. /Smith/ -// +// LR 0 INDI @P3@ +// L 1 NAME John /Smith/ +// LR 1 BIRT +// L 2 DATE Abt. Oct 1943 +// LR 2 DATE 3 SEP 1943 +// R 2 DATE Abt. Sep 1943 +// LR 1 DEAT +// L 2 PLAC England +// R 2 DATE Aft. 2001 +// R 2 PLAC Surry, England +// R 1 NAME J. /Smith/ func CompareNodes(left, right Node) *NodeDiff { result := &NodeDiff{} @@ -218,17 +217,17 @@ func (nd *NodeDiff) string(indent int) string { // String returns a readable comparison of nodes, like: // -// LR 0 INDI @P3@ -// L 1 NAME John /Smith/ -// LR 1 BIRT -// L 2 DATE Abt. Oct 1943 -// LR 2 DATE 3 SEP 1943 -// R 2 DATE Abt. Sep 1943 -// LR 1 DEAT -// L 2 PLAC England -// R 2 DATE Aft. 2001 -// R 2 PLAC Surry, England -// R 1 NAME J. /Smith/ +// LR 0 INDI @P3@ +// L 1 NAME John /Smith/ +// LR 1 BIRT +// L 2 DATE Abt. Oct 1943 +// LR 2 DATE 3 SEP 1943 +// R 2 DATE Abt. Sep 1943 +// LR 1 DEAT +// L 2 PLAC England +// R 2 DATE Aft. 2001 +// R 2 PLAC Surry, England +// R 1 NAME J. /Smith/ // // The L/R/LR represent which side has the node, followed by the GEDCOM indent // and node line. @@ -237,8 +236,8 @@ func (nd *NodeDiff) string(indent int) string { // displayed as two separate lines even though they both belong to the same // NodeDiff: // -// LR 0 INDI @P3@ -// LR 0 INDI @P4@ +// LR 0 INDI @P3@ +// LR 0 INDI @P4@ // // You should not rely on this format to be machine readable as it may change in // the future. @@ -254,16 +253,15 @@ func (nd *NodeDiff) String() string { // The following diff (rendered with String) shows each NodeDiff and if it would // be considered DeepEqual: // -// LR 0 INDI @P3@ | false -// LR 1 NAME John /Smith/ | true -// LR 1 BIRT | false -// L 2 DATE Abt. Oct 1943 | false -// LR 2 DATE 3 SEP 1943 | true -// R 2 DATE Abt. Sep 1943 | false -// LR 1 DEAT | true -// LR 2 PLAC England | true -// R 1 NAME J. /Smith/ | false -// +// LR 0 INDI @P3@ | false +// LR 1 NAME John /Smith/ | true +// LR 1 BIRT | false +// L 2 DATE Abt. Oct 1943 | false +// LR 2 DATE 3 SEP 1943 | true +// R 2 DATE Abt. Sep 1943 | false +// LR 1 DEAT | true +// LR 2 PLAC England | true +// R 1 NAME J. /Smith/ | false func (nd *NodeDiff) IsDeepEqual() bool { leftIsNil := IsNil(nd.Left) rightIsNil := IsNil(nd.Right) @@ -345,7 +343,7 @@ func (nd *NodeDiff) LeftNode() Node { // RightNode returns the flattening Node value that favors the right side. // -// To favor means to return the Left value when both the Left and Right are set. +// To favor means to return the Right value when both the Left and Right are set. func (nd *NodeDiff) RightNode() Node { n := nd.Right From aa77bab812afdaccad7706bfceedf9432ef1ef2f Mon Sep 17 00:00:00 2001 From: shmueldabomb441 Date: Tue, 1 Nov 2022 02:55:38 -0400 Subject: [PATCH 2/7] Add diff table headers --- html/diff_page.go | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/html/diff_page.go b/html/diff_page.go index 47c39ad..2fe9b2c 100644 --- a/html/diff_page.go +++ b/html/diff_page.go @@ -6,6 +6,7 @@ import ( "github.com/elliotchance/gedcom/html/core" "github.com/elliotchance/gedcom/util" "io" + "os" "sort" ) @@ -177,8 +178,32 @@ func (c *DiffPage) WriteHTMLTo(w io.Writer) (int64, error) { precalculatedComparisons = append(precalculatedComparisons, comparison) } + args := os.Args + var rightGedcom string + var leftGedcom string + for index, arg := range args { + if arg == "-right-gedcom" { + rightGedcom = args[index+1] + continue + } + if arg == "-left-gedcom" { + leftGedcom = args[index+1] + continue + } + } + class := "text-center" + attr := map[string]string{} + headerTag := "h5" // The index at the top of the page. - rows := []core.Component{} + rows := []core.Component{ + core.NewTableRow( + core.NewTableCell( + core.NewTag(headerTag, attr, core.NewText(leftGedcom))).Class(class), + core.NewTableCell( + core.NewTag(headerTag, attr, core.NewText("Similarity score"))).Class(class), + core.NewTableCell( + core.NewTag(headerTag, attr, core.NewText(rightGedcom))).Class(class)), + } for _, comparison := range precalculatedComparisons { weightedSimilarity := c.weightedSimilarity(comparison.comparison) From 4b3b8c25b9a0d3637d88acd0d54dd8f3ed6b4d69 Mon Sep 17 00:00:00 2001 From: shmueldabomb441 Date: Tue, 1 Nov 2022 02:56:55 -0400 Subject: [PATCH 3/7] Refactor DiffRow creation logic into DiffPage.getRow() --- html/diff_page.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/html/diff_page.go b/html/diff_page.go index 2fe9b2c..0127e36 100644 --- a/html/diff_page.go +++ b/html/diff_page.go @@ -224,23 +224,7 @@ func (c *DiffPage) WriteHTMLTo(w io.Writer) (int64, error) { case c.filterFlags.HideEqual: continue } - - leftNameAndDates := NewIndividualNameAndDatesLink(comparison.comparison.Left, c.visibility, "") - rightNameAndDates := NewIndividualNameAndDatesLink(comparison.comparison.Right, c.visibility, "") - - left := core.NewTableCell(leftNameAndDates).Class(leftClass) - right := core.NewTableCell(rightNameAndDates).Class(rightClass) - - middle := core.NewTableCell(core.NewText("")) - if weightedSimilarity != 0 { - similarityString := fmt.Sprintf("%.2f%%", weightedSimilarity*100) - middle = core.NewTableCell(core.NewText(similarityString)). - Class("text-center " + leftClass) - } - - tableRow := core.NewTableRow(left, middle, right) - - rows = append(rows, tableRow) + rows = append(rows, c.getRow(comparison, leftClass, rightClass, weightedSimilarity)) } // Individual pages @@ -261,6 +245,24 @@ func (c *DiffPage) WriteHTMLTo(w io.Writer) (int64, error) { ).WriteHTMLTo(w) } +func (c *DiffPage) getRow(comparison *IndividualCompare, leftClass string, rightClass string, weightedSimilarity float64) *core.TableRow { + + leftNameAndDates := NewIndividualNameAndDatesLink(comparison.comparison.Left, c.visibility, "") + rightNameAndDates := NewIndividualNameAndDatesLink(comparison.comparison.Right, c.visibility, "") + + left := core.NewTableCell(leftNameAndDates).Class(leftClass) + right := core.NewTableCell(rightNameAndDates).Class(rightClass) + + middle := core.NewTableCell(core.NewText("")) + if weightedSimilarity != 0 { + similarityString := fmt.Sprintf("%.2f%%", weightedSimilarity*100) + middle = core.NewTableCell(core.NewText(similarityString)). + Class("text-center " + leftClass) + } + + return core.NewTableRow(left, middle, right) +} + func (c *DiffPage) shouldSkip(comparison *IndividualCompare) bool { switch c.show { case DiffPageShowAll: From f4eae94825b3f27cb950519957405de2f8b471c1 Mon Sep 17 00:00:00 2001 From: shmueldabomb441 Date: Tue, 1 Nov 2022 02:59:26 -0400 Subject: [PATCH 4/7] Add clarifying inline comments --- html/diff_page.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/html/diff_page.go b/html/diff_page.go index 0127e36..6c398f7 100644 --- a/html/diff_page.go +++ b/html/diff_page.go @@ -211,17 +211,17 @@ func (c *DiffPage) WriteHTMLTo(w io.Writer) (int64, error) { rightClass := "" switch { - case comparison.comparison.Left != nil && comparison.comparison.Right == nil: + case comparison.comparison.Left != nil && comparison.comparison.Right == nil: //right is missing leftClass = "bg-warning" - case comparison.comparison.Left == nil && comparison.comparison.Right != nil: + case comparison.comparison.Left == nil && comparison.comparison.Right != nil: //left is missing rightClass = "bg-primary" - case weightedSimilarity < 1: + case weightedSimilarity < 1: //neither are missing, but they aren't identical leftClass = "bg-info" rightClass = "bg-info" - case c.filterFlags.HideEqual: + case c.filterFlags.HideEqual: //neither are missing, and they are identical (therefore equal); if user said to hide equal, hide this row continue } rows = append(rows, c.getRow(comparison, leftClass, rightClass, weightedSimilarity)) From b7daf5c1a95f87d2e205107c397aab53919790bf Mon Sep 17 00:00:00 2001 From: shmueldabomb441 Date: Tue, 1 Nov 2022 03:19:34 -0400 Subject: [PATCH 5/7] Add check for ancestry sources, fixing #324 --- simple_node.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/simple_node.go b/simple_node.go index 62553c8..fc89328 100644 --- a/simple_node.go +++ b/simple_node.go @@ -61,7 +61,7 @@ func (node *SimpleNode) Identifier() string { if node == nil { return "" } - + return fmt.Sprintf("@%s@", node.pointer) } @@ -84,6 +84,24 @@ func (node *SimpleNode) Equals(node2 Node) bool { } tag := node2.Tag() + //if both Ancestry sources, only check if their _APID is the same + if node.Tag().String() == "Source" && tag.String() == "Source" { + found := false + ancestry: + for _, leftNode := range node.Nodes() { + for _, rightNode := range node2.Nodes() { + leftValue := leftNode.Value() + rightValue := rightNode.Value() + if leftNode.Tag().String() == "_APID" && rightNode.Tag().String() == "_APID" && rightValue == leftValue { + found = true + break ancestry + } + } + } + if found { //can't just return found, because they may be non-ancestry sources + return true + } + } if node.tag != tag { return false } From 1c27a5d134bfb84e6352fbc028866a666e158a23 Mon Sep 17 00:00:00 2001 From: shmueldabomb441 <60489781+shmueldabomb441@users.noreply.github.com> Date: Sat, 5 Nov 2022 22:36:46 -0400 Subject: [PATCH 6/7] Remove tabs in node_diff.go --- node_diff.go | 134 +++++++++++++++++++++++++-------------------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/node_diff.go b/node_diff.go index c1e471f..e7c5058 100644 --- a/node_diff.go +++ b/node_diff.go @@ -2,29 +2,29 @@ // // CompareNodes recursively compares two nodes. For example: // -// 0 INDI @P3@ | 0 INDI @P4@ -// 1 NAME John /Smith/ | 1 NAME J. /Smith/ -// 1 BIRT | 1 BIRT -// 2 DATE 3 SEP 1943 | 2 DATE Abt. Sep 1943 -// 1 DEAT | 1 BIRT -// 2 PLAC England | 2 DATE 3 SEP 1943 -// 1 BIRT | 1 DEAT -// 2 DATE Abt. Oct 1943 | 2 DATE Aft. 2001 -// | 2 PLAC Surry, England +// 0 INDI @P3@ | 0 INDI @P4@ +// 1 NAME John /Smith/ | 1 NAME J. /Smith/ +// 1 BIRT | 1 BIRT +// 2 DATE 3 SEP 1943 | 2 DATE Abt. Sep 1943 +// 1 DEAT | 1 BIRT +// 2 PLAC England | 2 DATE 3 SEP 1943 +// 1 BIRT | 1 DEAT +// 2 DATE Abt. Oct 1943 | 2 DATE Aft. 2001 +// | 2 PLAC Surry, England // // Produces a *NodeDiff than can be rendered with the String method: // -// LR 0 INDI @P3@ -// L 1 NAME John /Smith/ -// LR 1 BIRT -// L 2 DATE Abt. Oct 1943 -// LR 2 DATE 3 SEP 1943 -// R 2 DATE Abt. Sep 1943 -// LR 1 DEAT -// L 2 PLAC England -// R 2 DATE Aft. 2001 -// R 2 PLAC Surry, England -// R 1 NAME J. /Smith/ +// LR 0 INDI @P3@ +// L 1 NAME John /Smith/ +// LR 1 BIRT +// L 2 DATE Abt. Oct 1943 +// LR 2 DATE 3 SEP 1943 +// R 2 DATE Abt. Sep 1943 +// LR 1 DEAT +// L 2 PLAC England +// R 2 DATE Aft. 2001 +// R 2 PLAC Surry, England +// R 1 NAME J. /Smith/ package gedcom import ( @@ -54,10 +54,10 @@ import ( // considered to be equal because the BirthNode.Equals regards all BirthNodes as // equal (see specific documentation for a complete explanation): // -// BIRT | BIRT | BIRT -// DATE 3 SEP 1943 | DATE 3 SEP 1943 | PLAC England -// BIRT | PLAC England | DATE 3 SEP 1943 -// PLAC England | | BIRT +// BIRT | BIRT | BIRT +// DATE 3 SEP 1943 | DATE 3 SEP 1943 | PLAC England +// BIRT | PLAC England | DATE 3 SEP 1943 +// PLAC England | | BIRT // // However, the semantics of Equals is quite different for other types of nodes. // For example ResidenceNodes are considered equal only if they have the same @@ -92,7 +92,7 @@ type NodeDiff struct { // If you need to be sure the root node are the equal after the comparison, you // can use (this is also nil safe): // -// d.Left.Equals(d.Right) +// d.Left.Equals(d.Right) // // The algorithm to perform the diff is actually very simple: // @@ -110,15 +110,15 @@ type NodeDiff struct { // // Here are two individuals that have slightly different data: // -// 0 INDI @P3@ | 0 INDI @P4@ -// 1 NAME John /Smith/ | 1 NAME J. /Smith/ -// 1 BIRT | 1 BIRT -// 2 DATE 3 SEP 1943 | 2 DATE Abt. Sep 1943 -// 1 DEAT | 1 BIRT -// 2 PLAC England | 2 DATE 3 SEP 1943 -// 1 BIRT | 1 DEAT -// 2 DATE Abt. Oct 1943 | 2 DATE Aft. 2001 -// | 2 PLAC Surry, England +// 0 INDI @P3@ | 0 INDI @P4@ +// 1 NAME John /Smith/ | 1 NAME J. /Smith/ +// 1 BIRT | 1 BIRT +// 2 DATE 3 SEP 1943 | 2 DATE Abt. Sep 1943 +// 1 DEAT | 1 BIRT +// 2 PLAC England | 2 DATE 3 SEP 1943 +// 1 BIRT | 1 DEAT +// 2 DATE Abt. Oct 1943 | 2 DATE Aft. 2001 +// | 2 PLAC Surry, England // // In this case both of the root nodes are different (because of the different // pointer values). The returned left and right will have the respective root @@ -126,17 +126,17 @@ type NodeDiff struct { // // Here is the output, rendered with NodeDiff.String(): // -// LR 0 INDI @P3@ -// L 1 NAME John /Smith/ -// LR 1 BIRT -// L 2 DATE Abt. Oct 1943 -// LR 2 DATE 3 SEP 1943 -// R 2 DATE Abt. Sep 1943 -// LR 1 DEAT -// L 2 PLAC England -// R 2 DATE Aft. 2001 -// R 2 PLAC Surry, England -// R 1 NAME J. /Smith/ +// LR 0 INDI @P3@ +// L 1 NAME John /Smith/ +// LR 1 BIRT +// L 2 DATE Abt. Oct 1943 +// LR 2 DATE 3 SEP 1943 +// R 2 DATE Abt. Sep 1943 +// LR 1 DEAT +// L 2 PLAC England +// R 2 DATE Aft. 2001 +// R 2 PLAC Surry, England +// R 1 NAME J. /Smith/ func CompareNodes(left, right Node) *NodeDiff { result := &NodeDiff{} @@ -217,17 +217,17 @@ func (nd *NodeDiff) string(indent int) string { // String returns a readable comparison of nodes, like: // -// LR 0 INDI @P3@ -// L 1 NAME John /Smith/ -// LR 1 BIRT -// L 2 DATE Abt. Oct 1943 -// LR 2 DATE 3 SEP 1943 -// R 2 DATE Abt. Sep 1943 -// LR 1 DEAT -// L 2 PLAC England -// R 2 DATE Aft. 2001 -// R 2 PLAC Surry, England -// R 1 NAME J. /Smith/ +// LR 0 INDI @P3@ +// L 1 NAME John /Smith/ +// LR 1 BIRT +// L 2 DATE Abt. Oct 1943 +// LR 2 DATE 3 SEP 1943 +// R 2 DATE Abt. Sep 1943 +// LR 1 DEAT +// L 2 PLAC England +// R 2 DATE Aft. 2001 +// R 2 PLAC Surry, England +// R 1 NAME J. /Smith/ // // The L/R/LR represent which side has the node, followed by the GEDCOM indent // and node line. @@ -236,8 +236,8 @@ func (nd *NodeDiff) string(indent int) string { // displayed as two separate lines even though they both belong to the same // NodeDiff: // -// LR 0 INDI @P3@ -// LR 0 INDI @P4@ +// LR 0 INDI @P3@ +// LR 0 INDI @P4@ // // You should not rely on this format to be machine readable as it may change in // the future. @@ -253,15 +253,15 @@ func (nd *NodeDiff) String() string { // The following diff (rendered with String) shows each NodeDiff and if it would // be considered DeepEqual: // -// LR 0 INDI @P3@ | false -// LR 1 NAME John /Smith/ | true -// LR 1 BIRT | false -// L 2 DATE Abt. Oct 1943 | false -// LR 2 DATE 3 SEP 1943 | true -// R 2 DATE Abt. Sep 1943 | false -// LR 1 DEAT | true -// LR 2 PLAC England | true -// R 1 NAME J. /Smith/ | false +// LR 0 INDI @P3@ | false +// LR 1 NAME John /Smith/ | true +// LR 1 BIRT | false +// L 2 DATE Abt. Oct 1943 | false +// LR 2 DATE 3 SEP 1943 | true +// R 2 DATE Abt. Sep 1943 | false +// LR 1 DEAT | true +// LR 2 PLAC England | true +// R 1 NAME J. /Smith/ | false func (nd *NodeDiff) IsDeepEqual() bool { leftIsNil := IsNil(nd.Left) rightIsNil := IsNil(nd.Right) From d2dc4867952764188d6ac863d7d8bbe1f3d9c159 Mon Sep 17 00:00:00 2001 From: shmueldabomb441 Date: Sat, 5 Nov 2022 22:57:39 -0400 Subject: [PATCH 7/7] 1. Add ancestry-source-matching flag to toggle whether to perform that check 2. Make table responsive by setting viewport to device width and adding table class `table-responsive` (#327) 3. Add GEDCOM paths to DiffPage 4. Add how many are only in the right, left, and both GEDCOMs (#327) 5. Fix error in node_diff.go documentation 6. Optimize Ancestry source matching and test --- cmd/gedcom/diff.go | 5 ++-- html/core/page.go | 1 + html/core/table.go | 2 +- html/diff_page.go | 65 +++++++++++++++++++++++------------------- html/diff_page_test.go | 2 +- simple_node.go | 29 +++++++++---------- simple_node_test.go | 45 +++++++++++++++++++++++++++++ 7 files changed, 101 insertions(+), 48 deletions(-) diff --git a/cmd/gedcom/diff.go b/cmd/gedcom/diff.go index c5e0b97..1c12377 100644 --- a/cmd/gedcom/diff.go +++ b/cmd/gedcom/diff.go @@ -80,6 +80,8 @@ func runDiffCommand() { "The Google Analytics ID, like 'UA-78454410-2'.") flag.BoolVar(&optionProgress, "progress", false, "Show progress bar.") + //No reference because it is currently being accessed in SimpleNode.Equals(), so the only way to pass it to Equals() would be to pass it in every single SimpleNode. + flag.Bool("ancestry-source-matching", false, "Match Ancestry.com sources by Ancestry Source ID (_APID) instead of default matching algorithm (GEDCOM SOUR).") flag.IntVar(&optionJobs, "jobs", 1, util.CLIDescription(`Number of jobs to run in parallel. If you are comparing large trees this will make the process @@ -279,8 +281,7 @@ func runDiffCommand() { diffProgress := make(chan gedcom.Progress) page := html.NewDiffPage(comparisons, filterFlags, optionGoogleAnalyticsID, - optionShow, optionSort, diffProgress, compareOptions, html.LivingVisibilityShow) - + optionShow, optionSort, diffProgress, compareOptions, html.LivingVisibilityShow, optionLeftGedcomFile, optionRightGedcomFile) go func() { _, err = page.WriteHTMLTo(out) if err != nil { diff --git a/html/core/page.go b/html/core/page.go index 1d92edf..0f99877 100644 --- a/html/core/page.go +++ b/html/core/page.go @@ -31,6 +31,7 @@ func (c *Page) WriteHTMLTo(w io.Writer) (int64, error) { +
`) diff --git a/html/core/table.go b/html/core/table.go index bfa533b..2f491e0 100644 --- a/html/core/table.go +++ b/html/core/table.go @@ -18,7 +18,7 @@ func NewTable(tableClass string, content ...Component) *Table { } func (c *Table) WriteHTMLTo(w io.Writer) (int64, error) { - n := appendSprintf(w, ``, c.tableClass) + n := appendSprintf(w, `
`, c.tableClass) n += appendComponent(w, NewComponents(c.content...)) n += appendString(w, "
") diff --git a/html/diff_page.go b/html/diff_page.go index 6c398f7..7f73fea 100644 --- a/html/diff_page.go +++ b/html/diff_page.go @@ -6,7 +6,6 @@ import ( "github.com/elliotchance/gedcom/html/core" "github.com/elliotchance/gedcom/util" "io" - "os" "sort" ) @@ -34,9 +33,11 @@ type DiffPage struct { progress chan gedcom.Progress compareOptions *gedcom.IndividualNodesCompareOptions visibility LivingVisibility + leftGedcomPath string + rightGedcomPath string } -func NewDiffPage(comparisons gedcom.IndividualComparisons, filterFlags *gedcom.FilterFlags, googleAnalyticsID string, show, sort string, progress chan gedcom.Progress, compareOptions *gedcom.IndividualNodesCompareOptions, visibility LivingVisibility) *DiffPage { +func NewDiffPage(comparisons gedcom.IndividualComparisons, filterFlags *gedcom.FilterFlags, googleAnalyticsID string, show, sort string, progress chan gedcom.Progress, compareOptions *gedcom.IndividualNodesCompareOptions, visibility LivingVisibility, leftGedcomPath string, rightGedcomPath string) *DiffPage { return &DiffPage{ comparisons: comparisons, filterFlags: filterFlags, @@ -46,6 +47,8 @@ func NewDiffPage(comparisons gedcom.IndividualComparisons, filterFlags *gedcom.F progress: progress, compareOptions: compareOptions, visibility: visibility, + leftGedcomPath: leftGedcomPath, + rightGedcomPath: rightGedcomPath, } } @@ -178,32 +181,12 @@ func (c *DiffPage) WriteHTMLTo(w io.Writer) (int64, error) { precalculatedComparisons = append(precalculatedComparisons, comparison) } - args := os.Args - var rightGedcom string - var leftGedcom string - for index, arg := range args { - if arg == "-right-gedcom" { - rightGedcom = args[index+1] - continue - } - if arg == "-left-gedcom" { - leftGedcom = args[index+1] - continue - } - } - class := "text-center" - attr := map[string]string{} - headerTag := "h5" // The index at the top of the page. - rows := []core.Component{ - core.NewTableRow( - core.NewTableCell( - core.NewTag(headerTag, attr, core.NewText(leftGedcom))).Class(class), - core.NewTableCell( - core.NewTag(headerTag, attr, core.NewText("Similarity score"))).Class(class), - core.NewTableCell( - core.NewTag(headerTag, attr, core.NewText(rightGedcom))).Class(class)), - } + var rows []core.Component + numOnlyLeft := 0 + numOnlyRight := 0 + numSimilar := 0 + numEqual := 0 for _, comparison := range precalculatedComparisons { weightedSimilarity := c.weightedSimilarity(comparison.comparison) @@ -213,25 +196,49 @@ func (c *DiffPage) WriteHTMLTo(w io.Writer) (int64, error) { switch { case comparison.comparison.Left != nil && comparison.comparison.Right == nil: //right is missing leftClass = "bg-warning" + numOnlyLeft++ case comparison.comparison.Left == nil && comparison.comparison.Right != nil: //left is missing rightClass = "bg-primary" + numOnlyRight++ case weightedSimilarity < 1: //neither are missing, but they aren't identical leftClass = "bg-info" rightClass = "bg-info" + numSimilar++ - case c.filterFlags.HideEqual: //neither are missing, and they are identical (therefore equal); if user said to hide equal, hide this row + case c.filterFlags.HideEqual: //are identical, but user said to hide equals + numEqual++ continue + default: + numEqual++ } rows = append(rows, c.getRow(comparison, leftClass, rightClass, weightedSimilarity)) } + leftHeader := fmt.Sprint(c.leftGedcomPath, " (", numOnlyLeft, " only in left)") + rightHeader := fmt.Sprint(c.rightGedcomPath, " (", numOnlyRight, " only in right)") + class := "text-center" + attr := map[string]string{} + headerTag := "h5" + wereHidden := "" + if c.filterFlags.HideEqual { + wereHidden = " - were hidden" + } + middleHeader := fmt.Sprint("Similarity score", " (", numSimilar, " similar, and ", numEqual, " equal", wereHidden, ")") + header := []core.Component{core.NewTableRow( + core.NewTableCell( + core.NewTag(headerTag, attr, core.NewText(leftHeader))).Class(class), + core.NewTableCell( + core.NewTag(headerTag, attr, core.NewText(middleHeader))).Class(class), + core.NewTableCell( + core.NewTag(headerTag, attr, core.NewText(rightHeader))).Class(class))} + // Individual pages components := []core.Component{ core.NewSpace(), core.NewCard(core.NewText("Individuals"), core.CardNoBadgeCount, - core.NewTable("", rows...)), + core.NewTable("", append(header, rows...)...)), core.NewSpace(), } for _, comparison := range precalculatedComparisons { diff --git a/html/diff_page_test.go b/html/diff_page_test.go index a479ecc..4450edb 100644 --- a/html/diff_page_test.go +++ b/html/diff_page_test.go @@ -44,7 +44,7 @@ func TestDiffPage_WriteHTMLTo(t *testing.T) { compareOptions := gedcom.NewIndividualNodesCompareOptions() component := html.NewDiffPage(comparisons, filterFlags, googleAnalyticsID, html.DiffPageShowAll, html.DiffPageSortHighestSimilarity, nil, - compareOptions, html.LivingVisibilityPlaceholder) + compareOptions, html.LivingVisibilityPlaceholder, "left", "right") buf := bytes.NewBuffer(nil) component.WriteHTMLTo(buf) diff --git a/simple_node.go b/simple_node.go index fc89328..1ecfdc5 100644 --- a/simple_node.go +++ b/simple_node.go @@ -3,6 +3,7 @@ package gedcom import ( "bytes" "encoding/json" + "flag" "fmt" "sync" ) @@ -84,28 +85,26 @@ func (node *SimpleNode) Equals(node2 Node) bool { } tag := node2.Tag() + if node.tag != tag { + return false + } + + useAncestrySourceMatching := flag.Lookup("ancestry-source-matching").Value.String() //indexes a map CommandLine.formal //if both Ancestry sources, only check if their _APID is the same - if node.Tag().String() == "Source" && tag.String() == "Source" { - found := false - ancestry: + if useAncestrySourceMatching == "true" && node.Tag().String() == "Source" && tag.String() == "Source" { + if node.Value() == node2.Value() { //if they have the same source id, then no need to check the apid + return true + } for _, leftNode := range node.Nodes() { for _, rightNode := range node2.Nodes() { - leftValue := leftNode.Value() - rightValue := rightNode.Value() - if leftNode.Tag().String() == "_APID" && rightNode.Tag().String() == "_APID" && rightValue == leftValue { - found = true - break ancestry + if leftNode.Tag().String() == "_APID" && + rightNode.Tag().String() == "_APID" && + rightNode.Value() == leftNode.Value() { + return true } } } - if found { //can't just return found, because they may be non-ancestry sources - return true - } - } - if node.tag != tag { - return false } - value := node2.Value() if node.value != value { return false diff --git a/simple_node_test.go b/simple_node_test.go index 541acf3..ae7ca75 100644 --- a/simple_node_test.go +++ b/simple_node_test.go @@ -64,6 +64,51 @@ func TestSimpleNode_Equals(t *testing.T) { } } +func TestAncestryNode_Equals(t *testing.T) { + //test when source ids are the same + original := GetAncestryIndividual("@S291470533@", "@S291470520@", "@S291470520@", "@S291470520@", "@S291470520@") + assert.True(t, gedcom.DeepEqualNodes(gedcom.newDocumentFromString(original).Nodes(), gedcom.newDocumentFromString(original).Nodes())) + + //test when source ids are different, but _apid stays the same + left := gedcom.newDocumentFromString(GetAncestryIndividual("@S222222222@", "@S444444444@", "@S666666666@", "@S888888888@", "@S111111111@")) + right := gedcom.newDocumentFromString(GetAncestryIndividual("@S333333333@", "@S555555555@", "@S777777777@", "@S999999999@", "@S000000000@")) + assert.True(t, gedcom.DeepEqualNodes(left.Nodes(), right.Nodes())) +} + +// This is an actual gedcom entry, hope that's ok. +func GetAncestryIndividual(source1 string, source2 string, source3 string, source4 string, source5 string) string { + return "0 @I152151456706@ INDI" + + "\n1 NAME Jacob /Yourow/" + + "\n2 GIVN Jacob" + + "\n2 SURN Yourow" + + "\n2 SOUR " + source1 + + "\n3 PAGE New York City Municipal Archives; New York, New York; Borough: Manhattan; Volume Number: 13" + + "\n3 _APID 1,61406::6159341" + + "\n2 SOUR " + source2 + + "\n3 PAGE Year: 1930; Census Place: Bronx, Bronx, New York; Page: 42A; Enumeration District: 0430; FHL microfilm: 2341213" + + "\n3 _APID 1,6224::30826480" + + "\n1 SEX M" + + "\n1 FAMS @F89@" + + "\n1 BIRT" + + "\n2 DATE abt 1888" + + "\n2 PLAC Russia" + + "\n2 SOUR " + source3 + + "\n3 PAGE Year: 1930; Census Place: Bronx, Bronx, New York; Page: 42A; Enumeration District: 0430; FHL microfilm: 2341213" + + "\n3 _APID 1,6224::30826480" + + "\n1 EVEN" + + "\n2 TYPE Arrival" + + "\n2 DATE 1905" + + "\n2 SOUR " + source4 + + "\n3 PAGE Year: 1930; Census Place: Bronx, Bronx, New York; Page: 42A; Enumeration District: 0430; FHL microfilm: 2341213" + + "\n3 _APID 1,6224::30826480" + + "\n1 RESI Marital Status: Married; Relation to Head: Head" + + "\n2 DATE 1930" + + "\n2 PLAC Bronx, Bronx, New York, USA" + + "\n2 SOUR " + source5 + + "\n3 PAGE Year: 1930; Census Place: Bronx, Bronx, New York; Page: 42A; Enumeration District: 0430; FHL microfilm: 2341213" + + "\n3 _APID 1,6224::30826480" +} + func TestSimpleNode_Tag(t *testing.T) { Tag := tf.Function(t, (*gedcom.SimpleNode).Tag)