모듈:연습장
- 장기간에 걸쳐 수정이 필요한 경우 별도로 모듈페이지를 만드는 것을 추천합니다.
- 다음 문서가 도움이 될 수 있습니다.
- 다른 이름공간에 대한 연습은 아래에서 가능합니다.
- 낙서장을 비우려면 여기 를 클릭하세요.
위 설명은 모듈:연습장/설명문서의 내용을 가져와 보여주고 있습니다. (편집 | 역사) 이 모듈에 대한 수정 연습과 시험은 연습장 (만들기 | 미러)과 시험장 (만들기)에서 할 수 있습니다. 분류는 /설명문서에 넣어주세요. 이 모듈에 딸린 문서. |
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