Module:Jam leaderboards
From VNDev Wiki
Documentation for this module may be created at Module:Jam leaderboards/doc
local p = {}
function p.occurrence( frame )
local rowsToTest = 23
local rowsToShow = 20
if frame.args['rows'] ~= nil then
rowsToShow = tonumber(frame.args['rows'])
rowsToTest = rowsToShow + 3
end
local statType = 'entries'
if frame.args['statType'] ~= nil then
statType = frame.args['statType']
end
local countColLabel = 'Count'
if statType == 'entries' then countColLabel = 'Entries' end
if statType == 'participants' then countColLabel = 'Participants' end
if statType == 'top prize' then countColLabel = 'Top Prize' end
if statType == 'prize pool' then countColLabel = 'Prize Pool' end
resultsTable = p.processOccurrence ( frame.args['rows'], frame.args['statType'], frame.args['date'], frame.args['vnOnly'] )
local myResult = '<table class="wikitable sortable"><tr><th class="headerSort">Rank</th> <th class="headerSort">' .. countColLabel .. '</th> <th class="headerSort">Jam</th></tr>'
for i=1,rowsToTest do
if resultsTable[i] ~= nil then
if resultsTable[i].count ~= 0 and tonumber(resultsTable[i].plainCount) ~= 0 then
myResult = myResult .. '<tr><td>' .. resultsTable[i].rank .. '</td><td>' .. resultsTable[i].count .. '</td><td>' .. resultsTable[i].jam .. '</td></tr>'
end
end
end
myResult = myResult .. '</table>'
return myResult
end
function p.processOccurrence( argRows, argStatType, argDate, argVNOnly )
local rowsToTest = 23
local rowsToShow = 20
if argRows ~= nil then
rowsToShow = tonumber(argRows)
rowsToTest = rowsToShow + 3
end
local statType = 'entries'
if argStatType ~= nil then
statType = argStatType
end
local date = 'Jan 1 2100'
if argDate ~= nil then
date = argDate
end
local vnOnly = false
if argVNOnly == 'VN-specific jams' then
vnOnly = true
end
local query = { '[[Jam occurrence:+]]', '[[Has start date::<' .. date .. ']]', '?#-=jam', '?Has ' .. statType .. '=count', '?Has end date#-F[U]=endDate', '?Modification date#-F[U]=modDate', '?Has ' .. statType .. '#-n=plainCount', '?Is occurrence of#-=occurrenceOf' }
if vnOnly == true then table.insert(query, '[[Is visual novels only::true]]') end
query.limit = rowsToTest
query.sort = 'Has ' .. statType
query.order = 'descending'
local queryResult = mw.smw.ask( query )
if type( queryResult ) == "table" then
local resultsTable = {}
for i=1,rowsToTest do
if queryResult[i] ~= nil then
local row = queryResult[i]
local isTie = false
local rank = i
if i > 1 and queryResult[i-1] ~= nil then
local prevRow = queryResult[i-1]
if prevRow.count == row.count then
isTie = true
rank = i-1
end
end
if i > 2 and queryResult[i-2] ~= nil then
local prevPrevRow = queryResult[i-2]
if prevPrevRow.count == row.count then
isTie = true
rank = i-2
end
end
if i < rowsToTest and queryResult[i+1] ~= nil then
local nextRow = queryResult[i+1]
if nextRow.count == row.count then isTie = true end
end
if i < rowsToTest-1 and queryResult[i+2] ~= nil then
local nextNextRow = queryResult[i+2]
if nextNextRow.count == row.count then isTie = true end
end
local rankToPrint = p.numToOrdinal(rank)
if isTie then rankToPrint = rankToPrint .. ' (tie)' end
local countToPrint = row.count
if statType == 'entries' or statType == 'participants' then
if tonumber(row.endDate) > tonumber(row.modDate) then countToPrint = row.count .. ' (partial)' end
end
if rank <= rowsToShow then
local toAdd = {}
toAdd.rank = rankToPrint
toAdd.count = countToPrint
toAdd.jam = mw.title.new( row.jam ).text
toAdd.plainCount = row.plainCount
toAdd.occurrenceOf = row.occurrenceOf
table.insert(resultsTable, toAdd )
end
end
end
return resultsTable
end
return queryResult
end
function p.series( frame )
local resultsTable = p.processSeries( frame.args['statType'], frame.args['date'], frame.args['vnOnly'] )
local myResult = '<table class="wikitable sortable"><tr><th class="headerSort">Rank</th> <th class="headerSort">Count</th> <th class="headerSort">Jam</th> <th class="headerSort">Includes</th></tr>'
for i=1,13 do
if resultsTable[i] ~= nil then
if resultsTable[i].count ~= 0 then
myResult = myResult .. '<tr><td>' .. resultsTable[i].rank .. '</td><td>' .. resultsTable[i].count .. '</td><td>' .. resultsTable[i].jam .. '</td><td>' .. resultsTable[i].includes .. ' ' .. resultsTable[i].info .. '</td></tr>'
end
end
end
myResult = myResult .. '</table>'
return myResult
end
function p.processSeries( argStatType, argDate, argVNOnly )
local rowsToTest = 13
local rowsToShow = 10
local statType = 'entries'
if argStatType ~= nil then
statType = argStatType
end
local date = 'Jan 1 2100'
if argDate ~= nil then
date = argDate
end
local vnOnly = false
if argVNOnly == 'VN-specific jams' then
vnOnly = true
end
local seriesQuery = {'[[Category:Jam series]]', '?#-=name', '?Has short name=shortName'}
seriesQuery.limit = 500
local seriesList = mw.smw.ask( seriesQuery )
local counts = {}
for i,series in pairs(seriesList) do
local subq = { '[[Jam occurrence:+]]', '[[Has start date::<' .. date .. ']]', '[[Is occurrence of::' .. series.name .. ']]', '?#-=jam', '?Has ' .. statType .. '=count', '?Has end date#-F[Y]=endYear', '?Has end date#-F[U]=endDate', '?Modification date#-F[U]=modDate' }
if vnOnly == true then table.insert(subq, '[[Is visual novels only::true]]') end
subq.limit = 50
local queryResult = mw.smw.ask( subq )
local seriesCount = 0
local latestEnd = 0
local latestName = ''
local partial = ''
if queryResult ~= nil then
for num, row in pairs( queryResult ) do
if type(row.count) == "number" then seriesCount = seriesCount + row.count end
if tonumber(row.endYear) > latestEnd then
if tonumber(row.endDate) > tonumber(row.modDate) and type(row.count) == "number" then
if row.count > 0 then
latestEnd = tonumber(row.endYear)
latestName = mw.title.new( row.jam ).text
partial = ' (partial)'
end
else
latestEnd = tonumber(row.endYear)
latestName = mw.title.new( row.jam ).text
end
end
end
table.insert(counts, { seriesCount, series.shortName, latestEnd, partial, latestName, series.name } )
end
end
table.sort(counts, function (left, right)
return left[1] > right[1]
end)
if type( counts ) == "table" then
local resultsTable = {}
for i=1,rowsToTest do
if counts[i] ~= nil then
local row = counts[i]
local isTie = false
local rank = i
if i > 1 and counts[i-1] ~= nil then
local prevRow = counts[i-1]
if prevRow[1] == row[1] then
isTie = true
rank = i-1
end
end
if i > 2 and counts[i-2] ~= nil then
local prevPrevRow = counts[i-2]
if prevPrevRow[1] == row[1] then
isTie = true
rank = i-2
end
end
if i < rowsToTest and counts[i+1] ~= nil then
local nextRow = counts[i+1]
if nextRow[1] == row[1] then isTie = true end
end
if i < rowsToTest-1 and counts[i+2] ~= nil then
local nextNextRow = counts[i+2]
if nextNextRow[1] == row[1] then isTie = true end
end
local rankToPrint = p.numToOrdinal(rank)
if isTie then rankToPrint = rankToPrint .. ' (tie)' end
if rank <= rowsToShow then
local toAdd = {}
toAdd.rank = rankToPrint
toAdd.count = row[1]
toAdd.jam = mw.title.new( row[2] ).text
toAdd.includes = row[3] .. row[4]
toAdd.info = mw.smw.info(row[5], 'info')
toAdd.longName = row[6]
table.insert( resultsTable, toAdd )
end
end
end
return resultsTable
end
return counts
end
function p.year( frame )
local statType = 'entries'
if frame.args['statType'] ~= nil then
statType = frame.args['statType']
end
local vnOnly = false
if frame.args['vnOnly'] == 'VN-specific jams' then
vnOnly = true
end
local dateNow = os.date("*t", mw.getContentLanguage():formatDate( "U", frame.args['date'] ) )
local maxYear = dateNow.year
if dateNow.month == 1 then maxYear = dateNow.year - 1 end
local myResult = '<table class="wikitable sortable"><tr><th class="headerSort">Year</th> <th class="headerSort">1st</th> <th class="headerSort">2nd</th> <th class="headerSort">3rd</th></tr>'
for i=maxYear,2015,-1 do
local query = { '[[Jam occurrence:+]]', '[[Has start date::>Jan 1 ' .. i .. ']]', '[[Has start date::<Dec 31 ' .. i .. ']]', '?Is occurrence of.Has short name=name', '?Has ' .. statType .. '=count', '?Has end date#-F[U]=endDate', '?Modification date#-F[U]=modDate' }
if vnOnly == true then table.insert(query, '[[Is visual novels only::true]]') end
query.limit = 3
query.sort = 'Has ' .. statType
query.order = 'descending'
local queryResult = mw.smw.ask( query )
local yearToPrint = i
if i == dateNow.year then yearToPrint = i .. ' (partial)' end
myResult = myResult .. '<tr><td>' .. yearToPrint .. '</td>'
for j=1,3 do
local part = ''
if tonumber(queryResult[j].endDate) > tonumber(queryResult[j].modDate) then part = ', partial' end
myResult = myResult .. '<td>' .. queryResult[j].name .. ' (' .. queryResult[j].count .. part .. ')</td>'
end
myResult = myResult .. '</tr>'
end
myResult = myResult .. '</table>'
return myResult
end
function p.seriesStats( frame )
local name = frame.args['name']
local results = {}
results[1] = p.processOccurrence( nil, 'entries', nil, '' )
results[2] = p.processOccurrence( nil, 'participants', nil, '' )
results[3] = p.processSeries( 'entries', nil, '')
results[4] = p.processSeries( 'participants', nil, '')
results[5] = p.processOccurrence( nil, 'top prize', nil, '')
results[6] = p.processOccurrence( nil, 'prize pool', nil, '')
local annotations = { 'most entries', 'most participants', 'most cumulative entries', 'most cumulative participants', 'largest top prize', 'largest prize pool' }
local ranks = { '', '', '', '', '', '' }
local toRet = ''
for j=1,6 do
for i=1,23 do
if results[j][i] ~= nil then
if ranks[j] == '' then
if results[j][i].occurrenceOf == name or results[j][i].longName == name then
ranks[j] = results[j][i].rank
end
end
end
end
if ranks[j] ~= '' then
if toRet ~= '' then toRet = toRet .. ', ' end
toRet = toRet .. ranks[j] .. ' ' .. annotations[j]
end
end
if toRet == '' then return 'None recorded' end
return toRet
end
function p.numToOrdinal( num )
if num == 1 then return '1st' end
if num == 2 then return '2nd' end
if num == 3 then return '3rd' end
return num .. 'th'
end
return p