🌟現在、鉄壁 鉄壁ヘッドショットには対応済みです。
鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。

「モジュール:Utility/TableUtil」の版間の差分

提供:Apex Data
ナビゲーションに移動 検索に移動
(LineCellにgridの実装を追加(自動で幅を調整できる改善含む))
(フッターの軸表示機能を実装)
38行目: 38行目:
if type(opts.cellClass) == 'string' then
if type(opts.cellClass) == 'string' then
obj.cellClass = opts.cellClass
obj.cellClass = opts.cellClass
end
if type(opts.footerClass) == 'string' then
obj.footerClass = opts.footerClass
end
end
83行目: 87行目:
end
end
return headerCell
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
end


195行目: 215行目:
function __TableUtil__LineCell.__new(typename, name, dataIndex, opts)
function __TableUtil__LineCell.__new(typename, name, dataIndex, opts)
local obj = __TableUtil__Cell.__new(typename, name, opts)
local obj = __TableUtil__Cell.__new(typename, name, opts)
obj.__cell__render = obj.render
obj.__cell__render       = obj.render
obj.__cell__renderFooter = obj.renderFooter
obj.dataIndex = dataIndex
obj.dataIndex = dataIndex
if type(opts) == 'table' then
if type(opts) == 'table' then
240行目: 261行目:
self._ticks = scale:ticks(self.preferredGridCount)
self._ticks = scale:ticks(self.preferredGridCount)
end
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')
list:tag('li'):wikitext(self._scale.domain[1])
for _, tick in ipairs(self._ticks) do
list:tag('li'):wikitext(tick)
end
end
return footerCell
end
end


320行目: 358行目:
function valueKlass.new(name, dataIndex, opts)
function valueKlass.new(name, dataIndex, opts)
local obj = superklass.__new(valuetype, name, dataIndex, opts)
local obj = superklass.__new(valuetype, name, dataIndex, opts)
obj.__super__render = obj.render
obj.__super__render       = obj.render
obj.__super__renderHeader = obj.renderHeader
obj.__super__renderFooter = obj.renderFooter
obj.mixinValue = true
obj.mixinValue = true
if type(opts) == 'table' then
if type(opts) == 'table' then
442行目: 482行目:
m:render(row, d, i, datainfo)
m:render(row, d, i, datainfo)
end
end
end
-- Build footer
local footerRow = tbl:tag('tr'):addClass('sortbottom')
for _, m in ipairs(metadata) do
-- Render footer
m:renderFooter(footerRow)
end
end



2021年8月21日 (土) 12:30時点における版

このモジュールについての説明文ページを モジュール: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 })

-- [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.colorStops         = opts.colorStops         or '#A7D7F9'
		if opts.gridEnabled then
			obj.gridEnabled    = opts.gridEnabled
		else
			obj.gridEnabled    = true
		end
		obj.height             = opts.height             or 1.2
		obj.minimumValue       = opts.minimumValue       or 0
		obj.maximumRate        = opts.maximumRate        or 1.05
		obj.preferredGridCount = opts.preferredGridCount or 4
	else
		obj.colorStops         = '#A7D7F9'
		obj.gridEnabled        = true
		obj.height             = 1.2
		obj.minimumValue       = 0
		obj.maximumRate        = 1.05
		obj.preferredGridCount = 4
	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 target = datainfo[self.dataIndex]
	local scale = scale.LinearScale.new()
		:setClamp(true)
		:setDomain({ self.minimumValue, self.maximumRate * target.maxValue })
		:nice(self.preferredGridCount)
	self._scale = scale
	if self.gridEnabled then
		self._ticks = scale:ticks(self.preferredGridCount)
	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')
		list:tag('li'):wikitext(self._scale.domain[1])
		for _, tick in ipairs(self._ticks) do
			list:tag('li'):wikitext(tick)
		end
	end
	return footerCell
end

-- [Function] Render
function __TableUtil__LineCell:render(row, dataset, i, datainfo)
	local gradientFormat
	if type(self.colorStops) == 'table' then
		if self.mixinValue then
			gradientFormat = function(percentage, value)
				percentage = 0.001 * aw.round(1000 * percentage)
				return string.format(
					'linear-gradient(to right,transparent,%s %s%%,%s %s%%,transparent %s%%)',
					self.colorStops[1],
					percentage,
					self.colorStops[2],
					percentage,
					percentage)
			end
		else
			gradientFormat = function(percentage, value)
				percentage = 0.001 * aw.round(1000 * percentage)
				return string.format(
					'linear-gradient(to right,transparent,%s %s%%,%s %s%%,transparent %s%%)!important',
					self.colorStops[1],
					percentage,
					self.colorStops[2],
					percentage,
					percentage)
			end
		end
	else
		if self.mixinValue then
			gradientFormat = function(percentage, value)
				percentage = 0.001 * aw.round(1000 * percentage)
				return string.format(
					'linear-gradient(to right,%s %s%%,transparent %s%%)',
					self.colorStops,
					percentage,
					percentage)
			end
		else
			gradientFormat = function(percentage, value)
				percentage = 0.001 * aw.round(1000 * percentage)
				return string.format(
					'linear-gradient(to right,%s %s%%,transparent %s%%)!important',
					self.colorStops,
					percentage,
					percentage)
			end
		end
	end
	
	local value = dataset[self.dataIndex]
	local percentage = self._scale:scale(value)
	local cell = self:__cell__render(row, dataset, i, datainfo)
		:addClass('st-line')
		:addClass(string.format('st-line-h%d', 10 * self.height))
	if self.gridEnabled then
		cell:addClass('st-grid')
			:addClass(string.format('st-grid-%d', #self._ticks + 1))
	end
	cell:attr('data-sort-value', value)
		:css('background-image', gradientFormat(percentage, value))
	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' }),
	}
	local node = tableutil.createTable({{ 45, 110 }, { 40, 60 }, { 40, 120 }, { 50, 90 }}, metadata)
	return tostring(node)
end

return tableutil