<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FNotsniwiast%2Flearn</id>
	<title>Module:Sandbox/Notsniwiast/learn - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FNotsniwiast%2Flearn"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Notsniwiast/learn&amp;action=history"/>
	<updated>2026-04-21T09:07:08Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Sandbox/Notsniwiast/learn&amp;diff=145925&amp;oldid=prev</id>
		<title>imported&gt;Notacardoor at 19:14, 9 September 2021</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Notsniwiast/learn&amp;diff=145925&amp;oldid=prev"/>
		<updated>2021-09-09T19:14:52Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local Error = require(&amp;#039;Module:Error&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local aliasesQ = {&lt;br /&gt;
    RottenTomatoes          = &amp;quot;Q105584&amp;quot;,&lt;br /&gt;
    RottenTomatoesScore     = &amp;quot;Q108403393&amp;quot;,&lt;br /&gt;
    RottenTomatoesAverage   = &amp;quot;Q108403540&amp;quot;,&lt;br /&gt;
    Fandango                = &amp;quot;Q5433722&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local aliasesP = {&lt;br /&gt;
	RottenTomatoesId        = &amp;quot;P1258&amp;quot;,&lt;br /&gt;
	reviewScore             = &amp;quot;P444&amp;quot;,&lt;br /&gt;
	reviewScoreBy           = &amp;quot;P447&amp;quot;,&lt;br /&gt;
	numberOfReviews         = &amp;quot;P7887&amp;quot;,&lt;br /&gt;
	pointInTime             = &amp;quot;P585&amp;quot;,&lt;br /&gt;
	determinationMethod     = &amp;quot;P459&amp;quot;,&lt;br /&gt;
    author                  = &amp;quot;P50&amp;quot;,&lt;br /&gt;
    publisher               = &amp;quot;P123&amp;quot;,&lt;br /&gt;
    statedIn                = &amp;quot;P248&amp;quot;,&lt;br /&gt;
    language                = &amp;quot;P407&amp;quot;,&lt;br /&gt;
    retrieved               = &amp;quot;P813&amp;quot;,&lt;br /&gt;
    referenceURL            = &amp;quot;P854&amp;quot;,&lt;br /&gt;
    archiveURL              = &amp;quot;P1065&amp;quot;,&lt;br /&gt;
    title                   = &amp;quot;P1476&amp;quot;,&lt;br /&gt;
    formatterURL            = &amp;quot;P1630&amp;quot;,&lt;br /&gt;
    archiveDate             = &amp;quot;P2960&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Helper functions ------------------------------------------------------------&lt;br /&gt;
function mw.ustring.startswith(s, pattern, plain)&lt;br /&gt;
	return mw.ustring.find(s, pattern, 1, plain) == 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- 0, nil, empty string, or empty table&lt;br /&gt;
local function falsy(x)&lt;br /&gt;
	if x == nil or x == &amp;#039;&amp;#039; or x == &amp;#039;&amp;#039; then&lt;br /&gt;
		return true&lt;br /&gt;
	elseif type(x) == &amp;#039;table&amp;#039; and next(x) == nil then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- copied from Module:wd&lt;br /&gt;
local function parseDate(dateStr, precision)&lt;br /&gt;
    precision = precision or &amp;quot;d&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local i, j, index, ptr&lt;br /&gt;
    local parts = {nil, nil, nil}&lt;br /&gt;
&lt;br /&gt;
    if dateStr == nil then&lt;br /&gt;
        return parts[1], parts[2], parts[3]  -- year, month, day&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- &amp;#039;T&amp;#039; for snak values, &amp;#039;/&amp;#039; for outputs with &amp;#039;/Julian&amp;#039; attached&lt;br /&gt;
    i, j = dateStr:find(&amp;quot;[T/]&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if i then&lt;br /&gt;
        dateStr = dateStr:sub(1, i-1)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local from = 1&lt;br /&gt;
&lt;br /&gt;
    if dateStr:sub(1,1) == &amp;quot;-&amp;quot; then&lt;br /&gt;
        -- this is a negative number, look further ahead&lt;br /&gt;
        from = 2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    index = 1&lt;br /&gt;
    ptr = 1&lt;br /&gt;
&lt;br /&gt;
    i, j = dateStr:find(&amp;quot;-&amp;quot;, from)&lt;br /&gt;
&lt;br /&gt;
    if i then&lt;br /&gt;
        -- year&lt;br /&gt;
        parts[index] = tonumber(mw.ustring.gsub(dateStr:sub(ptr, i-1), &amp;quot;^\+(.+)$&amp;quot;, &amp;quot;%1&amp;quot;), 10)  -- remove &amp;#039;+&amp;#039; sign (explicitly give base 10 to prevent error)&lt;br /&gt;
&lt;br /&gt;
        if parts[index] == -0 then&lt;br /&gt;
            parts[index] = tonumber(&amp;quot;0&amp;quot;)  -- for some reason, &amp;#039;parts[index] = 0&amp;#039; may actually store &amp;#039;-0&amp;#039;, so parse from string instead&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        if precision == &amp;quot;y&amp;quot; then&lt;br /&gt;
            -- we&amp;#039;re done&lt;br /&gt;
            return parts[1], parts[2], parts[3]  -- year, month, day&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        index = index + 1&lt;br /&gt;
        ptr = i + 1&lt;br /&gt;
&lt;br /&gt;
        i, j = dateStr:find(&amp;quot;-&amp;quot;, ptr)&lt;br /&gt;
&lt;br /&gt;
        if i then&lt;br /&gt;
            -- month&lt;br /&gt;
            parts[index] = tonumber(dateStr:sub(ptr, i-1), 10)&lt;br /&gt;
&lt;br /&gt;
            if precision == &amp;quot;m&amp;quot; then&lt;br /&gt;
                -- we&amp;#039;re done&lt;br /&gt;
                return parts[1], parts[2], parts[3]  -- year, month, day&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            index = index + 1&lt;br /&gt;
            ptr = i + 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if dateStr:sub(ptr) ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        -- day if we have month, month if we have year, or year&lt;br /&gt;
        parts[index] = tonumber(dateStr:sub(ptr), 10)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return parts[1], parts[2], parts[3]  -- year, month, day&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- nil dates precede all other (reasonable) dates since year becomes 1&lt;br /&gt;
local function datePrecedesDate(aY, aM, aD, bY, bM, bD)&lt;br /&gt;
    aY, aM, aD = aY or 1, aM or 1, aD or 1&lt;br /&gt;
    bY, bM, bD = bY or 1, bM or 1, bD or 1&lt;br /&gt;
    if aY &amp;lt; bY then return true end&lt;br /&gt;
    if aY &amp;gt; bY then return false end&lt;br /&gt;
    if aM &amp;lt; bM then return true end&lt;br /&gt;
    if aM &amp;gt; bM then return false end&lt;br /&gt;
    if aD &amp;lt; bD then return true end&lt;br /&gt;
    return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Returns either QID, true, or ErrorString, false&lt;br /&gt;
local function getEntityId(frame)&lt;br /&gt;
	local entityId = frame.args.qid&lt;br /&gt;
	local title = frame.args.title&lt;br /&gt;
	if falsy(entityId) then&lt;br /&gt;
		if falsy(title) then&lt;br /&gt;
			local currentPageEntityId = mw.wikibase.getEntityIdForCurrentPage()&lt;br /&gt;
			if currentPageEntityId then&lt;br /&gt;
				return currentPageEntityId, true&lt;br /&gt;
			end&lt;br /&gt;
			return Error.error({&amp;#039;No Wikidata item connected to current page. Need qid or title parameter.&amp;#039;}), false&lt;br /&gt;
		else&lt;br /&gt;
			if not mw.title.makeTitle(0, title).exists then&lt;br /&gt;
				return Error.error({&amp;#039;Article &amp;#039; .. title .. &amp;#039; does not exist.&amp;#039;}), false&lt;br /&gt;
			end&lt;br /&gt;
			entityId = mw.wikibase.getEntityIdForTitle(title)&lt;br /&gt;
			if not entityId then&lt;br /&gt;
				return Error.error({&amp;#039;Article &amp;quot;&amp;#039; .. title .. &amp;#039;&amp;quot; has no connected Wikidata item.&amp;#039;}), false&lt;br /&gt;
			end&lt;br /&gt;
			return entityId, true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	--At this point we should have an entityId. Check if valid.&lt;br /&gt;
	if not mw.wikibase.isValidEntityId(entityId) then&lt;br /&gt;
		return Error.error({&amp;#039;Invalid Q-identifier.&amp;#039;}), false&lt;br /&gt;
	end&lt;br /&gt;
	if not mw.wikibase.entityExists(entityId) then&lt;br /&gt;
		return Error.error({&amp;#039;Wikidata item &amp;#039; .. entityId .. &amp;#039; does not exist.&amp;#039;}), false&lt;br /&gt;
	end&lt;br /&gt;
	return entityId, true&lt;br /&gt;
	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function date_from_statement(statement)&lt;br /&gt;
	local pointintime = statement.qualifiers[aliasesP.pointInTime]&lt;br /&gt;
	if not falsy(pointintime) then&lt;br /&gt;
		pointintime = pointintime[1].datavalue.value.time&lt;br /&gt;
		return parseDate(pointintime)&lt;br /&gt;
	end&lt;br /&gt;
	if statement.references[1] then&lt;br /&gt;
		local accessdate = statement.references[1].snaks[aliasesP.retrieved]&lt;br /&gt;
		if not falsy(accessdate) then&lt;br /&gt;
			accessdate = accessdate[1].datavalue.value.time&lt;br /&gt;
			return parseDate(accessdate)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return nil, nil, nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function reviewedby_RT(statement)&lt;br /&gt;
	local x = statement.qualifiers[aliasesP.reviewScoreBy]&lt;br /&gt;
	if falsy(x) then return false end&lt;br /&gt;
	x = x[1].datavalue.value.id&lt;br /&gt;
	if x ~= aliasesQ.RottenTomatoes then return false end&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- statement should be a review score (P444) statement&lt;br /&gt;
local function score_type(statement)&lt;br /&gt;
	local x = statement.qualifiers[aliasesP.determinationMethod]&lt;br /&gt;
	if falsy(x) then return nil end&lt;br /&gt;
	x = x[1].datavalue.value.id&lt;br /&gt;
	if x == aliasesQ.RottenTomatoesScore then return &amp;#039;percent&amp;#039; end&lt;br /&gt;
	if x == aliasesQ.RottenTomatoesAverage then return &amp;#039;average&amp;#039; end&lt;br /&gt;
	local y = statement.mainsnak.datavalue.value&lt;br /&gt;
	if string.match(y, &amp;#039;^0%%$&amp;#039;) or string.match(y, &amp;#039;^[1-9][0-9]%%$&amp;#039;) or string.match(y, &amp;#039;^100%%$&amp;#039;) then&lt;br /&gt;
		return &amp;#039;percent&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if string.match(y, &amp;#039;^0 percent$&amp;#039;) or string.match(y, &amp;#039;^[1-9][0-9] percent$&amp;#039;) or string.match(y, &amp;#039;^100 percent$&amp;#039;) then&lt;br /&gt;
		return &amp;#039;percent&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if string.match(y, &amp;#039;^%d/10$&amp;#039;) or string.match(y, &amp;#039;^%d.%d%d?/10$&amp;#039;) then&lt;br /&gt;
		return &amp;#039;average&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if string.match(y, &amp;#039;^%d out of 10$&amp;#039;) or string.match(y, &amp;#039;^%d.%d%d? out of 10$&amp;#039;) then&lt;br /&gt;
		return &amp;#039;average&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function most_recent_score_statement(entityId, scoretype)&lt;br /&gt;
	scoretype = scoretype or &amp;#039;percent&amp;#039;&lt;br /&gt;
	local score_statements = mw.wikibase.getAllStatements(entityId, aliasesP.reviewScore)&lt;br /&gt;
	if falsy(score_statements) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local newest = nil&lt;br /&gt;
	local nY, nM, nD = nil, nil, nil&lt;br /&gt;
	for i, v in ipairs(score_statements) do&lt;br /&gt;
		local Y, M, D = date_from_statement(v)&lt;br /&gt;
		if v.rank ~= &amp;#039;deprecated&amp;#039; and reviewedby_RT(v) and score_type(v)==scoretype and not datePrecedesDate(Y, M, D, nY, nM, nD) then&lt;br /&gt;
			nY, nM, nD = Y, M, D&lt;br /&gt;
			newest = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return newest&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_score(entityId, scoretype)&lt;br /&gt;
	scoretype = scoretype or &amp;#039;percent&amp;#039;&lt;br /&gt;
	local x = most_recent_score_statement(entityId, scoretype)&lt;br /&gt;
	if x then return x.mainsnak.datavalue.value end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_count(entityId)&lt;br /&gt;
	local x = most_recent_score_statement(entityId)&lt;br /&gt;
	local y = x.qualifiers[aliasesP.numberOfReviews]&lt;br /&gt;
	if falsy(y) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	return string.match(y[1].datavalue.value.amount, &amp;#039;%d+&amp;#039;) -- dont get sign&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_rtid(entityId)&lt;br /&gt;
	local x = mw.wikibase.getBestStatements(entityId, aliasesP.RottenTomatoesId)&lt;br /&gt;
	if falsy(x) then return nil end&lt;br /&gt;
	return x[1].mainsnak.datavalue.value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_url(entityId)&lt;br /&gt;
	local rtid = get_rtid(entityId)&lt;br /&gt;
	if rtid == nil then return nil end&lt;br /&gt;
	local x = mw.wikibase.getBestStatements(aliasesP.RottenTomatoesId, aliasesP.formatterURL)&lt;br /&gt;
	subbed, k = string.gsub(x[1].mainsnak.datavalue.value, &amp;#039;$1&amp;#039;, rtid)&lt;br /&gt;
	return subbed&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_date(entityId, part)&lt;br /&gt;
	local Y, M, D = date_from_statement(most_recent_score_statement(entityId))&lt;br /&gt;
	local months = {&amp;#039;January&amp;#039;, &amp;#039;February&amp;#039;, &amp;#039;March&amp;#039;, &amp;#039;April&amp;#039;, &amp;#039;May&amp;#039;, &amp;#039;June&amp;#039;,&lt;br /&gt;
		&amp;#039;July&amp;#039;, &amp;#039;August&amp;#039;, &amp;#039;September&amp;#039;, &amp;#039;October&amp;#039;, &amp;#039;November&amp;#039;, &amp;#039;December&amp;#039;}&lt;br /&gt;
	if part == &amp;#039;year&amp;#039; then&lt;br /&gt;
		if Y then&lt;br /&gt;
			return Y&lt;br /&gt;
		else&lt;br /&gt;
			return &amp;#039;&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if part == &amp;#039;month&amp;#039; then&lt;br /&gt;
		if M then&lt;br /&gt;
			return months[M]&lt;br /&gt;
		else&lt;br /&gt;
			return &amp;#039;&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if part == &amp;#039;day&amp;#039; then&lt;br /&gt;
		if D then&lt;br /&gt;
			return D&lt;br /&gt;
		else&lt;br /&gt;
			return &amp;#039;&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local s = &amp;#039;&amp;#039;&lt;br /&gt;
	if Y then&lt;br /&gt;
		s = Y&lt;br /&gt;
		if M then&lt;br /&gt;
			s = M .. &amp;#039; &amp;#039; .. s&lt;br /&gt;
			if D then&lt;br /&gt;
				s = D .. &amp;#039; &amp;#039; .. s&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.test(frame)&lt;br /&gt;
	mw.log(&amp;#039;starting&amp;#039;)&lt;br /&gt;
	local entityId, is_good = getEntityId(frame)&lt;br /&gt;
	if not is_good then&lt;br /&gt;
		return entityId -- which is the error message&lt;br /&gt;
	end&lt;br /&gt;
	local command = frame.args[1]&lt;br /&gt;
	if falsy(command) then&lt;br /&gt;
		return Error.error({&amp;#039;Missing command.&amp;#039;})&lt;br /&gt;
	end&lt;br /&gt;
	local retval = &amp;#039;&amp;#039;&lt;br /&gt;
	if command == &amp;#039;score&amp;#039; then&lt;br /&gt;
		retval = get_score(entityId, &amp;#039;percent&amp;#039;)&lt;br /&gt;
	elseif command == &amp;#039;average&amp;#039; then&lt;br /&gt;
		retval = get_score(entityId, &amp;#039;average&amp;#039;)&lt;br /&gt;
	elseif command == &amp;#039;count&amp;#039; then&lt;br /&gt;
		retval = get_count(entityId)&lt;br /&gt;
	elseif command == &amp;#039;rtid&amp;#039; then&lt;br /&gt;
		retval = get_rtid(entityId)&lt;br /&gt;
	elseif command == &amp;#039;url&amp;#039; then&lt;br /&gt;
		retval = get_url(entityId)&lt;br /&gt;
	elseif command == &amp;#039;date&amp;#039; or command == &amp;#039;year&amp;#039; or command == &amp;#039;month&amp;#039; or command == &amp;#039;day&amp;#039; then&lt;br /&gt;
		retval = get_date(entityId, command)&lt;br /&gt;
	else&lt;br /&gt;
		return Error.error({&amp;#039;Invalid command.&amp;#039;})&lt;br /&gt;
	end&lt;br /&gt;
	if falsy(retval) then&lt;br /&gt;
		return Error.error({&amp;#039;Data for &amp;#039; .. command .. &amp;#039; unavailable.&amp;#039;})&lt;br /&gt;
	end&lt;br /&gt;
	return retval&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.test2(frame)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Notacardoor</name></author>
	</entry>
</feed>