Module:BioboxBody

Revision as of 00:06, 19 March 2025 by PeaceDeadC (talk | contribs) (Created page with "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,...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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