Parking/Assets/Scripts/ParkingManager.cs
2022-09-03 00:23:15 +02:00

207 lines
8.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
namespace Parking
{
public class ParkingManager : MonoBehaviour
{
public const float Width = 68;
public const float Height = 29;
public static ParkingManager Instance;
[SerializeField] private int stepTime = 15;
[SerializeField] private TextMeshProUGUI timeText;
[SerializeField] public TextMeshProUGUI countsText;
[SerializeField] public TextMeshProUGUI rejectedText;
[SerializeField] public GameObject spotPrefabA;
[SerializeField] public GameObject spotPrefabB;
[SerializeField] public GameObject spotPrefabC;
[SerializeField] public GameObject spotPrefabD;
[SerializeField] public GameObject carPrefab;
private readonly float[] _spotHeights = {3.5f, 4f, 5f, 7.5f};
public readonly List<List<Spot>> SpotMap = new()
{new List<Spot>(), new List<Spot>(), new List<Spot>(), new List<Spot>()};
private TimeSpan _currentTime = TimeSpan.FromHours(5) + TimeSpan.FromMinutes(45);
private int _rejectedDrivers = 0;
private void Awake()
{
Instance = this;
}
private void Start()
{
timeText.text = _currentTime.ToString();
DataImporter.ReadFile("Assets/Data/v1.csv");
Debug.Log(DataImporter.Drivers);
InitialConfigurationGenerator generator = new();
ArrangeSpots(generator.FindSolution());
}
public void AdvanceTime()
{
_currentTime += TimeSpan.FromMinutes(15);
timeText.text = _currentTime.ToString();
foreach (Driver driver in DataImporter.Drivers)
if (_currentTime <= driver.Times[1].TimeOfDay && _currentTime > driver.Times[0].TimeOfDay &&
!driver.Parked && !driver.Rejected)
{
if (!PlaceCarOnParking(driver))
{
Debug.Log($"Placing failed for car {driver.Priority}");
driver.Rejected = true;
_rejectedDrivers++;
rejectedText.text = $"Odrzuconych kierowców: {_rejectedDrivers}";
}
}
else if (_currentTime > driver.Times[1].TimeOfDay &&
driver.Parked)
{
driver.Spot.Free = true;
driver.Parked = false;
driver.Spot = null;
Destroy(driver.GameObject);
}
}
private bool PlaceCarOnParking(Driver driver)
{
for (var i = 0; i < SpotMap.Count; i++)
foreach (Spot spot in SpotMap[i])
if (spot.Size == driver.Size && spot.Free &&
(spot.ParkingDirection == driver.ParkingPreference ||
spot.ParkingDirection == ParkingPreference.Any))
{
spot.Free = false;
driver.Spot = spot;
driver.Parked = true;
driver.GameObject = Instantiate(carPrefab, spot.GameObject.transform, true);
driver.GameObject.transform.position = spot.GameObject.transform.position;
driver.GameObject.transform.rotation =
Quaternion.Euler(new Vector3(0, 0, spot.Flipped ? 180 : 0));
return true;
}
for (var i = 0; i < SpotMap.Count; i++)
foreach (Spot spot in SpotMap[i])
if (spot.Size == driver.Size && spot.Free)
{
spot.Free = false;
driver.Spot = spot;
driver.Parked = true;
driver.GameObject = Instantiate(carPrefab, spot.GameObject.transform, true);
driver.GameObject.transform.position = spot.GameObject.transform.position;
driver.GameObject.transform.rotation =
Quaternion.Euler(new Vector3(0, 0, spot.Flipped ? 180 : 0));
return true;
}
return false;
}
public void UpdateText(string text)
{
countsText.text = text;
}
private void ArrangeSpots(int[,] spotsCreated)
{
var spotMap = GenerateSpotMap(spotsCreated);
var maxP3 = _spotHeights[(int) spotMap[2].Max().Size];
var maxP2 = _spotHeights[(int) spotMap[1].Max().Size];
for (var i = 0; i < 4; i++)
{
float currentY;
switch (i)
{
case 0:
currentY = -Height / 2.0f + 2f;
break;
case 1:
currentY = Height / 2 - 5.5f - 5f - maxP3 / 2.0f - maxP2;
break;
case 2:
currentY = Height / 2 - 5.5f - 5f - maxP3 / 2.0f;
break;
case 3:
currentY = Height / 2.0f - 2f;
break;
default:
currentY = -10;
break;
}
float currentX;
if (i != 0) currentX = -Width / 2f - 2.25f / 2f + 2.25f;
else currentX = -Width / 2f + 5.5f - 2.25f / 2f + 2.25f + 1.75f;
var flipped = false;
var parkingFromTop = i % 2 != 0;
for (var j = 0; j < spotMap[i].Count; j++)
{
spotMap[i][j].Flipped = flipped;
var alignTop = i % 2 != 0;
switch (spotMap[i][j].Size)
{
case Size.A:
spotMap[i][j].GameObject = Instantiate(Instance.spotPrefabA);
spotMap[i][j].GameObject.transform.position = new Vector3(currentX, currentY, 0);
break;
case Size.B:
spotMap[i][j].GameObject = Instantiate(Instance.spotPrefabB);
spotMap[i][j].GameObject.transform.position =
new Vector3(currentX, currentY + (alignTop ? -1 : 1) * 0.25f, 0);
break;
case Size.C:
spotMap[i][j].GameObject = Instantiate(Instance.spotPrefabC);
spotMap[i][j].GameObject.transform.position =
new Vector3(currentX, currentY + (alignTop ? -1 : 1) * 0.5f, 0);
break;
case Size.D:
spotMap[i][j].GameObject = Instantiate(Instance.spotPrefabD);
spotMap[i][j].GameObject.transform.position =
new Vector3(currentX, currentY - 2.0f, 0);
break;
}
spotMap[i][j].GameObject.transform.rotation =
Quaternion.Euler(new Vector3(0, 0, spotMap[i][j].Flipped ? 180 : 0));
var frontalParking = !parkingFromTop ^ flipped;
spotMap[i][j].ParkingDirection = frontalParking ? ParkingPreference.Front : ParkingPreference.Back;
currentX += 2.25f;
flipped = !flipped;
}
}
}
private List<List<Spot>> GenerateSpotMap(int[,] spotsCreated)
{
for (var i = 0; i < 4; i++)
for (var j = 0; j < spotsCreated.GetLength(1); j++)
for (var k = 0; k < spotsCreated[i, j]; k++)
SpotMap[i].Add(new Spot((Size) j, false));
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;
}
}
}