Parking/Assets/Scripts/ParkingManager.cs

741 lines
31 KiB
C#
Raw Normal View History

2022-08-25 17:58:26 +02:00
using System;
using System.Collections.Generic;
2022-08-28 22:42:21 +02:00
using System.Linq;
2022-08-25 17:58:26 +02:00
using TMPro;
using UnityEngine;
2022-09-08 00:43:34 +02:00
using UnityEngine.UI;
2022-08-25 17:58:26 +02:00
namespace Parking
2022-08-25 17:58:26 +02:00
{
public class ParkingManager : MonoBehaviour
2022-08-28 22:42:21 +02:00
{
public const float Width = 68;
public const float Height = 29;
2022-08-28 22:42:21 +02:00
public static ParkingManager Instance;
2022-08-28 22:42:21 +02:00
2022-09-04 00:35:45 +02:00
private static readonly TimeSpan StartTime = TimeSpan.FromHours(5) + TimeSpan.FromMinutes(45);
private static readonly TimeSpan EndTime = TimeSpan.FromHours(17) + TimeSpan.FromMinutes(15);
private static TimeSpan _currentTime = StartTime;
[SerializeField] private int stepTime = 15;
[SerializeField] private TextMeshProUGUI timeText;
[SerializeField] public TextMeshProUGUI countsText;
[SerializeField] public TextMeshProUGUI rejectedText;
2022-09-07 21:47:41 +02:00
[SerializeField] public TextMeshProUGUI pathText;
[SerializeField] public GameObject startPanel;
[SerializeField] public GameObject notFoundPanel;
[SerializeField] public GameObject spotPrefabA;
[SerializeField] public GameObject spotPrefabB;
[SerializeField] public GameObject spotPrefabC;
2022-08-31 21:19:20 +02:00
[SerializeField] public GameObject spotPrefabD;
2022-09-01 22:31:57 +02:00
[SerializeField] public GameObject carPrefab;
2022-09-05 01:15:04 +02:00
[SerializeField] public Transform mainPlanContainer;
[SerializeField] public Transform emergencyPlanContainer;
2022-09-08 00:43:34 +02:00
[SerializeField] public Toggle reconfigurationToggle;
[SerializeField] public string defaultPath = "Assets/Data/Tablica2.csv";
2022-08-28 22:42:21 +02:00
2022-09-05 22:00:15 +02:00
private readonly float[] _spotHeights = {4f, 4.5f, 5f, 7.5f};
2022-08-28 22:42:21 +02:00
2022-09-04 00:35:45 +02:00
private readonly List<List<Spot>> _spotMap = new()
{new List<Spot>(), new List<Spot>(), new List<Spot>(), new List<Spot>()};
2022-09-05 01:15:04 +02:00
private bool _emergencyActivated;
2022-09-08 00:43:34 +02:00
private bool _reconfigurationActive = true;
2022-09-05 01:15:04 +02:00
2022-09-04 00:35:45 +02:00
private int _initialConfigurationSpotCount;
private int[,] _initialSolution;
2022-09-03 21:27:31 +02:00
private int[] _rejectedDrivers = {0, 0, 0, 0};
private List<GameObject> _spotPrefabs;
2022-08-28 22:42:21 +02:00
private void Awake()
2022-08-28 22:42:21 +02:00
{
Instance = this;
2022-08-28 22:42:21 +02:00
}
private void Start()
{
_spotPrefabs = new List<GameObject> {spotPrefabA, spotPrefabB, spotPrefabC, spotPrefabD};
2022-09-08 00:43:34 +02:00
startPanel.SetActive(true);
reconfigurationToggle.onValueChanged.AddListener(ReconfigurationToggle);
}
2022-09-07 21:47:41 +02:00
2022-09-08 00:43:34 +02:00
public void ReconfigurationToggle(bool value)
{
_reconfigurationActive = value;
Debug.Log($"Reconfiguration {(value ? "activated" : "deactivated")}");
2022-09-07 21:47:41 +02:00
}
public void ReadDataButtonClick()
{
2022-09-08 00:43:34 +02:00
string path = pathText.text.Replace("\u200B", "");
if (path.Length == 0)
path = defaultPath;
if (!DataImporter.ReadFile(path)) {
2022-09-07 21:47:41 +02:00
notFoundPanel.SetActive(true);
return;
}
2022-09-08 00:43:34 +02:00
2022-09-07 21:47:41 +02:00
InitiateManager();
startPanel.SetActive(false);
}
private void InitiateManager()
{
timeText.text = _currentTime.ToString();
2022-09-03 21:27:31 +02:00
rejectedText.text = $"Małe: {_rejectedDrivers[0]} Średnie: {_rejectedDrivers[1]} " +
$"Duże: {_rejectedDrivers[2]}";
2022-09-05 01:15:04 +02:00
GenerateEmergencyPlan();
2022-09-05 22:01:52 +02:00
InitialConfigurationGenerator generator = new();
_initialSolution = generator.FindSolution();
ArrangeSpots(_initialSolution);
2022-09-04 00:35:45 +02:00
ReserveInitialSpots();
}
2022-09-05 01:15:04 +02:00
public void Emergency()
{
ResetDrivers();
_emergencyActivated = true;
}
2022-09-04 00:35:45 +02:00
private void ReserveInitialSpots()
{
2022-09-05 01:15:04 +02:00
for (int j = 3; j >= 0; j--)
2022-09-04 12:47:46 +02:00
foreach (Spot spot in _spotMap[j]) {
spot.Reserved = false;
spot.ReservedPriority = 0;
}
2022-09-05 01:15:04 +02:00
for (int i = 0; i < Math.Min(DataImporter.Drivers.Count, _initialConfigurationSpotCount); i++) {
2022-09-04 00:35:45 +02:00
bool found = false;
// Find spot
2022-09-05 01:15:04 +02:00
for (int j = 3; j >= 0 && !found; j--)
2022-09-04 00:35:45 +02:00
foreach (Spot spot in _spotMap[j])
if (spot.Size == DataImporter.Drivers[i].Size && !spot.Reserved) {
spot.Reserved = true;
spot.ReservedPriority = DataImporter.Drivers[i].Priority;
found = true;
break;
}
}
2022-08-28 22:42:21 +02:00
}
2022-08-29 23:01:18 +02:00
public void AdvanceTime()
{
2022-09-04 00:35:45 +02:00
// Update time
2022-09-03 21:27:31 +02:00
_currentTime += TimeSpan.FromMinutes(stepTime);
2022-09-04 00:35:45 +02:00
if (_currentTime > EndTime) {
2022-09-03 21:27:31 +02:00
_currentTime = StartTime;
2022-09-05 01:15:04 +02:00
timeText.text = _currentTime.ToString();
2022-09-04 00:35:45 +02:00
_rejectedDrivers = new[] {0, 0, 0, 0};
2022-09-03 21:27:31 +02:00
rejectedText.text = $"Małe: {_rejectedDrivers[0]} Średnie: {_rejectedDrivers[1]} " +
$"Duże: {_rejectedDrivers[2]}";
2022-09-05 01:15:04 +02:00
if (_emergencyActivated) {
emergencyPlanContainer.gameObject.SetActive(true);
mainPlanContainer.gameObject.SetActive(false);
}
else {
ArrangeSpots(_initialSolution);
2022-09-05 01:15:04 +02:00
ReserveInitialSpots();
ResetDrivers();
}
2022-09-05 22:01:52 +02:00
2022-09-03 21:27:31 +02:00
return;
}
2022-09-04 00:35:45 +02:00
timeText.text = _currentTime.ToString();
2022-09-04 00:35:45 +02:00
2022-09-05 01:15:04 +02:00
if (_emergencyActivated)
return;
2022-09-04 00:35:45 +02:00
2022-09-08 00:43:34 +02:00
if(_reconfigurationActive)
ReconfigureSpots();
2022-09-04 00:35:45 +02:00
foreach (Driver driver in DataImporter.Drivers) {
2022-09-04 12:47:46 +02:00
// TODO: Check if car can stay before other reservation - may not work for priority-based reservations
2022-09-05 01:15:04 +02:00
bool triesToPark = _currentTime <= driver.Times[3].TimeOfDay &&
_currentTime > driver.Times[2].TimeOfDay;
bool leftTheParking = _currentTime > driver.Times[3].TimeOfDay && driver.Parked;
2022-09-04 13:36:19 +02:00
bool reservedButTimedout =
2022-09-05 01:15:04 +02:00
(_currentTime - driver.Times[0].TimeOfDay).TotalMinutes > driver.UpdateInterval &&
2022-09-04 13:36:19 +02:00
GetReservedSpotCount(driver.Priority, driver.Size) > 0
&& !driver.Parked && !driver.Rejected && _currentTime <= driver.Times[3].TimeOfDay;
2022-09-04 00:35:45 +02:00
if (triesToPark && !driver.Parked && !driver.Rejected) {
if (!PlaceCarOnParking(driver)) {
2022-09-08 00:43:34 +02:00
if (_reconfigurationActive && TryReconfigureSpotForSize(driver.Size)) {
if (!PlaceCarOnParking(driver)) {
Debug.Log($"Placing failed for car {driver.Number} size {driver.Size}");
driver.Rejected = true;
_rejectedDrivers[(int) driver.Size]++;
rejectedText.text = $"Małe: {_rejectedDrivers[0]} Średnie: {_rejectedDrivers[1]} " +
$"Duże: {_rejectedDrivers[2]}";
}
}
else {
Debug.Log($"Placing failed for car {driver.Number} size {driver.Size}");
driver.Rejected = true;
_rejectedDrivers[(int) driver.Size]++;
rejectedText.text = $"Małe: {_rejectedDrivers[0]} Średnie: {_rejectedDrivers[1]} " +
$"Duże: {_rejectedDrivers[2]}";
}
}
}
2022-09-04 00:35:45 +02:00
else if (leftTheParking) {
driver.Spot.Reserved = false;
2022-09-03 21:27:31 +02:00
driver.Reset();
2022-09-05 01:15:04 +02:00
}
else if (reservedButTimedout) {
2022-09-04 13:36:19 +02:00
Debug.Log($"Reserved but timed out driver {driver.Number}");
driver.Rejected = true;
2022-09-01 22:31:57 +02:00
}
2022-09-04 00:35:45 +02:00
}
2022-09-08 00:43:34 +02:00
UpdateCounts();
}
2022-09-04 13:36:19 +02:00
private void UpdateCounts()
{
int[] counts = {0, 0, 0, 0};
for (int i = 0; i < _spotMap.Count; i++)
for (int j = 0; j < _spotMap[i].Count; j++)
counts[(int) _spotMap[i][j].Size]++;
string countsString = $"Małe: {counts[0]} Średnie: {counts[1]} Duże: {counts[2]} " +
$"Suma: {counts.Sum()}";
UpdateText(countsString);
2022-09-01 22:31:57 +02:00
}
2022-09-03 21:27:31 +02:00
private void ResetDrivers()
{
2022-09-05 01:15:04 +02:00
foreach (Driver driver in DataImporter.Drivers) {
2022-09-04 12:47:46 +02:00
if (driver.Spot != null) {
driver.Spot.Reserved = false;
driver.Spot.ReservedPriority = 0;
}
2022-09-05 01:15:04 +02:00
2022-09-03 21:27:31 +02:00
driver.Reset();
2022-09-04 12:47:46 +02:00
}
2022-09-04 00:35:45 +02:00
}
2022-09-04 13:36:19 +02:00
private int GetReservedSpotCount(int priority, Size size)
{
int count = 0;
2022-09-08 00:43:34 +02:00
foreach (List<Spot> list in _spotMap)
2022-09-05 01:15:04 +02:00
foreach (Spot spot in list)
if (spot.Size == size && spot.Reserved && spot.ReservedPriority == priority)
count++;
2022-09-04 13:36:19 +02:00
return count;
}
2022-09-04 00:35:45 +02:00
private bool FindReservedSpot(Driver driver, out Spot spot)
{
2022-09-08 00:43:34 +02:00
foreach (List<Spot> list in _spotMap)
2022-09-04 00:35:45 +02:00
foreach (Spot spot1 in list)
if (spot1.Reserved && spot1.ReservedPriority == driver.Priority) {
spot = spot1;
return true;
}
spot = new Spot();
return false;
2022-09-03 21:27:31 +02:00
}
private bool PlaceCarOnParking(Driver driver)
2022-09-01 22:31:57 +02:00
{
2022-09-04 00:35:45 +02:00
if (FindReservedSpot(driver, out Spot reservedSpot)) {
if (reservedSpot.Free) {
PlaceDriverOnSpot(driver, reservedSpot);
return true;
}
2022-09-05 01:15:04 +02:00
Debug.Log("Spot should be reserved but is taken");
2022-09-04 00:35:45 +02:00
}
2022-09-04 00:35:45 +02:00
2022-09-08 00:43:34 +02:00
foreach (List<Spot> t in _spotMap)
2022-09-04 00:35:45 +02:00
foreach (Spot spot in t) {
2022-09-05 01:15:04 +02:00
bool spotAvailable = spot.Size == driver.Size && spot.Free &&
(spot.ParkingDirection == driver.ParkingPreference ||
spot.ParkingDirection == ParkingPreference.Any)
&& !spot.Reserved;
2022-09-04 00:35:45 +02:00
if (spotAvailable) {
PlaceDriverOnSpot(driver, spot);
return true;
}
}
2022-09-08 00:43:34 +02:00
foreach (List<Spot> t in _spotMap)
2022-09-04 00:35:45 +02:00
foreach (Spot spot in t)
if (spot.Size == driver.Size && spot.Free && !spot.Reserved) {
PlaceDriverOnSpot(driver, spot);
return true;
}
return false;
}
2022-08-29 23:01:18 +02:00
2022-09-04 00:35:45 +02:00
private void PlaceDriverOnSpot(Driver driver, Spot spot)
{
spot.Free = false;
spot.Reserved = false;
driver.Spot = spot;
driver.Parked = true;
2022-09-05 23:31:33 +02:00
driver.GameObject = Instantiate(carPrefab);
2022-09-04 00:35:45 +02:00
driver.GameObject.GetComponentInChildren<TextMeshProUGUI>().text = driver.Number.ToString();
driver.GameObject.GetComponentInChildren<TextMeshProUGUI>().transform.rotation =
Quaternion.Euler(new Vector3(0, 0, (spot.Flipped ? 180 : 0) + (!spot.Perpendicular ? -90 : 0)));
2022-09-05 23:31:33 +02:00
driver.GameObject.transform.rotation =
Quaternion.Euler(new Vector3(0, 0, (spot.Flipped ? 180 : 0) + (!spot.Perpendicular ? 90 : 0)));
2022-09-04 00:35:45 +02:00
driver.GameObject.transform.position = spot.GameObject.transform.position;
2022-09-05 23:31:33 +02:00
driver.GameObject.transform.SetParent(spot.GameObject.transform, true);
2022-09-05 22:00:15 +02:00
driver.GameObject.transform.localPosition += new Vector3(0, 0, -1);
2022-09-04 00:35:45 +02:00
}
public void UpdateText(string text)
2022-08-29 23:01:18 +02:00
{
countsText.text = text;
2022-08-29 23:01:18 +02:00
}
2022-09-03 21:27:31 +02:00
private void ReconfigureSpots()
{
2022-09-05 01:15:04 +02:00
int[] freeSpots = GetFreeSpotCount();
2022-09-08 00:43:34 +02:00
List<Driver> nextCars = GetNextCars(1);
2022-09-04 00:35:45 +02:00
int[] plannedSpots = {0, 0, 0, 0};
2022-09-03 21:27:31 +02:00
foreach (Driver driver in nextCars)
2022-09-04 00:35:45 +02:00
plannedSpots[(int) driver.Size]++;
int[] neededSpots = {0, 0, 0, 0};
2022-09-03 21:27:31 +02:00
2022-09-05 01:15:04 +02:00
for (int i = 0; i < neededSpots.Length; i++)
2022-09-04 13:36:19 +02:00
neededSpots[i] = Math.Max(plannedSpots[i] - freeSpots[i], 0);
if (neededSpots.Sum() > 1) {
2022-09-03 21:27:31 +02:00
Debug.Log($"Needed spots = {neededSpots[0]} {neededSpots[1]} {neededSpots[2]} {neededSpots[3]}");
2022-09-04 00:35:45 +02:00
Debug.Log("Attempting reconfiguration...");
2022-09-03 21:27:31 +02:00
2022-09-08 00:43:34 +02:00
List<Driver> spotlessCars = new List<Driver>();
// Filter drivers by assigning free space
foreach (Driver nextCar in nextCars)
if (freeSpots[(int) nextCar.Size] != 0)
freeSpots[(int) nextCar.Size]--;
else
spotlessCars.Add(nextCar);
2022-09-08 00:43:34 +02:00
foreach (Driver nextCar in spotlessCars)
TryReconfigureSpotForSize(nextCar.Size);
}
}
private bool TryReconfigureSpotForSize(Size newSize)
{
2022-09-08 00:43:34 +02:00
foreach (List<Spot> currentLaneSpots in _spotMap)
foreach (Spot spot in currentLaneSpots) {
2022-09-08 00:43:34 +02:00
if (!(spot.Free && spot.Size != Size.D)) // && !spot.Reserved))
continue;
if (GetSpotCountOfSize(Size.A) <= 2 && spot.Size == Size.A)
continue;
if (GetSpotCountOfSize(Size.B) <= 2 && spot.Size == Size.B)
continue;
if (spot.LastReconfiguration == _currentTime)
continue;
2022-09-08 20:42:11 +02:00
int size = (int) newSize;
Vector3 position = spot.GameObject.transform.position;
Quaternion rotation = spot.GameObject.transform.rotation;
2022-09-05 22:01:52 +02:00
2022-09-08 20:42:11 +02:00
float diff = (_spotHeights[(int) spot.Size] - _spotHeights[size]) / 2.0f;
if (!spot.AlignToTop)
diff *= -1;
Vector3 offset = spot.Perpendicular ? new Vector3(0, diff, 0) : new Vector3(-diff, 0, 0);
Vector3 newPosition = position + offset;
2022-09-08 20:42:11 +02:00
if (spot.Size > newSize) {
if (!spot.Perpendicular) {
2022-09-08 20:42:11 +02:00
float newX = GetNextBorderHorizontal(position, spot.Lane, spot.Perpendicular, newSize, true) -
2022-09-08 00:43:34 +02:00
_spotHeights[(int) spot.Size] / 2.0f;
newPosition = new Vector3(newX,
newPosition.y, newPosition.z);
}
else {
2022-09-08 20:42:11 +02:00
float newX = GetNextBorderHorizontal(position, spot.Lane, spot.Perpendicular, newSize, true) - 2.25f / 2.0f;
2022-09-08 00:43:34 +02:00
if (spot.Lane == 0) {
float xRelativeToRight = newX - Width / 2.0f - 2.25f / 2.0f;
xRelativeToRight -= (xRelativeToRight + 2.25f / 2.0f) % 2.25f;
newX = xRelativeToRight + Width / 2.0f;
}
else {
float xRelativeToLeft = newX + Width / 2.0f;
xRelativeToLeft -= (xRelativeToLeft + 2.25f / 2.0f) % 2.25f;
newX = xRelativeToLeft - Width / 2.0f;
}
2022-09-08 00:43:34 +02:00
newPosition = new Vector3(newX,
newPosition.y, newPosition.z);
2022-09-05 22:00:15 +02:00
}
2022-09-08 20:42:11 +02:00
}else if (spot.Size < newSize) {
2022-09-08 00:43:34 +02:00
float spotBorder;
float thisSizeOffset;
if (spot.Perpendicular)
thisSizeOffset = _spotHeights[(int) spot.Size] / 2.0f;
else
thisSizeOffset = 2.25f;
if (!spot.AlignToTop)
spotBorder = position.y + thisSizeOffset;
else
spotBorder = position.y - thisSizeOffset;
2022-09-08 20:42:11 +02:00
if (spot.Perpendicular) {
float nextBorder = GetNextBorderVectical(position, spot.Lane, spot.Perpendicular, newSize,
!spot.AlignToTop);
if (Math.Abs(spotBorder - nextBorder) < 5.5f)
continue; // Try parallel
2022-09-08 20:42:11 +02:00
}
else {
float nextBorderLeft = GetNextBorderHorizontal(position, spot.Lane, spot.Perpendicular, newSize,
!spot.AlignToTop);
float nextBorderRight = GetNextBorderHorizontal(position, spot.Lane, spot.Perpendicular, newSize,
!spot.AlignToTop);
if (nextBorderRight - nextBorderLeft < _spotHeights[(int) newSize]) {
// Try perpendicular
float bottomBorder = position.y - 2.25f / 2.0f;
float topBorder = position.y + 2.25f / 2.0f;
if (spot.AlignToTop) {
float newBottomBorder = topBorder - _spotHeights[size];
float newTopBorder = topBorder;
float nextBorder = GetNextBorderVectical(position, spot.Lane, spot.Perpendicular,
newSize,
!spot.AlignToTop);
if (Math.Abs(nextBorder - newBottomBorder) < 5.5f) {
continue;
}
}
else {
float newBottomBorder = bottomBorder;
float newTopBorder = bottomBorder + _spotHeights[size];
float nextBorder = GetNextBorderVectical(position, spot.Lane, spot.Perpendicular,
newSize,
!spot.AlignToTop);
if (Math.Abs(newTopBorder - nextBorder) < 5.5f) {
continue;
}
}
newPosition.y = bottomBorder + _spotHeights[(int) newSize] / 2.0f;
float newX = nextBorderRight;
if (spot.Lane == 0) {
// float xRelativeToRight = newX - Width / 2.0f;
// xRelativeToRight -= (xRelativeToRight + 2.25f / 2.0f) % 2.25f;
// newX = xRelativeToRight + Width / 2.0f;
float xRelativeToRight = -(newX - Width / 2.0f);
// xRelativeToRight -= (xRelativeToRight - 2.25f / 2.0f) % 2.25f;
xRelativeToRight -= (xRelativeToRight + 2.25f / 2.0f) % 2.25f;
xRelativeToRight += 2.25f;
xRelativeToRight = Math.Max(xRelativeToRight, 2.25f / 2.0f);
newX = (-xRelativeToRight + Width / 2.0f);
}
else {
float xRelativeToLeft = newX + Width / 2.0f;
xRelativeToLeft -= (xRelativeToLeft + 2.25f / 2.0f) % 2.25f;
newX = xRelativeToLeft - Width / 2.0f;
}
if(spot.Lane == 0 && Width / 2.0f - newX < 5.5f + 0.5f + 2.25f)
continue;
newPosition.x = newX;
spot.Flipped = currentLaneSpots.FindIndex(spotPredicate => spotPredicate == spot) % 2 == 0;
rotation *= Quaternion.Euler(0, 0, spot.Flipped ? 90 : -90);
spot.Perpendicular = true;
}
2022-09-08 00:43:34 +02:00
}
2022-09-05 22:01:52 +02:00
}
2022-09-08 20:42:11 +02:00
Destroy(spot.GameObject);
spot.Size = (Size) size;
spot.Reserved = false;
spot.GameObject = Instantiate(_spotPrefabs[size],
newPosition, rotation, mainPlanContainer);
spot.LastReconfiguration = _currentTime;
return true;
2022-09-05 22:00:15 +02:00
}
return false;
2022-09-03 21:27:31 +02:00
}
2022-09-08 00:43:34 +02:00
private float GetNextBorderVectical(Vector3 position, int lane, bool perpendicular, Size size, bool up)
{
float minX = position.x - (perpendicular ? 2.25f : _spotHeights[(int) size]);
float maxX = position.x + (perpendicular ? 2.25f : _spotHeights[(int) size]);
List<float> allBorders = new();
List<Spot> targetLane = up ? _spotMap[lane + 1] : _spotMap[lane - 1];
foreach (Spot spot1 in targetLane) {
Vector3 targetSpotPosition = spot1.GameObject.transform.position;
if (targetSpotPosition.x < minX || targetSpotPosition.x > maxX)
continue;
float sizeOffset;
if (spot1.Perpendicular)
sizeOffset = _spotHeights[(int) spot1.Size] / 2.0f;
else
sizeOffset = 2.25f;
if (up)
allBorders.Add(targetSpotPosition.y - sizeOffset);
else
allBorders.Add(targetSpotPosition.y + sizeOffset);
}
if (allBorders.Count == 0)
return up ? Height / 2.0f : -Height / 2.0f;
float nextBorder = up ? allBorders.Min() : allBorders.Max();
return nextBorder;
}
2022-09-08 20:42:11 +02:00
private float GetNextBorderHorizontal(Vector3 position, int lane, bool perpendicular, Size size, bool right)
2022-09-08 00:43:34 +02:00
{
List<float> allBorders = new List<float>();
2022-09-08 20:42:11 +02:00
List<Spot> targetLane = _spotMap[lane];
2022-09-08 00:43:34 +02:00
foreach (Spot spot1 in targetLane) {
2022-09-08 20:42:11 +02:00
if (spot1.GameObject.transform.position == position)
2022-09-08 00:43:34 +02:00
continue;
Vector3 spotPosition = spot1.GameObject.transform.position;
float sizeOffset;
if (spot1.Perpendicular)
sizeOffset = 2.25f / 2.0f;
else
sizeOffset = _spotHeights[(int) spot1.Size] / 2.0f;
if(right)
allBorders.Add(spotPosition.x - sizeOffset);
else
allBorders.Add(spotPosition.x + sizeOffset);
2022-09-08 00:43:34 +02:00
}
allBorders.Sort();
foreach (float adjacentBorder in allBorders)
if (adjacentBorder > position.x)
return adjacentBorder;
2022-09-08 20:42:11 +02:00
if (perpendicular)
return position.x + (right ? 1 : -1) * _spotHeights[(int) size] / 2.0f;
return (right ? 1 : -1) * Width / 2.0f;
2022-09-08 00:43:34 +02:00
}
2022-09-07 20:35:01 +02:00
private int GetSpotCountOfSize(Size size)
{
int count = 0;
2022-09-08 00:43:34 +02:00
foreach (List<Spot> t in _spotMap)
2022-09-07 20:35:01 +02:00
foreach (Spot spot in t)
if (spot.Size == size)
count++;
return count;
}
2022-09-03 21:27:31 +02:00
private int[] GetFreeSpotCount()
{
2022-09-04 00:35:45 +02:00
int[] freeSpots = {0, 0, 0, 0};
2022-09-08 00:43:34 +02:00
foreach (List<Spot> t in _spotMap)
2022-09-03 21:27:31 +02:00
foreach (Spot spot in t)
if (spot.Free)
2022-09-04 00:35:45 +02:00
freeSpots[(int) spot.Size]++;
2022-09-03 21:27:31 +02:00
return freeSpots;
}
2022-09-04 00:35:45 +02:00
private List<Driver> GetNextCars(int steps)
2022-09-03 21:27:31 +02:00
{
2022-09-08 00:43:34 +02:00
List<Driver> nextCars = new List<Driver>();
TimeSpan updatedTime = _currentTime + TimeSpan.FromMinutes(stepTime * steps);
foreach (Driver driver in DataImporter.Drivers)
if (updatedTime <= driver.Times[1].TimeOfDay &&
updatedTime >= driver.Times[0].TimeOfDay &&
!driver.Parked && !driver.Rejected)
nextCars.Add(driver);
2022-09-03 21:27:31 +02:00
return nextCars;
}
private void ArrangeSpots(int[,] spotsCreated)
2022-08-29 23:01:18 +02:00
{
2022-09-08 00:43:34 +02:00
List<List<Spot>> spotMap = GenerateSpotMap(spotsCreated);
2022-09-05 00:47:52 +02:00
float[] spotSizes = {4, 4.5f, 5, 0};
float maxP3 = 0;
float maxP2 = 0;
2022-09-05 01:15:04 +02:00
foreach (Spot spot in spotMap[2])
if (spot.Size != Size.D)
2022-09-05 23:31:33 +02:00
maxP3 = Math.Max(maxP3, spot.Perpendicular ? _spotHeights[(int) spot.Size] : 2.25f);
2022-09-05 01:15:04 +02:00
foreach (Spot spot in spotMap[1])
if (spot.Size != Size.D)
2022-09-05 23:31:33 +02:00
maxP2 = Math.Max(maxP2, spot.Perpendicular ? _spotHeights[(int) spot.Size] : 2.25f);
2022-09-05 00:47:52 +02:00
// float maxP3 = spotMap[2].Count == 0 ? 0 : _spotHeights[(int) spotMap[2].Max().Size];
// float maxP2 = spotMap[1].Count == 0 ? 0 : _spotHeights[(int) spotMap[1].Max().Size];
2022-09-08 00:43:34 +02:00
List<GameObject> prefabs = new List<GameObject> {spotPrefabA, spotPrefabB, spotPrefabC, spotPrefabD};
2022-09-05 01:15:04 +02:00
for (int i = 0; i < 4; i++) {
float currentY;
2022-09-05 00:47:52 +02:00
bool parkingFromTop = i % 2 != 0;
2022-09-04 00:35:45 +02:00
switch (i) {
case 0:
2022-09-05 00:47:52 +02:00
currentY = -Height / 2.0f;
break;
case 1:
2022-09-05 00:47:52 +02:00
currentY = Height / 2.0f - 5.5f - 5.0f - maxP3;
2022-08-29 23:01:18 +02:00
break;
case 2:
2022-09-05 00:47:52 +02:00
currentY = Height / 2.0f - 5.5f - 5.0f - maxP3;
2022-08-29 23:01:18 +02:00
break;
case 3:
2022-09-05 00:47:52 +02:00
currentY = Height / 2.0f;
2022-08-29 23:01:18 +02:00
break;
default:
currentY = -10;
2022-08-29 23:01:18 +02:00
break;
}
float currentX;
if (i != 0) currentX = -Width / 2f;
2022-09-05 23:31:33 +02:00
else currentX = Width / 2f; // + 5.5f - 2.25f / 2f + 2.25f + 1.75f;
2022-08-28 22:42:21 +02:00
2022-09-05 01:15:04 +02:00
bool flipped = false;
2022-08-28 22:42:21 +02:00
2022-09-05 01:15:04 +02:00
for (int j = 0; j < spotMap[i].Count; j++) {
// if (!spotMap[i][j].Perpendicular)
// currentX -= spotSizes[(int) spotMap[i][j].Size] / 2.0f;
// else if (spotMap[i][j].Perpendicular)
// currentX -= 2.25f / 2.0f;
currentX += (i != 0 ? 1 : -1) *
(spotMap[i][j].Perpendicular ? 2.25f / 2.0f : spotSizes[(int) spotMap[i][j].Size] / 2.0f);
2022-09-05 23:31:33 +02:00
spotMap[i][j].Flipped = flipped;
2022-09-05 01:15:04 +02:00
bool alignTop = i % 2 != 0;
2022-09-05 23:31:33 +02:00
spotMap[i][j].GameObject = Instantiate(prefabs[(int) spotMap[i][j].Size], mainPlanContainer);
2022-09-05 01:15:04 +02:00
2022-09-05 23:31:33 +02:00
if (spotMap[i][j].Perpendicular) {
spotMap[i][j].GameObject.transform.position =
new Vector3(currentX,
currentY + (alignTop ? -1 : 1) * spotSizes[(int) spotMap[i][j].Size] / 2.0f, 0);
}
else {
spotMap[i][j].GameObject.transform.position =
new Vector3(currentX,
currentY + (alignTop ? -1 : 1) * 2.25f / 2.0f, 0);
}
2022-09-05 00:47:52 +02:00
2022-09-05 22:00:15 +02:00
spotMap[i][j].AlignToTop = alignTop;
2022-09-05 23:31:33 +02:00
if (!spotMap[i][j].Perpendicular)
spotMap[i][j].Flipped = alignTop;
if (spotMap[i][j].Perpendicular) {
spotMap[i][j].GameObject.transform.rotation =
Quaternion.Euler(new Vector3(0, 0, spotMap[i][j].Flipped ? 180 : 0));
}
else {
spotMap[i][j].GameObject.transform.rotation =
Quaternion.Euler(new Vector3(0, 0, (spotMap[i][j].Flipped ? 180 : 0) + 90));
}
2022-09-05 01:15:04 +02:00
bool frontalParking = !parkingFromTop ^ flipped;
spotMap[i][j].ParkingDirection = frontalParking ? ParkingPreference.Front : ParkingPreference.Back;
2022-09-05 22:00:15 +02:00
spotMap[i][j].Lane = i;
2022-09-05 22:01:52 +02:00
2022-09-05 23:31:33 +02:00
currentX += (i != 0 ? 1 : -1) *
(spotMap[i][j].Perpendicular ? 2.25f / 2.0f : spotSizes[(int) spotMap[i][j].Size] / 2.0f);
flipped = !flipped;
2022-08-28 22:42:21 +02:00
}
}
}
2022-09-05 01:15:04 +02:00
private void GenerateEmergencyPlan()
{
emergencyPlanContainer.gameObject.SetActive(false);
for (int i = 0; i < 4; i++) {
float currentY;
switch (i) {
case 0:
currentY = -Height / 2.0f;
break;
case 1:
currentY = Height / 2.0f - 5.5f - 5.0f - 5.0f;
break;
case 2:
currentY = Height / 2.0f - 5.5f - 5.0f - 5.0f;
break;
case 3:
currentY = Height / 2.0f;
break;
default:
currentY = -10;
break;
}
float currentX;
if (i != 0) currentX = -Width / 2f - 2.25f / 2f + 2.25f;
else currentX = Width / 2f - 5.0f / 2f;
GameObject spawnedSpot;
2022-09-05 22:01:52 +02:00
int[] emergencyMap = {12, 27, 27, 20};
2022-09-05 01:15:04 +02:00
2022-09-05 22:01:52 +02:00
for (int j = 0; j < emergencyMap[i]; j++)
2022-09-05 01:15:04 +02:00
if (i == 0) {
2022-09-05 22:01:52 +02:00
Vector3 position = new(currentX, currentY + 2.25f / 2.0f, 0);
Instantiate(Instance.spotPrefabC, position,
2022-09-05 01:15:04 +02:00
Quaternion.Euler(new Vector3(0, 0, 90)), emergencyPlanContainer);
2022-09-05 22:01:52 +02:00
2022-09-05 01:15:04 +02:00
currentX -= 5;
2022-09-05 22:01:52 +02:00
}
else {
2022-09-05 01:15:04 +02:00
bool alignTop = i % 2 != 0;
2022-09-05 22:01:52 +02:00
Vector3 position = new(currentX, currentY, 0);
2022-09-05 01:15:04 +02:00
spawnedSpot = Instantiate(Instance.spotPrefabC, position,
Quaternion.Euler(new Vector3(0, 0, 0)), emergencyPlanContainer);
spawnedSpot.transform.position =
new Vector3(currentX,
currentY + (alignTop ? -1 : 1) * 5.0f / 2.0f,
0);
currentX += 2.25f;
}
}
}
private List<List<Spot>> GenerateSpotMap(int[,] spotsCreated)
2022-08-28 22:42:21 +02:00
{
2022-09-08 00:43:34 +02:00
foreach (List<Spot> list in _spotMap) {
foreach (Spot spot in list)
if (spot.GameObject != null)
Destroy(spot.GameObject);
list.Clear();
}
2022-09-05 01:15:04 +02:00
for (int i = 0; i < 4; i++)
for (int j = 0; j < spotsCreated.GetLength(1); j++)
for (int k = 0; k < spotsCreated[i, j]; k++) {
2022-09-05 23:31:33 +02:00
Spot spot = new((Size) (j % 4), false);
spot.Perpendicular = j < 4;
_spotMap[i].Add(spot);
2022-09-04 00:35:45 +02:00
_initialConfigurationSpotCount++;
}
_spotMap[0].Sort((a, b) => a.Size.CompareTo(b.Size)); // ascending sort
_spotMap[1].Sort((a, b) => b.Size.CompareTo(a.Size)); // descending sort
_spotMap[2].Sort((a, b) => b.Size.CompareTo(a.Size)); // descending sort
_spotMap[3].Sort((a, b) => a.Size.CompareTo(b.Size)); // ascending sort
_spotMap[2].Add(new Spot(Size.D, false));
return _spotMap;
2022-08-28 22:42:21 +02:00
}
}
}