表单在form:功法查询页面创建

使用模板:功法查询传递参数

查询功能在模块:GongFa/query实现

特殊:执行查询/功法查询页面使用该功能


local p = {}

local Linq = require('Module:Linq')
local Union = require('Module:Union')
local Const = require("Module:Const/name")
local Link = require('Module:GongFa/link')
local Translate = require('Module:GongFa/value').change
local Util = require('Module:Util')
local CalcExpr = require('Module:CalcExpr')
require('Module:no globals')

local function Err(...)
	error('\n'..mw.allToString(...))
end

local function Find(query)
	query = query or {}
	query['_id'] = { ["$regex"] = '^Data:GongFa\.tab' }
	query['id'] = {['$gte'] = 0}
	query.data6 = {['$gt'] = -1}
	return mw.huiji.db.find(query)
end

local function Fit(patternList, props, noError)
	if (patternList or '')=='' then return nil end
	local key = '$in'
	if string.sub(patternList, 1, 1)=='-' then
		patternList = string.sub(patternList, 2)
		key = '$nin'
	end
	patternList = mw.text.split(patternList, '、', true)
	props = Linq(props)
	local result = {}
	for i,pattern in ipairs(patternList) do
		local match = props:First(function(kvp) return mw.ustring.find(kvp[2], pattern, 1, true) end)
		if match==nil and not noError then
			Err('"'..pattern..'"','不是有效的输入')
		end
		table.insert(result, match and match[1])
	end
	if #result==0 then return end
	return {[key] = result}
end --标准化输入

local function MatchAll(str, arr)
	for _,v in ipairs(arr) do
		if not mw.ustring.find(str, v) then
			return false
		end
	end
	return true
end --字符串中同时包含多个匹配串

local function Highlight(str, orList)
	if str==nil or orList==nil then return end
	for _,andList in ipairs(orList) do
		if MatchAll(str, andList) then
			for _,pattern in ipairs(andList) do
				str = mw.ustring.gsub(str, '('..pattern..')', '<b style="color:orange;">%1</b>', 1)
			end
		end
	end
	return str
end

local function Wikitable(source, keys)
	local result = '<table class="wikitable">\n\n<tr>\n'
	result = result..'<th>'..'</th>\n'
	for _,v in pairs(keys) do
		result = result..'<th>'..v..'</th>\n'
	end
	result = result..'</tr>\n\n'
	for _,tuple in ipairs(source) do
		result = result..'<tr>\n'
		local name = tuple['名称']
		if name==nil then error(mw.dumpObject(tuple)) end
		result = result..'<td>'..Link(name)..'</td>\n'
		for _,key in pairs(keys) do
			local value = tuple[key] or 0
			if value==nil then Err(mw.dumpObject(tuple), key) end
			result = result..'<td>'..value..'</td>\n'
		end
		result = result..'</tr>\n\n'
	end
	result = result..'</table>'
	return result
end

local function MatchPredicate(orList, value)
	if value==nil then return false end
	for _,andList in ipairs(orList) do
		if MatchAll(value, andList) then
			return true
		end
	end
end

local function SplitPredicate(rawPredicate)
	local empty = true
	local orList = mw.text.split(rawPredicate, 'or', true)
	for i,v in ipairs(orList) do
		orList[i] = Util.filter(mw.text.split(v, ' ', true), function(s) return s~='' end)
		if #orList[i] > 0 then empty = false end
	end
	if empty then return end
	return orList
end

local function ColorPower(s)
	return Util.color(s, Const.color[s=='心法正练' and 4 or 9])
end

function p.e(frame)
	return p.f(frame:getParent(), true)
end

function p.f(frame, showHint) --p.f()
	local args = frame and frame.args or {['心法']='处世立场',['类型']='-奇窍、拳',['数量']=20}--['门派'] = '武当、少林',['描述'] = '刀法 无敌.天下' , ['品级'] = '123456789',  ['属性'] = '纯阳、混元',['描述'] = '(暂.说明',  ['排序'] = '{内力}/{占格}'

	local query = {}

	query.data0 = args['名称'] and {["$regex"] = args['名称'] }

	local showKeys = {}
	local function write(key)
		if Util.getText(key) then return end
		if not Util.contains(showKeys, key) then
			table.insert(showKeys, key)
		end
	end

	local desPredicate = args['描述']
	if desPredicate then
		desPredicate = SplitPredicate(desPredicate)
		if desPredicate and #desPredicate>0 and #desPredicate[1]>0 then
			local patterns = {}
			for _,v in ipairs(desPredicate[1]) do
				table.insert(patterns, {
					data99 = {["$regex"] = v}
				})
			end
			query["$and"] = patterns
			write('描述')
		else
			desPredicate = nil
		end
	end

	if args['品级'] then
		local num = tonumber(args['品级'])
		if not num or num<=0 then Err('[品级]应为一串0~9的数字') end
		local arr = {}
		while(num>0) do
			table.insert(arr, 10 - num%10)
			num = math.floor(num/10)
		end
		query.data2 = {['$in'] = arr}
	end

	query.data3 = Fit(args['门派'], Const.gang)
	query.data4 = Fit(args['属性'], Const.qi)

	local typ = args['类型']
	if typ then
		local data1 = Fit(typ, Const.gongfa, true)
		local data6 = Fit(typ, Const['运功位'], true)
		--if data1==nil and data6==nil then Err('"'..typ..'"','不是有效的输入') end
		local tmp = {}
		if data1 then table.insert(tmp,{data1=data1}) end
		if data6 then table.insert(tmp,{data6=data6}) end
		local key = string.sub(typ, 1, 1)=='-' and '$and' or '$or'
		query[key] = tmp
	end
	
	local list = Linq(Find(query))

	local powerPredicate = args['心法']
	if powerPredicate then
		powerPredicate = SplitPredicate(powerPredicate)
		if powerPredicate and #powerPredicate>0 then
			local allPower = require("Module:GongFa/power")
			list = list:Where(function(tuple)
				for _,key in ipairs{'data103', 'data104'} do
					local power = allPower[tuple[key]]
					if power and MatchPredicate(powerPredicate, power[1]) then
						return true
					end
				end
			end)
			write(ColorPower('心法正练'))
			write(ColorPower('心法逆练'))
		else
			powerPredicate = nil
		end
	end

	list = list:Select(function(t) return Union{t,Translate(t),default = 0} end)

	local filter = args['筛选']
	if filter then
		local s = filter
		local func,keysInExpr = CalcExpr(s)
		list = list:Where(func)
		for key,_ in pairs(keysInExpr) do
			write(key)
		end
	end
	local count = list:Count()
	if count==0 then return '没有符合条件的功法' end
	local limit = tonumber(args['数量']) or 20
	local hint = '共查得'..count..'个符合条件的功法'
	if limit<count then
		hint = hint..',显示其中的'..limit..'个'
	end
	local amount = math.min(count, limit)
	local sort = args['排序']
	if sort then
		write(sort)
		local func,argsInExpr = CalcExpr(sort)
		list = list:Select(function(t) 
			t[sort] = func(t)
			return t
		end)
		list = list:TakeByOrder(amount, function(t) return -t[sort] end)
		for key,_ in pairs(argsInExpr) do
			write(key)
		end
	else
		list = list:TakeByOrder(amount, function(t) return t.id end)
	end
	list = list:Select(function(t)
		t[ColorPower('心法正练')] = Highlight(t['心法正练'], powerPredicate)
		t[ColorPower('心法逆练')] = Highlight(t['心法逆练'], powerPredicate)
		t['描述'] = Highlight(t['描述'], desPredicate)
		return t
	end)
	return (showHint and hint..':<br>\n' or '')..Wikitable(list, showKeys)
end

return p
avatar