Module:Rotten Tomatoes data/sandbox explained

local Error = require('Module:Error')local getArgs = require('Module:Arguments').getArgs

local p =

local months =

local aliasesQ =

local aliasesP =

-- Helper functions ------------------------------------------------------------local function falsy(x) return x

false or x

nil or x

or x

0 or type(x)

'table' and next(x)

nilend

-- copied from Module:wdlocal function parseDate(dateStr, precision) precision = precision or "d"

local i, j, index, ptr local parts =

if dateStr

nil then return parts[1], parts[2], parts[3] -- year, month, day end

-- 'T' for snak values, '/' for outputs with '/Julian' attached i, j = dateStr:find("[T/]")

if i then dateStr = dateStr:sub(1, i-1) end

local from = 1

if dateStr:sub(1,1)

"-" then -- this is a negative number, look further ahead from = 2 end

index = 1 ptr = 1

i, j = dateStr:find("-", from)

if i then -- year parts[index] = tonumber(mw.ustring.gsub(dateStr:sub(ptr, i-1), "^%+(.+)$", "%1"), 10) -- remove '+' sign (explicitly give base 10 to prevent error)

if parts[index]

-0 then parts[index] = tonumber("0") -- for some reason, 'parts[index] = 0' may actually store '-0', so parse from string instead end

if precision

"y" then -- we're done return parts[1], parts[2], parts[3] -- year, month, day end

index = index + 1 ptr = i + 1

i, j = dateStr:find("-", ptr)

if i then -- month parts[index] = tonumber(dateStr:sub(ptr, i-1), 10)

if precision

"m" then -- we're done return parts[1], parts[2], parts[3] -- year, month, day end

index = index + 1 ptr = i + 1 end end

if dateStr:sub(ptr) ~= "" then -- day if we have month, month if we have year, or year parts[index] = tonumber(dateStr:sub(ptr), 10) end

return parts[1], parts[2], parts[3] -- year, month, dayend

-- nil dates precede all reasonable dates since year becomes 1local function datePrecedesDate(aY, aM, aD, bY, bM, bD) aY, aM, aD = aY or 1, aM or 1, aD or 1 bY, bM, bD = bY or 1, bM or 1, bD or 1 if aY < bY then return true end if aY > bY then return false end if aM < bM then return true end if aM > bM then return false end if aD < bD then return true end return falseend

-- format options: 'dmy', 'mdy', 'ymd', 'iso'local function format_date(Y, M, D, format) format = format or 'MDY' local s = (D or ) .. (months[M] or ) .. (Y or ) return mw.getCurrentFrame:expandTemplateend

---------------------------------------------------------------------------------- Returns either QID, true, or ErrorString, falselocal function getentityID(args) local entityID = args.qid if falsy(entityID) then local title = args.title if falsy(title) then local currentID = mw.wikibase.getEntityIdForCurrentPage if currentID then return currentID, true end return Error.error, false else -- if not mw.title.makeTitle(0, title).exists then -- return Error.error, false -- end entityID = mw.wikibase.getEntityIdForTitle(title) if not entityID then return Error.error, false end return entityID, true end end --At this point we should have an entityID. Check if valid. if not mw.wikibase.isValidEntityId(entityID) then return Error.error, false end if not mw.wikibase.entityExists(entityID) then return Error.error, false end return entityID, trueend

local function point_in_time(statement) if not statement.qualifiers then return nil, nil, nil end local pointintime = statement.qualifiers[aliasesP.pointInTime] if pointintime then return parseDate(pointintime[1].datavalue.value.time) end return nil, nil, nilend

local function access_date(statement) if statement.references then local accessdate = statement.references[1].snaks[aliasesP.retrieved] if accessdate then return parseDate(accessdate[1].datavalue.value.time) end end return nil, nil, nilend

local function date_from_statement(statement) local Y, M, D = point_in_time(statement) if Y then return Y, M, D end Y, M, D = access_date(statement) if Y then return Y, M, D end if statement.rank

'preferred' then return 1, 1, 3 elseif statement.rank

'normal' then return 1, 1, 2 end return 1, 1, 1end

local function reviewedby_RT(statement) if not statement.qualifiers then return false end local x = statement.qualifiers[aliasesP.reviewScoreBy] return x and x[1].datavalue.value.id

aliasesQ.RottenTomatoesend

local function score_type(statement) local x = nil if statement.qualifiers then x = statement.qualifiers[aliasesP.determinationMethod] end if x then x = x[1].datavalue.value.id end local y = if statement.mainsnak.snaktype

'value' then y = statement.mainsnak.datavalue.value end if x

aliasesQ.RottenTomatoesScore then return 'percent' elseif x

aliasesQ.RottenTomatoesAverage then return 'average' elseif string.match(y, '^[0-9]%%$') or string.match(y, '^[1-9][0-9]%%$') or string.match(y, '^100%%$') then return 'percent' elseif string.match(y, '^[0-9] percent$') or string.match(y, '^[1-9][0-9] percent$') or string.match(y, '^100 percent$') then return 'percent' elseif string.match(y, '^%d/10$') or string.match(y, '^%d%.%d%d?/10$') then return 'average' elseif string.match(y, '^%d out of 10$') or string.match(y, '^%d%.%d%d? out of 10$') then return 'average' end return nilend

local function most_recent_score_statement(entityID, scoretype) scoretype = scoretype or 'percent' local score_statements = mw.wikibase.getAllStatements(entityID, aliasesP.reviewScore) local newest, nY, nM, nD for i, v in ipairs(score_statements) do local Y, M, D = date_from_statement(v) if v.rank ~= 'deprecated' and v.mainsnak.snaktype

'value' and reviewedby_RT(v) and score_type(v)

scoretype and not datePrecedesDate(Y, M, D, nY, nM, nD) then nY, nM, nD = Y, M, D newest = v end end return newestend

local function get_score(entityID, scoretype) scoretype = scoretype or 'percent' local x = most_recent_score_statement(entityID, scoretype) if x

nil then return nil end return x.mainsnak.datavalue.valueend

local function get_count(entityID, args) local x = most_recent_score_statement(entityID) if x

nil then return nil end local y = x.qualifiers[aliasesP.numberOfReviews] if y

nil then return nil end local retval = string.match(y[1].datavalue.value.amount, '%d+') -- dont get sign if args ~= nil and args.spell then local s = for key, val in pairs(args) do if key

1 or key

'qid' or key

'title' then

elseif type(key) ~= 'number' then s[key] = val end end return mw.getCurrentFrame:expandTemplate end return retvalend

local function get_rtid(entityID, noprefix) local rtid_statements = mw.wikibase.getBestStatements(entityID, aliasesP.RottenTomatoesId) local newest, nY, nM, nD for i, v in ipairs(rtid_statements) do local Y, M, D = date_from_statement(v) if not datePrecedesDate(Y, M, D, nY, nM, nD) then nY, nM, nD = Y, M, D newest = v end end if newest

nil then return nil end newest = newest.mainsnak.datavalue.value if noprefix then newest = string.sub(newest, string.find(newest, '/') + 1) end return newestend

local function get_url(entityID) local rtid = get_rtid(entityID) if rtid

nil then return nil end local x = mw.wikibase.getBestStatements(aliasesP.RottenTomatoesId, aliasesP.formatterURL) return (string.gsub(x[1].mainsnak.datavalue.value, '$1', rtid))end

local function get_date(entityID, part, format) local z = most_recent_score_statement(entityID) if z

nil then return nil end local Y, M, D = date_from_statement(z) if part

'year' then return Y or elseif part

'month' then return months[M] or elseif part

'day' then return D or end return format_date(Y, M, D, format)end

local function get_access_date(entityID, format) local z = most_recent_score_statement(entityID) if z

nil then return nil end local Y, M, D = access_date(z) if not Y then Y, M, D = point_in_time(z) end return format_date(Y, M, D, format)end

local function get_asof(entityID, args) local s = for key, val in pairs(args) do if key

1 or key

'qid' or key

'title' then elseif key

2 then s[1] = get_date(entityID, 'year') elseif key

3 then s[2] = get_date(entityID, 'month') elseif key

4 then s[3] = get_date(entityID, 'day') elseif type(key)

'number' then s[key-1] = val else s[key] = val end end return mw.getCurrentFrame:expandTemplateend

local function get_rtprose(entityID, args) local s = s[1] = string.match(s[1], '%d+') s[2] = string.match(s[2], '%d%.%d%d?') or string.match(s[2], '%d') s["access-date"] = get_access_date(entityID, args.df) for key, val in pairs(args) do if key

1 or key

'qid' or key

'title' then elseif type(key)

'number' then s[key + 2] = val else s[key] = val end end return mw.getCurrentFrame:expandTemplateend

local function get_edit_icon(entityID) return require('Module:EditAtWikidata')._showMessageend

local function get_table(entityID) return get_score(entityID) .. ' (' .. get_count(entityID) .. ' reviews)'end

function p.main(frame) local args = getArgs(frame,) return p._main(args)end

function p._main(args) local entityID, is_good = getentityID(args) if not is_good then return entityID -- which is the error message in this case end local command = args[1] if falsy(command) then return Error.error end command = string.lower(command) local retval if command

'score' then retval = get_score(entityID, 'percent') elseif command

'average' then retval = get_score(entityID, 'average') elseif command

'count' then retval = get_count(entityID, args) elseif command

'rtid' then retval = get_rtid(entityID, args.noprefix) elseif command

'url' then retval = get_url(entityID) elseif command

'date' then retval = get_date(entityID, 'date', args.df) elseif command

'year' then retval = get_date(entityID, command) elseif command

'month' then retval = get_date(entityID, command) elseif command

'day' then retval = get_date(entityID, command) elseif command

'access date' or command

'accessdate' or command

'access-date' then retval = get_access_date(entityID, args.df) elseif command

'as of' or command

'asof' then retval = get_asof(entityID, args) elseif command

'prose' then retval = get_rtprose(entityID, args) elseif command

'edit' then retval = get_edit_icon(entityID) elseif command

'table' then retval = get_table(entityID) else return Error.error end if falsy(retval) then return Error.error end return retvalend

return p