/// <summary> /// Load the weather forecast for a county /// </summary> /// <param name="County">The county for which forecasts should be loaded</param> public void LoadWeatherForecast(MM_Boundary County) { WebRequest wReq = WebRequest.Create(MM_WeatherStationCollection.ForecastPrepend + County.Centroid.Y.ToString() + "," + County.Centroid.X.ToString()); wReq.UseDefaultCredentials = true; XmlDocument xDoc = new XmlDocument(); try { xDoc.Load(wReq.GetResponse().GetResponseStream()); XmlNodeList Messages = xDoc.SelectNodes("/forecast/txt_forecast/forecastday"); if (County.WeatherForecast != null) { County.WeatherForecast.Clear(); } County.WeatherForecast = new Dictionary <string, string>(Messages.Count); foreach (XmlElement xE in Messages) { County.WeatherForecast.Add(xE["title"].InnerText, xE["fcttext"].InnerText); } Debug.WriteLine("Loaded weather forecast for county" + County.Name); } catch (Exception ex) { Debug.WriteLine("Error parsing weather forecast for county" + County.Name + ":" + ex.Message); } finally { xDoc = null; wReq = null; } }
/// <summary> /// Load the weather alerts for a county /// </summary> /// <param name="County">The county for which alerts should be loaded</param> public void LoadWeatherAlerts(MM_Boundary County) { WebRequest wReq = WebRequest.Create(MM_WeatherStationCollection.AlertsPrepend + County.Centroid.Y.ToString() + "," + County.Centroid.X.ToString()); wReq.UseDefaultCredentials = true; XmlDocument xDoc = new XmlDocument(); try { xDoc.Load(wReq.GetResponse().GetResponseStream()); XmlNodeList Messages = xDoc.SelectNodes("/alerts/alert/AlertItem/message"); if (County.WeatherAlerts != null) { County.WeatherAlerts.Clear(); } County.WeatherAlerts = new List <string>(Messages.Count); foreach (XmlElement xE in Messages) { County.WeatherAlerts.Add(xE.InnerText); } Debug.WriteLine("Loaded weather alerts for county" + County.Name); } catch (Exception ex) { Debug.WriteLine("Error parsing weather alerts for county" + County.Name + ":" + ex.Message); } finally { xDoc = null; wReq = null; } }
/// <summary> /// Start a level by doing all the right things /// </summary> public void StartLevel() { if (CurrentLevel.TopLeftLngLat == null) { if (CurrentLevel.County == null) { nMap.ResetDisplayCoordinates(); } else { MM_Boundary County = MM_Repository.Counties[CurrentLevel.County]; nMap.SetDisplayCoordinates(County.Min, County.Max); } } else { nMap.SetDisplayCoordinates(CurrentLevel.TopLeftLngLat, CurrentLevel.BottomRightLngLat); } }
/// <summary> /// Load the weather stations for each county /// </summary> /// <param name="County">The county to be loaded</param> private void LoadWeatherStation(MM_Boundary County) { try { WebRequest wReq = WebRequest.Create(MM_WeatherStationCollection.QueryPrepend + County.Name + ",TX"); //+ County.Centroid.Y.ToString() + "," + County.Centroid.X.ToString()); wReq.UseDefaultCredentials = true; XmlDocument xDoc = new XmlDocument(); xDoc.Load(wReq.GetResponse().GetResponseStream()); XmlNodeList AirportStations = xDoc.SelectNodes("/location[@type='CITY']/nearby_weather_stations/airport/station"); County.WeatherStations = new List <MM_WeatherStation>(AirportStations.Count); foreach (XmlElement xE in AirportStations) { if (xE.ParentNode.ParentNode.ParentNode["state"].InnerText == "TX") { MM_WeatherStation wx = new MM_WeatherStation(xE); County.WeatherStations.Add(wx); if (!WeatherStations.ContainsKey(wx.StationID)) { WeatherStations.Add(wx.StationID, wx); } wx.UpdateWeather(); } } //Now load the alerts and forecast for the county LoadWeatherAlerts(County); LoadWeatherForecast(County); Debug.WriteLine("Loaded " + AirportStations.Count.ToString("#,##0") + " weather stations for " + County.Name + " county."); xDoc = null; } catch (Exception ex) { Debug.WriteLine("Error retrieving weather station list for county " + County.Name + ":" + ex.Message); } finally { } }
/// <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> /// Create a new element based on its definition /// </summary> /// <param name="xElem">The definition for the element</param> /// <param name="Prefix">The prefix for the element, if any</param> /// <param name="AddIfNew">Whether to add a new element to our master repository</param> /// <returns></returns> public static MM_Element CreateElement(XmlElement xElem, string Prefix, bool AddIfNew) { MM_Element OutElement = null; String ElemType; if (xElem.HasAttribute("ElemType")) { ElemType = String.IsNullOrEmpty(Prefix) ? xElem.Attributes["ElemType"].Value : xElem.HasAttribute(Prefix + ".ElemType") ? xElem.Attributes[Prefix + ".ElemType"].Value : Prefix; } else { ElemType = xElem.Name; } if (Prefix == "EPSMeter") { OutElement = new MM_EPSMeter(); OutElement.ElemType = MM_Repository.FindElementType(Prefix); } else if (xElem.HasAttribute("BaseElement.IsSeriesCompensator") && XmlConvert.ToBoolean(xElem.Attributes["BaseElement.IsSeriesCompensator"].Value)) { OutElement = new MM_Line(); } else if (ElemType == "Breaker" || ElemType == "Switch") { OutElement = new MM_Breaker_Switch(); } else if (ElemType == "DCTie") { OutElement = new MM_Tie(); } else if (ElemType == "Tie") { OutElement = new MM_Tie(); } else if (ElemType == "ElectricalBus") { OutElement = new MM_Electrical_Bus(); } else if (ElemType == "Line") { OutElement = new MM_Line(); } else if (ElemType == "Load" || ElemType.Equals("LaaR", StringComparison.CurrentCultureIgnoreCase)) { OutElement = new MM_Load(); } else if (ElemType == "Unit") { OutElement = new MM_Unit(); } else if (ElemType == "Capacitor" || ElemType == "Reactor") { OutElement = new MM_ShuntCompensator(); } else if (ElemType == "Transformer") { OutElement = new MM_Transformer(); } else if (ElemType == "TransformerWinding") { OutElement = new MM_TransformerWinding(); } else if (ElemType == "StaticVarCompensator") { OutElement = new MM_StaticVarCompensator(); } else if (ElemType == "Node") { OutElement = new MM_Node(); } else if (ElemType == "BusbarSection") { OutElement = new MM_Bus(); } else if (ElemType == "PricingVector") { OutElement = new MM_PricingVector(); ((MM_PricingVector)OutElement).EPSMeter = (MM_EPSMeter)CreateElement(xElem, "EPSMeter", false); } else if (ElemType == "EPSMeter") { OutElement = new MM_EPSMeter(); } else if (ElemType == "County" || ElemType == "State") { OutElement = new MM_Boundary(); } else if (ElemType == "Company") { OutElement = new MM_Company(); } else if (ElemType == "Flowgate") { OutElement = new MM_Flowgate(); } else if (ElemType == "Contingency") { OutElement = new MM_Contingency(); } else if (ElemType == "Substation") { OutElement = new MM_Substation(); } else if (ElemType == "VoltageLevel") { //OutElement = new MM_KVLevel(); } else { OutElement = new MM_Element(); } OutElement.ElemType = MM_Repository.FindElementType(ElemType); //Now, pull in our attributes foreach (XmlAttribute xAttr in xElem.Attributes) { if ((String.IsNullOrEmpty(Prefix) && xAttr.Name.IndexOf('.') == -1)) { MM_Serializable.AssignValue(xAttr.Name, xAttr.Value, OutElement, AddIfNew); } else if (!String.IsNullOrEmpty(Prefix) && xAttr.Name.StartsWith(Prefix + ".")) { MM_Serializable.AssignValue(xAttr.Name.Substring(xAttr.Name.IndexOf('.') + 1), xAttr.Value, OutElement, AddIfNew); } } if (xElem.HasAttribute("Contingencies")) { String[] splStr = xElem.Attributes["Contingencies"].Value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (OutElement.Contingencies == null || OutElement.Contingencies.Count == 0) { OutElement.Contingencies = new List <MM_Contingency>(); } else { OutElement.Contingencies = OutElement.Contingencies.ToList(); } foreach (string str in splStr) { MM_Contingency con = null; MM_Repository.Contingencies.TryGetValue(str, out con); if (con != null && !OutElement.Contingencies.Any(c => c.Name == con.Name)) { OutElement.Contingencies.Add(con); } } } //If we're a transformer, pull in our windings if (ElemType == "Transformer") { List <MM_TransformerWinding> Windings = new List <MM_TransformerWinding>(); foreach (XmlElement xWind in xElem.SelectNodes("Winding")) { Windings.Add(MM_Element.CreateElement(xWind, "BaseElement", AddIfNew) as MM_TransformerWinding); } if (xElem.HasAttribute("BaseElement.KVLevel1")) { Windings[0].Voltage = XmlConvert.ToSingle(xElem.Attributes["BaseElement.KVLevel1"].Value.Split(' ')[0]); } if (xElem.HasAttribute("BaseElement.KVLevel2")) { Windings[1].Voltage = XmlConvert.ToSingle(xElem.Attributes["BaseElement.KVLevel2"].Value.Split(' ')[0]); } (OutElement as MM_Transformer).Windings = Windings.ToArray(); } //If we're a line, check for series compensator status to upgrade our type if (OutElement is MM_Line && xElem.HasAttribute("BaseElement.IsSeriesCompensator") && XmlConvert.ToBoolean(xElem.Attributes["BaseElement.IsSeriesCompensator"].Value)) { OutElement.ElemType = MM_Repository.FindElementType("SeriesCompensator"); } //Return our new element return(OutElement); }
/// <summary> /// Prepare our level for questions. /// </summary> private void PrepareLevel() { MM_KVLevel KVLevel = null; MM_Boundary County = null; MM_Element_Type ElemType = null; if (CurrentLevel.KVLevel != null) { MM_Repository.KVLevels.TryGetValue(CurrentLevel.KVLevel, out KVLevel); } if (CurrentLevel.County != null) { MM_Repository.Counties.TryGetValue(CurrentLevel.County, out County); } if (CurrentLevel.ElemType != null) { MM_Repository.ElemTypes.TryGetValue(CurrentLevel.ElemType, out ElemType); } List <MM_Element> Elements = new List <MM_Element>(); foreach (MM_Element Elem in MM_Repository.TEIDs.Values) { bool Include = true; if (ElemType != null && Elem.ElemType != null && !Elem.ElemType.Equals(ElemType)) { Include = false; } if (Include && CurrentLevel.KVLevel != null) { if (Elem is MM_Substation) { if (((MM_Substation)Elem).KVLevels.IndexOf(KVLevel) == -1) { Include = false; } } else if (Elem.KVLevel != KVLevel) { Include = false; } } if (Include && CurrentLevel.County != null) { if (Elem is MM_Substation && (Elem as MM_Substation).County != County) { Include = false; } else if (Elem is MM_Line && (Elem as MM_Line).Substation1.County != County && (Elem as MM_Line).Substation2.County != County) { Include = false; } } if (Include && !string.IsNullOrEmpty(CurrentLevel.BooleanToCheck)) { MemberInfo[] mI = Elem.GetType().GetMember(CurrentLevel.BooleanToCheck); if (mI.Length != 1) { Include = false;//throw new InvalidOperationException("Unable to locate member " + CurrentLevel.BooleanToCheck); } else if (mI[0] is PropertyInfo) { if (!(bool)((PropertyInfo)mI[0]).GetValue(Elem, null)) { Include = false; } } else if (mI[0] is FieldInfo) { if (!(bool)((FieldInfo)mI[0]).GetValue(Elem)) { Include = false; } } } if (Include) { Elements.Add(Elem); } } QuestionsWrong = 0; QuestionsRight = 0; QuestionsAnswered = 0; PriorLevel = CurrentLevel; AvailableElements = Elements.ToArray(); StartLevel(); }