Module:Factions

From BTAWiki
Revision as of 19:09, 5 May 2023 by Fulmir (talk | contribs) (Added some new linked factions, removed a few erroneous factions.)
Jump to navigation Jump to search

Documentation for this module may be created at Module:Factions/doc

-- Module:Factions handles translating faction tags to their full names

local p = {}

local mechs = require('Module:Mech').core
local getArgs = require('Module:Arguments').getArgs

-- Dictionary of faction tags translated to how we want them rendered in the mech list. Also used as an indicator of being a "major" parent faction
p.factionTags = {
  AuriganDirectorate = 'Aurigan Directorate',
  Mercenaries = '[[List_of_Mercenary_Factions_For_SPAM|Mercenaries]]',
  AuriganPirates = '[[Local Pirates|Pirates]]',
  AuriganRestoration = '[[Aurigan Coalition|Aurigan Restoration (Arano)]]',
  Chainelane = '[[Chainelane Isles]]',
  Circinus = '[[Circinus Federation]]',
  ClanDiamondShark = '[[Clan Diamond Shark]]',
  ClanGhostBear = '[[Clan Ghost Bear]]',
  ClanJadeFalcon = '[[Clan Jade Falcon]]',
  ClanNovaCat = '[[Clan Nova Cat]]',
  ClanSnowRaven = '[[Clan Snow Raven]]',
  ClanWolf = '[[Clan Wolf]]',
  ComStar = '[[ComStar]]',
  DaneSacellum = '[[Dane Sacellum]]',
  Davion = '[[Federated Suns|Federated Suns (Davion)]]',
  DarkCaste = '[[Dark Caste]]',
  Delphi = '[[New Delphi Compact]]',
  Hanse = '[[Hanseatic League]]',
  Illyrian = '[[Illyrian Palatinate]]',
  Ives = '[[St. Ives Compact]]',
  JacobsonHaven = '[[Jacobson Haven]]',
  JarnFolk = '[[JàrnFòlk]]',
  Kurita = '[[Draconis Combine|Draconis Combine (Kurita)]]',
  Liao = '[[Capellan Confederation|Capellan Confederation (Liao)]]',
  Locals = 'Local Government',
  Lothian= '[[Lothian League]]',
  MagistracyOfCanopus = '[[Magistracy of Canopus]]',
  MallardRepublic = '[[Mallard Republic]]',
  Marian = '[[Marian Hegemony]]',
  Marik = '[[Free Worlds League|Free Worlds League (Marik)]]',
  Outworld = '[[Outworlds Alliance]]',
  Rasalhague = '[[Free Rasalhague Republic]]',
  Rim = '[[Rim Collection]]',
  SanctuaryAlliance = '[[Sanctuary Alliance]]',
  Steiner = '[[Lyran Commonwealth|Lyran Commonwealth (Steiner)]]',
  TaurianConcordat = '[[Taurian Concordat]]',
  Tortuga = '[[Tortuga Dominions]]',
  WordOfBlake = '[[Word of Blake]]'
}

-- Translates all faction IDs to names. Excludes factions we don't care about, like anything translating to "Darius" or the Mercenary Review Board. Blacklist is maintained in external C# export tool.
p.factionIdsToNames = {
  ["Axumite"] = "Axumite Providence",
  ["Castile"] = "Nueva Castile",
  ["Chainelane"] = "Chainelane Isles",
  ["Circinus"] = "Circinus Federation",
  ["ClanBurrock"] = "Clan Burrock",
  ["ClanCloudCobra"] = "Clan Cloud Cobra",
  ["ClanCoyote"] = "Clan Coyote",
  ["ClanDiamondShark"] = "Clan Diamond Shark",
  ["ClanFireMandrill"] = "Clan Fire Mandrill",
  ["ClanGhostBear"] = "Clan Ghost Bear",
  ["ClanGoliathScorpion"] = "Clan Goliath Scorpion",
  ["ClanHellsHorses"] = "Clan Hell's Horses",
  ["ClanIceHellion"] = "Clan Ice Hellion",
  ["ClanJadeFalcon"] = "Clan Jade Falcon",
  ["ClanNovaCat"] = "Clan Nova Cat",
  ["ClansGeneric"] = "Clans",
  ["ClanSmokeJaguar"] = "Clan Smoke Jaguar",
  ["ClanSnowRaven"] = "Clan Snow Raven",
  ["ClanStarAdder"] = "Clan Star Adder",
  ["ClanSteelViper"] = "Clan Steel Viper",
  ["ClanWolf"] = "Clan Wolf",
  ["ClanWolfInExile"] = "Clan Wolf-in-Exile",
  ["ComStar"] = "ComStar",
  ["DaneSacellum"] = "Dane Sacellum",
  ["DarkCaste"] = "The Dark Caste",
  ["Delphi"] = "New Delphi Compact",
  ["Elysia"] = "Elysian Fields",
  ["Mercenaries"] = "Mercenaries",
  ["Hanse"] = "Hanseatic League",
  ["Illyrian"] = "Illyrian Palatinate",
  ["Ives"] = "St. Ives Compact",
  ["JacobsonHaven"] = "Jacobson Haven",
  ["JarnFolk"] = "JarnFolk",
  ["Lothian"] = "Lothian League",
  ["MallardRepublic"] = "Mallard Republic",
  ["Marian"] = "Marian Hegemony",
  ["Oberon"] = "Oberon Confederation",
  ["Outworld"] = "Outworld Alliance",
  ["Rasalhague"] = "Free Rasalhague Republic",
  ["Rim"] = "Rim Collection",
  ["SanctuaryAlliance"] = "Sanctuary Alliance",
  ["Tortuga"] = "Tortuga Dominions",
  ["Valkyrate"] = "Greater Valkyrate",
  ["Wolfs_Dragoons"] = "Wolf's Dragoons",
  ["WordOfBlake"] = "Word of Blake",
  ["10thLyranGuards"] = "10th Lyran Guards",
  ["11thArmyVEta"] = "11th Army V-Eta",
  ["11thAvalonHussars"] = "11th Avalon Hussars",
  ["12thVeganRangers"] = "12th Vegan Rangers",
  ["15thLyranRegulars"] = "15th Lyran Regulars",
  ["1stAllianceAirWing"] = "1st Alliance Air Wing",
  ["1stKitteryBorderers"] = "1st Kittery Borderers",
  ["1stKnightsOfTheInnerSphere"] = "1st Knights of the Inner Sphere",
  ["1stMcCarronsArmoredCavalry"] = "1st McCarron's Armored Cavalry",
  ["1stSwordOfLight"] = "1st Sword Of Light",
  ["1stTyr"] = "1st Tyr",
  ["21stCentauriLancers"] = "21st Centauri Lancers",
  ["2ndArmyVMu"] = "2nd Army V-Mu",
  ["2ndCanopianFusiliers"] = "2nd Canopian Fusiliers",
  ["2ndCrucisLancers"] = "2nd Crucis Lancers",
  ["2ndFreemen"] = "2nd Freemen",
  ["2ndFreeWorldsGuards"] = "2nd Free Worlds Guards",
  ["2ndLegionOfVega"] = "2nd Legion Of Vega",
  ["30thMarikMilitia"] = "30th Marik Militia",
  ["3rdAllianceAirWing"] = "3rd Alliance Air Wing",
  ["3rdNightStalkers"] = "3rd Night Stalkers",
  ["3rdTaurianLancers"] = "3rd Taurian Lancers",
  ["40thShadowDivision"] = "40th Shadow Division",
  ["4thAllianceAirWing"] = "4th Alliance Air Wing",
  ["4thKavalleri"] = "4th Kavalleri",
  ["51stDarkPanzerJaegers"] = "51st Dark Panzer Jaegers",
  ["5thDonegalGuards"] = "5th Donegal Guards",
  ["6thConfederationReserveCavalry"] = "6th Confederation Reserve Cavalry",
  ["6thLyranGuards"] = "6th Lyran Guards",
  ["7thArmyVIota"] = "7th Army V-Iota",
  ["9thDivisionWoB"] = "9th Division III-Gamma",
  ["AlwaysFaithful"] = "Always Faithful",
  ["AntianLanciarii"] = "Antian Lanciarii",
  ["AvantisAngels"] = "Avanti's Angels",
  ["BandOfTheDamned"] = "Band of the Damned",
  ["BannockburnsBandits"] = "Bannockburn's Bandits",
  ["BarrettsFusiliers"] = "Barrett's Fusiliers",
  ["BlackCaravel"] = "Black Caravel",
  ["Blackhearts"] = "The Blackhearts",
  ["BlackOutlaws"] = "The Black Outlaws",
  ["BlueStarIrregulars"] = "Blue Star Irregulars",
  ["BroadswordLegion"] = "Broadsword Legion",
  ["BronsonsHorde"] = "Bronson's Horde",
  ["BullardsArmoredCavalry"] = "Bullard's Armored Cavalry",
  ["BurrsBlackCobras"] = "Burr's Black Cobras",
  ["CaesarsCohorts"] = "Caesar's Cohorts",
  ["CamachosCaballeros"] = "Camacho's Caballeros",
  ["CanopianHighlanders"] = "Canopian Highlanders",
  ["CGBThetaGalaxy"] = "CGB Theta Galaxy",
  ["CJFIotaGalaxy"] = "CJF Iota Galaxy",
  ["CleanKill"] = "Clean Kill",
  ["CNCOmicronGalaxy"] = "CNC Omicron Galaxy",
  ["CohorsMorituri"] = "Cohors Morituri",
  ["CWEpsilonGalaxy"] = "CW Epsilon Galaxy",
  ["DavionAssaultGuards"] = "Davion Assault Guards",
  ["DeathCommandos"] = "Death Commandos",
  ["DeathsConsorts"] = "Death's Consorts",
  ["Dioscuri"] = "Dioscuri",
  ["DismalDisinherited"] = "Dismal Disinherited",
  ["Dragonslayers"] = "Dragonslayers",
  ["EridaniLightHorse"] = "Eridani Light Horse",
  ["FederatedFreemen"] = "Federated Freemen",
  ["FistOfMokal"] = "Fist Of Mokal",
  ["GraysGhosts"] = "Gray's Ghosts",
  ["GreenburgsGodzillas"] = "Greenburg's Godzillas",
  ["GrimDetermination"] = "Grim Determination",
  ["HarcourtsDestructors"] = "Harcourt's Destructors",
  ["HarlocksWarriors"] = "Harlock's Warriors",
  ["HsienHotheads"] = "Hsien Hotheads",
  ["ILegioMartiaVictrix"] = "I Legio Martia Victrix",
  ["IrukjandiCompany"] = "Irukjandi Company",
  ["JacobsJuggernauts"] = "Jacob's Juggernauts",
  ["KhorsakovsCossacks"] = "Khorsakov's Cossacks",
  ["KnightsOfCaerbannog"] = "Knights of Caerbannog",
  ["KnightsOfStCameron"] = "Knights Of St. Cameron",
  ["LangendorfLancers"] = "Langendorf Lancers",
  ["LethalInjection"] = "Lethal Injection",
  ["LindonsBattalion"] = "Lindon's Battalion",
  ["LoneStarRegiment"] = "Lone Star Regiment",
  ["LongwoodsBluecoats"] = "Longwood's Bluecoats",
  ["MagistracyCavaliers"] = "Magistracy Cavaliers",
  ["MobileFire"] = "Mobile Fire",
  ["MorrisonsExtractors"] = "Morrison's Extractors",
  ["NarhalsRaiders"] = "Narhal's Raiders",
  ["NewBeltPirates"] = "New Belt Pirates",
  ["NorthwindHighlanders"] = "Northwind Highlanders",
  ["OlsonsRangers"] = "Olson's Rangers",
  ["PleiadesHussars"] = "Pleiades Hussars",
  ["QuintsOlympianGroundpounders"] = "Quint's Olympian Groundpounders",
  ["RamiliesRaiders"] = "Ramilie's Raiders",
  ["RaventhirsIronHand"] = "Raventhir's Iron Hand",
  ["RomanovsCrusaders"] = "Romanov's Crusaders",
  ["RubinskysLightHorse"] = "Rubinsky's Light Horse",
  ["ScreamingEagles"] = "Screaming Eagles",
  ["ShenSeTian"] = "Shen-Se Tian",
  ["SimonsonsCutthroats"] = "Simonson's Cutthroats",
  ["SmithsonsChineseBandits"] = "Smithson's Chinese Bandits",
  ["SnordsIrregulars"] = "Snord's Irregulars",
  ["SolarisVIIMercLeague"] = "Solaris VII Mercenary League",
  ["TaurianGuard"] = "Taurian Guard",
  ["TheArcadians"] = "The Arcadians",
  ["TheKrushers"] = "The Krushers",
  ["ThermoPolice"] = "Thermo Police",
  ["ToothOfYmir"] = "Tooth of Ymir",
  ["TortugaFusiliers"] = "Tortuga Fusiliers",
  ["VanguardLegion"] = "Vanguard Legion",
  ["VLegioRipariensis"] = "V Legio Ripariensis",
  ["WarriorHouseImarra"] = "Warrior House Imarra",
  ["WinfieldsRegiment"] = "Winfield's Regiment",
  ["WoBProtectorateMilitia"] = "WoB Protectorate Militia",
  ["Betrayers"] = "Arano Betrayers",
  ["AuriganDirectorate"] = "Aurigan Directorate",
  ["AuriganPirates"] = "Pirates",
  ["AuriganRestoration"] = "Aurigan Restoration (Arano)",
  ["Davion"] = "Federated Suns (Davion)",
  ["GrayDeathLegion"] = "Gray Death Legion",
  ["KellHounds"] = "Kell Hounds",
  ["Kurita"] = "Draconis Combine (Kurita)",
  ["Liao"] = "Capellan Confederation (Liao)",
  ["Locals"] = "Planetary Government",
  ["MagistracyCentrella"] = "Magistracy of Centrella",
  ["MagistracyOfCanopus"] = "Magistracy of Canopus",
  ["MajestyMetals"] = "Majesty Metals & Manufacturing",
  ["Marik"] = "Free Worlds League (Marik)",
  ["Nautilus"] = "Nautilus Base Defenses",
  ["NoFaction"] = "Abandoned",
  ["Steiner"] = "Lyran Commonwealth (Steiner)",
  ["TaurianConcordat"] = "Taurian Concordat"
}

-- Translates SPAM sub-faction IDs to their parent faciton IDs. Translates all Mercenary companies to "Mercenaries"
p.spamFactionsToParents = {
  ["ClanWolf"] = "ClanWolf",
  ["CWEpsilonGalaxy"] = "ClanWolf",
  ["ClanNovaCat"] = "ClanNovaCat",
  ["CNCOmicronGalaxy"] = "ClanNovaCat",
  ["ClanJadeFalcon"] = "ClanJadeFalcon",
  ["CJFIotaGalaxy"] = "ClanJadeFalcon",
  ["ClanGhostBear"] = "ClanGhostBear",
  ["CGBThetaGalaxy"] = "ClanGhostBear",
  ["WordOfBlake"] = "WordOfBlake",
  ["40thShadowDivision"] = "WordOfBlake",
  ["9thDivisionWoB"] = "WordOfBlake",
  ["WoBProtectorateMilitia"] = "WordOfBlake",
  ["Liao"] = "Liao",
  ["DeathCommandos"] = "Liao",
  ["1stMcCarronsArmoredCavalry"] = "Liao",
  ["WarriorHouseImarra"] = "Liao",
  ["6thConfederationReserveCavalry"] = "Liao",
  ["Kurita"] = "Kurita",
  ["1stSwordOfLight"] = "Kurita",
  ["3rdNightStalkers"] = "Kurita",
  ["2ndLegionOfVega"] = "Kurita",
  ["Davion"] = "Davion",
  ["DavionAssaultGuards"] = "Davion",
  ["2ndCrucisLancers"] = "Davion",
  ["1stKitteryBorderers"] = "Davion",
  ["10thLyranGuards"] = "Davion",
  ["Steiner"] = "Steiner",
  ["6thLyranGuards"] = "Steiner",
  ["5thDonegalGuards"] = "Steiner",
  ["15thLyranRegulars"] = "Steiner",
  ["11thAvalonHussars"] = "Steiner",
  ["Marik"] = "Marik",
  ["1stKnightsOfTheInnerSphere"] = "Marik",
  ["2ndFreeWorldsGuards"] = "Marik",
  ["30thMarikMilitia"] = "Marik",
  ["ComStar"] = "ComStar",
  ["2ndArmyVMu"] = "ComStar",
  ["11thArmyVEta"] = "ComStar",
  ["7thArmyVIota"] = "ComStar",
  ["Rasalhague"] = "Rasalhague",
  ["1stTyr"] = "Rasalhague",
  ["2ndFreemen"] = "Rasalhague",
  ["4thKavalleri"] = "Rasalhague",
  ["TaurianConcordat"] = "TaurianConcordat",
  ["TaurianGuard"] = "TaurianConcordat",
  ["PleiadesHussars"] = "TaurianConcordat",
  ["3rdTaurianLancers"] = "TaurianConcordat",
  ["MagistracyOfCanopus"] = "MagistracyOfCanopus",
  ["RaventhirsIronHand"] = "MagistracyOfCanopus",
  ["2ndCanopianFusiliers"] = "MagistracyOfCanopus",
  ["MagistracyCavaliers"] = "MagistracyOfCanopus",
  ["Outworld"] = "Outworld",
  ["1stAllianceAirWing"] = "Outworld",
  ["3rdAllianceAirWing"] = "Outworld",
  ["4thAllianceAirWing"] = "Outworld",
  ["Marian"] = "Marian",
  ["ILegioMartiaVictrix"] = "Marian",
  ["VLegioRipariensis"] = "Marian",
  ["CohorsMorituri"] = "Marian",
  ["Mercenaries"] = 'Mercenaries',
  ["BroadswordLegion"] = 'Mercenaries',
  ["BurrsBlackCobras"] = 'Mercenaries',
  ["51stDarkPanzerJaegers"] = 'Mercenaries',
  ["FistOfMokal"] = 'Mercenaries',
  ["HsienHotheads"] = 'Mercenaries',
  ["SimonsonsCutthroats"] = 'Mercenaries',
  ["AlwaysFaithful"] = 'Mercenaries',
  ["LangendorfLancers"] = 'Mercenaries',
  ["LethalInjection"] = 'Mercenaries',
  ["OlsonsRangers"] = 'Mercenaries',
  ["TheArcadians"] = 'Mercenaries',
  ["BlueStarIrregulars"] = 'Mercenaries',
  ["12thVeganRangers"] = 'Mercenaries',
  ["Dioscuri"] = 'Mercenaries',
  ["FederatedFreemen"] = 'Mercenaries',
  ["HarlocksWarriors"] = 'Mercenaries',
  ["ScreamingEagles"] = 'Mercenaries',
  ["SmithsonsChineseBandits"] = 'Mercenaries',
  ["VanguardLegion"] = 'Mercenaries',
  ["AvantisAngels"] = 'Mercenaries',
  ["KellHounds"] = 'Mercenaries',
  ["KnightsOfStCameron"] = 'Mercenaries',
  ["MobileFire"] = 'Mercenaries',
  ["SnordsIrregulars"] = 'Mercenaries',
  ["CamachosCaballeros"] = 'Mercenaries',
  ["GreenburgsGodzillas"] = 'Mercenaries',
  ["NarhalsRaiders"] = 'Mercenaries',
  ["NorthwindHighlanders"] = 'Mercenaries',
  ["Wolfs_Dragoons"] = 'Mercenaries',
  ["BarrettsFusiliers"] = 'Mercenaries',
  ["Blackhearts"] = 'Mercenaries',
  ["TheKrushers"] = 'Mercenaries',
  ["RomanovsCrusaders"] = 'Mercenaries',
  ["BannockburnsBandits"] = 'Mercenaries',
  ["CleanKill"] = 'Mercenaries',
  ["LoneStarRegiment"] = 'Mercenaries',
  ["LongwoodsBluecoats"] = 'Mercenaries',
  ["CaesarsCohorts"] = 'Mercenaries',
  ["CanopianHighlanders"] = 'Mercenaries',
  ["DismalDisinherited"] = 'Mercenaries',
  ["Dragonslayers"] = 'Mercenaries',
  ["HarcourtsDestructors"] = 'Mercenaries',
  ["RamiliesRaiders"] = 'Mercenaries',
  ["ThermoPolice"] = 'Mercenaries',
  ["BronsonsHorde"] = 'Mercenaries',
  ["BullardsArmoredCavalry"] = 'Mercenaries',
  ["QuintsOlympianGroundpounders"] = 'Mercenaries',
  ["GraysGhosts"] = 'Mercenaries',
  ["BlackOutlaws"] = 'Mercenaries',
  ["21stCentauriLancers"] = 'Mercenaries',
  ["RubinskysLightHorse"] = 'Mercenaries',
  ["KhorsakovsCossacks"] = 'Mercenaries',
  ["EridaniLightHorse"] = 'Mercenaries',
  ["IrukjandiCompany"] = 'Mercenaries',
  ["AntianLanciarii"] = 'Mercenaries',
  ["BlackCaravel"] = 'Mercenaries',
  ["KnightsOfCaerbannog"] = 'Mercenaries',
  ["WinfieldsRegiment"] = 'Mercenaries',
  ["ToothOfYmir"] = 'Mercenaries',
  ["JacobsJuggernauts"] = 'Mercenaries',
  ["LindonsBattalion"] = 'Mercenaries',
  ["GrimDetermination"] = 'Mercenaries',
  ["SolarisVIIMercLeague"] = 'Mercenaries',
  ["BandOfTheDamned"] = 'Mercenaries',
  ["DeathsConsorts"] = 'Mercenaries',
  ["MorrisonsExtractors"] = 'Mercenaries',
  ["NewBeltPirates"] = 'Mercenaries',
  ["TortugaFusiliers"] = 'Mercenaries',
  ["ShenSeTian"] = 'Mercenaries'
}

-- Outputs a list of the mechs a faction can field.
function p.factionMechs(frame)
  local tpl_args = getArgs(frame, {parentFirst=true})

  local faction = tpl_args[1]
  local where = string.format('Mech.MechTags HOLDS "%s"', faction)

  -- some mechs share the same name but have different tonnages and therefore
  -- different pages to be linked to
  local function MakeMechLink(name, variant, tonnage)
    if (name == "Blackjack" and tonnage ~= "45") or
       (name == "Centurion" and tonnage ~= "50") or
       (name == "Corsair" and tonnage ~= "95") or
       (name == "Stalker" and tonnage ~= "85") or
       (name == "Mad Cat MK II" and tonnage ~= "90") then
      return string.format('[[%s_(%sT)#%s|%s (%sT) %s]]', name, tonnage, variant, name, tonnage, variant)
    elseif string.find(variant, "ZEU-X", 1, true) then
      return string.format('[[Zeus_X#%s|Zeus X %s]]', variant, variant)
    else
      return string.format('[[%s#%s|%s %s]]', name, variant, name, variant)
    end
  end

  -- when querying for mechs, set the limit to 4000. this is arbitrarily high
  -- (larger than the total number of mechs). without this, factions with lots
  -- of mechs would not show all of them.
  local factionMechData = mw.ext.cargo.query(
    'Mech,Chassis','Chassis.Name=Name,Chassis.VariantName=VariantName,Chassis.Tonnage=Tonnage',
    { join = 'Mech.ChassisID=Chassis.Id', where=where, limit=4000 }
  )

  -- Attribute with style def for section titles, used at the end of this section.
  local weightClassStyle = {
    style="font-size:16px;font-weight:bold;line-height:1.6;"
  }

  -- Set up separate unordered lists under a central div element
  local mechsList = mw.html.create('div')
  local lightList = mw.html.create('ul')
  lightList:cssText('column-count: 3;-moz-column-count: 3;-webkit-column-count: 3')
  local mediumList = mw.html.create('ul')
  mediumList:cssText('column-count: 3;-moz-column-count: 3;-webkit-column-count: 3')
  local heavyList = mw.html.create('ul')
  heavyList:cssText('column-count: 3;-moz-column-count: 3;-webkit-column-count: 3')
  local assaultList = mw.html.create('ul')
  assaultList:cssText('column-count: 3;-moz-column-count: 3;-webkit-column-count: 3')

  -- Sort mechs by tonnage category and assign them to the appropriate list. Since we go in order of decreasing tonnage we only need one if statement per group.
  for _, mech in ipairs(factionMechData) do
    if tonumber(mech.Tonnage) >= 80 then
    assaultList:tag('li'):wikitext(MakeMechLink(mech.Name, mech.VariantName, tostring(mech.Tonnage)))
    elseif tonumber(mech.Tonnage) >= 60 then
    heavyList:tag('li'):wikitext(MakeMechLink(mech.Name, mech.VariantName, tostring(mech.Tonnage)))
    elseif tonumber(mech.Tonnage) >= 40 then
    mediumList:tag('li'):wikitext(MakeMechLink(mech.Name, mech.VariantName, tostring(mech.Tonnage)))
    else
    lightList:tag('li'):wikitext(MakeMechLink(mech.Name, mech.VariantName, tostring(mech.Tonnage)))
    end
  end
  -- Create a div to hold each list, create a div for the title section, apply attributes, and then escape the div before inserting the pre-populated list for that section.
  mechsList:tag('div'):tag('div'):wikitext("Assault Mechs"):attr(weightClassStyle):done():node(assaultList)
  mechsList:tag('div'):tag('div'):wikitext("Heavy Mechs"):attr(weightClassStyle):done():node(heavyList)
  mechsList:tag('div'):tag('div'):wikitext("Medium Mechs"):attr(weightClassStyle):done():node(mediumList)
  mechsList:tag('div'):tag('div'):wikitext("Light Mechs"):attr(weightClassStyle):done():node(lightList)
  
  return mechsList
end

function p.mechFactions(frame)
  -- Get the mech variant from args that we're working with here.
  local tpl_args = getArgs(frame, {parentFirst=true})
  variant = tpl_args[1]

  local mech = mechs.mech.byVariant(variant)

  -- If mech isn't found, return null
  if mech == nil then
    return mw.html.create('div').wikitext("''Mech not found''")
  end

  local spamDict = {}
  local tags = {}
  local factionIdSortedKeys = {}

  -- loops through the tags from the mech entry
  for _, tag in ipairs(mech.tags) do
    -- If the tag corresponds to a faction name that we care about then we want to sort it into our spamDict faction dictionary, by parent if it has one.
    if p.factionIdsToNames[tag] ~= nil then
      -- If it has a parent entry AND we don't already have an entry in the spamDict then create a new empty sub-array for it. Also insert the parent faction into our list of keys to be sorted later.
      if p.spamFactionsToParents[tag] ~= nil and spamDict[p.spamFactionsToParents[tag]] == nil then
        spamDict[p.spamFactionsToParents[tag]] = {}
        table.insert(factionIdSortedKeys, p.spamFactionsToParents[tag])
      -- If it's NOT in the Parent Faction dictionary AND it's in the faction names list, AND it doesn't already have an entry in the spamDict, then create one, and add the faction to our keys list for sorting.
      elseif p.spamFactionsToParents[tag] == nil and (p.factionIdsToNames[tag] ~= nil and spamDict[tag] == nil) then
        spamDict[tag] = {}
        table.insert(spamDict[tag], tag)
        table.insert(factionIdSortedKeys, tag)
      end
      -- If we don't need to create a new entry then just add the faction tag to the appropriate parent-faction sub-array
      -- First make sure it has a parent tag. Serves as a duplicates check.
      if (p.spamFactionsToParents[tag] ~= nil) then
        table.insert(spamDict[(p.spamFactionsToParents[tag])], tag)
      end
    end
  end

  if table.getn(factionIdSortedKeys) == 0 then
    return mw.html.create('div').wikitext("''Mech not found with any factions, it's probably obtained from Game World contracts or an event!'")
  end

  -- sort the list of parent faction keys so we can put them into the html in the right order. Use the raw names so we don't get all the unlinked names going at the top.
  local function sortByNamesFromIds(first, second)
    if (p.factionIdsToNames[first] or "a") == (p.factionIdsToNames[second] or "b") then
      return false
    else
      return (p.factionIdsToNames[first] or "a") < (p.factionIdsToNames[second] or "b")
    end
  end

  table.sort(factionIdSortedKeys, sortByNamesFromIds)

  -- Also sort the sub-faction lists, with any parent factions going at the top
  local function sortSubFactions(first, second)
    if first == nil or p.factionTags[first] == nil then
      return false
    elseif second == nil or p.factionTags[second] == nil then
      return true
    else
      return (p.factionIdsToNames[first] or "a") < (p.factionIdsToNames[second] or "b")
    end
  end

  for key, subList in pairs(spamDict) do
    table.sort(subList, sortSubFactions)
  end

  -- Set up our HTML bits, we'll use these in a moment...
  local factionList = mw.html.create('ul')
  local collapsibleTagAttributes = {
    class = 'mw-collapsible mw-collapsed'
  }
  local collapsibleContentTagAttributes = {
    class = 'mw-collapsible-content'
  }

  -- Loop through the sorted list of keys. We're doing it this way so the factions come out sorted in roughly alphabetical order
  for _, factionId in ipairs(factionIdSortedKeys) do
    -- If there's only one faction entry and it's not 'nil' then we create a simpler HTML list item
    if table.getn(spamDict[factionId]) == 1 and factionId == spamDict[factionId][1] then
      if p.factionTags[factionId] ~= nil then
        factionList:tag('li'):wikitext(p.factionTags[factionId])
      elseif p.factionIdsToNames[factionId] ~= nil then
        factionList:tag('li'):wikitext(p.factionIdsToNames[factionId])
      end
    -- If there's more than one item then we need to create a collapsible list item element with sub-entries
    else
      -- Create a collapsible div to start
      tempTagConstruct = mw.html.create('div'):attr(collapsibleTagAttributes)
      -- Do a 'nil' check and then create the list item with the parent faction's readible name out of the factionTags list. The fallback to the larger names list shouldn't be necessary but it's there just in case.
      if p.factionTags[p.spamFactionsToParents[factionId]] ~= nil then
        tempTagConstruct:tag('li'):wikitext((p.factionTags[p.spamFactionsToParents[factionId]]) or (p.factionIdsToNames[p.spamFactionsToParents[factionId]]))
      end
      -- Create the sub-list element for the inner list of sub-factions, and assign it to a temp variable.
      -- This is so we can add the whole list back onto the tag construct so it doesn't get confused about where tags should go.
      tempSubConstruct = mw.html.create('ul')
      -- Itterate through the list of sub-factions and add each to the inner list, tranlated to its proper name, as a list item
      for __, subFactionId in ipairs(spamDict[factionId]) do
        tempSubConstruct:tag('li'):wikitext(p.factionIdsToNames[subFactionId])
      end
      -- Add a collapsible content div so the parent faction name will stay visible. Then add the sub-list all in one go.
      tempTagConstruct:tag('div'):attr(collapsibleContentTagAttributes):node(tempSubConstruct)
      -- Add the whole list item element to the large list
      factionList:node(tempTagConstruct)
    end
  end
  
  -- Return our mostrous HTML construct to be rendered on the page
  return factionList
end

return p