Skip to content

Commit

Permalink
Merge pull request #115 from OliBomby/dev
Browse files Browse the repository at this point in the history
Dev update 1.7.0.1
  • Loading branch information
OliBomby authored Sep 1, 2020
2 parents 16573d2 + df5f98a commit 050f112
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 29 deletions.
108 changes: 90 additions & 18 deletions Mapping Tools/Classes/Tools/AutoFailDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public int GetEndTime() {
private List<ProblemArea> problemAreas;

private SortedSet<int> timesToCheckStartIndex;
private int?[] placementTimes;

public List<double> UnloadingObjects;
public List<double> PotentialUnloadingObjects;
Expand Down Expand Up @@ -172,6 +173,8 @@ public bool AutoFailFixDialogue(bool autoPlaceFix) {
if (problemAreas.Count == 0)
return false;

placementTimes = GetAllSafePlacementTimes();

int[] solution = SolveAutoFailPadding();
int paddingCount = solution.Sum();
bool acceptedSolution = false;
Expand Down Expand Up @@ -207,38 +210,71 @@ private void AddFixGuide(StringBuilder guideBuilder, IReadOnlyList<int> paddingS
guideBuilder.AppendLine("Auto-fail fix guide. Place these extra objects to fix auto-fail:\n");
int lastTime = 0;
for (int i = 0; i < problemAreas.Count; i++) {
guideBuilder.AppendLine(i == 0
? $"Extra objects before {problemAreas[i].GetStartTime()}: {paddingSolution[i]}"
: $"Extra objects between {lastTime} - {problemAreas[i].GetStartTime()}: {paddingSolution[i]}");
if (!(placementTimes != null && !placementTimes[i].HasValue)) {
guideBuilder.AppendLine(i == 0
? $"Extra objects before {problemAreas[i].GetStartTime()}: {paddingSolution[i]}"
: $"Extra objects between {lastTime} - {problemAreas[i].GetStartTime()}: {paddingSolution[i]}");
}
lastTime = GetAdjustedEndTime(problemAreas[i].unloadableHitObject) - approachTime;
}
guideBuilder.AppendLine($"Extra objects after {lastTime}: {paddingSolution.Last()}");

if (!(placementTimes != null && !placementTimes[placementTimes.Length - 1].HasValue)) {
guideBuilder.AppendLine($"Extra objects after {lastTime}: {paddingSolution.Last()}");
}
}

private void PlaceFixGuide(IReadOnlyList<int> paddingSolution) {
int lastTime = 0;
int lastTime = mapStartTime;
for (int i = 0; i < problemAreas.Count; i++) {
if (paddingSolution[i] > 0) {
var t = GetSafePlacementTime(lastTime, problemAreas[i].GetStartTime());
for (int j = 0; j < paddingSolution[i]; j++) {
hitObjects.Add(new HitObject { Pos = Vector2.Zero, Time = t, ObjectType = 8, EndTime = t - 1 });
var t = placementTimes != null ?
placementTimes[i] :
GetSafePlacementTime(lastTime, problemAreas[i].GetStartTime());
if (t.HasValue) {
for (int j = 0; j < paddingSolution[i]; j++) {
hitObjects.Add(
new HitObject {Pos = Vector2.Zero, Time = t.Value, ObjectType = 8, EndTime = t.Value - 1});
}
} else {
throw new Exception($"Can't find a safe place to place objects between {lastTime} and {problemAreas[i].GetStartTime()}.");
}
}

lastTime = GetAdjustedEndTime(problemAreas[i].unloadableHitObject) - approachTime;
}

if (paddingSolution.Last() > 0) {
var t = GetSafePlacementTime(lastTime, mapEndTime);
for (int i = 0; i < paddingSolution.Last(); i++) {
hitObjects.Add(new HitObject { Pos = Vector2.Zero, Time = t, ObjectType = 8, EndTime = t - 1 });
var t = placementTimes != null ?
placementTimes.Last() :
GetSafePlacementTime(lastTime, autoFailCheckTime - physicsTime);
if (t.HasValue) {
for (int i = 0; i < paddingSolution.Last(); i++) {
hitObjects.Add(new HitObject {Pos = Vector2.Zero, Time = t.Value, ObjectType = 8, EndTime = t.Value - 1});
}
} else {
throw new Exception($"Can't find a safe place to place objects between {lastTime} and {mapEndTime}.");
}
}

SortHitObjects();
}

private int GetSafePlacementTime(int start, int end) {
private int?[] GetAllSafePlacementTimes() {
int?[] allSafePlacementTimes = new int?[problemAreas.Count + 1];

int lastTime = mapStartTime;
for (int i = 0; i < problemAreas.Count; i++) {
var t = GetSafePlacementTime(lastTime, problemAreas[i].GetStartTime());
allSafePlacementTimes[i] = t;

lastTime = GetAdjustedEndTime(problemAreas[i].unloadableHitObject) - approachTime;
}
allSafePlacementTimes[allSafePlacementTimes.Length - 1] = GetSafePlacementTime(lastTime, autoFailCheckTime - physicsTime);

return allSafePlacementTimes;
}

private int? GetSafePlacementTime(int start, int end) {
var rangeObjects = hitObjects.FindAll(o => o.EndTime >= start && o.Time <= end);

for (int i = end - 1; i >= start; i--) {
Expand All @@ -249,7 +285,7 @@ private int GetSafePlacementTime(int start, int end) {
}
}

throw new Exception($"Can't find a safe place to place objects between {start} and {end}.");
return null;
}

private int[] SolveAutoFailPadding(int startPaddingCount = 0) {
Expand All @@ -276,12 +312,25 @@ private bool SolveAutoFailPadding(int paddingCount, out int[] solution) {
return false;
}

var lowest = problemAreaSolution.First(o => o >= leftPadding);
// The first element is always the lowest element equal or greater than leftPadding,
// because the single problem solver started iterating from leftPadding.
var lowest = problemAreaSolution.First();

// Check if placement is possible for this area and if not, assert 0 padding
if (placementTimes != null && !placementTimes[i].HasValue && lowest != leftPadding) {
return false;
}

solution[i] = lowest - leftPadding;
leftPadding = lowest;
}

solution[problemAreas.Count] = paddingCount - leftPadding;
// Check if placement is possible for the last area and if not, assert 0 padding
if (placementTimes != null && !placementTimes[placementTimes.Length - 1].HasValue && paddingCount != leftPadding) {
return false;
}

solution[solution.Length - 1] = paddingCount - leftPadding;

return true;
}
Expand Down Expand Up @@ -309,8 +358,22 @@ private IEnumerable<int[]> SolveAutoFailPaddingEnumerable(int paddingCount) {
yield break;
}

// The first element is always the lowest element equal or greater than minimalLeft,
// because the single problem solver started iterating from minimalLeft.
var lowest = problemAreaSolution.First();

// Check if placement is possible for this area and if not, assert 0 padding
if (placementTimes != null && !placementTimes[i].HasValue && lowest != minimalLeft) {
yield break;
}

allSolutions[i] = problemAreaSolution;
minimalLeft = problemAreaSolution.First();
minimalLeft = lowest;
}

// Check if placement is possible for the last area and if not, assert 0 padding
if (placementTimes != null && !placementTimes[placementTimes.Length - 1].HasValue && paddingCount != minimalLeft) {
yield break;
}

// Remove impossible max padding
Expand All @@ -328,21 +391,30 @@ private IEnumerable<int[]> SolveAutoFailPaddingEnumerable(int paddingCount) {
left = leftPadding[i];
}

// If there is no placement for the last area, assert 0 padding.
if (placementTimes != null && !placementTimes[placementTimes.Length - 1].HasValue && left != paddingCount) {
continue;
}

pads[pads.Length - 1] = paddingCount - left;
yield return pads;
}
}

private IEnumerable<int[]> EnumerateSolutions(IReadOnlyList<List<int>> allSolutions, int depth = 0, int minimum = 0) {
if (depth == allSolutions.Count - 1) {
foreach (var i in allSolutions[depth].Where(o => o >= minimum)) {
// Loop through all solutions which are greater or equal to the minimum or assert equal to paddingCount if there is no placement spot.
foreach (var i in allSolutions[depth].Where(o => o == minimum ||
!(placementTimes != null && !placementTimes[depth].HasValue) && o > minimum)) {
var s = new int[allSolutions.Count];
s[depth] = i;
yield return s;
}
yield break;
}
foreach (var i in allSolutions[depth].Where(o => o >= minimum)) {
// Loop through all solutions which are greater or equal to the minimum or assert equal to minimum if there is no placement spot.
foreach (var i in allSolutions[depth].Where(o => o == minimum ||
!(placementTimes != null && !placementTimes[depth].HasValue) && o > minimum)) {
foreach (var j in EnumerateSolutions(allSolutions, depth + 1, minimum = i)) {
j[depth] = i;
yield return j;
Expand Down
4 changes: 2 additions & 2 deletions Mapping Tools/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.7.0.0")]
[assembly: AssemblyFileVersion("1.7.0.0")]
[assembly: AssemblyVersion("1.7.0.1")]
[assembly: AssemblyFileVersion("1.7.0.1")]
[assembly: NeutralResourcesLanguage("en")]

Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
namespace Mapping_Tools.Views.AutoFailDetector {
[SmartQuickRunUsage(SmartQuickRunTargets.Always)]
public partial class AutoFailDetectorView : IQuickRun {
private List<double> _unloadingObjects = new List<double>();
private List<double> _potentialUnloadingObjects = new List<double>();
private List<double> _potentialDisruptors = new List<double>();
private List<double> _unloadingObjects;
private List<double> _potentialUnloadingObjects;
private List<double> _potentialDisruptors;
private double _endTimeMonitor;
private TimeLine _tl;

Expand Down Expand Up @@ -129,12 +129,9 @@ private string Run_Program(AutoFailDetectorVm args, BackgroundWorker worker, DoW
if (worker != null && worker.WorkerReportsProgress) worker.ReportProgress(67);

// Set the timeline lists
if (args.ShowUnloadingObjects)
_unloadingObjects = autoFailDetector.UnloadingObjects;
if (args.ShowPotentialUnloadingObjects)
_potentialUnloadingObjects = autoFailDetector.PotentialUnloadingObjects;
if (args.ShowPotentialDisruptors)
_potentialDisruptors = autoFailDetector.Disruptors;
_unloadingObjects = args.ShowUnloadingObjects ? autoFailDetector.UnloadingObjects : new List<double>();
_potentialUnloadingObjects = args.ShowPotentialUnloadingObjects ? autoFailDetector.PotentialUnloadingObjects : new List<double>();
_potentialDisruptors = args.ShowPotentialDisruptors ? autoFailDetector.Disruptors : new List<double>();

// Set end time for the timeline
_endTimeMonitor = mapEndTime;
Expand Down

0 comments on commit 050f112

Please sign in to comment.