Difference between revisions of "Module:Factions"

From BTAWiki
Jump to navigation Jump to search
 
(29 intermediate revisions by 3 users not shown)
Line 6: Line 6:
 
local getArgs = require('Module:Arguments').getArgs
 
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 = {
 
p.factionTags = {
 +
  ["331stDivision"] = 'The 331st Royal BattleMech Division',
 
   AuriganDirectorate = 'Aurigan Directorate',
 
   AuriganDirectorate = 'Aurigan Directorate',
  AuriganMercenaries = 'Mercenaries',
 
 
   AuriganPirates = '[[Local Pirates|Pirates]]',
 
   AuriganPirates = '[[Local Pirates|Pirates]]',
 
   AuriganRestoration = '[[Aurigan Coalition|Aurigan Restoration (Arano)]]',
 
   AuriganRestoration = '[[Aurigan Coalition|Aurigan Restoration (Arano)]]',
 +
  Cameron = '[[Terran Hegemony (Cameron)]]',
 +
  CalderonProtectorate = '[[Calderon Protectorate ]]',
 
   Chainelane = '[[Chainelane Isles]]',
 
   Chainelane = '[[Chainelane Isles]]',
 
   Circinus = '[[Circinus Federation]]',
 
   Circinus = '[[Circinus Federation]]',
 
   ClanDiamondShark = '[[Clan Diamond Shark]]',
 
   ClanDiamondShark = '[[Clan Diamond Shark]]',
 +
  ClanFireMandrill = '[[Clan Fire Mandrill]]',
 
   ClanGhostBear = '[[Clan Ghost Bear]]',
 
   ClanGhostBear = '[[Clan Ghost Bear]]',
 +
  ClanGoliathScorpion = '[[Clan Goliath Scorpion]]',
 
   ClanJadeFalcon = '[[Clan Jade Falcon]]',
 
   ClanJadeFalcon = '[[Clan Jade Falcon]]',
 
   ClanNovaCat = '[[Clan Nova Cat]]',
 
   ClanNovaCat = '[[Clan Nova Cat]]',
 +
  ClanSnowRaven = '[[Clan Snow Raven]]',
 
   ClanWolf = '[[Clan Wolf]]',
 
   ClanWolf = '[[Clan Wolf]]',
 
   ComStar = '[[ComStar]]',
 
   ComStar = '[[ComStar]]',
 +
  DaneSacellum = '[[Dane Sacellum]]',
 
   Davion = '[[Federated Suns|Federated Suns (Davion)]]',
 
   Davion = '[[Federated Suns|Federated Suns (Davion)]]',
 +
  DarkCaste = '[[Dark Caste]]',
 
   Delphi = '[[New Delphi Compact]]',
 
   Delphi = '[[New Delphi Compact]]',
 +
  FroncReaches = '[[Fronc Reaches]]',
 
   Hanse = '[[Hanseatic League]]',
 
   Hanse = '[[Hanseatic League]]',
 +
  Illyrian = '[[Illyrian Palatinate]]',
 
   Ives = '[[St. Ives Compact]]',
 
   Ives = '[[St. Ives Compact]]',
 +
  JacobsonHaven = '[[Jacobson Haven]]',
 
   JarnFolk = '[[JàrnFòlk]]',
 
   JarnFolk = '[[JàrnFòlk]]',
 
   Kurita = '[[Draconis Combine|Draconis Combine (Kurita)]]',
 
   Kurita = '[[Draconis Combine|Draconis Combine (Kurita)]]',
 
   Liao = '[[Capellan Confederation|Capellan Confederation (Liao)]]',
 
   Liao = '[[Capellan Confederation|Capellan Confederation (Liao)]]',
 
   Locals = 'Local Government',
 
   Locals = 'Local Government',
   MagistracyofCanopus = '[[Magistracy of Canopus]]',
+
   Lothian= '[[Lothian League]]',
 
   MagistracyOfCanopus = '[[Magistracy of Canopus]]',
 
   MagistracyOfCanopus = '[[Magistracy of Canopus]]',
 +
  MallardRepublic = '[[Mallard Republic]]',
 
   Marian = '[[Marian Hegemony]]',
 
   Marian = '[[Marian Hegemony]]',
 
   Marik = '[[Free Worlds League|Free Worlds League (Marik)]]',
 
   Marik = '[[Free Worlds League|Free Worlds League (Marik)]]',
 +
  Mercenaries = '[[List_of_Mercenary_Factions_For_SPAM|Mercenaries]]',
 
   Outworld = '[[Outworlds Alliance]]',
 
   Outworld = '[[Outworlds Alliance]]',
 
   Rasalhague = '[[Free Rasalhague Republic]]',
 
   Rasalhague = '[[Free Rasalhague Republic]]',
   Rim = '[[Rim Collection]]',
+
   RimWorldsRepublic = '[[Rim Worlds Republic]]',
 +
  SanctuaryAlliance = '[[Sanctuary Alliance]]',
 +
  ScorpionEmpire = '[[Scorpion Empire]]',
 
   Steiner = '[[Lyran Commonwealth|Lyran Commonwealth (Steiner)]]',
 
   Steiner = '[[Lyran Commonwealth|Lyran Commonwealth (Steiner)]]',
 
   TaurianConcordat = '[[Taurian Concordat]]',
 
   TaurianConcordat = '[[Taurian Concordat]]',
Line 40: Line 55:
 
}
 
}
  
 +
-- 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 = {
 +
  ["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",
 +
  ["1stHeliusLegionnaires"] = "1st Helius Legionnaires",
 +
  ["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",
 +
  ["331stDivision"] = "The 331st Royal BattleMech Division",
 +
  ["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",
 +
  ["8thHeliusFusiliers"] = "8th Helius Fusiliers",
 +
  ["9thDivisionWoB"] = "9th Division III-Gamma",
 +
  ["AlwaysFaithful"] = "Always Faithful",
 +
  ["AntianLanciarii"] = "Antian Lanciarii",
 +
  ["AuriganDirectorate"] = "Aurigan Directorate",
 +
  ["AuriganPirates"] = "Pirates",
 +
  ["AuriganRestoration"] = "Aurigan Restoration (Arano)",
 +
  ["AvantisAngels"] = "Avanti's Angels",
 +
  ["Axumite"] = "Axumite Providence",
 +
  ["BandOfTheDamned"] = "Band of the Damned",
 +
  ["BannockburnsBandits"] = "Bannockburn's Bandits",
 +
  ["BarrettsFusiliers"] = "Barrett's Fusiliers",
 +
  ["Betrayers"] = "Arano Betrayers",
 +
  ["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",
 +
  ["Cameron"] = "Terran Hegemony (Cameron)",
 +
  ["CanopianHighlanders"] = "Canopian Highlanders",
 +
  ["Castile"] = "Nueva Castile",
 +
  ["CGBThetaGalaxy"] = "CGB Theta Galaxy",
 +
  ["CGSOmegaGalaxy"] = "CGS Omega Galaxy",
 +
  ["Chainelane"] = "Chainelane Isles",
 +
  ["Circinus"] = "Circinus Federation",
 +
  ["CJFIotaGalaxy"] = "CJF Iota Galaxy",
 +
  ["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",
 +
  ["CleanKill"] = "Clean Kill",
 +
  ["CNCOmicronGalaxy"] = "CNC Omicron Galaxy",
 +
  ["CohorsMorituri"] = "Cohors Morituri",
 +
  ["ComStar"] = "ComStar",
 +
  ["CSRDeltaGalaxy"] = "CSR Delta Galaxy",
 +
  ["CWEpsilonGalaxy"] = "CW Epsilon Galaxy",
 +
  ["DaneSacellum"] = "Dane Sacellum",
 +
  ["DarkCaste"] = "The Dark Caste",
 +
  ["Davion"] = "Federated Suns (Davion)",
 +
  ["DavionAssaultGuards"] = "Davion Assault Guards",
 +
  ["DeathCommandos"] = "Death Commandos",
 +
  ["DeathsConsorts"] = "Death's Consorts",
 +
  ["Delphi"] = "New Delphi Compact",
 +
  ["Dioscuri"] = "Dioscuri",
 +
  ["DismalDisinherited"] = "Dismal Disinherited",
 +
  ["Dragonslayers"] = "Dragonslayers",
 +
  ["Elysia"] = "Elysian Fields",
 +
  ["EridaniLightHorse"] = "Eridani Light Horse",
 +
  ["FederatedFreemen"] = "Federated Freemen",
 +
  ["FistOfMokal"] = "Fist Of Mokal",
 +
  ["GrayDeathLegion"] = "Gray Death Legion",
 +
  ["GraysGhosts"] = "Gray's Ghosts",
 +
  ["GreenburgsGodzillas"] = "Greenburg's Godzillas",
 +
  ["GrimDetermination"] = "Grim Determination",
 +
  ["Hanse"] = "Hanseatic League",
 +
  ["HarcourtsDestructors"] = "Harcourt's Destructors",
 +
  ["HarlocksWarriors"] = "Harlock's Warriors",
 +
  ["HsienHotheads"] = "Hsien Hotheads",
 +
  ["ILegioMartiaVictrix"] = "I Legio Martia Victrix",
 +
  ["Illyrian"] = "Illyrian Palatinate",
 +
  ["IrukjandiCompany"] = "Irukjandi Company",
 +
  ["Ives"] = "St. Ives Compact",
 +
  ["JacobsJuggernauts"] = "Jacob's Juggernauts",
 +
  ["JacobsonHaven"] = "Jacobson Haven",
 +
  ["JarnFolk"] = "JarnFolk",
 +
  ["KellHounds"] = "Kell Hounds",
 +
  ["KhorsakovsCossacks"] = "Khorsakov's Cossacks",
 +
  ["KindraaSainze"] = "Kindraa Sainze",
 +
  ["KindraaFaradayTanaga"] = "Kindraa Faraday-Tanaga",
 +
  ["KindraaMickKreese"] = "Kindraa Mick-Kreese",
 +
  ["KnightsOfCaerbannog"] = "Knights of Caerbannog",
 +
  ["KnightsOfStCameron"] = "Knights Of St. Cameron",
 +
  ["Kurita"] = "Draconis Combine (Kurita)",
 +
  ["LangendorfLancers"] = "Langendorf Lancers",
 +
  ["LethalInjection"] = "Lethal Injection",
 +
  ["Liao"] = "Capellan Confederation (Liao)",
 +
  ["LindonsBattalion"] = "Lindon's Battalion",
 +
  ["Locals"] = "Planetary Government",
 +
  ["LoneStarRegiment"] = "Lone Star Regiment",
 +
  ["LongwoodsBluecoats"] = "Longwood's Bluecoats",
 +
  ["Lothian"] = "Lothian League",
 +
  ["MagistracyCavaliers"] = "Magistracy Cavaliers",
 +
  ["MagistracyCentrella"] = "Magistracy of Centrella",
 +
  ["MagistracyOfCanopus"] = "Magistracy of Canopus",
 +
  ["MajestyMetals"] = "Majesty Metals & Manufacturing",
 +
  ["MallardRepublic"] = "Mallard Republic",
 +
  ["Marian"] = "Marian Hegemony",
 +
  ["Marik"] = "Free Worlds League (Marik)",
 +
  ["Mercenaries"] = "Mercenaries",
 +
  ["MobileFire"] = "Mobile Fire",
 +
  ["MorrisonsExtractors"] = "Morrison's Extractors",
 +
  ["NarhalsRaiders"] = "Narhal's Raiders",
 +
  ["Nautilus"] = "Nautilus Base Defenses",
 +
  ["NewBeltPirates"] = "New Belt Pirates",
 +
  ["NoFaction"] = "Abandoned",
 +
  ["NorthwindHighlanders"] = "Northwind Highlanders",
 +
  ["Oberon"] = "Oberon Confederation",
 +
  ["OlsonsRangers"] = "Olson's Rangers",
 +
  ["Outworld"] = "Outworld Alliance",
 +
  ["PleiadesHussars"] = "Pleiades Hussars",
 +
  ["QuintsOlympianGroundpounders"] = "Quint's Olympian Groundpounders",
 +
  ["RamiliesRaiders"] = "Ramilie's Raiders",
 +
  ["Rasalhague"] = "Free Rasalhague Republic",
 +
  ["RaventhirsIronHand"] = "Raventhir's Iron Hand",
 +
  ["RepublicanGuard"] = "Republican Guard",
 +
  ["RimWorldsRepublic"] = "Rim Worlds Republic",
 +
  ["RomanovsCrusaders"] = "Romanov's Crusaders",
 +
  ["RubinskysLightHorse"] = "Rubinsky's Light Horse",
 +
  ["SaiphTriumvirate"] = "Saiph Triumvirate",
 +
  ["SanctuaryAlliance"] = "Sanctuary Alliance",
 +
  ["ScorpionEmpire"] = "Scorpion Empire",
 +
  ["SarnaSupremacy"] = "Sarna Supremacy",
 +
  ["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",
 +
  ["Steiner"] = "Lyran Commonwealth (Steiner)",
 +
  ["StykCommonality"] = "Styk Commonality",
 +
  ["TaurianConcordat"] = "Taurian Concordat",
 +
  ["TaurianGuard"] = "Taurian Guard",
 +
  ["TerracapConfederation"] = "Terracap Confederation",
 +
  ["TheArcadians"] = "The Arcadians",
 +
  ["TheKrushers"] = "The Krushers",
 +
  ["ThermoPolice"] = "Thermo Police",
 +
  ["ToothOfYmir"] = "Tooth of Ymir",
 +
  ["Tortuga"] = "Tortuga Dominions",
 +
  ["TortugaFusiliers"] = "Tortuga Fusiliers",
 +
  ["Valkyrate"] = "Greater Valkyrate",
 +
  ["VanguardLegion"] = "Vanguard Legion",
 +
  ["VLegioRipariensis"] = "V Legio Ripariensis",
 +
  ["WarriorHouseImarra"] = "Warrior House Imarra",
 +
  ["WinfieldsRegiment"] = "Winfield's Regiment",
 +
  ["WoBProtectorateMilitia"] = "WoB Protectorate Militia",
 +
  ["Wolfs_Dragoons"] = "Wolf's Dragoons",
 +
  ["WordOfBlake"] = "Word of Blake"
 +
}
 +
 +
-- Translates SPAM sub-faction IDs to their parent faciton IDs. Translates all Mercenary companies to "Mercenaries"
 +
p.spamFactionsToParents = {
 +
  ["Cameron"] = "Cameron",
 +
  ["StarGuardCorps"] = "Cameron",
 +
  ["ICorps"] = "Cameron",
 +
  ["IVCorps"] = "Cameron",
 +
  ["ClanWolf"] = "ClanWolf",
 +
  ["CWEpsilonGalaxy"] = "ClanWolf",
 +
  ["ClanNovaCat"] = "ClanNovaCat",
 +
  ["CNCOmicronGalaxy"] = "ClanNovaCat",
 +
  ["ClanJadeFalcon"] = "ClanJadeFalcon",
 +
  ["CJFIotaGalaxy"] = "ClanJadeFalcon",
 +
  ["ClanGhostBear"] = "ClanGhostBear",
 +
  ["CGBThetaGalaxy"] = "ClanGhostBear",
 +
  ["ClanGoliathScorpion"] = "ClanGoliathScorpion",
 +
  ["CGSOmegaGalaxy"] = "ClanGoliathScorpion",
 +
  ["ClanFireMandrill"] = "ClanFireMandrill",
 +
  ["KindraaSainze"] = "ClanFireMandrill",
 +
  ["KindraaFaradayTanaga"] = "ClanFireMandrill",
 +
  ["KindraaMickKreese"] = "ClanFireMandrill",
 +
  ["ClanSnowRaven"] = "ClanSnowRaven",
 +
  ["CSRDeltaGalaxy"] = "ClanSnowRaven",
 +
  ["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",
 +
  ["RimWorldsRepublic"] = "RimWorldsRepublic",
 +
  ["1stHeliusLegionnaires"] = "RimWorldsRepublic",
 +
  ["8thHeliusFusiliers"] = "RimWorldsRepublic",
 +
  ["RepublicanGuard"] = "RimWorldsRepublic",
 +
  ["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)
 
function p.factionMechs(frame)
 
   local tpl_args = getArgs(frame, {parentFirst=true})
 
   local tpl_args = getArgs(frame, {parentFirst=true})
Line 53: Line 409:
 
       (name == "Centurion" and tonnage ~= "50") or
 
       (name == "Centurion" and tonnage ~= "50") or
 
       (name == "Corsair" and tonnage ~= "95") or
 
       (name == "Corsair" and tonnage ~= "95") or
       (name == "Stalker" and tonnage ~= "85") then
+
       (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)
 
       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
 
     else
 
       return string.format('[[%s#%s|%s %s]]', name, variant, name, variant)
 
       return string.format('[[%s#%s|%s %s]]', name, variant, name, variant)
Line 60: Line 419:
 
   end
 
   end
  
   -- when querying for mechs, set the limit to 2000. this is arbitrarily high
+
   -- 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
 
   -- (larger than the total number of mechs). without this, factions with lots
 
   -- of mechs would not show all of them.
 
   -- of mechs would not show all of them.
 
   local factionMechData = mw.ext.cargo.query(
 
   local factionMechData = mw.ext.cargo.query(
 
     'Mech,Chassis','Chassis.Name=Name,Chassis.VariantName=VariantName,Chassis.Tonnage=Tonnage',
 
     'Mech,Chassis','Chassis.Name=Name,Chassis.VariantName=VariantName,Chassis.Tonnage=Tonnage',
     { join = 'Mech.ChassisID=Chassis.Id', where=where, limit=2000 }
+
     { join = 'Mech.ChassisID=Chassis.Id', where=where, limit=4000 }
 
   )
 
   )
  
   local mechsList = mw.html.create('ul')
+
  -- Attribute with style def for section titles, used at the end of this section.
   mechsList:cssText('column-count: 3;-moz-column-count: 3;-webkit-column-count: 3')
+
  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
 
   for _, mech in ipairs(factionMechData) do
     mechsList:tag('li'):wikitext(MakeMechLink(mech.Name, mech.VariantName, tostring(mech.Tonnage)))
+
     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
 
   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
 
   return mechsList
 
end
 
end
  
 
function p.mechFactions(frame)
 
function p.mechFactions(frame)
 +
  -- Get the mech variant from args that we're working with here.
 
   local tpl_args = getArgs(frame, {parentFirst=true})
 
   local tpl_args = getArgs(frame, {parentFirst=true})
 
   variant = tpl_args[1]
 
   variant = tpl_args[1]
Line 82: Line 471:
 
   local mech = mechs.mech.byVariant(variant)
 
   local mech = mechs.mech.byVariant(variant)
  
 +
  -- If mech isn't found, return null
 
   if mech == nil then
 
   if mech == nil then
 
     return mw.html.create('div').wikitext("''Mech not found''")
 
     return mw.html.create('div').wikitext("''Mech not found''")
 
   end
 
   end
  
 +
  local spamDict = {}
 
   local tags = {}
 
   local tags = {}
 +
  local factionIdSortedKeys = {}
  
   local factionList = mw.html.create('ul')
+
   -- 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)
  
   for _, tag in ipairs(mech.tags) do
+
   -- Also sort the sub-faction lists, with any parent factions going at the top
     if p.factionTags[tag] ~= nil then
+
  local function sortSubFactions(first, second)
       table.insert(tags, p.factionTags[tag])
+
     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
 
   end
 
   end
  
   table.sort(tags)
+
   for key, subList in pairs(spamDict) do
   for _, tag in ipairs(tags) do
+
    table.sort(subList, sortSubFactions)
     factionList:tag('li'):wikitext(tag)
+
  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
 
   end
 
    
 
    
 +
  -- Return our mostrous HTML construct to be rendered on the page
 
   return factionList
 
   return factionList
 
end
 
end
  
 
return p
 
return p

Latest revision as of 03:46, 19 October 2024

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 = {
  ["331stDivision"] = 'The 331st Royal BattleMech Division',
  AuriganDirectorate = 'Aurigan Directorate',
  AuriganPirates = '[[Local Pirates|Pirates]]',
  AuriganRestoration = '[[Aurigan Coalition|Aurigan Restoration (Arano)]]',
  Cameron = '[[Terran Hegemony (Cameron)]]',
  CalderonProtectorate = '[[Calderon Protectorate ]]',
  Chainelane = '[[Chainelane Isles]]',
  Circinus = '[[Circinus Federation]]',
  ClanDiamondShark = '[[Clan Diamond Shark]]',
  ClanFireMandrill = '[[Clan Fire Mandrill]]',
  ClanGhostBear = '[[Clan Ghost Bear]]',
  ClanGoliathScorpion = '[[Clan Goliath Scorpion]]',
  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]]',
  FroncReaches = '[[Fronc Reaches]]',
  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)]]',
  Mercenaries = '[[List_of_Mercenary_Factions_For_SPAM|Mercenaries]]',
  Outworld = '[[Outworlds Alliance]]',
  Rasalhague = '[[Free Rasalhague Republic]]',
  RimWorldsRepublic = '[[Rim Worlds Republic]]',
  SanctuaryAlliance = '[[Sanctuary Alliance]]',
  ScorpionEmpire = '[[Scorpion Empire]]',
  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 = {
  ["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",
  ["1stHeliusLegionnaires"] = "1st Helius Legionnaires",
  ["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",
  ["331stDivision"] = "The 331st Royal BattleMech Division",
  ["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",
  ["8thHeliusFusiliers"] = "8th Helius Fusiliers",
  ["9thDivisionWoB"] = "9th Division III-Gamma",
  ["AlwaysFaithful"] = "Always Faithful",
  ["AntianLanciarii"] = "Antian Lanciarii",
  ["AuriganDirectorate"] = "Aurigan Directorate",
  ["AuriganPirates"] = "Pirates",
  ["AuriganRestoration"] = "Aurigan Restoration (Arano)",
  ["AvantisAngels"] = "Avanti's Angels",
  ["Axumite"] = "Axumite Providence",
  ["BandOfTheDamned"] = "Band of the Damned",
  ["BannockburnsBandits"] = "Bannockburn's Bandits",
  ["BarrettsFusiliers"] = "Barrett's Fusiliers",
  ["Betrayers"] = "Arano Betrayers",
  ["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",
  ["Cameron"] = "Terran Hegemony (Cameron)",
  ["CanopianHighlanders"] = "Canopian Highlanders",
  ["Castile"] = "Nueva Castile",
  ["CGBThetaGalaxy"] = "CGB Theta Galaxy",
  ["CGSOmegaGalaxy"] = "CGS Omega Galaxy",
  ["Chainelane"] = "Chainelane Isles",
  ["Circinus"] = "Circinus Federation",
  ["CJFIotaGalaxy"] = "CJF Iota Galaxy",
  ["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",
  ["CleanKill"] = "Clean Kill",
  ["CNCOmicronGalaxy"] = "CNC Omicron Galaxy",
  ["CohorsMorituri"] = "Cohors Morituri",
  ["ComStar"] = "ComStar",
  ["CSRDeltaGalaxy"] = "CSR Delta Galaxy",
  ["CWEpsilonGalaxy"] = "CW Epsilon Galaxy",
  ["DaneSacellum"] = "Dane Sacellum",
  ["DarkCaste"] = "The Dark Caste",
  ["Davion"] = "Federated Suns (Davion)",
  ["DavionAssaultGuards"] = "Davion Assault Guards",
  ["DeathCommandos"] = "Death Commandos",
  ["DeathsConsorts"] = "Death's Consorts",
  ["Delphi"] = "New Delphi Compact",
  ["Dioscuri"] = "Dioscuri",
  ["DismalDisinherited"] = "Dismal Disinherited",
  ["Dragonslayers"] = "Dragonslayers",
  ["Elysia"] = "Elysian Fields",
  ["EridaniLightHorse"] = "Eridani Light Horse",
  ["FederatedFreemen"] = "Federated Freemen",
  ["FistOfMokal"] = "Fist Of Mokal",
  ["GrayDeathLegion"] = "Gray Death Legion",
  ["GraysGhosts"] = "Gray's Ghosts",
  ["GreenburgsGodzillas"] = "Greenburg's Godzillas",
  ["GrimDetermination"] = "Grim Determination",
  ["Hanse"] = "Hanseatic League",
  ["HarcourtsDestructors"] = "Harcourt's Destructors",
  ["HarlocksWarriors"] = "Harlock's Warriors",
  ["HsienHotheads"] = "Hsien Hotheads",
  ["ILegioMartiaVictrix"] = "I Legio Martia Victrix",
  ["Illyrian"] = "Illyrian Palatinate",
  ["IrukjandiCompany"] = "Irukjandi Company",
  ["Ives"] = "St. Ives Compact",
  ["JacobsJuggernauts"] = "Jacob's Juggernauts",
  ["JacobsonHaven"] = "Jacobson Haven",
  ["JarnFolk"] = "JarnFolk",
  ["KellHounds"] = "Kell Hounds",
  ["KhorsakovsCossacks"] = "Khorsakov's Cossacks",
  ["KindraaSainze"] = "Kindraa Sainze",
  ["KindraaFaradayTanaga"] = "Kindraa Faraday-Tanaga",
  ["KindraaMickKreese"] = "Kindraa Mick-Kreese",
  ["KnightsOfCaerbannog"] = "Knights of Caerbannog",
  ["KnightsOfStCameron"] = "Knights Of St. Cameron",
  ["Kurita"] = "Draconis Combine (Kurita)",
  ["LangendorfLancers"] = "Langendorf Lancers",
  ["LethalInjection"] = "Lethal Injection",
  ["Liao"] = "Capellan Confederation (Liao)",
  ["LindonsBattalion"] = "Lindon's Battalion",
  ["Locals"] = "Planetary Government",
  ["LoneStarRegiment"] = "Lone Star Regiment",
  ["LongwoodsBluecoats"] = "Longwood's Bluecoats",
  ["Lothian"] = "Lothian League",
  ["MagistracyCavaliers"] = "Magistracy Cavaliers",
  ["MagistracyCentrella"] = "Magistracy of Centrella",
  ["MagistracyOfCanopus"] = "Magistracy of Canopus",
  ["MajestyMetals"] = "Majesty Metals & Manufacturing",
  ["MallardRepublic"] = "Mallard Republic",
  ["Marian"] = "Marian Hegemony",
  ["Marik"] = "Free Worlds League (Marik)",
  ["Mercenaries"] = "Mercenaries",
  ["MobileFire"] = "Mobile Fire",
  ["MorrisonsExtractors"] = "Morrison's Extractors",
  ["NarhalsRaiders"] = "Narhal's Raiders",
  ["Nautilus"] = "Nautilus Base Defenses",
  ["NewBeltPirates"] = "New Belt Pirates",
  ["NoFaction"] = "Abandoned",
  ["NorthwindHighlanders"] = "Northwind Highlanders",
  ["Oberon"] = "Oberon Confederation",
  ["OlsonsRangers"] = "Olson's Rangers",
  ["Outworld"] = "Outworld Alliance",
  ["PleiadesHussars"] = "Pleiades Hussars",
  ["QuintsOlympianGroundpounders"] = "Quint's Olympian Groundpounders",
  ["RamiliesRaiders"] = "Ramilie's Raiders",
  ["Rasalhague"] = "Free Rasalhague Republic",
  ["RaventhirsIronHand"] = "Raventhir's Iron Hand",
  ["RepublicanGuard"] = "Republican Guard",
  ["RimWorldsRepublic"] = "Rim Worlds Republic",
  ["RomanovsCrusaders"] = "Romanov's Crusaders",
  ["RubinskysLightHorse"] = "Rubinsky's Light Horse",
  ["SaiphTriumvirate"] = "Saiph Triumvirate",
  ["SanctuaryAlliance"] = "Sanctuary Alliance",
  ["ScorpionEmpire"] = "Scorpion Empire",
  ["SarnaSupremacy"] = "Sarna Supremacy",
  ["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",
  ["Steiner"] = "Lyran Commonwealth (Steiner)",
  ["StykCommonality"] = "Styk Commonality",
  ["TaurianConcordat"] = "Taurian Concordat",
  ["TaurianGuard"] = "Taurian Guard",
  ["TerracapConfederation"] = "Terracap Confederation",
  ["TheArcadians"] = "The Arcadians",
  ["TheKrushers"] = "The Krushers",
  ["ThermoPolice"] = "Thermo Police",
  ["ToothOfYmir"] = "Tooth of Ymir",
  ["Tortuga"] = "Tortuga Dominions",
  ["TortugaFusiliers"] = "Tortuga Fusiliers",
  ["Valkyrate"] = "Greater Valkyrate",
  ["VanguardLegion"] = "Vanguard Legion",
  ["VLegioRipariensis"] = "V Legio Ripariensis",
  ["WarriorHouseImarra"] = "Warrior House Imarra",
  ["WinfieldsRegiment"] = "Winfield's Regiment",
  ["WoBProtectorateMilitia"] = "WoB Protectorate Militia",
  ["Wolfs_Dragoons"] = "Wolf's Dragoons",
  ["WordOfBlake"] = "Word of Blake"
}

-- Translates SPAM sub-faction IDs to their parent faciton IDs. Translates all Mercenary companies to "Mercenaries"
p.spamFactionsToParents = {
  ["Cameron"] = "Cameron",
  ["StarGuardCorps"] = "Cameron",
  ["ICorps"] = "Cameron",
  ["IVCorps"] = "Cameron",
  ["ClanWolf"] = "ClanWolf",
  ["CWEpsilonGalaxy"] = "ClanWolf",
  ["ClanNovaCat"] = "ClanNovaCat",
  ["CNCOmicronGalaxy"] = "ClanNovaCat",
  ["ClanJadeFalcon"] = "ClanJadeFalcon",
  ["CJFIotaGalaxy"] = "ClanJadeFalcon",
  ["ClanGhostBear"] = "ClanGhostBear",
  ["CGBThetaGalaxy"] = "ClanGhostBear",
  ["ClanGoliathScorpion"] = "ClanGoliathScorpion",
  ["CGSOmegaGalaxy"] = "ClanGoliathScorpion",
  ["ClanFireMandrill"] = "ClanFireMandrill",
  ["KindraaSainze"] = "ClanFireMandrill",
  ["KindraaFaradayTanaga"] = "ClanFireMandrill",
  ["KindraaMickKreese"] = "ClanFireMandrill",
  ["ClanSnowRaven"] = "ClanSnowRaven",
  ["CSRDeltaGalaxy"] = "ClanSnowRaven",
  ["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",
  ["RimWorldsRepublic"] = "RimWorldsRepublic",
  ["1stHeliusLegionnaires"] = "RimWorldsRepublic",
  ["8thHeliusFusiliers"] = "RimWorldsRepublic",
  ["RepublicanGuard"] = "RimWorldsRepublic",
  ["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