/// <summary> /// Handle the mouse click on our component /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void lvHistory_MouseClick(object sender, MouseEventArgs e) { ListViewHitTestInfo hti = lvHistory.HitTest(e.Location); if (hti.Item != null && e.Button == MouseButtons.Right) { MM_UserInteraction FoundInteraction = hti.Item as MM_UserInteraction; MM_Substation FoundSub = FoundInteraction.Elem.Substation; if (FoundSub == null) { return; } PopupMenu.Show(this, e.Location, FoundSub, true); } }
/// <summary> /// Handle the user's response /// </summary> /// <param name="LngLat"></param> public void HandleResponse(PointF LngLat) { //If we're a substation, find our position relative to the sub Double Dist; UserAnswer = LngLat; if (TargetElement is MM_Substation) { Dist = (TargetElement as MM_Substation).DistanceTo(LngLat); CorrectAnswer = (TargetElement as MM_Substation).LngLat; } else { MM_Line TargetLine = (MM_Line)TargetElement; Dist = MM_Substation.ComputeDistance(LngLat, CorrectAnswer = new PointF((TargetLine.Substation1.Longitude + TargetLine.Substation2.Longitude) / 2f, (TargetLine.Substation1.Latitude + TargetLine.Substation2.Latitude) / 2f)); } //Now, check through our list of reponses, and see if we made it QuestionsAnswered++; if (Dist > CurrentLevel.NoScoreThreshold) { AnswerText = "Sorry! You were " + Dist.ToString("#,##0.0") + " miles away."; TimeQuestionPresented = DateTime.Now; TrainingMode = enumTrainingMode.AnswerWrong; QuestionsWrong++; } else { double TotalScore; if (Dist <= CurrentLevel.BullsEyeThresholdDistance) { TotalScore = CurrentLevel.UpperScoreValue; } else { double XPercentile = (Dist - CurrentLevel.BullsEyeThresholdDistance) / (CurrentLevel.NoScoreThreshold - CurrentLevel.BullsEyeThresholdDistance); TotalScore = ((CurrentLevel.LowerScoreValue - CurrentLevel.UpperScoreValue) * XPercentile) + CurrentLevel.UpperScoreValue; } double TimeScore = CurrentLevel.MaximumTimeScore * ((CurrentLevel.QuestionTimeout - TimeSincePresentation) / CurrentLevel.QuestionTimeout); Score += TimeScore + TotalScore; LevelScore += TimeScore + TotalScore; QuestionsRight += 1; AnswerText = "Correct! You were " + Dist.ToString("#,##0.0") + " miles away (" + TotalScore.ToString("0") + " pts; bonus " + TimeScore.ToString("0") + " pts)"; TimeQuestionPresented = DateTime.Now; TrainingMode = enumTrainingMode.AnswerCorrect; } }
/// <summary> /// Handle the left mouse double-click by opening up our one-line /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void lvHistory_MouseDoubleClick(object sender, MouseEventArgs e) { ListViewHitTestInfo hti = lvHistory.HitTest(e.Location); if (hti.Item == null || e.Button != MouseButtons.Left) { return; } MM_UserInteraction FoundInteraction = hti.Item as MM_UserInteraction; MM_Substation FoundSub = FoundInteraction.Elem.Substation; if (FoundSub == null) { return; } MM_Form_Builder.OneLine_Display(FoundSub, Program.MM.ctlNetworkMap); }
/// <summary> /// Update the status of our element /// </summary> /// <param name="SelectedElement"></param> public void UpdateElement(MM_Element SelectedElement) { //Show our element in our selection list lblElementValue.Text = SelectedElement.ToString(); if (SelectedElement is MM_Substation) { MM_Substation BaseSubstation = SelectedElement as MM_Substation; txtSubLatitude.Visible = txtSubLongitude.Visible = true; txtSubLongitude.Text = BaseSubstation.Longitude.ToString(); txtSubLatitude.Text = BaseSubstation.Latitude.ToString(); dgvLineLngLat.Visible = false; } else { MM_Line BaseLine = SelectedElement as MM_Line; txtSubLatitude.Visible = txtSubLongitude.Visible = false; dgvLineLngLat.Visible = true; LineCoordinates.Rows.Clear(); for (int a = 0; a < BaseLine.Coordinates.Count; a++) { LineCoordinates.Rows.Add(a, BaseLine.Coordinates[a].Y, BaseLine.Coordinates[a].X); } } }
/// <summary> /// Initialize a new substation /// </summary> /// <param name="Substation"></param> public MM_Operatorship_Display_Substation(MM_Substation Substation) { this.Substation = Substation; }
/// <summary> /// When the primary/secondary path is selected, display all of our elements /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void cmbPrimarySecondary_SelectedIndexChanged(object sender, EventArgs e) { try { lvItems.Columns.Clear(); lvItems.Items.Clear(); lvItems.View = View.Details; lvItems.Columns.Add("#"); lvItems.Columns.Add("Action"); lvItems.Columns.Add("Subsatation"); lvItems.Columns.Add("Type"); lvItems.Columns.Add("Element"); lvItems.Columns.Add("Operator"); lvItems.FullRowSelect = true; lvItems.CheckBoxes = true; MM_Blackstart_Corridor_Target Target = cmbCorridorTarget.SelectedItem as MM_Blackstart_Corridor_Target; FieldInfo fI = Target.GetType().GetField(cmbPrimarySecondary.Text); if (Target != null && fI != null) { MM_Blackstart_Corridor_Element[] Elems = fI.GetValue(Target) as MM_Blackstart_Corridor_Element[]; MM_Substation LastSub = null; for (int a = 0; a < Elems.Length; a++) { try { ListViewItem lvI = new ListViewItem((a + 1).ToString("#,##0")); lvI.UseItemStyleForSubItems = true; if (MM_Server_Interface.Client != null && Array.IndexOf(Data_Integration.UserOperatorships, 999999) == -1 && Array.IndexOf(Data_Integration.UserOperatorships, Elems[a].AssociatedElement.Operator.TEID) == -1) { lvI.ForeColor = Color.Gray; } lvI.SubItems.Add(Elems[a].Action.ToString()); if (Elems[a].AssociatedElement != null) { MM_Element Elem = Elems[a].AssociatedElement; if (Elem is MM_Line) { MM_Line Line = (MM_Line)Elem; if (LastSub == Line.Substation2) { lvI.SubItems.Add(Line.Substation2.Name + " to " + Line.Substation1.Name); } else { lvI.SubItems.Add(Line.Substation1.Name + " to " + Line.Substation2.Name); } LastSub = Line.Substation2; } else { lvI.SubItems.Add(Elem.Substation.Name); LastSub = Elem.Substation; } lvI.SubItems.Add(Elem.ElemType.Name); lvI.SubItems.Add(MM_Repository.TitleCase(Elem.Name)); lvI.SubItems.Add(Elem.Operator.Alias.Substring(0, 1) + MM_Repository.TitleCase(Elem.Operator.Alias.Substring(1))); } else { if (Elems[a].Substation == null) { lvI.SubItems.Add("?"); } else { lvI.SubItems.Add(MM_Repository.TitleCase(Elems[a].Substation.Name)); } lvI.SubItems.Add("?"); lvI.SubItems.Add("?"); lvI.SubItems.Add("?"); lvI.ForeColor = Color.Red; lvI.UseItemStyleForSubItems = true; } lvI.Tag = Elems[a]; lvItems.Items.Add(lvI); } catch (Exception ex) { MM_System_Interfaces.LogError(ex); } } tmrUpdate_Tick(tmrUpdate, EventArgs.Empty); lvItems.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); } } catch (Exception) { } }
/// <summary> /// Locate an element, based on its substation name, element name, element type and KV level. /// </summary> /// <param name="SubstationName">The name of the substation</param> /// <param name="ElementName">The name of the element</param> /// <param name="ElementType">The type of the element</param> /// <param name="ElementKVLevel">The KV level of the element</param> /// <returns>The appropriate element</returns> public static MM_Element LocateElement(String SubstationName, String ElementName, String ElementType, String ElementKVLevel) { //First, if we have a line, let's try and find that line if ((ElementType == "LN" || ElementType == "Line") && (Lines.ContainsKey(ElementName))) { return(Lines[ElementName]); } //First, find the substation in question. MM_Substation BaseStation = Substations[SubstationName]; //Now, based on the element type, see if we already have the element MM_Element_Type OutElemType = null; if (ElementType == "DSC") { ElementType = "SW"; } else if (ElementType == "SHUNT") { ElementType = "CP"; } else if (ElementType == "TRANSF") { ElementType = "XF"; } foreach (MM_Element_Type ElemType in ElemTypes.Values) { if (String.Equals(ElemType.Name, ElementType, StringComparison.CurrentCultureIgnoreCase) || String.Equals(ElemType.Acronym, ElementType, StringComparison.CurrentCultureIgnoreCase)) { OutElemType = ElemType; break; } } //Now, if we have a unit, load or transformer, run a quick check to see if it's already there if (OutElemType.Name == "Unit") { foreach (MM_Unit Unit in BaseStation.Units) { if (String.Equals(Unit.Name, ElementName, StringComparison.CurrentCultureIgnoreCase)) { return(Unit); } else if (OutElemType.Name == "Load") { foreach (MM_Load Load in BaseStation.Loads) { if (String.Equals(Load.Name, ElementName, StringComparison.CurrentCultureIgnoreCase)) { return(Load); } else if (OutElemType.Name == "Transformer") { foreach (MM_Transformer Transformer in BaseStation.Transformers) { if (String.Equals(Transformer.Name, ElementName, StringComparison.CurrentCultureIgnoreCase)) { return(Transformer); } } } } } } } //If not, send out our request to the CIM server MM_Element FoundElement = null; //TODO: Handle loading of a new element /*if (MM_Server_Interface.Client != null) * FoundElement = MM_Server_Interface.Client.LoadElement(SubstationName, ElementName, OutElemType); */ //If we can't find it, let's create a new one. if (FoundElement == null) { FoundElement = new MM_Element(); FoundElement.ElemType = OutElemType; FoundElement.Name = ElementName; FoundElement.Substation = BaseStation; FoundElement.KVLevel = GetVoltageLevel(ElementKVLevel); } return(FoundElement); }
/// <summary> /// Ask our next question /// </summary> private void AskNextQuestion() { try { //Come up with a question int QuestionType = rnd.Next(1, 13); //1. Which of the following substations has a wind farm //2. Which of the following substations has a unit operated by X //3. Which of the following lines is highly congested? //4. Which of the following stations is in county X? //5. Which of the following lines is 345 KV? //6. Which of the following lines goes between county X and Y //7. Which county has the lowest bus voltages //8. Which county has the highest available reactive voltage support potential? //9: Which county has the highest available reactive capacitive support potential? //10: Which substation is operated by the following TO: //11: Which line is operated by the following TO: //12: Which Unit is operated by the following QSE? String Question = null; MM_Element[] Elems = new MM_Element[4]; if (QuestionType == 1) { Question = "Which station has a wind gen?"; List <MM_Substation> Subs = new List <MM_Substation>(MM_Repository.Substations.Values); for (int a = 0; a < 4; a++) { while (Elems[a] == null) { MM_Substation Sub = Subs[rnd.Next(Subs.Count)]; if (a == 0 && Sub.Units != null && Sub.Units.Count > 0 && Sub.Units[0].UnitType.Name == "Wind" && Sub.LongName.IndexOf("Wind", StringComparison.CurrentCultureIgnoreCase) == -1) { Elems[a] = Sub; } else if (a != 0 && Sub.Units != null && Sub.Units.Count > 0 && Sub.Units[0].UnitType.Name != "Wind") { Elems[a] = Sub; } } } } else if (QuestionType == 10 || QuestionType == 11) { for (int a = 0; a < 4; a++) { while (Elems[a] == null) { if (QuestionType == 10) { List <MM_Substation> Subs = new List <MM_Substation>(MM_Repository.Substations.Values); MM_Substation Sub = Subs[rnd.Next(Subs.Count)]; if (a == 0) { Elems[0] = Sub; } else if (!Sub.Operator.Equals(Elems[0].Operator)) { Elems[a] = Sub; } Question = "Which station is operated by " + Elems[0].Operator.Name + "?"; } else if (QuestionType == 11) { List <MM_Line> Lines = new List <MM_Line>(MM_Repository.Lines.Values); MM_Line Line = Lines[rnd.Next(Lines.Count)]; if (a == 0) { Elems[0] = Line; } else if (!Line.Operator.Equals(Elems[0].Operator)) { Elems[a] = Line; } Question = "Which line is operated by " + Elems[0].Operator.Name + "?"; } } } } else if (QuestionType == 2 || QuestionType == 12) { List <MM_Substation> Subs = new List <MM_Substation>(MM_Repository.Substations.Values); MM_Company FoundQSE = null; for (int a = 0; a < 4; a++) { while (Elems[a] == null) { MM_Substation Sub = Subs[rnd.Next(Subs.Count)]; if (a == 0 && Sub.Units != null && Sub.Units.Count > 0) { if (QuestionType == 2) { Elems[a] = Sub; } else { Elems[a] = Sub.Units[0]; } FoundQSE = Sub.Units[0].Operator; } else if (a != 0 && Sub.Units != null && Sub.Units.Count > 0 && Sub.LongName.IndexOf(FoundQSE.Name, StringComparison.CurrentCultureIgnoreCase) == -1) { bool FoundOne = false; foreach (MM_Unit Unit in Sub.Units) { if (Unit.Operator.Equals(FoundQSE)) { FoundOne = true; } } if (!FoundOne) { if (QuestionType == 2) { Elems[a] = Sub; } else { Elems[a] = Sub.Units[0]; } } } } } if (QuestionType == 2) { Question = "Which substation has unit(s) operated by " + FoundQSE.Name + "?"; } else { Question = "Which unit is operated by " + FoundQSE.Name + "?"; } } else if (QuestionType == 3) { List <MM_Line> Lines = new List <MM_Line>(MM_Repository.Lines.Values); MM_Line CongestedLine = null; while (CongestedLine == null) { MM_Line TestLine = Lines[rnd.Next(Lines.Count)]; if (TestLine.LineEnergizationState.Name.EndsWith("Energized") && !TestLine.IsSeriesCompensator && TestLine.LinePercentage >= .7f) { CongestedLine = TestLine; } } Elems[0] = CongestedLine; Question = "Which line is highly congested (" + CongestedLine.LinePercentageText + ")?"; for (int a = 1; a < 4; a++) { while (Elems[a] == null) { MM_Line TestLine = Lines[rnd.Next(Lines.Count)]; if (TestLine.LineEnergizationState.Name.EndsWith("Energized") && !TestLine.IsSeriesCompensator && TestLine.LinePercentage <= .4f) { Elems[a] = TestLine; } } } } else if (QuestionType == 4) { List <MM_Boundary> Bounds = new List <MM_Boundary>(MM_Repository.Counties.Values); List <MM_Substation> Subs = new List <MM_Substation>(MM_Repository.Substations.Values); MM_Boundary FoundBound = null; while (FoundBound == null || FoundBound.Substations.Count == 0) { FoundBound = Bounds[rnd.Next(Bounds.Count)]; } Question = "Which substation is in " + FoundBound.Name + " county?"; Elems[0] = FoundBound.Substations[rnd.Next(FoundBound.Substations.Count)]; for (int a = 1; a < 4; a++) { while (Elems[a] == null) { MM_Substation Sub = Subs[rnd.Next(Subs.Count)]; if (!Sub.County.Equals(FoundBound)) { Elems[a] = Sub; } } } } else if (QuestionType == 5) { MM_KVLevel VoltageToFind = new MM_KVLevel[] { MM_Repository.KVLevels["345 KV"], MM_Repository.KVLevels["138 KV"], MM_Repository.KVLevels["69 KV"] }[rnd.Next(3)]; List <MM_Line> Lines = new List <MM_Line>(MM_Repository.Lines.Values); for (int a = 0; a < 4; a++) { while (Elems[a] == null) { MM_Line TestLine = Lines[rnd.Next(Lines.Count)]; if (!TestLine.IsSeriesCompensator) { if (a == 0 && TestLine.KVLevel.Equals(VoltageToFind)) { Elems[a] = TestLine; } else if (a != 0 && !TestLine.KVLevel.Equals(VoltageToFind)) { Elems[a] = TestLine; } } } } Question = "Which line is " + VoltageToFind.Name + "?"; } else if (QuestionType == 6) { List <MM_Line> Lines = new List <MM_Line>(MM_Repository.Lines.Values); MM_Boundary Bound1 = null, Bound2 = null; for (int a = 0; a < 4; a++) { while (Elems[a] == null) { MM_Line TestLine = Lines[rnd.Next(Lines.Count)]; if (TestLine.IsSeriesCompensator) { } else if (a == 0 && !TestLine.Substation1.County.Equals(TestLine.Substation2.County)) { Elems[a] = TestLine; Bound1 = TestLine.Substation1.County; Bound2 = TestLine.Substation2.County; } else if (a != 0 && !TestLine.Substation1.County.Equals(Bound1) && !TestLine.Substation1.County.Equals(Bound2) && !TestLine.Substation2.County.Equals(Bound1) && !TestLine.Substation2.County.Equals(Bound2)) { Elems[a] = TestLine; } } } Question = "Which line travels between " + Bound1.Name + " and " + Bound2.Name + " (" + (Elems[0] as MM_Line).Length.ToString("#,##0.0") + " mi est.)?"; } else if (QuestionType == 7) { MM_Boundary LowestBound = null; float LowestpU = float.NaN; foreach (MM_Boundary Bound in MM_Repository.Counties.Values) { if (Bound.Substations.Count > 0) { float pU = Bound.Average_pU; if (float.IsNaN(LowestpU) || LowestpU > pU) { LowestBound = Bound; LowestpU = pU; } } } List <MM_Boundary> Bounds = new List <MM_Boundary>(MM_Repository.Counties.Values); Elems[0] = LowestBound; for (int a = 1; a < 4; a++) { while (Elems[a] == null) { MM_Boundary TestBound = Bounds[rnd.Next(0, Bounds.Count)]; if (TestBound.Substations.Count > 0 && TestBound.Average_pU > LowestpU + .1f) { Elems[a] = TestBound; } } } Question = "Which county has the lowest avg. bus voltage, at " + LowestpU.ToString("0.00%") + " pU?"; } else if (QuestionType == 8 || QuestionType == 9) { List <MM_Boundary> Bounds = new List <MM_Boundary>(); List <float> ReactivePotentials = new List <float>(); float MaxReac = float.NaN; foreach (MM_Boundary Bound in MM_Repository.Counties.Values) { if (Bound.Substations.Count > 0) { float ReacAvail = 0; int NumReacs = 0; foreach (MM_Substation Sub in Bound.Substations) { if (Sub.ShuntCompensators != null) { foreach (MM_ShuntCompensator SC in Sub.ShuntCompensators) { if (SC.Open && ((QuestionType == 8 && SC.ElemType.Name == "Reactor") || (QuestionType == 9 && SC.ElemType.Name == "Capacitor"))) { NumReacs++; ReacAvail += Math.Abs(SC.Nominal_MVAR); } } } } Bounds.Add(Bound); ReactivePotentials.Add(ReacAvail); if (float.IsNaN(MaxReac) || MaxReac < ReacAvail) { Elems[0] = Bound; MaxReac = ReacAvail; } } } Question = "Which county has the largest available " + (QuestionType == 8 ? "reactive" : "capacitive") + " voltage support (" + MaxReac.ToString("#,##0.0") + " MVar)?"; for (int a = 1; a < 4; a++) { while (Elems[a] == null) { Elems[a] = Bounds[rnd.Next(0, Bounds.Count)]; } } } lblQuestion.Text = Question; int[] OutVals = new int[] { -1, -1, -1, -1 }; for (int a = 0; a < OutVals.Length; a++) { while (OutVals[a] == -1) { bool FoundIt = false; int Next = rnd.Next(0, 4); for (int b = 0; b < a; b++) { if (OutVals[b] == Next) { FoundIt = true; } } if (!FoundIt) { OutVals[a] = Next; } } } int MaxRight = Math.Max(lblQuestion.Right, lblScore.Right); for (int a = 0; a < 4; a++) { Label lbl = Controls["lblAnswer" + (a + 1).ToString()] as Label; if (Elems[OutVals[a]] is MM_Substation) { MM_Substation Sub = Elems[OutVals[a]] as MM_Substation; if (Sub.LongName == Sub.Name) { lbl.Text = (a + 1).ToString() + ") " + Sub.LongName; } else { lbl.Text = (a + 1).ToString() + ") " + Sub.LongName + " (" + Sub.Name + ")"; } } else if (Elems[OutVals[a]] is MM_Boundary) { lbl.Text = (a + 1).ToString() + ") " + Elems[OutVals[a]].Name; } else { lbl.Text = (a + 1).ToString() + ") " + Elems[OutVals[a]].ElementDescription(); } lbl.Tag = new KeyValuePair <MM_Element, bool>(Elems[OutVals[a]], OutVals[a] == 0); lbl.BackColor = lbl.Parent.BackColor; lbl.BorderStyle = BorderStyle.None; lbl.AutoSize = true; MaxRight = Math.Max(MaxRight, lbl.Right); } this.Width = MaxRight + 20; this.Refresh(); pbTimeLeft.Value = 30; tmrQuestion.Enabled = true; tmrQuestion.Interval = 1000; IsAnswered = false; } catch (Exception) { AskNextQuestion(); } }
/// <summary> /// Initialize a new substation /// </summary> /// <param name="Substation"></param> /// <param name="Disp"></param> public MM_Substation_Display(MM_Substation Substation, MM_Operatorship_Display Disp) : base(Substation, Disp) { this.Substation = Substation; }
/// <summary> /// Process a line /// </summary> /// <param name="CurrentLine"></param> /// <param name="DisplayCommands"></param> /// <param name="UnknownTags"></param> /// <param name="SimTime"></param> private void ProcessLine(ref string CurrentLine, List <MM_EMS_Command> DisplayCommands, List <String> UnknownTags, DateTime SimTime) { String[] splStr = CurrentLine.Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries); MM_EMS_Command Command = null; try { if (splStr[0] == "DTS300") { if (splStr[4] == "CB") { foreach (MM_Breaker_Switch BreakerSwitch in MM_Repository.Substations[splStr[7]].BreakerSwitches) { if (BreakerSwitch.Name.Equals(splStr[5], StringComparison.CurrentCultureIgnoreCase)) { Command = new MM_EMS_Command() { Value = splStr[2], UserName = splStr[9], SimulatorTime = SimTime, Field = splStr[4], TEID = BreakerSwitch.TEID } } } ; } else { } } else if (splStr[0] == "DY308") { MM_Substation Site = MM_Repository.Substations[splStr[5]]; Command = new MM_EMS_Command() { SimulatorTime = SimTime, TEID = Site.TEID, UserName = String.Join(" ", splStr, 9, splStr.Length - 9) }; } else if (splStr[0] == "MSC004" || splStr[0] == "DY016") { MM_Substation Sub = MM_Repository.Substations[splStr[2]]; MM_Element FoundElem = null; //Find our element foreach (MM_Element Elem in MM_Repository.TEIDs.Values) { if (Elem.Substation == Sub && Elem.ElemType != null && Elem.ElemType.Acronym.Equals(splStr[3], StringComparison.CurrentCultureIgnoreCase)) { if (Elem.Name.Equals(splStr[4], StringComparison.CurrentCultureIgnoreCase) || (Elem is MM_Transformer && ((MM_Transformer)Elem).PrimaryWinding.Name.Equals(splStr[4], StringComparison.CurrentCultureIgnoreCase))) { FoundElem = Elem; } } } if (splStr[0] == "MSC004") { if (splStr[6] == "TOGGLED") { Command = new MM_EMS_Command() { Field = splStr[5], Value = splStr[8].TrimEnd(','), UserName = splStr[10], SimulatorTime = SimTime, TEID = FoundElem.TEID } } } ; else { Command = new MM_EMS_Command() { Field = splStr[5], Value = splStr[7].TrimEnd(','), OldValue = splStr[9], UserName = splStr[11], SimulatorTime = SimTime, TEID = FoundElem.TEID } }; else { int From = Array.IndexOf(splStr, "FROM"); Command = new MM_EMS_Command() { Field = splStr[5], Value = splStr[7].TrimEnd(','), OldValue = splStr[9], UserName = (From == -1?"?": splStr[From + 1] + splStr[From + 2]), SimulatorTime = SimTime, TEID = FoundElem.TEID }; } }
/// <summary> /// Build the list of words for this item /// </summary> /// <param name="Elem"></param> /// <param name="OutWords"></param> private void BuildWords(MM_Element Elem, Dictionary <String, bool> OutWords) { OutWords.Clear(); if (!String.IsNullOrEmpty(Elem.Name)) { AddWord(OutWords, Elem.Name); } if (Elem is MM_Substation) { MM_Substation Sub = Elem as MM_Substation; if (!String.IsNullOrEmpty(Sub.LongName)) { AddWord(OutWords, Sub.LongName); } if (Sub.County != null) { AddWord(OutWords, Sub.County.Name); } if (Sub.LoadZone != null) { AddWord(OutWords, Sub.LoadZone.Name); } if (Sub.WeatherZone != null) { AddWord(OutWords, Sub.WeatherZone.Name); } if (Sub.Units != null) { foreach (MM_Unit Unit in Sub.Units) { AddWord(OutWords, Unit.UnitType.Name); if (!String.IsNullOrEmpty(Unit.UnitType.EMSName)) { AddWord(OutWords, Unit.UnitType.EMSName); } if (Data_Integration.NetworkSource.Estimates && Data_Integration.UseEstimates) { AddWord(OutWords, Unit.Estimated_MW > 1f ? "Online" : "Offline"); } else { AddWord(OutWords, Unit.Telemetered_MW > 1f ? "Online" : "Offline"); } } } if (Sub.Loads != null) { foreach (MM_Load Load in Sub.Loads) { if (Data_Integration.NetworkSource.Estimates && Data_Integration.UseEstimates) { AddWord(OutWords, Load.Estimated_MW > 1f ? "Online" : "Offline"); } else { AddWord(OutWords, Load.Telemetered_MW > 1f ? "Online" : "Offline"); } } } } else if (Elem is MM_Unit) { MM_Unit Unit = Elem as MM_Unit; AddWord(OutWords, Unit.UnitType.Name); if (!String.IsNullOrEmpty(Unit.UnitType.EMSName)) { AddWord(OutWords, Unit.UnitType.EMSName); } if (Data_Integration.NetworkSource.Estimates && Data_Integration.UseEstimates) { AddWord(OutWords, Unit.Estimated_MW > 1f ? "Online" : "Offline"); } else { AddWord(OutWords, (!float.IsNaN(Unit.Telemetered_MW) && Unit.Telemetered_MW != 0 ? Unit.Telemetered_MW : Unit.Estimated_MW) > 1f ? "Online" : "Offline"); } } else if (Elem is MM_Load) { MM_Load Load = Elem as MM_Load; if (Data_Integration.NetworkSource.Estimates && Data_Integration.UseEstimates) { AddWord(OutWords, Load.Estimated_MW > 1f ? "Online" : "Offline"); } else { AddWord(OutWords, (!float.IsNaN(Load.Telemetered_MW) && Load.Telemetered_MW != 0 ? Load.Telemetered_MW : Load.Estimated_MW) > 1f ? "Online" : "Offline"); } } else if (Elem is MM_ShuntCompensator) { AddWord(OutWords, (Elem as MM_ShuntCompensator).Open ? "Open" : "Closed"); } if (Elem.Operator != null) { AddWord(OutWords, Elem.Operator.Name); AddWord(OutWords, Elem.Operator.Alias); } if (Elem.Owner != null) { AddWord(OutWords, Elem.Owner.Name); AddWord(OutWords, Elem.Owner.Alias); } if (Elem.Substation != null) { AddWord(OutWords, Elem.Substation.Name); AddWord(OutWords, Elem.Substation.LongName); if (Elem.Substation.County != null) { AddWord(OutWords, Elem.Substation.County.Name); } if (Elem.Substation.LoadZone != null) { AddWord(OutWords, Elem.Substation.LoadZone.Name); } if (Elem.Substation.WeatherZone != null) { AddWord(OutWords, Elem.Substation.WeatherZone.Name); } if (Elem.Substation.Units != null) { foreach (MM_Unit Unit in Elem.Substation.Units) { AddWord(OutWords, Unit.UnitType.Name); if (!string.IsNullOrEmpty(Unit.UnitType.EMSName)) { AddWord(OutWords, Unit.UnitType.EMSName); } if (Data_Integration.NetworkSource.Estimates && Data_Integration.UseEstimates) { if (Data_Integration.NetworkSource.Estimates && Data_Integration.UseEstimates) { AddWord(OutWords, Unit.Estimated_MW > 1f ? "Online" : "Offline"); } else { AddWord(OutWords, (!float.IsNaN(Unit.Telemetered_MW) && Unit.Telemetered_MW != 0 ? Unit.Telemetered_MW : Unit.Estimated_MW) > 1f ? "Online" : "Offline"); } } } } if (Elem.Substation.Loads != null) { foreach (MM_Load Load in Elem.Substation.Loads) { if (Data_Integration.NetworkSource.Estimates && Data_Integration.UseEstimates) { if (Data_Integration.NetworkSource.Estimates && Data_Integration.UseEstimates) { AddWord(OutWords, Load.Estimated_MW > 1f ? "Online" : "Offline"); } else { AddWord(OutWords, (!float.IsNaN(Load.Telemetered_MW) && Load.Telemetered_MW != 0 ? Load.Telemetered_MW : Load.Estimated_MW) > 1f ? "Online" : "Offline"); } } } } } if (Elem is MM_Line) { MM_Line Line = Elem as MM_Line; AddWord(OutWords, Line.ConnectedStations[0].Name); AddWord(OutWords, Line.ConnectedStations[0].LongName); AddWord(OutWords, Line.ConnectedStations[1].Name); AddWord(OutWords, Line.ConnectedStations[1].LongName); if (Line.ConnectedStations[0].County != null) { AddWord(OutWords, Line.ConnectedStations[0].County.Name); } if (Line.ConnectedStations[0].LoadZone != null) { AddWord(OutWords, Line.ConnectedStations[0].LoadZone.Name); } if (Line.ConnectedStations[0].WeatherZone != null) { AddWord(OutWords, Line.ConnectedStations[0].WeatherZone.Name); } if (Line.ConnectedStations[1].County != null) { AddWord(OutWords, Line.ConnectedStations[1].County.Name); } if (Line.ConnectedStations[1].LoadZone != null) { AddWord(OutWords, Line.ConnectedStations[1].LoadZone.Name); } if (Line.ConnectedStations[1].WeatherZone != null) { AddWord(OutWords, Line.ConnectedStations[1].WeatherZone.Name); } } }
/// <summary> /// Determine our next question /// </summary> public void NextQuestion() { //First, determine what our current level should be, and by threshold move to the next level if needed MM_Training_Level FoundLevel; if (CurrentLevel == null) { PriorLevel = null; if (!Levels.TryGetValue(0, out FoundLevel)) { TrainingMode = enumTrainingMode.NotTraning; return; } else { CurrentLevel = FoundLevel; } } else if (LevelScore >= CurrentLevel.ExitThresholdScore && QuestionsRight >= CurrentLevel.NumberOfQuestions) { if (!Levels.TryGetValue(CurrentLevel.ID + 1, out FoundLevel)) { MessageTime = DateTime.Now; TrainingMode = enumTrainingMode.UserWon; return; } else { CurrentLevel = FoundLevel; } } else if (QuestionsWrong >= CurrentLevel.FailureThreshold) { MessageTime = DateTime.Now; TrainingMode = enumTrainingMode.UserFailed; return; } //Based on our question, determine our next if (PriorLevel != CurrentLevel) { PrepareLevel(); } //If we have no elements, assume we won if (AvailableElements.Length == 0) { TrainingMode = enumTrainingMode.UserWon; return; } //Pick random elements based on our needs TargetElement = AvailableElements[rnd.Next(0, AvailableElements.Length)]; if (TargetElement is MM_Line || TargetElement is MM_Substation) { } else { TargetElement = TargetElement.Substation; } //Now, handle our target element if (TargetElement is MM_Substation) { MM_Substation TargetSub = (MM_Substation)TargetElement; QuestionText = "Where is substation " + TargetSub.LongName + (String.Equals(TargetSub.LongName, TargetSub.Name, StringComparison.CurrentCultureIgnoreCase) ? "?" : " (" + TargetSub.Name + ")?"); } else if (TargetElement is MM_Line) { MM_Line TargetLine = (MM_Line)TargetElement; QuestionText = "Where is line " + TargetLine.Name + " (from " + TargetLine.Substation1.LongName + " to " + TargetLine.Substation2.LongName + ")?"; } else { QuestionText = "Where is " + TargetElement.ElemType.Name + " " + TargetElement.Name + "?"; } Data_Integration.ReportSystemLevelData(QuestionText); TrainingMode = enumTrainingMode.QuestionAsked; TimeQuestionPresented = DateTime.Now; }