모듈:연습장: 두 판 사이의 차이

리버티게임(개발), 모두가 만들어가는 자유로운 게임
둘러보기로 이동 검색으로 이동
>BANIP
잔글 (내용을 "local p = {} function p.uselib(frame) return mw[frame.args[1]][frame.args[2]](frame.args[3]) end return p"(으)로 바꿈)
>BANIP
잔글편집 요약 없음
1번째 줄: 1번째 줄:
local p = {}
local p = {}  
local table = require('table') -- 배열 입출력을 위한 테이블 내부 라이브러리
function p.uselib(frame)
 
     return mw[frame.args[1]][frame.args[2]](frame.args[3])
-- 속성 케이스 검사할 값, 발견시 반환할 값 정의
p.propertyCases = {
    {
        key = "platform",
        formatter = "[[분류:$title 게임]]",
        validate = function(gameMeta, scheme)
            local platform = t.walk(gameMeta, {"platform"})
            if platform == nil then return false end
            local platFormDef = t.walk(scheme, {"$defs", "platform", "oneOf"})
            local platFormData = t.find(platFormDef, function(p)
                return p.const == platform
            end)
            if platFormData == nil then return false end
            return {{key = "title", value = platFormData.title}}
        end
    },
    {
        key = "abandon",
        formatter = "[[분류:버려진 게임]]",
        validate = function(gameMeta, scheme)
            return t.walk(gameMeta, {"abandon"}) or false
        end
    },
    {
        key = "construction",
        formatter = "[[분류:공사중인 게임]]",
        validate = function(gameMeta, scheme)
            local construction = t.walk(gameMeta, {"construction"})
            if not construction then return false end
            if construction == true then return {{key = "value", value = ""}} end
            return {{key = "value", value = construction}}
        end
    },
    {
        key = "progress",
        formatter = "[[분류:$title]]",
        validate = function(gameMeta, scheme)
            local progress = t.walk(gameMeta, {"progress"})
            if progress == nil then return false end
            local progressDef = t.walk(scheme, {"properties", "progress", "oneOf"})
            local progressData = t.find(progressDef, function(p)
                return p.const == progress
            end)
            if progressData == nil then return false end
            return {{key = "title", value = progressData.title}}
        end
     },
    {
        key = "rating",
        formatter = "[[분류:$title 게임]]",
        validate = function(gameMeta, scheme)
            local age = t.walk(gameMeta, {"rating", "libertygame", "age"})
            if age == nil then return false end
            local ageDef = t.walk(scheme, {"properties", "rating", "oneOf", 2, "properties", "libertygame", "properties", "age", "oneOf"})
            local ageData = t.find(ageDef, function(a)
                return a.const == age
            end)
            if ageData == nil then return false end
            return {{key = "title", value = ageData.title}}
        end
    },
    {
        key = "repair",
        formatter = "[[분류:수리중인 게임]]",
        validate = function(gameMeta, scheme)
            local repair = t.walk(gameMeta, {"repair"})
            if not repair then return false end
            if repair == true then return {{key = "value", value = ""}} end
            return {{key = "value", value = repair}}
        end
    },
    {
        key = "genre",
        formatter = "[[분류:$title]]",
        validate = function(gameMeta, scheme)
            local genres = t.walk(gameMeta, {"genre"})
            if genres == nil then return false end
            if type(genres) == "string" then genres = {genres} end
            local genreDef = t.walk(scheme, {"$defs", "genre", "oneOf"})
            local genreData = t.filter(t.map(genres, function(genre)
                return t.find(genreDef, function(genreData)
                    return genreData.const == genre
                end)
            end), function(genreData)
                return genreData ~= nil
            end)
 
            return t.map(genreData, function(genreData)
                return {key = "title", value = genreData.title}
            end)
        end
    }
}
 
-- 테이블 관련 유틸리티 함수들
t = {
    -- 자바스크립트의 find 함수와 동일
    -- 주어진 함수를 만족하는 첫 번째 요소를 반환
    find = function(tb, func)
        for _, value in ipairs(tb) do
            if func(value) then
                return value
            end
        end
        return nil
    end,
    -- 자바스크립트의 map 함수와 동일
    -- 주어진 함수를 이용하여 테이블의 모든 요소를 변환
    map = function(tb, func)
        local newTable = {}
        for i, value in ipairs(tb) do
            newTable[i] = func(value)
        end
        return newTable
    end,
    -- 자바스크립트의 filter 함수와 동일
    -- 주어진 함수를 만족하는 요소만으로 새 테이블 생성
    filter = function(tb, func)
        local newTable = {}
        for _, value in ipairs(tb) do
            if func(value) then
                table.insert(newTable, value)
            end
        end
        return newTable
    end,
    -- gameMeta.rating.libertygame.age와 같이 다단계 키로 이루어진 테이블 값을 가져오는 함수
    -- 키의 경로 중간에 nil이 있는 경우 nil 반환
    walk = function(tbl, keys)
        local value = tbl
        for i, key in ipairs(keys) do
            value = value[key]
            if value == nil or type(value) == 'number' or type(value) == 'string' then
                return value
            end
        end
        return value
    end,
}
 
 
-- 게임 메타데이터를 분석하고 각 속성에 대해 적절한 포맷을 적용하는 함수
function p._manualParser(scheme, gameMeta)
    local results = {}
 
    -- 각 속성 케이스를 순회합니다.
    for _, propertyCase in ipairs(p.propertyCases) do
        -- 현재 속성의 유효성을 확인합니다.
        local validatedGroup = propertyCase.validate(gameMeta,scheme)
 
        if validatedGroup ~= false and validatedGroup ~= nil then
            -- 배열이 아닌 경우 기본 배열로 변환
            if type(validatedGroup) ~= 'table' then
                validatedGroup = {}
            end           
           
            -- 2단계 배열이 아닌 경우 한번 더 감싸기(하위 테이블에 "key"라는 키가 있을 때)
            if #validatedGroup ~= 0 and validatedGroup[1].key ~= nil then
                validatedGroup = {validatedGroup}
            end
 
            for _, validated in ipairs(validatedGroup) do
                local resultString = propertyCase.formatter
                for _, v in ipairs(validated) do
                    local key = v.key
                    local value = v.value
                    resultString = resultString:gsub("$" .. key, value)
                end
                table.insert(results, resultString)
            end
        end
    end
 
    return results
end
 
-- 첫번째 파라미터에 리버티게임:게임 메타데이터/스키마.json,
-- 두번째 파라미터에 game.json 넣어서 게임 자동분류 사용 가능
function p.manualParse(frame)
frame:expandTemplate{title = 'template'}
local schemeRaw = frame:expandTemplate{title = '리버티게임:게임 메타데이터/스키마.json'}
    local scheme = mw.text.jsonDecode(schemeRaw)
   
    local gameMetaPagename = schemeRaw.args[1]
 
    -- 위키낚시/game.json => :위키낚시/game.json
    -- 사:BANIP/위키낚시/game.json => 사:BANIP/위키낚시/game.json
    if not gameMetaPagename:find(":") then
        gameMetaPagename = ":" .. gameMetaPagename
    end
    local gameMetaRaw = frame:expandTemplate{title = gameMetaPagename}
    local gameMeta = mw.text.jsonDecode(gameMetaRaw)
 
    local parsed = p._manualParser(scheme, gameMeta)
    return table.concat(parsed)
end
end


return p
return p

2023년 7월 28일 (금) 19:33 판


모듈 설명문서[보기] [편집] [역사] [새로 고침]

자유롭게 모듈의 사용법을 익힐 수 있는 연습장입니다.

  1. 장기간에 걸쳐 수정이 필요한 경우 별도로 모듈페이지를 만드는 것을 추천합니다.
  2. 다음 문서가 도움이 될 수 있습니다.
  3. 다른 이름공간에 대한 연습은 아래에서 가능합니다.
  4. 낙서장을 비우려면 여기를 클릭하세요.


local p = {} 
local table = require('table') -- 배열 입출력을 위한 테이블 내부 라이브러리

-- 속성 케이스 검사할 값, 발견시 반환할 값 정의
p.propertyCases = {
    {
        key = "platform",
        formatter = "[[분류:$title 게임]]",
        validate = function(gameMeta, scheme)
            local platform = t.walk(gameMeta, {"platform"})
            if platform == nil then return false end
            local platFormDef = t.walk(scheme, {"$defs", "platform", "oneOf"})
            local platFormData = t.find(platFormDef, function(p)
                return p.const == platform
            end)
            if platFormData == nil then return false end
            return {{key = "title", value = platFormData.title}}
        end
    },
    {
        key = "abandon",
        formatter = "[[분류:버려진 게임]]",
        validate = function(gameMeta, scheme)
            return t.walk(gameMeta, {"abandon"}) or false
        end
    },
    {
        key = "construction",
        formatter = "[[분류:공사중인 게임]]",
        validate = function(gameMeta, scheme)
            local construction = t.walk(gameMeta, {"construction"})
            if not construction then return false end
            if construction == true then return {{key = "value", value = ""}} end
            return {{key = "value", value = construction}}
        end
    },
    {
        key = "progress",
        formatter = "[[분류:$title]]",
        validate = function(gameMeta, scheme)
            local progress = t.walk(gameMeta, {"progress"})
            if progress == nil then return false end
            local progressDef = t.walk(scheme, {"properties", "progress", "oneOf"})
            local progressData = t.find(progressDef, function(p)
                return p.const == progress
            end)
            if progressData == nil then return false end
            return {{key = "title", value = progressData.title}}
        end
    },
    {
        key = "rating",
        formatter = "[[분류:$title 게임]]",
        validate = function(gameMeta, scheme)
            local age = t.walk(gameMeta, {"rating", "libertygame", "age"})
            if age == nil then return false end
            local ageDef = t.walk(scheme, {"properties", "rating", "oneOf", 2, "properties", "libertygame", "properties", "age", "oneOf"})
            local ageData = t.find(ageDef, function(a)
                return a.const == age
            end)
            if ageData == nil then return false end
            return {{key = "title", value = ageData.title}}
        end
    },
    {
        key = "repair",
        formatter = "[[분류:수리중인 게임]]",
        validate = function(gameMeta, scheme)
            local repair = t.walk(gameMeta, {"repair"})
            if not repair then return false end
            if repair == true then return {{key = "value", value = ""}} end
            return {{key = "value", value = repair}}
        end
    },
    {
        key = "genre",
        formatter = "[[분류:$title]]",
        validate = function(gameMeta, scheme)
            local genres = t.walk(gameMeta, {"genre"})
            if genres == nil then return false end
            if type(genres) == "string" then genres = {genres} end
            local genreDef = t.walk(scheme, {"$defs", "genre", "oneOf"})
            local genreData = t.filter(t.map(genres, function(genre)
                return t.find(genreDef, function(genreData)
                    return genreData.const == genre
                end)
            end), function(genreData)
                return genreData ~= nil
            end)

            return t.map(genreData, function(genreData)
                return {key = "title", value = genreData.title}
            end)
        end
    }
}

-- 테이블 관련 유틸리티 함수들
t = {
    -- 자바스크립트의 find 함수와 동일
    -- 주어진 함수를 만족하는 첫 번째 요소를 반환
    find = function(tb, func)
        for _, value in ipairs(tb) do
            if func(value) then
                return value
            end
        end
        return nil
    end,
    -- 자바스크립트의 map 함수와 동일
    -- 주어진 함수를 이용하여 테이블의 모든 요소를 변환
    map = function(tb, func)
        local newTable = {}
        for i, value in ipairs(tb) do
            newTable[i] = func(value)
        end
        return newTable
    end,
    -- 자바스크립트의 filter 함수와 동일
    -- 주어진 함수를 만족하는 요소만으로 새 테이블 생성
    filter = function(tb, func)
        local newTable = {}
        for _, value in ipairs(tb) do
            if func(value) then
                table.insert(newTable, value)
            end
        end
        return newTable
    end,
    -- gameMeta.rating.libertygame.age와 같이 다단계 키로 이루어진 테이블 값을 가져오는 함수
    -- 키의 경로 중간에 nil이 있는 경우 nil 반환
    walk = function(tbl, keys)
        local value = tbl
        for i, key in ipairs(keys) do
            value = value[key]
            if value == nil or type(value) == 'number' or type(value) == 'string' then
                return value
            end
        end
        return value
    end,
}


-- 게임 메타데이터를 분석하고 각 속성에 대해 적절한 포맷을 적용하는 함수
function p._manualParser(scheme, gameMeta)
    local results = {}

    -- 각 속성 케이스를 순회합니다.
    for _, propertyCase in ipairs(p.propertyCases) do
        -- 현재 속성의 유효성을 확인합니다.
        local validatedGroup = propertyCase.validate(gameMeta,scheme)

        if validatedGroup ~= false and validatedGroup ~= nil then
            -- 배열이 아닌 경우 기본 배열로 변환 
            if type(validatedGroup) ~= 'table' then
                validatedGroup = {}
            end            
            
            -- 2단계 배열이 아닌 경우 한번 더 감싸기(하위 테이블에 "key"라는 키가 있을 때)
            if #validatedGroup ~= 0 and validatedGroup[1].key ~= nil then
                validatedGroup = {validatedGroup}
            end

            for _, validated in ipairs(validatedGroup) do
                local resultString = propertyCase.formatter
                for _, v in ipairs(validated) do
                    local key = v.key
                    local value = v.value
                    resultString = resultString:gsub("$" .. key, value)
                end
                table.insert(results, resultString)
            end
        end
    end

    return results
end

-- 첫번째 파라미터에 리버티게임:게임 메타데이터/스키마.json, 
-- 두번째 파라미터에 game.json 넣어서 게임 자동분류 사용 가능 
function p.manualParse(frame)
	
	frame:expandTemplate{title = 'template'}
	
	local schemeRaw = frame:expandTemplate{title = '리버티게임:게임 메타데이터/스키마.json'} 
    local scheme = mw.text.jsonDecode(schemeRaw)
    
    local gameMetaPagename = schemeRaw.args[1]

    -- 위키낚시/game.json => :위키낚시/game.json
    -- 사:BANIP/위키낚시/game.json => 사:BANIP/위키낚시/game.json
    if not gameMetaPagename:find(":") then
        gameMetaPagename = ":" .. gameMetaPagename
    end
    local gameMetaRaw = frame:expandTemplate{title = gameMetaPagename} 
    local gameMeta = mw.text.jsonDecode(gameMetaRaw)

    local parsed = p._manualParser(scheme, gameMeta)
    return table.concat(parsed)
end

return p