<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://fs.playcodex.de/index.php?action=history&amp;feed=atom&amp;title=Modul%3AFirestone%2FEvent</id>
	<title>Modul:Firestone/Event - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://fs.playcodex.de/index.php?action=history&amp;feed=atom&amp;title=Modul%3AFirestone%2FEvent"/>
	<link rel="alternate" type="text/html" href="https://fs.playcodex.de/index.php?title=Modul:Firestone/Event&amp;action=history"/>
	<updated>2026-04-20T17:44:08Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Firestone Idle Rpg Wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://fs.playcodex.de/index.php?title=Modul:Firestone/Event&amp;diff=5&amp;oldid=prev</id>
		<title>Webmaster: Die Seite wurde neu angelegt: „-- Modul:Firestone/Event local Util = require(&#039;Modul:Firestone/Util&#039;) local I18n = require(&#039;Modul:Firestone/I18n&#039;)  local E = {}  local COL_OFFER, COL_PRICE, COL_LIMIT = &quot;50%&quot;, &quot;25%&quot;, &quot;25%&quot; local DAY = Util.DAY or 86400  -- alle Event-Daten zusammenführen (calendar + mini + special) local function loadTable(name)     local ok, data = pcall(mw.loadData, name)     if ok and type(data) == &#039;table&#039; then return data end     ok, data = pcall(require, name)…“</title>
		<link rel="alternate" type="text/html" href="https://fs.playcodex.de/index.php?title=Modul:Firestone/Event&amp;diff=5&amp;oldid=prev"/>
		<updated>2025-11-05T10:18:39Z</updated>

		<summary type="html">&lt;p&gt;Die Seite wurde neu angelegt: „-- Modul:Firestone/Event local Util = require(&amp;#039;Modul:Firestone/Util&amp;#039;) local I18n = require(&amp;#039;Modul:Firestone/I18n&amp;#039;)  local E = {}  local COL_OFFER, COL_PRICE, COL_LIMIT = &amp;quot;50%&amp;quot;, &amp;quot;25%&amp;quot;, &amp;quot;25%&amp;quot; local DAY = Util.DAY or 86400  -- alle Event-Daten zusammenführen (calendar + mini + special) local function loadTable(name)     local ok, data = pcall(mw.loadData, name)     if ok and type(data) == &amp;#039;table&amp;#039; then return data end     ok, data = pcall(require, name)…“&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- Modul:Firestone/Event&lt;br /&gt;
local Util = require(&amp;#039;Modul:Firestone/Util&amp;#039;)&lt;br /&gt;
local I18n = require(&amp;#039;Modul:Firestone/I18n&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
local E = {}&lt;br /&gt;
&lt;br /&gt;
local COL_OFFER, COL_PRICE, COL_LIMIT = &amp;quot;50%&amp;quot;, &amp;quot;25%&amp;quot;, &amp;quot;25%&amp;quot;&lt;br /&gt;
local DAY = Util.DAY or 86400&lt;br /&gt;
&lt;br /&gt;
-- alle Event-Daten zusammenführen (calendar + mini + special)&lt;br /&gt;
local function loadTable(name)&lt;br /&gt;
    local ok, data = pcall(mw.loadData, name)&lt;br /&gt;
    if ok and type(data) == &amp;#039;table&amp;#039; then return data end&lt;br /&gt;
    ok, data = pcall(require, name)&lt;br /&gt;
    if ok and type(data) == &amp;#039;table&amp;#039; then return data end&lt;br /&gt;
    return {}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function mergedEvents()&lt;br /&gt;
    local all = {}&lt;br /&gt;
    local sources = {&lt;br /&gt;
        &amp;#039;Modul:Firestone/Data/Events&amp;#039;,&lt;br /&gt;
        &amp;#039;Modul:Firestone/Data/Events/Mini&amp;#039;,&lt;br /&gt;
        &amp;#039;Modul:Firestone/Data/Events/Special&amp;#039;,&lt;br /&gt;
    }&lt;br /&gt;
    for _,name in ipairs(sources) do&lt;br /&gt;
        local t = loadTable(name)&lt;br /&gt;
        for k,v in pairs(t) do&lt;br /&gt;
            all[k] = v&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return all&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local EVENTS = mergedEvents()&lt;br /&gt;
local FRAME&lt;br /&gt;
&lt;br /&gt;
-- i18n helpers&lt;br /&gt;
local function evI18n()&lt;br /&gt;
    return (I18n.get().events or {})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function ev_label(evkey, which)&lt;br /&gt;
    local Eii = evI18n()&lt;br /&gt;
    local spec = (Eii.sections and Eii.sections[Util.norm(evkey)]) or {}&lt;br /&gt;
    local def  = (Eii.sections and Eii.sections.default) or {}&lt;br /&gt;
    return (spec[which] or def[which] or &amp;quot;&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function ev_name(evkey)&lt;br /&gt;
    local names = evI18n().names or {}&lt;br /&gt;
    return names[Util.norm(evkey)] or evkey&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function header_labels(evkey)&lt;br /&gt;
    return ev_label(evkey, &amp;quot;offer&amp;quot;), ev_label(evkey, &amp;quot;price&amp;quot;), ev_label(evkey, &amp;quot;limit&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- auto-translation wie vorher&lt;br /&gt;
local function autotr(key_name, value)&lt;br /&gt;
    if type(value) ~= &amp;quot;string&amp;quot; then return value end&lt;br /&gt;
    local k = Util.norm(key_name)&lt;br /&gt;
    local i18 = I18n.get()&lt;br /&gt;
    local m1 = (i18.i18n or {})[k]&lt;br /&gt;
    local v  = m1 and m1[Util.norm(value)]&lt;br /&gt;
    if v then return v end&lt;br /&gt;
    if k == &amp;quot;type&amp;quot; then&lt;br /&gt;
        local m2 = (((i18.events or {}).infobox) or {}).type or {}&lt;br /&gt;
        return m2[Util.norm(value)] or value&lt;br /&gt;
    end&lt;br /&gt;
    return value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function ev_notice_icon_wikitext(ev)&lt;br /&gt;
    local file = ev.currency and ev.currency.icon&lt;br /&gt;
    if not file or file == &amp;quot;&amp;quot; then return &amp;quot;&amp;quot; end&lt;br /&gt;
    local img = Util.fileTag(file, { size = &amp;quot;24px&amp;quot;, param = &amp;quot;frameless|link=&amp;quot; })&lt;br /&gt;
    return &amp;#039;&amp;lt;span class=&amp;quot;fs-ic&amp;quot;&amp;gt;&amp;#039; .. img .. &amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function ev_pagelink(ev, evkey, label)&lt;br /&gt;
    local page = ev.page&lt;br /&gt;
    if page and page ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        return string.format(&amp;quot;[[%s|%s]]&amp;quot;, page, label)&lt;br /&gt;
    end&lt;br /&gt;
    return label&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Zahlenformatierung (verkürzt, aber wie vorher)&lt;br /&gt;
local function parse_sci(v)&lt;br /&gt;
    if type(v) == &amp;quot;number&amp;quot; then return v end&lt;br /&gt;
    if type(v) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        local a,e = v:match(&amp;quot;^%s*([%d%.]+)[eE]([%+%-]?%d+)%s*$&amp;quot;)&lt;br /&gt;
        if a and e then return (tonumber(a) or 0) * 10^(tonumber(e) or 0) end&lt;br /&gt;
        local n = tonumber(v); if n then return n end&lt;br /&gt;
    end&lt;br /&gt;
    return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function i18n_big_units()&lt;br /&gt;
    local N = (I18n.get().numbers or {})&lt;br /&gt;
    return {&lt;br /&gt;
        {1e12, N.trillion_sing,  N.trillion_plur},&lt;br /&gt;
        {1e9,  N.billion_sing,   N.billion_plur},&lt;br /&gt;
        {1e6,  N.million_sing,   N.million_plur},&lt;br /&gt;
        {1e3,  N.thousand_sing,  N.thousand_plur},&lt;br /&gt;
    }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function format_big(v)&lt;br /&gt;
    local n = parse_sci(v); if not n then return tostring(v or &amp;quot;&amp;quot;) end&lt;br /&gt;
    for _,u in ipairs(i18n_big_units()) do&lt;br /&gt;
        local base, sing, plur = u[1], u[2], u[3]&lt;br /&gt;
        if base and sing and plur and n &amp;gt;= base and math.floor(n % base) == 0 then&lt;br /&gt;
            local q = math.floor(n / base)&lt;br /&gt;
            return string.format(&amp;quot;%d %s&amp;quot;, q, (q==1) and sing or plur)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return tostring(n)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function ref_gear_power(v)&lt;br /&gt;
    if Util.isEmpty(v) then return &amp;quot;&amp;quot; end&lt;br /&gt;
    local phr = (evI18n().phrases or {}).req_gear_power&lt;br /&gt;
    if Util.isEmpty(phr) then return &amp;quot;&amp;quot; end&lt;br /&gt;
    local name = &amp;quot;gear-&amp;quot; .. tostring(v):gsub(&amp;quot;%s&amp;quot;,&amp;quot;&amp;quot;)&lt;br /&gt;
    return string.format(&amp;#039;&amp;lt;ref name=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/ref&amp;gt;&amp;#039;, name, (phr:gsub(&amp;quot;$1&amp;quot;, format_big(v))))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function htag(level, text)&lt;br /&gt;
    if Util.isEmpty(text) then return &amp;quot;&amp;quot; end&lt;br /&gt;
    local eq = level==3 and &amp;quot;===&amp;quot; or &amp;quot;==&amp;quot;&lt;br /&gt;
    return string.format(&amp;quot;%s %s %s&amp;quot;, eq, text, eq)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function event_file(ev, evkey, which)&lt;br /&gt;
    if which==&amp;quot;deco&amp;quot; then&lt;br /&gt;
        local file   = ev.images and ev.images.deco or &amp;quot;&amp;quot;&lt;br /&gt;
        local legend = ev_label(evkey, &amp;quot;deco&amp;quot;)&lt;br /&gt;
        return Util.fileTag(file, { param = &amp;quot;thumb|&amp;quot;..legend })&lt;br /&gt;
    elseif which==&amp;quot;fullname&amp;quot; then&lt;br /&gt;
        local file   = ev.images and ev.images.fullname or &amp;quot;&amp;quot;&lt;br /&gt;
        local legend = ev_label(evkey, &amp;quot;fullname&amp;quot;)&lt;br /&gt;
        return Util.fileTag(file, { param = &amp;quot;thumb|&amp;quot;..legend })&lt;br /&gt;
    elseif which==&amp;quot;ex_shop&amp;quot; then&lt;br /&gt;
        local file   = ev.images and ev.images.ex_shop or &amp;quot;&amp;quot;&lt;br /&gt;
        local legend = ev_label(evkey, &amp;quot;ex_shop&amp;quot;)&lt;br /&gt;
        return Util.fileTag(file, { param = &amp;quot;thumb|&amp;quot;..legend })&lt;br /&gt;
    elseif which==&amp;quot;banner&amp;quot; then&lt;br /&gt;
        return Util.fileTag(ev.banner, { param=&amp;quot;thumb&amp;quot; })&lt;br /&gt;
    end&lt;br /&gt;
    return &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function event_link(ev, evkey, which)&lt;br /&gt;
    if which==&amp;quot;type&amp;quot; then&lt;br /&gt;
        local Eii = evI18n()&lt;br /&gt;
        local page  = (Eii.links and Eii.links.type and Eii.links.type[ev.type or &amp;quot;&amp;quot;])&lt;br /&gt;
                       or (Eii.links and Eii.links.type) or &amp;quot;Calendar Events&amp;quot;&lt;br /&gt;
        local map   = (Eii.infobox and Eii.infobox.type) or {}&lt;br /&gt;
        local label = map[Util.norm(ev.type or &amp;quot;&amp;quot;)] or (ev.type or &amp;quot;&amp;quot;)&lt;br /&gt;
        return string.format(&amp;quot;[[%s|%s]]&amp;quot;, page, label)&lt;br /&gt;
    end&lt;br /&gt;
    return &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function event_history(ev)&lt;br /&gt;
    local H = ev.history or {}&lt;br /&gt;
    if not Util.hasItems(H) then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local alt_gp = (evI18n().phrases or {}).alt_platform or &amp;quot;auf Google Play&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local function fmt_range_de(s1, s2)&lt;br /&gt;
        return string.format(&amp;quot;%s bis %s&amp;quot;, Util.formatDateDe(s1), Util.formatDateDe(s2))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local function fmt_alt_platform(val)&lt;br /&gt;
        local y1,m1,d1,y2,m2,d2 =&lt;br /&gt;
            tostring(val or &amp;quot;&amp;quot;):match(&amp;quot;^%s*(%d%d%d%d)%-(%d%d)%-(%d%d)%s+bis%s+(%d%d%d%d)%-(%d%d)%-(%d%d)%s*$&amp;quot;)&lt;br /&gt;
        if y1 then&lt;br /&gt;
            return fmt_range_de(y1..&amp;quot;-&amp;quot;..m1..&amp;quot;-&amp;quot;..d1, y2..&amp;quot;-&amp;quot;..m2..&amp;quot;-&amp;quot;..d2)&lt;br /&gt;
        end&lt;br /&gt;
        return tostring(val or &amp;quot;&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local out = {}&lt;br /&gt;
    for _,h in ipairs(H) do&lt;br /&gt;
        local year = tostring(h.year or &amp;quot;&amp;quot;)&lt;br /&gt;
        local s    = h.start or &amp;quot;&amp;quot;&lt;br /&gt;
        local e    = h[&amp;quot;end&amp;quot;] or &amp;quot;&amp;quot;&lt;br /&gt;
        local line = string.format(&amp;quot;* %s: %s&amp;quot;, year, fmt_range_de(s, e))&lt;br /&gt;
        if h.alt_platform then&lt;br /&gt;
            line = line .. string.format(&amp;quot; (%s %s)&amp;quot;, fmt_alt_platform(h.alt_platform), alt_gp)&lt;br /&gt;
        end&lt;br /&gt;
        table.insert(out, line)&lt;br /&gt;
    end&lt;br /&gt;
    return table.concat(out, &amp;quot;\n&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function item_label(key, amount)&lt;br /&gt;
    local I = (I18n.get().items or {})[key] or {}&lt;br /&gt;
    local n = tonumber(amount or 1) or 1&lt;br /&gt;
    local txt = (n == 1) and (I.sing or key) or (I.plur or (I.sing or key))&lt;br /&gt;
    local disp = I.link and string.format(&amp;quot;[[%s|%s]]&amp;quot;, I.link, txt) or txt&lt;br /&gt;
    return string.format(&amp;quot;%d %s&amp;quot;, n, disp)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tabber_render_from_content(content)&lt;br /&gt;
    if FRAME and FRAME.extensionTag then&lt;br /&gt;
        return FRAME:extensionTag(&amp;#039;tabber&amp;#039;, content)&lt;br /&gt;
    end&lt;br /&gt;
    return &amp;quot;&amp;lt;tabber&amp;gt;\n&amp;quot; .. content .. &amp;quot;\n&amp;lt;/tabber&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function references_tag()&lt;br /&gt;
    if FRAME and FRAME.extensionTag then&lt;br /&gt;
        return FRAME:extensionTag(&amp;#039;references&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    return &amp;#039;&amp;lt;references /&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function build_tabber_content_for(list)&lt;br /&gt;
    local out = {}&lt;br /&gt;
    for _,it in ipairs(list) do&lt;br /&gt;
        local label   = Util.prettyRange(it.range or &amp;quot;&amp;quot;)&lt;br /&gt;
        local note    = ref_gear_power(it.req_gear_power)&lt;br /&gt;
        local content = string.format(&lt;br /&gt;
            &amp;quot;%s %s%s&amp;quot;,&lt;br /&gt;
            Util.fileTag(it.icon or &amp;quot;&amp;quot;, { size=&amp;quot;30px&amp;quot; }),&lt;br /&gt;
            (it.item and item_label(it.item, it.amount or 1)) or (it.title or &amp;quot;&amp;quot;),&lt;br /&gt;
            note&lt;br /&gt;
        )&lt;br /&gt;
        out[#out+1] = &amp;quot;|-|&amp;quot; .. label .. &amp;quot;=\n&amp;quot; .. content&lt;br /&gt;
    end&lt;br /&gt;
    return table.concat(out, &amp;quot;\n&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function group_label(kind)&lt;br /&gt;
    local G = (evI18n().group_labels or {})&lt;br /&gt;
    return G[kind] or kind&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function build_avatar_table(list, token_icon, token_name)&lt;br /&gt;
    local t = {}&lt;br /&gt;
    t[#t+1] = &amp;#039;{| class=&amp;quot;article-table&amp;quot; style=&amp;quot;font-size:14px;&amp;quot;&amp;#039;&lt;br /&gt;
    t[#t+1] = &amp;#039;! colspan=&amp;quot;2&amp;quot; | Avatar\n! Preis&amp;#039;&lt;br /&gt;
    for _,it in ipairs(list) do&lt;br /&gt;
        t[#t+1] = &amp;#039;|-&amp;#039;&lt;br /&gt;
        t[#t+1] = string.format(&lt;br /&gt;
            &amp;#039;| %s || %s || %s %s %s&amp;#039;,&lt;br /&gt;
            Util.fileTag(it.file,  { size=&amp;quot;50px&amp;quot; }),&lt;br /&gt;
            it.title or &amp;quot;&amp;quot;,&lt;br /&gt;
            Util.fileTag(token_icon, { size=&amp;quot;25px&amp;quot; }),&lt;br /&gt;
            tostring(it.cost or 0),&lt;br /&gt;
            token_name&lt;br /&gt;
        )&lt;br /&gt;
    end&lt;br /&gt;
    t[#t+1] = &amp;#039;|}&amp;#039;&lt;br /&gt;
    return table.concat(t, &amp;quot;\n&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function event_avatars(ev, evkey)&lt;br /&gt;
    local AV = ev.avatars&lt;br /&gt;
    if not Util.hasItems(AV) then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local token_icon = (ev.currency or {}).icon or &amp;quot;&amp;quot;&lt;br /&gt;
    local token_name = ev_label(evkey, &amp;quot;currencies&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    local years = {}&lt;br /&gt;
    for y,_ in pairs(AV) do years[#years+1] = tostring(y) end&lt;br /&gt;
    table.sort(years, function(a,b) return a &amp;gt; b end)&lt;br /&gt;
&lt;br /&gt;
    local parts = {}&lt;br /&gt;
    for _,year in ipairs(years) do&lt;br /&gt;
        local list = AV[year] or AV[tonumber(year)]&lt;br /&gt;
        if Util.hasItems(list) then&lt;br /&gt;
            local table_markup = build_avatar_table(list, token_icon, token_name)&lt;br /&gt;
            parts[#parts+1] = &amp;quot;|-|&amp;quot; .. year .. &amp;quot;=\n&amp;quot; .. table_markup&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return tabber_render_from_content(table.concat(parts, &amp;quot;\n&amp;quot;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function event_exchange_tabs(ev, evkey)&lt;br /&gt;
    local ex = ev.exchange or {}&lt;br /&gt;
    local token_icon = (ev.currency or {}).icon or &amp;quot;&amp;quot;&lt;br /&gt;
    local token_name = ev_label(evkey, &amp;quot;currencies&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if not (Util.hasItems(ex.chests_by_level)&lt;br /&gt;
         or Util.hasItems(ex.chests_by_stars)&lt;br /&gt;
         or Util.hasItems(ex.chests_by_oracle)&lt;br /&gt;
         or Util.hasItems(ex.currencies)) then&lt;br /&gt;
      return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local outer_parts = {}&lt;br /&gt;
    local function add_group(kind, list)&lt;br /&gt;
        if not Util.hasItems(list) then return end&lt;br /&gt;
        local inner_content = build_tabber_content_for(list)&lt;br /&gt;
        local inner_tabber  = tabber_render_from_content(inner_content)&lt;br /&gt;
        outer_parts[#outer_parts+1] = &amp;quot;|-|&amp;quot; .. group_label(kind) .. &amp;quot;=\n&amp;quot; .. inner_tabber&lt;br /&gt;
    end&lt;br /&gt;
    add_group(&amp;quot;level&amp;quot;,  ex.chests_by_level)&lt;br /&gt;
    add_group(&amp;quot;stars&amp;quot;,  ex.chests_by_stars)&lt;br /&gt;
    add_group(&amp;quot;oracle&amp;quot;, ex.chests_by_oracle)&lt;br /&gt;
&lt;br /&gt;
    local left_tabber = tabber_render_from_content(table.concat(outer_parts, &amp;quot;\n&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    local function pick_price_limit()&lt;br /&gt;
        if Util.hasItems(ex.chests_by_level)  then return ex.chests_by_level[1].price or 0,  ex.chests_by_level[1].limit or &amp;quot;&amp;quot;  end&lt;br /&gt;
        if Util.hasItems(ex.chests_by_stars)  then return ex.chests_by_stars[1].price or 0,  ex.chests_by_stars[1].limit or &amp;quot;&amp;quot;  end&lt;br /&gt;
        if Util.hasItems(ex.chests_by_oracle) then return ex.chests_by_oracle[1].price or 0, ex.chests_by_oracle[1].limit or &amp;quot;&amp;quot; end&lt;br /&gt;
        return 0, &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    local price, limit = pick_price_limit()&lt;br /&gt;
&lt;br /&gt;
    local t = {}&lt;br /&gt;
    local H_offer, H_price, H_limit = header_labels(evkey)&lt;br /&gt;
    t[#t+1] = &amp;#039;{| class=&amp;quot;article-table fs-exchange&amp;quot; style=&amp;quot;font-size:14px;&amp;quot;&amp;#039;&lt;br /&gt;
    t[#t+1] = string.format(&lt;br /&gt;
        &amp;#039;! style=&amp;quot;width:%s;&amp;quot; | %s !! style=&amp;quot;width:%s;&amp;quot; | %s !! style=&amp;quot;width:%s;&amp;quot; | %s&amp;#039;,&lt;br /&gt;
        COL_OFFER, H_offer, COL_PRICE, H_price, COL_LIMIT, H_limit&lt;br /&gt;
    )&lt;br /&gt;
    t[#t+1] = &amp;#039;|-&amp;#039;&lt;br /&gt;
    t[#t+1] = &amp;#039;|&amp;#039; .. left_tabber .. string.format(&lt;br /&gt;
        &amp;#039; || style=&amp;quot;text-align:center;&amp;quot; | %s %s %s || style=&amp;quot;text-align:center;&amp;quot; | %s&amp;#039;,&lt;br /&gt;
        Util.fileTag(token_icon, { size=&amp;quot;25px&amp;quot; }),&lt;br /&gt;
        tostring(price), token_name,&lt;br /&gt;
        tostring(limit)&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    if Util.hasItems(ex.currencies) then&lt;br /&gt;
        for _,it in ipairs(ex.currencies) do&lt;br /&gt;
            local offer = string.format(&amp;#039;%s %s&amp;#039;,&lt;br /&gt;
                Util.fileTag(it.icon or &amp;quot;&amp;quot;, { size=&amp;quot;30px&amp;quot; }),&lt;br /&gt;
                item_label(it.item, it.amount or 1)&lt;br /&gt;
            )&lt;br /&gt;
            t[#t+1] = &amp;#039;|-&amp;#039;&lt;br /&gt;
            t[#t+1] = string.format(&lt;br /&gt;
                &amp;#039;| %s || style=&amp;quot;text-align:center;&amp;quot; | %s %s %s || style=&amp;quot;text-align:center;&amp;quot; | %s&amp;#039;,&lt;br /&gt;
                offer,&lt;br /&gt;
                Util.fileTag(token_icon, { size=&amp;quot;25px&amp;quot; }),&lt;br /&gt;
                tostring(it.price or 0), token_name,&lt;br /&gt;
                tostring(it.limit or &amp;quot;&amp;quot;)&lt;br /&gt;
            )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    t[#t+1] = &amp;#039;|}&amp;#039;&lt;br /&gt;
    t[#t+1] = references_tag()&lt;br /&gt;
    return &amp;#039;\n&amp;#039; .. table.concat(t, &amp;#039;\n&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Zeitfenster eines Events&lt;br /&gt;
local function event_window(ev)&lt;br /&gt;
    local S = ev.schedule or ev&lt;br /&gt;
    local s = S.start_date; if Util.isEmpty(s) then return nil end&lt;br /&gt;
&lt;br /&gt;
    local st = Util.parseIsoDate(s); if not st then return nil end&lt;br /&gt;
&lt;br /&gt;
    local en_excl, en_incl&lt;br /&gt;
    if not Util.isEmpty(S.end_date) then&lt;br /&gt;
        en_incl = Util.parseIsoDate(S.end_date)&lt;br /&gt;
        if not en_incl then return st, nil, nil end&lt;br /&gt;
        en_excl = en_incl + DAY&lt;br /&gt;
    else&lt;br /&gt;
        local d = tonumber(S.duration_days) or 14&lt;br /&gt;
        en_excl = st + d * DAY&lt;br /&gt;
        en_incl = en_excl - DAY&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return st, en_excl, en_incl&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Event wählen, das jetzt laufen/gleich startet&lt;br /&gt;
local function pick_notice_eventkey()&lt;br /&gt;
    local cfg = (evI18n().notice or {})&lt;br /&gt;
    local pre  = tonumber(cfg.pre_days)  or 7&lt;br /&gt;
    local post = tonumber(cfg.post_days) or 3&lt;br /&gt;
    local now = os.time()&lt;br /&gt;
&lt;br /&gt;
    local running, upcoming, ended_recent = {}, {}, {}&lt;br /&gt;
&lt;br /&gt;
    for k, ev in pairs(EVENTS) do&lt;br /&gt;
        local st, en_excl = event_window(ev)&lt;br /&gt;
        if st and en_excl then&lt;br /&gt;
            if now &amp;gt;= st and now &amp;lt; en_excl then&lt;br /&gt;
                table.insert(running, { k=k, st=st, en=en_excl })&lt;br /&gt;
            elseif now &amp;gt;= st - pre*DAY and now &amp;lt; st then&lt;br /&gt;
                table.insert(upcoming, { k=k, st=st, en=en_excl })&lt;br /&gt;
            elseif now &amp;gt;= en_excl and now &amp;lt; en_excl + post*DAY then&lt;br /&gt;
                table.insert(ended_recent, { k=k, st=st, en=en_excl })&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local function by_end(a,b)   return a.en &amp;lt; b.en end&lt;br /&gt;
    local function by_start(a,b) return a.st &amp;lt; b.st end&lt;br /&gt;
    if #running      &amp;gt; 0 then table.sort(running,      by_end)   ; return running[1].k      end&lt;br /&gt;
    if #upcoming     &amp;gt; 0 then table.sort(upcoming,     by_start) ; return upcoming[1].k     end&lt;br /&gt;
    if #ended_recent &amp;gt; 0 then table.sort(ended_recent, by_end)   ; return ended_recent[1].k end&lt;br /&gt;
    return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function event_notice(ev, evkey)&lt;br /&gt;
    local phrases = (evI18n().phrases or {})&lt;br /&gt;
    local PH_RUNNING = phrases.event_notice&lt;br /&gt;
    local PH_ENDED   = phrases.event_ended&lt;br /&gt;
&lt;br /&gt;
    if Util.isEmpty(PH_RUNNING) then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local st, en_excl, en_incl = event_window(ev); if not st or not en_excl then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local cfg  = (evI18n().notice or {})&lt;br /&gt;
    local pre  = tonumber(cfg.pre_days)  or 7&lt;br /&gt;
    local post = tonumber(cfg.post_days) or 3&lt;br /&gt;
    local now  = os.time()&lt;br /&gt;
&lt;br /&gt;
    local show_from = st - pre  * DAY&lt;br /&gt;
    local show_till = en_excl + post * DAY&lt;br /&gt;
    if now &amp;lt; show_from or now &amp;gt;= show_till then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local name_label = ev_label(evkey, &amp;quot;eventname&amp;quot;)&lt;br /&gt;
    if Util.isEmpty(name_label) then name_label = ev_name(evkey) end&lt;br /&gt;
&lt;br /&gt;
    local name = ev_pagelink(ev, evkey, name_label)&lt;br /&gt;
&lt;br /&gt;
    local ic = ev_notice_icon_wikitext(ev)&lt;br /&gt;
&lt;br /&gt;
    local text&lt;br /&gt;
    if now &amp;lt; en_excl then&lt;br /&gt;
        text = PH_RUNNING&lt;br /&gt;
            :gsub(&amp;quot;$1&amp;quot;, name)&lt;br /&gt;
            :gsub(&amp;quot;$2&amp;quot;, Util.formatDateDe(st))&lt;br /&gt;
            :gsub(&amp;quot;$3&amp;quot;, Util.formatDateDe(en_excl))&lt;br /&gt;
    else&lt;br /&gt;
        if Util.isEmpty(PH_ENDED) then return &amp;quot;&amp;quot; end&lt;br /&gt;
        local curr = ev_label(evkey, &amp;quot;currencies&amp;quot;)&lt;br /&gt;
        local shop = ev_label(evkey, &amp;quot;ex_shop&amp;quot;)&lt;br /&gt;
        if Util.isEmpty(curr) or Util.isEmpty(shop) then return &amp;quot;&amp;quot; end&lt;br /&gt;
        text = PH_ENDED&lt;br /&gt;
          :gsub(&amp;quot;$1&amp;quot;, name)&lt;br /&gt;
          :gsub(&amp;quot;$4&amp;quot;, curr)&lt;br /&gt;
          :gsub(&amp;quot;$5&amp;quot;, shop)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local prefix = (ic ~= &amp;quot;&amp;quot; and (ic .. &amp;quot; &amp;quot;) or &amp;quot;&amp;quot;)&lt;br /&gt;
    local suffix = (ic ~= &amp;quot;&amp;quot; and (&amp;quot; &amp;quot; .. ic) or &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    return string.format(&lt;br /&gt;
        &amp;#039;&amp;lt;div class=&amp;quot;fs-notice&amp;quot; data-ev=&amp;quot;%s&amp;quot;&amp;gt;%s%s%s&amp;lt;/div&amp;gt;&amp;#039;,&lt;br /&gt;
        mw.text.encode(evkey),&lt;br /&gt;
        prefix, text, suffix&lt;br /&gt;
    )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_event(evkey)&lt;br /&gt;
    local real = Util.pickKey(EVENTS, evkey)&lt;br /&gt;
    return real and EVENTS[real] or nil, real or evkey&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function E.handle(frame, args)&lt;br /&gt;
    FRAME = frame&lt;br /&gt;
    local evkey = args[2]&lt;br /&gt;
&lt;br /&gt;
    if evkey and Util.norm(evkey) == &amp;quot;notice&amp;quot; then&lt;br /&gt;
        local pick = pick_notice_eventkey()&lt;br /&gt;
        if not pick then return &amp;quot;&amp;quot; end&lt;br /&gt;
        local ev, r = get_event(pick); if not ev then return &amp;quot;&amp;quot; end&lt;br /&gt;
        return event_notice(ev, r)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if Util.isEmpty(evkey) then return &amp;quot;&amp;quot; end&lt;br /&gt;
    local ev, realkey = get_event(evkey); if not ev then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local a3, a4 = args[3], args[4]&lt;br /&gt;
    if Util.isEmpty(a3) then&lt;br /&gt;
        return ev_name(realkey)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if a3==&amp;quot;notice&amp;quot;  then return event_notice(ev, realkey)&lt;br /&gt;
    elseif a3==&amp;quot;file&amp;quot;   then return event_file(ev, realkey, a4 or &amp;quot;&amp;quot;)&lt;br /&gt;
    elseif a3==&amp;quot;link&amp;quot;   then return event_link(ev, realkey, a4 or &amp;quot;&amp;quot;)&lt;br /&gt;
    elseif a3==&amp;quot;h2&amp;quot;     then return htag(2, ev_label(realkey, a4 or &amp;quot;&amp;quot;))&lt;br /&gt;
    elseif a3==&amp;quot;h3&amp;quot;     then return htag(3, ev_label(realkey, a4 or &amp;quot;&amp;quot;))&lt;br /&gt;
    elseif a3==&amp;quot;history&amp;quot;  then return event_history(ev, realkey)&lt;br /&gt;
    elseif a3==&amp;quot;avatars&amp;quot;  then return event_avatars(ev, realkey)&lt;br /&gt;
    elseif a3==&amp;quot;exchange&amp;quot; then return event_exchange_tabs(ev, realkey)&lt;br /&gt;
    elseif a3==&amp;quot;offers&amp;quot;   then&lt;br /&gt;
        if a4==&amp;quot;start&amp;quot; then return event_offers(ev, realkey, &amp;quot;initial&amp;quot;)&lt;br /&gt;
        elseif a4==&amp;quot;more&amp;quot; then return event_offers(ev, realkey, &amp;quot;after&amp;quot;) end&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if a3 == &amp;quot;currency&amp;quot;   then return ev_label(realkey, &amp;quot;currency&amp;quot;)  end&lt;br /&gt;
    if a3 == &amp;quot;currencies&amp;quot; then return ev_label(realkey, &amp;quot;currencies&amp;quot;) end&lt;br /&gt;
&lt;br /&gt;
    local path, i = {}, 3&lt;br /&gt;
    while args[i] do&lt;br /&gt;
        table.insert(path, args[i])&lt;br /&gt;
        i = i + 1&lt;br /&gt;
    end&lt;br /&gt;
    local v = Util.deepGet(ev, path)&lt;br /&gt;
    if v ~= nil then&lt;br /&gt;
        local last = path[#path] and tostring(path[#path]) or &amp;quot;&amp;quot;&lt;br /&gt;
        v = autotr(last, v)&lt;br /&gt;
        return tostring(v)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local last = Util.norm(path[#path] or a3)&lt;br /&gt;
    if last==&amp;quot;eventname&amp;quot; or last==&amp;quot;name&amp;quot; then return ev_name(realkey) end&lt;br /&gt;
    local lbl = ev_label(realkey, last); if not Util.isEmpty(lbl) then return lbl end&lt;br /&gt;
    local Uu = (evI18n().unlocks or {})[last]&lt;br /&gt;
    if Uu then return Uu end&lt;br /&gt;
&lt;br /&gt;
    return &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return E&lt;/div&gt;</summary>
		<author><name>Webmaster</name></author>
	</entry>
</feed>