Modul:Firestone: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
| Zeile 2: | Zeile 2: | ||
local M = {} | local M = {} | ||
-- ===== helpers ===== | -- ========= helpers ========= | ||
local function isempty(v) return v==nil or v=="" end | local function isempty(v) return v == nil or v == "" end | ||
local function norm(s) | local function norm(s) | ||
if s==nil then return "" end | if s == nil then return "" end | ||
s = mw.text.trim(tostring(s)) | s = mw.text.trim(tostring(s)) | ||
return mw.ustring.lower(s):gsub("%s+"," ") | return mw.ustring.lower(s):gsub("%s+"," ") | ||
end | end | ||
-- bevorzugt Parent-Args (typisch bei Vorlagen) | |||
local function getArgs(frame) | local function getArgs(frame) | ||
local p = frame:getParent() | |||
local | |||
local src = (p and p.args) or frame.args or {} | local src = (p and p.args) or frame.args or {} | ||
for k,v in pairs(src) do if v~=nil and v~="" then a[k]=mw.text.trim(tostring(v)) end end | local a = {} | ||
for k,v in pairs(src) do if v ~= nil and v ~= "" then a[k] = mw.text.trim(tostring(v)) end end | |||
return a | return a | ||
end | end | ||
local function pick_key(tbl, key) | local function pick_key(tbl, key) | ||
if type(tbl)~="table" then return nil end | if type(tbl) ~= "table" then return nil end | ||
if tbl[key]~=nil then return key end | if tbl[key] ~= nil then return key end | ||
local k2 = tostring(key) | local k2 = tostring(key) | ||
if tbl[k2]~=nil then return k2 end | if tbl[k2] ~= nil then return k2 end | ||
local kn = norm(k2) | local kn = norm(k2) | ||
for k,_ in pairs(tbl) do if norm(k)==kn then return k end end | for k,_ in pairs(tbl) do if norm(k) == kn then return k end end | ||
return nil | return nil | ||
end | end | ||
| Zeile 31: | Zeile 32: | ||
local cur = tbl | local cur = tbl | ||
for _,k in ipairs(path) do | for _,k in ipairs(path) do | ||
if type(cur)~="table" then return nil end | if type(cur) ~= "table" then return nil end | ||
local real = pick_key(cur, k); if not real then return nil end | local real = pick_key(cur, k); if not real then return nil end | ||
cur = cur[real] | cur = cur[real] | ||
| Zeile 38: | Zeile 39: | ||
end | end | ||
local function | local function fileTag(file, opts) -- [[File:...]] | ||
if isempty(file) then return "" end | if isempty(file) then return "" end | ||
local parts = {" | local parts = { "Datei:"..file } | ||
if opts and opts.size | if opts and opts.size then table.insert(parts, opts.size) end | ||
if opts and opts. | if opts and opts.param then table.insert(parts, opts.param) end -- z.B. "thumb|Text" | ||
return string.format("[[%s]]", table.concat(parts, "|")) | return string.format("[[%s]]", table.concat(parts, "|")) | ||
end | end | ||
-- ========= lazy loads ========= | |||
local I18N, EVENTS, HEROES | |||
local function i18n() | |||
if I18N then return I18N end | |||
for _,t in ipairs{ "Modul:HeroI18n", "Module:HeroI18n" } do | |||
local ok, data = pcall(mw.loadData, t) ; if ok and type(data)=="table" then I18N=data; return I18N end | |||
local ok2, mod = pcall(require, t) ; if ok2 and type(mod) =="table" then I18N=mod ; return I18N end | |||
local | |||
local function | |||
if | |||
for _,t in ipairs{ " | |||
local ok, data = pcall(mw.loadData, t) | |||
local ok2, mod = pcall(require, t) | |||
end | end | ||
I18N = { i18n={}, events={ names={}, sections={default={}}, infobox={}, links={}, phrases={}, unlocks={} } } | |||
return I18N | |||
end | end | ||
local function events() | local function events() | ||
if EVENTS then return EVENTS end | if EVENTS then return EVENTS end | ||
for _,t in ipairs{ " | for _,t in ipairs{ "Modul:EventData", "Module:EventData" } do | ||
local ok, data = pcall(mw.loadData, t) | local ok, data = pcall(mw.loadData, t) ; if ok and type(data)=="table" and type(data.events)=="table" then EVENTS=data.events; return EVENTS end | ||
local ok2, mod = pcall(require, t) ; if ok2 and type(mod) =="table" and type(mod.events)=="table" then EVENTS=mod.events ; return EVENTS end | |||
local | |||
if | |||
end | end | ||
EVENTS = {}; return EVENTS | EVENTS = {}; return EVENTS | ||
end | end | ||
local function heroes() | |||
local function | if HEROES then return HEROES end | ||
if | for _,t in ipairs{ "Modul:HeroData", "Module:HeroData" } do | ||
for _,t in ipairs{ " | local ok, data = pcall(mw.loadData, t) ; if ok and type(data)=="table" and type(data.heroes)=="table" then HEROES=data.heroes; return HEROES end | ||
local ok, data = pcall(mw.loadData, t) | local ok2, mod = pcall(require, t) ; if ok2 and type(mod) =="table" and type(mod.heroes)=="table" then HEROES=mod.heroes ; return HEROES end | ||
local ok2, mod = pcall(require, t) | |||
if ok2 and type(mod)=="table" then | |||
end | end | ||
HEROES = {}; return HEROES | |||
end | end | ||
-- ===== | -- ========= i18n helpers ========= | ||
local function | local function tr_simple(kind, key) | ||
if isempty( | if isempty(key) then return "" end | ||
local map = (i18n().i18n or {})[kind] or {} | local map = (i18n().i18n or {})[kind] or {} | ||
return map[norm( | return map[norm(key)] or key | ||
end | end | ||
local function tr_month( | local function tr_month(m) return tr_simple("month", m) end | ||
local function tr_duration(d) return tr_simple("duration", d) end | |||
return | |||
local function ev_label(evkey, which) | |||
local E = i18n().events or {} | |||
local spec = (E.sections and E.sections[norm(evkey)]) or {} | |||
local def = (E.sections and E.sections.default) or {} | |||
return (spec[which] or def[which] or "") | |||
end | end | ||
local function | local function ev_name(evkey) | ||
local names = (i18n().events or {}).names or {} | local names = (i18n().events or {}).names or {} | ||
return names[norm(evkey)] or evkey | return names[norm(evkey)] or evkey | ||
end | end | ||
local function | -- ========= event core ========= | ||
local | local function get_event(evkey) | ||
local | local evs = events() | ||
local real = pick_key(evs, evkey) | |||
return real and evs[real] or nil, real or evkey | |||
end | end | ||
local function | -- plain field with built-in translations for exactly the keys, | ||
local map = ((i18n().events or {}).infobox or {}).type or {} | -- die du in der Vorlage verwendest | ||
local function event_field(ev, key, evkey) | |||
if key == "banner" then return ev.banner or "" | |||
elseif key == "type" then | |||
local t = ev.type or "" | |||
local map = ((i18n().events or {}).infobox or {}).type or {} | |||
return map[norm(t)] or t | |||
elseif key == "month" then | |||
return tr_month(ev.month or ev.date or "") | |||
return | elseif key == "duration" then | ||
return tr_duration(ev.duration or "") | |||
elseif key == "character_level_10" then | |||
return ((i18n().events or {}).unlocks or {}).character_level_10 or "Level 10" | |||
elseif key == "currency" then | |||
return ev_label(evkey, "currency") | |||
elseif key == "currencies" then | |||
return ev_label(evkey, "currencies") | |||
elseif key == "ex_shop" or key=="shopname" or key=="fullname" or key=="shortname" | |||
or key=="currency_exchange" or key=="avatar_exchange" or key=="name" or key=="eventname" then | |||
local k = key == "eventname" and "name" or key | |||
return ev_label(evkey, k) | |||
else | else | ||
return | -- generischer Pfad (falls du mal Werte direkt aus EventData brauchst) | ||
return tostring(ev[key] or "") | |||
end | end | ||
end | end | ||
local function | -- ==/=== Überschriften == | ||
if isempty( | local function htag(level, text) | ||
local | if isempty(text) then return "" end | ||
local eq = level==3 and "===" or "==" | |||
return string.format("%s %s %s", eq, text, eq) | |||
end | end | ||
local function | -- [[File:...|thumb|...]] | ||
local function event_file(ev, evkey, which) | |||
if which=="deco" then | |||
local file = ev.images and ev.images.deco or "" | |||
local legend = ev_label(evkey, "deco") | |||
local | return fileTag(file, { param = "thumb|"..legend }) | ||
return ( | elseif which=="fullname" then | ||
local file = ev.images and ev.images.fullname or "" | |||
local legend = ev_label(evkey, "fullname") | |||
return fileTag(file, { param = "thumb|"..legend }) | |||
elseif which=="banner" then | |||
return fileTag(ev.banner, { param="thumb" }) | |||
end | end | ||
return | return "" | ||
end | end | ||
-- | -- Links, z.B. [[Calendar Events|Kalenderevent]] | ||
local function | local function event_link(ev, evkey, which) | ||
local | if which=="type" then | ||
local page = ((i18n().events or {}).links or {}).type or "Calendar Events" | |||
local label= event_field(ev, "type", evkey) | |||
return string.format("[[%s|%s]]", page, label) | |||
end | |||
return "" | |||
end | end | ||
local function | -- History-List bullets | ||
local H = ev.history or {} | local function event_history(ev) | ||
local H = ev.history or {}; if #H==0 then return "" end | |||
local | local alt_gp = ((i18n().events or {}).phrases or {}).alt_platform or "auf Google Play" | ||
local t = {} | |||
for _,h in ipairs(H) do | for _,h in ipairs(H) do | ||
local | local line = string.format("* %s: %s bis %s", tostring(h.year or ""), tostring(h.start or ""), tostring(h["end"] or "")) | ||
if h.alt_platform | if h.alt_platform then | ||
line = line .. string.format(" (%s %s)", tostring(h.alt_platform), alt_gp) | |||
end | end | ||
table.insert( | table.insert(t, line) | ||
end | end | ||
return table.concat( | return table.concat(t, "\n") | ||
end | end | ||
local function | -- Avatars: alle Jahre in einem Rutsch | ||
local function event_avatars(ev, evkey) | |||
local AV = ev.avatars or {} | local AV = ev.avatars or {} | ||
local token_icon = ev.currency and ev.currency.icon or "" | |||
local token_name = event_field(ev, "currencies", evkey) | |||
local out = {} | |||
local years = {} | local years = {} | ||
for y,_ in pairs(AV) do table.insert(years, y) end | for y,_ in pairs(AV) do table.insert(years, y) end | ||
table.sort(years) | table.sort(years) | ||
for _,year in ipairs(years) do | for _,year in ipairs(years) do | ||
table.insert(out, string.format("==== %s ====", year)) | |||
table.insert(out, string.format("==== % | table.insert(out, '{| class="article-table" style="font-size:14px;"') | ||
table.insert(out, '{| class="article-table" style="font-size: 14px;"') | table.insert(out, '! colspan="2" | Avatar\n! Preis') | ||
table.insert(out, '!colspan="2" | Avatar\n!Preis') | for _,it in ipairs(AV[year]) do | ||
for _,it in ipairs( | |||
table.insert(out, "|-") | table.insert(out, "|-") | ||
table.insert(out, | table.insert(out, string.format("|%s || %s || %s %s %s", | ||
fileTag(it.file, { size="50px" }), | |||
it.title or "", | |||
fileTag(token_icon, { size="25px" }), | |||
tostring(it.cost or 0), | |||
token_name | |||
)) | |||
) | |||
end | end | ||
table.insert(out, "|}") | table.insert(out, "|}") | ||
end | end | ||
return table.concat(out, "\n") | return table.concat(out, "\n") | ||
end | end | ||
local function | -- Exchange-Tabelle (kurz & robust) | ||
local | local function event_exchange(ev, evkey) | ||
local | local ex = ev.exchange or {} | ||
local token = ev.currency or {} | |||
local token_icon = token.icon or "" | |||
local token_name = event_field(ev, "currencies", evkey) | |||
local | local function table_for(list, header) | ||
if type(list) ~= "table" or #list==0 then return "" end | |||
table.insert( | local t = {} | ||
table.insert( | table.insert(t, '{| class="article-table" style="font-size:14px;"') | ||
table.insert(t, "! "..header.." !! Preis !! Limit") | |||
for _,it in ipairs(list) do | |||
table.insert(t, "|-") | |||
local offer = string.format("[[Datei:%s|30px]] %s", it.icon or "", it.title or "") | |||
if it.range then offer = "level "..it.range..": "..offer end | |||
table.insert(t, string.format("| %s || %s %s %s || %s", | |||
offer, | |||
fileTag(token_icon, { size="25px" }), | |||
tostring(it.price or 0), | |||
token_name, | |||
tostring(it.limit or "") | |||
)) | |||
end | |||
table.insert(t, "|}") | |||
return table.concat(t, "\n") | |||
end | end | ||
local | local parts = {} | ||
if ex.chests_by_level then table.insert(parts, table_for(ex.chests_by_level, "Angebot")) end | |||
if ex.chests_by_stars then table.insert(parts, table_for(ex.chests_by_stars, "Angebot")) end | |||
if ex.chests_by_oracle then table.insert(parts, table_for(ex.chests_by_oracle, "Angebot")) end | |||
if ex.currencies then table.insert(parts, table_for(ex.currencies, "Angebot")) end | |||
return table.concat(parts, "\n") | |||
return table.concat( | |||
end | end | ||
local function | -- Shop-Angebote | ||
local list = | local function event_offers(ev, evkey, which) | ||
if type(list)~="table" or #list==0 then return "" end | local list = (ev.shop or {})[which] | ||
local | if type(list) ~= "table" or #list==0 then return "" end | ||
local token_icon = ev.currency and ev.currency.icon or "" | |||
local token_name = event_field(ev, "currencies", evkey) | |||
local t = {} | |||
table.insert(t, '{| class="article-table" style="font-size:14px;"') | |||
table.insert(t, "! colspan=\"2\" style=\"text-align:center\" | ") | |||
table.insert(t, "|-") | |||
for _,it in ipairs(list) do | |||
table.insert(t, string.format("| %s || %s %s %s", | |||
"''"..(it.name or "").."''<br />"..fileTag(it.image, { size="x50px" }), | |||
fileTag(token_icon, { size="30px" }), | |||
tostring(it.token or 0), | |||
token_name | |||
)) | |||
table.insert(t, "|-") | |||
end | end | ||
return | table.insert(t, "|}") | ||
return table.concat(t, "\n") | |||
end | end | ||
-- ===== | -- ===== main dispatcher for Event ===== | ||
local function | local function dispatch_event(args) | ||
local | local evkey = args[2]; if isempty(evkey) then return "" end | ||
local ev = | local ev, realkey = get_event(evkey); if not ev then return "" end | ||
local a3, a4 = args[3], args[4] | local a3, a4 = args[3], args[4] | ||
if isempty(a3) or a3=="eventname" then | |||
if isempty(a3) | return ev_name(realkey) | ||
return | |||
end | end | ||
-- | -- plain fields & labels | ||
if a3==" | if a3=="banner" or a3=="type" or a3=="month" or a3=="duration" | ||
return | or a3=="character_level_10" | ||
or a3=="currency" or a3=="currencies" | |||
or a3=="ex_shop" or a3=="fullname" or a3=="shortname" | |||
or a3=="shopname" or a3=="currency_exchange" or a3=="avatar_exchange" | |||
or a3=="name" then | |||
return event_field(ev, a3, realkey) | |||
end | end | ||
-- | -- file / link / headings | ||
if a3=="link" | if a3=="file" then return event_file(ev, realkey, a4 or "") | ||
elseif a3=="link" then return event_link(ev, realkey, a4 or "") | |||
end | elseif a3=="h2" then return htag(2, ev_label(realkey, a4 or "")) | ||
elseif a3=="h3" then return htag(3, ev_label(realkey, a4 or "")) end | |||
-- | -- composed blocks | ||
if a3=="history" then | if a3=="history" then return event_history(ev) | ||
elseif a3=="avatars" then return event_avatars(ev, realkey) | |||
elseif a3=="avatars" then | elseif a3=="exchange" then return event_exchange(ev, realkey) | ||
elseif a3=="offers" and (a4=="start" or a4=="more") then | |||
elseif a3=="exchange" then | return event_offers(ev, realkey, (a4=="start") and "initial" or "after") | ||
elseif a3=="offers" | |||
return | |||
end | end | ||
return "" | |||
end | |||
-- ===== hero (nur für Vollständigkeit deiner Wünsche) ===== | |||
local function dispatch_hero(args) | |||
local name = args[2]; if isempty(name) then return "" end | |||
local H = heroes() | |||
local real = pick_key(H, name); if not real then return "" end | |||
local h = H[real] | |||
local path, i = {}, 3 | local path, i = {}, 3 | ||
while args[i] do table.insert(path, args[i]); i=i+1 end | while args[i] do table.insert(path, args[i]); i=i+1 end | ||
local v = deep_get( | local v = deep_get(h, path) | ||
return tostring(v or "") | return tostring(v or "") | ||
end | end | ||
| Zeile 398: | Zeile 322: | ||
function M.main(frame) | function M.main(frame) | ||
local a = getArgs(frame) | local a = getArgs(frame) | ||
for i=1,10 do a[i] = a[i] and tostring(a[i]) or nil end | |||
for i=1, | |||
local dom = a[1] and norm(a[1]) or "" | local dom = a[1] and norm(a[1]) or "" | ||
if dom=="event" then return dispatch_event(a) | |||
if dom=="event" then | elseif dom=="hero" then return dispatch_hero(a) | ||
else return "" end | |||
else | |||
end | end | ||
return M | return M | ||
Version vom 20. Oktober 2025, 18:55 Uhr
Die Dokumentation für dieses Modul kann unter Modul:Firestone/Doku erstellt werden
-- Modul:Firestone
local M = {}
-- ========= helpers =========
local function isempty(v) return v == nil or v == "" end
local function norm(s)
if s == nil then return "" end
s = mw.text.trim(tostring(s))
return mw.ustring.lower(s):gsub("%s+"," ")
end
-- bevorzugt Parent-Args (typisch bei Vorlagen)
local function getArgs(frame)
local p = frame:getParent()
local src = (p and p.args) or frame.args or {}
local a = {}
for k,v in pairs(src) do if v ~= nil and v ~= "" then a[k] = mw.text.trim(tostring(v)) end end
return a
end
local function pick_key(tbl, key)
if type(tbl) ~= "table" then return nil end
if tbl[key] ~= nil then return key end
local k2 = tostring(key)
if tbl[k2] ~= nil then return k2 end
local kn = norm(k2)
for k,_ in pairs(tbl) do if norm(k) == kn then return k end end
return nil
end
local function deep_get(tbl, path)
local cur = tbl
for _,k in ipairs(path) do
if type(cur) ~= "table" then return nil end
local real = pick_key(cur, k); if not real then return nil end
cur = cur[real]
end
return cur
end
local function fileTag(file, opts) -- [[File:...]]
if isempty(file) then return "" end
local parts = { "Datei:"..file }
if opts and opts.size then table.insert(parts, opts.size) end
if opts and opts.param then table.insert(parts, opts.param) end -- z.B. "thumb|Text"
return string.format("[[%s]]", table.concat(parts, "|"))
end
-- ========= lazy loads =========
local I18N, EVENTS, HEROES
local function i18n()
if I18N then return I18N end
for _,t in ipairs{ "Modul:HeroI18n", "Module:HeroI18n" } do
local ok, data = pcall(mw.loadData, t) ; if ok and type(data)=="table" then I18N=data; return I18N end
local ok2, mod = pcall(require, t) ; if ok2 and type(mod) =="table" then I18N=mod ; return I18N end
end
I18N = { i18n={}, events={ names={}, sections={default={}}, infobox={}, links={}, phrases={}, unlocks={} } }
return I18N
end
local function events()
if EVENTS then return EVENTS end
for _,t in ipairs{ "Modul:EventData", "Module:EventData" } do
local ok, data = pcall(mw.loadData, t) ; if ok and type(data)=="table" and type(data.events)=="table" then EVENTS=data.events; return EVENTS end
local ok2, mod = pcall(require, t) ; if ok2 and type(mod) =="table" and type(mod.events)=="table" then EVENTS=mod.events ; return EVENTS end
end
EVENTS = {}; return EVENTS
end
local function heroes()
if HEROES then return HEROES end
for _,t in ipairs{ "Modul:HeroData", "Module:HeroData" } do
local ok, data = pcall(mw.loadData, t) ; if ok and type(data)=="table" and type(data.heroes)=="table" then HEROES=data.heroes; return HEROES end
local ok2, mod = pcall(require, t) ; if ok2 and type(mod) =="table" and type(mod.heroes)=="table" then HEROES=mod.heroes ; return HEROES end
end
HEROES = {}; return HEROES
end
-- ========= i18n helpers =========
local function tr_simple(kind, key)
if isempty(key) then return "" end
local map = (i18n().i18n or {})[kind] or {}
return map[norm(key)] or key
end
local function tr_month(m) return tr_simple("month", m) end
local function tr_duration(d) return tr_simple("duration", d) end
local function ev_label(evkey, which)
local E = i18n().events or {}
local spec = (E.sections and E.sections[norm(evkey)]) or {}
local def = (E.sections and E.sections.default) or {}
return (spec[which] or def[which] or "")
end
local function ev_name(evkey)
local names = (i18n().events or {}).names or {}
return names[norm(evkey)] or evkey
end
-- ========= event core =========
local function get_event(evkey)
local evs = events()
local real = pick_key(evs, evkey)
return real and evs[real] or nil, real or evkey
end
-- plain field with built-in translations for exactly the keys,
-- die du in der Vorlage verwendest
local function event_field(ev, key, evkey)
if key == "banner" then return ev.banner or ""
elseif key == "type" then
local t = ev.type or ""
local map = ((i18n().events or {}).infobox or {}).type or {}
return map[norm(t)] or t
elseif key == "month" then
return tr_month(ev.month or ev.date or "")
elseif key == "duration" then
return tr_duration(ev.duration or "")
elseif key == "character_level_10" then
return ((i18n().events or {}).unlocks or {}).character_level_10 or "Level 10"
elseif key == "currency" then
return ev_label(evkey, "currency")
elseif key == "currencies" then
return ev_label(evkey, "currencies")
elseif key == "ex_shop" or key=="shopname" or key=="fullname" or key=="shortname"
or key=="currency_exchange" or key=="avatar_exchange" or key=="name" or key=="eventname" then
local k = key == "eventname" and "name" or key
return ev_label(evkey, k)
else
-- generischer Pfad (falls du mal Werte direkt aus EventData brauchst)
return tostring(ev[key] or "")
end
end
-- ==/=== Überschriften ==
local function htag(level, text)
if isempty(text) then return "" end
local eq = level==3 and "===" or "=="
return string.format("%s %s %s", eq, text, eq)
end
-- [[File:...|thumb|...]]
local function event_file(ev, evkey, which)
if which=="deco" then
local file = ev.images and ev.images.deco or ""
local legend = ev_label(evkey, "deco")
return fileTag(file, { param = "thumb|"..legend })
elseif which=="fullname" then
local file = ev.images and ev.images.fullname or ""
local legend = ev_label(evkey, "fullname")
return fileTag(file, { param = "thumb|"..legend })
elseif which=="banner" then
return fileTag(ev.banner, { param="thumb" })
end
return ""
end
-- Links, z.B. [[Calendar Events|Kalenderevent]]
local function event_link(ev, evkey, which)
if which=="type" then
local page = ((i18n().events or {}).links or {}).type or "Calendar Events"
local label= event_field(ev, "type", evkey)
return string.format("[[%s|%s]]", page, label)
end
return ""
end
-- History-List bullets
local function event_history(ev)
local H = ev.history or {}; if #H==0 then return "" end
local alt_gp = ((i18n().events or {}).phrases or {}).alt_platform or "auf Google Play"
local t = {}
for _,h in ipairs(H) do
local line = string.format("* %s: %s bis %s", tostring(h.year or ""), tostring(h.start or ""), tostring(h["end"] or ""))
if h.alt_platform then
line = line .. string.format(" (%s %s)", tostring(h.alt_platform), alt_gp)
end
table.insert(t, line)
end
return table.concat(t, "\n")
end
-- Avatars: alle Jahre in einem Rutsch
local function event_avatars(ev, evkey)
local AV = ev.avatars or {}
local token_icon = ev.currency and ev.currency.icon or ""
local token_name = event_field(ev, "currencies", evkey)
local out = {}
local years = {}
for y,_ in pairs(AV) do table.insert(years, y) end
table.sort(years)
for _,year in ipairs(years) do
table.insert(out, string.format("==== %s ====", year))
table.insert(out, '{| class="article-table" style="font-size:14px;"')
table.insert(out, '! colspan="2" | Avatar\n! Preis')
for _,it in ipairs(AV[year]) do
table.insert(out, "|-")
table.insert(out, string.format("|%s || %s || %s %s %s",
fileTag(it.file, { size="50px" }),
it.title or "",
fileTag(token_icon, { size="25px" }),
tostring(it.cost or 0),
token_name
))
end
table.insert(out, "|}")
end
return table.concat(out, "\n")
end
-- Exchange-Tabelle (kurz & robust)
local function event_exchange(ev, evkey)
local ex = ev.exchange or {}
local token = ev.currency or {}
local token_icon = token.icon or ""
local token_name = event_field(ev, "currencies", evkey)
local function table_for(list, header)
if type(list) ~= "table" or #list==0 then return "" end
local t = {}
table.insert(t, '{| class="article-table" style="font-size:14px;"')
table.insert(t, "! "..header.." !! Preis !! Limit")
for _,it in ipairs(list) do
table.insert(t, "|-")
local offer = string.format("[[Datei:%s|30px]] %s", it.icon or "", it.title or "")
if it.range then offer = "level "..it.range..": "..offer end
table.insert(t, string.format("| %s || %s %s %s || %s",
offer,
fileTag(token_icon, { size="25px" }),
tostring(it.price or 0),
token_name,
tostring(it.limit or "")
))
end
table.insert(t, "|}")
return table.concat(t, "\n")
end
local parts = {}
if ex.chests_by_level then table.insert(parts, table_for(ex.chests_by_level, "Angebot")) end
if ex.chests_by_stars then table.insert(parts, table_for(ex.chests_by_stars, "Angebot")) end
if ex.chests_by_oracle then table.insert(parts, table_for(ex.chests_by_oracle, "Angebot")) end
if ex.currencies then table.insert(parts, table_for(ex.currencies, "Angebot")) end
return table.concat(parts, "\n")
end
-- Shop-Angebote
local function event_offers(ev, evkey, which)
local list = (ev.shop or {})[which]
if type(list) ~= "table" or #list==0 then return "" end
local token_icon = ev.currency and ev.currency.icon or ""
local token_name = event_field(ev, "currencies", evkey)
local t = {}
table.insert(t, '{| class="article-table" style="font-size:14px;"')
table.insert(t, "! colspan=\"2\" style=\"text-align:center\" | ")
table.insert(t, "|-")
for _,it in ipairs(list) do
table.insert(t, string.format("| %s || %s %s %s",
"''"..(it.name or "").."''<br />"..fileTag(it.image, { size="x50px" }),
fileTag(token_icon, { size="30px" }),
tostring(it.token or 0),
token_name
))
table.insert(t, "|-")
end
table.insert(t, "|}")
return table.concat(t, "\n")
end
-- ===== main dispatcher for Event =====
local function dispatch_event(args)
local evkey = args[2]; if isempty(evkey) then return "" end
local ev, realkey = get_event(evkey); if not ev then return "" end
local a3, a4 = args[3], args[4]
if isempty(a3) or a3=="eventname" then
return ev_name(realkey)
end
-- plain fields & labels
if a3=="banner" or a3=="type" or a3=="month" or a3=="duration"
or a3=="character_level_10"
or a3=="currency" or a3=="currencies"
or a3=="ex_shop" or a3=="fullname" or a3=="shortname"
or a3=="shopname" or a3=="currency_exchange" or a3=="avatar_exchange"
or a3=="name" then
return event_field(ev, a3, realkey)
end
-- file / link / headings
if a3=="file" then return event_file(ev, realkey, a4 or "")
elseif a3=="link" then return event_link(ev, realkey, a4 or "")
elseif a3=="h2" then return htag(2, ev_label(realkey, a4 or ""))
elseif a3=="h3" then return htag(3, ev_label(realkey, a4 or "")) end
-- composed blocks
if a3=="history" then return event_history(ev)
elseif a3=="avatars" then return event_avatars(ev, realkey)
elseif a3=="exchange" then return event_exchange(ev, realkey)
elseif a3=="offers" and (a4=="start" or a4=="more") then
return event_offers(ev, realkey, (a4=="start") and "initial" or "after")
end
return ""
end
-- ===== hero (nur für Vollständigkeit deiner Wünsche) =====
local function dispatch_hero(args)
local name = args[2]; if isempty(name) then return "" end
local H = heroes()
local real = pick_key(H, name); if not real then return "" end
local h = H[real]
local path, i = {}, 3
while args[i] do table.insert(path, args[i]); i=i+1 end
local v = deep_get(h, path)
return tostring(v or "")
end
-- ===== main =====
function M.main(frame)
local a = getArgs(frame)
for i=1,10 do a[i] = a[i] and tostring(a[i]) or nil end
local dom = a[1] and norm(a[1]) or ""
if dom=="event" then return dispatch_event(a)
elseif dom=="hero" then return dispatch_hero(a)
else return "" end
end
return M