Module:ChessBowserPrototype

Module documentation
local function build_notation_span(notation, plynum, current)
	local class = plynum and "pgn-movelink" or "pgn-steplink"
	if current then class = class .. " pgn-current-move" end
	local data = plynum and 'data-ply=' .. plynum or ''
	notation = mw.ustring.gsub(notation, '-', '‑') -- replace hyphens with non-breaלing hyphens, so results (like 1-0) and castling won't break
	return string.format('<span class="%s"%s>%s</span>', class, data, notation)
end

local function move_of(notation) 
	if not notation then return end
	local move = tonumber(string.sub(notation, 1, -2))
	if not move then return end
	local col = string.sub(notation, -1)
	local extra = 0
	if col == 'l' then extra = 1 elseif col ~= 'd' then return end
	return move * 2 - extra
end

local function piecediv( piece, row, file, res )
	local color = piece:match( '%u' ) and 'l' or 'd'
	piece = piece:lower()
	table.insert( res, string.format('<div class="pgn-chessPiece pgn-ptype-color-%s%s pgn-prow-%d pgn-pfile-%d"></div>', piece, color, 7-row, file) )
end
	
local function pieces_of_fen(fen)
	local result = {}
	local row = 0
	if not fen then return end
	for srow in string.gmatch("/" .. fen, "/%w+") do
		local file = 0
		for piece in srow:gmatch( "%w" ) do -- if a digit, increment "file" by the digit. else, add the piece _and_ increment file by 1
			file = file + ( piece:match("%d") or piecediv( piece, row, file, result ) or 1 )
		end
		row = row + 1
	end
	return result
end

local function demo(frame)
	local pgn = frame.args.pgn
	if not pgn then error('no valid pgn found') end
	local parser = require('Module:Parse-pgn')
	local fens, plys, notations, metadata = parser.parsePgn(pgn)
	local display_board = move_of(frame.args.display) or #fens - 1
	local passToScript = {
		fen = fens[1],
		plys = plys,
		metadata = metadata,
		display = display_board,
	}
	local baseTemp = [[
	<div class="pgnviewer" data-chess = ' $passToScript '>
	<div style="text-align:center">
	<table class="mw-collapsible mw-collapsed pgn-metadata-table" style="margin:auto;text-align:left;">
		<tr>
		<th colspan="2" style="text-align:center;">Game Details</th>
		</tr>
		$metadataRows
		</table>
	<div class="pgn-notations" style="scroll-behavior:smooth;">
		$notations
 	</div>     
 	<div class="pgn-board-div" style="width: 348px; height: 348px;">
         <div class="pgn-board-img" style="position: absolute; left: 20px; top: 20px; width: 308px; height: 308px;">
         <div class="pgn-chessPiece pgn-ply-source"></div>
         $pieces
         </div>
		<div class="pgn-row-legend pgn-row-left" style="top:20px;height:308px;width:20px;">$rowLegends</div>
		<div class="pgn-row-legend pgn-row-right" style="top:20px;left:328px;height:308px;width:20px;">$rowLegends</div>
		<div class="pgn-file-legend pgn-file-top" style="left:20px;width:308px;height:20px;">$fileLegends</div>
		<div class="pgn-file-legend pgn-file-bottom" style="left:20px;top:328px;width:308px;height:20px;">$fileLegends</div>

      </div>
      <div class="pgn-controls" style="text-align: center;">
         <div class="pgn-image-button pgn-image-button-off pgn-button-tostart" title="Go to initial position"></div>
         <div class="pgn-image-button pgn-image-button-off pgn-button-retreat" title="Previous"></div>
         <div class="pgn-image-button pgn-image-button-off pgn-button-slower" title="Slower (autoplay)"></div>
         <div class="pgn-image-button pgn-image-button-off pgn-button-play" title="Autoplay/Pause"></div>
         <div class="pgn-image-button pgn-image-button-off pgn-button-faster" title="Faster (autoplay)"></div>
         <div class="pgn-image-button pgn-image-button-off pgn-button-advance" title="Next"></div>
         <div class="pgn-image-button pgn-image-button-off pgn-button-toend" title="Go to final position"></div>
         <div class="pgn-image-button pgn-image-button-off pgn-button-flip" title="Flip to view board from Black or White poit of view"></div>
         $comments
      </div>
      <div class="pgn-nojs-message" style="text-align: center;">
To see the game interactively, enable Javascript for your browser
      </div>
	</div>
	</div>
]]
	local file_letters = { [0] = "a", [1] = "b", [2] = "c", [3] = "d", [4] = "e", [5] = "f", [6] = "g", [7] = "h" }
	local rowlegends, filelegends = '', ''
	for r = 0 ,7 do
		rowlegends = string.format('%s<span class="pgn-row-legend pgn-prow-%d">%d</span>', rowlegends, r, r + 1)
		filelegends = string.format('%s<span class="pgn-file-legend pgn-pfile-%d">%s</span>', filelegends, r, file_letters[r]) 
	end
	
	local notation_spans = { build_notation_span('⚃', 0) }
	for i, notation in ipairs(notations) do
		if i % 2 == 1 then
			table.insert(notation_spans, build_notation_span((i + 1) / 2 .. '.'))
		end
		table.insert(notation_spans, build_notation_span(notation, i, i == display_board))
	end
	local pieces = pieces_of_fen(fens[display_board + 1])
	local metadataRows = {}
	mw.logObject(metadata)
	for mdt, mdv in pairs(metadata) do
		if mdt and mdv then
			mw.log('token: ', mdt, ' value: ', mdv)
			table.insert(metadataRows, '<tr><td>' .. mdt .. '</td><td>' .. mdv .. '</td></tr>')
		end
	end
	mw.logObject(metadataRows)
		

	local result = string.gsub(baseTemp, '$passToScript', mw.text.jsonEncode(passToScript))
	result = string.gsub(result, '$rowLegends', rowlegends)
	result = string.gsub(result, '$fileLegends', filelegends)
	result = string.gsub(result, '$notations', table.concat(notation_spans, ' '))
	result = string.gsub(result, '$pieces', table.concat(pieces))
	result = string.gsub(result, '$metadataRows', table.concat(metadataRows))
	result = string.gsub(result, '$comments', '') -- N/A: create comments button if pgn contains comments:    <div class="pgn-image-button pgn-image-button-off pgn-button-cc"></div>
	return result
end






return {
	['demo'] = demo,
}