How Can We Help?
You are here:
< Back
require('strict')
local fn = require('Module:Formatnum')
local mm = require('Module:Math')
local p ={}
local pargs ={}

function p.lighthouse(frame)
	local page = frame.args['page']
	local qid = frame.args['qid']
	local property = frame.args['property']
	local text = page .. ": instance of :"
	
	--local item = mw.wikibase.getEntity('P'..prop)  --('P5354')
	if page then
		qid = mw.wikibase.getEntityIdForTitle(page)
		text = page .. ': instance of :'
	elseif qid then
		text = mw.wikibase.getLabel(qid) .. ' (' .. qid .. '): instance of :'
	else
		return "No page or qid given" 
	end
		
	local statements = mw.wikibase.getBestStatements(qid, 'P31')   -- get instance of
	for index, statement in pairs( statements ) do
    	local instanceOfId
    	if statement and statement.mainsnak and statement.mainsnak.datavalue then
    		instanceOfId = statement.mainsnak.datavalue.value.id
    		text = text .. '\n:::' .. instanceOfId .. ' (' .. mw.wikibase.getLabel(instanceOfId) .. ') '
    		
    		--local item2 = mw.wikibase.getEntity(instanceOfId)  -- returns full claims table [expensive,so just use best statements]
    	    --local statements2 = item2:getBestStatements( 'P279')  
    		
    		local instanceOfStatements = mw.wikibase.getBestStatements(instanceOfId, 'P279')
     	
     		text = text .. '[subclass: '
    		for _, instanceOfStatement in pairs( instanceOfStatements ) do
    			if instanceOfStatement.mainsnak and instanceOfStatement.mainsnak.datavalue then
    		    	local subclassId = instanceOfStatement.mainsnak.datavalue.value.id
    		    	text = text .. '\n:::::' .. subclassId .. ' (' .. mw.wikibase.getLabel(subclassId) .. ') '
    			end
    		end
    		text = text .. ']; '
    	end

	end
	
	return text
end
function p.testExpensive(frame, page, mode)
	
	local mode = frame.args['mode']
	if not mode then mode = "makeTitle" end
	
	local title
    local page = frame.args['page'] 
   	if not page then p.errormsg("Target page not found") end -- TODO check for page existence here
    
    if mode == "new" then
   		title = mw.title.new( page) -- , ns)
   	else 
   		title = mw.title.makeTitle( "Template", page) 
   	end
   	if not title then return p.errormsg("Title object not created") end 	
    
    if not title.exists then 
    	return "Invalid page name = " .. title.text  .. " (using mw.title." .. mode .. ")" 
    end
    
   	return "Title = " ..title.text   .. " (using mw.title." .. mode .. ")" 
end

function p.getdomain(frame)
	local url = frame.args[1]
	
	local domain =  string.match( url, "%/%/(.-)%/" )
	local domain2 = mw.uri.new(url).host
	return domain .. "|" .. domain2
end

function p.getclade(frame)
    
    local page = frame.args['page'] 
   	if not page then p.errormsg("Target page not found") end -- TODO check for page existence here

   	local title = mw.title.new( page) -- , ns)
   	if not title then p.errormsg("Title not retrieved from page") end 
   	
	local content = title:getContent()
		
    local cladogram = p.matchClade(content)
    
    if 1==2 then
    	return  frame:preprocess(p.matchClade(cladogram))
    else -- now do something with it
    	return p.parseCladogram(frame, cladogram)
    end

end
function p.parseCladogram(frame, cladogram)
	
	local pattern = '|1=(.+)[|}]'
    --local value = p.matchClade(cladogram, pattern)
    for match in cladogram:gmatch(pattern) do      -- most inclusive
	   if match:find("^{{clade") then
	   	 local value = p.matchClade(match)
	   	 return p.parseCladogram(frame, value)
	   	 --return frame:preprocess(p.matchClade(match)) --found clade
	   else
	   	return "no clade found" .. match
	   end	
	   return "no match found in match : " ..match
	end
	
	--return frame:preprocess(value)
	return "no match found in cladogram: " .. cladogram
end
function p.matchClade(content, pattern)

	if not pattern then
		pattern = '{{clade.-}}'                -- least inclusive (until first "}}")
		pattern       = '{{clade.+}}'                -- most inclusive (until last "}}", e.g. the taxonbar close)
	end

    for match in content:gmatch(pattern) do      -- most inclusive
		for match2 in match:gmatch('%b{}') do    -- match paired brackets
		    return match2
		end
	end
end



function p.getpage(frame)
    local page = frame.args['page'] 
    local wrap = frame.args['wrap'] 
   	if not page then p.errormsg("Target page not found") end -- TODO check for page existence here
   	
   	local title = mw.title.new( page) -- , ns)
	if title then 
		local content = title:getContent()
		
		if wrap then
			content = '<' .. wrap .. '>' .. tostring(content) .. '</' .. wrap .. '>'
		end
		
		return content
	end

end

p.main = function(frame) -- called from template
	pargs = frame:getParent().args
	local output 
	local page = pargs['page'] 
	if not page then p.errormsg("Target page not found") end -- TODO check for page existence here
	
	local section =  pargs['section'] or pargs['section1'] or pargs[1] 
	if section then
		output = p._section(frame, page, section)
		
	end
	
	local label =  pargs['label'] or pargs['label1'] or pargs[1] 
	if label then
		output = p._label(frame, page, label)
	end   
	
	local subtree =  pargs['subtree'] or pargs['subtree1'] or pargs[1] 
	if subtree then
		output = p._label(frame, page, subtree)
	end  
	
	local wrap = pargs['wrap'] 
	if wrap and (label or subtree) then
		local label1 = label or string.lower(subtree)
		if wrap ~= "" then label1 = wrap end
		output = "{{clade |label1=" .. p.firstToUpper(label1) .. "|1=" .. output .. "}}"
    end
	
	if output then
		return frame:preprocess(output)
	end
	
   return p.errormsg("No valid option for transclusion")
end

p.test = function(frame)

	--mw.title.makeTitle( namespace, title, fragment, interwiki )
	--mw.title.new( text, namespace )
	local page = "User:Jts1882/sandbox/test/Passeriformes"  --"Atelopus andinus"
	local section = "Passeriformes"
	
	local ns = 1
	if page:find("^User") then ns = 2 end
	if page:find("^Template") then ns = 10 end  -- TODO check number
	
	--mw.site.namespaces.User.id -- returns 2
	
	--TEST PAGE = User:Jts1882/sandbox 
	return p._section(frame,page, "Passeroidea ", "Corvida", "Tyranni")
		

end


p.test_working_prototype = function(frame)

	--mw.title.makeTitle( namespace, title, fragment, interwiki )
	--mw.title.new( text, namespace )
	local page = "User:Jts1882/sandbox/test/Passeriformes"  --"Atelopus andinus"
	
	local ns = 1
	if page:find("^User") then ns = 2 end
	if page:find("^Template") then ns = 10 end  -- TODO check number
	
	--mw.site.namespaces.User.id -- returns 2
	
	--TEST PAGE = User:Jts1882/sandbox 
	
	local title = mw.title.new( page) -- , ns)
	if title then 
		local content = title:getContent()
		
		local pattern = "<section begin=Passeriformes />(.+)<section end=Passeriformes />"
		pattern = "{{#tag:section||begin=Test}}(.+){{#tag:section||end=Test}}"
		local value = string.match( content , pattern )
		if value then
			return  frame:preprocess(value)
			--return value
	    else
	    	return  "no match found"
    	end
	
	   return content
	end 
	
	
	return "Hello"	
end
--================================== exclude LABEL ================================================

p.xlabel = function (frame, page, ...)
	local page = frame.args[1] --"User:Jts1882/sandbox/test/Passeriformes"
	local label = frame.args[1] or frame.args['label'] or frame.args['label1']
	                      -- page , target tree,  subtrees to exclude ...
	
	
	
	--                       page,   include clade, multple clades to exclude |
	return p._xlabel (frame, page, frame.args[2], frame.args[3], frame.args[4], frame.args[5])



end
p._xlabel = function (frame, page, target, ...)
--	local page = "User:Jts1882/sandbox/test/Passeriformes"
--	local label = frame.args[1] or frame.args['label']
	local args = { ... }
	local output = ""
	
	if not args[1] then return p.errormsg ("Label name not provided") end

	local fullOutput =  p._label(frame, page, target) 
	--local fullOutput =  p._section(frame, page, target) 

	output=fullOutput

	local title = mw.title.new( mw.text.trim(page)) -- , ns)  -- creates object if page doesn't exist (and valid page name)
	                                            --TODO: could use mw.title.makeTitle(), but that needs ns
	if title and title.exists then 
		local content = title:getContent()

		for k,v in pairs(args) do
			local section = mw.text.trim(v)
			local targetType = "label%d"
			local cladePrefix = "%d"
			if string.upper( section) == section then
				 targetType = "target%u"               -- by convention subtrees must be uppercase
				 cladePrefix = "subclade%u"
		    end

			--                label      = [[        name       ]]                 |n=   {...}
            local pattern = "("..targetType.."=[%s%p]*"..section .. "[%s%p]*.-"..cladePrefix.."=.-)(%b{})"
                                                                                        -- ^^ this .- skips section tags before clade
                                                                   -- ^^this .- skips |sublabel and styling following the label (but can return wrong clade when a subtree)
          
            
            --for value in string.gmatch( fullOutput , pattern ) do
            local value = string.match( fullOutput , pattern ) 

            
            if value then
            	local trimmedTree, matches = string.gsub(fullOutput, pattern, "%1".."replacement string")--replaces pattern with capture %1
 
            	--output = output .. trimmedTree
            	--output = output .. "<pre>" .. trimmedTree .. "</pre>"
                fullOutput = trimmedTree
            else
            	output = output .. p.errormsg ("Failed to capture subclade with label "..section)
            end

		end
		

    else
    	return  '<span class="error">No page title found</span>'
	end

    if output ~= "" then 
		return  frame:preprocess(fullOutput)
	else 
		return '<span class="error">Section for label not found</span>' 
    end
end	


--=============================== extract LABELS or SUBTREES=======================================
p.label = function (frame, page, ...)
	local page = frame.args[1] --"User:Jts1882/sandbox/test/Passeriformes"
	local label = frame.args[1] or frame.args['label'] or frame.args['label1']
	local wrap = frame.args['wrap'] 
	
	local output = p._label (frame, page, frame.args[2], frame.args[3], frame.args[4], frame.args[5] )
	if wrap then
		local label1 = string.lower(frame.args[2])
		if wrap ~= "" then label1 = wrap end
		output = "{{clade |label1=" .. p.firstToUpper(label1) .. "|1=" .. output .. "}}"
    end
	return frame:preprocess(output)
end

p._label = function (frame, page, ... )
--	local page = "User:Jts1882/sandbox/test/Passeriformes"
--	local label = frame.args[1] or frame.args['label']
	local args = { ... }
	local output = ""
	
	if not args[1] then return p.errormsg ("Label name not provided") end
	
	local title = mw.title.new( mw.text.trim(page)) -- , ns)  -- creates object if page doesn't exist (and valid page name)
	                                            --TODO: could use mw.title.makeTitle(), but that needs ns
	if title and title.exists then 
		local content = title:getContent()
		local targetType = "label%d"
		local cladePrefix = "%d"
		for k,v in pairs(args) do
			local section = mw.text.trim(v)
			if string.upper( section) == section then
				 targetType = "target%u"               -- by convention subtrees must be uppercase
				 cladePrefix = "subclade%u"
		    end

			--               label =   [[        name     ]]   |n=   {...}
            --local pattern = "label%d=[%s%p]*"..section .. "[%s%p]*%d=(%b{})"
                                                                -- the .- skips section tags before clade
            --local pattern = "label%d=[%s%p]*"..section .. "[%s%p]*%d=.-(%b{})"
                                                   -- this .- skips |sublabel and styling following the label (but can return wrong clade when a subtree)
            --local pattern = "label%d=[%s%p]*"..section .. ".-%d=.-(%b{})"
            local pattern = targetType.."=[%s%p]*"..section .. "[%s%p]*.-"..cladePrefix.."=.-(%b{})"
            
            -- for subtrees (how to capture right )
            --local pattern = "[%u]=[%s%p]*"..section .. ".-%d=.-(%b{})"
            
            
            local value = string.match( content , pattern )
            
	
            
            if value then
            	
                -- what if we have something like {FABIDS}   "{%u}"
                local pattern = "({%u-})"
	            if string.find(value, pattern ) then          -- if a subtree that hasn't been substituted.
	            	 --local i,j,target = string.find(value, pattern) -- only one subtree
	            	 for target in string.gmatch( value , pattern ) do
	            	   	 local subtree = p._label (frame, page, target) 
		            	 if subtree then
		            	 	value = string.gsub(value, target, subtree)
		            	 end
		            	 --return value  
		            	 --value = value .. " (subtree needs transcluding)"
	            	 end
	            end
	            --if (1==1) then return "Captured pattern=" .. (value or "no match")  end             	
            	
            	section = string.lower(section)
            	output = output .. value
            	--output = output ..  "{{clade |label1=" .. p.firstToUpper(section) .. "|1=" .. value .. "}}"
            else
            	output = output .. p.errormsg ("Failed to capture subclade with label "..section)
            end

		end
		

    else
    	return  '<span class="error">No page title found</span>'
	end

    if output ~= "" then 
		--return  frame:preprocess(output)
		return output -- preprocess in entry function
	else 
		return '<span class="error">Section for label not found</span>' 
    end
end	
p.section = function (frame)
	-------------------------target page  ---- sections
	return frame:preprocess(p._section(frame, mw.text.trim(frame.args[1]),frame.args[2],frame.args[3],frame.args[4],frame.args[5]))
end
p._section = function (frame,page,...)
	local args = { ... }
	local output = ""
	local title = mw.title.new( page) -- , ns)  -- creates object if page doesn't exist (and valid page name)
	                                            --TODO: could use mw.title.makeTitle(), but that needs ns
	if title and title.exists then 
		local content = title:getContent()
		
		content = string.gsub( content , "%<%!%-%-.-%-%-%>", "" ) -- strip out comments
		
		for k,v in pairs(args) do
			local section = mw.text.trim(v)
			--[[ note: using the non-greedy - in (.-) to allow capture of several sections 
			    this allows internal clade structures to be closed without capturing sisters clades
			    e.g. see section Tyranni in User:Jts1882/sandbox/test/Passeriformes
			]]
			local pattern = "<section begin="..section.."[ ]*/>(.-)<section end="..section.."[ ]*/>"

			for value in string.gmatch( content , pattern ) do
			    if value then 
					if frame.args.wrap or frame:getParent().args.wrap then
						local label1 = frame.args.wrap or frame:getParent().args.wrap 
						if label1 == "" then label1 = section end
						value =  "{{clade |label1=" .. label1 .. "|1=" .. value .. "}}"
				    end
					output = output .. value
				end

			end
		end
		

    else
    	return  '<span class="error">No page title found</span>'
	end
    
    if output ~= "" then 
		--return  frame:preprocess(output)
		return output -- leave preprocessing for entry function
	else 
		return '<span class="error">Section not found</span>' 
    end

end 

p.xsection = function (frame)
	local page = frame.args[1] --"User:Jts1882/sandbox/test/Passeriformes"
	local label = frame.args[1] or frame.args['label'] or frame.args['label1']
	                                       -- page , target tree,  sections to exclude ...	
	return frame:preprocess(p._xsection(frame, page ,frame.args[2],frame.args[3],frame.args[4],frame.args[5]))
end

p._xsection = function (frame,page, target, ...)
	local args = { ... }
	local output = ""
	local title = mw.title.new( page) -- , ns)  -- creates object if page doesn't exist (and valid page name)
	                                            --TODO: could use mw.title.makeTitle(), but that needs ns
	                                            
	
	
	                                            
	if title and title.exists then 
		local content = title:getContent()
		local fullOutput =  p._section(frame, page, target) 
	    output=fullOutput
	    
		
		for k,v in pairs(args) do
			local section = mw.text.trim(v)
			--[[ note: using the non-greedy - in (.-) to allow capture of several sections 
			    this allows internal clade structures to be closed without capturing sisters clades
			    e.g. see section Tyranni in User:Jts1882/sandbox/test/Passeriformes
			]]
			local pattern = "(<section begin="..section.."[ ]*/>)(.-)(<section end="..section.."[ ]*/>)"

            local value = string.match( fullOutput , pattern ) 

            
            if value then
            	local trimmedTree, matches = string.gsub(fullOutput, pattern, "replacement string")--replaces pattern with capture %1
 
            	output = output .. trimmedTree
            	output = output .. "<pre>" .. trimmedTree .. "</pre>"
                fullOutput = trimmedTree
            else
            	output = output .. p.errormsg ("Failed to capture subclade with label "..section)
            end

		end
		

    else
    	return  '<span class="error">No page title found</span>'
	end
    
    if output ~= "" then 
		--return  frame:preprocess(output)
		return output -- leave preprocessing for entry function
	else 
		return '<span class="error">Section not found</span>' 
    end

end 
function p.populations(frame)
    local args = frame.args
    local page = "List of countries by population (United Nations)"
	local output = ""
	local data = {}
	local total = 0
	local totalProjected = 0
	local count = 0
	local title = mw.title.new( page) -- , ns)  -- creates object if page doesn't exist (and valid page name)
	                                            --TODO: could use mw.title.makeTitle(), but that needs ns
	if title and title.exists then 
		local content = title:getContent()

		local pattern = "<section begin=date_1[ ]*/>(.-)<section end=date_1[ ]*/>"
		for value in string.gmatch( content , pattern ) do
			data['date']=value                                    -- date of latest data 
		end
		local pattern = "<section begin=date_0[ ]*/>(.-)<section end=date_0[ ]*/>"
		for value in string.gmatch( content , pattern ) do
			data['date2']=value                                    -- date of previous data 
		   data['date2']=mw.getContentLanguage():formatDate('j F Y', value)
		end		
		data['today'] = mw.getContentLanguage():formatDate('j F Y')      -- today's date (for formatting see https://www.mediawiki.org/wiki/Help:Extension:ParserFunctions#.23time)

        local ay =  (frame:callParserFunction{ name = '#time', args = { "U", data['today'] } }
                   - frame:callParserFunction{ name = '#time', args = { "U", data['date2'] } })
                       /60/60/24/365.2425 -- number of years since first date until today‬


		for k,v in pairs(args) do
			local country = mw.text.trim(v)
			
			-- get population data from section 
		    local section = country .. "_1"
			local pattern = "<section begin="..section.."[ ]*/>(.-)<section end="..section.."[ ]*/>"

			for value in string.gmatch( content , pattern ) do
			    if value then 
			    	count=count+1
			    	data[count] = {}
			        data[count]['country'] = country
					data[count]['populationString'] = frame:preprocess(value)
					local raw = string.gsub(data[count]['populationString'], ",", "") -- strip formatting from number string
                    data[count]['populationNumber'] = tonumber(raw)
                    total = total + data[count]['populationNumber']
                    
                    local section = country .. "_0"
		           	local pattern2 = "<section begin="..section.."[ ]*/>(.-)<section end="..section.."[ ]*/>"
		           	for value2 in  string.gmatch( content , pattern2 ) do
						data[count]['populationString2'] = frame:preprocess(value2)
						local raw = string.gsub(data[count]['populationString2'], ",", "") -- strip formatting from number string
	                    data[count]['populationNumber2'] = tonumber(raw)
	                    data[count]['populationIncrement']=data[count]['populationNumber'] - data[count]['populationNumber2']
	                    data[count]['populationGrowth'] =data[count]['populationIncrement']/data[count]['populationNumber2']
	                    data[count]['populationDouble'] = math.log( 2 ) / math.log(1 + data[count]['populationGrowth'])

	                    data[count]['populationProjected'] = math.pow(data[count]['populationNumber2'], 1 - ay ) 
	                                                       * math.pow(data[count]['populationNumber'], ay)
	                    totalProjected = totalProjected + data[count]['populationProjected'] 
	                end
				end
			end
		end
		
        local sort_function = function( a,b )
		    if (tonumber(a.populationNumber) > tonumber(b.populationNumber)) then                -- primary sort on 'population' -> a before b
		        return true
		    end
		end
		local test = "test: " 
		local number=5435.12345 
		test= 	fn.formatNum(5435.12345,"en",0)
		--test=   frame:expandTemplate{ title = "formatnum", args = { totalProjected ,"en",0 } }
		--test=frame:callParserFunction{ name = 'formatnum', args = { totalProjected, decs=2 } }
		
        table.sort(data, sort_function)
        
        local i = 1
        -- output table
        output = '{| class="wikitable sortable" style="text-align:right;" ' 
                  .. '\n!rowspan=2|#'
                  .. '\n!rowspan=2|Country'
                  .. '\n!rowspan=2|Projected population<br/>(' .. data['today'] .. ')' 
                  .. '\n!rowspan=2|Pct of total'
                  .. '\n!rowspan=2|Population<br/>(' .. data['date'] .. ')' 
                  --.. '\n!rowspan=2|Pct of total'
                  .. '\n!rowspan=2|Previous Population<br/>(' .. data['date2'] .. ')'
                  .. '\n!colspan=2|Annual growth'
                  .. '\n!rowspan=2|Doubling time<br/>(years)'
                  .. '\n|-\n!Increment'
                  .. '\n!Rate'                  
        while (data[i]) do
           output = output .. '\n|-\n|' ..  i 
           output = output .. '\n|style="text-align:left;" |' .. frame:expandTemplate{ title = "flagcountry", args = {data[i]['country'] }  }
           output = output .. '\n| ' .. mm._precision_format(data[i]['populationProjected'],0)  
           --output = output .. '\n| ' .. fn.formatNum(data[i]['populationProjected'],"en",0)  
           output = output .. '\n| ' .. mm._precision_format(data[i]['populationProjected']/totalProjected*100,2) .. "%" -- projected
           output = output .. '\n| ' .. data[i]['populationString'] 
           --output = output .. '\n| ' .. fn.formatNum(data[i]['populationNumber']/total*100,"en",2) .. "%"
           output = output .. '\n| ' .. data[i]['populationString2'] 
           output = output .. '\n| ' .. mm._precision_format(data[i]['populationIncrement'],0) 
           output = output .. '\n| ' .. mm._round(data[i]['populationGrowth']*100,2) .. "%"
           output = output .. '\n| ' .. mm._round(data[i]['populationDouble'],0)
           i=i+1
        end
                
        output = output .. '\n|-\n! !! Total' 
                        .. '\n! style="text-align:right;" |' .. fn.formatNum(mm._round(totalProjected,0),"en",0) 
                        .. '\n! style="text-align:right;" | 100% '
                        .. '\n! style="text-align:right;" |' .. fn.formatNum(total,"en",0) 
                        --.. '\n! style="text-align:right;" | 100% '
                        .. '\n! || || ||' -- ..test
        output = output .. '\n|}'
    else
    	return  '<span class="error">No page title found</span>'
	end

   
   
   
   return output
end

function p.firstToUpper(str)
    return (str:gsub("^%l", string.upper))
end
p.errormsg = function (message)
	return '<span class="error">' .. message .. '</span>' 
end	

return p
Categories
Table of Contents