| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:Utility/TableUtil」の版間の差分
ナビゲーションに移動
検索に移動
("maximumValue" を指定した場合、軸表示とグラフがズレることがある問題の修正) |
([LineCell] サブグラフの描画機能を実装) |
||
| 214行目: | 214行目: | ||
-- [Utils] | -- [Utils] | ||
local function multipleGradient(colorStop1, colorStop2 | local function multipleGradient(colorStop1, colorStop2) | ||
local | local gradientFormat = string.format('linear-gradient(to right,transparent %%s%%%%,%s %%s%%%%,%s %%s%%%%,transparent %%s%%%%)', colorStop1, colorStop2) | ||
return function(minValue, maxValue) | return function(minValue, maxValue) | ||
if minValue == maxValue then | if minValue == maxValue then | ||
| 234行目: | 229行目: | ||
end | end | ||
local function singleGradient(colorStop1, colorStop2 | local function singleGradient(colorStop1, colorStop2) | ||
local gradientFormat | local gradientFormat | ||
if colorStop1 == colorStop2 then | if colorStop1 == colorStop2 then | ||
gradientFormat = string.format('linear-gradient(to right,%s %%s%%%%,transparent %%s%%%%)', colorStop1) | |||
else | else | ||
gradientFormat = string.format('linear-gradient(to right,%s,%s %%s%%%%,transparent %%s%%%%)', colorStop1, colorStop2) | |||
end | end | ||
return function(value) | return function(value) | ||
| 264行目: | 251行目: | ||
obj.startIndex = opts.startIndex or dataIndex | obj.startIndex = opts.startIndex or dataIndex | ||
obj.endIndex = opts.endIndex or dataIndex | obj.endIndex = opts.endIndex or dataIndex | ||
obj.colorStops = opts.colorStops or '# | obj.colorStops = opts.colorStops or '#A7D7F9' | ||
obj._hasSubGraph = opts.subStartIndex and opts.subEndIndex | |||
if obj._hasSubGraph then | |||
obj.height = opts.height or 1.0 | |||
obj.subStartIndex = opts.subStartIndex or opts.subDataIndex | |||
obj.subEndIndex = opts.subEndIndex or opts.subDataIndex | |||
obj.subColorStops = opts.subColorStops or '#F9C9A7' | |||
obj.subHeight = opts.subHeight or 0.4 | |||
else | |||
obj.height = opts.height or 1.2 | |||
end | |||
if opts.gridEnabled then | if opts.gridEnabled then | ||
obj.gridEnabled = opts.gridEnabled | obj.gridEnabled = opts.gridEnabled | ||
| 270行目: | 267行目: | ||
obj.gridEnabled = true | obj.gridEnabled = true | ||
end | end | ||
obj.minimumValue = opts.minimumValue or 0 | obj.minimumValue = opts.minimumValue or 0 | ||
obj.maximumValue = opts.maximumValue or math.huge | obj.maximumValue = opts.maximumValue or math.huge | ||
| 280行目: | 276行目: | ||
obj.endIndex = dataIndex | obj.endIndex = dataIndex | ||
obj.colorStops = '#A7D7F9' | obj.colorStops = '#A7D7F9' | ||
obj._hasSubGraph = false | |||
obj.subColorStops = '#F9C9A7' | |||
obj.gridEnabled = true | obj.gridEnabled = true | ||
obj.height = 1.2 | obj.height = 1.2 | ||
| 303行目: | 301行目: | ||
-- [Function] Reset context | -- [Function] Reset context | ||
function __TableUtil__LineCell:resetContext(datainfo) | function __TableUtil__LineCell:resetContext(datainfo) | ||
local scale = scale.LinearScale.new():setClamp(true) | local scale = scale.LinearScale.new():setClamp(true) | ||
if self.maximumValue == math.huge then | if self.maximumValue == math.huge then | ||
scale:setDomain({ self.minimumValue, self.maximumRate * | local maxValue = datainfo[self.endIndex].maxValue | ||
if self._hasSubGraph then | |||
local subMaxValue = datainfo[self.subEndIndex].maxValue | |||
if maxValue < subMaxValue then | |||
maxValue = subMaxValue | |||
end | |||
end | |||
scale:setDomain({ self.minimumValue, self.maximumRate * maxValue }) | |||
else | else | ||
scale:setDomain({ self.minimumValue, self.maximumValue }) | scale:setDomain({ self.minimumValue, self.maximumValue }) | ||
| 318行目: | 322行目: | ||
if self.startIndex == self.endIndex then | if self.startIndex == self.endIndex then | ||
if type(self.colorStops) == 'table' then | if type(self.colorStops) == 'table' then | ||
self._gradientFormat = singleGradient(self.colorStops[1], self.colorStops[2] | self._gradientFormat = singleGradient(self.colorStops[1], self.colorStops[2]) | ||
else | else | ||
self._gradientFormat = singleGradient(self.colorStops, self.colorStops | self._gradientFormat = singleGradient(self.colorStops, self.colorStops) | ||
end | end | ||
else | else | ||
if type(self.colorStops) == 'table' then | if type(self.colorStops) == 'table' then | ||
self._gradientFormat = multipleGradient(self.colorStops[1], self.colorStops[2] | self._gradientFormat = multipleGradient(self.colorStops[1], self.colorStops[2]) | ||
else | else | ||
self._gradientFormat = multipleGradient(self.colorStops, self.colorStops | self._gradientFormat = multipleGradient(self.colorStops, self.colorStops) | ||
end | end | ||
end | |||
if self._hasSubGraph then | |||
if self.subStartIndex == self.subEndIndex then | |||
if type(self.subColorStops) == 'table' then | |||
self._subGradientFormat = singleGradient(self.subColorStops[1], self.subColorStops[2]) | |||
else | |||
self._subGradientFormat = singleGradient(self.subColorStops, self.subColorStops) | |||
end | |||
else | |||
if type(self.subColorStops) == 'table' then | |||
self._subGradientFormat = multipleGradient(self.subColorStops[1], self.subColorStops[2]) | |||
else | |||
self._subGradientFormat = multipleGradient(self.subColorStops, self.subColorStops) | |||
end | |||
end | |||
if self.gridEnabled then | |||
self._classes = string.format('st-grid st-grid-%d st-line st-line-h%d-h%d', #self._ticks + 1, 10 * self.height, 10 * self.subHeight) | |||
else | |||
self._classes = string.format('st-line st-line-h%d-h%d', 10 * self.height, 10 * self.subHeight) | |||
end | |||
elseif self.gridEnabled then | |||
self._classes = string.format('st-grid st-grid-%d st-line st-line-h%d', #self._ticks + 1, 10 * self.height) | |||
else | |||
self._classes = string.format('st-line st-line-h%d', 10 * self.height) | |||
end | end | ||
end | end | ||
| 352行目: | 381行目: | ||
-- [Function] Render | -- [Function] Render | ||
function __TableUtil__LineCell:render(row, dataset, i, datainfo) | function __TableUtil__LineCell:render(row, dataset, i, datainfo) | ||
local gradient | local gradient, subGradient | ||
if self.startIndex ~= self.endIndex then | if self.startIndex ~= self.endIndex then | ||
local minimumPercentage = self._scale:scale(dataset[self.startIndex]) | local minimumPercentage = self._scale:scale(dataset[self.startIndex]) | ||
| 360行目: | 389行目: | ||
local percentage = self._scale:scale(dataset[self.dataIndex]) | local percentage = self._scale:scale(dataset[self.dataIndex]) | ||
gradient = self._gradientFormat(percentage) | gradient = self._gradientFormat(percentage) | ||
end | |||
if self._hasSubGraph then | |||
if self.subStartIndex ~= self.subEndIndex then | |||
local minimumPercentage = self._scale:scale(dataset[self.subStartIndex]) | |||
local maximumPercentage = self._scale:scale(dataset[self.subEndIndex]) | |||
subGradient = self._subGradientFormat(minimumPercentage, maximumPercentage) | |||
else | |||
local percentage = self._scale:scale(dataset[self.subEndIndex]) | |||
subGradient = self._subGradientFormat(percentage) | |||
end | |||
end | end | ||
local value = dataset[self.dataIndex] | local value = dataset[self.dataIndex] | ||
local cell = self:__cell__render(row, dataset, i, datainfo) | local cell = self:__cell__render(row, dataset, i, datainfo) | ||
if self. | :addClass(self._classes) | ||
cell: | :attr('data-sort-value', value) | ||
: | if self._hasSubGraph then | ||
if not self.mixinValue then | |||
cell:css('background-image', string.format('%s,%s!important', gradient, subGradient)) | |||
else | |||
cell:css('background-image', string.format('%s,%s', gradient, subGradient)) | |||
end | |||
else | |||
if not self.mixinValue then | |||
cell:css('background-image', string.format('%s!important', gradient)) | |||
else | |||
cell:css('background-image', gradient) | |||
end | |||
end | end | ||
return cell | return cell | ||
end | end | ||
| 538行目: | 583行目: | ||
tableutil.LineValueCell.new('LineValue', 2, { cellClass = 'st-graph st-textshadow' }), | tableutil.LineValueCell.new('LineValue', 2, { cellClass = 'st-graph st-textshadow' }), | ||
tableutil.LineCell.new('Line (Range)', 1, { cellClass = 'st-graph', startIndex = 1, endIndex = 2 }), | tableutil.LineCell.new('Line (Range)', 1, { cellClass = 'st-graph', startIndex = 1, endIndex = 2 }), | ||
tableutil.LineCell.new('Line (Range & Sub)', 1, { cellClass = 'st-graph', startIndex = 1, endIndex = 2, subStartIndex = 1, subEndIndex = 3 }), | |||
} | } | ||
local node = tableutil.createTable({{ 45, 110 }, { 40, 60 }, { 40, 120 }, { 50, 90 }}, metadata) | local node = tableutil.createTable({{ 45, 110, 140 }, { 40, 60, 90 }, { 40, 120, 190 }, { 50, 90, 110 }}, metadata) | ||
return tostring(node) | return tostring(node) | ||
end | end | ||
return tableutil | return tableutil | ||
2021年8月28日 (土) 13:54時点における版
このモジュールについての説明文ページを モジュール:Utility/TableUtil/doc に作成できます
-- Table Utility for MediaWiki
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Copyright (C) 2021 mntone. All rights reserved.
-- This script is released under the MIT License.
-- ====================
-- namespace: TableUtil
-- ====================
local tableutil = {}
-- =====
-- Config
-- =====
local aw = require('Module:Utility/Library')
local scale = require('Module:Utility/Scale')
local function __passthrough(num)
return num
end
-- ==========
-- type: Cell
-- ==========
local __TableUtil__CellType__Cell = 'cell'
local __TableUtil__Cell = {
__typename = __TableUtil__CellType__Cell,
}
-- [Constructor]
function __TableUtil__Cell.__new(typename, name, opts)
local obj = {
typename = typename,
name = name,
}
if opts then
if type(opts.attributes) == 'table' then
obj.attributes = opts.attributes
end
if type(opts.cellClass) == 'string' then
obj.cellClass = opts.cellClass
end
if type(opts.footerClass) == 'string' then
obj.footerClass = opts.footerClass
end
if type(opts.headerClass) == 'string' then
obj.headerClass = opts.headerClass
end
if type(opts.headerColspan) == 'number' then
obj.headerColspan = opts.headerColspan
else
obj.headerColspan = 1
end
if type(opts.headerStyle) == 'table' then
obj.headerStyle = opts.headerStyle
end
else
obj.headerColspan = 1
end
return setmetatable(obj, { __index = __TableUtil__Cell })
end
function __TableUtil__Cell.new(name, opts)
return __TableUtil__Cell.__new(__TableUtil__CellType__Cell, name, opts)
end
-- [Function] Reset context
function __TableUtil__Cell:resetContext()
end
-- [Function] Render header
function __TableUtil__Cell:renderHeader(headerRow)
if self.headerColspan <= 0 then
return nil
end
local headerCell = headerRow:tag('th'):wikitext(self.name)
if self.headerClass then
headerCell:addClass(self.headerClass)
end
if self.headerColspan > 1 then
headerCell:attr('colspan', self.headerColspan)
end
if self.headerStyle then
headerCell:css(self.headerStyle)
end
return headerCell
end
-- [Function] Render footer
function __TableUtil__Cell:renderFooter(footerRow)
if self.headerColspan <= 0 then
return nil
end
local footerCell = footerRow:tag('td')
if self.footerClass then
footerCell:addClass(self.footerClass)
end
if self.headerColspan > 1 then
footerCell:attr('colspan', self.headerColspan)
end
return footerCell
end
-- [Function] Render
function __TableUtil__Cell:render(row)
local cell = row:tag('td')
if self.attributes then
cell:attr(self.attributes)
end
if self.cellClass then
cell:addClass(self.cellClass)
end
return cell
end
-- [Export]
tableutil.Cell = __TableUtil__Cell
-- =====================
-- type: ValueCell: Cell
-- =====================
local __TableUtil__CellType__ValueCell = 'value'
local __TableUtil__ValueCell = {
__typename = __TableUtil__CellType__ValueCell,
}
setmetatable(__TableUtil__ValueCell, { __index = __TableUtil__Cell })
-- [Constructor]
function __TableUtil__ValueCell.__new(typename, name, dataIndex, opts)
local obj = __TableUtil__Cell.__new(typename, name, opts)
obj.__cell__render = obj.render
obj.dataIndex = dataIndex
if type(opts) == 'table' then
obj.format = opts.format or __passthrough
else
obj.format = __passthrough
end
return setmetatable(obj, { __index = __TableUtil__ValueCell })
end
function __TableUtil__ValueCell.new(name, dataIndex, opts)
return __TableUtil__ValueCell.__new(__TableUtil__CellType__ValueCell, name, dataIndex, opts)
end
-- [Function] Render
function __TableUtil__ValueCell:render(row, dataset, i, datainfo)
local value = dataset[self.dataIndex]
local formattedValue = self.format(value)
local cell = self:__cell__render(row, dataset, i, datainfo)
:attr('data-sort-value', value)
:wikitext(formattedValue)
return cell
end
-- [Export]
tableutil.ValueCell = __TableUtil__ValueCell
-- =========================
-- type: RankCell: ValueCell
-- =========================
local __TableUtil__CellType__RankCell = 'rank'
local __TableUtil__RankCell = {
__typename = __TableUtil__CellType__RankCell,
}
setmetatable(__TableUtil__RankCell, { __index = __TableUtil__ValueCell })
-- [Constructor]
function __TableUtil__RankCell.new(name, dataIndex, descending)
local obj = __TableUtil__ValueCell.__new(__TableUtil__CellType__RankCell, name, dataIndex)
obj.currentRank = 0
obj.currentValue = -1
obj.descending = descending
return setmetatable(obj, { __index = __TableUtil__RankCell })
end
-- [Property] Is descending?
function __TableUtil__RankCell:isDescending()
return self.descending
end
-- [Function] Reset context
function __TableUtil__RankCell:resetContext(datainfo)
self.currentRank = 0
self.currentValue = -1
end
-- [Function] Render
function __TableUtil__RankCell:render(row, dataset, i)
local value = dataset[self.dataIndex]
if self.currentValue ~= value then
self.currentRank = i
self.currentValue = value
end
local cell = row:tag('th')
:attr('data-sort-value', value)
:wikitext(self.currentRank)
return cell
end
-- [Export]
tableutil.RankCell = __TableUtil__RankCell
-- ====================
-- type: LineCell: Cell
-- ====================
local __TableUtil__CellType__LineCell = 'line'
local __TableUtil__LineCell = {
__typename = __TableUtil__CellType__LineCell,
}
setmetatable(__TableUtil__LineCell, { __index = __TableUtil__ValueCell })
-- [Utils]
local function multipleGradient(colorStop1, colorStop2)
local gradientFormat = string.format('linear-gradient(to right,transparent %%s%%%%,%s %%s%%%%,%s %%s%%%%,transparent %%s%%%%)', colorStop1, colorStop2)
return function(minValue, maxValue)
if minValue == maxValue then
local value = 0.001 * aw.round(1000 * minValue)
minValue = value - 0.5
maxValue = value + 0.5
else
minValue = 0.001 * aw.round(1000 * minValue)
maxValue = 0.001 * aw.round(1000 * maxValue)
end
return string.format(gradientFormat, minValue, minValue, maxValue, maxValue)
end
end
local function singleGradient(colorStop1, colorStop2)
local gradientFormat
if colorStop1 == colorStop2 then
gradientFormat = string.format('linear-gradient(to right,%s %%s%%%%,transparent %%s%%%%)', colorStop1)
else
gradientFormat = string.format('linear-gradient(to right,%s,%s %%s%%%%,transparent %%s%%%%)', colorStop1, colorStop2)
end
return function(value)
value = 0.001 * aw.round(1000 * value)
return string.format(gradientFormat, value, value)
end
end
-- [Constructor]
function __TableUtil__LineCell.__new(typename, name, dataIndex, opts)
local obj = __TableUtil__Cell.__new(typename, name, opts)
obj.__cell__render = obj.render
obj.__cell__renderFooter = obj.renderFooter
obj.dataIndex = dataIndex
if type(opts) == 'table' then
obj.startIndex = opts.startIndex or dataIndex
obj.endIndex = opts.endIndex or dataIndex
obj.colorStops = opts.colorStops or '#A7D7F9'
obj._hasSubGraph = opts.subStartIndex and opts.subEndIndex
if obj._hasSubGraph then
obj.height = opts.height or 1.0
obj.subStartIndex = opts.subStartIndex or opts.subDataIndex
obj.subEndIndex = opts.subEndIndex or opts.subDataIndex
obj.subColorStops = opts.subColorStops or '#F9C9A7'
obj.subHeight = opts.subHeight or 0.4
else
obj.height = opts.height or 1.2
end
if opts.gridEnabled then
obj.gridEnabled = opts.gridEnabled
else
obj.gridEnabled = true
end
obj.minimumValue = opts.minimumValue or 0
obj.maximumValue = opts.maximumValue or math.huge
obj.maximumRate = opts.maximumRate or 1.05
obj.preferredGridCount = opts.preferredGridCount or 4
obj.ticksFormat = opts.ticksFormat or __passthrough
else
obj.startIndex = dataIndex
obj.endIndex = dataIndex
obj.colorStops = '#A7D7F9'
obj._hasSubGraph = false
obj.subColorStops = '#F9C9A7'
obj.gridEnabled = true
obj.height = 1.2
obj.minimumValue = 0
obj.maximumValue = math.huge
obj.maximumRate = 1.05
obj.preferredGridCount = 4
obj.ticksFormat = __passthrough
end
obj._gridCount = 2
return setmetatable(obj, { __index = __TableUtil__LineCell })
end
function __TableUtil__LineCell.new(name, dataIndex, opts)
return __TableUtil__LineCell.__new(__TableUtil__CellType__LineCell, name, dataIndex, opts)
end
-- [Property] Height
function __TableUtil__LineCell:setHeight(value)
self.height = value
return self
end
-- [Function] Reset context
function __TableUtil__LineCell:resetContext(datainfo)
local scale = scale.LinearScale.new():setClamp(true)
if self.maximumValue == math.huge then
local maxValue = datainfo[self.endIndex].maxValue
if self._hasSubGraph then
local subMaxValue = datainfo[self.subEndIndex].maxValue
if maxValue < subMaxValue then
maxValue = subMaxValue
end
end
scale:setDomain({ self.minimumValue, self.maximumRate * maxValue })
else
scale:setDomain({ self.minimumValue, self.maximumValue })
end
scale:nice(self.preferredGridCount)
self._scale = scale
if self.gridEnabled then
self._ticks = scale:ticks(self.preferredGridCount)
end
if self.startIndex == self.endIndex then
if type(self.colorStops) == 'table' then
self._gradientFormat = singleGradient(self.colorStops[1], self.colorStops[2])
else
self._gradientFormat = singleGradient(self.colorStops, self.colorStops)
end
else
if type(self.colorStops) == 'table' then
self._gradientFormat = multipleGradient(self.colorStops[1], self.colorStops[2])
else
self._gradientFormat = multipleGradient(self.colorStops, self.colorStops)
end
end
if self._hasSubGraph then
if self.subStartIndex == self.subEndIndex then
if type(self.subColorStops) == 'table' then
self._subGradientFormat = singleGradient(self.subColorStops[1], self.subColorStops[2])
else
self._subGradientFormat = singleGradient(self.subColorStops, self.subColorStops)
end
else
if type(self.subColorStops) == 'table' then
self._subGradientFormat = multipleGradient(self.subColorStops[1], self.subColorStops[2])
else
self._subGradientFormat = multipleGradient(self.subColorStops, self.subColorStops)
end
end
if self.gridEnabled then
self._classes = string.format('st-grid st-grid-%d st-line st-line-h%d-h%d', #self._ticks + 1, 10 * self.height, 10 * self.subHeight)
else
self._classes = string.format('st-line st-line-h%d-h%d', 10 * self.height, 10 * self.subHeight)
end
elseif self.gridEnabled then
self._classes = string.format('st-grid st-grid-%d st-line st-line-h%d', #self._ticks + 1, 10 * self.height)
else
self._classes = string.format('st-line st-line-h%d', 10 * self.height)
end
end
-- [Function] Render footer
function __TableUtil__LineCell:renderFooter(footerRow)
local footerCell = self:__cell__renderFooter(footerRow)
if self.gridEnabled and footerCell then
footerCell
:addClass('st-axis')
:addClass(string.format('st-axis-%d', #self._ticks + 2))
local list = footerCell:tag('ul')
local firstTickLabel = self.ticksFormat(self._scale.domain[1])
list:tag('li'):wikitext(firstTickLabel)
for _, tick in ipairs(self._ticks) do
local tickLabel = self.ticksFormat(tick)
list:tag('li'):wikitext(tickLabel)
end
end
return footerCell
end
-- [Function] Render
function __TableUtil__LineCell:render(row, dataset, i, datainfo)
local gradient, subGradient
if self.startIndex ~= self.endIndex then
local minimumPercentage = self._scale:scale(dataset[self.startIndex])
local maximumPercentage = self._scale:scale(dataset[self.endIndex])
gradient = self._gradientFormat(minimumPercentage, maximumPercentage)
else
local percentage = self._scale:scale(dataset[self.dataIndex])
gradient = self._gradientFormat(percentage)
end
if self._hasSubGraph then
if self.subStartIndex ~= self.subEndIndex then
local minimumPercentage = self._scale:scale(dataset[self.subStartIndex])
local maximumPercentage = self._scale:scale(dataset[self.subEndIndex])
subGradient = self._subGradientFormat(minimumPercentage, maximumPercentage)
else
local percentage = self._scale:scale(dataset[self.subEndIndex])
subGradient = self._subGradientFormat(percentage)
end
end
local value = dataset[self.dataIndex]
local cell = self:__cell__render(row, dataset, i, datainfo)
:addClass(self._classes)
:attr('data-sort-value', value)
if self._hasSubGraph then
if not self.mixinValue then
cell:css('background-image', string.format('%s,%s!important', gradient, subGradient))
else
cell:css('background-image', string.format('%s,%s', gradient, subGradient))
end
else
if not self.mixinValue then
cell:css('background-image', string.format('%s!important', gradient))
else
cell:css('background-image', gradient)
end
end
return cell
end
-- [Export]
tableutil.LineCell = __TableUtil__LineCell
-- =================
-- type: Value+XCell
-- =================
local function transformValueCell(superklass, klasstype)
local valuetype = string.format('value+%s', klasstype)
local valueKlass = {
__typename = valuetype,
}
setmetatable(valueKlass, { __index = superklass })
function valueKlass.new(name, dataIndex, opts)
local obj = superklass.__new(valuetype, name, dataIndex, opts)
obj.__super__render = obj.render
obj.__super__renderHeader = obj.renderHeader
obj.__super__renderFooter = obj.renderFooter
obj.mixinValue = true
if type(opts) == 'table' then
obj.format = opts.format or __passthrough
else
obj.format = __passthrough
end
return setmetatable(obj, { __index = valueKlass })
end
function valueKlass:render(row, dataset, i, datainfo)
local value = dataset[self.dataIndex]
local formattedValue = self.format(value)
local cell = self:__super__render(row, dataset, i, datainfo)
return cell:wikitext(formattedValue)
end
return valueKlass
end
-- [Export]
tableutil.LineValueCell = transformValueCell(__TableUtil__LineCell, __TableUtil__CellType__LineCell)
-- ===================
-- func: specifyUICell
-- ===================
function tableutil.specifyUICell(klasstype, renderFunction, propNames)
local specifictype = string.format('ui+%s', klasstype)
local specificKlass = {
__typename = specifictype,
}
setmetatable(specificKlass, { __index = __TableUtil__Cell })
function specificKlass.new(name, dataIndex, opts)
local obj = __TableUtil__Cell.__new(specifictype, name, opts)
obj.__cell__render = obj.render
obj.dataIndex = dataIndex
if propNames and opts then
for _, name in ipairs(propNames) do
obj[name] = opts[name]
end
end
return setmetatable(obj, { __index = specificKlass })
end
specificKlass.render = renderFunction
return specificKlass
end
-- =================
-- func: createTable
-- =================
function tableutil.createTable(dataset, metadata, opts)
local tbl = mw.html.create('table')
:addClass('numbertable')
:addClass('sortable')
:addClass('st')
:addClass('wikitable')
if opts and type(opts.tableClass) == 'string' then
tbl:addClass(opts.tableClass)
end
-- Build header
local headerRow = tbl:tag('tr'):addClass('row-sticky')
local sortIndex = 0
local isDesc = false
for _, m in ipairs(metadata) do
if m.typename == tableutil.RankCell.__typename then
sortIndex = m.dataIndex
isDesc = m:isDescending()
end
-- Render header
m:renderHeader(headerRow)
end
-- Sort data
if sortIndex ~= 0 then
local sortFunction
if isDesc then
sortFunction = function(a, b)
return a[sortIndex] > b[sortIndex]
end
else
sortFunction = function(a, b)
return a[sortIndex] < b[sortIndex]
end
end
table.sort(dataset, sortFunction)
end
-- Preprocess data
local datainfo = {}
for _, ary in ipairs(dataset) do
for key, d in pairs(ary) do
if type(d) == 'number' and d ~= math.huge then
if not datainfo[key] then
datainfo[key] = {
minValue = d,
maxValue = d,
}
else
if datainfo[key].minValue > d then
datainfo[key].minValue = d
end
if datainfo[key].maxValue < d then
datainfo[key].maxValue = d
end
end
end
end
end
-- Reset context
for _, m in ipairs(metadata) do
-- Reset context for building process
m:resetContext(datainfo)
end
-- Build cell
for i, d in ipairs(dataset) do
local row = tbl:tag('tr')
for k, m in ipairs(metadata) do
m:render(row, d, i, datainfo)
end
end
-- Build footer
local footerRow = tbl:tag('tr'):addClass('sortbottom')
for _, m in ipairs(metadata) do
-- Render footer
m:renderFooter(footerRow)
end
return tbl
end
-- =================
-- test: Simple test
-- =================
function tableutil.__test()
local metadata = {
tableutil.RankCell.new('', 1),
tableutil.ValueCell.new('Value', 1),
tableutil.LineCell.new('Line', 1, { cellClass = 'st-graph' }),
tableutil.LineCell.new('LineGradient', 1, { cellClass = 'st-graph', colorStops = { '#F8B3BC', '#F26D7D' }, height = 1.4 }),
tableutil.LineValueCell.new('LineValue', 2, { cellClass = 'st-graph st-textshadow' }),
tableutil.LineCell.new('Line (Range)', 1, { cellClass = 'st-graph', startIndex = 1, endIndex = 2 }),
tableutil.LineCell.new('Line (Range & Sub)', 1, { cellClass = 'st-graph', startIndex = 1, endIndex = 2, subStartIndex = 1, subEndIndex = 3 }),
}
local node = tableutil.createTable({{ 45, 110, 140 }, { 40, 60, 90 }, { 40, 120, 190 }, { 50, 90, 110 }}, metadata)
return tostring(node)
end
return tableutil