mirror of
https://github.com/metrostroi-repo/MetrostroiAddon.git
synced 2026-05-02 00:42:29 +00:00
init
This commit is contained in:
257
lua/metrostroi/sv_schedule.lua
Normal file
257
lua/metrostroi/sv_schedule.lua
Normal file
@@ -0,0 +1,257 @@
|
||||
--------------------------------------------------------------------------------
|
||||
-- Schedule generator
|
||||
--------------------------------------------------------------------------------
|
||||
-- List of all unique routes that can be used in schedule generation
|
||||
-- { station, platform }
|
||||
Metrostroi.ScheduleRoutes = Metrostroi.ScheduleRoutes or {}
|
||||
Metrostroi.SchedulesInitialized = false
|
||||
|
||||
-- List of all time intervals in which schedules must be generated
|
||||
-- { start_time, end_time, route_name, train_interval,
|
||||
Metrostroi.ScheduleConfiguration = Metrostroi.ScheduleConfiguration or {}
|
||||
|
||||
-- List of station names
|
||||
Metrostroi.StationNames = Metrostroi.StationNames or {}
|
||||
Metrostroi.StationTitles = Metrostroi.StationTitles or {}
|
||||
Metrostroi.StationNamesConfiguration = Metrostroi.StationNamesConfiguration or {}
|
||||
|
||||
-- AI train behavior configuration
|
||||
Metrostroi.AIConfiguration = Metrostroi.AIConfiguration or {}
|
||||
|
||||
-- Current server time
|
||||
function Metrostroi.ServerTime()
|
||||
return (os.time() % 86400)
|
||||
end
|
||||
|
||||
-- Departure time of last train from first station
|
||||
Metrostroi.DepartureTime = Metrostroi.DepartureTime or {}
|
||||
-- Schedule counter
|
||||
Metrostroi.ScheduleID = Metrostroi.ScheduleID or 0
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
local function timeToSec(str)
|
||||
local x = string.find(str,":")
|
||||
if not x then return tonumber(sec) or 0 end
|
||||
|
||||
local min = tonumber(string.sub(str,1,x-1)) or 0
|
||||
local sec = tonumber(string.sub(str,x+1)) or 0
|
||||
return min*60+sec,min,sec
|
||||
end
|
||||
|
||||
local function prepareRouteData(routeData,name)
|
||||
-- Prepare general route information
|
||||
routeData.Duration = 0
|
||||
routeData.Name = name
|
||||
|
||||
-- Fix up every station
|
||||
for i,stationID in ipairs(routeData) do
|
||||
routeData[i].ID = i
|
||||
routeData[i].TimeOffset = routeData.Duration
|
||||
if routeData[i+1] then
|
||||
if not Metrostroi.Stations[routeData[i][1]] then print(Format("No station %d",routeData[i][1])) return end
|
||||
if not Metrostroi.Stations[routeData[i][1]][routeData[i][2]] then print(Format("No platform %d for station %d",routeData[i][2],routeData[i][1])) return end
|
||||
if not Metrostroi.Stations[routeData[i+1][1]] then print(Format("No station %d",routeData[i+1][1])) return end
|
||||
if not Metrostroi.Stations[routeData[i+1][1]][routeData[i][2]] then print(Format("No platform %d for station %d",routeData[i+1][2],routeData[i+1][1])) return end
|
||||
|
||||
-- Get nodes
|
||||
local start_node = Metrostroi.Stations[routeData[i ][1]][routeData[i ][2]].node_end
|
||||
local end_node = Metrostroi.Stations[routeData[i+1][1]][routeData[i+1][2]].node_end
|
||||
if false and start_node.path ~= end_node.path then
|
||||
print(Format("Platform %d for station %d: path %d; Platform %d for station %d: path %d",
|
||||
routeData[i ][2],routeData[i ][1],start_node.path.id,
|
||||
routeData[i+1][2],routeData[i+1][1],end_node.path.id))
|
||||
return
|
||||
end
|
||||
|
||||
-- Calculate travel time between two nodes
|
||||
local travelTime,travelDistance = Metrostroi.GetTravelTime(start_node,end_node)
|
||||
-- Add time for startup and slowdown
|
||||
travelTime = travelTime + 25
|
||||
|
||||
-- Remember stats
|
||||
routeData.Duration = routeData.Duration + travelTime
|
||||
routeData[i].TravelTime = travelTime
|
||||
routeData[i].TravelDistance = travelDistance
|
||||
|
||||
-- Print debug information
|
||||
print(Format("\t\t[%03d-%d]->[%03d-%d] %02d:%02d min %4.0f m %4.1f km/h",
|
||||
routeData[i][1],routeData[i][2],
|
||||
routeData[i+1][1],routeData[i+1][2],
|
||||
math.floor(travelTime/60),math.floor(travelTime)%60,travelDistance,(travelDistance/travelTime)*3.6))
|
||||
else
|
||||
routeData.LastID = i
|
||||
routeData.LastStation = routeData[i][1]
|
||||
end
|
||||
end
|
||||
|
||||
-- Add a quick lookup
|
||||
routeData.Lookup = {}
|
||||
for i,_ in ipairs(routeData) do
|
||||
routeData.Lookup[routeData[i][1]] = routeData[i]
|
||||
end
|
||||
end
|
||||
|
||||
function Metrostroi.InitializeSchedules()
|
||||
if Metrostroi.SchedulesInitialized then return end
|
||||
Metrostroi.SchedulesInitialized = true
|
||||
|
||||
-- Fix up all routes
|
||||
print("Metrostroi: Preparing routes...")
|
||||
for routeName,routeData in pairs(Metrostroi.ScheduleRoutes) do
|
||||
print(Format("\tTravel distances for preset route '%s':",routeName))
|
||||
prepareRouteData(routeData,routeName)
|
||||
print(Format("\t\tTotal duration: %02d:%02d min",math.floor(routeData.Duration/60),math.floor(routeData.Duration)%60))
|
||||
end
|
||||
end
|
||||
|
||||
function Metrostroi.GenerateSchedule(routeID,starts,ends)
|
||||
Metrostroi.InitializeSchedules()
|
||||
if not Metrostroi.ScheduleRoutes[routeID] then print("Error generating schedule, line or path not found") return end
|
||||
local st = 1
|
||||
local fst = not starts
|
||||
local en = #Metrostroi.ScheduleRoutes[routeID]
|
||||
local fen = not ends
|
||||
for k,v in ipairs(Metrostroi.ScheduleRoutes[routeID]) do
|
||||
if v[1] == starts and not fst then
|
||||
st = k
|
||||
fst = true
|
||||
end
|
||||
if v[1] == ends and not fen then
|
||||
en = k
|
||||
fen = true
|
||||
end
|
||||
if fst and fen then break end
|
||||
end
|
||||
if not fst then print("Metrostroi: Warning! Station "..starts.." not found") st = 1 end
|
||||
if not fen then print("Metrostroi: Warning! Station "..ends.." not found") en = #Metrostroi.ScheduleRoutes[routeID] end
|
||||
|
||||
-- Time padding (extra time before schedule starts, wait time between trains)
|
||||
local paddingTime = timeToSec("1:30")
|
||||
-- Current server time
|
||||
local serverTime = Metrostroi.ServerTime()/60
|
||||
-- hack
|
||||
if routeID == "Line1_Platform2" then
|
||||
paddingTime = timeToSec("3:00")
|
||||
end
|
||||
|
||||
-- Determine schedule configuration
|
||||
local interval
|
||||
for _,config in pairs(Metrostroi.ScheduleConfiguration) do
|
||||
local t_start = timeToSec(config[1])
|
||||
local t_end = timeToSec(config[2])
|
||||
if (config[3] == routeID) and (t_start <= serverTime) and (t_end > serverTime) then
|
||||
interval = timeToSec(config[4])
|
||||
end
|
||||
end
|
||||
|
||||
-- If no interval, then no schedules available
|
||||
if not interval then return end
|
||||
|
||||
-- If no schedules started
|
||||
if not Metrostroi.DepartureTime[routeID] then
|
||||
Metrostroi.DepartureTime[routeID] = serverTime + paddingTime/60
|
||||
else
|
||||
-- If schedules started, depart with interval
|
||||
Metrostroi.DepartureTime[routeID] = math.max(Metrostroi.DepartureTime[routeID] + interval/60,serverTime + paddingTime/60)
|
||||
end
|
||||
|
||||
-- Create new schedule
|
||||
Metrostroi.ScheduleID = Metrostroi.ScheduleID + 1
|
||||
local schedule = {
|
||||
ScheduleID = Metrostroi.ScheduleID,
|
||||
Interval = interval,
|
||||
Duration = Metrostroi.ScheduleRoutes[routeID].Duration,
|
||||
}
|
||||
|
||||
-- Fill out all stations
|
||||
local currentTime = Metrostroi.DepartureTime[routeID]
|
||||
for id,stationData in ipairs(Metrostroi.ScheduleRoutes[routeID]) do
|
||||
if st > id or id > en then continue end
|
||||
-- Calculate stop time
|
||||
local stopTime = 15
|
||||
-- if not stationData.TravelTime then stopTime = 0 end
|
||||
|
||||
-- Add entry
|
||||
schedule[#schedule+1] = {
|
||||
stationData[1], -- Station
|
||||
stationData[2], -- Platform
|
||||
currentTime+stopTime/60, -- Departure time
|
||||
currentTime, -- Arrival time
|
||||
}
|
||||
|
||||
schedule[#schedule].arrivalTimeStr =
|
||||
Format("%02d:%02d:%02d",
|
||||
math.floor(schedule[#schedule][3]/60),
|
||||
math.floor(schedule[#schedule][3])%60,
|
||||
math.floor(schedule[#schedule][3]*60)%60)
|
||||
|
||||
-- Add travel time
|
||||
if stationData.TravelTime then
|
||||
currentTime = currentTime + (stationData.TravelTime + stopTime)/60
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill out start and end
|
||||
schedule.StartStation = schedule[1][1]
|
||||
schedule.EndStation = schedule[#schedule][1]
|
||||
schedule.StartTime = schedule[1][2]
|
||||
schedule.EndTime = schedule[#schedule][2]
|
||||
|
||||
-- Print result
|
||||
print(Format("--- %03d --- From %03d to %03d --------------------",
|
||||
schedule.ScheduleID,schedule.StartStation,schedule.EndStation))
|
||||
for i,d in ipairs(schedule) do
|
||||
print(Format("\t%03d %s",d[1],d.arrivalTimeStr))
|
||||
end
|
||||
return schedule
|
||||
end
|
||||
|
||||
function Metrostroi.LoadSchedulesData(data)
|
||||
Metrostroi.ScheduleRoutes = data.Routes or {}
|
||||
Metrostroi.ScheduleConfiguration = data.Configuration or {}
|
||||
Metrostroi.StationNames = data.StationNames or {}
|
||||
Metrostroi.StationTitles = data.StationTitles or {}
|
||||
Metrostroi.AIConfiguration = data.AIConfiguration or {}
|
||||
Metrostroi.StationNamesConfiguration = data.StationNamesConfiguration or {}
|
||||
Metrostroi.SchedulesInitialized = false
|
||||
timer.Simple(3.0,function()
|
||||
Metrostroi.InitializeSchedules()
|
||||
Metrostroi.DepartureTime = {}
|
||||
Metrostroi.ScheduleID = 0
|
||||
for k,v in pairs(Metrostroi.TrainClasses) do
|
||||
if v == "gmod_subway_base" then continue end
|
||||
local ents = ents.FindByClass(v)
|
||||
for k2,v2 in pairs(ents) do
|
||||
if v2.Schedule then v2.Schedule = nil end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
concommand.Add("metrostroi_resetschedules", function(ply, _, args)
|
||||
if not ply:IsAdmin() then return end
|
||||
Metrostroi.DepartureTime = {}
|
||||
Metrostroi.ScheduleID = 0
|
||||
for k,v in pairs(Metrostroi.TrainClasses) do
|
||||
if v == "gmod_subway_base" then continue end
|
||||
local ents = ents.FindByClass(v)
|
||||
for k2,v2 in pairs(ents) do
|
||||
if v2.Schedule then v2.Schedule = nil end
|
||||
end
|
||||
end
|
||||
end)
|
||||
concommand.Add("metrostroi_schedule1", function(ply, _, args)
|
||||
Metrostroi.GenerateSchedule("Line1_Platform1")
|
||||
end)
|
||||
|
||||
concommand.Add("metrostroi_schedule2", function(ply, _, args)
|
||||
Metrostroi.GenerateSchedule("Line1_Platform2")
|
||||
end)
|
||||
concommand.Add("metrostroi_print_scheduleinfo", function(ply, _, args)
|
||||
for routeName,routeData in pairs(Metrostroi.ScheduleRoutes) do
|
||||
print(Format("\tTravel distances for preset route '%s':",routeName))
|
||||
prepareRouteData(routeData,routeName)
|
||||
print(Format("\t\tTotal duration: %02d:%02d min",math.floor(routeData.Duration/60),math.floor(routeData.Duration)%60))
|
||||
end
|
||||
end)
|
||||
Reference in New Issue
Block a user