Jump to content

Module:Sandbox/AbstractWikipedia/Constructors

From Meta, a Wikimedia project coordination wiki
Module documentation

The Constructors module creates abstract content for the use of the NLG Scribunto prototype.

Each one of the publicly-exposed function (with the exception of the Constructors function) returns a constructor of a specific type, corresponding to the name of the function (e.g. the Birth function will return a Birth constructor). In general, the constructor will be instantiated with data from the Wikidata item corresponding to the given Q-id (an exception is the Age function which instantiates the constructor using the data given in two other constructors, namely Birth and Death). In order to facilitate access to Wikidata properties, the module uses the Wikidata module. In a Wikifunctions implementation, these constructor-creation functions would probably be user-supplied Wikifunctions functions.

The Constructors function

[edit]

The Constructors function is special in that it returns a list of instantiated constructors, which correspond to the abstract content which should be verbalized for a given topic (identified by its Q-id). First, the function will attempt to retrieve manually-curated abstract content (which is stored in the Abstract Content module). If that doesn't exist, it will attempt to dynamically assemble abstract content depending to the type of the Q-id's item. Currently only items which refer to people are supported. If no abstract content can be assembled, an error is raised.


local p = {}

local ac = require("Module:Sandbox/AbstractWikipedia/AbstractContent")
local wd = require("Module:Sandbox/AbstractWikipedia/Wikidata")

-- Helper function to insert information into constructor
-- Returns true if inserted, false otherwise
local function insertIfNotNil (constructor, field, value)
	if value then
		constructor[field] = value
		return true
	end
	return false	
end

-- Helper function to return a date associated with a q_id through property p_id
local function getDate (q_id, p_id)
	local property = wd.getProperty(q_id, p_id, "time")
	if not property then
		return nil
	end
	local time_string = property["time"]
	if not time_string then return nil end
	local result = { _predicate = "Date", year = '', month = '', day = ''}
	_, _, result.year, result.month, result.day = string.find(time_string, "(-?%d+)-(%d+)-(%d+)T")
	return result
end

function p.Birth ( q_id )
	local c = { _predicate = 'Birth', person = q_id }  -- Constructor to build
	local added
	added = insertIfNotNil(c, "date", getDate(q_id, "P569"))
	added = insertIfNotNil(c, "place", wd.getItemId(q_id, "P19")) or added
	if added then
		return c
	end
	return nil
end

function p.Death ( q_id )
	local c = { _predicate = 'Death', person = q_id }  -- Constructor to build
	local added
	added = insertIfNotNil(c, "date", getDate(q_id, "P570"))
	added = insertIfNotNil(c, "place", wd.getItemId(q_id, "P20")) or added
	if added then
		return c
	end
	return nil
end

-- Calculates the age of a person at the reference date in years
function calculateAge (birth, reference)
	local age = tonumber(reference.year) - tonumber(birth.year)
	if (tonumber(reference.month) < tonumber(birth.month) or tonumber(reference.day) < tonumber(birth.day)) then
		age = age - 1
	end
	return age
end

-- Returns age of person today if living, or age at death
function p.Age (q_id, birth, death)
	local c = { _predicate = "Age", person = q_id }  -- Constructor to build
	if not birth or not birth.date then return nil end
	if not death or not death.date then
		c.age=calculateAge(birth.date, os.date("*t"))
		c.alive = true
	else
		c.age=calculateAge(birth.date, death.date)
		c.alive = false
	end
	return c
end
	

-- Build a constructor for people
function p.Person ( q_id )
	local c = { _predicate = "Person", person = q_id }  -- Constructor to build
	insertIfNotNil(c, "origin", wd.getItemId(q_id, "P27"))
	insertIfNotNil(c, "occupation", wd.getItemId(q_id, "P106"))
	insertIfNotNil(c, "birth", p.Birth(q_id))
	insertIfNotNil(c, "death", p.Death(q_id))
	insertIfNotNil(c, "age", p.Age(q_id, c.birth, c.death))
	return c
end	

-- Returns a list of constructors appropriate for the q_id. 
-- This is either fetched from the abstract content repository or built
-- according to the type of the item.
function p.Constructors ( q_id )
	if ac[q_id] then -- Check if individually curated abstract content exists
		return ac[q_id]
	elseif wd.isHuman(q_id) then
		return { p.Person(q_id) }
	end
	error("Constructors can currently support only entites which refer to people")
end

return p