Module:Sandbox/Was a bee/tree explained

local p =

datas =

-- These setdata and getdata functions are used to access (read and write) to "datas" tablefunction p.setdata(n, key, val) if datas[n]

nil then datas[n] = end datas[n][key] = valend

function p.getdata(n, key, defval) if datas[n]

nil or datas[n][key]

nil then return defval else return datas[n][key] endend

function p.children(query, itemId, property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2) -------------------------------------------------------------------------------- -- children function which listing all childrens that certain item has. -- Not listing grand childrens, or grand-grand childrens. Listing only childrens. -- Final returning value "childrens" is like -------------------------------------------------------------------------------- local childrens = local entity = mw.wikibase.getEntity(itemId) local claims = nil local x = 1 local tmpValue = --------------------------------------------------------------- -- Start collecting data from the retrieved entity, and save that into the datas[] table. -- Because getEntity function is EXPENSIVE, so here, collecting all data at once. -- https://en.wikipedia.org/wiki/WP:EXPENSIVE -- https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua#mw.wikibase.getEntity ---------------------------------------------------------------- local globalSiteId_1 = lang1 .. 'wiki' local globalSiteId_2 if lang2 and lang2 ~= then globalSiteId_2 = lang2 .. 'wiki' else globalSiteId_2 = nil end p.setdata(itemId, "sitelink_1", entity:getSitelink(globalSiteId_1)) p.setdata(itemId, "label_1", entity:getLabel(lang1)) if lang2 and lang2 ~= then p.setdata(itemId, "sitelink_2", entity:getSitelink(globalSiteId_2)) p.setdata(itemId, "label_2", entity:getLabel(lang2)) end -- ★★★★ Start source specific code ★★★★ -- ------------TA98------------ claims = entity['claims']['P1323'] --TA98 ID if claims then for _,claim in pairs(claims) do tmpValue[x] = claim.mainsnak.datavalue.value x = x + 1 end p.setdata(itemId, "TA98", tmpValue) end tmpValue = --initialize x = 1 --initialize claims = nil --initialize ------------MeSH------------ --claims = entity['claims']['P672'] --MeSH Code --if claims then -- for _,claim in pairs(claims) do -- tmpValue[x] = claim.mainsnak.datavalue.value -- x = x + 1 -- end -- p.setdata(itemId, "MeSH", tmpValue) --end -- --tmpValue = --initialize --x = 1 --initialize --claims = nil --initialize -- ★★★★ End source specific code ★★★★ -- --------------------------------------------------------------- -- End collecting data --------------------------------------------------------------- --mw.logObject(datas[itemId]) --------------------------------------------------------------- -- Start collecting childrens --------------------------------------------------------------- claims = entity['claims'][property] --local claims = wikidata.getClaims(query) if not claims then return end local has_source if sources then -- If input setting about "sources" exists has_source = false -- default else has_source = true -- when setting doesn't requires sources, assuming as if all cliams are sourced end for _,claim in pairs(claims) do if sources then -- If input setting about "sources" exists has_source = false -- reset -- ★★★★ Start source specific code ★★★★ -- if claim['references'] and claim['references'][1]['snaks']['P248'] then -- If P248 ("stated in") claim exists if claim['references'][1]['snaks']['P248'][1]['datavalue']['value']['id']

'Q286567' then -- If it is TA98 ('Q286567') has_source = true --If the claim is sourced by Terminologia Anatomica, then "has_source" is true p.setdata('Q' .. claim.mainsnak.datavalue.value['numeric-id'], 'sourcedBy', 'TA98')-- set datas table, like datas[Q1234]['sourceType'] = 'TA98' end end -- ★★★★ End source specific code ★★★★ -- end --Adding item only when the claim is sourced by specific literature (e.g. Terminologia Anatomica) --or adding all item if input setting doesn't need source if has_source then local value = claim.mainsnak.datavalue.value local nextitem = 'Q' .. value['numeric-id']

childrens[x] = nextitem x = x + 1 end end --mw.logObject(datas[itemId]) --mw.log("childrens are : ") --mw.logObject(childrens) return childrens --------------------------------------------------------------- -- End collecting childrens ---------------------------------------------------------------end -- generator, see http://lua-users.org/wiki/LuaCoroutinesVersusPythonGenerators for lua doc-- definition a function that when called several times will generate a sequence of strings -- gensymbols = create_gensymbols("ABC")-- gensymbols

"A" -- gensymbols

"B" g-- gensymbols

"C" -- gensymbols

"AA" '-- gensymbols

"BABBA"-- ...function p.gensymbols(chars) local i = 0 local charset = chars local generator = function local symbol = "" local rest rest = i repeat local j j = rest % string.len(charset) rest = math.floor(rest / string.len(charset)) symbol = symbol .. string.sub(charset, j+1, j+1) until rest <= 0 i = i + 1 return symbol end return generatorend

------------------------------------------------------------------------------------------- -- Start definition of itemOutput function which returns text like '' .. label .. ''------------------------------------------------------------------------------------------- function p.itemOutput(item, lang1, lang2, datas, setdata, getdata, refStyle, pencil) local globalSiteId_1 = lang1 .. 'wiki' local globalSiteId_2 = lang2 .. 'wiki' --local lang_2 = 'en' --local langWiki = '//'..lang..'.wikipedia.org' -- if lang is 'fr', then this is '//fr.wikipedia.org' used to compare with mw.site.server --local currentEntity = mw.wikibase.getEntityObject(item) local currentLabel local currentLabel_temp local content local refTable = local referenceText = local pencilText if pencil

'none' then pencilText = else --(P527 "has part" or P361 "is part of") pencilText = '' end refStyle = 'asdasdsa' --mw.log('refStyle is: ' .. refStyle) if refStyle and refStyle ~= 'none' then -- ★★★★ Start source specific code ★★★★ -- if p.getdata(item, "sourcedBy", nil) and p.getdata(item, "sourcedBy", nil)

'TA98' then --mw.log('datas[] is: ') --mw.logObject(datas) mw.log('
') mw.log('
') mw.log('item is: ') mw.logObject(item) mw.log('datas[item] is: ') mw.logObject(datas[item]) mw.log('datas[item]["TA98"] is: ') mw.logObject(datas[item]["TA98"]) refTable = p.getdata(item, "TA98", nil) mw.log('refTable is: ') mw.logObject(refTable) mw.log('
') mw.log('
') if refTable and refTable ~= then for i, TA98ID in pairs(refTable) do refTable[i] = string.sub(refTable[i], 2) --Remove first character "A" from ID refTable[i] = '.. refTable[i] .. '%20Entity%20TA98%20EN.htm' .. ' ' .. 'A' .. refTable[i] ..']' -- Creating wikitext which links to TA98 official site --mw.log('refTable is :' .. tostring(table.concat(refTable))) end -- Converting multipul IDs into one line string, separated by comma, space ", " referenceText = tostring(table.concat(refTable, ', ')) referenceText = referenceText .. ' TA98, 1998' if refStyle

'normal' then referenceText = tostring(mw.getCurrentFrame:extensionTag('ref', referenceText,)) else referenceText = mw.getCurrentFrame:expandTemplate end else referenceText = end else referenceText = end -- ★★★★ End source specific code ★★★★ -- end --mw.log('referenceText is :' .. referenceText) --Link creation priority. Followings is an example. --'ja'(Japanese) represents your own language, and 'en'(English) represents other language which is familiar with your readers. --This section would be better to customize for your own readers. --1. Sitelink(ja) --If local sitelink data exists, use that. --2. Label(ja)(en link) --If local sitelink data doesn't exist, but local label data exists, use that (with en link). --3. Sitelink(en) (en link) --If both local language data doesn't exist, use sitelink to English Wikipedia --4. Label(en)(en link) --If such data doesn't exist, use English label --5. Q123456 --If all of such kind data doesn't exist, use bare item ID currentLabel = p.getdata(item, "sitelink_1", nil) -- wd._references if currentLabel ~= nil then content = '' .. currentLabel .. '' content = content .. ' ' .. referenceText content = content .. ' ' .. pencilText return content ----1. Sitelink(ja) style else currentLabel = p.getdata(item, "label_1", nil) if currentLabel ~= nil then content = '' .. currentLabel .. '' currentLabel_temp = p.getdata(item, "sitelink_2", nil) if currentLabel_temp ~= nil then content = content .. ' (' .. lang2 .. ')' ----adding (en) link end content = content .. ' ' .. referenceText content = content .. ' ' .. pencilText return content ----2. Label(ja)(en link) style else currentLabel = p.getdata(item, "sitelink_2", nil) if currentLabel ~= nil then content = currentLabel content = content .. ' (' .. lang2 .. ')' ----adding (en) link content = content .. ' ' .. referenceText content = content .. ' ' .. pencilText return content ----3. Sitelink(en) (en link) style else currentLabel = p.getdata(item, "label_2", nil) if currentLabel ~= nil then content = currentLabel content = content .. ' (' .. lang2 .. ')' ----adding (en) link content = content .. ' ' .. referenceText content = content .. ' ' .. pencilText return content ----4. Label(en)(en link) style else content = item content = content .. ' ' .. referenceText content = content .. ' ' .. pencilText return content --5. Q123456 style end end end endend------------------------------------------------------------------------------------------- -- End definition of itemOutput function which returns text like '' .. label .. ''-------------------------------------------------------------------------------------------

function p.outputTree(query, firstItemId, property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2)------------------------------------------------------------------------------------------- -- Start preparation of functions-------------------------------------------------------------------------------------------

----- topological sort and meta data of the DAG (https://en.wikipedia.org/wiki/Topological_sorting) --This firstPass function is called only once, at first local function firstPass(query, firstItemId, item_repr) local content = p.itemOutput(firstItemId, lang1, lang2, datas, setdata, getdata, refStyle, pencil) local opened = 1 -- This means the downstream branch of the item is under processing. -- If encountering opened item through the processing, it indicates that infinite loop exists. local closed = 2 -- This means the processing of all downstream branches of the item reached to its end. -- The downest item is showed with " ? " in tree. local incomplete = 3 -- This means the processing of all downstream branches of the item reached to its end. -- If more downstream branches exist but not processed (because of limitation from maxdepth), -- then the downest item showed with "…" in tree. local marks = --opened(1) or closed(2) or incomplete(3) for each QID (e.g. marks[Q12234234] -> closed) --local datas = --datas[QID]["nparents"], datas[QID]["symbol"], datas[QID]["looped"], datas[QID]["rank"], datas[QID]["status"] --datas[QID]["nparents"] represents "number of parents" of certain item. This is normally 1. --If this is 2 or more, it means that the exact same item appears several times in defferent branches of the tree repeatedly. local childrens = -- for example, childrens[Q1234] contains data like, three childrens of Q1234 --while there are unmarked nodes do -- select an unmarked node n -- visit(n) --function visit(node n) -- if n has a temporary mark then stop (not a DAG) -- if n is not marked (i.e. has not been visited yet) then -- mark n temporarily -- for each node m with an edge from n to m do -- visit(m) -- mark n permanently -- add n to head of L -- this function -- * visits and builds the tree, DAG or graph, -- * in the same pass, computes a topological ordering for the DAG -- * annotates the nodes with informations function visit(n, depth, rank) --mw.log("depth is " .. depth .. ">=" .. "maxdepth is " .. maxdepth) --mw.log(n .. ": mark is " .. tostring(marks[n])) if marks[n]

opened then p.setdata(n, "status", "loop") p.setdata(n, "rank", rank) return rank elseif marks[n] ~= closed then marks[n] = opened childrens[n] = p.children(query, n, property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2) for _, node in ipairs(childrens[n]) do p.setdata(node, "nparents", p.getdata(node, "nparents", 0) + 1 ) --mw.log(node .. ": nparents is " .. tostring(p.getdata(node, "nparents", "aaa"))) if depth <= maxdepth then rank = visit(node, depth + 1, rank + 1) end end if depth <= maxdepth then if p.getdata(n, "status", "complete") ~= "loop" then p.setdata(n, "status", "complete") end marks[n] = closed else p.setdata(n, "status", "incomplete") marks[n] = incomplete end p.setdata(n, "rank", rank) end return rank + 1 end p.setdata(firstItemId, "nparents", 0) visit(firstItemId, 1, 0) return datas, childrens end

local langobj = mw.language.new(lang1) -- link inside tree local function formatSymbol(prefix) return '

(' .. prefix .. ")" end local function genAnchor(id) return '' end local function anchorLink(id, content) return "" .. content .. "" end local function fmtTreeLinks(content) return mw.text.tag("sup",, content) end local function renderTree(itemId, datas, children, alreadyOuted, gs) local content = p.itemOutput(itemId, lang1, lang2, datas, setdata, getdata, refStyle, pencil) local state if datas[itemId]["status"] ~= nil then state = datas[itemId]["status"] end --mw.log(itemId .. ": status is " .. state) if datas[itemId] ["nparents"] > 1 and datas[itemId]["symbol"]

nil then p.setdata(itemId, "symbol", gs) end -- prevent infinite loops in non DAGs if state

"loop" then if datas[itemId]["looped"]

nil then datas[itemId]["looped"] = "treated" content = fmtTreeLinks(" ∞") .. " " .. content .. genAnchor(itemId) else return content .. fmtTreeLinks("∞" .. " ↑ " .. anchorLink(itemId, formatSymbol(datas[itemId]["symbol"]))) end elseif state

"incomplete" or state

"unvisited" then content = content .. " " .. fmtTreeLinks("…") return content end -- has no chilren ? display as leaf if children[itemId] ~= nil and table.getn(children[itemId])

0 then --return " " .. content .. " ? " -- would be great to use "?b, but font problem return " " .. content end datas[itemId] ["nparents"] = datas[itemId]["nparents"] - 1 local parts = -- sort children topologycally if alreadyOuted[itemId]

nil then local langobj = mw.language.new(lang1) local prefix = " " if datas[itemId] ["nparents"] > 0 then local arrow = langobj:getArrow prefix = fmtTreeLinks(genAnchor(itemId) .. " " .. arrow .. " " .. formatSymbol(datas[itemId]["symbol"])) end order = children[itemId] table.sort(order, function (a, b) return datas[a]["rank"] < datas[b]["rank"] end) for i, childId in ipairs(order) do table.insert(parts, renderTree(childId, datas, children, alreadyOuted, gs)) end if direction

"child" or direction

"brother" then local l = table.maxn(parts) for i = 1,(l - 1) do parts[i] = mw.text.tag('li',, parts[i]) end parts[l] = mw.text.tag('li',, parts[l]) alreadyOuted[itemId] = prefix .. " " .. content .. mw.text.tag('ul',, table.concat(parts)) elseif direction

"parent" then local texttmp local matchCount = 0 --mw.log("parts is: ") --mw.logObject(parts) texttmp = mw.text.tag('ul',, mw.text.tag('li',, content)) alreadyOuted[itemId], matchCount = string.gsub(table.concat(parts), "()", texttmp .. "%1", 1) --mw.log('matchCount is:') --mw.log(matchCount) if matchCount

0 then alreadyOuted[itemId] = prefix .. " " .. string.gsub(table.concat(parts), "$", texttmp, 1) end alreadyOuted[itemId] = prefix .. " " .. alreadyOuted[itemId] --mw.log("alreadyOuted[itemId] is: ") --mw.logObject(alreadyOuted[itemId]) end end if datas[itemId] ["nparents"] <= 0 or state

"loop" then return alreadyOuted[itemId] else return content .. " " .. fmtTreeLinks(anchorLink(itemId, formatSymbol(datas[itemId]["symbol"])) .. " " .. langobj:getArrow(forward)) end end------------------------------------------------------------------------------------------- -- End preparation of functions------------------------------------------------------------------------------------------- --------------------------- Start creating tree --------------------------- -- gen = p.gensymbols("??") -- gen = p.gensymbols("12") -- gen = p.gensymbols("★☆?") -- These symbols are used as link button for "jumping" from certain branch to other branch. -- "jumping" functionality is used when same item appears multipul times in one tree. local gen = p.gensymbols("@*#") local children datas, children = firstPass(query, firstItemId, gen) -- alreadyOuted is the table which contains html code for each QID. -- For example, like this... alreadyOuted[Q1234] = "

  • Human body
  • " -- Actually items which located more nearer to the root (to say, FirstItemId) contain html codes of their branchs within it. -- For example, like this... alreadyOuted[Q1234] = "
  • Human body
  • " -- This is done by recursive calling of renderTree function inside the renderTree function. local alreadyOuted = rendering = -- What does this do? return renderTree(firstItemId, datas, children, alreadyOuted, gen)------------------------- End creating tree -------------------------end

    function p.main(frame)-------------------------------------- Start adjustments of arguments ------------------------------------ local frame = frame:getParent local query = frame.args local sources local refStyle -- Option for refrence style. "none" or "normal" or other local pencil -- if pencil

    "none", wikidata-linked pencil image is not shown local maxdepth local lang1 local lang2 local firstItemId = query.items if firstItemId

    nil or firstItemId

    then --If QID is not defined, using the QID of the item which is connected to the current page. firstItemId = mw.wikibase.getEntityIdForCurrentPage if not firstItemId then return 'No items passed as parameter' --If there is no connected wikidata page, abort. end end --local firstItemsId = mw.text.split(query.items, ' ') --if firstItemsId[1]

    nil or firstItemsId[1]

    or table.maxn(firstItemsId)

    0 then -- --If QID is not defined, using the QID of the item which is connected to the current page. -- firstItemsId[1] = mw.wikibase.getEntityIdForCurrentPage -- if not firstItemsId[1] then -- return 'No items passed as parameter' --If there is no connected wikidata page, abort. -- end --end --for i, item in pairs(firstItemsId) do if tonumber(firstItemId) then --legacy format firstItemId = 'Q'.. tostring(firstItemId) end --end if tonumber(query.childProperty) then --legacy format query.childProperty = 'P'.. tostring(query.childProperty) end if tonumber(query.parentProperty) then --legacy format query.parentProperty = 'P'.. tostring(query.parentProperty) end if query.childDepth and query.childDepth ~= then query.childDepth = tonumber(query.childDepth) else query.childDepth = 4 end if query.parentDepth and query.parentDepth ~= then query.parentDepth = tonumber(query.parentDepth) else query.parentDepth = 2 end if query.brotherDepth and query.brotherDepth ~= then query.brotherDepth = tonumber(query.brotherDepth) else query.brotherDepth = 0 end if query.sources and query.sources ~= then sources = mw.text.split(query.sources, ' ') else sources = nil end if query.refStyle and query.refStyle ~= then if query.refStyle

    'none' then refStyle = 'none' elseif query.refStyle

    'normal' then refStyle = 'normal' else refStyle = mw.text.split(query.sources, ' ') end else refStyle = 'normal' end if query.pencil and query.pencil ~= then pencil = tostring(query.pencil) else pencil = nil end if query.lang1 and query.lang1 ~= then lang1 = query.lang1 else lang1 = mw.language.getContentLanguage.code end if query.lang2 and query.lang2 ~= then lang2 = query.lang2 else lang2 = 'en' end ------------------------------------ End adjustments of arguments ----------------------------------

    --------------------------- Start creating tree --------------------------- local content = local parent_content = nil local child_content = nil local brother_content = nil local direction -- tree searching direction. "child", "parent" or "brother" local property -- property used to search items. For example "P527" (has part) or "P361" (part of) -------------------------------------------------- --Creating tree for parent side (upstream side) -------------------------------------------------- if query.parentProperty and query.parentProperty ~= then parent_content = direction = "parent" property = query.parentProperty maxdepth = query.parentDepth --for _, item in pairs(firstItemsId) do parent_content = mw.text.tag('li',, p.outputTree(query, firstItemId, property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2)) --end end -------------------------------------------------- --Creating tree for brother side (substream side) -------------------------------------------------- -- Brother is, as definition, "parent's child". So both query.parentProperty and query.childProperty is needed. if query.brotherDepth and query.brotherDepth >= 0 and query.parentProperty and query.parentProperty ~= and query.parentDepth >= 1 and query.childProperty and query.childProperty ~= then brother_content = direction = "brother" maxdepth = query.brotherDepth property = query.parentProperty -- Get parent QID local parents = p.children(query, firstItemId, property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2) --local currentEntity = mw.wikibase.getEntityObject(firstItemId) --local claims = currentEntity['claims'][query.parentProperty] --if claims then -- If firstItemId has parent -- local x = 1 -- local parents = -- for _,claim in pairs(claims) do -- Check all parent claims and get QID from there. And stored it into parents[] table. -- local value = claim.mainsnak.datavalue.value -- local nextitem = 'Q' .. value['numeric-id']

    -- parents[x] = nextitem -- x = x + 1 -- end local currentEntity local claims local x = 1 local brothers, brothersPart = property = query.childProperty mw.log("parents is :") mw.logObject(parents) -- Get brother QID for _,parent in pairs(parents) do brothersPart = p.children(query, parent, property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2) mw.log("brothersPart is :") mw.logObject(brothersPart) --currentEntity = mw.wikibase.getEntityObject(parent) --claims = currentEntity['claims'][query.childProperty] -- Get child property in parent entity. Parent's child is brother. for _,bro in pairs(brothersPart) do -- Check all child claims and get QID from there. And stored it into brothers[] table. --local value = claim.mainsnak.datavalue.value --local nextitem = 'Q' .. value['numeric-id'] if bro ~= firstItemId then -- One of parent's child is ownself. It is not brother. So exclude that. brothers[x] = bro x = x + 1 end end end mw.log("brothers is :") mw.logObject(brothers) -- Creating trees for brother local l = table.maxn(brothers) if l >= 1 then for i = 1,(l - 1) do brother_content = brother_content .. mw.text.tag('li',, p.outputTree(query, brothers[i], property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2)) end brother_content = brother_content .. mw.text.tag('li',, p.outputTree(query, brothers[l], property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2)) end --end end -------------------------------------------------- --Creating tree for child side (downstream side) -------------------------------------------------- if query.childProperty and query.childProperty ~= then child_content = direction = "child" property = query.childProperty maxdepth = query.childDepth if brother_content and brother_content ~= then child_content = mw.text.tag('li',, p.outputTree(query, firstItemId, property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2)) else child_content = mw.text.tag('li',, p.outputTree(query, firstItemId, property, direction, maxdepth, sources, refStyle, pencil, lang1, lang2)) end end mw.log("parent_content is: ") mw.logObject(parent_content) mw.log("") mw.log("") mw.log("child_content is: ") mw.logObject(child_content) mw.log("") mw.log("") mw.log("brother_content is: ") mw.logObject(brother_content) mw.log("") mw.log("") -------------------------------------------------- -- Combine parent and child (and brother) trees -------------------------------------------------- if parent_content and parent_content ~= and child_content and child_content ~= then -- Append child-tree to parent-tree. -- What is doing here is only replacing the last item (final '

  • ...
  • ') in "parent_content", by "child_content" -- But because of Lua regex function is not high functioning, bit complicated process is done here. local a = 0 local b = 0 -- Finding start position of final item by searching
  • from the left to the right through text. while string.find(parent_content, '
  • ', b) do mw.log(a .. ' ' .. b) a, b = string.find(parent_content, '
  • ', b) end mw.log(a .. ' ' .. b) local c = 0 local d = 0 -- Finding end position of final item by searching
  • . c, d = string.find(parent_content, '.*$') --mw.log(c .. ' ' .. d) -- If c, d

    nil, it means "parent_content" is one level, is not multipul level tree. -- In other words, it contains only one item which is correponding to "firstItemId". -- In such case, ignore "parent_content". -- Ignore "brother_content" also. Because if no parent known, no brother known. if c ~= nil and d ~= nil then -- Replacing final item of "parent_content" by "child_content". -- If "brother_content" exists, inserts it just after the "child_content". if brother_content and brother_content ~= then content = string.sub(parent_content, 1, a - 1) .. brother_content .. child_content .. string.sub(parent_content, c) else content = string.sub(parent_content, 1, a - 1) .. child_content .. string.sub(parent_content, c) end else content = child_content end end mw.log("content after is: ") mw.logObject(content) -------------------------------------------------- -- Final formatting and adding like template at the bottom -------------------------------------------------- if parent_content or child_content then res = mw.text.tag('div',, mw.text.tag('ul',, content)) if sources then -- if sources are shown after each items like [1], then put like template at the bottom res = res .. frame:expandTemplate end end------------------------- End creating tree ------------------------- return resend

    return p