/// <summary> /// Format the grid. /// </summary> protected virtual void FormatGrid() { for (int i = 0; i < properties.Count; i++) { IGridCell cell = grid.GetCell(1, i); if (properties[i] is VariableObject) { cell.EditorType = EditorTypeEnum.TextBox; grid.SetRowAsSeparator(i, true); } else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.TableName) { cell.EditorType = EditorTypeEnum.DropDown; cell.DropDownStrings = storage.Reader.TableNames.ToArray(); } else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.CultivarName) { cell.EditorType = EditorTypeEnum.DropDown; IPlant crop = GetCrop(properties); if (crop != null) { cell.DropDownStrings = GetCultivarNames(crop); } } else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.FileName) { cell.EditorType = EditorTypeEnum.Button; } else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.FieldName) { cell.EditorType = EditorTypeEnum.DropDown; List <string> fieldNames = GetFieldNames(); if (fieldNames != null) { fieldNames.Insert(0, string.Empty); cell.DropDownStrings = fieldNames.ToArray(); } } else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.ResidueName && model is SurfaceOrganicMatter) { cell.EditorType = EditorTypeEnum.DropDown; string[] fieldNames = GetResidueNames(); if (fieldNames != null) { cell.DropDownStrings = fieldNames; } } else if (properties[i].Display != null && (properties[i].Display.Type == DisplayType.CLEMResourceName)) { cell.EditorType = EditorTypeEnum.DropDown; List <string> fieldNames = new List <string>(); fieldNames.AddRange(this.GetCLEMResourceNames(this.properties[i].Display.CLEMResourceNameResourceGroups)); // add any extras elements provided to the list. if (this.properties[i].Display.CLEMExtraEntries != null) { fieldNames.AddRange(this.properties[i].Display.CLEMExtraEntries); } if (fieldNames.Count != 0) { cell.DropDownStrings = fieldNames.ToArray(); } } else if (properties[i].Display != null && (properties[i].Display.Type == DisplayType.CLEMCropFileName)) { cell.EditorType = EditorTypeEnum.DropDown; List <string> fieldNames = new List <string>(); Simulation clemParent = Apsim.Parent(this.model, typeof(Simulation)) as Simulation; // get crop file names fieldNames.AddRange(Apsim.ChildrenRecursively(clemParent, typeof(FileCrop)).Select(a => a.Name).ToList()); fieldNames.AddRange(Apsim.ChildrenRecursively(clemParent, typeof(FileSQLiteCrop)).Select(a => a.Name).ToList()); if (fieldNames.Count != 0) { cell.DropDownStrings = fieldNames.ToArray(); } } else if (properties[i].Display != null && (properties[i].Display.Type == DisplayType.CLEMGraspFileName)) { cell.EditorType = EditorTypeEnum.DropDown; List <string> fieldNames = new List <string>(); Simulation clemParent = Apsim.Parent(this.model, typeof(Simulation)) as Simulation; // get GRASP file names fieldNames.AddRange(Apsim.ChildrenRecursively(clemParent, typeof(FileGRASP)).Select(a => a.Name).ToList()); fieldNames.AddRange(Apsim.ChildrenRecursively(clemParent, typeof(FileSQLiteGRASP)).Select(a => a.Name).ToList()); if (fieldNames.Count != 0) { cell.DropDownStrings = fieldNames.ToArray(); } } else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.Model) { cell.EditorType = EditorTypeEnum.DropDown; string[] modelNames = GetModelNames(properties[i].Display.ModelType); if (modelNames != null) { cell.DropDownStrings = modelNames; } } else { object cellValue = properties[i].ValueWithArrayHandling; if (cellValue is DateTime) { cell.EditorType = EditorTypeEnum.DateTime; } else if (cellValue is bool) { cell.EditorType = EditorTypeEnum.Boolean; } else if (cellValue.GetType().IsEnum) { cell.EditorType = EditorTypeEnum.DropDown; cell.DropDownStrings = VariableProperty.EnumToStrings(cellValue); Enum cellValueAsEnum = cellValue as Enum; if (cellValueAsEnum != null) { cell.Value = VariableProperty.GetEnumDescription(cellValueAsEnum); } } else if (cellValue.GetType() == typeof(IPlant)) { cell.EditorType = EditorTypeEnum.DropDown; List <string> cropNames = new List <string>(); foreach (Model crop in Apsim.FindAll(model, typeof(IPlant))) { cropNames.Add(crop.Name); } cell.DropDownStrings = cropNames.ToArray(); } else if (properties[i].DataType == typeof(IPlant)) { List <string> plantNames = Apsim.FindAll(model, typeof(IPlant)).Select(m => m.Name).ToList(); cell.EditorType = EditorTypeEnum.DropDown; cell.DropDownStrings = plantNames.ToArray(); } else if (!string.IsNullOrWhiteSpace(properties[i].Display?.Values)) { MethodInfo method = model.GetType().GetMethod(properties[i].Display.Values); string[] values = ((IEnumerable <object>)method.Invoke(model, null))?.Select(v => v?.ToString())?.ToArray(); cell.EditorType = EditorTypeEnum.DropDown; cell.DropDownStrings = values; } else { cell.EditorType = EditorTypeEnum.TextBox; } } cell.IsRowReadonly = !IsPropertyEnabled(i); } IGridColumn descriptionColumn = grid.GetColumn(0); descriptionColumn.Width = -1; descriptionColumn.ReadOnly = true; IGridColumn valueColumn = grid.GetColumn(1); valueColumn.Width = -1; }
/// <summary>Add a checkpoint</summary> /// <param name="name">Name of checkpoint</param> /// <param name="filesToCheckpoint">Files to checkpoint</param> public void AddCheckpoint(string name, IEnumerable <string> filesToCheckpoint = null) { if (checkpointIDs.ContainsKey(name)) { DeleteCheckpoint(name); } Open(readOnly: false); connection.ExecuteNonQuery("BEGIN"); int checkpointID = checkpointIDs["Current"]; int newCheckpointID = checkpointIDs.Values.Max() + 1; foreach (Table t in tables) { List <string> columnNames = t.Columns.Select(column => column.Name).ToList(); if (t.Name != "_CheckpointFiles" && columnNames.Contains("CheckpointID")) { columnNames.Remove("CheckpointID"); string csvFieldNames = null; foreach (string columnName in columnNames) { if (csvFieldNames != null) { csvFieldNames += ","; } csvFieldNames += "[" + columnName + "]"; } connection.ExecuteNonQuery("INSERT INTO " + t.Name + " (" + "CheckpointID," + csvFieldNames + ")" + " SELECT " + newCheckpointID + "," + csvFieldNames + " FROM " + t.Name + " WHERE CheckpointID = " + checkpointID); } } string version = Assembly.GetExecutingAssembly().GetName().Version.ToString(); string now = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"); connection.ExecuteNonQuery("INSERT INTO _Checkpoints (ID, Name, Version, Date) VALUES (" + newCheckpointID + ", '" + name + "', '" + version + "', '" + now + "')"); if (filesToCheckpoint != null) { IntPtr insertQuery = connection.Prepare("INSERT INTO _CheckpointFiles (CheckpointID, FileName, Contents) VALUES (?, ?, ?)"); // Add in all referenced files. Simulations sims = Apsim.Parent(this, typeof(Simulations)) as Simulations; object[] values = new object[3]; values[0] = newCheckpointID; foreach (string fileName in filesToCheckpoint) { if (File.Exists(fileName)) { values[1] = fileName; values[2] = File.ReadAllBytes(fileName); connection.BindParametersAndRunQuery(insertQuery, values); } } connection.Finalize(insertQuery); } connection.ExecuteNonQuery("END"); Open(readOnly: true); checkpointIDs.Add(name, newCheckpointID); }
/// <summary> /// Finds a shared marketplace /// </summary> /// <returns>Market</returns> public Market FindMarket() { IModel parentSim = Apsim.Parent(this, typeof(Simulation)); return(Apsim.Children(parentSim, typeof(Market)).Where(a => a.Enabled).FirstOrDefault() as Market); }
/// <summary> /// A new method for finding a model/object from a path in the simulations tree. /// Finds the node (whose name is surrounded by square brackets). From there, it looks for each /// successive period-delimited child or property given in the path string. /// </summary> /// <param name="relativeTo">Object in the simulations tree.</param> /// <param name="objectName">Name of the object or model for which we want completion options.</param> /// <returns></returns> private static object GetNodeFromPath(Model relativeTo, string objectName) { string modelNamePattern = @"\[[A-Za-z\s]+[A-Za-z0-9\s_]*\]"; object node = null; var matches = System.Text.RegularExpressions.Regex.Matches(objectName, modelNamePattern); if (matches.Count <= 0) { // object name doesn't contain square brackets. string textBeforeFirstDot = objectName; if (objectName.Contains(".")) { textBeforeFirstDot = textBeforeFirstDot.Substring(0, textBeforeFirstDot.IndexOf('.')); } node = Apsim.Find(relativeTo, textBeforeFirstDot); } else { // Get the raw model name without square brackets. string modelName = matches[0].Value.Replace("[", "").Replace("]", ""); // Get the node in the simulations tree corresponding to the model name which was surrounded by square brackets. node = Apsim.Find(relativeTo, modelName); // If we're under replacements we won't be able to find some simulation- // related nodes such as weather/soil/etc. In this scenario, we should // search through all models, not just those in scope. if (node == null && Apsim.Parent(relativeTo, typeof(Replacements)) != null) { node = Apsim.ChildrenRecursively(Apsim.Parent(relativeTo, typeof(Simulations))).FirstOrDefault(child => child.Name == modelName); } } // If the object name string does not contain any children/properties // (e.g. it doesn't contain any periods), we can return immediately. if (!objectName.Contains(".")) { return(node); } objectName = objectName.Substring(objectName.IndexOf('.') + 1); // Iterate over the 'child' models/properties. // childName is the next child we're looking for. e.g. in "[Wheat].Leaf", the first childName will be "Leaf". string[] namePathBits = StringUtilities.SplitStringHonouringBrackets(objectName, '.', '[', ']'); for (int i = 0; i < namePathBits.Length; i++) { if (node == null) { return(null); } string childName = namePathBits[i]; int squareBracketIndex = childName.IndexOf('['); if (squareBracketIndex == 0) { // User has typed something like [Wheat].[...] throw new Exception("Unable to parse child or property " + childName); } if (squareBracketIndex > 0) // childName contains square brackets - it may be an IList element { childName = childName.Substring(0, squareBracketIndex); } // First, check the child models. if (node is IModel) { node = (node as IModel).Children.FirstOrDefault(c => c.Name == childName) ?? node; } // If we couldn't find a matching child model, we check the model/object's properties. // This expression evaluates to true if node is not an IModel. if ((node as IModel)?.Name != childName) { // Node cannot be null here. try { Type propertyType = node is Type ? node as Type : node.GetType(); PropertyInfo property = propertyType.GetProperties(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(p => p.Name == childName); // If we couldn't find any matching child models or properties, all we can do is return. if (property == null) { return(null); } // Try to set node to the value of the property. node = ReflectionUtilities.GetValueOfFieldOrProperty(childName, node); if (node == null) { // This property has the correct name. If the property's type provides a parameterless constructor, we can use // reflection to instantiate an object of that type and assign it to the node variable. // Otherwise, we assign the type itself to node. if (property.PropertyType.GetConstructor(Type.EmptyTypes) == null) { node = property.PropertyType; } else { node = Activator.CreateInstance(property.PropertyType); } } } catch { // Any 'real' errors should be displayed to the user, so they should be caught // in a presenter which can access the explorer presenter. // Because of this, any unhandled exceptions here will kill the intellisense // generation operation, and we still have a few tricks up our sleeve. return(null); } } if (squareBracketIndex > 0) { // We have found the node, but the node is an IList of some sort, and we are actually interested in a specific element. int closingBracketIndex = namePathBits[i].IndexOf(']'); if (closingBracketIndex <= 0 || (closingBracketIndex - squareBracketIndex) < 1) { return(null); } string textBetweenBrackets = namePathBits[i].Substring(squareBracketIndex + 1, closingBracketIndex - squareBracketIndex - 1); if (node is IList) { int index = -1; if (Int32.TryParse(textBetweenBrackets, out index)) { IList nodeList = node as IList; if (index > nodeList.Count || index <= 0) { node = node.GetType().GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable <>)).Select(x => x.GetGenericArguments()[0]).FirstOrDefault(); } else { node = nodeList[index - 1]; } } else { throw new Exception("Unable to access element \"" + textBetweenBrackets + "\" of list \"" + namePathBits[i] + "\""); } } else if (node is IDictionary) { node = (node as IDictionary)[textBetweenBrackets]; } else { throw new Exception("Unable to parse child or property name " + namePathBits[i]); } } squareBracketIndex = -1; } return(node); }
/// <summary> /// Determines how much labour is required from this activity based on the requirement provided /// </summary> /// <param name="requirement">The details of how labour are to be provided</param> /// <returns></returns> public override double GetDaysLabourRequired(LabourRequirement requirement) { double daysNeeded = 0; double numberUnits = 0; switch (requirement.UnitType) { case LabourUnitType.Fixed: daysNeeded = requirement.LabourPerUnit; break; case LabourUnitType.perHa: CropActivityManageCrop cropParent = Apsim.Parent(this, typeof(CropActivityManageCrop)) as CropActivityManageCrop; CropActivityManageProduct productParent = Apsim.Parent(this, typeof(CropActivityManageProduct)) as CropActivityManageProduct; numberUnits = cropParent.Area * productParent.UnitsToHaConverter / requirement.UnitSize; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perTree: cropParent = Apsim.Parent(this, typeof(CropActivityManageCrop)) as CropActivityManageCrop; productParent = Apsim.Parent(this, typeof(CropActivityManageProduct)) as CropActivityManageProduct; numberUnits = productParent.TreesPerHa * cropParent.Area * productParent.UnitsToHaConverter / requirement.UnitSize; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perKg: cropParent = Apsim.Parent(this, typeof(CropActivityManageCrop)) as CropActivityManageCrop; productParent = Apsim.Parent(this, typeof(CropActivityManageProduct)) as CropActivityManageProduct; numberUnits = productParent.AmountHarvested; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perUnit: cropParent = Apsim.Parent(this, typeof(CropActivityManageCrop)) as CropActivityManageCrop; productParent = Apsim.Parent(this, typeof(CropActivityManageProduct)) as CropActivityManageProduct; numberUnits = productParent.AmountHarvested / requirement.UnitSize; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; default: throw new Exception(String.Format("LabourUnitType {0} is not supported for {1} in {2}", requirement.UnitType, requirement.Name, this.Name)); } return(daysNeeded); }
/// <summary> /// /// </summary> /// <param name="model"></param> /// <param name="useFullDescription">Use full verbose description</param> /// <param name="htmlString"></param> /// <returns></returns> public string GetFullSummary(object model, bool useFullDescription, string htmlString) { string html = ""; html += "\n<div class=\"holdermain\" style=\"opacity: " + ((!this.Enabled) ? "0.4" : "1") + "\">"; // get clock IModel parentSim = Apsim.Parent(this, typeof(Simulation)); // find random number generator RandomNumberGenerator rnd = Apsim.Children(parentSim, typeof(RandomNumberGenerator)).FirstOrDefault() as RandomNumberGenerator; if (rnd != null) { html += "\n<div class=\"clearfix defaultbanner\">"; html += "<div class=\"namediv\">" + rnd.Name + "</div>"; html += "<div class=\"typediv\">RandomNumberGenerator</div>"; html += "</div>"; html += "\n<div class=\"defaultcontent\">"; html += "\n<div class=\"activityentry\">Random numbers are provided for this simultion.<br />"; if (rnd.Seed == 0) { html += "Every run of this simulation will be different."; } else { html += "Each run of this simulation will be identical using the seed <span class=\"setvalue\">" + rnd.Seed.ToString() + "</span>"; } html += "\n</div>"; html += "\n</div>"; } Clock clk = Apsim.Children(parentSim, typeof(Clock)).FirstOrDefault() as Clock; if (clk != null) { html += "\n<div class=\"clearfix defaultbanner\">"; html += "<div class=\"namediv\">" + clk.Name + "</div>"; html += "<div class=\"typediv\">Clock</div>"; html += "</div>"; html += "\n<div class=\"defaultcontent\">"; html += "\n<div class=\"activityentry\">This simulation runs from "; if (clk.StartDate == null) { html += "<span class=\"errorlink\">[START DATE NOT SET]</span>"; } else { html += "<span class=\"setvalue\">" + clk.StartDate.ToShortDateString() + "</span>"; } html += " to "; if (clk.EndDate == null) { html += "<span class=\"errorlink\">[END DATE NOT SET]</span>"; } else { html += "<span class=\"setvalue\">" + clk.EndDate.ToShortDateString() + "</span>"; } html += "\n</div>"; html += "\n</div>"; html += "\n</div>"; } foreach (CLEMModel cm in Apsim.Children(this, typeof(CLEMModel)).Cast <CLEMModel>()) { html += cm.GetFullSummary(cm, true, ""); } return(html); }
private void OnCommencing(object sender, EventArgs e) { dataToWriteToDb = null; // sanitise the variable names and remove duplicates IModel zone = Apsim.Parent(this, typeof(Zone)); List <string> variableNames = new List <string>(); if (VariableNames != null) { for (int i = 0; i < this.VariableNames.Length; i++) { // each variable name is now a GrazeFoodStoreType bool isDuplicate = StringUtilities.IndexOfCaseInsensitive(variableNames, this.VariableNames[i].Trim()) != -1; if (!isDuplicate && this.VariableNames[i] != string.Empty) { if (this.VariableNames[i].StartsWith("[")) { variableNames.Add(this.VariableNames[i]); } else { string[] splitName = this.VariableNames[i].Split('.'); if (splitName.Count() == 2) { // get specified grazeFoodStoreType grazeStore = Resources.GetResourceItem(this, typeof(GrazeFoodStore), splitName[0], OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.ReportErrorAndStop) as GrazeFoodStoreType; // make each pool entry for (int j = 0; j <= 12; j++) { // variableNames.Add(splitName[0] + "-" + j.ToString() + "-" + splitName[1]); variableNames.Add("[Resources].GrazeFoodStore." + splitName[0] + ".Pool(" + j.ToString() + ")." + splitName[1] + " as " + splitName[0] + "" + j.ToString() + "" + splitName[1]); } if (splitName[1] == "Amount") { // add amounts variableNames.Add("[Resources].GrazeFoodStore." + splitName[0] + ".Amount as TotalAmount"); variableNames.Add("[Resources].GrazeFoodStore." + splitName[0] + ".KilogramsPerHa as TotalkgPerHa"); } } else { throw new ApsimXException(this, "Invalid report property. Expecting full property link or GrazeFoodStoreTypeName.Property"); } } } } // check if clock.today was included. if (!variableNames.Contains("[Clock].Today")) { variableNames.Insert(0, "[Clock].Today"); } } // Tidy up variable/event names. VariableNames = variableNames.ToArray(); VariableNames = TidyUpVariableNames(); EventNames = TidyUpEventNames(); this.FindVariableMembers(); // Subscribe to events. if (EventNames == null || EventNames.Count() == 0) { events.Subscribe("[Clock].CLEMHerdSummary", DoOutputEvent); } else { foreach (string eventName in EventNames) { if (eventName != string.Empty) { events.Subscribe(eventName.Trim(), DoOutputEvent); } } } }
/// <summary> /// Create the individual ruminant animals using the Cohort parameterisations. /// </summary> /// <returns></returns> public List <Ruminant> CreateIndividuals() { List <Ruminant> individuals = new List <Ruminant>(); RuminantType parent = Apsim.Parent(this, typeof(RuminantType)) as RuminantType; // get Ruminant Herd resource for unique ids RuminantHerd ruminantHerd = Resources.RuminantHerd(); if (Number > 0) { for (int i = 1; i <= Number; i++) { object ruminantBase = null; double u1 = ZoneCLEM.RandomGenerator.NextDouble(); double u2 = ZoneCLEM.RandomGenerator.NextDouble(); double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); double weight = Weight + WeightSD * randStdNormal; if (this.Gender == Sex.Male) { ruminantBase = new RuminantMale(Age, Gender, weight, parent); } else { ruminantBase = new RuminantFemale(Age, Gender, weight, parent); } Ruminant ruminant = ruminantBase as Ruminant; ruminant.ID = ruminantHerd.NextUniqueID; ruminant.Breed = parent.Breed; ruminant.HerdName = parent.Name; ruminant.SaleFlag = HerdChangeReason.None; if (Suckling) { ruminant.SetUnweaned(); } if (Sire) { if (this.Gender == Sex.Male) { RuminantMale ruminantMale = ruminantBase as RuminantMale; ruminantMale.BreedingSire = true; } else { Summary.WriteWarning(this, "Breeding sire switch is not valid for individual females [r=" + parent.Name + "].[r=" + this.Parent.Name + "].[r=" + this.Name + "]"); } } // if weight not provided use normalised weight ruminant.PreviousWeight = ruminant.Weight; if (this.Gender == Sex.Female) { RuminantFemale ruminantFemale = ruminantBase as RuminantFemale; ruminantFemale.DryBreeder = true; ruminantFemale.WeightAtConception = ruminant.Weight; ruminantFemale.NumberOfBirths = 0; } individuals.Add(ruminantBase as Ruminant); } } return(individuals); }
private string CreateHTML() { int maxErrors = 100; string htmlString = "<!DOCTYPE html>\n" + "<html>\n<head>\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n<style>\n" + "body {color: [FontColor]; max-width:1000px; font-size:10pt;}" + ".errorbanner {background-color:red !important; border-radius:5px 5px 0px 0px; color:white; padding:5px; font-weight:bold }" + ".errorcontent {background-color:[ContError] !important; margin-bottom:20px; border-radius:0px 0px 5px 5px; border-color:red; border-width:1px; border-style:none solid solid solid; padding:10px;}" + ".warningbanner {background-color:orange !important; border-radius:5px 5px 0px 0px; color:white; padding:5px; font-weight:bold }" + ".warningcontent {background-color:[ContWarn] !important; margin-bottom:20px; border-radius:0px 0px 5px 5px; border-color:orange; border-width:1px; border-style:none solid solid solid; padding:10px;}" + ".messagebanner {background-color:CornflowerBlue !important; border-radius:5px 5px 0px 0px; color:white; padding:5px; font-weight:bold }" + ".messagecontent {background-color:[ContMessage] !important; margin-bottom:20px; border-radius:0px 0px 5px 5px; border-color:CornflowerBlue; border-width:1px; border-style:none solid solid solid; padding:10px;}" + ".okbanner {background-color:green !important; border-radius:5px 5px 0px 0px; color:white; padding:5px; font-weight:bold }" + ".okcontent {background-color:[ContOK] !important; margin-bottom:20px; border-radius:0px 0px 5px 5px; border-color:green; border-width:1px; border-style:none solid solid solid; padding:10px;}" + ".holdermain {margin: 20px 0px 20px 0px}" + ".resourcelink {color:#996633; font-weight:bold; background-color:Cornsilk !important;border-color:#996633; border-width:1px; border-style:solid; padding:0px 5px 0px 5px; border-radius:3px; }" + ".activitylink {color:#009999; font-weight:bold; background-color:floralwhite !important;border-color:#009999; border-width:1px; border-style:solid; padding:0px 5px 0px 5px; border-radius:3px; }" + ".filterlink {border-color:#cc33cc; background-color:#f2e2f2 !important; color:#cc33cc; border-width:1px; border-style:solid; padding: 0px 5px 0px 5px; font-weight:bold; border-radius:3px;}" + ".filelink {color:green; font-weight:bold; background-color:mintcream !important;border-color:green; border-width:1px; border-style:solid; padding:0px 5px 0px 5px; border-radius:3px; }" + ".errorlink {color:white; font-weight:bold; background-color:red !important;border-color:darkred; border-width:1px; border-style:solid; padding:0px 5px 0px 5px; border-radius:3px; }" + ".setvalue {font-weight:bold; background-color: [ValueSetBack] !important; Color: [ValueSetFont]; border-color:#697c7c; border-width:1px; border-style:solid; padding:0px 5px 0px 5px; border-radius:3px;}" + ".otherlink {font-weight:bold; color:#333333; background-color:#eeeeee !important;border-color:#999999; border-width:1px; border-style:solid; padding:0px 5px 0px 5px; border-radius:3px;}" + ".messageentry {padding:5px 0px 5px 0px; line-height: 1.7em; }" + ".holdermain {margin: 20px 0px 20px 0px}" + "@media print { body { -webkit - print - color - adjust: exact; }}" + "\n</style>\n</head>\n<body>"; // apply theme based settings if (!Utility.Configuration.Settings.DarkTheme) { // light theme htmlString = htmlString.Replace("[FontColor]", "#000000"); htmlString = htmlString.Replace("[ContError]", "#FFFAFA"); htmlString = htmlString.Replace("[ContWarn]", "#FFFFFA"); htmlString = htmlString.Replace("[ContMessage]", "#FAFAFF"); htmlString = htmlString.Replace("[ContOK]", "#FAFFFF"); // values htmlString = htmlString.Replace("[ValueSetBack]", "#e8fbfc"); htmlString = htmlString.Replace("[ValueSetFont]", "#000000"); } else { // dark theme htmlString = htmlString.Replace("[FontColor]", "#E5E5E5"); htmlString = htmlString.Replace("[ContError]", "#490000"); htmlString = htmlString.Replace("[ContWarn]", "#A35D00"); htmlString = htmlString.Replace("[ContMessage]", "#030028"); htmlString = htmlString.Replace("[ContOK]", "#0C440C"); // values htmlString = htmlString.Replace("[ValueSetBack]", "#49adc4"); htmlString = htmlString.Replace("[ValueSetFont]", "#0e2023"); } // find IStorageReader of simulation IModel simulation = Apsim.Parent(model, typeof(Simulation)); IModel simulations = Apsim.Parent(simulation, typeof(Simulations)); IDataStore ds = Apsim.Children(simulations, typeof(IDataStore)).FirstOrDefault() as IDataStore; if (ds == null) { return(htmlString); } if (ds.Reader.GetData(simulationName: simulation.Name, tableName: "_Messages") == null) { return(htmlString); } DataRow[] dataRows = ds.Reader.GetData(simulationName: simulation.Name, tableName: "_Messages").Select(); if (dataRows.Count() > 0) { int errorCol = dataRows[0].Table.Columns["MessageType"].Ordinal; //7; // 8; int msgCol = dataRows[0].Table.Columns["Message"].Ordinal; //6; // 7; dataRows = ds.Reader.GetData(simulationName: simulation.Name, tableName: "_Messages").Select().OrderBy(a => a[errorCol].ToString()).ToArray(); foreach (DataRow dr in dataRows) { // convert invalid parameter warnings to errors if (dr[msgCol].ToString().StartsWith("Invalid parameter value in model")) { dr[errorCol] = "0"; } } foreach (DataRow dr in dataRows.Take(maxErrors)) { bool ignore = false; string msgStr = dr[msgCol].ToString(); if (msgStr.Contains("@i:")) { ignore = true; } if (!ignore) { // trim first two rows of error reporting file and simulation. List <string> parts = new List <string>(msgStr.Split('\n')); if (parts[0].Contains("ERROR in file:")) { parts.RemoveAt(0); } if (parts[0].Contains("ERRORS in file:")) { parts.RemoveAt(0); } if (parts[0].Contains("Simulation name:")) { parts.RemoveAt(0); } msgStr = string.Join("\n", parts.Where(a => a.Trim(' ').StartsWith("at ") == false).ToArray()); // remove starter text string[] starters = new string[] { "System.Exception: ", "Models.Core.ApsimXException: " }; foreach (string start in starters) { if (msgStr.Contains(start)) { msgStr = msgStr.Substring(start.Length); } } string type = "Message"; string title = "Message"; switch (dr[errorCol].ToString()) { case "2": type = "Error"; title = "Error"; break; case "1": type = "Warning"; title = "Warning"; break; default: break; } if (msgStr.IndexOf(':') >= 0 && msgStr.StartsWith("@")) { switch (msgStr.Substring(0, msgStr.IndexOf(':'))) { case "@error": type = "Error"; title = "Error"; msgStr = msgStr.Substring(msgStr.IndexOf(':') + 1); break; case "@validation": type = "Error"; title = "Validation error"; msgStr = msgStr.Replace("PARAMETER:", "<b>Parameter:</b>"); msgStr = msgStr.Replace("DESCRIPTION:", "<b>Description:</b>"); msgStr = msgStr.Replace("PROBLEM:", "<b>Problem:</b>"); msgStr = msgStr.Substring(msgStr.IndexOf(':') + 1); break; } } if (msgStr.Contains("terminated normally")) { type = "Ok"; title = "Success"; DataTable dataRows2 = ds.Reader.GetDataUsingSql("Select * FROM _InitialConditions WHERE Name = 'Run on'"); // (simulationName: simulation.Name, tableName: "_InitialConditions"); int clockCol = dataRows2.Columns["Value"].Ordinal; // 8; DateTime lastrun = DateTime.Parse(dataRows2.Rows[0][clockCol].ToString()); msgStr = "Simulation successfully completed at [" + lastrun.ToShortTimeString() + "] on [" + lastrun.ToShortDateString() + "]"; } htmlString += "\n<div class=\"holdermain\">"; htmlString += "\n<div class=\"" + type.ToLower() + "banner\">" + title + "</div>"; htmlString += "\n<div class=\"" + type.ToLower() + "content\">"; msgStr = msgStr.Replace("\n", "<br />"); msgStr = msgStr.Replace("]", "</span>"); msgStr = msgStr.Replace("[r=", "<span class=\"resourcelink\">"); msgStr = msgStr.Replace("[a=", "<span class=\"activitylink\">"); msgStr = msgStr.Replace("[f=", "<span class=\"filterlink\">"); msgStr = msgStr.Replace("[x=", "<span class=\"filelink\">"); msgStr = msgStr.Replace("[o=", "<span class=\"otherlink\">"); msgStr = msgStr.Replace("[", "<span class=\"setvalue\">"); htmlString += "\n<div class=\"messageentry\">" + msgStr; htmlString += "\n</div>"; htmlString += "\n</div>"; htmlString += "\n</div>"; } } if (dataRows.Count() > maxErrors) { htmlString += "\n<div class=\"holdermain\">"; htmlString += "\n <div class=\"warningbanner\">Warning limit reached</div>"; htmlString += "\n <div class=\"warningcontent\">"; htmlString += "\n <div class=\"activityentry\">In excess of " + maxErrors + " errors and warnings were generated. Only the first " + maxErrors + " are displayes here. PLease refer to the SummaryInformation for the full list of issues."; htmlString += "\n </div>"; htmlString += "\n </div>"; htmlString += "\n</div>"; } } else { htmlString += "\n<div class=\"holdermain\">"; htmlString += "\n <div class=\"messagebanner\">Message</div>"; htmlString += "\n <div class=\"messagecontent\">"; htmlString += "\n <div class=\"activityentry\">This simulation has not been performed"; htmlString += "\n </div>"; htmlString += "\n </div>"; htmlString += "\n</div>"; } htmlString += "\n</body>\n</html>"; return(htmlString); }
/// <summary> /// Determine resources available and perform transmutation if needed. /// </summary> /// <param name="resourceRequestList">List of requests</param> /// <param name="uniqueActivityID">Unique id for the activity</param> public void CheckResources(List <ResourceRequest> resourceRequestList, Guid uniqueActivityID) { if ((resourceRequestList == null) || (resourceRequestList.Count() == 0)) { this.Status = ActivityStatus.Success; return; } foreach (ResourceRequest request in resourceRequestList) { request.ActivityID = uniqueActivityID; request.Available = 0; // If resource group does not exist then provide required. // This means when resource is not added to model it will not limit simulations if (request.ResourceType == null || Resources.GetResourceGroupByType(request.ResourceType) == null) { request.Available = request.Required; request.Provided = request.Required; } else { if (request.ResourceType == typeof(Labour)) { // get available labour based on rules. request.Available = TakeLabour(request, false, this, Resources, this.OnPartialResourcesAvailableAction); } else { request.Available = TakeNonLabour(request, false); } } } // are all resources available List <ResourceRequest> shortfallRequests = resourceRequestList.Where(a => a.Required > a.Available).ToList(); int countShortfallRequests = shortfallRequests.Count(); if (countShortfallRequests > 0) { // check what transmutations can occur Resources.TransmutateShortfall(shortfallRequests, true); } // check if need to do transmutations int countTransmutationsSuccessful = shortfallRequests.Where(a => a.TransmutationPossible == true && a.AllowTransmutation).Count(); bool allTransmutationsSuccessful = (shortfallRequests.Where(a => a.TransmutationPossible == false && a.AllowTransmutation).Count() == 0); // OR at least one transmutation successful and PerformWithPartialResources if (((countShortfallRequests > 0) && (countShortfallRequests == countTransmutationsSuccessful)) || (countTransmutationsSuccessful > 0 && OnPartialResourcesAvailableAction == OnPartialResourcesAvailableActionTypes.UseResourcesAvailable)) { // do transmutations. // this uses the current zone resources, but will find markets if needed in the process Resources.TransmutateShortfall(shortfallRequests, false); // recheck resource amounts now that resources have been topped up foreach (ResourceRequest request in resourceRequestList) { // get resource request.Available = 0; if (request.Resource != null) { // get amount available request.Available = Math.Min(request.Resource.Amount, request.Required); } } } bool deficitFound = false; // report any resource defecits here foreach (var item in resourceRequestList.Where(a => a.Required > a.Available)) { ResourceRequestEventArgs rrEventArgs = new ResourceRequestEventArgs() { Request = item }; if (item.Resource != null && Apsim.Parent(item.Resource as Model, typeof(Market)).GetType() == typeof(Market)) { ActivitiesHolder marketActivities = Apsim.Children(Resources.FindMarket, typeof(ActivitiesHolder)).FirstOrDefault() as ActivitiesHolder; if (marketActivities != null) { marketActivities.ActivitiesHolder_ResourceShortfallOccurred(this, rrEventArgs); } } else { OnShortfallOccurred(rrEventArgs); } Status = ActivityStatus.Partial; deficitFound = true; } if (!deficitFound) { this.Status = ActivityStatus.Success; } }
/// <summary>Called by the graph presenter to get a list of all actual series to put on the graph.</summary> /// <param name="definitions">A list of definitions to add to.</param> public void GetSeriesToPutOnGraph(List <SeriesDefinition> definitions) { List <SeriesDefinition> ourDefinitions = new List <SeriesDefinition>(); // If this series doesn't have a table name then it must be getting its data from other models. if (TableName == null) { ourDefinitions.Add(CreateDefinition(Name, null, Colour, Marker, Line)); } else { Simulation parentSimulation = Apsim.Parent(this, typeof(Simulation)) as Simulation; Zone parentZone = Apsim.Parent(this, typeof(Zone)) as Zone; Experiment parentExperiment = Apsim.Parent(this, typeof(Experiment)) as Experiment; // If the graph is in a zone then just graph the zone. if (parentZone != null) { string filter = string.Format("Name='{0}' and ZoneName='{1}'", parentSimulation.Name, parentZone.Name); ourDefinitions.Add(CreateDefinition(Name + " " + parentZone.Name, filter, Colour, Marker, Line)); } else { List <Simulation> simulations = new List <Simulation>(); List <Experiment> experiments = new List <Experiment>(); // Graph is sitting in a simulation so graph just that simulation. if (parentSimulation != null) { string filter = string.Format("Name='{0}'", parentSimulation.Name); ourDefinitions.Add(CreateDefinition(Name, filter, Colour, Marker, Line)); } // See if graph is inside an experiment. If so then graph all simulations in experiment. else if (parentExperiment != null) { GraphExperiment(parentExperiment, ourDefinitions); } // Must be in a folder at the top level or at the top level of the .apsimx file. else { IModel parentOfGraph = this.Parent.Parent; // Look for experiments. foreach (Experiment experiment in Apsim.ChildrenRecursively(parentOfGraph, typeof(Experiment))) { experiments.Add(experiment); } // Look for simulations if we didn't find any experiments. if (experiments.Count == 0) { foreach (Simulation simulation in Apsim.ChildrenRecursively(parentOfGraph, typeof(Simulation))) { simulations.Add(simulation); } } } // Now create series definitions for each experiment found. int colourIndex = 0; foreach (Experiment experiment in experiments) { string filter = "SimulationName IN " + "(" + StringUtilities.Build(experiment.Names(), delimiter: ",", prefix: "'", suffix: "'") + ")"; CreateDefinitions(experiment.BaseSimulation, experiment.Name, filter, ref colourIndex, Marker, Line, ourDefinitions); } // Now create series definitions for each simulation found. foreach (Simulation simulation in simulations) { string filter = "SimulationName = '" + simulation.Name + "'"; CreateDefinitions(simulation, simulation.Name, filter, ref colourIndex, Marker, Line, ourDefinitions); } } } // We might have child models that wan't to add to our series definitions e.g. regression. foreach (IGraphable series in Apsim.Children(this, typeof(IGraphable))) { series.GetSeriesToPutOnGraph(ourDefinitions); } definitions.AddRange(ourDefinitions); }
/// <summary> /// Gets a list of names of simulations in scope. /// </summary> /// <returns></returns> public string[] GetValidSimNames() { return((Apsim.Parent(this, typeof(Series)) as Series)?.FindSimulationDescriptions()?.Select(s => s.Name)?.ToArray()); }
/// <summary> /// Provides the description of the model settings for summary (GetFullSummary) /// </summary> /// <param name="formatForParentControl">Use full verbose description</param> /// <returns></returns> public override string ModelSummary(bool formatForParentControl) { string html = ""; if (!formatForParentControl) { html += "\n<div class=\"activityentry\">"; if (Number <= 0) { html += "<span class=\"errorlink\">" + Number.ToString() + "</span> x "; } else if (Number > 1) { html += "<span class=\"setvalue\">" + Number.ToString() + "</span> x "; } else { html += "A "; } html += "<span class=\"setvalue\">"; html += Age.ToString("0") + "</span> month old "; html += "<span class=\"setvalue\">" + Gender.ToString() + "</span></div>"; if (Suckling) { html += "\n<div class=\"activityentry\">" + ((Number > 1)?"These individuals are suckling":"This individual is a suckling") + "</div>"; } if (Sire) { html += "\n<div class=\"activityentry\">" + ((Number > 1) ? "These individuals are breeding sires" : "This individual is a breeding sire") + "</div>"; } RuminantType rumtype = Apsim.Parent(this, typeof(RuminantType)) as RuminantType; Ruminant newInd = null; string normWtString = "Unavailable"; if (rumtype != null) { newInd = new Ruminant(this.Age, this.Gender, 0, Apsim.Parent(this, typeof(RuminantType)) as RuminantType); normWtString = newInd.NormalisedAnimalWeight.ToString("#,##0"); } if (WeightSD > 0) { html += "\n<div class=\"activityentry\">Individuals will be randomally assigned a weight based on a mean " + ((Weight == 0) ? "(using the normalised weight) " : "") + "of <span class=\"setvalue\">" + Weight.ToString("#,##0") + "</span> kg with a standard deviation of <span class=\"setvalue\">" + WeightSD.ToString() + "</span></div>"; if (newInd != null && Math.Abs(Weight - newInd.NormalisedAnimalWeight) / newInd.NormalisedAnimalWeight > 0.2) { html += "<div class=\"activityentry\">These individuals should weigh close to the normalised weight of <span class=\"errorlink\">" + normWtString + "</span> kg for their age</div>"; } } else { html += "\n<div class=\"activityentry\">" + ((Number > 1) ? "These individuals " : "This individual ") + "weigh" + ((Number > 1) ? "" : "s") + ((Weight == 0)?" the normalised weight of ":"") + " <span class=\"setvalue\">" + Weight.ToString("#,##0") + "</span> kg"; if (newInd != null && Math.Abs(Weight - newInd.NormalisedAnimalWeight) / newInd.NormalisedAnimalWeight > 0.2) { html += ", but should weigh close to the normalised weight of <span class=\"errorlink\">" + normWtString + "</span> kg for their age"; } html += "</div>"; } html += "</div>"; } else { if (this.Parent is CLEMActivityBase) { // when formatted for parent control. i.e. child fo trade html += "\n<div class=\"resourcebanneralone clearfix\">"; html += "Buy "; if (Number > 0) { html += "<span class=\"setvalue\">"; html += Number.ToString(); } else { html += "<span class=\"errorlink\">"; html += "NOT SET"; } html += "</span> x "; if (Age > 0) { html += "<span class=\"setvalue\">"; html += Number.ToString(); } else { html += "<span class=\"errorlink\">"; html += "NOT SET"; } html += "</span> month old "; html += "<span class=\"setvalue\">"; html += Gender.ToString() + ((Number > 1) ? "s" : ""); html += "</span> weighing "; if (Weight > 0) { html += "<span class=\"setvalue\">"; html += Weight.ToString(); html += "</span> kg "; if (WeightSD > 0) { html += "with a standard deviation of <span class=\"setvalue\">"; html += WeightSD.ToString(); html += "</span>"; } } else { html += "<span class=\"setvalue\">"; html += "Normalised weight"; html += "</span>"; } html += "\n</div>"; } } return(html); }
private void OnStartOfSimulation(object sender, EventArgs e) { parent = Apsim.Parent(this, typeof(LifeCyclePhase)) as LifeCyclePhase; }
/// <summary> /// Provides the description of the model settings for summary (GetFullSummary) /// </summary> /// <param name="formatForParentControl">Use full verbose description</param> /// <returns></returns> public override string ModelSummary(bool formatForParentControl) { string html = ""; if (this.Parent.GetType() != typeof(LabourActivityFeed)) { html += "<div class=\"warningbanner\">This Labour Feed Group must be placed beneath a Labour Activity Feed component</div>"; return(html); } LabourFeedActivityTypes ft = (this.Parent as LabourActivityFeed).FeedStyle; html += "\n<div class=\"activityentry\">"; switch (ft) { case LabourFeedActivityTypes.SpecifiedDailyAmountPerAE: case LabourFeedActivityTypes.SpecifiedDailyAmountPerIndividual: html += "<span class=\"" + ((Value <= 0) ? "errorlink" : "setvalue") + "\">" + Value.ToString() + "</span>"; break; default: break; } ZoneCLEM zoneCLEM = Apsim.Parent(this, typeof(ZoneCLEM)) as ZoneCLEM; ResourcesHolder resHolder = Apsim.Child(zoneCLEM, typeof(ResourcesHolder)) as ResourcesHolder; HumanFoodStoreType food = resHolder.GetResourceItem(this, (this.Parent as LabourActivityFeed).FeedTypeName, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.Ignore) as HumanFoodStoreType; if (food != null) { html += " " + food.Units + " "; } html += "<span class=\"setvalue\">"; switch (ft) { case LabourFeedActivityTypes.SpecifiedDailyAmountPerIndividual: html += " per individual per day"; break; case LabourFeedActivityTypes.SpecifiedDailyAmountPerAE: html += " per AE per day"; break; default: break; } html += "</span> "; switch (ft) { case LabourFeedActivityTypes.SpecifiedDailyAmountPerAE: case LabourFeedActivityTypes.SpecifiedDailyAmountPerIndividual: html += "is fed to each individual"; break; } html += " that matches the following conditions:"; html += "</div>"; return(html); }
/// <summary> /// Create the individual ruminant animals using the Cohort parameterisations. /// </summary> /// <returns></returns> public List <Ruminant> CreateIndividuals() { List <Ruminant> Individuals = new List <Ruminant>(); IModel parentNode = Apsim.Parent(this, typeof(IModel)); RuminantType parent = parentNode as RuminantType; // get Ruminant Herd resource for unique ids RuminantHerd ruminantHerd = Resources.RuminantHerd(); parent = this.Parent as RuminantType; if (StartingNumber > 0) { //TODO: get random generator from global store with seed Random rand = new Random(); for (int i = 1; i <= StartingNumber; i++) { object ruminantBase = null; if (this.Gender == Sex.Male) { ruminantBase = new RuminantMale(); } else { ruminantBase = new RuminantFemale(); } Ruminant ruminant = ruminantBase as Ruminant; ruminant.ID = ruminantHerd.NextUniqueID; ruminant.BreedParams = parent; ruminant.Breed = parent.Breed; ruminant.HerdName = parent.Name; ruminant.Gender = Gender; ruminant.Age = StartingAge; ruminant.SaleFlag = Common.HerdChangeReason.None; if (Suckling) { ruminant.SetUnweaned(); } double u1 = rand.NextDouble(); double u2 = rand.NextDouble(); double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); ruminant.Weight = StartingWeight + StartingWeightSD * randStdNormal; ruminant.PreviousWeight = ruminant.Weight; if (this.Gender == Sex.Female) { RuminantFemale ruminantFemale = ruminantBase as RuminantFemale; ruminantFemale.DryBreeder = true; ruminantFemale.WeightAtConception = this.StartingWeight; ruminantFemale.NumberOfBirths = 0; } Individuals.Add(ruminantBase as Ruminant); } } return(Individuals); }