Відмінності між версіями «Модуль:Graph»

updated from de.wikipedia.org
(кут нахилу тексту, примусове вирівнювання)
(updated from de.wikipedia.org)
-- УВАГАATTENTION: Будь ласка,Please редагуйтеedit цейthis кодcode наat https://de.wikipedia.org/wiki/Modul:Graph
-- This way all wiki languages can stay in sync. Thank you!
-- Таким чином код в усіх мовних розділах буде ідентичним. Дякуємо!
--
-- Version History:
-- Історія версій:
-- 2016-01-09 _PLEASE UPDATE when modifying anything_
-- 2016-01-09 _БУДЬ ЛАСКА, ПОНОВІТЬ ДАТУ при внесенні будь-яких змін_
-- 2016-01-28 ДляFor картmaps, завждиalways використовуйте протоколuse wikiraw:// protocol. Протокол https:// невдовзіwill be будеdisabled деактивованийsoon.
-- 2016-03-20 Allow omitted data for charts, labels for line charts with string (ordinal) scale at point location
-- 2016-05-16 Added encodeTitleForPath() to help all path-based APIs graphs like pageviews
 
local p = {}
local isInteger = true
for i = 1, #list do
resultif list[i] == tonumber(list[i])"" then
if not result[i] then return= endnil
else
if isInteger then
local int, fracresult[i] = math.modftonumber(resultlist[i])
if not result[i] then return end
isInteger = frac == 0.0
if isInteger then
local int, frac = math.modf(result[i])
isInteger = frac == 0.0
end
end
end
 
function p.map(frame)
-- map path data for geographic objects
-- дані контурів карт для географічних об’єктів
local basemap = frame.args.basemap or "WorldMap-iso2.json"
-- scaling factor
-- масштабний коефіцієнт
local scale = tonumber(frame.args.scale) or 100
-- проекціяmap картиprojection, див.see https://github.com/mbostock/d3/wiki/Geo-Projections
local projection = frame.args.projection or "equirectangular"
-- defaultValue for geographic objects without data
-- значення за замовчанням для географічних об’єктів без даних
local defaultValue = frame.args.defaultValue
local scaleType = frame.args.scaleType or "linear"
-- minimaler Wertebereich (nur für numerische Daten)
-- мінімальний діапазон значень (тільки для цифрових даних)
local domainMin = tonumber(frame.args.domainMin)
-- maximaler Wertebereich (nur für numerische Daten)
-- максимальний діапазон значень (тільки для цифрових даних)
local domainMax = tonumber(frame.args.domainMax)
-- Farbwerte der Farbskala (nur für numerische Daten)
-- кольорові координати шкали кольорів (тільки для цифрових даних)
local colorScale = frame.args.colorScale or "category10"
-- show legend
-- показати легенду
local legend = frame.args.legend
-- format JSON output
-- вивести в форматі JSON
local formatJson = frame.args.formatjson
 
-- map data are key-value pairs: keys are non-lowercase strings (ideally ISO codes) which need to match the "id" values of the map path data
-- картографічні дані — пари ключ-значення: ключі — рядки тільки з великих літер (бажано ISO-коди), які мають відповідати значенням "id" даних контурів карт
local values = {}
local isNumbers = nil
end
 
-- create highlight scale
-- створити шкалу виділення
local scales
if isNumbers then
if domainMax then scales[1].domainMax = domainMax end
 
local exponent = string.match(scaleType, "pow%s+(%d+%.?%d+)") -- перевіркаcheck експонентиfor exponent
if exponent then
scales[1].type = "pow"
end
 
-- create legend
-- створити легенду
if legend then
legend =
end
 
-- get map url
-- отримати url карти
local basemapUrl
if (string.sub(basemap, 1, 10) == "wikiraw://") then
basemapUrl = basemap
else
-- if not a (supported) url look for a colon as namespace separator. If none prepend default map directory name.
-- якщо url відсутній або не підтримується, шукати двокрапку як роздільник між простором назв і заголовком. Якщо двокрапки немає, подати першою директорію карти за замовчанням.
if not string.find(basemap, ":") then basemap = baseMapDirectory .. basemap end
basemapUrl = "wikiraw:///" .. mw.uri.encode(mw.title.new(basemap).prefixedText, "PATH")
{
version = 2,
width = 1, -- generic value as output size depends solely on map size and scaling factor
width = 1, -- загальне значення, оскільки розмір виводу залежить виключно від розміру карти і масштабного коефіцієнту
height = 1, -- див. вищеditto
data =
{
{
-- data source for the highlights
-- джерело даних для виділень
name = "highlights",
values = values
},
{
-- data source for map paths data
-- джерело даних для контурів карт
name = "countries",
url = basemapUrl,
{
{
-- geographic transformation ("geopath") of map paths data
-- географічна трансформація («геоконтур») даних про контури карт
type = "geopath",
value = "data", -- джерелоdata данихsource
scale = scale,
translate = { 0, 0 },
},
{
-- join ("zip") of mutiple data source: here map paths data and highlights
-- об’єднання («зіп») кількох джерел даних: тут — контурів карт і виділень
type = "lookup",
keys = { "id" }, -- ключkey дляfor данихmap проpaths контури картdata
on = "highlights", -- ім’яname джерелаof данихhighlight проdata виділенняsource
onKey = "id", -- ключkey дляfor джерелаhighlight данихdata про виділенняsource
as = { "zipped" }, -- ім’яname вихідноїof таблиціresulting table
default = { v = defaultValue } -- значенняdefault заvalue замовчаннямfor дляgeographic географічнихobjects об’єктів,that якіcould неnot вдалосяbe поєднатиjoined
}
}
marks =
{
-- output markings (map paths and highlights)
-- вивідна розмітка (контури карт і виділення)
{
type = "path",
}
for i = 1, #y do
local yLen = table.maxn(y[i])
for j = 1, #x do
if j <= #yLen and y[i][j] then table.insert(data.values, { series = seriesTitles[i], x = x[j], y = y[i][j] }) end
end
end
type = "linear",
range = "width",
zero = false, -- неdo включаєnot нульовеinclude значенняzero value
nice = true, -- примусовоforce виводитиround кругліnumbers числаfor дляy шкали yscale
domain = { data = "chart", field = "x" }
}
if chartType == "rect" then
xscale.type = "ordinal"
if not stacked then xscale.padding = 0.2 end -- доповнитиpad пробіламeach кожнуbar з групgroup
else
if xType == "date" then xscale.type = "time"
elseif xType == "string" then xscale.type = "ordinal" end
xscale.type = "ordinal"
xscale.points = true
end
end
 
type = "linear",
range = "height",
-- нижнєarea граничнеcharts значенняhave заливкиthe областейlower діаграмиboundary of their filling at y=0 (див.see marks.properties.enter.y2), томуtherefore these вониneed маютьto починатисяstart зat нуляzero
zero = chartType ~= "line",
nice = true
local function getAlphaColorScale(colors, y)
local alphaScale
-- if there is at least one color in the format "#aarrggbb", create a transparency (alpha) scale
-- якщо є принаймні один колір формату "#aarrggbb", створити (альфа-) шкалу прозорості
if isTable(colors) then
local alphas = {}
 
local function addInteractionToChartVisualisation(plotMarks, colorField, dataField)
-- initial setup
-- первісне налаштування
if not plotMarks.properties.enter then plotMarks.properties.enter = {} end
plotMarks.properties.enter[colorField] = { scale = "color", field = dataField }
 
-- action when cursor is over plot mark: highlight
-- дія, коли курсор над позначкою діаграми
if not plotMarks.properties.hover then plotMarks.properties.hover = {} end
plotMarks.properties.hover[colorField] = { value = "red" }
 
-- action when cursor leaves plot mark: reset to initial setup
-- дія, коли курсор залишає позначку діаграми: повернення до первісного налаштування
if not plotMarks.properties.update then plotMarks.properties.update = {} end
plotMarks.properties.update[colorField] = { scale = "color", field = dataField }
properties =
{
-- chart creation event handler
-- хендлер подій створення діаграм
enter =
{
 
if alphaScale then chartvis.properties.update[colorField .. "Opacity"] = { scale = "transparency" } end
-- for bars and area charts set the lower bound of their areas
-- для стовпчастих і площинних діаграм установити нижнє граничне значення їхніх площин
if chartType == "rect" or chartType == "area" then
if stacked then
-- for stacked charts this lower bound is the end of the last stacking element
-- для стосових діаграм це нижнє граничне значення є кінцем останнього елемента діаграми
chartvis.properties.enter.y2 = { scale = "y", field = "layout_end" }
else
--[[
for non-stacking charts the lower bound is y=0
для нестосових діаграм нижнє граничне значення y=0
ЗРОБИТИTODO: значення "yscale.zero" встановленеis якcurrently set to "true" дляfor цьогоthis випадкуcase, але якbut "false" дляfor всіхall іншихother випадківcases.
For the similar behavior "y2" should actually be set to where y axis crosses the x axis,
Для аналогічної поведінки "y2" треба насправді розмістити там, де вісь y перетинає вісь x,
if there are only positive or negative values in the data ]]
якщо дані мають тільки додатні або від’ємні значення ]]
chartvis.properties.enter.y2 = { scale = "y", value = 0 }
end
end
-- for bar charts ...
-- для стовпчастих діаграм…
if chartType == "rect" then
-- set 1 pixel width between the bars
-- задати ширину просвіту між стовпцями в 1 піксел
chartvis.properties.enter.width = { scale = "x", band = true, offset = -1 }
-- for multiple series the bar marking needs to use the "inner" series scale, whereas the "outer" x scale is used by the grouping
-- для серій діаграм маркування стовпців має використовувати «внутрішню» шкалу серії, тоді як «зовнішня» шкала x використувується для групування
if not stacked and yCount > 1 then
chartvis.properties.enter.x.scale = "series"
end
end
-- stacked charts have their own (stacked) y values
-- стосові діаграми мають власні (стосові) значення y
if stacked then chartvis.properties.enter.y.field = "layout_start" end
 
-- if there are multiple series group these together
-- якщо є множинні серії, згрупувати їх
if yCount == 1 then
chartvis.from = { data = "chart" }
else
-- if there are multiple series, connect colors to series
-- якщо є множинні серії, прив’язати до них кольори
chartvis.properties.update[colorField].field = "series"
if alphaScale then chartvis.properties.update[colorField .. "Opacity"].field = "series" end
-- apply a grouping (facetting) transformation
-- застосувати групувальну (поєднальну) трансформацію
chartvis =
{
}
}
-- for stacked charts apply a stacking transformation
-- для стосових діаграм застосувати трансформацію накладення
if stacked then
table.insert(chartvis.from.transform, 1, { type = "stack", groupby = { "x" }, sortby = { "series" }, field = "y" } )
else
-- for bar charts the series are side-by-side grouped by x
-- для стовпчастих діаграм серії групуються впритул по x
if chartType == "rect" then
-- for bar charts with multiple series: each serie is grouped by the x value, therefore the series need their own scale within each x group
-- для стовпчастих діаграм з багаторазовими серіями: кожна серія групується за значенням x, отже, серії потребують власної шкали в кожній групі x
local groupScale =
{
local properties
if chartType == "rect" then
properties =
{
x = { scale = chartvis.properties.enter.x.scale, field = chartvis.properties.enter.x.field, offset = tonumber(showValues.xoffset) },
y = { scale = chartvis.properties.enter.y.scale, field = chartvis.properties.enter.y.field, offset = -(tonumber(showValues.offset) or -4) },
--dx = { scale = chartvis.properties.enter.x.scale, band = true, mult = 0.5 }, -- дляfor горизонтальногоhorizontal текстуtext
dy = { scale = chartvis.properties.enter.x.scale, band = true, mult = 0.5 }, -- дляfor вертикальногоvertical текстуtext
align = { value = showValues.align },
baseline = { value = "middle" },
fill = { },
angle = { value = showValues.angle or -90 },
fontSize = { value = tonumber(showValues.fontsize) or 11 }
}
if properties.y.offset >= 0 then
properties.align.value = showValues.align or "right"
properties.fill.value = showValues.fontcolor or "white"
else
properties.align.value = showValues.align or "left"
properties.fill.value = showValues.fontcolor or "black"
end
elseif chartType == "pie" then
properties =
end
elseif tonumber(showValues.angle) then
-- qunatize scale for aligning text left on right half-circle and right on left half-circle
-- квантизувати шкалу для вирівнювання тексту вліво на правому півколі і вправо на лівому півколі
local alignScale = { name = "align", type = "quantize", domainMin = 0.0, domainMax = math.pi * 2, range = { "left", "right" } }
table.insert(scales, alignScale)
}
if chartType == "pie" then
-- move legend from center position to top
-- перемістити легенду з центральної позиції наверх
legend.properties = { legend = { y = { value = -outerRadius } } }
end
 
function p.chart(frame)
-- chart width and height
-- ширина й висота діаграми
local graphwidth = tonumber(frame.args.width) or 200
local graphheight = tonumber(frame.args.height) or 200
-- chart type
-- тип діаграми
local chartType = frame.args.type or "line"
-- режимinterpolation перекриттяmode кольорівfor дляline лінійнихand іarea площинних діаграмcharts: linear, step-before, step-after, basis, basis-open, basis-closed (type=line only), bundle (type=line only), cardinal, cardinal-open, cardinal-closed (type=line only), monotone
local interpolate = frame.args.interpolate
-- mark colors (if no colors are given, the default 10 color palette is used)
-- позначити кольори (якщо кольори не задані, використовується 10-кольорова палітра за замовчанням)
local colors = stringArray(frame.args.colors)
-- for line charts, the thickness of the line; for pie charts the gap between each slice
-- для лінійних діаграм — товщина лінії; для секторних діаграм — ширина проміжку між секторами
local linewidth = tonumber(frame.args.linewidth)
-- x and y axis caption
-- підпис під осями x та y
local xTitle = frame.args.xAxisTitle
local yTitle = frame.args.yAxisTitle
-- x and y value types
-- типи значень x та y
local xType = frame.args.xType
local yType = frame.args.yType
-- override x and y axis minimum and maximum
-- подавити мінімум і максимум осей x та y
local xMin = frame.args.xAxisMin
local xMax = frame.args.xAxisMax
local yMin = frame.args.yAxisMin
local yMax = frame.args.yAxisMax
-- override x and y axis label formatting
-- подавити форматування ярликів осей x та y
local xAxisFormat = frame.args.xAxisFormat
local yAxisFormat = frame.args.yAxisFormat
-- show legend with given title
-- показати легенду з заданим заголовком
local legendTitle = frame.args.legend
-- show values as text
-- показати значення як текст
local showValues = frame.args.showValues
-- pie chart radiuses
-- радіуси кругової діаграми
local innerRadius = tonumber(frame.args.innerRadius) or 0
local outerRadius = math.min(graphwidth, graphheight)
-- format JSON output
-- вивести у форматі JSON
local formatJson = frame.args.formatjson
 
-- get x values
-- отримати значення x
local x
x, xType, xMin, xMax = deserializeXData(frame.args.x, xType, xMin, xMax)
 
-- get y values (series)
-- отримати значення y (серії)
local yValues = {}
local seriesTitles = {}
if yNum then
yValues[yNum] = value
-- назватиname серіюthe series: заdefault замовчанням —is "y<number>". МожеCan бутиbe переписанаoverwritten зusing використанням параметрівthe "y<number>Title" parameters.
seriesTitles[yNum] = frame.args["y" .. yNum .. "Title"] or name
end
end
local y
y, yType, yMin, yMax = deserializeYData(yValues, yType, yMin, yMax)
 
-- create data tuples, consisting of series index, x value, y value
-- створити кортеж даних: індекс серії, значення x та y
local data
if chartType == "pie" then
-- for pie charts the second second series is merged into the first series as radius values
-- для секторних діаграм: друга серія розміщується всередині першої серії за значеннями радіусів
data = convertXYToSingleSeries(x, y, xType, yType, { "y", "r" })
else
end
 
-- configure stacked charts
-- сконфігурувати стосові діаграми
local stacked = false
local stats
if string.sub(chartType, 1, 7) == "stacked" then
chartType = string.sub(chartType, 8)
if #y > 1 then -- ігноруватиignore стосовіstacked діаграми,charts якщоif єthere тількиis однаonly серіяone series
stacked = true
-- aggregate data by cumulative y values
-- зібрати дані за кумулятивними значеннями y
stats =
{
name = "stats", source = "chart", transform =
{
{
type = "aggregate",
name = "stats", source = "chart", transform =
groupby = { "x" },
summarize = { y = "sum" }
{
type = "aggregate",
groupby = { "x" },
summarize = { y = "sum" }
}
}
}
}
}
end
end
 
-- create scales
-- створити шкали
local scales = {}
 
end
 
-- decide if lines (strokes) or areas (fills) should be drawn
-- вирішити, що саме необхідно вивести: лінії (контури) чи площини (заливки)
local colorField
if chartType == "line" then colorField = "stroke" else colorField = "fill" end
 
-- create chart markings
-- створити мітки діаграм
local chartvis = getChartVisualisation(chartType, stacked, colorField, #y, innerRadius, outerRadius, linewidth, alphaScale, radiusScale, interpolate)
 
-- text marks
-- текстові позначки
local textmarks
if showValues then
if type(showValues) == "string" then -- десеріалізуватиdeserialize якas таблицюtable
local keyValues = mw.text.split(showValues, "%s*,%s*")
showValues = {}
end
 
-- осіaxes
local xAxis, yAxis = getAxes(xTitle, xAxisFormat, xType, yTitle, yAxisFormat, yType, chartType)
 
-- легендаlegend
local legend
if legendTitle then legend = getLegend(legendTitle, chartType, outerRadius) end
 
-- construct final output object
-- створити об’єкт для фінального виводу
local output =
{
function p.chartWrapper(frame)
return p.chart(frame:getParent())
end
 
-- Given an HTML-encoded title as first argument, e.g. one produced with {{ARTICLEPAGENAME}},
-- convert it into a properly URL path-encoded string
-- This function is critical for any graph that uses path-based APIs, e.g. PageViews graph
function p.encodeTitleForPath(frame)
return mw.uri.encode(mw.text.decode(mw.text.trim(frame.args[1])), 'PATH')
end
 
570

редагувань