Useful links
1. Introduction
At 2002 I have predicted that my software projects should have Web versions. Recently (October 2012) I have begun implement this idea. However during ten years I developed software such that it can be easily adopted for Web. So I once again
reinvented
The time machine. My idea of engineering web applications rapid development is similar to LabVIEW idea. LabVIEW supports graphical programming for both business logics and user interface.
My approach is the same. Following picture shows this fact.
Desktop windows application enables us develop business logic. Then XAML designer yields interoperability of business logic with Silverlight user interface. So this soft contains desktop windows application and Web one. Both of them are developed for evaluation purposes only. Therefore Visual Studio Express 2012 for Windows Desktop
and Visual Studio Express 2012 for Web are used for development of these applications. Evaluation Web client is a frame of the original article. Original article contains desktop application source code and other useful resources.
2. Background
Here we will consider general elements of business logic and corresponding Silverlight UI elements
2.1 Exception handling
A lot of software contains code which looks like
void z_error (char *m)
{
fprintf(stderr, "%s\n", m);
exit(1);
}
or
try
{
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
Above code is not flexible and could not be easy used for Web applications. So I prefer construction which has a pure abstract exception handling and extension method.
public interface IErrorHandler
{
void ShowError(Exception exception, object obj);
void ShowMessage(string message, object obj);
}
static public void ShowError(this Exception exception, object obj = null)
{
if (errorHandler != null) {
errorHandler.ShowError(exception, obj);
}
}
Now exception handling looks like
try
{
}
catch (Exception exception)
{
exception.ShowError();
}
Desktop applications can have following implementation of IErrorHandler
interface
void IErrorHandler.ShowError(Exception exception, object obj)
{
MessageBox.Show(this, exception.Message);
}
However I prefer error handling with following UI
Web version of above error handling looks like:
<>
>
N |
Level |
Message |
Stack trace |
1 |
10 |
NaN |
at EngineeringInitializer.BasicEngineeringInitializer.b__0(Object o) in c:\AUsers\1MySoft\CSharp\src\src\EngineeringInitializer\BasicEngineeringInitializer.cs:line 72 at Calculation.Calculate.Update() in c:\DWASFiles\sites\orbitalforecast\Temp\agffdids.0.cs:line 90 at DataPerformer.DifferentialEquationSolver.CalculateDerivations() |
2 |
10 |
NaN |
at Diagram.UI.StaticExtensionDiagramUI.Throw(Object o, Exception exception) at DataPerformer.DataConsumer.UpdateChildrenData() at DataPerformer.VectorFormulaConsumer.UpdateMeasurements() |
3 |
10 |
NaN |
at Diagram.UI.StaticExtensionDiagramUI.Throw(Object o, Exception exception) at DataPerformer.DataConsumer.UpdateChildrenData() at DataPerformer.VectorFormulaConsumer.UpdateMeasurements() |
4 |
10 |
NaN |
at Diagram.UI.StaticExtensionDiagramUI.Throw(Object o, Exception exception) at DataPerformer.DataConsumer.UpdateChildrenData() at DataPerformer.VectorFormulaConsumer.UpdateMeasurements() |
This error handling has server and client tiers. Following code is implenentation of server tier.
Following code contains server side implementation
private List<object[]> exceptions = new List<object[]>();
#region IErrorHandler Menbers
public virtual void ShowError(Exception exception, object obj)
{
exceptions.Add(new object[] { exception, obj + "" });
onException(exception, obj);
}
#endregion
public void CreateErrorReport(XmlDocument doc)
{
if (exceptions.Count != 0)
{
XmlElement el = doc.CreateElement("Exceptions");
doc.DocumentElement.AppendChild(el);
foreach (object[] o in exceptions)
{
XmlElement e = doc.CreateElement("Exception");
el.AppendChild(e);
XmlElement eo = doc.CreateElement("Object");
eo.InnerText = o[1] + "";
e.AppendChild(eo);
XmlElement eex = doc.CreateElement("StackTrace");
e.AppendChild(eex);
eex.InnerText = (o[0] as Exception).StackTrace;
XmlElement em = doc.CreateElement("ExceptionMessage");
e.AppendChild(em);
em.InnerText = (o[0] as Exception).Message;
XmlElement et = doc.CreateElement("ExceptionType");
e.AppendChild(et);
et.InnerText = (o[0] as Exception).GetType() + "";
}
exceptions.Clear(); }
}
Serer side collects exceptions on list, then information about exceptions is appended to XML document. Then document is sent to client.
Client side also contains own error handling interface:
public interface IErrorHandler
{
void ShowErrorReport(XElement x);
}
Every client object which implements this interface shows report about errors. Following code contains an implementation of this interface.
public partial class SilverlightControlHtmlErrorHandler : UserControl, IErrorHandler
{
#region Fields
string elementID;
string scriptFunction;
#endregion
#region Ctor
public SilverlightControlHtmlErrorHandler()
{
InitializeComponent();
}
#endregion
#region IErrorHandler Members
void IErrorHandler.ShowErrorReport(XElement x)
{
XElement xe = x.Element("Exceptions");
if (xe == null)
{
return;
}
IEnumerable<XElement> l = xe.Elements("Exception");
string text = "<table border=\"1\"><tr><td>N</td><td>Level</td><td>Message</td><td>Stack trace</td></tr>";
int i = 1;
foreach (XElement e in l)
{
text += "<tr><td>" + i + "</td><td>" + e.Element("Object").Value + "</td><td>" +
e.Element("ExceptionMessage").Value + "</td><td>" + e.Element("StackTrace").Value + "</td></tr>";
++i;
}
text += "</table>";
Action<string> acttext = WriteText; if (scriptFunction != null)
{
if (scriptFunction.Length > 0)
{
acttext = WriteScript; }
}
Action act = () =>
{
acttext(text);
};
Dispatcher.BeginInvoke(act);
}
#endregion
#region Members
#region Public
public string ScriptFunction
{
get
{
return scriptFunction;
}
set
{
scriptFunction = value;
}
}
public string HtmlId
{
get
{
return elementID;
}
set
{
elementID = value;
}
}
#endregion
#region Private
void WriteText(string text)
{
HtmlDocument doc = HtmlPage.Document;
HtmlElement element = doc.GetElementById(elementID);
if (element != null)
{
element.SetAttribute("innerHTML", text);
}
}
void WriteScript(string text)
{
HtmlPage.Window.Invoke(scriptFunction, text);
}
#endregion
#endregion
This component shows exception report as inner HTML or calls script function. Following snippet contains example of error handler function.
<script type="text/javascript">
// Shows error
// text is error text
function showScriptError(text) {
var div_preview = document.getElementById("Errors");
div_preview.innerHTML = text;
}
</script>
<div id="Errors"></div>
Some Web client elements should be associated with error handlers. These elements implement following interface.
public interface IErrorHandlerConsumer
{
IErrorHandler ErrorHandler
{
get;
set;
}
}
Developer should not explicitly associate error handler. This operation is performed implicitly by following functions
public static void RecursiveAction<T>(this DependencyObject obj, Action<T> action) where T : class
{
if (obj is T)
{
action(obj as T);
}
int childrenCount = VisualTreeHelper.GetChildrenCount(obj);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(obj, i);
if (child is DependencyObject)
{
(child as DependencyObject).RecursiveAction<T>(action);
}
}
}
public static DependencyObject GetRoot(this DependencyObject element)
{
if (element is FrameworkElement)
{
DependencyObject dob = (element as FrameworkElement).Parent;
if (!(dob is FrameworkElement))
{
return element;
}
return GetRoot(dob);
}
return null;
}
public static void RootRecursiveAction<T>(this DependencyObject obj, Action<T> action)
where T : class
{
DependencyObject d = obj.GetRoot();
d.RecursiveAction<T>(action);
}
public static void FindErrorHandler(this ) consumer)
{
DependencyObject dob = consumer as DependencyObject;
IErrorHandler eh = null;
Action<IErrorHandler> find = (IErrorHandler h) =>
{
if (eh == null)
{
eh = h;
return;
}
};
dob.RootRecursiveAction<IErrorHandler>(find);
if (eh != null)
{
consumer.ErrorHandler = eh;
}
}
Following XAML code
<UserControl xmlns:SilverlightDiagramUI="clr-namespace:Diagram.UI.SilverlightDiagramUI;
assembly=Diagram.UI.SilverlightDiagramUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataPerformer.UI.SilverlightDataPerformer"
x:Class="DataPerformer.UI.SilverlightDataPerformer.SilverlightControlChartInputOutput"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"><StackPanel>
<Grid x:Name="LayoutRoot" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<SilverlightDiagramUI:SilverlightControlAlias x:Name="Aliases" Grid.Column="0"
Grid.Row="0" HorizontalAlignment="Stretch" Margin="0,0,0,0" />
<local:SilverlightControlHtmlOutput x:Name="Chart" Grid.Column="0" Grid.Row="1" />
<Button click="Button_Click" content="Start" grid.row="2"
horizontalalignment="Stretch" margin="0,0,0,0" width="75" x:name="Start"/>
<local:SilverlightControlHtmlErrorHandler x:Name="Errors"
HorizontalAlignment="Left" Height="0" Grid.Row="2" Width="0" Visibility="Collapsed"/>
</Grid>
</StackPanel>
</UserControl>
contains one IErrorHandler
(it is SilverlightControlHtmlErrorHandler
) and two IErrorHandlerConsumer
objects (SilverlightControlAlias
and SilverlightControlHtmlOutput
. Both consumers automatically associated with error handler because all three elements have common root. Following picture represents interoperability between IErrorHandler
and IErrorHandlerConsumer
. Following sequence diagram explains usage of exception handler.
2.2 Client interfaces
2.2.1 Initialization interface
Some UI elements should be initialized after their appearance. Following schema represents such initialization
All objects which require such initialization implement
IPostLoadService
interface.
2.2.2 Additional information interface
A lot of user controls contains child controls. Usually request for server contains information which is contained in all children. Following control
has two children. "Green" child generates following XML
<Aliases Desktop="Exponent.cfa">
<Alias>
<Name>Exp.a</Name>
<Value>0.7</Value>
<Type>System.Double</Type>
</Alias>
<Alias>
<Name>Exp.b</Name>
<Value>0.3</Value>
<Type>System.Double</Type>
</Alias>
</Aliases>
"Blue" component generates:
<ChartDocument Chart="ExponentChart.xml" Desktop="Exponent.cfa">
<Parameters>
<Start>0</Start>
<Step>1000</Step>
<Finish>20000</Finish>
<Xslt>Exponent.xslt</Xslt>
</Parameters>
</ChartDocument>
In result following XML is sent to server:
<ChartDocument Chart="ExponentChart.xml" Desktop="Exponent.cfa">
<Aliases Desktop="Exponent.cfa">
<Alias>
<Name>Exp.a</Name>
<Value>0.7</Value>
<Type>System.Double</Type>
</Alias>
<Alias>
<Name>Exp.b</Name>
<Value>0.3</Value>
<Type>System.Double</Type>
</Alias>
</Aliases>
<Parameters>
<Start>0</Start>
<Step>1000</Step>
<Finish>20000</Finish>
<Xslt>Exponent.xslt</Xslt>
</Parameters>
</ChartDocument>
So information from "blue" control is appended to information of "green" control. "Blue control implements following interface
public interface IAddRequest
{
void Add(XElement x);
}
All IAddRequest
objects add information to request. Following diagram illustrates logics of request:
Note that add request operation should not be called explicitly. It is called implicitly by following function
public static void AddRequest(this DependencyObject obj, XElement x)
{
Action<IAddRequest> action = (IAddRequest a) => { a.Add(x);};
obj.RootRecursiveAction<IAddRequest>(action);
}
2.3 Constant input
As rule every engineering task have input constants. For example calculation of f(t)=aebt function has two parameters a and b which can be regarded as constants. Software should support constant input.
2.3.1 Business logic
Following picture represents business logic of above task.
Where Exp component calculates f(t)=aebt. Whole above picture is named Desktop. Any desktop correspond to object which implemens IDesktop
interface. Properties of Exp are presented below.
Bottom right part of above window contains editor of a and b constants. The Exp object implements following interface:
public interface IAlias : IAliasBase
{
IList<string> AliasNames
{
get;
}
object this[string name]
{
get;
set;
}
object GetType(string name);
}
Following code explains usage of this interface.
IAlias alias = Exp as IAlias;
IList<string> names = alias.AliasNames; object a = alias["a"]; object b = alias["b"]; object t = alias.GetType("a"); double x = 0.8;
alias["a"] = x;
a = alias["a"];
Aliases can be accessed from desktop by following way.
IDesktop desktop = ...;
object a = desktop.GetAliasValue("Exp.a"); object t = desktop.GetAliasType("Exp.a"); double x = 0.8;
desktop.SetAliasValue("Exp.a", x);
a = desktop.GetAliasValue("Exp.a");
Also one can set aliases by following function
public static void SetAliases(this IDesktop desktop, XmlDocument document)
If document (second argument of above function) contains following element:
<Aliases Desktop="Exponent.cfa">
<Alias>
<Name>Exp.a</Name>
<Value>0.7</Value>
<Type>System.Double</Type>
</Alias>
<Alias>
<Name>Exp.b</Name>
<Value>0.3</Value>
<Type>System.Double</Type>
</Alias>
</Aliases>
then call of this function is equivalent to following code:
desktop.SetAliasValue("Exp.a", (double)0.7);
desktop.SetAliasValue("Exp.b", (double)0.3);
Business of constant input is call of SetAliases
function with proper arguments.
2.3.2 Client component
Following user control implicitly performs remote call SetAliases
. The term "implicitly" means that this task is not independent. Setting of aliases every time is subtask of major task.
public partial class SilverlightControlAlias : UserControl, IPostLoadService,
IAddRequest, IErrorHandlerConsumer
It has following key properties
<SilverlightDiagramUI:SilverlightControlAlias Desktop="Exponent.cfa" Aliases="ExponentAliases.xml" />
Where Desktop="Exponent.cfa"
(resp. Aliases="ExponentAliases.xml"
) is file name of desktop (resp. aliases). As IPostLoadService
it sends following initialization request.
<Aliases Desktop="Exponent.cfa" Aliases="ExponentAliases.xml" />
From content of files "Exponent.cfa"
, ExponentAliases.xml"
server generates following response
<Aliases>
<Item>
<Number>1</Number>
<Name> The "a" coefficient </Name>
<Alias>Exp.a</Alias>
<Value>0.7</Value>
<Type>System.Double</Type>
</Item>
<Item>
<Number>2</Number>
<Name> The "b" coefficient </Name>
<Alias>Exp.b</Alias>
<Value>0.3</Value>
<Type>System.Double</Type>
</Item>
</Aliases>
Then user control receives initialization response and its appearance is changed by following way:
This component implements IAddRequest
interface. So it provides information about values of aliases for major task. Additional information is considered in 2.2.2.
2.3 Output of chart
2.3.1 Business logic
Our sample
contains Chart component. Besides graphical mode it has text one.
This mode generates following XML:
<Root>
<Parameters>
<Parameter Name="Value" Value="0.7" />
<Parameter Name="Argument" Value="0" />
</Parameters>
<Parameters>
<Parameter Name="Value" Value="0.702103153152364" />
<Parameter Name="Argument" Value="0.01" />
</Parameters>
<Parameters>
<Parameter Name="Value" Value="0.704212625237845" />
<Parameter Name="Argument" Value="0.02" />
</Parameters>
<Parameters>
<Parameter Name="Value" Value="0.706328435241708" />
<Parameter Name="Argument" Value="0.03" />
</Parameters>
</Root>
This XML is returned by following function
static public XmlDocument CreateXmlDocument(this IDesktop desktop, XmlDocument input)
where input
is represented by following text.
<ChartDocument>
<Interval>
<Start>0</Start>
<Step>0.01</Step>
<Finish>0.03</Finish></Interval>
<ChartName>Chart</ChartName>
<Parameters>
<Parameter>
<Name>Exp.Formula_1</Name>
<Value>Value</Value>
</Parameter>
<Parameter>
<Name>Exp.Formula_2</Name>
<Value>Argument</Value>
</Parameter>
</Parameters>
</ChartDocument>
2.3.2 Client componentt
Client has following user control
public partial class SilverlightControlHtmlOutput : UserControl, IRequest,
IErrorHandlerConsumer, IPostLoadService
This control has following key properties:
<SilverlightControlHtmlOutput Desktop="Exponent.cfa" Xslt="Exponent.xslt"
Chart="Exponent.xml" ScriptFunction="showOutput" />
Here Desktop="Exponent.cfa"
is filename of serialized desktop. The Exponent.xml
<WriteText>;
<Interval>
<Start>0</Start>
<Step>500</Step>
<Finish>20000</Finish>
</Interval>
<ChartName>Chart</ChartName>
<Argument>Time</Argument>
<Parameters>
<Parameter>
<Name>Exp.Formula_1</Name>
<Value>Value</Value>
</Parameter>
<Parameter>
<Name>Exp.Formula_2</Name>
<Value>Argument</Value>
</Parameter>
</Parameters>
</WriteText>
This XML is responsible for initial appearance of user control
and call of CreateXmlDocument
function. These so this XML document structure of output document.
<>
>N | Output parameter | Name in output XML |
1 | Exp.Formula_1 | Value |
1 | Exp.Formula_2 | Argument |
Class SilverlightControlHtmlOutput
as IPostLoadService
sends following request to server:
<Chart>ExponentChart.xml</Chart>
Server response is content of ExponentChart.xml
. In result of this initialization user control obtains following visual appearance:
This class also implements following interface:
public interface IRequest
{
void Request();
}
The Request
sends to server following request.
<ChartDocument Chart="ExponentChart.xml" ShowFunction="showOutput" Desktop="Exponent.cfa">
<Parameters>
<Start>0</Start>
<Step>1000</Step>
<Finish>20000</Finish>
<Xslt>Exponent.xslt</Xslt>
</Parameters>
</ChartDocument>
This request and content of "ExponentChart.xml"
generate following XML:
<ChartDocument Chart="ExponentChart.xml" Desktop="Exponent.cfa">
<Interval>
<Start>0</Start>
<Step>1000</Step>
<Finish>20000</Finish>
<Xslt>Exponent.xslt</Xslt>
</Interval>
<ChartName>Chart</ChartName>
<Parameters>
<Parameter>
<Name>Exp.Formula_1</Name>
<Value>Value</Value>
</Parameter>
<Parameter>
<Name>Exp.Formula_2</Name>
<Value>Argument</Value>
</Parameter>
</Parameters>
</ChartDocument>
This XML is used as argument of CreateXmlDocument
function which returns following document:
<Root>
<Parameters>
<Parameter Name="Value" Value="0.7" />
<Parameter Name="Argument" Value="0" />
</Parameters>
<Parameters>
<Parameter Name="Value" Value="1.35969847666886E+130" />
<Parameter Name="Argument" Value="1000" /></Parameters>
<Parameters><Parameter Name="Value" Value="2.64111421065087E+260" />
<Parameter Name="Value" Value="2.64111421065087E+260" />
<Parameter Name="Argument" Value="2000" />
</Parameters>
</Root>
Then this XML is transformed by XSLT which is contained in Exponent.xslt
file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:my-scripts">
<xsl:key name="parameter-search" match="Parameter" use="@Name"/>
<xsl:template match="/">
<text>
<h1>
Table of <em>
ae<sup>bx</sup>
</em>
</h1>
<table border="1">
<tr>
<td>
<em>x</em>
</td>
<td>
<em>
ae<sup>bx</sup>
</em>
</td>
</tr>
<xsl:apply-templates/>
</table>
</text>
</xsl:template>
<xsl:template match="Parameters">
<tr>
<td>
<xsl:value-of select="Parameter[2]/@Value"/>
</td>
<td>
<xsl:value-of select="Parameter[1]/@Value"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
Transformation result is presented below:
<text>
<h1>Table of <em>ae<sup>bx</sup></em></h1>
<table border="1">
<tr><td><em>x</em></td><td><em>ae<sup>bx</sup></em></td></tr>
<tr><td>0</td><td>0.7</td></tr>
<tr><td>1000</td><td>1.35969847666886E+130</td></tr>
<tr><td>2000</td><td>2.64111421065087E+260</td></tr>
</table>
</text>
Server also generates error report. Result response contains calculation result
and exception report.
<Root>
<Text><![CDATA[<h1>Table of <em>ae<sup>bx</sup></em></h1>
<table border="1">
<tr><td><em>x</em></td><td><em>ae<sup>bx</sup></em></td></tr>
<tr><td>0</td><td>0.7</td></tr>
<tr><td>1000</td><td>1.35969847666886E+130</td></tr>
<tr><td>2000</td><td>2.64111421065087E+260</td></tr>
</table>]]>
</Text>
<Exceptions>
<Exception>
<Object>10</Object>
<StackTrace> at EngineeringInitializer.BasicEngineeringInitializer.<InitializeApplication>b__0(Object o)
at c:\AUsers\1MySoft\CSharp\src\src\EngineeringInitializer\BasicEngineeringInitializer.cs:line 68
at Calculation.Calculate.Update() at c:\Users\3D_MONSTR\AppData\Local\Temp\ewmveptb.0.cs:line 33
at DataPerformer.VectorFormulaConsumer.UpdateMeasurements()
at c:\AUsers\1MySoft\CSharp\src\src\DataPerformer\VectorFormulaConsumer.cs:line 401
</StackTrace>
<ExceptionMessage>Infinity</ExceptionMessage>
<ExceptionType>System.Exception</ExceptionType>
</Exception>
<Exception>
<Object>10</Object>
<StackTrace>
at OrbitalService.ServiceOrbital.<AppllicactionInitialize>b__0(Object o)
at c:\AUsers\1MySoft\CSharp\src\WCF\OrbitalService\ServiceOrbital.svc.cs:line 43
at DataPerformer.StaticExtensionDataPerformerAdvanced.<>c__DisplayClass5.<CreateXmlDocument>b__3()
at c:\AUsers\1MySoft\CSharp\src\src\DataPerformer\StaticExtensionDataPerformerAdvanced.cs:line 301
at DataPerformer.StaticExtensionDataPerformerBase.PerformFixed(IDataConsumer consumer,
Double start, Double step, Int32 count, ITimeMeasureProvider provider, IDifferentialEquationProcessor processor,
IComponentCollection collection, Int32 priority, Action action)
at c:\AUsers\1MySoft\CSharp\src\src\DataPerformer
\DataPerformer.Base\DataPerformer.Base\StaticExtensionDataPerformerBase.cs:line 1723
</StackTrace>
<ExceptionMessage>Infinity</ExceptionMessage>
<ExceptionType>System.Exception</ExceptionType>
</Exception>
</Exceptions>
</Root>
Content of Text
tag contains output HTML. Property ScriptFunction = "showOutput"
means that
showOutput
script is called.
<script type="text/javascript">
// Shows output
// text is output text
function showOutput(text) {
var div_preview = document.getElementById("Output");
div_preview.innerHTML = text;
}
</script>
-->
<div id="Output"></div>
Call of this script shows following:
+++++++++++++++++++++++++++++++
Table of aebx
<>
>x | aebx |
0 | 0.7 |
1000 | 1.35969847666886E+130 |
2000 | 2.64111421065087E+260 |
+++++++++++++++++++++++++++++++
2.4 Combination of user controls
It is clear that any of above component is useless as itself. For example exception handler never handles exceptions without substantial task. Following XAML code contains useful combination of user contrlos.
<UserControl xmlns:SilverlightDiagramUI="clr-namespace:Diagram.UI.SilverlightDiagramUI;
assembly=Diagram.UI.SilverlightDiagramUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataPerformer.UI.SilverlightDataPerformer"
x:Class="DataPerformer.UI.SilverlightDataPerformer.SilverlightControlChartInputOutput"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"><StackPanel>
<Grid x:Name="LayoutRoot" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<SilverlightDiagramUI:SilverlightControlAlias x:Name="Aliases" Grid.Column="0"
Grid.Row="0" HorizontalAlignment="Stretch" Margin="0,0,0,0" />
<local:SilverlightControlHtmlOutput x:Name="Chart" Grid.Column="0" Grid.Row="1" />
<Button click="Button_Click" content="Start" grid.row="2"
horizontalalignment="Stretch" margin="0,0,0,0" width="75" x:name="Start"/>
<local:SilverlightControlHtmlErrorHandler x:Name="Errors"
HorizontalAlignment="Left" Height="0" Grid.Row="2" Width="0" Visibility="Collapsed"/>
</Grid>
</StackPanel>
</UserControl>
Following sequence diagram explains logic of this user control.
This component appends aliases to chart request.st.
<ChartDocument Chart="ExponentChart.xml" Desktop="Exponent.cfa">
<Aliases Desktop="Exponent.cfa">
<Alias>
<Name>Exp.a</Name>
<Value>0.7</Value>
<Type>System.Double</Type>
</Alias>
<Alias>
<Name>Exp.b</Name>
<Value>0.3</Value>
<Type>System.Double</Type>
</Alias>
</Aliases>
<Parameters>
<Start>0</Start>
<Step>1000</Step>
<Finish>20000</Finish>
<Xslt>Exponent.xslt</Xslt>
</Parameters>
</ChartDocument>
If value of exponent become too big then program throws exceptions
Full picture of UI is presented below:
It contains aliases, parameters of interval, output html, error report.
3. Realistic sample. Artificial Earth's Satellite Motion Forecast
3.1 Business Logicgic
Business Logic of the this sample is already described hereere. But I have copied text for easy reading.
3.1.1 Motion model
The motion model of an artificial satellite is a system of ordinary differential equations that describe the motion in a Greenwich reference frame:
where
are the coordinates and components of velocity respectively,
is angular velocity of Earth, and
are components of the summary external acceleration. The current model contains gravitational force and the aerodynamic one. These accelerations can be defined by the following formulae:
The following table contains meaning of these parameters:
Component of ordinary differential equations is used for above equations. This component does not have a rich system of symbols and uses lower case variables only. However this component supports rich system of comments which is presented below:
These comments can contain mappings between variables and physical parameters. Independent variables of equations (x, y, z, u, v, w) are checked in right part. Mapping between these variables and
The component represents differential equations in the following way:
Besides independent variables equations contain additional parameters. The following table contains mapping of these parameters:
Some of these parameters are constants. Other parameters should be exported. Constants are checked and exported parameters are not checked below:
Exported parameters concern with gravity and atmosphere models. These models are contained in external libraries. The following picture contains components of motion model.
The Motion equations component is considered above component of ordinary differential equations. These equations have feedback. Right parts of equations depend on gravitational forces. Otherwise gravitational forces depend on coordinates of the satellite. The Vector component is used as feedback of Motion equations.
This picture has the following meaning. Variables x, y, z, u, v, w of Vector component are assigned to x, y, z, u, v, w variables of Motion equations. Input and output parameters of Vector are presented below:
Components Gravity, Atmosphere are objects obtained from external libraries which calculate Gravity of Earth and Earth's atmosphere respectively. Both these objects implement IObjectTransformer
interface. The G-transformation and A-transformation objects are helper objects which are used for application of Gravity, Atmosphere objects respectively. Properties of G-transformation are presented below:
The above picture has the following meaning. The G-transformation is connected to Gravity object. This object corresponds to exported Gravity
class (code of Gravity
class is above this text). The Gravity
class implements IObjectTransformer
interface. Input parameters of Gravity
are coordinates which are labeled by "x", "y", "z" labels. So above comboboxes are labeled by x", "y", "z labels. The above picture means that parameters x", "y", "z" are assigned to Formula_1, Formula_2, Formula_3 of Vector component. Otherwise Formula_1, Formula_2, Formula_3 of Vector are assigned to x, y, z of Motion equations. However Motion equations component uses parameters of G-transformation:
This picture means that parameters a, b, c of a, of Motion equations are assigned to parameters Gx, Gy, Gz of G-transformation. So of Earth's Gravity
function is exported to G-transformation. The Earth's atmosphere is exported in a similar way.
3.1.2 Generation of document
In this sample actual function f is used. However this function has another argument. This argument is Z- coordinate of the satellite.
Besides calculation, any software needs generation of documents. Facilities generation of documents are exhibited on forecast problem. Forecast document contains parameters of satellite motion in times of equator intersections. The following picture explains the forecast problem:
Satellite moves along its orbit. Parameters of motion correspond to the time when it moves from South to North and intersects equator. Satellite intersects equator when its Z - coordinate is equal to 0. If we have coordinates and time as function of Z, then we can see necessary parameters are values of these functions where Z = 0. The following picture represents a solution of this task.
The Delay component has FunctionAccumulator
type. This type is very similar to Transport delay of Simulink. However FunctionAccumulator
is more advanced. Properties of Delay are presented below:
The Delay component is connected to Data to data one. It stores latest output values of Data. The Step count = 4 means that Delay stores 4 last values of each output parameters. The Formula_4 of data is Z coordinate of satellite. So all parameters of Delay are considered as functions of Z. Let us consider all components of forecast. The Satellite component is a container which contains Motion equations of the satellite. The Data component is connected to Motion equations and adds time parameters to motion parameters. Properties of Data are presented below:
.
The Recursive component is similar to Memory component of Simulink. This component calculates time delay of Z coordinate. Properties of the Recursive element are presented below:
The Condition element is used for determination of time of equator intersection. Properties of Condition are presented below:
Meaning of parameters of this component is contained in comments:
And at last, Output component contains calculation of forecast parameters. It has the following formulae:
The 86 400 number is number of seconds in a day. The time function converts double
variable to DateTime
. The b is condition of equator intersection. Input parameters are motion parameters as functions of Z. Full list of parameters is contained in the following comments:
And at last, Chart component has the following properties:
These properties have the following meaning. Output is performed when condition variable is true
. In this case, condition is Formula_1 of Condition
object. It is condition of equator intersection. Output parameters are Formula_1 - Formula_7 of Output
object. Labels X, Y, Z, Vx, Vy, Vz are labels which are reflected in XML document. The XML document is presented below:
<Root>
<Parameters>
<Parameter Name="T" Value="Monday, June 28, 1999 11:17:05 PM.457" />
<Parameter Name="X" Value="-6595.47050815637" />
<Parameter Name="Y" Value="-2472.05799683873" />
<Parameter Name="Z" Value="0" />
<Parameter Name="Vx" Value="-0.541295154046453" />
<Parameter Name="Vy" Value="1.46945520971716" />
<Parameter Name="Vz" Value="7.45051367374592" />
</Parameters>
<Parameters>
<Parameter Name="T" Value="Tuesday, June 29, 1999 12:55:08 AM.068" />
<Parameter Name="X" Value="-7026.76544757067" />
<Parameter Name="Y" Value="487.053173194772" />
<Parameter Name="Z" Value="0" />
<Parameter Name="Vx" Value="0.117122882887633" />
<Parameter Name="Vy" Value="1.56173832654579" />
<Parameter Name="Vz" Value="7.45055871464937" />
</Parameters>
<Root>
The first parameter has DateTime
type and the other ones have double
type. The following code contains XSLT file.
<xsl:stylesheet version="1.0" xmlns:xsl=http://www.w3.org/1999/XSL/Transform
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:my-scripts">
<xsl:template match="/">
<html>
<body>
<p>
<h1>Forecast</h1>
</p>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="Parameters">
<p></p>
<p>
<table border="1">
<xsl:apply-templates />
</table>
</p>
</xsl:template>
<xsl:template match="Parameter">
<xsl:apply-templates />
<tr>
<td>
<xsl:value-of select="@Name" />
</td>
<td>
<xsl:value-of select="@Value" />
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
This XSLT code provides the following HTML document.
<>
>
T |
Monday, June 28, 1999 11:17:05 PM.457 |
X |
-6595.47050815637 |
Y |
-2472.05799683873 |
Z |
0 |
Vx |
-0.541295154046453 |
Vy |
1.46945520971716 |
Vz |
7.45051367374592 |
T |
Tuesday, June 29, 1999 12:55:08 AM.068 |
X |
-7026.76544757067 |
Y |
487.053173194772 |
Z |
0 |
Vx |
0.117122882887633 |
Vy |
1.56173832654579 |
Vz |
7.45055871464937 |
3.2 Web Version
As Web application this project is not principallly differerent from elementary project described in section 1. This project has output condition and this fact is reflected in following XML.
<WriteText>
<Interval>
<Start>1770457394</Start>
<Step>10</Step>
<Finish>1770460394</Finish>
</Interval>
<ChartName>Forecast</ChartName>
<Condition>Condition.Formula_1</Condition>
<Argument>Time</Argument>
<Parameters>
<Parameter>
<Name>Output.Formula_1</Name>
<Value>T</Value>
</Parameter>
<Parameter>
<Name>Output.Formula_2</Name>
<Value>X</Value>
</Parameter>
<Parameter>
<Name>Output.Formula_3</Name>
<Value>Y</Value>
</Parameter>
<Parameter>
<Name>Output.Formula_4</Name>
<Value>Vx</Value>
</Parameter>
<Parameter>
<Name>Output.Formula_5</Name>
<Value>Vy</Value>
</Parameter>
<Parameter>
<Name>Output.Formula_6</Name>
<Value>Vz</Value>
</Parameter>
</Parameters>
</WriteText>
Expression <Condition>Condition.Formula_1</Condition>
that output condition Formula_1 of Condition object. Following XML persents aliases:
<Root>
<Item>
<Number>1</Number> <Name> X - coordinate of the satellite (x) , km </Name>
<Alias>Motion equations/Motion equations.x</Alias>
<Type>System.Double</Type>
</Item>
<Item>
<Number>2</Number>
<Name> Y - coordinate of the satellite (y), km </Name>
<Alias>Motion equations/Motion equations.y</Alias>
<Type>System.Double</Type>
</Item>
<Item>
<Number>3</Number>
<Name> Z - coordinate of the satellite (z), km </Name>
<Alias>Motion equations/Motion equations.z</Alias>
<Type>System.Double</Type>
</Item>
<Item>
<Number>4</Number>
<Name> X - component of velicity of the satellite (Vx), km/s </Name>
<Alias>Motion equations/Motion equations.u</Alias>
<Type>System.Double</Type>
</Item>
<Item>
<Number>5</Number>
<Name> Y - component of velicity of the satellite (Vy), km/s </Name>
<Alias>Motion equations/Motion equations.v</Alias>
<Type>System.Double</Type>
</Item>
<Item>
<Number>6</Number>
<Name> Z - component of velicity of the satellite (Vz), km/s </Name>
<Alias>Motion equations/Motion equations.w</Alias>
<Type>System.Double</Type>
</Item>
</Root>gt;
These alises are initial conditions of differetial equation system.
Acting web client is placed at begin of this article.
Points of Interest
My very blue dream is invention of new time machine. I would like to develop online designer which is similar to Code Project one.
However my designer shall be a toolkit for developers of science and engineering portals.