Module:HostStars

From MicrasWiki
Revision as of 16:54, 27 December 2024 by NewZimiaGov (talk | contribs)
Jump to navigationJump to search

Documentation for this module may be created at Module:HostStars/doc

---------------------------------------------------------
-- Module: HostStarsBySeason
-- Creates a function "starsForTonight" that:
--   * uses dayOfYear in [1..183]
--   * identifies Atosiel(1..61), Thalassiel(62..122), Opsitheiel(123..183)
--   * for each star in the "top star chart" (north),
--     checks circumpolar or a "peak day" approach
--   * modifies the star's "halfWindow" for visibility depending on which
--     season we are currently in
---------------------------------------------------------

local p = {}

---------------------------------------------------------
-- 1. dayOfYear (Micras-based, 183-day year)
---------------------------------------------------------
local function getDayOfYearForPSSC()
    local startDate   = os.time({year=1999, month=8, day=6})
    local secPerDay   = 86400
    local daysPerYear = 183

    local currentTime = os.time()
    local totalDays   = math.floor((currentTime - startDate) / secPerDay)

    local fractionYear= totalDays / daysPerYear
    local psscYear    = math.floor(fractionYear)
    local dayOfYear   = math.floor((fractionYear - psscYear) * daysPerYear) + 1
    return dayOfYear
end

---------------------------------------------------------
-- 2. Identify which season we are in
--    Atosiel = 1..61
--    Thalassiel = 62..122
--    Opsitheiel = 123..183
---------------------------------------------------------
local function getSeasonName(dayOfYear)
    if dayOfYear <= 61 then
        return "Atosiel"
    elseif dayOfYear <= 122 then
        return "Thalassiel"
    else
        return "Opsitheiel"
    end
end

---------------------------------------------------------
-- 3. Star data (northern hemisphere top chart),
--    lat = approximate "declination" 
---------------------------------------------------------
local starDataNorth = {
    { name="Agave",     starClass="M",       lat=29.5 },
    { name="Amaäz",     starClass="K",       lat=31   },
    { name="Amáenu",    starClass="G",       lat=45   },
    { name="Amap",      starClass="A",       lat=55   },
    { name="Amazä",     starClass="F",       lat=39   },
    { name="Atämios",   starClass="F",       lat=56   },
    { name="Aprobelle", starClass="A",       lat=59   },
    { name="Azos",      starClass="Galaxy",  lat=60   },
    { name="Bebeakaus", starClass="K",       lat=30.5 },
    { name="Bulhanu",   starClass="A",       lat=40   },
    { name="Crösacío",  starClass="K",       lat=17   },
    { name="Danaß",     starClass="A",       lat=67   },
    { name="Dilëtaz",   starClass="G",       lat=36   },
    { name="Dranamos",  starClass="A",       lat=58   },
    { name="Gaht",      starClass="G",       lat=29   },
    { name="Häpi",      starClass="F",       lat=78   },
    { name="Hazaméos",  starClass="A",       lat=72   },
    { name="Liléigos",  starClass="F",       lat=18   },
    { name="Nyama",     starClass="F",       lat=64   },
    { name="Ocananus",  starClass="F",       lat=60.5 },
    { name="Orebele",   starClass="F",       lat=22   },
    { name="Osiríos",   starClass="G",       lat=53   },
    { name="Pythe",     starClass="A",       lat=45   },
    { name="Sanashalo", starClass="G",       lat=27   },
    { name="Tä",        starClass="F",       lat=39.5 },
    { name="Vï",        starClass="A",       lat=46   },
    { name="Wedíos",    starClass="A",       lat=54   },
}

---------------------------------------------------------
-- 4. Our location: Vaeringheim ~49°N
---------------------------------------------------------
local observerLat = 49

---------------------------------------------------------
-- 5. Check circumpolar:
--    if starLat >= (90 - observerLat) => circumpolar
---------------------------------------------------------
local function isCircumpolar(starLat)
    local limit = 90 - observerLat   -- ~41
    return (starLat >= limit)
end

---------------------------------------------------------
-- 6. We define starUpAtMidnight:
--    star has peakDay = lat*2 mod 183
--    star is visible if dayOfYear is within halfWindow around that peak
--    BUT halfWindow depends on the current season
---------------------------------------------------------
local function isStarUpAtMidnight(starLat, dayOfYear, halfWindow)
    local peakDay = (starLat * 2) % 183

    local diff = dayOfYear - peakDay
    diff = (diff + 183) % 183
    if diff > 91.5 then
       diff = 183 - diff
    end
    return (diff <= halfWindow)
end

---------------------------------------------------------
-- 7. MAIN: starsForTonight
--    show a table listing:
--      Star Name, Star Class, Season, Circumpolar, Visible, Note
---------------------------------------------------------
function p.starsForTonight(frame)
    local dayOfYear   = getDayOfYearForPSSC()
    local seasonName  = getSeasonName(dayOfYear)

    ---------------------------------------------------------
    -- Let's define halfWindow by season. Tweak if you want.
    -- e.g.: Atosiel => 45, Thalassiel => 40, Opsitheiel => 50
    ---------------------------------------------------------
    local halfWin
    if seasonName=="Atosiel" then
        halfWin = 45
    elseif seasonName=="Thalassiel" then
        halfWin = 40
    else
        halfWin = 50
    end

    local out = {}
    table.insert(out, "=== Stars Visible at Midnight in Vaeringheim (49°N) ===\n")
    table.insert(out, string.format("Current day of Micras year: %d (%s)\n\n", dayOfYear, seasonName))

    table.insert(out, '{| class="wikitable" style="width:100%; text-align:left;"\n')
    table.insert(out, "! Star Name !! Star Class !! Season !! Circumpolar !! Visibility at Midnight !! Note\n")

    for _, star in ipairs(starDataNorth) do
        local circ = isCircumpolar(star.lat)
        local visible
        local note

        if circ then
            visible = "Yes"
            note    = "Circumpolar"
        else
            local isUp = isStarUpAtMidnight(star.lat, dayOfYear, halfWin)
            visible = isUp and "Yes" or "No"
            note    = "Seasonal window (±"..halfWin.." days from peak)"
        end

        local circStr = circ and "Yes" or "No"

        table.insert(out, "|-\n")
        table.insert(out, string.format("| %s || %s || %s || %s || %s || %s\n",
            star.name, star.starClass, seasonName, circStr, visible, note
        ))
    end

    table.insert(out, "|}\n")

    return table.concat(out)
end

return p