public MovementStep(Person person, Tile sourceTile, Tile destinationTile) { Person = person; SourceTile = sourceTile; DestinationTile = destinationTile; Distance = sourceTile.DistanceTo(destinationTile); DistanceInMeters = Distance * GlobalVariables.BlockWidthInMeters; Person.PersonInteractionStats.DistanceTraveled += DistanceInMeters; }
public void PersonStart() { BuildingBlock block = new BuildingBlock(0,0); Person person = new Person(block); Assert.AreEqual(1,person.ID); Assert.AreEqual(false,person.Evacuated); Assert.AreEqual(new List<BuildingBlock>(), person.PathList); Tile tile = person.Position; Assert.AreEqual(0, tile.X); Assert.AreEqual(0, tile.Y); }
public Dictionary<int, Person> PrepareSimulation(IFloorPlan floorPlan) { if (UserInterface.BuildingHasBeenChanged) { TheFloorPlan.Initiate(); //Assign priority, and calculates neighbours, if the building has been changed. foreach (Tile tile in floorPlan.Tiles.Values) { tile.OriginalType = tile.Type; } } //adds all the new persons to the simulation foreach (Tile value in floorPlan.Tiles.Values.Where(t => t.OriginalType == Tile.Types.Person)) { if (AllPeople.Values.All(p => !Equals(p.OriginalPosition, value))) { Person newPerson = new Person(value as BuildingBlock); AllPeople.Add(newPerson.ID, newPerson); } } return AllPeople; }
/// <summary> /// Updates the visualisation of the building according to a persons step in the simulation. /// </summary> /// <param name="person"></param> private void UpdateVisualsOnEvacuatableMoved(Person person) { if (FirstTime) { foreach (Grid grid in _floorContainer) { foreach (Rectangle rect in grid.Children.Cast<Rectangle>()) { BuildingBlock current = LocalFloorPlan.Tiles[rect.Tag.ToString()] as BuildingBlock; rect.ToolTip = current?.Priority + " ," + current?.Room; } } FirstTime = false; } BuildingBlock prev = person.PathList[person.StepsTaken - 1]; BuildingBlock next = person.PathList[person.StepsTaken]; Rectangle prevRectangleToColorize; AllRectangles.TryGetValue(Coordinate(prev), out prevRectangleToColorize); if (prev.OriginalType == Tile.Types.Person) { prev.Type = Tile.Types.Free; if (_mainWindow.TheUserInterface.HeatMapActivated) ColorRectangle(prevRectangleToColorize, CalculateHeatMapColor(prev)); else ColorizeBuildingBlock(prevRectangleToColorize, Tile.Types.Free); } else { prev.Type = prev.OriginalType; if (_mainWindow.TheUserInterface.HeatMapActivated) ColorRectangle(prevRectangleToColorize, CalculateHeatMapColor(prev)); else ColorizeBuildingBlock(prevRectangleToColorize, prev.OriginalType); } Rectangle nextRectangleToColorize; AllRectangles.TryGetValue(Coordinate(next), out nextRectangleToColorize); if (next.OriginalType == Tile.Types.Exit || next.OriginalType == Tile.Types.Stair) { next.Type = next.OriginalType; ColorizeBuildingBlock(nextRectangleToColorize, next.OriginalType); } else { next.Type = Tile.Types.Person; ColorizeBuildingBlock(nextRectangleToColorize, next.Type); } }
//Subscribes to the correct simulation events, when evacuated is set to false, it subscrives to OnPersonMoved event. private void AddPersonToSimulation(Person person, IPathfinding pathfindingAlgorithm, int simulationSpeed) { person.Evacuated = false; person.OnPersonEvacuated += RemoveEvacuatedPerson; person.SimulationSpeed = simulationSpeed; person.OnExtendedPathRequest += FindNewPath; }
//Method using to person, when person is blocked more than 5 rounds. private IEnumerable<BuildingBlock> FindNewPath(Person person) { //Gets the personblocking's pathlist BuildingBlock target = person.PathList[person.StepsTaken + 1]; BuildingBlock pos = person.PathList[person.StepsTaken]; if (AllPeople.Values.Count(p => p.PathList.Count > p.StepsTaken + 1 && p.PathList[p.StepsTaken] == target && p.PathList[p.StepsTaken + 1] == pos) == 1) { Person personBlocking = AllPeople.Values.First(p => p.PathList[p.StepsTaken] == target); if (personBlocking.PathList.Count > 0 && (person.Position as BuildingBlock).BuildingBlockNeighbours.Any(n => n.Type != Tile.Types.Person)) { if (personBlocking.PathList.Count(b => b.Type != Tile.Types.Person) < person.PathList.Count(b => b.Type != Tile.Types.Person)) { person.PathList.Clear(); person.PathList.AddRange(personBlocking.PathList); person.StepsTaken = personBlocking.StepsTaken + 1; } } } return null; }
private static void RemoveEvacuatedPerson(Person person) { OnTick -= person.ConditionalMove; }
/// <summary> /// Updates the simulation stats, bar, evacuated people count etc. /// </summary> /// <param name="person"></param> private void UpdateSimulationStats(Person person) { int peopleCount = _parentWindow.TheUserInterface.LocalPeopleDictionary.Count(p => !p.Value.NoPathAvailable); PeopleWithNoPathAmount.Text = (_parentWindow.TheUserInterface.LocalPeopleDictionary.Count - peopleCount) + ""; TotalPersonCount.Text = peopleCount + ""; _fillWidthPerPerson = (PersonsEvacuatedProgressBarBackground.ActualWidth) / peopleCount; if (person.Evacuated) { if (!_evacuatedPeopleList.Contains(person)) { _evacuatedPeopleList.Add(person); double multiplier = 255f / peopleCount; double count = multiplier * _evacuatedPeopleList.Count; PersonsEvacuatedProgressBarFill.Fill = BarColor(count); PersonsEvacuatedProgressBarFill.Width = _fillWidthPerPerson * _evacuatedPeopleList.Count; CurrentNumberOfEvacuatedPersons.Text = _evacuatedPeopleList.Count + ""; double percentageEvacuated = ((double)_evacuatedPeopleList.Count) / peopleCount * 100; PersonsEvacuatedProgressBarText.Text = Math.Round(percentageEvacuated, 2) + "%"; person.PersonInteractionStats.TimeWhenEvacuated = _totalTimeElapsedField; } if (peopleCount == _evacuatedPeopleList.Count) { //Simulation has ended, so now we writes to the text file, uses stringbuilder all the way through UserInterface.HasSimulationEnded = true; UserInterface.IsSimulationReady = false; StringBuilder sb = new StringBuilder(); sb.AppendLine($"Statistics for simulation run at {DateTime.Now} by {Environment.UserName}{Environment.NewLine}"); double timeElapsed = _evacuatedPeopleList.Max(p => p.PersonInteractionStats.TimeWhenEvacuated); sb.AppendLine($"Time elapsed in simulation: {timeElapsed} seconds"); sb.AppendLine($"Amount of people: {_evacuatedPeopleList.Count}{Environment.NewLine}"); double quarterOfTimeElapsed = timeElapsed * 0.25; double halfOfTimeElapsed = timeElapsed * 0.50; double threeQuarterOfTimeElapsed = timeElapsed * 0.75; sb.AppendLine( $"Amount of people evacuated at {quarterOfTimeElapsed} seconds: " + $"{Math.Round((double)_evacuatedPeopleList.Count(p => p.PersonInteractionStats.TimeWhenEvacuated <= quarterOfTimeElapsed) / (double)_evacuatedPeopleList.Count * 100, 2)}%"); sb.AppendLine( $"Amount of people evacuated at {halfOfTimeElapsed} seconds: " + $"{Math.Round((double)_evacuatedPeopleList.Count(p => p.PersonInteractionStats.TimeWhenEvacuated <= halfOfTimeElapsed) / (double)_evacuatedPeopleList.Count * 100, 2)}%"); sb.AppendLine( $"Amount of people evacuated at {threeQuarterOfTimeElapsed} seconds: " + $"{Math.Round((double)_evacuatedPeopleList.Count(p => p.PersonInteractionStats.TimeWhenEvacuated <= threeQuarterOfTimeElapsed) / (double)_evacuatedPeopleList.Count * 100, 2)}%"); sb.AppendLine( $"Amount of people evacuated at {timeElapsed} seconds: " + $"{_evacuatedPeopleList.Count(p => p.PersonInteractionStats.TimeWhenEvacuated <= timeElapsed) / _evacuatedPeopleList.Count * 100}%"); double averageTime = _evacuatedPeopleList.Sum(p => p.PersonInteractionStats.TimeWhenEvacuated) / _evacuatedPeopleList.Count; sb.AppendLine($"Average evacuation time:{Math.Round(averageTime, 2)}"); double[] timearray = _evacuatedPeopleList.Select(p => p.PersonInteractionStats.TimeWhenEvacuated).ToArray(); var sortedTimearray = timearray.OrderBy(t => t); var median = sortedTimearray.ElementAt(sortedTimearray.Count() / 2); sb.AppendLine($"{Environment.NewLine}Evacuated before {median} seconds:"); foreach (Person person1 in _evacuatedPeopleList.Where(p => p.PersonInteractionStats.TimeWhenEvacuated < median)) { sb.AppendLine($"Person: {person1.ID} Time:{person1.PersonInteractionStats.TimeWhenEvacuated} seconds"); } sb.AppendLine($"{Environment.NewLine}Evacuated after or at {median} seconds:"); foreach (Person person1 in _evacuatedPeopleList.Where(p => p.PersonInteractionStats.TimeWhenEvacuated >= median)) { sb.AppendLine($"Person: {person1.ID} Time:{person1.PersonInteractionStats.TimeWhenEvacuated} seconds"); } Person personWithLongestDistance = _evacuatedPeopleList.OrderByDescending(p => p.PersonInteractionStats.DistanceTraveled).First(); Person personWithLongestTimeBeforeEvacuated = _evacuatedPeopleList.OrderByDescending(p => p.PersonInteractionStats.TimeWhenEvacuated).First(); sb.AppendLine($"{Environment.NewLine}Longest distance:{Environment.NewLine}" + $"{personWithLongestDistance.ID} - {personWithLongestDistance.PersonInteractionStats.DistanceTraveled} m{Environment.NewLine}"); sb.AppendLine($"Most time before evacuated: {Environment.NewLine}" + $"{personWithLongestTimeBeforeEvacuated.ID} - {personWithLongestTimeBeforeEvacuated.PersonInteractionStats.TimeWhenEvacuated} seconds{Environment.NewLine}"); foreach (Person person1 in _evacuatedPeopleList.OrderBy(p => p.ID)) { sb.AppendLine( "_____________________________________________________________________________________________________________"); int movementStepCounter = 0; sb.AppendLine( $"Person: {person1.ID}, Position{Settings.Coordinate(person.OriginalPosition)}{Environment.NewLine}" + $"Steps taken: {person1.StepsTaken}{Environment.NewLine}" + $"Distance traveled in meters: {person1.PersonInteractionStats.DistanceTraveled} m{Environment.NewLine}" + $"Movement speed: {Math.Round(person1.MovementSpeedInMetersPerSecond, 2)} m/s{Environment.NewLine}" + $"Time at evacuation: {person1.PersonInteractionStats.TimeWhenEvacuated} seconds{Environment.NewLine}" + $"Time waited because of blocked path: {Math.Round((double)person1.PersonInteractionStats.TicksWaited / SimulationSpeed.Value, 2)} seconds{Environment.NewLine}{Environment.NewLine}" + $"List of steps:"); foreach (MovementStep movementStep in person1.PersonInteractionStats.MovementSteps) { movementStepCounter++; sb.AppendLine( $"Step:{movementStepCounter} From: {Settings.Coordinate(movementStep.SourceTile)}\n" + $" - To: {Settings.Coordinate(movementStep.DestinationTile)}\n" + $" Distance in meters: {movementStep.DistanceInMeters} m{Environment.NewLine}" + $" Time at arrival: {Math.Round((double)movementStep.TicksAtArrival / SimulationSpeed.Value, 2)} seconds{Environment.NewLine}"); } } string stringToWrite = sb.ToString(); Directory.CreateDirectory(Environment.CurrentDirectory + @"\Statistics"); string nameOfStatsFile = $"{DateTime.Now.Day}-{DateTime.Now.Month}-{DateTime.Now.Year}.txt"; string path = Environment.CurrentDirectory + @"\Statistics\" + nameOfStatsFile; StatisticsTextbox.Text = $"Look at:{Environment.NewLine}{path}"; File.WriteAllText(path, stringToWrite); } } }