Module:Chessboard/sandbox

local p = {}

local cfg, nrows, ncols

local function innerboard(args, size, rev)
	pattern = cfg.pattern or '%w%w'
	local root = mw.html.create('div')
	root:addClass('chess-pieces notheme')
		:css('position', 'relative')
		:wikitext(cfg.image_board(size))
	
	for trow = 1,nrows do
		local row = rev and trow or ( 1 + nrows - trow )
		for tcol = 1,ncols do
			local col = rev and ( 1 + ncols - tcol ) or tcol
			local piece = args[ncols * ( nrows - row ) + col + 2] or ''
			if piece:match( pattern ) then
				local img = cfg.image_square(piece:match(pattern), row, col, size )
				root:tag('div')
					:css('top', tostring(( trow - 1 ) * size) .. 'px')
					:css('left', tostring(( tcol - 1 ) * size) .. 'px')
					:wikitext(img)
			end
		end
	end

	return tostring(root)
end

function chessboard(args, size, rev, letters, numbers, header, footer, align, clear)
	function letters_row( rev, num_lt, num_rt )
		local letters = cfg.letters()
		local root = mw.html.create('')
		if num_lt then
			root:tag('td')
		end
		for k = 1,ncols do
			root:tag('td')
				:css('height', '18px')
				:css('width', size .. 'px')
				:wikitext(rev and letters[1+ncols-k] or letters[k])
		end
		if num_rt then
			root:tag('td')
		end
		return tostring(root)
	end
	
	local letters_top = letters:match( 'both' ) or letters:match( 'top' )
	local letters_bottom = letters:match( 'both' ) or letters:match( 'bottom' )
	local numbers_left = numbers:match( 'both' ) or numbers:match( 'left' )
	local numbers_right = numbers:match( 'both' ) or numbers:match( 'right' )
	local width = ncols * size + 2
	if ( numbers_left ) then width = width + 18 end
	if ( numbers_right ) then width = width + 18 end

	local root = mw.html.create('div')
		:addClass('chessboard')
		:addClass('thumb')
		:addClass('noviewer')
		:addClass(align)
	if( header and header ~= '' ) then
		root:tag('div')
		:addClass('center')
		:css('line-height', '130%')
		:css('margin', '0 auto')
		:css('max-width', (width + ncols) .. 'px')
		:wikitext(header)
	end
	local div = root:tag('div')
		:addClass('thumbinner')
		:css('width', width .. 'px')
	local b = div:tag('table')
		:attr('cellpadding', '0')
		:attr('cellspacing', '0')

	if ( letters_top ) then
		b:tag('tr')
			:wikitext(letters_row( rev, numbers_left, numbers_right ))
	end
	local tablerow = b:tag('tr')
	if ( numbers_left ) then 
		tablerow:tag('td')
			:css('width', '18px')
			:css('height', size .. 'px')
			:wikitext(rev and 1 or nrows) 
	end
	local td = tablerow:tag('td')
		:attr('colspan', ncols)
		:attr('rowspan', nrows)
		:wikitext(innerboard(args, size, rev))
	
	if ( numbers_right ) then 
		tablerow:tag('td')
			:css('width', '18px')
			:css('height', size .. 'px')
			:wikitext(rev and 1 or nrows) 
	end
	if ( numbers_left or numbers_right ) then
		for trow = 2, nrows do
			local idx = rev and trow or ( 1 + nrows - trow )
			tablerow = b:tag('tr')
			if ( numbers_left ) then 
				tablerow:tag('td')
					:css('height', size .. 'px')
					:wikitext(idx)
			end
			if ( numbers_right ) then 
				tablerow:tag('td')
					:css('height', size .. 'px')
					:wikitext(idx)
			end
		end
	end
	if ( letters_bottom ) then
		b:tag('tr')
			:wikitext(letters_row( rev, numbers_left, numbers_right ))
	end

	if footer and mw.text.trim(footer)~='' then
		div:tag('div')
			:addClass('thumbcaption')
			:wikitext(footer)
	end

	return tostring(root) ..
		mw.getCurrentFrame():extensionTag( 'templatestyles', '', { src = 'Module:Chessboard/sandbox/styles.css' } )
end

function convertFenToArgs( fen )
	-- converts FEN notation to 64 entry array of positions, offset by 2
	local res = { ' ', ' ' }
	-- Loop over rows, which are delimited by /
	for srow in string.gmatch( "/" .. fen, "/%w+" ) do
		-- Loop over all letters and numbers in the row
		for piece in srow:gmatch( "%w" ) do
			if piece:match( "%d" ) then -- if a digit
				for k=1,piece do
					table.insert(res,' ')
				end
			else -- not a digit
				local color = piece:match( '%u' ) and 'l' or 'd'
				piece = piece:lower()
				table.insert( res, piece .. color )
			end
		end
	end

	return res
end

function convertArgsToFen( args, offset )
	function nullOrWhitespace( s ) return not s or s:match( '^%s*(.-)%s*$' ) == '' end
	function piece( s ) 
		return nullOrWhitespace( s ) and 1
		or s:gsub( '%s*(%a)(%a)%s*', function( a, b ) return b == 'l' and a:upper() or a end )
	end
	
	local res = ''
	offset = offset or 0
	for row = 1, 8 do
		for file = 1, 8 do
			res = res .. piece( args[8*(row - 1) + file + offset] )
		end
		if row < 8 then res = res .. '/' end
	end
	return mw.ustring.gsub(res, '1+', function( s ) return #s end )
end

function p.board(frame)
	local args = frame.args
	local pargs = frame:getParent().args
	local style = args.style or pargs.style or 'Chess'
	cfg = require('Module:Chessboard/' .. style .. '/sandbox')
	nrows, ncols = cfg.dims()
	
	local size = args.size or pargs.size or '26'
	local reverse = ( args.reverse or pargs.reverse or '' ):lower() == "true"
	local letters = ( args.letters or pargs.letters or 'both' ):lower() 
	local numbers = ( args.numbers or pargs.numbers or 'both' ):lower() 
	local header = args[2] or pargs[2] or ''
	local footer = args[nrows*ncols + 3] or pargs[nrows*ncols + 3] or ''
	local align = ( args[1] or pargs[1] or 'floatright' ):lower()
	local clear = args.clear or pargs.clear or ( align:match('floatright') and 'right' ) or 'none'
	local fen = args.fen or pargs.fen
	local pgn = args.pgn or pargs.pgn

	size = mw.ustring.match( size, '[%d]+' ) or '26' -- remove px from size
	if (pgn) then
		local pgnModule = require('Module:Pgn')
		metadata, moves = pgnModule.main(pgn)
		fen = moves[#moves]
	end
	if (fen) then
		align = args.align or pargs.align or 'floatright'
		clear = args.clear or pargs.clear or ( align:match('floatright') and 'right' ) or 'none'
		header = args.header or pargs.header or ''
		footer = args.footer or pargs.footer or ''
		return chessboard( convertFenToArgs( fen ), size, reverse, letters, numbers, header, footer, align, clear )
	end
	if args[3] then
		return chessboard(args, size, reverse, letters, numbers, header, footer, align, clear)
	else
		return chessboard(pargs, size, reverse, letters, numbers, header, footer, align, clear)
	end
end

-- Generates an HTML board of a specific size
function p.htmlBoard(frame)
	local args = require("Module:Arguments").getArgs(frame)
	local width = tonumber(args.width or '8')
	local light = args.light or '#FFFFFF00'
	local dark = args.dark or '#808080'
	
	local tbl = mw.html.create('table')
	tbl:css('table-layout', 'fixed'):css('border', 'none'):css('border-collapse', 'collapse'):css('width', '30%'):css('aspect-ratio', '1 / 1'):css('cellspacing', '0'):css('cellpadding', '0'):css('margin:0px')
	local rank = width + 2
	local file = 1
	local numberedarg = 1
	local alignment = args[numberedarg] or ''
	local root = mw.html.create('div')
		:addClass('chessboard')
		:addClass('thumb')
		:addClass('noviewer')
		:addClass(alignment)
	numberedarg = numberedarg + 1
	local title = args[numberedarg] or ''
	numberedarg = numberedarg + 1
	while rank > 0 do
		local row = tbl:tag('tr')
		while file <= width + 2 do
			if (rank == 1 or rank == width + 2) and (file == 1 or file == width + 2) then
				row
					:tag('th')
					:css('min-width', (1 / (width + 2) * 100) .. "%")
					:css('max-width', (1 / (width + 2) * 100) .. "%")
					:css('height', 'auto')
					:css('aspect-ratio', '1 / 1')
					:wikitext('')
			elseif (rank == 1 or rank == width + 2) then
				-- get letter corresponding to file
				local alphabet = "abcdefghijklmnopqrstuvwxyz"
				local fileLetter = alphabet:sub(math.mod(file - 2, 26) + 1, math.mod(file - 2, 26) + 1)
				local toadd = ''
				for n=1, math.ceil(file / 26), 1 do
					toadd = toadd .. fileLetter
				end
				row
					:tag('th')
					:css('min-width', (1 / (width + 2) * 100) .. "%")
					:css('max-width', (1 / (width + 2) * 100) .. "%")
					:css('overflow', 'hidden')
					:css('aspect-ratio', '1 / 1')
					:wikitext(toadd)
					:done()
			elseif (file == 1 or file == width + 2) then
				row
					:tag('th')
					:css('min-width', (1 / (width + 2) * 100) .. "%")
					:css('max-width', (1 / (width + 2) * 100) .. "%")
					:css('overflow', 'hidden')
					:css('aspect-ratio', '1 / 1')
					:wikitext(rank - 1)
			else
				-- get the HTML chess piece specified for this square
				-- currently supports standard chess set
				-- @todo specify appropriate font especially one that supports fairy chess pieces
				local pieceArg = args[numberedarg] or ''
				local pieceLetter = pieceArg:sub(1, 1)
				local pieceColor = pieceArg:sub(2, 2)
				local pieceDec = 9811
				if pieceLetter == "p" then
					pieceDec = pieceDec + 6
				elseif pieceLetter == "n" then
					pieceDec = pieceDec + 5
				elseif pieceLetter == "b" then
					pieceDec = pieceDec + 4
				elseif pieceLetter == "r" then
					pieceDec = pieceDec + 3
				elseif pieceLetter == "q" then
					pieceDec = pieceDec + 2
				elseif pieceLetter == "k" then
					pieceDec = pieceDec + 1
				end
				
				if (pieceDec > 9811 and pieceColor == "d") then
					pieceDec = pieceDec + 6
				end
				-- color the chessboard appropriately
				if (math.mod(file, 2) == math.mod(rank, 2)) then
					row
						:tag('td')
						:css('background-color', dark)
						:css('color', 'inherit')
						:css('min-width', (1 / (width + 2) * 100) .. "%")
						:css('max-width', (1 / (width + 2) * 100) .. "%")
						:css('overflow', 'hidden')
						:css('aspect-ratio', '1 / 1')
						:css('border-width', '0px')
						:css('font-family', 'monospace')
						:wikitext('<div style="display: flex;justify-content: center;align-items: center;font-size: 2em;">' .. (pieceDec == 9811 and ' ' or '&#' .. pieceDec .. ';&#xFE0E;') .. '</div>')
				else
					row
						:tag('td')
						:css('background-color', light)
						:css('color', 'inherit')
						:css('min-width', (1 / (width + 2) * 100) .. "%")
						:css('max-width', (1 / (width + 2) * 100) .. "%")
						:css('overflow', 'hidden')
						:css('aspect-ratio', '1 / 1')
						:css('border-width', '0px')
						:css('font-family', 'monospace')
						:wikitext('<div style="display: flex;justify-content: center;align-items: center;font-size: 2em;">' .. (pieceDec == 9811 and ' ' or '&#' .. pieceDec .. ';&#xFE0E;') .. '</div>')
				end
				numberedarg = numberedarg + 1
			end
			file = file + 1
		end
		file = 1
		rank = rank - 1
	end
	local caption = args[numberedarg]
	root
		:tag('div')
		:addClass('center')
		:wikitext(title)
		:done()
		:wikitext(tostring(tbl))
		:tag('div')
		:addClass('thumbcaption')
		:wikitext(caption)
		:done()
	return root
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.