/// <summary> /// Gets a soil description from the ISRIC REST API for World Modellers /// </summary> /// <returns>True if successful</returns> private IEnumerable <SoilFromDataSource> GetWorldModellersSoils() { var soils = new List <SoilFromDataSource>(); string url = "https://worldmodel.csiro.au/apsimsoil?lon=" + longitudeEditBox.Text + "&lat=" + latitudeEditBox.Text; try { MemoryStream stream = WebUtilities.ExtractDataFromURL(url); stream.Position = 0; XmlDocument doc = new XmlDocument(); doc.Load(stream); List <XmlNode> soilNodes = XmlUtilities.ChildNodesRecursively(doc, "Soil"); // We will have either 0 or 1 soil nodes if (soilNodes.Count > 0) { var soil = FileFormat.ReadFromString <Soil>(soilNodes[0].OuterXml, out List <Exception> errors); soil.Children.Add(new CERESSoilTemperature()); soil.OnCreated(); soils.Add(new SoilFromDataSource() { Soil = soil, DataSource = "ISRIC" }); } } catch (Exception) { } return(soils); }
/// <summary>Requests a "synthethic" Soil and Landscape grid soil from the ASRIS web service.</summary> private IEnumerable <SoilFromDataSource> GetGridSoils() { var soils = new List <SoilFromDataSource>(); string url = "http://www.asris.csiro.au/ASRISApi/api/APSIM/getApsoil?longitude=" + longitudeEditBox.Text + "&latitude=" + latitudeEditBox.Text; try { MemoryStream stream = WebUtilities.ExtractDataFromURL(url); stream.Position = 0; XmlDocument doc = new XmlDocument(); doc.Load(stream); List <XmlNode> soilNodes = XmlUtilities.ChildNodesRecursively(doc, "soil"); // We will have either 0 or 1 soil nodes if (soilNodes.Count > 0) { var soil = FileFormat.ReadFromString <Soil>(soilNodes[0].OuterXml, e => throw e, false); soil.Children.Add(new CERESSoilTemperature()); soil.OnCreated(); soils.Add(new SoilFromDataSource() { Soil = soil, DataSource = "SLGA" }); } } catch (Exception error) { explorerPresenter.MainPresenter.ShowError(error); } return(soils); }
/// <summary> /// Requests the closest APSOIL, using the ASRIS web service /// Currently obtains the closest 5, and presents these to the user /// </summary> /// <returns>True if successful</returns> private bool GetMatchingSoil() { if (!CheckValue(entryLatitude) || !CheckValue(entryLatitude)) { return(false); } string url = "http://www.asris.csiro.au/ASRISApi/api/APSIM/getClosestApsoil?maxCnt=5&longitude=" + entryLongitude.Text + "&latitude=" + entryLatitude.Text; Soil newSoil = null; WaitCursor = true; try { try { MemoryStream stream = WebUtilities.ExtractDataFromURL(url); stream.Position = 0; XmlDocument doc = new XmlDocument(); doc.Load(stream); List <XmlNode> soilNodes = XmlUtilities.ChildNodesRecursively(doc, "soil"); // We should have 0 to 5 nodes. If multiple nodes, we should let the user choose if (soilNodes.Count > 0) { int selNode = 0; if (soilNodes.Count > 1) { selNode = SelectSoil(soilNodes); } if (selNode >= 0) { newSoil = SoilFromApsoil(soilNodes[selNode]); } else { return(false); } } if (newSoil != null) { ReplaceModelCommand command = new ReplaceModelCommand(soil, newSoil, explorerPresenter); explorerPresenter.CommandHistory.Add(command, true); } return(true); } catch (Exception e) { return(false); } } finally { WaitCursor = false; } }
/// <summary>Return zero or more APSOIL soils.</summary> private IEnumerable <SoilFromDataSource> GetApsoilSoils() { var soils = new List <SoilFromDataSource>(); try { // fixme: Shouldn't this be using the current culture? double latitude = Convert.ToDouble(latitudeEditBox.Text, System.Globalization.CultureInfo.InvariantCulture); double longitude = Convert.ToDouble(longitudeEditBox.Text, System.Globalization.CultureInfo.InvariantCulture); double radius = Convert.ToDouble(radiusEditBox.Text, System.Globalization.CultureInfo.InvariantCulture); string url = $"http://apsimdev.apsim.info/ApsoilWebService/Service.asmx/SearchSoilsReturnInfo?latitude={latitude}&longitude={longitude}&radius={radius}&SoilType="; using (MemoryStream stream = WebUtilities.ExtractDataFromURL(url)) { stream.Position = 0; XmlDocument doc = new XmlDocument(); doc.Load(stream); List <XmlNode> soilNodes = XmlUtilities.ChildNodesRecursively(doc, "SoilInfo"); foreach (XmlNode node in soilNodes) { string name = node["Name"].InnerText; string infoUrl = $"https://apsimdev.apsim.info/ApsoilWebService/Service.asmx/SoilXML?Name={name}"; using (MemoryStream infoStream = WebUtilities.ExtractDataFromURL(infoUrl)) { infoStream.Position = 0; string xml = HttpUtility.HtmlDecode(Encoding.UTF8.GetString(infoStream.ToArray())); XmlDocument soilDoc = new XmlDocument(); soilDoc.LoadXml(xml); foreach (XmlNode soilNode in XmlUtilities.ChildNodesRecursively(soilDoc, "Soil")) { Soil soil = FileFormat.ReadFromString <Soil>(soilNode.OuterXml, out List <Exception> errors); if (errors != null && errors.Count > 0) { throw errors[0]; } // fixme: this should be handled by the converter or the importer. soil.Children.Add(new CERESSoilTemperature()); soils.Add(new SoilFromDataSource() { Soil = soil, DataSource = "APSOIL" }); } } } } } catch (Exception err) { explorerPresenter.MainPresenter.ShowError(err); } return(soils); }
/// <summary>Get a list of model names under the specified node</summary> /// <param name="node">Root node</param> internal static List<string> GetAllModelNames(XmlNode node) { SortedSet<string> childNames = new SortedSet<string>(); foreach (XmlNode child in XmlUtilities.ChildNodesRecursively(node, typeFilter:null)) { string name = XmlUtilities.Value(child, "Name"); if (name != string.Empty) childNames.Add(name); } return childNames.ToList(); }
/// <summary> /// Gets a soil description from the ISRIC REST API for World Modellers /// </summary> /// <returns>True if successful</returns> private bool GetISRICSoil() { if (!CheckValue(entryLatitude) || !CheckValue(entryLatitude)) { return(false); } string url = "https://worldmodel.csiro.au/apsimsoil?lon=" + entryLongitude.Text + "&lat=" + entryLatitude.Text; Soil newSoil = null; WaitCursor = true; try { try { MemoryStream stream = WebUtilities.ExtractDataFromURL(url); stream.Position = 0; XmlDocument doc = new XmlDocument(); doc.Load(stream); List <XmlNode> soilNodes = XmlUtilities.ChildNodesRecursively(doc, "Soil"); // We will have either 0 or 1 soil nodes if (soilNodes.Count > 0) { newSoil = SoilFromApsoil(soilNodes[0]); // Something looks very wrong with organic carbon in these soils. // It looks to me like it's off by a factor of 10. SoilOrganicMatter soilOrganic = Apsim.Child(newSoil, typeof(SoilOrganicMatter)) as SoilOrganicMatter; soilOrganic.OC = MathUtilities.Divide_Value(soilOrganic.OC, 10.0); ReplaceModelCommand command = new ReplaceModelCommand(soil, newSoil, explorerPresenter); explorerPresenter.CommandHistory.Add(command, true); } MessageDialog md = new MessageDialog(owningView.MainWidget.Toplevel as Window, DialogFlags.Modal, MessageType.Warning, ButtonsType.Ok, "Initial values for water and soil nitrogen have not been provided with this soil description. " + "Please add sensible values before using this soil in a simulation."); md.Title = "Soil use warning"; md.Run(); md.Destroy(); return(true); } catch (Exception) { return(false); } } finally { WaitCursor = false; } }
/// <summary> /// Requests a "synthethic" ASPIM soil from the ASRIS web service /// </summary> /// <returns>True if successful</returns> private bool GetSyntheticSoil() { if (!CheckValue(entryLatitude) || !CheckValue(entryLatitude)) { return(false); } string url = "http://www.asris.csiro.au/ASRISApi/api/APSIM/getApsoil?longitude=" + entryLongitude.Text + "&latitude=" + entryLatitude.Text; Soil newSoil = null; WaitCursor = true; try { try { MemoryStream stream = WebUtilities.ExtractDataFromURL(url); stream.Position = 0; XmlDocument doc = new XmlDocument(); doc.Load(stream); List <XmlNode> soilNodes = XmlUtilities.ChildNodesRecursively(doc, "soil"); // We will have either 0 or 1 soil nodes if (soilNodes.Count > 0) { newSoil = SoilFromApsoil(soilNodes[0]); ReplaceModelCommand command = new ReplaceModelCommand(soil, newSoil, explorerPresenter); explorerPresenter.CommandHistory.Add(command, true); } return(true); } catch (Exception e) { return(false); } } finally { WaitCursor = false; } }
/// <summary> /// Shows completion information for a method call. /// </summary> /// <param name="relativeTo">Model to be used as a reference when searching for completion data.</param> /// <param name="code">Code for which we want to generate completion data.</param> /// <param name="offset">Offset of the cursor/caret in the code.</param> public void ShowScriptMethodCompletion(IModel relativeTo, string code, int offset, Point location) { CSharpParser parser = new CSharpParser(); SyntaxTree syntaxTree = parser.Parse(code); string fileName = Path.GetTempFileName(); File.WriteAllText(fileName, code); syntaxTree.FileName = fileName; syntaxTree.Freeze(); IDocument document = new ReadOnlyDocument(new StringTextSource(code), syntaxTree.FileName); CodeCompletionResult result = completion.GetMethodCompletion(document, offset, false); File.Delete(fileName); if (result.OverloadProvider != null) { if (result.OverloadProvider.Count < 1) { return; } List <MethodCompletion> completions = new List <MethodCompletion>(); foreach (IParameterizedMember method in result.OverloadProvider.Items.Select(x => x.Method)) { // Generate argument signatures - e.g. string foo, int bar List <string> arguments = new List <string>(); foreach (var parameter in method.Parameters) { string parameterString = string.Format("{0} {1}", parameter.Type.Name, parameter.Name); if (parameter.ConstantValue != null) { parameterString += string.Format(" = {0}", parameter.ConstantValue.ToString()); } arguments.Add(parameterString); } MethodCompletion completion = new MethodCompletion() { Signature = string.Format("{0} {1}({2})", method.ReturnType.Name, method.Name, arguments.Any() ? arguments.Aggregate((x, y) => string.Format("{0}, {1}", x, y)) : string.Empty) }; if (method.Documentation == null) { completion.Summary = string.Empty; completion.ParameterDocumentation = string.Empty; } else { if (method.Documentation.Xml.Text.Contains("<summary>") && method.Documentation.Xml.Text.Contains("</summary>")) { completion.Summary = method.Documentation.Xml.Text.Substring(0, method.Documentation.Xml.Text.IndexOf("</summary")).Replace("<summary>", string.Empty).Trim(Environment.NewLine.ToCharArray()).Trim(); } else { completion.Summary = string.Empty; } // NRefactory doesn't do anything more than read the xml documentation file. // Therefore, we need to parse this XML to get the parameter summaries. XmlDocument doc = new XmlDocument(); doc.LoadXml(string.Format("<documentation>{0}</documentation>", method.Documentation.Xml.Text)); List <string> argumentSummariesList = new List <string>(); foreach (XmlElement parameter in XmlUtilities.ChildNodesRecursively(doc.FirstChild, "param")) { argumentSummariesList.Add(string.Format("{0}: {1}", parameter.GetAttribute("name"), parameter.InnerText)); } if (argumentSummariesList.Any()) { completion.ParameterDocumentation = argumentSummariesList.Aggregate((x, y) => x + Environment.NewLine + y); } else { completion.ParameterDocumentation = string.Empty; } } completions.Add(completion); } methodCompletionView.Completions = completions; methodCompletionView.Location = location; methodCompletionView.Visible = true; } }