![]() |
VOOZH | about |
This module implements {{crafting usage}}.
--[[ Test page listing important test cases, used to preview before saving any changes. Template:Crafting_usage/test_page --]] localp={} localtitleText=mw.title.getCurrentTitle().text locali18n={ emptyCategory='Empty crafting usage', moduleCrafting=[[Module:Crafting]], moduleSlot=[[Module:Inventory slot]], moduleAliases=[[Module:Inventory slot/Aliases]], moduleText=[[Module:Text]], templateCrafting='Crafting', } p.i18n=i18n localtext=require(i18n.moduleText) localslot=require(i18n.moduleSlot) localaliases=require(i18n.moduleAliases) localcrafting=require(i18n.moduleCrafting) localfunctionfilterFrames(craftingArgs,pinnedItems) -- Create a lookup table to easily determine if a string is a member of pinned items. localpinnedItemsLookup={} for_,entryinpairs(pinnedItems)do pinnedItemsLookup[entry]=true end -- Find any frames in this string that need to be pinned and pin them. localoutputPinnedFrameCount={} localshouldPinOutput=false localfunctionpinFrames(inputString,restrictToMatching,isOutput) ifnotinputStringthenreturnnilend isOutput=isOutputorfalse localpinFrames={}-- Only frames that are pinned localpinnedFrameCount=0 localpinnedFramesIndex={} localallFrames={}-- All input frames localallFrameCount=0 localframeCount=0-- Count how many expanded frames we are in our iteration. Used for restricting output frames to match input frames forframeStrinstring.gmatch(inputString,"[^;]+")do localshouldPin=false frameStr=mw.text.trim(frameStr) localoriginalFrameString=frameStr localframeObj=slot.makeFrame(frameStr,'') localname=(frameObj.name:gsub("[{}]",""))-- If this name is a subframe, remove the braces for alias testing. localsubframe=(frameObj.name:find("[{}]")~=nil)-- If the current frame is a subframe, don't advance the frame count for aliases localexpandedAlias=aliases[name] localisAlias=(expandedAliasandexpandedAlias[1])~=nil localisDesiredItem=(pinnedItemsLookup[name]~=nil)-- If this item is present in our list of items to pin -- Even if we have an exactly matching alias input, we have to step through each frame to log it as pinnable. ifisAlias==trueandisDesiredItemthen shouldPin=true-- Set this frame as adding to the list of pinned frames ifnotsubframethen for_,_inpairs(expandedAlias)do frameCount=frameCount+1 pinnedFramesIndex[frameCount]=true end else frameCount=frameCount+1 pinnedFramesIndex[frameCount]=true end elseifisAlias==falseorsubframe==truethen frameCount=frameCount+1 end ifisAlias-- If this is an alias andnotisDesiredItem-- and we don't want to keep the alias as is and(notisOutputor(isOutputandrestrictToMatching))then-- and we are either not output, or we are output that needs to be restricted. localreplacementString={} for_,candidateinpairs(expandedAlias)do-- Find all pinned items that are part of this alias ifnotsubframethen-- Subframes only actually count as one frame frameCount=frameCount+1 end candidate=candidate.nameorcandidate-- Sometimes alias returns a table of tables ifpinnedItemsLookup[candidate]or(restrictToMatchingandoutputPinnedFrameCount[frameCount])then localcandidateOut=candidate ifframeObj.numthen candidateOut=candidateOut..','..frameObj.num end table.insert(replacementString,candidateOut) pinnedFramesIndex[frameCount]=true-- When we find a good entry, store the number for use by Output end end if#replacementString>0then-- If this alias doesn't have any pinned items in it, leave it alone. ifname:find("^"..slot.i18n.prefixes.any.." ")then -- Simple in place randomization fori=#replacementString,2,-1do localj=math.random(i) replacementString[i],replacementString[j]=replacementString[j],replacementString[i] end else-- If we modify anything that isn't an "Any" alias, force pin the output. shouldPinOutput=true end replacementString=table.concat(replacementString,';') -- The gsub is to put a % in front of every non alphanumeric character in name, this escapes the name so special characters don't act as a pattern match. localfindString='('..name:gsub("(%W)","%%%1")..',?%d*)'-- Also capture the quantity, since the replacement string has the quantity attached. frameStr=frameStr:gsub(findString,replacementString,1)-- Replace the alias name in the frame with the expanded and filtered string shouldPin=true-- If we match with an expanded alias then we have to pin it end end -- Save modified frame to proper location ifisDesiredItemorshouldPinor(restrictToMatchingandoutputPinnedFrameCount[frameCount])then table.insert(pinFrames,frameStr) pinnedFrameCount=pinnedFrameCount+frameCount -- Don't pin an alias, unless its an exact match ifnotisOutputand(notisAliasandisDesiredItem)then pinnedFramesIndex[frameCount]=true-- When we find a good entry, store the number for use by Output end end table.insert(allFrames,frameStr) allFrameCount=allFrameCount+frameCount end ifpinnedFrameCount>0then ifpinnedFrameCount<allFrameCountthen shouldPinOutput=true end fork,vinpairs(pinnedFramesIndex)do outputPinnedFrameCount[k]=v end returntable.concat(pinFrames,';') else returntable.concat(allFrames,';') end end -- for A1, A2, A3, B1, B2, etc for_,arginipairs(crafting.cArgVals)do craftingArgs[arg]=pinFrames(craftingArgs[arg]) end craftingArgs.Output=pinFrames(craftingArgs.Output,shouldPinOutput,true) returncraftingArgs end --[[The main body, which retrieves the data, and returns the relevant crafting templates, sorted alphabetically --]] functionp.dpl(f) localargs=f iff==mw.getCurrentFrame()then args=f:getParent().args else f=mw.getCurrentFrame() end localstartingIngredients=args[1]andtext.split(args[1],'%s*,%s*')or{titleText} localseen={} localingredients={} -- Loop through all defined ingredients, and expand any aliases. for_,entryinpairs(startingIngredients)do ifnotseen[entry]then table.insert(ingredients,entry) seen[entry]=true localexpandedAlias=aliases[entry] ifexpandedAliasthen for_,ainpairs(expandedAlias)do ifnotseen[a]then table.insert(ingredients,(a.nameora)) seen[a]=true end end end end end localshowDescription localtemplates={} localconditions={} for_,ingredientinipairs(ingredients)do conditions[#conditions+1]={'ingredient',ingredient} end localquery=bucket('crafting_recipe') .select('page_name','json') .where(bucket.Or(unpack(conditions))) .limit(500) .run() ifquerythen for_,vinipairs(query)do ifv['page_name']~=titleTextthen-- Do not display results that came from the same page we are operating on, as they will be outdated. localtArgs=mw.text.jsonDecode(v['json']) tArgs['ignoreusage']='1'-- Always set ignore usage for crafting invocations that are usage. iftArgs.descriptionandtArgs.description~=''then showDescription='1' end localnewArgs=filterFrames(tArgs,startingIngredients) localnewSortKey=newArgs.OutputornewArgs.name ifnewSortKeythen table.insert(templates,{args=newArgs,sortKey=newSortKey}) end end end end localtemplateCount=#templates iftemplateCount==0then ifmw.title.getCurrentTitle().nsText==''then returnf:expandTemplate{title='Translation category',args={i18n.emptyCategory,project='0'}} end return'' end table.sort(templates,function(a,b) ifnotathenreturnbend ifnotbthenreturnaend returna.sortKey<b.sortKey end) localinitialArgs=templates[1].args initialArgs.head='1' initialArgs.showname='1' initialArgs.showdescription=showDescription ifnotargs.continuethen templates[templateCount].args.foot='1' end localout={} fori,templateinipairs(templates)do out[i]=crafting.table(template.args) end returntable.concat(out,'\n') end returnp