Module:OpenHistoricalMap/Statistics

From OpenStreetMap Wiki
Jump to navigation Jump to search
local p = {}
local languages = require("Module:Languages")
local contentEvents = mw.loadJsonData("Module:OpenHistoricalMap/Statistics/content.json")
local changesetEvents = mw.loadJsonData("Module:OpenHistoricalMap/Statistics/changesets.json")
local round = require("Module:Math")._round

function p.currentStats(frame)
	local title = mw.title.getCurrentTitle()
	local lang = mw.getLanguage(languages.languageFromTitle(title))
	local langCode = lang:getCode()
	
	local contentEvent, changesetEvent
	for i, event in ipairs(contentEvents) do
		contentEvent = event
	end
	for i, event in ipairs(changesetEvents) do
		changesetEvent = event
	end
	
	local timestamp = changesetEvent.date > contentEvent.date and changesetEvent.date or contentEvent.date
	
	local layoutTitle = mw.title.new("OpenHistoricalMap/Statistics/" .. langCode, 10)
	if not layoutTitle.exists then
		layoutTitle = mw.title.new("OpenHistoricalMap/Statistics/en", 10)
	end
	return frame:expandTemplate {
		title = layoutTitle.fullText,
		args = {
			timestamp = timestamp,
			["dated elements"] = contentEvent.count_dated,
			buildings = contentEvent.count_building,
			["railroad length"] = contentEvent.sum_railway_distance,
			["average age"] = contentEvent.avg_age,
			["average year"] = contentEvent.avg_date,
			contributors = changesetEvent.count_user,
		}
	}
end

function p.contentTable(frame)
	local title = mw.title.getCurrentTitle()
	local lang = mw.getLanguage(languages.languageFromTitle(title))
	
	local head = mw.html.create("tr")
		:tag("th"):attr("rowspan", 2)
			:wikitext("Date")
			:attr("data-sort-type", "isoDate")
			:done()
		:tag("th"):attr("rowspan", 2)
			:wikitext("Dated elements")
			:attr("data-sort-type", "number")
			:done()
		:tag("th"):attr("rowspan", 2)
			:attr("data-sort-type", "number")
			:wikitext("Buildings")
			:done()
		:tag("th"):attr("colspan", 3):wikitext("Railroad tracks"):done()
		:tag("th")
			:attr("rowspan", 2)
			:attr("data-sort-type", "number")
			:wikitext("Average age")
			:done()
		:tag("th")
			:attr("rowspan", 2)
			:attr("data-sort-type", "number")
			:wikitext("Average year")
			:done()
		:allDone()
	
	local headDetail = mw.html.create("tr")
		:tag("th")
			:wikitext("Miles")
			:attr("data-sort-type", "number")
			:done()
		:tag("th")
			:wikitext("Kilometers")
			:attr("data-sort-type", "number")
			:done()
		:tag("th")
			:wikitext("± %")
			:attr("data-sort-type", "number")
			:done()
		:allDone()
	
	local result = mw.html.create("table")
		:addClass("wikitable sortable")
		:node(head):done()
		:node(headDetail):done()
	
	local railMeters -- memoize for the next row
	for i, event in ipairs(contentEvents) do
		local dateFormat = #event.date == 10 and "F j, Y" or #event.date == 7 and "F Y" or event.date
		
		local prevRailMeters = railMeters
		railMeters = event.sum_railway_distance
		local railChange = railMeters and prevRailMeters and (railMeters - prevRailMeters) / railMeters * 100
		
		local secondsPerYear = 365.25 * 24 * 60 * 60
		local avgSeconds = event.avg_age and round(event.avg_age) * secondsPerYear
		
		local row = mw.html.create("tr")
			:tag("td")
				:attr("data-sort-value", event.date)
				:wikitext(lang:formatDate(dateFormat, event.date))
				:done()
			:tag("td")
				:attr("align", "right")
				:attr("data-sort-value", event.count_dated)
				:wikitext(event.count_dated and lang:formatNum(event.count_dated))
				:done()
			:tag("td")
				:attr("align", "right")
				:attr("data-sort-value", event.count_building)
				:wikitext(event.count_building and lang:formatNum(event.count_building))
				:done()
			:tag("td")
				:attr("align", "right")
				:attr("data-sort-value", event.railMeters)
				:wikitext(railMeters and frame:expandTemplate {
					title = "Convert",
					args = {
						railMeters,
						"m", "mi",
						0,
						disp = "number",
					},
				})
				:done()
			:tag("td")
				:attr("align", "right")
				:attr("data-sort-value", railMeters)
				:wikitext(railMeters and frame:expandTemplate {
					title = "Convert",
					args = {
						railMeters,
						"m", "km",
						0,
						disp = "number",
					},
				})
				:done()
			:tag("td")
				:attr("align", "right")
				:attr("data-sort-value", railChange)
				:wikitext(railChange and frame:expandTemplate {
					title = "Change",
					args = {
						prevRailMeters,
						railMeters,
						sort = "off",
						disp = "out",
					},
				})
				:done()
			:tag("td")
				:attr("align", "right")
				:attr("data-sort-value", event.avg_age)
				:wikitext(event.avg_age and lang:formatDuration(avgSeconds, { "years" }))
				:done()
			:tag("td")
				:attr("align", "right")
				:attr("data-sort-value", event.avg_date)
				:wikitext(event.avg_date and lang:formatDate("Y", tostring(round(event.avg_date))))
				:done()
			:allDone()
		result:node(row)
	end
	result:allDone()
	
	return result
end

function p.changesetsTable(frame)
	local title = mw.title.getCurrentTitle()
	local lang = mw.getLanguage(languages.languageFromTitle(title))
	
	local head = mw.html.create("tr")
		:tag("th")
			:wikitext("Date")
			:attr("data-sort-type", "isoDate")
			:done()
		:tag("th")
			:wikitext("Contributors")
			:attr("data-sort-type", "number")
			:done()
		:allDone()
	
	local result = mw.html.create("table")
		:addClass("wikitable sortable")
		:node(head)
		:node(headDetail)
	
	for i, event in ipairs(changesetEvents) do
		local dateFormat = #event.date == 10 and "F j, Y" or #event.date == 7 and "F Y" or event.date
		
		local row = mw.html.create("tr")
			:tag("td")
				:attr("data-sort-value", event.date)
				:wikitext(lang:formatDate(dateFormat, event.date))
				:done()
			:tag("td")
				:attr("align", "right")
				:attr("data-sort-value", event.count_user)
				:wikitext(event.count_user and lang:formatNum(event.count_user))
				:done()
			:allDone()
		result:node(row)
	end
	result:allDone()
	
	return result
end

return p