Last active
January 31, 2022 14:35
-
-
Save MrYossu/ecfed6773c88a65c955d8e6a1bdc3430 to your computer and use it in GitHub Desktop.
First pass at simulating buses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Random r = new(); | |
int delay = 250; | |
List<BusStop> busStops = new() { new(10), new(20), new(30), new(40), new(45), new(55), new(70), new(82), new(87), new(95), new(110) }; | |
int maxDistance = busStops.Max(l => l.Distance); | |
string stopsDisplay = string.Join("", Enumerable.Range(0, maxDistance).Select(n => busStops.Any(bs => bs.Distance == n) ? "|" : "-")) + "|"; | |
List<Bus> buses = new(); | |
int timeBetweenBuses = 10; | |
// The maximum number of passengers that can arrive at a bus stop at any one time | |
int maxNewPassengers = 5; | |
// The number of passengers that can board the bus in one time interval. | |
// If the number of passengers waiting exceeds this, the bus will be at the stop for longer | |
int boardingRate = 5; | |
int time = 0; | |
do { | |
// Is it time for the next bus to start? | |
if (time % timeBetweenBuses == 0) { | |
int newNumber = buses.Any() ? buses.Max(b => b.Number) + 1 : 1; | |
buses.Add(new(newNumber)); | |
} | |
// Have passengers arrive at three randomly chosen stops | |
for (int i = 0; i < r.Next() % 3; i++) { | |
// get the index of the bus stop, so we can add the passengers | |
int n = r.Next() % busStops.Count; | |
busStops[n] = busStops[n] with { PassengersWaiting = busStops[n].PassengersWaiting + r.Next() % maxNewPassengers }; | |
} | |
Util.ClearResults(); | |
// See what each bus should do in this time interval | |
for (int n = 0; n < buses.Count; n++) { | |
Bus bus = buses[n]; | |
if (busStops.Any(l => l.Distance == bus.Distance)) { | |
// We are at a bus stop. Get the index of the stop, so we can update in place (if we take on passengers) | |
int stopIndex = busStops.Select((bs, n) => (bs, n)).Where(t => t.bs.Distance == bus.Distance).Select(t => t.n).First(); | |
if (busStops[stopIndex].PassengersWaiting > 0) { | |
// There are passengers, so take on the number that can board in one time unit and don't move on | |
busStops[stopIndex] = busStops[stopIndex] | |
with { PassengersWaiting = Math.Max(0, busStops[stopIndex].PassengersWaiting - boardingRate) }; | |
} else { | |
// There aren't any passengers, just move on if the next location is empty. | |
if (!buses.Any(b => b.Number != bus.Number && b.Distance == bus.Distance + 1)) { | |
buses[n] = bus with { Distance = bus.Distance + 1 }; | |
} | |
} | |
} else { | |
// We are not at a bus stop. If the next location is empty, move on, otherwise stay here | |
if (!buses.Any(b => b.Number != bus.Number && b.Distance == bus.Distance + 1)) { | |
buses[n] = bus with { Distance = bus.Distance + 1 }; | |
} | |
} | |
} | |
$"Time: {time}".DumpFixed(); | |
ShowPassengers().DumpFixed(); | |
stopsDisplay.DumpFixed(); | |
ShowBuses().DumpFixed(); | |
await Task.Delay(delay); | |
time++; | |
} while (buses.First().Distance < maxDistance); | |
string ShowPassengers() { | |
string s = ""; | |
for (int i = 0; i < busStops.Count; i++) { | |
// Work out how far we are from the previous stop | |
int dist = i == 0 ? busStops[i].Distance : busStops[i].Distance - busStops[i - 1].Distance; | |
s += "".PadLeft(dist - 2, ' ') + busStops[i].PassengersWaiting.ToString("00"); | |
} | |
return s; | |
} | |
string ShowBuses() => | |
string.Join("", Enumerable.Range(0, maxDistance + 1).Select(n => buses.Any(b => b.Distance == n) ? Num(buses.First(b => b.Distance == n).Number) : " ")); | |
// Assuming there won't be more thna 26 buses on the route at any one time, we can display the buses as a digit or letter. | |
// This keeps it to one character, making the display line up correctly. | |
string Num(int n) => | |
n switch { | |
_ when n < 10 => n.ToString(), | |
_ => ((char)(n + 55)).ToString() | |
}; | |
record Bus(int Number, int Distance = 0); | |
record BusStop(int Distance, int PassengersWaiting = 0); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment