Zum Inhalt springen

Modul:Hours: Unterschied zwischen den Versionen

Aus Wikivoyage
Inhalt gelöscht Inhalt hinzugefügt
Nutzung wu; vereinfacht
Korrektur
Zeile 311: Zeile 311:
if statements ~= '' then
if statements ~= '' then
for i, value in ipairs( statements ) do
for i, value in ipairs( statements ) do
if value.value then
if value.id then
statements[ i ] = getLabelFromId( value.value, wikilang, fallbackLang )
statements[ i ] = getLabelFromId( value.id, wikilang, fallbackLang )
end
end
end
end

Version vom 1. Oktober 2020, 19:29 Uhr

Dokumentation für das Modul Hours[Ansicht] [Bearbeiten] [Versionsgeschichte] [Aktualisieren]

Anwendung

Das Modul liefert die Öffnungszeiten einer Einrichtung aus Wikidata. Es wird üblicherweise im Modul vCard verwendet, kann aber auch über einen {{#invoke: Hours | getHours }}-Aufruf in Vorlagen eingesetzt werden.

Versionsbezeichnung auf Wikidata: keine Version verfügbar

Verwendung in anderen Modulen

Dieses Modul ist notwendig für die Ausführung folgender Module. Bei Anpassungen sollte die Funktionstüchtigkeit der folgenden Module geprüft werden. Benutze dazu auch diese Tracking-Kategorie um Fehler zu finden, die sich dann auf Artikel auswirken:

Benötigte weitere Module

Dieses Modul benötigt folgende weitere Module: Hours/i18n • Wikidata utilities

Beispiele

id Label Öffnungszeiten
Q99477686 Chuchichäschtli Lua-Fehler in Modul:Wikidata_utilities, Zeile 180: bad argument #1 to 'min' (number expected, got string)
Q6373 British Museum Lua-Fehler in Modul:Wikidata_utilities, Zeile 180: bad argument #1 to 'min' (number expected, got string)
Q219867 Bahnhof King’s Cross Lua-Fehler in Modul:Wikidata_utilities, Zeile 180: bad argument #1 to 'min' (number expected, got string)
Q2292227 Skigebiet Gaißau-Hintersee Lua-Fehler in Modul:Wikidata_utilities, Zeile 180: bad argument #1 to 'min' (number expected, got string)
Q11323320 Pablo Gargallo Museum Lua-Fehler in Modul:Wikidata_utilities, Zeile 180: bad argument #1 to 'min' (number expected, got string)
Q27831262 Öömrang Hüs Lua-Fehler in Modul:Wikidata_utilities, Zeile 180: bad argument #1 to 'min' (number expected, got string)
Q99690036 Nationalpark-Tor Rurberg Lua-Fehler in Modul:Wikidata_utilities, Zeile 180: bad argument #1 to 'min' (number expected, got string)
Q2583681 Grand Egyptian Museum Lua-Fehler in Modul:Wikidata_utilities, Zeile 180: bad argument #1 to 'min' (number expected, got string)

Wartungskategorien

Anmerkungen

Bisher sind nur bei wenigen Wikidata-Einträgen Öffnungszeiten hinterlegt, so dass es sicher im Laufe der Zeit zu Anpassungen kommen wird.

  • Bisher werden alle Schließtage gesammelt und geschlossen am Ende ausgegeben, also nicht hinter jedem einzelnen Datensatz (erkennbar am trennenden Semikolon),
  • Beobachtung der Nutzung der einzelnen Eigenschaften, insbesondere P5102, P5817 und neu erfasste Eigenschaften. Evtl. Eigenschaften einschränken.

Mögliche Parameter für {{#invoke: Hours | getHours }}

  • Erforderliche Parameter:
    • |id= Wikidata-Id für die entsprechende Einrichtung mit vorangestelltem Q wie z. B. Q12345.
  • Optionale Parameter:
    • |format= Ausgabeformat, das anstelle der Standardzeichenkette verwendet werden soll, wenn eine Öffnungszeit bestimmt wurde, wie z. B. „Geöffnet: %s“. %s ist der Platzhalter für die Öffnungszeit.
    • |fallback= Ersatzsprache, auf die zurückgegriffen werden soll, wenn ein Öffnungszeit-Label nicht in der Inhaltssprache des Wikis vorliegt. Z. B. en.
    • |show= Kommaseparierte Liste von Anzeigeoptionen, die die Standardwerte ersetzen. Gegenwärtig werden die beiden Werte msg (Anzeige der Wartungskategorien) und nomsg (keine Anzeige der Wartungskategorien) unterstützt.

Beispiele

  • {{#invoke: Hours | getHours | id = Q6373 }}
  • {{#invoke: Hours | getHours | id = Q6373 | fallback = en }}
  • {{#invoke: Hours | getHours | id = Q6373 | show = msg }}
Hinweise
-- getting opening hours from Wikidata

-- documentation
local Hours = {
	suite  = 'Hours',
	serial = '2020-10-01',
	item   = 99600452
}

-- module import
local fs = require( 'Module:Failsafe' )
local hi = require( 'Module:Hours/i18n' )
local wu = require( 'Module:Wikidata utilities' )

-- module variable
local hr = {}
local categIds = {}
local showOptions = {}

local function isSet( s )
	return s and s ~= ''
end

-- insert a value into a table only if it is set
local function tableInsert( tab, value )
	if isSet( value ) then
		table.insert( tab, value )
	end
end

-- value count for any variable
local function getCount( tab )
	return type( tab ) == 'table' and #tab or 0
end

local function getLabelFromTable( id )
	local label = hi.dateIds[ id ] or ''
	if type( label ) == 'table' then
		label = label.a or label.f
	end
	return label
end

-- getting label for a qualifier id
-- to save computing time firstly the id will fetched from Hours/i18n table
-- if available, otherwise from Wikidata
local function getLabelFromId( id, wikilang, fallbackLang )
	local t

	-- from table
	local label = hi.dateIds[ id ]
	if label and type( label ) == 'table' then
		label = label.a or label.f

	-- from Wikidata
	elseif not label and mw.wikibase.isValidEntityId( id ) then
		t = wu.getMonolingualValues( id, hi.wd.shortName )
		label = t[ wikilang ]
		if not label then
			label = wu.getLabel( id, wikilang )
		else
			wu.addProperty( hi.wd.shortName )
		end
		if not label and isSet( fallbackLang ) then
			label = wu.getLabel( id, fallbackLang )
			if label then
				categIds.fallbackLabel = ''
			end
		end
		if label then
			categIds.labelFromWikidata = ''
		end
	end

	-- additional time formatting
	if isSet( label ) then
		if hi.months then
			for full, short in pairs( hi.months ) do
				label = mw.ustring.gsub( label, full, short )
			end
		end
		if hi.options.leadingZero then
			label = label:gsub( '^(%d):', '0%1:' )
		else
			label = label:gsub( '^0(%d):', '%1:' )
		end
		if hi.options.removeZeros then
			label = label:gsub( '^(%d%d?):00', '%1' )
		end
	end
	return label or ''
end

local function abbreviateTimeStr( s, all, pattern, repl )
	if not isSet( s ) or not isSet( pattern ) or not isSet( repl ) then
        return s or ''
	end
	if all then
		s = mw.ustring.gsub( s, pattern, repl )
	else
		local matchPattern = mw.ustring.gsub( pattern, '%(%%d%)', '' )
		local first, stop = mw.ustring.find( s, pattern )
		if first then
			local second = mw.ustring.find( s, pattern, stop + 1 )
			if second and mw.ustring.match( s, matchPattern ) ==
				mw.ustring.match( s, matchPattern, stop + 1 ) then
        		s = mw.ustring.gsub( s, pattern, repl, 1 )
        	end
    	end
    end
    return s
end

-- getting time period string
-- i:  position in from and to arrays
-- id: label for P3035 value
local function getTimePeriod( from, to, i, id )
	local result = ''
	if id and ( id == getLabelFromTable( hi.times.daily )
		or id == getLabelFromTable( hi.times.is24_7 ) )
		and from and to and from[ i ] == getLabelFromTable( hi.times.Jan1 ) and
		to[ i ] == getLabelFromTable( hi.times.Dec31 ) then
		return ''
	end
	if from and isSet( from[ i ] ) and to and isSet( to[ i ] ) then
		result = mw.ustring.format( hi.texts.fromTo, from[ i ], to[ i ] )
		if isSet( hi.texts.hourPattern ) then
			result = abbreviateTimeStr( result, hourReplAll, hi.texts.hourPattern,
				hi.texts.hourRepl )
		end
	elseif from and isSet( from[ i ] ) then
		result = mw.ustring.format( hi.texts.from, from[ i ] )
	elseif to and isSet( to[ i ] ) then
		result = mw.ustring.format( hi.texts.to, to[ i ] )
	end
	return result
end

-- collecting all maintenance categories
function hr.getCategories( formatStr )
	local result = wu.getCategories( formatStr )
	for k, v in pairs( categIds ) do
		result = result .. ( hi.categories[ k ] or hi.categories.unknownError )
	end
	if showOptions.demo then
		result = result:gsub( '%[%[[^%[]*%]%]', '' )
	end
	return result
end

-- getting a string with listed days at which an establishment is closed
local function getClosed( arr )
	return ( arr and #arr > 0 ) and mw.ustring.format( hi.texts.closed or '%s', 
		table.concat( arr, hi.texts.separator ) ) or ''
end

-- converting day range from Mo, Tu, We to Mo–We, and so on
local function getRange( arr, minPos, maxPos )
	if maxPos > 0 and minPos > 0 and maxPos > minPos then
		arr[ minPos ] = mw.ustring.format( hi.texts.fromTo, arr[ minPos ],
			arr[ maxPos ] )
		for i = maxPos, minPos + 1, -1 do
			table.remove( arr, i )
		end
	end
end

local function concatStrings( sep, str1, str2 )
	local tab = {}
	tableInsert( tab, str1 )
	tableInsert( tab, str2 )
	return table.concat( tab, sep )
end

-- main function for usage in Lua modules
-- entity: entity id or entity table
-- wikilang: content language of the wiki
-- fallbackLang: optional additional language for fallback
-- formatStr: optional format string for property categories
function hr.getHoursFromWikidata( entity, wikilang, fallbackLang, formatStr, show )
	-- collecting days at which an establishment is closed
	local closeDays = {}
	local closeDaysHelper = {}
	local function mergeDays( days )
		if not days or #days == 0 then
			return
		end
		for _, day in ipairs( days ) do
			if not closeDaysHelper[ day ] then
				table.insert( closeDays, day )
				closeDaysHelper[ day ] = ''
			end
		end
	end
	local function clearDays()
		closeDays = {}
		closeDaysHelper = {}
	end

	-- preparing show options
	showOptions = show or {}
	showOptions.addCategories = hi.options.addCategories
	if showOptions.msg then
		showOptions.addCategories = true
	elseif showOptions.nomsg then
		showOptions.addCategories = false
	end

	-- getting statements for P3025: open days
	local statements = wu.getValuesWithQualifiers( entity, hi.wd.opened,
		{ hi.wd.closed, hi.wd.dayOpen, hi.wd.dayClosed, hi.wd.hourOpen,
		  hi.wd.hourClosed }, nil, getLabelFromId, wikilang, fallbackLang )
	if #statements == 0 then
		return ''
	end

	-- format string for property categories
	if not isSet( formatStr ) then
		formatStr = hi.categories.properties
	end

	-- converting statements to human-readable strings
	local result = {}
	local s
	for i, tab in ipairs( statements ) do
		local item = {}

		-- opening times
		local count = math.max( getCount( tab[ hi.wd.dayOpen ] ),
			getCount( tab[ hi.wd.dayClosed ] ), getCount( tab[ hi.wd.hourOpen ] ),
			getCount( tab[ hi.wd.hourClosed ] ) )
		if count > 0 then
			for j = 1, count, 1 do
				local times = {}
				tableInsert( times,
					getTimePeriod( tab[ hi.wd.dayOpen ], tab[ hi.wd.dayClosed ], j, tab.value ) )
				s = getTimePeriod( tab[ hi.wd.hourOpen ], tab[ hi.wd.hourClosed ], j )
				if isSet( s ) then
					tableInsert( times, s )
				else
					categIds.withoutTime = ''
				end
				tableInsert( item, table.concat( times, hi.texts.joiner ) )
			end
			s = table.concat( item, hi.texts.separator )
			item = {}
			tableInsert( item, s )
		else
			categIds.withoutTime = ''
		end

		-- close statements (P3026) as qualifiers for open days property (P3025)
		mergeDays( tab[ hi.wd.closed ] )
		if not hi.options.clusterClosed and ( i == #statements or
			statements[ i ].value ~= statements[ i + 1 ].value ) then
			tableInsert( item, getClosed( closeDays ) )
			clearDays()
		end
		s = table.concat( item, hi.texts.separator )
	
		-- copying each statement to result table
		if tab.sort2 == 1 then
			tableInsert( result, { value = { tab.value }, times = s } )
		elseif s ~= '' then
			result[ #result ].times = concatStrings( hi.texts.separator,
				result[ #result ].times, s )
		end
	end

	-- checking for duplicates
	for i = #result, 2, -1 do
		if result[ i ].times == result[ i - 1 ].times then
			for _, value in ipairs( result[ i ].value ) do
				table.insert( result[ i - 1 ].value, value )
			end
			table.remove( result, i )
		end
	end

	-- converting day range
	for i = 1, #result, 1 do
		local count = #result[ i ].value
		local minPos = 0
		local maxPos = 0
		local value, valueMin
		while count > 0 do
			value = hi.weekdays[ result[ i ].value[ count ] ]
			if not value then
				getRange( result[ i ].value, minPos, maxPos )
				maxPos = 0
			elseif maxPos == 0 then
				maxPos = count
				valueMin = value
			elseif maxPos > 0 and value == valueMin - 1 then
				minPos = count
				valueMin = value
			else
				getRange( result[ i ].value, minPos, maxPos )
				maxPos = 0
			end
			count = count - 1
		end
		getRange( result[ i ].value, minPos, maxPos )

		result[ i ] = concatStrings( hi.texts.joiner,
			table.concat( result[ i ].value, hi.texts.separator ), result[ i ].times )
	end

	-- add separated close statements (P3026)
	statements = wu.getValues( entity, hi.wd.closed, nil )
	if statements ~= '' then
		for i, value in ipairs( statements ) do
			if value.id then
				statements[ i ] = getLabelFromId( value.id, wikilang, fallbackLang )
			end
		end
		mergeDays( statements )
	end
	tableInsert( result, getClosed( closeDays ) )

	-- merging all statements
	local result = table.concat( result, hi.texts.delimiter )

	-- adding maintenance categories
	if result ~= '' then
		categIds.fromWikidata = ''
		if showOptions.addCategories then
			result = result .. hr.getCategories( formatStr )
		end
	end
	return result
end

-- invoke helper functions
local function splitAndCheck( s )
	local err = {}
	if not isSet( s ) then
		return {}, err
	end
	local arr = {}
	for _, v in ipairs( mw.text.split( s, ',', true ) ) do
		v = mw.text.trim( v )
		if not hi.show[ v ] then
			table.insert( err, v )
		else
			arr[ v ] = ''
		end
	end
	return arr, err
end

local function checkParameters( args )
	local err = {}
	if not args and type( args ) ~= 'table' then
		return err
	end
	for k, v in pairs( args ) do
		if not hi.params[ k ] then
			table.insert( err, k )
		end
	end
	return err
end

local function getErrorStr( arr, formatStr )
	return #arr == 0 and '' or
		mw.ustring.format( formatStr, table.concat( arr, ', ' ) )
end

-- main function for template #invoke calls
-- id: Q-id of an establishment
-- format: output format like 'opened at %s'
-- fallback: fallback language if labels are not available in content language
function hr.getHours( frame )
    local args = frame.args
    args.id = mw.text.trim( args.id or '' )
    if not isSet( args.id ) or not mw.wikibase.isValidEntityId( args.id ) then
        return hi.categories.invalidId
    end
    if not isSet( args.format ) then
    	args.format = hi.texts.format
    else
	    local _, count = args.format:gsub( '%%s', '%%s' )
    	if count ~= 1 then
        	args.format = hi.texts.format
    	end
    end
    args.fallback = args.fallback or ''
    local wikilang = mw.getContentLanguage():getCode()

	local paramErr = checkParameters( args )
	local show, showErr = splitAndCheck( args.show )

    local result = hr.getHoursFromWikidata( args.id, wikilang, args.fallback, '', show )
    if result ~= '' then
    	result = mw.ustring.format( args.format, result )
    end
    return result .. getErrorStr( paramErr, hi.categories.unknownParams )
    	.. getErrorStr( showErr, hi.categories.unknownShowOptions )
end

-- module administration
function hr.Hours()
	return Hours
end

function hr.failsafe( version )
	return fs._failsafe( version, Hours ) or ''
end

return hr