Aller au contenu

« Module:Episode/MultiSeries » : différence entre les versions

De Stargate Wiki Sémantique
Contenu supprimé Contenu ajouté
Aucun résumé des modifications
Aucun résumé des modifications
Ligne 1 : Ligne 1 :
------------------------------------------------------------
-- Module:Episode/MultiSeries
-- Module:Episode/MultiSeries
-- Fusion SG1 + SGA + SGU
-- Fusionne toutes les séries et saisons (SG-1, SGA, SGU, Films…)
-- Normalisation, alias, indexation, cache, doublons
-- Fournit : get(id), get_by_alias(alias), resolve_alias(alias)
------------------------------------------------------------
-- + Détection automatique des doublons

-- + Cache interne pour éviter le signal 24
local Multi = {}


------------------------------------------------------------
------------------------------------------------------------
-- 1. Cache anti-signal-24
-- CACHE : si déjà chargé, on renvoie la version en mémoire
------------------------------------------------------------
------------------------------------------------------------
local cached = package.loaded["Module:Episode/MultiSeries"]
if package.loaded["Module:Episode/MultiSeries"] then
return package.loaded["Module:Episode/MultiSeries"]
if type(cached) == "table" then
return cached
end
end


------------------------------------------------------------
------------------------------------------------------------
-- 2. Chargement des séries
-- Dépendances
------------------------------------------------------------
------------------------------------------------------------
local utils = require("Module:Episode/Shared/Utils")
local SG1 = require("Module:Episode/SG1")
local SGA = require("Module:Episode/SGA")
local SGU = require("Module:Episode/SGU")


------------------------------------------------------------
------------------------------------------------------------
-- 3. Tables globales
-- Structure principale
------------------------------------------------------------
------------------------------------------------------------
local Multi = {
Multi.episodes = {}
Multi.by_id = {}
episodes = {}, -- id → table épisode
Multi.by_alias = {}
aliases = {}, -- alias normalisé → id
Multi.by_page = {}
loaded = {}, -- modules chargés
Multi.by_series = {}
duplicates = nil -- rapport de doublons
Multi.by_season = {}
}


------------------------------------------------------------
------------------------------------------------------------
-- 4. Fonction normalize() finale
-- Liste des modules index de séries
-- (tu ajoutes ici SG1, SGA, SGU, Films, etc.)
------------------------------------------------------------
------------------------------------------------------------
local SERIES_INDEX = {
local function normalize(str)
if not str then return "" end
"Module:Episode/SG1/Index",
"Module:Episode/SGA/Index",
"Module:Episode/SGU/Index",
"Module:Episode/Films/Index",
}


str = mw.ustring.lower(str)
------------------------------------------------------------
str = mw.ustring.toNFD(str)
-- Charge un module de saison et fusionne son contenu
str = mw.ustring.gsub(str, "%pM", "")
------------------------------------------------------------
str = str:gsub("'%s*", "")
local function load_season_module(path)
local ok, mod = pcall(require, path)
str = str:gsub("[{}]", " ")
if not ok or type(mod) ~= "table" then
str = str:gsub("[%p]", " ")
str = str:gsub("[^%w%s]", " ")
return false
str = str:gsub("%s+", " ")
end
str = mw.text.trim(str)

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


return str
table.insert(Multi.loaded, path)
return true
end
end


------------------------------------------------------------
------------------------------------------------------------
-- 5. Alias techniques SGX
-- Charge un module index de série (liste des saisons)
------------------------------------------------------------
------------------------------------------------------------
local function load_series_index(path)
local function make_tech_aliases(series, season, episode)
local ok, idx = pcall(require, path)
local s = string.format("%02d", tonumber(season))
local e = string.format("%02d", tonumber(episode))
if not ok or type(idx) ~= "table" or not idx.list_seasons then
series = normalize(series)
return
end


return {
for _, entry in ipairs(idx.list_seasons()) do
string.format("%s s%se%s", series, s, e),
load_season_module(entry.module)
string.format("%s %sx%s", series, s, e),
end
string.format("%s %s%s", series, s, e),
}
end
end


------------------------------------------------------------
------------------------------------------------------------
-- 6. Génération complète des alias
-- Détection des doublons (IDs, alias, alias contradictoires)
------------------------------------------------------------
------------------------------------------------------------
local function detect_duplicates()
local function make_aliases(ep)
local report = {
local a = {}
duplicate_ids = {},
duplicate_aliases = {},
conflicting_aliases = {},
}


-- IDs
-- titres normalisés
table.insert(a, normalize(ep.title_fr))
local seen_ids = {}
table.insert(a, normalize(ep.title_en))
for id,_ in pairs(Multi.episodes) do

if seen_ids[id] then
-- id normalisé
table.insert(report.duplicate_ids, id)
table.insert(a, normalize(ep.id))
else

seen_ids[id] = true
end
-- alias techniques
for _, alias in ipairs(make_tech_aliases(ep.series, ep.season, ep.episode)) do
table.insert(a, alias)
end
end


-- Aliases
-- extra_aliases
if ep.extra_aliases then
local alias_targets = {}
for alias, id in pairs(Multi.aliases) do
for _, alias in ipairs(ep.extra_aliases) do
table.insert(a, normalize(alias))
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
end
end


return a
Multi.duplicates = report
end
end


------------------------------------------------------------
------------------------------------------------------------
-- 7. Ajout d'une série complète
-- Chargement global (toutes séries + saisons)
------------------------------------------------------------
------------------------------------------------------------
local function load_all()
local function append_series(series_module)
for _, series_path in ipairs(SERIES_INDEX) do
for _, ep in ipairs(series_module.episodes or {}) do
load_series_index(series_path)
end
detect_duplicates()
end


----------------------------------------------------
load_all()
-- Génération des alias
----------------------------------------------------
ep.aliases = make_aliases(ep)


------------------------------------------------------------
----------------------------------------------------
-- Index par ID
-- API publique
------------------------------------------------------------
----------------------------------------------------
Multi.by_id[ep.id] = ep


----------------------------------------------------
-- Récupère un épisode par ID
-- Index par page (FR + EN)
function Multi.get(id)
----------------------------------------------------
return Multi.episodes[id]
if ep.page_title_fr then
end
Multi.by_page[normalize(ep.page_title_fr)] = ep
end
if ep.page_title_en then
Multi.by_page[normalize(ep.page_title_en)] = ep
end


----------------------------------------------------
-- Résout un alias → ID
-- Index par alias
function Multi.resolve_alias(alias)
----------------------------------------------------
if not alias then return nil end
for _, alias in ipairs(ep.aliases) do
local norm = utils.normalize_alias(alias)
alias = normalize(alias)
return Multi.aliases[norm]
Multi.by_alias[alias] = Multi.by_alias[alias] or {}
end
table.insert(Multi.by_alias[alias], ep)
end


----------------------------------------------------
-- Récupère un épisode via alias
-- Index par série
function Multi.get_by_alias(alias)
----------------------------------------------------
local id = Multi.resolve_alias(alias)
Multi.by_series[ep.series] = Multi.by_series[ep.series] or {}
if id then
table.insert(Multi.by_series[ep.series], ep)
return Multi.get(id)

----------------------------------------------------
-- Index par saison
----------------------------------------------------
local key = ep.series .. "-" .. ep.season
Multi.by_season[key] = Multi.by_season[key] or {}
table.insert(Multi.by_season[key], ep)

----------------------------------------------------
-- Ajout à la liste globale
----------------------------------------------------
table.insert(Multi.episodes, ep)
end
end
return nil
end
end


------------------------------------------------------------
------------------------------------------------------------
-- 8. Fusion des séries
-- CACHE : on stocke la table Multi pour les appels suivants
------------------------------------------------------------
append_series(SG1)
append_series(SGA)
append_series(SGU)

------------------------------------------------------------
-- 9. Cache final
------------------------------------------------------------
------------------------------------------------------------
package.loaded["Module:Episode/MultiSeries"] = Multi
package.loaded["Module:Episode/MultiSeries"] = Multi

Version du 2 juin 2026 à 14:47

Documentation icon Documentation module[créer]
------------------------------------------------------------
-- Module:Episode/MultiSeries
-- Fusion SG1 + SGA + SGU
-- Normalisation, alias, indexation, cache, doublons
------------------------------------------------------------

local Multi = {}

------------------------------------------------------------
-- 1. Cache anti-signal-24
------------------------------------------------------------
if package.loaded["Module:Episode/MultiSeries"] then
    return package.loaded["Module:Episode/MultiSeries"]
end

------------------------------------------------------------
-- 2. Chargement des séries
------------------------------------------------------------
local SG1 = require("Module:Episode/SG1")
local SGA = require("Module:Episode/SGA")
local SGU = require("Module:Episode/SGU")

------------------------------------------------------------
-- 3. Tables globales
------------------------------------------------------------
Multi.episodes = {}
Multi.by_id = {}
Multi.by_alias = {}
Multi.by_page = {}
Multi.by_series = {}
Multi.by_season = {}

------------------------------------------------------------
-- 4. Fonction normalize() finale
------------------------------------------------------------
local function normalize(str)
    if not str then return "" end

    str = mw.ustring.lower(str)
    str = mw.ustring.toNFD(str)
    str = mw.ustring.gsub(str, "%pM", "")
    str = str:gsub("'%s*", "")
    str = str:gsub("[{}]", " ")
    str = str:gsub("[%p]", " ")
    str = str:gsub("[^%w%s]", " ")
    str = str:gsub("%s+", " ")
    str = mw.text.trim(str)

    return str
end

------------------------------------------------------------
-- 5. Alias techniques SGX
------------------------------------------------------------
local function make_tech_aliases(series, season, episode)
    local s = string.format("%02d", tonumber(season))
    local e = string.format("%02d", tonumber(episode))
    series = normalize(series)

    return {
        string.format("%s s%se%s", series, s, e),
        string.format("%s %sx%s", series, s, e),
        string.format("%s %s%s", series, s, e),
    }
end

------------------------------------------------------------
-- 6. Génération complète des alias
------------------------------------------------------------
local function make_aliases(ep)
    local a = {}

    -- titres normalisés
    table.insert(a, normalize(ep.title_fr))
    table.insert(a, normalize(ep.title_en))

    -- id normalisé
    table.insert(a, normalize(ep.id))

    -- alias techniques
    for _, alias in ipairs(make_tech_aliases(ep.series, ep.season, ep.episode)) do
        table.insert(a, alias)
    end

    -- extra_aliases
    if ep.extra_aliases then
        for _, alias in ipairs(ep.extra_aliases) do
            table.insert(a, normalize(alias))
        end
    end

    return a
end

------------------------------------------------------------
-- 7. Ajout d'une série complète
------------------------------------------------------------
local function append_series(series_module)
    for _, ep in ipairs(series_module.episodes or {}) do

        ----------------------------------------------------
        -- Génération des alias
        ----------------------------------------------------
        ep.aliases = make_aliases(ep)

        ----------------------------------------------------
        -- Index par ID
        ----------------------------------------------------
        Multi.by_id[ep.id] = ep

        ----------------------------------------------------
        -- Index par page (FR + EN)
        ----------------------------------------------------
        if ep.page_title_fr then
            Multi.by_page[normalize(ep.page_title_fr)] = ep
        end
        if ep.page_title_en then
            Multi.by_page[normalize(ep.page_title_en)] = ep
        end

        ----------------------------------------------------
        -- Index par alias
        ----------------------------------------------------
        for _, alias in ipairs(ep.aliases) do
            alias = normalize(alias)
            Multi.by_alias[alias] = Multi.by_alias[alias] or {}
            table.insert(Multi.by_alias[alias], ep)
        end

        ----------------------------------------------------
        -- Index par série
        ----------------------------------------------------
        Multi.by_series[ep.series] = Multi.by_series[ep.series] or {}
        table.insert(Multi.by_series[ep.series], ep)

        ----------------------------------------------------
        -- Index par saison
        ----------------------------------------------------
        local key = ep.series .. "-" .. ep.season
        Multi.by_season[key] = Multi.by_season[key] or {}
        table.insert(Multi.by_season[key], ep)

        ----------------------------------------------------
        -- Ajout à la liste globale
        ----------------------------------------------------
        table.insert(Multi.episodes, ep)
    end
end

------------------------------------------------------------
-- 8. Fusion des séries
------------------------------------------------------------
append_series(SG1)
append_series(SGA)
append_series(SGU)

------------------------------------------------------------
-- 9. Cache final
------------------------------------------------------------
package.loaded["Module:Episode/MultiSeries"] = Multi
return Multi