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 bool _emergencyActivated;
|
||||||
|
|
||||||
private int _initialConfigurationSpotCount;
|
private int _initialConfigurationSpotCount;
|
||||||
|
private int[,] _initialSolution;
|
||||||
private int[] _rejectedDrivers = {0, 0, 0, 0};
|
private int[] _rejectedDrivers = {0, 0, 0, 0};
|
||||||
|
private List<GameObject> _spotPrefabs;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@ -46,14 +48,17 @@ namespace Parking
|
|||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
|
_spotPrefabs = new List<GameObject> {spotPrefabA, spotPrefabB, spotPrefabC, spotPrefabD};
|
||||||
|
|
||||||
timeText.text = _currentTime.ToString();
|
timeText.text = _currentTime.ToString();
|
||||||
rejectedText.text = $"Małe: {_rejectedDrivers[0]} Średnie: {_rejectedDrivers[1]} " +
|
rejectedText.text = $"Małe: {_rejectedDrivers[0]} Średnie: {_rejectedDrivers[1]} " +
|
||||||
$"Duże: {_rejectedDrivers[2]}";
|
$"Duże: {_rejectedDrivers[2]}";
|
||||||
GenerateEmergencyPlan();
|
GenerateEmergencyPlan();
|
||||||
|
|
||||||
DataImporter.ReadFile("Assets/Data/Tablica4.csv");
|
DataImporter.ReadFile("Assets/Data/Tablica3.csv");
|
||||||
InitialConfigurationGenerator generator = new();
|
InitialConfigurationGenerator generator = new();
|
||||||
ArrangeSpots(generator.FindSolution());
|
_initialSolution = generator.FindSolution();
|
||||||
|
ArrangeSpots(_initialSolution);
|
||||||
ReserveInitialSpots();
|
ReserveInitialSpots();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +111,7 @@ namespace Parking
|
|||||||
mainPlanContainer.gameObject.SetActive(false);
|
mainPlanContainer.gameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
ArrangeSpots(_initialSolution);
|
||||||
ReserveInitialSpots();
|
ReserveInitialSpots();
|
||||||
ResetDrivers();
|
ResetDrivers();
|
||||||
}
|
}
|
||||||
@ -118,6 +124,8 @@ namespace Parking
|
|||||||
if (_emergencyActivated)
|
if (_emergencyActivated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ReconfigureSpots();
|
||||||
|
|
||||||
foreach (Driver driver in DataImporter.Drivers) {
|
foreach (Driver driver in DataImporter.Drivers) {
|
||||||
// TODO: Check if car can stay before other reservation - may not work for priority-based reservations
|
// TODO: Check if car can stay before other reservation - may not work for priority-based reservations
|
||||||
bool triesToPark = _currentTime <= driver.Times[3].TimeOfDay &&
|
bool triesToPark = _currentTime <= driver.Times[3].TimeOfDay &&
|
||||||
@ -129,11 +137,22 @@ namespace Parking
|
|||||||
&& !driver.Parked && !driver.Rejected && _currentTime <= driver.Times[3].TimeOfDay;
|
&& !driver.Parked && !driver.Rejected && _currentTime <= driver.Times[3].TimeOfDay;
|
||||||
if (triesToPark && !driver.Parked && !driver.Rejected) {
|
if (triesToPark && !driver.Parked && !driver.Rejected) {
|
||||||
if (!PlaceCarOnParking(driver)) {
|
if (!PlaceCarOnParking(driver)) {
|
||||||
Debug.Log($"Placing failed for car {driver.Number}");
|
if (TryReconfigureSpotForSize(driver.Size)) {
|
||||||
driver.Rejected = true;
|
if (!PlaceCarOnParking(driver)) {
|
||||||
_rejectedDrivers[(int) driver.Size]++;
|
Debug.Log($"Placing failed for car {driver.Number} size {driver.Size}");
|
||||||
rejectedText.text = $"Małe: {_rejectedDrivers[0]} Średnie: {_rejectedDrivers[1]} " +
|
driver.Rejected = true;
|
||||||
$"Duże: {_rejectedDrivers[2]}";
|
_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) {
|
else if (leftTheParking) {
|
||||||
@ -145,8 +164,21 @@ namespace Parking
|
|||||||
driver.Rejected = true;
|
driver.Rejected = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateCounts();
|
||||||
|
}
|
||||||
|
|
||||||
ReconfigureSpots();
|
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()
|
private void ResetDrivers()
|
||||||
@ -230,7 +262,7 @@ namespace Parking
|
|||||||
driver.GameObject = Instantiate(carPrefab);
|
driver.GameObject = Instantiate(carPrefab);
|
||||||
driver.GameObject.GetComponentInChildren<TextMeshProUGUI>().text = driver.Number.ToString();
|
driver.GameObject.GetComponentInChildren<TextMeshProUGUI>().text = driver.Number.ToString();
|
||||||
driver.GameObject.GetComponentInChildren<TextMeshProUGUI>().transform.rotation =
|
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 =
|
driver.GameObject.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.position = spot.GameObject.transform.position;
|
driver.GameObject.transform.position = spot.GameObject.transform.position;
|
||||||
@ -245,9 +277,8 @@ namespace Parking
|
|||||||
|
|
||||||
private void ReconfigureSpots()
|
private void ReconfigureSpots()
|
||||||
{
|
{
|
||||||
var prefabs = new List<GameObject> {spotPrefabA, spotPrefabB, spotPrefabC};
|
|
||||||
int[] freeSpots = GetFreeSpotCount();
|
int[] freeSpots = GetFreeSpotCount();
|
||||||
var nextCars = GetNextCars(10);
|
var nextCars = GetNextCars(1);
|
||||||
int[] plannedSpots = {0, 0, 0, 0};
|
int[] plannedSpots = {0, 0, 0, 0};
|
||||||
foreach (Driver driver in nextCars)
|
foreach (Driver driver in nextCars)
|
||||||
plannedSpots[(int) driver.Size]++;
|
plannedSpots[(int) driver.Size]++;
|
||||||
@ -256,54 +287,85 @@ namespace Parking
|
|||||||
|
|
||||||
for (int i = 0; i < neededSpots.Length; i++)
|
for (int i = 0; i < neededSpots.Length; i++)
|
||||||
neededSpots[i] = Math.Max(plannedSpots[i] - freeSpots[i], 0);
|
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($"Needed spots = {neededSpots[0]} {neededSpots[1]} {neededSpots[2]} {neededSpots[3]}");
|
||||||
Debug.Log("Attempting reconfiguration...");
|
Debug.Log("Attempting reconfiguration...");
|
||||||
|
|
||||||
for (int size = 0; size < 3; size++) {
|
var spotlessCars = new List<Driver>();
|
||||||
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;
|
|
||||||
|
|
||||||
float diff = (_spotHeights[(int) spot.Size] - _spotHeights[size]) / 2.0f;
|
// Filter drivers by assigning free space
|
||||||
if (!spot.AlignToTop)
|
foreach (Driver nextCar in nextCars)
|
||||||
diff *= -1;
|
if (freeSpots[(int) nextCar.Size] != 0)
|
||||||
|
freeSpots[(int) nextCar.Size]--;
|
||||||
|
else
|
||||||
|
spotlessCars.Add(nextCar);
|
||||||
|
|
||||||
spot.Size = (Size) size;
|
|
||||||
Vector3 position = Vector3.zero;
|
|
||||||
Quaternion rotation = Quaternion.identity;
|
|
||||||
if (spot.GameObject != null) {
|
|
||||||
position = spot.GameObject.transform.position;
|
|
||||||
rotation = spot.GameObject.transform.rotation;
|
|
||||||
Destroy(spot.GameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
spot.Reserved = false;
|
foreach (Driver nextCar in spotlessCars) {
|
||||||
|
TryReconfigureSpotForSize(nextCar.Size);
|
||||||
Vector3 offset;
|
|
||||||
if (spot.Perpendicular)
|
|
||||||
offset = new Vector3(0, diff, 0);
|
|
||||||
else
|
|
||||||
offset = new Vector3(-diff, 0, 0);
|
|
||||||
|
|
||||||
// TODO: check how much space to right to push
|
|
||||||
|
|
||||||
spot.GameObject = Instantiate(prefabs[size],
|
|
||||||
position + offset, rotation, mainPlanContainer);
|
|
||||||
|
|
||||||
goto whileEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
whileEnd: ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
diff *= -1;
|
||||||
|
|
||||||
|
spot.Size = (Size) size;
|
||||||
|
Vector3 position = Vector3.zero;
|
||||||
|
Quaternion rotation = Quaternion.identity;
|
||||||
|
if (spot.GameObject != null) {
|
||||||
|
position = spot.GameObject.transform.position;
|
||||||
|
rotation = spot.GameObject.transform.rotation;
|
||||||
|
Destroy(spot.GameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
spot.Reserved = false;
|
||||||
|
|
||||||
|
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(_spotPrefabs[size],
|
||||||
|
newPosition, rotation, mainPlanContainer);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private int[] GetFreeSpotCount()
|
private int[] GetFreeSpotCount()
|
||||||
{
|
{
|
||||||
int[] freeSpots = {0, 0, 0, 0};
|
int[] freeSpots = {0, 0, 0, 0};
|
||||||
@ -314,18 +376,15 @@ namespace Parking
|
|||||||
return freeSpots;
|
return freeSpots;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Driver> GetNextCars(int n)
|
private List<Driver> GetNextCars(int steps)
|
||||||
{
|
{
|
||||||
var nextCars = new List<Driver>();
|
var nextCars = new List<Driver>();
|
||||||
TimeSpan updatedTime = _currentTime + TimeSpan.FromMinutes(stepTime);
|
TimeSpan updatedTime = _currentTime + TimeSpan.FromMinutes(stepTime * steps);
|
||||||
while (nextCars.Count < n && updatedTime < EndTime) {
|
foreach (Driver driver in DataImporter.Drivers)
|
||||||
foreach (Driver driver in DataImporter.Drivers)
|
if (updatedTime <= driver.Times[1].TimeOfDay &&
|
||||||
if (updatedTime <= driver.Times[1].TimeOfDay &&
|
updatedTime >= driver.Times[0].TimeOfDay &&
|
||||||
updatedTime > driver.Times[0].TimeOfDay &&
|
!driver.Parked && !driver.Rejected)
|
||||||
!driver.Parked && !driver.Rejected && !nextCars.Contains(driver))
|
nextCars.Add(driver);
|
||||||
nextCars.Add(driver);
|
|
||||||
updatedTime += TimeSpan.FromMinutes(stepTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nextCars;
|
return nextCars;
|
||||||
}
|
}
|
||||||
@ -458,7 +517,7 @@ namespace Parking
|
|||||||
for (int j = 0; j < emergencyMap[i]; j++)
|
for (int j = 0; j < emergencyMap[i]; j++)
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
Vector3 position = new(currentX, currentY + 2.25f / 2.0f, 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);
|
Quaternion.Euler(new Vector3(0, 0, 90)), emergencyPlanContainer);
|
||||||
|
|
||||||
currentX -= 5;
|
currentX -= 5;
|
||||||
@ -481,6 +540,13 @@ namespace Parking
|
|||||||
|
|
||||||
private List<List<Spot>> GenerateSpotMap(int[,] spotsCreated)
|
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 i = 0; i < 4; i++)
|
||||||
for (int j = 0; j < spotsCreated.GetLength(1); j++)
|
for (int j = 0; j < spotsCreated.GetLength(1); j++)
|
||||||
for (int k = 0; k < spotsCreated[i, j]; k++) {
|
for (int k = 0; k < spotsCreated[i, j]; k++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user