Module:SMWUtils: Difference between revisions
Rewrite to use frame:preprocess() instead of mw.smw.ask() (Semantic Scribunto not installed) (via update-page on MediaWiki MCP Server) |
Rewrite to use mw.smw.ask() now that Semantic Scribunto is installed (via update-page on MediaWiki MCP Server) |
||
| Line 1: | Line 1: | ||
-- Module:SMWUtils | -- Module:SMWUtils | ||
-- Utility functions for Semantic MediaWiki queries | -- Utility functions for Semantic MediaWiki queries | ||
-- | -- Requires Semantic Scribunto extension for mw.smw.ask() | ||
local p = {} | local p = {} | ||
| Line 13: | Line 13: | ||
end | end | ||
--- Find all results where a | --- Find all results where a property equals its minimum value across the result set | ||
-- @param frame Frame object with args: | -- @param frame Frame object with args: | ||
-- conditions: SMW query conditions (e.g., "[[Has video signal format::Component (YPbPr)]]") | -- conditions: SMW query conditions (e.g., "[[Has video signal format::Component (YPbPr)]]") | ||
| Line 21: | Line 20: | ||
-- format: Output format (table, ul, ol) - default "table" | -- format: Output format (table, ul, ol) - default "table" | ||
-- headers: Comma-separated header names for table format | -- headers: Comma-separated header names for table format | ||
-- intro: Optional intro text | -- intro: Optional intro text (supports wikitext) | ||
-- @return Wikitext output | -- @return Wikitext output | ||
function p.findAllWithMin(frame) | function p.findAllWithMin(frame) | ||
| Line 36: | Line 35: | ||
end | end | ||
-- | -- Build the printout list for the query | ||
local | local printoutList = {} | ||
' | for prop in printouts:gmatch('[^,]+') do | ||
table.insert(printoutList, '?' .. trim(prop)) | |||
end | |||
-- Always include the minProperty for comparison | |||
table.insert(printoutList, '?' .. minProperty) | |||
-- Build and execute the query | |||
local queryString = conditions .. '\n' .. table.concat(printoutList, '\n') .. '\n|limit=500' | |||
local results = mw.smw.ask(queryString) | |||
if not results or #results == 0 then | |||
return "No results found." | |||
end | |||
-- | -- Find the minimum value | ||
local minValue = nil | local minValue = nil | ||
for _, row in ipairs(results) do | |||
local val = row[minProperty] | |||
if val then | |||
local numVal = tonumber(val) | |||
local numVal = tonumber( | |||
if numVal then | if numVal then | ||
minValue = numVal | if minValue == nil or numVal < minValue then | ||
minValue = numVal | |||
end | |||
end | end | ||
end | end | ||
| Line 63: | Line 66: | ||
if minValue == nil then | if minValue == nil then | ||
return " | return "Could not determine minimum value." | ||
end | end | ||
-- | -- Filter results to only those matching the minimum | ||
local | local filtered = {} | ||
for | for _, row in ipairs(results) do | ||
local val = row[minProperty] | |||
if val and tonumber(val) == minValue then | |||
table.insert(filtered, row) | |||
end | |||
end | end | ||
-- Build output | -- Build output based on format | ||
local headerList = {} | local headerList = {} | ||
for h in headers:gmatch('[^,]+') do | for h in headers:gmatch('[^,]+') do | ||
| Line 105: | Line 92: | ||
if format == 'table' then | if format == 'table' then | ||
return p. | return p._formatTable(filtered, printoutProps, headerList, introText) | ||
elseif format == 'ul' or format == 'ol' then | elseif format == 'ul' or format == 'ol' then | ||
return p. | return p._formatList(filtered, printoutProps, format, introText) | ||
else | else | ||
return p. | return p._formatTable(filtered, printoutProps, headerList, introText) | ||
end | end | ||
end | end | ||
| Line 127: | Line 114: | ||
end | end | ||
-- | -- Build the printout list | ||
local | local printoutList = {} | ||
' | for prop in printouts:gmatch('[^,]+') do | ||
table.insert(printoutList, '?' .. trim(prop)) | |||
end | |||
table.insert(printoutList, '?' .. maxProperty) | |||
local | -- Build and execute the query | ||
local queryString = conditions .. '\n' .. table.concat(printoutList, '\n') .. '\n|limit=500' | |||
local results = mw.smw.ask(queryString) | |||
-- | if not results or #results == 0 then | ||
return "No results found." | |||
end | |||
-- Find the maximum value | |||
local maxValue = nil | local maxValue = nil | ||
for _, row in ipairs(results) do | |||
local val = row[maxProperty] | |||
if val then | |||
local numVal = tonumber( | local numVal = tonumber(val) | ||
if numVal then | if numVal then | ||
maxValue = numVal | if maxValue == nil or numVal > maxValue then | ||
maxValue = numVal | |||
end | |||
end | end | ||
end | end | ||
| Line 153: | Line 144: | ||
if maxValue == nil then | if maxValue == nil then | ||
return " | return "Could not determine maximum value." | ||
end | end | ||
-- | -- Filter results to only those matching the maximum | ||
local | local filtered = {} | ||
for | for _, row in ipairs(results) do | ||
local val = row[maxProperty] | |||
if val and tonumber(val) == maxValue then | |||
table.insert(filtered, row) | |||
end | |||
end | end | ||
| Line 195: | Line 170: | ||
if format == 'table' then | if format == 'table' then | ||
return p. | return p._formatTable(filtered, printoutProps, headerList, introText) | ||
elseif format == 'ul' or format == 'ol' then | elseif format == 'ul' or format == 'ol' then | ||
return p. | return p._formatList(filtered, printoutProps, format, introText) | ||
else | else | ||
return p. | return p._formatTable(filtered, printoutProps, headerList, introText) | ||
end | end | ||
end | end | ||
-- Internal: Format results as a wikitable | |||
function p._formatTable(results, printouts, headers, introText) | |||
-- Internal: Format | |||
function p. | |||
local output = {} | local output = {} | ||
| Line 251: | Line 195: | ||
-- Data rows | -- Data rows | ||
for i, row in ipairs(results) do | for i, row in ipairs(results) do | ||
local tr = '|-\n| ' .. tostring(i) | |||
for | for _, prop in ipairs(printouts) do | ||
local | local val = row[prop] | ||
table.insert( | local displayVal = '' | ||
if val then | |||
if type(val) == 'table' then | |||
-- Handle linked values (pages) | |||
if val.fulltext then | |||
displayVal = '[[' .. val.fulltext .. ']]' | |||
elseif #val > 0 then | |||
-- Array of values | |||
local parts = {} | |||
for _, v in ipairs(val) do | |||
if type(v) == 'table' and v.fulltext then | |||
table.insert(parts, '[[' .. v.fulltext .. ']]') | |||
else | |||
table.insert(parts, tostring(v)) | |||
end | |||
end | |||
displayVal = table.concat(parts, ', ') | |||
end | |||
else | |||
displayVal = tostring(val) | |||
end | |||
end | |||
tr = tr .. ' || ' .. displayVal | |||
end | end | ||
table.insert(output, '\n') | table.insert(output, tr .. '\n') | ||
end | end | ||
| Line 264: | Line 230: | ||
end | end | ||
-- Internal: Format | -- Internal: Format results as a list | ||
function p. | function p._formatList(results, printouts, listType, introText) | ||
local output = {} | local output = {} | ||
local bullet = listType == 'ol' and '#' or '*' | local bullet = listType == 'ol' and '#' or '*' | ||
| Line 273: | Line 239: | ||
for _, row in ipairs(results) do | for _, row in ipairs(results) do | ||
local parts = {} | local parts = {} | ||
for _, | for _, prop in ipairs(printouts) do | ||
if | local val = row[prop] | ||
if val then | |||
if type(val) == 'table' and val.fulltext then | |||
table.insert(parts, '[[' .. val.fulltext .. ']]') | |||
elseif type(val) ~= 'table' then | |||
table.insert(parts, tostring(val)) | |||
end | |||
end | end | ||
end | end | ||