« Module:Episode/MultiSeries » : différence entre les versions
Apparence
Contenu supprimé Contenu ajouté
Aucun résumé des modifications |
Aucun résumé des modifications |
||
| (3 versions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 1 : | Ligne 1 : | ||
-- Module:Episode/MultiSeries |
-- Module:Episode/MultiSeries |
||
-- Fusionne toutes les séries et saisons (SG-1, SGA, SGU, Films…) |
|||
-- Loads series index modules and season modules, merges episodes and aliases |
|||
-- Fournit : get(id), get_by_alias(alias), resolve_alias(alias) |
|||
-- + Détection automatique des doublons |
|||
-- + Cache interne pour éviter le signal 24 |
|||
------------------------------------------------------------ |
|||
-- CACHE : si déjà chargé, on renvoie la version en mémoire |
|||
------------------------------------------------------------ |
|||
local cached = package.loaded["Module:Episode/MultiSeries"] |
|||
if type(cached) == "table" then |
|||
return cached |
|||
end |
|||
------------------------------------------------------------ |
|||
-- Dépendances |
|||
------------------------------------------------------------ |
|||
local utils = require("Module:Episode/Shared/Utils") |
local utils = require("Module:Episode/Shared/Utils") |
||
local Master = { |
|||
------------------------------------------------------------ |
|||
episodes = {}, -- id -> episode table |
|||
-- Structure principale |
|||
aliases = {}, -- normalized alias -> id |
|||
------------------------------------------------------------ |
|||
loaded = {}, -- list of loaded module paths |
|||
local Multi = { |
|||
episodes = {}, -- id → table épisode |
|||
aliases = {}, -- alias normalisé → id |
|||
loaded = {}, -- modules chargés |
|||
duplicates = nil -- rapport de doublons |
|||
} |
} |
||
------------------------------------------------------------ |
|||
-- Load a season module safely and merge |
|||
-- Liste des modules index de séries |
|||
local function load_and_merge(module_path) |
|||
-- (tu ajoutes ici SG1, SGA, SGU, Films, etc.) |
|||
local ok, mod = pcall(require, module_path) |
|||
------------------------------------------------------------ |
|||
if not ok or type(mod) ~= "table" then return false end |
|||
local SERIES_INDEX = { |
|||
for k,v in pairs(mod) do |
|||
"Module:Episode/SG1/Index", |
|||
if type(v) == "table" and v.id and utils.validate_episode(v) then |
|||
"Module:Episode/SGA/Index", |
|||
Master.episodes[v.id] = v |
|||
"Module:Episode/SGU/Index", |
|||
if type(v.aliases) == "table" then |
|||
"Module:Episode/Films/Index", |
|||
for _, a in ipairs(v.aliases) do |
|||
} |
|||
local norm = utils.normalize_alias(a) |
|||
if norm then Master.aliases[norm] = v.id end |
|||
------------------------------------------------------------ |
|||
-- Charge un module de saison et fusionne son contenu |
|||
------------------------------------------------------------ |
|||
local function load_season_module(path) |
|||
local ok, mod = pcall(require, path) |
|||
if not ok or type(mod) ~= "table" then |
|||
return false |
|||
end |
|||
for key, value in pairs(mod) do |
|||
------------------------------------------------------------ |
|||
-- Cas 1 : entrée d’épisode (table avec .id) |
|||
------------------------------------------------------------ |
|||
if type(value) == "table" and value.id then |
|||
Multi.episodes[value.id] = value |
|||
-- Ajout des alias déclarés dans l’épisode |
|||
if type(value.aliases) == "table" then |
|||
for _, alias in ipairs(value.aliases) do |
|||
local norm = utils.normalize_alias(alias) |
|||
if norm then |
|||
Multi.aliases[norm] = value.id |
|||
end |
|||
end |
end |
||
end |
end |
||
elseif type(v) == "string" then |
|||
------------------------------------------------------------ |
|||
local norm = utils.normalize_alias(k) |
|||
-- Cas 2 : alias → id (clé = alias, valeur = id) |
|||
------------------------------------------------------------ |
|||
elseif type(value) == "string" then |
|||
local norm = utils.normalize_alias(key) |
|||
if norm then |
|||
Multi.aliases[norm] = value |
|||
end |
|||
end |
end |
||
end |
end |
||
table.insert(Master.loaded, module_path) |
|||
table.insert(Multi.loaded, path) |
|||
return true |
return true |
||
end |
end |
||
------------------------------------------------------------ |
|||
-- Public: load a list of series index modules |
|||
-- Charge un module index de série (liste des saisons) |
|||
function Master.load_series(series_index_modules) |
|||
------------------------------------------------------------ |
|||
series_index_modules = series_index_modules or { |
|||
local function load_series_index(path) |
|||
"Module:Episode/SG1/Index", |
|||
local ok, idx = pcall(require, path) |
|||
"Module:Episode/SGA/Index", |
|||
if not ok or type(idx) ~= "table" or not idx.list_seasons then |
|||
"Module:Episode/SGU/Index", |
|||
return |
|||
for _, idx_path in ipairs(series_index_modules) do |
|||
local ok, idx = pcall(require, idx_path) |
|||
if ok and type(idx) == "table" and idx.list_seasons then |
|||
for _, s in ipairs(idx.list_seasons()) do |
|||
load_and_merge(s.module) |
|||
end |
|||
end |
|||
end |
end |
||
return { |
|||
episodes_count = (function() local c=0; for _ in pairs(Master.episodes) do c=c+1 end; return c end)(), |
|||
aliases_count = (function() local c=0; for _ in pairs(Master.aliases) do c=c+1 end; return c end)(), |
|||
loaded = Master.loaded, |
|||
} |
|||
end |
|||
for _, entry in ipairs(idx.list_seasons()) do |
|||
function Master.get_by_id(id) return Master.episodes[id] end |
|||
load_season_module(entry.module) |
|||
function Master.resolve_alias(alias) return Master.aliases[utils.normalize_alias(alias)] end |
|||
end |
|||
function Master.get_by_alias(alias) |
|||
local id = Master.resolve_alias(alias) |
|||
if id then return Master.get_by_id(id) end |
|||
return nil |
|||
end |
end |
||
------------------------------------------------------------ |
|||
function Master.check_duplicates() |
|||
-- Détection des doublons (IDs, alias, alias contradictoires) |
|||
------------------------------------------------------------ |
|||
local function detect_duplicates() |
|||
local report = { |
local report = { |
||
duplicate_ids = {}, |
duplicate_ids = {}, |
||
| Ligne 67 : | Ligne 105 : | ||
} |
} |
||
-- |
-- IDs |
||
local seen_ids = {} |
local seen_ids = {} |
||
for id, |
for id,_ in pairs(Multi.episodes) do |
||
if seen_ids[id] then |
if seen_ids[id] then |
||
table.insert(report.duplicate_ids, id) |
table.insert(report.duplicate_ids, id) |
||
| Ligne 77 : | Ligne 115 : | ||
end |
end |
||
-- |
-- Aliases |
||
local alias_targets = {} |
local alias_targets = {} |
||
for alias, id in pairs( |
for alias, id in pairs(Multi.aliases) do |
||
if alias_targets[alias] and alias_targets[alias] ~= id then |
if alias_targets[alias] and alias_targets[alias] ~= id then |
||
-- même alias → deux IDs différents |
|||
table.insert(report.conflicting_aliases, { |
table.insert(report.conflicting_aliases, { |
||
alias = alias, |
alias = alias, |
||
id1 = alias_targets[alias], |
id1 = alias_targets[alias], |
||
id2 = id |
id2 = id, |
||
}) |
}) |
||
elseif alias_targets[alias] then |
elseif alias_targets[alias] then |
||
-- même alias → même ID (OK, mais on peut le signaler si tu veux) |
|||
table.insert(report.duplicate_aliases, alias) |
table.insert(report.duplicate_aliases, alias) |
||
else |
else |
||
| Ligne 95 : | Ligne 131 : | ||
end |
end |
||
Multi.duplicates = report |
|||
end |
end |
||
------------------------------------------------------------ |
|||
return Master |
|||
-- Chargement global (toutes séries + saisons) |
|||
------------------------------------------------------------ |
|||
local function load_all() |
|||
for _, series_path in ipairs(SERIES_INDEX) do |
|||
load_series_index(series_path) |
|||
end |
|||
detect_duplicates() |
|||
end |
|||
load_all() |
|||
------------------------------------------------------------ |
|||
-- API publique |
|||
------------------------------------------------------------ |
|||
-- Récupère un épisode par ID |
|||
function Multi.get(id) |
|||
return Multi.episodes[id] |
|||
end |
|||
-- Résout un alias → ID |
|||
function Multi.resolve_alias(alias) |
|||
if not alias then return nil end |
|||
local norm = utils.normalize_alias(alias) |
|||
return Multi.aliases[norm] |
|||
end |
|||
-- Récupère un épisode via alias |
|||
function Multi.get_by_alias(alias) |
|||
local id = Multi.resolve_alias(alias) |
|||
if id then |
|||
return Multi.get(id) |
|||
end |
|||
return nil |
|||
end |
|||
------------------------------------------------------------ |
|||
-- Vérifie les doublons d’ID et d’alias |
|||
-- CACHE : on stocke la table Multi pour les appels suivants |
|||
------------------------------------------------------------ |
|||
package.loaded["Module:Episode/MultiSeries"] = Multi |
|||
return Multi |
|||
Dernière version du 1 juin 2026 à 20:56
| Il sera peut-être nécessaire de créer une page documentation pour ce module Scribunto programmé dans la page créer Les éditeurs peuvent faire des tests sur les pages bac à sable (créer | miroir) et études de cas (créer) du module. Veuillez ajouter les catégories dans la sous-page /documentation. Sous-pages de ce module. |
-- Module:Episode/MultiSeries
-- Fusionne toutes les séries et saisons (SG-1, SGA, SGU, Films…)
-- Fournit : get(id), get_by_alias(alias), resolve_alias(alias)
-- + Détection automatique des doublons
-- + Cache interne pour éviter le signal 24
------------------------------------------------------------
-- CACHE : si déjà chargé, on renvoie la version en mémoire
------------------------------------------------------------
local cached = package.loaded["Module:Episode/MultiSeries"]
if type(cached) == "table" then
return cached
end
------------------------------------------------------------
-- Dépendances
------------------------------------------------------------
local utils = require("Module:Episode/Shared/Utils")
------------------------------------------------------------
-- Structure principale
------------------------------------------------------------
local Multi = {
episodes = {}, -- id → table épisode
aliases = {}, -- alias normalisé → id
loaded = {}, -- modules chargés
duplicates = nil -- rapport de doublons
}
------------------------------------------------------------
-- Liste des modules index de séries
-- (tu ajoutes ici SG1, SGA, SGU, Films, etc.)
------------------------------------------------------------
local SERIES_INDEX = {
"Module:Episode/SG1/Index",
"Module:Episode/SGA/Index",
"Module:Episode/SGU/Index",
"Module:Episode/Films/Index",
}
------------------------------------------------------------
-- Charge un module de saison et fusionne son contenu
------------------------------------------------------------
local function load_season_module(path)
local ok, mod = pcall(require, path)
if not ok or type(mod) ~= "table" then
return false
end
for key, value in pairs(mod) do
------------------------------------------------------------
-- Cas 1 : entrée d’épisode (table avec .id)
------------------------------------------------------------
if type(value) == "table" and value.id then
Multi.episodes[value.id] = value
-- Ajout des alias déclarés dans l’épisode
if type(value.aliases) == "table" then
for _, alias in ipairs(value.aliases) do
local norm = utils.normalize_alias(alias)
if norm then
Multi.aliases[norm] = value.id
end
end
end
------------------------------------------------------------
-- Cas 2 : alias → id (clé = alias, valeur = id)
------------------------------------------------------------
elseif type(value) == "string" then
local norm = utils.normalize_alias(key)
if norm then
Multi.aliases[norm] = value
end
end
end
table.insert(Multi.loaded, path)
return true
end
------------------------------------------------------------
-- Charge un module index de série (liste des saisons)
------------------------------------------------------------
local function load_series_index(path)
local ok, idx = pcall(require, path)
if not ok or type(idx) ~= "table" or not idx.list_seasons then
return
end
for _, entry in ipairs(idx.list_seasons()) do
load_season_module(entry.module)
end
end
------------------------------------------------------------
-- Détection des doublons (IDs, alias, alias contradictoires)
------------------------------------------------------------
local function detect_duplicates()
local report = {
duplicate_ids = {},
duplicate_aliases = {},
conflicting_aliases = {},
}
-- IDs
local seen_ids = {}
for id,_ in pairs(Multi.episodes) do
if seen_ids[id] then
table.insert(report.duplicate_ids, id)
else
seen_ids[id] = true
end
end
-- Aliases
local alias_targets = {}
for alias, id in pairs(Multi.aliases) do
if alias_targets[alias] and alias_targets[alias] ~= id then
table.insert(report.conflicting_aliases, {
alias = alias,
id1 = alias_targets[alias],
id2 = id,
})
elseif alias_targets[alias] then
table.insert(report.duplicate_aliases, alias)
else
alias_targets[alias] = id
end
end
Multi.duplicates = report
end
------------------------------------------------------------
-- Chargement global (toutes séries + saisons)
------------------------------------------------------------
local function load_all()
for _, series_path in ipairs(SERIES_INDEX) do
load_series_index(series_path)
end
detect_duplicates()
end
load_all()
------------------------------------------------------------
-- API publique
------------------------------------------------------------
-- Récupère un épisode par ID
function Multi.get(id)
return Multi.episodes[id]
end
-- Résout un alias → ID
function Multi.resolve_alias(alias)
if not alias then return nil end
local norm = utils.normalize_alias(alias)
return Multi.aliases[norm]
end
-- Récupère un épisode via alias
function Multi.get_by_alias(alias)
local id = Multi.resolve_alias(alias)
if id then
return Multi.get(id)
end
return nil
end
------------------------------------------------------------
-- CACHE : on stocke la table Multi pour les appels suivants
------------------------------------------------------------
package.loaded["Module:Episode/MultiSeries"] = Multi
return Multi