모듈:GameJSONParser: 두 판 사이의 차이

리버티게임, 모두가 만들어가는 자유로운 게임
잔글편집 요약 없음
(주석, 깊은 테이블 사용을 위한 t.walk 함수 추가, propertyCases에 반영)
1번째 줄: 1번째 줄:
local p = {}
local p = {}


-- 테이블 유틸리티 함수
t = {
t = {
    -- js의 find
     find = function(table, func)
     find = function(table, func)
         for _, value in ipairs(table) do
         for _, value in ipairs(table) do
10번째 줄: 12번째 줄:
         return nil
         return nil
     end,
     end,
 
    -- js의 map
     map = function(table, func)
     map = function(table, func)
         local newTable = {}
         local newTable = {}
18번째 줄: 20번째 줄:
         return newTable
         return newTable
     end,
     end,
 
    -- js의 필터
     filter = function(table, func)
     filter = function(table, func)
         local newTable = {}
         local newTable = {}
27번째 줄: 29번째 줄:
         end
         end
         return newTable
         return newTable
     end
     end,
    --t.walk(gameMeta, {"rating","libertygame","age"})를 호출 시
    --gameMeta.rating.libertygame.age로 들어가다가 도중에 들어갈 수 없는 구조를 만나면 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,
}
}


40번째 줄: 54번째 줄:
         -- 현재 속성의 유효성을 확인합니다.
         -- 현재 속성의 유효성을 확인합니다.
         local validatedGroup = propertyCase:validate(scheme,gameMeta)
         local validatedGroup = propertyCase:validate(scheme,gameMeta)
         if validatedGroup ~= false then
         if validatedGroup ~= false and validatedGroup ~= nil then
 
            -- 배열이 아닌 경우 기본 배열로 변환
            if type(validatedGroup) ~= 'table' then
                validatedGroup = {}
            end           
           
            -- 2단계 배열이 아닌 경우 한번 더 감싸기
             if #validatedGroup ~= 0 and type(validatedGroup[1]) ~= 'table' then
             if #validatedGroup ~= 0 and type(validatedGroup[1]) ~= 'table' then
                 validatedGroup = {validatedGroup}
                 validatedGroup = {validatedGroup}
67번째 줄: 88번째 줄:
     local gameMeta = mw.text.jsonDecode(frame.args[2])
     local gameMeta = mw.text.jsonDecode(frame.args[2])


     -- construct propertyCases table
     -- 속성 케이스 검사할 값, 발견시 반환할 값 정의
     local propertyCases = {
     local propertyCases = {
         {
         {
73번째 줄: 94번째 줄:
             formatter = "[[분류:$title 게임]]",
             formatter = "[[분류:$title 게임]]",
             validate = function(gameMeta, scheme)
             validate = function(gameMeta, scheme)
                 local platFormData = t.find(scheme["$defs"].platform.oneOf, function(platform)
                 local platform = t.walk(gameMeta, {"platform"})
                     return platform.const == 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)
                 end)
                 if platFormData == nil then return false end
                 if platFormData == nil then return false end
84번째 줄: 108번째 줄:
             formatter = "{{뱃지|버려진 게임}}",
             formatter = "{{뱃지|버려진 게임}}",
             validate = function(gameMeta, scheme)
             validate = function(gameMeta, scheme)
                 return gameMeta.abandon or false
                 return t.walk(gameMeta, {"abandon"}) or false
             end
             end
         },
         },
91번째 줄: 115번째 줄:
             formatter = "{{뱃지|공사중|$value}}",
             formatter = "{{뱃지|공사중|$value}}",
             validate = function(gameMeta, scheme)
             validate = function(gameMeta, scheme)
                 if not gameMeta.construction then return false end
                local construction = t.walk(gameMeta, {"construction"})
                 if gameMeta.construction == true then return {{key = "value", value = ""}} end
                 if not construction then return false end
                 return {{key = "value", value = gameMeta.construction}}
                 if construction == true then return {{key = "value", value = ""}} end
                 return {{key = "value", value = construction}}
             end
             end
         },
         },
100번째 줄: 125번째 줄:
             formatter = "[[분류:$title]]",
             formatter = "[[분류:$title]]",
             validate = function(gameMeta, scheme)
             validate = function(gameMeta, scheme)
                 local progressData = t.find(scheme.properties.progress.oneOf, function(progress)
                 local progress = t.walk(gameMeta, {"progress"})
                     return progress.const == 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)
                 end)
                 if progressData == nil then return false end
                 if progressData == nil then return false end
111번째 줄: 139번째 줄:
             formatter = "[[분류:$title 게임]]",
             formatter = "[[분류:$title 게임]]",
             validate = function(gameMeta, scheme)
             validate = function(gameMeta, scheme)
                 local age = gameMeta.rating.libertygame.age
                 local age = t.walk(gameMeta, {"rating", "libertygame", "age"})
                 local ageData = t.find(scheme.properties.rating.oneOf[2].properties.libertygame.properties.age.oneOf, function(ageData)
                if age == nil then return false end
                     return ageData.const == age
                 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)
                 end)
                 if ageData == nil then return false end
                 if ageData == nil then return false end
123번째 줄: 153번째 줄:
             formatter = "{{뱃지|수리중}}",
             formatter = "{{뱃지|수리중}}",
             validate = function(gameMeta, scheme)
             validate = function(gameMeta, scheme)
                 if not gameMeta.repair then return false end
                local repair = t.walk(gameMeta, {"repair"})
                 if gameMeta.repair == true then return {{key = "value", value = ""}} end
                 if not repair then return false end
                 return {{key = "value", value = gameMeta.repair}}
                 if repair == true then return {{key = "value", value = ""}} end
                 return {{key = "value", value = repair}}
             end
             end
         },
         },
132번째 줄: 163번째 줄:
             formatter = "[[분류:$title 게임]]",
             formatter = "[[분류:$title 게임]]",
             validate = function(gameMeta, scheme)
             validate = function(gameMeta, scheme)
                 local genres = gameMeta.genre
                 local genres = t.walk(gameMeta, {"genre"})
                if genres == nil then return false end
                 if type(genres) == "string" then genres = {genres} 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)
                 local genreData = t.filter(t.map(genres, function(genre)
                     return t.find(scheme["$defs"].genre.oneOf, function(genreData)
                     return t.find(genreDef, function(genreData)
                         return genreData.const == genre
                         return genreData.const == genre
                     end)
                     end)
141번째 줄: 174번째 줄:
                     return genreData ~= nil
                     return genreData ~= nil
                 end)
                 end)
 
   
                 return t.map(genreData, function(genreData)
                 return t.map(genreData, function(genreData)
                     return {key = "title", value = genreData.title}
                     return {key = "title", value = genreData.title}

2023년 7월 28일 (금) 00:44 판


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

getGameInfo

이 부분의 본문은 틀:게임 정보입니다.

getGamecard

이 부분의 본문은 틀:게임카드입니다.

getFeaturedCard

이 부분의 본문은 틀:추천평카드입니다.

도보시오


local p = {}

-- 테이블 유틸리티 함수
t = {
    -- js의 find
    find = function(table, func)
        for _, value in ipairs(table) do
            if func(value) then
                return value
            end
        end
        return nil
    end,
    -- js의 map
    map = function(table, func)
        local newTable = {}
        for i, value in ipairs(table) do
            newTable[i] = func(value)
        end
        return newTable
    end,
    -- js의 필터
    filter = function(table, func)
        local newTable = {}
        for _, value in ipairs(table) do
            if func(value) then
                table.insert(newTable, value)
            end
        end
        return newTable
    end,
    --t.walk(gameMeta, {"rating","libertygame","age"})를 호출 시 
    --gameMeta.rating.libertygame.age로 들어가다가 도중에 들어갈 수 없는 구조를 만나면 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, propertyCases, gameMeta)

    local results = {}

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

            -- 배열이 아닌 경우 기본 배열로 변환 
            if type(validatedGroup) ~= 'table' then
                validatedGroup = {}
            end            
            
            -- 2단계 배열이 아닌 경우 한번 더 감싸기
            if #validatedGroup ~= 0 and type(validatedGroup[1]) ~= 'table' then
                validatedGroup = {validatedGroup}
            end

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

    return results
end

-- 첫번째 파라미터에 리버티게임:게임 메타데이터/스키마.json, 
-- 두번째 파라미터에 game.json 넣어서 게임 자동분류 사용 가능 
-- 아직 테스트되지 않음
function p.manualParse(frame)
    local scheme = mw.text.jsonDecode(frame.args[1])
    local gameMeta = mw.text.jsonDecode(frame.args[2])

    -- 속성 케이스 검사할 값, 발견시 반환할 값 정의
    local 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 = "{{뱃지|공사중|$value}}",
            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
        }
    }

    local parsed = p._manualParser(scheme, propertyCases, gameMeta)
    return mw.text.jsonEncode(parsed)
    --return table.concat(parsed)
end


function p.testParser(frame)
    local jsonschema = require('모듈:Jsonschema')

    local validator = jsonschema.generate_validator {
        type = 'object',
        properties = {
          foo = { type = 'string' },
          bar = { type = 'number' },
        },
      }
      
    return mw.text.jsonEncode( validator{ foo='hello', bar=42 } )
end
 

function p.testImportJson(frame)
    local jsonschema = require('모듈:GameJSONParser/scheme.json')

      
    return mw.text.jsonEncode( jsonschema )
end
 

function p.test(frame)
    local jsonschema = require('모듈:Jsonschema')

    local validator = jsonschema.generate_validator {
        type = 'object',
        properties = {
          foo = { type = 'string' },
          bar = { type = 'number' },
        },
      }
      
    return mw.text.jsonEncode( validator{ foo='hello', bar=42 } )
end
 
function p.testjson(frame)
	local encoded = mw.text.jsonDecode(frame.args[1])
	return mw.text.jsonEncode(encoded["$defs"].platform.oneOf)
end
return p