Modul:Shogi diagram
local shogiobject = {}
-----------------------
-- internal functions
-----------------------
-- returns a japanese character for a roman letter abbreviation
-- called by the shogiboard() function
local function piecesymbol(abbreviation)
-- the abbreviation argument is a string of 1-3 letters that stand for the English names of the shogi pieces
-- the abbreviation is extracted out of a longer string by the processString() function
-- letter to character mapping (hash table)
local piecenames = {
p = '歩',
t = 'と',
l = '香',
pl = '杏',
n = '桂',
pn = '圭',
s = '銀',
ps = '全',
g = '金',
b = '角',
h = '馬',
r = '飛',
d = '龍',
gyoku = '玉',
ou = '王',
tx = '个',
plx = '仝',
pnx = '今',
dx = '竜',
e = '象',
a = '太'
}
-- spit out the character corresponding to abbreviation
-- if the abbreviation string is empty, then spit out nobreak space (for html tables)
piece = piecenames[abbreviation] or ' '
return string.format( piece )
end
-- function separates out the piece, the side, and the boldness info present in the string argument
-- it returns an array with these three values plus the color (for promoted pieces)
-- this info is passed to the makeTD() function
function processString(ss)
-- strip whitespace
ss = mw.text.trim(ss)
-- get the last character of the string
local lastchar = mw.ustring.sub(ss, -1)
-- chop off last character of string
local restofstring = mw.ustring.sub(ss, 1, -2)
-- default is normal font
-- but if the string ends with 'l' for 'last move',
-- then the font should be bold and we need to get a new string with the this 'l' chopped off (with a new last character)
local boldness = 'normal'
if lastchar:match('l') then
boldness = 'bold'
lastchar = mw.ustring.sub(restofstring, -1)
restofstring = mw.ustring.sub(restofstring, 1, -2)
end
-- the side is either 'g' for 'gote' or 's' for 'sente'
-- it's the last character in the string (and if the string ended)
local side = lastchar
-- the leftover string is the shogi piece abbreviation
local pieceabbr = restofstring
-- default is black font
-- if the piece is promoted (one the abbreviations below), then the piece should be red
local color = 'black'
if pieceabbr:match('t') or pieceabbr:match('pl') or pieceabbr:match('pn') or pieceabbr:match('ps') or pieceabbr:match('h') or pieceabbr:match('d') then
color = 'red'
end
-- this is an exceptional bit:
-- gote's king is usually 王 instead of 玉 by convention,
-- but it's convenient to use the 'k' code for both sente and gote and let the default character be side-dependent
if pieceabbr:match('k') and side:match('g') then
pieceabbr = 'ou'
end
if pieceabbr:match('k') and side:match('s') then
pieceabbr = 'gyoku'
end
-- similar to above exception, reverse default
if pieceabbr:match('ak') and side:match('s') then
pieceabbr = 'ou'
end
if pieceabbr:match('ak') and side:match('g') then
pieceabbr = 'gyoku'
end
-- convert abbreviation to Japanese character
local piecechar = piecesymbol(pieceabbr)
if ss:match('yy') or ss:match('gr') or ss:match('rat') or ss:match('lat') or ss:match('uat') or ss:match('dat') or
ss:match('lra') or ss:match('las') or ss:match('ras') or ss:match('uda') or ss:match('das') or ss:match('uas') or
ss:match('da') or ss:match('dau') or ss:match('dad') or ss:match('daus') or ss:match('dads') or ss:match('daa') or
ss:match('daad') or ss:match('daau') or ss:match('daaus') or ss:match('daads') or ss:match('kar') or ss:match('kal') or
ss:match('kadr') or ss:match('kadl') or ss:match('rah') or ss:match('lah') or ss:match('dah') or ss:match('uah') or
ss:match('durh') or ss:match('dulh') or ss:match('ddrh') or ss:match('ddlh') or ss:match('ddl') or ss:match('ddr') or
ss:match('dul') or ss:match('dur') then
piecechar = '[[File:shogi_' .. ss .. '22.svg|20px]]'
side = 'arrow'
color = 'arrow'
boldness = 'arrow'
end
local result = {piecechar, side, color, boldness}
return result
end
-- function makes a <td> containing the piece with CSS stuff
-- uses the info from processString() to customize the CSS based on which side, color, and boldness
function makeTD(stringarg)
-- got to process the string argument into its informational bits
-- this processedstring is an array (or whatever the equivalent is in Lua)
local processedstring = processString(stringarg)
-- saving the pieces of the array as separate objects to be referred to below
local piecechar = processedstring[1]
local side = processedstring[2]
local color = processedstring[3]
local bold = processedstring[4]
-- i guess one needs a root node?
local root = mw.html.create('')
-- the default <td>
local td = root:tag('td')
td:css('border', 'black 1px solid')
td:css('width', '20px')
td:css('height', '20px')
td:css('padding', '0')
td:css('line-height', '0')
td:css('font-family', '"Hiragino Mincho ProN", serif')
if not side:match('arrow') then
td:wikitext( piecechar )
end
-- g = gote
-- gote should be upside down text
if side:match( 'g' ) then
td:css('transform', 'rotate(180deg)')
end
-- for promoted pieces
if color:match( 'red' ) then
-- this is a darkish reddish color
td:css('color', '#E00303')
end
-- for bold pieces
if bold:match( 'bold' ) then
td:css('font-weight', 'bolder')
-- traditionally bold type is gothic (sans serif) in Japanese typesetting of shogi diagrams within Japanese shogi books
td:css('font-family', ' HiraginoSans-W5, sans-serif')
end
-- for arrow svgs
if side:match('arrow') then
td:css('padding', '0')
td:css('width', '20px')
td:css('height', '20px')
td:css('font-size', '1px')
td:css('line-height', '0')
td:wikitext( piecechar )
end
return tostring(root)
end
-- function makes the shogi diagram
-- this is basically a <div> enclosing a .css <div> wrapper with a <table> inside
function shogiboard(args)
-- these are the column coordinate labels 9-1
local colLabels = {'9', '8', '7', '6', '5', '4', '3', '2', '1', ' '}
-- these are the row coordinate labels a-i (western notation)
local rowLabels = {'1', '2', '3', '4', '5', '6', '7', '8', '9'}
-- these are the row coordinate labels 1-9 (Japanese notation)
-- this isn't set up for use yet
local rowLabelsJP = {'一', '二', '三', '四', '五', '六', '七', '八', '九'}
local headerarg = args[2]
local toppieceinhandarg = args[3]
local root = mw.html.create('div')
-- <div> wrapper
local shogiboardwrapper = root:tag('div')
:addClass('shogiboardwrapper')
:css('padding-left', '4px')
:css('padding-bottom', '2px')
-- the diagram header/caption
local headerstring = mw.text.trim(headerarg)
local header = shogiboardwrapper:tag('div')
header:css('padding', '0')
header:wikitext(headerstring)
header:css('font-size', '14px')
-- this is the 'piece-in-hand' argument for gote
-- strip whitespace
local strippedpieceinhandtop = mw.text.trim(toppieceinhandarg) or ''
-- put it in a <div> with .css formating
local pieceinhandtopdiv = shogiboardwrapper:tag('div')
pieceinhandtopdiv:css('padding', '0')
pieceinhandtopdiv:css('font-size', '12px')
pieceinhandtopdiv:wikitext('☖ bidak di tangan: ')
-- i was going to put the actual argument text into conditional <span> .css formating, but i couldn't get the logical test in an if/else structure right...
local piecesinhandtopspan = pieceinhandtopdiv:tag('span')
piecesinhandtopspan:css('font-size', '13px')
piecesinhandtopspan:wikitext(strippedpieceinhandtop)
-- the shogi table
local shogitable = shogiboardwrapper:tag('table')
:addClass('shogitable')
:attr('border', '1')
:css('border-collapse', 'collapse')
:css('border', 'none')
:css('padding-top', '0')
:css('background-color', 'white')
-- font size for the shogi piece text
piecefontsize = '17px'
-- font size for the column/row piece coordinate labels (9-1) and (a-i)
colrowfontsize = '11px'
-- padding amount for the row piece coordinate labels (a-i)
padrowlab = '1px'
-- the row for the column coordinate labels
local columnlabelrow = shogitable:tag('tr')
:css('font-size', colrowfontsize)
:css('background-color', '#f9f9f9')
-- iterating over the column label to put each label in a <td>
for i,v in ipairs(colLabels) do
local td = columnlabelrow:tag('td')
:css('border', 'none')
:css('width', '20px')
:css('height', '5px')
:wikitext( v )
end
-- iterate over the 81 shogi piece arguments (left to right, top to bottom)
-- i couldn't figure out how to do this is in a clever loopy way as i couldn't figure out how to close the html tags
-- whatever, it's repetitive, but it works
-- index number displacement/offset
-- this is just the number of arguments that precede the 81 shogi piece arguments that are in the html <table>
-- i just keep the piece arguments as indexes 1-81, then add nx to the index value
nx = 3
-- the row for the shogi pieces
-- row 1
local trow = shogitable:tag('tr')
:css('font-size', piecefontsize)
-- put a single piece into a <td>
-- iterate over 9 pieces in the row
for irow = 1,9 do
trow:wikitext( makeTD(args[(irow+nx)]) )
end
-- add row coordinate label <td>
local rowlabel = trow:tag('td')
:css('border', 'none')
:css('font-size', colrowfontsize)
:css('padding-left', padrowlab)
:css('padding-top', '0')
:css('padding-bottom', '0')
:css('background-color', '#f9f9f9')
:wikitext( rowLabels[1] )
-- row 2
local trow = shogitable:tag('tr')
:css('font-size', piecefontsize)
for irow = 10,18 do
trow:wikitext( makeTD(args[(irow+nx)]) )
end
local rowlabel = trow:tag('td')
:css('border', 'none')
:css('font-size', colrowfontsize)
:css('padding-left', padrowlab)
:css('background-color', '#f9f9f9')
:wikitext( rowLabels[2] )
-- row 3
local trow = shogitable:tag('tr')
:css('font-size', piecefontsize)
for irow = 19,27 do
trow:wikitext( makeTD(args[(irow+nx)]) )
end
local rowlabel = trow:tag('td')
:css('border', 'none')
:css('font-size', colrowfontsize)
:css('padding-left', padrowlab)
:css('background-color', '#f9f9f9')
:wikitext( rowLabels[3] )
-- row 4
local trow = shogitable:tag('tr')
:css('font-size', piecefontsize)
for irow = 28,36 do
trow:wikitext( makeTD(args[(irow+nx)]) )
end
local rowlabel = trow:tag('td')
:css('border', 'none')
:css('font-size', colrowfontsize)
:css('padding-left', padrowlab)
:css('background-color', '#f9f9f9')
:wikitext( rowLabels[4] )
-- row 5
local trow = shogitable:tag('tr')
:css('font-size', piecefontsize)
for irow = 37,45 do
trow:wikitext( makeTD(args[(irow+nx)]) )
end
local rowlabel = trow:tag('td')
:css('border', 'none')
:css('font-size', colrowfontsize)
:css('padding-left', padrowlab)
:css('background-color', '#f9f9f9')
:wikitext( rowLabels[5] )
-- row 6
local trow = shogitable:tag('tr')
:css('font-size', piecefontsize)
for irow = 46,54 do
trow:wikitext( makeTD(args[(irow+nx)]) )
end
local rowlabel = trow:tag('td')
:css('border', 'none')
:css('font-size', colrowfontsize)
:css('padding-left', padrowlab)
:css('background-color', '#f9f9f9')
:wikitext( rowLabels[6] )
-- row 7
local trow = shogitable:tag('tr')
:css('font-size', piecefontsize)
for irow = 55,63 do
trow:wikitext( makeTD(args[(irow+nx)]) )
end
local rowlabel = trow:tag('td')
:css('border', 'none')
:css('font-size', colrowfontsize)
:css('padding-left', padrowlab)
:css('background-color', '#f9f9f9')
:wikitext( rowLabels[7] )
-- row 8
local trow = shogitable:tag('tr')
:css('font-size', piecefontsize)
for irow = 64,72 do
trow:wikitext( makeTD(args[(irow+nx)]) )
end
local rowlabel = trow:tag('td')
:css('border', 'none')
:css('font-size', colrowfontsize)
:css('padding-left', padrowlab)
:css('background-color', '#f9f9f9')
:wikitext( rowLabels[8] )
-- row 9
local trow = shogitable:tag('tr')
:css('font-size', piecefontsize)
for irow = 73,81 do
trow:wikitext( makeTD(args[(irow+nx)]) )
end
local rowlabel = trow:tag('td')
:css('border', 'none')
:css('font-size', colrowfontsize)
:css('padding-left', padrowlab)
:css('background-color', '#f9f9f9')
:wikitext( rowLabels[9] )
-- this is the 'piece-in-hand' argument for sente (same as above for gote)
-- only difference is the black shogi piece glyph (☗)
local strippedpieceinhandbottom = mw.text.trim(args[81+1+nx]) or ''
local pieceinhandbottomdiv = shogiboardwrapper:tag('div')
pieceinhandbottomdiv:css('padding', '0')
pieceinhandbottomdiv:css('font-size', '12px')
pieceinhandbottomdiv:wikitext('☗ bidak di tangan: ')
local piecesinhandbottomspan = pieceinhandbottomdiv:tag('span')
piecesinhandbottomspan:css('font-size', '13px')
piecesinhandbottomspan:wikitext(strippedpieceinhandbottom)
return tostring(root)
end
-----------------------
-- main function
-----------------------
function shogiobject.board(frame)
-- need to use getParent().args for reasons i dont understand
local args = frame:getParent().args
return shogiboard(args)
end
return shogiobject