Find Duplicate Place Names.fh_lua--[[
@Title: Find Duplicate Place Names
@Type: Standard
@Author: Mike Tate
@Version: 1.0
@Keywords:
@LastUpdated: 25 Apr 2022
@Licence: This plugin is copyright (c) 2022 Mike Tate and contributors, and is licensed under the MIT License which is hereby incorporated by reference (see https://pluginstore.family-historian.co.uk/fh-plugin-licence)
@Description: List any Place records whose tidied names would be duplicates and thus should be merged. Variations due to placement of commas and spaces, or the case of letters are disregarded.
]]
local strVersion = "1.0"
function Main()
local arrTidyTxt = {}
local arrTidyRec = {}
local arrTidyRid = {}
local arrCopyRec = {}
local arrCopyRid = {}
local dicRec = {}
local ptrRec = fhNewItemPtr() -- See Sample Plugin Scripts ~ Surname Summary loop
ptrRec:MoveToFirstRecord("_PLAC")
while ptrRec:IsNotNull() do
local strText = fhGetItemText(ptrRec,"~.TEXT")
local strTidy = fhCallBuiltInFunction("TextPart",strText,1,0,"TIDY"):gsub(" +([ ,])","%1") -- gsub fixes TextPart bug
local ptrTidy = dicRec[strTidy:lower()] -- Need lower() to cater for case variants
if ptrTidy then -- Duplicate tidied name found so save Result Set data of both records
table.insert(arrTidyTxt,strTidy)
table.insert(arrTidyRec,ptrTidy:Clone())
table.insert(arrTidyRid,fhGetRecordId(ptrTidy))
table.insert(arrCopyRec,ptrRec:Clone())
table.insert(arrCopyRid,fhGetRecordId(ptrRec))
else
dicRec[strTidy:lower()] = ptrRec:Clone() -- Save pointer to Place record against tidied name -- Need lower() to cater for case variants
end
ptrRec:MoveNext()
end
if #arrTidyRec > 0 then
fhOutputResultSetTitles( "Find Duplicate Place Names "..strVersion )
fhOutputResultSetColumn( "Tidy Place Name", "text", arrTidyTxt, #arrTidyRec, 200, "align_left" )
fhOutputResultSetColumn( "Original Record", "item", arrTidyRec, #arrTidyRec, 200, "align_left" )
fhOutputResultSetColumn( "Rec Id", "integer", arrTidyRid, #arrTidyRec, 30, "align_right")
fhOutputResultSetColumn( "Duplicate Record","item", arrCopyRec, #arrTidyRec, 200, "align_left" )
fhOutputResultSetColumn( "Rec Id", "integer", arrCopyRid, #arrTidyRec, 30, "align_right")
-- fhMessageBox("\n" .. tostring(#arrTidyRec) .. " duplicate place names found\n")
else
fhMessageBox("\n No duplicate place names found \n")
end
end -- function Main
--[[
@Function: CheckVersionInStore
@Author: Mike Tate
@Version: 1.2
@LastUpdated: 10 Jul 2021
@Description: Check plugin version against version in Plugin Store
@Parameter: Plugin name and version
@Returns: None
@Requires: lfs & luacom
@V1.2: Ensure the Plugin Data folder exists;
@V1.1: Monthly interval between checks; Report if Internet is inaccessible;
@V1.0: Initial version;
]]
function CheckVersionInStore(strPlugin,strVersion) -- Check if later Version available in Plugin Store
require "lfs"
require "luacom"
local function OpenFile(strFileName,strMode) -- Open File and return Handle
local fileHandle, strError = io.open(strFileName,strMode)
if fileHandle == nil then
error("\n Unable to open file in \""..strMode.."\" mode. \n "..strFileName.." \n "..strError.." \n")
end
return fileHandle
end -- local function OpenFile
local function SaveStringToFile(strString,strFileName) -- Save string to file
local fileHandle = OpenFile(strFileName,"w")
fileHandle:write(strString)
assert(fileHandle:close())
end -- local function SaveStringToFile
local function httpRequest(strRequest) -- Luacom http request protected by pcall() below
local http = luacom.CreateObject("winhttp.winhttprequest.5.1")
http:Open("GET",strRequest,false)
http:Send()
return http.Responsebody
end -- local function httpRequest
local function intVersion(strVersion) -- Convert version string to comparable integer
local intVersion = 0
local arrNumbers = {}
strVersion:gsub("(%d+)", function(strDigits) table.insert(arrNumbers,strDigits) end)
for i = 1, 4 do
intVersion = intVersion * 1000 + tonumber(arrNumbers[i] or 0)
end
return intVersion
end -- local function intVersion
local strLatest = "0"
if strPlugin then
local strPath = fhGetContextInfo("CI_APP_DATA_FOLDER").."\\Plugin Data\\"
local strFile = strPath.."VersionInStore "..strPlugin..".dat"
local intTime = os.time() - 2600000 -- Time in seconds a month ago
local tblAttr, strError = lfs.attributes(strFile) -- Obtain file attributes
if not tblAttr or tblAttr.modification < intTime then -- File does not exist or was modified long ago
if lfs.attributes(strPath,"mode") ~= "directory" then
if not lfs.mkdir(strPath) then return end -- Ensure the Plugin Data folder exists
end
SaveStringToFile(strFile,strFile) -- Update file modified time
local strFile = strPath.."VersionInStoreInternetError.dat"
local strRequest ="http://www.family-historian.co.uk/lnk/checkpluginversion.php?name="..tostring(strPlugin)
local isOK, strReturn = pcall(httpRequest,strRequest)
if not isOK then -- Problem with Internet access
local intTime = os.time() - 36000 -- Time in seconds 10 hours ago
local tblAttr, strError = lfs.attributes(strFile) -- Obtain file attributes
if not tblAttr or tblAttr.modification < intTime then -- File does not exist or was modified long ago
fhMessageBox(strReturn.."\n The Internet appears to be inaccessible. ")
end
SaveStringToFile(strFile,strFile) -- Update file modified time
else
os.remove(strFile) -- Delete file if Internet is OK
if strReturn then
strLatest = strReturn:match("([%d%.]*),%d*") -- Version digits & dots then comma and Id digits
end
end
end
end
if intVersion(strLatest) > intVersion(strVersion or "0") then
fhMessageBox("Later Version "..strLatest.." of this Plugin is available from the Plugin Store.")
end
end -- function CheckVersionInStore
fhInitialise(6,0,0,"save_recommended")
CheckVersionInStore("Find Duplicate Place Names",strVersion)
Main()
--[[
@Title: Find Duplicate Place Names
@Type: Standard
@Author: Mike Tate
@Version: 1.0
@Keywords:
@LastUpdated: 25 Apr 2022
@Licence: This plugin is copyright (c) 2022 Mike Tate and contributors, and is licensed under the MIT License which is hereby incorporated by reference (see https://pluginstore.family-historian.co.uk/fh-plugin-licence)
@Description: List any Place records whose tidied names would be duplicates and thus should be merged. Variations due to placement of commas and spaces, or the case of letters are disregarded.
]]
local strVersion = "1.0"
function Main()
local arrTidyTxt = {}
local arrTidyRec = {}
local arrTidyRid = {}
local arrCopyRec = {}
local arrCopyRid = {}
local dicRec = {}
local ptrRec = fhNewItemPtr() -- See Sample Plugin Scripts ~ Surname Summary loop
ptrRec:MoveToFirstRecord("_PLAC")
while ptrRec:IsNotNull() do
local strText = fhGetItemText(ptrRec,"~.TEXT")
local strTidy = fhCallBuiltInFunction("TextPart",strText,1,0,"TIDY"):gsub(" +([ ,])","%1") -- gsub fixes TextPart bug
local ptrTidy = dicRec[strTidy:lower()] -- Need lower() to cater for case variants
if ptrTidy then -- Duplicate tidied name found so save Result Set data of both records
table.insert(arrTidyTxt,strTidy)
table.insert(arrTidyRec,ptrTidy:Clone())
table.insert(arrTidyRid,fhGetRecordId(ptrTidy))
table.insert(arrCopyRec,ptrRec:Clone())
table.insert(arrCopyRid,fhGetRecordId(ptrRec))
else
dicRec[strTidy:lower()] = ptrRec:Clone() -- Save pointer to Place record against tidied name -- Need lower() to cater for case variants
end
ptrRec:MoveNext()
end
if #arrTidyRec > 0 then
fhOutputResultSetTitles( "Find Duplicate Place Names "..strVersion )
fhOutputResultSetColumn( "Tidy Place Name", "text", arrTidyTxt, #arrTidyRec, 200, "align_left" )
fhOutputResultSetColumn( "Original Record", "item", arrTidyRec, #arrTidyRec, 200, "align_left" )
fhOutputResultSetColumn( "Rec Id", "integer", arrTidyRid, #arrTidyRec, 30, "align_right")
fhOutputResultSetColumn( "Duplicate Record","item", arrCopyRec, #arrTidyRec, 200, "align_left" )
fhOutputResultSetColumn( "Rec Id", "integer", arrCopyRid, #arrTidyRec, 30, "align_right")
-- fhMessageBox("\n" .. tostring(#arrTidyRec) .. " duplicate place names found\n")
else
fhMessageBox("\n No duplicate place names found \n")
end
end -- function Main
--[[
@Function: CheckVersionInStore
@Author: Mike Tate
@Version: 1.2
@LastUpdated: 10 Jul 2021
@Description: Check plugin version against version in Plugin Store
@Parameter: Plugin name and version
@Returns: None
@Requires: lfs & luacom
@V1.2: Ensure the Plugin Data folder exists;
@V1.1: Monthly interval between checks; Report if Internet is inaccessible;
@V1.0: Initial version;
]]
function CheckVersionInStore(strPlugin,strVersion) -- Check if later Version available in Plugin Store
require "lfs"
require "luacom"
local function OpenFile(strFileName,strMode) -- Open File and return Handle
local fileHandle, strError = io.open(strFileName,strMode)
if fileHandle == nil then
error("\n Unable to open file in \""..strMode.."\" mode. \n "..strFileName.." \n "..strError.." \n")
end
return fileHandle
end -- local function OpenFile
local function SaveStringToFile(strString,strFileName) -- Save string to file
local fileHandle = OpenFile(strFileName,"w")
fileHandle:write(strString)
assert(fileHandle:close())
end -- local function SaveStringToFile
local function httpRequest(strRequest) -- Luacom http request protected by pcall() below
local http = luacom.CreateObject("winhttp.winhttprequest.5.1")
http:Open("GET",strRequest,false)
http:Send()
return http.Responsebody
end -- local function httpRequest
local function intVersion(strVersion) -- Convert version string to comparable integer
local intVersion = 0
local arrNumbers = {}
strVersion:gsub("(%d+)", function(strDigits) table.insert(arrNumbers,strDigits) end)
for i = 1, 4 do
intVersion = intVersion * 1000 + tonumber(arrNumbers[i] or 0)
end
return intVersion
end -- local function intVersion
local strLatest = "0"
if strPlugin then
local strPath = fhGetContextInfo("CI_APP_DATA_FOLDER").."\\Plugin Data\\"
local strFile = strPath.."VersionInStore "..strPlugin..".dat"
local intTime = os.time() - 2600000 -- Time in seconds a month ago
local tblAttr, strError = lfs.attributes(strFile) -- Obtain file attributes
if not tblAttr or tblAttr.modification < intTime then -- File does not exist or was modified long ago
if lfs.attributes(strPath,"mode") ~= "directory" then
if not lfs.mkdir(strPath) then return end -- Ensure the Plugin Data folder exists
end
SaveStringToFile(strFile,strFile) -- Update file modified time
local strFile = strPath.."VersionInStoreInternetError.dat"
local strRequest ="http://www.family-historian.co.uk/lnk/checkpluginversion.php?name="..tostring(strPlugin)
local isOK, strReturn = pcall(httpRequest,strRequest)
if not isOK then -- Problem with Internet access
local intTime = os.time() - 36000 -- Time in seconds 10 hours ago
local tblAttr, strError = lfs.attributes(strFile) -- Obtain file attributes
if not tblAttr or tblAttr.modification < intTime then -- File does not exist or was modified long ago
fhMessageBox(strReturn.."\n The Internet appears to be inaccessible. ")
end
SaveStringToFile(strFile,strFile) -- Update file modified time
else
os.remove(strFile) -- Delete file if Internet is OK
if strReturn then
strLatest = strReturn:match("([%d%.]*),%d*") -- Version digits & dots then comma and Id digits
end
end
end
end
if intVersion(strLatest) > intVersion(strVersion or "0") then
fhMessageBox("Later Version "..strLatest.." of this Plugin is available from the Plugin Store.")
end
end -- function CheckVersionInStore
fhInitialise(6,0,0,"save_recommended")
CheckVersionInStore("Find Duplicate Place Names",strVersion)
Main()
Source:Find-Duplicate-Place-Names.fh_lua