JD2022-TU1/main/tools/apps/PleoLab/PleoLabForm.cs

990 lines
No EOL
37 KiB
C#

using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
namespace PleoLab
{
public partial class PleoLabForm : Form
{
#region GENERAL
string m_currentDragFilePath = "";
private const int m_drawEllipseSize = 10;
private const int m_curvePenSize = 2;
private const int m_starvePenSize = 5;
private const int EDITOR_INDEX = 0;
private const int REPORT_INDEX = 1;
public PleoLabForm()
{
InitializeComponent();
InitEditor();
InitReport();
}
private void StartSimulationMenuItem_Click(object sender, EventArgs e)
{
StartSimulationForm infos = new StartSimulationForm(
new Point(Left + Width / 2, Top + Height / 2));
infos.Show(this);
}
private void HelpMenuItem_Click(object sender, EventArgs e)
{
ToolHelpForm form = new ToolHelpForm(
new Point(Left + Width / 2, Top + Height / 2));
form.Show();
}
private void PopupMessage(string _header, string _message)
{
MessageBox.Show(_message, _header, MessageBoxButtons.OK);
}
private void PleoSimulatorTool_FormClosing(object sender, FormClosingEventArgs e)
{
if (m_editorFileNeedsSaving)
{
DialogResult msgBoxResult = EditorAskForSave();
if (msgBoxResult == DialogResult.Yes)
{
EditorSave();
}
else if (msgBoxResult == DialogResult.Cancel)
{
e.Cancel = true;
}
}
}
private void PleoSimulatorToolForm_DragEnter(object sender, DragEventArgs e)
{
string[] FileList = (string[])e.Data.GetData(DataFormats.FileDrop, false);
if (FileList.Count() == 1 && Path.GetExtension(FileList.First()) == ".xml")
{
m_currentDragFilePath = FileList.First();
e.Effect = DragDropEffects.Move;
}
else
{
m_currentDragFilePath = "";
e.Effect = DragDropEffects.None;
}
}
private void PleoSimulatorToolForm_DragDrop(object sender, DragEventArgs e)
{
if (m_currentDragFilePath != "")
{
XDocument doc = XDocument.Load(m_currentDragFilePath);
XElement simulationElem = doc.Element("Simulation");
if (doc.Element("Simulation") != null)
{
SimulationReadFile(m_currentDragFilePath);
}
else if(doc.Element("BandwidthCurves") != null)
{
if (m_editorFileNeedsSaving)
{
DialogResult msgBoxResult = EditorAskForSave();
if (msgBoxResult == DialogResult.Yes)
{
EditorSave();
}
else if (msgBoxResult == DialogResult.Cancel)
{
return;
}
}
EditorReadFile(m_currentDragFilePath);
}
}
}
private void DrawGrid(PaintEventArgs e, double _width, double _height)
{
double cellCount = 20.0;
double cellSizeX = _width / cellCount;
double cellSizeY = _height / cellCount;
Pen pen2 = new Pen(Color.FromArgb(50, 0, 0, 0), 1)
{
Alignment = PenAlignment.Center
};
for (int y = 0; y <= cellCount; ++y)
{
e.Graphics.DrawLine(pen2, 0, (int)(y * cellSizeY), (int)(cellCount * cellSizeX), (int)(y * cellSizeY));
}
for (int x = 0; x <= cellCount; ++x)
{
e.Graphics.DrawLine(pen2, (int)(x * cellSizeX), 0, (int)(x * cellSizeX), (int)(cellCount * cellSizeY));
}
}
private string GetMouseLocationString(double posX, double posY, double maxX, double maxY)
{
double percentageX = posX / maxX * 100.0;
double percentageY = (maxY - posY) / maxY * 100.0;
return "(" + Math.Round(percentageX, 2) + ", " + Math.Round(percentageY, 2) + ")";
}
#endregion
#region EDITOR VARIABLES
private int m_editorDrawAreaWidth;
private int m_editorDrawAreaHeight;
private CurveSet m_editorCurveSet = new CurveSet();
private string m_editorCurrentCurveName = "";
private Curve m_editorCurrentCurvePoints = new Curve();
private int m_editorCurrentPointIndex = -1;
private bool m_editorFileNeedsSaving = false;
#endregion
#region EDITOR FORM
private void EditorDrawArea_Paint(object sender, PaintEventArgs e)
{
base.OnPaint(e);
DrawGrid(e, m_editorDrawAreaWidth, m_editorDrawAreaHeight);
if (m_editorCurrentCurvePoints.Count > 0)
{
m_editorCurrentCurvePoints.Sort();
m_editorCurrentCurvePoints.RemoveAt(0);
m_editorCurrentCurvePoints.RemoveAt(m_editorCurrentCurvePoints.Count - 1);
if (m_editorCurrentCurvePoints.Count > 0)
{
m_editorCurrentCurvePoints.Insert(0, new Point(0, m_editorCurrentCurvePoints[0].Y));
m_editorCurrentCurvePoints.Add(new Point(m_editorDrawAreaWidth, m_editorCurrentCurvePoints[m_editorCurrentCurvePoints.Count - 1].Y));
}
}
if (m_editorCurrentCurvePoints.Count > 0)
{
// draw lines
Pen pen = new Pen(Color.Black)
{
Width = m_curvePenSize,
Alignment = PenAlignment.Center
};
e.Graphics.DrawLines(pen, m_editorCurrentCurvePoints.ToArray());
// draw points
SolidBrush brush = new SolidBrush(Color.Red);
for (int i = 0; i < m_editorCurrentCurvePoints.Count; ++i)
{
brush.Color = (i == m_editorCurrentPointIndex) ?
Color.Red
: Color.Black;
e.Graphics.FillEllipse(
brush,
new Rectangle(
new Point(m_editorCurrentCurvePoints[i].X - m_drawEllipseSize / 2, m_editorCurrentCurvePoints[i].Y - m_drawEllipseSize / 2),
new Size(m_drawEllipseSize, m_drawEllipseSize)));
}
}
}
private void EditorDrawArea_MouseClick(object sender, MouseEventArgs e)
{
if (m_editorCurrentCurveName != "")
{
if (e.Button == MouseButtons.Right)
{
if (m_editorCurrentCurvePoints.Count > 0)
{
m_editorFileNeedsSaving = true;
Point clickPoint = new Point(e.X, e.Y);
int indexToRemove = m_editorCurrentCurvePoints.FindClosestPointIndex(clickPoint);
m_editorCurrentCurvePoints.RemoveAt(indexToRemove);
}
}
else if (e.Button == MouseButtons.Left && !ModifierKeys.HasFlag(Keys.Control))
{
m_editorFileNeedsSaving = true;
m_editorCurrentCurvePoints.Add(new Point(e.X, e.Y));
m_editorCurrentCurvePoints.PreventXDuplicates();
m_editorCurrentCurvePoints.Sort();
if (m_editorCurrentCurvePoints.Count == 1)
{
m_editorCurrentCurvePoints.Insert(0, new Point(0, m_editorCurrentCurvePoints.First().Y));
m_editorCurrentCurvePoints.Add(new Point(m_editorDrawAreaWidth, m_editorCurrentCurvePoints.Last().Y));
}
}
Refresh();
}
}
private void EditorDrawArea_MouseMove(object sender, MouseEventArgs e)
{
bool doRefresh = false;
editorMousePositionTextBox.Text = GetMouseLocationString(
(double)e.Location.X,
(double)e.Location.Y,
(double)m_editorDrawAreaWidth,
(double)m_editorDrawAreaHeight);
if (m_editorCurrentCurveName != "")
{
int lastIndex = m_editorCurrentPointIndex;
Point clickPoint = new Point(e.X, e.Y);
m_editorCurrentPointIndex = m_editorCurrentCurvePoints.FindClosestPointIndex(clickPoint);
// refresh if the user is moving a point
if (m_editorCurrentPointIndex > 0
&& m_editorCurrentPointIndex < m_editorCurrentCurvePoints.Count - 1
&& Control.MouseButtons == MouseButtons.Left && ModifierKeys.HasFlag(Keys.Control))
{
m_editorFileNeedsSaving = true;
m_editorCurrentCurvePoints[m_editorCurrentPointIndex] = clickPoint;
m_editorCurrentCurvePoints.PreventXDuplicates();
m_editorCurrentCurvePoints.Sort();
doRefresh = true;
}
// refresh if the closest point to the cursor has changed
if (lastIndex != m_editorCurrentPointIndex)
{
doRefresh = true;
}
}
if (doRefresh)
{
Refresh();
}
}
private void EditorDrawArea_MouseLeave(object sender, EventArgs e)
{
m_editorCurrentPointIndex = -1;
Refresh();
}
private void EditorDrawPanelEditor_Resize(object sender, EventArgs e)
{
Control control = sender as Control;
if (control.Height > 0 && control.Width > 0)
{
for (int i = 0; i < m_editorCurrentCurvePoints.Count; ++i)
{
int newX = (int)((double)m_editorCurrentCurvePoints[i].X / (double)m_editorDrawAreaWidth * (double)control.Width);
int newY = (int)((double)m_editorCurrentCurvePoints[i].Y / (double)m_editorDrawAreaHeight * (double)control.Height);
m_editorCurrentCurvePoints[i] = new Point(newX, newY);
}
m_editorDrawAreaWidth = control.Width;
m_editorDrawAreaHeight = control.Height;
Refresh();
}
}
private void EditorButtonNewCurve_Click(object sender, EventArgs e)
{
if (m_editorCurrentCurveName != "")
{
EditorUpdateCurveSet();
}
m_editorFileNeedsSaving = true;
m_editorCurrentCurvePoints = new Curve();
int newNameNumber = 1;
string newCurveNamePre = "New Curve";
string newCurveName = newCurveNamePre;
while (m_editorCurveSet.Curves.ContainsKey(newCurveName))
{
newCurveName = newCurveNamePre + " " + (++newNameNumber);
}
m_editorCurrentCurveName = newCurveName;
m_editorCurveSet.Curves.Add(m_editorCurrentCurveName, new List<Vector2>());
foreach (ListViewItem item in curvesListView.Items)
{
item.Selected = false;
}
ListViewItem newCurve = new ListViewItem()
{
Text = m_editorCurrentCurveName,
Selected = true
};
curvesListView.Items.Add(newCurve);
curvesListView.Select();
Refresh();
}
private void EditorClearButton_Click(object sender, EventArgs e)
{
m_editorFileNeedsSaving = true;
m_editorCurrentCurvePoints.Clear();
Refresh();
}
private void EditorDeleteCurveButton_Click(object sender, EventArgs e)
{
if (m_editorCurveSet.Curves.ContainsKey(m_editorCurrentCurveName))
{
m_editorFileNeedsSaving = true;
m_editorCurveSet.Curves.Remove(m_editorCurrentCurveName);
// it is necessary to save the current curve name to a temporary and setting it to "" before removing it from the curvesListView
// because the removal triggers a curvesListView selectedIndexChanged callback, which saves the current curve if it's name is not ""
string currentCurveName = m_editorCurrentCurveName;
m_editorCurrentCurveName = "";
m_editorCurrentCurvePoints.Clear();
curvesListView.Items.Remove(curvesListView.Items.OfType<ListViewItem>().FirstOrDefault(i => i.Text == currentCurveName));
if (curvesListView.Items.Count > 0)
{
curvesListView.Items[0].Selected = true;
curvesListView.Select();
}
Refresh();
}
}
private void EditorCurvesListBox_SelectedIndexChanged(object sender, EventArgs e)
{
EditorUpdateCurveSet();
if (curvesListView.SelectedIndices.Count > 0)
{
m_editorCurrentCurveName = curvesListView.SelectedItems[0].Text;
m_editorCurrentCurvePoints = new Curve(m_editorCurveSet.Curves[m_editorCurrentCurveName], m_editorDrawAreaWidth, m_editorDrawAreaHeight);
Refresh();
}
}
private void EditorOpenMenuItem_Click(object sender, EventArgs e)
{
if (m_editorFileNeedsSaving)
{
DialogResult saveIsNeeded = EditorAskForSave();
if (saveIsNeeded == DialogResult.Yes)
{
EditorSave();
}
else if (saveIsNeeded == DialogResult.Cancel)
{
return;
}
}
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
EditorReadFile(openFileDialog.FileName);
m_editorFileNeedsSaving = false;
}
}
private void EditorSaveAsMenuItem_Click(object sender, EventArgs e)
{
EditorSave(true);
}
private void EditorSaveMenuItem_Click(object sender, EventArgs e)
{
EditorSave();
}
private void EditorCurvesListBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.F2 && curvesListView.SelectedItems.Count > 0)
{
curvesListView.SelectedItems[0].BeginEdit();
}
}
private void EditorCurvesListBox_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (curvesListView.SelectedItems.Count > 0)
{
curvesListView.SelectedItems[0].BeginEdit();
}
}
private void EditorCurvesListBox_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
if (e.Label == null || e.Label == "" || m_editorCurveSet.Curves.ContainsKey(e.Label.ToString()))
{
e.CancelEdit = true;
}
else
{
m_editorCurveSet.Curves.Remove(m_editorCurrentCurveName);
m_editorCurrentCurveName = e.Label.ToString();
m_editorCurveSet.Curves[m_editorCurrentCurveName] = m_editorCurrentCurvePoints.GetNormalizedCurve(m_editorDrawAreaWidth, m_editorDrawAreaHeight);
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.D1)
{
editorButtonNew.PerformClick();
return true;
}
if (keyData == Keys.D2)
{
editorButtonClear.PerformClick();
return true;
}
if (keyData == Keys.D3)
{
editorButtonDelete.PerformClick();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
#endregion
#region EDITOR UTILS
private void InitEditor()
{
m_editorDrawAreaWidth = drawPanelEditor.Width;
m_editorDrawAreaHeight = drawPanelEditor.Height;
labelFileName.Text = "";
}
private void EditorReadFile(string _filePath)
{
curvesListView.Items.Clear();
try
{
m_editorCurveSet.ReadFile(_filePath);
foreach (string name in m_editorCurveSet.Curves.Keys)
{
curvesListView.Items.Add(name);
}
labelFileName.Text = m_editorCurveSet.FileName;
if (m_editorCurveSet.Curves.Count > 0)
{
m_editorCurrentCurveName = m_editorCurveSet.Curves.First().Key;
m_editorCurrentCurvePoints = new Curve(m_editorCurveSet.Curves.First().Value, m_editorDrawAreaWidth, m_editorDrawAreaHeight);
curvesListView.Items.OfType<ListViewItem>().FirstOrDefault(i => i.Text == m_editorCurrentCurveName).Selected = true;
curvesListView.Select();
}
tabControlPleoLab.SelectedIndex = EDITOR_INDEX;
Refresh();
}
catch (FileNotFoundException exception)
{
PopupMessage("Error when opening the file", "Are you sure the path (" + exception.FileName + ") exists ?");
m_editorCurveSet.Curves.Clear();
}
catch (Exception)
{
PopupMessage("Error while parsing the file", "Are you sure your xml file is in a valid format ?");
m_editorCurveSet.Curves.Clear();
}
}
private void EditorUpdateCurveSet()
{
if (m_editorCurrentCurveName != "")
{
m_editorCurrentCurvePoints.Sort();
m_editorCurveSet.Curves[m_editorCurrentCurveName] = m_editorCurrentCurvePoints.GetNormalizedCurve(m_editorDrawAreaWidth, m_editorDrawAreaHeight);
return;
}
}
private void EditorSave(bool _saveAs = false)
{
EditorUpdateCurveSet();
bool canSave = true;
if (m_editorCurveSet.Curves.Count == 0)
{
PopupMessage("Error !", "You need curves to save !");
canSave = false;
}
else if (m_editorCurveSet.Curves.Values.Any(pointList => pointList.Count == 0))
{
PopupMessage("Error !", "You cannot save a file with empty curves !");
canSave = false;
}
if (canSave)
{
// save as new file
if (m_editorCurveSet.FileName == "" || _saveAs)
{
canSave = CreateFile();
}
if (canSave)
{
m_editorCurveSet.WriteToFile();
m_editorFileNeedsSaving = false;
}
}
}
private bool CreateFile()
{
bool fileCreated = false;
saveFileDialog.Filter = "xml files (*.xml)|*.xml";
saveFileDialog.FilterIndex = 2;
saveFileDialog.RestoreDirectory = true;
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
m_editorCurveSet.CreateFile(saveFileDialog.FileName);
labelFileName.Text = m_editorCurveSet.FileName;
fileCreated = true;
}
return fileCreated;
}
private DialogResult EditorAskForSave()
{
MessageBoxButtons buttons = MessageBoxButtons.YesNoCancel;
return MessageBox.Show("Would you like to save first ?", "", buttons);
}
#endregion
#region SIMULATION VARIABLES
private SimulationReport m_simulation;
private int m_simulationDrawAreaWidth;
private int m_simulationDrawAreaHeight;
private Curve m_simulationCurve = new Curve();
private List<RepresentationEvent> m_simulationRepresentationChanges = new List<RepresentationEvent>();
private List<RepresentationEvent> m_simulationRepresentationAdditions = new List<RepresentationEvent>();
private List<Curve> m_simulationStarvings = new List<Curve>();
private List<Point> m_simulationBufferTimeChanges = new List<Point>();
private Color m_simulationQualityColorLow = Color.FromArgb(150, 242, 41, 41); // red
private Color m_simulationQualityColorMid = Color.FromArgb(150, 242, 149, 29); // orange
private Color m_simulationQualityColorHigh = Color.FromArgb(150, 239, 209, 16); // yellow
private Color m_simulationQualityColorUltra = Color.FromArgb(150, 146, 239, 15); // green
private Pen m_simulationCurvePen = new Pen(Color.Black, m_curvePenSize);
private Pen m_simulationBufferPen = new Pen(Color.Blue, m_curvePenSize);
private Pen m_simulationStarvePen = new Pen(Color.Red, m_starvePenSize);
#endregion
#region SIMULATOR REPORT FORM
private void SimulationDrawPanel_Paint(object sender, PaintEventArgs e)
{
base.OnPaint(e);
DrawGrid(e, m_simulationDrawAreaWidth, m_simulationDrawAreaHeight);
if (m_simulationCurve.Count != 0)
{
// draw curve lines
e.Graphics.DrawLines(m_simulationCurvePen, m_simulationCurve.ToArray());
}
if (m_simulationBufferTimeChanges.Count != 0 && checkBoxShowBufferTime.Checked)
{
// draw curve lines
e.Graphics.DrawLines(m_simulationBufferPen, m_simulationBufferTimeChanges.ToArray());
}
if (buttonRepresentationChanges.Checked)
{
// draw representation changes
DrawRepresentation(m_simulationRepresentationChanges, e);
}
else if (buttonRepresentationAdditions.Checked)
{
// draw representation additions
DrawRepresentation(m_simulationRepresentationAdditions, e);
}
if (m_simulationStarvings.Count != 0)
{
// draw starving lines
SolidBrush brush = new SolidBrush(Color.Red);
for (int i = 0; i < m_simulationStarvings.Count; ++i)
{
e.Graphics.DrawLines(m_simulationStarvePen, m_simulationStarvings[i].ToArray());
}
}
}
private void SimulationDrawPanel_Resize(object sender, EventArgs e)
{
Control control = sender as Control;
m_simulationDrawAreaWidth = control.Width;
m_simulationDrawAreaHeight = control.Height;
UpdateDrawnSimulation();
Refresh();
}
private void SimulationOpenMenuItem_Click(object sender, EventArgs e)
{
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
SimulationReadFile(openFileDialog.FileName);
}
}
private void SimulationListBoxCurves_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateDrawnSimulation();
}
private void SimulationListBoxMaps_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateDrawnSimulation();
}
private void SimulationListBoxAlgos_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateDrawnSimulation();
}
private void SimulationButtonColorLow_Click(object sender, EventArgs e)
{
UpdateColor(ref m_simulationQualityColorLow, buttonColorLow);
}
private void SimulationButtonColorMid_Click(object sender, EventArgs e)
{
UpdateColor(ref m_simulationQualityColorMid, buttonColorMid);
}
private void SimulationButtonColorHigh_Click(object sender, EventArgs e)
{
UpdateColor(ref m_simulationQualityColorHigh, buttonColorHigh);
}
private void SimulationButtonColorUltra_Click(object sender, EventArgs e)
{
UpdateColor(ref m_simulationQualityColorUltra, buttonColorUltra);
}
private void ButtonRepresentationChanges_CheckedChanged(object sender, EventArgs e)
{
UpdateDrawnSimulation();
}
private void ButtonRepresentationAdditions_CheckedChanged(object sender, EventArgs e)
{
UpdateDrawnSimulation();
}
private void CheckBoxShowBufferTime_CheckedChanged(object sender, EventArgs e)
{
UpdateDrawnSimulation();
}
private void SimulatorDrawArea_MouseMove(object sender, MouseEventArgs e)
{
reportMousePositionTextBox.Text = GetMouseLocationString(
(double)e.Location.X,
(double)e.Location.Y,
(double)m_simulationDrawAreaWidth,
(double)m_simulationDrawAreaHeight);
}
#endregion
#region SIMULATION RESULTS UTILS
private void InitReport()
{
m_simulationDrawAreaWidth = drawPanelSimulation.Width;
m_simulationDrawAreaHeight = drawPanelSimulation.Height;
totalRunStarveDuration.Text = "";
labelRunDuration.Text = "";
labelMaxBandwidth.Text = "";
buttonColorLow.BackColor = m_simulationQualityColorLow;
buttonColorMid.BackColor = m_simulationQualityColorMid;
buttonColorHigh.BackColor = m_simulationQualityColorHigh;
buttonColorUltra.BackColor = m_simulationQualityColorUltra;
m_simulationCurvePen.Alignment = PenAlignment.Center;
m_simulationBufferPen.Alignment = PenAlignment.Center;
m_simulationStarvePen.Alignment = PenAlignment.Center;
}
List<RepresentationEvent> GetScaledRepresentationEvents(List<RepresentationEvent> _representations, double _clipDuration)
{
List<RepresentationEvent> scaledList = new List<RepresentationEvent>();
foreach (RepresentationEvent rep in _representations)
{
double xPos = (int)(rep.timeStamp / _clipDuration * m_simulationDrawAreaWidth);
RepresentationEvent scaledRep = new RepresentationEvent(rep.name, xPos);
scaledList.Add(scaledRep);
}
return scaledList;
}
List<Point> GetScaledBufferTimeChanges(List<BufferTimeChange> _bufferTimeChanges, double _clipDuration)
{
List<Point> scaledList = new List<Point>();
double maxTime = _bufferTimeChanges.Max(b => b.bufferTime);
foreach (var buffer in _bufferTimeChanges)
{
scaledList.Add(
new Point((int)(
buffer.timeStamp / _clipDuration * m_simulationDrawAreaWidth),
m_simulationDrawAreaHeight - (int)(buffer.bufferTime / maxTime * (double)m_simulationDrawAreaHeight)));
}
return scaledList;
}
private Tuple<int, int> GetSurroundingPointsIndexes(Point _point)
{
int previousIndex = Math.Max(m_simulationCurve.points.FindLastIndex(point => point.X <= _point.X), 0);
int nextIndex = Math.Min(m_simulationCurve.points.FindIndex(previousIndex, point => point.X > _point.X), m_simulationCurve.Count - 1);
return new Tuple<int, int>(previousIndex, nextIndex);
}
private Point ProjectOnCurve(Point _point, int _previousIndex, int _nextIndex)
{
int y = (int)EditorUtils.Lerp(
m_simulationCurve[_previousIndex].Y,
m_simulationCurve[_nextIndex].Y,
(double)(_point.X - m_simulationCurve[_previousIndex].X) / (double)(m_simulationCurve[_nextIndex].X - m_simulationCurve[_previousIndex].X));
return new Point(_point.X, y);
}
List<Curve> ComputeSimulationStarveSegments(List<Starve> _starves, double _runDuration)
{
List<Curve> starveCurves = new List<Curve>();
foreach (Starve starve in _starves)
{
// scaling starving points to the screen width and height
Curve starving = new Curve();
Point startPoint = new Point((int)(starve.start / _runDuration * m_simulationDrawAreaWidth), m_simulationDrawAreaHeight / 2);
Point endPoint = new Point((int)(starve.end / _runDuration * m_simulationDrawAreaWidth), m_simulationDrawAreaHeight / 2);
if (m_simulationCurve.Count > 0)
{
/*
* This part enables starving segments to be drawn on the simulation curve
* We look in the simulation curve for the closest 2 points (previous and next) from start and end points of each starve segments.
* We then scale start and end points of the starve segments with the previous and next points
*
* We then look for points in the simulation curve between start and end points of each starve curves
* If points are found, they are added to the starve segment
* */
var startIndexes = GetSurroundingPointsIndexes(startPoint);
var endIndexes = GetSurroundingPointsIndexes(endPoint);
startPoint = ProjectOnCurve(startPoint, startIndexes.Item1, startIndexes.Item2);
endPoint = ProjectOnCurve(endPoint, endIndexes.Item1, endIndexes.Item2);
starving.Add(startPoint);
starving.points.AddRange(m_simulationCurve.points.GetRange(startIndexes.Item2, endIndexes.Item2 - startIndexes.Item2));
starving.Add(endPoint);
}
else
{
starving.Add(startPoint);
starving.Add(endPoint);
}
starveCurves.Add(starving);
}
return starveCurves;
}
private double GetTotalStarveTime(double _runDuration)
{
double totalStarveTime = 0;
foreach (Curve starve in m_simulationStarvings)
{
totalStarveTime += (starve.Last().X - starve.First().X) * _runDuration / m_simulationDrawAreaWidth;
}
return totalStarveTime;
}
private void UpdateDrawnSimulation()
{
if (listBoxMaps.Text == "" || listBoxAlgos.Text == "")
{
return;
}
string selectedCurve = listBoxCurves.Text;
string selectedMap = listBoxMaps.Text;
string selectedAlgo = listBoxAlgos.Text;
RunStats selectedRunStats = null;
VideoStatistics videoStat = m_simulation.GetVideoStatistics(selectedMap);
selectedRunStats = videoStat.GetRunStats(selectedCurve, selectedAlgo);
// getting simulation curve and scaling it
m_simulationCurve = new Curve(
m_simulation.GetBandwidthCurve(selectedCurve),
(int)((double)m_simulationDrawAreaWidth * (double)videoStat.Duration / (double)selectedRunStats.Duration),
m_simulationDrawAreaHeight);
if (m_simulationCurve.Count > 0)
{
m_simulationCurve.Add(new Point(m_simulationDrawAreaWidth, m_simulationCurve.points.Last().Y));
}
// getting representation changes and scaling them
m_simulationRepresentationChanges = GetScaledRepresentationEvents(selectedRunStats.RepresentationChangeTimeStamps, videoStat.Duration);
m_simulationRepresentationAdditions = GetScaledRepresentationEvents(selectedRunStats.RepresentationAdditionTimeStamps, videoStat.Duration);
// getting buffer time changes and scaling them
m_simulationBufferTimeChanges = GetScaledBufferTimeChanges(selectedRunStats.BufferTimeChanges, videoStat.Duration);
// getting starve timings changes and scaling them
m_simulationStarvings = ComputeSimulationStarveSegments(selectedRunStats.StarveTimeStamps, selectedRunStats.Duration);
// getting general informations about the run
double totalStarveTime = GetTotalStarveTime(selectedRunStats.Duration);
totalRunStarveDuration.Text = "Total run starve duration : " + Math.Round(totalStarveTime, 2);
labelRunDuration.Text = "Run Duration : " + Math.Round(selectedRunStats.Duration, 2) + " s";
labelMaxBandwidth.Text = "Max Bandwidth : " + m_simulation.MaxBandwidthSpeed + " bps";
Refresh();
}
public void SimulationReadFile(string _fileName)
{
m_simulationCurve.Clear();
m_simulationRepresentationChanges.Clear();
m_simulationRepresentationAdditions.Clear();
m_simulationBufferTimeChanges.Clear();
m_simulationStarvings.Clear();
listBoxCurves.Items.Clear();
listBoxMaps.Items.Clear();
listBoxAlgos.Items.Clear();
m_simulation = new SimulationReport();
try
{
m_simulation.ReadReportFile(_fileName, m_simulationDrawAreaWidth, m_simulationDrawAreaHeight);
listBoxCurves.Items.AddRange(m_simulation.CurveSet.ToArray());
listBoxMaps.Items.AddRange(m_simulation.MapSet.ToArray());
listBoxAlgos.Items.AddRange(m_simulation.AlgoSet.ToArray());
if (listBoxCurves.Items.Count > 0)
{
listBoxCurves.SelectedIndex = 0;
}
if (listBoxMaps.Items.Count > 0)
{
listBoxMaps.SelectedIndex = 0;
}
if (listBoxAlgos.Items.Count > 0)
{
listBoxAlgos.SelectedIndex = 0;
}
tabControlPleoLab.SelectedIndex = REPORT_INDEX;
UpdateDrawnSimulation();
}
catch (FileNotFoundException exception)
{
PopupMessage("Error when trying opening the file", "Are you sure the path " + exception.FileName + " exists ?");
return;
}
catch (Exception exception)
{
PopupMessage("Error while parsing file", "Are you sure your xml file is in a valid format ?\n" + exception.Message);
return;
}
}
Color GetQualityColor(string _quality)
{
Color retval = Color.Black;
if (_quality == "VideoRepresentationID_LOW")
{
retval = m_simulationQualityColorLow;
}
else if (_quality == "VideoRepresentationID_MID")
{
retval = m_simulationQualityColorMid;
}
else if (_quality == "VideoRepresentationID_HIGH")
{
retval = m_simulationQualityColorHigh;
}
else if (_quality == "VideoRepresentationID_ULTRA")
{
retval = m_simulationQualityColorUltra;
}
return retval;
}
private void DrawRepresentation(List<RepresentationEvent> representation, PaintEventArgs e)
{
Rectangle rect;
// draw representation changes lines
for (int i = 0; i < representation.Count; ++i)
{
SolidBrush brush = new SolidBrush(GetQualityColor(representation[i].name));
if (i == representation.Count - 1)
{
rect = new Rectangle(
(int)representation[representation.Count - 1].timeStamp,
0,
(int)(m_simulationDrawAreaWidth - representation[representation.Count - 1].timeStamp),
m_simulationDrawAreaHeight);
}
else
{
rect = new Rectangle(
(int)representation[i].timeStamp,
0,
(int)(representation[i + 1].timeStamp - representation[i].timeStamp),
m_simulationDrawAreaHeight);
}
e.Graphics.FillRectangle(brush, rect);
}
}
private void UpdateColor(ref Color _simulationColor, Button _button)
{
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
_simulationColor = Color.FromArgb(150, colorDialog1.Color);
_button.BackColor = _simulationColor;
UpdateDrawnSimulation();
}
}
#endregion
}
}