Модуль:Statistical/Wikidata

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
Документация
local p={}

local function deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[deepcopy(orig_key)] = deepcopy(orig_value)
        end
        setmetatable(copy, deepcopy(getmetatable(orig)))
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end

local function formatPopulationPropertyImpl( context, options )
	if ( not context ) then error( 'context not specified' ); end;
	if ( not options ) then error( 'options not specified' ); end;
	if ( not options.entity ) then error( 'options.entity missing' ); end;

    local claims = context.selectClaims( options, options.property );
    if (claims == nil) then
        return nil -- TODO error?
    end
    
    local validClaims = {}
    for _, claim in ipairs( claims ) do
    	-- проверка на наличие корректного момента времени
    	if claim.qualifiers.P585[1] and claim.qualifiers.P585[1].snaktype == 'value' then
    		table.insert( validClaims, claim )
		end
    end

    if #validClaims == 0 then
        return nil -- TODO error?
    end

	local comparator = function( o1, o2 )
		local t1 = context.parseTimeFromSnak( o1.qualifiers.P585[1] )
		local t2 = context.parseTimeFromSnak( o2.qualifiers.P585[1] )
		return t1 < t2
	end
	table.sort( validClaims, comparator )

	return validClaims
end

local function GetFormatY(claim)
	local timeQualifier = claim.qualifiers.P585[1];
	if ( timeQualifier.datavalue.value.precision > 9 ) then
		timeQualifier = deepcopy( timeQualifier );
		timeQualifier.datavalue.value.precision = 9;
	end
	local year = string.sub( timeQualifier.datavalue.value.time, 2, 5 );
	return year
end

function p.FormatY(context, options)
	local claims = formatPopulationPropertyImpl( context, options );
	return GetFormatY(claims[#claims])
end

local function GetFormatN(claim)
	local out = string.gsub(claim.mainsnak.datavalue.value.amount, '+', '')
	return out
end

function p.FormatN(context, options)
	local claims = formatPopulationPropertyImpl( context, options );
	return GetFormatN(claims[#claims])
end
	
local function GetFormatS(context, options, claim)
	local out = context.formatRefs(options, claim)
	return out
end
	
function p.FormatS(context, options)
	local claims = formatPopulationPropertyImpl( context, options );
	local out = GetFormatS(context, options, claims[#claims])
	return out
end
	
local function GetFormatF(context, options, claim)
	local out = context.formatSnak( options, claim.mainsnak )
	out = string.gsub(out, '<[^>]*>', '')
	out = string.gsub(out, '%s*±.+', '')
	return out
end

function p.FormatF(context, options)
	local claims = formatPopulationPropertyImpl( context, options );
	return GetFormatF(context, options, claims[#claims])
end

local function GetFormatT(claims, index)
    if index > 1 then
		local FirstClaim = string.gsub(claims[index].mainsnak.datavalue.value.amount, '+', '')
		local SecondClaim = string.gsub(claims[index-1].mainsnak.datavalue.value.amount, '+', '')
        if FirstClaim > SecondClaim then
            return "<span style='color: #0c0; font-weight:bold; font-size: larger;'>↗</span>" 
        elseif FirstClaim < SecondClaim then
            return "<span style='color: red; font-weight:bold; font-size: larger;'>↘</span>"  
        else
            return "<span style='color:#0AF;'>→</span>"  
        end
    else
        return ""
    end
end

function p.FormatT(context, options)
	local claims = formatPopulationPropertyImpl( context, options );
	return GetFormatT(claims, #claims)
end

function p.FormatD(context, options)
	local claims = formatPopulationPropertyImpl( context, options );
	local LastRecord = #claims

	local tempHeight = 320
	local tempWidth = 800
	local tempMod = math.fmod (LastRecord, 5)
	if LastRecord < 40 then 
		tempHeight = 200  + 170 * (LastRecord - 1) / 40
		tempWidth = 200 + 600 * (LastRecord - 1) / 40
	end
	local tempGroup = ""
	local tempTooltip = ""
	local tempLegend = ""
    for k, claim in ipairs( claims ) do
		tempGroup = tempGroup .. GetFormatN(claim) .. ":"
		tempTooltip = tempTooltip .. GetFormatF(context, options, claim) .. " (" .. GetFormatY(claim) .. "):"
		if LastRecord < 5 or math.fmod (k, 5) == tempMod  then tempLegend = tempLegend .. GetFormatY(claim) end
		tempLegend = tempLegend .. ":"
    end	
	tempGroup = string.sub (tempGroup, 1, string.len (tempGroup)-1)
	tempTooltip = string.sub (tempTooltip, 1, string.len (tempTooltip)-1)
	tempLegend = string.sub (tempLegend, 1, string.len (tempLegend)-1)
	local barChart = require('Модуль:Chart')['bar chart'];
	local Diagram = {
		['height'] = tempHeight,
		['width'] = tempWidth,
		['group 1'] = tempGroup,
		['tooltip 1'] = tempTooltip,
		['colors'] = "#B0C4DE",
		['x legends'] = tempLegend,
		['group names'] = 'Численность населения',
		['default color'] = '#1E90FF'
		}    	
	local cframe = mw.getCurrentFrame();	
	return barChart(cframe:newChild{ title=cframe.title, args = Diagram})	
end

function p.FormatG(context, options)
	local claims = formatPopulationPropertyImpl( context, options );
	local csv = "year,population,formatted\\n"
    for _, claim in ipairs( claims ) do
		csv = csv .. GetFormatY(claim) .. "," .. GetFormatN(claim) .. "," .. GetFormatF(context, options, claim) .. "\\n"
    end	
	return csv
end	

function p.FormatTable(context, options)
	local claims = formatPopulationPropertyImpl( context, options );
	local HTML = mw.html.create('table')
	local LastRecord = #claims
	local NumRecord
    local MaxData
    local Column = tonumber(options.column or 7)
    if Column > LastRecord then Column = LastRecord end

    HTML:attr('class', options.decor or 'standard') 

    local TempRow
    local NumRow = 0
    HTML:tag('caption')
    	:wikitext(options.titul or 'Численность населения')
		:css('background-color', '#ebf3ff')
		:css('border', '1px solid #d6dadd')
		
    for i = 1, math.ceil(LastRecord / Column) do
        TempRow = HTML:tag('tr'):addClass("bright")
        for j = 1, Column do
			NumRecord = (i - 1) * Column + j
            if claims[NumRecord] == nil then
                TempRow:tag('th'):attr('scope', 'col'):wikitext("")
            else
                TempRow:tag('th'):attr('scope', 'col'):wikitext(GetFormatY(claims[NumRecord])..GetFormatS(context, options, claims[NumRecord]))
            end
        end

        TempRow = HTML:tag('tr'):css('text-align', 'center')
        for j = 1, Column do
			NumRecord = (i - 1) * Column + j
            if claims[NumRecord] == nil then
                TempRow:tag('td'):wikitext("")
            else
                TempRow:tag('td'):wikitext(GetFormatT(claims, NumRecord)..GetFormatF(context, options, claims[NumRecord]))
            end
        end
    end            
    return tostring(HTML)
end	        

return p