模組:沙盒/WhitePhosphorus/randiv

local p = {}
local vacant = {}
local t_width, t_height
local step = 5

local function init(frame)
	t_height, t_width = frame["height"] or 600, frame["width"] or 800
	t_height, t_width = t_height / step, t_width / step
	for i = 1, t_height do
		vacant[i] = {}
		for j = 1, t_width do
			vacant[i][j] = 1
		end
	end
end

local function largest_block()
	local tmp = {vacant[1]}
	table.insert(tmp[1], 0)
	for i = 2, t_height do
		tmp[i] = vacant[i]
		for j = 1, t_width do
			tmp[i][j] = tmp[i][j] ~= 0 and tmp[i-1][j] + 1 or 0
		end
		table.insert(tmp[i], 0)
   	end
	
	local max_area, max_top, max_left, max_height, max_width = 0
	for i = 1, t_height do
		local stack = {}
		for j = 1, t_width+1 do
			while next(stack) ~= nil and tmp[i][ stack[#stack] ] > tmp[i][j] do
				local s_top = table.remove(stack)
				local left = next(stack) == nil and 1 or stack[#stack]+1
				local area = (j - left) * tmp[i][s_top]
				if area > max_area then
					max_area, max_top, max_left, max_height, max_width = 
					area, i-tmp[i][s_top], left-1, tmp[i][s_top], j-left
				end
			end
			table.insert(stack, j)
		end
	end

	return max_top, max_left, max_height, max_width
end

local function random_block()
	max_top, max_left, max_height, max_width = largest_block()
	left, top = math.random(0, max_width-1), math.random(0, max_height-1)
	width, height = math.random(1, max_width-left), math.random(1, max_height-top)
	left, top = left + max_left, top + max_top
	
	for i = top+1, top+height do
		for j = left+1, left+width do
			vacant[i][j] = 0
		end
	end

	return top * step, left * step, height * step, width * step
end

local function gen_html(id, content, top, left, height, width)
	local hidden = mw.html.create('div')
		:attr('id', 'mw-customcollapsible-' .. id)
		:addClass('mw-collapsible mw-collapsed')
		:css({['position'] = 'absolute',
			  ['background-color'] = 'rgba(255,255,255,.8)',
			  ['left'] = '0px', ['top'] = '0px',
			  ['padding'] = '0 10px',
			  ['width'] = t_width * step .. 'px',
			  ['height'] = t_height * step .. 'px',
			  ['z-index'] = '999', ['text-align'] = 'left',
			  ['display'] = 'none', ['overflow'] = 'scroll'})
		:node(mw.html.create('span')
				:addClass('mw-customtoggle-' .. id)
				:css('cursor', 'pointer')
				:wikitext("'''×'''\n")
				:node(content)
				:done())
		:done()
	local block = mw.html.create('div')
		:css({['position'] = 'absolute',
			  ['left'] = left .. 'px', ['top'] = top .. 'px',
			  ['width'] = width .. 'px', ['height'] = height .. 'px'})
		:addClass('mw-customtoggle-' .. id)
		:done()
	return tostring(hidden) .. tostring(block)
end

function p.main(frame)
	math.randomseed(os.time())
	init(frame)
	html_t = {}
	for k, v in ipairs(frame.args) do
		top, left, height, width = random_block()
		table.insert(html_t, gen_html(k, v, top, left, height, width))
	end
	return table.concat(html_t)
end

return p