Module:Breaking row

local p = {} p.row = function( f ) local args = require( Module:ProcessArgs ).norm local getDplVar = function( var ) local val = f:callParserFunction( '#dplvar', 'breaking ' .. var ) if val == '' then val = false end return val end local dplVars = {} local setDplVar = function( var, val ) table.insert( dplVars, 'breaking ' .. var ) table.insert( dplVars, val or '1' ) end local rows = {} local tableParts = {} local horizontal if args.horizontal or args[1]:match( ';' ) then horizontal = true end local showTool = true local showShears = true local showSword = true local header, sortable, simple if horizontal or not getDplVar( 'header' ) then if args.hidetool or horizontal and not args[2] then showTool = false setDplVar( 'hidetool' ) end if args.hideshears or horizontal and not args.shears then showShears = false setDplVar( 'hideshears' ) end if args.hidesword or horizontal and not args.sword then showSword = false setDplVar( 'hidesword' ) end sortable = not horizontal and args.sort if sortable then setDplVar( 'sortable' ) end simple = args.simple if simple and not horizontal then setDplVar( 'simple' ) end local tableClasses = { 'wikitable' } if sortable then table.insert( tableClasses, 'sortable' ) end table.insert( rows, ' {| class="' .. table.concat( tableClasses, ' ' ) .. '" style="text-align:center"' ) local sortType = '' if sortable then sortType = 'data-sort-type="number"' end local rowspan = '' if not horizontal then rowspan = 'rowspan="2" ' end header = { '! ' .. rowspan .. ' | Block' }		if not simple then table.insert( header, '! ' .. rowspan .. sortType .. ' | Hardness' ) if showTool then table.insert( header, '! ' .. rowspan .. ' | Tool' ) end end local toolColumns = {} if showTool then toolColumns = { 'Wooden', 'Stone', 'Iron', 'Diamond', 'Golden' } end table.insert(			toolColumns, 1,			'Hand '		) if not simple then if showShears then table.insert( toolColumns, 'Shears' ) end if showSword then table.insert( toolColumns, 'Sword' ) end end if not horizontal then table.insert( header, '! colspan="' .. #toolColumns .. '" | Breaking time (seconds)' ) table.insert( header, '|-' ) end for _, tool in ipairs( toolColumns ) do table.insert( header, '! ' .. sortType .. ' | ' .. tool ) end if not horizontal then header = table.concat( header, '\n' ) setDplVar( 'header', header ) end table.insert( tableParts, header ) else showTool = not getDplVar( 'hidetool' ) showShears = not getDplVar( 'hideshears' ) showSword = not getDplVar( 'hidesword' ) sortable = getDplVar( 'sortable' ) simple = getDplVar( 'simple' ) end local sprite = require( Module:Sprite ) local hardness = require( Module:Block value ).value local fillCells = function( cellsTable, text, num ) for i = 1, num do			table.insert( cellsTable, text ) end end local materialGrade = { Any = 0, Wooden = 1, Wood = 1, Golden = 1, Stone = 2, Iron = 3, Diamond = 4, None = 5 }	local materialSpeed = { None = 1, Any = 1, Wooden = 2, Wood = 2, Stone = 4, Iron = 6, Diamond = 8, Golden = 12 }	local insertBlock = function( blockArgs ) local cells = {} local blocks = mw.text.split( blockArgs[1], '%s*,%s*' ) local hardnessVal = tonumber( hardness{ blocks[1], type = 'hardness' } ) if not hardnessVal then hardnessVal = '?' end local unbreakable if hardnessVal == -1 or blockArgs.liquid then unbreakable = true end local blockSprites = {} local links = mw.text.split( blockArgs.link or '', '%s*,%s*' ) local ids = mw.text.split( blockArgs.sprite or '', '%s*,%s*' ) local items = mw.text.split( blockArgs.item or '', '%s*,%s*' ) for i, block in ipairs( blocks ) do			local link if not links[i] and links[1] ~= '' then link = links[1] elseif links[i] ~= '' then link = links[i] end local id			if not ids[i] and ids[1] ~= '' then id = ids[1] elseif ids[i] ~= '' then id = ids[i] end local blockSpriteArgs = { settings = 'BlockSprite', block, text = block:gsub( args.textTrim or , ), link = link, id = id			} if items[i] == '1' or not items[i] and items[1] == '1' then blockSpriteArgs.settings = 'ItemSprite' end table.insert( blockSprites, sprite.link( blockSpriteArgs ) ) end table.insert( cells,			'! style="text-align:left" | ' .. table.concat( blockSprites, ' ' ) .. ( blockArgs.note or '' )		) local tool = mw.text.trim( simple and 'Tool' or blockArgs[2] or 'Any' ):gsub( '^%l', string.upper ) local material = mw.text.trim( simple and blockArgs[2] or blockArgs[3] or 'Any' ):gsub( '^%l', string.upper ) if tool == 'None' then material = tool end if not simple then local hardnessText = hardnessVal if hardnessVal == -1 then hardnessText = ( sortable and 'data-sort-value="999" | ' or '' ) .. '∞'			end table.insert( cells, '|' .. hardnessText ) if showTool then local toolCell = '—' if tool ~= 'Any' and tool ~= 'None' then if material == 'Wood' then material = 'Wooden' end local toolName = ( material ~= 'Any' and material .. ' ' or '' ) .. tool toolCell = ( sortable and 'data-sort-value="' .. toolName .. '" |' or '' ) .. sprite.sprite{ settings = 'ItemSprite', ( material == 'Any' and 'Wooden ' or '' ) .. toolName, title = toolName, link = tool }				end table.insert( cells, '|' .. toolCell ) end end local choices = {} local getChoice = function( choice, text ) if not choices[choice] then choices[choice] = f:expandTemplate{ title = 'Table Choice', args = { choice, '' } } end return choices[choice] .. text end if hardnessVal == '?' then fillCells( cells, '|?', 6 ) else local round = function( num, idp ) idp = idp or 0 local mult = 10 ^ ( idp < 0 and 0 or idp ) return math.floor( num * mult + 0.5 ) / mult end if unbreakable then table.insert( cells, '| ' .. ( sortable and 'data-sort-value="999" ' or '' ) .. getChoice( 'no', '∞' ) ) if showTool then fillCells( cells, '|—', 5 ) end else local drop = 'yes' if blockArgs.drop == '0' then drop = 'partial' end local requiredLevel = unbreakable and 999 or materialGrade[material] local insertMaterialCell = function( material ) local willDrop = drop if materialGrade[material] < requiredLevel then willDrop = 'no' end local breakTime = hardnessVal / materialSpeed[material] * ( willDrop == 'no' and 5 or 1.5 ) local precision = 5 - #tostring( round( breakTime ) ) breakTime = round( breakTime, precision ) table.insert( cells, '|' .. getChoice( willDrop, breakTime ) ) end if not showTool or tool == 'Any' or tool == 'None' then insertMaterialCell( 'Any' ) if showTool then fillCells( cells, '|—', 5 ) end else for _, material in ipairs{ 'Any', 'Wooden', 'Stone', 'Iron', 'Diamond', 'Golden' } do						insertMaterialCell( material ) end end end if not simple and ( showShears or showSword ) then local tools = {} if showShears then table.insert( tools, 'Shears' ) end if showSword then table.insert( tools, 'Sword' ) end if hardnessVal == '?' then fillCells( cells, '|?', #tools ) else local toolSpeed = { Shears = 15, Sword = 1.5 }					if blocks[1] == 'Wool' then toolSpeed.Shears = 5 elseif blocks[1] == 'Cobweb' then toolSpeed.Sword = 15 end for _, tool in ipairs( tools ) do						local toolDrop = blockArgs[mw.ustring.lower( tool )] if not toolDrop then table.insert( cells, '|—' ) else local willDrop = 'yes' if toolDrop == '0' then willDrop = 'partial' end local breakTime = hardnessVal / toolSpeed[tool] * 1.5 local precision = 5 - #tostring( round( breakTime ) ) breakTime = round( breakTime, precision ) table.insert( cells, '|' .. getChoice( willDrop, breakTime ) ) end end end end end if not horizontal then cells = table.concat( cells, '\n' ) end table.insert( tableParts, cells ) end if horizontal then local blocksArgs = {} for _, arg in ipairs{ 1, 'note', 'sprite', 'link', 'item', 'drop', 2, 3, 'shears', 'sword' } do			if args[arg] then local col = 0 for colVal in mw.text.gsplit( args[arg], '%s*;%s*' ) do					col = col + 1 if colVal ~= '' then if not blocksArgs[col] then blocksArgs[col] = {} end blocksArgs[col][arg] = colVal end end end end for _, block in ipairs( blocksArgs ) do			insertBlock( block ) end local columns = #tableParts for row = 1, #tableParts[1] do			local cells = {} for col = 1, columns do				table.insert( cells, tableParts[col][row] ) end table.insert( rows, table.concat( cells, '\n' ) ) end -- Insert breaking time header after block row when simple, or after tool or hardness row when not table.insert( rows, simple and 3 or showTool and 5 or 4, '! colspan="' .. columns + 1 .. '" | Breaking time (seconds)' ) else insertBlock( args ) for _, row in ipairs( tableParts ) do			table.insert( rows, row ) end end table.insert( rows, '' ) if args.foot or horizontal then if args.foot == '2' then table.insert( rows, header or getDplVar( 'header' ) ) end table.insert( rows, '|}' ) if not horizontal then f:callParserFunction( '#dplvar:set',				'breaking header', ,				'breaking hidetool', ,				'breaking hideshears', ,				'breaking hidesword', ,				'breaking simple', ,				'breaking sortable', 			) end elseif #dplVars > 0 then f:callParserFunction( '#dplvar:set', dplVars ) end return table.concat( rows, '\n|-\n' ) end return p