Aller au contenu

Module:Localisations

De Poképédia

Fonction « pokemon »

[modifier]

Cette fonction sert à générer automatiquement un tableau de localisations pour les Pokémon.

Comment ça fonctionne ?

[modifier]

Dans les pages de lieux, comme Carmin sur Mer ou Route 204, sont définis des tableaux de rencontre, à l'aide du Module:Tableau Pokémon. Ces données, en plus de renseigner les Pokémon disponibles dans le lieu, peuvent ensuite être agrégées automatiquement par un outil externe. Cet outil permet de mettre à jour une base de données de localisations, disponible ici.

Comment modifier un tableau de localisations ?

[modifier]
Loupe Pour plus d'informations sur le sujet, référez-vous à cette page.

S'il y a une erreur ou une information manquante dans un tableau de localisations sur la page d'un Pokémon, c'est que l'erreur est aussi présente dans la page du lieu correspondant. Dans ce cas, il est nécessaire de modifier la page du lieu en question, ce qui mettra à jour les bases de données (et donc les tableaux de localisations) avec les informations corrigées ou ajoutées au prochain passage de l'outil externe qui les remplit. Dans tous les cas, les bases de données évoquées dans la section précédente n'ont pas vocation à être manuellement modifiées. Pour plus d'informations, consulter cette page, ou contacter Matt.(d).

Paramètres

[modifier]
Légende des icônes
Certains paramètres sont accompagnés d'une ou plusieurs icône indiquant leur(s) caractéristique(s) :
 : Ce paramètre est facultatif, et n'a donc pas besoin d'être systématiquement défini.
 : Ce paramètre classe automatiquement l'article dans une catégorie.
 : Ce paramètre influe sur les données sémantiques présentes en pied de page.
  • paramètre non nommé  : permet de forcer le nom du Pokémon à partir duquel former le tableau. Par défaut, le nom est réglé sur celui de la page en cours ({{PAGENAME}}).
  • type  : la couleur de fond du tableau. Par défaut, elle est égale à la couleur du premier type du Pokémon.
  • ids  : permet de spécifier un ou plusieurs identifiants, séparés par un slash entouré d'espaces  / . Les identifiants sont ceux utilisés dans les tableaux pour préciser des formes spécifiques, au sens du Module:Ressources/infosPokemon. Par exemple, pour afficher les localisations de Sancoki, on pourra indiquer ids=Sancoki forme(Occident) / Sancoki forme(Orient). Pour savoir les identifiants utilisés dans un jeu, utiliser la fonction pokeliste.
  • génération  : permet de définir une génération pour les jeux indiqués. Par défaut, la génération est 8. Sur les pages du type "XXX/Génération Y", la génération par défaut est Y. Indiquer génération=toutes permet d'afficher toutes les générations dans un seul tableau, même si cette option n'a pas vocation à figurer dans des articles.

Exemples d'utilisation

[modifier]

Exemple général

[modifier]
{{#invoke:Localisations|pokemon}}

sur la page « Étourmi/Génération 4 » donne :

VersionsLocalisationsDétails
Diamant et PerleRoute 201, Route 202, Route 203, Route 204, Route 209, Route 212, Grand Marais, Lac Vérité
PlatineRoute 201, Route 202, Route 203, Route 204, Lac Vérité
Or HeartGold et Argent SoulSilverArgenta
Ce tableau est généré automatiquement. Pour que son contenu soit modifié, il faut modifier les pages de lieux. Informations détaillées sur cette page.
LieuNiveauTaux
Pokémon Diamant et Perle
MatinJourNuit
Route 201 • Hautes herbes2–350 %50 %40 %
Route 201 • En insérant Vert Feuille24 %
Route 201 • En insérant Rubis24 %
Route 201 • En insérant Saphir24 %
Route 201 • En insérant Émeraude24 %
Route 202 • Hautes herbes2–430 %40 %30 %
Route 203 • Hautes herbes4–635 %45 %35 %
Route 204 (zone sud) • Hautes herbes425 %35 %25 %
Route 204 (zone nord) • Hautes herbes625 %35 %25 %
Route 209 • Hautes herbes1620 %
Route 212 (partie nord) • Hautes herbes1620 %
Grand Marais (zone 5) • Hautes herbes2210 %10 %
Grand Marais (zone 6) • Hautes herbes2210 %10 %
Grand Marais (zones 1 et 2) • Hautes herbes2610 %10 %
Grand Marais (zones 3 et 4) • Hautes herbes2410 %10 %
Lac Vérité • Hautes herbes2–450 %50 %40 %
LieuNiveauTaux
Pokémon Platine
MatinJourNuit
Route 201 • Hautes herbes2–350 %50 %40 %
Route 202 • Hautes herbes2
4
20 %20 %10 %
Route 203 • Hautes herbes4
6–7
25 %
Route 203 • Hautes herbes510 %10 %
Route 204 (zone sud) • Hautes herbes4–625 %
Route 204 (zone nord) • Hautes herbes9–1125 %
Lac Vérité • Hautes herbes2–450 %
LieuNiveauTaux
Pokémon Or HeartGold et Argent SoulSilver
Argenta • Coup d'Boule (arbres isolés près de la Route 2)VariableVariable

Exemple avec des identifiants

[modifier]

Pour afficher toutes les formes de Vivaldaim dans un même tableau :

{{#invoke:Localisations|pokemon|ids=Vivaldaim / Vivaldaim forme(Printemps) / Vivaldaim forme(Été) / Vivaldaim forme(Automne) / Vivaldaim forme(Hiver)}}

sur la page « Vivadaim/Génération 5 » donne :

VersionsLocalisationsDétails
Noir et BlancRoute 6, Route 7, Tour Dragospire
Noir 2 et Blanc 2Route 6, Route 7
Ce tableau est généré automatiquement. Pour que son contenu soit modifié, il faut modifier les pages de lieux. Informations détaillées sur cette page.
FormeLieuNiveauTaux
Pokémon Noir et Blanc
PrintempsÉtéAutomneHiver
Vivaldaim Forme Printemps
Forme Printemps
Route 6 • Hautes herbes22–2435 %
Vivaldaim Forme Printemps
Forme Printemps
Route 6 • Herbes sombres26–2835 %
Vivaldaim Forme Été
Forme Été
Route 6 • Hautes herbes22–2435 %
Vivaldaim Forme Été
Forme Été
Route 6 • Herbes sombres26–2835 %
Vivaldaim Forme Automne
Forme Automne
Route 6 • Hautes herbes22–2435 %
Vivaldaim Forme Automne
Forme Automne
Route 6 • Herbes sombres26–2835 %
Vivaldaim Forme Hiver
Forme Hiver
Route 6 • Hautes herbes22–2435 %
Vivaldaim Forme Hiver
Forme Hiver
Route 6 • Herbes sombres26–2835 %
Vivaldaim Forme Été
Forme Été
Route 7 • Longues herbes2620 %
Vivaldaim Forme Été
Forme Été
Route 7 • Longues herbes sombres3020 %
Vivaldaim Forme Printemps
Forme Printemps
Route 7 • Longues herbes2620 %
Vivaldaim Forme Printemps
Forme Printemps
Route 7 • Longues herbes sombres3020 %
Vivaldaim Forme Hiver
Forme Hiver
Route 7 • Longues herbes2620 %
Vivaldaim Forme Hiver
Forme Hiver
Route 7 • Longues herbes sombres3020 %
Vivaldaim Forme Automne
Forme Automne
Route 7 • Longues herbes2620 %
Vivaldaim Forme Automne
Forme Automne
Route 7 • Longues herbes sombres3020 %
Vivaldaim Forme Hiver
Forme Hiver
Tour Dragospire (entrée) • Hautes herbes30–3230 %
Vivaldaim Forme Automne
Forme Automne
Tour Dragospire (entrée) • Hautes herbes31–3230 %
Vivaldaim Forme Printemps
Forme Printemps
Tour Dragospire (entrée) • Hautes herbes31–3230 %
Vivaldaim Forme Été
Forme Été
Tour Dragospire (entrée) • Hautes herbes31–3230 %
Vivaldaim Forme Printemps
Forme Printemps
Tour Dragospire (extérieur) • Hautes herbes30–3230 %
Vivaldaim Forme Hiver
Forme Hiver
Tour Dragospire (extérieur) • Hautes herbes30–3230 %
Vivaldaim Forme Automne
Forme Automne
Tour Dragospire (extérieur) • Hautes herbes30–3230 %
Vivaldaim Forme Été
Forme Été
Tour Dragospire (extérieur) • Hautes herbes30–3230 %
FormeLieuNiveauTaux
Pokémon Noir 2 et Blanc 2
PrintempsÉtéAutomneHiver
Vivaldaim Forme Hiver
Forme Hiver
Route 6 • Hautes herbes23–2530 %
Vivaldaim Forme Hiver
Forme Hiver
Route 6 • Herbes sombres26–2830 %
Vivaldaim Forme Automne
Forme Automne
Route 6 • Hautes herbes23–2530 %
Vivaldaim Forme Automne
Forme Automne
Route 6 • Herbes sombres26–2830 %
Vivaldaim Forme Été
Forme Été
Route 6 • Hautes herbes23–2530 %
Vivaldaim Forme Été
Forme Été
Route 6 • Herbes sombres26–2830 %
Vivaldaim Forme Printemps
Forme Printemps
Route 6 • Hautes herbes23–2530 %
Vivaldaim Forme Printemps
Forme Printemps
Route 6 • Herbes sombres26–2830 %
VivaldaimRoute 6 • Donné30Unique
Vivaldaim Forme Été
Forme Été
Route 7 • Longues herbes3020 %
Vivaldaim Forme Été
Forme Été
Route 7 • Longues herbes sombres3320 %
Vivaldaim Forme Printemps
Forme Printemps
Route 7 • Longues herbes3020 %
Vivaldaim Forme Printemps
Forme Printemps
Route 7 • Longues herbes sombres3320 %
Vivaldaim Forme Automne
Forme Automne
Route 7 • Longues herbes3020 %
Vivaldaim Forme Automne
Forme Automne
Route 7 • Longues herbes sombres3320 %
Vivaldaim Forme Hiver
Forme Hiver
Route 7 • Longues herbes3020 %
Vivaldaim Forme Hiver
Forme Hiver
Route 7 • Longues herbes sombres3320 %

Utiliser la fonction pokeliste pour savoir quels identifiants utiliser.

Fonction « pokeliste »

[modifier]

Cette fonction renvoie un tableau triable, qui sert à donner un point de vue global des Pokémon trouvables directement dans un certain jeu. Elle n'a pas vocation à être utilisée directement dans les articles, mais plutôt à se rendre compte des identifiants utilisés, au sens du Module:Ressources/infosPokemon.

Paramètres

[modifier]
  • jeu : l'abréviation du jeu dont on souhaite voir la liste des Pokémon trouvables.

Exemple d'utilisation

[modifier]
{{#invoke:Localisations|pokeliste|jeu=J}}

donne :

infosPokemonPokémonLieux
0142 PtéraLaboratoire de Cramois'Île
0037 GoupixCasino de Céladopole
0120 StariChenal 20, Bourg Palette, Îles Écume, Chenal 19, Carmin sur Mer, Chenal 21, Cramois'Île
0075 GravalanchCaverne Azurée, Route Victoire
0080 FlagadossÎles Écume, Route 13, Route 12
0040 GrodoudouCasino de Céladopole
0118 PoissirèneRoute 11, Parc Safari, Chenal 20, Caverne Azurée, Route 23, Route 22, Parc Safari, Route 25, Bourg Palette, Arène d'Azuria, Îles Écume, Jadielle, Parc Safari, Chenal 19, Carmin sur Mer, Route 18, Chenal 21, Route 10, Route 6, Route 24, Azuria, Cramois'Île, Route 17, Route 13, Route 12, Parc Safari, Céladopole, Parmanie
0113 LeveinardParc Safari, Caverne Azurée, Parc Safari
0044 OrtideCaverne Azurée, Route 14, Route 15, Route 13, Route 12
0063 AbraRoute 7, Route 5, Casino de Céladopole, Route 6, Route 8
0043 MystherbeRoute 25, Route 14, Route 24, Route 15, Route 13, Route 12
0128 TaurosParc Safari, Parc Safari
0056 FérosingeRoute 23, Route 3, Route 22, Route 4
0088 TadmorvManoir Pokémon, Centrale abandonnée
0137 PorygonCasino de Céladopole
0133 ÉvoliRésidence Céladon
0123 InsécateurParc Safari, Parc Safari, Casino de Céladopole
0112 RhinoférosCaverne Azurée, Laboratoire de Cramois'Île
0035 MéloféeMont Sélénite
0020 RattatacRoute 11, Route 16, Manoir Pokémon, Route 9, Route 18, Chenal 21, Route 10
0032 Nidoran♂Parc Safari, Route 22, Parc Safari, Route 2, Parc Safari, Route 9, Route 10, Parc Safari
0111 RhinocorneCaverne Azurée, Parc Safari, Parc Safari
0130 LéviatorParmanie
0061 TêtarteRoute 23, Route 22
0104 OsselaitParc Safari, Parc Safari, Tour Pokémon, Parc Safari
0114 SaquedeneuParc Safari, Parc Safari
0100 VoltorbeCentrale abandonnée
0079 RamolossÎles Écume, Route 13, Route 12
0046 ParasParc Safari, Mont Sélénite
0101 ÉlectrodeCentrale abandonnée
0066 MachocGrotte Sombre, Route 10
0122 M. MimeRoute 2
0145 ÉlecthorCentrale abandonnée
0116 HypotrempeRoute 11, Carmin sur Mer, Route 10, Route 13, Route 12
0117 HypocéanRoute 13, Route 12
0083 CanartichoRoute 13, Route 12
0042 NosferaltoCaverne Azurée, Îles Écume, Route Victoire
0147 MinidracoParc Safari, Parc Safari, Parc Safari, Parc Safari
0105 OssatueurParc Safari, Tour Pokémon, Parc Safari
0085 DodrioRoute 17
0064 KadabraRoute 8
0093 SpectrumTour Pokémon
0047 ParasectCaverne Azurée, Parc Safari, Route 18
0074 RacaillouGrotte Sombre, Route Victoire, Mont Sélénite
0057 ColossingeRoute 23
0143 RonflexRoute 16, Route 12
0030 NidorinaParc Safari, Route 23, Parc Safari, Route 9
0119 PoissoroyCaverne Azurée, Route 24, Azuria
0069 ChétiflorRoute 25, Route 14, Route 24, Route 15, Route 13, Route 12
0102 NoeunoeufParc Safari, Parc Safari, Parc Safari, Parc Safari
0144 ArtikodinÎles Écume
0098 KrabbyRoute 25, Îles Écume, Route 10
0028 SablaireauCaverne Azurée
0086 OtariaÎles Écume
0025 PikachuLaboratoire Pokémon du Professeur Chen
0131 LokhlassSylphe SARL
0050 TaupiqueurGrotte Taupiqueur
0151 MewRoute 24
0055 AkwakwakRoute 6
0054 PsykokwakRoute 6
0010 ChenipanForêt de Jade
0081 MagnétiRoute 10, Centrale abandonnée
0073 TentacruelChenal 20, Chenal 19, Chenal 21
0108 ExcelangueCaverne Azurée
0089 GrotadmorvLaboratoire de Cramois'Île, Manoir Pokémon, Centrale abandonnée
0146 SulfuraRoute Victoire
0048 MimitossRoute 25, Route 14, Route 24, Route 15
0021 PiafabecRoute 16, Route 3, Route 22, Route 4, Route 9, Route 18
0106 KickleeDojo de Safrania
0049 AéromiteCaverne Azurée, Route 14, Route 15
0140 KabutoLaboratoire de Cramois'Île
0090 KokiyasCarmin sur Mer, Route 18, Route 17
0027 SabeletteRoute 3, Route 4, Mont Sélénite
0007 CarapuceCarmin sur Mer
0041 NosferaptiGrotte Sombre, Îles Écume, Route Victoire, Mont Sélénite
0138 AmonitaLaboratoire de Cramois'Île
0051 TriopikeurRoute 11, Grotte Taupiqueur
0060 PtitardRoute 11, Parc Safari, Chenal 20, Caverne Azurée, Route 23, Route 22, Parc Safari, Route 25, Bourg Palette, Arène d'Azuria, Îles Écume, Jadielle, Parc Safari, Chenal 19, Carmin sur Mer, Route 18, Chenal 21, Route 10, Route 6, Route 24, Azuria, Cramois'Île, Route 17, Route 13, Route 12, Parc Safari, Céladopole, Parmanie
0058 CaninosManoir Pokémon
0099 KrabbossRoute 25, Îles Écume, Route 10
0148 DracoParc Safari
0132 MétamorphCaverne Azurée, Manoir Pokémon
0004 SalamècheRoute 24
0092 FantominusTour Pokémon
0001 BulbizarreAzuria
0077 PonytaRoute 17
0096 SoporifikRoute 11
0115 KangourexParc Safari
0129 MagicarpeRoute 11, Parc Safari, Chenal 20, Caverne Azurée, Route 23, Route 22, Parc Safari, Route 25, Bourg Palette, Arène d'Azuria, Îles Écume, Jadielle, Parc Safari, Chenal 19, Carmin sur Mer, Route 4, Route 18, Chenal 21, Route 10, Route 6, Route 24, Azuria, Cramois'Île, Route 17, Route 13, Route 12, Parc Safari, Céladopole, Parmanie
0150 MewtwoCaverne Azurée
0087 LamantineLaboratoire de Cramois'Île, Îles Écume
0072 TentacoolRoute 11, Chenal 20, Bourg Palette, Chenal 19, Carmin sur Mer, Route 18, Chenal 21, Cramois'Île, Route 17, Route 13
0082 MagnétonCentrale abandonnée
0084 DoduoRoute 16, Route 18, Route 17
0039 RondoudouRoute 7, Route 5, Route 6, Route 8
0067 MachopeurSouterrain, Route Victoire
0022 RapasdepicRoute 23, Route 16, Route 9, Route 18, Route 17
0029 Nidoran♀Parc Safari, Route 22, Parc Safari, Route 2, Parc Safari, Route 9, Route 10, Parc Safari
0019 RattataRoute 7, Route 11, Route 16, Route 3, Route 22, Route 5, Route 2, Manoir Pokémon, Route 4, Route 9, Route 1, Route 18, Chenal 21, Route 10, Route 6, Route 8
0017 RoucoupsRoute 7, Route 11, Forêt de Jade, Route 25, Route 5, Route 14, Chenal 21, Route 6, Route 24, Route 8, Route 15, Route 13, Route 12
0033 NidorinoRoute 23, Parc Safari, Route 9, Parc Safari
0016 RoucoolRoute 7, Route 11, Forêt de Jade, Route 25, Route 5, Route 2, Route 1, Chenal 21, Route 6, Route 24, Route 8, Route 13, Route 12
0011 ChrysacierForêt de Jade
0095 OnixGrotte Sombre, Route Victoire
0127 ScarabruteParc Safari, Casino de Céladopole, Parc Safari
0107 TygnonDojo de Safrania
0070 BoustiflorCaverne Azurée, Route 14, Route 15, Route 13, Route 12

local p = {}
local ressources = {
	["infosPokemon"] = require("Module:Ressources/infosPokemon")
}
local game_to_game_long = require("Module:Data/NomsJeux")
local subareas = require("Module:Localisations/sousZones")

function p.pokemon(frame)
	local maths = require("Module:Maths")

	local result = {}
	local result_header = {}
	local full_table = {}
	
	local pokemon = frame.args[1]
	local generation
	local is_mystery_dungeon = false
	if pokemon == nil or pokemon == ""
	then pokemon = frame:getParent():getTitle()
		
		if pokemon:match("Pokémon Donjon Mystère")
		then is_mystery_dungeon = true
		end
		
		local title_split = mw.text.split(pokemon, "/")
		pokemon = title_split[1]	-- remove the subpages
		
		if title_split[2]
		then generation = mw.ustring.gsub(title_split[2], "Génération ", "")
		end
	end
	
	local pokemon_ids = frame.args["ids"]
	local multiple_ids = false
	if pokemon_ids
	then pokemon_ids = mw.text.split(pokemon_ids, " / ")
		if pokemon_ids[2] then multiple_ids = true end
	else pokemon_ids = {pokemon}
	end
	
	local special_replacement_ids = {
		["Kyurem Blanc"] = {"Kyurem", "Blanc"},
		["Kyurem Noir"] = {"Kyurem", "Noir"},
		["Necrozma Crinière du Couchant"] = {"Necrozma", "Crinière du Couchant"},
		["Necrozma Ailes de l'Aurore"] = {"Necrozma", "Ailes de l'Aurore"},
		["Ultra%-Necrozma"] = {"Necrozma", "Ultra"},
		["Sylveroy, le Cavalier du Froid"] = {"Sylveroy", "Cavalier du Froid"},
		["Sylveroy, le Cavalier d'Effroi"] = {"Sylveroy", "Cavalier d'Effroi"}
	}
	
	local replacement_ids = {
		[" d'Alola"] = "Alola",
		[" de Galar"] = "Galar",
		[" de Hisui"] = "Hisui",
		[" de Paldea"] = "Paldea",
		["Méga%-"] = "Méga",
		["Primo%-"] = "Primo",
		[" Gigamax"] = "Gigamax",
		[" Infinimax"] = "Infinimax"
	}
	for i, id in pairs(pokemon_ids) do
		local j = 1
		for replacing, replaced in pairs(replacement_ids) do
			-- Les éléments entre parenthèses, notamment les liens, ne doivent pas être remplacés ;
			-- on ne remplace que ce qui est avant l'éventuelle première parenthèse
			if mw.ustring.find(pokemon_ids[i], replacing) and not(mw.ustring.find(pokemon_ids[i], "%(") and mw.ustring.find(pokemon_ids[i], replacing) > mw.ustring.find(pokemon_ids[i], "%("))
			then pokemon_ids[i] = mw.ustring.gsub(pokemon_ids[i], replacing, "") .. " forme(" .. replaced .. ")"
			end
		end
	end
	
	local pokemon_type = frame.args["type"]
	if not pokemon_type
	then local data_types = require("Module:Data/TypesPokémon")
		local skip = false
		
		-- special replacements
		for replacing, replaced in pairs(special_replacement_ids) do
			if pokemon == replacing
			then local pokemon_types = data_types[replaced[1]]
				local form = replaced[2]
				
				if pokemon_types
				then local pokemon_types_form = pokemon_types[form]
					if pokemon_types_form
					then pokemon_type = pokemon_types_form[1]
					else pokemon_type = pokemon_types[1][1]
					end
					skip = true
				else pokemon_type = ""
				end
				break
			end
		end
		
		-- regular replacements
		if not skip
		then
			for replacing, replaced in pairs(replacement_ids) do
				if mw.ustring.find(pokemon, replacing)
				then local pokemon_without_form = mw.ustring.gsub(pokemon, replacing, "")
					local form = replaced
					local pokemon_types = data_types[pokemon_without_form]
					if pokemon_types
					then local pokemon_types_form = pokemon_types[form]
						if pokemon_types_form
						then pokemon_type = pokemon_types_form[1]
						else pokemon_type = pokemon_types[1][1]
						end
					else pokemon_type = ""
					end
					break
				end
			end
		end
		if not pokemon_type
		then local pokemon_types = data_types[pokemon]
			if pokemon_types
			then pokemon_type = pokemon_types[1][1]
			else pokemon_type = ""
			end
		end
	end
	pokemon_type = mw.ustring.lower(pokemon_type)
	
	
	local generation_to_games = {
		{"RB", "J"},
		{"OA", "C"},
		{"RS", "RFVF", "E"},
		{"DP", "Pt", "HGSS"},
		{"NB", "N2B2"},
		{"XY", "ROSA"},
		{"SL", "USUL", "LGPE"},
		{"EB", "DEPS", "LPA"},
		{"EV", "LPZA"},
		{"VV"}
	}
	
	local games = {}
	
	if frame.args["pdm"] then is_mystery_dungeon = true end
	if is_mystery_dungeon
	then games = {"PDMRB", "PDMTO", "PDMC", "PDMPI", "PMDM", "PDMDX"}
	else
		if frame.args["génération"] then generation = frame.args["génération"] end
		if generation == "toutes"
		then
			local n = 1
			local g = 1
			while generation_to_games[g] do
				local i = 1
				local gen_games = generation_to_games[g]
				
				while gen_games[i] do
					games[n] = gen_games[i]
					n = n + 1
					i = i + 1
				end
				g = g + 1
			end
		else
			if not tonumber(generation) then generation = 8 else generation = tonumber(generation) end
			
			games = generation_to_games[generation]
			if games == nil
			then return "<i>Erreur : numéro de génération invalide.</i>"
			end
		end
	end
	
	if frame.args["jeux"] then games = mw.text.split(frame.args["jeux"], ", ") end
	
	
	
	local borders = {}
	local game_displays = {}
	local game_minisprites = {}
	local game_links = {}
	local locdatas = {}
	for _, game in pairs(games) do
		borders[game] = frame:expandTemplate{title='Bordure', args={game}}
		game_displays[game] = game_to_game_long[game]
		
		if is_mystery_dungeon
		then game_displays[game] = mw.ustring.gsub(game_displays[game], "Donjon Mystère : ", "")
		end
	
		local game_minisprite = game
		if game == "RV" or game == "RB" or game == "B-JP" or game == "B-jp" or game == "J" or game == "OA" or game == "C"
		then game_minisprite = "RS"
		elseif game == "Démo-ROSA" then game_minisprite = "ROSA"
		elseif game == "Démo-SL" then game_minisprite = "SL"
		elseif game == "PDMRB" then game_minisprite = "PDMTO"
		end
		game_minisprite = " jeu(" .. game_minisprite .. ")"
		game_minisprites[game] = game_minisprite
		
		local game_link = game_to_game_long[game]
		if game ~= "LPA" and game ~= "LPZA"
		then game_link = "Pokémon " .. game_to_game_long[game]
		end
		game_links[game] = game_link
		table.insert(locdatas, require("Module:Localisations/Données/" .. game_link))
	end
	
	
	local places = {}
	local game_id = 1
	local first_game = nil
	for _, game in pairs(games) do
		if game_id == 1 then first_game = game end
		
		local game_has_place = false
		for place_name, pokemon_list in pairs(locdatas[game_id]) do
			for _, pokemon_id in pairs(pokemon_ids) do
				local place_info = pokemon_list[pokemon_id]
				if place_info
				then table.insert(places, {["id"] = pokemon_id, ["game_id"] = game_id, ["game"] = game, ["name"] = place_name, ["contents"] = place_info})
					game_has_place = true
				end
			end
		end
		
		if not game_has_place
		then table.insert(places, {["game_id"] = game_id, ["game"] = game, ["name"] = "", ["contents"] = nil})
		end
		
		game_id = game_id + 1
	end
	
	local remove_accents = require("Module:Ressources/enleverAccents")
	local route_prefixes = {"Route ", "Chenal ", "Antre ", "Antre événementiel ", "Zone sauvage n° "}
	table.sort(places, function(x,y)
		if x.game_id ~= y.game_id
		then return x.game_id < y.game_id
		else local x_placename = mw.text.split(mw.text.split(x.name, "@")[1], "|")[1]
			local y_placename = mw.text.split(mw.text.split(y.name, "@")[1], "|")[1]
			local x_placeid = subareas.get_subarea_id_from_place(x_placename)
			local y_placeid = subareas.get_subarea_id_from_place(y_placename)
			if x_placeid ~= y_placeid
			then return x_placeid < y_placeid
			else 
				local x_routenumber = mw.ustring.gsub(x_placename, "%(.-%).-", "")
				local y_routenumber = mw.ustring.gsub(y_placename, "%(.-%).-", "")
				local route_prefix_ind = 1
				while route_prefixes[route_prefix_ind] do
					x_routenumber = mw.ustring.gsub(x_routenumber, route_prefixes[route_prefix_ind], "")
					y_routenumber = mw.ustring.gsub(y_routenumber, route_prefixes[route_prefix_ind], "")
					route_prefix_ind = route_prefix_ind + 1
				end
					
				x_routenumber = tonumber(tostring(x_routenumber))
				y_routenumber = tonumber(tostring(y_routenumber))
		
				if x_routenumber
				then if y_routenumber
					then return x_routenumber < y_routenumber
					else return true
					end
				else if y_routenumber
					then return false
					else return remove_accents(x.name) < remove_accents(y.name)
					end
				end
			end
		end
	end)
	
	-- subrate precomputation
	local subrates_dict = require("Module:Tableau Pokémon/sousTaux")
	local subrates = subrates_dict["sous-taux"]
	local times = subrates_dict["horaires"]
	local weathers = subrates_dict["météos"]

	local subarea_subrates_list = {}
	local subarea_times_list = {}
	local subarea_weathers_list = {}
	
	local colspan_rates = {}
	local reduced_colspan_rates = {} -- in case total colspan exceeds the 1000 limit
	local colspan_rates_decomposed = {}
	local rates_width = {}
	local base_rate_width = 45
	
	local colspan_times = {}
	local times_width = {}
	
	local colspan_weathers = {}
	local weathers_width = {}
	
	for _, game in pairs(games) do
		subarea_subrates_list[game] = {}
		subarea_times_list[game] = {}
		subarea_weathers_list[game] = {}
		
		colspan_rates[game] = 1
		reduced_colspan_rates[game] = 1
		colspan_rates_decomposed[game] = {}
		rates_width[game] = base_rate_width
		
		colspan_times[game] = 1
		times_width[game] = base_rate_width
		colspan_weathers[game] = 1
		weathers_width[game] = base_rate_width
	end
	
	local i = 1
	local last_place = nil
	local last_subarea = nil
	local last_game_id = nil
	local last_game = nil
	local current_subarea_has_subrates = false
	
	function add_to_subrates(game, subarea, subarea_has_subrates)
		if subarea == nil then subarea = "" end
		
		if subarea_has_subrates
		then local subrates_subarea = subrates.raccourcis[mw.ustring.lower(subarea)]

			if subrates_subarea == nil
			then subrates_subarea = subrates[game]
			end
			
			local count = 1
			if subrates_subarea ~= nil
			then 
				count = #subrates_subarea[1]
				local new_colspan_rates = maths.lcm(colspan_rates[game], count)
				colspan_rates[game] = new_colspan_rates
				table.insert(colspan_rates_decomposed[game], count)
				
				reduced_colspan_rates[game] = math.floor(colspan_rates[game] / (math.floor((new_colspan_rates - 1) / 1000) + 1))
				
				local minwidth = subrates_subarea.minwidth
				if not minwidth then minwidth = base_rate_width end
				
				rates_width[game] = math.max(rates_width[game], minwidth * count)
			end
			subarea_subrates_list[game][subarea] = {["subrates"] = subrates_subarea, ["number"] = count}
		else subarea_subrates_list[game][subarea] = {["subrates"] = nil, ["number"] = 0}
		end
		
		local times_subarea = times.raccourcis[mw.ustring.lower(subarea)]
		if times_subarea == nil
		then times_subarea = times[game]
		end
		if times_subarea
		then local count = #times_subarea[1]
			if count > 0
			then
				subarea_times_list[game][subarea] = {["times"] = times_subarea, ["number"] = count}
				local new_colspan_times = maths.lcm(colspan_times[game], count)
				colspan_times[game] = new_colspan_times
			else subarea_times_list[game][subarea] = {["times"] = nil, ["number"] = 0}
			end
		end
		
		local weathers_subarea = weathers.raccourcis[mw.ustring.lower(subarea)]
		if weathers_subarea == nil
		then weathers_subarea = weathers[game]
		end
		if weathers_subarea
		then local count = #weathers_subarea[1]
			if count > 0
			then
				subarea_weathers_list[game][subarea] = {["weathers"] = weathers_subarea, ["number"] = count}
				local new_colspan_weathers = maths.lcm(colspan_weathers[game], count)
				colspan_weathers[game] = new_colspan_weathers
			else subarea_weathers_list[game][subarea] = {["weathers"] = nil, ["number"] = 0}
			end
		end
	end
	
	
	-- actual subrate precomputation
	local current_game
	local current_subarea
	local has_rates = {}
	local has_locs = {}
	local current_game_has_any_rates = false
	local current_game_has_locs = false
	while places[i] do
		local current_place_id = places[i]["name"]
		local current_place_split = mw.text.split(current_place_id, "@")
		local current_place = current_place_split[1]
		local current_game_id = places[i]["game_id"]
		
		current_game = places[i]["game"]
		current_subarea = subareas.get_subarea_from_place(mw.text.split(current_place, "|")[1])
		if last_place == nil or subareas.get_subarea_id_from_place(last_place) ~= subareas.get_subarea_id_from_place(current_place) or last_game_id ~= current_game_id
		then if last_place ~= nil
			then add_to_subrates(last_game, last_subarea, current_subarea_has_subrates)
				if has_rates[last_game] == nil
				then has_rates[last_game] = current_game_has_any_rates
				else has_rates[last_game] = has_rates[last_game] or current_game_has_any_rates
				end
				current_game_has_any_rates = false
				
				has_locs[last_game] = current_game_has_locs
				current_game_has_locs = false
			end
			current_subarea_has_subrates = false
		end
		last_place = current_place
		last_subarea = current_subarea
		last_game = current_game
		last_game_id = current_game_id
		
		local place_info = places[i]["contents"]
		
		if place_info
		then local j = 1
			while not current_subarea_has_subrates and place_info[j] do
				-- si pas d'argument taux trouvé, on cherche s'il y a des sous-taux ou s'il y en a juste pas du tout
				if place_info[j]["taux"]
				then current_game_has_any_rates = true
				else local found_subrate = false
					for key, val in pairs(place_info[j]) do
						if key:find("taux-")
							or key == "1" or key == "2" or key == "3" or key == "4" or key == "5" -- difficultés de raid dynamax
						then found_subrate = true
						end
					end
					current_subarea_has_subrates = found_subrate
					if found_subrate then current_game_has_any_rates = true end
				end
				
				j = j + 1
			end
			if j > 1 then current_game_has_locs = true end
		end
		i = i + 1
	end
	add_to_subrates(current_game, current_subarea, current_subarea_has_subrates)
	if has_rates[current_game] == nil
	then has_rates[current_game] = current_game_has_any_rates
	else has_rates[current_game] = has_rates[current_game] or current_game_has_any_rates
	end
	has_locs[current_game] = current_game_has_locs
	
	for game, _ in pairs(has_rates) do
		if not has_rates[game]
		then
			colspan_rates[game] = 0
			reduced_colspan_rates[game] = 0
			for subarea, _ in pairs(subarea_subrates_list[game]) do
				subarea_subrates_list[game][subarea] = {}
			end
			
		end
		
		local game_has_times = false
		local game_has_weathers = false
		for subarea, _ in pairs(subarea_times_list[game]) do
			if subarea_times_list[game][subarea]["number"] ~= 0 then game_has_times = true end
			if subarea_weathers_list[game][subarea]["number"] ~= 0 then game_has_weathers = true end
		end
		
		if not has_locs[game] or not game_has_times then colspan_times[game] = 0 end
		if not has_locs[game] or not game_has_weathers then colspan_weathers[game] = 0 end
	end
	
	-- locations
	local current_game_locations = {}
	local current_game_locations_first_subarea = {}
	local current_game_full_locations = {}
	local current_subarea_full_locations = {}
	local seen_games_place = nil
	local number_subareas = 0
	local last_place = nil
	local current_game = nil
	local current_game_id = nil

	local last_game_id = nil
	local places_end = false
	local is_there_full_table = false
	local is_there_full_table_game = false
	local i = 1
	while true do
		last_game = current_game
		last_game_id = current_game_id
			
		if not places[i]
		then places_end = true
		else 
			current_game = places[i]["game"]
			current_game_id = places[i]["game_id"]
		end
		
		if places_end or last_game_id ~= current_game_id
		then 
			local full_table_header = {}
			
			if last_game_id ~= nil then
				-- game specifier in the simplified table, at the end of last area locations
				if last_game ~= first_game
				then table.insert(result, '</td></tr>')
				end
				table.insert(result, '<tr><td rowspan="' .. number_subareas .. '" class="' .. borders[last_game] .. '">[[' .. game_links[last_game] .. '|' .. game_displays[last_game] .. ']]</td>')
				
				-- if all encounters in the place are restricted to a single game of the two
				if seen_games_place and seen_games_place ~= "all" then table.insert(current_game_locations, frame:expandTemplate{title='Sup', args={seen_games_place}}) end
				seen_games_place = nil
				table.insert(current_game_locations, '</span></td>')
			
				if is_there_full_table_game
				then local form_header = ""
					if multiple_ids then form_header = "<th>Forme</th>" end
					table.insert(full_table_header, '<table class="tableaustandard centre ' .. pokemon_type .. ' tableau-overflow"><tbody><tr>' .. form_header .. '<th style="min-width: 300px; width:450px">Lieu</th>')
					
					if is_mystery_dungeon then table.insert(full_table_header, '<th width="50px">Étage</th>') end
					
					table.insert(full_table_header, '<th width="50px">Niveau</th>')
					
					if reduced_colspan_rates[last_game] > 0
					then
						local taux_header = "Taux"
						if is_mystery_dungeon
						then table.insert(full_table_header, '<th>Taux de<br>recrutement</th>')
							taux_header = "Taux<br>d'apparition"
						end
						table.insert(full_table_header, '<th colspan="' .. reduced_colspan_rates[last_game] .. '" >' .. taux_header .. '</th>')
					end
					
					if colspan_times[last_game] > 0
					then
						local times_header = "Horaire"
						table.insert(full_table_header, '<th colspan="' .. colspan_times[last_game] .. '" >' .. times_header .. '</th>')
					end
					
					if colspan_weathers[last_game] > 0
					then
						local weathers_header = "Météo"
						table.insert(full_table_header, '<th colspan="' .. colspan_weathers[last_game] .. '" >' .. weathers_header .. '</th>')
					end
					
					table.insert(full_table_header, '</tr>')
					
					
					local left_cell_colspan = 2
					if multiple_ids then left_cell_colspan = 3 end
					if is_mystery_dungeon then left_cell_colspan = left_cell_colspan + 2 end
						
					if colspan_rates[last_game] > 1
					then
						table.insert(full_table_header, '<tr><td style="padding:0px;border:0px" colspan="' .. left_cell_colspan .. '"></td>')
						local current_colspan = 0
						local factorize = reduced_colspan_rates[last_game] * 2 > rates_width[last_game]
						local is_multiple
						
						for c = 1, reduced_colspan_rates[last_game] do
							current_colspan = current_colspan + 1
							is_multiple = false
							
							local factor = 1
							if factorize
							then for _, fac in pairs(colspan_rates_decomposed[last_game]) do
									if fac ~= 1 and c % (reduced_colspan_rates[last_game] / fac) == 0
									then factor = fac
										is_multiple = true
										break
									end
								end
							end
							
							if not factorize or is_multiple
							then local colspan_text = ""
								if current_colspan ~= 1 then colspan_text = ' colspan="' .. current_colspan .. '"' end
								table.insert(full_table_header, '<td style="padding:0px;border:0px"' .. colspan_text .. '></td>')
								current_colspan = 0
							end
						end
						table.insert(full_table_header, '</tr>')
					end
					
					table.insert(full_table_header, '<tr><td colspan="' .. left_cell_colspan + reduced_colspan_rates[last_game] + colspan_times[last_game] + colspan_weathers[last_game]
						.. '" class="' .. borders[last_game] .. '"><b>' .. frame:expandTemplate{title='Jeu', args={last_game}} .. '</b></td></tr>')
				end
				
				table.insert(current_game_full_locations, table.concat(current_subarea_full_locations, ""))
				table.insert(full_table_header, table.concat(current_game_full_locations, ""))
				table.insert(full_table, table.concat(full_table_header, ""))
				table.insert(full_table, '</tbody></table></div>')
				
			end
			
			if is_there_full_table_game
			then if number_subareas == 1
				then current_game_locations_first_subarea = current_game_locations
					current_game_locations = {}
				end
				table.insert(current_game_locations_first_subarea,
					'<td rowspan="' .. number_subareas .. '"><button type="button" name="tauxdétaillés-' .. last_game .. '" value="afficher" title="[–]">[+]</button></td></th>')
				
			else table.insert(current_game_locations, "</th>")
			end
			
			table.insert(current_game_locations_first_subarea, table.concat(current_game_locations, ""))
			table.insert(result, table.concat(current_game_locations_first_subarea, ""))
			
			current_game_locations = {}
			current_game_locations_first_subarea = {}
			current_game_full_locations = {}
			current_subarea_full_locations = {}
			
			table.insert(current_game_locations, '<td>')
			
			number_subareas = 0
			
			if places_end
			then 
				break
			else
				-- row to specify the game, at the end of last area full locations; only if the game has places
				is_there_full_table_game = (places[i]["name"] ~= "")
				if is_there_full_table_game
				then is_there_full_table = true
					table.insert(full_table, '\n<div class="center tauxdétaillés-' .. current_game .. '">')
				end
			end
			
			last_place = nil
		end
		
		local place_name = places[i]["name"]
		local place_name_split = mw.text.split(place_name, "@")
		local place_link_split = mw.text.split(place_name_split[1], "|")
		local place_link = place_link_split[1]
		
		local place_link_display
		if place_link_split[2]
		then place_link_display = '[[' .. place_link_split[1] .. '|' .. place_link_split[2] .. ']]'
		else local place_link_filtered = mw.ustring.gsub(place_link, " %(.-%)", "")
			if place_link_filtered == place_link
			then place_link_display = '[[' .. place_link .. ']]'
			else place_link_display = '[[' .. place_link .. '|' .. place_link_filtered .. ']]'
			end
		end
		
		local place_suffix = ""
		
		if place_name_split[2]
		then place_suffix = " (" .. place_name_split[2] .. ")"
		end
		
		local comma_string = ""
		local subarea = subareas.get_subarea_from_place(mw.text.split(place_link, "|")[1])
		local subarea_text
		if subarea then subarea_text = subarea else subarea_text = "" end
		
		if last_place ~= place_link
		then if last_place ~= nil
			then 
				-- if all encounters in the place are restricted to a single game of the two
				if seen_games_place and seen_games_place ~= "all" then table.insert(current_game_locations, frame:expandTemplate{title='Sup', args={seen_games_place}}) end
				seen_games_place = nil
				table.insert(current_game_locations, '</span>')
			end
			
			if last_place == nil or subareas.get_subarea_id_from_place(last_place) ~= subareas.get_subarea_id_from_place(place_link)
			then 
				if last_place ~= nil
				then table.insert(current_game_locations, '</td>')
					if number_subareas == 1
					then current_game_locations_first_subarea = current_game_locations
						current_game_locations = {'</tr><tr><td>'}
					else table.insert(current_game_locations, '</tr><tr><td>')
					end
				end
				table.insert(current_game_full_locations, table.concat(current_subarea_full_locations, ""))
				current_subarea_full_locations = {}
				local subarea_text = subarea
				if not subarea then subarea_text = "" end
				local subrates_list = subarea_subrates_list[current_game][subarea_text]
				local times_list = subarea_times_list[current_game][subarea_text]
				local weathers_list = subarea_weathers_list[current_game][subarea_text]
				
				number_subareas = number_subareas + 1
				
				if subarea or (subrates_list and subrates_list.subrates) or (times_list and times_list.times) or (weathers_list and weathers_list.weathers)
				then
					local colspan_th = 2
					if multiple_ids then colspan_th = 3 end
					
					-- transition header with the name of the subarea
					if reduced_colspan_rates[current_game] == 0 or not (subrates_list and subrates_list.subrates)
					then colspan_th = colspan_th + reduced_colspan_rates[current_game]
						if colspan_times[current_game] == 0 or not (times_list and times_list.times)
						then colspan_th = colspan_th + colspan_times[current_game]
							if colspan_weathers[current_game] == 0 or not (weathers_list and weathers_list.weathers)
							then colspan_th = colspan_th + colspan_weathers[current_game]
							end
						end
					end
					
					if subarea
					then local link_subarea = subareas.get_link(subarea)
						table.insert(current_game_locations, link_subarea .. " : ")
						table.insert(current_subarea_full_locations, "<tr><th colspan='" .. colspan_th .. "'>" .. link_subarea .. "</th>")
					else table.insert(current_subarea_full_locations, '<tr><td style="background:transparent" colspan="' .. colspan_th .. '"></td>')
					end
					
					-- rates
					if reduced_colspan_rates[current_game] > 0 and subrates_list
					then local colspan_local = math.floor(reduced_colspan_rates[current_game] / subrates_list.number)
						local width_local = math.floor(rates_width[current_game] / subrates_list.number)
						
						for s = 1, subrates_list.number do
							if subrates_list.subrates
							then local subrate_s = subrates_list.subrates[1][s]
								table.insert(current_subarea_full_locations, '<td class="' .. subrates_list.subrates[3][s] .. '" width="' .. width_local .. 'px" colspan="' .. colspan_local .. '">')
								if subrates_list.subrates["no_icon"]
								then table.insert(current_subarea_full_locations, subrate_s .. '</td>')
								else table.insert(current_subarea_full_locations, '[[Fichier:Icône ' .. subrate_s .. ' ' .. current_game .. '.png|' .. subrate_s .. '|link=' .. subrates_list.subrates[4][1] .. '|x25px]]</td>')
								end
							end
						end
					end
					
					-- times
					if colspan_times[current_game] > 0
					then if times_list
						then local colspan_local = math.floor(colspan_times[current_game] / times_list.number)
							local width_local = math.floor(times_width[current_game] / times_list.number)
							
							for s = 1, times_list.number do
								if times_list.times
								then local time_s = times_list.times[1][s]
									table.insert(current_subarea_full_locations, '<td class="' .. times_list.times[2][s] .. '" width="' .. width_local .. 'px" colspan="' .. colspan_local .. '">')
									if times_list.times["no_icon"]
									then table.insert(current_subarea_full_locations, time_s .. '</td>')
									else table.insert(current_subarea_full_locations, '[[Fichier:Icône ' .. time_s .. ' ' .. current_game .. '.png|' .. time_s .. '|link=' .. times_list.times[3][1] .. '|x25px]]</td>')
									end
								end
							end
						elseif subarea and reduced_colspan_rates[current_game] > 0 and subrates_list and subrates_list.subrates
						then local colspan_th = colspan_times[current_game]
							if colspan_weathers[current_game] > 0 and not (weathers_list and weathers_list.weathers)
							then colspan_th = colspan_th + colspan_weathers[current_game]
							end
							
							table.insert(current_subarea_full_locations, "<th colspan='" .. colspan_th .. "'></th>")
						end
					end
					
					-- weathers
					if colspan_weathers[current_game] > 0
					then if weathers_list
						then local colspan_local = math.floor(colspan_weathers[current_game] / weathers_list.number)
							local width_local = math.floor(weathers_width[current_game] / weathers_list.number)
							
							for s = 1, weathers_list.number do
								if weathers_list.weathers
								then local weather_s = weathers_list.weathers[1][s]
									table.insert(current_subarea_full_locations, '<td class="' .. weathers_list.weathers[2][s] .. '" width="' .. width_local .. 'px" colspan="' .. colspan_local .. '">')
									if weathers_list.weathers["no_icon"]
									then table.insert(current_subarea_full_locations, weather_s .. '</td>')
									else table.insert(current_subarea_full_locations, '[[Fichier:Icône ' .. weather_s .. ' ' .. current_game .. '.png|' .. weather_s .. '|link=' .. weathers_list.weathers[3][1] .. '|x25px]]</td>')
									end
								end
							end
						elseif subarea and colspan_times[current_game] > 0 and times_list and times_list.times
						then local colspan_th = colspan_weathers[current_game]
							table.insert(current_subarea_full_locations, "<th colspan='" .. colspan_th .. "'></th>")
						end
					end
					
					table.insert(current_subarea_full_locations, '</tr>')
				end
				
			else comma_string = ", "
			end
			last_place = place_link
			
			if places[i]["name"] == ""
			then 
				local unavailable_sentence = "<i>Indisponible</i>"
				if current_game == "VV" then unavailable_sentence = "<i>À venir</i>" end
				
				local unavailable_table = require("Module:Localisations/Données/" .. game_links[current_game] .. "/Indisponibles")
				local custom_unavailable_sentence = false
				for _, pokemon_id in pairs(pokemon_ids) do
					local unavailable_sentence_tmp = unavailable_table[pokemon_id]
					
					if unavailable_sentence_tmp
					then unavailable_sentence = unavailable_sentence_tmp
						custom_unavailable_sentence = true
						break
					end
				end
				
				if not custom_unavailable_sentence
				then local unavailable_sentence_tmp = unavailable_table[pokemon]
					if unavailable_sentence_tmp
					then unavailable_sentence = unavailable_sentence_tmp
					end
				end
				
				-- template expansion
				local template = mw.ustring.gsub(unavailable_sentence, "(.*){{(.-)|(.-)}}(.*)", "%2")
				if template and template ~= unavailable_sentence
				then local arg = mw.ustring.gsub(unavailable_sentence, "(.*){{(.-)|(.-)}}(.*)", "%3")
					local template_expanded = frame:expandTemplate{title=template, args={arg}}
					unavailable_sentence = mw.ustring.gsub(unavailable_sentence, "(.*){{(.-)|(.-)}}(.*)", "%1" .. template_expanded .. "%4")
				end
					
				current_game_locations = {'<td>' .. unavailable_sentence .. '</td><td></td>'}
			else table.insert(current_game_locations, comma_string .. '<span style="white-space:nowrap">' .. place_link_display)
				-- '</span>' is added after the end of the rate calculation, to add a possible {{Sup|.}} after the rate
			end
			
		end
		
		
		
		function add_rate(rate, rate_precision, colspan, class, notes)
			local seen_games_here = nil
			local found_notes = false
			
			if notes and string.find(notes, "Capturable une seule fois")
			then rate = "Unique"
			end
			
			rate = mw.ustring.gsub(rate, "-", "—")
			rate = mw.text.split(rate, ", ")
			if tonumber(rate[1])
			then rate[1] = string.gsub(rate[1], "%.", ",") .. "&nbsp;%"
			else rate[1] = mw.ustring.gsub(rate[1], "{{!}}", "|")
			end
			if rate[1] == "Fixe" then rate[1] = "[[Fichier:Icône Fixe.svg|class=imagenoire|27px|link=|alt=Fixe|Fixe]]" end
			if rate[1]:find("{{") then rate[1] = frame:preprocess(rate[1]) end
			
			table.insert(current_subarea_full_locations, "<td")
			if class then table.insert(current_subarea_full_locations, ' class="' .. class .. '"') end
			if colspan then table.insert(current_subarea_full_locations, ' colspan="' .. colspan .. '"') end
			table.insert(current_subarea_full_locations, '>' .. rate[1])
			
			local k = 2
			while rate[k] do	-- Gestion des taux spécifiques à des jeux
				if tonumber(rate[k])
				then table.insert(current_subarea_full_locations, "<br>" .. string.gsub(rate[k], "%.", ",") .. "&nbsp;%")
				else 
					if rate[k]:find("{{") then rate[k] = frame:preprocess(rate[k]) end
					table.insert(current_subarea_full_locations, frame:expandTemplate{title='Sup', args={rate[k]}})
					if seen_games_here and seen_games_here ~= rate[k] then seen_games_here = "all" else seen_games_here = rate[k] end
				end
				k = k + 1
			end
			if notes and string.sub(notes, 1, 9) == "Exclusif "
			then found_notes = true
				local game = string.sub(notes, 10, string.find(notes, ".", 11))
				table.insert(current_subarea_full_locations, frame:expandTemplate{title='Sup', args={game}})
				if seen_games_here and seen_games_here ~= game then seen_games_here = "all" else seen_games_here = game end
			end
			
			if rate_precision then table.insert(current_subarea_full_locations, '<br><small><i>' .. rate_precision .. '</i></small>') end
			table.insert(current_subarea_full_locations, "</td>")
			
			-- might want rework if there is a trio of games at some point
			if rate[2] or rate[1] ~= "—" or found_notes
			then if seen_games_place and seen_games_place ~= seen_games_here
				then seen_games_place = "all"
				else if seen_games_here
					then seen_games_place = seen_games_here
					else seen_games_place = "all"
					end
				end
			end
		end
		
		local place_info = places[i]["contents"]
		if place_info
		then local j = 1
			while place_info[j] do
				local id = places[i]["id"]
				local milieu = place_info[j]["milieu"]
				local emplacement = place_info[j]["emplacement"]
				
				if milieu
				then milieu = mw.ustring.gsub(milieu, "<br>", " ")
					milieu_split = mw.ustring.gsub(milieu, ',', '')
				else milieu = ""
				end
				
				-- précision de localisation par rapport au "milieu"
				if emplacement
				then emplacement = ', ' .. mw.ustring.gsub(emplacement, "<br>", " ")
				else emplacement = ""
				end
				
				local endroit_unsplit = mw.text.split(milieu, ",, ")
				local prefixe_endroit = endroit_unsplit[2] -- éventuellement nil
				local endroit = mw.text.split(endroit_unsplit[1], ",")
				local endroit_untouched = endroit[1]
				if prefixe_endroit == nil
				then prefixe_endroit = ""
				else prefixe_endroit = prefixe_endroit .. " "
					endroit[1] = mw.ustring.lower(mw.ustring.sub(endroit[1],1,1)) .. mw.ustring.sub(endroit[1],2,endroit[1]:len())
					-- on a mis la première lettre de l'endroit en minuscule, puisqu'elle est précédée de prefixe_endroit
				end
				endroit[1] = mw.ustring.gsub(endroit[1], " %([^%)]*%)", "")
				-- on retire les parenthèses des milieux, elles ne servent qu'à spécifier l'image, inutile ici
				
				if endroit[2] == nil then endroit[2] = "" end
				-- Seule la première virgule sert à séparer
				local k = 3
				while endroit[k] ~= nil do
					endroit[2] = endroit[2] .. ", " .. endroit[k]
					k = k + 1
				end
			
				endroit[1] = mw.ustring.gsub(endroit[1], " – ", ", ")
				endroit[2] = mw.ustring.gsub(endroit[2], " – ", ", ")
				
				endroit[2] = mw.ustring.gsub(endroit[2], "{{!}}", "|")
				local template_replacement = endroit[2]:gsub(".*{{(.-)|(.-)}}.*", "%1") -- sert à process les modèles, qu'ils utilisent "|" ou "{{!}}"
				local templates_replaced = 0
				while template_replacement ~= endroit[2] and templates_replaced < 4 do -- pour empêcher une boucle infinie en cas de pépin, 4 modèles max devraient suffire
					local arg_template_replacement = endroit[2]:gsub(".*{{(.-)|(.-)}}.*", "%2")
					
					local template_result = frame:expandTemplate{title=template_replacement, args={arg_template_replacement}}
					endroit[2] = endroit[2]:gsub("(.*){{(.-)|(.-)}}(.*)", "%1" .. template_result .. "%4")
					
					local template_replacement = endroit[2]:gsub(".*{{(.-)|(.-)}}.*", "%1")
					templates_replaced = templates_replaced + 1
				end
				
				milieu = prefixe_endroit .. endroit[1] .. endroit[2] .. emplacement
				if milieu ~= "" then milieu = " • " .. milieu end
				
				table.insert(current_subarea_full_locations, "<tr>")
				if multiple_ids
				then if id
					then table.insert(current_subarea_full_locations, "<td>" .. ressources.infosPokemon(id .. game_minisprites[current_game], "forme") .. "</td>")
					else table.insert(current_subarea_full_locations, "<td></td>")
					end
				end
				table.insert(current_subarea_full_locations, "<td>" .. place_link_display .. place_suffix .. milieu .. '</td>')
				
				-- Étage
				if is_mystery_dungeon
				then
					local etage = place_info[j]["étage"]
					if etage then etage = mw.ustring.gsub(etage, "-", "−") else etage = "—" end
					etage = mw.text.split(etage, ", ")
					
					table.insert(current_subarea_full_locations, '<td><span style="white-space:nowrap">' .. etage[1])
					local k = 2
					while etage[k] do
						etage_k = mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(etage[k], "–", ""), " à ", ""), " et ", "")
						if tonumber(etage_k)
						then table.insert(current_subarea_full_locations, '</span><br><span style="white-space:nowrap">' .. etage[k])
						else table.insert(current_subarea_full_locations, frame:expandTemplate{title='Sup', args={etage[k]}})
						end
						k = k + 1
					end
					table.insert(current_subarea_full_locations, "</span></td>")
				end
				
				-- Niveau
				local level = place_info[j]["niveau"]
				if level then level = mw.ustring.gsub(level, "-", "–") else level = "–" end
				level = mw.text.split(level, ", ")
				
				table.insert(current_subarea_full_locations, "<td>")
				
				local is_pred_rate = false
				local span_br = ""
				local k = 1
				while level[k] do
					local baron_image = ""
					if level[k]:find("Baron ")
					then baron_image = "[[Fichier:Icône Pokémon Baron " .. current_game .. ".png|x20px|link=Pokémon Baron]] "
						level[k] = level[k]:gsub("Baron ", "")
					end
					
					level_k = mw.ustring.gsub(level[k], "–", "")
				
					if level_k == "" then
						table.insert(current_subarea_full_locations, span_br .. '<span style="white-space:nowrap">' .. baron_image .. "—")
						is_pred_rate = true
					elseif not is_pred_rate or tonumber(level_k) then
						table.insert(current_subarea_full_locations, span_br .. '<span style="white-space:nowrap">' .. baron_image .. level[k])
						is_pred_rate = true
					else
						table.insert(current_subarea_full_locations, frame:expandTemplate{title='Sup', args={level[k]}})
						is_pred_rate = false
					end
					span_br = "</span><br>"
					k = k + 1
				end
				table.insert(current_subarea_full_locations, "</span></td>")
				
				-- Taux de recrutement
				if is_mystery_dungeon
				then table.insert(current_subarea_full_locations, '<td>À venir</td>')
				end
				
				-- Taux d'apparition
				if reduced_colspan_rates[current_game] > 0
				then
					local rate = place_info[j]["taux"]
					if rate
					then local rate_precision = place_info[j]["précision-taux"]
						local notes = place_info[j]["notes"]
						add_rate(rate, rate_precision, reduced_colspan_rates[current_game], nil, notes)
						
					else local subarea_info = subarea_subrates_list[current_game][subarea_text]
						local notes = place_info[j]["notes"]
						if subarea_info.subrates
						then local colspan_local = math.floor(reduced_colspan_rates[current_game] / subarea_info.number)
							for s = 1, subarea_info.number do
								local subrate_s = place_info[j][subarea_info.subrates[2][s]]
								if not subrate_s then subrate_s = "—" end
								local subrate_s_precision = place_info[j]["précision-" .. subarea_info.subrates[2][s]]
								add_rate(subrate_s, subrate_s_precision, colspan_local, subarea_info.subrates[3][s], notes)
							end
						else add_rate("—", nil, reduced_colspan_rates[current_game], nil, notes)
						end
					end
				end
				
				-- Horaires
				if colspan_times[current_game] > 0
				then local subarea_times = subarea_times_list[current_game][subarea_text].times
					if subarea_times
					then local colspan_local = math.floor(colspan_times[current_game] / subarea_times_list[current_game][subarea_text].number)
						local time_j = place_info[j]["horaire"]
						if time_j
						then time_j_split = mw.text.split(time_j, ", ")
							local k = 1
							while subarea_times[1][k] do
								local time_k = ""
								local jj = 1
								while time_j_split[jj] do
									if subarea_times[1][k] == time_j_split[jj] then time_k = "✓" end
									jj = jj + 1
								end
								add_rate(time_k, nil, colspan_local, subarea_times[2][k], nil)
								k = k + 1
							end
						else add_rate("✓", nil, colspan_times[current_game], nil, nil)
						end
					else add_rate("—", nil, colspan_times[current_game], nil, nil)
					end
				end
				
				-- Météos
				if colspan_weathers[current_game] > 0
				then local subarea_weathers = subarea_weathers_list[current_game][subarea_text].weathers
					if subarea_weathers
					then local colspan_local = math.floor(colspan_weathers[current_game] / subarea_weathers_list[current_game][subarea_text].number)
						local weather_j = place_info[j]["météo"]
						if weather_j
						then weather_j_split = mw.text.split(weather_j, ", ")
							local k = 1
							while subarea_weathers[1][k] do
								local weather_k = ""
								local jj = 1
								while weather_j_split[jj] do
									if subarea_weathers[1][k] == weather_j_split[jj] then weather_k = "✓" end
									jj = jj + 1
								end
								add_rate(weather_k, nil, colspan_local, subarea_weathers[2][k], nil)
								k = k + 1
							end
						else add_rate("✓", nil, colspan_weathers[current_game], nil, nil)
						end
					else add_rate("—", nil, colspan_weathers[current_game], nil, nil)
					end
				end
				
				table.insert(current_subarea_full_locations, "</tr>")
				
				j = j + 1
			end
		end
		
		i = i + 1
	end
	table.insert(result, '<caption style="caption-side:bottom; font-weight:normal; line-height:100%; padding-top:0.5em"><small><i>Ce tableau est généré automatiquement. Pour que son contenu soit modifié, il faut modifier les pages de lieux. Informations détaillées sur [[Module:Localisations|cette page]].</i></small></caption></tbody></table>')
	
	-- if is_there_full_table
	-- then
		table.insert(result_header, '<table class="tableaustandard centre ' .. pokemon_type .. '"><tbody><tr><th width="150px">Versions</th><th width="600px">Localisations</th><th width="60px">Détails</th>')
		table.insert(result, table.concat(full_table, ""))
	-- else table.insert(result_header, '<table class="tableaustandard centre ' .. pokemon_type .. '"><tbody><tr><th width="150px">Versions</th><th width="600px" colspan="2">Localisations</th>')
	-- end
	
	table.insert(result_header, '</tr>')
	table.insert(result_header, table.concat(result, ""))
	return table.concat(result_header, "")
end



-- Fonction pour recenser les endroits de tous les Pokémon détectés pour un même jeu, donné en argument
function p.pokeliste(frame)
	local result = {}
	local game = frame.args["jeu"]
	if not game then game = frame.args[1] end
	local game_long = game_to_game_long[game]
	if not game_long then return "<i>Erreur : jeu invalide.</i>" end
	
	
	
	local game_minisprite = game
	if game == "RV" or game == "RB" or game == "B-JP" or game == "B-jp" or game == "J" or game == "OA" or game == "C"
	then game_minisprite = "RS"
	elseif game == "Démo-ROSA"
	then game_minisprite = "ROSA"
	elseif game == "Démo-SL"
	then game_minisprite = "SL"
	end
	game_minisprite = " jeu(" .. game_minisprite .. ")"
		
	if game ~= "LPA" and game ~= "LPZA"
	then game_long = "Pokémon " .. game_to_game_long[game]
	end
	
	local locdata = require("Module:Localisations/Données/" .. game_long)
	local pokemon_global_list = {}
	for place_name, pokemon_list in pairs(locdata) do
		local place_name_stripped = mw.text.split(mw.text.split(place_name, "@")[1], "|")[1]
		local place_name_link = "[[" .. place_name_stripped .. "|" .. mw.ustring.gsub(place_name_stripped, " %(.-%).-", "") .. "]]"
		for pokemon, _ in pairs(pokemon_list) do
			if pokemon_global_list[pokemon]
			then pokemon_global_list[pokemon] = pokemon_global_list[pokemon] .. ", " .. place_name_link
			else pokemon_global_list[pokemon] = place_name_link
			end
		end
	end
	
	table.insert(result, '<table class="tableaustandard sortable entetefixe"><tr><th>infosPokemon</th><th>Pokémon</th><th>Lieux</th></tr>')
	
	for pokemon, places in pairs(pokemon_global_list) do
		table.insert(result, '<tr><td>' .. ressources.infosPokemon(pokemon .. game_minisprite) .. '</td><td>' .. pokemon .. '</td><td>' .. places .. '</td></tr>')
	end
	
	table.insert(result, '</table>')
	
	return table.concat(result, "")
end

return p