Mòdul:Chart/proves
A continuació es mostra la documentació transclosa de la subpàgina /ús. [salta a la caixa de codi]
per a
Compte, no funcionen el missatge emergent de les llegendes en mode Mòdul.
dif_x_prior:num,perc_abs sum_gr_prior:num,perc sum_gr_next:num,perc sum_x_prior:num,perc sum_x_next:num,perc num perc_x perc_gr perc_all dif_gr_prior:num,perc_abs dif_gr_next:num,perc_abs dif_x_prior:num,perc_abs dif_x_next:num,perc_abs sum_prior:num,perc sum_next:num,perc
Evolució del pes a Crackcity |
Determinació de l'IMC segons els Servei Sanitari de la Salut de Llunyland[a] |
Passant el cursor del ratolí per sobre de $1 apareix informació emergent de les dades
- ↑ Com tothom sap, és un país molt llunyà
Religions |
Subtítol |
Passant el cursor del ratolí per sobre del pastís apareix informació emergent de les dades
Anotació
Religions |
Subtítol |
Anotació
Títol |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Títol de llibre |
Passant el cursor del ratolí per sobre de $1 apareix informació emergent de les dades
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Títol |
Passant el cursor del ratolí per sobre de $1 apareix informació emergent de les dades
Títol |
--<syntaxhighlight lang="lua">
local SDebug = {}
local p = {}
-- Required modules --
local DefColors = require "Module:Plotter/DefaultColors"
local SA = require "Module:SimpleArgs"
local BrewerColors = require "Module:BrewerColors"
local ChartColors = require "Module:ChartColors"
local CFCM = require "Module:ComplForColorModules"
local MC = require "Module:XCols"
local yesno = require "Module:Yesno"
local TNTT = require "Module:TNTTools"
local NTO = require "Module:NumTableOrder"
local sd = require "Module:SimpleDebug"
-- For tanslation go to :commons:Data:I18n/Chart.tab --
local TS_BarChart = 'BarChart'
local TS_PieChart = 'PieChart'
local ArgL = {
Width = 'Width',
UnitsPrefix = 'UnitsPrefix',
UnitsSuffix = 'UnitsSuffix',
Delimiter = 'Delimiter',
MouseOverTooltip = 'MouseOverTooltip',
PercDecim = 'PercDecim',
Title = 'Title',
TitleBackground = 'TitleBackground',
Subtit = 'Subtit',
SubtitBackground = 'SubtitBackground',
HideGroupLegends = 'HideGroupLegends',
LegendColumns = 'LegendColumns',
LegendTitle = 'LegendTitle',
Note = 'Note',
Align = 'Align',
Slices = 'Slices',
Slice = 'Slice',
Radius = 'Radius',
ColorPalette = 'ColorPalette',
Percent = 'Percent',
LegendNumbers = 'LegendNumbers',
SliceNumbers = 'SliceNumbers',
--main
Colors = 'Colors',
GroupNames = 'GroupNames',
DataTooltipMode = 'DataTooltipMode',
Stack = 'Stack',
Group = 'Group',
XLegend = 'XLegend',
--extract
Height = 'Height',
Links = 'Links',
DefColor = 'DefColor',
YTicks = 'YTicks',
ScalePerGroup = 'ScalePerGroup',
XText2Lines = 'XText2Lines',
InPercent = 'InPercent',
HideGridY = 'HideGridY',
WallColor = 'WallColor',
--tooltip
Tooltip = 'Tooltip',
AccumulateTooltip = 'AccumulateTooltip',
ColTooltip = 'ColTooltip',
XTooltip = 'XTooltip',
LegendTooltip = 'LegendTooltip',
TooltipSep = 'TooltipSep',
MeanLabel = 'MeanLabel',
OrderLabel = 'OrderLabel',
SumLabel = 'SumLabel',
DifLabel = 'DifLabel',
AllLabel = 'AllLabel',
}
local Opt = {
basic = "basic",
num = "num",
perc = "perc",
order = "order",
mean = "mean",
meandif ="meandif",
list = "list",
sum = "sum",
dif = "dif",
x = "x",
gr = "gr",
abs = "abs",
rel = "rel",
all = "all",
prior = "prior",
next = "next",
}
local Msg = {
--DefaultShow
Mean = "Mean",
Order = "Order",
Sum = "Sum",
Dif = "Dif",
All = "All",
--MouseOver
Pie = "Pie",
Tooltip = "Tooltip",
Cols = "Cols",
X = "X",
Legend = "Legend",
--Other
Quali = "Quali",
SemiQ = "SemiQ",
And = "And",
Tt_abs = "Tt_abs",
Tt_rel = "Tt_rel",
Total = "Total",
}
local Err = {
InvalTooltip = "InvalTooltip",
SliceWithNotNumber = "SliceWithNotNumber",
NoSlices = "NoSlices",
RequiredValForS = "RequiredValForS",
KWNumAndGroupNumNotMatched = "KWNumAndGroupNumNotMatched",
IncompatibleSettings = "IncompatibleSettings",
NotHaveSameNumber = "NotHaveSameNumber",
InvalLegendNumber = "InvalLegendNumber",
ExpectedNumForKW = "ExpectedNumForKW",
EmptyTooltip = "EmptyTooltip",
InvalTooltip1Group = "InvalTooltip1Group",
LookAtHelp = "LookAtHelp",
AnyGroupIsRequired = "AnyGroupIsRequired",
Selected2LinesButNoSpaces = "Selected2LinesButNoSpaces",
SetDataTooltipModeAndCustomDataTooltipMode = "SetDataTooltipModeAndCustomDataTooltipMode",
InvalDataTooltipMode = "InvalDataTooltipMode",
InvalDataTooltipMode2Need = "InvalDataTooltipMode2Need",
}
local i18n = {
["BarChart"] = "bar chart",
["PieChart"] = "pie chart",
["Arg"] = {
["Gral"] = {
[ArgL.Width] = "width",
[ArgL.UnitsPrefix] = "units prefix",
[ArgL.UnitsSuffix] = "units suffix",
[ArgL.Delimiter] = "delimiter",
[ArgL.MouseOverTooltip] = "tooltip info",
[ArgL.PercDecim] = "percent decimals",
[ArgL.Title] = "title",
[ArgL.TitleBackground] = "title background",
[ArgL.Subtit] = "subtitle",
[ArgL.SubtitBackground] = "subtitle background",
[ArgL.HideGroupLegends] = "hide group legends",
[ArgL.LegendColumns] = "legend columns",
[ArgL.LegendTitle] = "legend title",
[ArgL.Note] = "note",
[ArgL.Align] = "align",
},
["PC"] = { --Pie Chart
[ArgL.ColorPalette] = "color palette",
[ArgL.LegendNumbers] = "numbers in legend",
[ArgL.Percent] = "percent",
[ArgL.Radius] = "radius",
[ArgL.Slice] = "slice",
[ArgL.Slices] = "slices",
[ArgL.SliceNumbers] = "numbers in slices",
},
["BC"] = { --Bar Chart
[ArgL.Height] = "height",
[ArgL.Group] = "group",
[ArgL.GroupNames] = "group names",
[ArgL.Links] = "links",
[ArgL.Colors] = "colors",
[ArgL.Stack] = "stack",
[ArgL.XLegend] = "x legends",
[ArgL.YTicks] = "y tick marks",
[ArgL.ScalePerGroup] = "scale per group",
[ArgL.XText2Lines] = "x text in 2 lines",
[ArgL.InPercent] = "in percent",
[ArgL.HideGridY] = "hide grid y",
[ArgL.WallColor] = "wall color",
[ArgL.Tooltip] = "tooltip",
[ArgL.DataTooltipMode] = "data tooltip mode",
[ArgL.AccumulateTooltip] = "tooltip value accumulation",
[ArgL.ColTooltip] = "column tooltip",
[ArgL.XTooltip] = "x tooltip",
[ArgL.LegendTooltip] = "legend tooltip",
[ArgL.TooltipSep] = "tooltip separator",
[ArgL.MeanLabel] = "mean label",
[ArgL.OrderLabel] = "order label",
[ArgL.SumLabel] = "sum label",
[ArgL.DifLabel] = "difference label",
[ArgL.AllLabel] = "all label",
},
},
["Opt"] = {
[Opt.basic] = "basic",
[Opt.num] = "num",
[Opt.perc] = "perc",
[Opt.order] = "order",
[Opt.mean] = "mean",
[Opt.meandif] = "meandif",
[Opt.list] = "list",
[Opt.sum] = "sum",
[Opt.dif] = "dif",
[Opt.x] = "x",
[Opt.gr] = "gr",
[Opt.abs] = "abs",
[Opt.rel] = "rel",
[Opt.all] = "all",
[Opt.prior] = "prior",
[Opt.next] = "next",
},
["Msg"] = {
["DefShow"] = {
[Msg.Mean] = "x̄",
[Msg.Order] = "Order",
[Msg.Sum] = "∑",
[Msg.Dif] = "∆",
[Msg.All] = "All",
},
["MouseOver"] = {
[Msg.Pie] = "Moving the mouse cursor over the pie appears data tooltip",
[Msg.Tooltip] = "Moving the mouse cursor above $1 appears data tooltip",
[Msg.Cols] = "the columns",
[Msg.X] = "the X-axis text",
[Msg.Legend] = "the legend text",
},
[Msg.Quali] = "quali",
[Msg.SemiQ] = "semiq",
[Msg.And] = "and",
[Msg.Tt_abs] = "abs.:",
[Msg.Tt_rel] = "rel.:",
[Msg.Total] = "Total",
},
["Error"] = {
--Common--
[Err.InvalTooltip] = "Incorrect value for \"$1\": $2. Only \"$3\" are valid",
--PieChart--
[Err.SliceWithNotNumber] = "Sector $1: \"$2\", the first element (\"$3\") should be a number",
[Err.NoSlices] = "No sector found: a graph can not be drawn",
--BarChart--
[Err.RequiredValForS] = "Values must be provided for $1",
[Err.KWNumAndGroupNumNotMatched] = "$1 should contain the same item number as the group number, but contains $2 items and there are $2 groups",
[Err.IncompatibleSettings] = "Bad assignment: $1 and $2 are not supported",
[Err.NotHaveSameNumber] = "$1 $2 does not have the same number of values as $3 1",
[Err.InvalLegendNumber] = "Incorrect name of $1. It should be exactly $2",
[Err.ExpectedNumForKW] = "A numeric index was expected for key $1 instead of $2",
[Err.EmptyTooltip] = "No value for \"$1\" of \"$2\". Valid \"$3\"",
[Err.InvalTooltip1Group] = "When there is only one group, it is not allowed to assign options to \"$1\"",
[Err.LookAtHelp] = "Incorrect value for \"$1\": $2. See template help for this option",
[Err.AnyGroupIsRequired] = "Any group is required",
[Err.Selected2LinesButNoSpaces] = "Two lines are selected for the legends of the X values, but there is no legend with two words",
[Err.SetDataTooltipModeAndCustomDataTooltipMode] = "For automated tooltip mode of data, you have assigned values for $1 and $2",
[Err.InvalDataTooltipMode] = "Invalid automated tooltip mode of data ($1): $2",
[Err.InvalDataTooltipMode2Need] = "$1: Two parameters are required (for X and Y) and there are $2",
},
}
i18n = SA.loadI18n ('Chart', i18n)
local function I18nArgLabG (S)
return i18n["Arg"]["Gral"][S]
end
local function I18nArgLabP (S)
return i18n["Arg"]["PC"][S]
end
local function I18nArgLabB (S)
return i18n["Arg"]["BC"][S]
end
local function I18nArgOpt (S)
return i18n["Opt"][S]
end
local function I18nStrDS (S)
return i18n["Msg"]["DefShow"][S]
end
local function I18nStrMO (S)
return i18n["Msg"]["MouseOver"][S]
end
local function I18nStr (S)
return i18n["Msg"][S]
end
local function I18nError (S, ...)
return SA.I18nStrParams (i18n["Error"][S], ...)
end
-- Variables
local delimiter = ':'
local HideGroupLegends = false
local LegendColumns = 1
local LegendTitle = ''
local align = ''
local Title = ''
local TitleBackground = ''
local Subtit = ''
local SubtitBackground = ''
local prefix = ''
local suffix = ''
local TooltipSep = ':'
local PercDecim = 100
local MouseOverTooltip = false
local colors = {}
local function roundup (x) -- returns the next round number: eg., for 30 to 39.999 will return 40, for 3000 to 3999.99 wil return 4000. for 10 - 14.999 will return 15.
local ordermag = 10 ^ math.floor (math.log10 (x))
local normalized = x / ordermag
local top = normalized >= 1.5 and (math.floor (normalized + 1)) or 1.5
return ordermag * top, top, ordermag
end
local function round(num, PercDecimimalPlaces)
local mult = 10^(PercDecimimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
local function fnum (num)
return mw.getContentLanguage():formatNum (tonumber (num) or 0)
end
local function Mult100 (AValue,NDec)
return fnum(round(AValue*100,NDec))..'%'
end
local function nulOrWhitespace (s)
return (not s) or (mw.text.trim (s) == '')
end
local function NonBreak (s)
return string.gsub (s, ' ', ' ')
end
local function NonBreakArr (ATooltipLines)
for k = 1, #ATooltipLines do
ATooltipLines[k] = NonBreak (ATooltipLines[k])
end
end
local MarginsForText = 'margin-left:0.5em; margin-right:0.5em; margin-top:0.4em; margin-bottom:0.4em; '
local function createLegends (tab, legends, AddedLegends, cols, Tooltips)
if #legends > 1 and not HideGroupLegends then
local WithTooltips = table.getn(Tooltips) > 0
table.insert (tab, '<div style="width:auto; text-align:left; '..MarginsForText..'">')
if LegendTitle ~= '' then
table.insert (tab, '<div align="left"><b>'..LegendTitle..'</b></div>')
end
local Show = {}
local WithAddedLegends = AddedLegends ~= nil
for gi=1, #legends do
STooltip = ''
if WithTooltips then
STooltip = Tooltips[gi]
end
local WLegend = legends[gi]
if WithAddedLegends then
WLegend = WLegend..' '..AddedLegends[gi]
end
table.insert (Show, CFCM.LegendColor(cols[gi],WLegend,STooltip))
end
local SShow = MC.MultiColX (true, '100%', false, nil, LegendColumns, Show)
table.insert (tab, SShow)
table.insert (tab, '</div>')
end
end --createLegends
local function OkWord (wd, tab)
if type(tab) == 'table' then
return (wd == tab[1]) or (wd == tab[2])
else
return (wd == tab)
end
end
local function getbasicArgs (args)
align = SA.HAlign_Par(args, I18nArgLabG(ArgL.Align), '')
Title = SA.Str_Par (args, I18nArgLabG(ArgL.Title), '')
TitleBackground = SA.Str_Par (args, I18nArgLabG(ArgL.TitleBackground), '')
Subtit = SA.Str_Par (args, I18nArgLabG(ArgL.Subtit), '')
SubtitBackground = SA.Str_Par (args, I18nArgLabG(ArgL.SubtitBackground), '')
LegendColumns = SA.PosInt_Par (args, I18nArgLabG(ArgL.LegendColumns), 1)
LegendTitle = SA.Str_Par (args, I18nArgLabG(ArgL.LegendTitle), '')
HideGroupLegends = not SA.NulOrWhitespace_Par (args, I18nArgLabG(ArgL.HideGroupLegends))
Note = SA.Str_Par (args, I18nArgLabG(ArgL.Note), '')
PercDecim = SA.ZeroOrPosInt_Par (args, I18nArgLabG(ArgL.PercDecim), 100)
MouseOverTooltip = SA.Bool_Par (args, I18nArgLabG(ArgL.MouseOverTooltip), false)
delimiter = SA.Str_Par (args, I18nArgLabG(ArgL.Delimiter), ':')
end --getbasicArgs
local function AddPerhapsTitle (res, width)
if Title ~= '' then
table.insert (res, '<div style="width:100%; padding:0.2em">')
--table.insert (res, '<div style="width:'..(width-10)..'; padding:0.2em">')
table.insert (res, '<table style="width:100%;">')
local STB = ''
if TitleBackground ~= '' then
STB = 'background:'..TitleBackground..'; '
end
table.insert (res, '<tr><td style="'..STB..'font-size:120%; text-align:center; padding:0.3em"><b>'..Title..'</b></td></tr>')
if Subtit ~= '' then
local SSTB = ''
if SubtitBackground ~= '' then
SSTB = 'background:'..SubtitBackground..'; '
end
table.insert (res, '<tr><td style="'..SSTB..'valign=top; text-align:center; padding:0.2em">'..Subtit..'</td></tr>')
end
table.insert (res, '</table>')
table.insert (res, '</div>')
end
end --AddPerhapsTitle
local function AddMouseOverMess (res, S)
table.insert (res, '<p style="width:auto; font-size:93%; line-height:105%; valign=top; text-align:center; '..MarginsForText..'">'..S..'</p>')
end
local function AddPerhapsNote (res)
if Note ~= '' then
table.insert (res, '<p style="width:auto; '..MarginsForText..'valign=top; text-align:left; ">'..Note..'</p>')
end
end
local function PrepNum (AValue)
local SSuffix = suffix
if (suffix ~= '') and (suffix ~= ' ') then
SSuffix = ' '..suffix
end
return mw.ustring.gsub(prefix..fnum(AValue)..SSuffix, '_', ' ')
end
local function NDecOfVal (tot)
if PercDecim == 0 then
return 0
elseif PercDecim == 1 then
return 1
else
if tot > PercDecim then
return 1
else
return 0
end
end
end --NDecOfVal
local function ColorsFromPalette (Palette, Num)
local AColors = {}
ColorName, IsInv = CFCM.ColorNameInvFromS0 (Palette)
AColors = BrewerColors.GetColors (ColorName, IsInv, Num, false)
if table.getn(AColors) == 0 then
ColorName, IsInv, StartN = ChartColors.ColorNameInvStartFromS (Palette)
AColors = ChartColors.GetColors (ColorName, IsInv, StartN, Num, true)
end
return AColors
end --ColorsFromPalette
local function AppendResAtChartBegin (res, width)
if align ~= '' then
if align == 'center' then
table.insert (res, '<div class="center">')
end
local Al = ''
if align == 'left' then
Al = 'tleft'
elseif align == 'center' then
Al = 'tnone'
elseif align == 'right' then
Al = 'tright'
end
table.insert (res, '<div class="thumb '..Al..'>')
table.insert (res, '<div class="thumbinner" style="align:center; width:'..(width+8)..'px">')
table.insert (res, '<div class="noresize" style="align:center; width:'..width..'px">')
end
end --AppendResAtChartBegin
local function AppendResAtChartEnd (res)
if align ~= '' then
table.insert (res, '</div></div></div>')
if align == 'center' then
table.insert (res, '</div>')
end
end
end --AppendResAtChartEnd
-------------------------------------------------------------------------------
function pieChart (frame)
local args,NArgs = SA.GetArgs (frame)
if NArgs == 0 then return end
local res, imslices = {}, {}
local radius
local width
local values, names, AddedToName, legends, links = {}, {}, {}, {}, {}
local lang = mw.getContentLanguage()
function replaceH (s, subst, with)
return mw.ustring.gsub (s, subst, with)
end --replaceH
function analyzeParams()
getbasicArgs (args)
local PaletteRequired = false
function addSlice (i, slice)
local value, name, color, link = unpack (mw.text.split (slice, '%s*'..delimiter..'%s*'))
values[i] = tonumber (lang:parseFormattedNumber (value))
or I18nError(Err.SliceWithNotNumber, tostring(i), value or '', sliceStr)
colors[i] = not nulOrWhitespace (color) and color or 0
if colors[i] == 0 then
PaletteRequired = true
end
names[i] = name or ''
local PosSep = string.find (names[i], '%-%-')
if PosSep == nil then
table.insert (AddedToName, '')
else
table.insert (AddedToName, string.sub (names[i],PosSep+2))
names[i] = string.sub (names[i], 1, PosSep-1)
end
links[i] = link
end --addSlice
local NP = {'n','p'}
local LegendNumbers, SliceNumbers = {}, {}
function GetAndCheckNumber (tab)
local S = SA.Str_Par (args, tab, '')
local Numbers = {}
if S ~= '' then
local Wds = mw.text.split (S, ' ')
for l, m in ipairs(Wds) do
IsValid = (m == NP[1]) or (m == NP[2])
if IsValid then
table.insert (Numbers, m)
else
I18nError(Err.InvalTooltip, SA.ConcatParams (tab), m, table.concat(NP,', '))
end
end
end
return Numbers
end --GetAndCheckNumber
function InsertNP (tab, Two)
table.insert (tab, NP[1])
if Two then
table.insert (tab, NP[2])
end
end
prefix = replaceH (SA.Str_Par (args,I18nArgLabG(ArgL.UnitsPrefix),''), '_', ' ')
suffix = replaceH (SA.Str_Par (args,I18nArgLabG(ArgL.UnitsSuffix),''), '_', ' ')
radius = SA.PosInt_Par (args, I18nArgLabP(ArgL.Radius), 100, 40, 400)
width = SA.PosInt_Par (args, I18nArgLabG(ArgL.Width), radius * 2, radius * 2, 1000)
local percent = SA.Bool_Par (args, I18nArgLabP(ArgL.Percent))
LegendNumbers = GetAndCheckNumber (I18nArgLabP(ArgL.LegendNumbers))
SliceNumbers = GetAndCheckNumber (I18nArgLabP(ArgL.SliceNumbers))
if (#LegendNumbers == 0) and (#SliceNumbers == 0) then
InsertNP (LegendNumbers, percent)
InsertNP (SliceNumbers, percent)
end
--Add slices mode 1
local i = 0
local slicesStr = SA.Str_Par (args,I18nArgLabP(ArgL.Slices),'')
for slice in mw.ustring.gmatch (slicesStr, "%b()") do
i = i + 1
addSlice (i, mw.ustring.match (slice, '^%(%s*(.-)%s*%)$'))
end
--Add slices mode 2
for k, v in pairs(args) do
local ind = 0
local S = I18nArgLabP(ArgL.Slice)
function ForKw0 (Str)
return mw.ustring.match (k, '^'..Str..'%s+(%d+)$')
end
function ForKw (idx)
return ForKw0 (S[idx])
end
if type(S) == 'table' then
ind = ForKw(1) or ForKw(2)
else
ind = ForKw0 (S)
end
if ind then addSlice (tonumber (ind), v) end
end
local ColorPalette = SA.Str_Par (args, I18nArgLabP(ArgL.ColorPalette), '')
if PaletteRequired then
if ColorPalette == '' then
for i = 1, #colors do
if colors[i] == 0 then
colors[i] = DefColors[i * 2]
end
end
else
local AColors = ColorsFromPalette (ColorPalette, #colors)
for i = 1, #colors do
if colors[i] == 0 then
colors[i] = AColors[i]
end
end
end
end
local sum = 0
for _, val in ipairs (values) do
sum = sum + val
end
local NDOV = NDecOfVal(sum)
for i, value in ipairs (values) do
--local NP = {'n','p'}
local addNum = prefix..lang:formatNum (value)..suffix
local addPer = Mult100 (value/sum, NDOV)
legends[i] = names[i]
if AddedToName[i] ~= '' then
legends[i] = legends[i]..' '..AddedToName[i]
end
for j, what in ipairs (LegendNumbers) do
local S = ''
if what == NP[1] then
S = addNum
else
S = addPer
end
if j == 1 then
legends[i] = legends[i]..': '..S
else
legends[i] = legends[i]..' ('..S..')'
end
end
if not links[i] then
local SS = ''
for j, what in ipairs (SliceNumbers) do
local S = ''
if what == NP[1] then
S = addNum
else
S = addPer
end
if j == 1 then
SS = names[i]..': '..S
else
SS = SS..' ('..S..')'
end
end
links[i] = string.format('[[#noSuchAnchor|%s]]', SS)
end
end
end --analyzeParams
function addRes (...)
for _, v in pairs ({ ... }) do
table.insert (res, v)
end
end
function createSlices()
function drawSlice (i, q, start)
local color = colors[i]
local angle = start * 2 * math.pi
local sin, cos = math.abs (math.sin (angle)), math.abs (math.cos (angle))
local wsin, wcos = sin * radius, cos * radius
local s1, s2, w1, w2, w3, w4, width, border
local style
if q == 1 then
border = 'left'
w1, w2, w3, w4 = 0, 0, wsin, wcos
s1, s2 = 'bottom', 'left'
elseif q == 2 then
border = 'bottom'
w1, w2, w3, w4 = 0, wcos, wsin, 0
s1, s2 = 'bottom', 'right'
elseif q == 3 then
border = 'right'
w1, w2, w3, w4 = wsin, wcos, 0, 0
s1, s2 = 'top', 'right'
else
border = 'top'
w1, w2, w3, w4 = wsin, 0, 0, wcos
s1, s2 = 'top', 'left'
end
local style = string.format ('border:solid transparent;position:absolute;%s:%spx;%s:%spx;width:%spx;height:%spx', s1, radius, s2, radius, radius, radius)
if start <= (q - 1) * 0.25 then
style = string.format ('%s;border:0;background-color:%s', style, color)
else
style = string.format ('%s;border-width:%spx %spx %spx %spx;border-%s-color:%s', style, w1, w2, w3, w4, border, color)
end
addRes (mw.text.tag ('div', { style = style }, ''))
end --drawSlice
function coordsOfAngle (angle)
return (100 + math.floor (100 * math.cos (angle)))..' '.. (100 - math.floor (100 * math.sin (angle)))
end
-- BEGIN createSlices
local sum, start = 0, 0
for _, value in ipairs (values) do sum = sum + value end
for i, value in ipairs(values) do
local poly = { 'poly 100 100' }
local startC, endC = start / sum, (start + value) / sum
local startQ, endQ = math.floor (startC * 4 + 1), math.floor (endC * 4 + 1)
for q = startQ, math.min (endQ, 4) do drawSlice (i, q, startC) end
for angle = startC * 2 * math.pi, endC * 2 * math.pi, 0.02 do
table.insert (poly, coordsOfAngle (angle))
end
table.insert (poly, coordsOfAngle (endC * 2 * math.pi)..' 100 100 '..links[i])
table.insert (imslices, table.concat (poly, ' '))
start = start + values[i]
end
end --createSlices
function createImageMap()
addRes ('{{#tag:imagemap|', 'Image:Circle frame.svg{{!}}'.. (radius * 2)..'px')
addRes (unpack (imslices))
addRes ('desc none', '}}')
end
--BEGIN pieChart
analyzeParams()
if #values == 0 then
I18nError(Err.NoSlices)
end
AppendResAtChartBegin (res, width)
addRes (mw.text.tag ('div', { class = 'chart noresize', style = string.format ('align:center; margin-top:0.1em; margin-bottom:0.3em; max-width:%spx;', width) }))
AddPerhapsTitle (res, width)
--addRes (mw.text.tag ('div', { class = 'chart noresize', style = string.format ('left:%spx; margin-top:0.5em;max-width:%spx;', math.floor((width/2)-radius), radius * 2) }))
addRes (mw.text.tag ('div', { style = string.format ('position:relative;left:%spx; min-width:%spx;min-height:%spx;max-width:%spx;overflow:hidden;', math.floor((width/2)-radius), radius * 2, radius * 2, radius * 2) }))
--addRes (mw.text.tag ('div', { style = string.format ('position:relative;min-width:%spx;min-height:%spx;max-width:%spx;overflow:hidden;', radius * 2, radius * 2, radius * 2) }))
createSlices()
addRes (mw.text.tag ('div', { style = string.format ('position:absolute;min-width:%spx;min-height:%spx;overflow:hidden;', radius * 2, radius * 2) }))
createImageMap()
addRes ('</div>') -- close "position:relative" div that contains slices and imagemap.
addRes ('</div>') -- close "position:relative" div that contains slices and imagemap.
local Tooltips = {}
createLegends (res, legends, nil, colors, Tooltips) -- legends
if MouseOverTooltip then
AddMouseOverMess (res, I18nStrMO (Msg.Pie))
end
AddPerhapsNote (res)
addRes ('</div>') -- close containing div
AppendResAtChartEnd (res)
return frame:preprocess (table.concat (res, '\n'))
end --pieChart
-------------------------------------------------------------------------------
function barChart (frame)
local args,NArgs = SA.GetArgs (frame)
if NArgs == 0 then return end
local res = {}
local values, xlegends, tooltips, yscales = {}, {}, {}, {} ,{}, {}
local GroupNames, AddedToGroup, unitsSuffix, unitsPrefix, links = {}, {}, {}, {}, {}
local width, height, yticks, stack = 500, 350, -1, false
local chartWidth, chartHeight, DefColor, ScalePerGroup, accumulateTooltip
local IncTop = 5
local colTooltip = {}
local xTooltip = {}
local legendTooltip = {}
local NumGroups, NumXValues
local scaleWidth
local YSep = 0
local InPercent = false
local XText2Lines = false
local HideGridY = false
local DataTooltipMode = ''
local Tt_N = { --Tolltip
--SIMPLE
Basic = 1,
Num = 2,
Perc = 3,
Order = 4,
Mean = 5,
MeanDif = 6,
List = 7,
Sum = 8,
Dif = 9,
--to middle/end
Abs = 10,
Rel = 11,
All = 12,
X = 13,
Gr = 14,
--to end
Prior = 15,
Next = 16,
--COMPOST
Perc_x = 17,
Perc_gr = 18,
Perc_abs = 19,
Perc_rel = 20,
Perc_all = 21,
Sum_prior = 22,
Sum_next = 23,
Sum_x = 24,
Sum_gr = 25,
Sum_x_prior = 26,
Sum_x_next = 27,
Sum_gr_prior = 28,
Sum_gr_next = 29,
MeanDif_x = 30,
MeanDif_gr = 31,
Dif_prior = 32,
Dif_next = 33,
Dif_x = 34,
Dif_gr = 35,
Dif_x_prior = 36,
Dif_x_next = 37,
Dif_gr_prior = 38,
Dif_gr_next = 39,
}
local function SumArr (A1, A2)
if (type(A1) == 'string') and (type(A2) == 'string') then
return A1..'_'..A2
else
local A = {}
if (type(A1) == 'table') and (type(A2) == 'table') then
for k, v in ipairs (A1) do
for kk, vv in ipairs (A2) do
table.insert(A, v..'_'..vv)
end
end
elseif type(A1) == 'table' then
for k, v in ipairs (A1) do
table.insert(A, v..'_'..A2)
end
elseif type(A2) == 'table' then
for k, v in ipairs (A2) do
table.insert(A, A1..'_'..v)
end
end
return A
end
end
local RS_Tt_Perc = I18nArgOpt (Opt.perc)
local RS_Tt_X = I18nArgOpt (Opt.x)
local RS_Tt_Gr = I18nArgOpt (Opt.gr)
local RS_Tt_Abs = I18nArgOpt (Opt.abs)
local RS_Tt_Rel = I18nArgOpt (Opt.rel)
local RS_Tt_All = I18nArgOpt (Opt.all)
local Tt_A = {
Basic = I18nArgOpt (Opt.basic),
Num = I18nArgOpt (Opt.num),
Perc = RS_Tt_Perc,
Order = I18nArgOpt (Opt.order),
Mean = I18nArgOpt (Opt.mean),
MeanDif = I18nArgOpt (Opt.meandif),
List = I18nArgOpt (Opt.list),
Sum = I18nArgOpt (Opt.sum),
Dif = I18nArgOpt (Opt.dif),
Abs = RS_Tt_Abs,
Rel = RS_Tt_Rel,
All = RS_Tt_All,
X = RS_Tt_X,
Gr = RS_Tt_Gr,
Prior = I18nArgOpt (Opt.prior),
Next = I18nArgOpt (Opt.next),
Perc_x = SumArr (RS_Tt_Perc, RS_Tt_X),
Perc_gr = SumArr (RS_Tt_Perc, RS_Tt_Gr),
Perc_abs = SumArr (RS_Tt_Perc, RS_Tt_Abs),
Perc_rel = SumArr (RS_Tt_Perc, RS_Tt_Rel),
Perc_all = SumArr (RS_Tt_Perc, RS_Tt_All),
}
local RS_num = 'num'
local RS_perc = 'perc' --percentage
local RS_prior = 'prior'
local RS_next = 'next'
local RS_gr = 'gr' --group
local RS_x = 'x' --axes
local RS_basic = 'basic'
local RS_meandif = 'meandif'
local RS_mean = 'mean'
local RS_list = 'list'
local RS_sum = 'sum'
local RS_dif = 'dif'
local RS_abs = 'abs' --absolute
local RS_rel = 'rel' --relative
local RS_all = 'all'
local DefaultShow = {
Mean = I18nStrDS (Msg.Mean), --'x̄'
Order = I18nStrDS (Msg.Order), --'x̄'
Sum = I18nStrDS (Msg.Sum)..' ', --'∑'
Dif = I18nStrDS (Msg.Dif)..' ', --'∆'
All = I18nStrDS (Msg.All)..' ', --'All'
}
local RS_dif_ = RS_dif..'_'
local RS_perc_ = RS_perc..'_'
local RS_perc_abs = RS_perc_..RS_abs
local RS_perc_rel = RS_perc_..RS_rel
local RS_perc_x = RS_perc_..RS_x
local RS_perc_gr = RS_perc_..RS_gr
local RS_perc_all = RS_perc_..RS_all
local RS_gr_ = RS_gr..'_'
local RS_x_ = RS_x..'_'
local RS_meandif_ = RS_meandif..'_'
local RS_meandif_x = RS_meandif_..RS_x
local RS_meandif_gr = RS_meandif_..RS_gr
local RS_dif_prior = RS_dif_..RS_prior
local RS_dif_next = RS_dif_..RS_next
local RS_dif_x_prior = RS_dif_..RS_x_..RS_prior
local RS_dif_gr_prior = RS_dif_..RS_gr_..RS_prior
local RS_dif_x_next = RS_dif_..RS_x_..RS_next
local RS_dif_gr_next = RS_dif_..RS_gr_..RS_next
-- Accessory functions --
function AddAny (ATooltipLines, ALabel, Arg, SValue)
if ALabel ~= '' then
local LabelHere = ''
if not nulOrWhitespace(Arg) then
LabelHere = string.format(ALabel,Arg)
else
LabelHere = ALabel
end
SValue = LabelHere..TooltipSep..' '..SValue
end
table.insert (ATooltipLines, SValue)
end --AddAny
function AddPercS (ATooltipLines, ALabel, Arg, SValue)
AddAny (ATooltipLines, ALabel, Arg, SValue)
end
function AddPerc (ATooltipLines, ALabel, Arg, AValue, NDec)
AddPercS (ATooltipLines, ALabel, Arg, Mult100(AValue,NDec))
end
function NumToPercSign0 (AValue, NVals)
if AValue == 1 then
return '0'
elseif AValue > 1 then
return '+'..Mult100(AValue-1,NDecOfVal(NVals))
else
return '-'..Mult100(1-AValue,NDecOfVal(NVals))
end
end --NumToPercSign0
function NumToPercSign (ATooltipLines, ALabel, Arg, AValue, NVals)
local S = NumToPercSign0 (AValue, NVals)
AddPercS (ATooltipLines, ALabel, Arg, S)
end --NumToPercSign
function GetPrefixSuffix (gi)
prefix = unitsPrefix[gi]
suffix = unitsSuffix[gi]
end
-- Main functions --
function extractParams()
function IdxFromTabTrans1 (Str, TtA)
local Idx = 0
local Found = false
for I, A in ipairs(TtA) do
if type(A) == 'table' then
for J, W in ipairs(A) do
if W == Str then
Idx = I
Found = true
break
end
end
if Found then
break
end
else
if A == Str then
Idx = I
break
end
end
end
return Idx
end --IdxFromTabTrans1
function IdxFromTabTrans2 (Str, TtA, AChar)
local Idx = 0
local Found = false
local Pos, Len = 0, 0
local StrEnd = ''
local WW = ''
for I, A in ipairs(TtA) do
if type(A) == 'table' then
for J, W in ipairs(A) do
Pos = string.find (Str, W..AChar)
if Pos == 1 then
Idx = I
WW = W
Found = true
break
end
end
if Found then
break
end
else
Pos = string.find (Str, A..AChar)
if Pos == 1 then
WW = A
Found = true
break
end
end
end
if Found then
StrEnd = string.sub (Str, string.len(WW)+2)
end
return Idx, StrEnd, WW
end --IdxFromTabTrans2
function NumOrPerc0 (kw, m, what, whatCode, Pattern, PatternCode, Tooltip)
function MessError ()
return what..':['..table.concat(Pattern,'/')..']'
end
if #Pattern ~= #PatternCode then error ('Debug error') end
if m == '' then
I18nError(Err.EmptyTooltip, what, kw, MessError())
else
local SubPar = {}
local SubCode = {}
SubPar = mw.text.split (m, ',')
IsValid = true
for n, o in ipairs(SubPar) do
Idx = IdxFromTabTrans1 (o, Pattern)
if Idx == 0 then
I18nError(Err.InvalTooltip, kw, o, MessError())
else
table.insert (SubCode, PatternCode[Idx])
end
end
local W = {}
table.insert (W, whatCode)
table.insert (W, SubCode)
table.insert (Tooltip, W)
end
end --NumOrPerc0
function ErrorPattern(Pattern)
return '['..table.concat(Pattern,'/')..']'
end
local PatternNumPerc = {Tt_A.Num, Tt_A.Perc}
local PatternNumPercCode = {Tt_N.Num, Tt_N.Perc}
local PatternNumPercOrd = {Tt_A.Num, Tt_A.Perc, Tt_A.Order}
local PatternNumPercOrdCode = {Tt_N.Num, Tt_N.Perc, Tt_N.Order}
function ErrorPatternNumPerc ()
return ErrorPattern (PatternNumPerc)
end
function ErrorPatternNumPercOrd ()
return ErrorPattern (PatternNumPercOrd)
end
local PatternPriorNext = {Tt_A.Prior, Tt_A.Next}
local PatternPriorNextCode = {Tt_N.Prior, Tt_N.Next}
local function ErrorPatternPriorNext ()
return ErrorPattern (PatternPriorNext)
end
local PatternGrX = {Tt_A.Gr, Tt_A.X}
local function ErrorPatternGrX ()
return ErrorPattern (PatternGrX)
end
function ExtractAndCheckcolTt (kw, v, Tooltip)
local PatternNumPercs = {Tt_A.Num, Tt_A.Perc_abs, Tt_A.Perc_rel}
local PatternNumPercsCode = {Tt_N.Num, Tt_N.Perc_abs, Tt_N.Perc_rel}
function NumOrPerc (NParam, m, what, whatCode)
local tab = {}
local tabCode = {}
if NParam == 3 then
tab = PatternNumPercs
tabCode = PatternNumPercsCode
else--if NParam == 2 then
tab = PatternNumPerc
tabCode = PatternNumPercCode
end
NumOrPerc0 (kw, m, what, whatCode, tab, tabCode, Tooltip)
end
function Add (RS_Ini_, TtArr, TtCode, m, NParam)
local whatCode = ''
function ErrorPNand ()
local tab = {}
if RS_Ini_ == RS_sum_ then
tab = ErrorPatternNumPerc ()
else
tab = ErrorPattern (PatternNumPercs)
end
return ErrorPatternPriorNext()..':'..tab
end
function AddEndPosNext (S, SCode, m2)
Idx, m2, SFound = IdxFromTabTrans2 (m2, {Tt_A.Prior,Tt_A.Next}, ':')
if Idx == 0 then
I18nError(Err.InvalTooltip, kw, m, S..ErrorPNand (NParam))
else
if Idx == 1 then
if TtCode == Tt_N.Sum then
whatCode = Tt_N.Sum_prior
elseif TtCode == Tt_N.Dif then
whatCode = Tt_N.Dif_prior
elseif TtCode == Tt_N.Sum_x then
whatCode = Tt_N.Sum_x_prior
elseif TtCode == Tt_N.Dif_x then
whatCode = Tt_N.Dif_x_prior
elseif TtCode == Tt_N.Sum_gr then
whatCode = Tt_N.Sum_gr_prior
elseif TtCode == Tt_N.Dif_gr then
whatCode = Tt_N.Dif_gr_prior
end
elseif Idx == 2 then
if TtCode == Tt_N.Sum then
whatCode = Tt_N.Sum_next
elseif TtCode == Tt_N.Dif then
whatCode = Tt_N.Dif_next
elseif TtCode == Tt_N.Sum_x then
whatCode = Tt_N.Sum_x_next
elseif TtCode == Tt_N.Dif_x then
whatCode = Tt_N.Dif_x_next
elseif TtCode == Tt_N.Sum_gr then
whatCode = Tt_N.Sum_gr_next
elseif TtCode == Tt_N.Dif_gr then
whatCode = Tt_N.Dif_gr_next
end
end
NumOrPerc (NParam, m2, S..SFound, whatCode)
end
end --AddEndPosNext
Idx, m2, SFound = IdxFromTabTrans2 (m, TtArr, '_')
if Idx == 1 then
if NumGroups == 1 then
AddEndPosNext (SFound..'_', m2, TtCode)
else
Idx, m2, SFound2 = IdxFromTabTrans2 (m2, {Tt_A.Gr,Tt_A.X}, '_')
if Idx == 0 then
I18nError(Err.InvalTooltip, kw, m, SFound..'_'..ErrorPatternGrX()..'_'..ErrorPNand (NParam))
else
if Idx == 1 then
if TtCode == Tt_N.Sum then
whatCode = Tt_N.Sum_gr
elseif TtCode == Tt_N.Dif then
whatCode = Tt_N.Dif_gr
end
elseif Idx == 2 then
if TtCode == Tt_N.Sum then
whatCode = Tt_N.Sum_x
elseif TtCode == Tt_N.Dif then
whatCode = Tt_N.Dif_x
end
end
AddEndPosNext (SFound..'_'..SFound2, m2, whatCode)
end
end
end
end --Add
function AddMd (m, S)
Idx, m2, SFound = IdxFromTabTrans2 (m, {Tt_A.Gr,Tt_A.X}, ':')
if Idx == 0 then
I18nError(Err.InvalTooltip, kw, m, S..'_'..ErrorPatternGrX()..':'..ErrorPatternNumPerc())
else
if Idx == 1 then
whatCode = Tt_N.MeanDif_gr
elseif Idx == 2 then
whatCode = Tt_N.MeanDif_x
end
NumOrPerc (2, m2, S..'_'..SFound, whatCode)
end
end --AddMd
local STooltip = v or ''
local IsValid = false
if STooltip ~= '' then
local Wds = mw.text.split (STooltip, ' ')
local Usual = {Tt_A.Num, Tt_A.Perc_x, Tt_A.Perc_gr, Tt_A.Perc_all,}
local UsualCode = {Tt_N.Num, Tt_N.Perc_x, Tt_N.Perc_gr, Tt_N.Perc_all,}
local SumDif = {Tt_A.Sum, Tt_A.Dif}
local SumDifCode = {Tt_N.Sum, Tt_N.Dif}
local MdSumDif = {Tt_A.MeanDif, Tt_A.Sum, Tt_A.Dif}
local MdSumDifCode = {Tt_N.MeanDif, Tt_N.Sum, Tt_N.Dif}
for l, m in ipairs(Wds) do
if NumGroups == 1 then
Idx1, m1, SFound1 = IdxFromTabTrans2 (m, {Tt_A.Basic,Tt_A.MeanDif}, ':')
if Idx1 == 1 then
local tab = {Tt_A.Num, Tt_A.Perc, Tt_A.Order}
local tabCode = {Tt_N.Num, Tt_N.Perc, Tt_N.Order}
NumOrPerc0 (kw, m1, SFound1, Tt_N.Basic, tab, tabCode, Tooltip)
elseif Idx1 == 2 then
local tab = {Tt_A.Num, Tt_A.Perc}
local tabCode = {Tt_N.Num, Tt_N.Perc}
NumOrPerc0 (kw, m1, SFound1, Tt_N.MeanDif, tab, tabCode, Tooltip)
else
Idx2, m2, SFound2 = IdxFromTabTrans2 (m, SumDif, '_')
if Idx2 == 0 then
I18nError(Err.LookAtHelp, kw, m)
else
Add (SFound2..'_', SumDif[Idx2], SumDifCode[Idx2], m2, 2)
end
end
else
Idx = IdxFromTabTrans1 (m, Usual)
if Idx == 0 then
Idx2, m2, SFound2 = IdxFromTabTrans2 (m, {Tt_A.Order}, ':')
if Idx2 == 1 then
local tab = {Tt_A.X, Tt_A.Gr, Tt_A.All}
local tabCode = {Tt_N.X, Tt_N.Gr, Tt_N.All}
NumOrPerc0 (kw, m2, SFound2, Tt_N.Order, tab, tabCode, Tooltip)
else
Idx3, m3, SFound3 = IdxFromTabTrans2 (m, MdSumDif, '_')
if Idx3 == 0 then
I18nError(Err.LookAtHelp, kw, m)
elseif Idx3 == 1 then
AddMd (m3, SFound3)
else
Add (SFound3..'_', MdSumDif[Idx3], MdSumDifCode[Idx3], m3, 2)
end
end
else
table.insert (Tooltip, UsualCode[Idx])
end
end
end
end
end --ExtractAndCheckcolTt
function ExtractAndCheckXorLegTt (kw, v, Tooltip)
local STooltip = v or ''
local IsValid = false
function NumOrPerc3 (m, what, whatCode)
NumOrPerc0 (kw, m, what, whatCode, PatternNumPercOrd, PatternNumPercOrdCode, Tooltip)
end
function NumOrPerc2 (m, what, whatCode)
NumOrPerc0 (kw, m, what, whatCode, PatternNumPerc, PatternNumPercCode, Tooltip)
end
function Add (RS_Ini_, TtArr, TtCode, m)
Idx, m2, SFound = IdxFromTabTrans2 (m, TtArr, '_')
if Idx == 1 then
Idx, m2, SFound2 = IdxFromTabTrans2 (m2, {Tt_A.Prior, Tt_A.Next}, ':')
if Idx == 0 then
I18nError(Err.InvalTooltip, kw, m, RS_Ini_..ErrorPatternPriorNext())
else
local whatCode = ''
if Idx == 1 then
if TtCode == Tt_N.Sum then
whatCode = Tt_N.Sum_prior
elseif TtCode == Tt_N.Dif then
whatCode = Tt_N.Dif_prior
end
elseif Idx == 2 then
if TtCode == Tt_N.Sum then
whatCode = Tt_N.Sum_next
elseif TtCode == Tt_N.Dif then
whatCode = Tt_N.Dif_next
end
end
NumOrPerc2 (m2, SFound..'_'..SFound2, whatCode)
end
end
end
--BEGIN
if STooltip ~= '' then
if NumGroups == 1 then
I18nError(Err.InvalTooltip1Group, kw)
else
local Wds = mw.text.split (STooltip, ' ')
local Headers = {Tt_A.Basic, Tt_A.Mean, Tt_A.List, }
local HeadersCode = {Tt_N.Basic, Tt_N.Mean, Tt_N.List, }
local SumDif = {Tt_A.Sum, Tt_A.Dif}
local SumDifCode = {Tt_N.Sum, Tt_N.Dif}
for l, m in ipairs(Wds) do
Idx, m2, SFound = IdxFromTabTrans2 (m, Headers, ':')
if Idx > 0 then
if Idx == 1 then --Tt_N.Basic
NumOrPerc3 (m2, SFound, HeadersCode[Idx])
else
NumOrPerc2 (m2, SFound, HeadersCode[Idx])
end
else
Idx2, m2, SFound2 = IdxFromTabTrans2 (m, SumDif, '_')
if Idx2 == 0 then
I18nError(Err.InvalTooltip, kw, m, 'Algo')
--'['..RS_basic..'/'..RS_mean..'/'..RS_sum_..ErrorPatternPriorNext()..'/'..RS_dif_..ErrorPatternPriorNext()..'/'..RS_list..']:'..ErrorPatternNumPerc()), 0)
else
Add (SFound2..'_', MdSumDif[Idx2], MdSumDifCode[Idx2], m2, 2)
end
end
end
end
end
end --ExtractAndCheckXorLegTt
function SDelimiter (S)
local D = delimiter
if string.find (S,'\t') ~= nil then
D = '\t'
end
return '%s*'..D..'%s*'
end
function Test0 (val, tab)
for s in mw.text.gsplit (val, SDelimiter(val)) do
table.insert (tab, s)
end
end
local IdxForParams = false
function IsOk2 (key, keyword)
function ForKw0 (Str)
return (Str == key and 0) or key:match (Str.."%s+(%d+)")
end
function ForKw (idx)
return ForKw0 (keyword[idx])
end
if type(keyword) == 'table' then
IdxForParams = ForKw(1) or ForKw(2)
else
IdxForParams = ForKw0(keyword)
end
if not IdxForParams then
return false
else
IdxForParams = tonumber (IdxForParams) or I18nError(Err.ExpectedNumForKW, SA.ConcatParams (keyword), key)
return true
end
end
function InsertH (val, tab, NumRequired)
if IdxForParams > 0 then
tab[IdxForParams] = {}
end
for s in mw.text.gsplit (val, SDelimiter(val)) do
if NumRequired then
SA.CheckSIsNum (s, I18nArgLabB(ArgL.Group))
s = tonumber (s)
end
table.insert (IdxForParams == 0 and tab or tab[IdxForParams], s)
end
end
--BEGIN extractParams
getbasicArgs (args)
width = SA.PosInt_Par (args, I18nArgLabG(ArgL.Width), 500, 200, 1000)
height = SA.PosInt_Par (args, I18nArgLabB(ArgL.Height), 350, 150, 750)
stack = SA.Bool_Par (args, I18nArgLabB(ArgL.Stack), false)
yticks = SA.Int_Par (args, I18nArgLabB(ArgL.YTicks), -1, -1, 40)
ScalePerGroup = SA.Bool_Par (args, I18nArgLabB(ArgL.ScalePerGroup), false)
DefColor = 'blue'
accumulateTooltip = SA.Bool_Par (args, I18nArgLabB(ArgL.AccumulateTooltip), false)
TooltipSep = SA.Str_Par (args, I18nArgLabB(ArgL.TooltipSep), ':')
DefaultShow.Mean = SA.Str_Par (args, I18nArgLabB(ArgL.MeanLabel), DefaultShow.Mean)
DefaultShow.Order = SA.Str_Par (args, I18nArgLabB(ArgL.OrderLabel), DefaultShow.Order)
DefaultShow.Sum = SA.Str_Par (args, I18nArgLabB(ArgL.SumLabel), DefaultShow.Sum)
DefaultShow.Dif = SA.Str_Par (args, I18nArgLabB(ArgL.DifLabel), DefaultShow.Dif)
DefaultShow.All = SA.Str_Par (args, I18nArgLabB(ArgL.AllLabel), DefaultShow.All)
XText2Lines = SA.Bool_Par (args, I18nArgLabB(ArgL.XText2Lines), false)
InPercent = SA.Bool_Par (args, I18nArgLabB(ArgL.InPercent), false)
HideGridY = SA.Bool_Par (args, I18nArgLabB(ArgL.HideGridY), false)
WallColor = SA.Str_Par (args, I18nArgLabB(ArgL.WallColor), '')
for k, v in pairs (args) do
if OkWord (k, I18nArgLabB(ArgL.ColTooltip)) then
ExtractAndCheckcolTt (k, v, colTooltip)
elseif OkWord (k, I18nArgLabB(ArgL.XTooltip)) then
ExtractAndCheckXorLegTt (k, v, xTooltip)
elseif OkWord (k, I18nArgLabB(ArgL.LegendTooltip)) then
ExtractAndCheckXorLegTt (k, v, legendTooltip)
elseif OkWord (k, I18nArgLabB(ArgL.XLegend)) then
Test0 (v, xlegends)
elseif OkWord (k, I18nArgLabB(ArgL.Colors)) then
Test0 (v, colors)
elseif OkWord (k, I18nArgLabG(ArgL.UnitsPrefix)) then
Test0 (v, unitsPrefix)
elseif OkWord (k, I18nArgLabG(ArgL.UnitsSuffix)) then
Test0 (v, unitsSuffix)
elseif OkWord (k, I18nArgLabB(ArgL.GroupNames)) then
Test0 (v, GroupNames)
elseif IsOk2 (k, I18nArgLabB(ArgL.Group)) then
InsertH (v, values, true)
elseif IsOk2 (k, I18nArgLabB(ArgL.Tooltip)) then
InsertH (v, tooltips, false)
elseif IsOk2 (k, I18nArgLabB(ArgL.Links)) then
InsertH (v, links, false)
end
end
DataTooltipMode = SA.Str_Par (args, I18nArgLabB(ArgL.DataTooltipMode), '')
end --extractParams
local PercentByCell = {}
function ValuesFromType ()
if InPercent then
return PercentByCell
else
return values
end
end
local SumAll = 0
local SumSeries = {}
local SumGroups = {}
local OrdAll = {}
local OrdSeries = {}
local OrdGroups = {}
local OrdSumSeries = {}
local OrdSumGroups = {}
function calcSumsOrder ()
function OrderOfTempTab (Tab)
local res = {}
Tab, res = NTO.SortAnSetOrder (Tab, true, true, OnDupliValue)
return res
end
function ArrayToMatrix (A, ANumber)
local res = {}
local temp = {}
local Count = 0
local N = #A / ANumber
for I, V in ipairs (A) do
Count = Count + 1
table.insert (temp, V)
if Count == N then
Count = 0
table.insert (res, temp)
temp = {}
end
end
return res
end --ArrayToMatrix
--BEGIN--
--Sum--
local sum = 0
for i = 1, NumXValues do
for gi = 1, NumGroups do
sum = sum + values[gi][i]
end
table.insert (SumSeries, sum)
SumAll = SumAll + sum
sum = 0
end
sum = 0
for gi = 1, NumGroups do
for i = 1, NumXValues do
sum = sum + values[gi][i]
end
table.insert (SumGroups, sum)
sum = 0
end
local giPerc = {}
if NumGroups == 1 then
else
for gi = 1, NumGroups do
for i = 1, NumXValues do
table.insert (giPerc, (100*values[gi][i])/SumSeries[i])
end
table.insert (PercentByCell, giPerc)
giPerc = {}
end
end
--Order--
OrdSumSeries = OrderOfTempTab(SumSeries)
OrdSumGroups = OrderOfTempTab(SumGroups)
local temp = {}
local OnDupliValue = 3
local res = {}
for i = 1, NumXValues do
temp = {}
for gi = 1, NumGroups do
table.insert(temp, values[gi][i])
end
table.insert(OrdSeries, OrderOfTempTab(temp))
end
for gi = 1, NumGroups do
temp = {}
for i = 1, NumXValues do
table.insert(temp, values[gi][i])
end
table.insert (OrdGroups, OrderOfTempTab(temp))
end
temp = {}
for gi = 1, NumGroups do
for i = 1, NumXValues do
table.insert(temp, values[gi][i])
end
end
local tab = OrderOfTempTab(temp)
OrdAll = ArrayToMatrix (tab, NumGroups)
end --calcSumsOrder
local ValScales = {}
local ValScalesPG = {}
local NumNotches = 0
local NumNotchesPG = {}
local XSep = 0
function validate()
function ValiDataTooltipMode()
local ValWds = {}
local ValSemiQ = {}
function AddFor (Axis)
ValWds = {}
local S_Quali = I18nStr (Msg.Quali)
if type(S_Quali) == 'table' then
for k, v in ipairs(S_Quali) do
table.insert (ValWds, Axis..v)
end
else
table.insert (ValWds, Axis..S_Quali)
end
local S_SemiQ = I18nStr (Msg.SemiQ)
if type(S_SemiQ) == 'table' then
for k, v in ipairs(S_SemiQ) do
table.insert (ValWds, Axis..v)
table.insert (ValSemiQ, v)
end
else
table.insert (ValWds, Axis..S_SemiQ)
table.insert (ValSemiQ, S_SemiQ)
end
--[[]
local S_Quali = I18nStr (Msg.Quali)[1]
local S_SemiQ = I18nStr (Msg.SemiQ)[1]
table.insert (ValWds, Axis..S_Quali)
table.insert (ValWds, Axis..S_SemiQ)
table.insert (ValSemiQ, S_SemiQ)
if WithTrans then
local S_Quali = I18nStr (Msg.Quali)
local S_SemiQ = I18nStr (Msg.SemiQ)
table.insert (ValWds, Axis..S_Quali)
table.insert (ValWds, Axis..S_SemiQ)
table.insert (ValSemiQ, S_SemiQ)
end
--]]
end
function TestFor (s)
Found = false
s = string.sub (s, 2)
for i, w in ipairs(ValSemiQ) do
if w == s then
Found = true
break
end
end
return Found
end
function errorH (RS, S1)
I18nError (RS, SA.ConcatParams (I18nArgLabB(ArgL.DataTooltipMode)), S1)
end
if (DataTooltipMode ~= '') and ((#colTooltip ~= 0) or (#xTooltip ~= 0) or (#legendTooltip ~= 0)) then
if #colTooltip > 0 then
table.insert (SArr, I18nStrMO (Msg.Cols))
end
if #xTooltip > 0 then
table.insert (SArr, I18nStrMO (Msg.X))
end
if #legendTooltip > 0 then
table.insert (SArr, I18nStrMO (Msg.Legend))
end
local S = SArr[1]
if #SArr > 1 then
if #SArr > 2 then
S = S..', '..SArr[2]..' '..I18nStr (Msg.And)..' '..SArr[3]
else
S = S..' '..I18nStr (Msg.And)..' '..ValWds[2]
end
end
I18nError(Err.SetDataTooltipModeAndCustomDataTooltipMode, SA.ConcatParams (I18nArgLabB(ArgL.DataTooltipMode)), S)
elseif (DataTooltipMode == '') and (#colTooltip == 0) and (#xTooltip == 0) and (#legendTooltip == 0) then
elseif DataTooltipMode ~= '' then
local Found = false
local FoundN = 0
for s in mw.text.gsplit (DataTooltipMode, ' ') do
Found = false
FoundN = FoundN + 1
if FoundN == 1 then
AddFor ('x')
else
AddFor ('y')
end
for i, w in ipairs(ValWds) do
if w == s then
if FoundN == 1 then
IsXSemiQ = TestFor (s)
else
IsYSemiQ = TestFor (s)
end
Found = true
break
end
end
if not Found then
errorH (Err.InvalDataTooltipMode, s)
end
end
if FoundN ~= 2 then
errorH (Err.InvalDataTooltipMode2Need, tostring(FoundN))
else
if IsXSemiQ and IsYSemiQ then
SEnd = 'XY'
elseif IsXSemiQ then
SEnd = 'X-'
elseif IsYSemiQ then
SEnd = '-Y'
else
SEnd = '--'
end
end
end
end
function asGroups (kws, tab, toDuplicate, emptyOK)
if #tab == 0 and not emptyOK then
I18nError(Err.RequiredValForS, SA.ConcatParams (kws))
end
if #tab == 1 and toDuplicate then
for i = 2, NumGroups do
tab[i] = tab[1]
end
end
if #tab > 0 and #tab ~= NumGroups then
I18nError(Err.KWNumAndGroupNumNotMatched, SA.ConcatParams (kws), tostring(#tab), tostring(NumGroups))
end
end --asGroups
function fill (tab)
if #tab == 0 then
for gi = 1, NumGroups do
table.insert (tab, '')
end
end
end
function calcHeightLimits() -- if limits were passed by user, use them, otherwise calculate. for "stack" there's only one limet.
local sums = {}
local Vals = ValuesFromType()
if stack then
for _, group in pairs (Vals) do
for i, val in ipairs (group) do
sums[i] = (sums[i] or 0) + val
end
end
local sum = math.max (unpack (sums))
for i = 1, #values do
yscales[i] = sum
end
else
for i, group in ipairs (Vals) do
yscales[i] = math.max (unpack (group))
end
end
for i, scale in ipairs (yscales) do
yscales[i] = roundup (scale * 0.9999)
end
if not ScalePerGroup then
for i = 1, #values do
yscales[i] = math.max (unpack (yscales))
end
end
end --calcHeightLimits
function GetValScales()
function ScaleInGroup(gi)
local yscale = yscales[gi]
local VScales = {}
local _, top, ordermag = roundup (yscale * 0.999)
local NNotches = yticks >= 0 and yticks or
(top <= 1.5 and top * 4
or top < 4 and top * 2
or top)
for i = 1, NNotches do
table.insert (VScales, i / NNotches * yscale)
end
return NNotches, VScales
end
if ScalePerGroup then
for gi = 1, NumGroups do
local NN, VS = ScaleInGroup (gi)
table.insert (NumNotchesPG, NN)
table.insert (ValScalesPG, VS)
end
else
NumNotches, ValScales = ScaleInGroup (1)
end
end --GetValScales
-- do all sorts of validation here, so we can assume all params are good from now on.
-- among other things, replace numerical values with mw.language:parseFormattedNumber() result
ValiDataTooltipMode()
NumGroups = #values
if NumGroups == 0 then
I18nError(Err.AnyGroupIsRequired)
end
NumXValues = #values[1]
NumAllValues = NumGroups * NumXValues
YSep = 32
if XText2Lines then
YSep = 50
local FoundH = false
for i = 1, NumXValues do
if string.find(xlegends[i],' ') ~= nil then
FoundH = true
break
end
end
if not FoundH then
I18nError(Err.Selected2LinesButNoSpaces)
end
end
chartHeight = height - YSep
if table.getn(colors) == 0 then
if NumGroups == 1 then
DefColor = DefColor or 'blue'
colors[1] = colors[1] or DefColor
else
colors = ChartColors.GetColors ('plotter', false, 1, #values, false)
end
elseif (table.getn(colors) == 1) and (NumGroups > 1) then
colors = ColorsFromPalette (colors[1], #values)
end
calcSumsOrder()
calcHeightLimits()
GetValScales ()
local ZLen = 0
if InPercent then
ZLen = 4
else
if ScalePerGroup then
for gi = 1, NumGroups do
for i = 1, NumNotchesPG[gi] do
ZLen = math.max (ZLen, string.len(tostring(ValScalesPG[gi][i])))
end
end
else
for i = 1, NumNotches do
ZLen = math.max (ZLen, string.len(tostring(ValScales[i])))
end
end
end
XSep = (ZLen * 7)+ (math.floor(ZLen/3)*3) + 14
scaleWidth = (ScalePerGroup and XSep * NumGroups) or XSep
local ChartMargin = 0
chartWidth = width - (scaleWidth + ChartMargin*2)
asGroups (I18nArgLabG(ArgL.UnitsPrefix), unitsPrefix, true, true)
fill (unitsPrefix)
asGroups (I18nArgLabG(ArgL.UnitsSuffix), unitsSuffix, true, true)
fill (unitsSuffix)
asGroups (I18nArgLabB(ArgL.Colors), colors, true, true)
if #GroupNames == 0 then
table.insert (GroupNames, '')
end
asGroups (I18nArgLabB(ArgL.GroupNames), GroupNames, false, false)
local PosSep
for gi = 1, NumGroups do
PosSep = string.find (GroupNames[gi], '%-%-')
if PosSep == nil then
table.insert (AddedToGroup, '')
else
table.insert (AddedToGroup, string.sub (GroupNames[gi],PosSep+2))
GroupNames[gi] = string.sub (GroupNames[gi], 1, PosSep-1)
end
end
if stack and ScalePerGroup then
I18nError(Err.IncompatibleSettings, SA.ConcatParams (I18nArgLabB(ArgL.Stack)), SA.ConcatParams (I18nArgLabB(ArgL.ScalePerGroup)))
end
for gi = 2, NumGroups do
if #values[gi] ~= NumXValues then
I18nError(Err.NotHaveSameNumber, SA.ConcatParams (I18nArgLabB(ArgL.Group)), tostring(gi), SA.ConcatParams (I18nArgLabB(ArgL.Group)))
end
end
if #xlegends ~= NumXValues then
I18nError(Err.InvalLegendNumber, SA.ConcatParams (I18nArgLabB(ArgL.XLegend)), tostring(NumXValues))
end
end --validate
local XPrior = ''
local XNext = ''
function GetXPriorNext (i)
if i > 1 then
XPrior = not nulOrWhitespace (xlegends[i-1]) and xlegends[i-1] or ''
end
if i < NumXValues then
XNext = not nulOrWhitespace (xlegends[i+1]) and xlegends[i+1] or ''
end
end
local GPrior = ''
local GNext = ''
function GPriorNext (gi)
if gi > 1 then
GPrior = GroupNames[gi-1]
end
if gi < NumXValues then
GNext = GroupNames[gi+1]
end
end --GPriorNext
-- Next are used for GetColTooltip, GetXTooltip, GetLegendTooltip --
local AString = ''
local ATooltipLines = {}
function CharForSum (IsPrior)
if IsPrior then
return '≤'
else
return '≥'
end
end
function AddS2 (Idx, S)
if Idx == 2 then
S = '('..S..')'
end
AString = AString..' '..S
end
function AddS2b (Idx, S)
AString = AString..' '..S
end
function SumFrom (tab, Num, Sum, ALabel)
AString = ''
for l, m in ipairs(tab) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(Num)
elseif m == Tt_N.Perc then
S = Mult100 (Num/Sum,NDecOfVal(Sum))
end
AddS2 (l, S)
end
table.insert (ATooltipLines, ALabel..' '..AString)
end --SumFrom
function PrepMeanNum (Mean, NVals)
return PrepNum (round (Mean, NDecOfVal(NVals)))
end
function PrepMeanPerc (Mean, Z)
return DefaultShow.Dif..' '..NumToPercSign0 (Mean/(SumAll/Z), SumAll)
end
function GetColTooltip (gi, i, val)
if tooltips and tooltips[gi] and not nulOrWhitespace (tooltips[gi][i]) then return tooltips[gi][i], true end
local groupName = not nulOrWhitespace (GroupNames[gi]) and GroupNames[gi] or ''
GetXPriorNext (i)
local xlegend = not nulOrWhitespace (xlegends[i]) and xlegends[i] or ''
ATooltipLines = {}
function ALabelX (IsPrior)
return string.format (DefaultShow.Sum..'(%s & '..CharForSum(IsPrior)..'%s)', groupName, xlegend)
end
function ALabelGr (IsPrior)
return string.format (DefaultShow.Sum..'(%s & '..CharForSum(IsPrior)..'%s)', xlegend, groupName)
end
function AddS3 (Idx, Total, S)
if Idx == 1 then
AString = AString..' '..S
elseif Idx == 2 then
S = '('..S
if Total == 2 then
S = S..')'
end
AString = AString..' '..S
elseif Idx == 3 then
AString = AString..', '..S..')'
end
end
function SumAndOrPerc (tab)
AString = ''
for l, m in ipairs(tab) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val)
elseif m == Tt_N.Perc then
S = Mult100 (val/SumAll,NDecOfVal(SumAll))
end
AddS2 (l, S)
end
table.insert (ATooltipLines, xlegend..TooltipSep..' '..AString)
end
function SumFromPriorX (tab, gi, i)
local sum = 0
for j=1, i do
sum = sum + values[gi][j]
end
SumFrom (tab, sum, SumGroups[gi], ALabelX(true))
end
function SumFromPriorGr (tab, gi, i)
local sum = 0
for j=1, gi do
sum = sum + values[j][i]
end
SumFrom (tab, sum, SumSeries[i], ALabelGr(true))
end
function SumFromNextX (tab, gi, i)
local sum = 0
for j=NumXValues, i, -1 do
sum = sum + values[gi][j]
end
SumFrom (tab, sum, SumGroups[gi], ALabelX(false))
end
function SumFromNextGr (tab, gi, i)
local sum = 0
for j=NumGroups, gi, -1 do
sum = sum + values[j][i]
end
SumFrom (tab, sum, SumSeries[i], ALabelGr(false))
end
function AddPercOfSum (Arg, sum)
if sum > 0 then -- sum should always be > 0
AddPerc (ATooltipLines, '% / '..DefaultShow.Sum..' '..Arg, '', val/sum, NDecOfVal(sum))
end
end
local ExistsAbsRel = false
function SIfAbsAndRel (IsAbs)
if ExistsAbsRel then
if IsAbs then
return I18nStr (Msg.Tt_abs)
else
return I18nStr (Msg.Tt_rel)
end
else
return ''
end
end
function DifPriorX (IsAbs)
local S = SIfAbsAndRel (IsAbs)
if IsAbs then
S = S..NumToPercSign0 (val/values[gi][i-1],
math.max(val,values[gi][i-1]))
else
S = S..NumToPercSign0 ((val/SumSeries[i]) / (values[gi][i-1]/SumSeries[i-1]),
math.max(SumSeries[i],SumSeries[i-1]))
end
return S
end
function DifNextX (IsAbs)
local S = SIfAbsAndRel (IsAbs)
if IsAbs then
S = S..NumToPercSign0 (val/values[gi][i+1],
math.max(val,values[gi][i+1]))
else
S = S..NumToPercSign0 ((val/SumSeries[i]) / (values[gi][i+1]/SumSeries[i+1]),
math.max(SumSeries[i],SumSeries[i+1]))
end
return S
end
function DifPriorGr (IsAbs)
local S = SIfAbsAndRel (IsAbs)
if IsAbs then
S = S..NumToPercSign0 (val/values[gi-1][i],
math.max(val,values[gi-1][i]))
else
S = S..NumToPercSign0 ((val/SumGroups[gi]) / (values[gi-1][i]/SumGroups[gi-1]),
math.max(SumGroups[gi],SumGroups[gi-1]))
end
return S
end
function DifNextGr (IsAbs)
local S = SIfAbsAndRel (IsAbs)
if IsAbs then
S = S..NumToPercSign0 (val/values[gi+1][i],
math.max(val,values[gi+1][i]))
else
S = S..NumToPercSign0 ((val/SumGroups[gi]) / (values[gi+1][i]/SumGroups[gi+1]),
math.max(SumGroups[gi],SumGroups[gi+1]))
end
return S
end
function TestAbsRel (tab)
ExistsAbs = false
ExistsRel = false
for l, m in ipairs(tab) do
if m == Tt_N.Perc_abs then
ExistsAbs = true
elseif m == Tt_N.Perc_rel then
ExistsRel = true
end
end
return ExistsAbs and ExistsRel
end
function AddSSpc (AS, What, Order)
if AS ~= '' then
AS = AS..' '
end
return AS..What..' '..Order
end
GetPrefixSuffix (gi)
GPriorNext (gi)
if #colTooltip == 0 then
if NumGroups == 1 then
table.insert (ATooltipLines, xlegend..TooltipSep..' '..PrepNum(val))
else
if stack then
AString = groupName..', '..xlegend..' '..PrepNum(val)
table.insert (ATooltipLines, AString)
if gi > 1 then
SumFromPriorGr ({RS_num}, gi, i)
end
else
table.insert (ATooltipLines, groupName..', '..xlegend..TooltipSep..' '..PrepNum(val))
end
end
else
for j, k in ipairs(colTooltip) do
if type(k)=='table' then
if k[1] == Tt_N.Basic then
SumAndOrPerc (k[2])
elseif k[1] == Tt_N.Order then
AString = DefaultShow.Order..TooltipSep
local S = ''
for l, m in ipairs(k[2]) do
local Order = 0
local W = ''
if m == Tt_N.All then
S = AddSSpc (S, DefaultShow.All, OrdAll[gi][i])
elseif m == Tt_N.X then
S = AddSSpc (S, xlegend, OrdSeries[i][gi])
elseif m == Tt_N.Gr then
S = AddSSpc (S, groupName, OrdGroups[gi][i])
end
end
table.insert (ATooltipLines, AString..' '..S)
elseif (k[1] == Tt_N.Sum_x_prior) or (k[1] == Tt_N.Sum_prior) then
SumFromPriorX (k[2], gi, i)
elseif (k[1] == Tt_N.Sum_x_next) or (k[1] == Tt_N.Sum_next) then
SumFromNextX (k[2], gi, i)
elseif k[1] == Tt_N.Sum_gr_prior then
SumFromPriorGr (k[2], gi, i)
elseif k[1] == Tt_N.Sum_gr_next then
SumFromNextGr (k[2], gi, i)
elseif (k[1] == Tt_N.MeanDif_x) or (k[1] == Tt_N.MeanDif) then
AString = DefaultShow.Mean..'('..xlegend..')'..TooltipSep
for l, m in ipairs(k[2]) do
local S = DefaultShow.Mean..TooltipSep
local Mean = val/SumSeries[i]
if m == Tt_N.Num then
S = PrepMeanNum (Mean, SumSeries[i])
elseif m == Tt_N.Perc then
S = PrepMeanPerc (Mean, SumSeries[i])
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
elseif k[1] == Tt_N.MeanDif_gr then
AString = DefaultShow.Mean..'('..groupName..')'..TooltipSep
for l, m in ipairs(k[2]) do
local S = DefaultShow.Mean..TooltipSep
local Mean = val/SumGroups[gi]
if m == Tt_N.Num then
S = PrepMeanNum (Mean, SumGroups[gi])
elseif m == Tt_N.Perc then
S = PrepMeanPerc (Mean, SumGroups[gi])
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
elseif (k[1] == Tt_N.Dif_x_prior) or (k[1] == Tt_N.Dif_prior) then
if i > 1 then
AString = DefaultShow.Dif..XPrior..TooltipSep
ExistsAbsRel = TestAbsRel (k[2])
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val-values[gi][i-1])
elseif (m == Tt_N.Perc_abs) or (m == Tt_N.Perc) then
S = DifPriorX (true)
elseif m == Tt_N.Perc_rel then
S = DifPriorX (false)
end
AddS3 (l, #k[2], S)
end
table.insert (ATooltipLines, AString)
end
elseif (k[1] == Tt_N.Dif_x_next) or (k[1] == Tt_N.Dif_next) then
if i < NumXValues then
AString = DefaultShow.Dif..XNext..TooltipSep
ExistsAbsRel = TestAbsRel (k[2])
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val-values[gi][i+1])
elseif (m == Tt_N.Perc_abs) or (m == Tt_N.Perc) then
S = DifNextX (true)
elseif m == Tt_N.Perc_rel then
S = DifNextX (false)
end
AddS3 (l, #k[2], S)
end
table.insert (ATooltipLines, AString)
end
elseif k[1] == Tt_N.Dif_gr_prior then
if gi > 1 then
AString = DefaultShow.Dif..GPrior..TooltipSep
ExistsAbsRel = TestAbsRel (k[2])
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val-values[gi-1][i])
elseif m == Tt_N.Perc_abs then
S = DifPriorGr (true)
elseif m == Tt_N.Perc_rel then
S = DifPriorGr (false)
end
AddS3 (l, #k[2], S)
end
table.insert (ATooltipLines, AString)
end
elseif k[1] == Tt_N.Dif_gr_next then
if gi < NumGroups then
AString = DefaultShow.Dif..GNext..TooltipSep
ExistsAbsRel = TestAbsRel (k[2])
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val-values[gi+1][i])
elseif m == Tt_N.Perc_abs then
S = DifNextGr (true)
elseif m == Tt_N.Perc_rel then
S = DifNextGr (false)
end
AddS3 (l, #k[2], S)
end
table.insert (ATooltipLines, AString)
end
end
else
if k == Tt_N.Num then
if NumGroups > 1 then
AString = groupName..', '..xlegend
table.insert (ATooltipLines, AString)
AString = PrepNum(val)
table.insert (ATooltipLines, AString)
else
table.insert (ATooltipLines, xlegend..TooltipSep..' '..PrepNum(val))
end
elseif k == Tt_N.Perc_all then
AddPercOfSum (I18nStr (Msg.Total), SumAll)
elseif k == Tt_N.Perc_x then
AddPercOfSum (groupName, SumGroups[gi])
elseif k == Tt_N.Perc_gr then
AddPercOfSum (xlegend, SumSeries[i])
end
end
end
end
--[[
for k = 1, #ATooltipLines do
ATooltipLines[k] = NonBreak (ATooltipLines[k])
end
--]]
local ASS = table.concat(ATooltipLines," ")
return ASS, false
end --GetColTooltip
function calcHeights (gi, i, val)
local barHeight = math.floor (val / yscales[gi] * chartHeight + 0.5) -- add half to make it "round" instead of "trunc"
local top, base = chartHeight - barHeight, 0
local Vals = ValuesFromType()
if stack then
local rawbase = 0
for j = 1, gi - 1 do
rawbase = rawbase + Vals[j][i]
end -- sum the "i" value of all the groups below our group, gi.
base = math.floor (chartHeight * rawbase / yscales[gi]) -- normally, and especially if it's "stack", all the yscales must be equal.
end
return barHeight, top - base
end --calcHeights
function groupBounds (i)
local setWidth = math.floor (chartWidth / NumXValues)
local setOffset = (i - 1) * setWidth
return setOffset, setWidth
end
function calcx (gi, i)
local setOffset, setWidth = groupBounds (i)
if stack or NumGroups == 1 then
local barWidth = math.min (38, math.floor (0.8 * setWidth))
return setOffset + (setWidth - barWidth) / 2, barWidth
end
setWidth = 0.85 * setWidth
local barWidth = math.floor (0.75 * setWidth / NumGroups)
local left = setOffset + math.floor ( (gi - 1) / NumGroups * setWidth)
return left, barWidth
end --calcx
function drawbar (gi, i, val, ttval)
--if val == '0' then return end -- do not show single line (borders....) if value is 0, or rather, '0'. see talkpage
--local color, tooltip, custom = colors[gi] or DefColor or 'blue', GetColTooltip (gi, i, ttval or val)
local color, tooltip, custom = colors[gi] or DefColor or 'blue', GetColTooltip (gi, i, values[gi][i])
local left, barWidth = calcx (gi, i)
local barHeight, top = calcHeights (gi, i, val)
if barHeight == 0 then
return
end
-- borders so it shows up when printing
local style = string.format("position:absolute;left:%spx;top:%spx;height:%spx;min-width:%spx;max-width:%spx;background-color:%s;-webkit-print-color-adjust:exact;border:1px solid %s;border-bottom:none;overflow:hidden;",
left, top+IncTop, barHeight-1, barWidth-2, barWidth-2, color, color)
local S = ''
local link = links[gi] and links[gi][i] or ''
if not nulOrWhitespace (link) then
img = mw.ustring.format( '[[File:Transparent.png|1000px|link=%s|%s]]', link, custom and tooltip or '' ) or ''
S = mw.text.tag( 'div', { style = style, title = tooltip, }, img )
elseif tooltip ~= '' then
S = '<div style="'..style..'"><span title="'..tooltip..'">[[File:Transparent.png|1000px]]</span></div>'
else
S = '<div style="'..style..'">[[File:Transparent.png|1000px]]</div>'
end
table.insert (res, S)
end --drawbar
function drawWallAndYGrid()
if WallColor ~= '' then
local WallStr = string.format ('<div style="position:absolute; max-height:%spx; max-width:%spx; top:%spx; left:%spx; background-color:%s;"><span>[[File:Transparent.png|1000px|link=]]</span></div>',
chartHeight, chartWidth, IncTop, scaleWidth - XSep, WallColor)
table.insert (res, WallStr)
end
function drawSingle()
local lineStyleStr = 'position:absolute;height=1px;min-width:%spx;top:%spx;left:%spx;border:1px dotted %s;'
for i = 1, NumNotches do
local y = chartHeight - calcHeights (1, 1, ValScales[i])
local div = mw.text.tag ('div', { style = string.format (lineStyleStr, chartWidth-4, y + IncTop, (scaleWidth - XSep) + 2, 'Silver') }, '')
table.insert (res, div)
end
end --drawSingle
for gi = 1, NumGroups do
drawSingle()
end
end--drawWallAndYGrid
function drawYScale()
function drawSingle (gi, color, width, yticks, single)
local valStyleStr =
single and 'position:absolute;height=20px;text-align:right;vertical-align:middle;width:%spx;top:%spx;padding:0 2px'
or 'position:absolute;height=20px;text-align:right;vertical-align:middle;width:%spx;top:%spx;left:3px;background-color:%s;color:white;font-weight:bold;text-shadow:-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000;padding:0 2px'
local notchStyleStr = 'position:absolute;height=1px;min-width:5px;top:%spx;left:%spx;border:1px solid %s;'
local SS = {}
local NN = (ScalePerGroup and NumNotchesPG[gi]) or NumNotches
for i = 1, NN do
local val = (ScalePerGroup and ValScalesPG[gi][i]) or ValScales[i]
-- table.insert (SS, val)
local y = chartHeight - calcHeights (gi, i, val)
local temp = mw.getContentLanguage():formatNum (tonumber(val) or 0)
if InPercent then
temp = temp..'%'
end
-- table.insert (SS, temp..'='..y)
local div = mw.text.tag ('div', { style = string.format (valStyleStr, width - 10, (y - 10) + IncTop, color) }, temp)
table.insert (res, div)
div = mw.text.tag ('div', { style = string.format (notchStyleStr, y + IncTop, width - 4, color) }, '')
table.insert (res, div)
end
-- error (table.concat(SS, ' - '))
end --drawSingle
if ScalePerGroup then
local colWidth = XSep
local colStyle = "position:absolute;height:%spx;min-width:%spx;left:%spx;border-right:1px solid %s;color:%s"
for gi = 1, NumGroups do
local left = (gi - 1) * colWidth
local color = colors[gi] or DefColor
table.insert (res, mw.text.tag ('div', { style = string.format (colStyle, chartHeight, colWidth, left, color, color) }))
drawSingle (gi, color, colWidth, yticks)
table.insert (res, '</div>')
end
else
drawSingle (1, 'black', scaleWidth, yticks, true)
end
end --drawYScale
function drawXlegends()
function GetXTooltip(i)
ATooltipLines = {}
GetXPriorNext (i)
local val = SumSeries[i]
for j, k in ipairs(xTooltip) do
if k[1] == Tt_N.Basic then
AString = xlegends[i]..TooltipSep
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val)
elseif m == Tt_N.Perc then
S = Mult100 (val/SumAll,NDecOfVal(SumAll))
elseif m == Tt_N.Order then
S = OrdSumSeries[i]
end
AddS3 (l, S)
end
table.insert (ATooltipLines, AString)
elseif k[1] == Tt_N.Mean then
AString = DefaultShow.Mean..TooltipSep
for l, m in ipairs(k[2]) do
local S = DefaultShow.Mean..TooltipSep
local Mean = val/NumXValues
if m == Tt_N.Num then
S = PrepMeanNum (Mean, NumXValues)
elseif m == Tt_N.Perc then
S = PrepMeanPerc (Mean, NumXValues)
end
AddS2b (l, S)
end
table.insert (ATooltipLines, AString)
elseif k[1] == Tt_N.Sum_prior then
AString = DefaultShow.Sum..CharForSum(true)..xlegends[i]..TooltipSep
local sum = 0
for l = 1, i do
sum = sum + SumSeries[l]
end
SumFrom (k[2], sum, SumAll, AString)
elseif k[1] == Tt_N.Sum_next then
AString = DefaultShow.Sum..CharForSum(false)..xlegends[i]..TooltipSep
local sum = 0
for l = NumXValues, i, -1 do
sum = sum + SumSeries[l]
end
SumFrom (k[2], sum, SumAll, AString)
elseif (k[1] == Tt_N.Dif_prior) and (i > 1) then
AString = DefaultShow.Dif..XPrior..TooltipSep
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val-SumSeries[i-1])
elseif m == Tt_N.Perc then
S = NumToPercSign0 (val/SumSeries[i-1],math.max(val,SumSeries[i-1]))
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
elseif (k[1] == Tt_N.Dif_next) and (i < NumXValues) then
AString = DefaultShow.Dif..XNext..TooltipSep
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val-SumSeries[i+1])
elseif m == Tt_N.Perc then
S = NumToPercSign0 (val/SumSeries[i+1],math.max(val,SumSeries[i+1]))
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
elseif k[1] == Tt_N.List then
NDec = NDecOfVal(SumSeries[i])
for gi = 1, NumGroups do
AString = GroupNames[gi]..TooltipSep
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(values[gi][i])
elseif m == Tt_N.Perc then
S = Mult100(PercentByCell[gi][i],NDec)
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
end
end
end
for k = 1, #ATooltipLines do
ATooltipLines[k] = NonBreak (ATooltipLines[k])
end
NonBreakArr (ATooltipLines)
local ASS = table.concat(ATooltipLines," ")
return ASS, false
end --GetXTooltip
local setOffset, setWidth
local legendDivStyleFormat = "position:absolute;left:%spx;top:10px;min-width:%spx;max-width:%spx;text-align:center;vertical-align:top;"
local tickDivstyleFormat = "position:absolute;left:%spx;height:10px;width:1px;border-left:1px solid black;"
for i = 1, NumXValues do
if not nulOrWhitespace (xlegends[i]) then
setOffset, setWidth = groupBounds (i)
-- setWidth = 0.85 * setWidth
table.insert (res, mw.text.tag ('div', { style = string.format (legendDivStyleFormat, setOffset + 5, setWidth - 10, setWidth - 10) }, CFCM.TextWithTooltip(xlegends[i],GetXTooltip(i)) or ''))
table.insert (res, mw.text.tag ('div', { style = string.format (tickDivstyleFormat, setOffset + setWidth / 2) }, ''))
end
end
end --drawXlegends
function drawChart()
function GetLegendTooltip (gi)
GetPrefixSuffix (gi)
GPriorNext (gi)
local groupName = GroupNames[gi]
ATooltipLines = {}
function NumToPercSignH (idx, AValue, Arg, NVals)
local ALabel = legendTooltipLabel[idx] or ''
NumToPercSign (ATooltipLines, ALabel, Arg, AValue, NVals)
end
local val = SumGroups[gi]
for j, k in ipairs(legendTooltip) do
if k[1] == Tt_N.Basic then
AString = groupName..TooltipSep
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val)
elseif m == Tt_N.Perc then
S = Mult100 (val/SumAll,NDecOfVal(SumAll))
elseif m == Tt_N.Order then
S = OrdSumGroups[gi]
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
elseif k[1] == Tt_N.Mean then
AString = DefaultShow.Mean..TooltipSep
for l, m in ipairs(k[2]) do
local S = DefaultShow.Mean..TooltipSep
local Mean = val/NumGroups
if m == Tt_N.Num then
S = PrepMeanNum (Mean, NumGroups)
elseif m == Tt_N.Perc then
S = PrepMeanPerc (Mean, NumGroups)
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
elseif k[1] == Tt_N.Sum_prior then
AString = DefaultShow.Sum..CharForSum(true)..groupName..TooltipSep
local sum = 0
for l = 1, i do
sum = sum + SumGroups[l]
end
SumFrom (k[2], sum, SumAll, AString)
elseif k[1] == Tt_N.Sum_next then
AString = DefaultShow.Sum..CharForSum(false)..groupName..TooltipSep
local sum = 0
for l = NumXValues, i, -1 do
sum = sum + SumGroups[l]
end
SumFrom (k[2], sum, SumAll, AString)
elseif (k[1] == Tt_N.Dif_prior) and (gi > 1) then
AString = DefaultShow.Dif..GPrior..TooltipSep
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val-SumGroups[gi-1])
elseif m == Tt_N.Perc then
S = NumToPercSign0 (val/SumGroups[gi-1],math.max(val,SumGroups[gi-1]))
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
elseif (k[1] == Tt_N.Dif_next) and (gi < NumGroups) then
AString = DefaultShow.Dif..GNext..TooltipSep
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(val-SumGroups[gi+1])
elseif m == Tt_N.Perc then
S = NumToPercSign0 (val/SumGroups[gi+1],math.max(val,SumGroups[gi+1]))
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
elseif k[1] == Tt_N.List then
NDec = NDecOfVal(SumGroups[gi])
for i = 1, NumXValues do
AString = xlegends[i]..TooltipSep
for l, m in ipairs(k[2]) do
local S = ''
if m == Tt_N.Num then
S = PrepNum(values[gi][i])
elseif m == Tt_N.Perc then
S = Mult100(values[gi][i]/SumGroups[gi],NDec)
end
AddS2 (l, S)
end
table.insert (ATooltipLines, AString)
end
end
end
NonBreakArr (ATooltipLines)
local ASS = table.concat(ATooltipLines," ")
return ASS
end --GetLegendTooltip
-- BEGIN drawChart() --
table.insert (res, mw.text.tag ('div', { class = 'chart noresize', style = string.format ('margin-top:0.1em; margin-bottom:0.3em; max-width:%spx;', width) }))
AddPerhapsTitle (res, width)
table.insert (res, mw.text.tag ('div', { style = string.format("position:relative;min-height:%spx;min-width:%spx;max-width:%spx;", height, width, width) }))
local chartHeightH = chartHeight + IncTop
table.insert (res, mw.text.tag ('div', { style = string.format("float:right;position:relative;min-height:%spx;min-width:%spx;max-width:%spx;border-left:1px black solid;border-bottom:1px black solid;", chartHeightH, chartWidth, chartWidth) }))
if not (ScalePerGroup or HideGridY) then
drawWallAndYGrid()
end
local acum = stack and accumulateTooltip and {}
local Vals = ValuesFromType()
for gi, group in pairs (Vals) do
for i, val in ipairs (group) do
if acum then
acum[i] = (acum[i] or 0) + val
if val ~= 0 then
drawbar (gi, i, val, acum and acum[i])
end
else
drawbar (gi, i, val, acum and acum[i])
end
end
end
table.insert (res, '</div>')
table.insert (res, mw.text.tag ('div', { style = string.format("position:absolute;height:%spx;min-width:%spx;max-width:%spx;", chartHeightH, scaleWidth, scaleWidth, scaleWidth) }))
drawYScale()
table.insert (res, '</div>')
table.insert (res, mw.text.tag ('div', { style = string.format ("position:absolute;top:%spx;left:%spx;width:%spx;", chartHeightH, scaleWidth, chartWidth) }))
drawXlegends()
table.insert (res, '</div>')
table.insert (res, '</div>')
local Tooltips = {}
if table.getn(legendTooltip) > 0 then
for gi = 1, NumGroups do
table.insert (Tooltips, GetLegendTooltip(gi))
end
end
createLegends (res, GroupNames, AddedToGroup, colors, Tooltips)
if MouseOverTooltip then
local SArr = {}
if (#colTooltip > 0) or tooltips then
table.insert (SArr, I18nStrMO (Msg.Cols))
end
if #xTooltip > 0 then
table.insert (SArr, I18nStrMO (Msg.X))
end
if #legendTooltip > 0 then
table.insert (SArr, I18nStrMO (Msg.Legend))
end
if #SArr > 0 then
local S = SArr[1]
if #SArr > 1 then
if #SArr > 2 then
S = S..', '..SArr[2]..' '..I18nStr (Msg.And)..' '..SArr[3]
else
S = S..' '..I18nStr (Msg.And)..' '..SArr[2]
end
end
AddMouseOverMess (res, I18nStrMO (Msg.Tooltip, S))
end
end
AddPerhapsNote (res)
table.insert (res, '</div>')
end --drawChart
---- BEGIN ----
extractParams()
validate()
AppendResAtChartBegin (res, width)
drawChart()
AppendResAtChartEnd (res)
local Debug = false
if Debug then
return '<pre>'..table.concat (res, "\n")..'</pre>'
else
--return SDebug..table.concat (res, "\n")
return table.concat (res, "\n")
end
end --barChart
return {
[i18n["BarChart"]] = barChart,
['bar chart'] = barChart,
[i18n["PieChart"]] = pieChart,
['pie chart'] = pieChart,
}
--</syntaxhighlight>