Ancestors and Descendants Counts by Generation.fh_lua--[[
@Title: Ancestors and Descendants - Counts by Generation
@Author: Jane Taubman
@Version: 1.3
@LastUpdated: 15 Dec 2020
@Description: Report of the number of Grandparents recorded for an individual by Generation and the
number of direct decendants by Generation
1.1 Lua 5.3 Compatibility
1.2 V7 compatibility
1.3 Compute percentage and round before adding for V7
]]
function main()
tblIndi = fhPromptUserForRecordSel('INDI',1)
if #tblIndi == 0 then
return
end
local pRoot = tblIndi[1]
local iAncMax,iDecMax = 0,0
local tblAncGen = {}
local tblDecGen = {}
local TblAncestorDescriptions = {'Parents','Grandparents','Great Grandparents'}
local TblDescendantDescriptions = {'Child','Grandchildren','Great Grandchildren'}
for pi in records('INDI') do
local bAnc = fhCallBuiltInFunction('IsAncestorOf',pi,pRoot)
if bAnc then
-- Ancestor of selected person get number of Generations
local iGens = fhCallBuiltInFunction('RelationCode',pi,pRoot,'GENS_DOWN',1)
if tblAncGen[iGens] then tblAncGen[iGens] = tblAncGen[iGens] + 1
else tblAncGen[iGens] = 1 end
if iGens > iAncMax then iAncMax = iGens end
end
local bDec = fhCallBuiltInFunction('IsDescendantOf',pi,pRoot)
if bDec then
-- descendant of selected person get number of Generations
local iGens = fhCallBuiltInFunction('RelationCode',pi,pRoot,'GENS_UP',1)
print (fhGetDisplayText(pi),iGens)
if tblDecGen[iGens] then tblDecGen[iGens] = tblDecGen[iGens] + 1
else tblDecGen[iGens] = 1 end
if iGens > iDecMax then iDecMax = iGens end
end
end
------------------------------------- Output Results
local tblResults = createResultTable()
-- Define Columns
tblResults.gen = {title='Gen',type=integer,align='align_left',width=80,sort=1}
tblResults.desc = {title='Description',type='Text',width=140}
tblResults.poss1 = {title='Pos',type='integer',align='align_right',width=40}
tblResults.posssum = {title='Pos Sum',type='integer',align='align_right',width=40}
tblResults.actual = {title='Actual',type='integer',align='align_right',width=40}
tblResults.actualsum = {title='Actual Sum',type='integer',align='align_right',width=40}
tblResults.percent = {title='%',type='integer',align='align_right',width=40}
tblResults:newRow()
tblResults.gen:set(1)
local sum,psum = 1,1
tblResults.desc:set(fhGetDisplayText(pRoot))
tblResults.poss1:set(1)
tblResults.posssum:set(sum)
tblResults.actual:set(1)
tblResults.actualsum:set(1)
tblResults.percent:set(100)
for i = 1, iAncMax do
tblResults:newRow()
local sTitle = ''
if i<4 then
sTitle = TblAncestorDescriptions[i]
else
sTitle = (i - 2)..'x '..TblAncestorDescriptions[3]
end
tblAncGen[i] = tblAncGen[i] or 0
tblResults.gen:set(i+1)
tblResults.desc:set(sTitle)
tblResults.poss1:set(2 ^i)
psum = psum + 2^i
sum = sum + tblAncGen[i]
tblResults.posssum:set(psum)
tblResults.actual:set(tblAncGen[i])
tblResults.actualsum:set(sum)
local percent = math.floor((tblAncGen[i]/(2^i) * 100) + 0.5)
tblResults.percent:set(percent)
print (i,2 ^i,sTitle,tblAncGen[i] or 0)
end
sum = 0
for i = 1, iDecMax do
tblResults:newRow()
local sTitle = ''
if i<4 then
sTitle = TblDescendantDescriptions[i]
else
sTitle = (i - 2)..'x '..TblDescendantDescriptions[3]
end
tblDecGen[i] = tblDecGen[i] or 0
tblResults.gen:set((i+1) * -1)
tblResults.desc:set(sTitle)
tblResults.poss1:set(0)
sum = sum + tblDecGen[i]
tblResults.posssum:set(0)
tblResults.actual:set(tblDecGen[i])
tblResults.actualsum:set(sum)
tblResults.percent:set(0)
-- print (i,2 ^i,sTitle,tblDecGen[i] or 0)
end
local sTitle = "Ancestor and Descendant Breakdown for "..fhGetDisplayText(pRoot)
fhOutputResultSetTitles(sTitle, sTitle, "Created Date: %#x")
tblResults:outputResults()
end
function records(type)
local pi = fhNewItemPtr()
local p2 = fhNewItemPtr()
pi:MoveToFirstRecord(type)
return function ()
p2:MoveTo(pi)
pi:MoveNext()
if p2:IsNotNull() then return p2 end
end
end
function createResultTable()
local tblOutput_mt = {} -- create metatable
local iC = 0 -- Define count of lines
local tblOutput = {} -- Define Columns Table
tblOutput_mt.col = 0
tblOutput_mt.seq = {}
tblOutput_mt.__newindex =
function (t,k,v)
-- Set Values to Defaults if not supplied
if v.content == nil then v.content = {} end
if v.title == nil then v.title = k end
if v.type == nil then v.type = 'notset' end
if v.width == nil then v.width = 140 end
if v.align == nil then v.align = 'align_left' end
if v.sort == nil then v.sort = 0 end
if v.sortAscending == nil then v.sortAscending = true end
if v.sortType == nil then v.sortType = 'default' end
if v.visibility == nil then v. visibility = 'show' end
v.set =
function(self,value)
self.content[iC] = value
if self.type == 'notset' then
if type(value) == 'string' then
self.type = 'text'
elseif type(value) == 'number' then
self.type = 'integer'
self.width = '30'
else
self.type = 'item'
end
end
end
rawset(t,k,v) -- update original table
local m = getmetatable(t)
m.col = m.col + 1
table.insert(m.seq,k)
end
tblOutput_mt.__call =
function (t)
local i = 0
local m = getmetatable(t)
local n = table.getn(m.seq)
return function ()
i = i + 1
if i <= n then
return t[m.seq[i]]
end
end
end
tblOutput.newRow = function(t)
iC = iC + 1
end
tblOutput.rowCount = function(t)
return iC
end
tblOutput.outputResults = function(self)
for l in self() do
fhOutputResultSetColumn(l.title, l.type, l.content, iC, l.width,l.align,l.sort,l.sortAscending,l.sortType,l.visibility )
end
end
setmetatable(tblOutput, tblOutput_mt)
return tblOutput
end
---------------------------------------------------------------- Lua 5.3
if not(table.getn) then
if fhGetAppVersion() > 6 then
function table.getn(t)
local count = 0
for _, __ in pairs(t) do
count = count + 1
end
return count
end
function unpack(t)
return table.unpack(t)
end
end
end
---------------------------------------------------------------- Run Main
main()
--[[
@Title: Ancestors and Descendants - Counts by Generation
@Author: Jane Taubman
@Version: 1.3
@LastUpdated: 15 Dec 2020
@Description: Report of the number of Grandparents recorded for an individual by Generation and the
number of direct decendants by Generation
1.1 Lua 5.3 Compatibility
1.2 V7 compatibility
1.3 Compute percentage and round before adding for V7
]]
function main()
tblIndi = fhPromptUserForRecordSel('INDI',1)
if #tblIndi == 0 then
return
end
local pRoot = tblIndi[1]
local iAncMax,iDecMax = 0,0
local tblAncGen = {}
local tblDecGen = {}
local TblAncestorDescriptions = {'Parents','Grandparents','Great Grandparents'}
local TblDescendantDescriptions = {'Child','Grandchildren','Great Grandchildren'}
for pi in records('INDI') do
local bAnc = fhCallBuiltInFunction('IsAncestorOf',pi,pRoot)
if bAnc then
-- Ancestor of selected person get number of Generations
local iGens = fhCallBuiltInFunction('RelationCode',pi,pRoot,'GENS_DOWN',1)
if tblAncGen[iGens] then tblAncGen[iGens] = tblAncGen[iGens] + 1
else tblAncGen[iGens] = 1 end
if iGens > iAncMax then iAncMax = iGens end
end
local bDec = fhCallBuiltInFunction('IsDescendantOf',pi,pRoot)
if bDec then
-- descendant of selected person get number of Generations
local iGens = fhCallBuiltInFunction('RelationCode',pi,pRoot,'GENS_UP',1)
print (fhGetDisplayText(pi),iGens)
if tblDecGen[iGens] then tblDecGen[iGens] = tblDecGen[iGens] + 1
else tblDecGen[iGens] = 1 end
if iGens > iDecMax then iDecMax = iGens end
end
end
------------------------------------- Output Results
local tblResults = createResultTable()
-- Define Columns
tblResults.gen = {title='Gen',type=integer,align='align_left',width=80,sort=1}
tblResults.desc = {title='Description',type='Text',width=140}
tblResults.poss1 = {title='Pos',type='integer',align='align_right',width=40}
tblResults.posssum = {title='Pos Sum',type='integer',align='align_right',width=40}
tblResults.actual = {title='Actual',type='integer',align='align_right',width=40}
tblResults.actualsum = {title='Actual Sum',type='integer',align='align_right',width=40}
tblResults.percent = {title='%',type='integer',align='align_right',width=40}
tblResults:newRow()
tblResults.gen:set(1)
local sum,psum = 1,1
tblResults.desc:set(fhGetDisplayText(pRoot))
tblResults.poss1:set(1)
tblResults.posssum:set(sum)
tblResults.actual:set(1)
tblResults.actualsum:set(1)
tblResults.percent:set(100)
for i = 1, iAncMax do
tblResults:newRow()
local sTitle = ''
if i<4 then
sTitle = TblAncestorDescriptions[i]
else
sTitle = (i - 2)..'x '..TblAncestorDescriptions[3]
end
tblAncGen[i] = tblAncGen[i] or 0
tblResults.gen:set(i+1)
tblResults.desc:set(sTitle)
tblResults.poss1:set(2 ^i)
psum = psum + 2^i
sum = sum + tblAncGen[i]
tblResults.posssum:set(psum)
tblResults.actual:set(tblAncGen[i])
tblResults.actualsum:set(sum)
local percent = math.floor((tblAncGen[i]/(2^i) * 100) + 0.5)
tblResults.percent:set(percent)
print (i,2 ^i,sTitle,tblAncGen[i] or 0)
end
sum = 0
for i = 1, iDecMax do
tblResults:newRow()
local sTitle = ''
if i<4 then
sTitle = TblDescendantDescriptions[i]
else
sTitle = (i - 2)..'x '..TblDescendantDescriptions[3]
end
tblDecGen[i] = tblDecGen[i] or 0
tblResults.gen:set((i+1) * -1)
tblResults.desc:set(sTitle)
tblResults.poss1:set(0)
sum = sum + tblDecGen[i]
tblResults.posssum:set(0)
tblResults.actual:set(tblDecGen[i])
tblResults.actualsum:set(sum)
tblResults.percent:set(0)
-- print (i,2 ^i,sTitle,tblDecGen[i] or 0)
end
local sTitle = "Ancestor and Descendant Breakdown for "..fhGetDisplayText(pRoot)
fhOutputResultSetTitles(sTitle, sTitle, "Created Date: %#x")
tblResults:outputResults()
end
function records(type)
local pi = fhNewItemPtr()
local p2 = fhNewItemPtr()
pi:MoveToFirstRecord(type)
return function ()
p2:MoveTo(pi)
pi:MoveNext()
if p2:IsNotNull() then return p2 end
end
end
function createResultTable()
local tblOutput_mt = {} -- create metatable
local iC = 0 -- Define count of lines
local tblOutput = {} -- Define Columns Table
tblOutput_mt.col = 0
tblOutput_mt.seq = {}
tblOutput_mt.__newindex =
function (t,k,v)
-- Set Values to Defaults if not supplied
if v.content == nil then v.content = {} end
if v.title == nil then v.title = k end
if v.type == nil then v.type = 'notset' end
if v.width == nil then v.width = 140 end
if v.align == nil then v.align = 'align_left' end
if v.sort == nil then v.sort = 0 end
if v.sortAscending == nil then v.sortAscending = true end
if v.sortType == nil then v.sortType = 'default' end
if v.visibility == nil then v. visibility = 'show' end
v.set =
function(self,value)
self.content[iC] = value
if self.type == 'notset' then
if type(value) == 'string' then
self.type = 'text'
elseif type(value) == 'number' then
self.type = 'integer'
self.width = '30'
else
self.type = 'item'
end
end
end
rawset(t,k,v) -- update original table
local m = getmetatable(t)
m.col = m.col + 1
table.insert(m.seq,k)
end
tblOutput_mt.__call =
function (t)
local i = 0
local m = getmetatable(t)
local n = table.getn(m.seq)
return function ()
i = i + 1
if i <= n then
return t[m.seq[i]]
end
end
end
tblOutput.newRow = function(t)
iC = iC + 1
end
tblOutput.rowCount = function(t)
return iC
end
tblOutput.outputResults = function(self)
for l in self() do
fhOutputResultSetColumn(l.title, l.type, l.content, iC, l.width,l.align,l.sort,l.sortAscending,l.sortType,l.visibility )
end
end
setmetatable(tblOutput, tblOutput_mt)
return tblOutput
end
---------------------------------------------------------------- Lua 5.3
if not(table.getn) then
if fhGetAppVersion() > 6 then
function table.getn(t)
local count = 0
for _, __ in pairs(t) do
count = count + 1
end
return count
end
function unpack(t)
return table.unpack(t)
end
end
end
---------------------------------------------------------------- Run Main
main()Source:Ancestors-and-Descendants-Counts-by-Generation-2.fh_lua