Lecture – Use of a Dictionary for Property Labels

Use of a Dictionary for Property Labels

Prerequisites

This video extends the classes in Topic – Creating a Single Table Database Object Storage and is part of Topic – Using Collection Classes

Summary

Topics covered in this video;

-Calculator
-Flow
-CircularChannel
-AsHTMLTable
-XMLPropertyObject
-Abstract Classes
-Strings
-PropertyLabels
-PropertyPlaces
-PropertyValue
-Reflection

Video 

Reference Materials

Channel and CircularChannel classes

public Channel()
        {
            // Default Constructor
        }

        public override Dictionary<string, string> PropertyLabels()
        {
            var d = new Dictionary<string, string>();
            d.Add("Flow", "Flow (cfs)");
            d.Add("Slope", "Slope (fraction)");
            d.Add("ManningsN", "Mannings N");
            d.Add("Depth", "Depth (ft)");
            d.Add("Velocity", "Velocity (fps)");
            d.Add("HydraulicRadius", "Hydraulic Radius (ft)");
            d.Add("FlowArea", "Flow Area (cf)");
            d.Add("WettedPerimeter", "Wetted Perimeter (ft)");
            return d;
        }

        public override Dictionary<string, int> PropertyPlaces()
        {
            var d = new Dictionary<string, int>();
            d.Add("Flow", 1);
            d.Add("Slope", 3);
            d.Add("ManningsN", 3);
            d.Add("Depth", 1);
            d.Add("Velocity", 1);
            d.Add("HydraulicRadius", 1);
            d.Add("FlowArea", 2);
            d.Add("WettedPerimeter", 2);
            return d;
        }
    }

    public class CircularChannel : Channel
    {
        public double Diameter { get; set; }

        #region Static Methods

        public override Dictionary<string, string> PropertyLabels()
        {
            var d = base.PropertyLabels();
            d.Add("Diameter", "Diameter (in)");
            return d;
        }

        public override Dictionary<string, int> PropertyPlaces()
        {
            var d = base.PropertyPlaces();
            d.Add("Diameter", 1);
            return d;
        }

        #endregion

        #region Calculations

        public void Calculate()
        {

            if (Slope != 0 && ManningsN != 0 && Flow != 0 && Diameter != 0)
            {
                Depth = CalculateDepth();
                Velocity = CalculateVelocity();
                return;
            }

            if (Slope != 0 && ManningsN != 0 && Depth != 0 && Diameter != 0)
            {
                Flow = CalculateFlow();
                Velocity = CalculateVelocity();
                return;
            }
        }

        public double CalculateAngle()
        {
            // Uses Flow to calculate theta

            double d = Diameter / 12;
            double n = ManningsN;

            if (d == 0) return 0;
            if (n == 0) return 0;
            if (ManningsN <= 0) return 0;

            if (Flow > FullFlow()) return 2 * Math.PI;

            double theta = 1.0;
            double delta = 1.0;
            double lastdelta = 0.0;
            double incr = 0.5;
            int iter = 0;

            while (Math.Abs(delta) > 0.00001 && iter < 500)
            {
                double r = 0.25 * d * (1 - Math.Sin(theta) / theta);
                double b = Flow / ((1.0 / 8.0) * (theta - Math.Sin(theta)) * Math.Pow(d, 2));
                delta = (1.49 / n) * Math.Pow(r, 2.0 / 3.0) * Math.Pow(Slope, 0.5) - b;

                if (Math.Sign(lastdelta) != Math.Sign(delta)) incr = incr / 2;
                theta = (delta > 0 ? theta - incr : theta + incr);
                lastdelta = delta;

                if (theta > 2 * Math.PI) return 2 * Math.PI;
                iter++;
            }
            return theta;
        }

        public double CalculateDepth()
        {
            // Using Flow Calculates Depth

            if (Slope == 0) return 0;
            if (Flow == 0) return 0;
            if (ManningsN == 0) return 0;

            double theta = CalculateAngle();
            if (theta == 0) return 0;

            double d = Diameter / 12;
            double r = d / 2;

            if (theta > 2 * Math.PI) return d;

            if (theta < Math.PI)
            {
                double t = (Math.PI - theta) / 2;
                return r - r * Math.Sin(t);
            }
            else
            {
                double t = (theta - Math.PI) / 2;
                return r + r * Math.Sin(t);
            }
        }

        public double CalculateVelocity()
        {
            // Uses Flow to Calculate depth

            if (Slope == 0) return 0;
            if (Flow == 0) return 0;
            if (ManningsN == 0) return 0;

            double d = Diameter / 12;
            double r = d / 2;

            if (Flow > FullFlow())
                return Flow / (Math.PI * Math.Pow(r, 2));

            double theta = CalculateAngle();
            if (theta == 0) return 0;

            FlowArea = Math.PI * Math.Pow(r, 2) * (theta / (2 * Math.PI));
            Velocity = Flow/FlowArea;
            return Velocity;
        }

        public double CalculateHydraulicRadius()
        {
            // uses depth to calculate Hydraulic Radius

            if (Depth == 0) return 0;
            if (Depth > Diameter / 12) return 0.5;

            double r = Diameter / 24;

            double a = CalculateFlowArea();
            double p = CalculateWettedPerimeter();
            HydraulicRadius = a/p;
            return HydraulicRadius;
        }

        public double CalculateWettedPerimeter()
        {
            // uses depth to calculate Hydraulic Radius

            if (Depth == 0) return 0;
            if (Depth > Diameter / 12) return Math.PI * Diameter / 12;

            double r = Diameter / 24;
            if (Depth <= r)
            {
                double th = 2 * Math.Acos((r - Depth) / r);
                double a = (Math.Pow(r, 2) * (th - Math.Sin(th))) / 2;
                double p = r * th;
                WettedPerimeter = a/p;
                return WettedPerimeter;
            }
            else // more than half full
            {
                double h = Diameter / 12 - Depth;
                double th = 2 * Math.Acos((r - h) / r);
                double a = Math.PI * Math.Pow(r, 2) - (Math.Pow(r, 2) * (th - Math.Sin(th))) / 2;
                double p = 2 * Math.PI * r - r * th;
                return a / p;
            }
        }

        public double CalculateFlow()
        {
            HydraulicRadius = CalculateHydraulicRadius();
            FlowArea = CalculateFlowArea();

            return (1.49 / ManningsN) * FlowArea * Math.Pow(HydraulicRadius, 2.0 / 3.0) * Math.Pow(Slope, 0.5);
        }

        public double FullFlow()
        {
            double d = Diameter / 12;

            return (0.4644 / ManningsN) * Math.Pow(d, (8.0 / 3.0)) * Math.Pow(Slope, 0.5);
        }

        public double Capacity()
        {
            return FullFlow();
        }

        public double CalculateFlowArea()
        {
            if (Depth != 0)
            {
                double r = Diameter / 24;

                if (Depth > Diameter / 12)
                    return Math.PI * Math.Pow(r, 2);
                if (Depth <= r)
                {
                    double th = 2 * Math.Acos((r - Depth) / r);
                    return (Math.Pow(r, 2) * (th - Math.Sin(th))) / 2;
                }
                else // more than half full
                {
                    double h = Diameter / 12 - Depth;
                    double th = 2 * Math.Acos((r - h) / r);
                    return Math.PI * Math.Pow(r, 2) - (Math.Pow(r, 2) * (th - Math.Sin(th))) / 2;
                }
            }

            if (Flow != 0)
            {
                double r = Diameter / 24;
                double theta = CalculateAngle();
                if (theta == 0) return 0;

                double area = Math.PI * Math.Pow(r, 2) * (theta / (2 * Math.PI));
                return area;
            }
            return 0;
        }

        #endregion

        public double[,] DepthAsArray()
        {
            int n = 20;

            var v = new double[2, n];

            for (int i = 0; i < n; i++)
            {
                v[0, i] = i * (Diameter / 12) / 20;
                Depth = v[0, i];

                v[1, i] = CalculateFlow();

            }
            return v;
        }


    }

    public class TrapezoidalChannel : Channel
    {
        public double SideSlope { get; set; }
        public double BottomWidth { get; set; }

        public void Calculate()
        {

            if (Slope != 0 && ManningsN != 0 && Flow != 0 && BottomWidth != 0)
            {
                Depth = CalculateDepth();
                Velocity = CalculateVelocity();
                return;
            }

            if (Slope != 0 && ManningsN != 0 && Depth != 0 && BottomWidth != 0)
            {
                Flow = CalculateFlow();
                Velocity = CalculateVelocity();
                return;
            }
        }


        public double CalculateDepth()
        {
            // Iteratively calculates depth

            if (!CanCalculate()) return 0;

            double b = BottomWidth;
            double z = SideSlope;
            double q = Flow;
            double dh = 1.0;
            double delta = 1.0;
            double lastdelta = 1.0;
            double incr = 0.1;

            while (delta > 0.0001 && incr > 0.00001)
            {
                double area = (b + z * dh) * dh;
                double wp = b + 2 * dh * Math.Sqrt(((1 + Math.Pow(z, 2))));
                double hr = area / wp;
                double dq = (1.49 / ManningsN) * area * Math.Pow(hr, 2 / 3) * Math.Sqrt(Slope);

                delta = dq - q;
                if (Math.Sign(delta) != Math.Sign(lastdelta)) incr = incr / 2;
                if (delta > 0) dh -= incr;
                if (delta < 0) dh += incr;
                lastdelta = delta;
            }
            return dh;
        }

        public double CalculateFlowArea()
        {
            if (!CanCalculate()) return 0;

            return Depth * (BottomWidth + SideSlope * Depth);
        }

        public double CalculateWettedPerimeter()
        {
            if (!CanCalculate()) return 0;

            return BottomWidth + 2 * Depth * Math.Sqrt(1 + Math.Pow(SideSlope, 2));
        }

        public double CalculateHydraulicRadius()
        {
            if (!CanCalculate()) return 0;

            return CalculateFlowArea() / CalculateWettedPerimeter();
        }

        public double CalculateVelocity()
        {
            if (!CanCalculate()) return 0;

            double area = CalculateFlowArea();
            return Flow / area;
        }

        public double CalculateFlow()
        {
            if (!CanCalculate()) return 0;
            double area = CalculateFlowArea();
            double hr = CalculateHydraulicRadius();
            return (1.49 / ManningsN) * area * Math.Pow(hr, 2 / 3) * Math.Sqrt(Slope);
        }

        public Boolean CanCalculate()
        {
            if (Slope == 0) return false;
            if (ManningsN == 0) return false;
            if (Depth == 0) return false;
            return true;
        }

        public double[,] DepthAsArray()
        {
            int n = 20;

            double holdDepth = Depth;
            double maxDepth = Depth * 2;
            var v = new double[2, n];

            for (int i = 0; i < n; i++)
            {
                v[0, i] = i * (maxDepth) / 20;
                Depth = v[0, i];

                v[1, i] = CalculateFlow();

            }
            Depth = holdDepth;
            return v;
        }
    } 

XmlPropertyObject class

   public abstract class XmlPropertyObject : IXmlPropertyObject
    {
        public int id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string Owner { get; set; }

        public XmlPropertyObject(int ID)
        {
            id = ID;
            Select(ID);
        }

        public XmlPropertyObject() { }

        public string asXML()
        {
            // XML Serializer used to convert class to XML
            XmlSerializer x = new XmlSerializer(this.GetType());

            // Store the XML using a StringWriter
            StringWriter writer = new StringWriter();
            x.Serialize(writer, this);

            // Return a String
            return writer.ToString();
        }

        public Dictionary<String,String> AsDictionary()
        {
            var d = this.GetType().GetProperties().ToDictionary(property => property.Name, property => Convert.ToString(property.GetValue(this)));
            return d;
        }

        public string className()
        {
            string fc = this.GetType().ToString();
            while (fc.Contains("."))
            {
                fc = fc.Substring(fc.IndexOf(".") + 1);
            }
            return fc;
        }

        public string getPropertyFromXml(string property, string xml)
        {
            XDocument doc = XDocument.Parse(xml);
            // Gets the value fom XML
            try { return doc.Root.Element(property).Value; }
            catch { return String.Empty; }
        }

        public void setID(int ID)
        {
            id = ID;
            Select(ID);
        }

        public void setPropertyFromXml(string property, string xml)
        {
            string value = getPropertyFromXml(property, xml);
            setProperty(property, value);
        }

        public string getPropertyValue(string name)
        {
            PropertyInfo pi = this.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
            return Convert.ToString(pi.GetValue(this));
        }

        public string getPropertyValue(string name, int places)
        {
            // Specifically to deal with numeric formats
            string FormatString = "{0:N" + places.ToString().Trim()+"}";            

            PropertyInfo pi = this.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
            return String.Format(FormatString, pi.GetValue(this));
        }

        public void setProperty(string name, string value)
        {
            PropertyInfo pi = this.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
            if (null != pi && pi.CanWrite)
            {
                pi.SetValue(this, Convert.ChangeType(value, pi.PropertyType), null);
            }
        }

        public void setPropertiesFromXml(string xml)
        {
            XDocument doc = XDocument.Parse(xml);
            foreach (XElement xe in doc.Root.Elements())
            {
                setProperty(xe.Name.ToString(), xe.Value);
            }
        }

        public void Select(int ID)
        {
            DataTable dt = DatabaseXmlStore.Select(ID);
            if (dt.Rows.Count == 0) return;

            setPropertiesFromXml(dt.Rows[0]["XmlData"].ToString());
            id = ID;
        }

        public DataTable SelectAll(string ownerID)
        {
            return DatabaseXmlStore.SelectAll(ownerID, className());
        }

        public string Insert()
        {
            return DatabaseXmlStore.Insert(this);
        }

        public string Update()
        {
            if (id == 0)
                return Insert();
            else
                return DatabaseXmlStore.Update(this);
        }



        public string AsHtmlTable()
        {
            string s = "<table>";
            foreach (KeyValuePair<string, string> pair in PropertyLabels())
            {
                s += "<tr>";
                s += "<td>" + pair.Value + "</td>";
                int p = PropertyPlaces()[pair.Key];
                string v = getPropertyValue(pair.Key, p);
                s += "<td>" + v + "</td>";
                s += "</tr>";
            }
            s += "</table>";
            return s;
        }

        public abstract Dictionary<string, string> PropertyLabels();
        public abstract Dictionary<string, int> PropertyPlaces();
    } 

Additional Information

COP 4834 Lectures Page