模块:Pwd

From Limbo Wiki

刷新密码盘

密码是55555或12345。

连锁密码盘示例

{{#invoke:pwd|getMulti|<密码盘类别>|<密码盘位数>|List=<密码列表>|startClass=[开始类]|prefix=[前缀]}}
<密码盘类别>:选填Number或Word,或是使用{{#invoke:pwd|setJson|<Json>}}导入的新类别。
<密码盘位数>:字面意思。
<密码列表>:表示不同的密码,不同密码间用空格间隔,见计算器。
[开始类]:可选项,表示最开始显示的密码盘的样子。注:如果该参数存在,默认会隐藏密码盘。
[前缀]:可选项,顾名思义。

具体示例请自行查看源代码。

如果密码盘有特殊规则(比如指定某一字母为特殊密码等),可以使用下方的旧密码盘。

[已过期]单密码盘简要教程(来自AtomTheory,仍可以使用)

一、密码盘源代码

模块:Pwd的密码盘分为数字密码盘和字母密码盘,二者对应的最基础的源代码如下(未指定任何特殊按键,即为上方出现的密码盘):
数字密码盘:{{#invoke:pwd|get|Number|a}}
字母密码盘:{{#invoke:pwd|get|Word|b}}

目前已有使用的页面的密码盘通常都以以下源代码为基础,在其中添加元素而成:
{{#invoke:pwd|get|Word|class=def|2=w|2-10=def|3-8=def}}
(请注意,此处的“3-8=def”在有的地方“def”需要变成其他内容,具体在下方有提及)

每一个{{#invoke:pwd|get|Word|a}}对应一个键盘,密码盘包括多行此类代码

此处可以按照自己的需求加上指定按钮,只需要在其中加入相应指定内容(详见下方第二部分),用“|”隔开即可

二、指定按钮

以字母密码盘为例,在模块中,若需要指定正确密码为password,并且指定此步骤输入字母正确为r,错误为w。

  • 那么在第一步时密码盘就应该是这个样子:

{{#invoke:pwd|get|Word|class=def|2=w|2-10=def|3-8=def|1-10=r}}

此处的class=def指密码盘处于初始状态,“def”可以更改为其他任何文本内容
这里2-10对应的是“X”,即清空按钮;3-8对应的是退格按钮
“1-10=r”即指定第一行第十个按钮(p)对应r状态(相当于就是指定了一个TreeButton)
“2=w”即指定剩余所有没有被指定的按钮对应w状态(即剩余字母都是错误的)

  • 假设第一步输入正确,第二部则是这个样子:

{{#invoke:pwd|get|Word|class=r|2=rw|2-10=def|3-8=def|2-1=rr|style=display:none;}}

此处的“style=display:none;”即指这行代码对应的键盘只有在密码盘处于w状态时才会展示,避免页面打开时此键盘错误地出现(页面打开时应当只有初始状态键盘显示)影响观感以及解密体验。
此处,密码盘第一步正确(class=r)。此时若输入错误,为了让下一步退格可以回到此步骤而非被直接判错,指定错误状态为rw,相当于按照步骤顺序记录了不同步骤的正确情况,下一步时按退格可以回到r状态(3-8=r)。输入a正确,则a对应状态为rr。

  • 假设第一步输入错误,第二步则是这个样子:

{{#invoke:pwd|get|Word|class=w|2=ww|2-10=def|3-8=def|style=display:none;}}

显然,此处由于第一步已经错误(因此密码盘已经处于w的状态,class=w),所以接下来除了退格和清空之外无论做什么都是错误的,故不需要指定特殊按钮,只需要指定“2=ww”即可

  • 假设前面均输入正确,最后一步则是这个样子:

{{#invoke:pwd|get|Word|class=rrrrrrr|2=wwwwwwww|2-10=def|3-8=rrrrrr|2-3=rrrrrrrr|style=display:none;}}

这里因为是最后一步,输入过后直接判定密码是否正确,故不论任何的含有错误字母的情况都视作全错处理更佳。

三、排版建议&其他

排版建议

对于一般的只有一个密码的密码盘,建议按照如下排版顺序摆放(这里用def,w,r等代指处于不同状态的键盘):

 def
 
 w
 r

 ww
 rw
 rr
 
 www
 rww
 rrw
 rrr
 
 ……

实装密码盘参考

这里提供了两个目前在百科内已经实装的密码盘作为参考,对密码盘占用字节数不了解的可以查看。看完上方教程还有不理解的也可以查看这两个密码盘的代码并结合本指南进行参考。

金域的密码盘,位置金域#回忆,含有两个6位字母密码(不完全常规,双密码且有特殊指定按钮)加一个3位字母密码,占用字节约3400
末日的幻想乡的密码盘,位置末日的幻想乡#异闻·调查记录·07,4位字母密码,占用字节不足1000


-- Author: User:Staf_Irity
local function NonNull(value,def)
	if(type(value) == "nil") then return def end;
	return value;
end

local Data = mw.loadData('Module:pwd/Data');
local p = {}

--[[@Deprecated function p.setTable(frame)]]--
--[[@Deprecated function p.setJson(frame)]]--
--[[@Deprecated function p.setJsonTemplate(frame) {See id#38864}]]--
function get(t,list,class,style,dm)
	local pwd = mw.html.create('span')
		:attr('class',class)
		:attr('style',style)
		:attr('data-mode',dm);
	local a = 0;
	for i,v in ipairs(t) do
		if not(i==1) then pwd:tag('br') end
		for i2,v2 in ipairs(v) do
			a = a + 1;
			button = pwd:tag('span')
				:attr('class','lw-treebut')
				:attr('role','button')
				:attr('id',NonNull(list[a],list[0]))
				:wikitext(v2);
		end
	end
	return tostring(pwd);
end -- WIP

function p.get(frame) -- @Deprecated
	if ((type(frame.args[1]) == "nil") or (type(frame.args[2]) == "nil")) then
		return 'Error: Not Enough Arguments.'; --第一个是名字,第二个是默认的指向
	end
	t = Data[frame.args[1]];
	if (type(t) == 'nil') then return 'Error: Table Not Found.' end
	
	-- Start --
	class = frame.args["class"];
	if (type(class) == 'nil') then class='' end
	if (type(frame.args[DisablePWD]) == 'nil') then class= 'lw-treediv '.. class end
	class = 'lw-pwd ' ..class
	
	style = frame.args["style"];
	if (type(style) == 'nil') then style='' end
	
	pwd = mw.html.create('span')
		:attr('class',class)
		:attr('style',style)
		:attr('data-mode',frame.args[1]);
	
	for i,v in ipairs(t) do
		if not(i==1) then pwd:tag('br') end
		for i2,v2 in ipairs(v) do
			button = pwd:tag('span')
				:attr('class','lw-treebut')
				:attr('role','button')
			id = frame.args[tostring(i)..'-'..tostring(i2)]
			if (type(id) == 'nil') then id = frame.args[2] end
			button:attr('id',id):wikitext(v2);
		end
	end
	mw.log(tostring(pwd));
	return tostring(pwd);
end
function p.getSingle(frame)
	if ((type(frame.args[1]) == "nil") or (type(frame.args[2]) == "nil")) then
		return 'Error: Not Enough Arguments.'; --第一个是名字,第二个是默认的指向
	end
	t = Data[frame.args[1]];
	if (type(t) == 'nil') then return 'Error: Table Not Found.' end
	
	-- Start --
	class = 'lw-treediv lw-pwd ' .. NonNull(frame.args["class"],'');
	style = NonNull(frame.args["style"],"");
	
	pwd = mw.html.create('span')
		:attr('class',class)
		:attr('style',style)
		:attr('data-mode',frame.args[1]);
	local a = 0;
	for i,v in ipairs(t) do
		if not(i==1) then pwd:tag('br') end
		for i2,v2 in ipairs(v) do
			a = a + 1;
			-- mw.log(a);
			button = pwd:tag('span')
				:attr('class','lw-treebut')
				:attr('role','button')
			id = frame.args["key" .. tostring(a)]
			if (type(id) == 'nil') then id = frame.args[2] end
			button:attr('id',id):wikitext(v2);
		end
	end
	-- mw.log(tostring(pwd));
	return tostring(pwd);
end
--[[
p.getSingle{args={'Number','a',['key11']='b'}}
含义:数字密码盘,默认为a,第11个按钮为b

p.getSingle{args={'Number','a',['key11']='b',['class']='b',['style']='display:none;'}}
含义:数字密码盘,默认为a,第11个按钮为b,<带有b这一class,默认隐藏>(即当id=b的treebutton被点击后才显示)
]]--
-- p.getMulti{args={'Number','5',List='64112'}}
function p.getMulti(frame) -- getMulti(string Type,int Levels,[string]List,<string startClass>,<string prefix>)
	if ((type(frame.args[1]) == "nil") or (type(frame.args[2]) == "nil") or type(frame.args["List"]) == "nil") then
		return "'''Error: Not Enough Arguments.'''"; end
	
	local t = Data[frame.args[1]];
	if (type(t) == 'nil') then return "'''Error: Table Not Found.'''" end
	
	-- get length
	local l = 1; -- length
	local delBut,backBut;
	for i,v in ipairs(t) do
		for i2,v2 in ipairs(v) do
			if(v2 == 'X') then delBut = l end
			if(v2 == '←') then backBut = l end
			l = l + 1;
		end
	end
	
	local pwds = {};
	for i in string.gmatch(frame.args["List"],"([^%s]+)") do table.insert(pwds, tonumber(i)) end
	
	local treePWD = {};
	local pwdLength = tonumber(frame.args[2]);
	local tmp1;
	for it,v in ipairs(pwds) do
		for i=1, pwdLength do
			tmp1 = math.fmod(v,l^i);
			v = v - tmp1;
			if(type(treePWD[pwdLength-i]) == 'nil') then treePWD[pwdLength-i] = {} end
			if(type(treePWD[pwdLength-i][v]) == 'nil') then treePWD[pwdLength-i][v] = {} end
			for i2=pwdLength-i,pwdLength-1 do
				if(type(treePWD[i2]) == 'nil') then treePWD[i2] = {} end
				if(type(treePWD[i2][v]) == 'nil') then treePWD[i2][v] = {} end
				treePWD[i2][v][v] = 0;
			end
			treePWD[pwdLength-i][v][v+tmp1] = tmp1 / (l^(i-1));
		end
	end -- unzip
	
	-- REAL Tree Buttons
	local prefix = NonNull(frame.args["prefix"],"pwd");
	local startClass = NonNull(frame.args["startClass"],prefix .. "0-0");
	tmp1 = {-- Start
		[delBut] = startClass,
		[backBut] = startClass,
	};
	local tmp2 = ""; 
	if(not(type(frame.args["startClass"]) == "nil")) then tmp2 = "display:none;" end
	for it,v in pairs(treePWD[0][0]) do tmp1[v] = prefix .. "1-" .. it end
	local txt = get(t, tmp1, 'lw-treediv lw-pwd '.. startClass , tmp2, frame.args[1]);-- Start
	tmp2 = nil;
	
	for i=1,pwdLength-1 do
		for it,v in pairs(treePWD[i]) do
			tmp1 = {
				[delBut] = startClass,
				[backBut] = prefix .. (i-1) .. "-" .. (it - math.fmod(it,l^(pwdLength-i+1))),
			}
			for it2,v2 in pairs(treePWD[i][it]) do tmp1[v2] = prefix .. (i+1) .. "-" .. it2 end
			if(i == pwdLength-1) then tmp1[0] = startClass end
			txt = txt .. get(t, tmp1, 'lw-treediv lw-pwd '.. prefix .. i .. "-" .. it, "display:none;", frame.args[1]);
		end
	end
	mw.log(txt);
	return txt;
end
function p.test(frame) -- p.test{args={12,2,3,2,4,9}} 64112
	local l = tonumber(frame.args[1]) + 1;
	local g = table.getn(frame.args) - 1;
	local num = 0;
	for i,v in ipairs(frame.args) do
		if not(i == 1) then num = num + tonumber(v)*(l^(g - i + 1)); end
		mw.log(tonumber(v))
	end
	mw.log(num);
end
return p