Module:BassaridMarketActivity
From MicrasWiki
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