Модуль:StatisticalРеализация шаблона {{Население}} и, вероятно, некоторых других шаблонов. local p = {}
local templateIncrease = 'Увеличение'
local templateDecrease = 'Уменьшение'
local templateNoChange = 'Без изменения'
local Regions = mw.loadData("Модуль:Statistical/Regions")
bit32 = require( 'bit32' )
local function LimitDouble(Val)
local MaxNumber = 2147483648
return Val - (math.floor(Val / MaxNumber) * MaxNumber)
end
local function shl(Val, Shift)
if Shift > 0 then
return LimitDouble(Val * (2 ^ Shift))
else
return Value
end
end
local function shr(Val, Shift)
if Shift > 0 then
return math.floor(Val / (2 ^ Shift))
else
return Val
end
end
-- Код основан на алгоритме SuperFastHash:
-- http://www.azillionmonkeys.com/qed/hash.html
local function MakeHash(PlaceName)
local dataLength = mw.ustring.len(PlaceName)
if dataLength == 0 then return 0 end
local hash = dataLength
local remainingBytes = math.fmod(dataLength, 2)
local numberOfLoops = math.floor(dataLength / 2)
local currentIndex = 0
local tmp = 0
while (numberOfLoops > 0) do
hash = LimitDouble(hash + mw.ustring.codepoint(PlaceName, currentIndex + 1))
tmp = bit32.bxor(shl(mw.ustring.codepoint(PlaceName, currentIndex + 2), 11), hash)
hash = bit32.bxor(shl(hash, 16), tmp)
hash = LimitDouble(hash + shr(hash, 11))
currentIndex = currentIndex + 2
numberOfLoops = numberOfLoops - 1
end
if remainingBytes == 1 then
hash = LimitDouble(hash + mw.ustring.codepoint(PlaceName, currentIndex + 1))
hash = bit32.bxor(hash, shl(hash, 10))
hash = LimitDouble(hash + shr(hash, 1))
end
hash = bit32.bxor(hash, shl(hash, 3))
hash = LimitDouble(hash + shr(hash, 5))
hash = bit32.bxor(hash, shl(hash, 4))
hash = LimitDouble(hash + shr(hash, 17))
hash = bit32.bxor(hash, shl(hash, 25))
hash = LimitDouble(hash + shr(hash, 6))
return hash
end
local function First_less_Second(a, b)
local LenA = mw.ustring.len(a)
local LenB = mw.ustring.len(b)
for i = 1, (LenA < LenB) and LenA or LenB do
if mw.ustring.codepoint(a, i, i) ~= mw.ustring.codepoint(b, i, i) then
return mw.ustring.codepoint(a, i, i) < mw.ustring.codepoint(b, i, i)
end
end
return LenA < LenB
end
function GetHashData(PlaceHash)
local NumPage = math.floor((PlaceHash - 1) / 33554432 + 2)
if NumPage == 2 and (PlaceHash - 1) < 16777216 then NumPage = 1 end
local templatename
if NumPage < 10 then templatename = "Население/STA-00"..NumPage else templatename = "Население/STA-0"..NumPage end
local page = mw.title.new(templatename, 10)
local RawData = page:getContent()
HashData = RawData:match("|" .. PlaceHash .. "=([^\n<]+)")
if (HashData=="") then HashData=nil
elseif (tonumber(HashData)~=nil) then HashData=tonumber(HashData) end
return HashData
end
function p.GenerateAndReturnHash(frame)
local args = frame:getParent().args
if args == nil then return "Введите название объекта АТД" end
local PlaceName = args[1]
if PlaceName == nil then return "Введите название объекта АТД" end
PlaceName = mw.text.trim(PlaceName)
local PlaceHash = MakeHash(PlaceName)
local NumPage = math.floor((PlaceHash - 1) / 33554432 + 2)
if NumPage == 2 and (PlaceHash - 1) < 16777216 then NumPage = 1 end
local templatename
if NumPage < 10 then templatename = "Население/STA-00"..NumPage else templatename = "Население/STA-0"..NumPage end
return PlaceHash..' → '..'[[Шаблон:'..templatename..']]'
end
function p.GetStat(frame)
local args
if frame == mw.getCurrentFrame() then
args = frame:getParent().args
else
args = frame
end
if args == nil then return "Введите название объекта АТД" end
local PlaceName = args[1]
local Format = mw.text.trim ( (args[2] or "Таблица"))
if PlaceName == nil then return "Введите название объекта АТД" end
PlaceName = mw.text.trim(PlaceName)
if Format == 'Хеш' or Format == 'х' then do return MakeHash(PlaceName) end end
local Region = args['Регион'] or ''
local check = args['check'] or ''
if check == '' or check == '0' or check == 'false' then
check = false;
else
check = true;
end
local PlaceData = nil
local RegionData = nil
local CheckRedirect = false
local NeedhandleRedirect = false
local function GetPlaceData()
local PlaceHash = MakeHash(PlaceName)
PlaceData = nil
RegionData = nil
local test = PlaceName:match("%((%P+)%)")
if Region=='' and test~='' then
-- Если в имени населенного пункта есть уточнение с именем региона, то можно не пользоваться индексной таблицей, то есть не вызывать GetHashData
local value = Regions[test]
if(value) then
RegionData = mw.loadData("Модуль:Statistical/"..value)
PlaceData = RegionData[PlaceHash]
end
elseif Region ~= "" then
-- магия, позволяющая указывать не только индекс, но и значение напрямую
Region = Regions[Region] or Region
RegionData = mw.loadData("Модуль:Statistical/"..Region)
PlaceData = RegionData[PlaceHash]
end
if PlaceData == nil then
local RegionPage = GetHashData(PlaceHash)
if RegionPage == 0 then return "#Н/Д"..frame:callParserFunction{name = '#tag:ref', args = {PlaceName .." > Совпадение хешей. Пожалуйста, укажите регион вручную, например <code><nowiki>{{ Население | " .. PlaceName .. " | " .. Format .." | Регион = Приморский край }}</nowiki></code>" .. ((args.nocat and "") or "[[Категория:Википедия:Статьи с неправильными параметрами шаблона Население]]")}} end
if RegionPage ~= nil then
if type(tonumber(RegionPage)) == "number" then
-- очень плохая вещь, ибо GetHashData очень дорогая по памяти функция
PlaceHash=tonumber(RegionPage)
RegionPage = GetHashData(PlaceHash)
end
if type(RegionPage) == "table" then RegionPage = RegionPage[PlaceName] end
if RegionPage ~= nil then
RegionData = mw.loadData("Модуль:Statistical/"..RegionPage)
if RegionData ~= nil then PlaceData = RegionData[PlaceHash] end
end
end
end
end
GetPlaceData()
-- Проверка на редирект, если данные не найдены
if PlaceData == nil then
local page = mw.title.makeTitle('', PlaceName)
if page.redirectTarget then
PlaceName = page.redirectTarget.text
GetPlaceData()
end
end
local IsWikidata
-- Если данные перемещены из шаблона Население в Wikidata, то работаем с ними
if PlaceData ~= nil then
IsWikidata = PlaceData == "Wikidata"
else
if check then
return 0;
else
--return "#Н/Д"..frame:callParserFunction{name = '#tag:ref', args = {PlaceName .." > Данные не обнаружены. Возможно, страница переименовывалась. Проверьте справочник".. ((args.nocat and "") or "[[Категория:Википедия:Статьи с неправильными параметрами шаблона Население]]")}}
-- Вместо прекращения работы при неудаче поиска данных в шаблоне Население попытка поиска в Wikdata
IsWikidata = true
end
end
if check then
return 1;
end
local LastRecord = 0
local Qcode
if IsWikidata then
Qcode = args.from or mw.wikibase.getEntityIdForTitle(PlaceName) or ""
if Qcode == "" then
local page = mw.title.makeTitle('', PlaceName)
if page.redirectTarget then
PlaceName = page.redirectTarget.text
Qcode = args.from or mw.wikibase.getEntityIdForTitle(PlaceName) or ""
end
end
if Qcode == "" then
return "#Н/Д"..frame:callParserFunction{name = '#tag:ref', args = {PlaceName .." > Данные в Wikidata не обнаружены.".. ((args.nocat and "") or "[[Категория:Википедия:Статьи с неправильными параметрами шаблона Население]]")}}
end
if next(mw.wikibase.getBestStatements(Qcode, 'P1082')) == nil then
return "#Н/Д"..frame:callParserFunction{name = '#tag:ref', args = {PlaceName .." > Данные в Wikidata не обнаружены.".. ((args.nocat and "") or "[[Категория:Википедия:Статьи с неправильными параметрами шаблона Население]]")}}
end
else
for k in pairs(PlaceData) do
LastRecord = LastRecord + 1
if args[3] ~= nil and PlaceData[LastRecord][1] == tonumber(args[3]) then
break
end
end
end
local NumRecord = LastRecord
local function FormatY()
if IsWikidata then
return frame:expandTemplate{ title = "Wikidata", args={from=Qcode,['property-module']="Statistical/Wikidata",['property-function']="FormatY",property="p1082[p585][rank:preferred, rank:normal]"} }
else
return PlaceData[NumRecord][1]
end
end
local function FormatN()
if IsWikidata then
return frame:expandTemplate{ title = "Wikidata", args={from=Qcode,['property-module']="Statistical/Wikidata",['property-function']="FormatN",property="p1082[p585][rank:preferred, rank:normal]"} }
else
return PlaceData[NumRecord][2]
end
end
local function FormatS(SourceType)
if IsWikidata then
return frame:expandTemplate{ title = "Wikidata", args={from=Qcode,['property-module']="Statistical/Wikidata",['property-function']="FormatS",property="p1082[p585][rank:preferred, rank:normal]"} }
else
if ( PlaceData[NumRecord][3] == nil or PlaceData[NumRecord][3] == '' ) then
return ""
else
local Source1
local Source2
if string.find(PlaceData[NumRecord][3],"%d+[A-Z]+")==1 then
if RegionData['Источники'][PlaceData[NumRecord][3]] ~= nil then
Source1 = RegionData['Источники'][PlaceData[NumRecord][3]][1]
Source2 = PlaceData[NumRecord][3]
else
Source1 = PlaceData[NumRecord][3] .. '[[Категория:Википедия:Статьи с неправильными источниками в модуле Statistical]]'
Source2 = ""
end
else
Source1 = PlaceData[NumRecord][3]
Source2 = ""
end
if string.find(Source1, "https?://")==1 then
Source1 = '['..Source1..']'
end
if SourceType == "и" then
return Source1
end
if Source2 == "" then
return frame:callParserFunction{name = '#tag:ref', args = {Source1}}
else
return frame:callParserFunction{name = '#tag:ref', args = {Source1, name = Source2}}
end
end
end
end
local function FormatF()
if IsWikidata then
return frame:expandTemplate{ title = "Wikidata", args={from=Qcode,['property-module']="Statistical/Wikidata",['property-function']="FormatF",property="p1082[p585][rank:preferred, rank:normal]"} }
else
local lang = mw.language.getContentLanguage()
return lang:formatNum( PlaceData[NumRecord][2] )
end
end
local function FormatT()
if IsWikidata then
return frame:expandTemplate{ title = "Wikidata", args={from=Qcode,['property-module']="Statistical/Wikidata",['property-function']="FormatT",property="p1082[p585][rank:preferred, rank:normal]"} }
else
if NumRecord > 1 then
if PlaceData[NumRecord][2] > PlaceData[NumRecord - 1][2] then
return frame:expandTemplate{
title = templateIncrease
}
elseif PlaceData[NumRecord][2] < PlaceData[NumRecord - 1][2] then
return frame:expandTemplate{
title = templateDecrease
}
else
return frame:expandTemplate{
title = templateNoChange
}
end
else
return ""
end
end
end
local function FormatD()
if IsWikidata then
return frame:expandTemplate{ title = "Wikidata", args={from=Qcode,['property-module']="Statistical/Wikidata",['property-function']="FormatD",property="p1082[p585][rank:preferred, rank:normal]"} }
else
local tempHeight = 320
local tempWidth = 800
mw.logObject(LastRecord)
local tickCount = 5
if LastRecord > 100 then
tickCount = 10
end
local tempMod = math.fmod (LastRecord, tickCount)
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 in pairs(PlaceData) do
NumRecord = k
tempGroup = tempGroup .. FormatN() .. ":"
tempTooltip = tempTooltip .. FormatF() .. " (" .. FormatY() .. "):"
if LastRecord < tickCount or math.fmod (k, tickCount) == tempMod then tempLegend = tempLegend .. FormatY() 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
end
local function FormatG()
local csv = ""
if IsWikidata then
csv = frame:expandTemplate{ title = "Wikidata", args={from=Qcode,['property-module']="Statistical/Wikidata",['property-function']="FormatG",property="p1082[p585][rank:preferred, rank:normal]"} }
else
csv = "year,population,formatted\\n"
for k in pairs(PlaceData) do
NumRecord = k
csv = csv .. FormatY() .. "," .. FormatN() .. "," .. FormatF() .. "\\n"
end
end
local json = [[{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 400,
"height": 200,
"data": [
{
"name": "table",
"values": "]] .. csv .. [[",
"format": {
"parse": {"year": "integer", "population": "integer", "formatted": "string"},
"type": "csv"
},
// Convert year integer (2016) into a date object (2016-01-01)
"transform": [{ "type": "formula", "as": "date", "expr": "utc(datum.year,0,1)" }]
}
],
"scales": [
// The dates are scaled to the "x" axis - the width of the graph
{
"name": "x",
"type": "utc",
"range": "width",
"domain": {"data": "table", "field": "date"}
},
// The population are scaled to the "y" axis - the height of the graph
{
"name": "y",
"type": "linear",
"range": "height",
"domain": {"data": "table", "field": "population"}
}
],
// Simple axis with horizontal grid lines
"axes": [
{"scale": "x", "orient": "bottom", "tickCount": 5},
{"scale": "y", "orient": "right", "tickCount": 5, "grid": true, "format": "d"}
],
// The graph is drawn with two elements a thick line at the top, and a semi-transparent area below
"marks": [
{
"type": "area",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "date"},
"y": {"scale": "y", "value": 0},
"y2": {"scale": "y", "field": "population"},
"fill": {"value": "#99B2CC"},
"fillOpacity": {"value": 0.35},
"interpolate": {"value": "linear"}
}
}
},
{
"type": "line",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "date"},
"y": {"scale": "y", "field": "population"},
"stroke": {"value": "#99B2CC"},
"strokeWidth": {"value": 3},
"interpolate": {"value": "linear"}
}
}
},
{
"type": "symbol",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "date"},
"y": {"scale": "y", "field": "population"},
"stroke": {"value": "#99B2CC"},
"fill": {"value": "#fff"},
"size": {"value": 10}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "date"},
"y": {"scale": "y", "field": "population", "offset": -1},
"align": {"value": "center"},
"opacity": {"value": "0"},
"fill": {"value": "#000000"},
"fontWeight": {"value": "bold"},
"size": {"value": 4},
"text": {"signal": "datum.formatted + ' (' + datum.year + ')'"}
},
"hover": {"opacity": {"value": "1"}},
"update": {"opacity": {"value": "0"}}
}
}
]
}]]
local cframe = mw.getCurrentFrame()
return cframe:callParserFunction{ name = '#tag:graph', args = { json, mode = 'interactive' } }
end
local function FormatTable()
-- Формирование HTML-таблицы
if IsWikidata then
return frame:expandTemplate{ title = "Wikidata", args={from=Qcode, column = args['Столбцов'], decor = args['Оформление'], titul = args['Заголовок'], ['property-module']="Statistical/Wikidata",['property-function']="FormatTable",property="p1082[p585][rank:preferred, rank:normal]"} }
else
local HTML = mw.html.create('table')
local MaxData
if args['Столбцов'] then
Column = tonumber(args['Столбцов'])
else
Column = 7
end
if Column > LastRecord then Column = LastRecord end
if args['Оформление'] ~= nil then
HTML:attr('class', args['Оформление'])
else
HTML:attr('class', 'standard')
end
local TempRow
local NumRow = 0
HTML:tag('caption')
:wikitext(args['Заголовок'] or 'Численность населения')
:css('background-color', 'var(--ruwiki-background-color-blue200, #cfe3ff)')
:css('color', 'inherit')
:css('border', '1px solid var(--border-color-base, #a2a9b1)')
:css('border-bottom', '0')
for i = 1, math.ceil(LastRecord / Column) do
TempRow = HTML:tag('tr')
for j = 1, Column do
NumRecord = (i - 1) * Column + j
if PlaceData[NumRecord] == nil then
TempRow:tag('th'):attr('scope', 'col'):wikitext("")
else
TempRow:tag('th'):attr('scope', 'col'):wikitext(FormatY()..FormatS("с"))
end
end
TempRow = HTML:tag('tr'):css('text-align', 'center')
for j = 1, Column do
NumRecord = (i - 1) * Column + j
if PlaceData[NumRecord] == nil then
TempRow:tag('td'):wikitext("")
else
TempRow:tag('td'):wikitext(FormatT()..FormatF())
end
end
end
return tostring(HTML)
end
end
if Format == 'Год' or Format == 'г' then
mw.logObject(Format)
return FormatY()
elseif Format == 'Безформат' or Format == 'Число' or Format == 'ч' then
return FormatN()
elseif Format == 'Ссылка' or Format == 'с' then
return FormatS("с")
elseif Format == 'Источник' or Format == 'и' then
return FormatS("и")
elseif Format == 'Формат' or Format == 'ф' then
return FormatF()
elseif Format == 'ФорматГод' or Format == 'фг' then
return FormatF().." ("..FormatY()..")"
elseif Format == 'ФорматСсылка' or Format == 'фс' then
return FormatF()..FormatS()
elseif Format == 'ФорматСсылкаГод' or Format == 'фсг' then
return FormatF()..FormatS().." ("..FormatY()..")"
elseif Format == 'Тренд' or Format == 'т' then
return FormatT()..FormatF()
elseif Format == 'Значение' or Format == 'ТрендСсылка' or Format == 'тс' then
return FormatT()..FormatF()..FormatS()
elseif Format == 'ТрендСсылкаГод' or Format == 'тсг' then
return FormatT()..FormatF()..FormatS().." ("..FormatY()..")"
elseif Format == 'Диаграмма' or Format == 'д' or Format == 'График' or Format == 'график' then -- пока в Википедии отключены графики, вместо них временно выводим диаграммы
mw.logObject(FormatD())
return FormatD()
elseif Format == 'График' or Format == 'график' then
return FormatG()
else
return FormatTable()
end
return 1, Format
end
return p
|
Index:
pl ar de en es fr it arz nl ja pt ceb sv uk vi war zh ru af ast az bg zh-min-nan bn be ca cs cy da et el eo eu fa gl ko hi hr id he ka la lv lt hu mk ms min no nn ce uz kk ro simple sk sl sr sh fi ta tt th tg azb tr ur zh-yue hy my ace als am an hyw ban bjn map-bms ba be-tarask bcl bpy bar bs br cv nv eml hif fo fy ga gd gu hak ha hsb io ig ilo ia ie os is jv kn ht ku ckb ky mrj lb lij li lmo mai mg ml zh-classical mr xmf mzn cdo mn nap new ne frr oc mhr or as pa pnb ps pms nds crh qu sa sah sco sq scn si sd szl su sw tl shn te bug vec vo wa wuu yi yo diq bat-smg zu lad kbd ang smn ab roa-rup frp arc gn av ay bh bi bo bxr cbk-zam co za dag ary se pdc dv dsb myv ext fur gv gag inh ki glk gan guw xal haw rw kbp pam csb kw km kv koi kg gom ks gcr lo lbe ltg lez nia ln jbo lg mt mi tw mwl mdf mnw nqo fj nah na nds-nl nrm nov om pi pag pap pfl pcd krc kaa ksh rm rue sm sat sc trv stq nso sn cu so srn kab roa-tara tet tpi to chr tum tk tyv udm ug vep fiu-vro vls wo xh zea ty ak bm ch ny ee ff got iu ik kl mad cr pih ami pwn pnt dz rmy rn sg st tn ss ti din chy ts kcg ve
Portal di Ensiklopedia Dunia