Added parallel reconfiguration and other improvements
This commit is contained in:
parent
7571ca1d5d
commit
8a01e3f3bd
@ -37,7 +37,9 @@ namespace Parking
|
||||
private bool _emergencyActivated;
|
||||
|
||||
private int _initialConfigurationSpotCount;
|
||||
private int[,] _initialSolution;
|
||||
private int[] _rejectedDrivers = {0, 0, 0, 0};
|
||||
private List<GameObject> _spotPrefabs;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@ -46,14 +48,17 @@ namespace Parking
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_spotPrefabs = new List<GameObject> {spotPrefabA, spotPrefabB, spotPrefabC, spotPrefabD};
|
||||
|
||||
timeText.text = _currentTime.ToString();
|
||||
rejectedText.text = $"Małe: {_rejectedDrivers[0]} Średnie: {_rejectedDrivers[1]} " +
|
||||
$"Duże: {_rejectedDrivers[2]}";
|
||||
GenerateEmergencyPlan();
|
||||
|
||||
DataImporter.ReadFile("Assets/Data/Tablica4.csv");
|
||||
DataImporter.ReadFile("Assets/Data/Tablica3.csv");
|
||||
InitialConfigurationGenerator generator = new();
|
||||
ArrangeSpots(generator.FindSolution());
|
||||
_initialSolution = generator.FindSolution();
|
||||
ArrangeSpots(_initialSolution);
|
||||
ReserveInitialSpots();
|
||||
}
|
||||
|
||||
@ -106,6 +111,7 @@ namespace Parking
|
||||
mainPlanContainer.gameObject.SetActive(false);
|
||||
}
|
||||
else {
|
||||
ArrangeSpots(_initialSolution);
|
||||
ReserveInitialSpots();
|
||||
ResetDrivers();
|
||||
}
|
||||
@ -118,6 +124,8 @@ namespace Parking
|
||||
if (_emergencyActivated)
|
||||
return;
|
||||
|
||||
ReconfigureSpots();
|
||||
|
||||
foreach (Driver driver in DataImporter.Drivers) {
|
||||
// TODO: Check if car can stay before other reservation - may not work for priority-based reservations
|
||||
bool triesToPark = _currentTime <= driver.Times[3].TimeOfDay &&
|
||||
@ -129,13 +137,24 @@ namespace Parking
|
||||
&& !driver.Parked && !driver.Rejected && _currentTime <= driver.Times[3].TimeOfDay;
|
||||
if (triesToPark && !driver.Parked && !driver.Rejected) {
|
||||
if (!PlaceCarOnParking(driver)) {
|
||||
Debug.Log($"Placing failed for car {driver.Number}");
|
||||
if (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]}";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (leftTheParking) {
|
||||
driver.Spot.Reserved = false;
|
||||
driver.Reset();
|
||||
@ -146,7 +165,20 @@ namespace Parking
|
||||
}
|
||||
}
|
||||
|
||||
ReconfigureSpots();
|
||||
UpdateCounts();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private void ResetDrivers()
|
||||
@ -230,7 +262,7 @@ namespace Parking
|
||||
driver.GameObject = Instantiate(carPrefab);
|
||||
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)));
|
||||
Quaternion.Euler(new Vector3(0, 0, (spot.Flipped ? 180 : 0) + (!spot.Perpendicular ? -90 : 0)));
|
||||
driver.GameObject.transform.rotation =
|
||||
Quaternion.Euler(new Vector3(0, 0, (spot.Flipped ? 180 : 0) + (!spot.Perpendicular ? 90 : 0)));
|
||||
driver.GameObject.transform.position = spot.GameObject.transform.position;
|
||||
@ -245,9 +277,8 @@ namespace Parking
|
||||
|
||||
private void ReconfigureSpots()
|
||||
{
|
||||
var prefabs = new List<GameObject> {spotPrefabA, spotPrefabB, spotPrefabC};
|
||||
int[] freeSpots = GetFreeSpotCount();
|
||||
var nextCars = GetNextCars(10);
|
||||
var nextCars = GetNextCars(1);
|
||||
int[] plannedSpots = {0, 0, 0, 0};
|
||||
foreach (Driver driver in nextCars)
|
||||
plannedSpots[(int) driver.Size]++;
|
||||
@ -256,18 +287,32 @@ namespace Parking
|
||||
|
||||
for (int i = 0; i < neededSpots.Length; i++)
|
||||
neededSpots[i] = Math.Max(plannedSpots[i] - freeSpots[i], 0);
|
||||
if (neededSpots.Sum() > 5) {
|
||||
if (neededSpots.Sum() > 1) {
|
||||
Debug.Log($"Needed spots = {neededSpots[0]} {neededSpots[1]} {neededSpots[2]} {neededSpots[3]}");
|
||||
Debug.Log("Attempting reconfiguration...");
|
||||
|
||||
for (int size = 0; size < 3; size++) {
|
||||
bool foundReplacement = true;
|
||||
while (foundReplacement && neededSpots[size] != 0) {
|
||||
foundReplacement = false;
|
||||
foreach (var t in _spotMap)
|
||||
foreach (Spot spot in t)
|
||||
if ((int) spot.Size > size && spot.Free && spot.Lane != 3 && spot.Size != Size.D) {
|
||||
foundReplacement = true;
|
||||
var 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);
|
||||
|
||||
|
||||
foreach (Driver nextCar in spotlessCars) {
|
||||
TryReconfigureSpotForSize(nextCar.Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryReconfigureSpotForSize(Size newSize)
|
||||
{
|
||||
foreach (var currentLaneSpots in _spotMap)
|
||||
foreach (Spot spot in currentLaneSpots) {
|
||||
if (spot.Size > newSize && spot.Free && spot.Size != Size.D && !spot.Reserved) {
|
||||
int size = (int) newSize;
|
||||
|
||||
float diff = (_spotHeights[(int) spot.Size] - _spotHeights[size]) / 2.0f;
|
||||
if (!spot.AlignToTop)
|
||||
@ -284,24 +329,41 @@ namespace Parking
|
||||
|
||||
spot.Reserved = false;
|
||||
|
||||
Vector3 offset;
|
||||
if (spot.Perpendicular)
|
||||
offset = new Vector3(0, diff, 0);
|
||||
else
|
||||
offset = new Vector3(-diff, 0, 0);
|
||||
Vector3 offset = spot.Perpendicular ? new Vector3(0, diff, 0) : new Vector3(-diff, 0, 0);
|
||||
|
||||
Vector3 newPosition = position + offset;
|
||||
|
||||
if (!spot.Perpendicular) {
|
||||
var allBorders = new List<float>();
|
||||
foreach (Spot spot1 in currentLaneSpots) {
|
||||
if (spot1 == spot)
|
||||
continue;
|
||||
Vector3 spotPosition = spot1.GameObject.transform.position;
|
||||
float sizeOffset = _spotHeights[(int) spot1.Size] / 2.0f;
|
||||
allBorders.Add(spotPosition.x + sizeOffset);
|
||||
allBorders.Add(spotPosition.x - sizeOffset);
|
||||
}
|
||||
|
||||
allBorders.Sort();
|
||||
foreach (float adjacentBorder in allBorders)
|
||||
if (adjacentBorder > position.x) {
|
||||
newPosition = new Vector3(adjacentBorder -
|
||||
_spotHeights[size] / 2.0f,
|
||||
newPosition.y, newPosition.z);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check how much space to right to push
|
||||
|
||||
spot.GameObject = Instantiate(prefabs[size],
|
||||
position + offset, rotation, mainPlanContainer);
|
||||
spot.GameObject = Instantiate(_spotPrefabs[size],
|
||||
newPosition, rotation, mainPlanContainer);
|
||||
|
||||
goto whileEnd;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
whileEnd: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int[] GetFreeSpotCount()
|
||||
@ -314,18 +376,15 @@ namespace Parking
|
||||
return freeSpots;
|
||||
}
|
||||
|
||||
private List<Driver> GetNextCars(int n)
|
||||
private List<Driver> GetNextCars(int steps)
|
||||
{
|
||||
var nextCars = new List<Driver>();
|
||||
TimeSpan updatedTime = _currentTime + TimeSpan.FromMinutes(stepTime);
|
||||
while (nextCars.Count < n && updatedTime < EndTime) {
|
||||
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.Contains(driver))
|
||||
updatedTime >= driver.Times[0].TimeOfDay &&
|
||||
!driver.Parked && !driver.Rejected)
|
||||
nextCars.Add(driver);
|
||||
updatedTime += TimeSpan.FromMinutes(stepTime);
|
||||
}
|
||||
|
||||
return nextCars;
|
||||
}
|
||||
@ -458,7 +517,7 @@ namespace Parking
|
||||
for (int j = 0; j < emergencyMap[i]; j++)
|
||||
if (i == 0) {
|
||||
Vector3 position = new(currentX, currentY + 2.25f / 2.0f, 0);
|
||||
spawnedSpot = Instantiate(Instance.spotPrefabC, position,
|
||||
Instantiate(Instance.spotPrefabC, position,
|
||||
Quaternion.Euler(new Vector3(0, 0, 90)), emergencyPlanContainer);
|
||||
|
||||
currentX -= 5;
|
||||
@ -481,6 +540,13 @@ namespace Parking
|
||||
|
||||
private List<List<Spot>> GenerateSpotMap(int[,] spotsCreated)
|
||||
{
|
||||
foreach (var list in _spotMap) {
|
||||
foreach (Spot spot in list)
|
||||
if (spot.GameObject != null)
|
||||
Destroy(spot.GameObject);
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
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++) {
|
||||
|
Loading…
Reference in New Issue
Block a user