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

리버티게임, 모두가 만들어가는 자유로운 게임
imported>Hsl0
편집 요약 없음
imported>Hsl0
편집 요약 없음
134번째 줄: 134번째 줄:


function getData(source)
function getData(source)
local result, data = pcall(mw.text.jsonDecode, mw.title.new(rel2abs(source)):getContent() or source)
local result, data = unpack pcall(mw.text.jsonDecode, mw.title.new(rel2abs(source)):getContent() or source)
if result then
if result then

2023년 4월 5일 (수) 23:27 판


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

게임 메타데이터를 다루는 모듈입니다.

icon

게임 메타데이터를 바탕으로 게임아이콘을 만듭니다.

{{#invoke:metadata|icon|(게임 문서)}}

get

게임 메타데이터의 특정 속성을 불러옵니다. 이때, 원본 값을 그대로 불러오는 것이 아닌 활용하기 편한 형태로 불러오는 기능입니다. 일반적으로는 원본 값이지만, 특별히 수정된 경우 가공된 값이 불러와집니다.

{{#invoke:metadata|get|(게임 문서)|(속성)}}

rating

게임 등급을 불러옵니다. 리버티게임 등급 분류와 게임물관리위원회 등급 분류를 구별하지 않고 바로 등급만 가져옵니다.

{{#invoke:metadata|get|(게임 문서)|rating}}

if

게임 메타데이터의 특정 속성의 존재 여부를 확인하고, 있을 때와 없을 때 나올 내용을 구분합니다.

{{#invoke:metadata|if|(게임 문서)|(속성)|(있을 때)|(없을 때)}}

role

특정 사용자가 게임의 제작자인지, 기여자(조력자)인지, 이에 해당되지 않는 지 확인합니다. 제작자일 경우 author가, 기여자일 경우 contributor가 반환됩니다.

{{#invoke:metadata|role|(게임 문서)|(사용자 이름)}}

resolve

게임 메타데이터가 있는 문서를 찾습니다. 대상 문서의 하위 문서에 game.json이 없다면 그 상위 문서에서 찾고, 없으면 반복하며 있으면 찾은 game.json 문서에서 멈춥니다. 대상 문서가 넘겨주기 문서인 경우 넘어가는 문서를 기준으로 찾습니다. mw.title 객체를 반환하며 문자열로 변환해 문서 제목을 얻거나, :getContent() 함수를 통해 game.json 내용을 확인할 수 있습니다. 찾은 game.json 문서가 없다면 nil이 반환됩니다.

p.resolve(title)

root

게임의 최상위 문서를 찾습니다. 정확히는 게임 메타데이터(game.json)을 하위 문서로 갖는 문서를 찾습니다. mw.title 객체를 반환하며 문자열로 변환해 문서 제목을 얻거나, :getContent() 함수를 통해 game.json 내용을 확인할 수 있습니다. 찾은 game.json 문서가 없다면 루트 페이지가 반환됩니다.

p.root(title)

subpage

게임의 최상위 문서 바로 아래에 있는 하위 문서를 찾습니다. 첫번째 인수는 현재 위치 및 최상위 문서입니다. 현재 위치를 넣으면 root 함수를 통해 알아서 최상위 문서를 찾아줍니다. 두번째 인수는 하위 문서의 상대적 경로입니다. 예를 들어, 어떤 게임/하위라는 문서를 가리키고 싶을 경우 두번째 인수에 /하위만 입력하면 절대 경로인 어떤 게임/하위를 반환합니다. mw.title 객체를 반환하며 문자열로 변환해 문서 제목을 얻거나, :getContent() 함수를 통해 game.json 내용을 확인할 수 있습니다. 찾은 game.json 문서가 없다면 nil이 반환됩니다.

p.subpage(title, path)


local p = {} -- 패키지

-- 상수 시작
local DEFAULT_IMG = {
	progress = "[[파일:Progress unknown.svg|완성도 정도를 입력하세요|링크=|16px]]",
	openness = "[[파일:Crystal Clear action info.svg|17px|개방성 정도를 입력하세요|링크=]]",
	tech = "[[파일:Tech unknown.svg|게임 구조를 입력하세요|링크=]]",
	rating = "[[파일:GRAC Square Template.svg|16px|게임 제작자가 이용가 등급 판정을 하지 않았습니다|링크=]]"
}

local PROGRESS_IMG = {
	[0] = "[[파일:Progress base.svg|변경하지 말아야 하는 공사중인 게임|링크=|16px]]",
	[1] = "[[파일:Progress low.svg|조금 완성된 게임|링크=|16px]]",
	[2] = "[[파일:Progress medium.svg|중간 정도 완성된 게임|링크=|16px]]",
	[3] = "[[파일:Progress high.svg|거의 완성된 게임|링크=|16px]]",
	[4] = "[[파일:Progress full.svg|완성되었지만 추가할 수 있는 게임|링크=|16px]]",
	[5] = "[[파일:백괴게임 완성도 7단계.svg|완성되어 변경하지 말아야 하는 게임|링크=|16px]]"
}

local ABANDON = {} --Symbol

local OPENNESS_IMG = {
	[false] = "[[파일:Crystal Clear action editdelete.png|17px|편집 금지|링크=]]",
	partial = "[[파일:Crystal Clear bot on trial2.png|17px|규칙에 따라 편집 가능|링크=]]",
	[true] = "[[파일:Crystal Clear app clean.png|17px|편집 가능|링크=]]",
	[ABANDON] = "[[파일:Crystal Clear app logout.png|17px|버려진 게임|링크=]]"
}

local TECH_IMG = {
	link = "[[파일:Tech link.svg|링크|링크=]]",
	cgi = "[[파일:Tech CGI.svg|CGI|링크=]]",
	windows = "[[파일:Windows logo - 2021.svg|16px|윈도우|링크=]]",
	db = "[[파일:Tech DB.svg|DB|링크=]]",
	javascript = "[[파일:Tech JS.svg|16px|자바스크립트|링크=]]",
	lua = "[[파일:Tech Lua.svg|16px|루아|링크=]]",
	other = "[[파일:Tech other.svg|기타|링크=]]"
}

local RATING_IMG = {
	[18] = "[[파일:GRAC 18 Square.svg|16px|청소년 이용불가|링크=]]",
	[15] = "[[파일:GRAC 15 Square.svg|16px|15세 이용가|링크=]]",
	[12] = "[[파일:GRAC 12 Square.svg|16px|12세 이용가|링크=]]",
	all = "[[파일:GRAC All Square.svg|16px|전체 이용가|링크=]]",
	test  = "[[파일:GRAC Test Square.svg|16px|평가하고 있는 중입니다|링크=]]"
}
-- 상수 끝 코드 시작

function userLink(user, display)
	local title = mw.title.new(user, 'User')
	return '[[' .. tostring(title) .. '|' .. (display or title.subpageText) .. ']]'
end

function p.icon(frame)
	local title = frame.args[1]
	local doc = mw.title.new(title .. '/game.json')
	
	if not doc.exists then
		return mw.html.create('span'):addClass('error')
									 :wikitext('[[' .. title .. '/game.json]] 문서가 존재하지 않습니다. 메타데이터 문서를 만들어 주세요.')
									 :done()
	end
	
	local data = mw.text.jsonDecode(doc:getContent())
	local icon = mw.html.create('span'):addClass('gameicon')
	
	-- status
	local openness = data.openness
	if data.abandon then
		openness = ABANDON
	end
	
	local status = icon:tag('span'):addClass('gameicon-status')
	                :wikitext(data.progress ~= nil and PROGRESS_IMG[data.progress] or DEFAULT_IMG.progress)
	                :wikitext(openness ~= nil and OPENNESS_IMG[openness] or DEFAULT_IMG.openness)
	                :wikitext(data.tech and TECH_IMG[data.tech] or DEFAULT_IMG.tech)
	                :wikitext(data.rating and RATING_IMG[data.rating] or DEFAULT_IMG.rating)
                    :attr{
                        ['data-progress'] = data.progress,
                        ['data-openness'] = openness == ABANDON and "true" or tostring(openness),
                        ['data-tech'] = data.tech,
                        ['data-rating'] = data.rating
                    }
    if data.abandon then
    	status:attr('data-abandon', '')
    end
    
    -- name
    icon:tag('span'):addClass('gameicon-name')
    				:wikitext('[[' .. title .. '|' .. (data.name or title) .. ']]')
    
    -- maker
    local contributor
    if data.contributor then
    	contributor = ""
    	
    	if type(data.contributor) == 'string' then
    		data.contributor = {data.contributor}
    	end
    	
    	for index, name in pairs(data.contributor) do
    		contributor = contributor .. userLink(name) .. ", "
    	end
    	
    	contributor = contributor:sub(1, -3) .. " 사용자께서 도와주셨습니다."
    end
    
    local author
    if data.author then
	    if type(data.author) == 'table' then
	    	author = ""
	    	
	    	for index, name in pairs(data.author) do
	    		author = author .. userLink(name) .. ", "
	    	end
	    	
	    	author = author:sub(1, -2)
	    else
	    	author = userLink(data.author)
	    end
	    
	    icon:tag('span'):addClass('gameicon-maker')
	    				:wikitext(contributor and frame:expandTemplate{
	    					title = '툴팁',
	    					args = {author, contributor, sym = 1, class='messagebox gameicon-contributor'}
	    				} or author)
	end
	
	return icon:allDone()
end

function rel2abs(rel, base)
	return mw.getCurrentFrame():callParserFunction('#rel2abs', rel, base)
end

function getData(source)
	local result, data = unpack pcall(mw.text.jsonDecode, mw.title.new(rel2abs(source)):getContent() or source)
	
	if result then
		return data
	else
		error('유효하지 않은 게임 메타데이터', 2)
	end
end

function p.role(frame)
	local data = getData(frame.args[1])
	local user = mw.title.new(frame.args[2], 'User')
	local authors = type(data.author) == 'string' and {data.author} or data.author
	local contributors = type(data.contributor) == 'string' and {data.contributor} or data.contributor
	
	for index, author in ipairs(authors) do
		if mw.title.equals(user, mw.title.new(author, 'User')) then
			return 'author'
		end
	end
	
	for index, contributor in ipairs(contributors) do
		if mw.title.equals(user, mw.title.new(contributor, 'User')) then
			return 'contributor'
		end
	end
end

return p