Module:HostStars
From MicrasWiki
Documentation for this module may be created at Module:HostStars/doc
---------------------------------------------------------
-- Module: HostStars_Midnight
-- Purpose: Provide a "starsForTonight" function that:
-- 1) Uses Micras' 183-day orbit, 24-hour day, 22.5° tilt,
-- 2) Approximates day length (~9..15 hours) with a sine wave,
-- 3) Assigns random star rise/set times within the night,
-- 4) Checks if each star is visible at EXACTLY midnight (00:00).
--
-- Usage:
-- {{#invoke:HostStars_Midnight|starsForTonight}}
---------------------------------------------------------
local p = {}
---------------------------------------------------------
-- 1. dayOfYear (Micras-based)
-- 183-day orbit, start date=6 Aug 1999 => day=0
---------------------------------------------------------
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)
-- fractional year
local yearFrac = totalDays / daysPerYear
local psscYear = math.floor(yearFrac)
local dayOfYear = math.floor((yearFrac - psscYear) * daysPerYear) + 1
return dayOfYear
end
---------------------------------------------------------
-- 2. Sine-based day length at latitude=44°, tilt=22.5°
-- We'll approximate day length from ~9h to ~15h:
-- dayLength = base + amplitude * sin(2π*(dayOfYear - offset)/183)
-- where base=12, amplitude=3 => range [9..15].
-- offset=81 => "longest day" near day 81, purely by choice.
---------------------------------------------------------
local function getApproxDayLength(dayOfYear)
local base = 12 -- 12h is average day length
local amplitude = 3 -- ±3 => from 9 to 15
local offset = 81 -- shift so max day ~ mid-year
local sineTerm = math.sin( (2 * math.pi / 183) * (dayOfYear - offset) )
local length = base + amplitude * sineTerm
return length -- hours
end
---------------------------------------------------------
-- 3. Star Data (from "Top Image," Northern Hemisphere)
---------------------------------------------------------
local starDataNorth = {
{ name="Agave", starClass="M", latitude=29.5 },
{ name="Amaäz", starClass="K", latitude=31 },
{ name="Amáenu", starClass="G", latitude=45 },
{ name="Amap", starClass="A", latitude=55 },
{ name="Amazä", starClass="F", latitude=39 },
{ name="Atämios", starClass="F", latitude=56 },
{ name="Aprobelle", starClass="A", latitude=59 },
{ name="Azos", starClass="Galaxy", latitude=60 },
{ name="Bebeakaus", starClass="K", latitude=30.5 },
{ name="Bulhanu", starClass="A", latitude=40 },
{ name="Crösacío", starClass="K", latitude=17 },
{ name="Danaß", starClass="A", latitude=67 },
{ name="Dilëtaz", starClass="G", latitude=36 },
{ name="Dranamos", starClass="A", latitude=58 },
{ name="Gaht", starClass="G", latitude=29 },
{ name="Häpi", starClass="F", latitude=78 },
{ name="Hazaméos", starClass="A", latitude=72 },
{ name="Liléigos", starClass="F", latitude=18 },
{ name="Nyama", starClass="F", latitude=64 },
{ name="Ocananus", starClass="F", latitude=60.5 },
{ name="Orebele", starClass="F", latitude=22 },
{ name="Osiríos", starClass="G", latitude=53 },
{ name="Pythe", starClass="A", latitude=45 },
{ name="Sanashalo", starClass="G", latitude=27 },
{ name="Tä", starClass="F", latitude=39.5 },
{ name="Vï", starClass="A", latitude=46 },
{ name="Wedíos", starClass="A", latitude=54 },
}
---------------------------------------------------------
-- 4. Convert decimal hours to "HH:MM"
---------------------------------------------------------
local function hourToHM(decimalHour)
local hh = math.floor(decimalHour)
local mm = math.floor((decimalHour - hh) * 60 + 0.5)
hh = hh % 24
return string.format("%02d:%02d", hh, mm)
end
---------------------------------------------------------
-- 5. MAIN: starsForTonight
-- 1) dayOfYear => approximate dayLen => nightLen=24-dayLen
-- 2) define sunrise, sunset
-- 3) star rise in [sunset..(sunset+some fraction)], set later
-- 4) check if star is visible at midnight (00:00 local).
---------------------------------------------------------
function p.starsForTonight(frame)
local dayOfYear = getDayOfYearForPSSC()
local dailySeed = (os.date("*t").year * 1000) + dayOfYear
math.randomseed(dailySeed)
local dayLen = getApproxDayLength(dayOfYear) -- ~9..15
local nightLen= 24 - dayLen
-- We'll assume "sunrise = 12 - dayLen/2"
-- so day centered around ~noon. Then "sunset = sunrise + dayLen"
local sunrise = 12 - (dayLen/2)
local sunset = sunrise + dayLen
-- We'll define star rise times after sunset, up until well into night
local nightStart = sunset
local nightEnd = math.min(sunset + nightLen, 24) -- clamp to midnight if needed
local queryTime = 0.0 -- EXACT midnight local time
local out = {}
table.insert(out, "=== Host Stars Visible at Midnight (Vaeringheim ~44°N) ===\n")
table.insert(out, string.format(
"''DayOfYear=%d, Approx. DayLen=%.1fh, Sunrise=%.2f, Sunset=%.2f''\n\n",
dayOfYear, dayLen, sunrise, sunset
))
table.insert(out, '{| class="wikitable" style="width:100%; text-align:left;"\n')
table.insert(out, "! Star Name || Star Class || Rise Time || Set Time || Visible @ 00:00?\n")
for _, star in ipairs(starDataNorth) do
-------------------------------------------------------
-- random star rise in the evening or late night
-------------------------------------------------------
local rise = nightStart + math.random()*(nightLen*0.5)
if rise>24 then
rise = rise - 24 -- crosses midnight
end
-- star set: some random fraction after rise
local starSet = rise + math.random()*(nightLen*0.5 + 1.0)
if starSet>24 then
starSet = starSet -24
end
-- Format times
local riseStr = hourToHM(rise)
local setStr = hourToHM(starSet)
-- is star up at midnight?
local isVisible
if rise < starSet then
-- typical (doesn't cross midnight)
if (rise <= queryTime) and (queryTime < starSet) then
isVisible = "Yes"
else
isVisible = "No"
end
else
-- star crosses midnight
if (queryTime >= rise) or (queryTime < starSet) then
isVisible = "Yes"
else
isVisible = "No"
end
end
table.insert(out, "|-\n")
table.insert(out, string.format("| %s || %s || %s || %s || %s\n",
star.name, star.starClass, riseStr, setStr, isVisible))
end
table.insert(out, "|}\n")
return table.concat(out)
end
return p