require 'Амодуль:No globals'
local p = {}
local lib = require 'Амодуль:Wikidata/lib'
local ValueTypeToDefaultMethod = {
['monolingualtext'] = 'alpha',
['quantity'] = 'quantity',
['string'] = 'alpha',
['time'] = 'time',
['wikibase-entityid'] = 'alpha',
}
p.Sorters = {}
setmetatable(p.Sorters, {
__index = function(t, key)
t[key] = require('Амодуль:Wikidata/Sorters/' .. key)
return t[key]
end
})
local function resolveResult(result, inverted)
if math.abs(result) > 1 then
return result < 0
else
return (result < 0) ~= (inverted or false)
end
end
local function compareIncomplete(first, second)
if first then
return -2
end
if second then
return 2
end
return 0
end
local function getDefaultMethodForSnak(snak)
local valueType = lib.datatypeToValueType[snak.datatype]
return ValueTypeToDefaultMethod[valueType]
end
local function getCallbackForQualifiers(method)
return function(first, second)
local sorter = p.Sorters[method]
if not (sorter.mayCompareSnak(first) and sorter.mayCompareSnak(second)) then
return error(lib.formatError('invalid-sort', method))
end
local first_complete = sorter.isCompleteSnak(first)
local second_complete = sorter.isCompleteSnak(second)
if not (first_complete and second_complete) then
return compareIncomplete(first_complete, second_complete)
end
return sorter.compareSnaks(first, second)
end
end
local function defaultCallbackForQualifiers(first, second)
local default = getDefaultMethodForSnak(first)
return getCallbackForQualifiers(default)(first, second)
end
local function getQualifierToCompare(statement, prop)
local qualifiers = statement.qualifiers and statement.qualifiers[mw.ustring.upper(prop)]
if qualifiers then
qualifiers = mw.clone(qualifiers)
if #qualifiers > 1 then
table.sort(qualifiers, function(first, second)
return resolveResult(defaultCallbackForQualifiers(first, second))
end)
end
return qualifiers[1]
end
return nil
end
local function getCallbackForStatements(method)
return function(first, second)
local sorter = p.Sorters[method]
if not (sorter.mayCompareStatement(first) and sorter.mayCompareStatement(second)) then
return error(lib.formatError('invalid-sort', method))
end
local first_complete = sorter.isCompleteStatement(first)
local second_complete = sorter.isCompleteStatement(second)
if not (first_complete and second_complete) then
return compareIncomplete(first_complete, second_complete)
end
return sorter.compareStatements(first, second)
end
end
local function resolveMethodForStatements(method)
if method == 'default' then
return function(first, second)
local default = getDefaultMethodForSnak(first.mainsnak)
return getCallbackForStatements(default)(first, second)
end
elseif lib.isPropertyId(method) then
return function(first, second)
local first_qualifier = getQualifierToCompare(first, method)
local second_qualifier = getQualifierToCompare(second, method)
if not (first_qualifier and second_qualifier) then
return compareIncomplete(not not first_qualifier, not not second_qualifier)
end
local default = getDefaultMethodForSnak(first_qualifier)
return getCallbackForQualifiers(default)(first_qualifier, second_qualifier)
end
end
return getCallbackForStatements(method)
end
function p.sortStatements(statements, options)
local methods = lib.textToTable(options.sort)
local inverted = lib.IsOptionTrue(options, 'invert')
local cache = {}
table.sort(statements, function(first, second)
local result
for _, method in ipairs(methods) do
if not cache[method] then
cache[method] = resolveMethodForStatements(method)
end
result = cache[method](first, second)
if result ~= 0 then
return resolveResult(result, inverted)
end
end
return false
end)
end
local function resolveMethodForQualifiers(method)
if method == 'default' then
return defaultCallbackForQualifiers
end
return getCallbackForQualifiers(method)
end
function p.sortQualifiers(qualifiers, options)
local methods = lib.textToTable(options.sort)
local inverted = lib.IsOptionTrue(options, 'invert')
local cache = {}
table.sort(qualifiers, function(first, second)
local result
for _, method in ipairs(methods) do
if not cache[method] then
cache[method] = resolveMethodForQualifiers(method)
end
result = cache[method](first, second)
if result ~= 0 then
return resolveResult(result, inverted)
end
end
return false
end)
end
return p