Jump to content

Module:Random

विकिपीडिया से
मॉड्यूल बिबरनलेख[बनाईं]
-- This module contains a number of functions that make use of random numbers.

localcfg={}

--------------------------------------------------------------------------------------
-- Configuration
--------------------------------------------------------------------------------------

-- Set this to true if your wiki has a traffic rate of less than one edit every two minutes or so.
-- This will prevent the same "random" number being generated many times in a row until a new edit is made
-- to the wiki. This setting is only relevant if the |same= parameter is set.
cfg.lowTraffic=false

-- If cfg.lowTraffic is set to true, and the |same= parameter is set, this value is used for the refresh rate of the random seed.
-- This is the number of seconds until the seed is changed. Getting this right is tricky. If you set it too high, the same number
-- will be returned many times in a row. If you set it too low, you may get different random numbers appearing on the same page,
-- particularly for pages that take many seconds to process.
cfg.seedRefreshRate=60

--------------------------------------------------------------------------------------
-- End configuration
--------------------------------------------------------------------------------------

localp={}-- For functions available from other Lua modules.
locall={}-- For functions not available from other Lua modules, but that need to be accessed using table keys.

localyesno=require('Module:Yesno')
localmakeList=require('Module:List').makeList

--------------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------------

localfunctionraiseError(msg)
-- This helps to generate a wikitext error. It is the calling function's responsibility as to how to include it in the output.
returnmw.ustring.format('<b class= "error" >[[Module:Random]] error: %s.</b>',msg)
end

--------------------------------------------------------------------------------------
-- random number function
--------------------------------------------------------------------------------------

localfunctiongetBigRandom(l,u)
-- Gets a random integer between l and u, and is not limited to RAND_MAX.
localr=0
localn=2^math.random(30)-- Any power of 2.
locallimit=math.ceil(53/(math.log(n)/math.log(2)))
fori=1,limitdo
r=r+math.random(0,n-1)/(n^i)
end
returnmath.floor(r*(u-l+1))+l
end

functionl.number(args)
-- Gets a random number.
first=tonumber(args[1])
second=tonumber(args[2])
-- This needs to use if statements as math.random won't accept explicit nil values as arguments.
iffirstthen
ifsecondthen
iffirst>secondthen-- Second number cannot be less than the first, or it causes an error.
first,second=second,first
end
returngetBigRandom(first,second)
else
returngetBigRandom(1,first)
end
else
returnmath.random()
end
end

--------------------------------------------------------------------------------------
-- Date function
--------------------------------------------------------------------------------------

functionl.date(args)
-- This function gets random dates, and takes timestamps as positional arguments.
-- With no arguments specified, it outputs a random date in the current year.
-- With two arguments specified, it outputs a random date between the timestamps.
-- With one argument specified, the date is a random date between the unix epoch (1 Jan 1970) and the timestamp.
-- The output can be formatted using the "format" argument, which works in the same way as the #time parser function.
-- The default format is the standard Wikipedia timestamp.
locallang=mw.language.getContentLanguage()

localfunctiongetDate(format,ts)
localsuccess,date=pcall(lang.formatDate,lang,format,ts)
ifsuccessthen
returndate
end
end

localfunctiongetUnixTimestamp(ts)
localunixts=getDate('U',ts)
ifunixtsthen
returntonumber(unixts)
end
end

localt1=args[1]
localt2=args[2]

-- Find the start timestamp and the end timestamp.
localstartTimestamp,endTimestamp
ifnott1then
-- Find the first and last second in the current year.
localcurrentYear=tonumber(getDate('Y'))
localcurrentYearStartUnix=tonumber(getUnixTimestamp('1 Jan '..tostring(currentYear)))
localcurrentYearEndUnix=tonumber(getUnixTimestamp('1 Jan '..tostring(currentYear+1)))-1
startTimestamp='@'..tostring(currentYearStartUnix)-- @ is used to denote Unix timestamps with lang:formatDate.
endTimestamp='@'..tostring(currentYearEndUnix)
elseift1andnott2then
startTimestamp='@0'-- the Unix epoch, 1 January 1970
endTimestamp=t1
elseift1andt2then
startTimestamp=t1
endTimestamp=t2
end

-- Get Unix timestamps and return errors for bad input (or for bugs in the underlying PHP library, of which there are unfortunately a few)
localstartTimestampUnix=getUnixTimestamp(startTimestamp)
localendTimestampUnix=getUnixTimestamp(endTimestamp)
ifnotstartTimestampUnixthen
returnraiseError(' "'..tostring(startTimestamp)..' "was not recognised as a valid timestamp')
elseifnotendTimestampUnixthen
returnraiseError(' "'..tostring(endTimestamp)..' "was not recognised as a valid timestamp')
elseifstartTimestampUnix>endTimestampUnixthen
returnraiseError('the start date must not be later than the end date (start date: "'..startTimestamp..' ", end date:" '..endTimestamp..' ")')
end

-- Get a random number between the two Unix timestamps and return it using the specified format.
localrandomTimestamp=getBigRandom(startTimestampUnix,endTimestampUnix)
localdateFormat=args.formator'H:i, d F Y (T)'
localresult=getDate(dateFormat,'@'..tostring(randomTimestamp))
ifresultthen
returnresult
else
returnraiseError(' "'..dateFormat..' "is not a valid date format')
end
end

--------------------------------------------------------------------------------------
-- List functions
--------------------------------------------------------------------------------------

localfunctionrandomizeArray(t,limit)
-- Randomizes an array. It works by iterating through the list backwards, each time swapping the entry
-- "i" with a random entry. Courtesy of Xinhuan at http://forums.wowace /showthread.php?p=279756
-- If the limit parameter is set, the array is shortened to that many elements after being randomized.
-- The lowest possible value is 0, and the highest possible is the length of the array.
locallen=#t
fori=len,2,-1do
localr=math.random(i)
t[i],t[r]=t[r],t[i]
end
iflimitandlimit<lenthen
localret={}
fori,vinipairs(t)do
ifi>limitthen
break
end
ret[i]=v
end
returnret
else
returnt
end
end

localfunctionremoveBlanks(t)
-- Removes blank entries from an array so that it can be used with ipairs.
localret={}
fork,vinpairs(t)do
iftype(k)=='number'then
table.insert(ret,k)
end
end
table.sort(ret)
fori,vinipairs(ret)do
ret[i]=t[v]
end
returnret
end

localfunctionmakeSeparator(sep)
ifsep=='space'then
-- Include an easy way to use spaces as separators.
return' '
elseiftype(sep)=='string'then
-- If the separator is a recognised MediaWiki separator, use that. Otherwise use the value of sep if it is a string.
localmwseparators={'dot','pipe','comma','tpt-languages'}
for_,mwsepinipairs(mwseparators)do
ifsep==mwsepthen
returnmw.message.new(sep..'-separator'):plain()
end
end
returnsep
end
end

localfunctionmakeRandomList(args)
locallist=removeBlanks(args)
list=randomizeArray(list,tonumber(args.limit))
returnlist
end

functionl.item(args)
-- Returns a random item from a numbered list.
locallist=removeBlanks(args)
locallen=#list
iflen>=1then
returnlist[math.random(len)]
end
end

functionl.list(args)
-- Randomizes a list and concatenates the result with a separator.
locallist=makeRandomList(args)
localsep=makeSeparator(args.seporargs.separator)
returntable.concat(list,sep)
end

functionl.text_list(args)
-- Randomizes a list and concatenates the result, text-style. Accepts separator and conjunction arguments.
locallist=makeRandomList(args)
localsep=makeSeparator(args.seporargs.separator)
localconj=makeSeparator(args.conjorargs.conjunction)
returnmw.text.listToText(list,sep,conj)
end

functionl.array(args)
-- Returns a Lua array, randomized. For use from other Lua modules.
returnrandomizeArray(args.t,args.limit)
end

--------------------------------------------------------------------------------------
-- HTML list function
--------------------------------------------------------------------------------------

functionl.html_list(args,listType)
-- Randomizes a list and turns it into an HTML list. Uses [[Module:List]].
listType=listTypeor'bulleted'
locallistArgs=makeRandomList(args)-- Arguments for [[Module:List]].
fork,vinpairs(args)do
iftype(k)=='string'then
listArgs[k]=v
end
end
returnmakeList(listType,listArgs)
end

--------------------------------------------------------------------------------------
-- The main function. Called from other Lua modules.
--------------------------------------------------------------------------------------

functionp.main(funcName,args,listType)
-- Sets the seed for the random number generator and passes control over to the other functions.
localsame=yesno(args.same)
ifnotsamethen
-- Generates a different number every time the module is called, even from the same page.
-- This is because of the variability of os.clock (the time in seconds that the Lua script has been running for).
math.randomseed(mw.site.stats.edits+mw.site.stats.pages+os.time()+math.floor(os.clock()*1000000000))
else
ifnotcfg.lowTrafficthen
-- Make the seed as random as possible without using anything time-based. This means that the same random number
-- will be generated for the same input from the same page - necessary behaviour for some wikicode templates that
-- assume bad pseudo-random-number generation.
localstats=mw.site.stats
localviews=stats.viewsor0-- This is not always available, so we need a backup.
localseed=views+stats.pages+stats.articles+stats.files+stats.edits+stats.users+stats.activeUsers+stats.admins-- Make this as random as possible without using os.time() or os.clock()
math.randomseed(seed)
else
-- Make the random seed change every n seconds, where n is set by cfg.seedRefreshRate.
-- This is useful for low-traffic wikis where new edits may not happen very often.
math.randomseed(math.floor(os.time()/cfg.seedRefreshRate))
end
end
iftype(args)~='table'then
error('the second argument to p.main must be a table')
end
returnl[funcName](args,listType)
end

--------------------------------------------------------------------------------------
-- Process arguments from #invoke
--------------------------------------------------------------------------------------

localfunctionmakeWrapper(funcName,listType)
-- This function provides a wrapper for argument-processing from #invoke.
-- listType is only used with p.html_list, and is nil the rest of the time.
returnfunction(frame)
-- If called via #invoke, use the args passed into the invoking template, or the args passed to #invoke if any exist.
-- Otherwise assume args are being passed directly in from the debug console or from another Lua module.
localorigArgs
ifframe==mw.getCurrentFrame()then
origArgs=frame:getParent().args
fork,vinpairs(frame.args)do
origArgs=frame.args
break
end
else
origArgs=frame
end
-- Trim whitespace and remove blank arguments.
localargs={}
fork,vinpairs(origArgs)do
iftype(v)=='string'then
v=mw.text.trim(v)
end
ifv~=''then
args[k]=v
end
end
returnp.main(funcName,args,listType)
end
end

-- Process arguments for HTML list functions.
localhtmlListFuncs={
bulleted_list='bulleted',
unbulleted_list='unbulleted',
horizontal_list='horizontal',
ordered_list='ordered',
horizontal_ordered_list='horizontal_ordered'
}
forfuncName,listTypeinpairs(htmlListFuncs)do
p[funcName]=makeWrapper('html_list',listType)
end

-- Process arguments for other functions.
localotherFuncs={'number','date','item','list','text_list'}
for_,funcNameinipairs(otherFuncs)do
p[funcName]=makeWrapper(funcName)
end

returnp