Module:TourIndex
From Linkinpedia
More actions
Documentation for this module may be created at Module:TourIndex/doc
-- Module:TourIndex
local p = {}
local cargo = mw.ext.cargo
-- Manual items inserted immediately BEFORE the specified show.
-- Add only genuinely editorial/special separators here.
local before = {
["Live:20000815"] = {
{ type = "break" },
},
["Live:20010928"] = {
{ type = "break" },
},
["Live:20170725"] = {
{ type = "ripchester" },
},
["Live:20250131"] = {
{ type = "break" },
{ type = "header", text = "From Zero World Tour: Mexico" },
},
["Live:20250210"] = {
{ type = "break" },
{ type = "header", text = "From Zero World Tour: Asia" },
},
["Live:20250412"] = {
{ type = "break" },
{ type = "header", text = "From Zero World Tour: North America (Leg 1)" },
},
["Live:20250612"] = {
{ type = "break" },
{ type = "header", text = "From Zero World Tour: Europe" },
},
["Live:20250729"] = {
{ type = "break" },
{ type = "header", text = "From Zero World Tour: North America (Leg 2)" },
},
["Live:20251025"] = {
{ type = "break" },
{ type = "header", text = "From Zero World Tour: South America" },
},
["Live:20260118"] = {
{ type = "break" },
{ type = "header", text = "From Zero World Tour: Middle East + India" },
},
["Live:20260303"] = {
{ type = "break" },
{ type = "header", text = "From Zero World Tour: Australia and New Zealand" },
},
["Live:20260529"] = {
{ type = "break" },
{ type = "header", text = "From Zero World Tour: Europe" },
},
}
local function escape(value)
return tostring(value or "")
end
local function getDateParts(date)
if not date or date == "" then
return nil, nil, nil
end
local year, month, day =
tostring(date):match("^(%d%d%d%d)%-(%d%d)%-(%d%d)")
if year then
return tonumber(year), tonumber(month), tonumber(day)
end
-- Fallback in case Cargo returns YYYYMMDD.
year, month, day =
tostring(date):match("^(%d%d%d%d)(%d%d)(%d%d)$")
if year then
return tonumber(year), tonumber(month), tonumber(day)
end
return nil, nil, nil
end
local function getDisplayDate(row)
local page = tostring(row.Link or "")
local raw = page:gsub("^Live:", "")
local yearSet =
row.Year ~= nil and tostring(row.Year) ~= ""
local monthSet =
row.Month ~= nil and tostring(row.Month) ~= ""
local daySet =
row.Day ~= nil and tostring(row.Day) ~= ""
if yearSet and monthSet and daySet then
local year, month, day = getDateParts(row.Date)
if year and month and day then
return string.format(
"%04d.%02d.%02d",
year,
month,
day
)
end
end
-- An incomplete source date is displayed from the page name.
if #raw >= 8 then
return raw:sub(1, 4) .. "." ..
raw:sub(5, 6) .. "." ..
raw:sub(7, 8)
end
return raw
end
local function renderYear(year)
return table.concat({
'|-\n',
'| colspan="5" class="subheader" |\n',
'==', tostring(year), '==\n',
})
end
local function renderMonth()
return table.concat({
'|-\n',
'| colspan="5" | \n',
})
end
local function renderHeader(text)
return table.concat({
'|-\n',
'| colspan="5" class="subheader" |\n',
'===[[', tostring(text), ']]===\n',
})
end
local function renderBreak()
return table.concat({
'|-\n',
'|<hr>||<hr>||<hr>||<hr>\n',
})
end
local function renderRIPChester()
return table.concat({
'|-\n',
'| colspan="5" style="text-align:center;" | ',
"'''''On July 20th, the world was shocked and heartbroken ",
"to learn of the passing of Chester Bennington.'''''\n",
})
end
local function renderMarker(marker)
if marker.type == "break" then
return renderBreak()
elseif marker.type == "ripchester" then
return renderRIPChester()
elseif marker.type == "header" then
return renderHeader(marker.text)
elseif marker.type == "month" then
return renderMonth()
elseif marker.type == "year" then
return renderYear(marker.text)
end
return ""
end
local function hasStructuralMarker(markers)
if not markers then
return false
end
for _, marker in ipairs(markers) do
if marker.type == "break"
or marker.type == "header"
or marker.type == "ripchester"
then
return true
end
end
return false
end
local function getStyle(row)
if row.ShowType == "cancelled" then
return 'style="color: #D24501;"'
end
if row.Artist == "Linkin Park" then
local today = os.date("!%Y-%m-%d")
if row.Date == today then
return 'style="color: #00cc00;"'
elseif row.Date and row.Date > today then
return 'style="color: #2dbaba;"'
end
end
return ""
end
local function renderRow(row, frame)
local link = escape(row.Link)
local city = escape(row.City)
local venue = escape(row.Venue)
local country = escape(row.Country)
local event = escape(row.Event)
local style = getStyle(row)
local displayDate = getDisplayDate(row)
local flag = ""
if country ~= "" then
flag = frame:expandTemplate {
title = "flag",
args = { country }
}
end
local function styledCell(value)
if style ~= "" then
return style .. " | " .. value
end
return value
end
local output = {}
output[#output + 1] = "|-\n"
output[#output + 1] =
"|[[" .. link .. "|" .. displayDate .. "]]"
output[#output + 1] = "||" .. styledCell(city)
output[#output + 1] = "||" .. styledCell(venue)
output[#output + 1] = "||" .. flag
output[#output + 1] = "||" .. styledCell(event)
output[#output + 1] = "\n"
return table.concat(output)
end
local preLinkinParkArtists = {
["The Pricks"] = true,
["Relative Degree"] = true,
["Xero"] = true,
["Xero 818"] = true,
["Hybrid Theory"] = true,
}
function p.main(frame)
local fields = table.concat({
"ShowPage=Link",
"City",
"Venue",
"Country",
"Event",
"Date",
"Year",
"Month",
"Day",
"Tour",
"ShowType",
"Artist",
}, ",")
local args = {
where = table.concat({
'Artist IN ("Linkin Park","Hybrid Theory","Xero","Xero 818","The Pricks","Relative Degree")',
'ShowType IN ("upcoming","current","concert","private","TV","festival","radio","benefit","album","awards","sports","label","LPU","summit","fan rehearsal","studio","acoustic","cancelled")',
}, " AND "),
orderBy = "Date ASC, ShowPage ASC",
limit = 5000,
}
local rows = cargo.query(
"Shows",
fields,
args
)
local output = {}
local previousYear = nil
local previousMonth = nil
local previousTour = nil
local previousArtist = nil
local previousRowTour = nil
-- The historical section starts with one special heading rather
-- than individual calendar-year headings.
local preLinkinPark = true
local preLinkinParkHeadingWritten = false
for _, row in ipairs(rows) do
local link = tostring(row.Link or "")
local yearNumber = tonumber(row.Year)
-- Use the normalized Cargo Date for the numeric month.
-- The original Month field may contain names such as "November".
local _, monthNumber = getDateParts(row.Date)
local year = yearNumber and tostring(yearNumber) or ""
local month = monthNumber and tostring(monthNumber) or ""
local artist = tostring(row.Artist or "")
local tour = tostring(row.Tour or "")
local markers = before[link]
------------------------------------------------------------
-- PRE-LINKIN PARK SECTION
------------------------------------------------------------
if preLinkinPark then
if not preLinkinParkHeadingWritten then
output[#output + 1] =
renderYear("pre-Linkin Park")
preLinkinParkHeadingWritten = true
end
-- Your original index starts the ordinary yearly
-- structure with Live:20000525.
if link == "Live:20000525" then
preLinkinPark = false
output[#output + 1] =
renderYear("2000")
previousYear = "2000"
previousMonth = month
previousTour = nil
previousArtist = nil
previousRowTour = nil
end
end
------------------------------------------------------------
-- NORMAL YEAR CHANGES
------------------------------------------------------------
if not preLinkinPark
and link ~= "Live:20000525"
and year ~= ""
and year ~= previousYear
then
output[#output + 1] =
renderYear(year)
previousYear = year
previousMonth = month
previousTour = nil
previousArtist = nil
previousRowTour = nil
end
------------------------------------------------------------
-- ARTIST HEADERS FOR EARLY BANDS
------------------------------------------------------------
if preLinkinPark
and preLinkinParkArtists[artist]
and artist ~= previousArtist
then
output[#output + 1] =
renderHeader(artist)
previousArtist = artist
end
------------------------------------------------------------
-- TOUR / MONTH STATE
------------------------------------------------------------
local tourChanged =
tour ~= ""
and tour ~= previousTour
local startsTourBlock =
tour ~= ""
and tour ~= previousRowTour
local monthChanged =
not preLinkinPark
and month ~= ""
and previousMonth ~= nil
and previousMonth ~= ""
and month ~= previousMonth
------------------------------------------------------------
-- MONTH BREAK
--
-- Add between months within the existing flow, including
-- within a tour and among non-tour events.
--
-- Do not add immediately before a new tour header.
------------------------------------------------------------
if monthChanged
and not startsTourBlock
and not hasStructuralMarker(markers)
then
output[#output + 1] =
renderMonth()
end
------------------------------------------------------------
-- MANUAL BREAKS / SPECIAL CONTENT
------------------------------------------------------------
if markers then
for _, marker in ipairs(markers) do
output[#output + 1] =
renderMarker(marker)
end
end
------------------------------------------------------------
-- TOUR HEADER
------------------------------------------------------------
if not preLinkinPark and tourChanged then
output[#output + 1] =
renderHeader(tour)
end
------------------------------------------------------------
-- SHOW
------------------------------------------------------------
output[#output + 1] =
renderRow(row, frame)
------------------------------------------------------------
-- REMEMBER CURRENT VALUES
------------------------------------------------------------
if year ~= "" then
previousYear = year
end
if month ~= "" then
previousMonth = month
end
if tour ~= "" then
previousTour = tour
end
if artist ~= "" then
previousArtist = artist
end
previousRowTour = tour
end
return table.concat(output)
end
return p