Module:BassaridMarketActivity

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

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

---------------------------------------------------------
-- Module: BassaridiaDailyInvestorTable
-- Updates each day with new buy/sell, but uses the
-- "previous day" simulation to set 'Stocks at Start'
-- to 'Stocks at End' from that previous day.
--
-- NOTES:
-- 1) Because we do not store data externally, we
--    re-simulate "yesterday" each day with a slightly
--    different random seed. Then we use that to set the
--    starting stocks for "today."
-- 2) Everything is still stable for the current day, but
--    tomorrow it re-simulates again. Therefore, actual
--    day-to-day changes remain consistent in the script's
--    logic, *so long as* no additional changes are made.
---------------------------------------------------------
local p = {}

---------------------------------------------------------
-- 1. Calendar: Determine PSSC + daily seeds
---------------------------------------------------------
local function getCurrentDate()
    local startDate   = os.time({year=1999, month=8, day=6})
    local secondsInDay= 86400
    local daysPerYear = 183

    local currentDate = os.time()
    local totalDaysElapsed = math.floor((currentDate - startDate) / secondsInDay)

    local yearFraction = totalDaysElapsed / daysPerYear
    local psscYear     = math.floor(yearFraction)
    local dayOfYear    = math.floor((yearFraction - psscYear) * daysPerYear) + 1

    -- For demonstration, we do 3 months: 1..61, 62..122, 123..183
    local month, dayOfMonth
    if dayOfYear <= 61 then
        month = 1
        dayOfMonth = dayOfYear
    elseif dayOfYear <= 122 then
        month = 2
        dayOfMonth = dayOfYear - 61
    else
        month = 3
        dayOfMonth = dayOfYear - 122
    end

    local dateString = string.format("%d/%d/%d [[PSSC]]", dayOfMonth, month, psscYear)
    return dateString, psscYear, dayOfYear
end

---------------------------------------------------------
-- 2. Investor Data (Initial "Base" Stocks)
---------------------------------------------------------
-- This table holds each investor's *base* stock count,
-- used only if we had no prior day. We'll override each
-- day using the "simulateYesterday" logic below.
---------------------------------------------------------
local baseInvestors = {
    {name = "Vaeringheim Regional Investor", stocks = 17424},
    {name = "Alpazkigz Regional Investor",   stocks = 16214},
    {name = "Odiferia Regional Investor",    stocks = 14718},
    {name = "Hafaan Regional Investor",      stocks =  3630},
    {name = "Jeseri Regional Investor",      stocks =  1870},
    {name = "Hatch Ministry Regional Investor", stocks = 7810},
    {name = "New South Jangsong Division",   stocks = 11085},
    {name = "Haifan Bassaridia Division",    stocks = 12500},
}

---------------------------------------------------------
-- 3. Reasons for Increase or Decrease
---------------------------------------------------------
local increaseReasons = {
    "Improved logistics attracted new investors.",
    "An influx of goods boosted trade volume.",
    "High demand for Noctic-Rabrev exports raised confidence.",
    "Completion of a new shipping lane increased activity.",
    "Successful negotiations with Erythros merchants expanded trade.",
    "A local festival drove significant port activity.",
    "High attendance at a major trade symposium enhanced the port's reputation.",
    "Discovery of new mineral resources increased export potential.",
    "A surge in ceremonial wine exports bolstered port operations.",
    "Efficient cargo handling innovations improved investor sentiment.",
    "Seasonal agricultural exports saw a sharp increase.",
    "High sales of pearl and abalone products boosted port activity.",
    "Introduction of new luxury goods attracted high-end investors.",
    "Expansion of the port's capacity improved its competitiveness.",
    "Improved relations with local merchant guilds stabilized trade routes.",
    "Increased fishing yields led to greater port activity.",
    "Enhanced security measures reduced piracy concerns.",
    "Growing cultural appreciation for exotic exports boosted confidence.",
    "Trade agreements with neighboring cities expanded port usage.",
    "Launch of new fertilizer shipments attracted agricultural investors.",
    "Rising global interest in sacred resin exports spiked port activity.",
    "Successful marketing campaigns highlighted the port's strategic importance.",
    "Completion of high-speed rail connections improved trade efficiency.",
}

local decreaseReasons = {
    "Pirate raids in the Strait disrupted shipments.",
    "Unfavorable weather delayed agricultural exports.",
    "Labor shortages caused delays in cargo handling.",
    "A major fire in supply regions reduced exports.",
    "Rising costs impacted investor confidence.",
    "Unrest in Jangsong Province disrupted shipments.",
    "Currency fluctuations affected trade stability.",
    "Economic sanctions on neighbors reduced export activity.",
    "Decline in ceremonial artifact production reduced goods traffic.",
    "Cultural disputes caused delays in exports.",
    "Counterfeit relics discovered harmed the port's reputation.",
    "High demand outpaced supply, reducing exports.",
    "Decline in pearl quality lowered investor interest.",
    "Shortage of ceremonial wine hurt exports.",
    "Unrest among key merchants disrupted major trade agreements.",
    "Reduced demand for local textiles impacted port activity.",
    "Collapse of a key trade deal reduced port volume.",
    "Seasonal labor shortages decreased shipments.",
    "Alternate shipping routes bypassed the port.",
    "Economic downturn in a key region affected investor interest.",
    "Piracy concerns in Haifan waters harmed trade confidence.",
    "Failure to secure deals at a trade symposium reduced traffic.",
    "Natural disasters destroyed key trade routes.",
    "Sabotage of port infrastructure caused significant delays.",
}

---------------------------------------------------------
-- 4. Tiers
---------------------------------------------------------
local function determineTier(stocksAtEnd)
    if stocksAtEnd > 12500 then
        return "Tier I"
    elseif stocksAtEnd >= 5000 then
        return "Tier II"
    else
        return "Tier III"
    end
end

---------------------------------------------------------
-- 5. Single-Day Simulation
---------------------------------------------------------
local function simulateDailyActivity(stocksAtStart)
    local buyStocks = math.random(0, 500)
    local sellStocks = math.random(0, 500)

    local stocksAtEnd = stocksAtStart + buyStocks - sellStocks
    local change = "Increased"
    if stocksAtEnd < stocksAtStart then
        change = "Decreased"
    elseif stocksAtEnd == stocksAtStart then
        change = "No Change"
    end

    return {
        buyStocks     = buyStocks,
        sellStocks    = sellStocks,
        stocksAtEnd   = stocksAtEnd,
        change        = change,
    }
end

local function getReason(change)
    if change == "Increased" then
        return increaseReasons[math.random(#increaseReasons)]
    elseif change == "Decreased" then
        return decreaseReasons[math.random(#increaseReasons)]
    else
        return "Market activity remained stable."
    end
end

---------------------------------------------------------
-- 6. Yesterday Simulation:
--    1) We define a "yesterSeed" = dailySeed - 1
--    2) We replicate the random buy/sell from "yesterday"
--    3) We get stocksAtEndFromYesterday
--    4) That becomes today's StocksAtStart
---------------------------------------------------------
local function getYesterdaysEnd(investorBase, dailySeed)
    local yesterSeed = dailySeed - 1
    math.randomseed(yesterSeed)

    -- We'll simulate the same logic we use for the day,
    -- but only for "yesterday"
    local baseStart = investorBase.stocks
    local yResult   = simulateDailyActivity(baseStart)
    return yResult.stocksAtEnd  -- "yesterday's" stocks at end
end

---------------------------------------------------------
-- 7. Main Table Generation
---------------------------------------------------------
function p.generateTable()
    -- 7.1) Today’s date + seeds
    local dateString, psscYear, dayOfYear = getCurrentDate()
    local localTime = os.date("*t")
    local dailySeed = localTime.year * 1000 + localTime.yday
    math.randomseed(dailySeed)

    local stockPrice = 30
    local totalMarketValueAtStart = 0
    local totalMarketValueAtEnd   = 0
    local totalBoughtValue        = 0
    local totalSoldValue          = 0

    local out = {}
    table.insert(out, '{| class="wikitable"\n')
    table.insert(out,
        "! Date (Day/Month/Year PSSC) !! Investor !! Tier !! Stocks at Start !! Value at Start !! Stocks Bought !! Value of Stocks Bought !! Stocks Sold !! Value of Stocks Sold !! Stocks at End !! Value at End !! Change !! Reason\n"
    )

    -- For each investor
    for _, baseObj in ipairs(baseInvestors) do
        local yEnd = getYesterdaysEnd(baseObj, dailySeed)
        local stocksAtStart = yEnd  -- "today's start" is "yesterday's end"
        if stocksAtStart < 0 then
            stocksAtStart = 0  -- safety clamp
        end

        local valueAtStart = stocksAtStart * stockPrice

        -- Re-randomseed for "today"
        math.randomseed(dailySeed)

        local dayResult = simulateDailyActivity(stocksAtStart)
        local buyCount  = dayResult.buyStocks
        local sellCount = dayResult.sellStocks
        local stocksAtEnd = dayResult.stocksAtEnd
        if stocksAtEnd < 0 then
            stocksAtEnd = 0
        end
        local valueBought = buyCount  * stockPrice
        local valueSold   = sellCount * stockPrice
        local valueAtEnd  = stocksAtEnd * stockPrice
        local theChange   = dayResult.change
        local reason      = getReason(theChange)
        local tier        = determineTier(stocksAtEnd)

        -- accumulate totals
        totalMarketValueAtStart = totalMarketValueAtStart + valueAtStart
        totalMarketValueAtEnd   = totalMarketValueAtEnd   + valueAtEnd
        totalBoughtValue        = totalBoughtValue        + valueBought
        totalSoldValue          = totalSoldValue          + valueSold

        table.insert(out, "|-\n")
        table.insert(out, string.format(
            "| %s || %s || %s || %d || %d Polis || %d || %d Polis || %d || %d Polis || %d || %d Polis || %s || %s\n",
            dateString,          -- today's date
            baseObj.name,
            tier,
            stocksAtStart,
            valueAtStart,
            buyCount,
            valueBought,
            sellCount,
            valueSold,
            stocksAtEnd,
            valueAtEnd,
            theChange,
            reason
        ))
    end

    -- Totals row
    table.insert(out, "|-\n")
    table.insert(out, string.format(
        "| colspan=5 | Total Market Value at Start || %d Polis || %d Polis || %d Polis || %d Polis || ||\n",
        totalMarketValueAtStart, totalBoughtValue, totalSoldValue, totalMarketValueAtEnd
    ))
    table.insert(out, "|}")

    return table.concat(out)
end

return p