本模块为自动表核心功能程序,根据输入的信息自动筛选数据。

数据库储存在Module:db_song,通过Template:db可以调用数据库中的信息,也可以通过Template:songlist生成自动表格。


local p = {}

-- 1. 国际化和常量
local i18n = {
	['true'] = '是',      -- 布尔值:真
	['false'] = '否',     -- 布尔值:假
	['none'] = '无',
	['category_missing_value'] = '缺失%s',
	['error_no_type'] = '<span class="error">Db:调用时必须提供type参数。</span>',
}

-- 2. 辅助函数

-- 导入歌曲数据,从 Module:db_song 中获取数据表
local function GetValuesTable()
	-- 从 Module:db_song 中获取数据。
    return mw.loadData('Module:db_song')
end

-- 从值列表按照键值获得值,找不到则返回nil。
local function ValueFromValuesByKey(values, key)
	if values and key then
		return values[key]
	end
	return nil
end

-- 3. 值格式化方法 (valueMappingMethod)
local valueMappingMethod = {
    -- 格式化函数:将时长(秒)格式化为 'M:SS' 格式
    ['duration'] = (function (value)
        if type(value) == 'number' then
            local minutes = math.floor(value / 60)
            local seconds = value % 60
            return string.format('%d:%02d', minutes, seconds)
        end
        return value
    end),
    -- 格式化函数:将艺术家名称自动链接
    ['artist'] = (function (value)
        if type(value) == 'string' and value ~= '' then
            return '[[' .. value .. ']]'
        end
        return value
    end),
}

-- 4. 外部调用函数 (p.value)
function p.value(f)
	local args = f
	local frame = mw.getCurrentFrame()
	if f == frame then
		args = require('Module:ProcessArgs').merge(true)
	end
    
	local argTargetName = mw.text.trim(args[1] or '') -- 歌曲ID (键名)
	local argType = args.type                       -- 字段名 (type)
	local argNocat = args.nocat                     -- 是否禁止分类追踪
    
    if not argType then
        return i18n['error_no_type']
    end
    
    -- 1. 加载歌曲数据
    local values = GetValuesTable() 
    
    -- 2. 获取目标歌曲条目
    local songEntry = ValueFromValuesByKey(values, argTargetName)

    if not songEntry then
        -- [处理歌曲ID缺失...]
        -- ... (代码省略,与之前版本相同)
        return i18n['none']
    end
    
    -- 3. 从歌曲条目中获取特定字段的值
    local value = ValueFromValuesByKey(songEntry, argType)
    
    if value == nil then
        -- [处理特定字段的值缺失...]
        -- ... (代码省略,与之前版本相同)
        return i18n['none'] 
    end
    
    -- 4. 应用格式化
    
    -- **新增:优先级最高的布尔值转换**
    if type(value) == 'boolean' then
        if value then
            return i18n['true']
        else
            return i18n['false']
        end
    end
    
    -- 接下来应用字段特定的格式化
	if type(valueMappingMethod[argType]) == 'function' then
		return valueMappingMethod[argType](value)
	else
		-- 转换为字符串输出
		return tostring(value)
	end
end
	-- 5. 反向查找
	function p.findKeysByValue(f)
    local args = f
    local frame = mw.getCurrentFrame()
    if f == frame then
        args = require('Module:ProcessArgs').merge(true)
    end
    
    local targetField = mw.text.trim(args.field or '')
    -- 如果目标值是字符串,清除其两侧空格,否则保持原类型 (如数字)
    local targetValue = args.value 
    if type(targetValue) == 'string' then
        targetValue = mw.text.trim(targetValue)
    end
    
    -- 检查必要参数
    if targetField == '' or targetValue == nil then
        return i18n['error_find_keys_args']
    end

    -- 获取所有歌曲数据
    local songData = GetValuesTable()
    
    local matchingKeys = {}
    
    -- 遍历数据,查找匹配的键
    for songId, songEntry in pairs(songData) do
        local currentValue = ValueFromValuesByKey(songEntry, targetField)
        
        -- 直接比较当前值和目标值
        if currentValue == targetValue then
            table.insert(matchingKeys, songId)
        end
    end
    
    -- 对找到的键进行排序 (可选,但有助于规范输出)
    table.sort(matchingKeys)
    
    -- 返回以逗号和空格分隔的歌曲ID列表
    return table.concat(matchingKeys, ', ')
end
	--6. 表格生成函数
	function p.generateListTable(f)
    local args = require('Module:ProcessArgs').merge(true) 
    
    local conditionField = mw.text.trim(args.field or '')   -- 用于筛选的字段
    local conditionValue = args.value                       -- 用于筛选的值
    if type(conditionValue) == 'string' then
        conditionValue = mw.text.trim(conditionValue)
    end
    local displayFieldsString = mw.text.trim(args.columns or '') -- 要显示的字段列表
    
    if conditionField == '' or conditionValue == nil or displayFieldsString == '' then
        return i18n['error_generate_table_args']
    end

    local songData = GetValuesTable()
    local displayFields = mw.text.split(displayFieldsString, ',')
    local matchingKeys = {}
    
    -- 查找匹配的键
    for songId, songEntry in pairs(songData) do
        local currentValue = ValueFromValuesByKey(songEntry, conditionField)
        local checkValue = currentValue
        
        -- 针对布尔值的特殊处理,允许用户输入 'true'/'false'/'是'/'否' 来匹配
        if type(currentValue) == 'boolean' then
            local lowerTarget = type(conditionValue) == 'string' and string.lower(conditionValue) or conditionValue
            if lowerTarget == 'true' or lowerTarget == '是' then
                checkValue = true
            elseif lowerTarget == 'false' or lowerTarget == '否' then
                checkValue = false
            end
        end

        if checkValue == conditionValue then
            table.insert(matchingKeys, songId)
        end
    end
    
    table.sort(matchingKeys)

    if #matchingKeys == 0 then
        return '未找到符合条件的歌曲。'
    end

    local output = {}
    
    -- 构造表格头部
    table.insert(output, '{| class="wikitable sortable"')
    table.insert(output, '|-')
    -- ID 总是第一列
    table.insert(output, '! ' .. (displayNames['id'] or 'ID')) 
    
    for _, field in ipairs(displayFields) do
        field = mw.text.trim(field)
        table.insert(output, '! ' .. (displayNames[field] or field))
    end
    
    -- 构造表格行
    for _, songId in ipairs(matchingKeys) do
        local songEntry = songData[songId]
        table.insert(output, '|-')
        
        -- 第一列: Song ID
        table.insert(output, '| ' .. songId) 
        
        -- 后续列: 数据字段
        for _, field in ipairs(displayFields) do
            field = mw.text.trim(field)
            local rawValue = ValueFromValuesByKey(songEntry, field)
            local formattedValue = formatSingleValue(rawValue, field)
            table.insert(output, '| ' .. formattedValue)
        end
    end
    
    -- 闭合表格
    table.insert(output, '|}')
    
    return table.concat(output, '\n')
end
return p