* ADOP and PEDI tags.

Writing and using plugins for Version 5 and above.
Post Reply
User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

ADOP and PEDI tags.

Post by Ron Melby » 27 Oct 2020 19:38

Code: Select all

function rtvfID(fptr)

  local var     = type(fptr)
  if var == 'userdata' then
    local ptrtype = fhGetTag(fptr)

    if ptrtype == 'FAMC' 
    or ptrtype == 'FAMS' then
      fptr = fhGetValueAsLink(fptr) 
    end
  elseif var == 'number' then
    local xptr = fhNewItemPtr()
    xptr:MoveToRecordById('FAM', fptr)
    fptr = xptr:Clone()
  else
    return
  end

  local mdptr = fhNewItemPtr()
  local fmdat = fhNewDate()
  mdptr = fhGetItemPtr(mdptr, '~.MARR.DATE:COMPACT')
  if mdptr:IsNotNull() then
    fmdat = fhGetValueAsDate(mdptr)
  end
  
  local ddptr = fhNewItemPtr()
  local dmdat = fhNewDate()
  ddptr = fhGetItemPtr(ddptr, '~.MARR.DATE:COMPACT')
  if ddptr:IsNotNull() then
    dmdat = fhGetValueAsDate(ddptr)
  end

  local _cs = 
  {
    fID   = fhGetRecordId(fptr), 
    fptr  = fptr:Clone(), 
    mdptr = mdptr:Clone(),
    fmdat = fmdat,
    ddptr = ddptr:Clone(),
    dmdat = dmdat,
  }

  return _cs
end -- fn matfID

function rtvFAMCtbl(iptr) 
  local ptrFAMC = fhNewItemPtr() -- all famc
  local lnkFAMC = fhNewItemPtr() -- FAM pointer
  local ptrADOP = fhNewItemPtr() -- ADOP
  local lnkADOP = fhNewItemPtr()
  local this    = fhNewItemPtr()
  local pedi    = ''
  local famc    = {}
  local fc      = 0

  ptrFAMC:MoveTo(iptr, '~.FAMC')
  while ptrFAMC:IsNotNull() do
    --   lnkFAMC = fhGetValueAsLink(ptrFAMC)
    pedi = fhGetItemText(iptr, '.PEDI')
    ptrADOP = fhGetItemPtr(iptr, '~.ADOP.FAMC')
    if ptrADOP:IsNotNull() then
      lnkADOP = fhGetValueAsLink(ptrADOP)
      _ac = rtvfID(lnkADOP)
    end
    fc = fc + 1
    famc[fc] = rtvfID(ptrFAMC)

    ptrFAMC:MoveNext('SAME_TAG')
  end
  return famc
end -- fn rtvFAMCtbl
I am probably staring at the elegant solution and have been for some time, but I never have worked this out satisfactorily, and it is a neccessity now:

the problem lies with ptrADOP and pedi. I am not sure I can desribe it.
this is part of a much larger program.

forget for the moment that I will return a table with from 1 ... n entries in order that is not encoded yet:

famc = (will be)
{}

or

[1] {
fID = fhGetRecordId(ptrFAMC),
fpa = ['', 'PEDI' 'ADOP'],
fpp = ['', 'HUSB' 'WIFE', 'BOTH'],
}

or

[1] {
fID = fhGetRecordId(ptrFAMC),
fpa = ['', 'PEDI' 'ADOP'],
fpp = ['', 'HUSB' 'WIFE', 'BOTH'],
}


[2] {
fID = fhGetRecordId(ptrFAMC),
fpa = ['', 'PEDI' 'ADOP'],
fpp = ['', 'HUSB' 'WIFE', 'BOTH'],
}

and so on.

I cannot think of an efficient way to link either ADOP or PEDI to the correct FAMC in one fell swoop.
It seems that I sort of need a ptrCPLX = fhGetItemPtr(iptr, ptrFAMC, '~.ADOP' sort of thing... something simple is escaping me.

my tags are all in the form:
1 FAMC @F132@
2 PEDI Foster

1 ADOP
2 FAMC @F1796@
3 ADOP BOTH


Thanks.
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 29 Oct 2020 17:18

nope, no way to do it in one fell swoop.
I have gotten it in 2 swoops, a reduction from 3 swoops.
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 29 Oct 2020 18:13

and yet there is a fly in the ointment.

in order to address this:

--TYPE 1:
1 FAMC @F37@
2 _PEDI De Facto (father)

as well as this:

--TYPE 2:
1 FAMC @F37@
2 _PEDI De Facto (father)
2 _PEDI Birth (mother)

I went from this:

-- works for TYPE 1 NOT for TYPE 2:
ptrPEDI = fhGetItemPtr(ptrFAMC, '~.PEDI')
if ptrPEDI:IsNotNull{} then
-- TODO string sub into two parts
fpa = fhGetValueAsText(ptrPEDI)
fby = fhGetValueAsText(ptrPEDI)
end


to this:
-- does not work for TYPE 1 or TYPE2
if ptrPEDI:IsNotNull{} then
fpa = fhGetValueAsText(ptrPEDI)
ptrTEXT = fhGetItemPtr(ptrPEDI, '~._PEDI[1]')
fby = fhGetValueAsText(ptrTEXT)
ptrTEXT = fhGetItemPtr(ptrPEDI, '~._PEDI[2]')
fb2 = fhGetValueAsText(ptrTEXT)
end

apparently, ._PEDI is not an array , nothing is returned.

How do I address both cases? Thanks.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 19152
Joined: 25 May 2010 11:00
Family Historian: V6.2
Location: Torbay, Devon, UK
Contact:

Re: ADOP and PEDI tags.

Post by tatewise » 29 Oct 2020 18:35

Do as I suggested before and put a breakpoint on your script and step through to see what each variable holds.

HINT:
fhGetItemPtr(ptrPEDI, '~._PEDI[1]') is looking for INDI.FAMC.PEDI._PEDI[1] which does NOT exist.

fhGetItemPtr(ptrFAMC, '~.PEDI') you know finds INDI.FAMC.PEDI which you know exists.

fhGetItemPtr(ptrFAMC, '~._PEDI[1]') is looking for INDI.FAMC._PEDI[1] which does exist as in TYPE 1.
fhGetItemPtr(ptrFAMC, '~._PEDI[2]') is looking for INDI.FAMC._PEDI[2] which does exist as in TYPE 2.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 29 Oct 2020 20:02

OIC, a kludge, don't believe the tags. LOL, simple enough. Thanks.
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 30 Oct 2020 13:24

For those of you that are GEDCOM tag familiar, I have a 'situation' in my files with ADOP tags v FAMC tags. One of these things is true:

1) I have at some point in the halcyon days of yore, monkeyed up this file by hand.
2) This is normal behavior and can be produced by FH, depending on some action I have taken, and simply a programming issue (for me, which I have resolved).
3) This is incorrect behavior and FH has an issue, and needs a ticket.

Now to cases:
Let @F1@ represent the BIRTH FAMC
Let @F2@ represent the ADOP FAMC

TYPE 1:
1 ADOP
2 FAMC @F2@
3 ADOP HUSB (situational only to the 'by' TAG can be '', HUSB, WIFE, BOTH no difference in occurance)
1 FAMC @F2@

ADOP FAMC is the only FAMC known, and is therefore correct, and INDI displays in FAMC 2 focus window.


TYPE 2:
1 ADOP
2 FAMC @F2@
3 ADOP HUSB (situational only to the 'by' TAG can be '', HUSB, WIFE, BOTH no difference in occurance)
1 FAMC @F1@

ADOP FAMC only appears as an ADOP sequence, and CHIL displays in FAMC 1 focus window, and FAMC 2 focus window (if known.*)

TYPE 3:
1 ADOP
2 FAMC @F2@
3 ADOP BOTH (situational only to the 'by' TAG can be '', HUSB, WIFE, BOTH no difference in occurance)
1 FAMC @F1@
1 FAMC @F2@

ADOP FAMC appears as an ADOP sequence and as FAMC (in the correct time order), and CHIL displays in FAMC 1 focus window, and FAMC 2 focus window (if known.*)

* I have to know it somehow, both fams do not show on focus of INDI, and not sure how that would be logically displayed anyhow.

in either case, there is no difference in display, and FH validation does not complain, but several analyzers do.

In one sense, there should be no TYPE 2, it should be TYPE 1 and TYPE 3 logially extending TYPE 1, philisophically. But perhaps it is a distinction without a difference. I am not sure that the standard clearly defines the case.

Those of you with ADOP in your GEDCOM do you have mixed cases TYPE 2 and TYPE 3?

Thoughts, opinions, knowledge?

Thanks.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 19152
Joined: 25 May 2010 11:00
Family Historian: V6.2
Location: Torbay, Devon, UK
Contact:

Re: ADOP and PEDI tags.

Post by tatewise » 30 Oct 2020 14:02

They are all valid GEDCOM data structures.

The INDI.ADOP.FAMC.ADOP Adoption Event subsidiary FAMC.ADOP structure is rarely supported by other products.
Even in FH it is only supported via the All tab simply to support its claim of 100% GEDCOM compatibility.
It is NOT supported anywhere else. I would advise you to avoid using it.

The INDI.FAMC Family as Child relationship instances appear in the Focus Window and supported by most other products.
The INDI.FAMC.PEDI structure allows the Adoption Family to be identified.
I would advise that you only use these structures.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 01 Nov 2020 15:53

converted most of my file to PEDI tags from Adopted tags, and I am faced with the following problem.

Set 1:
2 _PEDI Adopted (father)
2 _PEDI Adopted

Set 2:
2 _PEDI De Facto (father)
2 _PEDI De Facto

given the tags, I am currently parsing them with:

fpa, fby = TXT:match('^(.+)%((.+)%)$')
** ^ in result denotes space char
Set 1 tag 1 results in 'Adopted^' 'father'
Set 1 tag 2 results in 'Adopted'

I cannot fathom a way to remove the end space in the Set 1 tag 1 capture in situ without clobbering Set 2 tags capture. I have looked all over, and while I have a rudimentary understanding of patterns, I am still murky in nuanced matching.

is there a way? thanks.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 19152
Joined: 25 May 2010 11:00
Family Historian: V6.2
Location: Torbay, Devon, UK
Contact:

Re: ADOP and PEDI tags.

Post by tatewise » 01 Nov 2020 17:29

fpa, fby = TXT:match('^(.+) %((.+)%)$') will cope with both Adopted (father) and De Facto (father)

The point is that the ' %(' space bracket pair is unique and can only match the last space and the opening bracket.

But this revised pattern and your original pattern cannot match Adopted and De Facto but I'm not sure if you expected that.

It is not possible to match all four forms of _PEDI values with one pattern.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 01 Nov 2020 17:40

I see what you mean, and it only worked on the first couple adopted pedis I have, its useless on anything else, now I am farther away than what I thought I was
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 19152
Joined: 25 May 2010 11:00
Family Historian: V6.2
Location: Torbay, Devon, UK
Contact:

Re: ADOP and PEDI tags.

Post by tatewise » 01 Nov 2020 18:05

Farther away from what? Please explain your objective to save me having to guess.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 02 Nov 2020 01:09

Code: Select all

function rtvFAMCtbl(iptr) 
  local _cvt =
  {
    ['Adopted'] = 'ADOP',
    ['Foster']  = 'FOSTER',
    ['Step']    = 'STEP',

    ['father']   = 'HUSB',
    ['mother']   = 'WIFE',

    ['']         = '',
  }

  local ptrFAMC  = fhNewItemPtr()
  local ptrPEDI  = fhNewItemPtr()

  local ptrTXT   = fhNewItemPtr()
  local TXT      = ''

  local ptrADOP  = fhNewItemPtr()
  local ptrITER  = fhNewItemPtr()
  local tag      = ''

  local famc     = {}
  local fc       = 0

  local ptxt     = {}
  local p        = 0 
  local fpa      = ''
  local fby      = ''

  ptrFAMC = fhGetItemPtr(iptr, '~.FAMC')
  while ptrFAMC:IsNotNull() do
    local _fs  = rtvfID(ptrFAMC)
    local fPTR = _fs.fPTR:Clone()
    local fID  = _fs.fID

    ptrPEDI = fhGetItemPtr(ptrFAMC, '~.PEDI')
    if ptrPEDI:IsNotNull{} then
      ptrTXT = fhGetItemPtr(ptrFAMC, '~.PEDI[1]')
      TXT    = fhGetValueAsText(ptrTXT)
      fpa, fby = TXT:match('^(.+) ?%((.+)%)$')
      if fpa == nil then
        fpa = TXT:match('^(.+)$')
        fby = ''
      end
      if _cvt[fpa] then 
        p = 1
        ptxt[p] = 
        {
          fpa = _cvt[fpa],
          fby = _cvt[fby],
        }

        ptrTXT = fhGetItemPtr(fPTR, '~.PEDI[2]')
        TXT = fhGetValueAsText(ptrTXT)
        fpa, fby = TXT:match('^(.+) ?%((.+)%)$')
        if fpa == nil then
          fpa = TXT:match('^(.+)$')
          fby = ''
        end
        if _cvt[fpa] then 
          p = p + 1
          ptxt[p] = 
          {
            fpa = _cvt[fpa],
            fby = _cvt[fby],
          }
        end
        if #ptxt == 1 then
          fpa = ptxt[1].fpa
          fby = ptxt[1].fby
        elseif #ptxt == 2 then
          if ptxt[1].fpa == ptxt[2].fpa 
          and ptxt[1].fby == 'HUSB'
          and ptxt[2].fby == 'WIFE' then
            fpa = ptxt[1].fpa
            fby = 'BOTH'
          else
            fpa = '*ERR'
            fby = '(**)'
          end
        end
      end
    end

    fc = fc + 1
    famc[fc] =   
    {
      fPTR = fPTR:Clone(),  
      fID  = fID,
      fpa  = fpa, 
      fby  = fby, -- 'HUSB' 'WIFE', 'BOTH'
    }
    ptrFAMC:MoveNext('SAME_TAG')
  end

  ptrITER = fhGetItemPtr(iptr, '~.ADOP')
  while ptrITER:IsNotNull() do
    ptrADOP = fhGetItemPtr(ptrITER, '~.FAMC')
    ptrTXT  = fhGetItemPtr(ptrADOP, '~.ADOP')
    tag     = fhGetTag(ptrTXT)
    fby     = fhGetValueAsText(ptrTXT)
    ptrADOP = fhGetValueAsLink(ptrADOP)
    local infamc = nil
    for k, _ in ipairs(famc) do
      if ptrADOP:IsSame(famc[k].fPTR) then
        famc[k].fpa  = tag
        famc[k].fby  = fby
        infamc = true
      end
    end

    if not infamc then
      local _fs  = rtvfID(ptrADOP)
      local fPTR = _fs.fPTR
      local fID  = _fs.fID

      fc = fc + 1
      famc[fc] =   
      {
        fPTR = fPTR:Clone(),  
        fID  = fID,
        fpa  = tag,
        fby  = fby, 
      }
    end

    ptrITER:MoveNext('SAME_TAG')
  end

  return famc
end -- fn rtvFAMCtbl
from having lean, and elegant code. This is how it stands at present, and it aint pretty. It seems to handle everything correctly. I have one of those *miracle occurs here* bits if _PEDI[1] and PEDI[2] fpa (first parts of the pedi tag) are not equal. To me, I can understand no situation in which that would not be an error, logically.

maybe looking you can see some shortcuts. or more elegant solutions to covering the cases. I have written spaghetti before that you have streamlined by cutting out yards of code.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 19152
Joined: 25 May 2010 11:00
Family Historian: V6.2
Location: Torbay, Devon, UK
Contact:

Re: ADOP and PEDI tags.

Post by tatewise » 02 Nov 2020 10:44

You are joking :D
You say "It seems to handle everything correctly." but I don't know what you are trying to handle.
There is not one word of explanatory comment in the code, so what is the purpose of each section?
It is extremely time-consuming to tidy code when I don't know what it is trying to achieve.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 02 Nov 2020 13:10

Code: Select all

function rtvfID(fptr)
  local _cs = matfID(fptr)
  return _cs
end -- fn rtvfID

-- materialize FAM RCD ID
function matfID(fptr)

  local _ptyp  = type(fptr)

  if _ptyp == 'userdata' then
    local _ptag  = fhGetTag(fptr)
    if _ptag == 'FAMC' 
    or _ptag == 'FAMS' then
      fptr = fhGetValueAsLink(fptr) 
    end
  elseif _ptyp == 'number' then
    local xptr = fhNewItemPtr()
    xptr:MoveToRecordById('FAM', fptr)
    fptr = xptr:Clone()
  else
    return
  end

  local mdptr = fhNewItemPtr()
  local fmdat = fhNewDate()
  local ddptr = fhNewItemPtr()
  local dmdat = fhNewDate()

  mdptr = fhGetItemPtr(fptr, '~.MARR.DATE:COMPACT')
  if mdptr:IsNotNull() then
    fmdat = fhGetValueAsDate(mdptr)
  end

  ddptr = fhGetItemPtr(fptr, '~.DIV.DATE:COMPACT')
  if ddptr:IsNotNull() then
    dmdat = fhGetValueAsDate(ddptr)
  end

  local _cs = 
  {
    fID   = fhGetRecordId(fptr), 
    fPTR  = fptr:Clone(), 
    mdptr = mdptr:Clone(),
    fmdat = fmdat,
    ddptr = ddptr:Clone(),
    dmdat = dmdat,
  }

  local _fn = debug.getinfo(2, 'n')
  if string.sub(_fn.name or '', 1, 3) ~= 'rtv' then
    cw.mdt = math.max(cw.mdt, #tostring(_cs.fmdat))
    cw.mdt = math.max(cw.mdt, #tostring(_cs.dmdat))
    for ged, add in pairs(_cs) do 
      GEDRCD[#GEDRCD][ged] = add
    end
  end
  return _cs
end -- fn matfID




function rtvFAMCtbl(iptr) 

  -- make std PEDI ADOP info
  -- disregard LDS 
  -- De Facto and Birth are di minimus
  local _cvt =
  {
    ['Adopted'] = 'ADOP',
    ['Foster']  = 'FOSTER',
    ['Step']    = 'STEP',

    ['father']   = 'HUSB',
    ['mother']   = 'WIFE',

    ['']         = '',
  }

  local ptrFAMC  = fhNewItemPtr() -- FAMC
  local ptrPEDI  = fhNewItemPtr() -- PEDI

  local ptrTXT   = fhNewItemPtr() 
  local TXT      = ''

  local ptrADOP  = fhNewItemPtr()  --adop
  local ptrITER  = fhNewItemPtr()  -- adop iterator
  local tag      = ''

  local famc     = {} -- family as child table
  local fc       = 0  -- family as child index

  local ptxt     = {} -- sorting out pedi tag text
  local p        = 0  -- ptxt index 
  local fpa      = '' -- tag of pedi type or adop
  local fby      = '' -- HUSB WIFE BOTH ''

  ptrFAMC = fhGetItemPtr(iptr, '~.FAMC')
  while ptrFAMC:IsNotNull() do
    local _fs  = rtvfID(ptrFAMC)  -- returns an array of FAMC items rtvfID-matfID above
    local fPTR = _fs.fPTR:Clone() -- PTRFAMC:Clone() 
    local fID  = _fs.fID          -- fhRecordId(PTRFAMC   

    ptrPEDI = fhGetItemPtr(ptrFAMC, '~.PEDI')
    if ptrPEDI:IsNotNull{} then
      ptrTXT = fhGetItemPtr(ptrFAMC, '~.PEDI[1]') -- get first _PEDI
      TXT    = fhGetValueAsText(ptrTXT) 
      fpa, fby = TXT:match('^(.+) ?%((.+)%)$')    -- parse out (ie) 'Adopted' 'father'
      if fpa == nil then
        fpa = TXT:match('^(.+)$') -- parse out 'Adopted' (short type pedi)
        fby = '' --  no by whom 
      end
      if _cvt[fpa] then  -- if its in the list of interest
        p = 1 
        ptxt[p] =  
        {
          fpa = _cvt[fpa],
          fby = _cvt[fby], 
        }   -- hold it

        ptrTXT = fhGetItemPtr(fPTR, '~.PEDI[2]')  -- get the second
        TXT = fhGetValueAsText(ptrTXT)
        fpa, fby = TXT:match('^(.+) ?%((.+)%)$')  -- parse out (ie) 'Adopted' 'Wife'
        if fpa == nil then
          fpa = TXT:match('^(.+)$') -- parse out short form 'Adopted' (should not happen in a PEDI[2]
          fby = ''
        end
        if _cvt[fpa] then  -- if of interest
          p = p + 1
          ptxt[p] = 
          {
            fpa = _cvt[fpa],
            fby = _cvt[fby],
          } --hold it 
        end
        if #ptxt == 1 then  --one entry post it and fall thru
          fpa = ptxt[1].fpa
          fby = ptxt[1].fby
        elseif #ptxt == 2 then
          if ptxt[1].fpa == ptxt[2].fpa    -- if the tags are equal then by is 'BOTH'
          and ptxt[1].fby == 'HUSB'
          and ptxt[2].fby == 'WIFE' then
            fpa = ptxt[1].fpa
            fby = 'BOTH'
          else
            fpa = '*ERR'  -- if tags are not = (ie) 'STEP' 'ADOP' then throw error
            fby = '(**)'
          end
        end
      end
    end
--pedis are reduced to 1 if any or the fields are blank
    fc = fc + 1
    famc[fc] =   
    {
      fPTR = fPTR:Clone(),  
      fID  = fID,
      fpa  = fpa, -- 'ADOP', 'STEP', '' so on from cvt or default
      fby  = fby, -- 'HUSB' 'WIFE', 'BOTH' '' from cvt or default
    }
    ptrFAMC:MoveNext('SAME_TAG')   -- exhaust FAMC tags fil famc array 
  end

  ptrITER = fhGetItemPtr(iptr, '~.ADOP')          -- separate ADOP events 2nd round 
  while ptrITER:IsNotNull() do
    ptrADOP = fhGetItemPtr(ptrITER, '~.FAMC')     -- for this FAMC 
    ptrTXT  = fhGetItemPtr(ptrADOP, '~.ADOP')
    tag     = fhGetTag(ptrTXT)
    fby     = fhGetValueAsText(ptrTXT)
    ptrADOP = fhGetValueAsLink(ptrADOP)
    local infamc = nil                             -- is it in famc already?   
    for k, _ in ipairs(famc) do
      if ptrADOP:IsSame(famc[k].fPTR) then
        famc[k].fpa  = tag
        famc[k].fby  = fby
        infamc = true                              -- update the ADOP info and by info    
      end
    end

    if not infamc then                             -- case where not a naked FAMC as well 
      local _fs  = rtvfID(ptrADOP)                 -- see rtvfID-mat_fID
      local fPTR = _fs.fPTR
      local fID  = _fs.fID

      fc = fc + 1
      famc[fc] =   
      {
        fPTR = fPTR:Clone(),  
        fID  = fID,
        fpa  = tag,
        fby  = fby, 
      }                                             -- add it
    end

    ptrITER:MoveNext('SAME_TAG')                    -- exhaust adop tags
  end

  return famc
end -- fn rtvFAMCtbl
*annotated. not joking. :lol:
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 19152
Joined: 25 May 2010 11:00
Family Historian: V6.2
Location: Torbay, Devon, UK
Contact:

Re: ADOP and PEDI tags.

Post by tatewise » 03 Nov 2020 13:41

Try this script. Yours did NOT handle everything correctly. So your debugging was incomplete.
It did NOT check for both PEDI and _PEDI and the ADOP values for HUSB & WIFE & BOTH were wrong.

This script has simplified and corrected the get PEDI & _PEDI tag block.
It corrects the Husband, Wife, Both values.
It does not yet cope with INDI.FAMC._PEDI = Adopted (father) and INDI.ADOP.FAMC.ADOP = Wife and convert to Both.

Code: Select all

function rtvfID(fptr)
  local _cs = matfID(fptr)
  return _cs
end -- fn rtvfID

-- materialize FAM RCD ID
function matfID(fptr)

  local _ptyp  = type(fptr)

  if _ptyp == 'userdata' then
    local _ptag  = fhGetTag(fptr)
    if _ptag == 'FAMC' 
    or _ptag == 'FAMS' then
      fptr = fhGetValueAsLink(fptr) 
    end
  elseif _ptyp == 'number' then
    local xptr = fhNewItemPtr()
    xptr:MoveToRecordById('FAM', fptr)
    fptr = xptr:Clone()
  else
    return
  end

  local mdptr = fhNewItemPtr()
  local fmdat = fhNewDate()
  local ddptr = fhNewItemPtr()
  local dmdat = fhNewDate()

  mdptr = fhGetItemPtr(fptr, '~.MARR.DATE:COMPACT')
  if mdptr:IsNotNull() then
    fmdat = fhGetValueAsDate(mdptr)
  end

  ddptr = fhGetItemPtr(fptr, '~.DIV.DATE:COMPACT')
  if ddptr:IsNotNull() then
    dmdat = fhGetValueAsDate(ddptr)
  end

  local _cs = 
  {
    fID   = fhGetRecordId(fptr), 
    fPTR  = fptr:Clone(), 
    mdptr = mdptr:Clone(),
    fmdat = fmdat,
    ddptr = ddptr:Clone(),
    dmdat = dmdat,
  }

  local _fn = debug.getinfo(2, 'n')
  if string.sub(_fn.name or '', 1, 3) ~= 'rtv' then
    cw.mdt = math.max(cw.mdt, #tostring(_cs.fmdat))
    cw.mdt = math.max(cw.mdt, #tostring(_cs.dmdat))
    for ged, add in pairs(_cs) do 
      GEDRCD[#GEDRCD][ged] = add
    end
  end
  return _cs
end -- fn matfID

function rtvFAMCtbl(iptr)

  -- make std PEDI ADOP info
  -- disregard LDS 
  -- De Facto and Birth are di minimus
  local _cvt =
  {                 -- [' '] are not necessary for alphabetic indexes
    Adopted = 'ADOP',
    Foster  = 'FOSTER',
    Step    = 'STEP',

    father  = 'Husband',
    mother  = 'Wife',

    ['']    = '',
  }

  -- Most local variables are usually best declared where they are used

  local famc = {} -- family as child table

  local ptrFAMC = fhGetItemPtr(iptr, '~.FAMC')
  while ptrFAMC:IsNotNull() do
    local _fs  = rtvfID(ptrFAMC)  -- returns an array of FAMC items rtvfID-matfID above
    local fPTR = _fs.fPTR:Clone() -- PTRFAMC:Clone() 
    local fID  = _fs.fID          -- fhRecordId(PTRFAMC   
    local fpa  = ''               -- tag of pedi type or adop
    local fby  = ''               -- 'Husband', 'Wife', 'Both', ''
    local ptxt = {}               -- sorting out pedi tag text

    local ptrPEDI = fhNewItemPtr()
    ptrPEDI:MoveToFirstChildItem(ptrFAMC)
    while ptrPEDI:IsNotNull() do
      if fhGetTag(ptrPEDI):match('PEDI') then      -- allow for PEDI and _PEDI
        local TXT = fhGetValueAsText(ptrPEDI) 
        fpa, fby = TXT:match('^(.+) %((.+)%)$')    -- parse out (ie) 'Adopted' 'father'
        if fpa == nil then
          fpa = TXT -- 'Adopted' (short type pedi)
          fby = '' --  no by whom 
        end
        if _cvt[fpa] then  -- if its in the list of interest
          fpa = _cvt[fpa]
          fby = _cvt[fby]
          table.insert( ptxt, { fpa = fpa; fby = fby; } )   -- hold it
        end
      end
      ptrPEDI:MoveNext('ANY')   -- exhaust PEDI and _PEDI tags 
    end
    if #ptxt == 2 then
      if ptxt[1].fpa == ptxt[2].fpa    -- if the tags are equal then by is 'BOTH'
      and ptxt[1].fby == 'Husband'
      and ptxt[2].fby == 'Wife' then
        fby = 'Both'
      else
        fpa = '*ERR'  -- if tags are not = (ie) 'STEP' 'ADOP' then throw error
        fby = '(**)'
      end
    end
--pedis are reduced to 1 if any or the fields are blank
    table.insert( famc,   
    {
      fPTR = fPTR:Clone();  
      fID  = fID;
      fpa  = fpa; -- 'ADOP', 'STEP', '' so on from cvt or default
      fby  = fby; -- 'Husband', 'Wife', 'Both' '' from cvt or default
    } )
    ptrFAMC:MoveNext('SAME_TAG')   -- exhaust FAMC tags fil famc array 
  end

  local ptrITER = fhGetItemPtr(iptr, '~.ADOP')          -- separate ADOP events 2nd round 
  while ptrITER:IsNotNull() do
    local ptrADOP = fhGetItemPtr(ptrITER, '~.FAMC')     -- for this FAMC 
    local ptrTXT  = fhGetItemPtr(ptrADOP, '~.ADOP')
    local fby     = fhGetValueAsText(ptrTXT)
    ptrADOP = fhGetValueAsLink(ptrADOP)
    local infamc = nil                             -- is it in famc already?   
    for k, _ in ipairs(famc) do
      if ptrADOP:IsSame(famc[k].fPTR)
      and fby == famc[k].fby then
        famc[k].fpa  = 'ADOP'
        famc[k].fby  = fby
        infamc = true                              -- update the ADOP info and by info    
      end
    end

    if not infamc then                             -- case where not a naked FAMC as well 
      local _fs  = rtvfID(ptrADOP)                 -- see rtvfID-mat_fID
      local fPTR = _fs.fPTR
      local fID  = _fs.fID

      table.insert( famc,   
      {
        fPTR = fPTR:Clone();  
        fID  = fID;
        fpa  = 'ADOP';
        fby  = fby; 
      } )                                            -- add it
    end

    ptrITER:MoveNext('SAME_TAG')                    -- exhaust adop tags
  end

  return famc
end -- fn rtvFAMCtbl
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 03 Nov 2020 15:36

I am not sure what you mean I missed, I will run thru my file and debug it, for understanding.
I never quite got the full check to work, because I couldnt get both cases
pedi adopted
and
_pedi adopted (father)
to work with a single match-capture statement, since captures themselves cannot be made optional.

Oh, I never even considered mixed tags in a single INDI.... of course, I don't have them, but the case probably exists out there.

the lofty goal here is to run thru every INDI building famc and fams information, and events of interest, then run thru every FAM and glue the INDI tables info to the FAM table info and create a FAMobject then sort of like the places plink table which you showed me the linked list index I will have an index by INDI with famc, fams and last update, compare tablelast update to today check, if index date is less than last update, update the indi, and then update fams and famcs and FAMobject. then I can pull premade information out into my (supposedly new) programs.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 19152
Joined: 25 May 2010 11:00
Family Historian: V6.2
Location: Torbay, Devon, UK
Contact:

Re: ADOP and PEDI tags.

Post by tatewise » 03 Nov 2020 15:50

Ron, when you posted your script you said: "It seems to handle everything correctly." and only wanted it more efficient.
I assumed you had run and debugged the script with sample PEDI & _PEDI and ADOP tags in a small test Project.
But you now say you "never quite got the full check to work".
Please don't expect me to debug your scripts.

It is not possible to have both PEDI and _PEDI tags for the same INDIvidual.
But they can have two _PEDI tags.
They can also have ADOP.FAMC.ADOP with either PEDI or _PEDI.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 635
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: ADOP and PEDI tags.

Post by Ron Melby » 03 Nov 2020 15:59

I meant I had to do 2 checks, could not get the first to work in all cases:

fpa, fby = TXT:match('^(.+) ?%((.+)%)$')
if fpa == nil then
fpa = TXT:match('^(.+)$')
end

and it worked on every case I could find in my file. my live file, but I havent got a lot of cases, but as you pointed out, it can be drastically simplified, and I hadnt even thought of mixed cases. I have only started converting ADOP events to PEDI, because of what you said, I only have 5 cases right now.

but now I understand your refinements.
FH V.6.2.7 Win 10 64 bit

Post Reply