Documentation for this module may be created at Module:BioboxBody/doc
local p = {}
local PBD = require('Module:PBD')
local PBDIB = require('Module:PornBaseDataIB')
local BioboxUnits = require('Module:BioboxUnits')
local CategoryMapping = require('Module:BioboxCategoryMapping')
local function isEmpty(value)
return value == nil or value == ''
end
local function isPositive(value)
if isEmpty(value) then return false end
value = tostring(value):lower()
local positiveValues = {
['yes'] = true,
['y'] = true,
['ya'] = true,
['yep'] = true,
['true'] = true,
['1'] = true
}
return positiveValues[value] or false
end
local function getHeight(frame, args)
local height = args.height
if BioboxUnits.isValidHeight(height) then
return BioboxUnits.formatHeight(frame, height, {})
end
local pbdHeight = PBD._property{[1] = 'P156', raw = true, multilanguage = true, ['eid'] = args.qid}
local heightNum = BioboxUnits.extractNumber(pbdHeight)
if heightNum then
return BioboxUnits.formatHeight(frame, heightNum, {})
end
return 'N/A'
end
local function getWeight(frame, args)
local weight = args.weight
if BioboxUnits.isValidWeight(weight) then
return BioboxUnits.formatWeight(frame, weight, {})
end
local pbdWeight = PBD._property{[1] = 'P159', raw = true, multilanguage = true, ['eid'] = args.qid}
local weightNum = BioboxUnits.extractNumber(pbdWeight)
if weightNum then
return BioboxUnits.formatWeight(frame, weightNum, {})
end
return 'N/A'
end
local function getPenisSize(frame, args)
frame = frame or mw.getCurrentFrame()
local penisSize = args['penis_size'] or args['penis size']
if not isEmpty(penisSize) then
local childArgs = {}
childArgs[1] = tostring(penisSize)
childArgs["break"] = "y"
childArgs["linkspan"] = "y"
return BioboxUnits.formatPenisSize(frame:newChild{args = childArgs})
end
local pbdPenisSize = PBD._property{[1] = 'P161', raw = true, multilanguage = true, ['eid'] = args.qid}
if not isEmpty(pbdPenisSize) then
local childArgs = {}
childArgs[1] = tostring(pbdPenisSize)
childArgs["break"] = "y"
childArgs["linkspan"] = "y"
return BioboxUnits.formatPenisSize(frame:newChild{args = childArgs})
end
return 'N/A'
end
function p.formatHair(state, args, rowIndex)
local section = {}
local hairValues = state:collectNumberedParams(args, "hair_color")
if #hairValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P162',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(hairValues, pbdValue)
end
end
if #hairValues > 0 then
local displayValue = state:formatFeatureList(hairValues, 'hair')
if displayValue then
local hairLengthValue = args.hair_length
if isEmpty(hairLengthValue) and args.qid then
hairLengthValue = PBD._property{
[1] = 'P166',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
end
if not isEmpty(hairLengthValue) then
hairLengthValue = mw.ustring.lower(hairLengthValue)
for _, mapping in ipairs(CategoryMapping.MAPPINGS.hair_length) do
for _, alias in ipairs(mapping.aliases) do
if mw.ustring.lower(alias) == hairLengthValue then
displayValue = displayValue .. ' (' .. mapping.display .. ')'
break
end
end
end
end
section[#section + 1] = state:formatField("Hair:",
displayValue,
"hair",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function p.formatEyeColor(state, args, rowIndex)
local section = {}
local eyeValues = state:collectNumberedParams(args, "eye_color")
if #eyeValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P386',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(eyeValues, pbdValue)
end
end
if #eyeValues > 0 then
local displayValue = state:formatFeatureList(eyeValues, 'eye_color')
if displayValue then
section[#section + 1] = state:formatField("Eye color:",
displayValue,
"eye_color",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function p.formatBodyType(state, args, rowIndex)
local section = {}
local bodyValues = state:collectNumberedParams(args, "body_type")
if #bodyValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P399',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(bodyValues, pbdValue)
end
end
if #bodyValues > 0 then
local displayValue = state:formatFeatureList(bodyValues, 'body_type')
if displayValue then
section[#section + 1] = state:formatField("Body type:",
displayValue,
"body_type",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function p.formatSkin(state, args, rowIndex)
local section = {}
local skinValues = state:collectNumberedParams(args, "skincomplexion")
if #skinValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P421',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(skinValues, pbdValue)
end
end
if #skinValues > 0 then
local displayValue = state:formatFeatureList(skinValues, 'skin')
if displayValue then
section[#section + 1] = state:formatField("Skin:",
displayValue,
"skin",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function p.formatAssType(state, args, rowIndex)
local section = {}
local assTypeValues = {}
if not isEmpty(args.ass_type) then
table.insert(assTypeValues, args.ass_type)
end
for i = 2, 10 do
local paramName = "ass_type" .. i
if not isEmpty(args[paramName]) then
table.insert(assTypeValues, args[paramName])
else
break
end
end
if #assTypeValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P585',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(assTypeValues, pbdValue)
end
end
if #assTypeValues > 0 then
local displayValue = state:formatFeatureList(assTypeValues, 'ass_type')
if displayValue then
section[#section + 1] = state:formatField("Ass type:",
displayValue,
"ass_type",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function p.formatForeskin(state, args, rowIndex)
local section = {}
local value = args.foreskin
if isEmpty(value) and args.qid then
value = PBD._property{
[1] = 'P398',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
end
if not isEmpty(value) then
local displayValue = state:formatFeatureList({value}, 'foreskin')
if displayValue then
section[#section + 1] = state:formatField("Foreskin:",
displayValue,
"foreskin",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function p.formatChestHair(state, args, rowIndex)
local section = {}
local value = args.chest_hair
if not value and args.qid then
value = PBD._property{
[1] = 'P589',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
end
if not isEmpty(value) then
value = mw.ustring.lower(value)
local mappings = CategoryMapping.MAPPINGS.chest_hair
local match = nil
for _, mapping in ipairs(mappings) do
for _, alias in ipairs(mapping.aliases) do
if mw.ustring.lower(alias) == value then
match = mapping
break
end
end
if match then break end
end
if match then
local displayValue = '[[:Category:' .. match.category .. '|' .. match.display .. ']] <small>([[:Category:Chest hair|Legend]])</small>'
if mw.title.getCurrentTitle().namespace == 0 then
displayValue = displayValue .. '[[Category:' .. match.category .. ']]'
end
section[#section + 1] = state:formatField(
"Chest hair:",
displayValue,
"chest_hair",
rowIndex
)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function p.formatTattoo(state, args, rowIndex)
local section = {}
local tattooValue = args.tattoo
if not isEmpty(tattooValue) then
if isPositive(tattooValue) then
local displayValue = '[[:Category:Performers with Tattoos|Yes]]'
if mw.title.getCurrentTitle().namespace == 0 then
displayValue = displayValue .. '[[Category:Performers with Tattoos]]'
end
section[#section + 1] = state:formatField('Tattoo:',
displayValue,
'tattoo',
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function p.formatBodySection(state, args, rowIndex)
local section = {}
section[#section + 1] = string.format('|-\n! colspan="2" %s | \'\'\'Body\'\'\'', state.STYLES.SECTION_HEADER)
section[#section + 1] = '<tr><td colspan="2" style="text-align:center;">'
section[#section + 1] = '<div style="width: 100%; border: 1px white; background:#657D91; padding: 1px 0; display: grid; grid-template-columns: auto auto auto; color: white; text-align: center;">'
section[#section + 1] = '<div>[[File:Height attribute symbol.png|40px|link=Height]]</div>'
section[#section + 1] = '<div>[[File:Weight attribute symbol.png|40px|link=Weight]]</div>'
section[#section + 1] = '<div>[[File:Penis size attribute symbol.png|40px|link=Penis size]]</div>'
local frame = mw.getCurrentFrame()
local height = getHeight(frame, args)
local weight = getWeight(frame, args)
local penisSize = getPenisSize(frame, args)
section[#section + 1] = string.format(
'<div>\'\'\'%s\'\'\'</div><div>\'\'\'%s\'\'\'</div><div>\'\'\'%s\'\'\'</div></div></td></tr>',
height, weight, penisSize
)
local hairSection, newRowIndex = p.formatHair(state, args, rowIndex)
for _, line in ipairs(hairSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local eyeSection, newRowIndex = p.formatEyeColor(state, args, rowIndex)
for _, line in ipairs(eyeSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local bodySection, newRowIndex = p.formatBodyType(state, args, rowIndex)
for _, line in ipairs(bodySection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local skinSection, newRowIndex = p.formatSkin(state, args, rowIndex)
for _, line in ipairs(skinSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local assTypeSection, newRowIndex = p.formatAssType(state, args, rowIndex)
for _, line in ipairs(assTypeSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local foreskinSection, newRowIndex = p.formatForeskin(state, args, rowIndex)
for _, line in ipairs(foreskinSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local chestHairSection, newRowIndex = p.formatChestHair(state, args, rowIndex)
for _, line in ipairs(chestHairSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local tattooSection, newRowIndex = p.formatTattoo(state, args, rowIndex)
for _, line in ipairs(tattooSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
return table.concat(section, '\n'), rowIndex
end
return p