<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://doc.expecco.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sv</id>
	<title>expecco Wiki (Version 25.x) - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://doc.expecco.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sv"/>
	<link rel="alternate" type="text/html" href="https://doc.expecco.de/wiki/Spezial:Beitr%C3%A4ge/Sv"/>
	<updated>2026-04-26T14:21:15Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Plot/Graph_Action_Blocks&amp;diff=30941</id>
		<title>Plot/Graph Action Blocks</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Plot/Graph_Action_Blocks&amp;diff=30941"/>
		<updated>2026-03-03T13:37:42Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
With expecco18.1, a new block type named &amp;quot;&#039;&#039;Plot/Graph Actions&#039;&#039;&amp;quot; was first introduced.&lt;br /&gt;
These behave similar to other script action blocks, in that they are defined by a script&lt;br /&gt;
(in this case: gnuplot scripting language) and are placed into the test sequence flow&lt;br /&gt;
just like any other block.&lt;br /&gt;
&lt;br /&gt;
However, when executed, these actions generate a graphic document (jpeg, png or postscript),&lt;br /&gt;
which is then either added to the activity log, or added as attachment. It will therefore be &lt;br /&gt;
available in the generated &amp;quot;&amp;lt;code&amp;gt;elf&amp;lt;/code&amp;gt;&amp;quot; execution log file, or shown in the generated &amp;quot;&amp;lt;code&amp;gt;pdf&amp;lt;/code&amp;gt;&amp;quot; report file.&lt;br /&gt;
Of course, you can do anything you like with the generated graphic file, by feeding the name&lt;br /&gt;
of the generated file to another action for further processing.&lt;br /&gt;
&lt;br /&gt;
Notice: if you prefer other graphic packages or other programming languages, you may of course use R language scripts or Python scripts (with matplotlib and/or seaboarn) to generate graphics in a similar way.&lt;br /&gt;
&lt;br /&gt;
== Creating Plot/Graph Action Blocks ==&lt;br /&gt;
&lt;br /&gt;
Plot/graph action blocks are created via the &lt;br /&gt;
&amp;quot;&#039;&#039;Actions&#039;&#039; - &#039;&#039;More&#039;&#039; - &#039;&#039;Plot/Graph&#039;&#039;&amp;quot; menu item.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Plot_Graph_Actions_in_Menu.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Select the &amp;quot;&#039;&#039;Plot/Graph&#039;&#039;&amp;quot; item, to create a new gnuplot action.&lt;br /&gt;
An initial set of input pins and an initial (demo-) script is generated for you.&lt;br /&gt;
&lt;br /&gt;
For details on the scripting language, please refer to the public  &lt;br /&gt;
[http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf gnuplot documentation].&lt;br /&gt;
&lt;br /&gt;
Any input pin named &amp;quot;&amp;lt;code&amp;gt;&amp;lt;pinName&amp;gt;&amp;lt;/code&amp;gt;&amp;quot; is available in the script as &amp;quot;&amp;lt;code&amp;gt;%(pinName)&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
Thus, the script can be parametrized in arbitrary ways.&lt;br /&gt;
A number of pins are already created for you; these are:&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;outputFile&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;both an input and an output. If the input is specified, gnuplot will generate the plot into that file. Otherwise, a new temporary file will be created and the output written into that. In any case will the actual outputFileName be available on the corresponding output pin for further processing.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;outputFormat&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;specifies the kind of file to generate. For inclusion into the report, an image format should be chosen (i.e. one of &amp;quot;jpeg&amp;quot;, &amp;quot;png&amp;quot; or &amp;quot;gif&amp;quot;). For archival or to generate high quality documents, you can also choose &amp;quot;postscript&amp;quot; or &amp;quot;svg&amp;quot;. However, those can (currently) not be automatically converted for the pdf report.&amp;lt;br&amp;gt;On Unix systems, you can also specify &amp;quot;x11&amp;quot; as output format. In this case, a window is opened, displaying the generated graph. Be aware that expecco is (currently) not informed about the window being closed, so you may have to stop the test-run via the expecco-&amp;quot;Stop&amp;quot; button. &lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;title&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;A title string to be drawn above the graphic (actually, the position of the title is specified by the &amp;quot;set key&amp;quot; gnuplot expression, inside the script)&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;data&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;If connected, and a collection of values is present, these values will be written into a temporary data file, and the filename is available in the gnuplot script as &amp;quot;&amp;lt;code&amp;gt;%(dataFile)&amp;lt;/code&amp;gt;&amp;quot;. This will be the raw data, to be processed by the script.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;dataSize&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;There is no pin for that, but the value is available to the script. It provides the number of data points (or rows) in the data file.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;attachToLog&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;if true (the default), the generated graph will be attached to the final pdf report. This pin&#039;s value is not forwarded to the gnuplot script.&lt;br /&gt;
&lt;br /&gt;
You can add additional input pins and refer to the corresponding pin value in the script with the &amp;quot;%(...)&amp;quot; notation.&lt;br /&gt;
&lt;br /&gt;
== A Simple Graph Script ==&lt;br /&gt;
&lt;br /&gt;
A typical gnuplot script looks like:&lt;br /&gt;
&lt;br /&gt;
 # The code below is sent to gnuplot and the generated output&lt;br /&gt;
 # will be stored in a file named %%(outputFile) &lt;br /&gt;
 # (unless explicitly specified, a temporary file is created)&lt;br /&gt;
 #&lt;br /&gt;
 set output &amp;quot;%(outputFile)&amp;quot;&lt;br /&gt;
  &lt;br /&gt;
 # &lt;br /&gt;
 set term %(outputFormat)&lt;br /&gt;
 &lt;br /&gt;
 # All input pin values can be used here as %%(nameOfPin).&lt;br /&gt;
 # so the next line controls the title via the &amp;quot;title&amp;quot; pin&lt;br /&gt;
 #&lt;br /&gt;
 set title &amp;quot;%(title)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 # You can add more pins.&lt;br /&gt;
 # For example, add pins named &amp;quot;min&amp;quot; and &amp;quot;max&amp;quot; with type Number,&lt;br /&gt;
 # and replace &amp;quot;-10:10&amp;quot; below by &amp;quot;%%(min):%%(max) to parametrize the y-axis range.&lt;br /&gt;
 set key left box&lt;br /&gt;
 plot [1:%(dataSize)] [-10:10] &amp;quot;%(dataFile)&amp;quot; title &amp;quot;My Data&amp;quot; with impulses&lt;br /&gt;
&lt;br /&gt;
to plot a simple impulse graph of the data values, as presented at the input pin,&lt;br /&gt;
assuming that the pins get the following values:&lt;br /&gt;
* &amp;quot;outputFile&amp;quot; - leave unconnected or remove the pin (to let the action choose a temp file)&lt;br /&gt;
* &amp;quot;outputFormat&amp;quot; - freeze as &amp;quot;&amp;lt;code&amp;gt;png&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
* &amp;quot;title&amp;quot; - any title - such as &amp;quot;Measurement #1&amp;quot;&lt;br /&gt;
* &amp;quot;data&amp;quot; - a vector of numbers&lt;br /&gt;
&lt;br /&gt;
Of course, this is actually the simplest possible script to render such data.&lt;br /&gt;
Gnuplot provides a wide area of possible plots, both 2D and 3D, with or without colors, etc.&lt;br /&gt;
A few examples are provided in the &amp;quot;&amp;lt;code&amp;gt;Plot_Graph Library.ets&amp;lt;/code&amp;gt;&amp;quot;, but much more is found on the gnuplot&lt;br /&gt;
website [http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf gnu plot documentation].&lt;br /&gt;
&lt;br /&gt;
== Short List of Useful Script Commands ==&lt;br /&gt;
&lt;br /&gt;
For a full list, please take a look at the [http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf gnu plot documentation]. The following list is only presenting the most common plot commands:&lt;br /&gt;
* &amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with impulses&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;You can omit the &amp;quot;[yMin:yMax]&amp;quot; parameter, for a reasonable box to be automatically chosen by gnuplot.&amp;lt;br&amp;gt;Replace &amp;quot;nameOfDataFile&amp;quot; by &amp;quot;%(dataFile)&amp;quot; if the data comes via an input pin and is not already in a file.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;Without the &amp;quot;impulses&amp;quot; parameter, a regular graph is drawn (straight lines between points)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with: lines&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;The same as above (straight lines between points)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with: dots&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;Draws dots&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with candlesticks&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;the data file should contain multiple colums per line. Select the colums with a &amp;quot;using...&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set key left box&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines the position (left) and type (boxed) of the graph-title (the string comes from the &amp;lt;code&amp;gt;title &amp;quot;graph title&amp;quot;&amp;lt;/code&amp;gt; argument in the plot command)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set title &amp;quot;someTitle&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines a headline title&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set term %(outputFormat)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines the type of image to be generated. For &amp;quot;%(outputFormat)&amp;quot;, the input pin&#039;s format is generated. Otherwise, you can also hardcode any of &amp;quot;&amp;lt;code&amp;gt;png&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;jpg&amp;lt;/code&amp;gt;&amp;quot;, etc. here&lt;br /&gt;
&lt;br /&gt;
A few examples are found in the demo library: &amp;quot;Plot_Graph_Library.ets&amp;quot;, which is found in the plugin&#039;s folder and in the online documentation [http://www.gnuplot.info/docs_5.0/gnuplot.pdf &amp;quot;http://www.gnuplot.info/docs_5.0/gnuplot.pdf&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
== Accessing Data from Attachments ==&lt;br /&gt;
&lt;br /&gt;
You can directly access expecco attachment files by their name inside the script. I.e. if you have an attachment with file named &amp;quot;&amp;lt;code&amp;gt;foo.dat&amp;lt;/code&amp;gt;&amp;quot;, use &amp;lt;code&amp;gt;... data &amp;quot;foo.dat&amp;quot; ...&amp;lt;/code&amp;gt; inside the script. Notice that the attchment&#039;s filename is to be used - not its name in the tree.&lt;br /&gt;
&lt;br /&gt;
== Plotting Multiple Graphs into a Single Picture ==&lt;br /&gt;
&lt;br /&gt;
To do this, generate multiple datasets (as ascii files, with one textline per row). Add &amp;lt;code&amp;gt;data&amp;amp;lt;i&amp;amp;gt;&amp;lt;/code&amp;gt; input pins and feed them the filenames. Add multiple &amp;lt;code&amp;gt;plot&amp;lt;/code&amp;gt; commands, each with its own &amp;quot;&amp;lt;code&amp;gt;%(data&amp;amp;lt;i&amp;amp;gt;&amp;lt;/code&amp;gt;)&amp;quot; argument, and possibly with its own graph-title.&lt;br /&gt;
&lt;br /&gt;
== Changing the Size of the Generated Image ==&lt;br /&gt;
&lt;br /&gt;
By default, the generated image&#039;s size is 640 x 400 pixels.&lt;br /&gt;
For a fix size, change the script&#039;s &amp;quot;&amp;lt;code&amp;gt;set term&amp;lt;/code&amp;gt;&amp;quot; statement to:&lt;br /&gt;
&lt;br /&gt;
 set term %(outputFormat) size &amp;lt;width&amp;gt;,&amp;lt;height&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;lt;width&amp;amp;gt; and &amp;amp;lt;height&amp;amp;gt; define the size in pixels.&lt;br /&gt;
&lt;br /&gt;
Alternatively, add two pins named &amp;quot;&#039;&#039;width&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;height&#039;&#039;&amp;quot;, and&lt;br /&gt;
change the statement to:&lt;br /&gt;
&lt;br /&gt;
 set term %(outputFormat) size %(width),%(height)&lt;br /&gt;
&lt;br /&gt;
and provide the desired size (as integers) at the input pins.&lt;br /&gt;
&lt;br /&gt;
== Caveats ==&lt;br /&gt;
&lt;br /&gt;
Do not place &amp;lt;code&amp;gt;pause&amp;lt;/code&amp;gt; statements into the script; there is no input stream given to gnuplot, so it will immediately read an EOF (end of file) and proceed.&lt;br /&gt;
&lt;br /&gt;
== Complete Example 1: Gathering Response Times of MQTT Protocol Messages ==&lt;br /&gt;
&lt;br /&gt;
This example demonstrates, how a test suite can gather response times of a remote system,&lt;br /&gt;
when sending MQTT messages to it.&lt;br /&gt;
&lt;br /&gt;
==== Step 1: Define the Test Sequence ====&lt;br /&gt;
&lt;br /&gt;
this is a very simple publish-response setup, in that a topic is published to an MQTT broker,&lt;br /&gt;
and the time measured, until the notification arrives (in order to run this on your machine,&lt;br /&gt;
the expecco MQTT plugin needs to be installed):&lt;br /&gt;
&lt;br /&gt;
Outside (Schema) view of the measuring action:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schema_Measuring_MQTT.png|400px]]&lt;br /&gt;
&lt;br /&gt;
which is implemented as:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Net_Measuring_MQTT.png|800px]]&lt;br /&gt;
&lt;br /&gt;
The yellow area does the MQTT setup. First, an MQTT client connection is created,&lt;br /&gt;
and the client handle forwarded to the Subscribe action, which registers expecco&lt;br /&gt;
to react to the &amp;quot;expeccoTesting/test&amp;quot; topic.&lt;br /&gt;
&lt;br /&gt;
The green area does the actual publish operation,&lt;br /&gt;
publishing the &amp;quot;Hello from Expecco&amp;quot; string on this topic.&lt;br /&gt;
&lt;br /&gt;
In parallel, the blue area waits for the next incoming event,&lt;br /&gt;
(and generates a printed detail info on the received packet for the&lt;br /&gt;
activity log).&lt;br /&gt;
&lt;br /&gt;
The red area contains a stopWatch action block, which gets started&lt;br /&gt;
with when the publish is done, and stops when the event arrives.&lt;br /&gt;
&lt;br /&gt;
The measurement action is prametrized with the broker&#039;s host and port,&lt;br /&gt;
and generates the measured timeDuration as output.&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Test Run ====&lt;br /&gt;
&lt;br /&gt;
Assuming that you have an MQTT client running on the local host,&lt;br /&gt;
the test sequence can be immediately tried via the Test/Demo page:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Test_Measuring_MQTT.png|300px]]&lt;br /&gt;
&lt;br /&gt;
A good strategy is to package the MQTT broker into a docker file.&lt;br /&gt;
Here is the MQTT client&#039;s output of the above run:&lt;br /&gt;
&lt;br /&gt;
 $ sh rundocker.sh &lt;br /&gt;
 1522084243: mosquitto version 1.4.8 (build date Thu, 01 Mar 2018 09:34:49 -0500) starting&lt;br /&gt;
 1522084243: Using default config.&lt;br /&gt;
 1522084243: Opening ipv4 listen socket on port 1883.&lt;br /&gt;
 1522084243: Opening ipv6 listen socket on port 1883.&lt;br /&gt;
 1522084272: New connection from 172.17.0.1 on port 1883.&lt;br /&gt;
 1522084272: New client connected from 172.17.0.1 as expeccoMQTT (c1, k0).&lt;br /&gt;
 1522084272: Client expeccoMQTT disconnected.&lt;br /&gt;
&lt;br /&gt;
and here the activitylog in expecco:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log1_Measuring_MQTT.png|600px]]&lt;br /&gt;
&lt;br /&gt;
with the event info detail:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log2_Measuring_MQTT.png|600px]]&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Running that Sequence Multiple Times ====&lt;br /&gt;
&lt;br /&gt;
Now that we have verified, that the communication with the MQTT broker works correctly,&lt;br /&gt;
we create another action bock, which runs the above action multiple times and collects&lt;br /&gt;
all the execution times:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT.png|700px]]&lt;br /&gt;
&lt;br /&gt;
[ explanation: first, a new empty colletion is created, then, the timing values of&lt;br /&gt;
the multi-triggered measure-step are all added to this collection.&lt;br /&gt;
When done (no step active), the collection is forwarded (now filled) to the output pin]&lt;br /&gt;
&lt;br /&gt;
Here is the activity log after 10 runs:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log1_Multiple_Measuring_MQTT.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==== Step 4: Adding the Graph ====&lt;br /&gt;
&lt;br /&gt;
The last step is the easiest: select the &amp;quot;New Plot/Graph&amp;quot; action block from the menu,&lt;br /&gt;
name it &amp;quot;Time Measurement Graph&amp;quot;&lt;br /&gt;
and change its autogenerated gnuplot script to:&lt;br /&gt;
&lt;br /&gt;
 set output &amp;quot;%(outputFile)&amp;quot;&lt;br /&gt;
 set term %(outputFormat)&lt;br /&gt;
 set title &amp;quot;%(title)&amp;quot;&lt;br /&gt;
 set key left box&lt;br /&gt;
 plot [1:%(dataSize)] [0:100] &amp;quot;%(dataFile)&amp;quot; title &amp;quot;%(lineTitle)&amp;quot; with impulses&lt;br /&gt;
&lt;br /&gt;
then place a step of it into your network and connect the &amp;quot;collectedTimes&amp;quot; output of the above measurement step with the &amp;quot;data&amp;quot; input&lt;br /&gt;
of the &amp;quot;Measurement-Graph&amp;quot; step:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_plus_Graph_MQTT.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Running it, and generating the report, produces the following pdf-report (the logging of subactivities was disabled for this report):&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT_Report_img.png|700px]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT_Report.pdf]]&lt;br /&gt;
&lt;br /&gt;
== Example 1 Simplified: Using Probes to Gather the Data ==&lt;br /&gt;
&lt;br /&gt;
The above data collection may look a bit complicated, due to the need for start/stop synchronization.&lt;br /&gt;
A much nicer and easier to use solution is in using a probe to gather the data.&lt;br /&gt;
For this, we need a probe which does no range checks, but instead only collects the incoming values:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_Probe.png|700px]]&lt;br /&gt;
&lt;br /&gt;
Here, a probe was added (via the &amp;quot;timeDelta&amp;quot; pin&#039;s &amp;quot;Add Probe&amp;quot; menu item),&lt;br /&gt;
and specified to &amp;quot;collect incoming data without check&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_ProbeMenu.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Now that we have a probe at the roundtrip time,&lt;br /&gt;
the outer measurement looks much simpler:&lt;br /&gt;
&lt;br /&gt;
* reset the probe (to clear any previously gathered data)&lt;br /&gt;
* prime the probe enable data collecting)&lt;br /&gt;
* run the roundtrip-test n-times&lt;br /&gt;
* unprime the probe (disable further data collecting)&lt;br /&gt;
* fetch the probe&#039;s values and pass them to the gnuplot action&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_Probe2.png|500px]]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
[http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf Gnuplot Manual]&lt;br /&gt;
&amp;lt;br&amp;gt;[https://alvinalexander.com/technology/gnuplot-charts-graphs-examples Collection of Examples]&lt;br /&gt;
&lt;br /&gt;
&amp;quot;[[R Action Blocks]]&amp;quot; which provide similar graph/plot functions in addition to sophisticated mathematical and statistics libraries.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;quot;[[Octave Script Action Tutorial|Octave/Matlab Actions]]&amp;quot; another framework for mathematical computations and/or to generate graphs/plots.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- {{Languages}} --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Languages ]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Plot/Graph_Action_Blocks&amp;diff=30940</id>
		<title>Plot/Graph Action Blocks</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Plot/Graph_Action_Blocks&amp;diff=30940"/>
		<updated>2026-03-03T13:36:32Z</updated>

		<summary type="html">&lt;p&gt;Sv: Renamed %(data) to %(dataFile)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
With expecco18.1, a new block type named &amp;quot;&#039;&#039;Plot/Graph Actions&#039;&#039;&amp;quot; is introduced.&lt;br /&gt;
These behave similar to other script action blocks, in that they are defined by a script&lt;br /&gt;
(in this case: gnuplot scripting language) and are placed into the test sequence flow&lt;br /&gt;
just like any other block.&lt;br /&gt;
&lt;br /&gt;
However, when executed, these actions generate a graphic document (jpeg, png or postscript),&lt;br /&gt;
which is then either added to the activity log, or added as attachment. It will therefore be &lt;br /&gt;
available in the generated &amp;quot;&amp;lt;code&amp;gt;elf&amp;lt;/code&amp;gt;&amp;quot; execution log file, or shown in the generated &amp;quot;&amp;lt;code&amp;gt;pdf&amp;lt;/code&amp;gt;&amp;quot; report file.&lt;br /&gt;
Of course, you can do anything you like with the generated graphic file, by feeding the name&lt;br /&gt;
of the generated file to another action for further processing.&lt;br /&gt;
&lt;br /&gt;
Notice: if you prefer other graphic packages or other programming languages, you may of course use R language scripts or Python scripts (with matplotlib and/or seaboarn) to generate graphics in a similar way.&lt;br /&gt;
&lt;br /&gt;
== Creating Plot/Graph Action Blocks ==&lt;br /&gt;
&lt;br /&gt;
Plot/graph action blocks are created via the &lt;br /&gt;
&amp;quot;&#039;&#039;Actions&#039;&#039; - &#039;&#039;More&#039;&#039; - &#039;&#039;Plot/Graph&#039;&#039;&amp;quot; menu item.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Plot_Graph_Actions_in_Menu.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Select the &amp;quot;&#039;&#039;Plot/Graph&#039;&#039;&amp;quot; item, to create a new gnuplot action.&lt;br /&gt;
An initial set of input pins and an initial (demo-) script is generated for you.&lt;br /&gt;
&lt;br /&gt;
For details on the scripting language, please refer to the public  &lt;br /&gt;
[http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf gnuplot documentation].&lt;br /&gt;
&lt;br /&gt;
Any input pin named &amp;quot;&amp;lt;code&amp;gt;&amp;lt;pinName&amp;gt;&amp;lt;/code&amp;gt;&amp;quot; is available in the script as &amp;quot;&amp;lt;code&amp;gt;%(pinName)&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
Thus, the script can be parametrized in arbitrary ways.&lt;br /&gt;
A number of pins are already created for you; these are:&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;outputFile&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;both an input and an output. If the input is specified, gnuplot will generate the plot into that file. Otherwise, a new temporary file will be created and the output written into that. In any case will the actual outputFileName be available on the corresponding output pin for further processing.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;outputFormat&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;specifies the kind of file to generate. For inclusion into the report, an image format should be chosen (i.e. one of &amp;quot;jpeg&amp;quot;, &amp;quot;png&amp;quot; or &amp;quot;gif&amp;quot;). For archival or to generate high quality documents, you can also choose &amp;quot;postscript&amp;quot; or &amp;quot;svg&amp;quot;. However, those can (currently) not be automatically converted for the pdf report.&amp;lt;br&amp;gt;On Unix systems, you can also specify &amp;quot;x11&amp;quot; as output format. In this case, a window is opened, displaying the generated graph. Be aware that expecco is (currently) not informed about the window being closed, so you may have to stop the test-run via the expecco-&amp;quot;Stop&amp;quot; button. &lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;title&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;A title string to be drawn above the graphic (actually, the position of the title is specified by the &amp;quot;set key&amp;quot; gnuplot expression, inside the script)&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;data&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;If connected, and a collection of values is present, these values will be written into a temporary data file, and the filename is available in the gnuplot script as &amp;quot;&amp;lt;code&amp;gt;%(dataFile)&amp;lt;/code&amp;gt;&amp;quot;. This will be the raw data, to be processed by the script.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;dataSize&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;There is no pin for that, but the value is available to the script. It provides the number of data points (or rows) in the data file.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;attachToLog&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;if true (the default), the generated graph will be attached to the final pdf report. This pin&#039;s value is not forwarded to the gnuplot script.&lt;br /&gt;
&lt;br /&gt;
You can add additional input pins and refer to the corresponding pin value in the script with the &amp;quot;%(...)&amp;quot; notation.&lt;br /&gt;
&lt;br /&gt;
== A Simple Graph Script ==&lt;br /&gt;
&lt;br /&gt;
A typical gnuplot script looks like:&lt;br /&gt;
&lt;br /&gt;
 # The code below is sent to gnuplot and the generated output&lt;br /&gt;
 # will be stored in a file named %%(outputFile) &lt;br /&gt;
 # (unless explicitly specified, a temporary file is created)&lt;br /&gt;
 #&lt;br /&gt;
 set output &amp;quot;%(outputFile)&amp;quot;&lt;br /&gt;
  &lt;br /&gt;
 # &lt;br /&gt;
 set term %(outputFormat)&lt;br /&gt;
 &lt;br /&gt;
 # All input pin values can be used here as %%(nameOfPin).&lt;br /&gt;
 # so the next line controls the title via the &amp;quot;title&amp;quot; pin&lt;br /&gt;
 #&lt;br /&gt;
 set title &amp;quot;%(title)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 # You can add more pins.&lt;br /&gt;
 # For example, add pins named &amp;quot;min&amp;quot; and &amp;quot;max&amp;quot; with type Number,&lt;br /&gt;
 # and replace &amp;quot;-10:10&amp;quot; below by &amp;quot;%%(min):%%(max) to parametrize the y-axis range.&lt;br /&gt;
 set key left box&lt;br /&gt;
 plot [1:%(dataSize)] [-10:10] &amp;quot;%(dataFile)&amp;quot; title &amp;quot;My Data&amp;quot; with impulses&lt;br /&gt;
&lt;br /&gt;
to plot a simple impulse graph of the data values, as presented at the input pin,&lt;br /&gt;
assuming that the pins get the following values:&lt;br /&gt;
* &amp;quot;outputFile&amp;quot; - leave unconnected or remove the pin (to let the action choose a temp file)&lt;br /&gt;
* &amp;quot;outputFormat&amp;quot; - freeze as &amp;quot;&amp;lt;code&amp;gt;png&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
* &amp;quot;title&amp;quot; - any title - such as &amp;quot;Measurement #1&amp;quot;&lt;br /&gt;
* &amp;quot;data&amp;quot; - a vector of numbers&lt;br /&gt;
&lt;br /&gt;
Of course, this is actually the simplest possible script to render such data.&lt;br /&gt;
Gnuplot provides a wide area of possible plots, both 2D and 3D, with or without colors, etc.&lt;br /&gt;
A few examples are provided in the &amp;quot;&amp;lt;code&amp;gt;Plot_Graph Library.ets&amp;lt;/code&amp;gt;&amp;quot;, but much more is found on the gnuplot&lt;br /&gt;
website [http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf gnu plot documentation].&lt;br /&gt;
&lt;br /&gt;
== Short List of Useful Script Commands ==&lt;br /&gt;
&lt;br /&gt;
For a full list, please take a look at the [http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf gnu plot documentation]. The following list is only presenting the most common plot commands:&lt;br /&gt;
* &amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with impulses&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;You can omit the &amp;quot;[yMin:yMax]&amp;quot; parameter, for a reasonable box to be automatically chosen by gnuplot.&amp;lt;br&amp;gt;Replace &amp;quot;nameOfDataFile&amp;quot; by &amp;quot;%(dataFile)&amp;quot; if the data comes via an input pin and is not already in a file.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;Without the &amp;quot;impulses&amp;quot; parameter, a regular graph is drawn (straight lines between points)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with: lines&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;The same as above (straight lines between points)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with: dots&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;Draws dots&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with candlesticks&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;the data file should contain multiple colums per line. Select the colums with a &amp;quot;using...&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set key left box&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines the position (left) and type (boxed) of the graph-title (the string comes from the &amp;lt;code&amp;gt;title &amp;quot;graph title&amp;quot;&amp;lt;/code&amp;gt; argument in the plot command)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set title &amp;quot;someTitle&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines a headline title&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set term %(outputFormat)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines the type of image to be generated. For &amp;quot;%(outputFormat)&amp;quot;, the input pin&#039;s format is generated. Otherwise, you can also hardcode any of &amp;quot;&amp;lt;code&amp;gt;png&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;jpg&amp;lt;/code&amp;gt;&amp;quot;, etc. here&lt;br /&gt;
&lt;br /&gt;
A few examples are found in the demo library: &amp;quot;Plot_Graph_Library.ets&amp;quot;, which is found in the plugin&#039;s folder and in the online documentation [http://www.gnuplot.info/docs_5.0/gnuplot.pdf &amp;quot;http://www.gnuplot.info/docs_5.0/gnuplot.pdf&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
== Accessing Data from Attachments ==&lt;br /&gt;
&lt;br /&gt;
You can directly access expecco attachment files by their name inside the script. I.e. if you have an attachment with file named &amp;quot;&amp;lt;code&amp;gt;foo.dat&amp;lt;/code&amp;gt;&amp;quot;, use &amp;lt;code&amp;gt;... data &amp;quot;foo.dat&amp;quot; ...&amp;lt;/code&amp;gt; inside the script. Notice that the attchment&#039;s filename is to be used - not its name in the tree.&lt;br /&gt;
&lt;br /&gt;
== Plotting Multiple Graphs into a Single Picture ==&lt;br /&gt;
&lt;br /&gt;
To do this, generate multiple datasets (as ascii files, with one textline per row). Add &amp;lt;code&amp;gt;data&amp;amp;lt;i&amp;amp;gt;&amp;lt;/code&amp;gt; input pins and feed them the filenames. Add multiple &amp;lt;code&amp;gt;plot&amp;lt;/code&amp;gt; commands, each with its own &amp;quot;&amp;lt;code&amp;gt;%(data&amp;amp;lt;i&amp;amp;gt;&amp;lt;/code&amp;gt;)&amp;quot; argument, and possibly with its own graph-title.&lt;br /&gt;
&lt;br /&gt;
== Changing the Size of the Generated Image ==&lt;br /&gt;
&lt;br /&gt;
By default, the generated image&#039;s size is 640 x 400 pixels.&lt;br /&gt;
For a fix size, change the script&#039;s &amp;quot;&amp;lt;code&amp;gt;set term&amp;lt;/code&amp;gt;&amp;quot; statement to:&lt;br /&gt;
&lt;br /&gt;
 set term %(outputFormat) size &amp;lt;width&amp;gt;,&amp;lt;height&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;lt;width&amp;amp;gt; and &amp;amp;lt;height&amp;amp;gt; define the size in pixels.&lt;br /&gt;
&lt;br /&gt;
Alternatively, add two pins named &amp;quot;&#039;&#039;width&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;height&#039;&#039;&amp;quot;, and&lt;br /&gt;
change the statement to:&lt;br /&gt;
&lt;br /&gt;
 set term %(outputFormat) size %(width),%(height)&lt;br /&gt;
&lt;br /&gt;
and provide the desired size (as integers) at the input pins.&lt;br /&gt;
&lt;br /&gt;
== Caveats ==&lt;br /&gt;
&lt;br /&gt;
Do not place &amp;lt;code&amp;gt;pause&amp;lt;/code&amp;gt; statements into the script; there is no input stream given to gnuplot, so it will immediately read an EOF (end of file) and proceed.&lt;br /&gt;
&lt;br /&gt;
== Complete Example 1: Gathering Response Times of MQTT Protocol Messages ==&lt;br /&gt;
&lt;br /&gt;
This example demonstrates, how a test suite can gather response times of a remote system,&lt;br /&gt;
when sending MQTT messages to it.&lt;br /&gt;
&lt;br /&gt;
==== Step 1: Define the Test Sequence ====&lt;br /&gt;
&lt;br /&gt;
this is a very simple publish-response setup, in that a topic is published to an MQTT broker,&lt;br /&gt;
and the time measured, until the notification arrives (in order to run this on your machine,&lt;br /&gt;
the expecco MQTT plugin needs to be installed):&lt;br /&gt;
&lt;br /&gt;
Outside (Schema) view of the measuring action:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schema_Measuring_MQTT.png|400px]]&lt;br /&gt;
&lt;br /&gt;
which is implemented as:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Net_Measuring_MQTT.png|800px]]&lt;br /&gt;
&lt;br /&gt;
The yellow area does the MQTT setup. First, an MQTT client connection is created,&lt;br /&gt;
and the client handle forwarded to the Subscribe action, which registers expecco&lt;br /&gt;
to react to the &amp;quot;expeccoTesting/test&amp;quot; topic.&lt;br /&gt;
&lt;br /&gt;
The green area does the actual publish operation,&lt;br /&gt;
publishing the &amp;quot;Hello from Expecco&amp;quot; string on this topic.&lt;br /&gt;
&lt;br /&gt;
In parallel, the blue area waits for the next incoming event,&lt;br /&gt;
(and generates a printed detail info on the received packet for the&lt;br /&gt;
activity log).&lt;br /&gt;
&lt;br /&gt;
The red area contains a stopWatch action block, which gets started&lt;br /&gt;
with when the publish is done, and stops when the event arrives.&lt;br /&gt;
&lt;br /&gt;
The measurement action is prametrized with the broker&#039;s host and port,&lt;br /&gt;
and generates the measured timeDuration as output.&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Test Run ====&lt;br /&gt;
&lt;br /&gt;
Assuming that you have an MQTT client running on the local host,&lt;br /&gt;
the test sequence can be immediately tried via the Test/Demo page:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Test_Measuring_MQTT.png|300px]]&lt;br /&gt;
&lt;br /&gt;
A good strategy is to package the MQTT broker into a docker file.&lt;br /&gt;
Here is the MQTT client&#039;s output of the above run:&lt;br /&gt;
&lt;br /&gt;
 $ sh rundocker.sh &lt;br /&gt;
 1522084243: mosquitto version 1.4.8 (build date Thu, 01 Mar 2018 09:34:49 -0500) starting&lt;br /&gt;
 1522084243: Using default config.&lt;br /&gt;
 1522084243: Opening ipv4 listen socket on port 1883.&lt;br /&gt;
 1522084243: Opening ipv6 listen socket on port 1883.&lt;br /&gt;
 1522084272: New connection from 172.17.0.1 on port 1883.&lt;br /&gt;
 1522084272: New client connected from 172.17.0.1 as expeccoMQTT (c1, k0).&lt;br /&gt;
 1522084272: Client expeccoMQTT disconnected.&lt;br /&gt;
&lt;br /&gt;
and here the activitylog in expecco:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log1_Measuring_MQTT.png|600px]]&lt;br /&gt;
&lt;br /&gt;
with the event info detail:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log2_Measuring_MQTT.png|600px]]&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Running that Sequence Multiple Times ====&lt;br /&gt;
&lt;br /&gt;
Now that we have verified, that the communication with the MQTT broker works correctly,&lt;br /&gt;
we create another action bock, which runs the above action multiple times and collects&lt;br /&gt;
all the execution times:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT.png|700px]]&lt;br /&gt;
&lt;br /&gt;
[ explanation: first, a new empty colletion is created, then, the timing values of&lt;br /&gt;
the multi-triggered measure-step are all added to this collection.&lt;br /&gt;
When done (no step active), the collection is forwarded (now filled) to the output pin]&lt;br /&gt;
&lt;br /&gt;
Here is the activity log after 10 runs:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log1_Multiple_Measuring_MQTT.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==== Step 4: Adding the Graph ====&lt;br /&gt;
&lt;br /&gt;
The last step is the easiest: select the &amp;quot;New Plot/Graph&amp;quot; action block from the menu,&lt;br /&gt;
name it &amp;quot;Time Measurement Graph&amp;quot;&lt;br /&gt;
and change its autogenerated gnuplot script to:&lt;br /&gt;
&lt;br /&gt;
 set output &amp;quot;%(outputFile)&amp;quot;&lt;br /&gt;
 set term %(outputFormat)&lt;br /&gt;
 set title &amp;quot;%(title)&amp;quot;&lt;br /&gt;
 set key left box&lt;br /&gt;
 plot [1:%(dataSize)] [0:100] &amp;quot;%(dataFile)&amp;quot; title &amp;quot;%(lineTitle)&amp;quot; with impulses&lt;br /&gt;
&lt;br /&gt;
then place a step of it into your network and connect the &amp;quot;collectedTimes&amp;quot; output of the above measurement step with the &amp;quot;data&amp;quot; input&lt;br /&gt;
of the &amp;quot;Measurement-Graph&amp;quot; step:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_plus_Graph_MQTT.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Running it, and generating the report, produces the following pdf-report (the logging of subactivities was disabled for this report):&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT_Report_img.png|700px]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT_Report.pdf]]&lt;br /&gt;
&lt;br /&gt;
== Example 1 Simplified: Using Probes to Gather the Data ==&lt;br /&gt;
&lt;br /&gt;
The above data collection may look a bit complicated, due to the need for start/stop synchronization.&lt;br /&gt;
A much nicer and easier to use solution is in using a probe to gather the data.&lt;br /&gt;
For this, we need a probe which does no range checks, but instead only collects the incoming values:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_Probe.png|700px]]&lt;br /&gt;
&lt;br /&gt;
Here, a probe was added (via the &amp;quot;timeDelta&amp;quot; pin&#039;s &amp;quot;Add Probe&amp;quot; menu item),&lt;br /&gt;
and specified to &amp;quot;collect incoming data without check&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_ProbeMenu.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Now that we have a probe at the roundtrip time,&lt;br /&gt;
the outer measurement looks much simpler:&lt;br /&gt;
&lt;br /&gt;
* reset the probe (to clear any previously gathered data)&lt;br /&gt;
* prime the probe enable data collecting)&lt;br /&gt;
* run the roundtrip-test n-times&lt;br /&gt;
* unprime the probe (disable further data collecting)&lt;br /&gt;
* fetch the probe&#039;s values and pass them to the gnuplot action&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_Probe2.png|500px]]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
[http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf Gnuplot Manual]&lt;br /&gt;
&amp;lt;br&amp;gt;[https://alvinalexander.com/technology/gnuplot-charts-graphs-examples Collection of Examples]&lt;br /&gt;
&lt;br /&gt;
&amp;quot;[[R Action Blocks]]&amp;quot; which provide similar graph/plot functions in addition to sophisticated mathematical and statistics libraries.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;quot;[[Octave Script Action Tutorial|Octave/Matlab Actions]]&amp;quot; another framework for mathematical computations and/or to generate graphs/plots.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- {{Languages}} --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Languages ]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Plot/Graph_Action_Blocks&amp;diff=30939</id>
		<title>Plot/Graph Action Blocks</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Plot/Graph_Action_Blocks&amp;diff=30939"/>
		<updated>2026-03-03T11:14:53Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Creating Plot/Graph Action Blocks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
With expecco18.1, a new block type named &amp;quot;&#039;&#039;Plot/Graph Actions&#039;&#039;&amp;quot; is introduced.&lt;br /&gt;
These behave similar to other script action blocks, in that they are defined by a script&lt;br /&gt;
(in this case: gnuplot scripting language) and are placed into the test sequence flow&lt;br /&gt;
just like any other block.&lt;br /&gt;
&lt;br /&gt;
However, when executed, these actions generate a graphic document (jpeg, png or postscript),&lt;br /&gt;
which is then either added to the activity log, or added as attachment. It will therefore be &lt;br /&gt;
available in the generated &amp;quot;&amp;lt;code&amp;gt;elf&amp;lt;/code&amp;gt;&amp;quot; execution log file, or shown in the generated &amp;quot;&amp;lt;code&amp;gt;pdf&amp;lt;/code&amp;gt;&amp;quot; report file.&lt;br /&gt;
Of course, you can do anything you like with the generated graphic file, by feeding the name&lt;br /&gt;
of the generated file to another action for further processing.&lt;br /&gt;
&lt;br /&gt;
Notice: if you prefer other graphic packages or other programming languages, you may of course use R language scripts or Python scripts (with matplotlib and/or seaboarn) to generate graphics in a similar way.&lt;br /&gt;
&lt;br /&gt;
== Creating Plot/Graph Action Blocks ==&lt;br /&gt;
&lt;br /&gt;
Plot/graph action blocks are created via the &lt;br /&gt;
&amp;quot;&#039;&#039;Actions&#039;&#039; - &#039;&#039;More&#039;&#039; - &#039;&#039;Plot/Graph&#039;&#039;&amp;quot; menu item.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Plot_Graph_Actions_in_Menu.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Select the &amp;quot;&#039;&#039;Plot/Graph&#039;&#039;&amp;quot; item, to create a new gnuplot action.&lt;br /&gt;
An initial set of input pins and an initial (demo-) script is generated for you.&lt;br /&gt;
&lt;br /&gt;
For details on the scripting language, please refer to the public gnuplot documentation &lt;br /&gt;
[http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf &amp;quot;http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
Any input pin named &amp;quot;&amp;lt;code&amp;gt;&amp;lt;pinName&amp;gt;&amp;lt;/code&amp;gt;&amp;quot; is available in the script as &amp;quot;&amp;lt;code&amp;gt;%(pinName)&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
Thus, the script can be parametrized in arbitrary ways.&lt;br /&gt;
A number of pins are already created for you; these are:&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;outputFile&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;both an input and an output. If the input is specified, gnuplot will generate the plot into that file. Otherwise, a new temporary file will be created and the output written into that. In any case will the actual outputFileName be available on the corresponding output pin for further processing.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;outputFormat&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;specifies the kind of file to generate. For inclusion into the report, an image format should be chosen (i.e. one of &amp;quot;jpeg&amp;quot;, &amp;quot;png&amp;quot; or &amp;quot;gif&amp;quot;). For archival or to generate high quality documents, you can also choose &amp;quot;postscript&amp;quot; or &amp;quot;svg&amp;quot;. However, those can (currently) not be automatically converted for the pdf report.&amp;lt;br&amp;gt;On Unix systems, you can also specify &amp;quot;x11&amp;quot; as output format. In this case, a window is opened, displaying the generated graph. Be aware that expecco is (currently) not informed about the window being closed, so you may have to stop the test-run via the expecco-&amp;quot;Stop&amp;quot; button. &lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;title&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;A title string to be drawn above the graphic (actually, the position of the title is specified by the &amp;quot;set key&amp;quot; gnuplot expression, inside the script)&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;data&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;If connected, and a collection of values is present, these values will be written into a temporary data file, and the filename is available in the gnuplot script as &amp;quot;&amp;lt;code&amp;gt;%(data)&amp;lt;/code&amp;gt;&amp;quot;. Theis will be the raw data, to be processed by the script.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;dataSize&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;There is no pin for that, but the value is available to the script. It provides the number of data points (or rows) in the data file.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;attachToLog&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;if true (the default), the generated graph will be attached to the final pdf report. This pin&#039;s value is not forwarded to the gnuplot script.&lt;br /&gt;
&lt;br /&gt;
You can add additional input pins and refer to the corresponding pin value in the script with the &amp;quot;%(...)&amp;quot; notation.&lt;br /&gt;
&lt;br /&gt;
== A Simple Graph Script ==&lt;br /&gt;
&lt;br /&gt;
A typical gnuplot script looks like:&lt;br /&gt;
&lt;br /&gt;
 # The code below is sent to gnuplot and the generated output&lt;br /&gt;
 # will be stored in a file named %%(outputFile) &lt;br /&gt;
 # (unless explicitly specified, a temporary file is created)&lt;br /&gt;
 #&lt;br /&gt;
 set output &amp;quot;%(outputFile)&amp;quot;&lt;br /&gt;
  &lt;br /&gt;
 # &lt;br /&gt;
 set term %(outputFormat)&lt;br /&gt;
 &lt;br /&gt;
 # All input pin values can be used here as %%(nameOfPin).&lt;br /&gt;
 # so the next line controls the title via the &amp;quot;title&amp;quot; pin&lt;br /&gt;
 #&lt;br /&gt;
 set title &amp;quot;%(title)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 # You can add more pins.&lt;br /&gt;
 # For example, add pins named &amp;quot;min&amp;quot; and &amp;quot;max&amp;quot; with type Number,&lt;br /&gt;
 # and replace &amp;quot;-10:10&amp;quot; below by &amp;quot;%%(min):%%(max) to parametrize the y-axis range.&lt;br /&gt;
 set key left box&lt;br /&gt;
 plot [1:%(dataSize)] [-10:10] &amp;quot;%(data)&amp;quot; title &amp;quot;My Data&amp;quot; with impulses&lt;br /&gt;
&lt;br /&gt;
to plot a simple impulse graph of the data values, as presented at the input pin,&lt;br /&gt;
assuming that the pins get the following values:&lt;br /&gt;
* &amp;quot;outputFile&amp;quot; - leave unconnected or remove the pin (to let the action choose a temp file)&lt;br /&gt;
* &amp;quot;outputFormat&amp;quot; - freeze as &amp;quot;&amp;lt;code&amp;gt;png&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
* &amp;quot;title&amp;quot; - any title - such as &amp;quot;Measurement #1&amp;quot;&lt;br /&gt;
* &amp;quot;data&amp;quot; - a vector of numbers&lt;br /&gt;
&lt;br /&gt;
Of course, this is actually the simplest possible script to render such data.&lt;br /&gt;
Gnuplot provides a wide area of possible plots, both 2D and 3D, with or without colors, etc.&lt;br /&gt;
A few examples are provided in the &amp;quot;&amp;lt;code&amp;gt;Plot_Graph Library.ets&amp;lt;/code&amp;gt;&amp;quot;, but much more is found on the gnuplot&lt;br /&gt;
website and gnuplot documentation [http://www.gnuplot.info/docs_5.0/gnuplot.pdf &amp;quot;http://www.gnuplot.info/docs_5.0/gnuplot.pdf&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
== Short List of Useful Script Commands ==&lt;br /&gt;
&lt;br /&gt;
For a full list, please take a look at the gnu plot documentation [http://www.gnuplot.info/docs_5.0/gnuplot.pdf &amp;quot;http://www.gnuplot.info/docs_5.0/gnuplot.pdf&amp;quot;]. The following list is only presenting the most common plot commands:&lt;br /&gt;
* &amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with impulses&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;You can omit the &amp;quot;[yMin:yMax]&amp;quot; parameter, for a reasonable box to be automatically chosen by gnuplot.&amp;lt;br&amp;gt;Replace &amp;quot;nameOfDataFile&amp;quot; by &amp;quot;%(data)&amp;quot; if the data comes via an input pin and is not already in a file.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;Without the &amp;quot;impulses&amp;quot; parameter, a regular graph is drawn (straight lines between points)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with: lines&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;The same as above (straight lines between points)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with: dots&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;Draws dots&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with candlesticks&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;the data file should contain multiple colums per line. Select the colums with a &amp;quot;using...&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set key left box&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines the position (left) and type (boxed) of the graph-title (the string comes from the &amp;lt;code&amp;gt;title &amp;quot;graph title&amp;quot;&amp;lt;/code&amp;gt; argument in the plot command)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set title &amp;quot;someTitle&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines a headline title&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set term %(outputFormat)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines the type of image to be generated. For &amp;quot;%(outputFormat)&amp;quot;, the input pin&#039;s format is generated. Otherwise, you can also hardcode any of &amp;quot;&amp;lt;code&amp;gt;png&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;jpg&amp;lt;/code&amp;gt;&amp;quot;, etc. here&lt;br /&gt;
&lt;br /&gt;
A few examples are found in the demo library: &amp;quot;Plot_Graph_Library.ets&amp;quot;, which is found in the plugin&#039;s folder and in the online documentation [http://www.gnuplot.info/docs_5.0/gnuplot.pdf &amp;quot;http://www.gnuplot.info/docs_5.0/gnuplot.pdf&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
== Accessing Data from Attachments ==&lt;br /&gt;
&lt;br /&gt;
You can directly access expecco attachment files by their name inside the script. I.e. if you have an attachment with file named &amp;quot;&amp;lt;code&amp;gt;foo.dat&amp;lt;/code&amp;gt;&amp;quot;, use &amp;lt;code&amp;gt;... data &amp;quot;foo.dat&amp;quot; ...&amp;lt;/code&amp;gt; inside the script. Notice that the attchment&#039;s filename is to be used - not its name in the tree.&lt;br /&gt;
&lt;br /&gt;
== Plotting Multiple Graphs into a Single Picture ==&lt;br /&gt;
&lt;br /&gt;
To do this, generate multiple datasets (as ascii files, with one textline per row). Add &amp;lt;code&amp;gt;data&amp;amp;lt;i&amp;amp;gt;&amp;lt;/code&amp;gt; input pins and feed them the filenames. Add multiple &amp;lt;code&amp;gt;plot&amp;lt;/code&amp;gt; commands, each with its own &amp;quot;&amp;lt;code&amp;gt;%(data&amp;amp;lt;i&amp;amp;gt;&amp;lt;/code&amp;gt;)&amp;quot; argument, and possibly with its own graph-title.&lt;br /&gt;
&lt;br /&gt;
== Changing the Size of the Generated Image ==&lt;br /&gt;
&lt;br /&gt;
By default, the generated image&#039;s size is 640 x 400 pixels.&lt;br /&gt;
For a fix size, change the script&#039;s &amp;quot;&amp;lt;code&amp;gt;set term&amp;lt;/code&amp;gt;&amp;quot; statement to:&lt;br /&gt;
&lt;br /&gt;
 set term %(outputFormat) size &amp;lt;width&amp;gt;,&amp;lt;height&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;lt;width&amp;amp;gt; and &amp;amp;lt;height&amp;amp;gt; define the size in pixels.&lt;br /&gt;
&lt;br /&gt;
Alternatively, add two pins named &amp;quot;&#039;&#039;width&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;height&#039;&#039;&amp;quot;, and&lt;br /&gt;
change the statement to:&lt;br /&gt;
&lt;br /&gt;
 set term %(outputFormat) size %(width),%(height)&lt;br /&gt;
&lt;br /&gt;
and provide the desired size (as integers) at the input pins.&lt;br /&gt;
&lt;br /&gt;
== Caveats ==&lt;br /&gt;
&lt;br /&gt;
Do not place &amp;lt;code&amp;gt;pause&amp;lt;/code&amp;gt; statements into the script; there is no input stream given to gnuplot, so it will immediately read an EOF (end of file) and proceed.&lt;br /&gt;
&lt;br /&gt;
== Complete Example 1: Gathering Response Times of MQTT Protocol Messages ==&lt;br /&gt;
&lt;br /&gt;
This example demonstrates, how a test suite can gather response times of a remote system,&lt;br /&gt;
when sending MQTT messages to it.&lt;br /&gt;
&lt;br /&gt;
==== Step 1: Define the Test Sequence ====&lt;br /&gt;
&lt;br /&gt;
this is a very simple publish-response setup, in that a topic is published to an MQTT broker,&lt;br /&gt;
and the time measured, until the notification arrives (in order to run this on your machine,&lt;br /&gt;
the expecco MQTT plugin needs to be installed):&lt;br /&gt;
&lt;br /&gt;
Outside (Schema) view of the measuring action:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schema_Measuring_MQTT.png|400px]]&lt;br /&gt;
&lt;br /&gt;
which is implemented as:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Net_Measuring_MQTT.png|800px]]&lt;br /&gt;
&lt;br /&gt;
The yellow area does the MQTT setup. First, an MQTT client connection is created,&lt;br /&gt;
and the client handle forwarded to the Subscribe action, which registers expecco&lt;br /&gt;
to react to the &amp;quot;expeccoTesting/test&amp;quot; topic.&lt;br /&gt;
&lt;br /&gt;
The green area does the actual publish operation,&lt;br /&gt;
publishing the &amp;quot;Hello from Expecco&amp;quot; string on this topic.&lt;br /&gt;
&lt;br /&gt;
In parallel, the blue area waits for the next incoming event,&lt;br /&gt;
(and generates a printed detail info on the received packet for the&lt;br /&gt;
activity log).&lt;br /&gt;
&lt;br /&gt;
The red area contains a stopWatch action block, which gets started&lt;br /&gt;
with when the publish is done, and stops when the event arrives.&lt;br /&gt;
&lt;br /&gt;
The measurement action is prametrized with the broker&#039;s host and port,&lt;br /&gt;
and generates the measured timeDuration as output.&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Test Run ====&lt;br /&gt;
&lt;br /&gt;
Assuming that you have an MQTT client running on the local host,&lt;br /&gt;
the test sequence can be immediately tried via the Test/Demo page:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Test_Measuring_MQTT.png|300px]]&lt;br /&gt;
&lt;br /&gt;
A good strategy is to package the MQTT broker into a docker file.&lt;br /&gt;
Here is the MQTT client&#039;s output of the above run:&lt;br /&gt;
&lt;br /&gt;
 $ sh rundocker.sh &lt;br /&gt;
 1522084243: mosquitto version 1.4.8 (build date Thu, 01 Mar 2018 09:34:49 -0500) starting&lt;br /&gt;
 1522084243: Using default config.&lt;br /&gt;
 1522084243: Opening ipv4 listen socket on port 1883.&lt;br /&gt;
 1522084243: Opening ipv6 listen socket on port 1883.&lt;br /&gt;
 1522084272: New connection from 172.17.0.1 on port 1883.&lt;br /&gt;
 1522084272: New client connected from 172.17.0.1 as expeccoMQTT (c1, k0).&lt;br /&gt;
 1522084272: Client expeccoMQTT disconnected.&lt;br /&gt;
&lt;br /&gt;
and here the activitylog in expecco:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log1_Measuring_MQTT.png|600px]]&lt;br /&gt;
&lt;br /&gt;
with the event info detail:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log2_Measuring_MQTT.png|600px]]&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Running that Sequence Multiple Times ====&lt;br /&gt;
&lt;br /&gt;
Now that we have verified, that the communication with the MQTT broker works correctly,&lt;br /&gt;
we create another action bock, which runs the above action multiple times and collects&lt;br /&gt;
all the execution times:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT.png|700px]]&lt;br /&gt;
&lt;br /&gt;
[ explanation: first, a new empty colletion is created, then, the timing values of&lt;br /&gt;
the multi-triggered measure-step are all added to this collection.&lt;br /&gt;
When done (no step active), the collection is forwarded (now filled) to the output pin]&lt;br /&gt;
&lt;br /&gt;
Here is the activity log after 10 runs:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log1_Multiple_Measuring_MQTT.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==== Step 4: Adding the Graph ====&lt;br /&gt;
&lt;br /&gt;
The last step is the easiest: select the &amp;quot;New Plot/Graph&amp;quot; action block from the menu,&lt;br /&gt;
name it &amp;quot;Time Measurement Graph&amp;quot;&lt;br /&gt;
and change its autogenerated gnuplot script to:&lt;br /&gt;
&lt;br /&gt;
 set output &amp;quot;%(outputFile)&amp;quot;&lt;br /&gt;
 set term %(outputFormat)&lt;br /&gt;
 set title &amp;quot;%(title)&amp;quot;&lt;br /&gt;
 set key left box&lt;br /&gt;
 plot [1:%(dataSize)] [0:100] &amp;quot;%(data)&amp;quot; title &amp;quot;%(lineTitle)&amp;quot; with impulses&lt;br /&gt;
&lt;br /&gt;
then place a step of it into your network and connect the &amp;quot;collectedTimes&amp;quot; output of the above measurement step with the &amp;quot;data&amp;quot; input&lt;br /&gt;
of the &amp;quot;Measurement-Graph&amp;quot; step:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_plus_Graph_MQTT.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Running it, and generating the report, produces the following pdf-report (the logging of subactivities was disabled for this report):&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT_Report_img.png|700px]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT_Report.pdf]]&lt;br /&gt;
&lt;br /&gt;
== Example 1 Simplified: Using Probes to Gather the Data ==&lt;br /&gt;
&lt;br /&gt;
The above data collection may look a bit complicated, due to the need for start/stop synchronization.&lt;br /&gt;
A much nicer and easier to use solution is in using a probe to gather the data.&lt;br /&gt;
For this, we need a probe which does no range checks, but instead only collects the incoming values:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_Probe.png|700px]]&lt;br /&gt;
&lt;br /&gt;
Here, a probe was added (via the &amp;quot;timeDelta&amp;quot; pin&#039;s &amp;quot;Add Probe&amp;quot; menu item),&lt;br /&gt;
and specified to &amp;quot;collect incoming data without check&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_ProbeMenu.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Now that we have a probe at the roundtrip time,&lt;br /&gt;
the outer measurement looks much simpler:&lt;br /&gt;
&lt;br /&gt;
* reset the probe (to clear any previously gathered data)&lt;br /&gt;
* prime the probe enable data collecting)&lt;br /&gt;
* run the roundtrip-test n-times&lt;br /&gt;
* unprime the probe (disable further data collecting)&lt;br /&gt;
* fetch the probe&#039;s values and pass them to the gnuplot action&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_Probe2.png|500px]]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
[http://www.gnuplot.info/docs_5.0/gnuplot.pdf Gnuplot Manual]&lt;br /&gt;
&amp;lt;br&amp;gt;[https://alvinalexander.com/technology/gnuplot-charts-graphs-examples Collection of Examples]&lt;br /&gt;
&lt;br /&gt;
&amp;quot;[[R Action Blocks]]&amp;quot; which provide similar graph/plot functions in addition to sophisticated mathematical and statistics libraries.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;quot;[[Octave Script Action Tutorial|Octave/Matlab Actions]]&amp;quot; another framework for mathematical computations and/or to generate graphs/plots.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- {{Languages}} --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Languages ]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Plot/Graph_Action_Blocks&amp;diff=30938</id>
		<title>Plot/Graph Action Blocks</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Plot/Graph_Action_Blocks&amp;diff=30938"/>
		<updated>2026-03-03T11:13:55Z</updated>

		<summary type="html">&lt;p&gt;Sv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
With expecco18.1, a new block type named &amp;quot;&#039;&#039;Plot/Graph Actions&#039;&#039;&amp;quot; is introduced.&lt;br /&gt;
These behave similar to other script action blocks, in that they are defined by a script&lt;br /&gt;
(in this case: gnuplot scripting language) and are placed into the test sequence flow&lt;br /&gt;
just like any other block.&lt;br /&gt;
&lt;br /&gt;
However, when executed, these actions generate a graphic document (jpeg, png or postscript),&lt;br /&gt;
which is then either added to the activity log, or added as attachment. It will therefore be &lt;br /&gt;
available in the generated &amp;quot;&amp;lt;code&amp;gt;elf&amp;lt;/code&amp;gt;&amp;quot; execution log file, or shown in the generated &amp;quot;&amp;lt;code&amp;gt;pdf&amp;lt;/code&amp;gt;&amp;quot; report file.&lt;br /&gt;
Of course, you can do anything you like with the generated graphic file, by feeding the name&lt;br /&gt;
of the generated file to another action for further processing.&lt;br /&gt;
&lt;br /&gt;
Notice: if you prefer other graphic packages or other programming languages, you may of course use R language scripts or Python scripts (with matplotlib and/or seaboarn) to generate graphics in a similar way.&lt;br /&gt;
&lt;br /&gt;
== Creating Plot/Graph Action Blocks ==&lt;br /&gt;
&lt;br /&gt;
Plot/graph action blocks are created via the &lt;br /&gt;
&amp;quot;&#039;&#039;Actions&#039;&#039; - &#039;&#039;More&#039;&#039; - &#039;&#039;Plot/Graph&#039;&#039;&amp;quot; menu item.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Plot_Graph_Actions_in_Menu.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Select the &amp;quot;&#039;&#039;Plot/Graph&#039;&#039;&amp;quot; item, to create a new gnuplot action.&lt;br /&gt;
An initial set of input pins and an initial (demo-) script is generated for you.&lt;br /&gt;
&lt;br /&gt;
For details on the scripting language, please refer to the public gnuplot documentation &lt;br /&gt;
[http://www.gnuplot.info/docs_5.0/gnuplot.pdf &amp;quot;http://www.gnuplot.info/docs_6.0/Gnuplot_6.pdf&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
Any input pin named &amp;quot;&amp;lt;code&amp;gt;&amp;lt;pinName&amp;gt;&amp;lt;/code&amp;gt;&amp;quot; is available in the script as &amp;quot;&amp;lt;code&amp;gt;%(pinName)&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
Thus, the script can be parametrized in arbitrary ways.&lt;br /&gt;
A number of pins are already created for you; these are:&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;outputFile&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;both an input and an output. If the input is specified, gnuplot will generate the plot into that file. Otherwise, a new temporary file will be created and the output written into that. In any case will the actual outputFileName be available on the corresponding output pin for further processing.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;outputFormat&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;specifies the kind of file to generate. For inclusion into the report, an image format should be chosen (i.e. one of &amp;quot;jpeg&amp;quot;, &amp;quot;png&amp;quot; or &amp;quot;gif&amp;quot;). For archival or to generate high quality documents, you can also choose &amp;quot;postscript&amp;quot; or &amp;quot;svg&amp;quot;. However, those can (currently) not be automatically converted for the pdf report.&amp;lt;br&amp;gt;On Unix systems, you can also specify &amp;quot;x11&amp;quot; as output format. In this case, a window is opened, displaying the generated graph. Be aware that expecco is (currently) not informed about the window being closed, so you may have to stop the test-run via the expecco-&amp;quot;Stop&amp;quot; button. &lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;title&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;A title string to be drawn above the graphic (actually, the position of the title is specified by the &amp;quot;set key&amp;quot; gnuplot expression, inside the script)&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;data&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;If connected, and a collection of values is present, these values will be written into a temporary data file, and the filename is available in the gnuplot script as &amp;quot;&amp;lt;code&amp;gt;%(data)&amp;lt;/code&amp;gt;&amp;quot;. Theis will be the raw data, to be processed by the script.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;dataSize&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;There is no pin for that, but the value is available to the script. It provides the number of data points (or rows) in the data file.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;&#039;attachToLog&#039;&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;if true (the default), the generated graph will be attached to the final pdf report. This pin&#039;s value is not forwarded to the gnuplot script.&lt;br /&gt;
&lt;br /&gt;
You can add additional input pins and refer to the corresponding pin value in the script with the &amp;quot;%(...)&amp;quot; notation.&lt;br /&gt;
&lt;br /&gt;
== A Simple Graph Script ==&lt;br /&gt;
&lt;br /&gt;
A typical gnuplot script looks like:&lt;br /&gt;
&lt;br /&gt;
 # The code below is sent to gnuplot and the generated output&lt;br /&gt;
 # will be stored in a file named %%(outputFile) &lt;br /&gt;
 # (unless explicitly specified, a temporary file is created)&lt;br /&gt;
 #&lt;br /&gt;
 set output &amp;quot;%(outputFile)&amp;quot;&lt;br /&gt;
  &lt;br /&gt;
 # &lt;br /&gt;
 set term %(outputFormat)&lt;br /&gt;
 &lt;br /&gt;
 # All input pin values can be used here as %%(nameOfPin).&lt;br /&gt;
 # so the next line controls the title via the &amp;quot;title&amp;quot; pin&lt;br /&gt;
 #&lt;br /&gt;
 set title &amp;quot;%(title)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 # You can add more pins.&lt;br /&gt;
 # For example, add pins named &amp;quot;min&amp;quot; and &amp;quot;max&amp;quot; with type Number,&lt;br /&gt;
 # and replace &amp;quot;-10:10&amp;quot; below by &amp;quot;%%(min):%%(max) to parametrize the y-axis range.&lt;br /&gt;
 set key left box&lt;br /&gt;
 plot [1:%(dataSize)] [-10:10] &amp;quot;%(data)&amp;quot; title &amp;quot;My Data&amp;quot; with impulses&lt;br /&gt;
&lt;br /&gt;
to plot a simple impulse graph of the data values, as presented at the input pin,&lt;br /&gt;
assuming that the pins get the following values:&lt;br /&gt;
* &amp;quot;outputFile&amp;quot; - leave unconnected or remove the pin (to let the action choose a temp file)&lt;br /&gt;
* &amp;quot;outputFormat&amp;quot; - freeze as &amp;quot;&amp;lt;code&amp;gt;png&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
* &amp;quot;title&amp;quot; - any title - such as &amp;quot;Measurement #1&amp;quot;&lt;br /&gt;
* &amp;quot;data&amp;quot; - a vector of numbers&lt;br /&gt;
&lt;br /&gt;
Of course, this is actually the simplest possible script to render such data.&lt;br /&gt;
Gnuplot provides a wide area of possible plots, both 2D and 3D, with or without colors, etc.&lt;br /&gt;
A few examples are provided in the &amp;quot;&amp;lt;code&amp;gt;Plot_Graph Library.ets&amp;lt;/code&amp;gt;&amp;quot;, but much more is found on the gnuplot&lt;br /&gt;
website and gnuplot documentation [http://www.gnuplot.info/docs_5.0/gnuplot.pdf &amp;quot;http://www.gnuplot.info/docs_5.0/gnuplot.pdf&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
== Short List of Useful Script Commands ==&lt;br /&gt;
&lt;br /&gt;
For a full list, please take a look at the gnu plot documentation [http://www.gnuplot.info/docs_5.0/gnuplot.pdf &amp;quot;http://www.gnuplot.info/docs_5.0/gnuplot.pdf&amp;quot;]. The following list is only presenting the most common plot commands:&lt;br /&gt;
* &amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with impulses&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;You can omit the &amp;quot;[yMin:yMax]&amp;quot; parameter, for a reasonable box to be automatically chosen by gnuplot.&amp;lt;br&amp;gt;Replace &amp;quot;nameOfDataFile&amp;quot; by &amp;quot;%(data)&amp;quot; if the data comes via an input pin and is not already in a file.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;Without the &amp;quot;impulses&amp;quot; parameter, a regular graph is drawn (straight lines between points)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with: lines&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;The same as above (straight lines between points)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with: dots&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;Draws dots&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;plot [xMin:xMax] [yMin:yMax] &amp;quot;nameOfDataFile&amp;quot; title &amp;quot;graph title&amp;quot; with candlesticks&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;the data file should contain multiple colums per line. Select the colums with a &amp;quot;using...&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set key left box&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines the position (left) and type (boxed) of the graph-title (the string comes from the &amp;lt;code&amp;gt;title &amp;quot;graph title&amp;quot;&amp;lt;/code&amp;gt; argument in the plot command)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set title &amp;quot;someTitle&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines a headline title&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;set term %(outputFormat)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;defines the type of image to be generated. For &amp;quot;%(outputFormat)&amp;quot;, the input pin&#039;s format is generated. Otherwise, you can also hardcode any of &amp;quot;&amp;lt;code&amp;gt;png&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;jpg&amp;lt;/code&amp;gt;&amp;quot;, etc. here&lt;br /&gt;
&lt;br /&gt;
A few examples are found in the demo library: &amp;quot;Plot_Graph_Library.ets&amp;quot;, which is found in the plugin&#039;s folder and in the online documentation [http://www.gnuplot.info/docs_5.0/gnuplot.pdf &amp;quot;http://www.gnuplot.info/docs_5.0/gnuplot.pdf&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
== Accessing Data from Attachments ==&lt;br /&gt;
&lt;br /&gt;
You can directly access expecco attachment files by their name inside the script. I.e. if you have an attachment with file named &amp;quot;&amp;lt;code&amp;gt;foo.dat&amp;lt;/code&amp;gt;&amp;quot;, use &amp;lt;code&amp;gt;... data &amp;quot;foo.dat&amp;quot; ...&amp;lt;/code&amp;gt; inside the script. Notice that the attchment&#039;s filename is to be used - not its name in the tree.&lt;br /&gt;
&lt;br /&gt;
== Plotting Multiple Graphs into a Single Picture ==&lt;br /&gt;
&lt;br /&gt;
To do this, generate multiple datasets (as ascii files, with one textline per row). Add &amp;lt;code&amp;gt;data&amp;amp;lt;i&amp;amp;gt;&amp;lt;/code&amp;gt; input pins and feed them the filenames. Add multiple &amp;lt;code&amp;gt;plot&amp;lt;/code&amp;gt; commands, each with its own &amp;quot;&amp;lt;code&amp;gt;%(data&amp;amp;lt;i&amp;amp;gt;&amp;lt;/code&amp;gt;)&amp;quot; argument, and possibly with its own graph-title.&lt;br /&gt;
&lt;br /&gt;
== Changing the Size of the Generated Image ==&lt;br /&gt;
&lt;br /&gt;
By default, the generated image&#039;s size is 640 x 400 pixels.&lt;br /&gt;
For a fix size, change the script&#039;s &amp;quot;&amp;lt;code&amp;gt;set term&amp;lt;/code&amp;gt;&amp;quot; statement to:&lt;br /&gt;
&lt;br /&gt;
 set term %(outputFormat) size &amp;lt;width&amp;gt;,&amp;lt;height&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;lt;width&amp;amp;gt; and &amp;amp;lt;height&amp;amp;gt; define the size in pixels.&lt;br /&gt;
&lt;br /&gt;
Alternatively, add two pins named &amp;quot;&#039;&#039;width&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;height&#039;&#039;&amp;quot;, and&lt;br /&gt;
change the statement to:&lt;br /&gt;
&lt;br /&gt;
 set term %(outputFormat) size %(width),%(height)&lt;br /&gt;
&lt;br /&gt;
and provide the desired size (as integers) at the input pins.&lt;br /&gt;
&lt;br /&gt;
== Caveats ==&lt;br /&gt;
&lt;br /&gt;
Do not place &amp;lt;code&amp;gt;pause&amp;lt;/code&amp;gt; statements into the script; there is no input stream given to gnuplot, so it will immediately read an EOF (end of file) and proceed.&lt;br /&gt;
&lt;br /&gt;
== Complete Example 1: Gathering Response Times of MQTT Protocol Messages ==&lt;br /&gt;
&lt;br /&gt;
This example demonstrates, how a test suite can gather response times of a remote system,&lt;br /&gt;
when sending MQTT messages to it.&lt;br /&gt;
&lt;br /&gt;
==== Step 1: Define the Test Sequence ====&lt;br /&gt;
&lt;br /&gt;
this is a very simple publish-response setup, in that a topic is published to an MQTT broker,&lt;br /&gt;
and the time measured, until the notification arrives (in order to run this on your machine,&lt;br /&gt;
the expecco MQTT plugin needs to be installed):&lt;br /&gt;
&lt;br /&gt;
Outside (Schema) view of the measuring action:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schema_Measuring_MQTT.png|400px]]&lt;br /&gt;
&lt;br /&gt;
which is implemented as:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Net_Measuring_MQTT.png|800px]]&lt;br /&gt;
&lt;br /&gt;
The yellow area does the MQTT setup. First, an MQTT client connection is created,&lt;br /&gt;
and the client handle forwarded to the Subscribe action, which registers expecco&lt;br /&gt;
to react to the &amp;quot;expeccoTesting/test&amp;quot; topic.&lt;br /&gt;
&lt;br /&gt;
The green area does the actual publish operation,&lt;br /&gt;
publishing the &amp;quot;Hello from Expecco&amp;quot; string on this topic.&lt;br /&gt;
&lt;br /&gt;
In parallel, the blue area waits for the next incoming event,&lt;br /&gt;
(and generates a printed detail info on the received packet for the&lt;br /&gt;
activity log).&lt;br /&gt;
&lt;br /&gt;
The red area contains a stopWatch action block, which gets started&lt;br /&gt;
with when the publish is done, and stops when the event arrives.&lt;br /&gt;
&lt;br /&gt;
The measurement action is prametrized with the broker&#039;s host and port,&lt;br /&gt;
and generates the measured timeDuration as output.&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Test Run ====&lt;br /&gt;
&lt;br /&gt;
Assuming that you have an MQTT client running on the local host,&lt;br /&gt;
the test sequence can be immediately tried via the Test/Demo page:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Test_Measuring_MQTT.png|300px]]&lt;br /&gt;
&lt;br /&gt;
A good strategy is to package the MQTT broker into a docker file.&lt;br /&gt;
Here is the MQTT client&#039;s output of the above run:&lt;br /&gt;
&lt;br /&gt;
 $ sh rundocker.sh &lt;br /&gt;
 1522084243: mosquitto version 1.4.8 (build date Thu, 01 Mar 2018 09:34:49 -0500) starting&lt;br /&gt;
 1522084243: Using default config.&lt;br /&gt;
 1522084243: Opening ipv4 listen socket on port 1883.&lt;br /&gt;
 1522084243: Opening ipv6 listen socket on port 1883.&lt;br /&gt;
 1522084272: New connection from 172.17.0.1 on port 1883.&lt;br /&gt;
 1522084272: New client connected from 172.17.0.1 as expeccoMQTT (c1, k0).&lt;br /&gt;
 1522084272: Client expeccoMQTT disconnected.&lt;br /&gt;
&lt;br /&gt;
and here the activitylog in expecco:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log1_Measuring_MQTT.png|600px]]&lt;br /&gt;
&lt;br /&gt;
with the event info detail:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log2_Measuring_MQTT.png|600px]]&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Running that Sequence Multiple Times ====&lt;br /&gt;
&lt;br /&gt;
Now that we have verified, that the communication with the MQTT broker works correctly,&lt;br /&gt;
we create another action bock, which runs the above action multiple times and collects&lt;br /&gt;
all the execution times:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT.png|700px]]&lt;br /&gt;
&lt;br /&gt;
[ explanation: first, a new empty colletion is created, then, the timing values of&lt;br /&gt;
the multi-triggered measure-step are all added to this collection.&lt;br /&gt;
When done (no step active), the collection is forwarded (now filled) to the output pin]&lt;br /&gt;
&lt;br /&gt;
Here is the activity log after 10 runs:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Log1_Multiple_Measuring_MQTT.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==== Step 4: Adding the Graph ====&lt;br /&gt;
&lt;br /&gt;
The last step is the easiest: select the &amp;quot;New Plot/Graph&amp;quot; action block from the menu,&lt;br /&gt;
name it &amp;quot;Time Measurement Graph&amp;quot;&lt;br /&gt;
and change its autogenerated gnuplot script to:&lt;br /&gt;
&lt;br /&gt;
 set output &amp;quot;%(outputFile)&amp;quot;&lt;br /&gt;
 set term %(outputFormat)&lt;br /&gt;
 set title &amp;quot;%(title)&amp;quot;&lt;br /&gt;
 set key left box&lt;br /&gt;
 plot [1:%(dataSize)] [0:100] &amp;quot;%(data)&amp;quot; title &amp;quot;%(lineTitle)&amp;quot; with impulses&lt;br /&gt;
&lt;br /&gt;
then place a step of it into your network and connect the &amp;quot;collectedTimes&amp;quot; output of the above measurement step with the &amp;quot;data&amp;quot; input&lt;br /&gt;
of the &amp;quot;Measurement-Graph&amp;quot; step:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_plus_Graph_MQTT.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Running it, and generating the report, produces the following pdf-report (the logging of subactivities was disabled for this report):&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT_Report_img.png|700px]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:Multiple_Measuring_MQTT_Report.pdf]]&lt;br /&gt;
&lt;br /&gt;
== Example 1 Simplified: Using Probes to Gather the Data ==&lt;br /&gt;
&lt;br /&gt;
The above data collection may look a bit complicated, due to the need for start/stop synchronization.&lt;br /&gt;
A much nicer and easier to use solution is in using a probe to gather the data.&lt;br /&gt;
For this, we need a probe which does no range checks, but instead only collects the incoming values:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_Probe.png|700px]]&lt;br /&gt;
&lt;br /&gt;
Here, a probe was added (via the &amp;quot;timeDelta&amp;quot; pin&#039;s &amp;quot;Add Probe&amp;quot; menu item),&lt;br /&gt;
and specified to &amp;quot;collect incoming data without check&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_ProbeMenu.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Now that we have a probe at the roundtrip time,&lt;br /&gt;
the outer measurement looks much simpler:&lt;br /&gt;
&lt;br /&gt;
* reset the probe (to clear any previously gathered data)&lt;br /&gt;
* prime the probe enable data collecting)&lt;br /&gt;
* run the roundtrip-test n-times&lt;br /&gt;
* unprime the probe (disable further data collecting)&lt;br /&gt;
* fetch the probe&#039;s values and pass them to the gnuplot action&lt;br /&gt;
&lt;br /&gt;
[[Datei:Measuring_MQTT_with_Probe2.png|500px]]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
[http://www.gnuplot.info/docs_5.0/gnuplot.pdf Gnuplot Manual]&lt;br /&gt;
&amp;lt;br&amp;gt;[https://alvinalexander.com/technology/gnuplot-charts-graphs-examples Collection of Examples]&lt;br /&gt;
&lt;br /&gt;
&amp;quot;[[R Action Blocks]]&amp;quot; which provide similar graph/plot functions in addition to sophisticated mathematical and statistics libraries.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;quot;[[Octave Script Action Tutorial|Octave/Matlab Actions]]&amp;quot; another framework for mathematical computations and/or to generate graphs/plots.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- {{Languages}} --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Languages ]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_26.x&amp;diff=30914</id>
		<title>Release Notes 26.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_26.x&amp;diff=30914"/>
		<updated>2026-02-23T13:31:04Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Release 26.1 (Q2 2026) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 25.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 26.2 (Q4 2026) ==&lt;br /&gt;
&lt;br /&gt;
== Release 26.1 (Q2 2026) ==&lt;br /&gt;
*Feature: Qt-Plugin supports Qt6.8 ([[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Delivered versions for QT and build environment]])&lt;br /&gt;
* Feature: improved search text box behavior in text editors (type RETURN, CMD-f or CMD-b while box is open) and back to original position button added.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_26.x&amp;diff=30913</id>
		<title>Release Notes 26.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_26.x&amp;diff=30913"/>
		<updated>2026-02-23T13:30:43Z</updated>

		<summary type="html">&lt;p&gt;Sv: Release dates added&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 25.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 26.2 (Q4 2026) ==&lt;br /&gt;
&lt;br /&gt;
== Release 26.1 (Q&amp;quot; 2026) ==&lt;br /&gt;
*Feature: Qt-Plugin supports Qt6.8 ([[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Delivered versions for QT and build environment]])&lt;br /&gt;
* Feature: improved search text box behavior in text editors (type RETURN, CMD-f or CMD-b while box is open) and back to original position button added.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Hauptseite&amp;diff=30912</id>
		<title>Hauptseite</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Hauptseite&amp;diff=30912"/>
		<updated>2026-02-23T13:29:46Z</updated>

		<summary type="html">&lt;p&gt;Sv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Hauptseite/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
Klicken Sie links auf &#039;&#039;&amp;quot;Letzte Änderungen&amp;quot;&#039;&#039; (&amp;quot;Recent changes&amp;quot;) um die neuesten Einträge in der Dokumentation zu sehen.&amp;lt;br&amp;gt;Sie sehen dann meist, woran unsere Entwickler gerade vornehmlich arbeiten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h2&amp;gt;expecco&amp;lt;/h2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:flex; flex-wrap:wrap; padding:0; white-space:nowrap&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Für Einsteiger&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;!-- Link mit Fragezeichen funktioniert nicht, deshalb externer Link --&amp;gt;&lt;br /&gt;
			&amp;lt;!-- &amp;lt;li&amp;gt;[[Was ist expecco?|Allgemeine Informationen]]&amp;lt;/li&amp;gt; --&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[https://doc.expecco.de/w2.x/index.php?title=Was_ist_expecco%3F Allgemeine Informationen]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Expecco Usecases|Einsatzbereiche]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Features|expecco Feature-List]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Tutorials]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[usageHints/en|Hinweise zur Bedienung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Glossary|Begriffserklärung]] (Glossar)&amp;lt;/li&amp;gt;&lt;br /&gt;
 			&amp;lt;!-- &amp;lt;li&amp;gt;[[Testorganisation|Testorganisation]]&amp;lt;/li&amp;gt; --&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[FAQ]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage5.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Installation&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Installation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Installing additional Frameworks/en| Installation zusätzlicher Tools (Node, Python, ...)]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Personal Settings|Persönliche&amp;amp;nbsp;Einstellungen]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Configuration &amp;amp; Setup|Konfiguration]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Anbindung expecco ALM]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[SAP_Testing|Anbindung expecco an SAP]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Spezifische Anpassung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco UI]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_Remote_Control_App|expecco Mobile Remote App]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Probleme &amp;amp; Fehler]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage4.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Werkzeuge&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[API von Elementaraktionen]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Debugger]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Editoren]]&amp;lt;/li&amp;gt;		&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Standard Libraries/Bibliotheken]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Weitere Werkzeuge]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Weitere Funktionen]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage6.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Reportgenerierung&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Report Generation|Reportgenerierung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Errors during Execution|Fehler während der Ausführung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Secret Strings|Geheime Zeichenketten und Passwörter]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	 &amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Erweiterung_plugin.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Erweiterungen (Plugins)&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[GUI Testing]]&lt;br /&gt;
				&amp;lt;ul&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Java GUI Plugins|Java Swing/FX/SWT UI Testing]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Mobile Testing Plugin|Mobile Testing auf Android und iOS]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[WindowsAutomation Reference 2.0|UI Testing mit der Windows Automation Library]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Selenium_WebDriver_Plugin|Web Testing mit Selenium WebDriver]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                                        &amp;lt;li&amp;gt;[[VNC_Plugin_Reference|VNC UI Testing]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[GUI Testing|Weitere GUI Testing Plugins]]&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;/ul&amp;gt;&lt;br /&gt;
			&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Schnittstellen zum SUT]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[ManualTest]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;Produktivit&amp;amp;auml;t&lt;br /&gt;
				&amp;lt;ul&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[GIT Plugin]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                                        &amp;lt;li&amp;gt;[[HG Plugin (Mercurial)]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[CVS Plugin]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Anbindung expecco ALM | expeccoALM Schnittstelle]]&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;/ul&amp;gt;&lt;br /&gt;
			&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Weitere Plugins]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe;  margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage3.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Elemente der Testsuite&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Tree Elements|Tree Elemente]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Folder Element|Ordner]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Testplan Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Aktionen/Aktionsblöcke]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Datatype Element|Datentyp Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Inventory Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Skill Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Resource Element|Ressource Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Attachment Element|Anhänge]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[ReportTemplate Element|Report Templates]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color:#ecf0fe;  margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage3.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;API Referenz (Elementarbausteine)&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[API von Elementaraktionen|Übersicht]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco API#JavaScript_and_Smalltalk_Elementary_Blocks|Smalltalk &amp;amp; JavaScript]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco API#Groovy_Elementary_Blocks|Groovy]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Node.js_.28Bridged.29_Elementary_Blocks|NodeJS]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Bridged_Python_Elementary_Blocks|Python]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Bridged_Ruby_Elementary_Blocks|Ruby]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Bridged_C_Elementary_Blocks|C]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco API#VisualBasic_Elementary_Blocks|VisualBasic ]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Expecco Scripting API|Shell und Script Languages]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;p&amp;gt;&amp;amp;nbsp;&amp;lt;/p&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Useful API Functions|Useful API Functions:]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;ul&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Number API Functions|Number API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[String API Functions|String API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Collection API Functions|Collection API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Filename API Functions|Filename API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Stream API Functions|Stream API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Date_and_Time_API_Functions|Date &amp;amp; Time API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;/ul&amp;gt; &lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Diagramm.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Diagramm - Elemente&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Step|Schritt]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Pins (Ein - Ausgänge)]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Code Ausführung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Connection|Verbindung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Pin|Pin Beschreibung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Annotation|Notiz]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Probe|Messfühler]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Refresh.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Sonstiges&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 26.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 25.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 24.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 23.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 22.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 21.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 20.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 19.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 18.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 2.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 1.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Future releases expecco|Zukünftige Releases]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Smalltalk]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Beispiele_icon.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Beispiele&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
                &amp;lt;span style=&amp;quot;padding:0 1em;font-size:0.9em&amp;quot;&amp;gt;Sie haben Fragen, wie ein Projekt aussieht?&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
                &lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;amp;nbsp;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Beispiele | Hier finden Sie weitere Anwendungsbeispiele.]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Expecco Code Snippets/en | Codeschnipsel]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Beispiele_icon.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Unterstützung weiterer Qualitätsmanagement Tools&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
                &lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Jira_Plugin_Reference|Jira]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[PolarionPlugin_Reference|Polarion]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Aqua_Plugin_Reference|Aqua]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Starting_expecco_via_Command_Line#Integration_with_Jenkins|Jenkins Integration]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h2 style=&amp;quot;clear:left&amp;quot;&amp;gt;expecco ALM&amp;lt;/h2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:flex; flex-wrap:wrap; padding:0; white-space:nowrap&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Sonstiges-Info.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Allgemein&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Was ist expecco ALM?]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Was ist der expecco Lizenzserver?]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Anbindung expecco ALM]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Rollen und Rechte]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Filter]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[FAQ expeccoALM/en | FAQ]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage5.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Installation/Einrichten&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Installation|Installation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Installation Patches|expecco ALM Installation Patches]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Einrichten Vorgehensweise|expecco ALM Einrichten]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM expecco Patch Service |Patchservice für expecco]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Refresh.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Plugins&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[AIDYMO Jira|Atlassian Jira]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[CustomerSpecific|Kundenspezifische Portale]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Refresh.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Sonstiges&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM App]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Installation Lizenzserver]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Release Notes|Release Notes]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Known Issues|Known Issues]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Settings_ExternalScriptInterpreterSettings/en&amp;diff=30911</id>
		<title>Settings ExternalScriptInterpreterSettings/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Settings_ExternalScriptInterpreterSettings/en&amp;diff=30911"/>
		<updated>2026-02-23T12:53:21Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 19.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== External Script Interpreter Settings ==&lt;br /&gt;
&lt;br /&gt;
=== General Script Execution ===&lt;br /&gt;
===== Additional Path =====&lt;br /&gt;
Defines additional paths which are added to the $PATH environment variable (%PATH% on Windows).&lt;br /&gt;
This is passed to any external script interpreter.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:bulb.png|20px]]Notice, that paths are separated by &amp;quot;:&amp;quot; (colon) under Unix/Linux but &amp;quot;;&amp;quot; (semi) under Windows.&lt;br /&gt;
Additional paths are useful if a script calls for other programs, and you do not want to hardcode any paths in the script, in order to allow for the suite to be portable to other machines.&lt;br /&gt;
&lt;br /&gt;
===== Environment Variables =====&lt;br /&gt;
Additional environment variables passed to external script interpreters.&lt;br /&gt;
To change, enter name and value and press &amp;quot;&#039;&#039;Add&#039;&#039;&amp;quot;, or select a variable from the list and press &amp;quot;&#039;&#039;Remove&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Subitems under External Script Interpreter Settings ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_Shell_and_BatchSettings/en |Shell &amp;amp; Batch Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_GroovyClassPathSettings/en|Groovy Class Path Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_NodeSettings/en|Node Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_PythonSettings/en|Python Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_Jython_and_IronPythonSettings/en|Jython &amp;amp; IronPython Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_CBridgeSettings/en|CBridge Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_ClingSettings/en|Root/Cling Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_RubySettings/en|Ruby Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_DartSettings/en|Dart Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_JuliaSettings/en|Julia Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_SmalltalkSettings/en|Smalltalk Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_SchemeSettings/en|Scheme Settings]]&lt;br /&gt;
* [[ Settings_ExternalScriptInterpreters_OtherSettings/en|Other Settings]]&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
See also [[ Installing_additional_Frameworks/en |&amp;quot;Installing additional frameworks&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
[[ Settings_ExternalScriptInterpreterSettings/en|Back to &amp;quot;External Script Interpreter Settings&amp;quot;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[ Settings/en|Back to the main page &amp;quot;Settings&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Settings]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Settings_SSDPSettings/en&amp;diff=30910</id>
		<title>Settings SSDPSettings/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Settings_SSDPSettings/en&amp;diff=30910"/>
		<updated>2026-02-23T12:50:54Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 19.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Enable SSDP Announcements ==&lt;br /&gt;
&lt;br /&gt;
If enabled, expecco will announce its availability via SSDP multicast messages (also known as UPnP).&lt;br /&gt;
These announcements are especially useful for:&lt;br /&gt;
* the remote control app which runs on a mobile device&lt;br /&gt;
* other expeccos to detect possible execution partners&lt;br /&gt;
* expeccoALM to detect possible execution slaves&lt;br /&gt;
* administrators looking for machines which might have floating licenses allocated&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Notice, that SSDP messages are UDP messages which are sent in regular time intervals, &lt;br /&gt;
and received within your local network (the site), depending on your router/switch and firewall setup.&lt;br /&gt;
&lt;br /&gt;
To reduce traffic in the local network, some (usually bigger) organizations might disable, block or forbid SSDP announcements. &lt;br /&gt;
Or their spread may be limited to a subset of your machines (i.e. rooms/departments).&lt;br /&gt;
&amp;lt;br&amp;gt;Also, WLAN access points may have to be configured to forward these messages within the segment.&lt;br /&gt;
 &lt;br /&gt;
If in doubt, ask your administrator.&lt;br /&gt;
&lt;br /&gt;
For your convenience, expecco includes a monitor window to show incoming SSDP messages (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Network Diagnose&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;SSDP Monitor&#039;&#039;&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Folder_Element/en&amp;diff=30909</id>
		<title>Folder Element/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Folder_Element/en&amp;diff=30909"/>
		<updated>2026-02-23T12:48:51Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 19.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Folder elements are used to group related items. Notice that any action block item can have sub items. Besides being used to specify user-defined action menus (see [[Testsuite Editor-Metadata Editor/en | Testsuite Editor]]), folders have no special semantic relevance.&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Notice that in contrast to other test tools, folders are NOT used to group testcases into test sequences or sub-activities into a composite activities. They are only used for organization - not to specify any execution order or execution behavior.&lt;br /&gt;
&lt;br /&gt;
Folder elements only provide a single editor tab, into which documentation related to the folder can be entered. If this documentation is left empty, the documentation editor presents a short summary of the containing element&#039;s documentation texts (read-only).&lt;br /&gt;
&lt;br /&gt;
== Useful Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== Public vs. Private Actions ===&lt;br /&gt;
&lt;br /&gt;
In imported library suites, put stuff which is supposed to be used by importing projects into a separate folder named &amp;quot;API&amp;quot; or &amp;quot;Exported&amp;quot;. This makes it easier for other team members to find reusable stuff. You may also want to change the folder&#039;s icon color (contextMenu &amp;amp;#8594; &amp;quot;&#039;&#039;Misc&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;IconColor&#039;&#039;&amp;quot;) to emphasize particular folders (such as &amp;quot;red&amp;quot; for obsolete or experimental actions, &amp;quot;green&amp;quot; for released/public actions etc.)&lt;br /&gt;
&lt;br /&gt;
=== Demos and Examples ===&lt;br /&gt;
&lt;br /&gt;
Add a folder named &amp;quot;Playground&amp;quot;, &amp;quot;Sandbox&amp;quot; or &amp;quot;Examples&amp;quot; or similar and place compound action blocks which demonstrate key features or low level access functionality. Other team members may later easily find those and play with the examples. It is also a good idea to place simple connection, communication, [[Glossary/en#SUT_.28System_Under_Test.29|SUT]] is running tests, setup and shutdown blocks there (unless those are commonly used, then put them into API/Exported).&lt;br /&gt;
&lt;br /&gt;
=== Define Useful Actions as Menu Functions ===&lt;br /&gt;
&lt;br /&gt;
Add a folder named &amp;quot;menu Actions&amp;quot; or similar, place and useful actions for test setup, equipment startup and shutdown or calibration into it. When this folder is defined as the project&#039;s operation menu folder (in the test suite&#039;s &amp;quot;Misc&amp;quot; editor page), you can quickly execute those functions via the main menu. For more information, see [[User Defined Menu Items]].&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
[[Tree Elements]]&lt;br /&gt;
&amp;lt;br&amp;gt;[[ Navigation Tree ]]&lt;br /&gt;
&lt;br /&gt;
[[Category: Tree Elements]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Settings_WindowsAutomationSettings/en&amp;diff=30908</id>
		<title>Settings WindowsAutomationSettings/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Settings_WindowsAutomationSettings/en&amp;diff=30908"/>
		<updated>2026-02-23T12:47:06Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 25.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
[[Datei:bulb.png|20px]]Notice:&amp;lt;br&amp;gt;The Windows Automation Plugin (WA V1) has been replaced by a new version,&lt;br /&gt;
and is only maintained to provide backward compatibility for customers using it.&lt;br /&gt;
Please migrate to use the WA2 Plugin, which is described in&lt;br /&gt;
&amp;quot;[[WindowsAutomation_Reference_2.0/en| WindowsAutomation Reference 2.0]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Windows-Automation Plugin Settings ==&lt;br /&gt;
 &lt;br /&gt;
The Windows-Automation plugin extends the GUI-browser&#039;s capabilities to support recording, replay and testing of GUI applications via the Windows-Automation technology.&lt;br /&gt;
&lt;br /&gt;
This settings dialog is only shown/enabled if the plugin is loaded and licensed.&lt;br /&gt;
----&lt;br /&gt;
Back to [[Online Documentation]]&lt;br /&gt;
&lt;br /&gt;
[[Category: Settings]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=WindowsAutomation_Reference_2.0/en&amp;diff=30907</id>
		<title>WindowsAutomation Reference 2.0/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=WindowsAutomation_Reference_2.0/en&amp;diff=30907"/>
		<updated>2026-02-23T11:49:22Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Known issues in the current Release 19.1.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is the documentation for the Windows Automation 2.0 plugin.&lt;br /&gt;
It provides facilities to automate tests incorporating applications with a GUI based on Windows Presentation Foundation (WPF), WinForms, and the old Win32 API.&lt;br /&gt;
&lt;br /&gt;
Notice:&amp;lt;br&amp;gt;The vsn2 replaces the previous vsn1 plugin, which is no longer maintained.&lt;br /&gt;
The change was necessary due to changes in the Windows operating system, and features which were discontinued by Microsoft.&lt;br /&gt;
The vsn2 plugin uses Microsoft&#039;s UI-Automation2 API to interact with the application.&lt;br /&gt;
This API was not avaliable in Windows-XP, Vista and other older OS versions, and many features used by the previous version are no longer supported in newer OS versions, or need different parameters.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
*Automated GUI testing of WPF, WinForms, and Win32 applications.&lt;br /&gt;
*Contains an expecco block library and tools which help to model tests and inspect the GUI of the application.&lt;br /&gt;
*Parallel remote test-execution on multiple systems.&lt;br /&gt;
*Performs tests against already built executables. No source code changes / recompilation of the application is required.&lt;br /&gt;
*Access to GUI components using XPath locators.&lt;br /&gt;
*Access objects of the application live at execution time.&lt;br /&gt;
*Full access to keyboard and mouse of the target system.&lt;br /&gt;
*Lots of additional features such as screen capturing, taking screenshots, highlighting GUI elements, mouse tracking, ...&lt;br /&gt;
&lt;br /&gt;
= Known issues in release 19.1.0 =&lt;br /&gt;
* The WindowsAutomation2.ets library has got a new functional id. When reimporting the library in existing Pre-19.1.0 test suites (which is mandatory), a warning about a changed functional id is shown once. It is ok to accept this dialog.&lt;br /&gt;
* Instant follow mouse is very expensive in Windows and is therefore disabled. Use &#039;&#039;HotKeys&#039;&#039; to select a GUI element in the tree at the current pointer position or to update the element tree. HotKeys can be configured in the settings. The HotKey-service has to be started. Take care that the keys have not already been grabbed by another application. If that is the case, a warning will be shown, and you should either make sure that expecco is started before the other application, or that you use other hotkey combinations (in either expecco or the application).&lt;br /&gt;
&lt;br /&gt;
= Limitations =&lt;br /&gt;
* WindowsAutomation only supports XPath1.0.&lt;br /&gt;
: That means for example, that the &amp;quot;ends-with&amp;quot; function, which is an XPath2 function, is not supported and thus not possible as XPath attribute filter.&lt;br /&gt;
: See [[https://en.wikipedia.org/wiki/XPath_2.0#Function_library XPath vs. XPath2]] for details. For some (especially &amp;quot;ends-with&amp;quot;) there are workarounds by comparing against a substring which is based on the length of the attribute string or a regex match (see [https://stackoverflow.com/questions/40934644/xpath-testing-that-string-ends-with-substring]). &lt;br /&gt;
: Notice, that this is a limitation of the Windows operating system, which cannot be worked around in expecco.&lt;br /&gt;
&lt;br /&gt;
=Installation and Connection=&lt;br /&gt;
The WindowsAutomation testing plugin uses the expecoo &amp;quot;.NET-Bridge&amp;quot; which consists of two parts: A plugin for expecco, and a server executable using the .NET framework running on the remote computer to connect to.&lt;br /&gt;
&lt;br /&gt;
==Requirements==&lt;br /&gt;
On the machine running the system under test:&lt;br /&gt;
*.NET Framework 4.7 [https://www.microsoft.com/net/download/all] or higher.&lt;br /&gt;
* One of the following operation systems:&lt;br /&gt;
::- Windows 7 SP1&lt;br /&gt;
::- Windows 8&lt;br /&gt;
::- Windows 8.1&lt;br /&gt;
::- Windows 10&lt;br /&gt;
::- Windows 11&lt;br /&gt;
&lt;br /&gt;
::- Windows Server 2012 R2&lt;br /&gt;
::- Windows Server 2016&lt;br /&gt;
::- Windows Server 2019&lt;br /&gt;
::- Windows Server 2022&lt;br /&gt;
&lt;br /&gt;
==Plugin Components==&lt;br /&gt;
The plugin consists of the following parts:&lt;br /&gt;
* The [[GUI Browser]], used to interactively explore your application.&lt;br /&gt;
* The Windows Automation Library, which provides blocks that you can use in your test cases.&lt;br /&gt;
* The .NET-Bridge server, which provides an interface between the application under test and expecco.&lt;br /&gt;
&lt;br /&gt;
==Installing and Configuring the Plugin in Expecco==&lt;br /&gt;
The plugin is usually installed automatically by the installer; either included in the main expecco installation or provided as a separate installable add-on package. Its files are stored in the &amp;quot;&amp;lt;code&amp;gt;plugin&amp;lt;/code&amp;gt;&amp;quot; subfolder of the expecco installation folder. You can also copy those files manually to that folder, if required. Expecco detects the plugin automatically during startup. You may have to restart your expecco session, if the plugin is installed later.&lt;br /&gt;
&lt;br /&gt;
==Preparing a local system for test execution==&lt;br /&gt;
To automate applications running on the SAME host as expecco, there is no need to set up anything - it should work out of the box.&lt;br /&gt;
&lt;br /&gt;
Try to connect to an application via the GUIBrowser&#039;s &#039;&#039;WindowsAutomation&#039;&#039;-connect dialog:&lt;br /&gt;
&lt;br /&gt;
[[Datei:WindowsAutomation2Connect.png]]&lt;br /&gt;
&lt;br /&gt;
==Preparing a remote system for test execuction==&lt;br /&gt;
&lt;br /&gt;
===Security Considerations===&lt;br /&gt;
Please make sure, that remote access is only possible from inside a secure local network.&lt;br /&gt;
Under no circumstances should you grant access to the DotNetBridgeServer from untrusted hosts.&lt;br /&gt;
&lt;br /&gt;
===DotNet Bridge Server===&lt;br /&gt;
&lt;br /&gt;
The remote system has to run the &amp;quot;&#039;&#039;.Net-Bridge server&#039;&#039;&amp;quot; which in turn either actively connects to expecco or passively waits for an incoming connection from expecco.&lt;br /&gt;
&lt;br /&gt;
For this, copy &amp;quot;&amp;lt;code&amp;gt;DotNetBridgeServer.exe&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;DotNetBridge.dll&amp;lt;/code&amp;gt;&amp;quot; (found in the &amp;quot;&amp;lt;code&amp;gt;packages/exept/bridgeFramework/dotNetBridge/dotNetBin&amp;lt;/code&amp;gt;&amp;quot; folder under the expecco installation directory) to the computer where your system under test is running (you can copy it into any folder). No further installation is needed.&lt;br /&gt;
&lt;br /&gt;
To start the bridge, navigate to the executable in a shell/cmd/console and start it with the following arguments&lt;br /&gt;
(&amp;quot;&amp;lt;code&amp;gt;DotNetBridgeServer.exe --help&amp;lt;/code&amp;gt;&amp;quot; outputs a list of valid options):&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Arguments !! Required !! Description&lt;br /&gt;
|-&lt;br /&gt;
| -s || Yes || &amp;quot;&#039;&#039;server mode&#039;&#039;&amp;quot;. Tells the executable to run in server mode (it will wait for expecco to connect to it, as opposed to client mode,&amp;lt;br&amp;gt;where it actively connects to the partner).&lt;br /&gt;
|-&lt;br /&gt;
| -k || Yes || &amp;quot;&#039;&#039;keepalive&#039;&#039;&amp;quot;. Tells the client to keep the connection open after a connection has been terminated.&amp;lt;br&amp;gt;This saves you the hassle to restart it every time a test finishes.&lt;br /&gt;
|-&lt;br /&gt;
| -a&amp;amp;nbsp;&amp;lt;ip/hostname&amp;gt;|| Yes || &amp;quot;&#039;&#039;IP address accepting connections&#039;&#039;&amp;quot;. The IP-address or hostname of an interface on the host on which connections will be accepted (in server mode) or to which it connects (in client mode).&amp;lt;br&amp;gt;If you have multiple network interfaces, you can ensure that only incoming connections on the secure network will be accepted by setting the IP address of this interface.&amp;lt;br&amp;gt;To allow incoming connections on any network interface (i.e. to have it listen on any IP-address), set it to 0.0.0.0. If you are not inside a secure network, you should use a secure tunnel (e.g. a SSH or Powershell tunnel) between the machine running expecco and the machine running the bridge and listen only on 127.0.0.1 (the default).&lt;br /&gt;
|-&lt;br /&gt;
| -p &amp;lt;int&amp;gt; || No || &amp;quot;&#039;&#039;port&#039;&#039;&amp;quot;. The port the server should listen on (in server mode) or to which is should connect (default is 34318).&lt;br /&gt;
|-&lt;br /&gt;
| -L &amp;lt;string&amp;gt; || No || &amp;quot;&#039;&#039;assembly&#039;&#039;&amp;quot;. Load a .NET assembly on startup. Omit the .dll extension (so use &amp;quot;WindowsAutomation&amp;quot; but not &amp;quot;WindowsAutomation.dll&amp;quot;).&amp;lt;br&amp;gt;You can repeat this option to load multiple assemblies. &lt;br /&gt;
Note: this is not normally needed, as expecco loads the required assemblies automatically into the bridge.&amp;lt;br&amp;gt;However, if security settings forbid external assemblies, you have to copy them to the target machine, and load them via command line option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
So you may execute on the remote host:&lt;br /&gt;
&lt;br /&gt;
    DotNetBridgeServer.exe -s -k -a 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
For automatic tests, you must setup the target system for the bridge server to be running; either by adding it to some &amp;quot;auto exec&#039; script, or by adding to the &amp;quot;scheduled tasks&amp;quot;, or by remote starting it from your test-host via a powershell script, remote ssh command or similar.&lt;br /&gt;
&lt;br /&gt;
If you get an &amp;quot;Assembly not Found&amp;quot; error, you may have an incompatible .NET framework or the &amp;quot;DotNetBridge.dll&amp;quot; is missing. If you get a network error, or the expecco-host cannot connect, make sure that your firewall settings allow access to the given ports (you may try an alternative port like 8080, which must then be specified on both sides).&lt;br /&gt;
&lt;br /&gt;
=Settings=&lt;br /&gt;
There are currently no configurable settings.&lt;br /&gt;
&lt;br /&gt;
=GUI Browser=&lt;br /&gt;
The GUI browser is used to explore a running application. You can browse the application, inspect element properties and execute actions. See &amp;quot;[[GUI Browser| Expecco GUI Tests Extension Reference]]&amp;quot; for details.&lt;br /&gt;
&lt;br /&gt;
=Library=&lt;br /&gt;
This article gives a short overview over the design philosophy of the library. You can find more detailed documentation and examples attached to the blocks itself.&lt;br /&gt;
&lt;br /&gt;
== Connect to Application vs. Connect to Screen ==&lt;br /&gt;
You can either &amp;quot;connect to a single application&amp;quot;, or &amp;quot;connect to the screen&amp;quot;.&lt;br /&gt;
The first provides faster access to the components, but will not work, if the app creates subprocesses with a GUI (eg. for dialogs or additional windows). There exist also applications which always create a subprocess, even for the main GUI.&lt;br /&gt;
&lt;br /&gt;
For such applications, you have to &amp;quot;connect to the screen&amp;quot;, and provide an additional window-reference in the XPath locator.&lt;br /&gt;
&amp;lt;br&amp;gt;You must also use a screen connection, if your test contains interactions between multiple top-level windows, for example a drag&amp;amp;drop between windows.&lt;br /&gt;
&lt;br /&gt;
== Connecting to an Application ==&lt;br /&gt;
To automate an application, you first have to connect to it or to its screen. You can do this with the&lt;br /&gt;
blocks from the &amp;quot;&#039;&#039;Connecting&#039;&#039;&amp;quot; group.&lt;br /&gt;
[[Bild:WindowsAutomation2_Library_ConnectingBlocks.PNG|frame|The Library&#039;s Connection Blocks (old picture without screen connection blocks).]]&lt;br /&gt;
&lt;br /&gt;
You can connect to an individual application by its &#039;&#039;executable name&#039;&#039;, or by its &#039;&#039;process id&#039;&#039;. &lt;br /&gt;
If you use the executable name, expecco will attach to the main process of the specified executable.&lt;br /&gt;
Be careful as this is not necessarily the process drawing the GUI! &lt;br /&gt;
Use the process id if an application spawns more than one process and you need to make sure you connect to the GUI process and not some background process.&lt;br /&gt;
&lt;br /&gt;
All connection blocks also require you to specify a &#039;&#039;name&#039;&#039; by which the connection should be known in future.&lt;br /&gt;
This is needed when you automate multiple applications at the same time and need to change&lt;br /&gt;
&#039;&#039;connection contexts&#039;&#039; during test execution.&lt;br /&gt;
Please note that the application to connect to has to be started before the corresponding connection block is executed.&lt;br /&gt;
You can change in context of which connection a block is executed with the [&#039;&#039;Set Active Connection&#039;&#039;] block.&lt;br /&gt;
This allows you, for example, to automate and compare the state of applications running on multiple systems in one test case.&lt;br /&gt;
&lt;br /&gt;
=== Establishing a Local Connection === &lt;br /&gt;
To automate an application running on the same host as expecco, there is no need to set up anything. &lt;br /&gt;
Use &amp;quot;[&#039;&#039;Create Local Connection&#039;&#039;]&amp;quot; with the above mentioned parameters.&lt;br /&gt;
&lt;br /&gt;
=== Establishing a Remote Connection ===&lt;br /&gt;
Make sure that the DotNet-Bridge server (&amp;quot;&amp;lt;code&amp;gt;DotNetBridgeServer.exe&amp;lt;/code&amp;gt;&amp;quot;) is running on the remote system, as explained in the chapter [[#Preparing a remote system for test execuction|&amp;quot;&#039;&#039;Preparing a remote system for test execuction&#039;&#039;&amp;quot;]]&lt;br /&gt;
When the bridge is running, you can connect to it with the &amp;quot;[&#039;&#039;Create Remote Connection&#039;&#039;]&amp;quot; block using the hostname and IP-Address you specified when you started the bridge.&lt;br /&gt;
&lt;br /&gt;
Notice, that the DotNet-Bridge server only accepts local connections by default.&lt;br /&gt;
This is done for security reasons. Use the &amp;quot;-a x.x.x.x&amp;quot; command line argument to specify, which hosts are allowed&lt;br /&gt;
to connect. With &amp;quot;-a 0.0.0.0&amp;quot;, any host is allowed. Do NOT use this, if the remote host is reachable from untrusted hosts.&lt;br /&gt;
&lt;br /&gt;
=== Closing a Connection ===&lt;br /&gt;
Remember to always close a connection when it is no longer needed, as it otherwise needlessly consumes resources.&lt;br /&gt;
One simple way to do this is to setup your connection in the &amp;quot;&#039;&#039;Before Execution&#039;&#039;&amp;quot; (pre-action) part of the test suite or test case,&lt;br /&gt;
and put the &amp;quot;[&#039;&#039;Close All Connections&#039;&#039;]&amp;quot; action block in the &amp;quot;&#039;&#039;After exeuction&#039;&#039;&amp;quot; (post-action) part.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Accessing GUI Elements ==&lt;br /&gt;
[[Bild:WindowsAutomation_Library_AccessBlocks.PNG|frame|The Library&#039;s GUI Element Access Blocks.]]&lt;br /&gt;
[[Bild:WindowsAutomation_Library_AccessBlocksExamples.PNG|frame|A Few Examples on How to Access Elements in Notepad.]]&lt;br /&gt;
[[Bild:WindowsAutomation_Library_AccessBlocksModes.PNG|frame|Different Ways to Reference a GUI Element.]]&lt;br /&gt;
All Windows applications are built as a &#039;&#039; tree&#039;&#039;  of &#039;&#039; GUI elements&#039;&#039;.&lt;br /&gt;
Some elements act as container of other element - their children. Tables, for example, are containers&lt;br /&gt;
for their cell elements which themselves might contain text labels.&lt;br /&gt;
At the root of the tree are one or more &#039;&#039;windows&#039;&#039; . When you connect to an application, you get access to&lt;br /&gt;
all windows at the tree&#039;s root.&lt;br /&gt;
To manipulate any of the system under test&#039;s GUI element, you first have to gain access to it.&lt;br /&gt;
The group named &amp;quot;&#039;&#039;GUI Element Access&#039;&#039;&amp;quot; provides action blocks to access elements. The actions are further categorized into sub-groups named &amp;quot;&#039;&#039; Access By XPath&#039;&#039;&amp;quot; , &amp;quot;&#039;&#039;Access By Property&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;Existence Test&#039;&#039;&amp;quot; etc. &lt;br /&gt;
For each category, blocks with the same interface exist. The only difference is the method of retrieval.&lt;br /&gt;
&lt;br /&gt;
;Get GUI Element : returns a &#039;&#039;single&#039;&#039; GUI element matching the search condition. If multiple elements match the condition, an &#039;&#039;arbitrary&#039;&#039; element matching the condition is returned.&lt;br /&gt;
:To make sure that there is only one single element matching, set &#039;&#039;ensureExclusive&#039;&#039;  to true. You can also enforce this globally by setting the environment variable &amp;quot;&#039;&#039;ensureExclusive&#039;&#039;&amp;quot; in your environment. &lt;br /&gt;
:If ensureExclusive is set and more than one element is found, the block will fail and notify about the ambiguity. This is disabled by default, as checking for uniqueness is a very costly (ie. slow) operation.&lt;br /&gt;
:You can also specify a &#039;&#039;timeout&#039;&#039; after which the search is aborted. This is useful if you know an element should be there already (or soon but might currently be loading).&lt;br /&gt;
&lt;br /&gt;
;Get GUI Elements: returns &#039;&#039;all&#039;&#039; GUI elements matching the search condition. If no element is found, it returns an empty list &#039;&#039;Timeout&#039;&#039; and &#039;&#039;cacheXPath&#039;&#039; are also applicable.&lt;br /&gt;
&lt;br /&gt;
;Exists: Works exactly the same as &#039;&#039;Get GUI Element&#039;&#039; but does not fail if no element is found. Additionally provides an output pin specifying if an element has been found.&lt;br /&gt;
&lt;br /&gt;
Both of these blocks are also available in the &amp;quot;&#039;&#039;Relative To Anchor&#039;&#039;&amp;quot; variety. Those blocks also take a GUI Element as &#039;&#039;anchor&#039;&#039; in relation to which they search. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using XPaths ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;XPath&#039;&#039;&#039; is the query language used to select GUI elements in the application&#039;s element tree.&lt;br /&gt;
You can find the XPath of an element with the [[Expecco GUI Tests Extension Reference/en|Gui Browser]] or with third-party applications like &amp;quot;Inspect.exe&amp;quot; [https://msdn.microsoft.com/en-us/library/dd318521(v=vs.85).aspx] or &amp;quot;FlaUInspect&amp;quot; [https://github.com/FlauTech/FlaUInspect].&lt;br /&gt;
&amp;lt;br&amp;gt;As an example, the full &#039;&#039;XPath&#039;&#039; of the scroll button on the &lt;br /&gt;
vertical scrollbar in the german Windows &amp;quot;Notepad.exe&amp;quot; application looks like this:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;code&amp;gt;/Window[@Name=&#039;Unbenannt - Editor&#039;]/Document[@Name=&#039;Text-Editor&#039;]/ScrollBar[@Name=&#039;Vertikale Bildlaufleiste&#039;]/Button[@Name=&#039;Bildlauf nach unten&#039;] &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For each level in the GUI tree, a new &#039;&#039;Location Step&#039;&#039; containing the child element&#039;s &#039;&#039;Control Type&#039;&#039; was added in the above XPath.&lt;br /&gt;
&amp;lt;br&amp;gt;You do not have to use any predicates, the following XPath is valid as well:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;code&amp;gt;/Window/Document/ScrollBar/Button &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
but might lead to issues if multiple GUI Elements match this path.&lt;br /&gt;
&lt;br /&gt;
You can select by three predicates (which can be mixed and matched in the same query):&lt;br /&gt;
&lt;br /&gt;
; Name: the name the application developer has given an element. Be careful as this name might change during programm execution (See for example Notepad&#039;s window name which always begins with the name of the currently opened file).&lt;br /&gt;
:  &amp;lt;code&amp;gt;/Window[@Name=&#039;Unbenannt - Editor&#039;] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
; AutomationId: An ID the application developer has given an element. It is meant to be unique between siblings but that is not enforced on lazy or incompetent programmers.&lt;br /&gt;
: Many lazy developers leave the ID empty or reuse it, making it useless.&lt;br /&gt;
: You should use this ID wherever applicable as it is static and meant for this exact purpose.&lt;br /&gt;
:  &amp;lt;code&amp;gt;/Window/Document[@AutomationId=&#039;15&#039;] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;List Index: If there are multiple siblings with the same Control Type, you can select one of them by (1-based) list index.&lt;br /&gt;
:  &amp;lt;code&amp;gt;/Window[1]/Document[1] &amp;lt;/code&amp;gt;&lt;br /&gt;
:  &amp;lt;code&amp;gt;/Window[1]/Document[last()] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Warning there are XPath Limitations ===&lt;br /&gt;
&#039;&#039;&#039;Please Note&#039;&#039;&#039;: You can ONLY use the three predicates above in your XPaths.&lt;br /&gt;
&amp;lt;br&amp;gt;Other predicates &#039;&#039;&#039;DO NOT&#039;&#039;&#039; work! &lt;br /&gt;
&amp;lt;br&amp;gt;To search for an element by another property (e.g. its help text), use the &#039;&#039;&#039;By Property&#039;&#039;&#039; variant of the block instead. &lt;br /&gt;
If the property is not unique, you can select a unique ancestor of the target by property or XPath relative to which the property is unique.&lt;br /&gt;
You can then use that ancestor as anchor in the [&#039;&#039;Get GUI Element By Property (Relative to Anchor)&#039;&#039;] block.&lt;br /&gt;
&lt;br /&gt;
=== Using Wildcards in XPaths ===&lt;br /&gt;
&lt;br /&gt;
XPath also supports &#039;&#039;&#039;wildcards&#039;&#039;&#039;. You can:&lt;br /&gt;
* replace &#039;&#039;&#039;one tree level&#039;&#039;&#039; with a &amp;quot;*&amp;quot; wildcard: &lt;br /&gt;
: &amp;lt;code&amp;gt;/Window/Document[@AutomationId=&#039;15&#039;]/*/Button[1]&amp;lt;/code&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;/*/*/*/Button[1] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
* replace a &#039;&#039;&#039;control type&#039;&#039;&#039; with a &amp;quot;*&amp;quot; wildcard:&lt;br /&gt;
: &amp;lt;code&amp;gt;/Window/*[@AutomationId=&#039;15&#039;] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
* replace &#039;&#039;&#039;an arbitrary amount of levels&#039;&#039;&#039; with a &amp;quot;//&amp;quot; wildcard:&lt;br /&gt;
: &amp;lt;code&amp;gt;//Button &amp;lt;/code&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;/Window//Button[1] &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Especially the last option is useful as it makes your tests more readable, in that the reader can easily focus on the relevant parts of the xpath.&lt;br /&gt;
&lt;br /&gt;
But be careful: using wildcards comes at a steep performance cost (due to the implementation inside the Windows API). &lt;br /&gt;
If your test runs unacceptably slow, first try to remove wildcards where they are not needed.&lt;br /&gt;
&lt;br /&gt;
=== Using Properties===&lt;br /&gt;
&lt;br /&gt;
You can also search for elements by property; i.e. by specifying a value an element&#039;s property with the given name must have. &lt;br /&gt;
&lt;br /&gt;
For a list of properties a GUI element might have, take a look at Microsoft&#039;s documentation [https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-control-patterns-overview#control-pattern-classes-and-interfaces].&lt;br /&gt;
&lt;br /&gt;
=== XPath Resolution in Action Blocks ===&lt;br /&gt;
&lt;br /&gt;
Xpath resolution may be slow in the Windows Automation API, depending on the number of windows/elements which have to be checked.&lt;br /&gt;
&lt;br /&gt;
To speed up test execution, you should reuse a resolved XPath if possible.&lt;br /&gt;
For this, use the &amp;quot;Get Element by XPath&amp;quot; action, and feed the &amp;quot;element handle&amp;quot; to multiple actions.&lt;br /&gt;
All action- and property access blocks can take either an XPath or an element handle as locator input.&lt;br /&gt;
&lt;br /&gt;
The image on the right shows this mode in action. Variants 1 and 2 are functionally equivalent.&lt;br /&gt;
While Variant 2 is more concise, Variant 1 is the right choice in most cases. While it has an additional block, you have control over the other input parameters. &lt;br /&gt;
You also can recycle the GUI element reference as seen in 3). This is invaluable as the XPath only has to be resolved once. This speeds up test execution by a lot as XPath resolution is very expensive operation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rule of thumb&#039;&#039;&#039;: Always use Variant 1 except if you need the reference to the GUI element only once, or if the application replaces the element dynamically.&lt;br /&gt;
&lt;br /&gt;
=== Separating Path Definitions ===&lt;br /&gt;
&lt;br /&gt;
It is highly recommended to add definitions for element-paths into an environment (typically the project environment), and use &amp;quot;Environment Value&amp;quot; references as input to the steps. This gives two benefits:&lt;br /&gt;
&lt;br /&gt;
* the paths are hidden and the values at the steps become more readable&lt;br /&gt;
* your tests are easier to maintain: in case of a changed window layout/structure, only the variable definitions need to be changed at one place.&lt;br /&gt;
* you can import those definitions from a CSV or XML file, and thus separate the locators from the actual test suite. In case of changed UI-layout / UI-hierarchy after a revision change of the tested application, all you need is a new excel or xml file containing those definitions.  &lt;br /&gt;
&lt;br /&gt;
If the development team of the application can provide the paths of the UI components in a machine readable form (i.e. CVS or XML file), you may even let expecco read and parse those path definitions at test start time, and let it automatically adapt to any change. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interacting with GUI Elements ==&lt;br /&gt;
Once you retrieved a GUI element, you can interact with it by making use of the library&#039;s blocks located in the groups &#039;&#039;&#039;Elements&#039;&#039;&#039;, &#039;&#039;&#039;Patterns&#039;&#039;&#039;, and &#039;&#039;&#039;Properties&#039;&#039;&#039;. &lt;br /&gt;
Blocks in those categories take a GUI Element (and sometimes additional data) as input and manipulate it or query for its properties in some way.&lt;br /&gt;
&lt;br /&gt;
[[Bild:WindowsAutomation_Library_ElementsPatternsProperties.png|600px|The Library&#039;s Blocks for Interacting With Elements.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The &#039;Elements&#039; Group ===&lt;br /&gt;
&lt;br /&gt;
This group contains blocks that are applicable to blocks that only work on GUI elements of a specific type. For a block&#039;s detailed description with examples ,&lt;br /&gt;
take a look at the block&#039;s documentation in expecco.&lt;br /&gt;
&lt;br /&gt;
Even though not only Checkboxes can be &#039;checked&#039;, the [&#039;&#039;Check&#039;&#039;] block in the &amp;quot;&#039;&#039;Checkbox group&#039;&#039;&amp;quot; only works for checkboxes and not e.g. for radio buttons. &lt;br /&gt;
Because of this limitation there are not that many blocks targeting specific elements. Most blocks target a specific &#039;&#039;pattern&#039;&#039; instead and are therefore in the &amp;quot;&#039;&#039;Patterns&#039;&#039;&amp;quot; group.&lt;br /&gt;
&lt;br /&gt;
=== The &#039;Patterns&#039; Group ===&lt;br /&gt;
&lt;br /&gt;
This group contains blocks that are applicable to GUI elements supporting a certain &#039;&#039;pattern&#039;&#039;. &lt;br /&gt;
Patterns describe how a GUI element &#039;&#039;behaves&#039;&#039; rather than what it &#039;&#039;is&#039;&#039;. An element can also support multiple patterns at the same time. &lt;br /&gt;
You can find out which patterns an element supports with the [&#039;&#039;Get Supported Patterns&#039;&#039;] block or by taking a look at Microsoft&#039;s documentation about patterns [https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-control-patterns-overview].&lt;br /&gt;
&lt;br /&gt;
Pattern blocks can therefore be &#039;&#039;re-used&#039;&#039; between GUI elements of different types. &lt;br /&gt;
For example, the [&#039;&#039;Expand&#039;&#039;] block in &amp;quot;&#039;&#039;ExpandCollapse pattern&#039;&#039;&amp;quot;, can be used to expand Comboboxes, Menus, Submenus, or Trees.&lt;br /&gt;
&lt;br /&gt;
=== The &#039;Properties&#039; Group ===&lt;br /&gt;
&lt;br /&gt;
Blocks in the &amp;quot;&#039;&#039;Patterns&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Elements&#039;&#039;&amp;quot; group already allow you to query the value of properties pertaining to that element or pattern. Blocks in the &amp;quot;&#039;&#039;Properties&#039;&#039;&amp;quot; group allow you to query both properties which all elements share as well as arbitrary properties. If you try to retrieve a property an element does not support, the block will fail.&lt;br /&gt;
&lt;br /&gt;
Please note that the [&#039;&#039;Get Arbitrary Property&#039;&#039;] block can only query for properties that belong to a pattern. You cannot, for example, query &amp;quot;Text&amp;quot; from a textfield as this is not a property, use &amp;quot;Value&amp;quot; of the value pattern instead. Microsoft&#039;s documentation has a list of patterns and the properties they provide [https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-control-patterns-overview#control-pattern-classes-and-interfaces]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Automating Keyboard and Mouse ==&lt;br /&gt;
[[Bild:WindowsAutomation_Library_KeyboardMouse.png|400px|The Library&#039;s Blocks for Interacting With Keyboard and Mouse.]]&lt;br /&gt;
&lt;br /&gt;
You can control keyboard and mouse with action blocks in the &amp;quot;&#039;&#039;Keyboard&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Mouse&#039;&#039;&amp;quot; groups, as shown on the right. In contrast to the blocks above, which work in context of a GUI element, the keyboard and mouse blocks work on a global level. You therefore do not need to provide a GUI element when using them. &lt;br /&gt;
&lt;br /&gt;
You might want to execute some blocks in context of a GUI elemenet nontheless (e.g. enter a number into a text field instead of just pressing keys while the application is running). You can achieve this by selecting the element with the mouse beforehand as you would do when using the application normally (use the [&#039;&#039;Left/Double/Right Click On Element&#039;&#039;] blocks for this).&lt;br /&gt;
If you do not want to wait for the mouse to move, you can also use the [&#039;&#039;Set Focus&#039;&#039;] block instead.&lt;br /&gt;
&lt;br /&gt;
=== Keyboard ===&lt;br /&gt;
The plugin provides blocks to interact with the keyboard on different abstraction levels. The most versatile block is [&#039;&#039;Type With Control Keys Pressed&#039;&#039;] where you can specify a string of characters to be typed while any number of control keys (e.g. &amp;quot;esc&amp;quot;, &amp;quot;alt&amp;quot;, &amp;quot;shift&amp;quot;, &amp;quot;ctrl&amp;quot;, ...) are held down. All other blocks are specializations of this block.&lt;br /&gt;
&lt;br /&gt;
[&#039;&#039;Press Control Keys&#039;&#039;] e.g. allows you to enter key commands such as renaming files (&amp;quot;ALT+F2&amp;quot;), starting the task manager (&amp;quot;CTRL+ALT+DEL&amp;quot;), or closing a window (&amp;quot;ALT+F4&amp;quot;). [&#039;&#039;Press Control Key&#039;&#039;] makes it easy to just press a single key (e.g. &amp;quot;RETURN&amp;quot; to start a new line in an edit box). The &amp;quot;&#039;&#039;Shortcuts&#039;&#039;&amp;quot; group provides an assorted collection of often used key combinations for your convenience.&lt;br /&gt;
&lt;br /&gt;
Use the [&#039;&#039;Type&#039;&#039;] action to just type some text, or if you just need some throwaway demo text, use [&#039;&#039;Type Random Phrase&#039;&#039;].&lt;br /&gt;
&lt;br /&gt;
If you need more fine grained control over the keyboard, you can make use of &#039;&#039;Scan Codes&#039;&#039;. The keyboard sends a scan code to the operating system whenever a key is pressed or released. &lt;br /&gt;
Microsoft provides a list of the scan codes it supports [https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-6.0/aa299374(v=vs.60)].&lt;br /&gt;
[&#039;&#039;Press Key By Scan Code&#039;&#039;] sends a signal to Windows that a key with a given scan code has been pressed (and is held down). The matching [&#039;&#039;Release Key By Scan Code&#039;&#039;] sends Windows the adverse signal.&lt;br /&gt;
Please note that a key that is pressed, stays pressed until it is explicitly released. If you want to just press and release a key by scan code, use [&#039;&#039;Type Key By Scan Code&#039;&#039;].&lt;br /&gt;
&lt;br /&gt;
=== Mouse ===&lt;br /&gt;
The plugin provides blocks manipulating the mouse in three ways: &#039;&#039;Clicking&#039;&#039;, &#039;&#039;Moving&#039;&#039;, and interacting with its &#039;&#039;Buttons&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Recording and Taking Screenshots ==&lt;br /&gt;
&lt;br /&gt;
= Frequently Asked Questions =&lt;br /&gt;
&lt;br /&gt;
== Some elements are not presented in the UI browser&#039;s tree ==&lt;br /&gt;
This happens if the application &amp;quot;draws&amp;quot; elements (such as checkboxes, buttons or text) without using Windows widgets and without providing proper automation support (btw: which a well behaved application should, because this also affects/prevents usability and makes these controls inaccessable to eg. users with vision disabilities).&lt;br /&gt;
We encountered such in table-views containing checkboxes (probably OLE embedded database-tables).&lt;br /&gt;
These elements must be addressed either via coordinates (relative to the containing parent element), or via an image search (grab and define the image in the GUI browser). Both have disadvantages and are inconvenient, but there is no other technical solution. &lt;br /&gt;
&lt;br /&gt;
== What is the difference between Click/Invoke/Select/Toggle? ==&lt;br /&gt;
Click sends a click event; Invoke calls directly into the application&#039;s or widget&#039;s event handler; Select and Toggle usually call the corresponding automation functions (if the app-programmer provided that).&lt;br /&gt;
&lt;br /&gt;
A click generates a click event to the widget; may disfunction if the widget is invisible or covered (eg. by a tooltip).&lt;br /&gt;
&lt;br /&gt;
An invoke skips over the event mechanism and calls the event hander directly. It may also not work, if the event handler insists on keyboard focus, mouse position, shift- or ctrl-key or other state.&lt;br /&gt;
&lt;br /&gt;
There exists no mechanism which work with any application: for some, you will have to record a mouse-move and/or a set-focus for the click to work. &lt;br /&gt;
If possible, disable tooltips and other automatically appearing popups in the target app.&lt;br /&gt;
&lt;br /&gt;
If none works, try the click at screen position action (which generates a real mouse-click, not via UI-automation to the widget, but via the Windows Event Queue). This should work in any case, but suffers most from popups, mouse position and keyboard focus.&lt;br /&gt;
&lt;br /&gt;
== My element supports a certain pattern but blocks of that pattern don&#039;t work ==&lt;br /&gt;
&lt;br /&gt;
== I have designed custom elements, how can I automate them? ==&lt;br /&gt;
&lt;br /&gt;
== I have extended my GUI elements to have custom properties, how can I query them? ==&lt;br /&gt;
&lt;br /&gt;
== Hotkey &amp;quot;Get hovered element&amp;quot; selects the wrong element in the tree ==&lt;br /&gt;
&lt;br /&gt;
Sometimes there are elements which overlap or hide other elements. This element is then selected in the tree. In this case, you can use the Hotkey &amp;quot;Get focused element&amp;quot; to select the element in the tree&lt;br /&gt;
&lt;br /&gt;
== DevExpress controls are not visible in the GUI Browser ==&lt;br /&gt;
&lt;br /&gt;
DevExpress has some possibilities to disable UIAutomation support, which is also used by expecco.If you can&#039;t see one or some controls, please check e.g. https://supportcenter.devexpress.com/ticket/details/bc4069/devexpress-controls-now-clear-ui-automation-peers-for-the-application and other information on the DevExpress Support Site.&lt;br /&gt;
&lt;br /&gt;
== Connect fails with &amp;quot;Permission Denied&amp;quot; ==&lt;br /&gt;
Some apps required admin access rights to connect to.&lt;br /&gt;
You will get a &amp;quot;failed to connect&amp;quot; error and a walkback which looks like:&lt;br /&gt;
&lt;br /&gt;
 Could not connect to application: wireguard&lt;br /&gt;
 System.ComponentModel.Win32Exception (0x80004005): Access denied&lt;br /&gt;
  bei System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited)&lt;br /&gt;
  bei System.Diagnostics.NtProcessManager.GetModuleInfos(Int32 processId, Boolean firstModuleOnly)&lt;br /&gt;
  bei System.Diagnostics.NtProcessManager.GetFirstModuleInfo(Int32 processId)&lt;br /&gt;
  bei System.Diagnostics.Process.get_MainModule()&lt;br /&gt;
  bei FlaUI.Core.WindowsAPI.WindowsApiTools.GetMainModuleFilepath(Process process)&lt;br /&gt;
  bei FlaUI.Core.Application.Attach(Process process)&lt;br /&gt;
  bei WindowsAutomation.Application..ctor(String name, UIA3Automation automation, PropertyRepository propertyRepository, String windowTitle)&lt;br /&gt;
  bei WindowsAutomation.Client.GetApplication(String name, String windowTitle)&lt;br /&gt;
&lt;br /&gt;
You have two options:&lt;br /&gt;
* run expecco as admin&lt;br /&gt;
* start a dotNet-bridge manually as admin (in the local or remote machine):&lt;br /&gt;
    ...\bridgeFramework\dotNetBridge\dotNetBin&amp;gt;DotNetBridgeServer.exe -k -s -a 0.0.0.0 -p 34319 &lt;br /&gt;
: then create a &amp;quot;remote connection&amp;quot; to it.&lt;br /&gt;
&lt;br /&gt;
== Execution of GUI Actions blocks after Mouse Down ==&lt;br /&gt;
UI Automation is blocking further execution of some blocks after a mouse button &amp;lt;Press&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Unable to interact with application (SUT) after Startup  ==&lt;br /&gt;
In some cases - e.g. starting the test via Jenkins - the application (SUT) is not in the correct state after startup. You can&#039;t find elements and/or actions fail. &lt;br /&gt;
You can try to send &amp;quot;[WA]Window - Normalize&amp;quot; with the path of the window to solve this&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=WindowsAutomation_Reference_2.0/en&amp;diff=30906</id>
		<title>WindowsAutomation Reference 2.0/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=WindowsAutomation_Reference_2.0/en&amp;diff=30906"/>
		<updated>2026-02-23T11:48:34Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 29.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is the documentation for the Windows Automation 2.0 plugin.&lt;br /&gt;
It provides facilities to automate tests incorporating applications with a GUI based on Windows Presentation Foundation (WPF), WinForms, and the old Win32 API.&lt;br /&gt;
&lt;br /&gt;
Notice:&amp;lt;br&amp;gt;The vsn2 replaces the previous vsn1 plugin, which is no longer maintained.&lt;br /&gt;
The change was necessary due to changes in the Windows operating system, and features which were discontinued by Microsoft.&lt;br /&gt;
The vsn2 plugin uses Microsoft&#039;s UI-Automation2 API to interact with the application.&lt;br /&gt;
This API was not avaliable in Windows-XP, Vista and other older OS versions, and many features used by the previous version are no longer supported in newer OS versions, or need different parameters.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
*Automated GUI testing of WPF, WinForms, and Win32 applications.&lt;br /&gt;
*Contains an expecco block library and tools which help to model tests and inspect the GUI of the application.&lt;br /&gt;
*Parallel remote test-execution on multiple systems.&lt;br /&gt;
*Performs tests against already built executables. No source code changes / recompilation of the application is required.&lt;br /&gt;
*Access to GUI components using XPath locators.&lt;br /&gt;
*Access objects of the application live at execution time.&lt;br /&gt;
*Full access to keyboard and mouse of the target system.&lt;br /&gt;
*Lots of additional features such as screen capturing, taking screenshots, highlighting GUI elements, mouse tracking, ...&lt;br /&gt;
&lt;br /&gt;
= Known issues in the current Release 19.1.0 =&lt;br /&gt;
* The WindowsAutomation2.ets library has got a new functional id. When reimporting the library in existing Pre-19.1.0 test suites (which is mandatory), a warning about a changed functional id is shown once. It is ok to accept this dialog.&lt;br /&gt;
* Instant follow mouse is very expensive in Windows and is therefore disabled. Use &#039;&#039;HotKeys&#039;&#039; to select a GUI element in the tree at the current pointer position or to update the element tree. HotKeys can be configured in the settings. The HotKey-service has to be started. Take care that the keys have not already been grabbed by another application. If that is the case, a warning will be shown, and you should either make sure that expecco is started before the other application, or that you use other hotkey combinations (in either expecco or the application).&lt;br /&gt;
= Limitations =&lt;br /&gt;
* WindowsAutomation only supports XPath1.0.&lt;br /&gt;
: That means for example, that the &amp;quot;ends-with&amp;quot; function, which is an XPath2 function, is not supported and thus not possible as XPath attribute filter.&lt;br /&gt;
: See [[https://en.wikipedia.org/wiki/XPath_2.0#Function_library XPath vs. XPath2]] for details. For some (especially &amp;quot;ends-with&amp;quot;) there are workarounds by comparing against a substring which is based on the length of the attribute string or a regex match (see [https://stackoverflow.com/questions/40934644/xpath-testing-that-string-ends-with-substring]). &lt;br /&gt;
: Notice, that this is a limitation of the Windows operating system, which cannot be worked around in expecco.&lt;br /&gt;
&lt;br /&gt;
=Installation and Connection=&lt;br /&gt;
The WindowsAutomation testing plugin uses the expecoo &amp;quot;.NET-Bridge&amp;quot; which consists of two parts: A plugin for expecco, and a server executable using the .NET framework running on the remote computer to connect to.&lt;br /&gt;
&lt;br /&gt;
==Requirements==&lt;br /&gt;
On the machine running the system under test:&lt;br /&gt;
*.NET Framework 4.7 [https://www.microsoft.com/net/download/all] or higher.&lt;br /&gt;
* One of the following operation systems:&lt;br /&gt;
::- Windows 7 SP1&lt;br /&gt;
::- Windows 8&lt;br /&gt;
::- Windows 8.1&lt;br /&gt;
::- Windows 10&lt;br /&gt;
::- Windows 11&lt;br /&gt;
&lt;br /&gt;
::- Windows Server 2012 R2&lt;br /&gt;
::- Windows Server 2016&lt;br /&gt;
::- Windows Server 2019&lt;br /&gt;
::- Windows Server 2022&lt;br /&gt;
&lt;br /&gt;
==Plugin Components==&lt;br /&gt;
The plugin consists of the following parts:&lt;br /&gt;
* The [[GUI Browser]], used to interactively explore your application.&lt;br /&gt;
* The Windows Automation Library, which provides blocks that you can use in your test cases.&lt;br /&gt;
* The .NET-Bridge server, which provides an interface between the application under test and expecco.&lt;br /&gt;
&lt;br /&gt;
==Installing and Configuring the Plugin in Expecco==&lt;br /&gt;
The plugin is usually installed automatically by the installer; either included in the main expecco installation or provided as a separate installable add-on package. Its files are stored in the &amp;quot;&amp;lt;code&amp;gt;plugin&amp;lt;/code&amp;gt;&amp;quot; subfolder of the expecco installation folder. You can also copy those files manually to that folder, if required. Expecco detects the plugin automatically during startup. You may have to restart your expecco session, if the plugin is installed later.&lt;br /&gt;
&lt;br /&gt;
==Preparing a local system for test execution==&lt;br /&gt;
To automate applications running on the SAME host as expecco, there is no need to set up anything - it should work out of the box.&lt;br /&gt;
&lt;br /&gt;
Try to connect to an application via the GUIBrowser&#039;s &#039;&#039;WindowsAutomation&#039;&#039;-connect dialog:&lt;br /&gt;
&lt;br /&gt;
[[Datei:WindowsAutomation2Connect.png]]&lt;br /&gt;
&lt;br /&gt;
==Preparing a remote system for test execuction==&lt;br /&gt;
&lt;br /&gt;
===Security Considerations===&lt;br /&gt;
Please make sure, that remote access is only possible from inside a secure local network.&lt;br /&gt;
Under no circumstances should you grant access to the DotNetBridgeServer from untrusted hosts.&lt;br /&gt;
&lt;br /&gt;
===DotNet Bridge Server===&lt;br /&gt;
&lt;br /&gt;
The remote system has to run the &amp;quot;&#039;&#039;.Net-Bridge server&#039;&#039;&amp;quot; which in turn either actively connects to expecco or passively waits for an incoming connection from expecco.&lt;br /&gt;
&lt;br /&gt;
For this, copy &amp;quot;&amp;lt;code&amp;gt;DotNetBridgeServer.exe&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;DotNetBridge.dll&amp;lt;/code&amp;gt;&amp;quot; (found in the &amp;quot;&amp;lt;code&amp;gt;packages/exept/bridgeFramework/dotNetBridge/dotNetBin&amp;lt;/code&amp;gt;&amp;quot; folder under the expecco installation directory) to the computer where your system under test is running (you can copy it into any folder). No further installation is needed.&lt;br /&gt;
&lt;br /&gt;
To start the bridge, navigate to the executable in a shell/cmd/console and start it with the following arguments&lt;br /&gt;
(&amp;quot;&amp;lt;code&amp;gt;DotNetBridgeServer.exe --help&amp;lt;/code&amp;gt;&amp;quot; outputs a list of valid options):&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Arguments !! Required !! Description&lt;br /&gt;
|-&lt;br /&gt;
| -s || Yes || &amp;quot;&#039;&#039;server mode&#039;&#039;&amp;quot;. Tells the executable to run in server mode (it will wait for expecco to connect to it, as opposed to client mode,&amp;lt;br&amp;gt;where it actively connects to the partner).&lt;br /&gt;
|-&lt;br /&gt;
| -k || Yes || &amp;quot;&#039;&#039;keepalive&#039;&#039;&amp;quot;. Tells the client to keep the connection open after a connection has been terminated.&amp;lt;br&amp;gt;This saves you the hassle to restart it every time a test finishes.&lt;br /&gt;
|-&lt;br /&gt;
| -a&amp;amp;nbsp;&amp;lt;ip/hostname&amp;gt;|| Yes || &amp;quot;&#039;&#039;IP address accepting connections&#039;&#039;&amp;quot;. The IP-address or hostname of an interface on the host on which connections will be accepted (in server mode) or to which it connects (in client mode).&amp;lt;br&amp;gt;If you have multiple network interfaces, you can ensure that only incoming connections on the secure network will be accepted by setting the IP address of this interface.&amp;lt;br&amp;gt;To allow incoming connections on any network interface (i.e. to have it listen on any IP-address), set it to 0.0.0.0. If you are not inside a secure network, you should use a secure tunnel (e.g. a SSH or Powershell tunnel) between the machine running expecco and the machine running the bridge and listen only on 127.0.0.1 (the default).&lt;br /&gt;
|-&lt;br /&gt;
| -p &amp;lt;int&amp;gt; || No || &amp;quot;&#039;&#039;port&#039;&#039;&amp;quot;. The port the server should listen on (in server mode) or to which is should connect (default is 34318).&lt;br /&gt;
|-&lt;br /&gt;
| -L &amp;lt;string&amp;gt; || No || &amp;quot;&#039;&#039;assembly&#039;&#039;&amp;quot;. Load a .NET assembly on startup. Omit the .dll extension (so use &amp;quot;WindowsAutomation&amp;quot; but not &amp;quot;WindowsAutomation.dll&amp;quot;).&amp;lt;br&amp;gt;You can repeat this option to load multiple assemblies. &lt;br /&gt;
Note: this is not normally needed, as expecco loads the required assemblies automatically into the bridge.&amp;lt;br&amp;gt;However, if security settings forbid external assemblies, you have to copy them to the target machine, and load them via command line option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
So you may execute on the remote host:&lt;br /&gt;
&lt;br /&gt;
    DotNetBridgeServer.exe -s -k -a 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
For automatic tests, you must setup the target system for the bridge server to be running; either by adding it to some &amp;quot;auto exec&#039; script, or by adding to the &amp;quot;scheduled tasks&amp;quot;, or by remote starting it from your test-host via a powershell script, remote ssh command or similar.&lt;br /&gt;
&lt;br /&gt;
If you get an &amp;quot;Assembly not Found&amp;quot; error, you may have an incompatible .NET framework or the &amp;quot;DotNetBridge.dll&amp;quot; is missing. If you get a network error, or the expecco-host cannot connect, make sure that your firewall settings allow access to the given ports (you may try an alternative port like 8080, which must then be specified on both sides).&lt;br /&gt;
&lt;br /&gt;
=Settings=&lt;br /&gt;
There are currently no configurable settings.&lt;br /&gt;
&lt;br /&gt;
=GUI Browser=&lt;br /&gt;
The GUI browser is used to explore a running application. You can browse the application, inspect element properties and execute actions. See &amp;quot;[[GUI Browser| Expecco GUI Tests Extension Reference]]&amp;quot; for details.&lt;br /&gt;
&lt;br /&gt;
=Library=&lt;br /&gt;
This article gives a short overview over the design philosophy of the library. You can find more detailed documentation and examples attached to the blocks itself.&lt;br /&gt;
&lt;br /&gt;
== Connect to Application vs. Connect to Screen ==&lt;br /&gt;
You can either &amp;quot;connect to a single application&amp;quot;, or &amp;quot;connect to the screen&amp;quot;.&lt;br /&gt;
The first provides faster access to the components, but will not work, if the app creates subprocesses with a GUI (eg. for dialogs or additional windows). There exist also applications which always create a subprocess, even for the main GUI.&lt;br /&gt;
&lt;br /&gt;
For such applications, you have to &amp;quot;connect to the screen&amp;quot;, and provide an additional window-reference in the XPath locator.&lt;br /&gt;
&amp;lt;br&amp;gt;You must also use a screen connection, if your test contains interactions between multiple top-level windows, for example a drag&amp;amp;drop between windows.&lt;br /&gt;
&lt;br /&gt;
== Connecting to an Application ==&lt;br /&gt;
To automate an application, you first have to connect to it or to its screen. You can do this with the&lt;br /&gt;
blocks from the &amp;quot;&#039;&#039;Connecting&#039;&#039;&amp;quot; group.&lt;br /&gt;
[[Bild:WindowsAutomation2_Library_ConnectingBlocks.PNG|frame|The Library&#039;s Connection Blocks (old picture without screen connection blocks).]]&lt;br /&gt;
&lt;br /&gt;
You can connect to an individual application by its &#039;&#039;executable name&#039;&#039;, or by its &#039;&#039;process id&#039;&#039;. &lt;br /&gt;
If you use the executable name, expecco will attach to the main process of the specified executable.&lt;br /&gt;
Be careful as this is not necessarily the process drawing the GUI! &lt;br /&gt;
Use the process id if an application spawns more than one process and you need to make sure you connect to the GUI process and not some background process.&lt;br /&gt;
&lt;br /&gt;
All connection blocks also require you to specify a &#039;&#039;name&#039;&#039; by which the connection should be known in future.&lt;br /&gt;
This is needed when you automate multiple applications at the same time and need to change&lt;br /&gt;
&#039;&#039;connection contexts&#039;&#039; during test execution.&lt;br /&gt;
Please note that the application to connect to has to be started before the corresponding connection block is executed.&lt;br /&gt;
You can change in context of which connection a block is executed with the [&#039;&#039;Set Active Connection&#039;&#039;] block.&lt;br /&gt;
This allows you, for example, to automate and compare the state of applications running on multiple systems in one test case.&lt;br /&gt;
&lt;br /&gt;
=== Establishing a Local Connection === &lt;br /&gt;
To automate an application running on the same host as expecco, there is no need to set up anything. &lt;br /&gt;
Use &amp;quot;[&#039;&#039;Create Local Connection&#039;&#039;]&amp;quot; with the above mentioned parameters.&lt;br /&gt;
&lt;br /&gt;
=== Establishing a Remote Connection ===&lt;br /&gt;
Make sure that the DotNet-Bridge server (&amp;quot;&amp;lt;code&amp;gt;DotNetBridgeServer.exe&amp;lt;/code&amp;gt;&amp;quot;) is running on the remote system, as explained in the chapter [[#Preparing a remote system for test execuction|&amp;quot;&#039;&#039;Preparing a remote system for test execuction&#039;&#039;&amp;quot;]]&lt;br /&gt;
When the bridge is running, you can connect to it with the &amp;quot;[&#039;&#039;Create Remote Connection&#039;&#039;]&amp;quot; block using the hostname and IP-Address you specified when you started the bridge.&lt;br /&gt;
&lt;br /&gt;
Notice, that the DotNet-Bridge server only accepts local connections by default.&lt;br /&gt;
This is done for security reasons. Use the &amp;quot;-a x.x.x.x&amp;quot; command line argument to specify, which hosts are allowed&lt;br /&gt;
to connect. With &amp;quot;-a 0.0.0.0&amp;quot;, any host is allowed. Do NOT use this, if the remote host is reachable from untrusted hosts.&lt;br /&gt;
&lt;br /&gt;
=== Closing a Connection ===&lt;br /&gt;
Remember to always close a connection when it is no longer needed, as it otherwise needlessly consumes resources.&lt;br /&gt;
One simple way to do this is to setup your connection in the &amp;quot;&#039;&#039;Before Execution&#039;&#039;&amp;quot; (pre-action) part of the test suite or test case,&lt;br /&gt;
and put the &amp;quot;[&#039;&#039;Close All Connections&#039;&#039;]&amp;quot; action block in the &amp;quot;&#039;&#039;After exeuction&#039;&#039;&amp;quot; (post-action) part.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Accessing GUI Elements ==&lt;br /&gt;
[[Bild:WindowsAutomation_Library_AccessBlocks.PNG|frame|The Library&#039;s GUI Element Access Blocks.]]&lt;br /&gt;
[[Bild:WindowsAutomation_Library_AccessBlocksExamples.PNG|frame|A Few Examples on How to Access Elements in Notepad.]]&lt;br /&gt;
[[Bild:WindowsAutomation_Library_AccessBlocksModes.PNG|frame|Different Ways to Reference a GUI Element.]]&lt;br /&gt;
All Windows applications are built as a &#039;&#039; tree&#039;&#039;  of &#039;&#039; GUI elements&#039;&#039;.&lt;br /&gt;
Some elements act as container of other element - their children. Tables, for example, are containers&lt;br /&gt;
for their cell elements which themselves might contain text labels.&lt;br /&gt;
At the root of the tree are one or more &#039;&#039;windows&#039;&#039; . When you connect to an application, you get access to&lt;br /&gt;
all windows at the tree&#039;s root.&lt;br /&gt;
To manipulate any of the system under test&#039;s GUI element, you first have to gain access to it.&lt;br /&gt;
The group named &amp;quot;&#039;&#039;GUI Element Access&#039;&#039;&amp;quot; provides action blocks to access elements. The actions are further categorized into sub-groups named &amp;quot;&#039;&#039; Access By XPath&#039;&#039;&amp;quot; , &amp;quot;&#039;&#039;Access By Property&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;Existence Test&#039;&#039;&amp;quot; etc. &lt;br /&gt;
For each category, blocks with the same interface exist. The only difference is the method of retrieval.&lt;br /&gt;
&lt;br /&gt;
;Get GUI Element : returns a &#039;&#039;single&#039;&#039; GUI element matching the search condition. If multiple elements match the condition, an &#039;&#039;arbitrary&#039;&#039; element matching the condition is returned.&lt;br /&gt;
:To make sure that there is only one single element matching, set &#039;&#039;ensureExclusive&#039;&#039;  to true. You can also enforce this globally by setting the environment variable &amp;quot;&#039;&#039;ensureExclusive&#039;&#039;&amp;quot; in your environment. &lt;br /&gt;
:If ensureExclusive is set and more than one element is found, the block will fail and notify about the ambiguity. This is disabled by default, as checking for uniqueness is a very costly (ie. slow) operation.&lt;br /&gt;
:You can also specify a &#039;&#039;timeout&#039;&#039; after which the search is aborted. This is useful if you know an element should be there already (or soon but might currently be loading).&lt;br /&gt;
&lt;br /&gt;
;Get GUI Elements: returns &#039;&#039;all&#039;&#039; GUI elements matching the search condition. If no element is found, it returns an empty list &#039;&#039;Timeout&#039;&#039; and &#039;&#039;cacheXPath&#039;&#039; are also applicable.&lt;br /&gt;
&lt;br /&gt;
;Exists: Works exactly the same as &#039;&#039;Get GUI Element&#039;&#039; but does not fail if no element is found. Additionally provides an output pin specifying if an element has been found.&lt;br /&gt;
&lt;br /&gt;
Both of these blocks are also available in the &amp;quot;&#039;&#039;Relative To Anchor&#039;&#039;&amp;quot; variety. Those blocks also take a GUI Element as &#039;&#039;anchor&#039;&#039; in relation to which they search. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using XPaths ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;XPath&#039;&#039;&#039; is the query language used to select GUI elements in the application&#039;s element tree.&lt;br /&gt;
You can find the XPath of an element with the [[Expecco GUI Tests Extension Reference/en|Gui Browser]] or with third-party applications like &amp;quot;Inspect.exe&amp;quot; [https://msdn.microsoft.com/en-us/library/dd318521(v=vs.85).aspx] or &amp;quot;FlaUInspect&amp;quot; [https://github.com/FlauTech/FlaUInspect].&lt;br /&gt;
&amp;lt;br&amp;gt;As an example, the full &#039;&#039;XPath&#039;&#039; of the scroll button on the &lt;br /&gt;
vertical scrollbar in the german Windows &amp;quot;Notepad.exe&amp;quot; application looks like this:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;code&amp;gt;/Window[@Name=&#039;Unbenannt - Editor&#039;]/Document[@Name=&#039;Text-Editor&#039;]/ScrollBar[@Name=&#039;Vertikale Bildlaufleiste&#039;]/Button[@Name=&#039;Bildlauf nach unten&#039;] &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For each level in the GUI tree, a new &#039;&#039;Location Step&#039;&#039; containing the child element&#039;s &#039;&#039;Control Type&#039;&#039; was added in the above XPath.&lt;br /&gt;
&amp;lt;br&amp;gt;You do not have to use any predicates, the following XPath is valid as well:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;code&amp;gt;/Window/Document/ScrollBar/Button &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
but might lead to issues if multiple GUI Elements match this path.&lt;br /&gt;
&lt;br /&gt;
You can select by three predicates (which can be mixed and matched in the same query):&lt;br /&gt;
&lt;br /&gt;
; Name: the name the application developer has given an element. Be careful as this name might change during programm execution (See for example Notepad&#039;s window name which always begins with the name of the currently opened file).&lt;br /&gt;
:  &amp;lt;code&amp;gt;/Window[@Name=&#039;Unbenannt - Editor&#039;] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
; AutomationId: An ID the application developer has given an element. It is meant to be unique between siblings but that is not enforced on lazy or incompetent programmers.&lt;br /&gt;
: Many lazy developers leave the ID empty or reuse it, making it useless.&lt;br /&gt;
: You should use this ID wherever applicable as it is static and meant for this exact purpose.&lt;br /&gt;
:  &amp;lt;code&amp;gt;/Window/Document[@AutomationId=&#039;15&#039;] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;List Index: If there are multiple siblings with the same Control Type, you can select one of them by (1-based) list index.&lt;br /&gt;
:  &amp;lt;code&amp;gt;/Window[1]/Document[1] &amp;lt;/code&amp;gt;&lt;br /&gt;
:  &amp;lt;code&amp;gt;/Window[1]/Document[last()] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Warning there are XPath Limitations ===&lt;br /&gt;
&#039;&#039;&#039;Please Note&#039;&#039;&#039;: You can ONLY use the three predicates above in your XPaths.&lt;br /&gt;
&amp;lt;br&amp;gt;Other predicates &#039;&#039;&#039;DO NOT&#039;&#039;&#039; work! &lt;br /&gt;
&amp;lt;br&amp;gt;To search for an element by another property (e.g. its help text), use the &#039;&#039;&#039;By Property&#039;&#039;&#039; variant of the block instead. &lt;br /&gt;
If the property is not unique, you can select a unique ancestor of the target by property or XPath relative to which the property is unique.&lt;br /&gt;
You can then use that ancestor as anchor in the [&#039;&#039;Get GUI Element By Property (Relative to Anchor)&#039;&#039;] block.&lt;br /&gt;
&lt;br /&gt;
=== Using Wildcards in XPaths ===&lt;br /&gt;
&lt;br /&gt;
XPath also supports &#039;&#039;&#039;wildcards&#039;&#039;&#039;. You can:&lt;br /&gt;
* replace &#039;&#039;&#039;one tree level&#039;&#039;&#039; with a &amp;quot;*&amp;quot; wildcard: &lt;br /&gt;
: &amp;lt;code&amp;gt;/Window/Document[@AutomationId=&#039;15&#039;]/*/Button[1]&amp;lt;/code&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;/*/*/*/Button[1] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
* replace a &#039;&#039;&#039;control type&#039;&#039;&#039; with a &amp;quot;*&amp;quot; wildcard:&lt;br /&gt;
: &amp;lt;code&amp;gt;/Window/*[@AutomationId=&#039;15&#039;] &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
* replace &#039;&#039;&#039;an arbitrary amount of levels&#039;&#039;&#039; with a &amp;quot;//&amp;quot; wildcard:&lt;br /&gt;
: &amp;lt;code&amp;gt;//Button &amp;lt;/code&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;/Window//Button[1] &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Especially the last option is useful as it makes your tests more readable, in that the reader can easily focus on the relevant parts of the xpath.&lt;br /&gt;
&lt;br /&gt;
But be careful: using wildcards comes at a steep performance cost (due to the implementation inside the Windows API). &lt;br /&gt;
If your test runs unacceptably slow, first try to remove wildcards where they are not needed.&lt;br /&gt;
&lt;br /&gt;
=== Using Properties===&lt;br /&gt;
&lt;br /&gt;
You can also search for elements by property; i.e. by specifying a value an element&#039;s property with the given name must have. &lt;br /&gt;
&lt;br /&gt;
For a list of properties a GUI element might have, take a look at Microsoft&#039;s documentation [https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-control-patterns-overview#control-pattern-classes-and-interfaces].&lt;br /&gt;
&lt;br /&gt;
=== XPath Resolution in Action Blocks ===&lt;br /&gt;
&lt;br /&gt;
Xpath resolution may be slow in the Windows Automation API, depending on the number of windows/elements which have to be checked.&lt;br /&gt;
&lt;br /&gt;
To speed up test execution, you should reuse a resolved XPath if possible.&lt;br /&gt;
For this, use the &amp;quot;Get Element by XPath&amp;quot; action, and feed the &amp;quot;element handle&amp;quot; to multiple actions.&lt;br /&gt;
All action- and property access blocks can take either an XPath or an element handle as locator input.&lt;br /&gt;
&lt;br /&gt;
The image on the right shows this mode in action. Variants 1 and 2 are functionally equivalent.&lt;br /&gt;
While Variant 2 is more concise, Variant 1 is the right choice in most cases. While it has an additional block, you have control over the other input parameters. &lt;br /&gt;
You also can recycle the GUI element reference as seen in 3). This is invaluable as the XPath only has to be resolved once. This speeds up test execution by a lot as XPath resolution is very expensive operation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rule of thumb&#039;&#039;&#039;: Always use Variant 1 except if you need the reference to the GUI element only once, or if the application replaces the element dynamically.&lt;br /&gt;
&lt;br /&gt;
=== Separating Path Definitions ===&lt;br /&gt;
&lt;br /&gt;
It is highly recommended to add definitions for element-paths into an environment (typically the project environment), and use &amp;quot;Environment Value&amp;quot; references as input to the steps. This gives two benefits:&lt;br /&gt;
&lt;br /&gt;
* the paths are hidden and the values at the steps become more readable&lt;br /&gt;
* your tests are easier to maintain: in case of a changed window layout/structure, only the variable definitions need to be changed at one place.&lt;br /&gt;
* you can import those definitions from a CSV or XML file, and thus separate the locators from the actual test suite. In case of changed UI-layout / UI-hierarchy after a revision change of the tested application, all you need is a new excel or xml file containing those definitions.  &lt;br /&gt;
&lt;br /&gt;
If the development team of the application can provide the paths of the UI components in a machine readable form (i.e. CVS or XML file), you may even let expecco read and parse those path definitions at test start time, and let it automatically adapt to any change. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interacting with GUI Elements ==&lt;br /&gt;
Once you retrieved a GUI element, you can interact with it by making use of the library&#039;s blocks located in the groups &#039;&#039;&#039;Elements&#039;&#039;&#039;, &#039;&#039;&#039;Patterns&#039;&#039;&#039;, and &#039;&#039;&#039;Properties&#039;&#039;&#039;. &lt;br /&gt;
Blocks in those categories take a GUI Element (and sometimes additional data) as input and manipulate it or query for its properties in some way.&lt;br /&gt;
&lt;br /&gt;
[[Bild:WindowsAutomation_Library_ElementsPatternsProperties.png|600px|The Library&#039;s Blocks for Interacting With Elements.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The &#039;Elements&#039; Group ===&lt;br /&gt;
&lt;br /&gt;
This group contains blocks that are applicable to blocks that only work on GUI elements of a specific type. For a block&#039;s detailed description with examples ,&lt;br /&gt;
take a look at the block&#039;s documentation in expecco.&lt;br /&gt;
&lt;br /&gt;
Even though not only Checkboxes can be &#039;checked&#039;, the [&#039;&#039;Check&#039;&#039;] block in the &amp;quot;&#039;&#039;Checkbox group&#039;&#039;&amp;quot; only works for checkboxes and not e.g. for radio buttons. &lt;br /&gt;
Because of this limitation there are not that many blocks targeting specific elements. Most blocks target a specific &#039;&#039;pattern&#039;&#039; instead and are therefore in the &amp;quot;&#039;&#039;Patterns&#039;&#039;&amp;quot; group.&lt;br /&gt;
&lt;br /&gt;
=== The &#039;Patterns&#039; Group ===&lt;br /&gt;
&lt;br /&gt;
This group contains blocks that are applicable to GUI elements supporting a certain &#039;&#039;pattern&#039;&#039;. &lt;br /&gt;
Patterns describe how a GUI element &#039;&#039;behaves&#039;&#039; rather than what it &#039;&#039;is&#039;&#039;. An element can also support multiple patterns at the same time. &lt;br /&gt;
You can find out which patterns an element supports with the [&#039;&#039;Get Supported Patterns&#039;&#039;] block or by taking a look at Microsoft&#039;s documentation about patterns [https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-control-patterns-overview].&lt;br /&gt;
&lt;br /&gt;
Pattern blocks can therefore be &#039;&#039;re-used&#039;&#039; between GUI elements of different types. &lt;br /&gt;
For example, the [&#039;&#039;Expand&#039;&#039;] block in &amp;quot;&#039;&#039;ExpandCollapse pattern&#039;&#039;&amp;quot;, can be used to expand Comboboxes, Menus, Submenus, or Trees.&lt;br /&gt;
&lt;br /&gt;
=== The &#039;Properties&#039; Group ===&lt;br /&gt;
&lt;br /&gt;
Blocks in the &amp;quot;&#039;&#039;Patterns&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Elements&#039;&#039;&amp;quot; group already allow you to query the value of properties pertaining to that element or pattern. Blocks in the &amp;quot;&#039;&#039;Properties&#039;&#039;&amp;quot; group allow you to query both properties which all elements share as well as arbitrary properties. If you try to retrieve a property an element does not support, the block will fail.&lt;br /&gt;
&lt;br /&gt;
Please note that the [&#039;&#039;Get Arbitrary Property&#039;&#039;] block can only query for properties that belong to a pattern. You cannot, for example, query &amp;quot;Text&amp;quot; from a textfield as this is not a property, use &amp;quot;Value&amp;quot; of the value pattern instead. Microsoft&#039;s documentation has a list of patterns and the properties they provide [https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-control-patterns-overview#control-pattern-classes-and-interfaces]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Automating Keyboard and Mouse ==&lt;br /&gt;
[[Bild:WindowsAutomation_Library_KeyboardMouse.png|400px|The Library&#039;s Blocks for Interacting With Keyboard and Mouse.]]&lt;br /&gt;
&lt;br /&gt;
You can control keyboard and mouse with action blocks in the &amp;quot;&#039;&#039;Keyboard&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Mouse&#039;&#039;&amp;quot; groups, as shown on the right. In contrast to the blocks above, which work in context of a GUI element, the keyboard and mouse blocks work on a global level. You therefore do not need to provide a GUI element when using them. &lt;br /&gt;
&lt;br /&gt;
You might want to execute some blocks in context of a GUI elemenet nontheless (e.g. enter a number into a text field instead of just pressing keys while the application is running). You can achieve this by selecting the element with the mouse beforehand as you would do when using the application normally (use the [&#039;&#039;Left/Double/Right Click On Element&#039;&#039;] blocks for this).&lt;br /&gt;
If you do not want to wait for the mouse to move, you can also use the [&#039;&#039;Set Focus&#039;&#039;] block instead.&lt;br /&gt;
&lt;br /&gt;
=== Keyboard ===&lt;br /&gt;
The plugin provides blocks to interact with the keyboard on different abstraction levels. The most versatile block is [&#039;&#039;Type With Control Keys Pressed&#039;&#039;] where you can specify a string of characters to be typed while any number of control keys (e.g. &amp;quot;esc&amp;quot;, &amp;quot;alt&amp;quot;, &amp;quot;shift&amp;quot;, &amp;quot;ctrl&amp;quot;, ...) are held down. All other blocks are specializations of this block.&lt;br /&gt;
&lt;br /&gt;
[&#039;&#039;Press Control Keys&#039;&#039;] e.g. allows you to enter key commands such as renaming files (&amp;quot;ALT+F2&amp;quot;), starting the task manager (&amp;quot;CTRL+ALT+DEL&amp;quot;), or closing a window (&amp;quot;ALT+F4&amp;quot;). [&#039;&#039;Press Control Key&#039;&#039;] makes it easy to just press a single key (e.g. &amp;quot;RETURN&amp;quot; to start a new line in an edit box). The &amp;quot;&#039;&#039;Shortcuts&#039;&#039;&amp;quot; group provides an assorted collection of often used key combinations for your convenience.&lt;br /&gt;
&lt;br /&gt;
Use the [&#039;&#039;Type&#039;&#039;] action to just type some text, or if you just need some throwaway demo text, use [&#039;&#039;Type Random Phrase&#039;&#039;].&lt;br /&gt;
&lt;br /&gt;
If you need more fine grained control over the keyboard, you can make use of &#039;&#039;Scan Codes&#039;&#039;. The keyboard sends a scan code to the operating system whenever a key is pressed or released. &lt;br /&gt;
Microsoft provides a list of the scan codes it supports [https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-6.0/aa299374(v=vs.60)].&lt;br /&gt;
[&#039;&#039;Press Key By Scan Code&#039;&#039;] sends a signal to Windows that a key with a given scan code has been pressed (and is held down). The matching [&#039;&#039;Release Key By Scan Code&#039;&#039;] sends Windows the adverse signal.&lt;br /&gt;
Please note that a key that is pressed, stays pressed until it is explicitly released. If you want to just press and release a key by scan code, use [&#039;&#039;Type Key By Scan Code&#039;&#039;].&lt;br /&gt;
&lt;br /&gt;
=== Mouse ===&lt;br /&gt;
The plugin provides blocks manipulating the mouse in three ways: &#039;&#039;Clicking&#039;&#039;, &#039;&#039;Moving&#039;&#039;, and interacting with its &#039;&#039;Buttons&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Recording and Taking Screenshots ==&lt;br /&gt;
&lt;br /&gt;
= Frequently Asked Questions =&lt;br /&gt;
&lt;br /&gt;
== Some elements are not presented in the UI browser&#039;s tree ==&lt;br /&gt;
This happens if the application &amp;quot;draws&amp;quot; elements (such as checkboxes, buttons or text) without using Windows widgets and without providing proper automation support (btw: which a well behaved application should, because this also affects/prevents usability and makes these controls inaccessable to eg. users with vision disabilities).&lt;br /&gt;
We encountered such in table-views containing checkboxes (probably OLE embedded database-tables).&lt;br /&gt;
These elements must be addressed either via coordinates (relative to the containing parent element), or via an image search (grab and define the image in the GUI browser). Both have disadvantages and are inconvenient, but there is no other technical solution. &lt;br /&gt;
&lt;br /&gt;
== What is the difference between Click/Invoke/Select/Toggle? ==&lt;br /&gt;
Click sends a click event; Invoke calls directly into the application&#039;s or widget&#039;s event handler; Select and Toggle usually call the corresponding automation functions (if the app-programmer provided that).&lt;br /&gt;
&lt;br /&gt;
A click generates a click event to the widget; may disfunction if the widget is invisible or covered (eg. by a tooltip).&lt;br /&gt;
&lt;br /&gt;
An invoke skips over the event mechanism and calls the event hander directly. It may also not work, if the event handler insists on keyboard focus, mouse position, shift- or ctrl-key or other state.&lt;br /&gt;
&lt;br /&gt;
There exists no mechanism which work with any application: for some, you will have to record a mouse-move and/or a set-focus for the click to work. &lt;br /&gt;
If possible, disable tooltips and other automatically appearing popups in the target app.&lt;br /&gt;
&lt;br /&gt;
If none works, try the click at screen position action (which generates a real mouse-click, not via UI-automation to the widget, but via the Windows Event Queue). This should work in any case, but suffers most from popups, mouse position and keyboard focus.&lt;br /&gt;
&lt;br /&gt;
== My element supports a certain pattern but blocks of that pattern don&#039;t work ==&lt;br /&gt;
&lt;br /&gt;
== I have designed custom elements, how can I automate them? ==&lt;br /&gt;
&lt;br /&gt;
== I have extended my GUI elements to have custom properties, how can I query them? ==&lt;br /&gt;
&lt;br /&gt;
== Hotkey &amp;quot;Get hovered element&amp;quot; selects the wrong element in the tree ==&lt;br /&gt;
&lt;br /&gt;
Sometimes there are elements which overlap or hide other elements. This element is then selected in the tree. In this case, you can use the Hotkey &amp;quot;Get focused element&amp;quot; to select the element in the tree&lt;br /&gt;
&lt;br /&gt;
== DevExpress controls are not visible in the GUI Browser ==&lt;br /&gt;
&lt;br /&gt;
DevExpress has some possibilities to disable UIAutomation support, which is also used by expecco.If you can&#039;t see one or some controls, please check e.g. https://supportcenter.devexpress.com/ticket/details/bc4069/devexpress-controls-now-clear-ui-automation-peers-for-the-application and other information on the DevExpress Support Site.&lt;br /&gt;
&lt;br /&gt;
== Connect fails with &amp;quot;Permission Denied&amp;quot; ==&lt;br /&gt;
Some apps required admin access rights to connect to.&lt;br /&gt;
You will get a &amp;quot;failed to connect&amp;quot; error and a walkback which looks like:&lt;br /&gt;
&lt;br /&gt;
 Could not connect to application: wireguard&lt;br /&gt;
 System.ComponentModel.Win32Exception (0x80004005): Access denied&lt;br /&gt;
  bei System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited)&lt;br /&gt;
  bei System.Diagnostics.NtProcessManager.GetModuleInfos(Int32 processId, Boolean firstModuleOnly)&lt;br /&gt;
  bei System.Diagnostics.NtProcessManager.GetFirstModuleInfo(Int32 processId)&lt;br /&gt;
  bei System.Diagnostics.Process.get_MainModule()&lt;br /&gt;
  bei FlaUI.Core.WindowsAPI.WindowsApiTools.GetMainModuleFilepath(Process process)&lt;br /&gt;
  bei FlaUI.Core.Application.Attach(Process process)&lt;br /&gt;
  bei WindowsAutomation.Application..ctor(String name, UIA3Automation automation, PropertyRepository propertyRepository, String windowTitle)&lt;br /&gt;
  bei WindowsAutomation.Client.GetApplication(String name, String windowTitle)&lt;br /&gt;
&lt;br /&gt;
You have two options:&lt;br /&gt;
* run expecco as admin&lt;br /&gt;
* start a dotNet-bridge manually as admin (in the local or remote machine):&lt;br /&gt;
    ...\bridgeFramework\dotNetBridge\dotNetBin&amp;gt;DotNetBridgeServer.exe -k -s -a 0.0.0.0 -p 34319 &lt;br /&gt;
: then create a &amp;quot;remote connection&amp;quot; to it.&lt;br /&gt;
&lt;br /&gt;
== Execution of GUI Actions blocks after Mouse Down ==&lt;br /&gt;
UI Automation is blocking further execution of some blocks after a mouse button &amp;lt;Press&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Unable to interact with application (SUT) after Startup  ==&lt;br /&gt;
In some cases - e.g. starting the test via Jenkins - the application (SUT) is not in the correct state after startup. You can&#039;t find elements and/or actions fail. &lt;br /&gt;
You can try to send &amp;quot;[WA]Window - Normalize&amp;quot; with the path of the window to solve this&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Common_Keyboard_Shortcuts/en&amp;diff=30905</id>
		<title>Common Keyboard Shortcuts/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Common_Keyboard_Shortcuts/en&amp;diff=30905"/>
		<updated>2026-02-23T11:45:34Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 13.12.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In general, keyboard shortcuts perform functions which are also available on popup menus of the individual UI components, and these popup menu are usually context/selection menus. This means, that they typically offer operations on the current selected element within that view. In contrast to eg. Mac OSX, the keyboard shortcuts are context sensitive, and depend on the current focus window. This means that the same shortcut may perform different operations depending on which component has the keyboard focus.&lt;br /&gt;
&lt;br /&gt;
All editing functions can be undone via the &amp;quot;&#039;&#039;Undo&#039;&#039;&amp;quot; (&amp;lt;kbd&amp;gt;Ctrl-z&amp;lt;/kbd&amp;gt;) menu function, in case you pressed the wrong key or inside another component.&lt;br /&gt;
&lt;br /&gt;
Notice that the &amp;lt;kbd&amp;gt;Alt&amp;lt;/kbd&amp;gt; key is labelled &amp;lt;kbd&amp;gt;Cmd&amp;lt;/kbd&amp;gt; on some keyboards (and also inside the &amp;lt;code&amp;gt;&amp;quot;keyboard.rc&amp;quot;&amp;lt;/code&amp;gt; file and the settings dialog.&lt;br /&gt;
&lt;br /&gt;
=== General Editing ===&lt;br /&gt;
&lt;br /&gt;
These shortcuts usually work in any view (i.e. project tree view, diagram- and text editors).&lt;br /&gt;
Specific operations are found below.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Ctrl-c&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Copy&#039;&#039;&amp;quot;.&amp;lt;br&amp;gt;Copies the selection into the clipboard. The object to be copied depends on the context and selection:&amp;lt;br&amp;gt;- in a text editor, the text-selection is copied.&amp;lt;br&amp;gt;- in the diagram editor, the selected element(s) are copied&amp;lt;br&amp;gt;- in the navigation tree, the selected tree items are copied.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Ctrl-v&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Paste&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Pastes the clipboard object. This is not always possible, and sometimes simply ignored (for example, if a tree-item is copied and tried to be pasted into a text editor).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Ctrl-x&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Cut&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Deletes the selection and puts it into the clipboard (for later pasting)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Del&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Delete&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Deletes but does NOT put the deleted object into the clipboard.&amp;lt;br&amp;gt;In a text editor, the selected text is deleted, or if nothing is selected, the next character (after the cursor) is deleted.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Backspace&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Delete&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Deletes but does NOT put the deleted object into the clipboard.&amp;lt;br&amp;gt;In a text editor, the selected text is deleted, or if nothing is selected, the previous character (before the cursor) is deleted.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Ctrl-z&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Undo&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Undoes the last operation. This is a multi-undo. This is the same function as performed by the undo toolbar menu button. This button shows a tooltip, which describes what would be undone if pressed. If you are uncertain, what would be undone, place the mouse over this toolbar button (without pressing) and read the tooltip. Undo for complex operations (tree manipulations, imports etc. are performed via a toolbar button, which shows the kind of operation to be undone in its tooltip).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Ctrl-y&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Redo&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Undoes the last undo operation. Currently, this works only in text editor windows (i.e. be careful in the diagram editor).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Ctrl-f&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Find&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Opens a dialog to enter a search string and various options for search (pattern-matching search, wrap at end, etc.). In a text editor, a replace string can be entered for search and replace.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;F2&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Rename&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;In the tree or diagram editor, lets you rename the selected element.&amp;lt;br&amp;gt;In a code editor, it renames a variable.&lt;br /&gt;
&lt;br /&gt;
=== Tree/List Organisation ===&lt;br /&gt;
&lt;br /&gt;
The tree interpretes certain shortcuts differently than other views.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-&amp;amp;#x2193;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-CursorDown) - &amp;quot;&#039;&#039;Move Down&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;This moves the selected item(s) down in the navigation tree or a testplan&#039;s list of test cases. In a diagram editor, if a step&#039;s pin is selected in the diagram editor, this is moved towards the bottom.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-&amp;amp;#x2191;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-CursorUp) - &amp;quot;&#039;&#039;Move Up&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;This moves the selected item up in the navigation tree or a testplan&#039;s list of test cases. In a diagram editor, if a step&#039;s pin is selected in the diagram editor, this is moved towards the top.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-&amp;amp;#x2190;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-CursorLeft) - &amp;quot;&#039;&#039;Move Out&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;In the navigation tree, this moves the selected item out of its containing (parent) item and places it below the parent in the list.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-&amp;amp;#x2192;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-CursorRight) - &amp;quot;&#039;&#039;Move In&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;In the navigation tree, this moves the selected item into the tree item right above it. I.e. it makes it a child element of the other item.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-Shift-&amp;amp;#x2193;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-Shift-CursorDown) - &amp;quot;&#039;&#039;Move to Bottom&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;This moves the selected item(s) down in the navigation tree to the end of the children list.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-Shift-&amp;amp;#x2191;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-Shift-CursorUp] - &amp;quot;&#039;&#039;Move to Top&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;This moves the selected item up in the navigation tree to the beginning of the children list.&lt;br /&gt;
&lt;br /&gt;
=== Element Creation (Diagram Editor) ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-n&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;New Step&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;In the diagram editor: opens a dialog to create a new step. The dialog lets you choose the action which is to be instantiated. If a pin is selected, the dialog filters are preset to only show action blocks with correspondingly typed pins.&amp;lt;br&amp;gt;In the scheme editor: adds a new input or output pin, depending on the currently selected pin&#039;s type.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-r&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Replace&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;In the diagram editor, this opens a dialog to choose another action which is to replace the selected action.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-g&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Graphic&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;In the diagram editor, this opens a dialog to choose an image which is added as annotation (useful to mark areas of the diagram as &amp;quot;Under Construction&amp;quot; or &amp;quot;Attention Here&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-i&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;New InputPin&#039;&#039;&amp;quot;.&amp;lt;br&amp;gt;In the scheme editor, this adds a new input pin - same as clicking on the &amp;quot;&#039;&#039;Add Input Pin&#039;&#039;&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-o&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;New OutputPin&#039;&#039;&amp;quot;.&amp;lt;br&amp;gt;In the scheme editor, this adds a new output pin - same as clicking on the &amp;quot;&#039;&#039;Add Output Pin&#039;&#039;&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
More editing functions are found in every text editor&#039;s, lists or diagram&#039;s right-button menu; some of which do have keyboard shortcuts.&lt;br /&gt;
&lt;br /&gt;
=== Code Editor ===&lt;br /&gt;
&lt;br /&gt;
For a full list, see [[Code_Editor/en#Editor_Functions_and_Keyboard_Shortcuts|&amp;quot;Editor Functions and Keyboard Shortcuts&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Ctrl-g&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Goto Line&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;In text editors: to position the cursor to an entered line number. If the entered number has a sign (+/-), the positioning is relative to the current line. In a diagram editor, a graphic annotation is inserted (see below)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Alt-f&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Forward Search&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Searches for the next occurrence of the previous search string.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;Alt-b&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Backward Search&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Searches for the previous occurrence of the previous search string.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;F8&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Again&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Repeats the last cut or replace operation in a text editor. For example, to replace a string by another string, first select it, type in the new word, then press &amp;lt;kbd&amp;gt;F8&amp;lt;/kbd&amp;gt; to search for the next occurrence and replace again. If the previous operation was a &amp;quot;cut&amp;quot; or &amp;quot;delete&amp;quot;, then &amp;lt;kbd&amp;gt;F8&amp;lt;/kbd&amp;gt; searches for the next occurrence and deletes that again.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;F4&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Comment&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;In an elementary code editor, comments the selection or the current cursor line&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;F5&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Uncomment&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;In an elementary code editor, uncomments the selection or the current cursor line&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;F6&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Toggle Case&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;toggles the selection between titlecase, uppercase and lowercase (press multiple times)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;F9&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Undent by 4&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;remove the left 4 spaces of the selected line range, or the cursor line (if no lines are seleted).&amp;lt;br&amp;gt;Undent is also possible by selecting a number of lines and pressing &amp;lt;kbd&amp;gt;Shift-Tab&amp;lt;/kbd&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;F10&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Indent by 4&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;add 4 spaces to the left of the selected line range, or the cursor line.&amp;lt;br&amp;gt;Indent is also possible by selecting a number of lines and pressing &amp;lt;kbd&amp;gt;Tab&amp;lt;/kbd&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;F11&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Undent by 1&#039;&#039;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;span style=&amp;quot;box-shadow: 1px 1px 2px rgba(0,0,0,0.3);&amp;quot;&amp;gt;&amp;lt;kbd&amp;gt;F12&amp;lt;/kbd&amp;gt;&amp;lt;/span&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;Indent by 1&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-d;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;DoIt&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;This works in code editors for Smalltalk or the builtin JavaScript actions. It takes the currently selected piece of text and immediately executes it as a program. The result is silently discarded (see below for more).&amp;lt;br&amp;gt;If no text is currently selected, the current cursor line is taken as input.&amp;lt;br&amp;gt;See the &amp;quot;[[Smalltalk Syntax Cheat Sheet]]&amp;quot; for a short syntax summary.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-p;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;PrintIt&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Simular to the above, but the result is pasted after the selection. As an example, in a code editor, type &amp;quot;&amp;lt;code&amp;gt;45 degrees sin&amp;lt;/code&amp;gt;&amp;quot; (without the double quotes), select it, and press &amp;lt;kbd&amp;gt;PrintIt&amp;lt;/kbd&amp;gt;. The result will be pasted after the selection. This also works in a workspace/notepad window.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-q;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; - &amp;quot;&#039;&#039;InspectIt&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Simular to the above, but an inspector window is opened on the result.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-B;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (Ctrl-Shift-B) - &amp;quot;&#039;&#039;BrowseIt&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Simular to the above, but a class browser is opened on the result&#039;s class, showing all operations (methods) which are implemented by this object.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-I;&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (Ctrl-Shift-I) - &amp;quot;&#039;&#039;Implementors&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Extracts a Smalltalk message name (i.e. the name of an operation) and opens a browser on all methods in the system which implement that message.&lt;br /&gt;
&lt;br /&gt;
=== Other ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-+&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-plus) - &amp;quot;&#039;&#039;Zoom In&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Text in the current focus view is shown in a larger font; diagrams are magnified&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl--&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-minus) - &amp;quot;&#039;&#039;Zoom Out&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Text in the current focus view is shown in a smaller font; diagrams are shrunk&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-Shift-+&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-Shift-plus) - &amp;quot;&#039;&#039;Zoom In All&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Zoom-In all components of the expecco window&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;kbd&amp;gt;Ctrl-Shift--&amp;lt;/kbd&amp;gt;&#039;&#039;&#039; (= Ctrl-Shift-minus) - &amp;quot;&#039;&#039;Zoom Out All&#039;&#039;&amp;quot;&amp;lt;br&amp;gt;Zoom-Out all components of the expecco window.&lt;br /&gt;
&lt;br /&gt;
=== Customizing Keyboard Shortcuts ===&lt;br /&gt;
&lt;br /&gt;
When expecco starts, it looks for a file named &amp;quot;&amp;lt;code&amp;gt;keyboard.rc&amp;lt;/code&amp;gt;&amp;quot; in the &amp;quot;&amp;lt;code&amp;gt;bin&amp;lt;/code&amp;gt;&amp;quot; folder (where the expecco executable is installed). All keyboard shortcuts are defined in this script file. To customize the keyboard shortcuts, take the code there as a guide.&lt;br /&gt;
&lt;br /&gt;
These definitions are the default settings; however, individual users may as well change or add personal preferences&lt;br /&gt;
via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Keyboard&#039;&#039;&amp;quot; dialog.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_26.x&amp;diff=30904</id>
		<title>Release Notes 26.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_26.x&amp;diff=30904"/>
		<updated>2026-02-23T11:41:53Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 14.1.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 25.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 26.2 ==&lt;br /&gt;
&lt;br /&gt;
== Release 26.1 ==&lt;br /&gt;
*Feature: Qt-Plugin supports Qt6.8 ([[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Delivered versions for QT and build environment]])&lt;br /&gt;
* Feature: improved search text box behavior in text editors (type RETURN, CMD-f or CMD-b while box is open) and back to original position button added.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Expecco_API/en&amp;diff=30903</id>
		<title>Expecco API/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Expecco_API/en&amp;diff=30903"/>
		<updated>2026-02-23T11:38:55Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 18.12.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== How to Program ==&lt;br /&gt;
&lt;br /&gt;
Before you start programming, please read the [[How_to_Program/en | &amp;quot;How to Program&amp;quot;]] document, which describes how program code is handled in expecco.&lt;br /&gt;
Unless you are familiar with the dynamics of a Smalltalk development environment, some of it may be unknown to you, and you will have more fun and be more productive, if you know the power of the tools. For the best development experience, take a look at the debugger, workspace (notepad) and data inspectors.&lt;br /&gt;
&lt;br /&gt;
The rest of this document describes the syntax and semantics of the elementary action languages. For tool usage, please read the [[How_to_Program/en | HowTo]] document.&lt;br /&gt;
&lt;br /&gt;
== expecco API ==&lt;br /&gt;
&lt;br /&gt;
The expecco API provides functions and access to the underlying class library for the use in [[Elementary Block|elementary blocks]] written in Smalltalk and JavaScript (i.e. for code which is executed inside expecco itself). This API is not available for elementary blocks written in other languages which are executed by external script engines (Shell, Batch, Python, Node.js etc.) or inside a different Java or CLR Virtual Machine (Groovy, VBScript, IronPython). However, a subset of the functions are supported as RPC (remote procedure calls) in bridged elementary actions.&lt;br /&gt;
&lt;br /&gt;
For a short introduction to the Smalltalk programming language,&lt;br /&gt;
please read the [http://live.exept.de/doc/online/english/getstart/tut_2.html Smalltalk tutorial in the Smalltalk/X online manual].&lt;br /&gt;
For a full book on learning Smalltalk, read [http://live.exept.de/doc/books/JoyOfST/JoyOfST.pdf &amp;quot;The joy of Smalltalk, An introduction to Smalltalk&amp;quot; by Ivan Tomek].&lt;br /&gt;
&lt;br /&gt;
The [[#Groovy Elementary Blocks|API for Groovy elementary blocks]] is different and described below.&lt;br /&gt;
&amp;lt;br&amp;gt;The API for bridged Node.js actions is described [[#Node.js_.28Bridged.29_Elementary_Blocks|here]].&lt;br /&gt;
&amp;lt;br&amp;gt;The API for bridged Python and Jython actions is described [[#Bridged Python Elementary Blocks|here]].&lt;br /&gt;
&amp;lt;br&amp;gt;The API for bridged Ruby actions is described [[#Bridged Ruby Elementary Blocks|here]].&lt;br /&gt;
&amp;lt;br&amp;gt;The API for bridged C actions is described [[#Bridged C Elementary Blocks|here]].&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;Smalltalk_Elementary_Blocks&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span id=&amp;quot;JavaScript_Elementary_Blocks&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;JavaScript and Smalltalk Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
The expecco JavaScript and the Smalltalk API consist of the same functions - both call into the underlying [http://www.smalltalk-x.de Smalltalk/X] system, for which extensive documentation is available as &lt;br /&gt;
[http://live.exept.de/doc/online/english/TOP.html Online Documentation] and&lt;br /&gt;
as [http://live.exept.de/ClassDoc Class Reference].&lt;br /&gt;
&lt;br /&gt;
The Smalltalk/X language and class library are [http://wiki.squeak.org/squeak/uploads/172/standard_v1_9-indexed.pdf ANSI compatible]; therefore the official ANSI documents, Smalltalk literature and tutorials are also valuable sources of information (for example, the online tutorials you may find in youtube).&lt;br /&gt;
&lt;br /&gt;
:- If you wonder &amp;quot;why Smalltalk?&amp;quot;, you should know that [https://insights.stackoverflow.com/survey/2017#most-loved-dreaded-and-wanted Smalltalk ranked nr. 2 in a 2017 survey of &amp;quot;most loved languages&amp;quot;] - admittedly, this ranking may be subjective (in that Smalltalk programmers might be more loyal), but it should at least raise your eyebrows.&lt;br /&gt;
:- It is not among the most used languages - but that decision is usually made by people who do not even know Smalltalk or who think that language does not matter.  &lt;br /&gt;
:- If you think it is outdated, be reminded that Smalltalk has the most consistent object model and reflection facilities of all OO languages, and that modern clones like Ruby and Python only provide a subset of Smalltalk&#039;s facilities. If you don&#039;t know it, don&#039;t judge it.&lt;br /&gt;
:- The underlying virtual machine (VM) is feature rich and provides many mechanisms which are not possible in most &#039;modern&#039; languages. For example, in most (if not all) of the current languages it is not possible to interrupt a thread which blocks in a system call (eg. in a read). In none of them, are exceptions proceedable. In none of them can you interrupt other threads in any situation (again: especially not if it is inside a blocking read).&lt;br /&gt;
:- The set of integrated tools is massive in Smalltalk: full access to classes, threads, semaphores, any object&#039;s internals are all provided by graphical tools which can be opened by double clicks or via menus.&lt;br /&gt;
&lt;br /&gt;
Expecco&#039;s JavaScript is implemented by compiling JavaScript syntax to the underlying Smalltalk bytecode. It is not fully compatible with a &amp;quot;real&amp;quot; JavaScript: it is class based, and the underlying object model and class library are actually the Smalltalk/X object model and class library. Thus, expecco&#039;s JavaScript can be seen as &amp;quot;&amp;lt;I&amp;gt;a Smalltalk with JavaScript syntax&amp;lt;/I&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Please be not confused by two JavaScript-based elementary actions: the builtin JavaScript described here is executed within expecco itself whereas Node-actions are executed in a separate Node.js virtual machine. These Node actions are &amp;quot;real JavaScript&amp;quot; and are described in a separate [[#Node.js_.28Bridged.29_Elementary_Blocks |chapter below]].&lt;br /&gt;
&lt;br /&gt;
===Smalltalk / JavaScript Short Syntax Overview===&lt;br /&gt;
Expecco&#039;s builtin JavaScript and Smalltalk only differ in their syntax - semantically they are very similar:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! JavaScript&lt;br /&gt;
! Smalltalk&lt;br /&gt;
!&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 15em&amp;quot;|this&lt;br /&gt;
|style=&amp;quot;width: 15em&amp;quot;|self&lt;br /&gt;
| the current activity (inside an elementary action)&lt;br /&gt;
|-&lt;br /&gt;
|this.&amp;lt;I&amp;gt;functionName&amp;lt;/I&amp;gt;()&lt;br /&gt;
|self &amp;lt;I&amp;gt;functionName&amp;lt;/I&amp;gt;&lt;br /&gt;
| a call without arguments&lt;br /&gt;
|-&lt;br /&gt;
|this.&#039;&#039;functionName&#039;&#039;(&#039;&#039;arg&#039;&#039;)&lt;br /&gt;
|self &#039;&#039;functionName&#039;&#039;:&#039;&#039;arg&#039;&#039;&lt;br /&gt;
| a call with one argument&lt;br /&gt;
|-&lt;br /&gt;
|this.&#039;&#039;namePart1_part2&#039;&#039;(&#039;&#039;arg1&#039;&#039;,&#039;&#039;arg2&#039;&#039;)&lt;br /&gt;
|self &#039;&#039;namePart1&#039;&#039;:&#039;&#039;arg1&#039;&#039; &#039;&#039;part2&#039;&#039;:&#039;&#039;arg2&#039;&#039;&lt;br /&gt;
| two arguments&amp;lt;br&amp;gt;Notice that in Smalltalk, the arguments are &#039;&#039;sliced&#039;&#039; into the name parts, and that the concatenation of the parts is the actual name (incl. the colons).&amp;lt;br&amp;gt;Thus, in &amp;quot;&amp;lt;code&amp;gt;x at:5 put:10&amp;lt;/code&amp;gt;&amp;quot; the name of the called method is &amp;quot;at:put:&amp;quot; and it gets two arguments: 5 and 10. Whereas &amp;quot;&amp;lt;code&amp;gt;(x at:5) put:10&amp;lt;/code&amp;gt;&amp;quot; would first send an &amp;quot;at:&amp;quot; message, then send a&amp;quot;put:&amp;quot; message to the object returned from &amp;quot;at:&amp;quot;.&amp;lt;br&amp;gt;In JavaScript, &amp;quot;:&amp;quot; is not a valid character in a function name, and a translation mechanism is applied which replaces &amp;quot;:&amp;quot; by underline, and drops the final colon.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;functionName&#039;&#039;(...)&lt;br /&gt;
| self &#039;&#039;functionName&#039;&#039;...&lt;br /&gt;
| implicit &#039;&#039;this&#039;&#039; receiver in JS&amp;lt;br&amp;gt;explicit in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;accessor&#039;&#039;&lt;br /&gt;
| self &#039;&#039;accessor&#039;&#039;&lt;br /&gt;
| slot access - implicit this receiver in JS&amp;lt;br&amp;gt;explicit in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;stat1&#039;&#039; ; &#039;&#039;stat2&#039;&#039; ;&lt;br /&gt;
| &#039;&#039;stat1&#039;&#039; . &#039;&#039;stat2&#039;&#039;&lt;br /&gt;
| statement terminator / separator&amp;lt;br&amp;gt;in ST: to &#039;&#039;&#039;separate&#039;&#039;&#039; statements&amp;lt;br&amp;gt;in JS: to &#039;&#039;&#039;terminate&#039;&#039;&#039; a statement.&amp;lt;br&amp;gt;In Smalltalk, the last period &amp;quot;.&amp;quot; inside a method or block can be and often is omitted.&lt;br /&gt;
|-&lt;br /&gt;
| if (&#039;&#039;cond&#039;&#039;) {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;ifStats&#039;&#039;&amp;lt;br&amp;gt;} else {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;elseStats&#039;&#039;&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;cond&#039;&#039; ifTrue:[&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;ifStats&#039;&#039;&amp;lt;br&amp;gt;] ifFalse:[&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;elseStats&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
| conditional execution.&amp;lt;br&amp;gt;Notice the square brackets in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| while (&#039;&#039;cond&#039;&#039;) {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats&#039;&#039;&amp;lt;br&amp;gt;}&lt;br /&gt;
| [ &#039;&#039;cond&#039;&#039; ] whileTrue:[&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
| while-loop.&amp;lt;br&amp;gt;Notice the brackets around the condition in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| for (i=&#039;&#039;start&#039;&#039;; i&amp;amp;lt;=&#039;&#039;end&#039;&#039;; i++) {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats using i&#039;&#039;&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;start&#039;&#039; to:&#039;&#039;end&#039;&#039; do:[:i &amp;amp;#124;&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats using i&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
| counting-loop.&amp;lt;br&amp;gt;Seldom used in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| foreach (&#039;&#039;el&#039;&#039; in &#039;&#039;collection&#039;&#039;) {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats using el&#039;&#039;&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;collection&#039;&#039; do:[:el &amp;amp;#124;&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats using el&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
| loop over collection elements.&amp;lt;br&amp;gt;Very often used in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| function () { &#039;&#039;stats&#039;&#039; }&lt;br /&gt;
| [ &#039;&#039;stats&#039;&#039; ]&lt;br /&gt;
| an anonymous (inner) function (called &amp;quot;block&amp;quot; in ST).&amp;lt;br&amp;gt;JS: return value via explicit return&amp;lt;br&amp;gt;ST: return value is last expression&#039;s value&lt;br /&gt;
|-&lt;br /&gt;
| function (&#039;&#039;a1&#039;&#039;, &#039;&#039;a2&#039;&#039;,...) { &#039;&#039;stats&#039;&#039; }&lt;br /&gt;
| [:&#039;&#039;a1&#039;&#039; :&#039;&#039;a2&#039;&#039; ...&amp;amp;#124; &#039;&#039;stats&#039;&#039; ]&lt;br /&gt;
| in ST: blocks are references to anonymous function&lt;br /&gt;
|-&lt;br /&gt;
| var &#039;&#039;v1&#039;&#039;, &#039;&#039;v2&#039;&#039;, ... ;&lt;br /&gt;
| &amp;amp;#124; &#039;&#039;v1&#039;&#039; &#039;&#039;v2&#039;&#039; ... &amp;amp;#124;&lt;br /&gt;
| local variables inside a function (or block). Semantically, these are &amp;quot;let&amp;quot; variables (i.e. only seen in the current scope)&lt;br /&gt;
|-&lt;br /&gt;
| return &#039;&#039;expr&#039;&#039;;&lt;br /&gt;
| ^ &#039;&#039;expr&#039;&#039;&lt;br /&gt;
| return a value.&amp;lt;br&amp;gt;In ST: a return from within a block returns the enclosing &#039;&#039;&#039;top-level&#039;&#039;&#039; method&amp;lt;br&amp;gt;In JS: a return returns from the &#039;&#039;&#039;inner&#039;&#039;&#039; function&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &#039;...&#039;&lt;br /&gt;
| String constant without c-escapes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;...&amp;quot;&amp;lt;br&amp;gt;or&amp;lt;br&amp;gt;&#039;...&#039;&lt;br /&gt;
| c&#039;...&#039;&lt;br /&gt;
| String constant with c-escapes (\n, \t, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| `...${ expr1 } .. ${ expr2 } ...`&lt;br /&gt;
| e&#039;..{ expr1 } .. { expr2 } ...&#039;&lt;br /&gt;
| String with sliced in expressions (exprs will be converted to string). Also known as &#039;&#039;TemplateStrings&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| 0xXXX, 0bXXX, 0XXX&lt;br /&gt;
| 0xXXX, 0bXXX, 0oXXX&amp;lt;br&amp;gt;or&amp;lt;br&amp;gt;16rXXX, 2rXXX, 8rXXX &amp;lt;br&amp;gt;(notice: 0177 is a decimal in Smalltalk, but octal in JS)&lt;br /&gt;
| Integer constants (hex, binary, octal)&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| #(el1 ... el2)&lt;br /&gt;
| literal (constant) array constructed at compile time.&amp;lt;br&amp;gt;Notice that elements are separated by spaces&lt;br /&gt;
|-&lt;br /&gt;
| [ex1 , ex2 , ... , exN]&lt;br /&gt;
| {ex1 . ex2 . ... . exN}&lt;br /&gt;
| literal (constant) array constructed at execution time.&amp;lt;br&amp;gt;Notice that in Smalltalk, expressions are separated by periods (must be, because &amp;quot;,&amp;quot; is an operator to concatenate collections)&lt;br /&gt;
|-&lt;br /&gt;
| /* ... */&lt;br /&gt;
| &amp;quot; ... &amp;quot;&lt;br /&gt;
| comment&lt;br /&gt;
|-&lt;br /&gt;
| // ...&lt;br /&gt;
| &amp;quot;/ ...&lt;br /&gt;
| end of line comment&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &amp;quot;&amp;lt;&amp;lt;TOKEN&amp;lt;br&amp;gt; ... &amp;lt;br&amp;gt;TOKEN&lt;br /&gt;
| token comment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Smalltalk Operator Precedence ====&lt;br /&gt;
Smalltalk beginners may be irritated by the missing binary operator precedence rules: in Smalltalk, all operators have the same precedence and are evaluated left to right.&amp;lt;br&amp;gt;Thus if you write: &lt;br /&gt;
 a + b * 5 &lt;br /&gt;
the JavaScript semantic is: &lt;br /&gt;
 a + (b * 5) &lt;br /&gt;
whereas in Smalltalk, it is evaluated as:&lt;br /&gt;
 (a + b) * 5&lt;br /&gt;
(i.e. left to right). &lt;br /&gt;
&lt;br /&gt;
Therefore, as a guideline (and actually a good convention), all Smalltalk binary expressions with more than one operator should be parenthesized to make the intention clear. It make clear that it is intended, that should be done even if the left-to-right order matches the mathematical precedences.&lt;br /&gt;
&lt;br /&gt;
==== Smalltalk Operators ====&lt;br /&gt;
Another uncommon feature of the Smalltalk language is that there are only 6 keywords in the language&lt;br /&gt;
(&amp;quot;&amp;lt;code&amp;gt;self&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;thisContext&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&amp;lt;br&amp;gt;Every other word is either the name of a variable or the name of a message to be sent to an object (aka a &amp;quot;&#039;&#039;virtual function call&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;method invocation&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Every sequence of special characters (except &amp;quot;&amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt;&amp;quot; (colon), &amp;quot;&amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;&amp;quot; (period), &amp;quot;&amp;lt;code&amp;gt;(&amp;lt;/code&amp;gt;&amp;quot; (left), &amp;quot;&amp;lt;code&amp;gt;)&amp;lt;/code&amp;gt;&amp;quot; (right parenthesis), &amp;quot;&amp;lt;code&amp;gt;[&amp;lt;/code&amp;gt;&amp;quot; (left), &amp;quot;&amp;lt;code&amp;gt;]&amp;lt;/code&amp;gt;&amp;quot; (right bracket), &amp;lt;code&amp;gt;{&amp;lt;/code&amp;gt;&amp;quot; (left),&amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt;&amp;quot; (right brace), &amp;quot;&amp;lt;code&amp;gt;:=&amp;lt;/code&amp;gt;&amp;quot; (assign), &amp;quot;&amp;lt;code&amp;gt;^&amp;lt;/code&amp;gt;&amp;quot; (return) and &amp;quot;&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;&amp;quot; (semicolon) ) is interpreted as operator (or in other words: as the name of a message/virtual function call).&lt;br /&gt;
&lt;br /&gt;
Thus, the sequences &amp;quot;&amp;lt;code&amp;gt;-&amp;gt;&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;=&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;=&amp;gt;&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;&amp;lt;-&amp;lt;/code&amp;gt;&amp;quot; and especially the comma (&amp;quot;&amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt;&amp;quot;) are operators which are treated like &amp;quot;&amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
Finally, message sends (&amp;quot;&#039;&#039;function calls&#039;&#039;&amp;quot;) with arguments are always written with keyword arguments. I.e. the arguments are prefixed by a keyword (which is an identifier with a colon). Smalltalk does not allow positional arguments in a message send.&lt;br /&gt;
&lt;br /&gt;
==== Calling Functions and Invoking Methods (aka &amp;quot;Sending Messages&amp;quot;) ====&lt;br /&gt;
All functions are actually implemented in Smalltalk and follow the standard Smalltalk naming conventions. The same function names are used for JavaScript. As seen above, this scheme works well for functions without or with a single argument, but requires a name translation for functions with more than one argument. This translation is done by the JavaScript compiler by replacing every colon (:) of the Smalltalk name by an underline (_) character, except for the last colon if there are more than one. Thus for example, the Smalltalk name &amp;quot;&amp;lt;code&amp;gt;at:put:&amp;lt;/code&amp;gt;&amp;quot; will be named &amp;quot;&amp;lt;code&amp;gt;at_put&amp;lt;/code&amp;gt;&amp;quot; in JavaScript.&lt;br /&gt;
&lt;br /&gt;
In JavaScript, a function-name alone (i.e. without explicit receiver) is translated into a self-send; thus &amp;quot;&amp;lt;code&amp;gt;this.foo()&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;foo()&amp;lt;/code&amp;gt;&amp;quot; are equivalent.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- not recommended and bad style&lt;br /&gt;
Also, for non-argument accessor functions (getters), the empty argument list can be omitted in JavaScript; therefore, &amp;quot;foo&amp;quot; and &amp;quot;this.foo&amp;quot;, &amp;quot;foo()&amp;quot; and &amp;quot;this.foo()&amp;quot; are all equivalent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, the JavaScript call:&lt;br /&gt;
 this.&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&amp;quot;foo&amp;quot;)&lt;br /&gt;
is written in Smalltalk as:&lt;br /&gt;
 self &#039;&#039;&#039;environmentAt:&#039;&#039;&#039;&#039;foo&#039;&lt;br /&gt;
&lt;br /&gt;
and, to demonstrate the multi-argument translation rule, the Smalltalk code:&lt;br /&gt;
 self &#039;&#039;&#039;environmentAt:&#039;&#039;&#039;&#039;foo&#039; &#039;&#039;&#039;put:&#039;&#039;&#039;1234&lt;br /&gt;
is written in JavaScript as:&lt;br /&gt;
 this.&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039;(&amp;quot;foo&amp;quot;, 1234)&lt;br /&gt;
or (because of the implicit receiver being &amp;quot;this&amp;quot;), alternatively:&lt;br /&gt;
 &#039;&#039;&#039;environmentAt_put&#039;&#039;&#039;(&amp;quot;foo&amp;quot;, 1234)&lt;br /&gt;
&lt;br /&gt;
=== Syntax Summary ===&lt;br /&gt;
For a formal specification of the JavaScript and Smalltalk languages, see the appendixes below.&lt;br /&gt;
The following gives a rough overview over the most common syntactic constructs.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! JavaScript&lt;br /&gt;
! Smalltalk&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 10em&amp;quot;| this&lt;br /&gt;
|style=&amp;quot;width: 10em&amp;quot;| self&lt;br /&gt;
| the current activity&lt;br /&gt;
|-&lt;br /&gt;
| null&lt;br /&gt;
| nil&lt;br /&gt;
| a null reference (UndefinedObject)&lt;br /&gt;
|-&lt;br /&gt;
| ;&lt;br /&gt;
| .&lt;br /&gt;
| statement terminator/separator&amp;lt;br&amp;gt;In JavaScript it is a terminator, meaning that every statement (except brace-blocks) must be terminated by a semicolon.&amp;lt;br&amp;gt;In Smalltalk, it is a separator, meaning that the last statement in a block or method does not need one.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;...&amp;quot;&lt;br /&gt;
| &#039;...&#039;&lt;br /&gt;
| a String constant (JavaScript allows single quotes too);&amp;lt;br&amp;gt;no C-escapes in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| c&#039;...&#039;&lt;br /&gt;
| a Smalltalk String constant with c-escapes&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| e&#039;..{ expr } ..&#039;&lt;br /&gt;
| a Smalltalk String with embedded expressions (sliced-in)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| #&#039;...&#039;&lt;br /&gt;
| a Symbol constant&amp;lt;br&amp;gt;(not available in JavaScript; use &amp;quot;xxx&amp;quot;.asSymbol() in JS)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| #...&lt;br /&gt;
| also a Symbol constant&amp;lt;br&amp;gt;(not available in JavaScript; use &amp;quot;xxx&amp;quot;.asSymbol() in JS)&lt;br /&gt;
|-&lt;br /&gt;
| [ el1 , el2 , ... ]&lt;br /&gt;
| #( el1 el2 ... )&lt;br /&gt;
| an Array constant&amp;lt;br&amp;gt;(elements must be constant literals)&amp;lt;br&amp;gt;Notice the separating comma in JS, but space-separated elements in Smalltalk.&amp;lt;br&amp;gt;In Smalltalk, the array is created at compile time (i.e. runtime cost is zero); the array is immutable,&amp;lt;br&amp;gt;whereas in JS it is created mutable at runtime&lt;br /&gt;
|-&lt;br /&gt;
| [ expr1 , expr2 , ... ]&lt;br /&gt;
| { expr1 . expr2 . ... }&lt;br /&gt;
| a computed Array&amp;lt;br&amp;gt;(elements are expressions)&amp;lt;br&amp;gt;notice the expression terminators in ST (periods),&amp;lt;br&amp;gt;and that &amp;quot;,&amp;quot; (comma) is an operator in ST.&amp;lt;br&amp;gt;The array is created at runtime; the array is mutable&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| #[ el1 el2 ... ]&lt;br /&gt;
| an immutable ByteArray constant&amp;lt;br&amp;gt;(not available in JavaScript)&lt;br /&gt;
|-&lt;br /&gt;
| 1234&lt;br /&gt;
| 1234&lt;br /&gt;
| an Integer constant&amp;lt;br&amp;gt;(arbitrary precision)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1234&lt;br /&gt;
| 0x1234 or 16r1234&lt;br /&gt;
| a hexadecimal Integer constant (radix is 16)&amp;lt;br&amp;gt;(arbitrary precision)&lt;br /&gt;
|-&lt;br /&gt;
| 0b10001010&lt;br /&gt;
| 0b10001010 or 2r10001010&lt;br /&gt;
| a binary Integer constant (radix is 2)&amp;lt;br&amp;gt;(arbitrary precision)&lt;br /&gt;
|-&lt;br /&gt;
| 0177&lt;br /&gt;
| 8r177&lt;br /&gt;
| an octal Integer constant (radix is 8)&amp;lt;br&amp;gt;(arbitrary precision)&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| 3r10001010&lt;br /&gt;
| a ternary Integer constant (radix is 3);&amp;lt;br&amp;gt;not available in JavaScript&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &amp;amp;lt;N&amp;amp;gt;rxxxx&lt;br /&gt;
| an N-ary Integer constant (radix is N);&amp;lt;br&amp;gt;not available in JavaScript&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| ( num / den )&lt;br /&gt;
| a Fraction constant (not available in JavaScript);&amp;lt;br&amp;gt;both numerator and denominator must be integers&lt;br /&gt;
|-&lt;br /&gt;
| 1.234&amp;lt;br&amp;gt;1e5&lt;br /&gt;
| 1.234&amp;lt;br&amp;gt;1e5&lt;br /&gt;
| Floating Point constants&amp;lt;br&amp;gt;(double precision)&lt;br /&gt;
|-&lt;br /&gt;
| v = expression&lt;br /&gt;
| v := expression&lt;br /&gt;
| assignment to a variable&lt;br /&gt;
|-&lt;br /&gt;
| expr1 == expr2&lt;br /&gt;
| expr1 = expr2&lt;br /&gt;
| compare for equal value&lt;br /&gt;
|-&lt;br /&gt;
| expr1 === expr2&lt;br /&gt;
| expr1 == expr2&lt;br /&gt;
| compare for identity&amp;lt;br&amp;gt;be careful: 1.0 (the float) is NOT identical to 1 (the integer)&amp;lt;br&amp;gt;However, they are equal in value.&lt;br /&gt;
|-&lt;br /&gt;
| rcvr.f ()&lt;br /&gt;
| rcvr f&lt;br /&gt;
| function call (always a &amp;quot;virtual function call&amp;quot;)&lt;br /&gt;
|-&lt;br /&gt;
| rcvr.f (arg)&lt;br /&gt;
| rcvr f: arg&lt;br /&gt;
| with 1 arg&lt;br /&gt;
|-&lt;br /&gt;
| rcvr.a_b (arg1, arg2)&lt;br /&gt;
| rcvr a: arg1 b: arg2&lt;br /&gt;
| with args&amp;lt;br&amp;gt;notice the different names of the function&amp;lt;br&amp;gt;&amp;quot;a_b&amp;quot; vs.&amp;quot;a:b:&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| return;&lt;br /&gt;
| ^ self&lt;br /&gt;
| without return value&amp;lt;br&amp;gt;ST: from enclosing method;&amp;lt;br&amp;gt;JS: from current function&lt;br /&gt;
|-&lt;br /&gt;
| return expr;&lt;br /&gt;
| ^ expr&lt;br /&gt;
| with return value&amp;lt;br&amp;gt;ST: from enclosing method;&amp;lt;br&amp;gt;JS: from current function&lt;br /&gt;
|-&lt;br /&gt;
| return from execute;&lt;br /&gt;
| ^ self&lt;br /&gt;
| return from execute activity from within an inner function&lt;br /&gt;
|-&lt;br /&gt;
| ! expr&lt;br /&gt;
| expr not&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| e1 &amp;amp;&amp;amp; e2&lt;br /&gt;
| (e1 and:[ e2 ])&lt;br /&gt;
| non evaluating and&amp;lt;br&amp;gt;(e2 is not evaluated if e1 is false)&lt;br /&gt;
|-&lt;br /&gt;
| e1 &amp;amp;#124;&amp;amp;#124; e2&lt;br /&gt;
| (e1 or:[ e2 ])&lt;br /&gt;
| non evaluating or&amp;lt;br&amp;gt;(e2 is not evaluated if e1 is true)&lt;br /&gt;
|-&lt;br /&gt;
|  &lt;br /&gt;
| pin &amp;lt;- value&lt;br /&gt;
| only for output pins: writes value to the pin (same as &amp;quot;pin value(val)&amp;quot;)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Syntactic Sugar ===&lt;br /&gt;
&lt;br /&gt;
Some syntactic constructs of the JavaScript language are implemented as library functions in Smalltalk. Among others, most noteworthy are conditional execution (if-the-else) and loops.&lt;br /&gt;
&lt;br /&gt;
Non-Smalltalkers should be aware that in Smalltalk all control structures are implemented as library functions (i.e. method invocations) to corresponding receiver objects. They get a block (=closure or anonymous function) as argument, which is then possibly evaluated. The Smalltalk block syntax &amp;quot;&amp;lt;code&amp;gt;[...]&amp;lt;/code&amp;gt;&amp;quot; makes this extremely convenient and easy to use.&lt;br /&gt;
&lt;br /&gt;
It is the responsibility of the Smalltalk compiler and runtime system, to care for optimized execution of such code (typically by inlining the code). However, it is still possible to put a block into a variable, to pass it as argument, or to return it as value from a method or block. Thus, in Smalltalk, variables or computed blocks may also be used as arguments to messages like &amp;quot;&amp;lt;code&amp;gt;ifTrue:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;whileTrue:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;do:&amp;lt;/code&amp;gt;&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;The JavaScript syntax for control structures is mapped to corresponding Smalltalk library functions as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! JavaScript&lt;br /&gt;
! Smalltalk&lt;br /&gt;
! Notes&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 15em&amp;quot;|if (&#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
|style=&amp;quot;width: 15em&amp;quot;|  (&#039;&#039;expr&#039;&#039;) ifTrue:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
| Notice the square brackets&lt;br /&gt;
|-&lt;br /&gt;
|if (! &#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| (&#039;&#039;expr&#039;&#039;) ifFalse:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| if (&#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;} else {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| (&#039;&#039;expr&#039;&#039;) ifTrue:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] ifFalse:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| if (!&#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;} else {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| (&#039;&#039;expr&#039;&#039;) ifFalse:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] ifTrue:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| while (&#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;}&lt;br /&gt;
| [&#039;&#039;expr&#039;&#039;] whileTrue:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
| Notice the square brackets around the condition&lt;br /&gt;
|-&lt;br /&gt;
| for (&#039;&#039;expr1&#039;&#039;;&#039;&#039;expr2&#039;&#039;;&#039;&#039;expr3&#039;&#039;) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;expr1&#039;&#039;. [&#039;&#039;expr2&#039;&#039;] whileTrue:[&amp;lt;br&amp;gt;... .&amp;lt;br&amp;gt;&#039;&#039;expr3&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| for (var i=&#039;&#039;start&#039;&#039;; i&amp;lt;=&#039;&#039;stop&#039;&#039;; i++) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;start&#039;&#039; to:&#039;&#039;stop&#039;&#039; do:[:i &amp;amp;#124;&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| for (var i=&#039;&#039;start&#039;&#039;; i&amp;lt;=&#039;&#039;stop&#039;&#039;; i+=&#039;&#039;incr&#039;&#039;) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;start&#039;&#039; to:&#039;&#039;stop&#039;&#039; by:&#039;&#039;incr&#039;&#039; do:[:i &amp;amp;#124;&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| try {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;} finally {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| [&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] ensure:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| try {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;} catch(e) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| [&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] on:Error do:[:e &amp;amp;#124;&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| try {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;} catch(e) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;} finally {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| [&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] on:Error do:[:e &amp;amp;#124;&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] ensure:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;var&#039;&#039;++&lt;br /&gt;
| &#039;&#039;var&#039;&#039; := &#039;&#039;var&#039;&#039; + 1&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;var&#039;&#039;--&lt;br /&gt;
| &#039;&#039;var&#039;&#039; := &#039;&#039;var&#039;&#039; - 1&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;arr&#039;&#039;[ &#039;&#039;idx&#039;&#039; ]&lt;br /&gt;
| &#039;&#039;arr&#039;&#039; at:&#039;&#039;idx&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;arr&#039;&#039;[ &#039;&#039;idx&#039;&#039; ]&lt;br /&gt;
| Array and Dictionary indexed fetch&amp;lt;br&amp;gt;Notice that real JavaScript uses 0-based indexing, whereas Smalltalk and expecco JavaScript is 1-based.&amp;lt;br&amp;gt;Smalltalk/X also allows the bracket notation for indexed access.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;arr&#039;&#039;[ &#039;&#039;idx&#039;&#039; ] = &#039;&#039;expr&#039;&#039;&lt;br /&gt;
| &#039;&#039;arr&#039;&#039; at:&#039;&#039;idx&#039;&#039; put:&#039;&#039;expr&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;arr&#039;&#039;[ &#039;&#039;idx&#039;&#039; ] := &#039;&#039;expr&#039;&#039;&lt;br /&gt;
| Array and Dictionary indexed store&amp;lt;br&amp;gt;Smalltalk/X also allows the bracket notation for indexed access.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
{|  Border&lt;br /&gt;
! JavaScript&lt;br /&gt;
! Smalltalk&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| %&lt;br /&gt;
| \\&amp;lt;br&amp;gt;%&lt;br /&gt;
| modulu operator&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;&amp;amp;lt;&lt;br /&gt;
| leftShift:&lt;br /&gt;
| left-shift&amp;lt;br&amp;gt;negative shift count is right-shift&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;gt;&amp;amp;gt;&lt;br /&gt;
| rightShift:&lt;br /&gt;
| right-shift&amp;lt;br&amp;gt;negative shift count is left-shift&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| bitShift:&lt;br /&gt;
| left or right shift;&amp;lt;br&amp;gt;negative shift count is right-shift&amp;lt;br&amp;gt;positive is left shift&amp;lt;br&amp;gt;(not available in JavaScript)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
More details are in the [[Smalltalk Syntax Cheat Sheet]].&lt;br /&gt;
&lt;br /&gt;
=== Array Indexing ===&lt;br /&gt;
&lt;br /&gt;
A big potential pitfall is the different indexing base used in Smalltalk vs. (standard) JavaScript: in Smalltalk, array indices start at 1 and end at the array&#039;s size. In (standard) JavaScript, indices start at 0 and end at the array&#039;s size minus 1.&lt;br /&gt;
&lt;br /&gt;
This also affects some character- and substring search functions, which return 0 (zero) in Smalltalk, whereas some of the standard JavaScript functions return -1 if nothing is found.&lt;br /&gt;
&lt;br /&gt;
The following functions expect or return 0-based indices if used in JavaScript:&lt;br /&gt;
* &#039;&#039;collection&#039;&#039;.&amp;lt;code&amp;gt;&#039;&#039;&#039;indexOf:&#039;&#039;&#039;&amp;lt;/code&amp;gt;(&#039;&#039;element&#039;&#039;)&amp;lt;br&amp;gt;attention: there exists a corresponding Smalltalk method, which returns a 1-based index&lt;br /&gt;
* &#039;&#039;collection&#039;&#039;.&amp;lt;code&amp;gt;&#039;&#039;&#039;lastIndexOf:&#039;&#039;&#039;&amp;lt;/code&amp;gt;(&#039;&#039;element&#039;&#039;)&amp;lt;br&amp;gt;attention: there exists a corresponding Smalltalk method, which returns a 1-based index&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;collection&#039;&#039;.&amp;lt;code&amp;gt;&#039;&#039;&#039;indexOf:&#039;&#039;&#039;&amp;lt;/code&amp;gt;(&#039;&#039;element&#039;&#039;, &#039;&#039;startIndex&#039;&#039;)&amp;lt;br&amp;gt;the corresponding Smalltalk method &amp;quot;&amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt;&#039;&#039;element&#039;&#039; &amp;lt;code&amp;gt;startingAt:&amp;lt;/code&amp;gt;&#039;&#039;startIndex&#039;&#039;&amp;quot; uses 1-based indices&lt;br /&gt;
* &#039;&#039;collection&#039;&#039;.&amp;lt;code&amp;gt;&#039;&#039;&#039;lastIndexOf:&#039;&#039;&#039;&amp;lt;/code&amp;gt;(&#039;&#039;element&#039;&#039;, &#039;&#039;startIndex&#039;&#039;)&amp;lt;br&amp;gt;ditto&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We admit that this is a little confusing at times, but there is no easy solution to this: and we decided to neither change the Smalltalk nor the JavaScript scripting languages inside expecco.&lt;br /&gt;
&lt;br /&gt;
To make your intentions explicit, you can use variants of the &amp;quot;&amp;lt;code&amp;gt;indexOf&amp;quot;/&amp;quot;lastIndexOf&amp;lt;/code&amp;gt;&amp;quot; functions which make these implicit differences more explicit: &amp;quot;&amp;lt;code&amp;gt;indexOf0()&amp;lt;/code&amp;gt;&amp;quot; / &amp;quot;&amp;lt;code&amp;gt;lastIndexOf0()&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;indexOf1()&amp;lt;/code&amp;gt;&amp;quot; / &amp;quot;&amp;lt;code&amp;gt;lastIndexOf1()&amp;lt;/code&amp;gt;&amp;quot; are available for both languages.&lt;br /&gt;
&lt;br /&gt;
Shame on us:&amp;lt;br&amp;gt;&lt;br /&gt;
the above array indexing behavior was changed for &amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt; between 2.7 and 2.8 (due to a missing translation, the 2.7 versions used 1-based indices in both languages).&lt;br /&gt;
This leads to a problem, if you run any old 2.7 suite in newer expecco versions without reimporting the StandardLibrary or if you used those functions in your own elementary code.&lt;br /&gt;
To avoid a need to touch those old suites, we have added a backward-bug-compatibility mode, which is described in a separate note of the release notes.&lt;br /&gt;
&lt;br /&gt;
=== Inner Functions ===&lt;br /&gt;
==== Inner Functions in JavaScript ====&lt;br /&gt;
&lt;br /&gt;
It is possible to create functions within the elementary block&#039;s code. This example shows how to do so:&lt;br /&gt;
 execute() {&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
    function f(arg1, arg2) {&lt;br /&gt;
      return(arg1 + arg2);&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
An inner function &amp;quot;f&amp;quot; is created with two arguments (&amp;quot;arg1&amp;quot; and &amp;quot;arg2&amp;quot;), which returns the sum of both. The function is called like this:&lt;br /&gt;
   f(3,5)&lt;br /&gt;
Inner functions can be used for example to filter specific elements from collections, as in:&lt;br /&gt;
   function isEven(n) { return n.even(); }&lt;br /&gt;
 &lt;br /&gt;
   var numbers = [1,2,3,4,5,6,7];&lt;br /&gt;
   var evenNumbers = numbers.select( isEven );&lt;br /&gt;
&lt;br /&gt;
Inner functions are &#039;&#039;&#039;first class objects&#039;&#039;&#039;: they can be stored in variables, collections, passed as argument or returned from functions. They can even be passed to other blocks via input- and output pins or via environment variables. Functions can be anonymous; the above example could also be written as:&lt;br /&gt;
 execute() {&lt;br /&gt;
    var f;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
    f = function (arg1, arg2) {&lt;br /&gt;
      return(arg1 + arg2);&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
(notice the missing function name after the &amp;quot;function&amp;quot; keyword).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice, that there is a difference in the behavior of the return statement between JavaScript inner functions and Smalltalk blocks:&lt;br /&gt;
a JavaScript &amp;quot;return&amp;quot; statement inside an inner function returns from that inner function only, whereas a return in Smalltalk always returns from the outer-most method.&lt;br /&gt;
&lt;br /&gt;
To return from the outermost function in JavaScript, use the &amp;quot;&amp;lt;CODE&amp;gt;return from &amp;amp;lt;&#039;&#039;fnName&#039;&#039;&amp;amp;gt;&amp;lt;/CODE&amp;gt;&amp;quot; statement form.&lt;br /&gt;
&lt;br /&gt;
In expecco, where the outermost function is always named &amp;quot;&#039;&#039;execute&#039;&#039;&amp;quot;, write:&lt;br /&gt;
    execute() {&lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
       function myFunction() {&lt;br /&gt;
           &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
           return from execute;&lt;br /&gt;
       }&lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
(notice that the execute function is not supposed to return a value)&lt;br /&gt;
&lt;br /&gt;
===== Lambda Expressions in JavaScript =====&lt;br /&gt;
&lt;br /&gt;
JavaScript functions can also be written in a slightly shorter lambda notation as:&lt;br /&gt;
    (arg1, ... argN) =&amp;gt; { statement; ... return expression; }&lt;br /&gt;
or (with a single argument) as:&lt;br /&gt;
    arg =&amp;gt; { statement; ... return expression; }&lt;br /&gt;
or (without arguments) as:&lt;br /&gt;
    () =&amp;gt; { statement; ... return expression; }&lt;br /&gt;
and results in a function object comparable to:&lt;br /&gt;
    function (arg1, ... argN) { statement; ... return expression; }&lt;br /&gt;
&lt;br /&gt;
The function&#039;s body may also be a single expression (without braces), as:&lt;br /&gt;
    arg =&amp;gt; expression&lt;br /&gt;
For example:&lt;br /&gt;
    aCollection.map( el =&amp;gt; el ** 2 )&lt;br /&gt;
returns a collection of squared numbers,&lt;br /&gt;
the same as the corresponding Smalltalk code:&lt;br /&gt;
    aCollection map:[:el | el ** 2 ]&lt;br /&gt;
This is plain &amp;quot;syntactic sugar&amp;quot; - it does not give any new semantic functionality, but makes the code shorter and possibly easier to read.&lt;br /&gt;
&lt;br /&gt;
==== Inner Functions in Smalltalk (Blocks) ====&lt;br /&gt;
&lt;br /&gt;
In Smalltalk, inner functions are called &amp;quot;&#039;&#039;block&#039;&#039;&amp;quot;, and are defined as:&lt;br /&gt;
   f := [:arg1 :arg2 | arg1 + arg2 ].&lt;br /&gt;
This block can be called by sending at a &amp;quot;&amp;lt;code&amp;gt;value:value:&amp;lt;/code&amp;gt;&amp;quot; message (i.e. one &amp;quot;&amp;lt;code&amp;gt;value:&amp;lt;/code&amp;gt;&amp;quot; for each argument) &amp;lt;sup&amp;gt;(1)&amp;lt;/sup&amp;gt;:&lt;br /&gt;
   f value:3 value:5&lt;br /&gt;
or by passing an array of argument values with &amp;quot;&amp;lt;code&amp;gt;valueWithArguments:&amp;lt;/code&amp;gt;&amp;quot; as in:&lt;br /&gt;
   args := #(3 5).   &amp;quot;/ an array constant&lt;br /&gt;
   f valueWithArguments:args&lt;br /&gt;
or:&lt;br /&gt;
   args := { 3 . 5 }. &amp;quot;/ a computed array&lt;br /&gt;
   f valueWithArguments:args&lt;br /&gt;
&lt;br /&gt;
The returned value is the value of the last expression inside the block. Thus, blocks can contain multiple expressions separated by a period:&lt;br /&gt;
   f := [:arg1 :arg2 | &lt;br /&gt;
             Transcript showCR: e&#039;my first arg is: {arg1}&#039;.&lt;br /&gt;
             Transcript showCR: e&#039;my second arg is: {arg2}&#039;.&lt;br /&gt;
             arg1 + arg2 &amp;quot;/ the block&#039;s return value&lt;br /&gt;
        ].&lt;br /&gt;
This is in contrast to a JavaScript inner function, where an explicit &amp;quot;return&amp;quot; statement is needed. The return value of JavaScript inner function without an explicit return will be void.&lt;br /&gt;
Therefore, the above inner function in JavaScript has to have a return:&lt;br /&gt;
   f = function(arg1, arg2) { &lt;br /&gt;
             Transcript.showCR(&#039;my first arg is: &#039;+arg1);&lt;br /&gt;
             Transcript showCR(&#039;my second arg is: &#039;+arg2);&lt;br /&gt;
             return (arg1 + arg2); // the function&#039;s return value&lt;br /&gt;
       };&lt;br /&gt;
&lt;br /&gt;
Blocks without argument are defined as:&lt;br /&gt;
   f := [ Transcript showCR:&#039;blabla: Euler was great&#039; ].&lt;br /&gt;
and invoked with a simple &amp;quot;&amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
In both JavaScript and Smalltalk code, it is an error to invoke an inner function/block with a wrong number of arguments &amp;lt;sup&amp;gt;(2)&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Smalltalk blocks and JavaScript inner functions can be used interchangeable - i.e. it is possible to pass a JS inner function to a collection method such as &amp;quot;&amp;lt;code&amp;gt;collect:&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;select:&amp;lt;/code&amp;gt;&amp;quot;. It is also possible, to pass either via input/output pins to other activities (which is not considered good style, as it could make the program quite hard to understand, if not used with caution).&lt;br /&gt;
&lt;br /&gt;
Notice again, that the behavior of the Smalltalk return (&amp;quot;^&amp;quot;) is different from a JavaScript return (&amp;quot;&#039;&#039;return-Statement&#039;&#039;&amp;quot;) inside inner functions. The JavaScript return returns a value from the inner function, whereas the Smalltalk return forces a return from the containing method (the block&#039;s &amp;quot;execute&amp;quot; method). The Smalltalk return always behaves like the &amp;quot;&amp;lt;I&amp;gt;return from execute&amp;lt;/I&amp;gt;&amp;quot; JavaScript special form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt; Smalltalk/X allows for a non-standard block evaluation message using the &amp;quot;normal&amp;quot; parentheses notation. I.e. you can call a block with its arguments in parentheses as in &amp;quot;&amp;lt;code&amp;gt;f(1, 2, 3)&amp;lt;/code&amp;gt;. This is syntactic sugar for the standard &amp;lt;code&amp;gt;f value:1 value:2 value:3&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt; in Smalltalk, you can define &amp;quot;&#039;&#039;varargs blocks&#039;&#039;&amp;quot; with the &amp;quot;&amp;lt;code&amp;gt;asVarArgBlock&amp;lt;/code&amp;gt;&amp;quot; message. The block will then receive its arguments as a vector, and fetch them using collection protocol (i.e. &amp;quot;size&amp;quot;, &amp;quot;at:&amp;quot; or enumeration messages like &amp;quot;do:&amp;quot;). For example,&lt;br /&gt;
 b := [:args | Transcript showCR: e&#039;my arguments are {args}&#039; ] asVarArgBlock&lt;br /&gt;
can be called with any number of arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example uses for Inner Functions ====&lt;br /&gt;
&lt;br /&gt;
In Smalltalk, blocks are very often used when enumerating collections.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, code corresponding to a C# 3.0 collection &amp;quot;&amp;lt;code&amp;gt;select (where(x =&amp;gt; ...))&amp;lt;/code&amp;gt;&amp;quot; is written in Smalltalk as:&lt;br /&gt;
    |names namesStartingWithA|&lt;br /&gt;
 &lt;br /&gt;
    names := #( &#039;Alice&#039; &#039;Ann&#039; &#039;Bob&#039; &#039;Mallory&#039; ).&lt;br /&gt;
    namesStartingWithA := names select:[:n | n startsWith:&#039;A&#039;].&lt;br /&gt;
&lt;br /&gt;
or in JavaSript as:&lt;br /&gt;
    var names, namesStartingWithA;&lt;br /&gt;
 &lt;br /&gt;
    names = [ &amp;quot;Alice&amp;quot; , &amp;quot;Ann&amp;quot; , &amp;quot;Bob&amp;quot; , &amp;quot;Mallory&amp;quot; ];&lt;br /&gt;
    namesStartingWithA = names.select( function(n) { n.startsWith(&amp;quot;A&amp;quot;); } );&lt;br /&gt;
or alternative using lambda expressions as:&lt;br /&gt;
    var names, namesStartingWithA;&lt;br /&gt;
 &lt;br /&gt;
    names = [ &amp;quot;Alice&amp;quot; , &amp;quot;Ann&amp;quot; , &amp;quot;Bob&amp;quot; , &amp;quot;Mallory&amp;quot; ];&lt;br /&gt;
    namesStartingWithA = names.select( n =&amp;gt; n.startsWith(&amp;quot;A&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
To find the first element in a collection, for which some condition is true, use:&lt;br /&gt;
    |names firstNameContainingAnO|&lt;br /&gt;
 &lt;br /&gt;
    names := #( &#039;Alice&#039; &#039;Ann&#039; &#039;Bob&#039; &#039;Mallory&#039; ).&lt;br /&gt;
    firstNameContainingAnO:= names detect:[:n | n includesString:&#039;o&#039;].&lt;br /&gt;
&lt;br /&gt;
or in JavaSript as:&lt;br /&gt;
    var names, firstNameContainingAnO;&lt;br /&gt;
 &lt;br /&gt;
    names = [ &amp;quot;Alice&amp;quot; , &amp;quot;Ann&amp;quot; , &amp;quot;Bob&amp;quot; , &amp;quot;Mallory&amp;quot; ];&lt;br /&gt;
    firstNameContainingAnO = names.detect( function(n) { n.includesString(&amp;quot;o&amp;quot;); } );&lt;br /&gt;
&lt;br /&gt;
For more information on the Smalltalk syntax, see [[http://live.exept.de/doc/online/english/getstart/tut_2.html Smalltalk Basics]] in the [[http://live.exept.de/doc/online/english/getstart/tutorial.html Smalltalk Online Tutorial]].&lt;br /&gt;
&lt;br /&gt;
=== Builtin Data Types ===&lt;br /&gt;
&lt;br /&gt;
The builtin types below and user defined primary types are mapped to corresponding classes of the underlying Smalltalk runtime system.&lt;br /&gt;
An introductory overview and links to the detailed documentation of individual classes is found in the&lt;br /&gt;
[http://live.exept.de/doc/online/english/classDoc/TOP.html Smalltalk Class Documentation] of the [http://live.exept.de/doc/online/english/TOP.html Smalltalk/X online documentation]. The following gives a rough summary of the main concepts. A good entry point for further learning is the [http://live.exept.de/doc/online/english/overview/basicClasses/TOP.html Smalltalk/X Basic Classes Overview Document], which provides links to the most heavily used classes and more detailed information.&lt;br /&gt;
&lt;br /&gt;
==== Numeric Types ====&lt;br /&gt;
&lt;br /&gt;
The underlying numeric type implementation supports multiple number representations. These can be used transparently in mixed-operations, and values are automatically converted as required. For example, the division of two integers returns another integer iff the division does not produce a remainder. Otherwise, a fraction object is returned.&lt;br /&gt;
Although very very rarely required in practice,&lt;br /&gt;
values can be converted explicitly, via one of the &amp;quot;&amp;lt;code&amp;gt;asXXX&amp;lt;/code&amp;gt;&amp;quot; messages:&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat64()&amp;lt;/code&amp;gt; - to convert to a double precision IEEE 64bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat32()&amp;lt;/code&amp;gt; - to convert to a single precision IEEE 32bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat80()&amp;lt;/code&amp;gt; - to convert to an extended precision IEEE 80bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat128()&amp;lt;/code&amp;gt; - to convert to an extended precision IEEE 128bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asInteger()&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;asFraction()&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;asScaledDecimal(scale)&amp;lt;/code&amp;gt;&lt;br /&gt;
the older API is still supported, but less self explanatory:&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat()&amp;lt;/code&amp;gt; - to convert to a double precision IEEE 64bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asShortFloat()&amp;lt;/code&amp;gt; - to convert to a single precision IEEE 32bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asLongFloat()&amp;lt;/code&amp;gt; - to convert to an extended precision IEEE 80bit float&lt;br /&gt;
&lt;br /&gt;
Thus, if you want to avoid fractions (why would you?), process the result of an integer division using one of the &amp;lt;code&amp;gt;asFloat()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;truncated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;floor()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ceiling()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;rounded()&amp;lt;/code&amp;gt; functions. But be aware that fractions provide an exact result, whereas float arithmetic is inherently imprecise, rounds on the the last bit and that such rounding errors accumulate.&lt;br /&gt;
&lt;br /&gt;
===== Integer =====&lt;br /&gt;
&lt;br /&gt;
This represents arbitrary precision integral numbers. Conversion and memory allocation is completely automatic.&lt;br /&gt;
&amp;lt;br&amp;gt;Thus, without danger of overflow, you can write:&lt;br /&gt;
 x = 1234567890 * 12345678901234567890 / 10&lt;br /&gt;
to get: &lt;br /&gt;
 1524157875171467887501905210&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
 x = 100.factorial();&lt;br /&gt;
to get the huge number:&lt;br /&gt;
 933262154439441526816992388562667004907159682643816214685929638952175999932299156089&lt;br /&gt;
 41463976156518286253697920827223758251185210916864000000000000000000000000&lt;br /&gt;
&lt;br /&gt;
Small integer values (smaller than 32 or 64bit, depending in the underlying hardware&#039;s native word length) are stored more efficiently than large integers - however, the conversion and representation as used by the system is transparent and automatic.&lt;br /&gt;
The same is true for mixed mode arithmetic between small and large integers.&lt;br /&gt;
&lt;br /&gt;
Occasionally it is required to perform modulo arithmetic in 32 or 64bit; for example to reproduce or check values as generated by C or Java programs. For this, use methods from the &amp;quot;&#039;&#039;special modulo&#039;&#039;&amp;quot; category, such as &amp;quot;&amp;lt;code&amp;gt;add_32()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;add_32u()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;mul_32()&amp;lt;/code&amp;gt;&amp;quot; etc. Use a [[Tools_ClassBrowser|class browser]] to find those methods.&lt;br /&gt;
&lt;br /&gt;
Integer constants (of arbitrary size) can be given in hexadecimal (Smalltalk: 16rxxx, JavaScript 0xXXXX), octal (Smalltalk: 8rxxx, JavaScript 0XXXX), and binary (Smalltalk: 2rxxx, JavaScript 0bXXXX). In fact, Smalltalk supports any base from 2 to 36 written as &amp;amp;lt;b&amp;amp;gt;rxxx, where &amp;amp;lt;b&amp;amp;gt; is the base. Thus 3r100 is the ternary representation of the integer 9.&lt;br /&gt;
For ease of use, Smalltalk also supports 0x, 0o and 0b radix prefixes (hex, octal and binary).&lt;br /&gt;
&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#INTEGER More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Integer Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Float =====&lt;br /&gt;
&lt;br /&gt;
Float represents double precision IEEE floating point numbers (64bit).&lt;br /&gt;
Although seldom needed, conversion to single precision (32bit) and high precision (80bit/128bit, depending on the underlying hardware) is possible via the &#039;&#039;asShortFloat()&#039;&#039; and &#039;&#039;asLongFloat()&#039;&#039; conversion functions.&amp;lt;br&amp;gt;Notice that the actual precision of longFloat numbers depends on the CPU: x86 and x86_64 provide 80bits, Sparc and a few other CPUs provide 128 bits.&lt;br /&gt;
&lt;br /&gt;
For more precision, additional classes called &amp;quot;&amp;lt;code&amp;gt;QDouble&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;LargeFloat&amp;lt;/code&amp;gt;&amp;quot; are provided: QDouble provides roughly 200 bits (70 digits) of precision, and LargeFloat offers an arbitrary (configurable) precision. Both are described in the [[Numeric Limits/en|Numeric Limits]] and [[Number_API_Functions|Number API Functions]] documents. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;[[Number_API_Functions|Number API Functions]]&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#FLOAT More Info] in the Smalltalk/X online documentation&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Float Class Documentation]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,ShortFloat ShortFloat],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,LongFloat LongFloat],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,QDouble QDouble]&lt;br /&gt;
&amp;lt;!-- [http://live.exept.de/ClassDoc/classDocOf:,LargeFloat LargeFloat ] --&amp;gt;&lt;br /&gt;
Class Documentation&lt;br /&gt;
&amp;lt;br&amp;gt;Details on QDoubles in [https://www.davidhbailey.com/dhbpapers/qd.pdf https:/www.davidhbailey.com/dhbpapers/qd.pdf].&lt;br /&gt;
 &lt;br /&gt;
====== Float Rounding Errors ======&lt;br /&gt;
Be reminded that floating point arithmetic is inherently inaccurate: there will almost always be rounding errors on the last bit. The reason is inherent in that most rational numbers simply cannot be represented as the sum of powers of two. For example, 0.1 and 0.3 are two of them: no sum of powers of two (1/2, 1/4, 1/8, ...) is able to represent these numbers exactly. Thus, there will definitely be an error in the last bit of the stored float value.&lt;br /&gt;
&lt;br /&gt;
Typically, print functions (which convert floating point values to a string representation) will &amp;quot;cheat&amp;quot; and round on the last bit. However, if you operate with such numbers (i.e. add, multiply, etc.) these rounding errors will accumulate and may finally add up to more than one bit of error. When this happens, the print function will no longer round up, and you will get the typical &amp;quot;.999999&amp;quot; result strings.&lt;br /&gt;
&lt;br /&gt;
As an example, try adding 0.3 a thousand times, as in:&lt;br /&gt;
&lt;br /&gt;
 |t|&lt;br /&gt;
 t := 0.3.&lt;br /&gt;
 1000 timesRepeat:[t := t + 0.3].&lt;br /&gt;
 t print&lt;br /&gt;
may give &amp;quot;300.300000000006&amp;quot; as a result.&lt;br /&gt;
&lt;br /&gt;
As a consequence, NEVER ever compare floating point values for equality. In the above case, the comparison with &amp;quot;300.3&amp;quot; would return false!&lt;br /&gt;
&lt;br /&gt;
Floating point numbers should always be compared by giving a range (i.e. between x-delta and x+delta) or by giving a number of valid digits or bits, by which to compare.&lt;br /&gt;
expecco provides a number of action blocks for this kind of &amp;quot;&#039;&#039;almost-equal&#039;&#039;&amp;quot; comparisons.&lt;br /&gt;
&lt;br /&gt;
Of course, there are also similar functions in the Float class, in case you need this in elementary Smalltalk or JavaScript code.&lt;br /&gt;
&lt;br /&gt;
And also: NEVER ever compute monetary values using floating point - or your legal advisor will blame you for missing Cents in the invoice. Monetary values should never be processed with floats (expecco provides a ScaledDecimal number type for that, as described below).&lt;br /&gt;
&lt;br /&gt;
Problems with numbers are discussed in detail in &amp;quot;[[Numeric Limits/en|Numeric Limits]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== Fraction =====&lt;br /&gt;
&lt;br /&gt;
Fractions are arbitrary-precision rational numbers. You will get them when dividing two integers and the result is not integral. Fractions represent an exact result, in contrast to floats, which are only approximations.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 1 / 3&lt;br /&gt;
returns a fractional result with a numerator of 1 and a denominator of 3 (as opposed to the Smalltalk // operator, which truncates the result of the division to an integer).&lt;br /&gt;
&lt;br /&gt;
Fractions have the advantage of avoiding rounding errors. Thus, when the above fraction is divided by 3, you will get &#039;&#039;(1/9)&#039;&#039;, which we can multiply by 9 to get the exact &#039;&#039;1&#039;&#039; (an integer) without any rounding error. Be reminded that this is typically not the case with Float or Double precision numbers. Due to rounding errors on the last bit, you will often get 0.9999999 as a result there (even though printf may &amp;quot;cheat&amp;quot; and round it to &amp;quot;1.0&amp;quot;, as long as the error is in the last bit only; however, when doing multiple operations in a row, these errors accumulate into the next bit, and rounding will no longer generate a &amp;quot;nice looking&amp;quot; output).&lt;br /&gt;
&lt;br /&gt;
Fraction results are automatically reduced - therefore, when adding &#039;&#039;(1/3) + (2/6)&#039;&#039;, you will get &#039;&#039;(2/3)&#039;&#039;.&lt;br /&gt;
&amp;lt;br&amp;gt;And if you add another &#039;&#039;(1/3)&#039;&#039; to it, you will get an exact &#039;&#039;1&#039;&#039;.&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
Be aware that fractional arithmetic is done by software, whereas floating point arithmetic is done by CPU instructions.&lt;br /&gt;
Therefore, floating point arithmetic is usually faster.&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#FRACTION More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Fraction Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== ScaledDecimal =====&lt;br /&gt;
&lt;br /&gt;
ScaledDecimal (also called &amp;quot;&#039;&#039;FixedPoint&#039;&#039;&amp;quot;) numbers are decimals, with a configurable number of post-decimal digits. They are typically used when dealing with money. Like fractions, they avoid rounding errors. When printed, they round in their last digit, however, the exact information is always kept for further processing. ScaledDecimal numbers are perfect to represent money and other fractional data, which must be represented with a fixed number of post-decimal digits. Internally, fixed point numbers are represented as fractions with a power-of-10 denominator.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
ScaledDecimal numbers are also great to print tabular data; for example: &amp;lt;code&amp;gt;someNumber as ScaledDecimal:3&amp;lt;/code&amp;gt; will print the number with and rounded to 3 post-decimal digits.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#FIXEDPOINT More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,FixedPoint Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Complex=====&lt;br /&gt;
&lt;br /&gt;
Complex numbers with real and imaginary part are sometimes used in technical/physical applications.&lt;br /&gt;
They can be read as &amp;quot;&amp;lt;code&amp;gt;a * b i&amp;lt;/code&amp;gt;&amp;quot;, for example: &amp;quot;&amp;lt;code&amp;gt;5 + 3i&amp;lt;/code&amp;gt;&amp;quot; represents the complex number with 5 as real and 3 as imaginary part.&lt;br /&gt;
&lt;br /&gt;
Complex numbers can result from math functions such as sqrt and log (by default, these raise an error, which can be ignored for a complex result)&lt;br /&gt;
&amp;lt;!-- &amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#COMPLEX More Info] --&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Complex Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Number =====&lt;br /&gt;
&lt;br /&gt;
The Number type is an abstract union type which includes all of the above types. Thus, a variable or pin declared as being of &amp;quot;&amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt;&amp;quot; type can take any of the above values. Due to the polymorphic implementation of the underlying numeric class library, most operations can be passed any of the above values (even mixing arguments is possible). For example, the &amp;quot;[Add]&amp;quot; elementary block, which is implemented by simply calling the Smalltalk &amp;quot;+&amp;quot; operation, is able to deal with any combination of argument types.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#NUMBER More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Number Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== String Types ====&lt;br /&gt;
&lt;br /&gt;
Strings can come in three flavours (subclasses of CharacterArray), depending on how many bits are required to encode the character&#039;s code point. In general, Unicode is used internally as the encoding. However, converters are available to translate into other encodings, such as JIS or ISO 8859-x.&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|16px]] Notice that ASCII (0..127) and ISO 8859-1 (0..255) are proper subsets of the Unicode set.&lt;br /&gt;
Do not confuse Unicode with UTF-8: Unicode is the numeric value associated to a character and used everywhere within expecco.&lt;br /&gt;
UTF-8 is an encoding format for data interchange of Unicode characters. UTF-8 is NOT used inside expecco, only for data exchange with the external world (see &amp;quot;[[String_API_Functions#Encoding_.2F_Decoding|Encoding and Decoding]]&amp;quot; in the String API doc).&lt;br /&gt;
&lt;br /&gt;
In most situations, you do not need to care for the actual number of bits required to store the characters, and expecco/Smalltalk takes care of the actual representation in memory. However, when dealing with the external world (files, sockets, devices), it may be required to perform explicit conversions to/from wider formats or different encodings (UTF-8, UTF-16, etc.)&lt;br /&gt;
&lt;br /&gt;
===== String=====&lt;br /&gt;
&lt;br /&gt;
This is used to represent character strings, where each individual character has a one-byte encoding. I.e. the values are 0..255.&lt;br /&gt;
Individual characters of a string can be accessed by an integral index starting with 1 in both Smalltalk and JavaScript. The String class provides many useful functions for substring searching, matching, concatenation/replacing etc.&lt;br /&gt;
Also, because String inherits all functions from the Collection superclass hierarchy, all enumeration, mapping, filtering functions are also applicable to strings.&lt;br /&gt;
&amp;lt;br&amp;gt;See also: [[String API Functions | &#039;&#039;Most Useful String Functions&#039;&#039;]] and [[Collection API Functions | &#039;&#039;Most Useful Collection Functions&#039;&#039;]]&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#STRING More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,String Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Unicode16String =====&lt;br /&gt;
&lt;br /&gt;
This is used to represent character strings, where at least one character needs a two-byte encoding. I.e. any character&#039;s code point is in the range 0x0100 .. 0xFFFF. In fact, there is even a Unicode32String class (see below), which supports the full four-byte Unicode character set. But in practice, such strings are very rarely ever encountered or needed.&lt;br /&gt;
&lt;br /&gt;
===== Unicode32String =====&lt;br /&gt;
&lt;br /&gt;
This is used to represent character strings, where at least one character needs more than a two-byte encoding. I.e. any character&#039;s code point is above 0xFFFF. Such strings are very rarely ever encountered or needed.&lt;br /&gt;
&lt;br /&gt;
===== Character =====&lt;br /&gt;
Individual characters (as extracted from a string or possibly read from a file) are represented as instances of the Character class. Queries are available to ask the character for its type (isLetter, isDigit etc.) or its Unicode encoding (codePoint). There is virtually no limit and every character from the full Unicode set (e.g. even above 0xFFFF) can be represented by instances of the Character class.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#CHARACTER More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Character Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== Collection Types ====&lt;br /&gt;
&lt;br /&gt;
Smalltalk and therefore also expecco provides a very complete set of collection types which are tuned for different access patterns or memory consumption.&lt;br /&gt;
An introductory overview on the collection classes is found in the&lt;br /&gt;
&amp;lt;br&amp;gt;Most Useful API: [[Collection API Functions | Most Useful Collection Functions]]&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html Collections Overview] of the [http://live.exept.de/doc/online/english/TOP.html Smalltalk/X online documentation].&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Collection Class Documentation]&lt;br /&gt;
&lt;br /&gt;
The following paragraphs list the most used collection classes. &lt;br /&gt;
Notice, that Smalltalk provides many more container classes, so please take a look at the online documentation or take a life tour with the browser.&lt;br /&gt;
&lt;br /&gt;
===== Array =====&lt;br /&gt;
&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1 in both Smalltalk and JavaScript.&lt;br /&gt;
Can store any type of object, and storage requirements are 1 machine word per element (i.e. arrays store pointers to the elements). As the size is fixed (when created), adding and removing of&lt;br /&gt;
elements is not possible. Use one of the other collections (OrderedCollection, Set or Dictionary) if the number&lt;br /&gt;
of elements needs to change later or is not known in advance.&lt;br /&gt;
&amp;lt;br&amp;gt;When accessing elements by index, access time complexity is constant O(1).&amp;lt;br&amp;gt;A search for an element in an Array (using &amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;findFirst:&amp;lt;/code&amp;gt; or similar methods) has O(N) time complexity (because the search is linear through all elements of the array).&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#ARRAY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Array Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== ByteArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;ByteArrays can only store very small byte-valued unsigned integers (0..255), and allocate 1 byte per element. Access time and complexity are like with ordinary arrays, but the required memory is much less. ByteArrays are used to represent the contents of binary data, binary files, bitmap images, protocol elements (data packets) or low level memory dumps.&lt;br /&gt;
&amp;lt;br&amp;gt;UInt8Array is an alias for ByteArray.&lt;br /&gt;
&amp;lt;br&amp;gt; Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#BYTEARRAY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,ByteArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SignedByteArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;These store very small 8bit signed integer values (-128..127), requiring 1 byte of storage per element.&lt;br /&gt;
&amp;lt;br&amp;gt;Int8Array is an alias for SignedByteArray.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SignedByteArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== BitArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;BitArrays can only store tiny bit-valued unsigned integers (0..1), but only need one byte of storage for every 8 elements.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,BitArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== BooleanArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;BooleanArrays can only store booleans (false..true), but only need 1 byte for every 8 stored boolean elements.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,BooleanArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== FloatArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;FloatArrays store short IEEE floats (32bit) and allocate 4 bytes per element.&lt;br /&gt;
Access times and complexity are like those of regular arrays, but they require much less memory. FloatArrays are often used for data interchange with C language functions or in data acquisition scenarios (series of measurement values).&lt;br /&gt;
&amp;lt;br&amp;gt;Float32Array is an alias for FloatArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#FLOATARRAY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,FloatArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== DoubleArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;DoubleArrays store IEEE doubles (64bit) and allocate 8 bytes per element.&lt;br /&gt;
These are used in similar situations as FloatArrays.&lt;br /&gt;
&amp;lt;br&amp;gt;Float64Array is an alias for DoubleArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#FLOATARRAY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,DoubleArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== HalfFloatArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;HalfFloatArray can only store IEEE half floats (16bit) and allocate 2 bytes per element.&lt;br /&gt;
: [[Datei:bulb.png|16px]] Notice that half floats have a very low precision and are seldom used.&lt;br /&gt;
: Exceptions are game programs and 3D graphics accelerators which preserve memory by using this very compact format for depth information, texture attributes and some audio formats. They are also used with AI programs in neural networks.&lt;br /&gt;
&amp;lt;br&amp;gt;Float16Array is an alias for HalfFloatArray , and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&lt;br /&gt;
===== IntegerArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;These store small 32bit unsigned integer values (0..0xFFFFFFFF) and require 4 bytes of storage per element.&lt;br /&gt;
&amp;lt;br&amp;gt;UInt32Array is an alias for IntegerArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,IntegerArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SignedIntegerArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;They store small 32bit signed integer values (-0x800000000..0x7FFFFFFF), requiring 4 bytes of storage per element.&lt;br /&gt;
&amp;lt;br&amp;gt;Int32Array is an alias for SignedIntegerArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SignedIntegerArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== WordArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;They store small 16bit unsigned integer values (0..0xFFFF), allocating 2 bytes per element.&lt;br /&gt;
&amp;lt;br&amp;gt;UInt16Array is an alias for WordArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,WordArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SignedWordArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;They store small 16bit signed integer values (-0x8000..0x7FFF), allocating 2 bytes per element.&lt;br /&gt;
&amp;lt;br&amp;gt;Int16Array is an alias for SignedWordArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SignedWordArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== LongIntegerArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;They store small 64bit unsigned integer values (0..0xFFFFFFFFFFFFFF), allocating 8 bytes per element.&lt;br /&gt;
&amp;lt;br&amp;gt;UInt64Array is an alias. &lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,LongIntegerArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SignedLongIntegerArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;These store small 64bit signed integer values (-0x80000000000000000..0x7FFFFFFFFFFFFFFF), allocating 8 bytes per element.&lt;br /&gt;
&amp;lt;br&amp;gt;Int64Array is an alias. &lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SignedLongIntegerArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== ComplexFloatArray and ComplexDoubleArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;These store complex numbers as pairs of IEEE floats (32bit) or doubles (64bit) and allocate 8/16 bytes per element.&lt;br /&gt;
These are used in similar situations as FloatArrays and DoubleArrays.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,ComplexFloatArray] [http://live.exept.de/ClassDoc/classDocOf:,ComplexDoubleArray]&lt;br /&gt;
&lt;br /&gt;
===== OrderedCollection =====&lt;br /&gt;
Ordered, variable size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;OrderedCollections can store any type of object and are specifically tuned for adding/removing elements at either end.&lt;br /&gt;
&amp;lt;br&amp;gt;Access time to elements by index has a time complexity of O(1).&lt;br /&gt;
&amp;lt;br&amp;gt;Insertion and remove at either end approach O(1), but is O(n) for inner elements, because the elements are moved inside a linear container.&lt;br /&gt;
When searching for an element in an OrderedCollection (using &amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt; or similar methods), time complexity is O(n) (because a linear search is done).&lt;br /&gt;
&lt;br /&gt;
Java users will recognize the similarity to &amp;quot;&#039;&#039;ArrayLists&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note: For very big or lightly sparse collections, you can use a [http://live.exept.de/ClassDoc/classDocOf:,SegmentedOrderedCollection SegmentedOrderedCollection]. This uses a hierarchy of buckets and does not need storage for big unused regions inside the collection. However, due to the additional computations, the breakeven in performance compared to regular OrderedCollections is usually at around 100K to 1M elements.&lt;br /&gt;
&lt;br /&gt;
Note: For very very big collections (millions of elements) which are very lightly filled, use a [http://live.exept.de/ClassDoc/classDocOf:,SparseArray SparseArray]. This only keeps the filled slots, and is great, if you have only a few valid elements inside a virtually huge index space.&lt;br /&gt;
&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#ORDCOLL More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,OrderedCollection Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SortedCollection =====&lt;br /&gt;
Sorts itself, variable size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;SortedCollections can store any type of object for which a order relationship is either implicit (i.e. the elements responds to the &amp;quot;&amp;lt;code&amp;gt;&amp;lt;&amp;lt;/code&amp;gt;&amp;quot; (less) message) or for which an explicit comparison block can is given (i.e. you provide a sort-block, which takes two elements and returns a boolean depending on the ordering).&lt;br /&gt;
&lt;br /&gt;
By default, sorting is by ascending order based on the &amp;quot;&amp;lt;code&amp;gt;&amp;lt;&amp;lt;/code&amp;gt;&amp;quot;-message. However, the sort order can be arbitrarily changed by setting the sortBlock, a two-argument JS-function or a two-argument Smalltalk block which should return true, if its first argument is to be &amp;quot;&#039;&#039;considered&#039;&#039;&amp;quot; smaller than the order&amp;lt;br&amp;gt;(i.e. the default sort block is &amp;quot;&amp;lt;code&amp;gt;[:a :b | a &amp;lt; b]&amp;lt;/code&amp;gt;&amp;quot; or in Javascript: &amp;quot;&amp;lt;code&amp;gt;(a,b) =&amp;gt; a &amp;lt; b&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Access time complexity by numeric index is O(1).&amp;lt;br&amp;gt;When searching for an element in a SortedCollection (using &amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt; or similar methods); time complexity is O(log n), because a binary search can be done.&amp;lt;br&amp;gt;Insertion and remove is O(1) for the first and last element, O(log n + n) for inner elements, because the insert index is first searched, then elements are moved inside a linear container.&lt;br /&gt;
&lt;br /&gt;
When a big sorted collection is created, it is faster to first create it as a non-sorted collection (OrderedCollection) and then converting the whole collection via &amp;lt;code&amp;gt;asSortedCollection&amp;lt;/code&amp;gt;, instead of adding individual elements one-by-one.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#SORTCOLL More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SortedCollection Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Set =====&lt;br /&gt;
Unordered, variable size, keeps a single reference only, per equal element.&lt;br /&gt;
&amp;lt;br&amp;gt;Sets can store any type of object.&lt;br /&gt;
When searching a Set for an element (eg. using the &amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt; method), time complexity approaches O(1), because the search can be done based on a hashing algorithm in asymptotic constant time (however, the time to compute the hash of an element may affect the effective execution time; it should not be too slow). For very small sets, the hash-computation time might be long compared to the time it takes to compare elements. It may then be faster to simply use an Array or OrderedCollection and do a sequential search (use eg. &amp;quot;includes:&amp;quot;, &amp;quot;indexOf:&amp;quot; or &amp;quot;anySatisfy:&amp;quot;).&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#SET More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Set Class Documentation]&lt;br /&gt;
&amp;lt;br&amp;gt;In addition to the unordered Set, useful classes are also &amp;lt;code&amp;gt;[http://live.exept.de/ClassDoc/classDocOf:,OrderedSet OrderedSet]&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[http://live.exept.de/ClassDoc/classDocOf:,SortedSet SortedSet]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Bag =====&lt;br /&gt;
Unordered, variable size, keeps a count, per equal element. Adding, removing and insertion check all run in O(1).&lt;br /&gt;
Can store any type of object.&lt;br /&gt;
&amp;lt;br&amp;gt;Bags are similar to Sets, but keep the number of occurrences of each element. Thus, bags are perfect to count the number of elements in a collection, for example words and word counts in a document. &lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Bag Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
Unordered, variable size, implements arbitrary key-value mappings.&lt;br /&gt;
&amp;lt;br&amp;gt;Dictionaries can store any type of object and use any kind of object as key.&lt;br /&gt;
When accessing or searching an element in a Dictionary (using &amp;lt;code&amp;gt;at:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;includesKey:&amp;lt;/code&amp;gt; and similar methods), the time complexity asymptotically approaches O(1), because the key search is based on a hashing algorithm. Notice, that the same value may be stored multiple times in a dictionary (i.e. stored under multiple keys).&lt;br /&gt;
Asking for the presence of a particular &#039;&#039;&#039;value&#039;&#039;&#039; in the dictionary (i.e. the reverse query without key) still has O(N) time complexity.&lt;br /&gt;
&lt;br /&gt;
If you need fast access both via the key and the value, either use an additional reverse mapping dictionary, or store&lt;br /&gt;
an additional &#039;&#039;value&#039;&#039;-&amp;gt;&#039;&#039;key&#039;&#039; mapping in the same dictionary (if the key and value spaces are disjoint).&lt;br /&gt;
&lt;br /&gt;
Java users will know a subset of the dictionary functionality as &amp;quot;&#039;&#039;Hashtable&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#DICTIONARY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Dictionary Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== OrderedDictionary =====&lt;br /&gt;
Ordered, variable size, implements arbitrary key-value mappings.&lt;br /&gt;
Can store any type of object and use any kind of object as key.&lt;br /&gt;
Being similar to dictionaries, these remember the order by which elements were added. It provides both access by hash-key and access by index (which is the order in which elements have been added). When enumerated, elements are processed in that order. Creation of an OrderedDictionary is somewhat slower than for Dictionary or OrderedCollection, but access by either numeric or hashkey is fast with O(1) time complexity.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,OrderedDictionary Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== OrderedSet =====&lt;br /&gt;
This is very similar to a Set, but remembers the order in which elements were added, and provides index read access methods. When enumerated, the elements are generated in this order.&lt;br /&gt;
&lt;br /&gt;
===== Queue =====&lt;br /&gt;
Ordered, variable size.&lt;br /&gt;
Can store any type of object. Queues are especially tuned for adding elements at one end, and removing them at the other. The internal representation uses a buffer in round-robin fashion. Both adding and removal are done on O(1) time.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#QUEUE More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Queue Class Documentation]&lt;br /&gt;
&lt;br /&gt;
If multiple processes are accessing the same queue concurrently, use a &amp;lt;code&amp;gt;[http://live.exept.de/ClassDoc/classDocOf:,SharedQueue SharedQueue]&amp;lt;/code&amp;gt;, which is implicitly synchronized.&lt;br /&gt;
&lt;br /&gt;
===== SharedCollection =====&lt;br /&gt;
Any collection can be wrapped into a &#039;&#039;SharedCollection&#039;&#039; to add synchronization locks around its access functions. These should be used if multiple processes (threads) are going to access (i.e: update) the collection simultaneously.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SharedCollection Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== BTree, AATree, BinaryTree =====&lt;br /&gt;
Combining the functionality of &amp;lt;code&amp;gt;Dictionary&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SortedCollection&amp;lt;/code&amp;gt;, these keep their elements in a sorted order, indexed by a key, both of which can be arbitrary objects.&lt;br /&gt;
In contrast to dictionaries, which use hashing, these use a tree-like representation and guarantee both asymptotic O(log N) worst case and average runtime. (Dictionaries have a much better typical time complexity of O(C), but also a worst case of O(N), if the hash keys are badly distributed). These trees are self balancing to avoid the linear worst case access time of non balanced trees. [[http://live.exept.de/ClassDoc/classDocOf:,BTree Class Documentation]]&lt;br /&gt;
&lt;br /&gt;
There is also a non-balancing BinaryTree, which is slightly faster (by not balancing), but its worst case access times may degenerate to O(N), if elements are added non-randomly. &amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,BinaryTree Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Interval and GeometricSeries =====&lt;br /&gt;
&lt;br /&gt;
This represent ranges of numbers as in &amp;quot;&amp;lt;CODE&amp;gt;(1 to:5)&amp;lt;/CODE&amp;gt;&amp;quot; or &amp;quot;&amp;lt;CODE&amp;gt;(1 to:10 by:2)&amp;lt;/CODE&amp;gt;&amp;quot; or &amp;quot;&amp;lt;CODE&amp;gt;(7 to:4 by:-1)&amp;lt;/CODE&amp;gt;&amp;quot;, which represent collections of numbers [1,2,3,4,5], [1,3,5,7,9] and [7,6,5,4] respectively.&lt;br /&gt;
&lt;br /&gt;
GeometricSeries are similar, but have a constant factor between elements, instead of a constant difference. For example, the &amp;quot;&amp;lt;CODE&amp;gt;(GeometricSeries from:1 to:64 byFactor:2)&amp;lt;/CODE&amp;gt;&amp;quot; represents the collection of [1,2,4,8,16,32,64]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Intervals and GeometricSeries  can be used wherever a readonly collection can be used.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Interval Interval Class Documentation] and [http://live.exept.de/ClassDoc/classDocOf:,GeometricSeries GeometricSeries Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== Stream Types ====&lt;br /&gt;
&lt;br /&gt;
Streams are accessors for either internal collections or external files, sockets and other character oriented I/O devices.&lt;br /&gt;
They are created by either &amp;quot;&#039;&#039;opening&#039;&#039;&amp;quot; a file or device or by creation &amp;quot;&#039;&#039;on&#039;&#039;&amp;quot; a numerical indexable collection object (String, Array, OrderedCollection etc.).&lt;br /&gt;
Once created, readstreams deliver the next element via a &amp;quot;&#039;&#039;next&#039;&#039;()&amp;quot; operation, writestreams append elements via the &amp;quot;&#039;&#039;nextPut(e)&#039;&#039;&amp;quot; operation.&lt;br /&gt;
In addition to the above elementary functions, bulk read/write and linewise read/write and various other functionality is provided.&lt;br /&gt;
&lt;br /&gt;
An introductory overview on the stream classes is found in the &lt;br /&gt;
[[http://live.exept.de/doc/online/english/overview/basicClasses/streams.html Streams Overview]] of the [[http://live.exept.de/doc/online/english/TOP.html Smalltalk/X online documentation]].&lt;br /&gt;
&lt;br /&gt;
===== ExternalStream =====&lt;br /&gt;
A common superclass providing bytewise, blockwise and linewise access to any stream of the underlying operating system. Concrete subclasses are Socket, Filestream, Console Streams, PTYStream etc.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/streams.html#FILESTREAM More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,ExternalStream Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== FileStream =====&lt;br /&gt;
Provide bytewise, blockwise or linewise access to the underlying file system.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/streams.html#FILESTREAM More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,FileStream Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== CharacterWriteStream =====&lt;br /&gt;
A special stream usable for mixed single- and multibyte characters (i.e. Unicode). This stream starts to collect into a single byte string buffer, but switches automatically to a multibyte character string as required.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,CharacterWriteStream Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Socket =====&lt;br /&gt;
Provides low level bytewise, blockwise or linewise access to a communication socket. Typically, but not limited to TCP/IP connections.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/streams.html#FILESTREAM More Info]&lt;br /&gt;
&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Socket Class Documentation]&lt;br /&gt;
&lt;br /&gt;
There are a number of useful companion classes which deal with host addresses:&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SocketAddress SocketAddress],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,SocketAddress IPSocketAddress] and&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,SocketAddress IPv6SocketAddress].&lt;br /&gt;
&lt;br /&gt;
===== PipeStream =====&lt;br /&gt;
These are used to read/write from/to another program&#039;s standard input or standard output. For details, consult a Unix programmer&#039;s manual.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,PipeStream Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Filename =====&lt;br /&gt;
Represents names of files in the filesystem. Provides many useful query functions for file size, access- and modification time, parent directory, children, path queries etc.&lt;br /&gt;
&amp;lt;br&amp;gt;Most Useful API: [[Filename API Functions]]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Filename Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== Encoders / Decoders ====&lt;br /&gt;
&lt;br /&gt;
The &lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,CharacterEncoder CharacterEncoder] class provides a number of functions to encode/decode strings into various other encodings;&lt;br /&gt;
for example, to read an ISO 8859-7 encoded string,&lt;br /&gt;
use:&lt;br /&gt;
    decodedString := &lt;br /&gt;
        (CharacterEncoder encoderFor:#&#039;ISO8859-7&#039;) &lt;br /&gt;
            decodeFrom:encodedString.&lt;br /&gt;
and vice versa:&lt;br /&gt;
    encodedString := &lt;br /&gt;
        (CharacterEncoder encoderFor:#&#039;ISO8859-7&#039;)&lt;br /&gt;
            encodeFrom:originalString.&lt;br /&gt;
&lt;br /&gt;
By the time of writing, the following encodings are supported (many are aliases of others):&lt;br /&gt;
&lt;br /&gt;
adobe-fontspecific ansi_x3.4-1968 arabic ascii ascii7 asmo-708 &lt;br /&gt;
big5 &lt;br /&gt;
cns11643 cp-037 cp-37 cp-437 cp10000 cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp367 cp437 cp878 cyrillic &lt;br /&gt;
ebcdic ebcdic-037 ecma-114 ecma-118  &lt;br /&gt;
gb2312 gb2312.1980 gb2312.1980-0 greek &lt;br /&gt;
hangul hebrew &lt;br /&gt;
ibm-367 ibm-437 ibm-819 ibm-cp367 ibm-cp437 ibm-cp819 iso-10646-1 iso-8859-1 iso-8859-10 iso-8859-11 iso-8859-13 iso-8859-14 iso-8859-15 iso-8859-16 iso-8859-2 iso-8859-3 iso-8859-4 iso-8859-5 iso-8859-6 iso-8859-7 iso-8859-8 iso-8859-9 iso-ir-100 iso-ir-101 iso-ir-109 iso-ir-110 iso-ir-126 iso-ir-127 iso-ir-138 iso-ir-144 iso-ir-148 iso-ir-157 iso-ir-203 iso-ir-6 iso10646-1 iso10646_1 iso646-us iso8859 iso8859-1 iso8859-10 iso8859-11 iso8859-13 iso8859-14 iso8859-15 iso8859-16 iso8859-2 iso8859-3 iso8859-4 iso8859-5 iso8859-6 iso8859-7 iso8859-8 iso8859-9 iso8859_1 iso8859_10 iso8859_11 iso8859_13 iso8859_14 iso8859_15 iso8859_16 iso8859_2 iso8859_3 iso8859_4 iso8859_5 iso8859_6 iso8859_7 iso8859_8 iso8859_9&lt;br /&gt;
java javaText jis0201 jis0208 jis0212 jisx0201.1976-0 jisx0208 jisx0208.1983-0 jisx0208.1990-0 johab &lt;br /&gt;
koi7 koi8-r koi8-u ksc5601 &lt;br /&gt;
latin-1 latin-10 latin-2 latin-3 latin-4 latin-5 latin-6 latin-7 latin-8 latin-9 latin-celtic latin1 latin10 latin2 latin3 latin4 latin5 latin6 latin7 latin8 latin9 &lt;br /&gt;
mac-arabic mac-centraleurope mac-centraleuropean mac-croatian mac-cyrillic mac-dingbats mac-farsi mac-greek mac-hebrew mac-iceland mac-japanese mac-korean mac-roman mac-romanian mac-symbol mac-thai mac-turkish macarabic maccentraleurope maccentraleuropean maccroatian maccyrillic macdingbat macdingbats macfarsi macgreek machebrew maciceland macintosh macjapanese mackorean macroman macromanian macsymbol macthai macturkish microsoft-ansi microsoft-arabic microsoft-baltic microsoft-cp1250 microsoft-cp1251 microsoft-cp1252 microsoft-cp1253 microsoft-cp1254 microsoft-cp1255 microsoft-cp1256 microsoft-cp1257 microsoft-cp437 microsoft-cyrillic microsoft-easteuropean microsoft-greek microsoft-hebrew microsoft-turkish ms-ansi ms-arabic ms-baltic ms-cp1250 ms-cp1251 ms-cp1252 ms-cp1253 ms-cp1254 ms-cp1255 ms-cp1256 ms-cp1257 ms-cp367 ms-cp437 ms-cp819 ms-cyrillic ms-default ms-easteuropean ms-ee ms-greek ms-hebrew ms-oem ms-turkish next &lt;br /&gt;
nextstep &lt;br /&gt;
sgml &lt;br /&gt;
thai &lt;br /&gt;
us-ascii utf-16b utf-16be utf-16e utf-16le utf-8 utf-8-mac utf16b utf16be utf16l utf16le utf8 utf8-XML utf8-mac &lt;br /&gt;
windows-1250 windows-1251 windows-1252 windows-1253 windows-1254 windows-1255 windows-1256 windows-1257 windows-latin1&lt;br /&gt;
&lt;br /&gt;
For base64 encoding, refer to the &lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Base64Coder Base64Coder] &lt;br /&gt;
class, or use the string messages: &amp;lt;code&amp;gt;base64Encoded&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;base64Decoded&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For utf8 encoding/decoding, use the string messages: &amp;lt;code&amp;gt;utf8Encoded&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;utf8Decoded&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Other useful Types ====&lt;br /&gt;
&lt;br /&gt;
===== Date =====&lt;br /&gt;
Represents a calendar date. Instances can be created with eg. &amp;quot;&amp;lt;code&amp;gt;Date today&amp;lt;/code&amp;gt;&amp;quot;, by giving day/month/year or a calendar day. Instances offer a large number of queries, such as weekday, dayInWeek, leapYear etc.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#DATE More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Date Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Time =====&lt;br /&gt;
Represents a time-of-day in second resolution. Instances are created with &amp;quot;&amp;lt;code&amp;gt;Time now&amp;lt;/CODE&amp;gt;&amp;quot; or by giving hour/minute/seconds.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#TIME More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Time Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Timestamp (Date and Time) =====&lt;br /&gt;
Represents a timestamp. With the 18.1 release, the resolution has been improved to sub-nanosecond resolution, although internal timestamps as generated by the operating system will usually not generate such fine grained values (some systems will only generate, 1 millisecond resolution stamps).&lt;br /&gt;
&lt;br /&gt;
Update: now the resolution supported by Timestamps is 1 picosecond, and microsecond times are also supported on Windows systems.&lt;br /&gt;
&lt;br /&gt;
For backward compatibility, the default resolution is 1 millisecond for internally generated stamps, and whatever resolution is provided when stamps are read from an external source. When printed, the default print format includes 3 millisecond digits, but a separate print generator can produce higher resolution strings (in 18.1).&lt;br /&gt;
&lt;br /&gt;
The Timestamp class has been enhanced to support dates before 1.1.1970 and after 2036, which are typical restrictions of systems which represent times as &amp;quot;&#039;&#039;seconds since the epoch&#039;&#039;&amp;quot; in a 32bit integer. Expecco timestamps handle values before and after those dates, although no calendar adjustments are done for timestamps before the julian/gregorian switch (i.e. this affects weekdays, leap years, etc. before 1582, which are very unlikely to be encountered in technical environments ;-) ).&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#TIMESTAMP More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Timestamp Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== TimeDuration =====&lt;br /&gt;
Represents an amount of time, to represent time intervals in picosecond resolution. &lt;br /&gt;
&lt;br /&gt;
When reading from a string or stream, a unit-specifier character is allowed to specify milliseconds (ms), seconds (s), minutes (m), hours (h) or days (d). For example, &amp;quot;&amp;lt;code&amp;gt;1h 20s&amp;lt;/code&amp;gt;&amp;quot; specifies 1 hour and 20 seconds.&lt;br /&gt;
&lt;br /&gt;
As a programmer, you can write (in Smalltalk): &amp;quot;&amp;lt;code&amp;gt;1 hours + 20 seconds&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Creation:&lt;br /&gt;
* TimeDuration fromString: &amp;amp;apos;&#039;&#039;aString&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromSeconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromMinutes: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromHours: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromMilliseconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromMicroseconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromNanoseconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromPicoseconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration days: &amp;amp;apos;&#039;&#039;dayNumber&#039;&#039;&amp;amp;apos; hours: &amp;amp;apos;&#039;&#039;hourNumber&#039;&#039;&amp;amp;apos;  minutes: &amp;amp;apos;&#039;&#039;minuteNumber&#039;&#039;&amp;amp;apos;  seconds: &amp;amp;apos;&#039;&#039;secondsNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#TIMEDURATION More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,TimeDuration Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Delay =====&lt;br /&gt;
Delay is a utility providing timed delay functions. Most useful are (written in Smalltalk):&lt;br /&gt;
   Delay waitForSeconds: &amp;lt;i&amp;gt;n&amp;lt;/i&amp;gt;.   (arg is a number)&lt;br /&gt;
 and: &lt;br /&gt;
   Delay waitFor: &amp;lt;i&amp;gt;n&amp;lt;/i&amp;gt; seconds.  (arg is a time duration)&lt;br /&gt;
 and: &lt;br /&gt;
   Delay waitUntil: &amp;lt;i&amp;gt;timestamp&amp;lt;/i&amp;gt;. (arg is a timestamp)&lt;br /&gt;
&lt;br /&gt;
or (written in JavaScript):&lt;br /&gt;
   &amp;quot;&amp;lt;code&amp;gt;Delay.waitForSeconds(n)&amp;lt;/code&amp;gt;&amp;quot;;&lt;br /&gt;
   &amp;quot;&amp;lt;code&amp;gt;Delay.waitFor(n.seconds())&amp;lt;/code&amp;gt;&amp;quot;;&lt;br /&gt;
 and &lt;br /&gt;
   &amp;quot;&amp;lt;code&amp;gt;Delay.waitUntil(timestamp)&amp;lt;/code&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Delay Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== CTypes ====&lt;br /&gt;
&lt;br /&gt;
These types describe C-data structures. They are needed when data is exchanged with DLL functions or is to be read/written in binary from/to a file or a communication channel.&lt;br /&gt;
&lt;br /&gt;
CTypes are usually parsed from a string using the C Parser, which is invoked by expecco when a type definition starts with a comment like &amp;quot;/* C: */&amp;quot;.&lt;br /&gt;
But of course, the C-Parser can also be invoked explicitly in a workspace or programmatically via an elementary block.&lt;br /&gt;
The following example would create a C-type from a structure definition string (in JavaScript code):&lt;br /&gt;
    t = CParser.parseDeclaration(&amp;quot;&lt;br /&gt;
        struct s {&lt;br /&gt;
            unsigned long DPR_Address;&lt;br /&gt;
            unsigned long DPR_Length;&lt;br /&gt;
            unsigned long PortAddress;&lt;br /&gt;
            struct p {&lt;br /&gt;
                unsigned char ProtocolID;&lt;br /&gt;
                union u {&lt;br /&gt;
                    uint16 dpInOutAreaSize;&lt;br /&gt;
                    uint16 dpInAreaSize;&lt;br /&gt;
                } Parameter;&lt;br /&gt;
            } Protocol[4];&lt;br /&gt;
        };&lt;br /&gt;
    &amp;quot;);&lt;br /&gt;
the type in variable &amp;quot;&amp;lt;code&amp;gt;t&amp;lt;/code&amp;gt;&amp;quot; can then be instantiated by sending it a &amp;quot;&amp;lt;code&amp;gt;new&amp;lt;/code&amp;gt;&amp;quot; message:&lt;br /&gt;
    cDatum = t.new();&lt;br /&gt;
or with:&lt;br /&gt;
    cDatum = t.malloc();&lt;br /&gt;
The difference is that &amp;quot;&amp;lt;code&amp;gt;new&amp;lt;/code&amp;gt;&amp;quot; allocates the bytes in the regular garbage collected expecco memory (which may move objects),&lt;br /&gt;
whereas &amp;quot;&amp;lt;code&amp;gt;malloc&amp;lt;/code&amp;gt;&amp;quot; allocates in pinned (not moving) memory on the C heap. Thus references to such malloc&#039;d memory can be passed to DLL code which wants to keep a reference to it, whereas C-data allocated with &amp;lt;code&amp;gt;new&amp;lt;/code&amp;gt; can only be used temporarily by C code and will vanish sooner or later after the call returns.&lt;br /&gt;
&lt;br /&gt;
You can inspect the created instance via the inspector (evaluate: &amp;quot;&amp;lt;code&amp;gt;cDatum.inspect()&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Individual fields of the c-datum are accessed via the following functions:&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.memberAt(fieldName)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;retrieves a field. If the field is a composite datum (array or structure), a new datum is extracted (i.e. a structure copy is made).&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.at(index0Based)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;retrieves an indexed array element as a copy.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.memberAtPut(fieldName, value)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;stores a field. If the field is a composite datum (array or structure), the whole value is copied.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.atPut(index0Based)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;stores an indexed array element.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;CDatum.refMemberAt(fieldName)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;creates a pointer to a field. This allows for subfields to be modified.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.refAt(index0Based)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;creates a pointer to an array element.&lt;br /&gt;
&lt;br /&gt;
notice that in JavaScript, indexed access can be written more convenient as &amp;quot;&amp;lt;code&amp;gt;cDatum[index0Based]&amp;lt;/code&amp;gt;&amp;quot; and that member field access can be written as &amp;quot;&amp;lt;code&amp;gt;cDatum.fieldName&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the full protocol of CDatum, please refer to the class code in the&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Ctype Class Documentation].&lt;br /&gt;
&amp;lt;br&amp;gt;Additional information is also found in the [[Datatype Element/en#CTypes]] documentation.&lt;br /&gt;
&lt;br /&gt;
=== Additional Standard Objects for JavaScript ===&lt;br /&gt;
&lt;br /&gt;
In order for a &amp;quot;&#039;&#039;well known&#039;&#039;&amp;quot; environment to be provided to those who know JavaScript, but do not know Smalltalk, mimicri classes (Math) and mimicri protocol has been added to the underlying Smalltalk system. These functions simply call corresponding Smalltalk functions and only exist to provide a JavaScript compatible API which is described below. &lt;br /&gt;
&lt;br /&gt;
Notice that this represents only a small fraction (less than 1/100th) of the real functionality of the base system. In order to find out more about all existing classes, you should open a class browser and navigate through the system yourself (eg. Number and subclasses).&amp;lt;br&amp;gt;There is also a more detailed introduction to the basic classes found in the &lt;br /&gt;
[http://live.exept.de/doc/online/english/overview/basicClasses/TOP.html Smalltalk/X Base Classes Documentation].&lt;br /&gt;
&lt;br /&gt;
==== Math ====&lt;br /&gt;
&lt;br /&gt;
===== Constants =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;E&#039;&#039;&#039;&amp;lt;br&amp;gt;Euler&#039;s constant, the base of the natural logarithm (approximately 2.718 as double precision IEEE number).&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;code&amp;gt;Float e&amp;lt;/code&amp;gt;&amp;quot; in Smalltalk (or &amp;quot;&amp;lt;code&amp;gt;Math E&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;LN10&#039;&#039;&#039;&amp;lt;br&amp;gt;Natural logarithm of 10 (approximately 2.302 as double).&amp;lt;br&amp;gt;In Smalltalk, you can use &amp;quot;&amp;lt;code&amp;gt;Float ln10&amp;lt;/code&amp;gt;&amp;quot; (or &amp;quot;&amp;lt;code&amp;gt;Math LN10&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;LN2&#039;&#039;&#039;&amp;lt;br&amp;gt;Natural logarithm of 2 (approximately 0.693 as double).&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;code&amp;gt;Float ln2&amp;lt;/code&amp;gt;&amp;quot; in Smalltalk.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;LOG10E&#039;&#039;&#039;&amp;lt;br&amp;gt;Base 10 logarithm of E (approximately 0.434 as double)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;LOG2E&#039;&#039;&#039;&amp;lt;br&amp;gt;Base 2 logarithm of E (approximately 1.442 as double)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;PI&#039;&#039;&#039;&amp;lt;br&amp;gt;Pi (approximately 3.14159 as double).&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;code&amp;gt;Float pi&amp;lt;/code&amp;gt;&amp;quot; in Smalltalk.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;SQRT1_2&#039;&#039;&#039;&amp;lt;br&amp;gt;Square root of 1/2 (approximately 0.707 as double)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;SQRT2&#039;&#039;&#039;&amp;lt;br&amp;gt;Square root of 2 (approximately 1.414 as double).&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;code&amp;gt;Float sqrt2&amp;lt;/code&amp;gt;&amp;quot; in Smalltalk.&lt;br /&gt;
&lt;br /&gt;
===== Min &amp;amp; Max =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;max&#039;&#039;&#039; (&#039;&#039;number1 , number2,...&#039;&#039;)&amp;lt;br&amp;gt;Returns the largest of up to 6 arguments&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;min&#039;&#039;&#039; (&#039;&#039;number1, number2,...&#039;&#039;)&amp;lt;br&amp;gt;Returns the smallest of up to 6 arguments&lt;br /&gt;
&lt;br /&gt;
===== Miscellaneous =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;abs&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the absolute value of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;binco&#039;&#039;&#039; (&#039;&#039;n, k&#039;&#039;) &amp;lt;br&amp;gt;Returns the binomial coefficient C(n,k) (&amp;lt;span title=&amp;quot;aka. = also known as&amp;quot;&amp;gt;aka&amp;lt;/span&amp;gt;. &amp;quot;n over k&amp;quot; or &amp;quot;choose k from n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cbrt&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the cubic root of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;ceil&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the smallest integer greater than or equal to aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;exp&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns e&amp;lt;sup&amp;gt;aNumber&amp;lt;/sup&amp;gt;, where aNumber is the argument, and e is Euler&#039;s constant, the base of the natural logarithm&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fac&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the factorial of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;floor&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the greatest integer less than or equal to aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;gcd&#039;&#039;&#039; (&#039;&#039;a, b&#039;&#039;)&amp;lt;br&amp;gt;Returns the greatest common divisor of a and b&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;log10&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the log base 10 of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;log&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the log base E of aNumber&lt;br /&gt;
&amp;lt;!--ATTENTION:&lt;br /&gt;
    In JavaScript log is a base E log&lt;br /&gt;
    In Smalltalk log is a base 10 log (use ln for base E)&lt;br /&gt;
    In JavaScript, better use log10 to make things explicit.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pow&#039;&#039;&#039; (&#039;&#039;base, exp&#039;&#039;)&amp;lt;br&amp;gt;Returns base to the exponent power, that is, base&amp;lt;sup&amp;gt;exp&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;random&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a pseudo random number between 0 and 1&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;round&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the value of aNumber rounded to the nearest integer&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;sqrt&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the square root of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;trunc&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the value of aNumber truncated towards zero&amp;lt;br&amp;gt;(that is: the smallest integer greater or equal if aNumber is negative, or the largest integer less or equal if positive)&lt;br /&gt;
&lt;br /&gt;
===== Trigonometric =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;sin&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the sine of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cos&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the cosine of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;tan&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the tangent of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cot&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the cotangent of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;csc&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the cosecant of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;sec&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the secant of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;arcSin&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the arcsine (in radians) of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;arcCos&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the arccosine (in radians) of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;arcTan&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the arctangent (in radians) of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;arcTan2&#039;&#039;&#039; (&#039;&#039;x, y&#039;&#039;)&amp;lt;br&amp;gt;Returns the arctangent of the quotient of its arguments (in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;sinh&#039;&#039;&#039; / &#039;&#039;&#039;cosh&#039;&#039;&#039; / &#039;&#039;&#039;tanh&#039;&#039;&#039; / &#039;&#039;&#039;arSinh&#039;&#039;&#039; / &#039;&#039;&#039;arCosh&#039;&#039;&#039; etc.&amp;lt;br&amp;gt;Hyperbolic versions of above&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;degreesToRadians&#039;&#039;&#039;(&#039;&#039;d&#039;&#039;) / &#039;&#039;&#039;radiansToDegrees&#039;&#039;&#039;(&#039;&#039;r&#039;&#039;)&amp;lt;br&amp;gt;Conversions&lt;br /&gt;
&lt;br /&gt;
==== Number ====&lt;br /&gt;
===== Properties =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;MAX_VALUE&#039;&#039;&#039;&amp;lt;br&amp;gt;The largest representable number. The returned number is 0x7FFFFFFFFFFFFFFF, to mimicri a 64 bit limit on numbers for JS programs ported from other systems. In fact, expecco does not impose any such limit in integer values.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;MIN_VALUE&#039;&#039;&#039;&amp;lt;br&amp;gt;The smallest representable number. The returned number is -0x8000000000000000, to mimicri a 64 bit limit on numbers for JS programs ported from other systems. In fact, expecco does not impose any such limit in integer values.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;NEGATIVE_INFINITY&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the special &#039;negative infinity&#039; value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;NaN&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the special &#039;not a number&#039; value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;POSITIVE_INFINITY&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the special &#039;positive infinity&#039; value&lt;br /&gt;
&lt;br /&gt;
===== Methods =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;asFloat&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Returns a floating-point version of the receiver object.&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.asFloat()&amp;lt;/code&amp;gt;&amp;quot; yields the (double precision) floating point number: &amp;quot;1.0&amp;quot;.&amp;lt;br&amp;gt;You can also use one of &amp;quot;asFloat32&amp;quot;, &amp;quot;asFloat64&amp;quot;, &amp;quot;asFloat80&amp;quot;, &amp;quot;asFloat128&amp;quot; or &amp;quot;asLargeFloat&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;asInteger&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Returns an integer version of the receiver object (truncating).&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.0.asInteger()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;1&amp;quot;. Alternatives are ceiling(), floor() and rounded().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;ceiling&#039;&#039;&#039; ()&amp;lt;br&amp;gt;For non-integral values, ceiling returns the smallest integer which is larger than the receiver. For integers, the original value is returned.&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.4.ceiling()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;2&amp;quot;, whereas &amp;quot;&amp;lt;code&amp;gt;1.ceiling()&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1&amp;quot;. See also: floor() and rounded().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;floor&#039;&#039;&#039; ()&amp;lt;br&amp;gt;For non-integral values, floor returns the largest integer which is smaller than the receiver. For integers, the original value is returned.&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.4.floor()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;1&amp;quot;, whereas &amp;quot;&amp;lt;code&amp;gt;1.floor()&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1&amp;quot;. See also: ceiling() and rounded().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;rounded&#039;&#039;&#039; ()&amp;lt;br&amp;gt;For non-integral values, rounded returns the nearest integer from rounding. For integers, the original value is returned.&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.4.rounded()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;1&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;1.6.rounded()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;2&amp;quot; and whereas &amp;quot;&amp;lt;code&amp;gt;1.rounded()&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1&amp;quot;. See also: ceiling() and floor().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;roundTo&#039;&#039;&#039; (&#039;&#039;r&#039;&#039;)&amp;lt;br&amp;gt;Rounds towards the nearest multiple of r.&amp;lt;br&amp;gt;For example, &amp;quot;&amp;lt;code&amp;gt;1.543.roundedTo(0.01)&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1.54&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;1.567.roundedTo(0.01)&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1.57&amp;quot;. See also: ceiling(), floor() and rounded().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;toExponential&#039;&#039;&#039; (&#039;&#039;nDigits&#039;&#039;)&amp;lt;br&amp;gt;Returns a string representing the number in exponential notation, where nDigits is the number of digits to appear after the decimal point&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;toExponential&#039;&#039;&#039; (&#039;&#039;nDigits, nDigitsAfter&#039;&#039;)&amp;lt;br&amp;gt;Returns a string representing the number in exponential notation&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;toFixed&#039;&#039;&#039; (&#039;&#039;nDigits&#039;&#039;)&amp;lt;br&amp;gt;Returns a string representing the number in fixed notation, where nDigits is the number of digits to appear after the decimal point&lt;br /&gt;
&lt;br /&gt;
==== Random ====&lt;br /&gt;
&lt;br /&gt;
A built in random generator, which generates linear congruential pseudo random numbers itself. On Unix/Linux operating systems, an additional class called &amp;quot;RandomGenerator&amp;quot; uses the operating system&#039;s random generator (&amp;lt;code&amp;gt;/dev/rand&amp;lt;/code&amp;gt;). In addition, alternative generators are available as &amp;quot;&amp;lt;code&amp;gt;RandomParkMiller&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;RandomTT800&amp;lt;/code&amp;gt;&amp;quot;. For most applications, the default generator named &amp;quot;&amp;lt;code&amp;gt;Random&amp;lt;/code&amp;gt;&amp;quot; should provide a reasonable random sequence (this will be the &amp;quot;/dev/rand&amp;quot;-based generator on Unix/Linux, and a Cryptographic Hash-based generator on other systems).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;next ()&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a random number between 0 and 1 (float)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;next (&#039;&#039;n&#039;&#039;)&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns n random numbers between 0 and 1 (float) as an array&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;nextBoolean ()&#039;&#039;&#039;&amp;lt;br&amp;gt;Randomly returns either true or false&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;nextBetween_and_&#039;&#039;&#039; (&#039;&#039;min, max&#039;&#039;)&amp;lt;br&amp;gt;Returns a random float between min and max&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;nextIntegerBetween_and_&#039;&#039;&#039; (&#039;&#039;min, max&#039;&#039;)&amp;lt;br&amp;gt;Returns a random integer between min and max (use 1 and 6, to simulate a dice)&lt;br /&gt;
&lt;br /&gt;
==== Time / Date ====&lt;br /&gt;
&lt;br /&gt;
Time and Date instances provide a rich protocol for all kinds of queries. The list below is only a short extract of the most used methods:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Time now&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the current time&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Date today&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the current date&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aDate&#039;&#039;.&#039;&#039;&#039;getDate&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the day of the month (1..31)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aDate&#039;&#039;.&#039;&#039;&#039;getDay&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the day of the week (0..6); Sunday is 0&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aDate&#039;&#039;.&#039;&#039;&#039;getMonth&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the day of the month (1..12)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aDate&#039;&#039;.&#039;&#039;&#039;getFullYear&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the year&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTime&#039;&#039;.&#039;&#039;&#039;getHours&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the hours (0..24)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTime&#039;&#039;.&#039;&#039;&#039;getMinutes&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the minutes (0..60)&lt;br /&gt;
&lt;br /&gt;
==== String ====&lt;br /&gt;
&lt;br /&gt;
Be reminded that the String class inherits from CharacterArray, ByteArray, SequentialCollection, Collection and Object. Thus all of those methods are also available (and useful) with strings. Use the browser or take a look at the online documentation for the full protocol (which is much larger than what is listed below).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;charAt0&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)&amp;lt;br&amp;gt;Returns the n&#039;th character as a Character instance object, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;charAt1&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)&amp;lt;br&amp;gt;Returns the n&#039;th character as a Character instance object, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;charCodeAt0&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)&amp;lt;br&amp;gt;Returns the code of the n&#039;th character, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;charCodeAt1&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)&amp;lt;br&amp;gt;Returns the code of the n&#039;th character, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;indexOf0&#039;&#039;&#039; (&#039;&#039;aCharacter&#039;&#039;)&amp;lt;br&amp;gt;Returns the index of aCharacter, using a 0-based indexing scheme; -1 if not found&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;indexOf1&#039;&#039;&#039; (&#039;&#039;aCharacter&#039;&#039;)&amp;lt;br&amp;gt;Returns the index of aCharacter, using a 1-based indexing scheme; 0 if not found&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;lastIndexOf0&#039;&#039;&#039; (&#039;&#039;aCharacter&#039;&#039;)&amp;lt;br&amp;gt;Returns the last index of aCharacter, using a 0-based indexing scheme; -1 if not found&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;lastIndexOf1&#039;&#039;&#039; (&#039;&#039;aCharacter&#039;&#039;)&amp;lt;br&amp;gt;Returns the last index of aCharacter, using a 1-based indexing scheme; 0 if not found&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;quote()&#039;&#039;&#039;&amp;lt;br&amp;gt;Wraps the receiver into double quotes (&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;split&#039;&#039;&#039; (&#039;&#039;separator&#039;&#039;)&amp;lt;br&amp;gt;Splits the string into a collection of substrings using the separator. Warning: the JavaScript split(xxx) function and the Smalltalk split: method have different semantics (and argument order)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substr0&#039;&#039;&#039; (&#039;&#039;index, count&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring starting at the index with the given length, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substr1&#039;&#039;&#039; (&#039;&#039;index, count&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring starting at the index with the given length, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substring0&#039;&#039;&#039; (&#039;&#039;index1&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring starting at the index, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substring0&#039;&#039;&#039; (&#039;&#039;index1, index2&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring between the given indices, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substring1&#039;&#039;&#039; (&#039;&#039;index1&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring starting at the index, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substring1&#039;&#039;&#039; (&#039;&#039;index1, index2&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring between the given indices, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;toLowerCase&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all chars in lower case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;toUpperCase&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all chars in upper case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;trim&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all leading and trailing white space removed&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;trimLeft&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all leading white space removed&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;trimRight&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all trailing white space removed&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Collection (Array) ====&lt;br /&gt;
&lt;br /&gt;
Notice that Array, OrderedCollection, ByteArray, String and others are also inheriting the Collection protocol. Thus the below listed messages can also be applied to instances of those.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;concat&#039;&#039;&#039; (&#039;&#039;aCollection&#039;&#039;)&amp;lt;br&amp;gt;Returns a new collection consisting of the concatenation of the receiver and the argument&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;every&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Returns true, if &amp;quot;filterFunction&amp;quot; returns true for all elements&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;filter&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Selects elements for which &amp;quot;filterFunction&amp;quot; returns true&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;forEach&#039;&#039;&#039; (&#039;&#039;function&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; for each element&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;join&#039;&#039;&#039; (&#039;&#039;seperator&#039;&#039;)&amp;lt;br&amp;gt;Joins the strings of the receiver into a new single string using the separator&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;map&#039;&#039;&#039; (&#039;&#039;function&#039;&#039;)&amp;lt;br&amp;gt;Returns a new collection collecting the results of applying &amp;quot;function&amp;quot; to each element in sequence&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;pop&#039;&#039;&#039;&amp;lt;br&amp;gt;Removes and returns the last element of the collection. Modifies the receiver collection as a side effect.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;push&#039;&#039;&#039; (&#039;&#039;value&#039;&#039;)&amp;lt;br&amp;gt;Adds an element to the end of the collection. Modifies the receiver collection as a side effect.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;reduce0&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; against two values, reducing from left to right. Function must be declared as: f(previousValue, currentValue, index, arr). Pass 0-based indices to the filter.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;reduce0&#039;&#039;&#039; (&#039;&#039;filterFunction, initialValue&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; against two values, reducing from left to right. Function must be declared as: f(previousValue, currentValue, index, arr). Pass 0-based indices to the filter.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;reduce1&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; against two values, reducing from left to right. Function must be declared as: f(previousValue, currentValue, index, arr). Pass 1-based indices to the filter.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;reduce1&#039;&#039;&#039; (&#039;&#039;filterFunction, initialValue&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; against two values, reducing from left to right. Function must be declared as: f(previousValue, currentValue, index, arr). Pass 1-based indices to the filter.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;shift&#039;&#039;&#039;&amp;lt;br&amp;gt;Removes and returns the first element of the collection. Same as &#039;&#039;removeFirst&#039;&#039;. Notice that this modifies the receiver collection as a side effect.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;slice0&#039;&#039;&#039; (&#039;&#039;index1, index2&#039;&#039;)&amp;lt;br&amp;gt;Extracts a subcollection, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;slice1&#039;&#039;&#039; (&#039;&#039;index1, index2&#039;&#039;)&amp;lt;br&amp;gt;Extracts a subcollection, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;some&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Returns true, if &amp;quot;filterFunction&amp;quot; returns true for any element&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;unshift&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds an element to the beginning of the collection. Same as &#039;&#039;addFirst&#039;&#039;. Notice that this modifies the receiver collection as a side effect.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Transcript ====&lt;br /&gt;
&lt;br /&gt;
The global variable &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot; refers to either the Transcript information window (if it is open) or the standard error stream. As such, it implements most of the stream interface functions. Most noteworthy are:&lt;br /&gt;
&lt;br /&gt;
*Transcript.&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;,...)&amp;lt;br&amp;gt;Like show, but &amp;quot;%i&amp;quot; (i=1..8) sequences in the format argument are expanded by corresponding argument strings. Up to 8 arguments are allowed.&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;,...)&amp;lt;br&amp;gt;Like showCR, but &amp;quot;%i&amp;quot; (i=1..8) sequences in the format argument are expanded by corresponding argument strings. Up to 8 arguments are allowed.&lt;br /&gt;
&lt;br /&gt;
and from the inherited write stream interface:&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;nextPut&#039;&#039;&#039; (&#039;&#039;aChar&#039;&#039;)&amp;lt;br&amp;gt;Sends a single character&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;nextPutAll&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039;)&amp;lt;br&amp;gt;Sends a string&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;nextPutLine&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039;)&amp;lt;br&amp;gt;Sends a string followed by a linebreak&lt;br /&gt;
&lt;br /&gt;
Notice that if a prefix string is defined in a variable named &amp;quot;__Transcript_Prefix__&amp;quot;, that string is prepended to the output.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logger ====&lt;br /&gt;
&lt;br /&gt;
The global variable &amp;quot;&amp;lt;code&amp;gt;Logger&amp;lt;/code&amp;gt;&amp;quot; refers to an object which will handle system log messages. This is the underlying Smalltalk framework&#039;s logging mechanism, not to be confused with expecco&#039;s &#039;&#039;ActivityLog&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The Logger will filter messages according to their &#039;&#039;severity&#039;&#039;, which is one of {&amp;lt;code&amp;gt;debug, info, warn, error, fatal&amp;lt;/code&amp;gt;}. Severities are ordered as &amp;lt;code&amp;gt;debug &amp;lt; info &amp;lt; warn &amp;lt; error &amp;lt; fatal&amp;lt;/code&amp;gt;.&lt;br /&gt;
For filtering, a severityThreshold can be set, and only messages with a higher severity will be reported.&lt;br /&gt;
 &lt;br /&gt;
By default, the Logger sends its output to the &#039;&#039;stderr&#039;&#039; stream, which is usually redirected into a (log-)file when expecco runs unattended as a service or controlled by command line arguments.&lt;br /&gt;
This behavior can be changed by assigning a different logger to the global &amp;quot;Logger&amp;quot;. &lt;br /&gt;
Under Unix systems (OSX and Linux), the defaul logger can also be replaced by one which writes to the syslog facility.&lt;br /&gt;
&amp;lt;br&amp;gt;The Logger supports the following protocol:&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;debug&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs a debug message&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;info&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs an info message&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs an warning message&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs an error message&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;fatal&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs a fatal message&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
=== Expecco Objects ===&lt;br /&gt;
Many objects internal to expecco&#039;s execution machinery are reachable via elementary code (i.e. from within an elementary-coded action&#039;s code).&lt;br /&gt;
A lot of useful and required information can be acquired by consulting these objects.&lt;br /&gt;
The anchor to all those objects is the &amp;quot;&#039;&#039;current activity&#039;&#039;&amp;quot; object.&lt;br /&gt;
&lt;br /&gt;
==== Current Activity ====&lt;br /&gt;
Within elementary code the activity instance which is executing this piece of code can be accessed via the variable &amp;quot;&amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt;&amp;quot; (in Smalltalk: &amp;quot;&amp;lt;code&amp;gt;self&amp;lt;/code&amp;gt;&amp;quot;). For every executed action, a new activity object is created. It is usually alive during the execution only (i.e. it is destroyed and its memory reused automatically, after the block&#039;s action has finished).&lt;br /&gt;
&lt;br /&gt;
The current activity object supports the following functions:&lt;br /&gt;
&lt;br /&gt;
===== Reporting =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; () &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report a defect (in the test) with infoString to be shown in the activity log. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] ) &amp;lt;br&amp;gt;Report a failure (in the SUT) with optional infoString to be shown in the activity log. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] ) &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;success&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] ) OBSOLETE - see activitySuccess below&amp;lt;br&amp;gt;Finishes the current activity with success.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] )&amp;lt;br&amp;gt;Finishes the current activity with success. Actually not needed, because simply returning from an action&#039;s execute method is semantically equivalent (however, this allows for early successful finish). Due to the more descriptive name, use this function instead of &amp;quot;&amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testPass&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] )&amp;lt;br&amp;gt;Finishes the current test case with success. Notice: this aborts the current activity and all of the callers up to the test case level. This behavior is different from activitySuccess&#039;s behavior.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] )&amp;lt;br&amp;gt;Same as testPass (backward compatibility).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Logging =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logData&#039;&#039;&#039; (&#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Adds data to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logDataFile&#039;&#039;&#039; (&#039;&#039;fileName&#039;&#039;) &amp;lt;br&amp;gt;Adds a file attachment to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, &#039;&#039;detail&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, &#039;&#039;detail&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, detail) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logImageInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, image) &amp;lt;br&amp;gt;Adds an info message with an image (screendump) to the activity log. There is an option in the report generator to include those in the generated pdf-report.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;[[Settings_LoggingSettings/en|Execution-Log-Settings]]&amp;quot; dialog (by default, it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Same as &#039;&#039;alert()&#039;&#039; (for Smalltalk protocol compatibility).&lt;br /&gt;
&lt;br /&gt;
Notice the similarity and difference between &amp;quot;error()&amp;quot; and &amp;quot;logError()&amp;quot;: both actually create a log-data entry, but &amp;quot;error()&amp;quot; stops the execution, whereas &amp;quot;logError()&amp;quot; proceeds (maybe, the naming is a bit confusing here...)&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Execution =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;call&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;) &amp;lt;br&amp;gt;Calls another action without any input values. The called action is specified by the &amp;quot;&#039;&#039;calledActionName&#039;&#039;&amp;quot; parameter.&lt;br /&gt;
*&#039;&#039;&#039;call&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;, &#039;&#039;arg&#039;&#039;...) &amp;lt;br&amp;gt;Calls another action with &#039;&#039;argi&#039;&#039; input value(s). The called action is specified by the &amp;quot;&#039;&#039;calledActionName&#039;&#039;&amp;quot; parameter. Up to 8 arguments are supported.&lt;br /&gt;
*&#039;&#039;&#039;call_with&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;, &#039;&#039;inPinValues&#039;&#039;) &amp;lt;br&amp;gt;Calls another action passing input values as a collection of values. The called action is specified by the &amp;quot;&#039;&#039;calledActionName&#039;&#039;&amp;quot; parameter.&lt;br /&gt;
*&#039;&#039;&#039;call_into&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;, &#039;&#039;funcReceivingValues&#039;&#039;)&amp;lt;br&amp;gt;Not passing any input values (similar to call), for actions with multiple output values or which write multiple values. &lt;br /&gt;
*&#039;&#039;&#039;call_with_into&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;, &#039;&#039;inPinValues&#039;&#039;, &#039;&#039;funcReceivingValues&#039;&#039;)&amp;lt;br&amp;gt;Similar to the above, for actions with multiple output values or which write multiple values. &lt;br /&gt;
The called action is specified by the &amp;quot;&#039;&#039;calledActionName&#039;&#039;&amp;quot; parameter which must be one of:&lt;br /&gt;
* a UUID (the called action-block&#039;s version- or function-ID), &lt;br /&gt;
* a UUID-string (the called action-block&#039;s version- or function-ID), &lt;br /&gt;
* a name-string (the called action-block&#039;s name), &lt;br /&gt;
* a direct reference to the action-block object.&lt;br /&gt;
 &lt;br /&gt;
Although giving a simple name-string is propably the easiest way to specify the action, it may lead to an error, if multiple actions are found with the same name (which never happens, if a UUID is used). If a UUID is used, this can be either the action&#039;s functional- or version-ID. If the version-ID is given, that particular action is called. If a functional-ID is given, the first action which is found to have a matching functional-ID is called. The version-ID is specific, but intolerant to reimports or changes in the called action. Therefore, you should propably use the functional-ID, if you do not want to use the action&#039;s name.&lt;br /&gt;
&amp;lt;br&amp;gt;In most &amp;quot;normal&amp;quot; situations, the action&#039;s name is unique and good enough.&lt;br /&gt;
&lt;br /&gt;
There is an automatic mechanism, to deal with renaming, in that constant action names are found and replaced. &lt;br /&gt;
Also, such action references are found via the &amp;quot;&#039;&#039;References&#039;&#039;&amp;quot; tree menu item and you&#039;ll get a warning if such an action is renamed or removed.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;&#039;&#039;inPinValues&#039;&#039;&amp;quot; argument can be either a vector (array) or a dictionary (mapping pin-name to value) of values to be passed to the input pins of the called action. An input value of &amp;quot;Void&amp;quot; (&amp;quot;void&amp;quot; in JavaScript) will be treated like an unconnected pin.&lt;br /&gt;
&lt;br /&gt;
The first variants (without the &amp;quot;into:&amp;quot; argument) return the value of the first output pin (or nil, if there are no output pins). If the output is written multiple times, an error is reported. &lt;br /&gt;
&lt;br /&gt;
The other variant expects a &amp;quot;&#039;&#039;funcReceivingValues&#039;&#039;&amp;quot; argument, which must be a JS-function or Smalltalk-Block. This function/block is called with the output pin values as arguments. For each pin, one collection containing all values written to the corresponding pin is passed to it as argument (a collection of values is passed, because the pins could be written multiple times by the action). &lt;br /&gt;
&lt;br /&gt;
For example from a Smalltalk coded action, the &amp;quot;&amp;lt;code&amp;gt;Arith [MinMax]&amp;lt;/code&amp;gt;&amp;quot; action (which has 2 outputs) can be called with:&lt;br /&gt;
 self&lt;br /&gt;
     call:&amp;quot;Arith [ MinMax ]&amp;quot; &lt;br /&gt;
     with:{ addend1 . addend2 } &lt;br /&gt;
     into:[:minOutValues :maxOutValues | &lt;br /&gt;
        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ ... do something with the min/max values ...&amp;lt;/span&amp;gt;&lt;br /&gt;
        min := minOutValues first.&lt;br /&gt;
        max := maxOutputValues first.&lt;br /&gt;
     ]&lt;br /&gt;
with JavaScript code, the above would be written as:&lt;br /&gt;
 this.call_with_into(&amp;quot;Arith [ MinMax ]&amp;quot;,&lt;br /&gt;
                           [ addend1 , addend2 ], &lt;br /&gt;
                           function (minOutValues , maxOutValues) { &lt;br /&gt;
                              &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// ... do something with the min/max values ...&amp;lt;/span&amp;gt;&lt;br /&gt;
                              min = minOutValues.first();&lt;br /&gt;
                              max = maxOutputValues.first();&lt;br /&gt;
                           })&lt;br /&gt;
or, using a lambda function, as:&lt;br /&gt;
 this.call_with_into(&amp;quot;Arith [ MinMax ]&amp;quot;,&lt;br /&gt;
                           [ addend1 , addend2 ], &lt;br /&gt;
                           (minOutValues , maxOutValues) =&amp;gt; { &lt;br /&gt;
                              &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// ... do something with the min/max values ...&amp;lt;/span&amp;gt;&lt;br /&gt;
                              min = minOutValues.first();&lt;br /&gt;
                              max = maxOutputValues.first();&lt;br /&gt;
                           })&lt;br /&gt;
In most cases, this callback function would simply store the output values into local variables, as in:&lt;br /&gt;
 execute&lt;br /&gt;
    |.. minResult maxResult ..|&lt;br /&gt;
    ...&lt;br /&gt;
    self &lt;br /&gt;
        call:&#039;Arith [ MinMax ]&#039; with:#(10 20)&lt;br /&gt;
        into:[:mins :maxes |&lt;br /&gt;
            minResult := mins first.&lt;br /&gt;
            maxResult := maxes first.&lt;br /&gt;
        ].&lt;br /&gt;
    ...&lt;br /&gt;
    do something with minResult and maxResult&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
Exceptions in the called action can be handled in the calling action:&lt;br /&gt;
     ...&lt;br /&gt;
    [&lt;br /&gt;
        result := self call:&#039;Arith [ Quotient ]&#039; with:{ dividend . 0}.&lt;br /&gt;
    ] on:ZeroDivide do:[:ex |&lt;br /&gt;
        Transcript showCR:&#039;a division by zero occurred&#039;.&lt;br /&gt;
    ].&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
Notice, that a test-fail verdict is reported as TestFail, which is a subclass of Exception, &lt;br /&gt;
whereas a test-error verdict is reported as TestError, which is a subclass of Error.&lt;br /&gt;
Thus, to handle both failure and error in one handler, you may write:&lt;br /&gt;
    ...&lt;br /&gt;
    [&lt;br /&gt;
        result := self call: ...&lt;br /&gt;
    ] on:(Error, Exception) do:[:ex |&lt;br /&gt;
        Transcript showCR:&#039;either error or fail&#039;.&lt;br /&gt;
    ].&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
or in JS:&lt;br /&gt;
    ...&lt;br /&gt;
    try {&lt;br /&gt;
        result = call( ... )&lt;br /&gt;
    } catch(Error + Exception) {&lt;br /&gt;
        Transcript.showCR(&amp;quot;either error or fail&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
===== Reflection, Information, Queries and Accessing =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activityCreator&#039;&#039;&#039; () &amp;lt;br&amp;gt;The triggering activity (i.e. the caller). Except for special tricks, this is only useful to generate nice print messages (such as &amp;quot;activity foo, called from bar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activityProcess&#039;&#039;&#039; () &amp;lt;br&amp;gt;The thread executing the activity&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;blockDescription&#039;&#039;&#039; () &amp;lt;br&amp;gt;The definition of the activity (i.e. the tree definition item of the action&#039;s step)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;executor&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the current executor. See [[#Executor Functions|&amp;quot;Executor Functions&amp;quot;]] below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inputValueForPin&#039;&#039;&#039; (&#039;&#039;pin&#039;&#039;)&amp;lt;br&amp;gt;The value of a certain pin&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inputValueFor&#039;&#039;&#039; (&#039;&#039;pinName&#039;&#039;)&amp;lt;br&amp;gt;The value of a certain pin by name. Reports an error, if there is no such pin, the pin is unconnected or has no value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inputValueFor_ifAbsent&#039;&#039;&#039; (&#039;&#039;pinName&#039;&#039;, &#039;&#039;ifAbsentValue&#039;&#039;)&amp;lt;br&amp;gt;The value of a certain pin by name. Returns &amp;quot;ifAbsentValue&amp;quot; if there is no such pin, the pin is unconnected or has no value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inventory&#039;&#039;&#039; () &amp;lt;br&amp;gt;The inventory of the activity&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;resources&#039;&#039;&#039; () &amp;lt;br&amp;gt;All resources which have been acquired for the activity (as specified in the resource-definition of the action). Retrieves a collection of Resource objects, as described below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;resourcesForId&#039;&#039;&#039; (&#039;&#039;skillId&#039;&#039;) &amp;lt;br&amp;gt;Resources which have been acquired for one particular skill-requirement. The argument &#039;&#039;skillId&#039;&#039; corresponds to the name as specified in the first column of the resource definition of the action). Notice, that a collection of Resource objects is returned - even if only one resource has been acquired.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;step&#039;&#039;&#039; () &amp;lt;br&amp;gt;The corresponding step of the activity&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;stepLocalStorageAt&#039;&#039;&#039; (&amp;quot;&amp;lt;varName&amp;gt;&amp;quot;) &amp;lt;br&amp;gt;Retrieves a step&#039;s local storage value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;stepLocalStorageAt_put&#039;&#039;&#039; (&amp;quot;&amp;lt;varName&amp;gt;&amp;quot;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Defines a step&#039;s local storage value.&lt;br /&gt;
:Step local storage can be seen as a kind of static variable, which is only visible inside the code of a single execute function, but with the live time of the step. This means that the value is still present, when the step is executed the next time. However, it will vanish, whenever the diagram which contains the step is edited. Also, its value is not copied, when the step is copied. It is also not made persistent. The value will be reset to nil with every edit operation on the diagram, or via a menu function in the project&#039;s &amp;quot;More&amp;quot; menu, or the step&#039;s menu.&lt;br /&gt;
:Step local storage can be used to count the number of invocations, or to implement static state which is to be preserved between step executions.&lt;br /&gt;
:This is an experimental feature, only to be used by advanced users.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Environment Access =====&lt;br /&gt;
&lt;br /&gt;
Starting at every compound activity, a nested stack of outer environments is present, ending in a top project environment. The following activity methods provide access to some of them. This can be used to automatically setup environment variables from a configuration or when autodetecting a system-under-test&#039;s configuration and leaving the values in a defined outer environment. Depending on the intended lifetime of those values, one of the following environments should be chosen as target of such operations:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environment&#039;&#039;&#039; () &amp;lt;br&amp;gt;The currently valid environment variables of the compound step which contains this action, or (if none) of the test plan in which this action executes (see &amp;quot;[[#Environment Access|Environment Access]]&amp;quot; below)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;) &amp;lt;br&amp;gt;The value of an environment variable (in the environment as described above)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Changing the value of an environment variable (in the environment as describe above)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;executorEnvironment&#039;&#039;&#039; () &amp;lt;br&amp;gt; an environment which is only present during a single testplan execution&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;projectEnvironment&#039;&#039;&#039; () &amp;lt;br&amp;gt; an environment which is attached to the current test suite (but not persistent when the suite is saved/loaded from an ets file)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;browserEnvironment&#039;&#039;&#039; () &amp;lt;br&amp;gt; an environment which is attached to the expecco application window; i.e. present while the window is open (i.e. the current session). (it is not made persistent)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;systemEnvironment&#039;&#039;&#039; () &amp;lt;br&amp;gt; an environment which is present while the expecco application is running (i.e. the current session). (it is not made persistent)&lt;br /&gt;
&lt;br /&gt;
Except for the project environment, none of them are made persistent directly (i.e. the values will not saved with the &amp;quot;.ets&amp;quot;file). However, every test suite, test plan and compound block provides a description of initial values and how to compute them in their environment description, which is edited using the [[ Environment Editor ]] or which can be modified with actions from the reflection library.&lt;br /&gt;
Also, such descriptions can be saved and loaded separately from the test suite via the &amp;quot;&#039;&#039;Load/Save Parameter Set&#039;&#039;&amp;quot; menu functions of the &amp;quot;&#039;&#039;File&#039;&#039;&amp;quot; menu or via the &amp;quot;--parameters&amp;quot; [[Starting_expecco_via_Command_Line/en#Test_Parameters | command line argument]].&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Event Sending =====&lt;br /&gt;
Events can be pushed onto an event queue from either actions found in the standard library or via&lt;br /&gt;
API calls to the current activity (also from bridged elementary actions).&lt;br /&gt;
The global event handler should be already running (and especially, a handler should be registered) before the first&lt;br /&gt;
event is sent. Otherwise, the event might be ignored or an error is raised. A sample suite is found in &amp;quot;demos/d62_Event_Queue_Demos&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
* &#039;&#039;&#039;pushEvent&#039;&#039;&#039; (&#039;&#039;eventOrPayloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event onto the global event handler&#039;s event queue. The argument may be either an instance of Event, or the payload (which is packed into an Event instance with type #default). Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pushEventType_data&#039;&#039;&#039; (&#039;&#039;eventTypeSymbolOrNil&#039;&#039;, &#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event of type (or #default) onto the global event handler&#039;s event queue. Raises an error, if no global event handler process is running.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Executor Functions ====&lt;br /&gt;
&lt;br /&gt;
The executor (as returned from the current activity via the &amp;quot;&#039;&#039;executor()&#039;&#039;&amp;quot; function described above) is responsible&lt;br /&gt;
to execute steps in a network and elementary code in a controlled fashion. In addition to sequencing and assigning activities to a particular execution thread, it also cares for the activityLog and error handling.&lt;br /&gt;
Usually, you do not need to interact with an executor directly.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;executorsWorkingDirectory&#039;&#039;&#039; () &amp;lt;br&amp;gt;Temporary working directory. This is removed after the execution (i.e. useful only for very temporary files, which are generated in an action and read in another)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testplan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The currently executed testplan (nil if a block test blocks are executed)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;project&#039;&#039;&#039; () &amp;lt;br&amp;gt;Project (testsuite or library) in which the test is executed&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Resource Functions ====&lt;br /&gt;
&lt;br /&gt;
Resources can be assigned to an action as a &amp;quot;&#039;&#039;required resource&#039;&#039;&amp;quot;, and the execution will be synchronized with the&lt;br /&gt;
allocation and reservation of a particular resource as acquired from an inventory.&lt;br /&gt;
Once allocated, the resources are available to the action via &#039;&#039;resources()&#039;&#039; or &#039;&#039;resourcesForId()&#039;&#039; functions:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;resources&#039;&#039;&#039; () &amp;lt;br&amp;gt;retrieves the set of resources allocated for the action. The collection is keyed by the name as given in the &amp;quot;Resources&amp;quot; tab, the associated value is a resource instance providing the concrete values of the resource&#039;s skills.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;resourceForId&#039;&#039;&#039; (idString) &amp;lt;br&amp;gt;retrieves the resource allocated for the idString as given in the &amp;quot;Resources&amp;quot; tab, the returned value is a resource instance providing the concrete values of the resource&#039;s skills.&lt;br /&gt;
&lt;br /&gt;
Resource instances respond to the following protocol:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;name&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the resource&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;skillNamed&#039;&#039;&#039; (&#039;&#039;nameOrUUID&#039;&#039;) &amp;lt;br&amp;gt;Fetch a concrete skill-value of that resource. The argument can be either a skill&#039;&#039;s name, or the functional-UUID of the skill element (in the project tree).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;skillAttributeNamed&#039;&#039;&#039; (&#039;&#039;name&#039;&#039;) &amp;lt;br&amp;gt;Fetch a concrete skill-attribute-value of the resource&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Test Suite (Project) Functions ====&lt;br /&gt;
&lt;br /&gt;
Every activity, step or action has a reference to its containing project (or library, if imported).&lt;br /&gt;
The direct enclosing project/library is returned by the &amp;quot;project()&amp;quot; function, the top level project (i.e. the loaded suite) via the &amp;quot;topProject()&amp;quot; call.&lt;br /&gt;
Projects, Test Suites and Libraries are all the same kind of object (i.e. any project can be used as a test suite or imported into another as imported library). &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;documentation&#039;&#039;&#039; () &amp;lt;br&amp;gt;The documentation or nil&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;functionalId&#039;&#039;&#039; () &amp;lt;br&amp;gt;A unique ID which defines this testSuite independent of its name (remains constant after change)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;projectsWorkingDirectory&#039;&#039;&#039; () &amp;lt;br&amp;gt;Project directory - i.a. all attachments. This directory is created when a project file is loaded and is deleted when expecco is closed. Do not use it for permanently needed files.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;modelLanguageStringFor&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039;)&amp;lt;br&amp;gt;translates a string according to the model-language translation table&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;versionId&#039;&#039;&#039; () &amp;lt;br&amp;gt;A unique ID which defines this testSuite in exactly this version. (changed with any edit operation)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;elementWithName&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039;) &amp;lt;br&amp;gt;Retrieve an element by name&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;elementWithId&#039;&#039;&#039; (&#039;&#039;aUUID&#039;&#039;) &amp;lt;br&amp;gt;Retrieve an element by its version id&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;elementWithFunctionalId&#039;&#039;&#039; (&#039;&#039;aUUID&#039;&#039;)&amp;lt;br&amp;gt;Retrieve an element by its functional id&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;typeNamed&#039;&#039;&#039; (&#039;&#039;aTypeName&#039;&#039;)&amp;lt;br&amp;gt;Retrieve a datatype. To instantiate a type, write&amp;lt;br&amp;gt;&amp;quot;&amp;lt;code&amp;gt;(self project typeNamed:&#039;Foo&#039;) new&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Testplan Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;documentation&#039;&#039;&#039; () &amp;lt;br&amp;gt;The documentation or nil&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;name&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the Testplan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;tags&#039;&#039;&#039; () &amp;lt;br&amp;gt;A collection of tags of the testplan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;functionalId&#039;&#039;&#039; () &amp;lt;br&amp;gt;A unique ID which defines this testplan independent of its name (remains constant after change)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;versionId&#039;&#039;&#039; () &amp;lt;br&amp;gt;A unique ID which defines this testplan in exactly this version. (changed with any edit operation)&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Step Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;name&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the Step&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;tags&#039;&#039;&#039; () &amp;lt;br&amp;gt;A collection of tags of the Step&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;inputPins&#039;&#039;&#039;() &amp;lt;br&amp;gt;A collection with all input pins&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;inputPinForPinName&#039;&#039;&#039;(&#039;&#039;inputPinName&#039;&#039;) &amp;lt;br&amp;gt;The corresponding input pin. Raises an error, if no such input pin exists.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;inputPinForPinName_ifAbsent&#039;&#039;&#039;(&#039;&#039;inputPinName&#039;&#039;, &#039;&#039;ifAbsentValue&#039;&#039;) &amp;lt;br&amp;gt;The corresponding input pin. Returns &#039;&#039;ifAbsentValue&#039;&#039;, if no such input pin exists.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;outputPins&#039;&#039;&#039;() &amp;lt;br&amp;gt;A collection with all output pins&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;outputPinForPinName&#039;&#039;&#039;(&#039;&#039;outputPinName&#039;&#039;) &amp;lt;br&amp;gt;The corresponding output pin. Raises an error, if no such output pin exists.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;outputPinForPinName_ifAbsent&#039;&#039;&#039;(&#039;&#039;outputPinName&#039;&#039;, &#039;&#039;ifAbsentValue&#039;&#039;) &amp;lt;br&amp;gt;The corresponding output pin. Returns &#039;&#039;ifAbsentValue&#039;&#039;, if no such output pin exists.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span id=&amp;quot;Smalltalk_PinFunctions&amp;gt;Pin Functions&amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
The input and output pins can be referenced in elementary code directly by their name.&lt;br /&gt;
The name refers to the pin - &#039;&#039;&#039;NOT&#039;&#039;&#039; the passed value (this allows for the code to check, if a value is present). For indexed pins (i.e. in steps with a variable number of pins), the collection of pins is referred to by the name, and pins are accessed via an index (1..). See more about variable pins in the section below.&lt;br /&gt;
&lt;br /&gt;
===== Common to all Pins: =====&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;datatype&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the data type of the pin (Reflection-API)&lt;br /&gt;
&lt;br /&gt;
===== Input Pins: =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has received a value (useful to determine if there is a value if the trigger condition is &amp;quot;AndConnected&amp;quot; or &amp;quot;Or&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasEnvironmentFreezeValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has a freezeValue from an environment&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasFreezeValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has a freezeValue&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin is connected (but not frozen)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value of the pin. This is either the value received via a connection, or a constant freeze value, or an environment variable freeze value. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfPresent&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value of a pin or nil if the pin did not receive any value. Similar to &amp;quot;&amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the alternativeValue, if the pin did not receive any value. Similar to &amp;quot;&amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;mbxPinName&#039;&#039;.&#039;&#039;&#039;waitForValue&#039;&#039;&#039; () - &#039;&#039;Mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;The pin has to be a mailbox pin. The execution of this action will be suspended until the pin receives a value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;mbxPinName&#039;&#039;.&#039;&#039;&#039;waitForValueWithTimeout&#039;&#039;&#039; (&#039;&#039;seconds&#039;&#039;) - &#039;&#039;Mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Like above, but the execution will only wait for the specified time limit, given in seconds. The parameter is typically an integer, but can also be a fraction (e.g. 1/3) or a floating-point number (e.g. 0.3).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;mbxPinName&#039;&#039;.&#039;&#039;&#039;consumeValue&#039;&#039;&#039; () - &#039;&#039;Mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Consumes the current value which is present at the mailbox input pin. If there is another pending input value, &amp;lt;code&amp;gt;hasValue()&amp;lt;/code&amp;gt; will continue to return true, and &amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt; will return the next pending value.&lt;br /&gt;
&lt;br /&gt;
===== Output Pins: =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;outPinName&#039;&#039;.&#039;&#039;&#039;isBuffered&#039;&#039;&#039; () &amp;lt;br&amp;gt;True if the pin is buffered (only generates a value if the action completes successful)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;outPinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin is connected. This can be used to not perform expensive computations in an elementary action, iff no-one is interested in that value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;outPinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; (&#039;&#039;data&#039;&#039; ) &amp;lt;br&amp;gt;Writes the value. If the output pin is unbuffered and connected to another step&#039;s input pin, the other step&#039;s action may be triggered (if the other step&#039;s trigger condition is fulfilled). If the output pin is buffered, the datum will be passed to the connected input, when the action has finished with success.&lt;br /&gt;
&lt;br /&gt;
===== Variable Input Pins =====&lt;br /&gt;
&lt;br /&gt;
Elementary steps can have a variable number of input pins, if the pin&#039;s schema has the &amp;quot;variable pin&amp;quot; attribute set. To change the number of pins of a step in the diagram editor, pull the pin-handle of a placed step, to add or remove pins. In elementary code, the following API call entries (to the variable pin) are provided to deal with this situation:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039; &amp;lt;br&amp;gt; now refers to a collection of pins, representing the set of pins actually present at the step. In contrast to regular pins, where pinName refers to a single pin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;numberOfVariablePins&#039;&#039;&#039; () &amp;lt;br&amp;gt; returns the number of actual pins present in the step for the (variable) schema pin named &amp;quot;pinName&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;size&#039;&#039;&#039; () &amp;lt;br&amp;gt; same as the above &amp;quot;numberOfVariablePins&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;inputPinAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; returns the idx&#039;th actual pin of the schema pin named &amp;quot;pinName&amp;quot;. Notice this retrieves the pin for reflection queries, NOT the pin value. To get value or query if it has a value, call &#039;&#039;valueAt:&#039;&#039;() / &#039;&#039;hasValueAt&#039;&#039;(). Pin indexing starts with 1.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;at&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; same as inputPinAt(&#039;&#039;idx&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;hasValueAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; true if the idx&#039;th variable pin is connected and has received a value. Same as &amp;lt;code&amp;gt;hasValue()&amp;lt;/code&amp;gt; for variable input pins. Indices start with 1.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;values&#039;&#039;&#039; () &amp;lt;br&amp;gt;Retrieves the values passed to the pins as an array. The array contains nil entries for disconnected pins and those without a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;valuesPresent&#039;&#039;&#039; () &amp;lt;br&amp;gt;Retrieves the values as present; skips unconnected pins or those without a value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;valueAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; to get the idx&#039;th pin&#039;s value; raises an error if no value was given or pin is not connected. Same as &amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt; for variable input pins.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;valueIfPresentAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; to get the idx&#039;th pin&#039;s value, or nil if no value was given or pin is not connected&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varMbxPinName&#039;&#039;.&#039;&#039;&#039;waitForValueAt&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)  -&#039;&#039;Variable mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Same as &amp;lt;code&amp;gt;waitForValue()&amp;lt;/code&amp;gt; for variable input mailbox pins.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varMbxPinName&#039;&#039;.&#039;&#039;&#039;waitForValueAt_withTimeout&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;, &#039;&#039;seconds&#039;&#039;) - &#039;&#039;Variable mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Same as &amp;lt;code&amp;gt;waitForValue()&amp;lt;/code&amp;gt; for variable input mailbox pins.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varMbxPinName&#039;&#039;.&#039;&#039;&#039;consumeValueAt&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;) - &#039;&#039;Variable mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Same as &amp;lt;code&amp;gt;consumeValue()&amp;lt;/code&amp;gt; for variable input mailbox pins.&lt;br /&gt;
&lt;br /&gt;
===== Variable Output Pins =====&lt;br /&gt;
&lt;br /&gt;
Starting with expecco v2.1, steps can also have a variable number of output pins, if the schema has the &amp;quot;variable output pin&amp;quot; attribute set. To change the number of pins, pull the pin-handle of a placed step, to add or remove pins. In elementary code, the following API call entries (to the variable pin) are provided to deal with this situation:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;numberOfVariablePins&#039;&#039;&#039; () &amp;lt;br&amp;gt; returns the number of actual pins present in the step for the (variable) schema pin named &amp;quot;pinName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;outputPinAt_value&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt; write a value to the idx&#039;th output pin. Index starts with 1.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;outputPinAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; returns the idx&#039;th actual pin of the schema pin named &amp;quot;pinName&amp;quot;. Notice that this retrieves the pin; to write an output value to it, call &#039;&#039;value&#039;&#039;(v) on the returned pin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;at&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; same as outputPinAt(&#039;&#039;idx&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;outputPins&#039;&#039;&#039; () &amp;lt;br&amp;gt; returns a collection of all actual pins present in the step for the (variable) schema pin named &amp;quot;pinName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Datatype Functions ====&lt;br /&gt;
&lt;br /&gt;
A datatype can be retrieved by asking a pin for its datatype using the &#039;&#039;&#039;datatype&#039;&#039;&#039; () function.&lt;br /&gt;
This is sometimes useful in elementary code, in order to instantiate a new value (given the pin) or to ask for details of the type.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;name&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the Datatype&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isAnyType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is the builtin &amp;quot;Any&amp;quot; type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isArrayType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is an &amp;quot;Array&amp;quot; type (with any element type)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isCompoundType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is a compound (structure) type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isEnumType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is an enumeration type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isPrimaryType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is any builtin primary type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isRangeType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is a subrange of another type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isTupleType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is a tuple type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isUnionType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is a union type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isStringPrimaryType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is the builtin &amp;quot;String&amp;quot; primary type&lt;br /&gt;
&lt;br /&gt;
==== Enum Type Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnumType&#039;&#039;.&#039;&#039;&#039;values&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns an array of enum-value names (symbolic)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnumType&#039;&#039;.&#039;&#039;&#039;integerValueOf&#039;&#039;&#039; (&#039;&#039;elementName&#039;&#039;) &amp;lt;br&amp;gt;returns the associated integer value.&lt;br /&gt;
&lt;br /&gt;
==== Compound Type Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCompoundType&#039;&#039;.&#039;&#039;&#039;namedFieldDescriptions&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns an array of descriptions of the named fields (if any)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCompoundType&#039;&#039;.&#039;&#039;&#039;indexedFieldDescriptins&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns a description of indexed fields (if any)&lt;br /&gt;
&lt;br /&gt;
Each field description can be asked for the &amp;quot;fieldName()&amp;quot;, &amp;quot;fieldType()&amp;quot; and &amp;quot;defaultValue()&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Primary Type Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPrimaryType&#039;&#039;.&#039;&#039;&#039;typeClass&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns the underlying Smalltalk class, of which values are instances of.&lt;br /&gt;
&lt;br /&gt;
==== Range Type Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aRangeType&#039;&#039;.&#039;&#039;&#039;baseType&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns the underlying base type. Typically this will be the Integer primary type.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aRangeType&#039;&#039;.&#039;&#039;&#039;minValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns the minimum value of the range&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aRangeType&#039;&#039;.&#039;&#039;&#039;maxValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns the maximum value of the range&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Functions for Any Tree- or Diagram Element ====&lt;br /&gt;
&lt;br /&gt;
These include: BlockDescriptions, Types, TestPlans, TestCases, Steps, Connections, Pins, Annotations etc.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;versionId&#039;&#039;&#039; &amp;lt;br&amp;gt;A globally unique identifier (GUID or UUID) which is changed with every modification of the item&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;functionalId&#039;&#039;&#039; &amp;lt;br&amp;gt;A globally unique identifier (GUID or UUID) which is assigned once-and-for-all to the item&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;id&#039;&#039;&#039; &amp;lt;br&amp;gt;alias for versionId().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;tags&#039;&#039;&#039; &amp;lt;br&amp;gt;A collection of tags.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isAnnotation&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is an annotation (in a diagram)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isStep&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is a step (in a diagram)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isConnection&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is a connection (in a diagram)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isBlockDescription&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is a block description (in the tree)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isAttachment&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is any attachment (in the tree)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isFileAttachment&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is a file attachment (in the tree)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;taggedValueAt&#039;&#039;&#039; (&#039;&#039;aKey&#039;&#039;) &amp;lt;br&amp;gt;To retrieve a tagged value. These are usually preserved when objects are transported to/from other systems.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;taggedValueAt_put&#039;&#039;&#039; (&#039;&#039;aKey&#039;&#039;, &#039;&#039;anObject&#039;&#039;) &amp;lt;br&amp;gt;to change a tagged value. Only a limited set of datatypes are supported: anObject must be a &#039;&#039;&#039;String&#039;&#039;&#039; or a &#039;&#039;&#039;Number&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;propertyAt&#039;&#039;&#039; (&#039;&#039;aKey&#039;&#039;)&amp;lt;br&amp;gt;to retrieve an expecco property. These are expecco-internal properties. These are usually not recognized by other systems.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;propertyAt_put&#039;&#039;&#039; (&#039;&#039;aKey&#039;&#039;, &#039;&#039;anObject&#039;&#039;)&amp;lt;br&amp;gt;to set an expecco property. These are usually not recognized by other systems. Only a limited set of datatypes are supported: anObject must be a &#039;&#039;&#039;String&#039;&#039;&#039; or a &#039;&#039;&#039;Number&#039;&#039;&#039;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Groovy Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Groovy is an open source interpreter and compiler for a Java like scripting language which runs on top of the Java Virtual machine. For details, visit [http://groovy-lang.org/ &amp;quot;groovy-lang.org&amp;quot;] and especially the [http://groovy-lang.org/documentation.html Groovy Documentation Portal].&lt;br /&gt;
&lt;br /&gt;
Code written as a Groovy elementary block is not executed directly by expecco. Instead, the code is forwarded to a Groovy shell which runs inside a Java Virtual Machine (JVM). This may be a local JVM, whose sole purpose is to provide additional utility functions or which provides an interface to the actual system under test (SUT), or it may be the JVM which executes the tested application and is running physically on the SUT. &lt;br /&gt;
&lt;br /&gt;
By using Groovy blocks, expecco&#039;s basic black-box test functionality is extended to include powerful gray- and white-box tests. You can access the internals of objects inside the SUT, call its functions and even define new classes and functions and call them. Groovy is especially useful, if you have to install callback- or hooks inside the SUT, which interact back to expecco (e.g. to collect SUT-internal events and allow expecco to read those from the SUT). However, you should keep in mind that your tests may become affected by changes in the SUT and needs to be modified if interfaces change (which is a general property of white box tests, not a limitation of expecco).&lt;br /&gt;
&lt;br /&gt;
The machinery to interact with a JVM (and therefore to execute Groovy code blocks) requires the Java Bridge plugin, which is now (rel18.1) part of the basic expecco package. Groovy itself is available for free as a jar class library, which is loaded with or into the target application. The Java Bridge plugin already includes a prepackaged Groovy interpreter which can be loaded transparently into the SUT application whenever a Groovy block is executed. So except for the setting of the JVM path, no further setup or installation is required.&lt;br /&gt;
&lt;br /&gt;
=== Why use Groovy Elementary Blocks? ===&lt;br /&gt;
The Java Bridge and especially Groovy code is very useful when testing GUI frameworks, communication protocols or machine control soft- and hardware which is written in Java. Especially, if you have to call functions internal to the SUT in order to trigger actions or if you need to be informed about state changes via listeners or callbacks, Groovy is the perfect tool for the task. Note that calls into the JVM are relatively straight forward, using the method forwarding mechanism, even from Smalltalk code. However, callbacks and listeners, which usually have to be implemented as instances of special derived classes of a an abstract framework class, are hard to realize without Groovy.&lt;br /&gt;
&lt;br /&gt;
Without Groovy, you would have to add such classes to the software inside the SUT - e.g. by adding them to the tested software&#039;s jar packages, or by adding extra jar packages. In addition, you&#039;d have to provide a communication mechanism (socket, pipe or file interchange), by which your test action is able to retrieve this information.&lt;br /&gt;
&lt;br /&gt;
=== What is the Difference between a regular (expecco-) JavaScript Block and a Groovy Block? ===&lt;br /&gt;
&lt;br /&gt;
In one sentence: expecco JavaScript actions are executed inside expecco, Groovy actions inside the SUT (System Under Test) or any other external JVM (Java Virtual Machine).&lt;br /&gt;
&lt;br /&gt;
More detailed:&lt;br /&gt;
&lt;br /&gt;
Expecco&#039;s JavaScript actions are actually alternative syntactic forms of Smalltalk actions. When executed, they run inside the expecco executable and have access to any class or object inside expecco itself, or those which are passed in via input pins or environment variables.&lt;br /&gt;
&lt;br /&gt;
On the other hand, Groovy actions are &amp;quot;&#039;&#039;injected&#039;&#039;&amp;quot; (eg. downloaded) into a Java VM and execute in that object space. They cannot directly access expecco classes or objects, but instead can access all public classes and objects within the JVM in which they run, which can be the SUT (System Under Test). By means of proxy objects (which are forwarding operation-calls), expecco can deal with remote objects almost transparently: these can be returned from a Groovy action to expecco, and later be used again as arguments to other Groovy actions; i.e. they can be passed around via output- and input pins, stored in variables and inspected.&lt;br /&gt;
&lt;br /&gt;
=== What is the Difference between a Groovy Block and a Bridged Node Block? ===&lt;br /&gt;
&lt;br /&gt;
Groovy blocks execute inside a JVM (Java Virtual Machine) and can access any Java code (eg. classes inside a java application or inside a dynamically loaded jar-library).&lt;br /&gt;
&lt;br /&gt;
In contrast, Node actions are executed inside a Node (aka &amp;quot;Node.js&amp;quot;) interpreter (which is not a JVM). &lt;br /&gt;
&lt;br /&gt;
There are also slight differences in the syntax: Groovy is more Java-like, whereas Node blocks use pure JavaScript.&lt;br /&gt;
&lt;br /&gt;
=== Groovy Compilation Mechanism and Performance Issues ===&lt;br /&gt;
When a Groovy action is executed for the very first time, the block&#039;s code is transmitted via the bridge to the Groovy shell on the target JVM as a string. There, the code is parsed and an anonymous jar is created, containing Java byte code. Thus, there is some initial overhead involved in both sending the code and more so in compiling the code in the JVM. However, for every followup call, the JVM will directly call the generated code and run at full Java speed (i.e. the execution speed is almost as if native Java code was executed), although there is still some overhead due to the interprocess communication (typically a few milliseconds for every call)&lt;br /&gt;
&lt;br /&gt;
=== Using a Single Local JVM Connection / Executing Groovy Actions on the Local Machine ===&lt;br /&gt;
By default, a Groovy action is executed on a JVM which runs on the local machine; i.e. the machine on which expecco itself is running.&lt;br /&gt;
With the execution of the very first Groovy action, a JVM is started as defined in the expecco settings dialog, then a bridge connection is established to that JVM, and the Groovy interpreter (called &amp;quot;&#039;&#039;GroovyShell&#039;&#039;&amp;quot;) is loaded and instantiated on the JVM. Then a reference to that GroovyShell object is remembered and used for all followup Groovy actions which are to execute on that local JVM.&lt;br /&gt;
This default behavior is convenient if you want to use Java support libraries for reporting, statistics or other computations, or if your SUT is running inside a local JVM, or if you want to call interface functions (protocols) which actually talk to your SUT.&lt;br /&gt;
&lt;br /&gt;
=== Using a Particular JVM Connection / Executing Groovy on a Possibly Remote Machine ===&lt;br /&gt;
If you either need to customize the JVM startup and/or your test scenario has to talk to one or multiple remote systems (or multiple java programs within one scenario), you have to setup multiple java connections, and pass the connection to use to your Groovy actions.&lt;br /&gt;
This can be done either via an input pin, or via an expecco environment variable.&lt;br /&gt;
The algorithm to provide this is as follows:&lt;br /&gt;
&lt;br /&gt;
* if the action has a pin named &amp;quot;&amp;lt;code&amp;gt;groovy&amp;lt;/code&amp;gt;&amp;quot;, and it is connected, that pin&#039;s value is used as GroovyShell handle&lt;br /&gt;
* otherwise, if the environment contains a variable named &amp;quot;&amp;lt;code&amp;gt;GROOVY&amp;lt;/code&amp;gt;&amp;quot;, that variable&#039;s value is used&lt;br /&gt;
* otherwise, a new GroovyShell is instantiated and used, on the JVM which is given by:&lt;br /&gt;
** if the action has a pin named &amp;quot;&amp;lt;code&amp;gt;java&amp;lt;/code&amp;gt;&amp;quot;, and it is connected, that pin&#039;s value is used as Java Bridge handle&lt;br /&gt;
** otherwise, if the environment contains a variable named &amp;quot;&amp;lt;code&amp;gt;JAVA&amp;lt;/code&amp;gt;&amp;quot;, that variable&#039;s value is used&lt;br /&gt;
** finally, otherwise a local JVM connection is used (a shared singleton connection).&lt;br /&gt;
&lt;br /&gt;
This scheme makes the most common case easy, where only one single local JVM is required,&lt;br /&gt;
but still allows the flexibility to handle multiple JVMs and even multiple different GroovyShell instances within each JVM.&lt;br /&gt;
&lt;br /&gt;
To use input pins, you have to create corresponding pins manually, and the pin names MUST be &amp;quot;java&amp;quot; / &amp;quot;groovy&amp;quot;.&lt;br /&gt;
You cannot use these two reserved names as regular input pin names.&lt;br /&gt;
&lt;br /&gt;
=== Choosing another JVM Version ===&lt;br /&gt;
By default, the Groovy interpreter runs in the default Java virtual machine. That is the JWM which would be executed when&lt;br /&gt;
entering &amp;quot;&amp;lt;CODE&amp;gt;java&amp;lt;/CODE&amp;gt;&amp;quot; on the command line. To verify the version, open a command shell (or cmd.exe window) and enter&lt;br /&gt;
 java -version&lt;br /&gt;
&lt;br /&gt;
To specify another JVM, go to &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Java Bridge&#039;&#039;&amp;quot;,&lt;br /&gt;
and enter the path to a JRE (Java Runtime Environment) folder into the &amp;quot;&#039;&#039;Java Installation Path&#039;&#039;&amp;quot; field.&lt;br /&gt;
You can also enter a JDK (Java Development Kit) folder name into that field.&amp;lt;br&amp;gt;See also [[Settings_JavaBridgeSettings]].&lt;br /&gt;
&lt;br /&gt;
=== Additional JAR Class Libraries ===&lt;br /&gt;
By default, the Groovy code runs inside a JVM which has its classPath initialized from the preferences.&lt;br /&gt;
These class path preferences can be changed in the &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Project Management&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Groovy Class Path&#039;&#039;&amp;quot; settings dialog.&lt;br /&gt;
Additional jars can be added to the common classPath  (before a JVM is started) by the &amp;quot;[&#039;&#039;Add JAR to Groovy Class Path&#039;&#039;]&amp;quot; action,&lt;br /&gt;
or dynamically to a concrete already running JVM instance via the &amp;quot;[&#039;&#039;Add JAR to JVM&#039;&#039;]&amp;quot; action.&lt;br /&gt;
&lt;br /&gt;
Notice that you have to restart existing groovy connections to make such changes effective (via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Shut Down Bridge Connections&#039;&#039;&amp;quot; menu function).&lt;br /&gt;
&lt;br /&gt;
=== Groovy Code Snippets / Examples ===&lt;br /&gt;
==== Calling Existing Code in the System Under Test (SUT) via a Groovy Action====&lt;br /&gt;
&lt;br /&gt;
A Groovy block&#039;s code looks very similar to a regular JavaScript block&#039;s code (with some differences in the Groovy language). &lt;br /&gt;
However, it is executed inside a JVM, which may be inside the SUT.&lt;br /&gt;
It can therefore instantiate Java objects and call static and member functions inside the target system, if it is programmed in Java.&lt;br /&gt;
&lt;br /&gt;
For example, too call a static function named &amp;quot;&#039;&#039;foo&#039;&#039;&amp;quot; in a class named &amp;quot;&#039;&#039;MyTestClass&#039;&#039;&amp;quot;, use the following Groovy block:&lt;br /&gt;
&lt;br /&gt;
 def execute() {&lt;br /&gt;
    MyTestClass.foo(&amp;quot;hello world&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
if the class is located in another package (or especially: in one of your own), &lt;br /&gt;
use explicit package prefixes:&lt;br /&gt;
 def execute() {&lt;br /&gt;
    javax.swing.JFrame frame = new javax.swing.JFrame();&lt;br /&gt;
    javax.swing.JButton button = new javax.swing.JButton( &amp;quot;Press Me&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
    frame.add(button);&lt;br /&gt;
    frame.setSize(300,100);&lt;br /&gt;
    frame.setVisible(true);&lt;br /&gt;
 }&lt;br /&gt;
or an import declaration:&lt;br /&gt;
&lt;br /&gt;
 import javax.swing.*;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of import definitions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    JFrame frame = new JFrame();&lt;br /&gt;
    JButton button = new JButton( &amp;quot;Press Me&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
    frame.add(button);&lt;br /&gt;
    frame.setSize(300,100);&lt;br /&gt;
    frame.setVisible(true);&lt;br /&gt;
 }&lt;br /&gt;
Notice that you may not remove the comment line starting with &amp;quot;// end of....&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;This separator pattern has been hardcoded into the Groovy machinery to separate any class and import&lt;br /&gt;
definitions from the execution method.&lt;br /&gt;
&lt;br /&gt;
==== Defining a New Class in the System Under Test using Groovy ====&lt;br /&gt;
[[Bild:Groovy_Defining_Class1.png|thumb|300px|Drag this image into expecco]]&lt;br /&gt;
You can define your own classes in a Groovy block:&lt;br /&gt;
&lt;br /&gt;
For demonstration, let&#039;s start with a simple running example:&lt;br /&gt;
 class TestSleep {&lt;br /&gt;
   static void main(String[] args) {          &lt;br /&gt;
      println &#039;Step 1&#039;&lt;br /&gt;
      sleep(1000)&lt;br /&gt;
      println &#039;Step 2&#039;&lt;br /&gt;
      sleep(1000)&lt;br /&gt;
      println &#039;Step 3&#039;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of definitions -- do not remove this line unless imports above is empty&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    TestSleep.main(null);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Instances of new classes may be required especially to install listeners and callbacks when testing UI or server applications. A typical scenario is when you want expecco to be informed about mouse or keyboard events (MouseListener).&lt;br /&gt;
&lt;br /&gt;
Usually, instances of such classes are created in one Groovy action,&lt;br /&gt;
and passed to expecco via an output pin:&lt;br /&gt;
&lt;br /&gt;
 class MyClass extends Object {&lt;br /&gt;
    Object someState;&lt;br /&gt;
 &lt;br /&gt;
    def set_someState(Object newValue) {&lt;br /&gt;
        someState = newValue;&lt;br /&gt;
    }&lt;br /&gt;
    def get_someState() {&lt;br /&gt;
        return someState;&lt;br /&gt;
    }&lt;br /&gt;
    def String toString() {&lt;br /&gt;
        return &amp;quot;a very\nlong\nmultiline\na\nb\nstring\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of local definitions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    outputPin.value( new MyClass() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Then, additional Groovy actions take that as an input value and call the classes methods:&lt;br /&gt;
 def execute() {&lt;br /&gt;
    Object myInst = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
    myInst.setSomeState(123);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
or:&lt;br /&gt;
 def execute() {&lt;br /&gt;
    Object myInst = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
    output.value( myInst.getSomeState() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== Defining a Listener Class in the System Under Test using Groovy ====&lt;br /&gt;
A common pattern in Java communication frameworks is to define an abstract classes or interfaces which has to be subclassed by users of the framework. This pattern is common for callbacks or event listeners. The programmer has to define a listener class, create an instance of it, and register it towards the communication framework. To interact with such a framework in expecco, you will need a listener class, which responds to callbacks from the framework and either remembers them for later queries from a testcase&#039;s activity, or by directly calling back into expecco. The later is much harder to deal with, as those callbacks may come at any time, even when the test has already finished or the test is being debugged (remember that the JVM may run independent from expecco). So synchronization issues may be hard to solve. It is much easier and recommended to implement the first approach: the listener collects incoming events, until expecco is ready to process them.&lt;br /&gt;
&lt;br /&gt;
You will need an elementary Groovy block to instantiate and register the listener towards the framework similar to the conceptual code below:&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// a Groovy Elementary Block&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 import &amp;lt;interface or abstract class from which to inherit&amp;gt;;&lt;br /&gt;
 &lt;br /&gt;
 class MyListener extends AbstractListener {&lt;br /&gt;
    ArrayList eventQueue = new ArrayList();&lt;br /&gt;
    Object eventNotifier = new Object();&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;/**&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  * Called from a framework when an event occurs.&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  */&amp;lt;/span&amp;gt;&lt;br /&gt;
    public void onExampleEvent(Object event) {&lt;br /&gt;
        synchronized (eventQueue) {&lt;br /&gt;
            eventQueue.add(event);&lt;br /&gt;
        }&lt;br /&gt;
        synchronized (eventNotifier) {&lt;br /&gt;
            eventNotifier.notifyAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;/**&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  * Called from expecco to fetch next event.&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  *&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  * Of there is no event in the queue, blocks&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  * until an event arrives (by means of #onExampleEvent())&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  */&amp;lt;/span&amp;gt;&lt;br /&gt;
    public Object getNextEvent() {&lt;br /&gt;
        while (true) {&lt;br /&gt;
            synchronized (eventQueue) {&lt;br /&gt;
                if (! eventQueue.isEmpty()) {&lt;br /&gt;
                    return eventQueue.remove(0);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            synchronized (eventNotifier) {&lt;br /&gt;
                try {&lt;br /&gt;
                    eventNotifier.wait();&lt;br /&gt;
                } catch (InterruptedException ie) {&lt;br /&gt;
                    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// Pass, try again&amp;lt;/span&amp;gt;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of local definitions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// called from expecco, to instantiate a listener&amp;lt;/span&amp;gt;&lt;br /&gt;
 def execute() {&lt;br /&gt;
    var theListener = new MyListener();&lt;br /&gt;
 &lt;br /&gt;
    framework.registerListener ( theListener );&lt;br /&gt;
    outputPin.value( theListener ); &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// return it to expecco&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Make sure that the above elementary code is called from your activity diagram in the initialization/setup phase, and that the returned listener reference is either remembered in an environment variable of your suite, or passed down to the actual test case via input/output pins.&lt;br /&gt;
&lt;br /&gt;
Define an additional elementary block (here in JavaScript, but could also be Smalltalk or Groovy), which takes the listener as input pin and fetches the next event via &amp;lt;code&amp;gt;getNextEvent()&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// a JavaScript Elementary Block&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 execute() {&lt;br /&gt;
    var theListener;&lt;br /&gt;
    var event;&lt;br /&gt;
  &lt;br /&gt;
    theListener = inPin.value();&lt;br /&gt;
    event = theListener.getNextEvent();&lt;br /&gt;
    outpin.value ( event );&lt;br /&gt;
 }&lt;br /&gt;
The above code blocks the test suite until an event arrives. It may be useful to add another method to query the number of received events, or to flush any previously received and already enqueued events.&lt;br /&gt;
&lt;br /&gt;
In your test case, perform any stimulation required to make the framework generate an event, so that the listener&#039;s framework entry is called.&lt;br /&gt;
Then, invoke the #getNextEvent() action to suspend execution until an incoming event arrives (you will probably set a [[DiagramElements-Pin#Timelimit Input Pin|time limit]] on that step&#039;s execution). Once this action finishes, the event is available in expecco as a reference to the real event object (remember: the event object is an object inside the remote Java machine, so what you have in expecco is a handle to that remote object).&lt;br /&gt;
&lt;br /&gt;
All getters, setters and other methods of the event&#039;s implementation can be invoked from elementary code (any of the programming languages can do that, due to the message forwarding of the bridge).&lt;br /&gt;
&lt;br /&gt;
For example, assuming that the event provides getEventID() and getMessageString() getters,&lt;br /&gt;
which can be called from a Smalltalk action with:&lt;br /&gt;
 id := theEvent getEventID. msg := theEvent getMessageString.&lt;br /&gt;
and from a JavaScript action or from another Groovy action witht:&lt;br /&gt;
 id = theEvent.getEventID(); msg = theEvent.getMessageString();.&lt;br /&gt;
&lt;br /&gt;
Also, the expecco object inspector has been enhanced to recognize those proxy bridge objects, and presents the internal state, inheritance and class protocol in a multitab fashion. This makes looking into those remote objects almost as comfortable as looking into local ones.&lt;br /&gt;
&lt;br /&gt;
==== Accessing JMX MBeans ====&lt;br /&gt;
&lt;br /&gt;
 import java.lang.management.*&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of definitions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    def os = ManagementFactory.operatingSytemMXBean;&lt;br /&gt;
    def mem = ManagementFactory.memoryMXBean;&lt;br /&gt;
 &lt;br /&gt;
    Transcript.showCR(&amp;quot;OS architecture: &amp;quot; + os.arch.toString() );&lt;br /&gt;
    Transcript.showCR(&amp;quot;MEM heapUsage  : &amp;quot; + mem.heapMemoryUsage.toString() );&lt;br /&gt;
    Transcript.showCR(&amp;quot;POOLS:&amp;quot;);&lt;br /&gt;
    ManagementFactory.memoryPoolMXBeans.each { eachPool -&amp;gt;&lt;br /&gt;
        Transcript.showCR(&amp;quot;  pool name     : &amp;quot; + eachPool.name.toString() );&lt;br /&gt;
        Transcript.showCR(&amp;quot;  pool peakUsage: &amp;quot; + eachPool.peakUsage.toString() );&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
Please refer to the corresponding Java documentation for details.&lt;br /&gt;
&lt;br /&gt;
==== Executing Jython, JRuby or other Script Code inside the JVM ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|16px]]  the following example is somewhat outdated due to the new builtin support for jython (in 19.2).&lt;br /&gt;
&lt;br /&gt;
The following example executes Jython (Python) code inside the JVM (please make sure that the jython jar is in your Groovy class path):&lt;br /&gt;
 import org.python.util.PythonInterpreter; &lt;br /&gt;
 import org.python.core.*; &lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of definitions -- do not remove this line unless imports above is empty&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def main()&lt;br /&gt;
    throws PyException&lt;br /&gt;
 { &lt;br /&gt;
    Properties p = new Properties();&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// p.setProperty(&amp;quot;sys.path&amp;quot;, &amp;quot;/Users/cg/work/exept/bridgeFramework/javaBridge/javaBin/jython2.7.0&amp;quot;);&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    p.setProperty(&amp;quot;python.path&amp;quot;, &amp;quot;&amp;lt;path to jython2.7.0/Lib&amp;gt;&amp;quot;);&lt;br /&gt;
    p.setProperty(&amp;quot;python.home&amp;quot;, &amp;quot;&amp;lt;jython2.7.0&amp;gt;&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    Object props = System.getProperties();&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// String[] args = new String[0];&amp;lt;/span&amp;gt;&lt;br /&gt;
    String[] args = { &amp;quot;&amp;quot; };&lt;br /&gt;
    PythonInterpreter.initialize(props, p, args);&lt;br /&gt;
 &lt;br /&gt;
    PythonInterpreter interp =&lt;br /&gt;
        new PythonInterpreter();&lt;br /&gt;
 &lt;br /&gt;
    System.out.println(&amp;quot;Hello, brave new world&amp;quot;);&lt;br /&gt;
    interp.exec(&amp;quot;import sys&amp;quot;);&lt;br /&gt;
    interp.exec(&amp;quot;print sys&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    interp.set(&amp;quot;a&amp;quot;, new PyInteger(42));&lt;br /&gt;
    interp.exec(&amp;quot;print a&amp;quot;);&lt;br /&gt;
    interp.exec(&amp;quot;x = 2+2&amp;quot;);&lt;br /&gt;
    PyObject x = interp.get(&amp;quot;x&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    System.out.println(&amp;quot;x: &amp;quot;+x);&lt;br /&gt;
    System.out.println(&amp;quot;Goodbye, cruel world&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    main();&lt;br /&gt;
 }&lt;br /&gt;
Of course, you can also write the &amp;quot;interp&amp;quot; instance to an output pin, and remember it somewhere or pass it to other actions. Then, other actions can directly invoke the &amp;quot;exec(...)&amp;quot; function, without instantiating a new interpreter.&lt;br /&gt;
&lt;br /&gt;
=== Groovy Datatype Limitations ===&lt;br /&gt;
&lt;br /&gt;
==== Integer types ====&lt;br /&gt;
As Groovy dynamically compiles to plain Java bytecode and executes on top of a regular JVM, the integer range is limited to 32bit (64bit for &amp;quot;long int&amp;quot; types).&lt;br /&gt;
No automatic conversion between small and large integers is performed. If required, you will have to use a BigNum package and/or cast int to long int. There is currently no automatic conversion or transparent support to pass large numbers from expecco to Groovy and vice versa. Integers passed from Java to expecco will be represented as instances of the Integer type there.&lt;br /&gt;
&lt;br /&gt;
==== Limited Object Conversion to/from Groovy ====&lt;br /&gt;
Some limited form of object conversion is automatically performed when passing expecco&#039;s Smalltalk objects to Groovy, and back when returning values from Groovy. This conversion especially affects values passed to/from pins of a Groovy action.&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the conversion process:&lt;br /&gt;
{|  Border &lt;br /&gt;
! from Smalltalk&lt;br /&gt;
! to Java and from Java&lt;br /&gt;
! to Smalltalk&lt;br /&gt;
! &lt;br /&gt;
|- &lt;br /&gt;
| String &lt;br /&gt;
| String &lt;br /&gt;
| String&lt;br /&gt;
|- &lt;br /&gt;
| Integer (up to 32/64 bit)&lt;br /&gt;
| int, long int, boxed Integer&lt;br /&gt;
| Integer&lt;br /&gt;
|- &lt;br /&gt;
| Float, Double&lt;br /&gt;
| float, double; boxed or unboxed&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Notice that Smalltalk Floats have double precision)&lt;br /&gt;
|- &lt;br /&gt;
| Fraction&lt;br /&gt;
| float, double; boxed or unboxed (danger alert: precision may be lost)&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Notice that Smalltalk Floats have double precision)&lt;br /&gt;
|- &lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
|- &lt;br /&gt;
| Array of any above&lt;br /&gt;
| ArrayList of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
|- &lt;br /&gt;
| other Smalltalk Object(!)&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(!) does not work, yet: at the time of writing, Smalltalk objects other than the basic types listed above cannot be passed to Java.&lt;br /&gt;
However, the reverse direction is possible, and Smalltalk includes a mechanisms to handle (and even inspect) remote Java objects.&lt;br /&gt;
&lt;br /&gt;
==== No Smalltalk Classes, No Smalltalk Objects in Groovy ====&lt;br /&gt;
Of course, no Smalltalk class can be used directly in Groovy code.&lt;br /&gt;
And Smalltalk objects can only be passed as opaque handles to/from Groovy as described above.&lt;br /&gt;
However, all Java classes are at your hands now!&lt;br /&gt;
Some limited interaction with expecco and underlying Smalltalk objects is possible via the &amp;quot;&amp;lt;code&amp;gt;eval()&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;perform()&amp;lt;/code&amp;gt;&amp;quot; API described below.&lt;br /&gt;
&lt;br /&gt;
However, in general: if more complex objects need to be interchanged, this must be either done by converting them to an array (of objects), possibly an array of arrays, which is passed to a Groovy &amp;quot;interface function&amp;quot; first, which instantiates the required Java object(s). Or, alternatively to some ASCII representation (XML or JSON, for a more lightweight approach) and convert this back and forth.&lt;br /&gt;
&lt;br /&gt;
=== Handling of Java (and Groovy) Objects in expecco/Smalltalk ===&lt;br /&gt;
&lt;br /&gt;
==== Java Object References (Handles) ====&lt;br /&gt;
&lt;br /&gt;
Groovy elementary function can return references to Java objects via output pins. Because the actual object is located inside a JVM (i.e. outside of expecco), these references are treated like opaque handles by the underlying Smalltalk runtime system. However, a mechanism is provided to allow for almost transparent access to the referenced object&#039;s private slots, its classes&#039; static slots, its class hierarchy and method information. The object inspector is able to present that information in a convenient way, similar to how Smalltalk objects are presented. Also methods of the Java object can be called and values returned to expecco.&lt;br /&gt;
&lt;br /&gt;
==== Message Forwarding ====&lt;br /&gt;
&lt;br /&gt;
Smalltalk and JavaScript code can send regular messages to Java objects inside a remote JVM. This is possible via the Smalltalk &amp;quot;&amp;lt;code&amp;gt;doesNotUnderstand:&amp;lt;/code&amp;gt;&amp;quot; mechanism, which intercepts any call, sends a message to the real object (via the Java Bridge), awaits an answer and returns the result, which is usually a reference to another Java object. &lt;br /&gt;
&lt;br /&gt;
All of this is transparent to the programmer of the elementary code, except for the fact that Java method naming is different from Smalltalk. And of course a performance penalty, due to the interprocess communication, marshalling overhead and dynamic lookup via reflection on the Java side.&lt;br /&gt;
&lt;br /&gt;
==== Method Name Conversions ====&lt;br /&gt;
&lt;br /&gt;
When a message is sent from Smalltalk code to a Java object, a message translation mechanism similar to the Smalltalk &amp;lt;-&amp;gt; JavaScript mechanism is used:&lt;br /&gt;
 foo                  -&amp;gt; foo()&lt;br /&gt;
 foo:arg              -&amp;gt; foo(arg)&lt;br /&gt;
 foo:a1 _:a2 ... _:aN -&amp;gt; foo(a1, a2, ... aN) where the &amp;quot;_&amp;quot; are arbitrary strings.&lt;br /&gt;
&lt;br /&gt;
thus, to call a Java object&#039;s &amp;quot;installHandler(arg1, arg2, arg3)&amp;quot; function, you should write in Smalltalk:&lt;br /&gt;
 javaObject installHandler:arg1 _:arg2 _:arg3&lt;br /&gt;
and in JavaScript:&lt;br /&gt;
 javaObject.installhandler(arg1, arg2, arg3)&lt;br /&gt;
&lt;br /&gt;
It is obvious, that this kind of code is better written in JavaScript, being the same as a native Java call would look like.&lt;br /&gt;
&lt;br /&gt;
==== Conversion of Dynamic Smalltalk Objects to Static Java Types ====&lt;br /&gt;
&lt;br /&gt;
Inside expecco (which is running under a Smalltalk VM), all object references are dynamically typed.&lt;br /&gt;
This means, that in Smalltalk, every object holds a reference to its class and in principle, any object can be passed as argument to&lt;br /&gt;
a called function.&lt;br /&gt;
In contrast, Java requires the type of a function argument to be declared (either as a class or interface),&lt;br /&gt;
and the argument type(s) are part of a method&#039;s signature.&lt;br /&gt;
&lt;br /&gt;
Therefore, when calling a Java function from Smalltalk, the correct function must be found by reflection at execution time.&lt;br /&gt;
&lt;br /&gt;
For example, if the Java object provides two methods as in:&lt;br /&gt;
&lt;br /&gt;
 public void foo(Integer arg) { ... }&lt;br /&gt;
&lt;br /&gt;
 public void foo(Float arg) { ... }&lt;br /&gt;
&lt;br /&gt;
and it is called from Smalltalk with:&lt;br /&gt;
&lt;br /&gt;
 aJavaObjectHandle foo: 1&lt;br /&gt;
&lt;br /&gt;
then the &amp;quot;Integer&amp;quot;-argument version of foo must be called.&lt;br /&gt;
&lt;br /&gt;
Whereas if called as:&lt;br /&gt;
&lt;br /&gt;
 aJavaObjectHandle foo: 1.0&lt;br /&gt;
&lt;br /&gt;
then the &amp;quot;Float&amp;quot;-argument version is to be called.&lt;br /&gt;
&lt;br /&gt;
For this, the Java Bridge side uses reflection to scan the available methods for a best fit,&lt;br /&gt;
and transforms the passed Smalltalk argument to the best matching type before calling the actual function.&lt;br /&gt;
&lt;br /&gt;
There are some rare situations, where this automatic lookup fails or finds a wrong method.&lt;br /&gt;
For example, if same-named functions exist with&lt;br /&gt;
both a &amp;quot;&amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&amp;quot; (unboxed) and a &amp;quot;&amp;lt;code&amp;gt;Float&amp;lt;/code&amp;gt;&amp;quot; (boxed) argument,&lt;br /&gt;
and you need to make sure which is called.&lt;br /&gt;
In such cases, you can either use a Groovy block as mediator, which calls the desired function with an explicitly casted argument, and call the Groovy block from Smalltalk (or JavaScript) or use an explicit cast operation (&amp;quot;&amp;lt;code&amp;gt;Bridge2::Cast object:o as:typeName&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Current IDE Limitations ====&lt;br /&gt;
&lt;br /&gt;
The Smalltalk IDE has currently only limited support to extract and present Java&#039;s static type information. Currently, there is no class- and function name completion in the editor, making elementary code development for Java/Groovy less pleasant. Therefore, for complicated setups, it is a good idea to open a specialized Java development environment (e.g. eclipse) in parallel, and test the setup code there before copy-pasting it into a Groovy block.&lt;br /&gt;
&lt;br /&gt;
Eclipse is also useful to find out class- and method names during development.&lt;br /&gt;
&lt;br /&gt;
=== Groovy Code API ===&lt;br /&gt;
&lt;br /&gt;
Groovy code supports a &#039;&#039;&#039;subset&#039;&#039;&#039; of the above activity functions, which is intended provide an interface similar to the JavaScript and Smalltalk elementary code API. Of course, technically for every API function below, the elementary code executing in the remote Java VM has to make a remote procedure call back to expecco. On the JVM side, this is done very similar to the above described remote message mechanism, when messages are sent from Smalltalk to Java/Groovy. However, due to the static type system, it is not possible to call previously unknown interfaces. Therefore, only a fixed set of API entry points is supported.&lt;br /&gt;
&lt;br /&gt;
==== Attention / Warning (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
Unless explicitly prevented by the &amp;quot;&amp;lt;code&amp;gt;mayStillDoExpeccoCalls()&amp;lt;/code&amp;gt;&amp;quot; function ([[#Special_Functions (Groovy) |described below]]),&lt;br /&gt;
all called expecco functions listed below will ONLY work as expected WHILE the Groovy action is still ACTIVE (i.e. while inside the Groovy &amp;quot;&amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt;&amp;quot; function).&lt;br /&gt;
&lt;br /&gt;
The reason is that expecco ensures that handlers, which are responsible for transferring information from the Groovy code back to expecco,&lt;br /&gt;
will always be released, when the Groovy step has finished its execution.&lt;br /&gt;
This is mostly required to prevent memory leaks in the Java VM, because the observer instance object is registered inside the JVM and would remain there forever, if not unregistered. This observer object is a proxy for Java code, which implements all the functions below and forwards them (via an IPC mechanism) to expecco. One new such object is required for every Groovy action execution and if not released, they sooner or later consume huge amounts of JVM memory. Therefore by default, the observer is released after the Groovy action execution.&lt;br /&gt;
&lt;br /&gt;
In most Groovy blocks this is not a problem, except for those which install callback methods,&lt;br /&gt;
AND those callbacks get called AFTER the Groovy block has finished (for example by another Java thread),&lt;br /&gt;
AND the callback code calls one of those expecco interface functions. This includes the Transcript output functions, notifications and pin value writers.&lt;br /&gt;
&lt;br /&gt;
Unless the observer is still around, callbacks are ignored and behave like a no-operation, if called after the step has finished.&lt;br /&gt;
Of course, writing to a pin from within a callback AFTER the execute() function has finished does not work in any case (with or without a kept observer). The behavior in this case is undefined; currently, it is a no-operation, but it may be changed to raise an error in future versions.&lt;br /&gt;
&lt;br /&gt;
==== The Current Activity (Groovy) ====&lt;br /&gt;
The current activity instance is accessed as &amp;quot;&#039;&#039;this&#039;&#039;&amp;quot; inside the Groovy action code (like in an elementary JavaScript block). For every executed action, a new activity object is instantiated. It is usually alive during the execution only (i.e. it is destroyed and its memory reused automatically, after the block&#039;s action has finished). &lt;br /&gt;
&lt;br /&gt;
In Groovy (as in JavaScript or Java), if no receiver is given for a function call, &amp;quot;&#039;&#039;this&#039;&#039;&amp;quot; is the implicit receiver. Thus the statements &amp;quot;&amp;lt;CODE&amp;gt;this.logInfo(&amp;quot;hello&amp;quot;)&amp;lt;/CODE&amp;gt;&amp;quot; and &amp;quot;&amp;lt;CODE&amp;gt;logInfo(&amp;quot;hello&amp;quot;)&amp;lt;/CODE&amp;gt;&amp;quot; are equivalent.&lt;br /&gt;
&lt;br /&gt;
==== Objects are passed by Reference ====&lt;br /&gt;
Except for Strings and Numbers, objects are passed from Groovy to expecco by reference. These references can later be sent back to other Groovy actions transparently. Notice, that these references will keep the Groovy object (which is actually a Java object) alive until the reference object is garbage collected in expecco. Be aware that such references may have a very long life time, if kept in an activity log. Therefore, output pins which receive such references should either be marked as non-logging, or you should set the &amp;quot;&#039;&#039;Log Strings of Bridge Objects&#039;&#039;&amp;quot; flag in the [[Settings_LoggingSettings/en||&amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Logging&#039;&#039;&amp;quot; dialog]].&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; () &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution. The infoString argument will be shown in the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;]) &amp;lt;br&amp;gt;Report a failure (in the SUT) with optional infoString. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;]) &amp;lt;br&amp;gt;Report an inconclusive test (with optional infoString). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;])&amp;lt;br&amp;gt;Finishes the current activity with success.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;])&amp;lt;br&amp;gt;Finishes the current testCase with success. The optional infoString argument will be shown in the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testPass&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;])&amp;lt;br&amp;gt;Same as pass(); for compatibility with bridged languages where &amp;quot;pass&amp;quot; is a reserved keyword (i.e. python).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logging (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, &#039;&#039;detail&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, &#039;&#039;detail&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, detail) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;[[Settings_LoggingSettings/en|Execution-Log-Settings]]&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Same as &#039;&#039;alert()&#039;&#039; (for Smalltalk protocol compatibility).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Reflection, Information, Queries and Accessing (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;) &amp;lt;br&amp;gt;The value of an environment variable&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Changing the value of an environment variable.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text plan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlanItem&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Interaction with Expecco and Debugging (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inspect&#039;&#039;&#039; (&#039;&#039;javaObject&#039;&#039;) &amp;lt;br&amp;gt;Opens the expecco-inspector showing details of the argument object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;halt&#039;&#039;&#039;() or &#039;&#039;&#039;halt&#039;&#039;&#039;(&#039;&#039;message&#039;&#039;) &amp;lt;br&amp;gt;stops (breakpoint) and opens the expecco-debugger; however, this debugger cannot show the internals of the suspended Groovy code, but will only present the expecco calling chain up to the bridge call.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Special Functions (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;mayStillDoExpeccoCalls&#039;&#039;&#039; (&#039;&#039;boolean&#039;&#039;) &amp;lt;br&amp;gt;Ensures that the API-functions described here will still be callable (by Java callback functions from other threads) even after the step has finished execution. In other words, it prevents releasing the observer object which is responsible for the transfer of information between the two systems. Be aware that this object remains and will never be released, until the bridge connection is closed. I.e. there is a potential for a memory leak inside the Java VM here.&lt;br /&gt;
:Even with mayStillDoExpeccoCalls(true), only functions which are not depending on the step&#039;s activity may be called after the activity has finished. This includes event, logging and transcript/stderr functions, but no pin access or verdict reporting functions. &lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Pin Functions (Groovy) ====&lt;br /&gt;
Currently, Groovy blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
Attention:&lt;br /&gt;
&amp;lt;br&amp;gt;Groovy uses many more reserved keywords for syntax than JavaScript or Smalltalk. These keywords cannot be used as pin names, and you will get a syntax error (&amp;quot;&amp;lt;foo&amp;gt; token not expected&amp;quot;) if you try. Be careful to not name your pins as any of: &amp;quot;in&amp;quot;, &amp;quot;return&amp;quot;, &amp;quot;class&amp;quot;, &amp;quot;private&amp;quot;, &amp;quot;public&amp;quot;, etc. As a proven best practice, add a &amp;quot;Pin&amp;quot; suffix to your pin names (i.e. name it &amp;quot;inPin&amp;quot;, instead of &amp;quot;in&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
===== Input Pins (Groovy) =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;hasValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;value&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value of the pin. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the alternativeValue if the pin did not receive any value.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Output Pins (Groovy) =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;isBuffered&#039;&#039;&#039; () &amp;lt;br&amp;gt;True if the pin is buffered&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- *&#039;&#039;&#039;isConnected&#039;&#039;&#039;() &amp;lt;br&amp;gt;Returns true if the pin is connected&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;value&#039;&#039;&#039; (&#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes the value.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from Groovy code. However, only a limited subset of messages is supported:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;writeLine&#039;&#039;&#039; (&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;For compatibility with Java&#039;s PrintStream protocol.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;print&#039;&#039;&#039; (&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;For compatibility with Java&#039;s PrintStream protocol (expecco 2.8).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;println&#039;&#039;&#039; (&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;For compatibility with Java&#039;s PrintStream protocol (expecco 2.8).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;println&#039;&#039;&#039; ()&amp;lt;br&amp;gt;For compatibility with Java&#039;s PrintStream protocol (expecco 2.8).&lt;br /&gt;
&lt;br /&gt;
In addition, stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Node.js (Bridged) Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Node.js is an open source interpreter for JavaScript. For details on the language and libraries, visit [https://www.w3schools.com/nodejs &amp;quot;NodeJS Tutorial&amp;quot;] .&lt;br /&gt;
&amp;lt;br&amp;gt;You have to download and install &amp;quot;node&amp;quot; separately - the interpreter is not part of the expecco installation procedure (see [[Installing_additional_Frameworks/en | &amp;quot;Installing additional Frameworks&amp;quot;]]) and [https://nodejs.org/en/download/ https://nodejs.org/en/download] ).&lt;br /&gt;
&lt;br /&gt;
Node.js code execution in expecco is supported via 2 different mechanisms:&lt;br /&gt;
* Node.js Bridged Action Blocks - these look at the outside like regular action blocks with typed input and output pins, which are available inside the action&#039;s code via &amp;quot;&amp;lt;code&amp;gt;.value()&amp;lt;/code&amp;gt;&amp;quot; APIs. The bridge-partner in which the code is to be executed is started once and will remain an active process until terminated. Any state (data) created inside the bridge remains alive while the partner is running and the connection is alive.&lt;br /&gt;
* [[ElementaryBlock_Element/en#Node.js-Script_Blocks | Node.js-Script Action Blocks]] - these look like shell-script blocks, in that the standard input and output is used to interact with the script. For every individual script action, the script interpreter is started anew. No state is alive between and across actions (the script-interpreter is terminated after each action)&lt;br /&gt;
&lt;br /&gt;
The following describes the first kind of blocks (bridged). Node.js-Script blocks are described elsewhere, in the [[ElementaryBlock_Element/en#Node.js-Script_Blocks | Node.js-Script Blocks]] chapter.&lt;br /&gt;
&lt;br /&gt;
Code written as a Node.js elementary block is not executed directly by expecco. Instead, the code is forwarded to a node interpreter. This may be a local node process, whose sole purpose is to provide additional utility functions or which provides an interface to the actual system under test (SUT), or it may be on a remote system.&lt;br /&gt;
&lt;br /&gt;
=== NodeJS Datatype Limitations ===&lt;br /&gt;
Because expecco objects and Node objects live in different processes,&lt;br /&gt;
no direct object access is possible between the two partners. &lt;br /&gt;
When objects are passed via an input pin from expecco to Node, or via an output pin from Node to expecco, the object is either converted to JSON on the sender side and reconstructed on the receiver side, or it is passed by reference, in that the sender transmits a &amp;quot;handle&amp;quot; (which is some unique number) to the partner.&lt;br /&gt;
&lt;br /&gt;
Since the class system / object model is different, not all objects are exactly representable on the other side, and some information may be lost. If required, additional information must be explicitly passed (eg. by generating a string representation &#039;&#039;manually&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
==== Limited NodeJS Object Conversion ====&lt;br /&gt;
Some limited form of object conversion is automatically performed when passing expecco&#039;s Smalltalk objects to NodeJS, and back when returning values from NodeJS. This conversion especially affects values passed to/from pins of a NodeJS action.&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the conversion process:&lt;br /&gt;
{|  Border&lt;br /&gt;
! from Smalltalk&lt;br /&gt;
! to NodeJS and from NodeJS&lt;br /&gt;
! to Smalltalk&lt;br /&gt;
!&lt;br /&gt;
|-&lt;br /&gt;
| String&lt;br /&gt;
| String&lt;br /&gt;
| String&lt;br /&gt;
|-&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(node ONLY supports IEEE double numbers)&lt;br /&gt;
| Float&lt;br /&gt;
| Float&lt;br /&gt;
|-&lt;br /&gt;
| Float, Double&lt;br /&gt;
| Float&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Smalltalk Floats have double precision)&lt;br /&gt;
|-&lt;br /&gt;
| Fraction&lt;br /&gt;
| Float&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Smalltalk Floats have double precision)&lt;br /&gt;
|-&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
|-&lt;br /&gt;
| Array of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
|-&lt;br /&gt;
| -&lt;br /&gt;
| any&lt;br /&gt;
| any NodeJS object as Reference&amp;lt;br&amp;gt;via &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot;&amp;lt;br&amp;gt;fetch in Node via &amp;quot;&amp;lt;code&amp;gt;inpin.refValue()&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Filename&lt;br /&gt;
| String (i.e. pathname)&lt;br /&gt;
| String&lt;br /&gt;
|-&lt;br /&gt;
| arbitrary Smalltalk Object (!)&lt;br /&gt;
| Object with slots&lt;br /&gt;
| Dictionary with slots&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(-) does not work. In general, only objects which can be represented by JSON can be transmitted between expecco and the node action.&lt;br /&gt;
&lt;br /&gt;
==== No Smalltalk Classes, No Smalltalk Objects in NodeJS ====&lt;br /&gt;
Of course, no Smalltalk class can be used directly in NodeJS code.&lt;br /&gt;
And only a subset of Smalltalk objects (those which can be represented as JSON string) can be passed to/from NodeJS as described above.&lt;br /&gt;
However, all node.js code (packages/modules) are at your hands now!&lt;br /&gt;
&lt;br /&gt;
In general: if more complex objects need to be interchanged, this must be either done by converting them to an array (of objects), possibly an array of arrays.&lt;br /&gt;
Or, alternatively to some ASCII representation (XML or JSON, for a more lightweight approach) and convert this back and forth.&lt;br /&gt;
&lt;br /&gt;
It is also possible to pass Node-object-references from the Node interpreter to expecco, and pass it back to the Node interpreter later (usually in another action).&lt;br /&gt;
This is used to get connection, protocol or device handles from Node, and pass them to other (transmission or control) actions later.&lt;br /&gt;
&lt;br /&gt;
==== Limited Error Reporting ====&lt;br /&gt;
Notice, that arithmetic errors are usually not reported by Node. &lt;br /&gt;
Dividing by zero or taking the logarithm of a negative number will deliver a Nan (&amp;quot;Not a Number&amp;quot;) instead of raising an error. Thus you have to explicitly check the result from such computations in your code (this is different in expecco&#039;s builtin JavaScript actions, where an error is reported).&lt;br /&gt;
&lt;br /&gt;
=== Debugging NodeJS Actions ===&lt;br /&gt;
Some debugging facilities are provided to support development of Node code.&lt;br /&gt;
If your code contains an endless loop, you can interrupt the Node interpreter&lt;br /&gt;
(via the &amp;quot;&#039;&#039;Interrupt Execution&#039;&#039;&amp;quot; button at the top right)&lt;br /&gt;
and get a debugger window, showing the call stack and local variables.&lt;br /&gt;
&lt;br /&gt;
However, there are situations, when the Node interpreter gets completely locked up and ceases to react.&lt;br /&gt;
In this situation, you will have to shut down the Node interpreter via the &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Node JS&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Close Connections&#039;&#039;&amp;quot; menu function.&lt;br /&gt;
Of course, this also implies, that any state inside the Node interpreter is lost, and you&#039;ll have to rerun your test setup from the start.&lt;br /&gt;
&lt;br /&gt;
===== Debugger Functions =====&lt;br /&gt;
Currently, you cannot look &amp;quot;into&amp;quot; objects, and you cannot modify the local variables.&lt;br /&gt;
The debugger looks very similar to the Smalltalk/JavaScript debugger&lt;br /&gt;
and supports &#039;&#039;continue&#039;&#039;, &#039;&#039;line stepping&#039;&#039;, &#039;&#039;stepping into called functions&#039;&#039;, &#039;&#039;stepping out of called functions&#039;&#039;,&lt;br /&gt;
&#039;&#039;aborting an activity&#039;&#039; and &#039;&#039;terminating&#039;&#039; the whole node-interpreter.&lt;br /&gt;
&lt;br /&gt;
===== Limitations of the Debugger =====&lt;br /&gt;
One problem which is encountered with the current node version is that the breakpoint line numbers&lt;br /&gt;
are sometimes off-by-one; this means, that the line reported by the node-debugger is wrong and&lt;br /&gt;
therefore also shown wrong in the debugger. This is a problem of the particular node version,&lt;br /&gt;
and may or may not appear in your concrete installation (i.e. node interpreter version).&lt;br /&gt;
&lt;br /&gt;
Sorry, but we cannot currently provide a workaround for this problem, as we have not yet figured out,&lt;br /&gt;
what constellation of source-code/statement/situation leads to this problem. &lt;br /&gt;
(this problem was also reported by other node users in the internet forums).&lt;br /&gt;
&lt;br /&gt;
=== NodeJS Code API ===&lt;br /&gt;
&lt;br /&gt;
NodeJS code supports a &#039;&#039;&#039;subset&#039;&#039;&#039; of the above activity functions, which is intended provide an interface similar to the JavaScript and Smalltalk elementary code API. Of course, technically for every API function below, the code executing in the remote Node interpreter has to make a remote procedure call back to expecco. On the Node side, this is done very similar to the above described remote message mechanism, when messages are sent from expecco to a bridge.&lt;br /&gt;
Also notice, that due to the single threaded nature of Node programs, all functions which ask for a value from expecco (eg. &amp;quot;&amp;lt;code&amp;gt;environmentAt&amp;lt;/code&amp;gt;&amp;quot;) will take a callback argument, which is called when the return value arrives.&lt;br /&gt;
&lt;br /&gt;
Be remonded that the objects described below are proxy objects inside node, which will forward messages back to expecco when functions listed below are called on them. Due to the roundtrip times, these will be relatively slow (in the order of milliseconds).&lt;br /&gt;
&lt;br /&gt;
==== Variables seen by the Executed Node Function ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed function:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages in the expecco Transcript window (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stdout stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stderr stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Logger &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports &amp;lt;code&amp;gt;info()/warn()/error()/fatal()&amp;lt;/code&amp;gt;; these are forwarded to the Smalltalk Logger object (see Logger)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;__bridge__&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;the bridge object which handles the communication with expecco. The instance slot named &amp;quot;&amp;lt;code&amp;gt;asynchronous&amp;lt;/code&amp;gt;&amp;quot; is of special interest if the called function uses asynchronous callbacks (see below)&lt;br /&gt;
&lt;br /&gt;
==== Reporting (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...) &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution. &amp;lt;br&amp;gt;If the infoString argument contains &amp;quot;%i&amp;quot; placeholders (&amp;quot;%1&amp;quot;,&amp;quot;%2&amp;quot;,...), these will be expanded by the remaining arguments.&amp;lt;br&amp;gt;(eg. &amp;lt;code&amp;gt;logFail(&amp;quot;foo:%1 bar:%2&amp;quot;, 123, 234.0)&amp;lt;/code&amp;gt; will generate the failure string &amp;quot;foo:123 bar:234.0&amp;quot;). &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...) &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...) &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...)&amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;success&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...)&amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;activitySuccess()&amp;quot;). Please use &amp;quot;activitySuccess&amp;quot; (&amp;quot;success&amp;quot; is not supported in all bridges due to name conflictswith other libraries. For readability, it is better to use the same name in all bridges: &amp;quot;activitySuccess&amp;quot;, which is supported on all bridges)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...)&amp;lt;br&amp;gt;Finishes the current testCase with success.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testPass&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...)&amp;lt;br&amp;gt;Same as pass(); for compatibility with bridged languages where &amp;quot;pass&amp;quot; is a reserved keyword (i.e. python).&lt;br /&gt;
&lt;br /&gt;
==== Logging (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logFail&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...) &amp;lt;br&amp;gt;Adds a fail message to the activity log.&amp;lt;br&amp;gt;Execution continues, but the test will be marked as failed.&amp;lt;br&amp;gt;If the messageString argument contains &amp;quot;%i&amp;quot; placeholders (&amp;quot;%1&amp;quot;,&amp;quot;%2&amp;quot;,...), these will be expanded by the remaining arguments.&amp;lt;br&amp;gt;(eg. &amp;lt;code&amp;gt;logFail(&amp;quot;foo:%1 bar:%2&amp;quot;, 123, 234.0)&amp;lt;/code&amp;gt; will generate the failure string &amp;quot;foo:123 bar:234.0&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...) &amp;lt;br&amp;gt;Adds a error message to the activity log.&amp;lt;br&amp;gt;Execution continues, but the test will be marked as erroneous.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...) &amp;lt;br&amp;gt;Adds a warning to the activity log.&amp;lt;br&amp;gt;Execution continues.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...) &amp;lt;br&amp;gt;Adds an info message to the activity log.&amp;lt;br&amp;gt;Execution continues&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log -Settings&#039;&#039;&amp;quot; (by default it is enabled).&amp;lt;br&amp;gt;Notice that the code in the bridge is suspended until the box is confirmed.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...)&amp;lt;br&amp;gt;Same as &#039;&#039;alert()&#039;&#039; (for Smalltalk protocol compatibility).&lt;br /&gt;
&lt;br /&gt;
==== Reflection, Information, Queries and Accessing (NodeJS) ====&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text plan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlanItem&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;nameOfAction&#039;&#039;&#039; ()&amp;lt;br&amp;gt;The name of the activity&lt;br /&gt;
&lt;br /&gt;
==== Interaction with Expecco (NodeJS) ====&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;call&#039;&#039;&#039;(&amp;amp;lt;actionName&amp;amp;gt;, &amp;amp;lt;arg1&amp;amp;gt;, &amp;amp;lt;arg2&amp;amp;gt;, ... &amp;amp;lt;argN&amp;amp;gt;, function(rslt...) {...});&amp;lt;br&amp;gt;Executes any other expecco action (inside expecco - not inside the node interpreter), and finally calls the callBack function, when the action has finished.&amp;lt;br&amp;gt;Notice that this is an asynchronous callback; you should not perform any further actions after the call, but instead continue inside the callback (and signal final completion via &amp;quot;&amp;lt;code&amp;gt;activitySuccess() / error()&amp;lt;/code&amp;gt;&amp;quot; call from there).&amp;lt;br&amp;gt;The callback may expect multiple rslt-arguments, to get the output values of more than one pin. However, it is currently not possible to get the values of pins which are written multiple times (i.e. an error will be reported, if that is the case)&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
==== Event Sending (NodeJS) ====&lt;br /&gt;
* &#039;&#039;&#039;pushEvent&#039;&#039;&#039; (&#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event onto the global event handler&#039;s event queue. The payload is packed into an Event object with eventType &amp;quot;#default. Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pushEventType_data&#039;&#039;&#039; (&#039;&#039;eventTypeSymbolOrNil&#039;&#039;, &#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event of type (or #default) onto the global event handler&#039;s event queue. Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
==== Environment Access (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&#039;&#039;varName&#039;&#039;, function(err, rslt) {...});&amp;lt;br&amp;gt;Fetches a value from the expecco environment which is in scope of the current activity, and finally calls the callBack function, when the value has been retrieved (passing the retrieved value as argument).&amp;lt;br&amp;gt;Notice that this is an asynchronous callback; you should not perform any further actions after the call, but instead continue inside the callback (and signal final completion via &amp;quot;&amp;lt;code&amp;gt;activitySuccess() / error()&amp;lt;/code&amp;gt;&amp;quot; call from there).&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from node actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAtPut&#039;&#039;&#039;(&#039;&#039;varName&#039;&#039;, &#039;&#039;newValue&#039;&#039;, function(err) {...});&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity, and finally calls the callBack function, when the value has been stored.&amp;lt;br&amp;gt;Notice that this is an asynchronous callback; you should not perform any further actions after the call, but instead continue inside the callback (and signal final completion via &amp;quot;&amp;lt;code&amp;gt;activitySuccess() / error()&amp;lt;/code&amp;gt;&amp;quot; call from there).&amp;lt;br&amp;gt;The &#039;&#039;varName&#039;&#039; argument must be a string and &#039;&#039;newValue&#039;&#039; a simple object (number, boolean or string) from node actions.&lt;br /&gt;
&lt;br /&gt;
==== Special Functions (NodeJS) ====&lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039; (&amp;amp;lt;anyNodeObject&amp;amp;gt; [, &amp;lt;optionalName&amp;gt; ]) &amp;lt;br&amp;gt;Generates a reference to a NodeJS object, which can be passed to expecco as an output pin value. Such reference objects can be passed back to NodeJS later and are dereferenced there back to the original object. This is used to pass NodeJS handles (i.e. server/client handles) to expecco and later back to NodeJS. Read below about reference passing vs. value passing.&amp;lt;br&amp;gt;Notice that the nodeObject will be registered (i.e. remembered) inside the node interpreter, in order to be found later, when the reference is passed as input by another node action. When the reference is no longer needed, it should be deregistered by calling the &amp;quot;&amp;lt;code&amp;gt;releaseRef&amp;lt;/code&amp;gt; function described below.&amp;lt;br&amp;gt;Also notice, that expecco will do this automatically, when the reference object is finalized.&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;releaseRef&#039;&#039;&#039; (&amp;amp;lt;nodeObjectReference&amp;amp;gt;) &amp;lt;br&amp;gt;removes the reference from the registery inside the node interpreter.&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;wait&#039;&#039;&#039; () &amp;lt;br&amp;gt;Tells expecco to wait until one of the &amp;quot;&amp;lt;code&amp;gt;activitySuccess/error/fail/inconclusive&amp;lt;/code&amp;gt;&amp;quot; functions is called.&amp;lt;br&amp;gt;Use this if the action&#039;s execution is not finished when the execute() function returns, but instead will explicitly notify the finish from within a callback. This is also to be used if a pin value has to be written later by a callback function.&amp;lt;br&amp;gt;See example and description of callbacks/async functions below.&lt;br /&gt;
*&#039;&#039;&#039;waitForPin&#039;&#039;&#039; (&#039;&#039;pinName&#039;&#039;)&amp;lt;br&amp;gt;Tells expecco to wait until the given output pin receives a value. This is needed for async/await (promise resolved) pin values.&amp;lt;br&amp;gt;See example and description of callbacks/async functions below.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;mayStillDoExpeccoCalls&#039;&#039;&#039; (&#039;&#039;boolean&#039;&#039;) &amp;lt;br&amp;gt;Make sure that the functions described here will still be callable (by Java callback functions from other threads) even after the step has finished execution. In other words, do NOT release the observer object which is responsible for the transfer of information between the two systems. Be aware that this object remains and will never be released, until the bridge connection is closed. I.e. there is a potential for a memory leak inside the Java VM here.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Pin Functions (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
Attention:&lt;br /&gt;
&amp;lt;br&amp;gt;Javascript uses many more reserved keywords for syntax than Smalltalk. These keywords cannot be used as pin names, and you will get a syntax error (&amp;quot;&amp;lt;foo&amp;gt; token not expected&amp;quot;) if you try. Be careful to not name your pins as any of: &amp;quot;&amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&amp;quot;, etc.&amp;lt;br&amp;gt;As a proven best practice, add a &amp;quot;&#039;&#039;Pin&#039;&#039;&amp;quot; suffix to your pin names (i.e. name it &amp;quot;&#039;&#039;inPin&#039;&#039;&amp;quot;, instead of &amp;quot;&#039;&#039;in&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
===== Input Pins (NodeJS) =====&lt;br /&gt;
&lt;br /&gt;
Currently, NodeJS blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin is connected&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value at the pin (the datum). Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;refValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the object referenced by the value at the pin. The pin must have received a reference. Raises an error if the pin did not receive any value. Use this to pass back the original reference object to expecco. The input pin must have received a reference to a Node object as generated previously by &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot;. Read below about reference passing vs. value passing. &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the alternativeValue if the pin did not receive any value.&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfPresent&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, null otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
===== Output Pins (NodeJS) =====&lt;br /&gt;
&lt;br /&gt;
Currently, NodeJS blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isBuffered&#039;&#039;&#039; () &amp;lt;br&amp;gt;True if the pin is buffered&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039;() &amp;lt;br&amp;gt;Returns true if the pin is connected (this can be used to prevent writing output values and thus speed up the execution, especially if big arrays of data values are generated)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; (&#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes the value.&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from Node code. However, only a limited subset of messages is supported:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;...)&amp;lt;br&amp;gt;Like &amp;quot;&amp;lt;code&amp;gt;show()&amp;lt;/code&amp;gt;, but &amp;quot;%i&amp;quot; sequences in the format argument are expanded by the corresponding arg strings.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;fmt&#039;, &#039;&#039;arg&#039;&#039;...)&amp;lt;br&amp;gt;Like &amp;quot;&amp;lt;code&amp;gt;showCR()&amp;lt;/code&amp;gt;, but &amp;quot;%i&amp;quot; sequences in the format argument are expanded by the corresponding arg strings.&lt;br /&gt;
&lt;br /&gt;
In addition, stdout (console.log) and stderr (console.error) are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
=== Reference passing vs. value passing of Node objects to expecco ===&lt;br /&gt;
&lt;br /&gt;
When values are passed via an output pin from Node to expecco, two mechanisms are possible:&lt;br /&gt;
* pass by value&amp;lt;br&amp;gt;The object&#039;s JSON string is generated and passed to expecco. There, the JSON encoding is decoded and a corresponding expecco object is constructed. Conceptional, the expecco object is a copy of the original object.&lt;br /&gt;
&lt;br /&gt;
* pass by reference&amp;lt;br&amp;gt;The object is remembered inside Node, and a reference is passed to expecco. Whenever this reference object is later sent to Node again (via an input pin), the original Node object is retrieved and passed to the JavaScript code. This mechanism preserves the object&#039;s identity on the Node side and must be used for object handles (such as protocol handles).&lt;br /&gt;
&lt;br /&gt;
The default mechanism is &amp;quot;&#039;&#039;pass by value&#039;&#039;&amp;quot;. To pass a reference, use &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot; and pass the generated reference to an output pin.&lt;br /&gt;
==== Example (NodeJS) ====&lt;br /&gt;
The following code snippet sends an object&#039;s reference to an output pin:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... generate a handle object ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    outputPin.value( makeRef (someHandle , &amp;quot;aNodeHandle&amp;quot; ) );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the returned handle can later be sent via an input pin to another Node action, and used transparently there:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     var handle = inputPin.value();&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with handle ...&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
occasionally, it is required that a reference which was received via an input pin must later be sent to an output pin again, preserving the original reference. This is to prevent additional memory allocations which would result from calling &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; again (you would get multiple references to the same object).&lt;br /&gt;
For this, use &amp;quot;&amp;lt;code&amp;gt;inputPin.refValue()&amp;lt;/code&amp;gt;&amp;quot; and send this to an output pin without a &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     var handle = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with handle ...&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// send the original reference to the output&amp;lt;/span&amp;gt;&lt;br /&gt;
     outputPin.value( inputPin.refValue() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Finally, you want to release the reference inside the node interpreter, to prevent memory leaks.&lt;br /&gt;
Usually, this should be called, when a handle becomes invalid (e.g. when a connection handle is closed).&lt;br /&gt;
&lt;br /&gt;
For this, call the &amp;quot;&amp;lt;code&amp;gt;releaseRef&amp;lt;/code&amp;gt;&amp;quot; function (on the node side), passing the reference instead of the referenced object.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, a close-connection action block might look like:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     var reference = inputPin.refValue();&lt;br /&gt;
     var referredObject = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with referredObject ...&amp;lt;/span&amp;gt;&lt;br /&gt;
     closeConnection( referredObject );&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// release to prevent memory leaks&amp;lt;/span&amp;gt;&lt;br /&gt;
     releaseRef(referredObject);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Asynchronous and Callback Functions  ===&lt;br /&gt;
A common pattern in node is &amp;quot;&#039;&#039;continuation passing style&#039;&#039;&amp;quot; control flow. That means, that many functions expect a function as callback argument, which is called later whenever the requested operation has finished. This is used especially with I/O and protocol related operations (such as socket connect, http requests, client connect setup etc.).&lt;br /&gt;
A similar situation arises with async functions, which somehow get a promise as value, and the promise is resolved via an await.&lt;br /&gt;
&lt;br /&gt;
If your &amp;quot;&amp;lt;code&amp;gt;execute&amp;lt;/code&amp;gt;&amp;quot; function calls any of those or is an async function which awaits on a promise, it has to tell expecco that the node-action is effectively still active when the execute function returns and that expecco should wait for an explicit finished-notification. This is done by either calling either &amp;quot;&amp;lt;code&amp;gt;wait()&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;waitForPin()&amp;lt;/code&amp;gt;&amp;quot; somewhere within the execute function. &lt;br /&gt;
&lt;br /&gt;
Then expecco will continue to wait for the action to be finished until the node code calls one of the &amp;quot;&amp;lt;code&amp;gt;fail()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;error()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;pass()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;inconclusive()&amp;lt;/code&amp;gt;&amp;quot; functions (listed above) or - in case of a previous &amp;lt;code&amp;gt;waitForPin()&amp;lt;/code&amp;gt;, until that pin receives a value.&lt;br /&gt;
&lt;br /&gt;
Example 1:&amp;lt;br&amp;gt;the following code fragment represents a typical callback situation: the &amp;quot;myProtocolConnect()&amp;quot; call gets a callback, which will be called later (asynchronously), when a connection is established. However, &amp;quot;myProtocolConnect()&amp;quot; will return immediately. Without the &amp;quot;wait()&amp;quot; at the end, expecco would assume that the action has finished and would proceed with other actions (possibly without any output being written to the output pin (actually, it would later detect a value being written by an already finished action, and write a warning message to the console and the log).&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... call a function which does a callback ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    myProtocolConnect( ... , function(err) {&lt;br /&gt;
        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... callback possibly called much later ...&amp;lt;/span&amp;gt;&lt;br /&gt;
        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// tell expecco that we&#039;re done&amp;lt;/span&amp;gt;&lt;br /&gt;
        if (err) {&lt;br /&gt;
            error(&amp;quot;some error happened: &amp;quot;+err.toString());&lt;br /&gt;
        } else {&lt;br /&gt;
            outputPin.value(someConnectionHandle); &lt;br /&gt;
            success();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// tell expecco to continue waiting&amp;lt;/span&amp;gt;&lt;br /&gt;
    wait();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Notice that callbacks can be either written as functions (with a statement body):&lt;br /&gt;
 function(err) { statement; ... statement; }&lt;br /&gt;
or as a lambda expression, where the body is an expression:&lt;br /&gt;
 (err) =&amp;gt; expression&lt;br /&gt;
&lt;br /&gt;
Example 2:&amp;lt;br&amp;gt;the following code fragment is typical for async/await functions. Similar to the above, but covered by syntactic sugar which makes this less obvious, the execute function will return early, but execute code asynchronously due to the awaited promise:&lt;br /&gt;
&lt;br /&gt;
 async function execute() {&lt;br /&gt;
    let appiumMacDriver = require(&amp;quot;appium-mac-driver&amp;quot;);  &lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// due to the async operations,&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// this execute function will effectively finish when&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// the await receives the value,&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// and it is written to the pin.&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// tell expecco that the function is finished when that pin&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// receives a value&amp;lt;/span&amp;gt;&lt;br /&gt;
    waitForPin(sessionOut);&lt;br /&gt;
 &lt;br /&gt;
    let driver = new appiumMacDriver.MacDriver();&lt;br /&gt;
    let session = driver.createSession(defaultCaps);&lt;br /&gt;
    let s = await session;&lt;br /&gt;
    sessionOut.value(s);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Example 3:&amp;lt;br&amp;gt;The following example demonstrates what happens if the &amp;quot;wait()&amp;quot; call is missing. The code below installs a callback which writes to an output pin 1 second AFTER the finished action:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     output.value(&amp;quot;Value1&amp;quot;);&lt;br /&gt;
     setTimeout(function(err) {&lt;br /&gt;
         output.value(&amp;quot;Value2&amp;quot;);&lt;br /&gt;
     }, 1000);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
the above code will lead to an error.&lt;br /&gt;
&lt;br /&gt;
The correct version is:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     output.value(&amp;quot;Value1&amp;quot;);&lt;br /&gt;
     setTimeout(function(err) {&lt;br /&gt;
         output.value(&amp;quot;Value2&amp;quot;);&lt;br /&gt;
         success();&lt;br /&gt;
     }, 1000);&lt;br /&gt;
     wait();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Up to version 23.2, this situation was not always detected and could have lead to an output value being written to a same-named output pin of a followup action (iff another bridged action was triggered which was of the same type, that second action&#039;s output was sometimes written, depending on timing constraints).&amp;lt;br&amp;gt;With version 24.1, this is detected and an error message is sent to the Transcript (it cannot be reported as an error in the activity log, because the first action which is responsible has already finished, whereas the second action (which is innocent) cannot be blamed for that).&lt;br /&gt;
&lt;br /&gt;
=== Calling other Expecco Actions  ===&lt;br /&gt;
Any expecco action (i.e. elementary or compound) can be called from Node code.&lt;br /&gt;
However, as node uses a callback mechanism, the code looks a bit different from other languages, in that an additional callback argument is to be passed. You can pass either the name or the UUID of the activity which is to be called.&lt;br /&gt;
Arguments are passed to the called action&#039;s input pin (top to bottom).&lt;br /&gt;
&lt;br /&gt;
For now, there is a limitation, in that only a single value (per pin) can be passed to the callback (i.e. you cannot get the values of pins which are written multiple times).&lt;br /&gt;
&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&lt;br /&gt;
  function execute() {&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... call an expecco activity ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    call(&amp;quot;myAction&amp;quot;, 100, 200 , &lt;br /&gt;
        function(result) {&lt;br /&gt;
            &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... callback gets the first value from myAction&#039;s first output pin ...&amp;lt;/span&amp;gt;&lt;br /&gt;
            success();&lt;br /&gt;
        });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Notice, that in order to get a sequence of calls, the code needs nested functions, as in:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
    &lt;br /&gt;
    call(&amp;quot;myAction1&amp;quot;, 1000, 2000, &lt;br /&gt;
        function(rslt1) {&lt;br /&gt;
            Transcript.showCR(&amp;quot;after first call: &amp;quot;+rslt1);&lt;br /&gt;
            call(&amp;quot;myAction2&amp;quot;, 10000, 20000, &lt;br /&gt;
                function(err, rslt2) {&lt;br /&gt;
                    Transcript.showCR(&amp;quot;after second call: &amp;quot;+rslt2);&lt;br /&gt;
                    success();&lt;br /&gt;
                });&lt;br /&gt;
            &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
        });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If the called action has multiple output pins, provide a callback function which expects more than one rslt argument,&lt;br /&gt;
as in:&lt;br /&gt;
 function execute() {&lt;br /&gt;
    &lt;br /&gt;
    call(&amp;quot;actionWithTwoOutputPins&amp;quot;, 1000, 2000, &lt;br /&gt;
        function(valueAtPin1, valueAtPin2) {&lt;br /&gt;
            Transcript.showCR(&amp;quot;received two values: &amp;quot;+valueAtPin1+&amp;quot; and: &amp;quot;+valueAtPin2);&lt;br /&gt;
            success();&lt;br /&gt;
        });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Reading expecco Environment Variables  ===&lt;br /&gt;
Expecco variables can be fetched via the &amp;quot;&amp;lt;code&amp;gt;environmentAt&amp;lt;/code&amp;gt;&amp;quot; function. Notice, that this takes a second callback function as argument, which is called when the value is (later) received. The execution of the action proceeds with this continuation, and &amp;quot;&amp;lt;code&amp;gt;environmentAt&amp;lt;/code&amp;gt;&amp;quot; does not return. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;For example:&lt;br /&gt;
 function execute() {&lt;br /&gt;
    environmentAt(&amp;quot;variable1&amp;quot;, function(err, varValue) {&lt;br /&gt;
            Transcript.showCR(&amp;quot;the variable value is: &amp;quot;+varValue);&lt;br /&gt;
            success();&lt;br /&gt;
    });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
=== Executing Node Actions in Multiple Node Interpreters ===&lt;br /&gt;
In order to test the interaction between multiple node programs, &lt;br /&gt;
or to generate load for performance tests,&lt;br /&gt;
it may be required to start multiple node interpreters,&lt;br /&gt;
and run action code in them.&lt;br /&gt;
&lt;br /&gt;
This chapter describes how to start a node interpreter and how to interact with them.&lt;br /&gt;
&lt;br /&gt;
==== Starting another Node Interpreter on the Local Machine ====&lt;br /&gt;
&lt;br /&gt;
Every Node bridge uses the given port for bridge communication plus the next port for debugging.&lt;br /&gt;
Every bridge running on the same host must use different ports.&lt;br /&gt;
The default bridge uses port 8777 (and 8778 for debugging).&lt;br /&gt;
Thus, additional bridges should be given ports incremented in steps of 2,&lt;br /&gt;
and useful ports are 8779, 8781, 8783 etc. for additional node bridges.&lt;br /&gt;
&lt;br /&gt;
===== Programmatic Start =====&lt;br /&gt;
&lt;br /&gt;
 nodeBridge := Expecco &lt;br /&gt;
                    newNodeJSBridgeConnectionForHost:hostName port:portNr &lt;br /&gt;
                    in:aDirectoryOrNil.&lt;br /&gt;
&lt;br /&gt;
===== Using an Action from the Standard Library =====&lt;br /&gt;
use the &amp;quot;&#039;&#039;Start new Local Node Bridge&#039;&#039;&amp;quot; action from the library.&lt;br /&gt;
&lt;br /&gt;
===== Executing an Action inside another Node Interpreter =====&lt;br /&gt;
&lt;br /&gt;
Either add a &amp;quot;&#039;&#039;nodejs&#039;&#039;&amp;quot; input pin to the action (passing the other node-bridge&#039;s handle) or&lt;br /&gt;
set the &amp;quot;&amp;lt;code&amp;gt;NODEJS&amp;lt;/code&amp;gt;&amp;quot; environment variable before the action.&lt;br /&gt;
An example is found in the &amp;quot;&amp;lt;code&amp;gt;d62_Event_Queue_Demos.ets&amp;lt;/code&amp;gt;&amp;quot; suite:&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:Event_Queue_Demo.png|600px|]]&lt;br /&gt;
&lt;br /&gt;
=== Node Packages ===&lt;br /&gt;
&lt;br /&gt;
===Example: Installing Additional Node Packages ===&lt;br /&gt;
Use the Node package manager &amp;quot;&amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt;&amp;quot; to install packages.&lt;br /&gt;
&amp;lt;br&amp;gt;The &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Node Bridge&#039;&#039;&amp;quot; menu also contains an entry to install npm packages.&lt;br /&gt;
&amp;lt;br&amp;gt;Find packages in [https://www.npmjs.com https://www.npmjs.com].&lt;br /&gt;
&lt;br /&gt;
For example, assume you need the current city weather in a suite, navigate to &amp;quot;https://www.npmjs.com&amp;quot;, search for &amp;quot;weather&amp;quot;, find the &amp;quot;&amp;lt;code&amp;gt;city-weather&amp;lt;/code&amp;gt;&amp;quot; package and click on it. You will arrive on a page giving installation instructions and sample code at the end.&lt;br /&gt;
Scroll down to the example code and keep that page open (we can use the code later).&lt;br /&gt;
&lt;br /&gt;
Open a cmd/shell window and execute on the command line:&lt;br /&gt;
 npm install city-weather&lt;br /&gt;
&lt;br /&gt;
=== Examples: Using a Node Package in Expecco ===&lt;br /&gt;
==== Example1: Access to the City Weather Service ====&lt;br /&gt;
For a first test, we will take the original code from the example.&lt;br /&gt;
Create a new node action, and enter the code:&lt;br /&gt;
 var weather = require(&amp;quot;city-weather&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 function execute() {&lt;br /&gt;
     weather.getActualTemp(&#039;Rome&#039;, function(temp){&lt;br /&gt;
         console.log(&amp;quot;Actual temperature: &amp;quot; + temp);&lt;br /&gt;
     });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
(you can copy-paste the sample code from the webpage)&lt;br /&gt;
&lt;br /&gt;
Open the expecco console (aka &amp;quot;Transcript&amp;quot; via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Transcript&#039;&#039;&amp;quot; menu item) and run the test.&lt;br /&gt;
A temperature should be displayed on the Transcript.&lt;br /&gt;
&lt;br /&gt;
Now add an input pin named &amp;quot;&#039;&#039;city&#039;&#039;&amp;quot;, and change the code to:&lt;br /&gt;
 ...&lt;br /&gt;
 weather.getActualTemp(city.value(), function(temp){&lt;br /&gt;
 ...&lt;br /&gt;
and try the code in the &amp;quot;&#039;&#039;Test/Demo&#039;&#039;&amp;quot; page with a few different cities at the input pin.&lt;br /&gt;
&lt;br /&gt;
Then, add an output pin named &amp;quot;&#039;&#039;temperature&#039;&#039;&amp;quot;, and change the code again to:&lt;br /&gt;
 var weather = require(&amp;quot;city-weather&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 function execute() {&lt;br /&gt;
     weather.getActualTemp(city.value(), function(temp){&lt;br /&gt;
         console.log(&amp;quot;Actual temperature: &amp;quot; + temp);&lt;br /&gt;
         temperature.value( temp );&lt;br /&gt;
     });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
if you now execute this action, you will notice, that the output pin does NOT get the value.&lt;br /&gt;
The reason is, that the pin is written by a node-callback function, which is called at a time after the action&#039;s &amp;quot;&amp;lt;code&amp;gt;execute&amp;lt;/code&amp;gt;&amp;quot; function has already finished.&lt;br /&gt;
Thus, we have to tell expecco, that it should wait until the callback is actually called.&lt;br /&gt;
For this, you should add a call to the &amp;quot;&amp;lt;code&amp;gt;wait()&amp;lt;/code&amp;gt;&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
This tells expecco, that the execute-function is not complete, and will wait for one of the &amp;quot;&amp;lt;code&amp;gt;success/fail/error&amp;lt;/code&amp;gt;&amp;quot; functions to be called.&lt;br /&gt;
So we also have to add a call to &amp;quot;&amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;&amp;quot; inside the callback (otherwise, expecco would wait forever).&lt;br /&gt;
&lt;br /&gt;
Thus, we change the code to:&lt;br /&gt;
 var weather = require(&amp;quot;city-weather&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 function execute() {&lt;br /&gt;
     weather.getActualTemp(city.value(), function(temp){&lt;br /&gt;
         console.log(&amp;quot;Actual temperature: &amp;quot; + temp);&lt;br /&gt;
         temperature.value( temp );&lt;br /&gt;
         success();&lt;br /&gt;
     });&lt;br /&gt;
    wait();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As a final step, you should remove or comment the call to &amp;quot;&amp;lt;code&amp;gt;console.log()&amp;lt;/code&amp;gt;&amp;quot; and add some error reporting, in case a city was not found:&lt;br /&gt;
 var weather = require(&amp;quot;city-weather&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 function execute() {&lt;br /&gt;
    weather.getActualTemp(city.value(), function(temp){&lt;br /&gt;
        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// console.log(&amp;quot;Actual temperature: &amp;quot; + temp);&amp;lt;/span&amp;gt;        &lt;br /&gt;
        if (temp == &amp;quot;City was not found&amp;quot;) {&lt;br /&gt;
            error(temp+&amp;quot;: &amp;quot;+city.value());&lt;br /&gt;
        }&lt;br /&gt;
        temperature.value( temp );&lt;br /&gt;
        success();&lt;br /&gt;
    });&lt;br /&gt;
    wait();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== Example2: Access OpenStreetMap Services ====&lt;br /&gt;
This is described in a [[Node_Examples/en | separate document]].&lt;br /&gt;
&lt;br /&gt;
== Bridged Python Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Code written as a Python elementary block is not executed directly by expecco. Instead, the code is forwarded to a python interpreter. This may be a local python process, whose sole purpose is to provide additional utility functions or which provides an interface to the actual system under test (SUT), or it may be on a remote system.&lt;br /&gt;
&lt;br /&gt;
==== Python Versions ====&lt;br /&gt;
Python is available in 2 major dialects (2.x vs. 3.x) and different implementations (cPython, Jython, IronPython):&lt;br /&gt;
* use &#039;&#039;&#039;jython&#039;&#039;&#039;, if you have to interface/embed java classes or jars; &lt;br /&gt;
* use &#039;&#039;&#039;ironPython&#039;&#039;&#039;, if you have to interface with .NET assemblies; &lt;br /&gt;
* use &#039;&#039;&#039;python3&#039;&#039;&#039; to interface to modern frameworks such as Tesseract (optical character recognition), computer vision, Tensorflow (machine learning) etc.&lt;br /&gt;
* use &#039;&#039;&#039;python2&#039;&#039;&#039; for some older frameworks, which have not yet been ported to the newer python3 (notice, that support for python2 is going to cease soon)&lt;br /&gt;
 &lt;br /&gt;
Of course, if you need to interface to a Python module which is specifically written for a version, that specific version is obligatory.&lt;br /&gt;
&lt;br /&gt;
You have to download and install Python, Python3, Jython and/or IronPython separately; these interpreters are not part of the expecco installation procedure.&lt;br /&gt;
&amp;lt;br&amp;gt;See ([[Installing_additional_Frameworks/en | &amp;quot;Installing Additional Frameworks&amp;quot;]]) and download Python from [https://www.python.org/downloads https://www.python.org/downloads], &lt;br /&gt;
[https://jython.org/downloads.html http://jython.org/downloads.html] for Jython, and [ https://ironpython.net/download/] for IronPython. &lt;br /&gt;
&lt;br /&gt;
Additional frameworks may be needed as prerequisite (i.e. Java for Jython, Mono for IronPython on non-Windows machines).&lt;br /&gt;
&lt;br /&gt;
==== Bridged vs. Scripted Actions====&lt;br /&gt;
Similar to Node, Python code execution is supported via 2 different mechanisms:&lt;br /&gt;
* &#039;&#039;&#039;Bridged Python&#039;&#039;&#039; action blocks - these look at the outside like regular action blocks with typed input and output pins, which are available inside the action&#039;s code via &amp;quot;&amp;lt;code&amp;gt;.value()&amp;lt;/code&amp;gt;&amp;quot; APIs. Objects can be interchanged between expecco and the python process either by value or by reference. The bridge-partner in which the code is to be executed is started once and will remain an active process until terminated. Any state (data) created inside the bridge remains alive while the partner is running and the connection is alive.&lt;br /&gt;
* &#039;&#039;&#039;Python-Script&#039;&#039;&#039; action blocks - these look like shell-script blocks, in that the standard input and output is used to interact with the script. For every individual script action, the interpreter  (i.e. Python) is started anew. No state is alive between and across actions (the python-interpreter is terminated after each action), and no objects can be exchanged (except for very simple objects by means of reading encoded objects via stdin/stdout/stderr).&lt;br /&gt;
&lt;br /&gt;
The following describes the first kind of blocks (bridged). Script blocks are described elsewhere, in the [[ElementaryBlock_Element/en#Python_Script_Blocks | Python-Script Blocks]] chapter.&lt;br /&gt;
&lt;br /&gt;
=== Debugging Python Actions ===&lt;br /&gt;
Debug support for Python actions is still being developped and more features are added with newer versions. However, there are probably better IDEs available and it might be a good idea to develop and debug Python code in your preferred IDE, and only add interface code to already debugged modules as expecco actions (this is certainly a matter of your personal preferences; in the past, interfaces to many modules have been implemented using only expecco&#039;s debug facilities). &lt;br /&gt;
&lt;br /&gt;
In order to support debugging of Python actions, you have to install either the &amp;quot;&#039;&#039;debugpy&#039;&#039;&amp;quot; or the &amp;quot;&#039;&#039;ptvsd&#039;&#039;&amp;quot; package (*) with:&lt;br /&gt;
 pip install debugpy&lt;br /&gt;
or:&lt;br /&gt;
 pip3 install debugpy&lt;br /&gt;
or:&lt;br /&gt;
 python3 -m pip install debugpy&lt;br /&gt;
&lt;br /&gt;
*) ptvsd is no longer maintained and has been replaced by the debugpy package. Ptvsd might be obsolete by the time of reading this.&lt;br /&gt;
&lt;br /&gt;
For more information on the ptvsd package, see [https://pypi.org/project/ptvsd https://pypi.org/project/ptvsd] and [https://github.com/Microsoft/ptvsd https://github.com/Microsoft/ptvsd].&lt;br /&gt;
&amp;lt;br&amp;gt;For debugpy, refer to [https://pypi.org/project/debugpy https://pypi.org/project/debugpy].&lt;br /&gt;
 &lt;br /&gt;
Notice that the debug features are currently not supported by python2 or jython.&lt;br /&gt;
&lt;br /&gt;
=== Python Datatype Limitations ===&lt;br /&gt;
&lt;br /&gt;
==== Limited Python Object Conversion ====&lt;br /&gt;
Some limited form of object conversion is automatically performed when passing expecco objects to Python, and back when returning values from Python. This conversion especially affects values passed to/from pins of a Python action.&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the conversion process:&lt;br /&gt;
{|  Border&lt;br /&gt;
! from Expecco (Smalltalk)&lt;br /&gt;
! to Python and from Python&lt;br /&gt;
! to Expecco&lt;br /&gt;
!&lt;br /&gt;
|-&lt;br /&gt;
| String&lt;br /&gt;
| String&lt;br /&gt;
| String&lt;br /&gt;
|-&lt;br /&gt;
| Float&amp;lt;br&amp;gt;&lt;br /&gt;
| Float&lt;br /&gt;
| Float&lt;br /&gt;
|-&lt;br /&gt;
| Float, Double&lt;br /&gt;
| Float&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Smalltalk Floats have double precision)&lt;br /&gt;
|-&lt;br /&gt;
| Fraction&lt;br /&gt;
| Float&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Smalltalk Floats have double precision)&lt;br /&gt;
|-&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
|-&lt;br /&gt;
| Array of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
|-&lt;br /&gt;
| ByteArray&lt;br /&gt;
| Array&lt;br /&gt;
| Array&lt;br /&gt;
|-&lt;br /&gt;
| -&lt;br /&gt;
| any&lt;br /&gt;
| any Python object as Reference&amp;lt;br&amp;gt;via &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Python object reference&amp;lt;br&amp;gt;as previously generated&amp;lt;br&amp;gt;by &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot;&amp;lt;br&amp;gt;fetch the reference in Python via &amp;quot;&amp;lt;code&amp;gt;inpin.refValue()&amp;lt;/code&amp;gt;&amp;quot;&amp;lt;br&amp;gt;or the value via &amp;quot;&amp;lt;code&amp;gt;inpin.value()&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
| fetch the reference in Python via &amp;quot;&amp;lt;code&amp;gt;inpin.refValue()&amp;lt;/code&amp;gt;&amp;quot;&amp;lt;br&amp;gt;or the value via &amp;quot;&amp;lt;code&amp;gt;inpin.value()&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
| send value or reference with &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Filename&lt;br /&gt;
| String (i.e. pathname)&lt;br /&gt;
| String&lt;br /&gt;
|-&lt;br /&gt;
| arbitrary Smalltalk Object (!)&lt;br /&gt;
| Object with slots&lt;br /&gt;
| Dictionary with slots&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(-) does not work. In general, only objects which can be represented by JSON can be transmitted between expecco and the python action.&lt;br /&gt;
&lt;br /&gt;
==== No Smalltalk Classes, No Smalltalk Objects in Python ====&lt;br /&gt;
Of course, no Smalltalk class can be used directly in Python code.&lt;br /&gt;
And only a subset of Smalltalk objects (those which can be represented as JSON string) can be passed to/from Python as described above.&lt;br /&gt;
&lt;br /&gt;
In general: if more complex objects need to be interchanged, this must be either done by converting them to an array (of objects), an array of arrays or a dictionary.&lt;br /&gt;
Or, alternatively to some ASCII representation (XML or JSON, for a more lightweight approach) and convert this back and forth.&lt;br /&gt;
&lt;br /&gt;
It is also possible to pass an object-reference from the Python interpreter to expecco, and pass it back to the Python interpreter later (usually in another action).&lt;br /&gt;
This is used to get connection, protocol or device handles from Python, and pass them to other (transmission or control) actions later.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
==== Debugging Support ====&lt;br /&gt;
Some debugging facilities are provided to support development of Node code.&lt;br /&gt;
If your code contains an endless loop, you can interrupt the Node interpreter (via the &amp;quot;Interrupt Execution&amp;quot; button at the top right)&lt;br /&gt;
and get a debugger window, showing the call stack and local variables.&lt;br /&gt;
However, there are situations, when the Python interpreter gets completely locked up and ceases to react.&lt;br /&gt;
In this situation, you will have to shut down the Python interpreter via the &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Node JS&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Close Connections&#039;&#039;&amp;quot; menu function.&lt;br /&gt;
Of course, thi also implies, that any state inside the Python interpreter is lost, and you&#039;ll have to rerun your test setup from the start.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Limited Syntax Highlighting, Code Completion and Debugging Support ====&lt;br /&gt;
Currently, all of those are very limited: the syntax highlighter only detects keywords and some constants as such; code completion does not work and no interactive debugger is provided currently.&lt;br /&gt;
&lt;br /&gt;
=== Bridged Python Code API ===&lt;br /&gt;
&lt;br /&gt;
WARNING: Bridged Python Elementary Actions are still being developed - their behavior might be subject to changes (aka the protocol will be extended).&lt;br /&gt;
 &lt;br /&gt;
Python code may consist of function- and/or class definitions. Among the functions, there should be one named &amp;quot;&amp;lt;CODE&amp;gt;execute()&amp;lt;/CODE&amp;gt;&amp;quot;; typically, that is the last defined function, which calls into other python code. If no &amp;quot;execute&amp;quot;-function is defined, expecco tries to call &amp;quot;&amp;lt;code&amp;gt;main()&amp;lt;/CODE&amp;gt;&amp;quot; as fallback. This special behavior was added to make it easier to reuse existing script code.&lt;br /&gt;
&lt;br /&gt;
Bridged Python code can use activity functions similar to the above Groovy or Node actions.&lt;br /&gt;
The API is intended to provide an interface similar to the JavaScript and Smalltalk elementary code API. Of course, technically for every API function below, the code executing in the remote Python interpreter has to make a remote procedure call back to expecco. On the Python side, this is done very similar to the above described remote message mechanism, when messages are sent from Smalltalk to a bridge.&lt;br /&gt;
&lt;br /&gt;
==== Variables seen by the Executed Python Function ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed function:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages in the expecco Transcript window (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stdout stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stderr stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Logger &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports &amp;lt;code&amp;gt;info(), warn(), error() and fatal()&amp;lt;/code&amp;gt;; these are forwarded to the Smalltalk Logger object (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Dialog &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports &amp;lt;code&amp;gt;confirm(), warn(), information()&amp;lt;/code&amp;gt;; these are forwarded to the Smalltalk Dialog object (see below)&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&amp;lt;code&amp;gt;__bridge__&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;the bridge object which handles the communication with expecco. The instance slot named &amp;quot;&amp;lt;code&amp;gt;asynchronous&amp;lt;/code&amp;gt;&amp;quot; is of special interest if the called function uses asynchronous callbacks (see below)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Python) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report a defect (in the test). Finishes the current activity with an &#039;&#039;error&#039;&#039; verdict.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report a failure (in the SUT). Finishes the current activity.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report an inconclusive test. Finishes the current activity.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;)&amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testPass&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;)&amp;lt;br&amp;gt;Finishes the current testCase with success. This has the same effect as &amp;quot;pass()&amp;quot; in other actions - its name had to be changed because &amp;quot;pass&amp;quot; is a reserved keyword in Python.&lt;br /&gt;
&lt;br /&gt;
==== Logging (Python) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logFail&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a fail message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Log -Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Same as &#039;&#039;alert()&#039;&#039; (for Smalltalk protocol compatibility).&lt;br /&gt;
&lt;br /&gt;
==== Reflection, Information, Queries and Accessing (Python) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;) &amp;lt;br&amp;gt;The value of an environment variable&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Changing the value of an environment variable.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text plan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlanItem&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Interaction with Expecco (Python) ====&lt;br /&gt;
*&#039;&#039;&#039;call&#039;&#039;&#039;(&amp;amp;lt;actionName&amp;amp;gt;, &amp;amp;lt;arg1&amp;amp;gt;, &amp;amp;lt;arg2&amp;amp;gt;, ... &amp;amp;lt;argN&amp;amp;gt;);&amp;lt;br&amp;gt;Executes any other expecco action (inside expecco - not inside the Python interpreter), and returns the generated output pin values as a tuple&amp;lt;br&amp;gt;It is currently not possible to get the values of pins which are written multiple times (i.e. an error will be reported, if that is the case)&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
==== Environment Access (Python) ====&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;);&amp;lt;br&amp;gt;Fetches and returns a value from the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from python actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAtPut&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;, &amp;amp;lt;newValue&amp;amp;gt;);&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only write simple objects (numbers, booleans and strings) from python actions.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Event Sending (Python) ====&lt;br /&gt;
* &#039;&#039;&#039;pushEvent&#039;&#039;&#039; (&#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event onto the global event handler&#039;s event queue. The payload is packed into an Event object with eventType &amp;quot;&amp;lt;code&amp;gt;#default&amp;lt;/code&amp;gt;. Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pushEventType_data&#039;&#039;&#039; (&#039;&#039;eventTypeSymbolOrNil&#039;&#039;, &#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event of type (or &amp;lt;code&amp;gt;#default&amp;lt;/code&amp;gt;) onto the global event handler&#039;s event queue. Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
==== Special Functions (Python) ====&lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039; (&amp;amp;lt;anyPythonObject&amp;amp;gt;) &amp;lt;br&amp;gt;Generates a reference to a Python object, which can be passed to expecco as an output pin value. Such reference objects can be passed back to Python later and are dereferenced there back to the original object. This is used to pass Python handles (i.e. server/client handles) to expecco and later back to Python. Read below about reference passing vs. value passing.&amp;lt;br&amp;gt;Notice that the pythonObject will be registered (i.e. remembered) inside the python interpreter, in order to be found later, when the reference is passed as input by another node action. When the reference is no longer needed, it should be deregistered by calling the &amp;quot;&amp;lt;code&amp;gt;releaseRef&amp;lt;/code&amp;gt; function described below.&amp;lt;br&amp;gt;Also notice, that expecco will do this automatically, when the reference object is finalised.&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;releaseRef&#039;&#039;&#039; (&amp;amp;lt;nodeObjectReference&amp;amp;gt;) &amp;lt;br&amp;gt;removes the reference from the registery inside the Python interpreter.&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;wait&#039;&#039;&#039; () &amp;lt;br&amp;gt;Tells expecco to wait until one of the &amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;error()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fail()&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;inconclusive()&amp;lt;/code&amp;gt; functions is called.&amp;lt;br&amp;gt;Use this if a pin value has to be written later by a callback function.&amp;lt;br&amp;gt;See explanation of [[#Asynchronous_and_Callback_Functions|async callbacks]] and the example in the NodeJS API description.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;mayStillDoExpeccoCalls&#039;&#039;&#039; (&#039;&#039;boolean&#039;&#039;) &amp;lt;br&amp;gt;Make sure that the functions described here will still be callable (by Java callback functions from other threads) even after the step has finished execution. In other words, do NOT release the observer object which is responsible for the transfer of information between the two systems. Be aware that this object remains and will never be released, until the bridge connection is closed. I.e. there is a potential for a memory leak inside the Java VM here.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;bridge_inMainThread&#039;&#039;&#039; (task)&amp;lt;br&amp;gt;OS X only:&amp;lt;br&amp;gt;Task must be a lambda expression which is executed by the main thread (as opposed to the bridge connection thread).&amp;lt;br&amp;gt;This is required on eg. OS X to run code which interacts with OS X windowing framework.&amp;lt;br&amp;gt;On non-OSX systems, this executes the task directly (and also in the main thread).&amp;lt;br&amp;gt;Typical use: &amp;lt;code&amp;gt;bridge_inMainThread(lambda: someWindow.show() )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Pin Functions (Python) ====&lt;br /&gt;
Currently, python blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
Attention:&lt;br /&gt;
&amp;lt;br&amp;gt;Python uses many more reserved keywords for syntax than Smalltalk. These keywords cannot be used as pin names, and you will get a syntax error if you try. Be careful to not name your pins as any of: &amp;quot;&amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;def&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;&amp;quot; etc. As a proven best practice, add a &amp;quot;&#039;&#039;Pin&#039;&#039;&amp;quot; suffix to your pin names (i.e. name it &amp;quot;&#039;&#039;inPin&#039;&#039;&amp;quot;, instead of &amp;quot;&#039;&#039;in&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
===== Input Pins (Python) =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin is connected&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value at the pin (the datum). Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;refValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the object referenced by the value at the pin. The pin must have received a reference. Raises an error if the pin did not receive any value. Use this to pass back the original reference object to expecco. The input pin must have received a reference to a Python object as generated previously by &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot;. Read below about reference passing vs. value passing. &lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfPresent&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the pin-datum if it has one, None otherwise. Similar to &amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;, but avoids the exception.&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;, but avoids the exception. Use this, if &amp;quot;None&amp;quot; is a possible value at the pin, and the code needs to distinguish between getting a &amp;quot;None&amp;quot; at the pin and not having a value at all at the pin.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the alternativeValue if the pin did not receive any value.&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Output Pins (Python) =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isBuffered&#039;&#039;&#039; () &amp;lt;br&amp;gt;True if the pin is buffered&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
&amp;lt;!-- *&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039;() &amp;lt;br&amp;gt;Returns true if the pin is connected&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; (&#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes the value.&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (Python) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from Python code. However, only a limited subset of messages is supported:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;...)&amp;lt;br&amp;gt;Like &amp;quot;&amp;lt;code&amp;gt;show()&amp;lt;/code&amp;gt;, but &amp;quot;%i&amp;quot; sequences in the format argument are expanded by the corresponding arg strings.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;...)&amp;lt;br&amp;gt;Like &amp;quot;&amp;lt;code&amp;gt;showCR()&amp;lt;/code&amp;gt;, but &amp;quot;%i&amp;quot; sequences in the format argument are expanded by the corresponding arg strings.&lt;br /&gt;
&lt;br /&gt;
*Transcript &#039;&#039;&#039;clear&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Clears the contents of the Transcript window (new in 24.2)&lt;br /&gt;
&lt;br /&gt;
*Transcript &#039;&#039;&#039;raiseWindow&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Makes the Transcript window visible (new in 24.2)&lt;br /&gt;
&lt;br /&gt;
In addition, stdout (console.log) and stderr (console.error) are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Dialog (Python) ====&lt;br /&gt;
Some of expecco&#039;s Dialog messages are forwarded from Python:&lt;br /&gt;
*&#039;&#039;&#039;information&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;) (new in 23.2)&amp;lt;br&amp;gt;Opens an information dialog. I.e. &amp;quot;&amp;lt;code&amp;gt;Dialog.information(&amp;quot;Hello&amp;quot;)&amp;lt;/code&amp;gt; will show &amp;quot;Hello&amp;quot; in a popup dialog window.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;confirm&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a Yes/No confirmation dialog (and returns True/False)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;request&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a dialog asking for a string (and returns the entered string or None on cancel)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestPassword&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a dialog asking for a password string (and returns the entered string or None on cancel)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestFilename&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;) (new in 23.2)&amp;lt;br&amp;gt;Opens a dialog asking for a file name string (and returns the entered file name or None on cancel)&lt;br /&gt;
&lt;br /&gt;
=== Global and Static Variables ===&lt;br /&gt;
Python actions are defined within the scope of another function, to prevent accidentically overwriting/redefining any global.&lt;br /&gt;
Thus, you have to access globals via &amp;quot;globals().get(&amp;quot;name&amp;quot;)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Static Variables ====&lt;br /&gt;
Starting with v24.1, static variables (which are visible within one activity and which are preserved across calls) can be defined by&lt;br /&gt;
prepending the execute function&#039;s code with:&lt;br /&gt;
 # start of static definitions&lt;br /&gt;
 ... any variables which should be static ...&lt;br /&gt;
 # end of static definitions&lt;br /&gt;
&lt;br /&gt;
Notice that these comment lines must be written exactly as above.&lt;br /&gt;
&amp;lt;br&amp;gt;As an example, the following uses a static variable to increment a counter whenever the action is Ivoked:&lt;br /&gt;
 # start of static definitions&lt;br /&gt;
 count=0&lt;br /&gt;
 # end of static definitions&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     nonlocal count&lt;br /&gt;
 &lt;br /&gt;
     count = count + 1&lt;br /&gt;
     print(f&amp;quot;count={count}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Notice that the above example does not work in pre 24.1 versions.&lt;br /&gt;
&amp;lt;br&amp;gt;Also notice, that the static definitions are re-executed whenever the action code is changed or recompiled (i.e. that the count variable is reset to 0).&lt;br /&gt;
&lt;br /&gt;
==== Global Variables ====&lt;br /&gt;
&lt;br /&gt;
Example of a global variable that can also be used in other modules.&lt;br /&gt;
&lt;br /&gt;
Caution: Please make sure that the name of the global variable is unique in your test suite!&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
     global count&lt;br /&gt;
     try:&lt;br /&gt;
         count&lt;br /&gt;
     except NameError:&lt;br /&gt;
         # Throws a NameError if not yet initialised&lt;br /&gt;
         count = 0&lt;br /&gt;
     count = count + 1&lt;br /&gt;
     print(f&amp;quot;count={count}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Printing Debug Messages in Python ===&lt;br /&gt;
Be aware, that the stdout stream is buffered in Python. Thus, debugprints generated by print might not appear immeditely.&lt;br /&gt;
&amp;lt;br&amp;gt;Eg, the following code:&lt;br /&gt;
 print(&amp;quot;start&amp;quot;)&lt;br /&gt;
 time.sleep(10)&lt;br /&gt;
 print(&amp;quot;end&amp;quot;)&lt;br /&gt;
will show both lines after the sleep.&lt;br /&gt;
&lt;br /&gt;
Use&lt;br /&gt;
 sys.stdout.flush()&lt;br /&gt;
to force messages to be passed immediately to expecco; eg:&lt;br /&gt;
 print(&amp;quot;start&amp;quot;)&lt;br /&gt;
 sys.stdout.flush()&lt;br /&gt;
 time.sleep(10)&lt;br /&gt;
 print(&amp;quot;end&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Python Asynchronous and Callback Functions  ===&lt;br /&gt;
If output pins are to be written by a callback which is invoked AFTER the python function returned, the expecco activity will already be finished, and the pin will NOT be written.&lt;br /&gt;
Instead, a warning is generated in the log.&lt;br /&gt;
&lt;br /&gt;
You MUST tell expecco that the execute function has not yet finished, by calling &amp;quot;wait()&amp;quot; and signal the real activity end in the callback via one of &amp;quot;success()&amp;quot;, &amp;quot;error()&amp;quot;or &amp;quot;fail()&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For a detailed description of this mechanism, read the &lt;br /&gt;
[[#Asynchronous and Callback Functions|corresponding section]] in the Node API.&lt;br /&gt;
&lt;br /&gt;
=== Reference passing vs. value passing of Python objects to expecco ===&lt;br /&gt;
&lt;br /&gt;
When values are passed via an output pin from Python to expecco, two mechanisms are possible:&lt;br /&gt;
* pass by value&amp;lt;br&amp;gt;The object&#039;s JSON string is generated and passed to expecco. There, the JSON encoding is decoded and a corresponding expecco object is constructed. Conceptional, the expecco object is a copy of the original object.&lt;br /&gt;
&lt;br /&gt;
* pass by reference&amp;lt;br&amp;gt;The object is remembered inside Python, and a reference is passed to expecco. Whenever this reference object is later sent to Python again (via an input pin), the original Python object is retrieved and passed to the Python code. This mechanism preserves the object&#039;s identity on the Python side and must be used for object handles (such as protocol handles).&lt;br /&gt;
&lt;br /&gt;
The default mechanism is &amp;quot;&#039;&#039;pass by value&#039;&#039;&amp;quot;. &lt;br /&gt;
&amp;lt;br&amp;gt;To pass a reference, use &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot; and pass the generated reference to an output pin.&lt;br /&gt;
&lt;br /&gt;
When objects are passed from expecco to python, this is transparent. Python will automatically resolve passed in references. Thus you can send a &amp;quot;pointer&amp;quot; to an object to an output pin via &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot; and pass it to another Python action, where the value will refer to the original object.&lt;br /&gt;
 &lt;br /&gt;
==== Example (Python) ====&lt;br /&gt;
The following code snippet sends an object&#039;s reference to an output pin:&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... generate a handle object ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    outputPin.value( makeRef (someHandle ) )&lt;br /&gt;
&lt;br /&gt;
the returned handle can later be sent via an input pin to another Python action inside the same bridge, and use transparently there:&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
     handle = inputPin.value()&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with handle ...&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
occasionally, it is required that a reference which was received via an input pin must later be sent to an output pin again, preserving the original reference. This is to prevent additional memory allocations which would result from calling &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; again (you would get multiple references to the same object).&lt;br /&gt;
For this, use &amp;quot;&amp;lt;code&amp;gt;inputPin.refValue()&amp;lt;/code&amp;gt;&amp;quot; and send this to an output pin without a &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
     handle = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with handle ...&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;# send the original reference to the output&amp;lt;/span&amp;gt;&lt;br /&gt;
     outputPin.value( inputPin.refValue() )&lt;br /&gt;
&lt;br /&gt;
Finally, you want to release the reference inside the Python interpreter, to prevent memory leaks.&lt;br /&gt;
Usually, this should be called, when a handle becomes invalid (e.g. when a connection handle is closed).&lt;br /&gt;
&lt;br /&gt;
For this, call the &amp;quot;&amp;lt;code&amp;gt;releaseRef&amp;lt;/code&amp;gt;&amp;quot; function (on the node side), passing the reference instead of the referenced object.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, a close-connection action block might look like:&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
     reference = inputPin.refValue()&lt;br /&gt;
     referredObject = inputPin.value()&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with referredObject ...&amp;lt;/span&amp;gt;&lt;br /&gt;
     closeConnection( referredObject )&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;# release to prevent memory leaks&amp;lt;/span&amp;gt;&lt;br /&gt;
     releaseRef(referredObject)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Commented: text was copy-pasted from Node; may need adoption to Python&lt;br /&gt;
=== Asynchronous and Callback Functions  ===&lt;br /&gt;
A common pattern in node is &amp;quot;&#039;&#039;continuation passing style&#039;&#039;&amp;quot; control flow. That means, that many functions expect function as callback argument, which is called later whenever the requested operation has finished. This is used especially with I/O and protocol related operations (such as socket connect, http requests, client connect setup etc.).&lt;br /&gt;
If your &amp;quot;&amp;lt;code&amp;gt;execute&amp;lt;/code&amp;gt;&amp;quot; functions calls any of those, and wants the expecco action to wait until the callback occurred, you should call the &amp;quot;wait()&amp;quot; function at the end of the execute function. &lt;br /&gt;
&lt;br /&gt;
Then expecco will continue to wait for the action to be finished until the node code calls one of the &amp;quot;&amp;lt;code&amp;gt;fail()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;error()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;pass()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;inconclusive()&amp;lt;/code&amp;gt;&amp;quot; functions (listed above).&lt;br /&gt;
&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&lt;br /&gt;
  function execute() {&lt;br /&gt;
     ... call a function which does a callback ...&lt;br /&gt;
    myProtocolConnect( ... , function(err) {&lt;br /&gt;
        ... callback possibly called much later ...&lt;br /&gt;
        // tell expecco that we&#039;re done&lt;br /&gt;
        if (err) {&lt;br /&gt;
            error(&amp;quot;some error happened: &amp;quot;+err.toString());&lt;br /&gt;
        } else { &lt;br /&gt;
            success();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
    // tell expecco to continue waiting&lt;br /&gt;
    wait();&lt;br /&gt;
 }&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Calling other Expecco Actions (Python) ===&lt;br /&gt;
Not yet implemented &lt;br /&gt;
&lt;br /&gt;
Any expecco action (i.e. elementary or compound) can be called from Python code.&lt;br /&gt;
You can pass either the name or the UUID of the activity which is to be called.&lt;br /&gt;
Arguments are passed to the called action&#039;s input pin (top to bottom).&lt;br /&gt;
&lt;br /&gt;
For now, there is a limitation, in that only a single value (per pin) can be returned (i.e. you cannot get the values of pins which are written multiple times).&lt;br /&gt;
&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&lt;br /&gt;
  def execute():&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... call an expecco activity ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    result = call(&amp;quot;myAction&amp;quot;, 100, 200)&lt;br /&gt;
&lt;br /&gt;
=== Python2 vs. Python3 ===&lt;br /&gt;
Although python2 is going to be obsoleted soon, there are still many packages and frameworks around, which require that version. &lt;br /&gt;
&lt;br /&gt;
If all of your actions use the same python version, specify it in the &amp;quot;Python&amp;quot; field of the interpreter settings dialog.&lt;br /&gt;
Otherwise, change individual action&#039;s python version via the &amp;quot;Language&amp;quot; comboList, above the code editor (change to &amp;quot;BridgedPython2&amp;quot; or &amp;quot;BridgedPython3&amp;quot; to make it explicit).  &lt;br /&gt;
&lt;br /&gt;
Paths to the explicit versions and to the unspecific version are all defined in the pathon settings.&lt;br /&gt;
&lt;br /&gt;
=== Reading expecco Environment Variables (Python) ===&lt;br /&gt;
Expecco variables can be fetched via the &amp;quot;&amp;lt;code&amp;gt;environmentAt&amp;lt;/code&amp;gt;&amp;quot; function.&lt;br /&gt;
&amp;lt;br&amp;gt;For example:&lt;br /&gt;
 def execute():&lt;br /&gt;
    varValue = environmentAt(&amp;quot;variable1&amp;quot;)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
=== Python Packages ===&lt;br /&gt;
You should install python packages using &amp;quot;pip&amp;quot; or &amp;quot;pip3&amp;quot;, depending on the python version, for which a package is to be installed.&lt;br /&gt;
For more information, please consult the [http://pip.pypa.io pip documentation].&lt;br /&gt;
&lt;br /&gt;
On Windows, &amp;quot;pipwin&amp;quot; seems to perform best, if additional C/C++ libraries need to be installed or compiled (eg. &amp;quot;pipwin install pyaudio&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
When installing, make sure that the packages are installed in the correct target directory, as per Python environment; i.e. if you have multiple versions of the interpreter or virtual environments, make sure that the Python as started by expecco (and defined in the settings) uses and sees the correct module path.&lt;br /&gt;
&lt;br /&gt;
===Installing Additional Python Packages ===&lt;br /&gt;
Use the Python package installer &amp;quot;&amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt;&amp;quot; (or &amp;quot;&amp;lt;code&amp;gt;pip3&amp;lt;/code&amp;gt;&amp;quot;) to install packages.&lt;br /&gt;
The &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Python Bridge&#039;&#039;&amp;quot; menu also contains an entry to install pip packages.&lt;br /&gt;
If you use virtual environments, make sure that your packages are installed in the correct location.&lt;br /&gt;
&lt;br /&gt;
Find packages in [https://pypi.org/ https://pypi.org/] or [https://docs.python.org/3/py-modindex.html https://docs.python.org/3/py-modindex.html].&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
For example, assume you need the current city weather in a suite, navigate to &amp;quot;https://www.npmjs.com&amp;quot;, search for &amp;quot;weather&amp;quot;, find the &amp;quot;&amp;lt;code&amp;gt;city-weather&amp;lt;/code&amp;gt;&amp;quot; package and click on it. You will arrive on a page giving installation instructions and sample code at the end.&lt;br /&gt;
Scroll down to the example code and keep that page open (we can use the code later).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Open a cmd/shell window and execute on the command line:&lt;br /&gt;
 npm install city-weather&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Accessing Assemblies in IronPython ===&lt;br /&gt;
Because IronPython executes inside a CLR environment, it has access to any assembly (written in any language).&lt;br /&gt;
For this, IronPython provides a special language extension, which is described in detail in [[https://ironpython.net/documentation/dotnet/dotnet.html the IronPython documentation]].&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 *** to be added **&lt;br /&gt;
&lt;br /&gt;
=== Example 1: Using the &amp;quot;overpy&amp;quot; Python Package (open street map access) in Expecco ===&lt;br /&gt;
In this example, we will access the OpenStreetMap API to fetch information about a particular street&lt;br /&gt;
(&amp;quot;Straße der Nationen&amp;quot;) in a given city (&amp;quot;Chemnitz&amp;quot;).&lt;br /&gt;
 &lt;br /&gt;
The example was taken from [https://pypi.org/project/overpy https://pypi.org/project/overpy] which is documented in [https://python-overpy.readthedocs.io/en/latest/index.html https://python-overpy.readthedocs.io/en/latest/index.html].&amp;lt;br&amp;gt;It requires python3 (you will get a UnicodeEncodeError if you try it in python2).&lt;br /&gt;
&lt;br /&gt;
First, install the package with:&lt;br /&gt;
 pip3 install overpy&lt;br /&gt;
&lt;br /&gt;
For a first test, we will take the original code from the example.&lt;br /&gt;
Create a new Python action, and enter the code:&lt;br /&gt;
 import overpy&lt;br /&gt;
 &lt;br /&gt;
 api = overpy.Overpass()&lt;br /&gt;
 &lt;br /&gt;
 def execute(): &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;# fetch all ways and nodes&amp;lt;/span&amp;gt;&lt;br /&gt;
    result = api.query(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        way(50.746,7.154, 50.748,7.157) [&amp;quot;highway&amp;quot;];&lt;br /&gt;
        (._;&amp;gt;;);&lt;br /&gt;
        out body;&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for way in result.ways:&lt;br /&gt;
        print(&amp;quot;Name:%s&amp;quot; % way.tags.get(&amp;quot;name&amp;quot;, &amp;quot;n/a&amp;quot;))&lt;br /&gt;
        print(&amp;quot;  Highway:%s&amp;quot; % way.tags.get(&amp;quot;highway&amp;quot;, &amp;quot;n/a&amp;quot;))&lt;br /&gt;
        print(&amp;quot;  Nodes:&amp;quot;)&lt;br /&gt;
        for node in way.nodes:&lt;br /&gt;
            print(&amp;quot;    Lat:%f, Lon:%f&amp;quot; % (node.lat, node.lon))&lt;br /&gt;
&lt;br /&gt;
(you can copy-paste the sample code from the webpage)&lt;br /&gt;
&lt;br /&gt;
Open the expecco console (aka &amp;quot;Transcript&amp;quot; via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Transcript&#039;&#039;&amp;quot; menu item) and run the test.&lt;br /&gt;
A list of street nodes should be displayed on the Transcript.&lt;br /&gt;
&lt;br /&gt;
=== Example 2: Accessing other Python Packages or Individual Script Files ===&lt;br /&gt;
The following works in 19.2 and later.&amp;lt;br&amp;gt;&lt;br /&gt;
In the following example, functions contained in a regular Python script file are called.&lt;br /&gt;
We assume, that the file is named &amp;quot;MyLib.py&amp;quot;, and located in some directory &#039;&#039;DIR&#039;&#039;:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
DIR/MyLib.py:&lt;br /&gt;
 def fun1(a,b):&lt;br /&gt;
    return a+b;&lt;br /&gt;
 &lt;br /&gt;
 def fun2(a,b):&lt;br /&gt;
    return a-b;&lt;br /&gt;
&lt;br /&gt;
We also assume, that you have created a new python action block, containing the code:&lt;br /&gt;
&lt;br /&gt;
 import MyLib&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
    Transcript.showCR(&amp;quot;fun1:&amp;quot; + str(MyLib.fun1(10,20))&lt;br /&gt;
                    + &amp;quot; fun2:&amp;quot; + str(MyLib.fun2(10,20)))&lt;br /&gt;
&lt;br /&gt;
If you execute this action, you will probably get a &amp;quot;Module Not Found&amp;quot; error from python,&lt;br /&gt;
(unless DIR is already in your PYTHONPATH environment variable).&lt;br /&gt;
&lt;br /&gt;
To fix the problem, open the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot; dialog,&lt;br /&gt;
and add DIR to the &amp;quot;Module Path&amp;quot; value. Notice that on Unix/Linux, you have to separate directories with colons &amp;quot;:&amp;quot;, whereas under Windows, you&#039;ll have to separate them with semicolons &amp;quot;;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You will have to shut down the already running Python interpreter and restart it, for the new PYTHONPATH setting to become valid.&amp;lt;br&amp;gt;For this, use the &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python Bridge&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Shutdown Interpreters&#039;&#039;&amp;quot; menu item (or shut down all external interpreters via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Debug&#039;&#039;&amp;quot; menu).&lt;br /&gt;
&lt;br /&gt;
=== Example 3: Accessing Python Script Files in Attachments ===&lt;br /&gt;
The following works in 19.2 and later.&amp;lt;br&amp;gt;&lt;br /&gt;
You can add Python script files (i.e. like the &amp;quot;MyLib.py&amp;quot; file in the above example) as attachment to to the suite.&amp;lt;br&amp;gt;For this you have to add &amp;quot;$(Attachments)&amp;quot; to the Python module path setting in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot;, and import it in the Python code as in the previous example.&lt;br /&gt;
&lt;br /&gt;
=== Example 4: Using the Python Appium Bindings ===&lt;br /&gt;
In the following, we&#039;ll use a Python Appium interface for automation of a mobile application&lt;br /&gt;
(in this case, not using the mobile plugin, and not using the GUI Browser).&lt;br /&gt;
This may be a useful scenario, if you already have python test actions, which you want to integrate into&lt;br /&gt;
expecco.&lt;br /&gt;
&lt;br /&gt;
First install the required python package(s) via the command line or via expecco&#039;s &amp;quot;&#039;&#039;Plugin&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot; menu:&lt;br /&gt;
 pip3 install Appium-Python-Client&lt;br /&gt;
or:&lt;br /&gt;
 python -m pip install Appium-Python-Client&lt;br /&gt;
then make a dummy BridgePython block to check if the package is found:&lt;br /&gt;
 import appium&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     Transcript.showCR (&amp;quot;Hello world; Appium was found&amp;quot;);&lt;br /&gt;
Now take either existing code, or copy-paste samples from the [https://pypi.org/project/Appium-Python-Client Appium-Python-Client website]; here is a typical code fragment (of course, you have to adjust the values as required). Obviously, it is also a good idea to add input pins to the python action, so the capabilities and connection parameters can be passed as arguments.&lt;br /&gt;
 from appium import webdriver&lt;br /&gt;
 &lt;br /&gt;
 desired_caps = dict(&lt;br /&gt;
     platformName=&#039;Android&#039;,&lt;br /&gt;
     platformVersion=&#039;10&#039;,&lt;br /&gt;
     automationName=&#039;uiautomator2&#039;,&lt;br /&gt;
     deviceName=&#039;Android Emulator&#039;,&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     driver = webdriver.Remote(&#039;http://localhost:4723/wd/hub&#039;, desired_caps)&lt;br /&gt;
     el = driver.find_element_by_accessibility_id(&#039;item&#039;)&lt;br /&gt;
     el.click()&lt;br /&gt;
&lt;br /&gt;
=== Example 5: Interfacing to Tensorflow ===&lt;br /&gt;
&lt;br /&gt;
* Create a bridged Python action containing the following code:&lt;br /&gt;
 import numpy as np &lt;br /&gt;
 import tensorflow as tf&lt;br /&gt;
 import tensorflow_hub as hub&lt;br /&gt;
 import tensorflow_datasets as tfds&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     print(&amp;quot;Version: &amp;quot;, tf.__version__)&lt;br /&gt;
     print(&amp;quot;Eager mode: &amp;quot;, tf.executing_eagerly())&lt;br /&gt;
     print(&amp;quot;Hub Version: &amp;quot;, hub.__version__)&lt;br /&gt;
     print(&amp;quot;GPU is&amp;quot;, &amp;quot;available&amp;quot; if tf.config.experimental.list_physical_devices(&amp;quot;GPU&amp;quot;) else &amp;quot;NOT AVAILABLE&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
* run it&lt;br /&gt;
* if you get a &amp;quot;module not found&amp;quot; error message, either click on the link (named &amp;quot;here&amp;quot;), embedded in the error message, or alternatively select the &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Install pip Package&#039;&#039;&amp;quot; menu item. Of course, you can also install packaged from the command line in a shell/cmd window.&lt;br /&gt;
* install missing packages (care for the correct virtual environment if you use them)&lt;br /&gt;
* repeat running it, until you get an output on the Transcript (or stderr) similar to:&lt;br /&gt;
 1: Version:  2.4.1&lt;br /&gt;
 1: Eager mode:  True&lt;br /&gt;
 1: Hub Version:  0.11.0&lt;br /&gt;
 1: GPU is NOT AVAILABLE&lt;br /&gt;
&lt;br /&gt;
* You may have to shutdown the bridge after installation of new packages (although it usually works without, unless existing and already loaded packages are upgraded during the installation).&lt;br /&gt;
&lt;br /&gt;
=== Example 6: Interfacing to the &amp;quot;astropy&amp;quot; Package ===&lt;br /&gt;
The &amp;quot;astropy&amp;quot; package contains a number of very useful functions for astronomy applications. Among others, you&#039;ll find time functions, geo-location mapping, physical constants, image processing and much more inside.&amp;lt;br&amp;gt;(see https://docs.astropy.org/en/stable/index.html)&lt;br /&gt;
&lt;br /&gt;
===== Installation =====&lt;br /&gt;
&lt;br /&gt;
First install the required python package(s) via the command line or via expecco&#039;s &amp;quot;&#039;&#039;Plugin&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot; menu:&lt;br /&gt;
 pip3 install numpy&lt;br /&gt;
 pip3 install astropy (astropy-Python-Client)&lt;br /&gt;
or:&lt;br /&gt;
 python -m pip install numpy&lt;br /&gt;
 python -m pip install astropy (astropy-Python-Client)&lt;br /&gt;
&lt;br /&gt;
===== Smoke Test if Package is Installed =====&lt;br /&gt;
&lt;br /&gt;
then make a dummy BridgePython block to check if the package is found:&lt;br /&gt;
 import astropy&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     Transcript.showCR (&amp;quot;Hello world; astropy was found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Notice: because bumpy and astropy are relatively big packages, the first initial execution may take a few seconds because the Python interpreter has to load these packages (but this only happens when the very first Python action is executed).&lt;br /&gt;
&lt;br /&gt;
===== Interface to an astropy Function =====&lt;br /&gt;
&lt;br /&gt;
The following example demonstrates how to call functions within astropy;&lt;br /&gt;
this will convert an expecco timestamp (a DateTime object) to a julianDate (as Float).&lt;br /&gt;
(Hint: JulianDates are commonly used in Astronomy and Space Sciences).&lt;br /&gt;
&lt;br /&gt;
Please read https://docs.astropy.org/en/stable/time/index.html for details on time functions.&lt;br /&gt;
&lt;br /&gt;
The code includes a few debug prints (to the Transcript). In a production suite, these should probably be commented (or replaced by calls to a logger, which can be switched on/off dynamically).&lt;br /&gt;
&lt;br /&gt;
[[Datei:AstroPyExample1.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The action can then be used in a diagram as:&lt;br /&gt;
&lt;br /&gt;
[[Datei:AstroPyExample2.png|500px]]&lt;br /&gt;
&lt;br /&gt;
After a run, we get the Julian date as a float:&lt;br /&gt;
&lt;br /&gt;
[[Datei:AstroPyExample3.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Be aware that expecco requires objects to be JSON serializable to be passed from/to the Python interpreter. Sadly, this is not true for all atrophy objects. If required either pass objects by reference or encode/decode them as strings (or extract subfields into an array and pass the array or pass subfields via individual input/output pins).&lt;br /&gt;
&lt;br /&gt;
It may also be possible to define additional JSON encoders/decoders for individual types.&lt;br /&gt;
&lt;br /&gt;
=== Example 7: Background Thread Inside Python ===&lt;br /&gt;
&lt;br /&gt;
It may be useful to execute python code in a Python background thread;&lt;br /&gt;
for example to poll for data or to check for external equipment status&lt;br /&gt;
in a loop.&lt;br /&gt;
&lt;br /&gt;
===== Extra Process with a Secondary Python Bridge =====&lt;br /&gt;
&lt;br /&gt;
In many cases, you can start a secondary Python bridge and execute actions&lt;br /&gt;
in it via an expecco background action. &lt;br /&gt;
&amp;lt;br&amp;gt;For this: &lt;br /&gt;
* start a new Python bridge (using the &amp;quot;[Python] Start bridge&amp;quot; action from the standard library) in the background action&lt;br /&gt;
* add a python bridge input pin to actions which are to be executed there and pass that bridge reference to the background action&#039;s python step inputs.&lt;br /&gt;
:As an alternative, define an environment variable named &amp;quot;PYTHON&amp;quot; in the background action and set its value to the second bridge instance. Then all python actions inside and under the bg-action will be executed there.&lt;br /&gt;
Notice that no object references can be exchanged between the two bridges;&lt;br /&gt;
you are limited to data types which are JSON representable.&lt;br /&gt;
&lt;br /&gt;
===== Thread inside the Same Python Bridge =====&lt;br /&gt;
If the above is not feasable (for example because the background actions needs access to values or handles of the other actions), you can start a thread inside the same bridge.&lt;br /&gt;
&lt;br /&gt;
However, a number of have to be considered:&lt;br /&gt;
* ensure that the extra thread can be terminated eventually.&amp;lt;br&amp;gt;Because Python does not provide a kill-thread mechanism, the thread must check for a stop variable, and terminate itself.&lt;br /&gt;
* the stop variable should not be a Python global, to avoid name conflicts if more than one background thread is started (or another imported library uses a similar mechanism)&lt;br /&gt;
* communication with the background thread must be performed via event queues, because it cannot write to any output pin.&lt;br /&gt;
&lt;br /&gt;
Here is an example which follows the above scheme:&lt;br /&gt;
====== Background Thread Starter ======&lt;br /&gt;
[[Datei:Python_background_action_schema.png|mini]]&lt;br /&gt;
A Python action which gets a bridge and additional parameters as input. Here, a deltaTime, which defines the poll-loop cycle and a token which is passed with the checkStatus to the event queue.&lt;br /&gt;
&lt;br /&gt;
The action defines 3 functions, the threaded function itself, for which a new thread is started by &amp;quot;execute&amp;quot;, and a thread-stop function (which simply sets the &amp;quot;running&amp;quot; variable to False.&lt;br /&gt;
&lt;br /&gt;
A reference to the stop-function is sent to the output pin.&lt;br /&gt;
&lt;br /&gt;
 import sys&lt;br /&gt;
 import time&lt;br /&gt;
 import threading&lt;br /&gt;
 &lt;br /&gt;
 running = True &lt;br /&gt;
 &lt;br /&gt;
 def thread_function(dt, tok):&lt;br /&gt;
    nonlocal running&lt;br /&gt;
 &lt;br /&gt;
    ExpeccoLogger.info(&amp;quot;Thread %s: starting&amp;quot;, tok)&lt;br /&gt;
    while running:&lt;br /&gt;
        time.sleep(dt)&lt;br /&gt;
        if running:&lt;br /&gt;
            checkOutcome = True # perform check...&lt;br /&gt;
            pushEventType_data(&amp;quot;bg-check&amp;quot;, (tok,checkOutcome))&lt;br /&gt;
    ExpeccoLogger.info(&amp;quot;Thread %s: finishing&amp;quot;, tok)&lt;br /&gt;
 &lt;br /&gt;
 def stopThread():&lt;br /&gt;
    nonlocal running&lt;br /&gt;
    ExpeccoLogger.info(&amp;quot;stopThread&amp;quot;)&lt;br /&gt;
    running = False&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
    ExpeccoLogger.info (&amp;quot;start&amp;quot;)&lt;br /&gt;
    x = threading.Thread(target=thread_function, &lt;br /&gt;
                         args=(waitTime.value(), token.value(),))&lt;br /&gt;
    x.start()&lt;br /&gt;
    stopper = stopThread &lt;br /&gt;
    stopThreadOut.value(makeRef(stopThread))&lt;br /&gt;
    ExpeccoLogger.info (&amp;quot;end&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
====== Thread Stopper ======&lt;br /&gt;
[[Datei:Call_Python_Function.png|mini]]&lt;br /&gt;
the stop-function provided by the thread-starter can later be called to clear the &amp;quot;running&amp;quot; flag. An action to call it would look like:&lt;br /&gt;
&lt;br /&gt;
 import threading&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
   f = func.value()&lt;br /&gt;
   f()&lt;br /&gt;
&lt;br /&gt;
====== EventQueue Setup ======&lt;br /&gt;
The background thread will write to an event queue, with its events marked as &#039;bg-check&#039;. Thus, we must define a handler for those events.&lt;br /&gt;
In expecco, a handler can be either an action block, or a Smalltalk block or a JavaScript function.&lt;br /&gt;
&amp;lt;br&amp;gt;This example uses a Smalltalk block which send a message to the Transcript:&lt;br /&gt;
[[Datei:Python_BG-Thread-Setup.png]]&lt;br /&gt;
When executed, the Transcript shows:&lt;br /&gt;
 [info]: start {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
 [info]: Thread action1: starting {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
 [info]: end {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:49.907)&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:50.909)&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:51.914)&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:52.919)&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:53.937)&lt;br /&gt;
 [info]: stopThread {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
 [info]: Thread action1: finishing {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
&lt;br /&gt;
=== Example 8: Interfacing to a .NET Assembly via IronPython ===&lt;br /&gt;
&lt;br /&gt;
IronPython is a python interpreter running within the .NET CLR framework. The ability of IronPython to import .NET assemblies, makes it easy to also interface those to expecco.&lt;br /&gt;
 &lt;br /&gt;
Please refer to the IronPython documentation on how to import .NET assemblies.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;--- example to be added ---&lt;br /&gt;
&lt;br /&gt;
== Bridged C Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
The following works in 19.2 and above.&amp;lt;br&amp;gt;&lt;br /&gt;
You have to make sure that a C-compiler toolchain is available and can be called directly or indirectly (see [[Installing_additional_Frameworks/en | &amp;quot;Installing additional Frameworks&amp;quot;]]).&lt;br /&gt;
&lt;br /&gt;
Bridged C-code is highly dependent on the C-compiler toolchain of the target machine and may require preparations for machine dependencies with #ifdefs (word length, OS-APIs etc.). It is typically used by experts and for special situations, when simpler alternatives are not available. &lt;br /&gt;
&lt;br /&gt;
Bridged C-code can be used to implement time critical functions or to interface to C/C++ libraries, when the simple DLL-call interface is too complicated to use (for example, if complicated data structures have to be exchanged, if C-callbacks are needed, or if C++ interfaces are to be implemented).&lt;br /&gt;
&lt;br /&gt;
In addition, bridged C-Code actions run in a separate process, isolated from expecco. Thus expecco is not affected by errors in the C-code and cannot be disturbed (eg. by invalid memory references), which is not guaranteed for DLL called functions (which are executed within the expecco process).&amp;lt;br&amp;gt;On the downside, there is some overhead involved in calling a bridged action, since input/output parameters and the call itself are transmitted via an interprocess communication mechanism (i.e. socket/network message). Thus the call roundtrip times are in the millisecond range, as opposed to microseconds for DLL calls.&lt;br /&gt;
&lt;br /&gt;
Other applications are high-speed data acquisition and protocol implementations, in which a C-part is responsible for the time critical task, and expecco can query/control that task remotely (i.e. fetch captured data or state information).&lt;br /&gt;
&lt;br /&gt;
=== The C Bridge ===&lt;br /&gt;
Be reminded that bridged C-Code actions are executed inside a separate OS-process, which runs the c-bridge code.&lt;br /&gt;
Whenever a bridged C-action is to be executed, the pin-data is transferred via an interprocess communication mechanism (IPC), and the code executed inside the bridge process. Pin data and event requests are transmitted back to expecco via the same IPC mechanism.&lt;br /&gt;
&lt;br /&gt;
The C-bridge itself is available as executable or as shared or linkable library in two configurations, with or without the dynamic C code injection facility.&lt;br /&gt;
&lt;br /&gt;
Setups without code injection are useful to augment (statically compiled) embedded systems with a debug interface, through which expecco can later access specific (and explicitly published) interfaces. In such a setup, no dynamic C-code can be injected into the running application. Instead, the set of callable interfaces must be declared and implemented in advance (in the embedded system).&lt;br /&gt;
&lt;br /&gt;
The following chapter describes the dynamic C-code injection facility as seen by elementary activity code in expecco.&amp;lt;br&amp;gt;For static embedded systems, please refer to the [[Embedded Systems C Bridge API | &amp;quot;Embedded Systems C Bridge API&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== Bridged C Code API ===&lt;br /&gt;
&lt;br /&gt;
Note: This is a preliminary API documentation. Bridged C elementary actions are still being developed and the API may be extended or improved in the future (However, it is very very likely to be backward compatible).&lt;br /&gt;
 &lt;br /&gt;
The API is intended to look similar to the other languages&#039; elementary code API.&lt;br /&gt;
However, due to the nature and syntax of the C-language, certain differences are apparent.&amp;lt;br&amp;gt;&lt;br /&gt;
The biggest differences are due to C being a statically typed language: the simple &amp;quot;&amp;lt;code&amp;gt;pin.value()&amp;lt;/code&amp;gt;&amp;quot; interface for pins (as used in other languages) cannot be offered here; instead, a datatype-specific API is provided in C. &lt;br /&gt;
&lt;br /&gt;
==== Variables Seen by the Executed C Function ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed function:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages in the expecco Transcript window (used as argument; see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stdout stream (used as argument; see below). This is NOT the same as the stdout FILE*.&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stderr stream (used as argument; see below). This is NOT the same as the stderr FILE*.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&amp;lt;code&amp;gt;__bridge__&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;the bridge object which handles the communication with expecco. The instance slot named &amp;quot;&amp;lt;code&amp;gt;asynchronous&amp;lt;/code&amp;gt;&amp;quot; is of special interest if the called function uses asynchronous callbacks (see below)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (C) ====&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;error&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution. The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;fail&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039;, ...) &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution. The arguments are printf-style. &lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;inconclusive&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution. The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;activitySuccess&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...)&amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;). The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
==== Logging (C) ====&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;logFail&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Adds a fail message to the activity log, but continues execution. The arguments are printf-style.&amp;lt;br&amp;gt;Notice: although the action continues to be executed, it will be marked as failed at the end.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;logError&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Adds a error message to the activity log, but continues execution. The arguments are printf-style.&amp;lt;br&amp;gt;Notice: although the action continues to be executed, it will be marked as erronous at the end.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;logWarning&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Adds a warning to the activity log, but continues execution. The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;logInfo&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Adds an info message to the activity log, and continues execution. The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;alert&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log -Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;warn&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...)&amp;lt;br&amp;gt;Same as alert(). (For Smalltalk protocol compatibility)&lt;br /&gt;
&lt;br /&gt;
==== Event Sending (C) ====&lt;br /&gt;
*void &#039;&#039;&#039;pushEventType_data&#039;&#039;&#039;(char* &#039;&#039;event&#039;&#039;, char* &#039;&#039;dataOrNULL&#039;&#039;)&amp;lt;br&amp;gt;adds an event to expecco&#039;s event queue. The payload in &#039;&#039;dataOrNULL&#039;&#039; must be a 0-terminated string.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;pushEventType_dataBytes&#039;&#039;&#039;(char* &#039;&#039;event&#039;&#039;, unsigned char* &#039;&#039;dataOrNULL&#039;&#039;, int &#039;&#039;numBytes&#039;&#039;)&amp;lt;br&amp;gt;adds an event to expecco&#039;s event queue. The payload in &#039;&#039;dataOrNULL&#039;&#039; points to a byte-buffer of given length.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;pushEventType_dataJSON&#039;&#039;&#039;(char* &#039;&#039;event&#039;&#039;, jsonObject &#039;&#039;dataOrNULL&#039;&#039;)&amp;lt;br&amp;gt;adds an event to expecco&#039;s event queue. The payload in &#039;&#039;dataOrNULL&#039;&#039; is a [[Embedded_Systems_C_Bridge_API#JSON_Library|json object]].&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
==== Reflection, Information, Queries and Accessing (C) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;) &amp;lt;br&amp;gt;The value of an environment variable&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Changing the value of an environment variable.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text plan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlanItem&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Pin Functions (C) ====&lt;br /&gt;
Currently, C blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
Attention:&lt;br /&gt;
&amp;lt;br&amp;gt;C uses many more reserved keywords for syntax than Smalltalk. These keywords cannot be used as pin names, and you will get a syntax error if you try.&amp;lt;br&amp;gt;Be careful to not name your pins as any of: &amp;quot;&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;&amp;quot;, etc. &lt;br /&gt;
&lt;br /&gt;
As a proven best practice, add a &amp;quot;&#039;&#039;Pin&#039;&#039;&amp;quot; suffix to your pin names (e.g. name it &amp;quot;&#039;&#039;inPin&#039;&#039;&amp;quot;, instead of &amp;quot;&#039;&#039;in&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
===== Input Pins (C) =====&lt;br /&gt;
&lt;br /&gt;
====== Queries ======&lt;br /&gt;
*bool_t &#039;&#039;&#039;hasValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns true if the pin has received a value, where &#039;&#039;true&#039;&#039; is represented as 1, false as 0.&lt;br /&gt;
&lt;br /&gt;
*bool_t &#039;&#039;&#039;isConnected&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns true if the pin is connected.&lt;br /&gt;
&lt;br /&gt;
====== Pin Value ======&lt;br /&gt;
&#039;&#039;&#039;Scalar Values&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
*char* &#039;&#039;&#039;stringValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the string value at the pin as a c-char*. Raises an error if the pin did not receive a value, or if the value was not a string. The returned pointer becomes invalid after the action&#039;s execution; it should therefore be strcpy&#039;d if it is needed later (i.e. do not keep a reference to it). &lt;br /&gt;
&lt;br /&gt;
*long &#039;&#039;&#039;longValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the integer value at the pin as a c-long. Raises an error if the pin did not receive a value, or if the value was not an integer.&lt;br /&gt;
&lt;br /&gt;
*longlong &#039;&#039;&#039;longLongValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) (vsn24.1, 64bit)&amp;lt;br&amp;gt;Returns the integer value at the pin as a c-longLong. Raises an error if the pin did not receive a value, or if the value was not an integer.&amp;lt;br&amp;gt;This API is only avalable in 64bit versions of the C-bridge (i.e. not in the cBridge32.exe for Windows) and only with expecco vsn 24.1 and later.&lt;br /&gt;
&lt;br /&gt;
*double &#039;&#039;&#039;doubleValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the double value at the pin as a c-double Raises an error if the pin did not receive a value, or if the value was not a number.&lt;br /&gt;
&lt;br /&gt;
*bool_t &#039;&#039;&#039;booleanValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the boolean value at the pin as a c-int. Raises an error if the pin did not receive a value, or if the value was not a boolean.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vectors&#039;&#039;&#039; (aka Arrays)&amp;lt;br&amp;gt;&lt;br /&gt;
*uchar* &#039;&#039;&#039;bytesValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the byteArray value at the pin as a c-unsigned char*. Raises an error if the pin did not receive a value, or if the value was not a byteArray or C-struct. This can also be used to receive other bulk data, such as an int32 or float array. For example, by converting a collection of numbers first to a byteArray, and then casting the bytesValue to another pointer type in the bridge code. Use arraySize to get the number of bytes in the byte[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request. If you need to keep it (for whatever reason), it must be copied to a static or another malloc&#039;d memory area.&lt;br /&gt;
&lt;br /&gt;
*ushort* &#039;&#039;&#039;shortsValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the shortArray value at the pin as a c-unsigned short*. Raises an error if the pin did not receive a value, or if the value was not an array. Use arraySize to get the number of shorts in the short[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request.&lt;br /&gt;
&lt;br /&gt;
*uint* &#039;&#039;&#039;intsValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the intArray value at the pin as a c-unsigned int*. Raises an error if the pin did not receive a value, or if the value was not an array. Use arraySize to get the number of ints in the int[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request.&lt;br /&gt;
&lt;br /&gt;
*float* &#039;&#039;&#039;floatsValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the floatArray value at the pin as a c-float*. Raises an error if the pin did not receive a value, or if the value was not an array. Use arraySize to get the number of floats in the float[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request.&lt;br /&gt;
&lt;br /&gt;
*double* &#039;&#039;&#039;doublesValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the doubleArray value at the pin as a c-double*. Raises an error if the pin did not receive a value, or if the value was not an array. Use arraySize to get the number of doubles in the double[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
*void* &#039;&#039;&#039;pointerValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pointer value at the pin as a void*. This must be a pointer which has been previously sent to expecco via putPointer(). Raises an error if the pin did not receive a value, or if the value was not a pointer. This means, that it must be a pointer as previously sent to expecco with putPointer. Please read the description of &amp;quot;putPointer()&amp;quot; below.&lt;br /&gt;
&lt;br /&gt;
*jsonObject &#039;&#039;&#039;jsonValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the value at the pin as a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]]. Raises an error if the pin did not receive a value.&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]The returned pointer becomes invalid after the action&#039;s execution; field values should therefore be extracted and copied if needed later (i.e. do not keep a reference to it or its components).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queries&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
*int &#039;&#039;&#039;arraySize&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the number of array elements, if there is a byte-, short-, int-, float- or double-Array at the pin. Raises an error if the pin did not receive a value, or if the value was not an array or C-struct.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Values with Default&#039;&#039;&#039;&lt;br /&gt;
*char* &#039;&#039;&#039;stringValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, char* &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;stringValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception. The returned pointer becomes invalid after the action&#039;s execution.&lt;br /&gt;
&lt;br /&gt;
*long &#039;&#039;&#039;longValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, long &#039;&#039;repl&#039;&#039;) (vsn24.1, 64bit)&amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;longValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*longlong &#039;&#039;&#039;longLongValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, longlong &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;longLongValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&amp;lt;br&amp;gt;This API is only avalable in 64bit versions of the C-bridge (i.e. not in the cBridge32.exe for Windows) and only with expecco vsn 24.1 and later.&lt;br /&gt;
&lt;br /&gt;
*double &#039;&#039;&#039;doubleValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, double &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;doubleValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*bool_t &#039;&#039;&#039;booleanValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, bool_t &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;booleanValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*uchar* &#039;&#039;&#039;bytesValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, uchar* &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;bytesValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*jsonObject &#039;&#039;&#039;jsonValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, jsonObject &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin-datum as a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]] if it has one, &#039;&#039;repl&#039;&#039;  otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;jsonValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception. The returned pointer becomes invalid after the action&#039;s execution.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*char* &#039;&#039;&#039;stringValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, an empty string otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;stringValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception. The returned pointer becomes invalid after the action&#039;s execution.&lt;br /&gt;
&lt;br /&gt;
*long &#039;&#039;&#039;longValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, 0 (zero) otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;longValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*longlong &#039;&#039;&#039;longLongValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) (vsn24.1, 64bit)&amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, 0 (zero) otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;longLongValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&amp;lt;br&amp;gt;This API is only avalable in 64bit versions of the C-bridge (i.e. not in the cBridge32.exe for Windows) and only with expecco vsn 24.1 and later.&lt;br /&gt;
&lt;br /&gt;
*double &#039;&#039;&#039;doubleValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, 0.0 (zero) otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;doubleValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*bool_t &#039;&#039;&#039;booleanValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, 0 (false) otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;booleanValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*uchar* &#039;&#039;&#039;bytesValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, NULL otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;bytesValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*jsonObject &#039;&#039;&#039;jsonValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin-datum as a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]] if it has one, NULL otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;jsonValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception. The returned pointer becomes invalid after the action&#039;s execution.&lt;br /&gt;
&lt;br /&gt;
Variable number of input/output pins are not supported. You should pass an array or structure if required.&lt;br /&gt;
&lt;br /&gt;
===== Output Pins (C) =====&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putString&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, char* &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a string to the output pin. The string must be zero-terminated.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putStringN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, char* &#039;&#039;data&#039;&#039;, int &#039;&#039;len&#039;&#039;) &amp;lt;br&amp;gt;Writes len bytes of a string to the output pin.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putLong&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, long &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a long to the output pin.&amp;lt;br&amp;gt;Be aware that the size of a long depends on the cbridge host&#039;s CPU architecture, the OS and the C-compiler: on Unix machines, it is typically an int64, whereas on Windows it is usually an int32.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putULong&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned long &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes an unsigned long to the output pin.&amp;lt;br&amp;gt;Be aware that the size of an unsigned long depends on the cbridge host&#039;s CPU architecture, the OS and the C-compiler: on Unix machines, it is typically an uint64, whereas on Windows it is usually an uint32.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putLongLong&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, long long &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a long long to the output pin. Typically, a long long is an int64 on all architectures.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putULongLong&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned long long &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes an unsigned long long to the output pin. Typically, an unsigned long long is an uint64 on all architectures (depends on cbridge host&#039;s CPU, OS and compiler). This API is not available in the 32 bit cBridge version.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putDouble&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, double &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a double (float64) to the output pin.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putBoolean&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, bool_t &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a boolean to the output pin. Anything but 0 (zero) is interpreted as true.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putJsonObject&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, jsonObject &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]] to the output pin. Refer to [[Embedded_Systems_C_Bridge_API#JSON_Library | the JSON library documentation]] on how to create a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]].&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putBytesN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned char* &#039;&#039;bytes&#039;&#039;, int &#039;&#039;nBytes&#039;&#039;) &amp;lt;br&amp;gt;Writes nBytes from a byte array to the output pin.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putPointer&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, void* &#039;&#039;dataPtr&#039;&#039;) &amp;lt;br&amp;gt;Writes a reference for dataPtr to the output pin. This value can be passed to another cBridge action (executed on the same bridge), where it can be read from the input with &amp;lt;code&amp;gt;pointerValue()&amp;lt;/code&amp;gt; (this is similar to the makeRef mechanism of other bridged languages).&lt;br /&gt;
&lt;br /&gt;
The following API will be available with the 21.2 release:&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putDoublesN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, double*  &#039;&#039;doubles&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count double values as a vector to the output pin. expecco will receive these values as a collection of double precision floating point values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putFloatsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, float*  &#039;&#039;floats&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count float values as a vector to the output pin. expecco will receive these values as a collection of single precision floating point values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putIntsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, int*  &#039;&#039;ints&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count int values as a vector to the output pin. expecco will receive these values as a collection of integer values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putLongsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, long*  &#039;&#039;longs&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count long values as a vector to the output pin. expecco will receive these values as a collection of integer values.&amp;lt;br&amp;gt;Be reminded that the sizeof longs may be different between Windows and non-Windows machines.&lt;br /&gt;
&lt;br /&gt;
These vectors will appear at the output pin as a collection; the type of collection is given by the pin&#039;s datatype. For most space efficient representation, we recommend the use of the bulk data types (FloatArray, DoubleArray, etc.)&lt;br /&gt;
&lt;br /&gt;
The following API will be available with the 21.2.1 update release:&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putShortsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, short*  &#039;&#039;longs&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count (signed) short values as a vector to the output pin. expecco will receive these values as a collection of integer values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putUIntsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned int*  &#039;&#039;ints&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count unsigned int values as a vector to the output pin. expecco will receive these values as a collection of integer values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putULongsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned long*  &#039;&#039;longs&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count unsigned long values as a vector to the output pin. expecco will receive these values as a collection of integer values.&amp;lt;br&amp;gt;Be reminded that the sizeof longs may be different between Windows and non-Windows machines.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putUShortsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned short*  &#039;&#039;longs&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count unsigned short values as a vector to the output pin. expecco will receive these values as a collection of integer values.&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (C) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from C code (as pseudo variables).&lt;br /&gt;
However, only a very limited subset of operations is supported (in the following, &#039;&#039;stream&#039;&#039; stands for one of the above wellknown expecco streams and is given as argument to the function):&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;cr&#039;&#039;&#039; (&#039;&#039;stream&#039;&#039;)&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;stream&#039;&#039;, char* &#039;&#039;fmt&#039;&#039;, ...)&amp;lt;br&amp;gt;Adds a textual representation of the argument. The argument is printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;stream&#039;&#039;, char* &#039;&#039;fmt&#039;&#039;, ...)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
If the bridge was started by expecco (as opposed to being executed on a remote host), stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Thus, you can use &amp;quot;&amp;lt;code&amp;gt;fprintf(stdout, ...)&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;fprintf(stderr, ...)&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;showCR(Transcript, ...)&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Additional Utility Functions (C) ====&lt;br /&gt;
&lt;br /&gt;
*char* &#039;&#039;&#039;getTmpDirectory&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Returns a pointer to the pathname of the temp directory.&lt;br /&gt;
&lt;br /&gt;
*char* &#039;&#039;&#039;getenv&#039;&#039;&#039; (char* &#039;&#039;varName&#039;&#039;)&amp;lt;br&amp;gt;Returns a pointer to the shell variable&#039;s value.&lt;br /&gt;
&lt;br /&gt;
*int &#039;&#039;&#039;setenv&#039;&#039;&#039; (char* &#039;&#039;varName&#039;&#039;, char* &#039;&#039;value&#039;&#039;)&amp;lt;br&amp;gt;Set the shell variable&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Referring to Functions in Shared Libraries ===&lt;br /&gt;
&lt;br /&gt;
If the cBridge code refers to any functions which are located in additional shared libraries (DLLs), the bridge needs to know where to find those.&lt;br /&gt;
&lt;br /&gt;
The location of any shared library must be specified in the C-bridge settings dialog, unless the library is found in the CBridge executable&#039;s folder or at a standard place (eg. &amp;quot;/usr/lib&amp;quot;, &amp;quot;/usr/local/lib&amp;quot;, etc. on Unix and &amp;quot;C:\Windows&amp;quot; and others on Windows).&lt;br /&gt;
The details depend on the OperatingSystem; Windows searches along the PATH setting, linux along LD_LIBRARY_PATH. If in doubt, consult your OS documentation.&lt;br /&gt;
&lt;br /&gt;
Navigate to &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and add the path to the &amp;quot;DLL Path&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
As an alternative, edit the CC-Script and add appropriate command line arguments to the linker command near the end (it is recommended to keep the original, and make an edited copy).&lt;br /&gt;
&lt;br /&gt;
You&#039;ll also have to edit the script, if additional compiler or linkage arguments are required, or if you have to determine the location of additional frameworks dynamically.&lt;br /&gt;
&lt;br /&gt;
=== Referring to Types Defined in expecco ===&lt;br /&gt;
&lt;br /&gt;
User defined struct, union and enum &amp;quot;CType (C-Defined)&amp;quot; dataypes (which are declared in expecco and present in the suite&#039;s element tree) are visible inside the activity code, and can be included as:&lt;br /&gt;
 #include &amp;quot;expecco/Types/XXX.h&amp;quot;&lt;br /&gt;
where &amp;quot;XXX&amp;quot; is the name of the expecco type (in the tree).&lt;br /&gt;
If the type declares an unnamed struct, the type will be known as a typedef in the C-code. &lt;br /&gt;
==== Typedef Name vs. struct/union Name ====&lt;br /&gt;
If the type is named &amp;quot;myStruct&amp;quot; and defined as:&lt;br /&gt;
 struct {&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
it should be referred to in the C-code as:&lt;br /&gt;
 myStruct s, *sP;&lt;br /&gt;
In this case, the name of the typedef is the name of the type.&lt;br /&gt;
&lt;br /&gt;
In contrast, if it was defined as:&lt;br /&gt;
 struct foo {&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
you can also write:&lt;br /&gt;
 struct foo s;&lt;br /&gt;
 struct foo *sP; &lt;br /&gt;
In other words, there will be a typedef for &amp;quot;myStruct&amp;quot; (the name of the type) and a struct by the name as in the type&#039;s definition.&lt;br /&gt;
&lt;br /&gt;
Notice, that these files do actually not exist; instead, the activity&#039;s C-code is scanned and dynamically expanded to include those definitions. See example below.&lt;br /&gt;
You should shutdown any already running bridge, when a type is changed, to enforce a recompilation of the C code.&lt;br /&gt;
&lt;br /&gt;
=== Including Attachments as Header Files ===&lt;br /&gt;
&lt;br /&gt;
Attached files can be included as:&lt;br /&gt;
 #include &amp;quot;expecco/Attachments/XXX.h&amp;quot;&lt;br /&gt;
where &amp;quot;XXX.h&amp;quot; is the name of the expecco attachment file.&lt;br /&gt;
&amp;lt;br&amp;gt;Be reminded that the name of the attachment itself (the tree-item name) is not required to be the same as the name of the file, although usually, they are.&lt;br /&gt;
&lt;br /&gt;
=== C++ Interfaces ===&lt;br /&gt;
C++ functions should be called indirectly via a C function wrapper (i.e. &amp;lt;code&amp;gt;extern &amp;quot;C&amp;quot;&amp;lt;/code&amp;gt;). &lt;br /&gt;
&amp;lt;br&amp;gt;Object references can be passed from the bridge to expecco and back via the &amp;quot;&amp;lt;code&amp;gt;putPointer&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;pointerValue&amp;lt;/code&amp;gt;&amp;quot; functions.&lt;br /&gt;
&lt;br /&gt;
=== Running Bridged C-Code on a Remote Computer ===&lt;br /&gt;
&lt;br /&gt;
The remote computer must have the cBridge executable running.&lt;br /&gt;
The executable is found in the &amp;quot;&amp;lt;code&amp;gt;packages/bridgeFramework/cBridge/cLibrary&amp;lt;/code&amp;gt;&amp;quot; folder under your expecco installation folder and should be copied to the remote machine. Windows users will find both a 64bit version (&amp;quot;cBridge.exe&amp;quot;) and a 32bit one (&amp;quot;cBrige32.exe&amp;quot;). If your C-code needs or refers to any existing dll, make sure that the correct bridge is configured in the settings (a 32bit bridge will not be able to load a 64bit dll and vice versa).  &lt;br /&gt;
&lt;br /&gt;
On the expecco side, you have two options:&lt;br /&gt;
# specify that the bridge is already running in the settings; then all cBridge actions which have not been explicitly given a bridge to execute in will be executed there&lt;br /&gt;
# explicitly connect to a running bridge via the &amp;quot;&#039;&#039;Connect to Running Bridge&#039;&#039;&amp;quot; action block, and passing the resulting bridge handle to the C-action.&lt;br /&gt;
The handle can be passed either explicitly via the step&#039;s cBridge input pin, or implicitly by declaring a variable named &amp;quot;CBRIDGE&amp;quot; and storing the handle there. The cBridge input pin is generated via the step&#039;s &#039;&#039;Special Pins&#039;&#039; menu.&lt;br /&gt;
&lt;br /&gt;
Bridges can be started either by one of the bridge start actions in the standard library or by a batch-, shell- or powershell script. Type &amp;quot;&amp;lt;code&amp;gt;cBridge --help&amp;lt;/code&amp;gt;&amp;quot; for command line options.&lt;br /&gt;
&lt;br /&gt;
You can have multiple bridges running, even in heterogenous networks (i.e. call for a remote C-action on a Windows machine, while running expecco on a Linux machine). &lt;br /&gt;
We provide bridge executables for additional architectures (eg. Raspberry-PI) upon request and for a small additional fee.&lt;br /&gt;
&lt;br /&gt;
=== Running Multiple Bridges in Parallel ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can start multiple bridges via the &amp;quot;[Start new local CBridge]&amp;quot; action from the standard library and remember the bridge connection handles in variables.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:Setup.png|300px]]&amp;lt;br&amp;gt;Make sure, that the bridges are using different ports.&lt;br /&gt;
&lt;br /&gt;
In addition, add a bridge input pin to the action(s) which you want to execute on one of those bridges (via the &amp;quot;Special Pins&amp;quot; popup menu in the action&#039;s schema).&amp;lt;br&amp;gt;[[Datei:ShowTempDir.png|300px]]&amp;lt;br&amp;gt;&lt;br /&gt;
For example, the following simply sends a message to the standard error:&lt;br /&gt;
 static void&lt;br /&gt;
 execute() {&lt;br /&gt;
    char buffer[128];&lt;br /&gt;
 &lt;br /&gt;
    snprintf(buffer, sizeof(buffer), &amp;quot;%s&amp;quot;, getTmpDirectory());&lt;br /&gt;
    putString(output, buffer);&lt;br /&gt;
 }&lt;br /&gt;
and finally, here is an example which executes this action in parallel on&lt;br /&gt;
4 bridges:&amp;lt;br&amp;gt;[[Datei:FourActions.png|300px]].&lt;br /&gt;
&lt;br /&gt;
=== Bulk Data ===&lt;br /&gt;
&lt;br /&gt;
If a huge number of data elements (known as &amp;quot;&#039;&#039;Bulk Data&#039;&#039;&amp;quot;) are to be transferred, transmission times may get much longer than the actual execution time of the action (keep in mind that the communication times take most of the time if the executed computation is simple).&lt;br /&gt;
&lt;br /&gt;
There are multiple possible ways to deal with this situation:&lt;br /&gt;
&lt;br /&gt;
* Passing a Pointer to expecco&lt;br /&gt;
:if you can leave the data inside the bridge (eg. as malloc&#039;d data vector), &#039;&#039;&#039;and&#039;&#039;&#039; expecco does not need to access the elements of the vector, you can leave the data inside the cBridge and only pass a handle to expecco. This handle may later be sent to another C-action to process the data at non-critical times (eg. at the end of the test).&lt;br /&gt;
:This mechanism is the fastest because only a small handle (typically 32/64 bits) has to be transmitted to expecco. However, it degrades to become very very slow if you access individual elements of the vector from expecco, as this will result in one IPC roundtrip per accessed element.&lt;br /&gt;
* Passing Bulk Data as a Vector&lt;br /&gt;
:If each vector element is sent individually to an output pin (i.e. in a loop with putFloat()/putDouble()), one IPC roundtrip will be performed per element. &lt;br /&gt;
:It is much faster to send the whole vector data sent as one array via putDoublesN(), putFloatsN() or putIntsN(). This still does introduce some additional cost due to JSON-encoding (on the cBridge side) and JSON-decoding on the expecco side, but the effective transmission time is dramatically reduced.&lt;br /&gt;
* Passing Bulk Data as a ByteArray&lt;br /&gt;
:Further speedup is possible by not sending the data as a number vector, but instead as a byte vector, actually sending the raw ended bytes from the bridge to expecco. For this, use a putBytesN() call and case your bulk data to a &amp;quot;char *&amp;quot;.&lt;br /&gt;
:However (big warning): expecco will receive a byte-vector and you will have to add code to extract the relevant elements from this. If the cBridge CPU and the expecco-CPU use a different byte order or a different floating-point-number representations, you will have to deal with that in that extraction code. Be aware, that it may even depend on the compiler: Microsoft VisualC compilers for x86_64 interpret &amp;quot;long&amp;quot; as a 32bit integer, whereas most other compilers/systems treat them as 64bit integers.&amp;lt;br&amp;gt;&lt;br /&gt;
:This is probably the fastest method to transmit bytes, but comes with those possible pitfalls. We therefore recommend to try the &amp;quot;Bulk Data as Vector&amp;quot; method first. In most situations that is either within the acceptable timing constraints, or too far off, such that the ByteArray transmission will also not be fast enough, and you should use the pointer passing method anyway.&lt;br /&gt;
&lt;br /&gt;
If the cBridge runs on the same machine as expecco, shared memory will be used to exchange bulk data. This may reduce the transmission times drastically, depending on the amount of data (there are still other messages exchanged via the socket communication).&lt;br /&gt;
&lt;br /&gt;
=== Example1: Writing and Calling C Code in Expecco ===&lt;br /&gt;
&lt;br /&gt;
In this example, numbers and a string will be passed to a C action block.&amp;lt;br&amp;gt;The action has been defined with 3 input pins:&lt;br /&gt;
* &amp;lt;code&amp;gt;in1&amp;lt;/code&amp;gt; (type Float)&lt;br /&gt;
* &amp;lt;code&amp;gt;in2&amp;lt;/code&amp;gt; (type Integer)&lt;br /&gt;
* &amp;lt;code&amp;gt;in3&amp;lt;/code&amp;gt; (type String)&lt;br /&gt;
and the single output &amp;quot;&amp;lt;code&amp;gt;out1&amp;lt;/code&amp;gt;&amp;quot;, with type String.&lt;br /&gt;
&lt;br /&gt;
The code will generate a string by concatenating the printf strings of its arguments at the output&lt;br /&gt;
and also print a number of messages via different output channels.&lt;br /&gt;
&lt;br /&gt;
Create a new bridged C action,&amp;lt;br&amp;gt; &lt;br /&gt;
[[Datei:CBridge Demo Action1.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;and enter the code:&lt;br /&gt;
 &lt;br /&gt;
 static void&lt;br /&gt;
 execute() {&lt;br /&gt;
    double dVal = &#039;&#039;&#039;doubleValue&#039;&#039;&#039;(in1); &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// fetch input pin&#039;s double value&amp;lt;/span&amp;gt;&lt;br /&gt;
    long lVal   = &#039;&#039;&#039;longValue&#039;&#039;&#039;(in2);   &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// fetch input pin&#039;s integer value&amp;lt;/span&amp;gt;&lt;br /&gt;
    char* sVal  = &#039;&#039;&#039;stringValue&#039;&#039;&#039;(in3); &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// fetch input pin&#039;s string value&amp;lt;/span&amp;gt;&lt;br /&gt;
    char buffer[512];&lt;br /&gt;
 &lt;br /&gt;
    snprintf(buffer, sizeof(buffer), &amp;quot;%s / %ld / %g&amp;quot;, sVal, lVal, dVal);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// write to output pin&amp;lt;/span&amp;gt;&lt;br /&gt;
    &#039;&#039;&#039;putString&#039;&#039;&#039;(out1, buffer);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// a regular print&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// (will be shown inside expecco&#039;s Transcript, if io-trace is enabled)&amp;lt;/span&amp;gt;&lt;br /&gt;
    fprintf(stderr, &amp;quot;hello on stderr from C-Code!\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// another regular print&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// (will be shown inside expecco&#039;s Transcript, if io-trace is enabled)&amp;lt;/span&amp;gt;&lt;br /&gt;
    fprintf(stdout, &amp;quot;hello on stdout from C-Code!\n&amp;quot;);&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// explicit output to expecco&#039;s Transcript&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// explicit output to expecco&#039;s stdout&amp;lt;/span&amp;gt;&lt;br /&gt;
    &#039;&#039;&#039;show&#039;&#039;&#039;(Stdout, &amp;quot;hello on expecco&#039;s stdout from C-Code!\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// explicit output to expecco&#039;s stderr&amp;lt;/span&amp;gt;&lt;br /&gt;
    &#039;&#039;&#039;show&#039;&#039;&#039;(Stderr, &amp;quot;hello on expecco&#039;s stderr from C-Code!\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// explicit output to expecco&#039;s Transcript&amp;lt;/span&amp;gt;&lt;br /&gt;
    &#039;&#039;&#039;show&#039;&#039;&#039;(Transcript, &amp;quot;another hello from C-Code!\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// possibly report failure to expecco&amp;lt;/span&amp;gt;&lt;br /&gt;
    if (strlen(sVal) &amp;lt; 20) {&lt;br /&gt;
        &#039;&#039;&#039;fail&#039;&#039;&#039;(&amp;quot;short string \&amp;quot;%s\&amp;quot; (length=%d)&amp;quot;, sVal, strlen(sVal))&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Example2: Passing Complex Objects to and from C-Code (by value) ===&lt;br /&gt;
&lt;br /&gt;
Complex struct objects can be passed by value to the C-code by defining a CStruct type&lt;br /&gt;
i.e. create a new type named eg. &amp;quot;myStruct&amp;quot; in the tree, define it as C-Type and enter a definition similar to:&lt;br /&gt;
&lt;br /&gt;
 /* C: */&lt;br /&gt;
 struct {&lt;br /&gt;
    int i1;&lt;br /&gt;
    float f1;&lt;br /&gt;
    double d1;&lt;br /&gt;
    char c[20];&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
then, add an input pin with that datatype to the C-action,&lt;br /&gt;
and add the following line to the action&#039;s C-code, to include the type&#039;s definition:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;expecco/Types/myStruct.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(the name of the include must match the type&#039;s typename in the tree)&lt;br /&gt;
&lt;br /&gt;
From within your C-code, access the fields with:&lt;br /&gt;
&lt;br /&gt;
 struct myStruct* p;&lt;br /&gt;
 &lt;br /&gt;
 p = (struct myStruct*)&#039;&#039;&#039;bytesValue&#039;&#039;&#039;(inPin);&lt;br /&gt;
 &lt;br /&gt;
 fprintf(stderr, &amp;quot;got i1:%d\n&amp;quot;, p-&amp;gt;i1);&lt;br /&gt;
 fprintf(stderr, &amp;quot;got f1:%f\n&amp;quot;, p-&amp;gt;f1);&lt;br /&gt;
 fprintf(stderr, &amp;quot;got d1:%F\n&amp;quot;, p-&amp;gt;d1);&lt;br /&gt;
 fprintf(stderr, &amp;quot;got c:%s\n&amp;quot;, p-&amp;gt;c);&lt;br /&gt;
&lt;br /&gt;
and write such a struct to an output pin with:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;putBytesN&#039;&#039;&#039;(outPin, p, sizeof(struct myStruct));&lt;br /&gt;
&lt;br /&gt;
To create such a struct argument, use an instance creation action block (and possibly additional field setter actions).&lt;br /&gt;
Those can be automatically generated by selecting the type in the tree,&lt;br /&gt;
and invoking the popup menu function &amp;quot;&#039;&#039;Refactoring&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Generate&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Creators and Accessors&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Example3: Passing Handles/Pointers to expecco and Back to Another C Action ===&lt;br /&gt;
&lt;br /&gt;
A common situation is when two C actions are given, where one generates a handle (i.e. pointer),&lt;br /&gt;
which must be passed to the other action (in the same bridge). &lt;br /&gt;
&amp;lt;br&amp;gt;For example, the first may be a &amp;quot;&amp;lt;code&amp;gt;createConnection()&amp;lt;/code&amp;gt;&amp;quot; function,&lt;br /&gt;
and the second needs that connection handle as argument (that would typically be a kind of &amp;quot;&amp;lt;code&amp;gt;send()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;receive()&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;close()&amp;lt;/code&amp;gt;&amp;quot; function, and the handle something like a FILE pointer or Windows handle).&lt;br /&gt;
&lt;br /&gt;
For this scenario, the cBridge provides a mechanism similar to the &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; facility of other bridges.&lt;br /&gt;
The first action function will send the handle to an output pin via &amp;quot;&amp;lt;code&amp;gt;putPointer()&amp;lt;/code&amp;gt;&amp;quot;;&lt;br /&gt;
the pin&#039;s datatype should be &amp;quot;&amp;lt;code&amp;gt;Any&amp;lt;/code&amp;gt;&amp;quot;,  &amp;quot;&amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;&amp;quot; or a struct type as described above:&lt;br /&gt;
&lt;br /&gt;
 void execute() {&lt;br /&gt;
     ...&lt;br /&gt;
     &#039;&#039;&#039;putPointer&#039;&#039;&#039;( outPin, (void*) handle );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
and the other action functions can get this handle from an input pin:&lt;br /&gt;
&lt;br /&gt;
 void execute() {&lt;br /&gt;
     handle = &#039;&#039;&#039;pointerValue&#039;&#039;&#039;( inPin );&lt;br /&gt;
     ...&lt;br /&gt;
&lt;br /&gt;
=== Example4: Passing Bulk Data to expecco and to another C Action ===&lt;br /&gt;
&lt;br /&gt;
In this example, one generates some data (eg. a vector of float values),&lt;br /&gt;
and passes this to another C action (possibly in another bridge). &lt;br /&gt;
&amp;lt;br&amp;gt;For example, the first may be a measurement value collector,&lt;br /&gt;
and the second computes some statistical analysis.&lt;br /&gt;
Be aware, that this example was created for demnstration; in practice, you would probably pass a pointer within the same bridge. But the example is also useful if one of those actions is a non-C action, for example a Python numpy action.&lt;br /&gt;
&lt;br /&gt;
The first action function generates some data and sends them to an output pin.&lt;br /&gt;
The pin&#039;s datatype should be &amp;quot;&amp;lt;code&amp;gt;float*&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;FloatArray&amp;lt;/code&amp;gt;&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 #define NUM_FLOATS 1024 // or whatever&lt;br /&gt;
 void execute() {&lt;br /&gt;
     float data[NUM_FLOATS];&lt;br /&gt;
     ...&lt;br /&gt;
     // compute or generate the data&lt;br /&gt;
     for (i=0; i&amp;lt;NUM_FLOATS; i++) {&lt;br /&gt;
         data[i] = ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     // send it to the output pin  &lt;br /&gt;
     &#039;&#039;&#039;putFloatsN&#039;&#039;&#039;( outPin, data, NUM_FLOATS );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the receiving action can get this data from an input pin (also with type &amp;quot;&amp;lt;code&amp;gt;float*&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;FloatArray&amp;lt;/code&amp;gt;&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 void execute() {&lt;br /&gt;
     float* data;&lt;br /&gt;
     int numElements;&lt;br /&gt;
&lt;br /&gt;
     // receive from an input pin &lt;br /&gt;
     // always verify the size! &lt;br /&gt;
     // The data could have been created by any action with any size!&lt;br /&gt;
     data = &#039;&#039;&#039;floatsValue&#039;&#039;&#039;( inPin );&lt;br /&gt;
     numElements = &#039;&#039;&#039;arraySize&#039;&#039;&#039;( inPin );&lt;br /&gt;
     ...&lt;br /&gt;
     // processing&lt;br /&gt;
     for (i=0; i&amp;lt;numElements; i++) {&lt;br /&gt;
         ... do something with data[i] ....&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Bridged Smalltalk Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
The following works in 20.1 and above.&amp;lt;br&amp;gt;&lt;br /&gt;
Similar to the above described bridged Node and bridged Python actions, these actions are coded in the Smalltalk language and executed by a separate Smalltalk engine (separate process). Both local and remote execution are possible.&lt;br /&gt;
&lt;br /&gt;
By the time of writing, bridged Smalltalk actions can be executed in an ST/X Smalltalk engine, support for VA-Smalltalk and VW-Smalltalk is being developed and will be available in one of the next expecco releases.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Bridged Smalltalk Code API ===&lt;br /&gt;
&lt;br /&gt;
Note: This is a preliminary API documentation. &lt;br /&gt;
Bridged Smalltalk elementary actions are still being developed and the API may change slightly until officially released.&lt;br /&gt;
&lt;br /&gt;
Bridged Smalltalk actions will execute in another Smalltalk system; by the time of writing, this may be another Smalltalk/X or a VisualWorks Smalltalk system. With enough customer interest, other dialects (VisualAge and Squeak) may be supported in the future.&lt;br /&gt;
 &lt;br /&gt;
The API looks similar to the API of regular Smalltalk actions, which execute inside expecco itself.&lt;br /&gt;
However, for some objects, only a subset of the protocol is available.&lt;br /&gt;
&lt;br /&gt;
==== Variables (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed code:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display messages in the expecco Transcript window (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy supports a few functions to display messages on expecco&#039;s stdout stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy supports a few functions to display messages on expecco&#039;s stderr stream (see below)&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&amp;lt;code&amp;gt;bridge&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;the bridge object which handles the communication with expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ] &amp;lt;br&amp;gt;Report a defect (in the test). Up to 4 optional with:-args are sliced into the string, if it contains &amp;quot;%i&amp;quot; placeholders. Stops execution. &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ]  &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ]  &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ] &amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ] &amp;lt;br&amp;gt;Finishes the current testCase with success.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logging (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logFail&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039; &amp;lt;br&amp;gt;Adds a fail message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039; &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039; &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039; &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039;&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039;&amp;lt;br&amp;gt;Same as &#039;&#039;alert:&#039;&#039; (for JavaScript compatibility).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Environment Access (Bridged Smalltalk) ====&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;);&amp;lt;br&amp;gt;Fetches and returns a value from the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from remote smalltalk actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAtPut&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;, &amp;amp;lt;newValue&amp;amp;gt;);&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;The variable must be writable.&amp;lt;br&amp;gt;You can only write simple objects (numbers, booleans and strings) from remote smalltalk actions.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Input Pins (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;hasValue&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;value&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the value of the pin. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039;:&#039;&#039;alternativeValue&#039;&#039; &amp;lt;br&amp;gt;Returns the value of a pin or the value from alternativeValue if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;valueIfPresent&#039;&#039;&#039; &amp;lt;br&amp;gt;Returns the value of a pin or nil if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;isConnected&#039;&#039;&#039; &amp;lt;br&amp;gt;Returns true if the pin has a connection&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Output Pins (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;value&#039;&#039;&#039;:&#039;&#039;someValue&#039;&#039;&amp;lt;br&amp;gt;Writes the value to the pin. Only simple object can be transferred by value (nil, booleans, integers, floats, strings).&amp;lt;br&amp;gt;Anything else should be passed by reference (see makeRef below).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from remote Smalltalk images. &lt;br /&gt;
However, only a limited subset of messages is supported:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039;:&#039;&#039;arg&#039;&#039;&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039;:&#039;&#039;arg&#039;&#039;&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutAll&#039;&#039;&#039;:&#039;&#039;string&#039;&#039;&amp;lt;br&amp;gt;String writing&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutLine&#039;&#039;&#039;:&#039;&#039;string&#039;&#039;&amp;lt;br&amp;gt;String printing with cr&lt;br /&gt;
&lt;br /&gt;
In addition, stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Passing Objects by Reference (Bridged Smalltalk) ====&lt;br /&gt;
By default, objects written to output pins via &amp;quot;&#039;&#039;&#039;value:&#039;&#039;&#039;&amp;quot; will be marshalled to JSON, transferred to expecco and decoded there.&lt;br /&gt;
Effectively, a copy of the object is created, which looses its identity when sent back later to the remote smalltalk in another action.&lt;br /&gt;
This would make it impossible to get handles from a remote action, which is to be sent to another action on the same remote machine.&lt;br /&gt;
The &amp;quot;makeRef&amp;quot; method solves this.&lt;br /&gt;
 &lt;br /&gt;
*&#039;&#039;self&#039;&#039; &#039;&#039;&#039;makeRef&#039;&#039;&#039;:&#039;&#039;object&#039;&#039;&amp;lt;br&amp;gt;creates a reference object, which can be written to a pin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;self&#039;&#039; &#039;&#039;&#039;makeRef&#039;&#039;&#039;:&#039;&#039;object&#039;&#039; &#039;&#039;&#039;name&#039;&#039;&#039;:&#039;&#039;aString&#039;&#039;&amp;lt;br&amp;gt;ditto, but gives it a user friendly name (eg. for the expecco log)&lt;br /&gt;
&lt;br /&gt;
I.e. to write a reference to a pin, use:&lt;br /&gt;
 &#039;&#039;somePin&#039;&#039; &#039;&#039;&#039;value&#039;&#039;&#039;:(self &#039;&#039;&#039;makeRef&#039;&#039;&#039;:&#039;&#039;someObject&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== Additional Information on Bridged VisualWorks Smalltalk Actions ===&lt;br /&gt;
&lt;br /&gt;
Inside bridged VisualWorks actions, the above described &amp;quot;Transcript&amp;quot; refers to the expecco Transcript; not the VisualWorks Transcript (the remote code is compiled inside an environment, where the Transcript variable has been redefined).&lt;br /&gt;
&lt;br /&gt;
To send output to the VisualWorks Transcript, use &amp;quot;Smalltalk.Core.Transcript&amp;quot;, as in:&lt;br /&gt;
 ...&lt;br /&gt;
 Smalltalk.Core.Transcript show:&#039;Hello on VW Transcript&#039;; cr&lt;br /&gt;
 ...&lt;br /&gt;
 Transcript show:&#039;Hello on expecco Transcript&#039;; cr&lt;br /&gt;
 ...&lt;br /&gt;
 Be aware, that the VW Transcript does not understand the &amp;quot;showCR:&amp;quot; message; you need &amp;quot;show:&amp;quot; followed by &amp;quot;cr&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Bridged Ruby Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a preliminary API documentation. &lt;br /&gt;
Bridged Ruby elementary actions are still being developed and the API may change slightly until officially released.&lt;br /&gt;
&lt;br /&gt;
Bridged Ruby actions will execute in a Ruby interpreter.&lt;br /&gt;
 &lt;br /&gt;
The API looks similar to the API of regular actions, which execute inside expecco itself or another language interpreter.&lt;br /&gt;
However, due to Ruby language specifics, some differences are noticable.&lt;br /&gt;
&lt;br /&gt;
==== Variables (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed code&amp;lt;br&amp;gt;(notice the &amp;quot;$&amp;quot; prefix; Ruby requires global variables to be prefixed by a &amp;quot;$&amp;quot; character):&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;$Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display messages in the expecco Transcript window (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; $Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display messages on expecco&#039;s stdout stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; $Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display messages on expecco&#039;s stderr stream (see below)&lt;br /&gt;
&amp;lt;!-- *&amp;lt;code&amp;gt; $Logger&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to generate log messages using expecco&#039;s Logger stream (see below) --&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt; $Dialog&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display confirmation dialogs (see below)&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ]) &amp;lt;br&amp;gt;Report a defect (in the test). Up to 4 optional args are sliced into the string, if it contains &amp;quot;%i&amp;quot; placeholders. Stops execution. &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ])  &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ])  &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ]) &amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ]) &amp;lt;br&amp;gt;Finishes the current testCase with success.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== $Transcript, $Stderr and $Stdout (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from Ruby actions (with a $-prefix). &lt;br /&gt;
Notice, that $Stderr refers to expecco&#039;s stderr and $Stdout refers to expecco&#039;s stdout. Both may be (and usually are) different from the Ruby interpreter&#039;s STDERR/STDOUT.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039;(&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039;(&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutAll&#039;&#039;&#039;(&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;String writing&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutLine&#039;&#039;&#039;(&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;String printing with cr&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;puts&#039;&#039;&#039;(&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;String printing with cr&lt;br /&gt;
&lt;br /&gt;
In addition, stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== $Dialog (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;confirm&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a simple yes/no dialog; returns a boolean.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;request&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a simple string-input dialog; returns a string or nil if cancel was pressed.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestPassword&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;same, but the entered string is not shown on the screen&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestFilename&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;asks for a filename&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logging (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logFail&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a fail message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Same as &#039;&#039;alert:&#039;&#039; (for JavaScript compatibility).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
==== Environment Access (Bridged Ruby) ====&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;);&amp;lt;br&amp;gt;Fetches and returns a value from the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from ruby actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAtPut&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;, &amp;amp;lt;newValue&amp;amp;gt;);&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;The variable must be writable.&amp;lt;br&amp;gt;You can only write simple objects (numbers, booleans and strings) from ruby actions.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Input Pins (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;hasValue&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the value of the pin. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039;(&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the value from alternativeValue if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;valueIfPresent&#039;&#039;&#039;() &amp;lt;br&amp;gt;Returns the value of a pin or nil if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039;() &amp;lt;br&amp;gt;Returns true if the pin has a connection&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Output Pins (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039;(&#039;&#039;someValue&#039;&#039;)&amp;lt;br&amp;gt;Writes the value to the pin. Only simple object can be transferred by value (nil, booleans, integers, floats, strings).&amp;lt;br&amp;gt;Anything else should be passed by reference (see &amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt; below).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Passing Objects by Reference (Bridged Ruby) ====&lt;br /&gt;
By default, objects written to output pins via &amp;quot;&#039;&#039;&#039;value:&#039;&#039;&#039;&amp;quot; will be marshalled to JSON, transferred to expecco and decoded there.&lt;br /&gt;
Effectively, a copy of the object is created, which looses its identity when sent back later to the remote ruby in another action.&lt;br /&gt;
This would make it impossible to get a handle from a remote action, which is to be sent to another action on the same remote machine.&lt;br /&gt;
The &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; method solves this, by creating a &amp;quot;pointer&amp;quot; or &amp;quot;handle&amp;quot; to the object inside the remote machine.&lt;br /&gt;
 &lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039;(&#039;&#039;object&#039;&#039;)&amp;lt;br&amp;gt;creates a reference object, which can be written to a pin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039;(&#039;&#039;object&#039;&#039;, &#039;&#039;&#039;name&#039;&#039;&#039;)&amp;lt;br&amp;gt;ditto, but gives it a user friendly name (eg. for the expecco log)&lt;br /&gt;
:I.e. to write a reference to a pin, use:&lt;br /&gt;
::: &#039;&#039;somePin&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039;(&#039;&#039;&#039;makeRef&#039;&#039;&#039;(&#039;&#039;someObject&#039;&#039;))&lt;br /&gt;
&lt;br /&gt;
== Bridged Dart Elementary Blocks ==&lt;br /&gt;
coming with one of the next expecco versions&lt;br /&gt;
== Bridged Scheme Elementary Blocks ==&lt;br /&gt;
coming with one of the next expecco versions&lt;br /&gt;
&lt;br /&gt;
== DotNET Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Editing support for C# will be provided in a later expecco version. Currently, .NET objects must be instantiated and methods be called via the transparent message forwarning mechanism provided by Smalltalk. This means, that you use Smalltalk code to send (Smalltalk-) messages to proxy objects, which forward the call information to the corresponding bridge object.&lt;br /&gt;
&lt;br /&gt;
As an alternative, you can use bridged IronPython actions and refer to the assembly from there.&lt;br /&gt;
&lt;br /&gt;
== VisualBasic Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Support for VisualBasic Script elementary block execution is provided as an extension plugin, and requires a separate plugin license.&lt;br /&gt;
It is only available for expecco running on the MS Windows operating system.&lt;br /&gt;
&lt;br /&gt;
Code written as a VisualBasic elementary block is not executed directly by expecco. Instead, the code is forwarded to a VisualBasic scripting host which runs as another process either on the local or on a remote host. The scripting host must be a Microsoft Windows host (but expecco itself may run on any type of operating system). By using VisualBasic blocks, expecco&#039;s basic black box test functionality can be easily extended by many powerful gray- and white-box tests. Many libraries for device and equipment control, COM/DCOM and other technologies and UI interaction are possible with the VisualBasic plugin.&lt;br /&gt;
&lt;br /&gt;
Please consult the separate [[VBScript/en | VisualBasic plugin documentation]] for more detail.&lt;br /&gt;
&lt;br /&gt;
== Shell, Batch and other Script Elementary Blocks ==&lt;br /&gt;
There is no special API for those, except for pin-value expansion and stdin/stdout/stderr handling.&lt;br /&gt;
All of this is described in the [[ElementaryBlock_Element/en#Script_Action_Blocks | &amp;quot;Script Action Blocks&amp;quot; documentation]]&lt;br /&gt;
&lt;br /&gt;
== Remote expecco Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
These run on a remote expecco system, and can be used to generate load (stress) or perform additional measurements.&lt;br /&gt;
Remote expecco actions will be available in or after the 24.2 expecco version.&lt;br /&gt;
&lt;br /&gt;
--- to be documented ---&lt;br /&gt;
&lt;br /&gt;
== Tutorial: Common Tasks ==&lt;br /&gt;
&lt;br /&gt;
This chapter gives code fragments and examples for common tasks.&lt;br /&gt;
&lt;br /&gt;
The underlying Smalltalk class library contains (among others) very powerful and robust collection, stream and number representation systems, of which many functions are useful for elementary block developers. The set of usable functions is much larger than for example in Java or C standard libraries. Thus for a newcomer to Smalltalk, it is highly recommended and fruitful to read the introduction texts and/or use the class browser for a deeper understanding. You can benefit from existing code and save a lot of development time in knowing a little about your class libraries.&lt;br /&gt;
&lt;br /&gt;
Also, it is a good idea to try the sample code in a &amp;quot;workspace&amp;quot; window or within the code editor,&lt;br /&gt;
by selecting the piece of code to be tried, and performing the &amp;quot;&#039;&#039;printIt&#039;&#039;&amp;quot; menu function.&lt;br /&gt;
Thus you can quickly test&amp;amp;try code fragments without a need for an elementary block and its setup.&lt;br /&gt;
&lt;br /&gt;
Or use the [[How_to_Program/en#MethodFinder:_Find_Functions_by_Example|MethodFinder]] tool to find operations.&lt;br /&gt;
&lt;br /&gt;
=== String Handling ===&lt;br /&gt;
&lt;br /&gt;
Notice, that in Smalltalk all collection indices are 1-based. I.e. the index of the first element is 1, and the last index is the collection&#039;s size. This is the same in Mathematica, but different in C, JavaScript, Java and others.&lt;br /&gt;
Thus Smalltalk loops over collection elements should run from 1 to the collection&#039;s size, not from zero to the size minus 1. You will get an index exception, if you try.&lt;br /&gt;
&lt;br /&gt;
Also notice, that index-based enumerations (i.e. loops from 1 to the size) are actually seldom needed, due to the powerful &amp;quot;&amp;lt;code&amp;gt;do:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;collect:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;select:&amp;lt;/code&amp;gt;&amp;quot; etc. family of enumeration methods.&lt;br /&gt;
These do all the index computations for you, and are often heavily tuned for better performance.&lt;br /&gt;
&lt;br /&gt;
Also notice, that in Smalltalk, String is a subclass of Collection, and most of the functions described below are actually not implemented in the String class, but inherited from a superclass. Take this into consideration, when searching for String utility functions in the class browser (i.e. look there first or click on the &amp;quot;See Inherited Methods&amp;quot; button in the class browser [[Datei:SeeInheritedInBrowser.png]] ).&lt;br /&gt;
On the other hand, the fact that most of those functions are implemented in the Collection superclass also means, that they work on many other collections (Arrays, ByteArray, OrderedCollection, Set, Dictionary etc.).&lt;br /&gt;
&lt;br /&gt;
If you are in doubt, open a [[Tools_Notepad/en|Workspace]] window, enter a piece of code and evaluate it (using the &amp;quot;&#039;&#039;printIt&#039;&#039;&amp;quot; menu function).&lt;br /&gt;
Or open the [[How_to_Program/en#Find_Functions_by_Example|Method Finder]] to find an operation given the desired outcome.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Copying Parts of a String ====&lt;br /&gt;
&lt;br /&gt;
To extract a substring, and the index and/or count is known, use one of:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom: &#039;&#039;startIndex&#039;&#039; to: &#039;&#039;stopIndex&#039;&#039;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyTo: &#039;&#039;stopIndex&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom: &#039;&#039;startIndex&#039;&#039; count: &#039;&#039;n&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFirst: &#039;&#039;count&#039;&#039;   &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ same as copyTo:&amp;lt;/span&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyLast: &#039;&#039;count&#039;&#039;    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the last count characters&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom: &#039;&#039;startIndex&#039;&#039; butLast: &#039;&#039;count&#039;&#039; &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ copy except the last count characters&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All of the above will copy including the character at the start- and stop index.&lt;br /&gt;
I.e.&lt;br /&gt;
    &#039;hello world&#039; copyFrom:2 to:5&lt;br /&gt;
will return &#039;ello&#039;. &lt;br /&gt;
&amp;lt;br&amp;gt;[[Datei:point_right.png|20px]]This is different from some C/Java functions, which usually expect the stopIndex to be one-after the last copied element.&lt;br /&gt;
===== Search &amp;amp; Copy =====&lt;br /&gt;
to search for a character and copy up to that character&#039;s position, use:&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyUpTo: &#039;&#039;characterToSearch&#039;&#039; &lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom:&#039;&#039;startIndex&#039;&#039; upTo: &#039;&#039;characterToSearch&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can also search backward from the end (i.e. the last occurrence of a character):&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyUpToLast: &#039;&#039;characterToSearch&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Finding Elements and Substrings ====&lt;br /&gt;
&lt;br /&gt;
To search for elements of a string (which are characters), use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOf: &#039;&#039;aCharacter&#039;&#039; &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOf: &#039;&#039;aCharacter&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; lastIndexOf: &#039;&#039;aCharacter&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; lastIndexOf: &#039;&#039;aCharacter&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
to search backward from the end.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;[[Datei:point_right.png|20px]]The Smalltalk methods return a 1-based index, and 0 (zero) if not found; JavaScript methods return a 0-based index and -1 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]]Notice that a character constant is written in Smalltalk as &amp;lt;code&amp;gt;$&amp;lt;x&amp;gt;&amp;lt;/code&amp;gt;, where &amp;lt;x&amp;gt; is a printable character or a space. Non-printable characters must be specified by their name (&amp;quot;&amp;lt;code&amp;gt;Character return&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Character lf&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Character tab&amp;lt;/code&amp;gt;&amp;quot;) or their Unicode-point (decimal: &amp;quot;&amp;lt;code&amp;gt;Character value: 127&amp;lt;/code&amp;gt;&amp;quot; or hex: &amp;quot;&amp;lt;code&amp;gt;Character value: 16r1F00&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
If there are multiple characters to be searched for, pass a collection of searched characters to one of:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfAny: &#039;&#039;aBunchOfCharacters&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfAny: &#039;&#039;aBunchOfCharacters&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
&lt;br /&gt;
    &#039;hello world&#039; indexOfAny: &#039;eiou&#039; startingAt:3&lt;br /&gt;
&lt;br /&gt;
looks for the next vocal at or after position 3.&lt;br /&gt;
&lt;br /&gt;
Both receiver and argument may actually be any kind of Collection;&lt;br /&gt;
thus:&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfAny: #( $a $A $e $E )&lt;br /&gt;
&lt;br /&gt;
works the same.&lt;br /&gt;
&lt;br /&gt;
Finally, there is a very generic search function, where you can pass a test-procedure as argument:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; findFirst:[:ch | ...a boolean test on &#039;&#039;ch&#039;&#039; ...]&lt;br /&gt;
&lt;br /&gt;
will return the index of the next character for which your boolean check computes a true value.&lt;br /&gt;
For example, to search for the next digit, use:&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; findFirst:[:ch | ch isDigit]&lt;br /&gt;
&lt;br /&gt;
to search for a digit OR period OR dollar character, you can use one of:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; findFirst:[:ch | ch isDigit or:[ ch == $. or:[ ch == $$]]]&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfAny:&#039;0123456789$.&#039;&lt;br /&gt;
&lt;br /&gt;
use whichever you find more readable.&lt;br /&gt;
(there is also a &amp;quot;&amp;lt;code&amp;gt;findFirst:startingAt:&amp;lt;/code&amp;gt;&amp;quot;, and corresponding &amp;quot;&amp;lt;code&amp;gt;findLast:&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;findLast:startingAt:&amp;lt;/code&amp;gt;&amp;quot; for backward searches)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because it is a common task to search for separators and other non-printable characters,&lt;br /&gt;
special methods exist for those:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfSeparatorStartingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfNonSeparatorStartingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfControlCharacterStartingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
where separators are the whitespace characters (space, tab, vt, cr and lf),&lt;br /&gt;
and control characters are all characters below ASCII 32.&lt;br /&gt;
&lt;br /&gt;
All of the index-search methods return a 0 (zero) if the character is not found.&lt;br /&gt;
&lt;br /&gt;
Substrings can be searched with:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039; caseSensitive: false&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039; caseSensitive: false&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: anotherString startingAt: startIndex&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfSubCollection: &#039;&#039;anotherString&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfSubCollection: &#039;&#039;anotherString&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also corresponding backward search variants &amp;quot;&amp;lt;code&amp;gt;lastIndexOfSubCollection:&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Notice the somewhat generic names &amp;quot;&amp;lt;code&amp;gt;indexOfSubCollection:&amp;lt;/code&amp;gt;&amp;quot; instead of a more intuitive &amp;quot;&amp;lt;code&amp;gt;indexOfString:&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
The reason is that these methods are inherited from collection, which does not care if the elements are&lt;br /&gt;
characters or other objects (&amp;lt;code&amp;gt;indexOfString:&amp;lt;/code&amp;gt; is an alias for &amp;lt;code&amp;gt;indexOfSubCollection:&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
This means, that you can use the same method to search for a slice in an array:&lt;br /&gt;
&lt;br /&gt;
    #(1 2 3 4 5 6 7 8 9 8 7 6 5 1 2 3 2 1) indexOfSubCollection:#(9 8 7)&lt;br /&gt;
&lt;br /&gt;
using the same code.&lt;br /&gt;
&lt;br /&gt;
To find all such methods in the class browser, search for implementors of &amp;quot;&amp;lt;code&amp;gt;*indexOf*&amp;lt;/code&amp;gt;&amp;quot;, and look at the matches in &amp;lt;code&amp;gt;Collection&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SequenceableCollection&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CharacterArray&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== If you don&#039;t need the Index ====&lt;br /&gt;
&lt;br /&gt;
If you only need to check if a character or substring is present, but not its position,&lt;br /&gt;
you can use &amp;quot;&amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;includesString:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;includesString:caseSensitive:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;includesSubCollection:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;includesAny:&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;includesAll:&amp;lt;/code&amp;gt;&amp;quot; in a similar spirit.&lt;br /&gt;
These may be slightly faster and make the code more readable. They return a boolean.&lt;br /&gt;
&lt;br /&gt;
==== Caseless Searches ====&lt;br /&gt;
&lt;br /&gt;
For strings, special substring searches are available, which ignore case (upper/lower) differences:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; includesString: &#039;&#039;anotherString&#039;&#039; caseSensitive: false&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039; caseSensitive: false&lt;br /&gt;
&lt;br /&gt;
==== Prefix and Suffix Checks ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; startsWith: &#039;&#039;anotherString&#039;&#039; &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; endsWith: &#039;&#039;anotherString&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
are obvious.&lt;br /&gt;
The powerful:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; startsWithAnyOf: &#039;&#039;aCollectionOfStrings&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
searches for multiple string prefixes. For example,&lt;br /&gt;
&lt;br /&gt;
    &#039;hello&#039; startsWithAnyOf: #( &#039;ab&#039; &#039;ce&#039; &#039;de&#039; )&lt;br /&gt;
&lt;br /&gt;
would look for all of them and return false in this concrete example.&lt;br /&gt;
Of course, there is a corresponding &amp;quot;&amp;lt;code&amp;gt;endsWithAnyOf:&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Splitting Parts of a String (or Collection) ====&lt;br /&gt;
&lt;br /&gt;
The simplest are:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; asCollectionOfWords&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; asCollectionOfLines&lt;br /&gt;
&lt;br /&gt;
which split at separators and line-ends respectively and return a collection as they say in their name.&lt;br /&gt;
&lt;br /&gt;
More generic is:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; js_split: charOrString&lt;br /&gt;
&lt;br /&gt;
which returns a collection of substrings split at &amp;quot;&#039;&#039;charOrString&#039;&#039;&amp;quot; elements. as the name suggests, you can pass either a single character or a substring as argument.&lt;br /&gt;
Thus:&lt;br /&gt;
&lt;br /&gt;
    &#039;hello world isn&#039;t this nice&#039; js_split:(Character space)&lt;br /&gt;
&lt;br /&gt;
will give you the strings &amp;lt;code&amp;gt;(&#039;hello&#039; &#039;world&#039; &#039;isnt&#039; &#039;this&#039; &#039;nice&#039;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Whereas:&lt;br /&gt;
    &#039;some : string : separated : by : space : colon space&#039; js_split:&#039; : &#039;&lt;br /&gt;
will return a collection containing: &amp;lt;code&amp;gt;(&#039;some&#039; &#039;string&#039; &#039;separated&#039; &#039;by&#039; &#039;space&#039; &#039;colon&#039; &#039;space&#039;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Notice, that we used &amp;quot;&amp;lt;code&amp;gt;js_split:&amp;lt;/code&amp;gt;&amp;quot; in the above examples, which is the method used by JavaScript&#039;s &amp;quot;&amp;lt;code&amp;gt;split()&amp;lt;/code&amp;gt;&amp;quot; function. This is because in Smalltalk, the &amp;quot;&amp;lt;code&amp;gt;split:&amp;lt;/code&amp;gt;&amp;quot; method has a different semantics: the receiver is a &amp;quot;&#039;&#039;splitter&#039;&#039;&amp;quot;, and the argument is splitted by it.&lt;br /&gt;
&amp;lt;br&amp;gt;In Smalltalk, the splitter can be both a simple string or a [[Regex Pattern Info| regular expression]]. For example:&lt;br /&gt;
&lt;br /&gt;
    &#039;[a-z]*&#039; asRegex split:&#039;123abc456def789&#039;&lt;br /&gt;
&lt;br /&gt;
will generate the collection: &amp;lt;code&amp;gt;#(&#039;123&#039; &#039;456&#039; &#039;789&#039;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To split into same-sized pieces, use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; splitForSize: &#039;&#039;charCount&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
this may be less of interest for strings, but is handy to split fixed records of binary data (remember: these functions are implemented in a superclass of &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;, from which &amp;lt;code&amp;gt;ByteArray&amp;lt;/code&amp;gt; also inherits).&lt;br /&gt;
&lt;br /&gt;
==== Joining and Concatenating Strings ====&lt;br /&gt;
&lt;br /&gt;
The simplest of them is the &amp;quot;,&amp;quot; (comma) operator. This takes two collections (and as such also Strings) and creates a new collection containing the concatenation of them.&lt;br /&gt;
Thus:&lt;br /&gt;
&lt;br /&gt;
    &#039;hello&#039; , &#039;world&#039;&lt;br /&gt;
&lt;br /&gt;
will create a new string containing &#039;helloworld&#039;,&lt;br /&gt;
and:&lt;br /&gt;
    &#039;hello&#039; , &#039; &#039; , &#039;world&#039;&lt;br /&gt;
&lt;br /&gt;
will give you &#039;hello world&#039;,&lt;br /&gt;
&amp;lt;br&amp;gt;and:&lt;br /&gt;
    #(1 2 3) , #(4 5 6)&lt;br /&gt;
will generate a 6-element array containing the elements 1 to 6.&lt;br /&gt;
&lt;br /&gt;
Notice that concatenation may become somewhat inefficient, if many strings are concatenated,&lt;br /&gt;
because many temporary string objects are created. Its time complexity is O(n&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;), where n is the number of strings concatenated.&lt;br /&gt;
&lt;br /&gt;
If you have to construct a string from many substrings, either use one of the join functions below (with O(n) complexity),&lt;br /&gt;
or a writeStream with O(n log n) complexity.&lt;br /&gt;
Both handle the reallocations much more efficiently (actually: avoiding most of them).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To join a set of strings, use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;asCollectionOfStrings&#039;&#039; asStringWith: &#039;&#039;separator&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
where separator may be a character, a separator string or nil.&lt;br /&gt;
For example:&lt;br /&gt;
    #( &#039;a&#039; &#039;b&#039; &#039;c&#039;) asStringWith:nil&lt;br /&gt;
gives &#039;abc&#039;,&lt;br /&gt;
and:&lt;br /&gt;
    #( &#039;a&#039; &#039;b&#039; &#039;c&#039;) asStringWith:&#039; : &#039;&lt;br /&gt;
returns: &#039;a : b : c&#039;&lt;br /&gt;
&lt;br /&gt;
Using a writeStream, write:&lt;br /&gt;
&lt;br /&gt;
    |w result|&lt;br /&gt;
 &lt;br /&gt;
    w := WriteStream on:(String new:10).&lt;br /&gt;
    w nextPutAll: &#039;a&#039;.&lt;br /&gt;
    w nextPutAll: &#039;b&#039;.&lt;br /&gt;
    ...&lt;br /&gt;
    result := w contents&lt;br /&gt;
&lt;br /&gt;
or, using a convenient utility method (which does exactly the same):&lt;br /&gt;
&lt;br /&gt;
    result := String streamContents:[:s |&lt;br /&gt;
        s nextPutAll: &#039;hello&#039;.&lt;br /&gt;
        s nextPutAll: &#039;world&#039;.&lt;br /&gt;
        ...&lt;br /&gt;
        s nextPutAll: &#039;Nice world&#039;&lt;br /&gt;
    ].&lt;br /&gt;
&lt;br /&gt;
but please read more on streams in the stream chapter below.&lt;br /&gt;
&lt;br /&gt;
==== Formatting Strings (Method A) ====&lt;br /&gt;
&lt;br /&gt;
For text messages, you may want to construct a pretty user readable string which contains printed representations of other objects.&lt;br /&gt;
For this, use:&lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWith: &#039;&#039;argument&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWith: &#039;&#039;argument1&#039;&#039; with: &#039;&#039;argument2&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWith: &#039;&#039;argument1&#039;&#039; with: ... with: &#039;&#039;argumentN&#039;&#039; (up to 5 arguments)&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWithArguments: &#039;&#039;argumentCollection&#039;&#039; (any number of arguments)&lt;br /&gt;
 &lt;br /&gt;
using the &amp;quot;&amp;lt;code&amp;gt;{ .. }&amp;lt;/code&amp;gt;&amp;quot; array constructor (notice the periods as expression separators), this is usually written as:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWithArguments: { &#039;&#039;argument1&#039;&#039; . &#039;&#039;argument2&#039;&#039; . ... . &#039;&#039;argumentN&#039;&#039; }&lt;br /&gt;
&lt;br /&gt;
The formatString itself may contain &amp;quot;%X&amp;quot; placeholders, which are replaced by corresponding&lt;br /&gt;
printed representations of the argumentX. The arguments will be converted to strings if they are not, thus arbitrary objects can be given as argument (although, in practice, these are usually numbers).&lt;br /&gt;
&lt;br /&gt;
If many arguments are to be passed in,&lt;br /&gt;
the placeholder names X may consist of a single digit (1-9) only for the first 9 arguments.&lt;br /&gt;
For other arguments, you must write &amp;quot;%(X)&amp;quot;. I.e. &#039;%(10)&#039; to get the tenth argument sliced at that position (1).&lt;br /&gt;
&lt;br /&gt;
The last of the above methods is a powerful tool, in that it does not only handle argumentCollections indexed by numbers (i.e. Array of arguments), but also Dictionaries, which are indexed by name.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a Dictionary collection of a person record (in expecco: a compound datatype instance), with element keys &amp;quot;firstName&amp;quot;, &amp;quot;lastName&amp;quot; and &amp;quot;city&amp;quot;,&lt;br /&gt;
you can generate a nice printed string with:&lt;br /&gt;
&lt;br /&gt;
    |record|&lt;br /&gt;
 &lt;br /&gt;
    record := Dictionary new.  &amp;quot;/ example using a dictionary&lt;br /&gt;
    record at:&#039;firstName&#039; put: &#039;Fritz&#039;.&lt;br /&gt;
    record at:&#039;lastName&#039; put: &#039;Müller&#039;.&lt;br /&gt;
    record at:&#039;city&#039; put: &#039;Stuttgart&#039;.&lt;br /&gt;
 &lt;br /&gt;
    &#039;%(lastName), %(firstName) lives in %(city)&#039; bindWithArguments: record.&lt;br /&gt;
&lt;br /&gt;
gives you the string: &#039;Müller, Fritz lives in Stuttgart&#039;.&lt;br /&gt;
&amp;lt;br&amp;gt;In combination with a expecco compound datatype instance, this would be:&lt;br /&gt;
&lt;br /&gt;
    |person|&lt;br /&gt;
 &lt;br /&gt;
    person := myType new.&lt;br /&gt;
    person firstName:&#039;Fritz&#039;.&lt;br /&gt;
    person lastName:&#039;Müller&#039;.&lt;br /&gt;
    person city:&#039;Stuttgart&#039;.&lt;br /&gt;
  &lt;br /&gt;
    &#039;%(lastName), %(firstName) lives in %(city)&#039; bindWithArguments: person.&lt;br /&gt;
&lt;br /&gt;
1) Note: this has been relaxed in 19.2, where %10 is allowed. However, all digits up to the first non-digit character will make up the index. If you need a sliced in value followed by a digit, you&#039;d still have to use %(x).&lt;br /&gt;
&lt;br /&gt;
==== Formatting Strings with Printf (Method B) ====&lt;br /&gt;
There is also a formatting method similar to &amp;quot;&amp;lt;code&amp;gt;printf&amp;lt;/code&amp;gt;&amp;quot;. It takes a format string and a number of arguments and constructs a string representation.&lt;br /&gt;
As Smalltalk does not support variable numbers of arguments, these must be passed with different keyword messages:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; printfWith:&#039;&#039;arg&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; printfWith:&#039;&#039;arg1&#039;&#039; with:&#039;&#039;arg2&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; printfWith:&#039;&#039;arg1&#039;&#039; with:&#039;&#039;arg2&#039;&#039; with:&#039;&#039;arg3&#039;&#039;&lt;br /&gt;
    ... up to 5 arguments&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; printf:&#039;&#039;argVector&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For the argVector, use the &amp;quot;{&amp;quot; .. &amp;quot;}&amp;quot; construct.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
    &#039;%05d 0x%-7x %f&#039; printf:{ 123 . 517 . 1.234 }&lt;br /&gt;
generates the string:&lt;br /&gt;
    &#039;00123 0x205     1.234&#039;&lt;br /&gt;
&lt;br /&gt;
The above provides the functionality of C&#039;s &amp;quot;sprintf&amp;quot; - i.e. it generates a string as result. However, streams also understand printf-messages, so you can also print directly to a stream:&lt;br /&gt;
&lt;br /&gt;
    Transcript printf:&#039;%05x\n&#039; with:12345&lt;br /&gt;
or:&lt;br /&gt;
    Transcript printf:&#039;%05x %d %f %o\n&#039; withAll:{ 123. 234*5. 1.234. 254 }&lt;br /&gt;
&lt;br /&gt;
Notice, that printf translates the standard C-character escapes &amp;quot;\n&amp;quot;, ”\t&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
==== Formatting Strings with Embedded Expressions (Method C) ====&lt;br /&gt;
A string constant prefixed with &amp;quot;e&amp;quot; is a so called expression-string. This may contain Smalltalk expressions enclosed in &amp;quot;{&amp;quot; .. &amp;quot;}&amp;quot;, which are sliced into the string (actually, the expression&#039;s printString is sliced in). In addition, C-style escape sequences like &amp;quot;\n&amp;quot; are recognized in e-strings.&lt;br /&gt;
&lt;br /&gt;
    Transcript show: e&#039;today is {Date today} and the time is {Time now}\nAnd the dayName is {Date today dayName}&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Regex and Glob Matching ====&lt;br /&gt;
&lt;br /&gt;
Both match a string against a match pattern, but the syntax and functionality is different.&lt;br /&gt;
* Glob is much easier to use but less powerful. Glob is the match algorithm used in the Unix and MS-DOS filesystem (e.g. when saying &amp;quot;&amp;lt;code&amp;gt;ls *.foo&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;dir *.foo&amp;lt;/code&amp;gt;&amp;quot; on the command line).&lt;br /&gt;
* [[Regex Pattern Info| Regex]] is the algorithm used in tools like &amp;quot;grep&amp;quot; and many text processing systems and languages.&lt;br /&gt;
&lt;br /&gt;
Notice that regex patterns are different and not just a superset of glob patterns. Especially the meanings of &amp;quot;*&amp;quot; and &amp;quot;.&amp;quot; are different.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Please consult Wikipedia for more information on Regex [https://en.wikipedia.org/wiki/Regular_expression] and GLOB [https://en.wikipedia.org/wiki/Glob_%28programming%29].&lt;br /&gt;
A chapter on regex is also found in this [[Regex Pattern Info| wiki]].&lt;br /&gt;
&lt;br /&gt;
For a Glob match, use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aGlobPattern&#039;&#039; match:&#039;&#039;aString&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aGlobPattern&#039;&#039; match:&#039;&#039;aString&#039;&#039; caseSensitive:false&lt;br /&gt;
&lt;br /&gt;
or, reversed argument order, if you prefer:&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matches:&#039;&#039;aGlobPattern&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matches:&#039;&#039;aGlobPattern&#039;&#039; caseSensitive:false&lt;br /&gt;
&lt;br /&gt;
For a regex match, use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matchesRegex:&#039;&#039;aRegexPattern&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matchesRegex:&#039;&#039;aRegexPattern&#039;&#039; caseSensitive:false&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matchesRegex:&#039;&#039;aRegexPattern&#039;&#039; ignoringCase:true  &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ an alias to the above&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sorry for the inconsistent method naming which is due to the fact that the regex matcher originated in a public domain package, which was developed independently from the original ST/X system. In order to remain compatible with other Smalltalk dialects, the names were kept.&lt;br /&gt;
&lt;br /&gt;
The CharacterArray class provides a whole bunch of useful match methods (eg. to extract multiple occurrences of a pattern, to do prefix matches and to extract sub patterns from a complex match pattern). Please use the class browser (from the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; menu) to find them.&lt;br /&gt;
&lt;br /&gt;
==== Code Converting ====&lt;br /&gt;
&lt;br /&gt;
There are code converters for various character encodings in and below the CharacterEncoder class.&lt;br /&gt;
Most of them are obsolete or seldom used these days, as now most systems support Unicode (which was not the case, the ST/X was written 30 years ago and switched to Unicode in the 90&#039;s!).&lt;br /&gt;
&lt;br /&gt;
In general, you can get an instance of an encoder via a convenient CharacterEncoder interface:&lt;br /&gt;
&lt;br /&gt;
    CharacterEncoder encoderFor:&amp;lt;encoding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    CharacterEncoder encoderToEncodeFrom:&amp;lt;encoding1&amp;gt; to:&amp;lt;encoding2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where encoding is a name, such as &#039;iso8859-1&#039;, &#039;unicode&#039;, &#039;utf8&#039;, &#039;utf16&#039;, &#039;ascii&#039;, &#039;jis7&#039; etc.&lt;br /&gt;
&lt;br /&gt;
Thus, to encode a string from Unicode (which is the internal encoding anyway) to Japanese JIS0201, use:&lt;br /&gt;
&lt;br /&gt;
    (CharacterEncoder encoderFor:#&#039;jis0201&#039;) encode:&#039;hello&#039;&lt;br /&gt;
&lt;br /&gt;
or to encode from Microsoft cp1253 to koi8-r, use:&lt;br /&gt;
&lt;br /&gt;
    (CharacterEncoder encoderToEncodeFrom:#&#039;cp1253&#039; to:#&#039;koi8-r&#039;) encode:&amp;lt;&#039;&#039;someStringInCP1253&#039;&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will probably not need that general interface, but use UTF-8 these days.&lt;br /&gt;
For those, the String class provides easier to use interface:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; utf8Encoded&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; utf8Decoded&lt;br /&gt;
&lt;br /&gt;
==== Collection Slices ====&lt;br /&gt;
&lt;br /&gt;
A slice is a reference to a subcollection, which looks and behaves like any other collection, but shares the underlying data with the original collection. Thus modifications in either the original or slice are visible in the other and vice versa.&lt;br /&gt;
&lt;br /&gt;
To get a slice, use one of the &amp;quot;&amp;lt;code&amp;gt;from:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;from:to:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;to:&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;from:count:&amp;lt;/code&amp;gt;&amp;quot; methods (the names are similar to the above mentioned &amp;quot;copy*&amp;quot; methods).&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    data := ... some big ByteArray read from a file ...&lt;br /&gt;
 &lt;br /&gt;
    record1 := data from:1 to:recordSize.&lt;br /&gt;
    record2 := data from:(recordSize+1) to:recordSize*2.&lt;br /&gt;
    etc.&lt;br /&gt;
&lt;br /&gt;
gives you the records from the big collection as individual objects. If any modification is made to any of the slices, that modification is actually made in the underlying data collection (i.e. C-Programmers may think of this as a &amp;quot;&#039;&#039;pointer into the data object&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Slices are especially useful with bulk data processing, to avoid the creation of individual record copies. &lt;br /&gt;
&lt;br /&gt;
However, they are a bit dangerous, as the programmer has to be always aware of possible side effects. If you are uncertain, do not pass a slice to another (unknown) function; instead use the corresponding copy methods.&lt;br /&gt;
&lt;br /&gt;
=== Stream Handling ===&lt;br /&gt;
&lt;br /&gt;
Streams can be both internal streams (streaming out-of or into a collection) or external streams.&lt;br /&gt;
External streams are always byte- or character-oriented and operate on files, sockets, pipes or i/o devices.&lt;br /&gt;
An internal stream&#039;s element type depends on the underlying collection.&lt;br /&gt;
&lt;br /&gt;
The following presents only a very small excerpt of the full stream protocol.&lt;br /&gt;
Please refer to the online documentation of the Smalltalk/X stream classes.&lt;br /&gt;
&lt;br /&gt;
==== Creating (Internal Streams) ====&lt;br /&gt;
&lt;br /&gt;
streams for reading:&lt;br /&gt;
 rs := ReadStream on:&#039;&#039;aCollection&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 rs := &#039;&#039;aCollection&#039;&#039; readStream&lt;br /&gt;
&lt;br /&gt;
streams for writing:&lt;br /&gt;
 ws := WriteStream on:(String new:&#039;&#039;initialSize&#039;&#039;)&lt;br /&gt;
 &lt;br /&gt;
 ws := &amp;amp;#39;&amp;amp;#39; writeStream&lt;br /&gt;
 &lt;br /&gt;
 ws := WriteStream on:(Array new)&lt;br /&gt;
&lt;br /&gt;
notice that the underlying collection is reallocated when more elements are added due to nextPut: operations.&lt;br /&gt;
The reallocations are done by doubling the size, resulting in O(n log n) complexity. If you have a rough idea on the final size, preallocating with an initialSize avoids or reduces the number of reallocations.&lt;br /&gt;
&lt;br /&gt;
==== Checking ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; atEnd&lt;br /&gt;
returns true iff the read stream &amp;quot;s&amp;quot; is positioned at the end.&lt;br /&gt;
 &#039;&#039;s&#039;&#039; size&lt;br /&gt;
returns the size of the read stream&#039;s buffer, or the number of elements written into a write stream.&lt;br /&gt;
&lt;br /&gt;
==== Positioning ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; position&lt;br /&gt;
&lt;br /&gt;
returns the stream&#039;s current read position, starting at 0 when at the beginning.&lt;br /&gt;
I.e. position represents the number of elements which have already been read or written.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; position:&#039;&#039;pos&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
set the position.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; rewind&lt;br /&gt;
&lt;br /&gt;
reset the position to the beginning&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; setToEnd&lt;br /&gt;
&lt;br /&gt;
set the position to the end (normally only useful for appending write streams)&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; backStep&lt;br /&gt;
&lt;br /&gt;
position one element backwards&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; skip:n&lt;br /&gt;
&lt;br /&gt;
skip n elements when reading&lt;br /&gt;
&lt;br /&gt;
==== Reading ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; next&lt;br /&gt;
&lt;br /&gt;
retrieve the next element from the stream. Nil if there are no more elements.&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;rs&#039;&#039; next:&#039;&#039;count&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
retrieve the next &amp;quot;n&amp;quot; elements from the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; nextAvailable:&#039;&#039;count&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
retrieve the next &amp;quot;n&amp;quot; elements or whatever number of elements are available.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; upTo:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
retrieve elements up to an element which is equal to &amp;quot;element&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; skipTo:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
skip over elements up to an element which is equal to &amp;quot;element&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; through:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
retrieve elements up-to and including an element which is equal to &amp;quot;element&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Writing ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; nextPut:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append element to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; next:&#039;&#039;count&#039;&#039; put:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append element multiple times to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; nextPutAll:&#039;&#039;aCollectionOfElements&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append all elements from the given collection to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; println&lt;br /&gt;
&lt;br /&gt;
append a newline character.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; cr&lt;br /&gt;
&lt;br /&gt;
also&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; nextPutLine:&#039;&#039;aCollectionOfElements&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append all elements from the given collection followed by a newline to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; print:&#039;&#039;anObject&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append a printed representation of anObject (for humans) to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; store:&#039;&#039;anObject&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append the printed representation of anObject (for the system) to the stream.&lt;br /&gt;
Unless the object has recursive references, a copy of the element can be reconstructed with &amp;lt;code&amp;gt;Object readFrom:&amp;lt;/code&amp;gt;&#039;&#039;aReadStream&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; println:&#039;&#039;anObject&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append a printed representation of anObject (for humans) to the stream, followed by a newline.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; printCR:&#039;&#039;anObject&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the same&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; contents&lt;br /&gt;
&lt;br /&gt;
retrieve the stream&#039;s contents (typically, the characters buffered so far)&lt;br /&gt;
&lt;br /&gt;
==== File Streams ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;aString&#039;&#039; asFilename readStream&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;aString&#039;&#039; asFilename writeStream&lt;br /&gt;
&lt;br /&gt;
See more below in the chapter on [[#File_Operations |file operations]].&lt;br /&gt;
&lt;br /&gt;
=== Numbers ===&lt;br /&gt;
&lt;br /&gt;
==== Reading Numbers from a String ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To read a number from a string, use the &amp;quot;readFrom:&amp;quot; method provided by the number classes,&lt;br /&gt;
where the argument is either a string, or a headstream.&lt;br /&gt;
A readstream is obtained with either &amp;quot;&amp;lt;code&amp;gt;(ReadStream on:&#039;&#039;aString&#039;&#039;)&amp;lt;/code&amp;gt;&amp;quot; or the more convenient &amp;quot;&amp;lt;code&amp;gt;(&#039;&#039;aString&#039;&#039; readStream)&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Thus, in general, code to read a number looks like:&lt;br /&gt;
    &amp;lt;class&amp;gt; &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039;&lt;br /&gt;
or:&lt;br /&gt;
    &amp;lt;class&amp;gt; &#039;&#039;&#039;readFrom:&#039;&#039;&#039; (ReadStream on:&#039;&#039;aString&#039;&#039;)&lt;br /&gt;
or:&lt;br /&gt;
    &amp;lt;class&amp;gt; &#039;&#039;&#039;readFrom:&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039; readStream)&lt;br /&gt;
&lt;br /&gt;
where &amp;quot;&amp;lt;class&amp;gt;&amp;quot; is one of &amp;quot;&amp;lt;code&amp;gt;Integer&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Float&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;FixedPoint&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
If &amp;quot;&amp;lt;class&amp;gt;&amp;quot; is &amp;quot;&amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt;&amp;quot;, any type of number will be read and returned. Otherwise, only that type of number will be accepted (i.e. &amp;quot;&amp;lt;code&amp;gt;Integer readFrom:&#039;&#039;String&#039;&#039;&amp;lt;/code&amp;gt;&amp;quot;, will report an error if there is a decimal point in the string.&lt;br /&gt;
&lt;br /&gt;
If the string contains nothing but the number string, the above two code expressions behave the same.&lt;br /&gt;
However, there is an often overlooked difference in case of extra characters after the number:&lt;br /&gt;
&lt;br /&gt;
* the string-reader expects that the given string contains a representation of a corresponding number object, and NO extra characters before or after it. It will report an error otherwise.&lt;br /&gt;
&lt;br /&gt;
* in contrast, the stream reader will first skip any spaces, then read as many characters as required from the stream, return the number and leave the stream positioned after the number. It will report an error if no number can be read. More values can be read from the stream if required.&lt;br /&gt;
&lt;br /&gt;
Thus both:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;1234&#039;&lt;br /&gt;
and:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; (ReadStream on:&#039;1234&#039;).&lt;br /&gt;
&lt;br /&gt;
return the Integer object 1234.&lt;br /&gt;
&lt;br /&gt;
Whereas:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;1234bla&#039;&lt;br /&gt;
will raise an error, but:&lt;br /&gt;
    myStream := ReadStream &#039;&#039;&#039;on:&#039;&#039;&#039; &#039;1234bla&#039;.&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.&lt;br /&gt;
&lt;br /&gt;
returns the integer 1234 and leave the stream positioned on the &#039;bla&#039;. Thus further elements can be read from the stream later.&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;&amp;lt;code&amp;gt;Integer readFrom:&amp;lt;/code&amp;gt;&amp;quot; will read an integer, but not a float.&lt;br /&gt;
Thus:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;1234.5&#039;&lt;br /&gt;
will raise an error, but:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; (ReadStream on:&#039;1234.5&#039;).&lt;br /&gt;
&lt;br /&gt;
will return the Integer object 1234 and leave the stream positioned on the decimal point character.&lt;br /&gt;
&lt;br /&gt;
When expecting an arbitrary number (e.g. with or without decimal point),&lt;br /&gt;
use:&lt;br /&gt;
    Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039;&lt;br /&gt;
which will return either an integer object or a float object depending on what it gets.&lt;br /&gt;
&lt;br /&gt;
If you want to enforce getting a float, use&lt;br /&gt;
    Float &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039;&lt;br /&gt;
which returns the float &amp;quot;1234.0&amp;quot;, even when given the string &amp;quot;1234&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== Error handling =====&lt;br /&gt;
&lt;br /&gt;
By default, the readers raise an exception, if any conversion error occurs.&lt;br /&gt;
This can be caught in an error handler as described elsewhere (hint: catch the error with &amp;quot;&amp;lt;code&amp;gt;on:do:&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
However, the conversion routines can also be given a correction function as argument,&lt;br /&gt;
which is invoked in case of an error, and which provides a replacement value. This is easier and shorter to write then an exception handler.&lt;br /&gt;
&lt;br /&gt;
For this, all of the methods described are also present in a variant with an extra &amp;quot;&amp;lt;code&amp;gt;onError:&amp;lt;/code&amp;gt;&amp;quot; argument, which provides that replacement.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039; &#039;&#039;&#039;onError:&#039;&#039;&#039; [ 0 ]&lt;br /&gt;
&lt;br /&gt;
will return the number as usual if OK, but zero if not.&lt;br /&gt;
&amp;lt;br&amp;gt;Of course, arbitrary code can be provided inside this handler - especially it may show an error dialog and ask the user for a replacement, or return from the executed elementary block:&lt;br /&gt;
&lt;br /&gt;
    val := Integer&lt;br /&gt;
            &#039;&#039;&#039;readFrom:&#039;&#039;&#039;aString&lt;br /&gt;
            &#039;&#039;&#039;onError:&#039;&#039;&#039;[&lt;br /&gt;
                |ersatz|&lt;br /&gt;
                ersatz := Dialog &#039;&#039;&#039;request:&#039;&#039;&#039;&#039;Please enter a correct number&#039;.&lt;br /&gt;
                Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039;ersatz&lt;br /&gt;
            ]&lt;br /&gt;
&lt;br /&gt;
===== Reading with a Different Decimal Point Character =====&lt;br /&gt;
&lt;br /&gt;
If the number was originally for a european, it may contain a decimal point different from &amp;quot;.&amp;quot; -&lt;br /&gt;
for example, in Germany you may encouter a monetary amount as &amp;quot;1245,99&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For this, use:&lt;br /&gt;
&lt;br /&gt;
    Float &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039; &#039;&#039;&#039;decimalPointCharacters:&#039;&#039;&#039; &#039;,&#039;&lt;br /&gt;
&lt;br /&gt;
or (better):&lt;br /&gt;
&lt;br /&gt;
    FixedPoint &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039; &#039;&#039;&#039;decimalPointCharacters:&#039;&#039;&#039; &#039;,&#039;&lt;br /&gt;
&lt;br /&gt;
If your code has to deal with both US and German numbers, provide all possible decimal points in the string, as in:&lt;br /&gt;
&lt;br /&gt;
    FixedPoint &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039; &#039;&#039;&#039;decimalPointCharacters:&#039;&#039;&#039; &#039;,.&#039;&lt;br /&gt;
&lt;br /&gt;
===== Reading Multiple Numbers from a Stream =====&lt;br /&gt;
&lt;br /&gt;
A common task is to read multiple numbers from a single long string.&lt;br /&gt;
Of course, you could first split the string into pieces and use the above &amp;quot;readFrom:&amp;quot; on each.&lt;br /&gt;
&lt;br /&gt;
This may also be a quick&amp;amp;dirty solution, if the individual number strings are contained in fixed-length fields and there are no separators in between the fields (but read below for a better way to do this).&lt;br /&gt;
Take a look at the string handling examples on how to split strings.&lt;br /&gt;
&lt;br /&gt;
To read multiple numbers, the best solution is to first create a read stream on the string, then read the individual numbers:&lt;br /&gt;
&lt;br /&gt;
    myString := &#039;1234 456.7 0.5 2345.3456 3234234234234234234234234234234234234&#039;.&lt;br /&gt;
    myStream := myString &#039;&#039;&#039;readStream&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
    n1 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.      &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the integer 1234 in n1&amp;lt;/span&amp;gt;&lt;br /&gt;
    n2 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.      &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the float 456.7 in n2&amp;lt;/span&amp;gt;&lt;br /&gt;
    n3 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.      &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the float 0.5 in n3&amp;lt;/span&amp;gt;&lt;br /&gt;
    n4 := FixedPoint &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.  &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the fixedPoint 2345.3456 in n4&amp;lt;/span&amp;gt;&lt;br /&gt;
    n5 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.      &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the large integer 3234...34 in n5&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;&amp;lt;code&amp;gt;readFrom:&amp;lt;/code&amp;gt;&amp;quot; first skips any separators (spaces) - therefore no extra code is needed to deal with those.&lt;br /&gt;
&lt;br /&gt;
If extra stuff needs to be skipped, use any of the existing stream functions (&amp;lt;code&amp;gt;skipFor:&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;skipUntil:&amp;lt;/code&amp;gt; etc.). If none does the job, you can look at individual characters and skip until a match is found.&lt;br /&gt;
For example, to read 3 numbers from the following string &#039;123 bla 456.8|0.5&#039;,&lt;br /&gt;
you could use:&lt;br /&gt;
&lt;br /&gt;
    s := &#039;123 bla 456.8|0.5&#039; readStream.&lt;br /&gt;
    n1 := Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
    s &#039;&#039;&#039;skipSeparators&#039;&#039;&#039;.&lt;br /&gt;
    s &#039;&#039;&#039;nextAlphanumericWord&#039;&#039;&#039;.  &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ skips over the &#039;bla&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
    n2 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
    s next.                  &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ skips over one character&amp;lt;/span&amp;gt;&lt;br /&gt;
    n3 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
&lt;br /&gt;
of course, the above code would not handle strings like &#039;123 bla bla 456.8|0.5&#039; or &#039;123 bla 456.8 |0.5&#039;.&lt;br /&gt;
&amp;lt;br&amp;gt;Using &amp;quot;peek&amp;quot;, which looks at the next character in the stream without consuming it,&lt;br /&gt;
we could to change the code to:&lt;br /&gt;
&lt;br /&gt;
    n1 := Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
    [ s &#039;&#039;&#039;peek&#039;&#039;&#039; &#039;&#039;&#039;isDigit&#039;&#039;&#039; ] &#039;&#039;&#039;whileFalse:&#039;&#039;&#039;[ s &#039;&#039;&#039;next&#039;&#039;&#039; ]. &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ skips over the &#039;bla bla&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
    n2 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
    s &#039;&#039;&#039;next&#039;&#039;&#039;.                                   &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ skips over one character&amp;lt;/span&amp;gt;&lt;br /&gt;
    n3 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;&amp;lt;code&amp;gt;peek&amp;lt;/code&amp;gt;&amp;quot; returns nil, if the end of the stream is reached. And that &amp;quot;&amp;lt;code&amp;gt;nil isDigit&amp;lt;/code&amp;gt;&amp;quot; will report an error (because only characters can be asked for being a digit).&lt;br /&gt;
Thus, the code like the above is not prepared to read a variable number of numbers.&lt;br /&gt;
&lt;br /&gt;
===== Reading with Scanf =====&lt;br /&gt;
&lt;br /&gt;
There is also a C-like scanf utility, which can read numbers, strings, characters in various formats.&lt;br /&gt;
&lt;br /&gt;
    myString := &#039;1234 456.7 0.5 2345.3456 3234234234234234234234234234234234234&#039;.&lt;br /&gt;
    values := &#039;%d %f %f %f %d&#039; &#039;&#039;&#039;scanf:&#039;&#039;&#039; myString.&lt;br /&gt;
&lt;br /&gt;
generates a collection of numbers in &amp;quot;values&amp;quot;: &lt;br /&gt;
    OrderedCollection(1234 456.7 0.5 2345.3456 3234234234234234234234234234234234234)&lt;br /&gt;
&lt;br /&gt;
The details and format characters are described in the PrintfScanf utility class, here is a short summary:&lt;br /&gt;
&lt;br /&gt;
Conversions (upper case same as lower case):&lt;br /&gt;
* &#039;b&#039;     binary (base 2)&lt;br /&gt;
* &#039;c&#039;     character or (first char of string)&lt;br /&gt;
* &#039;d&#039;     decimal&lt;br /&gt;
* &#039;e&#039;     float&lt;br /&gt;
* &#039;f&#039;     float&lt;br /&gt;
* &#039;g&#039;     float&lt;br /&gt;
* &#039;i&#039;     integer (alias for &#039;d&#039;)&lt;br /&gt;
* &#039;o&#039;     base-8 octal&lt;br /&gt;
* &#039;s&#039;     string&lt;br /&gt;
* &#039;u&#039;     integer&lt;br /&gt;
* &#039;x&#039;     base-16 hex&lt;br /&gt;
&lt;br /&gt;
Length prefix:&lt;br /&gt;
&lt;br /&gt;
* &#039;h&#039;     with float formats: reads as ShortFloat&lt;br /&gt;
* &#039;L&#039;     with float formats: reads as LongFloat&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
* &#039;%d %x&#039; &#039;&#039;&#039;scanf:&#039;&#039;&#039;&#039;1234 ff00&#039;         -&amp;gt; OrderedCollection(1234 65280)&lt;br /&gt;
* &#039;%d %s&#039; &#039;&#039;&#039;scanf:&#039;&#039;&#039;&#039;1234 ff00&#039;         -&amp;gt; OrderedCollection(1234 &#039;ff00&#039;)&lt;br /&gt;
* &#039;%d %x %b&#039; &#039;&#039;&#039;scanf:&#039;&#039;&#039;&#039;1234 ff00 1001&#039; -&amp;gt; OrderedCollection(1234 65280 9)&lt;br /&gt;
&lt;br /&gt;
==== Reading a Particular Number of Numbers from a Stream ====&lt;br /&gt;
&lt;br /&gt;
Assume that you are given a number which defines how many numbers to extract from a given string.&lt;br /&gt;
&lt;br /&gt;
Of course, you can use a &amp;quot;&amp;lt;code&amp;gt;start to: stop do:[:idx |...&amp;lt;/code&amp;gt;&amp;quot; loop,&lt;br /&gt;
but experienced Smalltalk programmers make use of the collection protocol,&lt;br /&gt;
as in:&lt;br /&gt;
    (1 to: count) collect:[:idx | Number readFrom:aStream ]&lt;br /&gt;
&lt;br /&gt;
Such a construct is needed e.g. when you have to parse a string, where the first entry defines how many numbers follow:&lt;br /&gt;
&lt;br /&gt;
    coll := (1 to: (Integer readFrom:myString)) collect:[:idx | Number readFrom:aStream ].&lt;br /&gt;
&lt;br /&gt;
which would parse the string &amp;quot;5 1.0 3.0 2.0 -1.0 .05&amp;quot; into a 5-element collection containing the converted numbers.&lt;br /&gt;
&lt;br /&gt;
==== Reading a Variable Number of Numbers from a Stream ====&lt;br /&gt;
&lt;br /&gt;
To do so, we should collect numbers as being read from the stream in a collection:&lt;br /&gt;
&lt;br /&gt;
    collectedNumbers := OrderedCollection new.&lt;br /&gt;
 &lt;br /&gt;
    [ aStream atEnd ] whileFalse:[&lt;br /&gt;
        collectedNumbers add: ( Number readFrom:aStream ).&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
or, if any non-digits and non-spaces between numbers should be skipped,&lt;br /&gt;
use:&lt;br /&gt;
&lt;br /&gt;
    collectedNumbers := OrderedCollection new.&lt;br /&gt;
 &lt;br /&gt;
    [ aStream atEnd ] whileFalse:[&lt;br /&gt;
        aStream skipUntil:[:char | char isDigit].&lt;br /&gt;
        collectedNumbers add:( Number readFrom:aStream ).&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
==== Using the Pattern Matcher to Extract Parts ====&lt;br /&gt;
&lt;br /&gt;
In rare situations, complex patterns need to be matched and numeric values&lt;br /&gt;
retrieved from the matched parts. For this, use a regex pattern matcher to first extract parts from the string, and then convert the substrings.&lt;br /&gt;
For example, to fetch numbers after certain keywords in a string, you could use:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ assuming that the string is of the form:&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/    &amp;lt;..arbitrary-text...&amp;gt;key1&amp;lt;number1&amp;gt;&amp;lt;...arbitrary text...&amp;gt;key2&amp;lt;number&amp;gt;&amp;lt;...arbitrary text...&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ where arbitrary text may even contain key1 and key2, but not followed by a number,&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ we first use a regex to match, then convert the matched regex parts:&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    myString := &#039;bla bla key1 bla key11234more bla key2 bla key29876bla bla&#039;.&lt;br /&gt;
 &lt;br /&gt;
    parts := myString allRegexMatches:&#039;((key[12]))([0-9]+)&#039;.&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ now, parts contains #( &#039;key11234&#039; &#039;key29876&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
    numbers := parts collect:[:eachPart | Number readFrom: (eachPart copyFrom:5) ].&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ now, numbers contains #( 1234 9876 )&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
notice that &#039;&#039;parts&#039;&#039; delivers the matched strings i.e. the collection (&#039;key11234&#039; &#039;key29876&#039;),&lt;br /&gt;
so that we have to skip over the &#039;keyX&#039; prefix before extracting the numbers.&lt;br /&gt;
&lt;br /&gt;
=== File Operations ===&lt;br /&gt;
&lt;br /&gt;
Expecco (i.e. Smalltalk) represents file names as instances of a specialized class called &amp;quot;&amp;lt;code&amp;gt;Filename&amp;lt;/code&amp;gt;&amp;quot;. These look similar to strings, but provide an abstraction over details of the underlying file- and operating system.&lt;br /&gt;
 &lt;br /&gt;
This makes it possible to write portable code which runs on Windows, Linux and even VMS, even though these systems use very different filename separators and volume naming schemes.&lt;br /&gt;
&lt;br /&gt;
Thus, we recommend to use filename operations instead of string concatenation, e.g. to construct pathnames.&lt;br /&gt;
In Smalltalk, the abstract class &amp;quot;&amp;lt;code&amp;gt;Filename&amp;lt;/code&amp;gt;&amp;quot; is subclassed by concrete classes named &amp;quot;&amp;lt;code&amp;gt;PCFilename&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;UnixFilename&amp;lt;/code&amp;gt;&amp;quot;. &lt;br /&gt;
You should not access those concrete classes explicitly by name! &lt;br /&gt;
Instead, always refer to &amp;quot;&amp;lt;code&amp;gt;Filename&amp;lt;/code&amp;gt;&amp;quot; and let Smalltalk decide, which concrete class to use.&lt;br /&gt;
(unless you know that you are dealing with a unix-style filename, independent of your operating system, which is e.g. the case if you deal with CVS names or you get file-URLS as strings).&lt;br /&gt;
&lt;br /&gt;
for now, a short summary:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; asFilename  - to get a Filename-instance for a given String instance &lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; readStream - to get a readStream on the contents of a file&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; writeStream - to get a writeStream writing to a file&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; appendingWriteStream - to get a writeStream appending to the end of a file&lt;br /&gt;
&lt;br /&gt;
==== Checking ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; exists &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ true if the file exists&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isReadable &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ true if it is readable&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isWritable&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isExecutable &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ for folders, this means: &amp;quot;can be changed into&amp;quot;&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isExecutableProgram&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; fileSize&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isDirectory&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isNonEmptyDirectory&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isRegularFile&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isSymbolicLink&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; info &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gets all info; follows any symbolic link. Includes ownerID, groupID, access and modification times etc.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; linkInfo &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gets all info of a symbolic link itself. Includes ownerID, groupID, access and modification times etc.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; accessTime&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; modificationTime&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; creationTime &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ (same as modificationTime on Unix systems)&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; fileType&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; mimeType&lt;br /&gt;
&lt;br /&gt;
==== File names ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; pathName&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; directory &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ the containing directory, as a Filename instance&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; directoryName &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ ditto, as string&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; baseName&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; suffix&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; hasSuffix:&#039;&#039;aString&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isAbsolute&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isRelative&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; / &#039;&#039;subPath&#039;&#039; &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ yes, &amp;quot;/&amp;quot; is an operator to construct the name of a file inside a folder&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; construct:&#039;&#039;subPath&#039;&#039; &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ alternative to &amp;quot;/&amp;quot;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operations ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; makeDirectory&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; recursiveMakeDirectory &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ ensures that all folders along the path are also created.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; removeDirectory &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ raises an error, if the folder is not empty&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; recursiveRemoveDirectory &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ removes everything below also&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; moveTo:&#039;&#039;newName&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; copyTo:&#039;&#039;newName&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; recursiveCopyTo:&#039;&#039;destinationName&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Directory Contents ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; directoryContents&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; directoryContentsDo:[:eachFile | ...]&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; filesMatching:aGLOBPatternString&lt;br /&gt;
&lt;br /&gt;
==== File Contents ====&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; contents&lt;br /&gt;
retrieves the contents as a collection of line strings.&lt;br /&gt;
Be careful - this should not be used for huge files.&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; contentsAsString&lt;br /&gt;
retrieves the contents as one (possibly big) string.&lt;br /&gt;
Be careful - this should not be used for huge files.&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; binaryContentsOfEntireFile&lt;br /&gt;
retrieves the contents as one (possibly big) byte array.&lt;br /&gt;
Be careful - this should not be used for huge files.&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; readingLinesDo:[:eachLineString | ... ]&lt;br /&gt;
better use this for large files. Ensures that the file is closed.&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; readingFileDo:[:stream | ... ]&lt;br /&gt;
or that to read inside the code block. Ensures that the file is closed.&lt;br /&gt;
&lt;br /&gt;
=== Shared Data and Synchronization ===&lt;br /&gt;
&lt;br /&gt;
A number of mechanisms for synchronisation and mutual access to shared data structures are available: &amp;lt;code&amp;gt;Semaphore&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RecursionLock&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Monitor&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SharedQueue&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SharedCollection&amp;lt;/code&amp;gt; and the &amp;lt;code&amp;gt;synchronized:&amp;lt;/code&amp;gt; method, which is understood by every object.&lt;br /&gt;
For details, please refer to the Smalltalk/X Online Documentation.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following code examples contain versions for Smalltalk, JavaScript, Groovy and Node.js.&lt;br /&gt;
Notice that Groovy and Node.js actions are invoked via a remote procedure call ([[Glossary#RPC|RPC]]) mechanism, which means that they are much slower due to the communication, encoding, decoding and general round trip delays. Therefore, Groovy and Node.js blocks (bridged actions in general) should only be used to access data inside the system under test or to call functions which are not available in the base system (such as additional protocols or hardware access, for which only a JAR or node- or python package is available). Or, functions for which the call overhead is small compared to the runtime (i.e. for heavy computing tasks, it may very well make sense).&lt;br /&gt;
&lt;br /&gt;
Thus, most of the examples below are for demonstration purposes, not for real world scenarios (i.e. it will certainly slow down your test runs, if you do math via Groovy or even Node.js, as shown below). &lt;br /&gt;
&lt;br /&gt;
Also bear in mind, that the underlying numeric representations are less flexible and more error-prone if you do math outside Smalltalk:&lt;br /&gt;
in Groovy, because there will be no signalling of overflow/underflow situations. Especially with integer arithmetic, which may be outside the 32bit/64bit range. Also, Java has no exact fraction representations, which means that you may loose precision in floating point operations.&lt;br /&gt;
&lt;br /&gt;
Things are even worse in Node.js, which represents all numbers as double precision floats, giving roughly 53 bits of precision. Thus, in Node.js the two integers 12345678901234567890 and 12345678901234567891 will be reported as being equal! (this may change in a future Node version, though).&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Do NOT use Groovy or Node.js for numeric computations, if large integer values are involved (or use a Bignum package).&lt;br /&gt;
&lt;br /&gt;
=== Reading/Writing Pin Values ===&lt;br /&gt;
&lt;br /&gt;
Assuming that the block has two input pins, named &amp;quot;&amp;lt;code&amp;gt;in1&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;in2&amp;lt;/code&amp;gt;&amp;quot; and two output pins, named &amp;quot;&amp;lt;code&amp;gt;out1&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;out2&amp;lt;/code&amp;gt;&amp;quot;,&lt;br /&gt;
all of String type,&lt;br /&gt;
the following blocks write concatenated strings to both outputs:&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    out1.value( in1.value() + in2.value() );&lt;br /&gt;
    out2.value( in2.value() + in1.value() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    out1 value:(in1 value , in2 value).&lt;br /&gt;
    out2 value:(in2 value , in1 value).&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
(runs inside the JVM, which may be the system under test or another machine running Java)&lt;br /&gt;
 def execute() {&lt;br /&gt;
    out1.value( in1.value() + in2.value() );&lt;br /&gt;
    out2.value( in2.value() + in1.value() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Node =====&lt;br /&gt;
(runs inside a node VM, which may be the system under test or another machine running &amp;quot;node&amp;quot;)&lt;br /&gt;
 function execute() {&lt;br /&gt;
    out1.value( in1.value() + in2.value() );&lt;br /&gt;
    out2.value( in2.value() + in1.value() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Python =====&lt;br /&gt;
(runs inside a Python interpreter, which may be the system under test or another machine running &amp;quot;python&amp;quot;)&lt;br /&gt;
 def execute():&lt;br /&gt;
    out1.value( in1.value() + in2.value() )&lt;br /&gt;
    out2.value( in2.value() + in1.value() )&lt;br /&gt;
&lt;br /&gt;
===== C =====&lt;br /&gt;
 static void execute() {&lt;br /&gt;
    char* s1 = stringValue(in1);&lt;br /&gt;
    char* s2 = stringValue(in2);&lt;br /&gt;
    char buffer[512];&lt;br /&gt;
 &lt;br /&gt;
    snprintf(buffer, sizeof(buffer), &amp;quot;%s%s&amp;quot;, s1, s2);&lt;br /&gt;
    putString(out1, buffer);&lt;br /&gt;
 &lt;br /&gt;
    snprintf(buffer, sizeof(buffer), &amp;quot;%s%s&amp;quot;, s2, s1);&lt;br /&gt;
    putString(out1, buffer);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note: be aware, that due to the Remote Procedure Call ([[Glossary#RPC|RPC]]), the calling overhead of bridged actions is in the order of milliseconds, &lt;br /&gt;
whereas actions executed inside expecco (Smalltalk and JavaScript) are executed typically within a few hundred nanoseconds.&lt;br /&gt;
&lt;br /&gt;
Thus, bridged actions are typically used to invoke longer running, complex operations or to trigger services, which run autonomous, or to talk to interfaces/devices. They are normally not be used for trivial operations like string manipulation or arithmetic.&lt;br /&gt;
&lt;br /&gt;
=== Reading/Writing Environment Variables ===&lt;br /&gt;
&lt;br /&gt;
Assuming that a String-typed environment variable named &amp;quot;&#039;&#039;IncDec&#039;&#039;&amp;quot; and an Integer-typed variable named &amp;quot;&#039;&#039;Counter&#039;&#039;&amp;quot; exist in the project&#039;s environment, and are writable,&lt;br /&gt;
the following blocks read and write to either variable:&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    if ( environmentAt(&amp;quot;IncDec&amp;quot;) == &amp;quot;inc&amp;quot; ) {&lt;br /&gt;
        environmentAt_put(&amp;quot;Counter&amp;quot;, environmentAt(&amp;quot;Counter&amp;quot;) + 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        environmentAt_put(&amp;quot;Counter&amp;quot;, environmentAt(&amp;quot;Counter&amp;quot;) - 1);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    (self environmentAt:&#039;IncDec&#039;) = &#039;inc&#039; ifTrue:[&lt;br /&gt;
        self environmentAt:&#039;Counter&#039; put:(self environmentAt:&#039;Counter&#039;)+1.&lt;br /&gt;
    ] ifFalse:[&lt;br /&gt;
        self environmentAt:&#039;Counter&#039; put:(self environmentAt:&#039;Counter&#039;)-1.&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
(runs inside the JVM, which may be the system under test or another machine running Java).&lt;br /&gt;
Notice that the environment-access from inside Groovy involves even more overhead, as those require another RPC call from Groovy back to expecco. When executed, the code below will make 4 full remote-procedure call roundtrips (1 for the call and return value, one for &amp;quot;environmentAt(IncDec)&amp;quot;, one for &amp;quot;environmentAt(Counter)&amp;quot; and a fourth one for &amp;quot;environmentAt_put()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
 def execute() {&lt;br /&gt;
    if ( environmentAt(&amp;quot;IncDec&amp;quot;) == &amp;quot;inc&amp;quot; ) {&lt;br /&gt;
        environmentAt_put(&amp;quot;Counter&amp;quot;, environmentAt(&amp;quot;Counter&amp;quot;) + 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        environmentAt_put(&amp;quot;Counter&amp;quot;, environmentAt(&amp;quot;Counter&amp;quot;) - 1);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Sending Messages to the Transcript ===&lt;br /&gt;
The &amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; refers to the expecco console, if it has been opened (via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; menu). If it is not open, &amp;quot;Trnscript&amp;quot; will refer to the standard error stream (Stderr).&lt;br /&gt;
In place of &amp;quot;Transcript&amp;quot;, the following examples also work for &amp;quot;Stdout&amp;quot; and &amp;quot;Stderr&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    Transcript.showCR(&amp;quot;---------------------&amp;quot;);&lt;br /&gt;
    for (var y=1; y&amp;lt;=10; y++) {&lt;br /&gt;
        for (var x=1; x&amp;lt;=10; x++) {&lt;br /&gt;
            Transcript.show( x * y );&lt;br /&gt;
            Transcript.show( &amp;quot; &amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
        Transcript.cr();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    Transcript showCR:&#039;---------------------&#039;.&lt;br /&gt;
    1 to:10 do:[:y |&lt;br /&gt;
        1 to:10 do:[:x |&lt;br /&gt;
            Transcript show:(x * y); show:&#039; &#039;.&lt;br /&gt;
        ].&lt;br /&gt;
        Transcript cr.&lt;br /&gt;
    ].&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
&lt;br /&gt;
A few of the common messages and objects for logging and printing are also made available to Groovy code. Of course, a hidden inter-process mechanism is used, which forwards those calls back to expecco (remember: the Groovy code runs inside the system under test). The &amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; object seen by Groovy code is such a proxy object which implements a subset of the Smalltalk Transcript object but passes the argument strings via IPC back to expecco.&lt;br /&gt;
So although the code looks similar to the above, the internal implementation (and timing) is completely different, because these calls are implemented as RPC calls from Groovy back to expecco.&lt;br /&gt;
&lt;br /&gt;
(runs inside JavaVM when executed)&lt;br /&gt;
 def execute() {&lt;br /&gt;
    Transcript.showCR(&amp;quot;---------------------&amp;quot;);&lt;br /&gt;
    for (int y=1; y&amp;lt;=10; y++) {&lt;br /&gt;
        for (int x=1; x&amp;lt;=10; x++) {&lt;br /&gt;
            Transcript.show( x * y );&lt;br /&gt;
            Transcript.show( &amp;quot; &amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
        Transcript.cr();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
For compatibility with existing Java/Groovy code, the functions &amp;lt;code&amp;gt;print()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;println()&amp;lt;/code&amp;gt; can also be used&lt;br /&gt;
(in addition to the above used &amp;lt;code&amp;gt;show()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;showCR()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;cr()&amp;lt;/code&amp;gt; functions)&lt;br /&gt;
&lt;br /&gt;
===== Node =====&lt;br /&gt;
&lt;br /&gt;
A subset of the logging and printing functions are available to Node code. Of course, a hidden inter-process mechanism is used, which forwards those calls back to expecco (remember: the code runs inside the system under test). The &amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; object seen by Node code is such a proxy object which implements a subset of the Smalltalk Transcript object, but passes the argument strings via IPC back to expecco.&lt;br /&gt;
&lt;br /&gt;
So although the code looks similar to the above, the internal implementation (and timing) is completely different, because these calls are implemented as RPC calls from Node back to expecco.&lt;br /&gt;
&lt;br /&gt;
(runs inside Node when executed)&lt;br /&gt;
 function execute() {&lt;br /&gt;
    Transcript.showCR(&amp;quot;---------------------&amp;quot;);&lt;br /&gt;
    Transcript.show( &amp;quot;hello &amp;quot; );&lt;br /&gt;
    Transcript.show( &amp;quot;world&amp;quot; );&lt;br /&gt;
    Transcript.cr();&lt;br /&gt;
    Transcript.show( &amp;quot;A message with embedded args: %1 and %2\n&amp;quot;, &amp;quot;foo&amp;quot;, 123);&lt;br /&gt;
 }&lt;br /&gt;
For compatibility with existing Node programs, you can also use &amp;quot;&amp;lt;code&amp;gt;console.log()&amp;lt;/code&amp;gt;&amp;quot; &lt;br /&gt;
and &amp;quot;&amp;lt;code&amp;gt;console.error()&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Square Root Block ===&lt;br /&gt;
&lt;br /&gt;
A function, which computes the square root of its input value, could be implemented like that:&lt;br /&gt;
(the names of the pins are: &#039;&#039;in&#039;&#039; and &#039;&#039;out&#039;&#039;, their data type is &#039;&#039;Number):&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    var inValue;&lt;br /&gt;
 &lt;br /&gt;
    inValue = in.value;          // Reading input pin value&lt;br /&gt;
    out.value( inValue.sqrt() ); // Writing to output pin&lt;br /&gt;
 }&lt;br /&gt;
alternative:&lt;br /&gt;
 execute() {&lt;br /&gt;
    var inValue;&lt;br /&gt;
 &lt;br /&gt;
    inValue = in.value;              // Reading input pin value&lt;br /&gt;
    out.value( Math.sqrt(inValue) ); // Writing to output pin&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    |inValue|&lt;br /&gt;
 &lt;br /&gt;
    inValue := in value.       &amp;quot;/ Reading input pin value&lt;br /&gt;
    out value: inValue sqrt.   &amp;quot;/ Writing to output pin&lt;br /&gt;
&lt;br /&gt;
===== Groovy=====&lt;br /&gt;
(runs inside a JVM/the SUT, when executed).&amp;lt;br&amp;gt;As mentioned above, this kind of operation should definitely be executed in Smalltalk/JavaScript inside expecco, and not in the system under test, due to the [[Glossary|RPC]] overheads.&lt;br /&gt;
 def execute {&lt;br /&gt;
    Object inValue;&lt;br /&gt;
 &lt;br /&gt;
    inValue = inPin.value();           // Reading input pin value&lt;br /&gt;
    outPin.value(Math.sqrt(inValue));   // Writing to output pin&lt;br /&gt;
 }&lt;br /&gt;
(Notice: &amp;quot;in&amp;quot; is a reserved keyword in Groovy and cannot be used as pin name)&lt;br /&gt;
&lt;br /&gt;
===== Node=====&lt;br /&gt;
(runs inside Node, when executed).&lt;br /&gt;
 function execute {&lt;br /&gt;
    outPin.value(Math.sqrt(inPin.value()));  &lt;br /&gt;
 }&lt;br /&gt;
(Notice: &amp;quot;in&amp;quot; is a reserved keyword in Node and cannot be used as pin name)&lt;br /&gt;
&lt;br /&gt;
=== Random-Fail Block ===&lt;br /&gt;
&lt;br /&gt;
A block, which randomly fails (to demonstrate exception handling), could be implemented like:&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    var dice;&lt;br /&gt;
 &lt;br /&gt;
    dice = Random.nextIntegerBetween_and_(1,6);&lt;br /&gt;
    if (dice &amp;lt;= 2) {&lt;br /&gt;
        fail();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    |dice|&lt;br /&gt;
 &lt;br /&gt;
    dice := Random nextIntegerBetween:1 and:6.&lt;br /&gt;
    (dice &amp;lt;= 2) ifTrue:[&lt;br /&gt;
        self fail.&lt;br /&gt;
    ].&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
(runs inside a JVM/the SUT, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    Random rand = new Random();&lt;br /&gt;
    int dice = rand.nextInt(5)+1;&lt;br /&gt;
 &lt;br /&gt;
    if (dice &amp;lt;= 2) {&lt;br /&gt;
        fail();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Calling other Actions ===&lt;br /&gt;
&lt;br /&gt;
Script code can call other action blocks via the &amp;quot;&amp;lt;code&amp;gt;call&amp;lt;/code&amp;gt;&amp;quot; method/function.&lt;br /&gt;
Notice, that the call is &amp;quot;&#039;&#039;by name&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;by ID&#039;&#039;&amp;quot;, and the called function is specified by a string argument.&lt;br /&gt;
The following examples assume that action blocks named &amp;quot;&#039;&#039;Action_A&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Action_B&#039;&#039;&amp;quot; are present, and that &amp;quot;Action_B&amp;quot; expects two numeric arguments and returns a value through its single output pin. &lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    var result;&lt;br /&gt;
 &lt;br /&gt;
    call(&amp;quot;Action_A&amp;quot;);&lt;br /&gt;
    result = call(&amp;quot;Action_B&amp;quot;, 123.0, 9999); &lt;br /&gt;
    Transcript.showCR(&amp;quot;got result: %1&amp;quot;, result);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    |result|&lt;br /&gt;
 &lt;br /&gt;
    self call:&#039;Action_A&#039;.&lt;br /&gt;
    result := self call:&#039;Action_B&#039; _:123.0 _:9999). &lt;br /&gt;
    Transcript showCR:(&#039;got result: %1&#039; bindWith:result).&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
runs inside a JVM/the SUT, when executed, but the called actions are expecco actions; &lt;br /&gt;
i.e. the call performs a remote-procedure-call back to expecco, to execute the called action, and continue in the JVM&#039;s action when finished.&lt;br /&gt;
 execute() {&lt;br /&gt;
    var result;&lt;br /&gt;
 &lt;br /&gt;
    call(&amp;quot;Action_A&amp;quot;);&lt;br /&gt;
    result = call(&amp;quot;Action_B&amp;quot;, 123.0, 9999); &lt;br /&gt;
    Transcript.showCR(&amp;quot;got result: %1&amp;quot;, result);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Node =====&lt;br /&gt;
runs inside the node interpreter, when executed.&lt;br /&gt;
The call performs a remote-procedure-call back to expecco, to execute the called action, and continue in the node action when finished.&lt;br /&gt;
&lt;br /&gt;
Notice, that due to the single threaded callback oriented nature of node,&lt;br /&gt;
the value from the called function is passed back via a callback function,&lt;br /&gt;
not as return value. This is required because the &amp;quot;call&amp;quot; is actually performing&lt;br /&gt;
a remote procedure call into expecco (i.e. interprocess communication).&lt;br /&gt;
It is also currently not possible to call another node action from a node action (neither directly, nor indirectly).&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
    var result;&lt;br /&gt;
    &lt;br /&gt;
    Transcript.showCR(&amp;quot;calling from Node...&amp;quot;);&lt;br /&gt;
    call(&amp;quot;Action_A&amp;quot;, function(err, result) {&lt;br /&gt;
        call(&amp;quot;Action_B&amp;quot;, 100, 200, function(err, result) {&lt;br /&gt;
            Transcript.showCR(&amp;quot;got value: %1&amp;quot;, result);&lt;br /&gt;
            success();&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Using the Smalltalk/X Class Library (Smalltalk and JavaScript Blocks Only) ===&lt;br /&gt;
&lt;br /&gt;
Please note, that besides these direct interfaces with the expecco system described here, you can also use the whole class library of the runtime system. Please check the corresponding [http://live.exept.de/doc/online/english/programming/TOP.html Smalltalk/X Documentation] as well as the [http://live.exept.de/ClassDoc Documentation of the Class APIs].&lt;br /&gt;
&lt;br /&gt;
expecco includes a fully featured class browser, to explore the underlying system&#039;s code.&lt;br /&gt;
&lt;br /&gt;
You will see the source code, if you have checked the &amp;quot;&#039;&#039;Install Source Code&#039;&#039;&amp;quot; checkbox during the installation procedure (if you did not, redo the installation, and only check this box). You can also access the source code via the public eXept CVS repository.&lt;br /&gt;
&lt;br /&gt;
The class browser is opened via the main-menu&#039;s &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Class Browser&#039;&#039;&amp;quot; item. It is documented in full detail in the [http://live.exept.de/doc/online/english/programming/TOP.html Smalltalk/X Documentation].&lt;br /&gt;
&lt;br /&gt;
Here are a few more examples, using that class library:&lt;br /&gt;
&lt;br /&gt;
=== Bulk-Data Reading from a File ===&lt;br /&gt;
&lt;br /&gt;
The following code reads a measurement data block of 100000 floating point values from file. The file was created beforehand by a recorder device, which was triggered by a dll-callout.&lt;br /&gt;
For the demonstration, the code below does not read its values from input pins. In a real world application, the size of the file and its fileName would probably be passed in via input pins, of course.&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
 execute() {&lt;br /&gt;
    var N;        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// should be read from an input-pin&amp;lt;/span&amp;gt;&lt;br /&gt;
    var fileName; &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// should be read from an input-pin&amp;lt;/span&amp;gt;&lt;br /&gt;
    var dataArray;&lt;br /&gt;
    var fileStream;&lt;br /&gt;
 &lt;br /&gt;
    N = 100000;&lt;br /&gt;
    fileName = &#039;dataFile.dat&#039;;&lt;br /&gt;
    fileStream = fileName.asFilename().readStream();&lt;br /&gt;
    dataArray = Array.new(N);&lt;br /&gt;
    for (i=1; i&amp;lt;=N; i++) {&lt;br /&gt;
        dataArray[i] = fileStream.nextIEEESingle();&lt;br /&gt;
    }&lt;br /&gt;
    out.value(dataArray);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
 execute&lt;br /&gt;
    |N fileName dataArray fileStream|&lt;br /&gt;
 &lt;br /&gt;
    N := 100000.&lt;br /&gt;
    fileName := &#039;dataFile.dat&#039;.&lt;br /&gt;
    fileStream := fileName asFilename readStream.&lt;br /&gt;
    dataArray := (1 to:N) collect:[:i | fileStream nextIEEESingle].&lt;br /&gt;
    out value:dataArray.&lt;br /&gt;
an alternative is:&lt;br /&gt;
    ...&lt;br /&gt;
    dataArray := N timesCollect:[:i | fileStream nextIEEESingle].&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
=== Opening/Using Smalltalk/X Applications, Dialogs and Components ===&lt;br /&gt;
&lt;br /&gt;
Any existing Smalltalk/X utility (both the one&#039;s which are provided with the base system, and even those coming from additional loaded Smalltalk code) can be called and used. For example, the following uses the builtin file dialog to ask for a directory.&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
 execute() {&lt;br /&gt;
    var answer;&lt;br /&gt;
 &lt;br /&gt;
    answer = Dialog.requestDirectory(&amp;quot;Please select an output folder:&amp;quot;);&lt;br /&gt;
    if ( answer.notEmptyOrNil() ) {&lt;br /&gt;
        out.value( answer );&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
 execute&lt;br /&gt;
    |answer|&lt;br /&gt;
 &lt;br /&gt;
    answer := Dialog requestDirectory: &#039;Please select an output folder:&#039;.&lt;br /&gt;
    answer notEmptyOrNil ifTrue:[&lt;br /&gt;
        out value: answer&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
Take a look at the &amp;quot;Dialog&amp;quot; class (using &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Class Browser&#039;&#039;&amp;quot;), &lt;br /&gt;
where you&#039;ll find many common standard dialogs, for confirmations, simple questions, file dialogs etc.&lt;br /&gt;
&lt;br /&gt;
=== Loading Additional Smalltalk/X Code ===&lt;br /&gt;
&lt;br /&gt;
You can even create whole library or application packages, compile it as separate package, and load it dynamically to be used from within an elementary block. Assuming that a package named &amp;quot;myPackage.dll&amp;quot; (or &amp;quot;myPackage.so&amp;quot; under Unix/Linux) containing an application class named &amp;quot;MyApplication&amp;quot; has been created and is located in the expecco bin folder, the code can be loaded and executed with:&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
 execute&lt;br /&gt;
    |answer|&lt;br /&gt;
 &lt;br /&gt;
    Smalltalk loadPackage:&#039;myPackage&#039;. &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ checks if already loaded, to only load the first time called&amp;lt;/span&amp;gt;&lt;br /&gt;
    MyApplication open.&lt;br /&gt;
&lt;br /&gt;
To create your own applications or addons, download the free [http://www.smalltalk-x.de Smalltalk/X development IDE ] for development and package building.&lt;br /&gt;
&lt;br /&gt;
== Expecco and Smalltalk API Stability ==&lt;br /&gt;
&lt;br /&gt;
The Smalltalk/X class library has been around for more than 30 years now,&lt;br /&gt;
and of course grew over time.&lt;br /&gt;
We have always tried hard to keep the API backward compatible, in not removing existing methods, even when new methods appeared, which provided a similar or superset functionality.&lt;br /&gt;
&lt;br /&gt;
Thus, code written 30 years ago can still depend on the interface and it is still working unchanged.&lt;br /&gt;
&lt;br /&gt;
We will continue to keep this backward compatibility in the future,&lt;br /&gt;
to avoid breaking customer code, whenever possible (there were very few exceptions in the past, where obvious bugs had to be fixed, and customer code already depended on the wrong behavior).&lt;br /&gt;
&lt;br /&gt;
That said, we must emphasize on that being only true for the ST/X class libraries themselves, and any officially published expecco APIs from this document.&lt;br /&gt;
&lt;br /&gt;
If you use internal expecco functionality (which you may find when browsing in the class browser),&lt;br /&gt;
we cannot guarantee backward compatibility in future versions.&lt;br /&gt;
If you feel a need for using such an interface, please consult/inform eXept to either get help on a cleaner solution, and/or inform us that the API is used and to get your used interface be marked as &amp;quot;stable EXPECCO_API&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
&lt;br /&gt;
=== Smalltalk Language Syntax (BNF) ===&lt;br /&gt;
&lt;br /&gt;
See also: [http://rosettacode.org/wiki/Category:Smalltalk Smalltalk Short Description (in rosettacode wiki)], [http://live.exept.de/doc/online/english/getstart/tut_2.html Smalltalk Basics]&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; Notice: an elementary Smalltalk action&#039;s &amp;quot;execute&amp;quot; method is a unary method (no argument).&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; there can be only one single such method in an elementary action (private functions should be defined as Smalltalk blocks)&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;;&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; This is standard Smalltalk language, with Smalltalk/X language extensions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;;&amp;lt;/span&amp;gt;&lt;br /&gt;
 method ::= selectorSpec body&lt;br /&gt;
 &lt;br /&gt;
 selectorSpec&amp;gt; ::= unarySelectorSpec&lt;br /&gt;
                   | binarySelectorSpec&lt;br /&gt;
                   | keywordSelectorSpec&lt;br /&gt;
 &lt;br /&gt;
 unarySelectorSpec ::= symbol&lt;br /&gt;
 &lt;br /&gt;
 binarySelectorSpec ::= binopSymbol identifier&lt;br /&gt;
 &lt;br /&gt;
 keywordSelectorSpec ::= ( keywordSymbol identifier )+&lt;br /&gt;
 &lt;br /&gt;
 body ::= [ &amp;quot;|&amp;quot; localVarList &amp;quot;|&amp;quot; ]  [statements]&lt;br /&gt;
 &lt;br /&gt;
 localVarList ::= ( identifier )+&lt;br /&gt;
 &lt;br /&gt;
 statements ::= statement&lt;br /&gt;
                | statement &amp;quot;.&amp;quot;&lt;br /&gt;
                | statement &amp;quot;.&amp;quot; statements&lt;br /&gt;
 &lt;br /&gt;
 statement ::= expression&lt;br /&gt;
               | returnStatement&lt;br /&gt;
 &lt;br /&gt;
 returnStatement ::= &amp;quot;^&amp;quot; expression&lt;br /&gt;
 &lt;br /&gt;
 expression ::= identifier &amp;quot;:=&amp;quot; expression&lt;br /&gt;
                | keywordExpression&lt;br /&gt;
 &lt;br /&gt;
 keywordExpression ::= binaryExpression&lt;br /&gt;
                       | binaryExpression ( keywordSymbolPart binaryExpression )+&lt;br /&gt;
 &lt;br /&gt;
 binaryExpression ::= unaryExpression&lt;br /&gt;
                      | unaryExpression ( binopSymbol unaryExpression )+&lt;br /&gt;
 &lt;br /&gt;
 unaryExpression ::= primary&lt;br /&gt;
                     | primary ( unarySymbol )+&lt;br /&gt;
 &lt;br /&gt;
 primary ::= identifier&lt;br /&gt;
             | literalConstant&lt;br /&gt;
             | expandedStringExpression&lt;br /&gt;
             | braceArray&lt;br /&gt;
             | &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot;&lt;br /&gt;
             | block&lt;br /&gt;
             | &amp;quot;self&amp;quot;&lt;br /&gt;
             | &amp;quot;super&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 identifier ::= ( &amp;quot;_&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot;)   ( &amp;quot;_&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot; | &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; )*&lt;br /&gt;
 &lt;br /&gt;
 literalConstant ::= integerConstant&lt;br /&gt;
                     | radixIntegerConstant&lt;br /&gt;
                     | floatConstant&lt;br /&gt;
                     | arrayConstant&lt;br /&gt;
                     | byteArrayConstant&lt;br /&gt;
                     | stringConstant&lt;br /&gt;
                     | characterConstant&lt;br /&gt;
                     | &amp;quot;true&amp;quot;&lt;br /&gt;
                     | &amp;quot;false&amp;quot;&lt;br /&gt;
                     | &amp;quot;nil&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 integerConstant ::= ( &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; )+&lt;br /&gt;
 &lt;br /&gt;
 radixIntegerConstant ::= base &amp;quot;r&amp;quot; baseDigits+&lt;br /&gt;
 &lt;br /&gt;
 base ::= integerConstant (valid are: 2-31)&lt;br /&gt;
 &lt;br /&gt;
 baseDigits := &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; (valid are &amp;quot;0&amp;quot;..&amp;quot;0&amp;quot;+base-1 and &amp;quot;a&amp;quot;..&amp;quot;a&amp;quot;+base-10-1 and &amp;quot;A&amp;quot;..&amp;quot;A&amp;quot;+base-10-1)&lt;br /&gt;
 &lt;br /&gt;
 floatConstant ::= [ &amp;quot;-&amp;quot; ] [ digits+ ] &amp;quot;.&amp;quot; [ digits+ ] [ (&amp;quot;e&amp;quot; | &amp;quot;E&amp;quot; | &amp;quot;d&amp;quot; | &amp;quot;D&amp;quot;) [ &amp;quot;-&amp;quot;] digits+ ]&lt;br /&gt;
 &lt;br /&gt;
 arrayConstant ::= &amp;quot;#(&amp;quot; literalConstant* &amp;quot;)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 byteArrayConstant ::= &amp;quot;#[&amp;quot; integerConstant(0..255)* &amp;quot;]&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 stringConstant ::= &#039; characters...  &#039; &lt;br /&gt;
                    | cString&lt;br /&gt;
 &lt;br /&gt;
 characterConstant ::= &amp;quot;$&amp;quot; character&lt;br /&gt;
  &lt;br /&gt;
 block ::= &amp;quot;[&amp;quot; [ blockArgList ] body &amp;quot;]”&lt;br /&gt;
 &lt;br /&gt;
 blockArgList ::= (identifier&amp;quot;:&amp;quot; )*&lt;br /&gt;
 &lt;br /&gt;
 comment ::= &amp;quot; &amp;quot; &amp;quot; any-character* &amp;quot; &amp;quot; &amp;quot; | eolComment&lt;br /&gt;
 &lt;br /&gt;
 unarySymbol ::= identifier&lt;br /&gt;
 &lt;br /&gt;
 binopSymbol ::= ( &amp;quot;+&amp;quot; | &amp;quot;-&amp;quot; | &amp;quot;*&amp;quot; | &amp;quot;/&amp;quot; | &amp;quot;\&amp;quot; | &amp;quot;,&amp;quot; | &amp;quot;@&amp;quot; | &amp;quot;%&amp;quot; | &amp;quot;&amp;amp;&amp;quot; | &amp;quot;=&amp;quot; | &amp;quot;&amp;lt;&amp;quot; | &amp;quot;&amp;gt;&amp;quot; | &amp;quot;~&amp;quot; )+&lt;br /&gt;
 &lt;br /&gt;
 keywordSymbolPart ::= identifier&amp;quot;:&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 keywordSymbol ::= keywordSymbolPart+&lt;br /&gt;
 &lt;br /&gt;
 symbolConstant ::= &amp;quot;#&amp;quot;unarySymbol&lt;br /&gt;
                    | &amp;quot;#&amp;quot;binarySymbol&lt;br /&gt;
                    | &amp;quot;#&amp;quot;keywordSymbol&lt;br /&gt;
                    | &amp;quot;#&#039;&amp;quot;any-character*&amp;quot;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Smalltalk/X Language Extensions (BNF) ====&lt;br /&gt;
&lt;br /&gt;
Smalltalk/X provides a few very useful syntax extensions w.r.t. standard Ansi Smalltalk:&lt;br /&gt;
&lt;br /&gt;
 eolComment ::= &amp;quot; &amp;quot;/ &amp;quot; any-character-up-to-end-of-line&lt;br /&gt;
 &lt;br /&gt;
 tokenComment ::= &amp;quot; &amp;quot;&amp;lt;&amp;lt;&amp;quot;TOKEN&lt;br /&gt;
                     ...  &lt;br /&gt;
                     any number of lines not beginning with TOKEN&lt;br /&gt;
                     (where TOKEN is any valid identifier string)&lt;br /&gt;
                     ...&lt;br /&gt;
                     TOKEN&lt;br /&gt;
 &lt;br /&gt;
 braceArray ::= &amp;quot;{&amp;quot; [ expression | expression ( &amp;quot;.&amp;quot; expression )+ ] &amp;quot;}&amp;quot; (an array with computed elements)&lt;br /&gt;
 &lt;br /&gt;
 literalObject ::= &amp;quot;#{&amp;quot; ( fieldName: constant )+ &amp;quot;}&amp;quot;  (a constant object with getters for fields)&lt;br /&gt;
 &lt;br /&gt;
 immediateObject ::= &amp;quot;{&amp;quot; ( fieldName: expression )+ &amp;quot;}&amp;quot; (an immediate object with getters and setters)&lt;br /&gt;
 &lt;br /&gt;
 cString ::= c&#039;string with C-escapes&#039;&lt;br /&gt;
 &lt;br /&gt;
 eString ::= e&#039;string with C-escapes and {embedded expressions}&#039;&lt;br /&gt;
 &lt;br /&gt;
 iString ::= i&#039;string with C-escapes and {embedded expressions} which is also internationalized&#039;&lt;br /&gt;
 &lt;br /&gt;
 typedArrayLiteral ::= #u8(...)     &amp;quot;/ unsigned byte array constant&lt;br /&gt;
                       | #s8(...)   &amp;quot;/ signed byte array constant&lt;br /&gt;
                       | #u16(...)  &amp;quot;/ unsigned int16 array constant&lt;br /&gt;
                       | #s16(...)  &amp;quot;/ signed int16 array constant&lt;br /&gt;
                       | #u32(...)  &amp;quot;/ unsigned int32 array constant&lt;br /&gt;
                       | #s32(...)  &amp;quot;/ signed int32 array constant&lt;br /&gt;
                       | #u64(...)  &amp;quot;/ unsigned int64 array constant&lt;br /&gt;
                       | #s64(...)  &amp;quot;/ signed int64 array constant&lt;br /&gt;
                       | #f32(...)  &amp;quot;/ single precision IEEE float array constant&lt;br /&gt;
                       | #f64(...)  &amp;quot;/ double precision IEEE float array constant&lt;br /&gt;
  &lt;br /&gt;
 cStyleInt ::= 0xXXX&lt;br /&gt;
               | 0oOOO&lt;br /&gt;
               | 0bBBB&lt;br /&gt;
 &lt;br /&gt;
 indexedAccess ::= array-expr &amp;quot;[&amp;quot; index-expr &amp;quot;]&amp;quot;&lt;br /&gt;
                   | array-expr &amp;quot;[&amp;quot; index1-expr &amp;quot;][&amp;quot; index2-expr &amp;quot;]&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 indexedStore ::= array-expr &amp;quot;[&amp;quot; index-expr &amp;quot;]&amp;quot; := &amp;lt;expr&amp;gt;&lt;br /&gt;
                  | array-expr &amp;quot;[&amp;quot; index1-expr &amp;quot;][&amp;quot; index2-expr &amp;quot;]&amp;quot; := &amp;lt;expr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JavaScript Language Syntax (BNF) ===&lt;br /&gt;
&lt;br /&gt;
-- incomplete w.r.t. expression syntax -- to be added&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; Notice: an elementary JavaScript action&#039;s &amp;quot;execute&amp;quot; function&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; must be a unary function (no argument).&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; However, it is possible to define additional (private) helper functions.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; These will only be visible within that single elementary action&#039;s code.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; Also notice the syntax extensions for character constants and the &amp;quot;return from&amp;quot; statement.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; &amp;lt;/span&amp;gt;&lt;br /&gt;
 method ::= functionSpec functionBody&lt;br /&gt;
 &lt;br /&gt;
 functionSpec ::= [&amp;quot;async&amp;quot;] &amp;quot;function&amp;quot; identifier &amp;quot;(&amp;quot;  [argList] &amp;quot;)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 functionBody ::= &amp;quot;{&amp;quot; (statement)+ &amp;quot;}&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 statement ::= varDeclaration&lt;br /&gt;
                      | ifStatement&lt;br /&gt;
                      | whileStatement&lt;br /&gt;
                      | doStatement&lt;br /&gt;
                      | forStatement&lt;br /&gt;
                      | tryCatchStatement&lt;br /&gt;
                      | switchStatement&lt;br /&gt;
                      | returnStatement&lt;br /&gt;
                      | &amp;quot;{&amp;quot; (statement)+ &amp;quot;}&amp;quot;&lt;br /&gt;
                      | expression&lt;br /&gt;
 &lt;br /&gt;
 varDeclaration ::= &amp;quot;var&amp;quot; identifier ( &amp;quot;,&amp;quot;  identifier)* &amp;quot;;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 ifStatement ::= &amp;quot;if&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot; statement&lt;br /&gt;
                         [ &amp;quot;else&amp;quot; statement ]&lt;br /&gt;
 &lt;br /&gt;
 whileStatement ::= &amp;quot;while&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot; statement&lt;br /&gt;
  &lt;br /&gt;
 doStatement ::= &amp;quot;do&amp;quot; statement &amp;quot;while&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot;  &amp;quot;;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 forStatement ::= &amp;quot;for&amp;quot; &amp;quot;(&amp;quot; [expression] &amp;quot;;&amp;quot; [expression] &amp;quot;;&amp;quot; [expression] &amp;quot;)&amp;quot; statement&lt;br /&gt;
 &lt;br /&gt;
 tryCatchStatement ::= &amp;quot;try&amp;quot; statement (catchClause | finallyClause | catchFinallyClause)&lt;br /&gt;
 &lt;br /&gt;
 catchClause ::= &amp;quot;catch&amp;quot;  &amp;quot;(&amp;quot; identifier [identifier] &amp;quot;)&amp;quot; statement&lt;br /&gt;
 &lt;br /&gt;
 finallyClause ::= &amp;quot;finally&amp;quot;  statement&lt;br /&gt;
 &lt;br /&gt;
 catchFinallyClause ::= catchClause finallyClause&lt;br /&gt;
 &lt;br /&gt;
 switchStatement ::= &amp;quot;switch&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot; &amp;quot;{&amp;quot; (&amp;quot;case constantExpression &amp;quot;:&amp;quot; statement)+ [ &amp;quot;default:&amp;quot; statement+ &amp;quot;}&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 returnStatement ::= &amp;quot;return&amp;quot; expression [ &amp;quot;from&amp;quot; identifier ]&lt;br /&gt;
 &lt;br /&gt;
 expression ::= term ( (&amp;quot;+&amp;quot; | &amp;quot;-&amp;quot;) term)*&lt;br /&gt;
                | &amp;quot;await&amp;quot; expression&lt;br /&gt;
 &lt;br /&gt;
 term ::= factor ( (&amp;quot;*&amp;quot; | &amp;quot;/&amp;quot; | &amp;quot;%&amp;quot; ) factor)*&lt;br /&gt;
 &lt;br /&gt;
 factor ::= powExpr ( &amp;quot;**&amp;quot;  powExpr)*&lt;br /&gt;
 &lt;br /&gt;
 powExpr ::= &amp;quot;typeof&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot;&lt;br /&gt;
                | &amp;quot;!&amp;quot; factor&lt;br /&gt;
                | &amp;quot;-&amp;quot; factor&lt;br /&gt;
                | &amp;quot;++&amp;quot; factor&lt;br /&gt;
                | &amp;quot;--&amp;quot; factor&lt;br /&gt;
                | primary &amp;quot;--&amp;quot;&lt;br /&gt;
                | primary &amp;quot;++&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 primary ::= identifier&lt;br /&gt;
                   | literalConstant&lt;br /&gt;
                   | arrayExpression&lt;br /&gt;
                   | &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot;&lt;br /&gt;
                   | block&lt;br /&gt;
                   | &amp;quot;this&amp;quot;&lt;br /&gt;
                   | &amp;quot;super&amp;quot;&lt;br /&gt;
                   | &amp;quot;new&amp;quot; classIdentifier [ &amp;quot;(&amp;quot; constant &amp;quot;)&amp;quot; ]&lt;br /&gt;
                   | functionDefinition&lt;br /&gt;
                   | lambdaFunction&lt;br /&gt;
 &lt;br /&gt;
 functionDefinition ::= &amp;quot;function&amp;quot; [functionName] &amp;quot;(&amp;quot;  [argList] &amp;quot;)&amp;quot; functionBody&lt;br /&gt;
 &lt;br /&gt;
 lambdaFunction ::= &amp;quot;(&amp;quot;  [argList] &amp;quot;)&amp;quot; &amp;quot;=&amp;gt;&amp;quot; functionBody&lt;br /&gt;
                   | arg &amp;quot;=&amp;gt;&amp;quot; functionBody&lt;br /&gt;
                   | &amp;quot;(&amp;quot;  [argList] &amp;quot;)&amp;quot; &amp;quot;=&amp;gt;&amp;quot; expression&lt;br /&gt;
                   | arg &amp;quot;=&amp;gt;&amp;quot; expression&lt;br /&gt;
  &lt;br /&gt;
 identifier ::= ( &amp;quot;_&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot;)   ( &amp;quot;_&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot; | &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; )*&lt;br /&gt;
 &lt;br /&gt;
 literalConstant ::= integerConstant&lt;br /&gt;
                              | radixIntegerConstant&lt;br /&gt;
                              | floatConstant&lt;br /&gt;
                              | arrayConstant&lt;br /&gt;
                              | byteArrayConstant&lt;br /&gt;
                              | stringConstant&lt;br /&gt;
                              | characterConstant&lt;br /&gt;
                              | &amp;quot;true&amp;quot;&lt;br /&gt;
                              | &amp;quot;false&amp;quot;&lt;br /&gt;
                              | &amp;quot;null&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 integerConstant ::= ( &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; )+&lt;br /&gt;
 &lt;br /&gt;
 radixIntegerConstant ::= hexIntegerConstant | octalIntegerConstant | binaryIntegerConstant&lt;br /&gt;
 &lt;br /&gt;
 hexIntegerConstant ::= &amp;quot;0x&amp;quot;hexDigit+&lt;br /&gt;
 &lt;br /&gt;
 hexDigit := &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;F&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;f&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 octalIntegerConstant ::= &amp;quot;0&amp;quot;octalDigit+&lt;br /&gt;
 &lt;br /&gt;
 octalDigit := &amp;quot;0&amp;quot;-&amp;quot;7&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 binaryIntegerConstant ::= &amp;quot;0b&amp;quot;binaryDigit+&lt;br /&gt;
 &lt;br /&gt;
 binaryDigit := &amp;quot;0&amp;quot; | &amp;quot;1&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 floatConstant ::= [ &amp;quot;-&amp;quot; ] [ digits+ ] &amp;quot;.&amp;quot; [ digits+ ] [ (&amp;quot;e&amp;quot; | &amp;quot;E&amp;quot; | &amp;quot;d&amp;quot; | &amp;quot;D&amp;quot;) [ &amp;quot;-&amp;quot;] digits+ ]&lt;br /&gt;
 &lt;br /&gt;
 arrayConstant ::= &amp;quot;[&amp;quot; [literalConstant (&amp;quot;,&amp;quot; literalConstant)*] &amp;quot;]&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 arrayExpression ::= &amp;quot;[&amp;quot; [expression (&amp;quot;,&amp;quot; expression)*] &amp;quot;]&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 stringConstant ::= apos character* apos &lt;br /&gt;
                  | quote character* quote&lt;br /&gt;
 &lt;br /&gt;
 characterConstant ::= &amp;quot;$&amp;quot; character&lt;br /&gt;
 &lt;br /&gt;
 apos ::= &amp;quot;&#039;&amp;quot;&#039; (single quote)&lt;br /&gt;
 &lt;br /&gt;
 quote ::= &amp;quot; &amp;quot; &amp;quot; (double quote)&lt;br /&gt;
 &lt;br /&gt;
 comment ::= &amp;quot;/*&amp;quot; any-character* &amp;quot; */ &amp;quot; | eolComment&lt;br /&gt;
 &lt;br /&gt;
 eolComment ::= &amp;quot; // &amp;quot; any-character-up-to-end-of-line&lt;br /&gt;
&lt;br /&gt;
Notice the nonstandard extension for single character constants&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Back to [[ Online_Documentation#Code_API_Overview Online Documentation ]]&lt;br /&gt;
&lt;br /&gt;
[[Category: Advanced/en]]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Code_Editor/en&amp;diff=30902</id>
		<title>Code Editor/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Code_Editor/en&amp;diff=30902"/>
		<updated>2026-02-23T11:35:20Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 12.2.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Introduction ==&lt;br /&gt;
[[Bild:Code Editor.png|thumb|300px|Code Editor]]&lt;br /&gt;
The code editor is used to view and edit the source code of an [[ElementaryBlock_Element/en | elementary block]]. It is found on the &amp;quot;&#039;&#039;Code&#039;&#039;&amp;quot; tab after selecting an elementary block in the navigation tree. The same editor is also used in all tools (File-Browser, Data-Viewers, Inspectors, Notepad, Documentation Editor, Debugger etc.)&lt;br /&gt;
&lt;br /&gt;
An example for some code in the editor is shown on the right.&lt;br /&gt;
&lt;br /&gt;
The editor consists of a language drop down list item at the top, and a code editor area, which covers the rest of the editor&#039;s space. The code input area is a regular text editor which provides syntax coloring and some code-related functions on its pop-up (right button) menu.&lt;br /&gt;
&lt;br /&gt;
The drop down list selects the programming language in which the block is to be coded. If changed, the system tries to convert the current code into the newly selected language, which is only possible/supported for some language combinations. The block&#039;s icon is adjusted depending on the language.&lt;br /&gt;
&lt;br /&gt;
When an elementary block is initially created, some template code is shown in the editor. This consists of the &amp;quot;&amp;lt;code&amp;gt;execute&amp;lt;/code&amp;gt;&amp;quot; function body, a comment which gives advice on how to access the input and output values, and a transcript command which prints a standard output message to the transcript. Thus, the block can be immediately executed and does &amp;quot;something useful&amp;quot;. Once you get familiar with elementary code, this template comment can be disabled via the settings menu (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Look &amp;amp; Feel&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Code Editor&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Long Code Template&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Usually, you will cut out the comment and the transcript command, and replace it by your own code. The function name and body delimiters should be left as is. While typing, a just-in-time parser performs syntax coloring and some syntactic and semantic checks. Most errors and typos are thus detected immediately at editing time.&lt;br /&gt;
&lt;br /&gt;
The [[expecco API]] describes some appropriate method calls for JavaScript and Smalltalk. To access the full protocol of the underlying framework classes, use a system browser from the tools menu or refer to the [http://live.exept.de/doc/online/english/TOP.html &amp;quot;Smalltalk/X Online Documentation&amp;quot;] or the [http://live.exept.de/ClassDoc &amp;quot;Smalltalk/X Online Class Documentation&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
== Programming Language Awareness ==&lt;br /&gt;
&lt;br /&gt;
==== Builtin Languages ====&lt;br /&gt;
&lt;br /&gt;
Currently, two programming languages are built right into expecco. These are translated into an internal compact bytecode form whenever code is &amp;quot;&#039;&#039;accepted&#039;&#039;&amp;quot;, and further compiled to machine code whenever the action block is first invoked. The languages are the system&#039;s underlying [[ Expecco_API#expecco_API | Smalltalk ]] language and a [[ Expecco_API#expecco_API | JavaScript ]] lookalike language, which follows the syntax of JavaScript, but has an object and inheritance model of the underlying Smalltalk system (i.e. it is class based, not instance based, and does not support dynamic change of an object&#039;s slot layout).&lt;br /&gt;
&lt;br /&gt;
These built-in languages are fully supported by the code editor and the debugger: you can place breakpoints (or explicit &amp;quot;halts&amp;quot;) into the code, single step, inspect local variables etc. Also, syntax coloring, code completion and quick syntax checking are supported for those built-in languages.&lt;br /&gt;
&lt;br /&gt;
The API is described in the the &amp;quot;[[expecco API]]&amp;quot; document.&lt;br /&gt;
&amp;lt;br&amp;gt;The underlying Smalltalk system is described on the [https://live.exept.de/doc/online/english/TOP.html  Smalltalk/X website]&lt;br /&gt;
&lt;br /&gt;
==== Non Builtin (Bridged) Languages ====&lt;br /&gt;
&lt;br /&gt;
For some languages a [[ElementaryBlock_Element/en#Bridged_Actions | bridge framework]] is provided. Bridges setup a communication channel to an external language interpreter. This interpreter is started once, when the very first such action is to be executed, and kept alive. So any internal state of the interpreter (open files, protocol channels, objects or frameworks) can be accessed by later actions.&lt;br /&gt;
&lt;br /&gt;
For NodeJS and Python, debugging support is partially implemented or being developed.&lt;br /&gt;
&lt;br /&gt;
[[ElementaryBlock_Element/en#Bridged_Actions | Bridged code execution]] is supported for:&lt;br /&gt;
* [[ElementaryBlock_Element/en#Groovy_Language | Groovy / Java]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#Bridged_NodeJS_Actions | Node.js]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#Python_Blocks_.28Bridged.29 | Python, Jython and IronPython]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#Ruby_Blocks_.28Bridged.29 | Ruby]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#Bridged_Smalltalk_Actions | Smalltalk (eg. on a remote machine)]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#C Blocks (Bridged) | C ]]&lt;br /&gt;
&lt;br /&gt;
==== Non Builtin (Script) Languages ====&lt;br /&gt;
&lt;br /&gt;
Other (non-builtin) script languages are processed and executed by external interpreters, and the editor may not be aware of or support any language specific editing support. For some languages, syntax highlighting and comment detection is provided.&lt;br /&gt;
For other languages, neither breakpoints, nor single stepping, nor evaluation of expressions or inspection of values in the debugger are possible in general.&lt;br /&gt;
&lt;br /&gt;
For example, shell and batch scripts are executed by forwarding the code to an appropriate command line interpreter.&lt;br /&gt;
&lt;br /&gt;
[[ElementaryBlock_Element/en#Script_Action_Blocks | Script language]] programs written for &lt;br /&gt;
* [[ElementaryBlock_Element/en#Shell_Script_Blocks | Unix/Linux Shell]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#Batch_Script_Blocks | Windows Batch]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#AppleScript_Blocks | AppleScript]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#Ruby_Script_Blocks | Ruby]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#Node.js-Script_Blocks | Node.js]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#Python_Script_Blocks | Python and Jython]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#TCL.2C_Perl_and_Go_Script_Actions | Tcl, Perl and Go]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#R_Action_Blocks | &#039;R&#039;]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#Plot.2FGraph_Action_Blocks | GnuPlot]]&lt;br /&gt;
* [[ElementaryBlock_Element/en#GNU_Octave_Action_Blocks | GNU Octave (a Matlab clone)]]&lt;br /&gt;
 &lt;br /&gt;
are executed by an appropriate external scripting engine.&lt;br /&gt;
&lt;br /&gt;
Debugging facilities are limited for those external languages (no single stepping, for example). Although not normally a major issue (as these languages are less used inside expecco), language support for those can be made available by defining an external language editor in the settings dialog. For example, under Windows, a Notepad++ or under Unix, an Emacs editor may be useful in some situations.&lt;br /&gt;
&lt;br /&gt;
== Mouse Click and Selection ==&lt;br /&gt;
&lt;br /&gt;
Single click the left mouse button to move the cursor.&lt;br /&gt;
Click and drag to select a piece of text.&lt;br /&gt;
&lt;br /&gt;
Double click to select a word.&lt;br /&gt;
Double click and drag (not releasing the mouse button after the second click) will select more text word-wise.&lt;br /&gt;
&lt;br /&gt;
Triple click to select a line.&lt;br /&gt;
Triple click and drag (not releasing the mouse button after the third click) will select more text line-wise.&lt;br /&gt;
&lt;br /&gt;
Quadruple click to select the whole text.&lt;br /&gt;
&lt;br /&gt;
The selection can extended either by pressing the mouse button and the &amp;lt;kbd&amp;gt;Shift&amp;lt;/kbd&amp;gt; key simultaneously,&lt;br /&gt;
or the &amp;lt;kbd&amp;gt;Shift&amp;lt;/kbd&amp;gt; key and one of the cursor keys. If no previous selection exists, the selection is extended from the previous cursor position.&lt;br /&gt;
&lt;br /&gt;
A right button click shows the editor&#039;s menu, which contains more editing functions, including many useful operations in its &amp;quot;&#039;&#039;Misc&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;More&#039;&#039;&amp;quot; submenus.&lt;br /&gt;
&lt;br /&gt;
== Special Characters ==&lt;br /&gt;
To enter special characters which are not on your keyboard and cannot be entered via &amp;lt;kbd&amp;gt;ALT&amp;lt;/kbd&amp;gt;-key combinations, open a &amp;quot;special characters&amp;quot;-dialog via the popup menu (&amp;quot;&#039;&#039;More&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Special Characters&#039;&#039;&amp;quot;). This presents all possible characters of the Unicode character set. This dialog can be used like a second keyboard; click on the character to get it inserted at the current cursor position. You can keep this window open and around to enter multiple characters.&lt;br /&gt;
&lt;br /&gt;
== National Characters on International Keyboards ==&lt;br /&gt;
These can be entered either via the special characters dialog (found in the context menu under &amp;quot;&#039;&#039;More&#039;&#039;&amp;quot;) or by enabling the dead key input feature (unless this is already done by your operating system). The dead key feature can be enabled globally for all editors (via the &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Look&amp;amp;Feel&#039;&#039;&amp;quot; dialog), or for an individual editor via its context menu (&amp;quot;&#039;&#039;More&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Misc&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Dead Keys&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
With dead keys enabled, type one of the diacritical character (i.e. quote, tilde, double quote, grave or acute) followed by a character. Press the Cursor-Right key or Space to get the diacritical character in isolation.&lt;br /&gt;
&lt;br /&gt;
== Editor Functions and Keyboard Shortcuts ==&lt;br /&gt;
&lt;br /&gt;
The editor provides the most common edit functions both via its right-button pop-up menu and via keyboard shortcuts.&lt;br /&gt;
For some functions, more than one keyboard shortcut is present (the reason is that on some systems, some shortcuts are reserved by the operating system or window manager, so that the alternative shortcut must be used, or that not all keyboards have all keys).&lt;br /&gt;
&lt;br /&gt;
A more detailed description of the editor&#039;s features is found in the [http://live.exept.de/doc/online/english/getstart/TOP.html#EDITING Smalltalk/X online manual&#039;s &amp;quot;Editing Text&amp;quot; section].&lt;br /&gt;
&lt;br /&gt;
The most useful operations are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Function      !! Shortcut (s)                          !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Cut           || &amp;lt;kbd&amp;gt;Ctrl-x&amp;lt;/kbd&amp;gt;                     || Cut the selected text. The text is placed into the clipboard and can be pasted via Paste (also into other programs).&lt;br /&gt;
|-&lt;br /&gt;
| Copy          || &amp;lt;kbd&amp;gt;Ctrl-c&amp;lt;/kbd&amp;gt;                     || Copy the selected text. The text is placed into the clipboard and can be pasted via Paste.&lt;br /&gt;
|-&lt;br /&gt;
| Paste         || &amp;lt;kbd&amp;gt;Ctrl-v&amp;lt;/kbd&amp;gt;                     || Paste the previously copied or cut text (i.e. the text from the clipboard). The text can be pasted multiple times.&lt;br /&gt;
|-&lt;br /&gt;
| Paste Previous         || &amp;lt;kbd&amp;gt;Ctrl-V&amp;lt;/kbd&amp;gt;            || Paste a previously copied or cut text (i.e. from the clipboard history).&lt;br /&gt;
|-&lt;br /&gt;
| Undo          || &amp;lt;kbd&amp;gt;Ctrl-z&amp;lt;/kbd&amp;gt;                     || Undo the previous edit operation or text insertion.&lt;br /&gt;
|-&lt;br /&gt;
| Redo          || &amp;lt;kbd&amp;gt;Ctrl-y&amp;lt;/kbd&amp;gt;                     || Undo the previous undo.&lt;br /&gt;
|-&lt;br /&gt;
| Delete        || &amp;lt;kbd&amp;gt;Del&amp;lt;/kbd&amp;gt; or &amp;lt;kbd&amp;gt;Backspace&amp;lt;/kbd&amp;gt;|| Delete the selected text without affecting the clipboard.&amp;lt;br&amp;gt;If nothing is selected, &amp;lt;kbd&amp;gt;Del&amp;lt;/kbd&amp;gt; deletes the next character whereas &amp;lt;kbd&amp;gt;Backspace&amp;lt;/kbd&amp;gt; deletes the previous.&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;3 style=&amp;quot;text-align:center&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| Again         || &amp;lt;kbd&amp;gt;F8&amp;lt;/kbd&amp;gt;                         || Repeat the previous cut or replace operation. Implies a search for the next occurrence of the affected text.&amp;lt;br&amp;gt;This is a very useful function, eg. to replace multiple occurrences of a string by another, you double-click on the first, type over it, and press &amp;quot;&#039;&#039;Again&#039;&#039;&amp;quot; to repeat.&amp;lt;br&amp;gt;The right-button menu also contains an &amp;quot;&#039;&#039;Again For All&#039;&#039;&amp;quot; function, which repeats the last operation for every occurrence.&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;3 style=&amp;quot;text-align:center&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| Goto          || &amp;lt;kbd&amp;gt;Ctrl-g&amp;lt;/kbd&amp;gt;                     || Goto a given line number&lt;br /&gt;
|-&lt;br /&gt;
| Find          || &amp;lt;kbd&amp;gt;Ctrl-f&amp;lt;/kbd&amp;gt;                     || Open a search / search+replace dialog&lt;br /&gt;
|-&lt;br /&gt;
| Find-Forward  || &amp;lt;kbd&amp;gt;Cmd-f&amp;lt;/kbd&amp;gt;                  || Search forward for the currently selected text or the previous searched text (if the text selection was unchanged).&lt;br /&gt;
|-&lt;br /&gt;
| Find-Backward || &amp;lt;kbd&amp;gt;Cmd-b&amp;lt;/kbd&amp;gt;                  || Search backward for the currently selected text or the previous searched text.&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;3 style=&amp;quot;text-align:center&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| Begin of Line || &amp;lt;kbd&amp;gt;Pos1&amp;lt;/kbd&amp;gt;&amp;lt;br&amp;gt;or &amp;lt;kbd&amp;gt;Home&amp;lt;/kbd&amp;gt;                     || Move the cursor to the first non space in the current line. If pressed again, move to the very begin. The key is labelled &amp;lt;kbd&amp;gt;Home&amp;lt;/kbd&amp;gt; on many keyboards.&lt;br /&gt;
|-&lt;br /&gt;
| Begin of Page&amp;lt;br&amp;gt;Begin of Text|| &amp;lt;kbd&amp;gt;Ctrl-Pos1&amp;lt;/kbd&amp;gt;&amp;lt;br&amp;gt;or &amp;lt;kbd&amp;gt;Ctrl-Home&amp;lt;/kbd&amp;gt;                    || Move the cursor to the top of the page; press again to move to the top of the text &lt;br /&gt;
|-&lt;br /&gt;
| End of Line || &amp;lt;kbd&amp;gt;Ctrl-e&amp;lt;/kbd&amp;gt;&amp;lt;br&amp;gt;or &amp;lt;kbd&amp;gt;End&amp;lt;/kbd&amp;gt;                     || Move the cursor to the end of the current line&lt;br /&gt;
|-&lt;br /&gt;
| End of Page&amp;lt;br&amp;gt;End of Text|| &amp;lt;kbd&amp;gt;Ctrl-End&amp;lt;/kbd&amp;gt;                    || Move the cursor to the end of the page; press again to move to the end of the text &lt;br /&gt;
|-&lt;br /&gt;
| Next-Word     || &amp;lt;kbd&amp;gt;Ctrl-w&amp;lt;/kbd&amp;gt;                     || Move the cursor to the next word. Press multiple times to advance&lt;br /&gt;
|-&lt;br /&gt;
| Select next Word   || &amp;lt;kbd&amp;gt;Cmd-w&amp;lt;/kbd&amp;gt;                  || Select the word under the cursor, the space between or the next word.&amp;lt;br&amp;gt;Press multiple times to advance to the next word&lt;br /&gt;
|-&lt;br /&gt;
| Select plus Word   || &amp;lt;kbd&amp;gt;Cmd-W&amp;lt;/kbd&amp;gt;                  || Extends the selection by the next word under the cursor, the space between or the next word.&amp;lt;br&amp;gt;Press multiple times to select more words&lt;br /&gt;
|-&lt;br /&gt;
| Select-Line   || &amp;lt;kbd&amp;gt;Cmd-l&amp;lt;/kbd&amp;gt;                  || Select the cursor line, the space between or the next word.&amp;lt;br&amp;gt;Press multiple times to select more lines&lt;br /&gt;
|-&lt;br /&gt;
| Select-All    || &amp;lt;kbd&amp;gt;Cmd-a&amp;lt;/kbd&amp;gt;                  || Select the whole text&lt;br /&gt;
|-&lt;br /&gt;
| Select from Begin || &amp;lt;kbd&amp;gt;Cmd-A&amp;lt;/kbd&amp;gt;                  || Select the text from start to the cursor&lt;br /&gt;
|-&lt;br /&gt;
| Select to End || &amp;lt;kbd&amp;gt;Cmd-E&amp;lt;/kbd&amp;gt;                  || Select the text from the cursor to the end&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;3 style=&amp;quot;text-align:center&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| DoIt          || &amp;lt;kbd&amp;gt;Ctrl-d&amp;lt;/kbd&amp;gt;                     || Execute the selected text as a Smalltalk or JavaScript expression.&amp;lt;br&amp;gt;If there is no selection, the whole contents of the current cursor line is executed.&lt;br /&gt;
|-&lt;br /&gt;
| PrintIt       || &amp;lt;kbd&amp;gt;Ctrl-p&amp;lt;/kbd&amp;gt;                     || Execute the selected text as a Smalltalk or JavaScript expression and paste the result&lt;br /&gt;
|-&lt;br /&gt;
| InspectIt     || &amp;lt;kbd&amp;gt;Ctrl-q&amp;lt;/kbd&amp;gt;                     || Execute the selected text as a Smalltalk or JavaScript expression and show the result in an inspector window&lt;br /&gt;
|-&lt;br /&gt;
| BrowseIt     || &amp;lt;kbd&amp;gt;Ctrl-B&amp;lt;/kbd&amp;gt;                     || Evaluate the selected text as a Smalltalk or JavaScript expression and open a class browser on the class of the result. If a class name is selected, that classes source code is shown.&lt;br /&gt;
|-&lt;br /&gt;
| ImpementorsOfIt     || &amp;lt;kbd&amp;gt;Ctrl-I&amp;lt;/kbd&amp;gt;                     || Open a class browser on all implementations of the selected message name. For C and Java programmers: all virtual functions in the system which implement the selected &#039;function&#039; name are shown. Because methods are not functions, these are called &amp;quot;methods&amp;quot; in Smalltalk. Period.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|colspan=&amp;quot;3 style=&amp;quot;text-align:center&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| Indent        || select+&amp;lt;kbd&amp;gt;Tab&amp;lt;/kbd&amp;gt;            || indent the selected line(s) or the current line if none is selected by one tab.&lt;br /&gt;
|-&lt;br /&gt;
| Undent        || select+&amp;lt;kbd&amp;gt;Shift&amp;lt;/kbd&amp;gt;-&amp;lt;kbd&amp;gt;Tab&amp;lt;/kbd&amp;gt;      || undent the selected line(s) by one tab&lt;br /&gt;
|-&lt;br /&gt;
| Indent4       || &amp;lt;kbd&amp;gt;F12&amp;lt;/kbd&amp;gt;                        || indent the selected line(s) by 4&lt;br /&gt;
|-&lt;br /&gt;
| Undent4       || &amp;lt;kbd&amp;gt;F11&amp;lt;/kbd&amp;gt;                        || undent the selected line(s) by 4&lt;br /&gt;
|-&lt;br /&gt;
| Indent1       || &amp;lt;kbd&amp;gt;F10&amp;lt;/kbd&amp;gt;                        || indent the selected line(s) by 1&lt;br /&gt;
|-&lt;br /&gt;
| Undent1       || &amp;lt;kbd&amp;gt;F9&amp;lt;/kbd&amp;gt;                         || undent the selected line(s) by 1&lt;br /&gt;
|-&lt;br /&gt;
| Change Case   || &amp;lt;kbd&amp;gt;F6&amp;lt;/kbd&amp;gt;                         || toggle the selection between UPPERCASE, Titlecase and lowercase&lt;br /&gt;
|-&lt;br /&gt;
| Rename        || &amp;lt;kbd&amp;gt;F2&amp;lt;/kbd&amp;gt;                         || rename a variable (not supported by all programming language editors)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;kbd&amp;gt;Cmd&amp;lt;/kbd&amp;gt; key is usually labeled &amp;quot;Cmd&amp;quot;, &amp;quot;Alt&amp;quot; or &amp;quot;Meta&amp;quot;, depending on your keyboard.&lt;br /&gt;
&amp;lt;br&amp;gt;To search text that is already on the screen, select it and press &amp;lt;kbd&amp;gt;Cmd-f&amp;lt;/kbd&amp;gt; (or &amp;lt;kbd&amp;gt;Cmd-b&amp;lt;/kbd&amp;gt; to search backward).&lt;br /&gt;
&amp;lt;br&amp;gt;If it is not already visible, press &amp;lt;kbd&amp;gt;Ctrl-f&amp;lt;/kbd&amp;gt; to get a search dialog.&lt;br /&gt;
&amp;lt;br&amp;gt;To evaluate and paste the result, select some text and press &amp;lt;kbd&amp;gt;Ctrl-p&amp;lt;/kbd&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;To replace a string with another, select it, type in the new text, and press &amp;lt;kbd&amp;gt;F8&amp;lt;/kbd&amp;gt; (Again) - and again, and again...&amp;lt;br&amp;gt;The popup meny also contains an &amp;quot;&amp;lt;i&amp;gt;Again for All&amp;lt;/i&amp;gt;&amp;quot; entry, which repeats this til the end of the text.&lt;br /&gt;
&amp;lt;br&amp;gt;If you want to search first, before replacing, alternate between &amp;lt;kbd&amp;gt;Cmd-f&amp;lt;/kbd&amp;gt; (Forward search) and &amp;lt;kbd&amp;gt;F8&amp;lt;/kbd&amp;gt; (Again) or use the search dialog, which also offers a search and replace function.&lt;br /&gt;
&lt;br /&gt;
==== DoIt and PrintIt ====&lt;br /&gt;
&lt;br /&gt;
Especially the &amp;quot;&#039;&#039;DoIt&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;PrintIt&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;InspectIt&#039;&#039;&amp;quot;  functions deserve more explanation as they are often very useful. &lt;br /&gt;
These are avilable in the builtin languages (Smalltalk and JavaScript) and interpret the selected text as a code fragment of the programming language and execute it. For example, if you select &amp;quot;&amp;lt;code&amp;gt;Math.sin(45.degreesToRadians)&amp;lt;/code&amp;gt;&amp;quot; in a JavaScript editor, then press the &amp;quot;&#039;&#039;PrintIt&#039;&#039;&amp;quot; shortcut (&amp;lt;kbd&amp;gt;Ctrl-p&amp;lt;/kbd&amp;gt;), that code is interpreted and the result pasted at the cursor position.&lt;br /&gt;
&amp;lt;br&amp;gt;Useful JavaScript expressions are:&lt;br /&gt;
 Date.today()&lt;br /&gt;
 Time.now()&lt;br /&gt;
 UUID.new()&lt;br /&gt;
 OperatingSystem.getHostName()&lt;br /&gt;
 OperatingSystem.getSystemInfo()&lt;br /&gt;
 OperatingSystem.isMSWindows()&lt;br /&gt;
 1234567.nextPrime()&lt;br /&gt;
 1234567.nextPowerOf2()&lt;br /&gt;
 Math.sin(45.degreesToRadians())&lt;br /&gt;
&lt;br /&gt;
or in Smalltalk:&lt;br /&gt;
 Date today &lt;br /&gt;
 Time now &lt;br /&gt;
 UUID new &lt;br /&gt;
 OperatingSystem getHostName&lt;br /&gt;
 OperatingSystem getSystemInfo&lt;br /&gt;
 OperatingSystem isMSWindows&lt;br /&gt;
 1234567 nextPrime&lt;br /&gt;
 1234567 nextPowerOf2&lt;br /&gt;
 45 degreesToRadians sin&lt;br /&gt;
 10 kilo ohm * 23 milli ampere&lt;br /&gt;
&lt;br /&gt;
Of course, this immediate expression evaluation is very useful while programming an elementary block. You can try out code fragments right in the editor.&lt;br /&gt;
By the way: every window which shows code can evaluate code: the elementary block editor, the workspace windows and especially the debugger. In the debugger, local variables and &#039;&#039;self&#039;&#039; (&#039;&#039;this&#039;&#039;) can be used in evaluated code.&lt;br /&gt;
For incremental programming, place a halt in your elementary block&#039;s code, and write the program (after testing it with doIt/printIt) right in the debugger (Click on the &amp;quot;&#039;&#039;Resend&#039;&#039;&amp;quot; button after a change, to restart the changed function&#039;s code).&lt;br /&gt;
&lt;br /&gt;
For a full list of useful expressions, please refer to the [http://live.exept.de/doc/online/english/TOP.html Smalltalk/X Online Documentation].&lt;br /&gt;
The debugger&#039;s documentation is found in the [http://live.exept.de/doc/online/english/tools/debugger/TOP.html Smalltalk/X Tools Documentation].&lt;br /&gt;
&lt;br /&gt;
==== Again (Repeat Last Edit) ====&lt;br /&gt;
The &amp;quot;&#039;&#039;Again&#039;&#039;&amp;quot; operation (press &amp;lt;kbd&amp;gt;F8&amp;lt;/kbd&amp;gt; or select it from the operations (= right-button) menu) repeats the last delete or replace operation, after searching for the next occurrence of the original string. So, to incrementally rename all occurrences of &amp;quot;foo&amp;quot; with &amp;quot;bar&amp;quot;, find the very first occurrence &amp;quot;foo&amp;quot;, select it, type &amp;quot;bar&amp;quot; over it. This is the first edit operation. Then press &amp;lt;kbd&amp;gt;F8&amp;lt;/kbd&amp;gt; to repeat this for the next occurrence of &amp;quot;foo&amp;quot; in the text.&lt;br /&gt;
&lt;br /&gt;
The operations menu also offers an &amp;quot;&#039;&#039;Again until End&#039;&#039;&amp;quot; function in its &amp;quot;&#039;&#039;More&amp;quot;&#039;&#039; sub-menu. This performs multiple &amp;quot;&#039;&#039;Again&#039;&#039;&amp;quot; operations, until the original string is no longer found. Use this to replace ALL occurrences of a string by another.&lt;br /&gt;
&lt;br /&gt;
==== Additional Useful Editor Commands ====&lt;br /&gt;
The popup-menu and especially the submenus under &amp;quot;&#039;&#039;More&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Other&#039;&#039;&amp;quot; contain a number of additional, often very useful editor commands. Among many others, will find functions to paste the current date and time, to generate UUIDs or to sort your text alphabetically or by columns. Very useful functions are also &amp;quot;&#039;&#039;Open Filebrowser on Selected Name&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Open Webbrowser on Selected URL&#039;&#039;&amp;quot;, which are enabled if the current selected text looks like a valid filename or URL.&lt;br /&gt;
&lt;br /&gt;
== Editor Customization ==&lt;br /&gt;
=== Line End Behavior ===&lt;br /&gt;
By default, the editor is configured to treat the whole page like a piece of paper, where the cursor can be arbitrarily positioned. If you move the cursor, or click into the view, any short line will be automatically lengthened to the current cursor position, when a non-blank character is entered (&amp;quot;&#039;&#039;Rand-editor behavior&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
This may be an unusual behavior if you are used to vi, emacs, notepad and other editors, which only allow positioning of the cursor to the actual line end, without automatic line lengthening. If you prefer this behavior, go to the editor&#039;s settings dialog (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Look &amp;amp; Feel&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Code Editor&#039;&#039;&amp;quot;) and toggle the &amp;quot;&#039;&#039;Standard Line-End Behavior&#039;&#039;&amp;quot; toggle. However, if you do so, it is probably a good idea to also check the &amp;quot;&#039;&#039;Automatic Indent&#039;&#039;&amp;quot; toggle.&lt;br /&gt;
&lt;br /&gt;
Expecco 26.1 also adds a popup menu item in the editor (&amp;quot;&#039;&#039;More&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Misc&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Rand Cursor Behavior&#039;&#039;&amp;quot;) to change this in a single editor.&lt;br /&gt;
&lt;br /&gt;
=== Edit Tab Stops ===&lt;br /&gt;
The default is multiples of 8.&lt;br /&gt;
&lt;br /&gt;
This can be changed for an individual editor via its popup menu (&amp;quot;&#039;&#039;More&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Misc&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Toggle Tabs&#039;&#039;&amp;quot;) or as a default setting via the settings (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Look &amp;amp; Feel&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Code Editor&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Although the default is 8, we recommend and use a 4-space tab setting at exept; tab8 makes the text too wide and will lead to a lot of horizontal scrolling, whereas tab2 makes it harder to see the control structure quickly.&lt;br /&gt;
&lt;br /&gt;
=== Tab Stops when Writing Files ===&lt;br /&gt;
When saving text to a file, leading spaces in multiples of 8 are replaced by a tab.&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Notice: This conversion is independent of your &#039;&#039;edit tab setting&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
In the file, tab stops are always in multiples of 8.&lt;br /&gt;
&lt;br /&gt;
This was done to prevent unintended corruption especially of makefiles,&lt;br /&gt;
which require tab characters to be present.&lt;br /&gt;
&lt;br /&gt;
In case you have to change a file&#039;s tab interpretation, use a file browser (or external editor).&lt;br /&gt;
 &lt;br /&gt;
In the file browser, the behavior can be changed to either 4 spaces per tab, or to no tab generation, via its own &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Tab Stop Conversion&#039;&#039;&amp;quot; menu. &lt;br /&gt;
&lt;br /&gt;
This may also be an unusual behavior if you are used to vi, emacs, notepad and other editors, which treat the edit-tab setting the same as the file&#039;s tab setting.&lt;br /&gt;
&lt;br /&gt;
=== Changing the Keyboard Mapping ===&lt;br /&gt;
The editor&#039;s keyboard-to-command mapping is loaded at startup time from a file named &amp;quot;&amp;lt;code&amp;gt;keyboard.rc&amp;lt;/code&amp;gt;&amp;quot; in the expecco installation folder. Once you get a little familiar with the syntax, you may even change the keyboard mapping and/or add additional macro functions to suit your personal preferences.&lt;br /&gt;
Detailed information on how this is one in found in the [http://live.exept.de/doc/online/english/custom/TOP.html#KEYBOARD Smalltalk/X Documentation on Keyboard Customization].&lt;br /&gt;
&lt;br /&gt;
=== Insert Mode vs. Overwrite Mode ===&lt;br /&gt;
Is toggled via the popup menu of the &amp;quot;I&amp;quot;-insert indicator at the bottom right of the window, or under the &amp;quot;&#039;&#039;More&#039;&#039;&amp;quot; submenu of the editor&#039;s context (right-click) menu.&lt;br /&gt;
&lt;br /&gt;
== Other Useful Functions ==&lt;br /&gt;
A number of functions are found under the &amp;quot;&#039;&#039;More&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; items of the popup menu.&lt;br /&gt;
Useful are:&lt;br /&gt;
* &amp;quot;&#039;&#039;Open WebBrowser on Selection&#039;&#039;&amp;quot; - takes the selected text as an URL and opens a browser for it&lt;br /&gt;
* &amp;quot;&#039;&#039;Open FileBrowser on Selection&#039;&#039;&amp;quot; - dimilar for file names&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;Sort&#039;&#039;&amp;quot; - sort the selected lines by various criteria (eg. column number)&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;&#039;&#039;Insert UUID&#039;&#039;&amp;quot; - to generate a new, globally unique identifiers&lt;br /&gt;
&lt;br /&gt;
== Break- and Tracepoints ==&lt;br /&gt;
To toggle a breakpoint, double-click into the area left of the line-number, where the breakpoint or tracepoint should be placed. With shift pressed, a tracepoint will be placed, without shift, a breakpoint is toggled.&lt;br /&gt;
&lt;br /&gt;
Breakpoints will open a debugger, tracepoints will simple send a trace message to the Transcript window (which should obviously be open).&lt;br /&gt;
&lt;br /&gt;
The debugger allows for stepping, aborting or continuing.&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Notice: you can also get into a debugger by pressing the interrupt key (&amp;lt;kbd&amp;gt;CTRL&amp;lt;/kbd&amp;gt;+&amp;lt;kbd&amp;gt;.&amp;lt;/kbd&amp;gt;, &amp;lt;kbd&amp;gt;CMD&amp;lt;/kbd&amp;gt;+&amp;lt;kbd&amp;gt;.&amp;lt;/kbd&amp;gt; or &amp;lt;kbd&amp;gt;Pause&amp;lt;/kbd&amp;gt;) or by clicking on the &amp;quot;&#039;&#039;Interrupt &amp;amp; Debug&#039;&#039;&amp;quot; icon at the top right.&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Notice also, that not all language interpreters will handle interrupts at any time - especially interrupts while waiting for I/O or while setting up socket connections are uninterruptable in many interpreters (i.e. Node and Python), in contrast to the builtin languages ST and JS, which are interruptable and proceedable.&lt;br /&gt;
&lt;br /&gt;
== Use of an External Editor ==&lt;br /&gt;
If you prefer to use an external text editor, navigate to the externalTools Settings (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Tools&#039;&#039;&amp;quot;) and enter the path to your editor into the &amp;quot;&#039;&#039;Code Editor&#039;&#039;&amp;quot; field.&lt;br /&gt;
If that field is non-empty, an icon is shown in the elementary action&#039;s code page, which calls the configured editor on the current text.&lt;br /&gt;
&amp;lt;br&amp;gt;A very powerful editor for any operating System is [https://code.visualstudio.com/download VisualStudio Code],&lt;br /&gt;
other good editors for Windows are [https://notepad-plus-plus.org/downloads &amp;quot;notepad++&amp;quot;], [https://www.gnu.org/software/emacs/download.html &amp;quot;Emacs&amp;quot;] and [https://www.scintilla.org/SciTEDownload.html &amp;quot;SciTE&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
If an external editor is opened, expecco waits for the editor&#039;s executable to finish, then reads back the edited file.&lt;br /&gt;
Some of the above commands will need an additional command line argument to ensure this (see the offered command list in the settings dialog for concrete examples).&lt;br /&gt;
&lt;br /&gt;
Be aware that some apps take some time to start; it is therefore probably only useful for large scripts or if special language editing features are required (eg. code completion). You have to configure the editor, in order for any imported packages/source to be shown correctly.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
[[Scheme_Editor | Scheme Editor]]&lt;br /&gt;
&lt;br /&gt;
For the programmer API for the builtin languages see: [[Expecco API]],&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Sections of interest are the [[Expecco_API/en#Pin Functions  | Pin-API ]], [[ Expecco_API/en#Current Activity | Activity-API ]]&lt;br /&gt;
&lt;br /&gt;
==== Language specific info ====&lt;br /&gt;
is found in the API chapters on:&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;[[Expecco_API/en#JavaScript_and_Smalltalk_Elementary_Blocks|JavaScript and Smalltalk (builtin)]],&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;[[Expecco_API/en#Groovy_Elementary_Blocks|Groovy (bridged)]],&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;[[Expecco_API/en#Node.js_.28Bridged.29_Elementary_Blocks|Node (bridged)]],&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;[[Expecco_API/en#Bridged_Python_Elementary_Blocks|Python (bridged)]],&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;[[Expecco_API/en#Bridged_C_Elementary_Blocks|C (bridged)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;[[Expecco_API/en#Bridged_Ruby_Elementary_Blocks|Ruby (bridged)]],&lt;br /&gt;
&lt;br /&gt;
Functions of the underlying expecco runtime system are accessible via JavaScript or Smalltalk elementary actions.&lt;br /&gt;
For information on the functions available in the built-in classes (method protocol), please refer to the [http://live.exept.de/doc/online/english/classDoc/TOP.html Smalltalk/X Online Documentation] and especially the [http://live.exept.de/ClassDoc Class Reference].&lt;br /&gt;
For example, some of the mathematical functions are described [http://live.exept.de/ClassDoc/classDocOf:,Number#Number_category_mathematical%20functions here]&lt;br /&gt;
and String processing functions are found [http://live.exept.de/ClassDoc/classDocOf:,String here] and [http://live.exept.de/ClassDoc/classDocOf:,CharacterArray here].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
For elementary blocks in general, see [[ElementaryBlock Element]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
More information on the Debugger and Inspector are found in the tools section of the [http://live.exept.de/doc/online/english/tools/TOP.html Smalltalk/X Online Documentation].&lt;br /&gt;
&lt;br /&gt;
====Shell and CMD scripts====&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;[[Shell_Environment_Variables/en|Environment Variables]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- {{Languages}} --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Editors]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=PhysicalValues/en&amp;diff=30901</id>
		<title>PhysicalValues/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=PhysicalValues/en&amp;diff=30901"/>
		<updated>2026-02-23T11:32:32Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 27.1.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Notice: the physical values package as described here is still considered &amp;quot;work in progress&amp;quot; and provided as a preview feature. However it is quite stable and tested by an exhaustive test suite). &lt;br /&gt;
We hope to have transcribed nature constant values and unit conversion factors correctly from public information (mostly wikipedia).&lt;br /&gt;
Please report any errors or inconveniences (or wishes) to exept.&lt;br /&gt;
&lt;br /&gt;
== Introduction &amp;amp; Motivation ==&lt;br /&gt;
In the past, a number of big projects failed or went completely out of budget due to misinterpretations of data. An example well known to insiders (but not named here) lead to millions of loss due to some misinterpretation of metric versus imperial values in documentation and software. In addition, some units are even different in imperial vs. american systems.&lt;br /&gt;
&lt;br /&gt;
Expecco supports values with units, to represent physical values such as length, acceleration, area, volume, mass, temperature, electric current etc.&lt;br /&gt;
&lt;br /&gt;
Physical values are useful for a nicer presentation of measurement values (e.g. in a report) and to convert between unit systems (e.g. metric vs. imperial vs. US). They can also make elementary code which computes physical values more readable and more robust. And if the correct unit is returned from an expression, you know that you used the correct formula (or at least: not completely wrong).&lt;br /&gt;
&lt;br /&gt;
Physical values are implemented by the underlying Smalltalk system and can be used both in Smalltalk and in JavaScript elementary blocks. Similar public domain packages might be available for Java or Node. There is at least on such package available for Python (see &amp;quot;astropy&amp;quot;). These can be installed with &amp;quot;npm&amp;quot; or &amp;quot;pip&amp;quot;.&amp;lt;br&amp;gt;However, there are currently no plans to transparently support exchange of physical values between expecco and Node, Java or Python. There is some support for Python&#039;s astropy quantities. If required, these should be passed as composite &amp;quot;&amp;lt;code&amp;gt;{ unitAmount:xxx unit:xxx }&amp;lt;/code&amp;gt;&amp;quot; or objects and converted in the bridge as required. Sorry, but there exists as yet no commonly used encoding standard for such data (e.g. in JSON). &lt;br /&gt;
&lt;br /&gt;
The following document describes the programmer&#039;s API for elementary Smalltalk and JavaScript actions. Corresponding types are found in datatype menus under the &amp;quot;&#039;&#039;Physics&#039;&#039;&amp;quot; group.&lt;br /&gt;
&lt;br /&gt;
This document is meant for &amp;quot;experts&amp;quot; who understand some minimum Smalltalk syntax (which is easy). It will help to write your own eleemntary code in case you need additional functionality.&lt;br /&gt;
&lt;br /&gt;
== No Warranty ==&lt;br /&gt;
&lt;br /&gt;
The nature constants and conversion factors have been taken from wikipedia and other sources.&lt;br /&gt;
&amp;lt;br&amp;gt;We do not guarantee for their correctness. For some, new measures might give different values. If you encounter any errors or know about newer/better values, please let us know.&lt;br /&gt;
&lt;br /&gt;
We recommend that you add additional verification/check actions (which should run before). A typical example wcould be:&lt;br /&gt;
 self &#039;&#039;&#039;assert:&#039;&#039;&#039;(1 &#039;&#039;&#039;pound&#039;&#039;&#039; &#039;&#039;&#039;printString&#039;&#039;&#039; = &#039;453.59237 g&#039;).&lt;br /&gt;
That code will also document any of your expectations.&lt;br /&gt;
&lt;br /&gt;
== Motivating Examples ==&lt;br /&gt;
&lt;br /&gt;
The nice thing about using values with units is that you will get a better feedback if the used formula is correct (at least from the units point of view - forgotten scalar constants in physical expressions are still undetected). If you get an unexpected or strange unit in your result, you will certainly have an error in your computation.&lt;br /&gt;
&lt;br /&gt;
Take these as examples and don&#039;t take the values for granted: please let us know, if there are any errors in those examples (the author is not an electrical engineer ;-).&lt;br /&gt;
&lt;br /&gt;
=== Example1: Metric vs. Imperial Units ===&lt;br /&gt;
Need to convert millimeters to inches, or know how thick a 3 AWG wire is?&lt;br /&gt;
&amp;lt;br&amp;gt;Simply [[Tools_Notepad/en#Code_Evaluation|evaluate (&amp;quot;&#039;&#039;doIt&#039;&#039;&amp;quot;)]] in a notepad or smalltalk elementary action&#039;s codeview:&lt;br /&gt;
 10 &#039;&#039;&#039;milliMeter&#039;&#039;&#039; &#039;&#039;&#039;asInches&#039;&#039;&#039;&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 0.393700787401575 in&amp;lt;/small&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;awgDiameter&#039;&#039;&#039; &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;3) &#039;&#039;&#039;asMilliMeter&#039;&#039;&#039;&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 5.82733981304513 mm&amp;lt;/small&amp;gt;&lt;br /&gt;
 or:&lt;br /&gt;
     (PhysicalUnit &#039;&#039;&#039;unit:&#039;&#039;&#039;&#039;awg&#039; &#039;&#039;&#039;amount:&#039;&#039;&#039;3) &#039;&#039;&#039;asSquareMillimeter&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
 (1 &#039;&#039;&#039;british&#039;&#039;&#039; &#039;&#039;&#039;gallon&#039;&#039;&#039;) &#039;&#039;&#039;asMilliLiter&#039;&#039;&#039;&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 3785.411784 ml&amp;lt;/small&amp;gt;&lt;br /&gt;
 (1 &#039;&#039;&#039;american&#039;&#039;&#039; &#039;&#039;&#039;gallon&#039;&#039;&#039;) &#039;&#039;&#039;asMilliLiter&#039;&#039;&#039;&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 4546.09 ml&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example2: Time to Load a Cap (i.e. RC time constant) ===&lt;br /&gt;
You want to compute how long it takes to load a 100uF capacitor, given a 5V supply and a current limiting resistor with 100 kOhm?&lt;br /&gt;
&lt;br /&gt;
First, compute the RC time constant; the electric charge (in Coulomb) transported through a wire is:&lt;br /&gt;
 charge = I*t (I = current in Ampere; t in Seconds)&lt;br /&gt;
and the charge (in Coulomb) of a capacitor is:&lt;br /&gt;
 charge = C*U  (C = capacity in Farad; U = voltage)&lt;br /&gt;
&lt;br /&gt;
We can immediately compute the electrical charge (in Coulomb) with the formula (C*U):&lt;br /&gt;
 (5 &#039;&#039;&#039;volt&#039;&#039;&#039; * 100 &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;farad&#039;&#039;&#039;)&lt;br /&gt;
and get the result:&lt;br /&gt;
 (1/2000) C&lt;br /&gt;
Notice that the above is Smalltalk syntax, and can be written exactly like that in a Smalltalk action.&lt;br /&gt;
&lt;br /&gt;
We can also compute the current through the loading resistor (I = U / R) as:&lt;br /&gt;
 5 &#039;&#039;&#039;volt&#039;&#039;&#039; / 100 &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;ohm&#039;&#039;&#039;&lt;br /&gt;
and get the result:&lt;br /&gt;
 50 µA&lt;br /&gt;
&lt;br /&gt;
To compute the time, equate and rearrange the above formulas: &lt;br /&gt;
     (C * U)&lt;br /&gt;
 t = -------&lt;br /&gt;
        I&lt;br /&gt;
&lt;br /&gt;
with I = U / R, we get:&lt;br /&gt;
&lt;br /&gt;
     (C * U)&lt;br /&gt;
 t = -------&lt;br /&gt;
     (U / R)&lt;br /&gt;
&lt;br /&gt;
in Smalltalk (*):&lt;br /&gt;
 t := (5 &#039;&#039;&#039;volt&#039;&#039;&#039; * 100 &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;farad&#039;&#039;&#039; ) / (5 &#039;&#039;&#039;volt&#039;&#039;&#039; / 100 &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;ohm&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
and will get the RC time for t as:&lt;br /&gt;
 10s&lt;br /&gt;
&lt;br /&gt;
In other words, Smalltalk automatically found the correct result unit from the above computation and figured, that the result must be a time duration given in seconds.&lt;br /&gt;
&lt;br /&gt;
(*) obviously, we could have further simplified the formula, or ask expecco to simplify it for us with:&lt;br /&gt;
::    &amp;lt;CODE&amp;gt;Physic::Expression &#039;&#039;&#039;simplify:&#039;&#039;&#039;&#039;(U * C) / (U / R)&#039;&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:or:&lt;br /&gt;
::    &amp;lt;CODE&amp;gt;&#039;(U * C) / (U / R)&#039; &#039;&#039;&#039;asPhysicExpression&#039;&#039;&#039; &#039;&#039;&#039;simplified&#039;&#039;&#039;&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:which both give the result:&amp;lt;CODE&amp;gt;C * R&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:So, we could have also computed:&lt;br /&gt;
::    &amp;lt;CODE&amp;gt;t := 100 &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;farad&#039;&#039;&#039; * 100 &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;ohm&#039;&#039;&#039;&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:and also get the same 10 seconds as result.&lt;br /&gt;
&lt;br /&gt;
The capacitor&#039;s voltage will grow along a logarithmic curve, and is not fully charged after its RC time constant (its roughly 2/3 loaded).&lt;br /&gt;
Typical approximations will go for a 90% load, taking 3-5 times the RC time constant. (see wikipedia)&lt;br /&gt;
&lt;br /&gt;
=== Example3: Signal Rise Time ===&lt;br /&gt;
&lt;br /&gt;
Of course, you may also get the time with a given delta-voltage and current flow. From the formula:&lt;br /&gt;
 I = C * ΔV / Δt. &lt;br /&gt;
we get:&lt;br /&gt;
 Δt = C * ΔV / I&lt;br /&gt;
As an example, if an output pin of an IC drives 10mA, and it is connected to an input pin with 100pF input capacitance to ground, it will take:&lt;br /&gt;
 100 &#039;&#039;&#039;pico&#039;&#039;&#039; &#039;&#039;&#039;farad&#039;&#039;&#039; * 5 &#039;&#039;&#039;volt&#039;&#039;&#039; / 10 &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;ampere&#039;&#039;&#039;&lt;br /&gt;
to get it from 0V to 5V (in this case: 50ns).&lt;br /&gt;
&lt;br /&gt;
=== Example4: Bandpass Filter Frequency ===&lt;br /&gt;
&lt;br /&gt;
A filter&#039;s frequency is computed as:&lt;br /&gt;
          1  &lt;br /&gt;
 f = ------------&lt;br /&gt;
       2*&amp;amp;pi;*R*C&lt;br /&gt;
&lt;br /&gt;
What is the frequency, given 1 Megaohm and 0.1 Microfarad as values?&lt;br /&gt;
&amp;lt;br&amp;gt;In Smalltalk:&lt;br /&gt;
&lt;br /&gt;
 |r c f| &lt;br /&gt;
 r := 1 &#039;&#039;&#039;mega&#039;&#039;&#039; &#039;&#039;&#039;ohm&#039;&#039;&#039;.&lt;br /&gt;
 c := 0.1 &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;farad&#039;&#039;&#039;.&lt;br /&gt;
 f := 1 / (2*Float &#039;&#039;&#039;pi&#039;&#039;&#039; * r * c)&lt;br /&gt;
&lt;br /&gt;
result:&lt;br /&gt;
 f = 1.59154943091895 Hz&lt;br /&gt;
&lt;br /&gt;
=== Example5: Capacitance of a Wire ===&lt;br /&gt;
&lt;br /&gt;
Assume that there is a 10 cm long connection between 2 pins on a printed circuit board, and the connection faces a ground plane at a distance of 0.7 mm. The trace has a width of 0.5 mm.&lt;br /&gt;
&amp;lt;br&amp;gt;What is the capacitance of the wire, and how long does it take the output to rise from 0 to 5 V if it can drive 10 mA?.&lt;br /&gt;
&lt;br /&gt;
The capacitance is:&lt;br /&gt;
 C = &amp;amp;#949;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; * a / d&lt;br /&gt;
where &amp;amp;#949;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; is the [https://de.wikipedia.org/wiki/Elektrische_Feldkonstante permittability constant], a is the area and d is the distance of the capacitor&#039;s plates. We take the vacuum permutability as an approximation (strictly speaking, that is incorrect; it should be replaced by the printed board material&#039;s value and also depends on the frequency [https://en.wikipedia.org/wiki/Permittivity]). The trace has an area of 10 cm by 0.5 mm, and has a distance of 0.7mm from the ground plate. Thus we get:&lt;br /&gt;
 a := 10 &#039;&#039;&#039;centi&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039; * 0.5 &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;. &amp;quot;area&amp;quot;&lt;br /&gt;
 d := 0.7 &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;. &amp;quot;distance&amp;quot;&lt;br /&gt;
 e0 := Physic::NatureConstants &#039;&#039;&#039;vacuumPermittivity&#039;&#039;&#039;. &amp;quot;&amp;amp;#949;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&amp;quot; &lt;br /&gt;
 C := e0 * a / d.&lt;br /&gt;
or:&lt;br /&gt;
 C := Physic::NatureConstants &#039;&#039;&#039;vacuumPermittivity&#039;&#039;&#039; &amp;quot;&amp;amp;#949;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&amp;quot;&lt;br /&gt;
      * (10 &#039;&#039;&#039;centi&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039; * 0.5 &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;)&lt;br /&gt;
      / 0.7 &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;.&lt;br /&gt;
that gives us 0.63 pF.&lt;br /&gt;
According to the above Example2, we can compute the signal&#039;s rise time as:&lt;br /&gt;
 0.63 &#039;&#039;&#039;pico&#039;&#039;&#039; &#039;&#039;&#039;farad&#039;&#039;&#039; * 5 &#039;&#039;&#039;volt&#039;&#039;&#039; / 10 &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;ampere&#039;&#039;&#039;&lt;br /&gt;
which gives: 315 ps&lt;br /&gt;
&amp;lt;br&amp;gt;or as a frequency:&lt;br /&gt;
 1 / 315.0 &#039;&#039;&#039;pico&#039;&#039;&#039; &#039;&#039;&#039;seconds&#039;&#039;&#039; &lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 3174.60317460317 Mhz&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example6: E = mcˆ2 ===&lt;br /&gt;
&lt;br /&gt;
Energy content of 1 gram of (rest) mass:&lt;br /&gt;
 c := Physic::NatureConstants &#039;&#039;&#039;lightspeed&#039;&#039;&#039;.&lt;br /&gt;
 1.0 &#039;&#039;&#039;gram&#039;&#039;&#039; * c &#039;&#039;&#039;squared&#039;&#039;&#039; &lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 89.8755178736818 TJ&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 c := Physic::NatureConstants &#039;&#039;&#039;lightspeed&#039;&#039;&#039;.&lt;br /&gt;
 (1.0 &#039;&#039;&#039;gram&#039;&#039;&#039; * c &#039;&#039;&#039;squared&#039;&#039;&#039;) &#039;&#039;&#039;asKiloWattHours&#039;&#039;&#039;   &lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 24965421.6315783 kWh&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 c := Physic::NatureConstants &#039;&#039;&#039;lightspeed&#039;&#039;&#039;.&lt;br /&gt;
 (1.0 &#039;&#039;&#039;gram&#039;&#039;&#039; * (c ** 2)) &#039;&#039;&#039;asMegaWattHours&#039;&#039;&#039; &#039;&#039;&#039;rounded&#039;&#039;&#039;   &lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 24965 MWh&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We&#039;d love to use antimatter for energy supply!&lt;br /&gt;
&lt;br /&gt;
=== Example7: Gravitational Force ===&lt;br /&gt;
&lt;br /&gt;
F = (m1 * m2) * G / rˆ2&lt;br /&gt;
&lt;br /&gt;
Force on two masses separated by one meter:&lt;br /&gt;
 m1 := 1 &#039;&#039;&#039;kiloGram&#039;&#039;&#039;. &amp;quot;/ or kilo gram&lt;br /&gt;
 m2 := 1 &#039;&#039;&#039;kiloGram&#039;&#039;&#039;.&lt;br /&gt;
 G := Physic::NatureConstants &#039;&#039;&#039;gravitationalConstant&#039;&#039;&#039;.&lt;br /&gt;
 r := 1 &#039;&#039;&#039;meter&#039;&#039;&#039;.&lt;br /&gt;
 (m1 * m2 * G) / r &#039;&#039;&#039;squared&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 6.6743e-11 N&amp;lt;/small&amp;gt;&lt;br /&gt;
or (in one expression):&lt;br /&gt;
 (1 &#039;&#039;&#039;kiloGram&#039;&#039;&#039; * 1 &#039;&#039;&#039;kiloGram&#039;&#039;&#039; * (Physic::NatureConstants &#039;&#039;&#039;gravitationalConstant&#039;&#039;&#039;)) / 1 &#039;&#039;&#039;meter&#039;&#039;&#039; &#039;&#039;&#039;squared&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 6.6743e-11 N&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How long will it take till they touch (in space without other gravitional fields around):&lt;br /&gt;
&lt;br /&gt;
By F = m * a, we get the acceleration a = F / m; assuming m1 = m2 = 1 kg, we get the above divided by m1:&lt;br /&gt;
 a = (m * G) / r &#039;&#039;&#039;squared&#039;&#039;&#039;&lt;br /&gt;
and, to get from an acceleration to the distance:&lt;br /&gt;
 s = (a/2) * t^2, from which:&lt;br /&gt;
&lt;br /&gt;
 t = sqrt ( 2*s / a)&lt;br /&gt;
&lt;br /&gt;
since the masses are the same 1 kg, each has to move half the distance; thus:&lt;br /&gt;
 t := ( 1 meter / ((1 kiloGram * G) / 1 meter squared)) sqrt &lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt;122404.43 s&amp;lt;/small&amp;gt;&lt;br /&gt;
or (asHours):&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 34.001 h&amp;lt;/small&amp;gt;&lt;br /&gt;
(I did not expect this happening so fast; if there is an error, let me know... ;-) )&lt;br /&gt;
&lt;br /&gt;
Oh, I found out myself; sorry for my mistake: the acceleration increases when the distance gets smaller, but the above calculation was made with a constant acceleration, which is wrong!.&lt;br /&gt;
&amp;lt;br&amp;gt;So the formula is actually more complicated (integral of a differential equation). In fact, they touch even earlier: after only roughly 96000 seconds or 26.7 hours !!!&lt;br /&gt;
&amp;lt;br&amp;gt;The actual formula is: &lt;br /&gt;
 Float pi * (  1 meter cubed / (8 * G *(1 kiloGram + 1 kiloGram)) ) sqrt&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 96136.215 s&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example8: British Drinking vs. US Drinking ===&lt;br /&gt;
Who gets most bang for the glas in a pub:&lt;br /&gt;
British, US or German drinkers?&lt;br /&gt;
&lt;br /&gt;
 1 &#039;&#039;&#039;british&#039;&#039;&#039; &#039;&#039;&#039;pint&#039;&#039;&#039;  &amp;lt;small&amp;gt;=&amp;gt; 568.26125 ml&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 &#039;&#039;&#039;american&#039;&#039;&#039; &#039;&#039;&#039;pint&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 473.176473 ml&amp;lt;/small&amp;gt;&lt;br /&gt;
 (1/2) &#039;&#039;&#039;liter&#039;&#039;&#039;     &amp;lt;small&amp;gt;=&amp;gt; 500 ml&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ok, lets go to the next british pub!&lt;br /&gt;
&lt;br /&gt;
=== Example9: Potential Energy ===&lt;br /&gt;
The potential energy of 10 gram lifted 1 meter (m*h*G) is on earth:&lt;br /&gt;
 10 &#039;&#039;&#039;gram&#039;&#039;&#039; * 1 &#039;&#039;&#039;meter&#039;&#039;&#039; * (Physic::NatureConstants &#039;&#039;&#039;earthGravity&#039;&#039;&#039;) &amp;lt;small&amp;gt;=&amp;gt; 0.0980665 J&amp;lt;/small&amp;gt;&lt;br /&gt;
or alternatively:&lt;br /&gt;
 10 &#039;&#039;&#039;gram&#039;&#039;&#039; * 1 &#039;&#039;&#039;meter&#039;&#039;&#039; * (Physic::NatureConstants &#039;&#039;&#039;astronomicalObjects&#039;&#039;&#039;[&#039;earth&#039;][&#039;gravity&#039;]) &amp;lt;small&amp;gt;=&amp;gt; 0.0980665 J&amp;lt;/small&amp;gt;&lt;br /&gt;
or even:&lt;br /&gt;
 10 &#039;&#039;&#039;gram&#039;&#039;&#039; * 1 &#039;&#039;&#039;meter&#039;&#039;&#039; * (Physic::NatureConstants &#039;&#039;&#039;earth&#039;&#039;&#039; &#039;&#039;&#039;gravity&#039;&#039;&#039;) &amp;lt;small&amp;gt;=&amp;gt; 0.0980665 J&amp;lt;/small&amp;gt;&lt;br /&gt;
Note: astronomicalObjects returns a collection which can be indexed by &#039;earth&#039;, &#039;moon&#039;, &#039;mars&#039; etc.&lt;br /&gt;
This returned object can then further be indexed by &#039;gravity&#039;, &#039;mass&#039;, etc.&lt;br /&gt;
The &amp;quot;earth&#039;-message in the 3rd example also returns the earth&#039;s data. &lt;br /&gt;
&amp;lt;br&amp;gt;To see what is there, inspect the returned object.&lt;br /&gt;
&lt;br /&gt;
=== Example10: Voltage at a Loudspeaker ===&lt;br /&gt;
Lets assume, we want to get 20 Watt out of a 4 Ohm loudspeaker. Which voltage will we need (only assuming non-complex resistance).&lt;br /&gt;
&amp;lt;br&amp;gt;The formulas are: &lt;br /&gt;
  P = U * I  (power is voltage times current) &lt;br /&gt;
 and &lt;br /&gt;
  U = R * I (voltage drop is resistance times current).&lt;br /&gt;
Lets rewrite into &lt;br /&gt;
  U = P / I &lt;br /&gt;
 and&lt;br /&gt;
  I = U / R. &lt;br /&gt;
Then replace I in the first formula to get &lt;br /&gt;
  U = P / (U/R) &lt;br /&gt;
 or&lt;br /&gt;
  U = (P * R) / U&lt;br /&gt;
Multiply both sides by U, we get:&lt;br /&gt;
  U^2 = P * R&lt;br /&gt;
 or&lt;br /&gt;
  U = SQRT( P * R)&lt;br /&gt;
&lt;br /&gt;
Lets evaluate (Smalltalk code here!):&lt;br /&gt;
 (20 &#039;&#039;&#039;watt&#039;&#039;&#039; * 4 &#039;&#039;&#039;ohm&#039;&#039;&#039;) sqrt =&amp;gt; 8.9443 V&lt;br /&gt;
&lt;br /&gt;
(you&#039;ll need an up-to-date version of expecco for this, as previous versions did not recognize square roots of formulas correctly, delivering a funny unit as result).&lt;br /&gt;
&lt;br /&gt;
=== Example11: Energy of a Photon ===&lt;br /&gt;
&lt;br /&gt;
The frequency f of a photon with a wavelength of 550 nanometer is:&lt;br /&gt;
 f := Physic::NatureConstants &#039;&#039;&#039;c&#039;&#039;&#039; / 550 &#039;&#039;&#039;nano&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 545.077 THz&amp;lt;/small&amp;gt;&lt;br /&gt;
and its energy is the Planck constant h times the frequency:&lt;br /&gt;
 e := Physic::NatureConstants &#039;&#039;&#039;h&#039;&#039;&#039; * f&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 3.61171974027078e-19 J&amp;lt;/small&amp;gt;&lt;br /&gt;
in electron volts gives:&lt;br /&gt;
 e &#039;&#039;&#039;asElectronVolts&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 2.25425815333091 eV&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Physic Package Loading ==&lt;br /&gt;
&lt;br /&gt;
If you have an older expecco version, the physic packages (&amp;lt;CODE&amp;gt;stx:goodies/physic/units&amp;lt;/CODE&amp;gt; for units and &amp;lt;CODE&amp;gt;stx:goodies/physic/formula&amp;lt;/CODE&amp;gt; for formula parsing) may not be already loaded.&lt;br /&gt;
&amp;lt;br&amp;gt;If not, either add it to the list of required packages of your test suite or evaluate:&lt;br /&gt;
 Smalltalk &#039;&#039;&#039;requirePackage:&#039;&#039;&#039;&#039;stx:goodies/physics/units&#039;.&lt;br /&gt;
 Smalltalk &#039;&#039;&#039;requirePackage:&#039;&#039;&#039;&#039;stx:goodies/physics/formula&#039;.&lt;br /&gt;
in either an elementary action or in the startup file (&amp;quot;&amp;lt;code&amp;gt;expeccoStart.rc&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
All physic classes will be found in the &amp;quot;&amp;lt;CODE&amp;gt;Physic&amp;lt;/CODE&amp;gt;&amp;quot; namespace&amp;lt;br&amp;gt;(i.e. class names are prefixed with &amp;quot;&amp;lt;CODE&amp;gt;Physic::&amp;lt;/CODE&amp;gt;&amp;quot; as in &amp;quot;&amp;lt;CODE&amp;gt;Physic::Energy&amp;lt;/CODE&amp;gt;&amp;quot; or &amp;quot;&amp;lt;CODE&amp;gt;Physic::Volume&amp;lt;/CODE&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
== Programming Language API==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Smalltalk&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;As you&#039;ll have noticed, Smalltalk has a convenient syntax, for this kind of framework: you can immediately write code like:&lt;br /&gt;
 1 &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039; / 10 &#039;&#039;&#039;minutes&#039;&#039;&#039;&lt;br /&gt;
to compute a velocity. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JavaScript&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;Due to the fact that the builtin Javascript also allows for numbers to be treated like objects, the same code written in JavaScript still looks somewhat readable:&lt;br /&gt;
 1.&#039;&#039;&#039;kilo&#039;&#039;&#039;().&#039;&#039;&#039;meter&#039;&#039;&#039;() / 10.&#039;&#039;&#039;minutes&#039;&#039;&#039;()&lt;br /&gt;
although the parentheses make the code somewhat ugly.&lt;br /&gt;
&lt;br /&gt;
All code fragments in the following document are written in Smalltalk syntax (add periods and parentheses to get the corresponding JS code).&lt;br /&gt;
&lt;br /&gt;
== Units ==&lt;br /&gt;
=== Base Units ===&lt;br /&gt;
&lt;br /&gt;
All [https://en.wikipedia.org/wiki/SI_base_unit base units] are measured in their corresponding [https://en.wikipedia.org/wiki/International_System_of_Units SI standard] units and print with an appropriate scaling prefix. I.e. by default, the unit chooses a &amp;quot;reasonable&amp;quot; prefix.&lt;br /&gt;
&lt;br /&gt;
For example, a mass which has a [https://en.wikipedia.org/wiki/SI_base_unit base unit] of kilogram (&amp;quot;kg&amp;quot;), will print itself as &amp;quot;kg&#039;, &#039;mg&#039;, &#039;µg&#039; etc. depending on its magnitude. &lt;br /&gt;
&lt;br /&gt;
Explicit converters can be used to enforce a particular unit printing (e.g. if you insist on printing a mass in pounds, in grams, etc.) or if you want to enforce a particular scaling SI prefix (e.g. to enforce printing output in &amp;quot;cm&amp;quot; instead of &amp;quot;m&amp;quot; or &amp;quot;mm&amp;quot;). &lt;br /&gt;
&lt;br /&gt;
See examples below on how those converters affect the printout of a value. &lt;br /&gt;
&lt;br /&gt;
Independent from any enforced print format, the internal representation of physical values is always using base unit amounts (i.e. SI units).&lt;br /&gt;
&lt;br /&gt;
Base units are:&lt;br /&gt;
 Unit    Name        Smalltalk       Description&lt;br /&gt;
 -----------------------------------------------&lt;br /&gt;
 s	Second	    second           [https://en.wikipedia.org/wiki/Time time]&lt;br /&gt;
 m	Metre	    metre or meter   [https://en.wikipedia.org/wiki/Length length]&lt;br /&gt;
 kg	Kilogram    kilogram         [https://en.wikipedia.org/wiki/Mass mass]&lt;br /&gt;
 A	Ampere	    ampere           [https://en.wikipedia.org/wiki/Electric_current electric current]&lt;br /&gt;
 K	Kelvin	    kelvin           [https://en.wikipedia.org/wiki/Thermodynamic_temperature temperature]&lt;br /&gt;
 mol	Mole	    mole             [https://en.wikipedia.org/wiki/Amount_of_substance amount of substance]&lt;br /&gt;
 cd	Candela	    candela          [https://en.wikipedia.org/wiki/Luminous_intensity luminous intensity]&lt;br /&gt;
&lt;br /&gt;
To get a constant physical value in your Smalltalk code, write a [[Number_API_Functions|number]] followed by the unit name (in lowercase). For example:&lt;br /&gt;
&lt;br /&gt;
 1 second   &amp;lt;small&amp;gt;=&amp;gt; 1s&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 meter    &amp;lt;small&amp;gt;=&amp;gt; 1 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 kilogram &amp;lt;small&amp;gt;=&amp;gt; 1 kg&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 ampere   &amp;lt;small&amp;gt;=&amp;gt; 1 A&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 kelvin   &amp;lt;small&amp;gt;=&amp;gt; 1 K&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 mole     &amp;lt;small&amp;gt;=&amp;gt; 1 mol&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 candela  &amp;lt;small&amp;gt;=&amp;gt; 1 cd&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(in other words: there are a number of methods defined in the  [[Number_API_Functions|Number]] class, &lt;br /&gt;
which take the receiver and construct a corresponding unit instance from it. These methods are named after the SI unit names).&lt;br /&gt;
&lt;br /&gt;
=== Derived Units ===&lt;br /&gt;
Additional [https://en.wikipedia.org/wiki/SI_derived_unit derived units] are:&lt;br /&gt;
&lt;br /&gt;
 Unit    Name             Smalltalk                Description&lt;br /&gt;
 -------------------------------------------------------------&lt;br /&gt;
 V      Volt              volt                     voltage&lt;br /&gt;
 Hz     Hertz             hertz                    frequency&lt;br /&gt;
 m/s    Meter per Second  meterPerSecond           speed, velocity&lt;br /&gt;
 m/s²   m/s per Second    meterPerSecondPerSecond  acceleration&lt;br /&gt;
 m²     Square Meter      squareMeter              area&lt;br /&gt;
 m³     Cubic Meter       cubicMeter               volume&lt;br /&gt;
 pa     Pascal            pascal                   pressure&lt;br /&gt;
 W      Watt              watt                     power&lt;br /&gt;
 N      Newton            newton                   force&lt;br /&gt;
 J      Joule             joule                    energy&lt;br /&gt;
 Ω      Ohm               ohm                      electric resistance&lt;br /&gt;
 S      Siemens           siemens                  electric conductance&lt;br /&gt;
 C      Coulomb           coulomb                  electric charge&lt;br /&gt;
 F      Farad             farad                    electric capacitance&lt;br /&gt;
 H      Henry             henry                    electric inductance&lt;br /&gt;
 T      Tesla             tesla                    magnetic flux density&lt;br /&gt;
 rad    Radian            radian                   angle&lt;br /&gt;
 sr     Steradian         steradian                solid angle&lt;br /&gt;
 °      Degrees           degrees                  angle&lt;br /&gt;
&lt;br /&gt;
Plus possibly more, by the time you read this.&lt;br /&gt;
There are a number of less frequently used derived units, for which no Smalltalk shortcut exists.&lt;br /&gt;
These might result from computations with physical values or be instantiated by sending explicit constructor messages to the unit (instead of sending a message to a  [[Number_API_Functions|number]]).&lt;br /&gt;
&amp;lt;br&amp;gt;These are described below.&lt;br /&gt;
&lt;br /&gt;
=== Converting Units ===&lt;br /&gt;
By default, values are presented as SI units. However, you may want to convert the to other unit systems. For this, converting units are provided.&lt;br /&gt;
These present a value in another unit system. For example as a value in imperial units (Inches, Pounds, etc.). Like all physical values they keep the actual amount internally in multiples of the SI base unit (metric), but will show the value with some scaling and with another unitString (eg. &#039;lb&#039; or &#039;ft&#039;).&lt;br /&gt;
&lt;br /&gt;
You can ask any other unit (usually a base unit) for a converting unit via getter messages, or by asking for a unit by its formula or by name.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, you can ask the Length base unit for a number of common converting units:&lt;br /&gt;
 Physic::Length yards               =&amp;gt; a unit which presents its metric amount in yards&lt;br /&gt;
 Physic::Length inches                 or inches&lt;br /&gt;
 Physic::Length feetAndInches          ...he&#039;s 5 foot 2, he&#039;s 6 foot 4...&lt;br /&gt;
 Physic::Length angstrom            =&amp;gt; a unit which presents its amount in angstrom&lt;br /&gt;
 Physic::Length lightYears             or light years&lt;br /&gt;
 Physic::Length awgDiameter         =&amp;gt; presents its amount as american wire gauge diameter&lt;br /&gt;
and then create a value for it with the &amp;quot;&amp;lt;code&amp;gt;unitAmount:&amp;lt;/code&amp;gt;&amp;quot; message.&lt;br /&gt;
&amp;lt;br&amp;gt;This will generate a value in multiples of the message-receiver&#039;s unit, as in:&lt;br /&gt;
 Physic::Length yards unitAmount:5  &amp;lt;small&amp;gt;=&amp;gt; 5 yd&amp;lt;/small&amp;gt;&lt;br /&gt;
The list of converting units available per unit is shown below.&lt;br /&gt;
&lt;br /&gt;
=== Scaling Units ===&lt;br /&gt;
As already mentioned above, unit values by default determine themself how small or large amounts are printed. For example, the Length unit will print amounts with an SI scale (kilo, mega, milli, etc.). Thus, when the value &amp;quot;4.5 milli meter&amp;quot; is printed (or displayed), it will present itself as &amp;quot;4.5 mm&amp;quot; (not as &amp;quot;0.45 cm&amp;quot; or &amp;quot;0.0045 m&amp;quot;). The scale used depends on heuristic and is chosen to conform to usual human written conventions.&lt;br /&gt;
&lt;br /&gt;
You can convert any physical value to one where this heuristic is overwritten and an explicit SI-scale is preferred.&lt;br /&gt;
For this, use a &#039;&#039;Scaling Unit&#039;&#039;. Specifying an explicit scaling unit is useful if you want to present values in a table or if you have to export values in a particular scale to some other program. Notice that the value of the scaling unit instance is still same - the only difference is how it prints itself.  &lt;br /&gt;
&lt;br /&gt;
Scaling units will print the amount with an explicit scale. Any unit can be asked for a scaling unit, although not all combinations are typically used in real live: for example, no-one would write &amp;quot;2 Hm&amp;quot; (hecto meter) or &amp;quot;1 Mm&amp;quot; (mega meter).&lt;br /&gt;
&amp;lt;br&amp;gt;You can get a scaling unit from any other unit with one of:&lt;br /&gt;
 nanoUnit, microUnit, milliUnit, centiUnit, deciUnit, hectorUnit, kiloUnit, megaUnit, gigaUnit, etc.&lt;br /&gt;
(any of the possible scaling prefixes listed below concatenated with &amp;quot;Unit&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Similar to the above, you can create values with &amp;quot;&amp;lt;code&amp;gt;unitAmount:&amp;lt;/code&amp;gt;&amp;quot;, as in:&lt;br /&gt;
 Physic::Mass pounds kiloUnit unitAmount:2&lt;br /&gt;
to create a mass of &amp;quot;2 kilo pounds (imperial)&amp;quot; which prints itself as &amp;quot;2 klb&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;Or:&lt;br /&gt;
 Physic::Frequency kiloUnit unitAmount:10&lt;br /&gt;
to enforce that the frequency will be printed in kilohertz.&lt;br /&gt;
&lt;br /&gt;
There is also a special &amp;quot;&amp;lt;code&amp;gt;unitUnit&amp;lt;/code&amp;gt;&amp;quot;, which prints its values as SI base units (without any scaling prefix). Use this eg. to enforce a length value to always print itself as meters.&lt;br /&gt;
&lt;br /&gt;
Conversion methods are also available on values. Every physical value can be converted using one of the messages: &lt;br /&gt;
 asKiloUnitValue, asMilliUnitValue, asMicroUnitValue, etc. &lt;br /&gt;
And you get a base unit value using &amp;quot;&amp;lt;code&amp;gt;asUnitUnitValue&amp;lt;/code&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Thus, &amp;quot;&amp;lt;code&amp;gt;4.5 milli meter asCentiUnitValue&amp;lt;/code&amp;gt;&amp;quot; will present itself as &amp;quot;0.45 cm&amp;quot; &lt;br /&gt;
and &amp;quot;&amp;lt;code&amp;gt;4.5 milli meter asUnitUnitValue&amp;lt;/code&amp;gt;&amp;quot; as &amp;quot;0.0045 m&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Unit vs. BaseUnit ===&lt;br /&gt;
&lt;br /&gt;
As described, there are base units (eg. Meter, Kilogram, etc.) and their combinations (eg. Acceleration, Velocity, Energy ec.) and converting units such as Imperial Pound, Feet, Nautical Mile etc.&lt;br /&gt;
&lt;br /&gt;
Every unit understands two pairs of value generator and value extracting messages: &lt;br /&gt;
 unitAmount: / unitAmount&lt;br /&gt;
and:&lt;br /&gt;
 baseUnitAmount: /baseUnitAmount&lt;br /&gt;
the unitAmount is the amount in that value&#039;s converted amount (eg. in Feet or Acre), whereas the baseUnitAmount is always the amount in the SI base or combination unit (eg. in Meter or SquareMeter).&lt;br /&gt;
&lt;br /&gt;
Thus, every length unit will return a length of 1 meter if created with the &amp;quot;baseUnitAmount:&amp;quot; instance creation message; independent on how it will later be printed.&lt;br /&gt;
&lt;br /&gt;
And every length unit will return a length with its own scale value via the &amp;quot;unitAmount:&amp;quot; creation message. For base units and directly derived units, the baseUnitAmount it the same as the unitAmount.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;2) &amp;lt;small&amp;gt;=&amp;gt; 2 m&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;baseUnitAmount:&#039;&#039;&#039;2) &amp;lt;small&amp;gt;=&amp;gt; 2 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;feet&#039;&#039;&#039; &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;2) &amp;lt;small&amp;gt;=&amp;gt; 2 ft&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;feet&#039;&#039;&#039; &#039;&#039;&#039;baseUnitAmount:&#039;&#039;&#039;2) &amp;lt;small&amp;gt;=&amp;gt; 6.56167979002624 ft&amp;lt;/small&amp;gt; (because 2 meters - the base unit value - is 6.56 ft)&lt;br /&gt;
&lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;unitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 2&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;baseUnitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;unitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 2&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;baseUnitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 2&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;baseUnitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;baseUnitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 2&amp;lt;/small&amp;gt; &lt;br /&gt;
&lt;br /&gt;
 (Physic::Length feet &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;unitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 2&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length feet &#039;&#039;&#039;baseUnitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;unitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 6.56167979002624&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length feet &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;baseUnitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 0.6096&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length feet &#039;&#039;&#039;baseUnitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;baseUnitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 2&amp;lt;/small&amp;gt; &lt;br /&gt;
&lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;10000000) &#039;&#039;&#039;unitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 10000000&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;meter&#039;&#039;&#039; &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;10000000) &#039;&#039;&#039;unitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 10000000&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;meter&#039;&#039;&#039; &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;10000000) &#039;&#039;&#039;baseUnitAmount&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 10000000&amp;lt;/small&amp;gt; &lt;br /&gt;
but when printed:&lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;10000000) &#039;&#039;&#039;printString&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 10000 km&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;meter&#039;&#039;&#039; &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;10000000) &#039;&#039;&#039;printString&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 10000000 m&amp;lt;/small&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition, physical value instances can be converted to their corresponding SI base unit value via &amp;quot;asBaseUnitValue&amp;quot;. And of course, values in base units will return themself.&amp;lt;br&amp;gt;For example:&lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;asBaseUnitValue&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 2 m&amp;lt;/small&amp;gt; &lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;feet&#039;&#039;&#039; &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;2) &#039;&#039;&#039;asBaseUnitValue&#039;&#039;&#039;  &amp;lt;small&amp;gt;=&amp;gt; 0.6096 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 (Physic::Length &#039;&#039;&#039;meter&#039;&#039;&#039; &#039;&#039;&#039;unitAmount:&#039;&#039;&#039;10000000) &#039;&#039;&#039;asBaseUnitValue&#039;&#039;&#039;  &amp;lt;small&amp;gt;=&amp;gt; 10000 km&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More on this below in the physical values chapter.&lt;br /&gt;
&lt;br /&gt;
=== Number Prefix Messages===&lt;br /&gt;
&lt;br /&gt;
==== SI Prefix ====&lt;br /&gt;
&lt;br /&gt;
[[Number_API_Functions|Numbers]] (in Smalltalk and JavaScript) can be scaled by an SI prefix message.&lt;br /&gt;
Thus, when combining a unit message with a scaled number, we get a scaled physical value.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, without SI prefix, we get:&lt;br /&gt;
 1 &#039;&#039;&#039;gram&#039;&#039;&#039;        &amp;lt;small&amp;gt;=&amp;gt; &#039;1 g&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
whereas with a &#039;micro&#039; prefix, the result is:&lt;br /&gt;
 1 &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;gram&#039;&#039;&#039;  &amp;lt;small&amp;gt;=&amp;gt; &#039;1 µg&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
or:&lt;br /&gt;
 1 &#039;&#039;&#039;hecto&#039;&#039;&#039; &#039;&#039;&#039;liter&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; &#039;100 liter&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The corresponding JavaScript code is similar, but slightly less elegant looking due to the required periods and parentheses:&lt;br /&gt;
 1.&#039;&#039;&#039;gram&#039;&#039;&#039;()&lt;br /&gt;
 1.&#039;&#039;&#039;micro&#039;&#039;&#039;().&#039;&#039;&#039;gram&#039;&#039;&#039;()&lt;br /&gt;
 1.&#039;&#039;&#039;hecto&#039;&#039;&#039;().&#039;&#039;&#039;liter&#039;&#039;&#039;()&lt;br /&gt;
&lt;br /&gt;
Possible scaling prefixes are:&lt;br /&gt;
 yocto   1E-24   1 / 1000000000000000000000000 &lt;br /&gt;
 zepto   1E-21   1 / 1000000000000000000000 &lt;br /&gt;
 atto    1E-18   1 / 1000000000000000000&lt;br /&gt;
 femto   1E-15   1 / 1000000000000000&lt;br /&gt;
 pico    1E-12   1 / 1000000000000&lt;br /&gt;
 nano    1E-9    1 / 1000000000&lt;br /&gt;
 micro   1E-6    1 / 1000000&lt;br /&gt;
 milli   1E-3    1 / 1000&lt;br /&gt;
 centi   1E-2    1 / 100&lt;br /&gt;
 deci    1E-1    1 / 10&lt;br /&gt;
 deca    1E+1    10&lt;br /&gt;
 hecto   1E+2    100&lt;br /&gt;
 kilo    1E+3    1000&lt;br /&gt;
 mega    1E+6    1000000&lt;br /&gt;
 giga    1E+9    1000000000&lt;br /&gt;
 tera    1E+12   1000000000000&lt;br /&gt;
 peta    1E+15   1000000000000000&lt;br /&gt;
 exa     1E+18   1000000000000000000&lt;br /&gt;
 zetta   1E+21   1000000000000000000000&lt;br /&gt;
 yotta   1E+24   1000000000000000000000000&lt;br /&gt;
 ronna   1E+27   1000000000000000000000000000&lt;br /&gt;
 quetta  1E+30   1000000000000000000000000000000&lt;br /&gt;
&lt;br /&gt;
You can combine the SI scale with a unit, as in:&lt;br /&gt;
 1 &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;&lt;br /&gt;
 1 &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;ampere&#039;&#039;&#039;&lt;br /&gt;
 1 &#039;&#039;&#039;mega&#039;&#039;&#039; &#039;&#039;&#039;watt&#039;&#039;&#039;&lt;br /&gt;
 1 &#039;&#039;&#039;pico&#039;&#039;&#039; &#039;&#039;&#039;farad&#039;&#039;&#039;&lt;br /&gt;
 1 &#039;&#039;&#039;exa&#039;&#039;&#039; &#039;&#039;&#039;bytes&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For some common units, additional shortcuts exist:&lt;br /&gt;
 1 kiloMeter   ; centiMeter ;  milliMeter ;  microMeter ; nanoMeter&lt;br /&gt;
 1 milliGram   ; microGram&lt;br /&gt;
 1 kiloAmpere  ; milliAmpere ; microAmpere ; nanoAmpere&lt;br /&gt;
 1 kiloVolt    ; milliVolt ; microVolt&lt;br /&gt;
 1 kiloByte    ; megaByte ; teraByte ; peraByte ; exaByte&lt;br /&gt;
 1 kiloJoule   ; megaJoule&lt;br /&gt;
 1 kiloHertz   ; megaHertz ; gigaHertz&lt;br /&gt;
 1 kiloOhm     ; megaOhm&lt;br /&gt;
 1 kiloWatt    ; teraWatt ; gigaWatt ; megaWatt ; milliWatt&lt;br /&gt;
&lt;br /&gt;
But in general, you will have to combine the SI scale with a unit as described above.&lt;br /&gt;
&lt;br /&gt;
==== Bits &amp;amp; Bytes ====&lt;br /&gt;
In addition to the above listed powers-of-10 scaling prefixes,&lt;br /&gt;
there are also powers-of-2 prefixes, which are usually only used with byte or bit amounts.&lt;br /&gt;
&lt;br /&gt;
 kibi    2ˆ10    1024&lt;br /&gt;
 mebi    2ˆ20    1048576 (same as &amp;quot;1024 * 1024&amp;quot; or &amp;quot;1024 kibi&amp;quot;)&lt;br /&gt;
 gibi    2ˆ30    1073741824 (same as &amp;quot;1024 * 1024 * 1024&amp;quot; or &amp;quot;1024 mebi)&lt;br /&gt;
 tebi    2ˆ40    1099511627776&lt;br /&gt;
 pebi    2ˆ50    1125899906842624&lt;br /&gt;
 exbi    2ˆ60    1152921504606846976&lt;br /&gt;
 zebi    2ˆ70    1180591620717411303424&lt;br /&gt;
 yobi    2ˆ80    1208925819614629174706176&lt;br /&gt;
&lt;br /&gt;
For the kibi scaler, you can use the shortcut:&lt;br /&gt;
 1 &#039;&#039;&#039;kibiByte&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 1024 B&amp;lt;/small&amp;gt;&lt;br /&gt;
all others need to be combined, as in:&lt;br /&gt;
 1.0 &#039;&#039;&#039;mebi&#039;&#039;&#039; &#039;&#039;&#039;byte&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 1024 kiB&amp;lt;/small&amp;gt;&lt;br /&gt;
 1.0 &#039;&#039;&#039;mebi&#039;&#039;&#039; &#039;&#039;&#039;byte&#039;&#039;&#039; &#039;&#039;&#039;asMegaBytes&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 1.048576 MB&amp;lt;/small&amp;gt;&lt;br /&gt;
 1.0 &#039;&#039;&#039;mebi&#039;&#039;&#039; &#039;&#039;&#039;byte&#039;&#039;&#039; &#039;&#039;&#039;asMebiBytes&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 1 MiB&amp;lt;/small&amp;gt;&lt;br /&gt;
 1.0 &#039;&#039;&#039;mebi&#039;&#039;&#039; &#039;&#039;&#039;bits&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 1048.576 kbit&amp;lt;/small&amp;gt;&lt;br /&gt;
 1.0 &#039;&#039;&#039;mebi&#039;&#039;&#039; &#039;&#039;&#039;bits&#039;&#039;&#039; &#039;&#039;&#039;asMegaBytes&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 0.131072 MB&amp;lt;/small&amp;gt;&lt;br /&gt;
 1.0 &#039;&#039;&#039;mebi&#039;&#039;&#039; &#039;&#039;&#039;bits&#039;&#039;&#039; &#039;&#039;&#039;asMebiBytes&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 0.125 MiB&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Hundreds, thousands etc. ====&lt;br /&gt;
In addition, the prefixes &amp;quot;hundred&amp;quot;, &amp;quot;thousand&amp;quot; and &amp;quot;million&amp;quot; are supported:&lt;br /&gt;
 1 &#039;&#039;&#039;hundred&#039;&#039;&#039; &#039;&#039;&#039;million&#039;&#039;&#039; &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;gram&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt;100000000 kg&amp;lt;/small&amp;gt;&lt;br /&gt;
To represent the pressure inside the sun, write:&lt;br /&gt;
 26.5 &#039;&#039;&#039;million&#039;&#039;&#039; &#039;&#039;&#039;giga&#039;&#039;&#039; &#039;&#039;&#039;pascal&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 2.65e+16 Pa&amp;lt;/small&amp;gt; &lt;br /&gt;
or&lt;br /&gt;
 26.5 &#039;&#039;&#039;million&#039;&#039;&#039; &#039;&#039;&#039;giga&#039;&#039;&#039; &#039;&#039;&#039;pascal&#039;&#039;&#039; &#039;&#039;&#039;asPSI&#039;&#039;&#039; &amp;lt;small&amp;gt;=&amp;gt; 3843364757070.34 psi&amp;lt;/small&amp;gt;&lt;br /&gt;
There is intentionally NO SUPPORT for billion, trillion etc., because most german journalists and even some non journalists have no idea about US vs. continental meanings of those (big smiley here). In britain, its even worse, where both systems are used in parallel (https://de.wikipedia.org/wiki/Billion).&lt;br /&gt;
&lt;br /&gt;
==== Imperial / American / Metric Prefix ====&lt;br /&gt;
For some units, additional prefixes are allowed.&lt;br /&gt;
&lt;br /&gt;
american / imperial:&lt;br /&gt;
 barrel, cup, floz, gallon, pint, quart, tablespoon, teaspoon&lt;br /&gt;
 dry pint, dry quart, dry peck&lt;br /&gt;
metric / imperial:&lt;br /&gt;
 ton, hp&lt;br /&gt;
&lt;br /&gt;
I.e. you can write:&lt;br /&gt;
 1 imperial gallon &amp;lt;small&amp;gt;=&amp;gt; 4.54609 l&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 american gallon &amp;lt;small&amp;gt;=&amp;gt; 3.785411784 l&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 metric ton &amp;lt;small&amp;gt;=&amp;gt; 1000 kg&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 imperial ton &amp;lt;small&amp;gt;=&amp;gt; 1016.0469088 kg&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 imperial teaspoon &amp;lt;small&amp;gt;=&amp;gt; 5.91939880031792 ml&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 american pint &amp;lt;small&amp;gt;=&amp;gt; 473.176473 ml&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 american dry pint &amp;lt;small&amp;gt;=&amp;gt; 550.6104713575 ml&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Square / Cubic Prefix ====&lt;br /&gt;
For readability, there are also a square and cubic prefíxes, usable with: centiMeter. feet, inches, kiloMeter, meter, miles, milliMeter, yards.&lt;br /&gt;
&lt;br /&gt;
You can write:&lt;br /&gt;
 1 square meter &amp;lt;small&amp;gt;=&amp;gt; 1 m²&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 cubic feet &amp;lt;small&amp;gt;=&amp;gt; 28.316846592 l&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 square yard &amp;lt;small&amp;gt;=&amp;gt; 0.83612736 m²&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Troy Prefix ====&lt;br /&gt;
For readability, there is also a troy prefíx, usable only with ounces.&lt;br /&gt;
&lt;br /&gt;
You can write:&lt;br /&gt;
 1 troy ounce &amp;lt;small&amp;gt;=&amp;gt; 31.1034768 g&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 american ounce &amp;lt;small&amp;gt;=&amp;gt; 28.349523125 g&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 british ounce &amp;lt;small&amp;gt;=&amp;gt; 28.349523125 g&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Unit API == &lt;br /&gt;
&lt;br /&gt;
==== Units vs. Values ====&lt;br /&gt;
Internally, PhysicalValues are represented as a pair of a PhysicalUnit and an amount. PhysicalUnit may be either one of the above listed base units (i.e. SI base units), or a scaling/converting unit (e.g. Inches or Hectare but also MilliMeter). The amount is always the baseUnit amount i.e. meter, kilogram, square meter etc.&lt;br /&gt;
&lt;br /&gt;
===== Units =====&lt;br /&gt;
You can get a unit (in contrast to a value) by sending one of the unit-messages to the Physic::PhysicalUnit class (i.e. the class named &amp;quot;&#039;&#039;PhysicalUnit&#039;&#039;&amp;quot; in the &amp;quot;&#039;&#039;Physic&#039;&#039;&amp;quot; namespace).&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
 Physic::PhysicalUnit energy&lt;br /&gt;
will give you the &amp;quot;Energy&amp;quot; class which represents values in &amp;quot;Joule&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Conversion units are retrieved by asking one such unit for another unit, by sending it a corresponding getter message.&lt;br /&gt;
&lt;br /&gt;
For example, we can ask the Energy class for a converting class named &amp;quot;Calories&amp;quot; or &amp;quot;KiloCalories&amp;quot; with:&lt;br /&gt;
 Physic::PhysicalUnit energy calories&lt;br /&gt;
 Physic::PhysicalUnit energy kilo calories&lt;br /&gt;
&lt;br /&gt;
Actually, you can also ask the (abstract) PhysicalUnit class for a unit:&lt;br /&gt;
 Physic::PhysicalUnit calories&lt;br /&gt;
 Physic::PhysicalUnit kilo calories&lt;br /&gt;
&lt;br /&gt;
===== Values =====&lt;br /&gt;
On the basic level, PhysicalValue are created by sending the &amp;quot;&amp;lt;CODE&amp;gt;unitAmount:&amp;lt;/CODE&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;baseUnitAmount:&amp;lt;/code&amp;gt; message to a unit. However, for the most common units, convenient and more readable messages are implemented in the [[Number_API_Functions|Number]] hierarchy. These allow for shorter code and will be described below.&lt;br /&gt;
&amp;lt;br&amp;gt;For example:&lt;br /&gt;
 Physic::PhysicalUnit energy unitAmount:100&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 100 J&amp;lt;/small&amp;gt;&lt;br /&gt;
generates an energy instance of 100 joule.&lt;br /&gt;
&lt;br /&gt;
The argument of the &amp;quot;&amp;lt;CODE&amp;gt;unitAmount:&amp;lt;/CODE&amp;gt;&amp;quot; call is always given in units of the receiver unit, whereas the alternative constructor named &amp;quot;&amp;lt;CODE&amp;gt;baseUnitAmount:&amp;lt;/CODE&amp;gt;&amp;quot; expects the argument to be in the underlying base unit (i.e. one of the SI units).&lt;br /&gt;
&lt;br /&gt;
This makes no difference for the base SI units, but is relevant, if you deal with conversion units (e.g. imperial units) as described later.&lt;br /&gt;
&amp;lt;br&amp;gt;Thus,&lt;br /&gt;
 Physic::PhysicalUnit energy calories unitAmount:100&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 100 cal&amp;lt;/small&amp;gt;&lt;br /&gt;
 Physic::PhysicalUnit calories unitAmount:100&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 100 cal&amp;lt;/small&amp;gt;&lt;br /&gt;
will create an energy instances of 100 calories (which will print themself as 100 calories),&lt;br /&gt;
&amp;lt;br&amp;gt;whereas:&lt;br /&gt;
 Physic::PhysicalUnit energy calories baseUnitAmount:100&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 23.9005736137667 cal&amp;lt;/small&amp;gt;&lt;br /&gt;
will create an energy instance of 100 joule (but it will print itself as 23.90 calories).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice, that the &amp;quot;&amp;lt;code&amp;gt;energy&amp;lt;/code&amp;gt;&amp;quot; message is a facade getter method of Physic::PhysicalUnit. It retrieves the Energy class, which is actually named &amp;quot;Physic::Energy&amp;quot; and is also located in the Physic namespace. &lt;br /&gt;
&amp;lt;br&amp;gt;So we could have written:&lt;br /&gt;
 Physic::Energy calories unitAmount:100&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 100 cal&amp;lt;/small&amp;gt;&lt;br /&gt;
or, given 100 joule:&lt;br /&gt;
 Physic::Energy calories baseUnitAmount:100&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 23.9005736137667 cal&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Value Creation ======&lt;br /&gt;
&lt;br /&gt;
Given one of the units as listed below, a value instance can be created by different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;Given an amount in that unit, as in:&lt;br /&gt;
 Physic::Mass kilogram unitAmount:1.5.   &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 1.5 kg&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::Mass troyOunces unitAmount:1.5. &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 1.5 oz t&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Given an amount in base SI units (same as unitAmount for the SI units, but different for derived units):&lt;br /&gt;
 Physic::Mass kilogram baseUnitAmount:1.5.   &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 1.5 kg&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::Mass troyOunces baseUnitAmount:1.5. &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 48.226119852942 oz t. (i.e. 1.5kg as troy ounces)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By converting, given a value in any unit and a target unit:&lt;br /&gt;
 (Physic::Mass kilogram unitAmount:0.1) as:(Physic::Mass troyOunces) &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 3.2150746568628 oz t. (i.e. 0.1 kg as troy ounces)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
same, but given a target unit&#039;s name:&lt;br /&gt;
 (Physic::Mass kilogram unitAmount:0.1) as:&#039;Pounds&#039; &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 0.220462262184878 lb.&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
or given a target unit&#039;s unitString:&lt;br /&gt;
 (Physic::Mass kilogram unitAmount:0.1) as:&#039;lb&#039; &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 0.220462262184878 lb.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== SI Base and Derived Units ==== &lt;br /&gt;
Getters for well known units are:&lt;br /&gt;
&lt;br /&gt;
 Physic::PhysicalUnit acceleration&lt;br /&gt;
 Physic::PhysicalUnit amountOfSubstance&lt;br /&gt;
 Physic::PhysicalUnit angle&lt;br /&gt;
 Physic::PhysicalUnit area&lt;br /&gt;
 Physic::PhysicalUnit currentDensity&lt;br /&gt;
 Physic::PhysicalUnit electricCapacitance&lt;br /&gt;
 Physic::PhysicalUnit electricCharge&lt;br /&gt;
 Physic::PhysicalUnit electricConductance&lt;br /&gt;
 Physic::PhysicalUnit electricCurrent&lt;br /&gt;
 Physic::PhysicalUnit electricResistance&lt;br /&gt;
 Physic::PhysicalUnit energy&lt;br /&gt;
 Physic::PhysicalUnit force&lt;br /&gt;
 Physic::PhysicalUnit frequency&lt;br /&gt;
 Physic::PhysicalUnit inductance&lt;br /&gt;
 Physic::PhysicalUnit length&lt;br /&gt;
 Physic::PhysicalUnit luminousIntensity&lt;br /&gt;
 Physic::PhysicalUnit mass&lt;br /&gt;
 Physic::PhysicalUnit massDensity&lt;br /&gt;
 Physic::PhysicalUnit power&lt;br /&gt;
 Physic::PhysicalUnit pressure&lt;br /&gt;
 Physic::PhysicalUnit specificVolume&lt;br /&gt;
 Physic::PhysicalUnit temperature&lt;br /&gt;
 Physic::PhysicalUnit time&lt;br /&gt;
 Physic::PhysicalUnit velocity&lt;br /&gt;
 Physic::PhysicalUnit voltage&lt;br /&gt;
 Physic::PhysicalUnit volume&lt;br /&gt;
  &lt;br /&gt;
 Physic::PhysicalUnit knownUnits&lt;br /&gt;
&lt;br /&gt;
The last returns a collection of all known units (there are actually more than listed above).&lt;br /&gt;
&lt;br /&gt;
The very most used units are directly accessible via a global under the Physic namespace:&lt;br /&gt;
 Physic::Mass&lt;br /&gt;
 Physic::Length&lt;br /&gt;
 Physic::Energy&lt;br /&gt;
 Physic::Velocity&lt;br /&gt;
 etc.&lt;br /&gt;
&lt;br /&gt;
For common units, additional instance creation protocol is provided in the [[Number_API_Functions|Number]] class. E.g.: &lt;br /&gt;
 100 joule &amp;lt;br&amp;gt;  &amp;lt;small&amp;gt;=&amp;gt; 100 J&amp;lt;/small&amp;gt;&lt;br /&gt;
will generate the same as: &lt;br /&gt;
 (Physic::PhysicalUnit energy) baseUnitAmount:100&amp;lt;br&amp;gt;   &amp;lt;small&amp;gt;=&amp;gt; 100 J&amp;lt;/small&amp;gt;&lt;br /&gt;
which is the same as:&lt;br /&gt;
 Physic::Energy baseUnitAmount:100&amp;lt;br&amp;gt;  &amp;lt;small&amp;gt;=&amp;gt; 100 J&amp;lt;/small&amp;gt;&lt;br /&gt;
which (for base units) is the same as:&lt;br /&gt;
 Physic::Energy unitAmount:100 &amp;lt;br&amp;gt;  &amp;lt;small&amp;gt;=&amp;gt; 100 J&amp;lt;/small&amp;gt;&lt;br /&gt;
The additional [[Number_API_Functions|Number]]-protocol is described below.&lt;br /&gt;
&lt;br /&gt;
In the above examples, the unit was a baseUnit, and therefore the baseUnitAmoun the same as the unitAmount.&lt;br /&gt;
&lt;br /&gt;
Things are different for derived units:&lt;br /&gt;
 Physic::Energy calories unitAmount:100 &amp;lt;br&amp;gt;  &amp;lt;small&amp;gt;=&amp;gt; 100 cal&amp;lt;/small&amp;gt;&lt;br /&gt;
vs.&lt;br /&gt;
 Physic::Energy calories baseUnitAmount:100 &amp;lt;br&amp;gt;  &amp;lt;small&amp;gt;=&amp;gt; 23.9005736137667 cal (because these are 100 joule)&amp;lt;/small&amp;gt;&lt;br /&gt;
More on that below.&lt;br /&gt;
&lt;br /&gt;
==== Printing Unit Values ==== &lt;br /&gt;
When printed, physical values will scale and use an SI prefix as appropriate.&amp;lt;br&amp;gt;For example, by default, a value of 10 millimeter will print as &amp;quot;10 mm&amp;quot; instead of &amp;quot;0.01 m&amp;quot; (remember: meter is the underlying SI base unit). The choice of prefix (milli, micro, nano, etc.) is decided by the unit&#039;s &amp;quot;printWithUnit:on:&amp;quot; method, which in case of length values chooses an appropriate prefix from nanos to lightyears, based on heuristics.&lt;br /&gt;
&lt;br /&gt;
This print behavior can be changed by converting to an explicit converting unit via one of the &amp;quot;&amp;lt;CODE&amp;gt;asXXX&amp;lt;/CODE&amp;gt;&amp;quot; messages listed below. However, the SI base unit amount will be kept internally and used in arithmetic operations. Thus, e.g. when adding a meter with inches, an SI meter value will be generated, and the result will be presented in the same unit as the receiver (first operand).&amp;lt;br&amp;gt;For example:&lt;br /&gt;
 1 inch&lt;br /&gt;
returns an SI base-unit value (i.e. in meters) and will print as meter (actually as &#039;25.4 mm&#039;), whereas:&lt;br /&gt;
 1 inch asInches&lt;br /&gt;
will print itself as inches because of the &amp;quot;asInches&amp;quot; message. &lt;br /&gt;
&amp;lt;br&amp;gt;All of:&lt;br /&gt;
 1 meter + 1 inch &lt;br /&gt;
 1 meter + 1 inch asInches &lt;br /&gt;
 1 inch + 1 meter &lt;br /&gt;
will print as meter (&#039;1.0254 m&#039;), because the first operand&#039;s unit determines the unitString. &lt;br /&gt;
&amp;lt;br&amp;gt;However,&lt;br /&gt;
 1 inch asInches + 1 meter &lt;br /&gt;
 1 inch asInches + 1 meter asInches&lt;br /&gt;
will all print as inches (&#039;40.37 in&#039;).&lt;br /&gt;
&lt;br /&gt;
You can also pass a target unit string, as in:&lt;br /&gt;
 1 meter as:&#039;in&#039;&lt;br /&gt;
or the target unit:&lt;br /&gt;
 1 meter as:(Physic::Length inches)&lt;br /&gt;
or the unit&#039;s name:&lt;br /&gt;
 1 meter as:&#039;Inches&#039;&lt;br /&gt;
which all print as &#039;39.3700787401575 in&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Printing with another Unitstring ====&lt;br /&gt;
Some units are printed with different unit symbols, depending on context.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, nautical miles are printed in aviation as &amp;quot;NM&amp;quot;, whereas in US official documents they are printed as &amp;quot;nmi&amp;quot;. And a german document might want to print them as &amp;quot;sm&amp;quot; (&amp;quot;Seemeilen&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
For that, convert the value (or unit) with &amp;quot;&amp;lt;code&amp;gt;withUnitSymbol:&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, a value of two nauticalMiles is printed in different units:&lt;br /&gt;
 2 nauticalMiles printString &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; &#039;3704 m&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 2 nauticalMiles asNauticalMiles printString &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; &#039;2 NM&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 (2 nauticalMiles asNauticalMiles withUnitSymbol:&#039;nmi&#039;) printString &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; &#039;2 nmi&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 (2 nauticalMiles asNauticalMiles withUnitSymbol:&#039;sm&#039;) printString &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; &#039;2 sm&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Applying the above message to a unit (instead of a value) gives a new unit.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, a bottle unit, which corresponds to 0.7 lters:&lt;br /&gt;
 bottleUnit := Physic::Volume liter withUnitSymbol:&#039;bottle&#039; scaleFactor:0.7.&lt;br /&gt;
&lt;br /&gt;
can create bottle-values:&lt;br /&gt;
 (bottleUnit unitAmount:10) &lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 10 bottle&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or convert from liters:&lt;br /&gt;
 10 liter as:bottleUnit&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 14.286 bottle&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Printing in Another Language =====&lt;br /&gt;
The same scheme can be used to print values with national translations of a unit.&lt;br /&gt;
For example, tons of coal equivalents (&#039;toe&#039;) is &amp;quot;Tonnen Steinkohle Äquivalent&amp;quot; or tSKE in German.&amp;lt;br&amp;gt;Reasonable definitions could be:&lt;br /&gt;
 toeGerman := Physic::Energy toe withUnitSymbol:&#039;tSKE&#039; scaleFactor:1.&lt;br /&gt;
 mtoeGerman := toeGerman megaUnit.&lt;br /&gt;
so the mtoeGerman unit will represent megatons of coal equivalents and print its values with a &#039;MtSKE&#039; unit (see scaling units below):&lt;br /&gt;
 mtoeGerman unitAmount:100&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 100 MtSKE&amp;lt;/small&amp;gt;&lt;br /&gt;
and&lt;br /&gt;
 (mtoeGerman unitAmount:100) asGigaJoules&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 4186800000 GJ&amp;lt;/small&amp;gt;&lt;br /&gt;
or:&lt;br /&gt;
 (mtoeGerman unitAmount:100) as:&#039;PJ&#039;&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 4186.8 PJ&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similar:&lt;br /&gt;
 meterChinese := Physic::Length withUnitSymbol:&#039;米 (Mǐ)&#039; scaleFactor:1.&lt;br /&gt;
 meterChinese unitAmount:15&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 15 米 (Mǐ)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Converting Units ==== &lt;br /&gt;
&lt;br /&gt;
In addition to predefined converting units, as listed below,&lt;br /&gt;
it is also possible to define custom units, with different (customizable) print behavior (more on that below).&lt;br /&gt;
&lt;br /&gt;
==== Predefined Converting Units ====&lt;br /&gt;
&lt;br /&gt;
Some such custom units are already predefined; for example, to represent imperial units, conversion units derived from mass are found (among others) as:&lt;br /&gt;
 Physic::PhysicalUnit mass ounces (or Physic::Mass ounces)&lt;br /&gt;
 Physic::PhysicalUnit mass pounds (or Physic::Mass pounds)&lt;br /&gt;
and length units as:&lt;br /&gt;
 Physic::PhysicalUnit length inches (or Physic::Length inches)&lt;br /&gt;
 Physic::PhysicalUnit length feet&lt;br /&gt;
 Physic::PhysicalUnit length yards&lt;br /&gt;
&lt;br /&gt;
Thus, you can create unit values which print themself (e.g.) in imperial units:&lt;br /&gt;
 yardsUnit := Physic::Length yards.&lt;br /&gt;
 distance := yardsUnit unitAmount:10&lt;br /&gt;
will give you 10 yards, which prints itself as such (&#039;10 yd&#039;).&lt;br /&gt;
&lt;br /&gt;
Whereas:&lt;br /&gt;
 distance2 := yardsUnit baseUnitAmount:10&lt;br /&gt;
will create a distance of 10 meters (the underlying base unit), which prints itself in yards.&lt;br /&gt;
&lt;br /&gt;
Be careful to not confuse &#039;&#039;unit amounts&#039;&#039; with &#039;&#039;base unit amounts&#039;&#039;,&lt;br /&gt;
and be reminded that the internal storage representation of all units is always in SI base units. The conversion is only performed when such values are printed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In general, you can ask most base units for common conversion units (which are the units used by the asXXX converters below). &lt;br /&gt;
These can also be used to instantiate instances or for conversion.&lt;br /&gt;
E.g. &lt;br /&gt;
 Physic::Mass ounces unitAmount:1 &lt;br /&gt;
returns 1 ounce (which prints itself as such),&lt;br /&gt;
and:&lt;br /&gt;
 1 kiloGram as:(Physic::Mass ounces)&lt;br /&gt;
returns 32.27 ounces (which also prints itself as such).&lt;br /&gt;
&lt;br /&gt;
==== Predefined Scaling Units ====&lt;br /&gt;
By default, the unit chooses itself, how values are scaled when printing.&lt;br /&gt;
For example, &amp;quot;(1/1000.0) kilo gram&amp;quot; will print itself as &amp;quot;1 g&amp;quot;, although the underlying baseUnit is kilogram.&lt;br /&gt;
&lt;br /&gt;
You can force a particular scale either by using one of the scale-converting units, eg:&lt;br /&gt;
 &#039;&#039;someUnit&#039;&#039; asMilliUnit baseUnitAmount:&#039;&#039;scalarValueInBaseUnits&#039;&#039;&lt;br /&gt;
or by giving it a unit amount:&lt;br /&gt;
 &#039;&#039;someUnit&#039;&#039; asMilliUnit unitAmount:&#039;&#039;scalarValueInUnits&#039;&#039;&lt;br /&gt;
or by converting a unit-value:&lt;br /&gt;
 &#039;&#039;someUnitValue&#039;&#039; asMilliUnitValue&lt;br /&gt;
Again, &#039;&#039;scalarValueInBaseUnits&#039;&#039; is in base-units (kg, N, Hz,...), whereas &#039;&#039;scalarValueInUnits&#039;&#039; is in scaled-units (mg, kN, Mhz,...).&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 0.01 kilo gram&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; prints as &amp;quot;10 g&amp;quot;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::Mass baseUnitAmount:0.01&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; prints as &amp;quot;10 g&amp;quot;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::Mass milliUnit baseUnitAmount:0.01 &amp;quot;/ specified in kg here&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; prints as &amp;quot;10000 mg&amp;quot;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::Mass milliUnit unitAmount:100      &amp;quot;/ specified in mg here&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; prints as &amp;quot;100 mg&amp;quot;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get a scaling unit from a given base unit (such as &amp;quot;Mass&amp;quot;, &amp;quot;Length&amp;quot;, &amp;quot;Volume&amp;quot;, etc.)&lt;br /&gt;
or from a given derived Unit (such as &amp;quot;Volume liters&amp;quot;), apply one of the following:&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; picoUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; nanoUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; microUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; milliUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; centiUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; deciUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; hectoUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; kiloUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; megaUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; gigaUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; teraUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; petaUnit&lt;br /&gt;
 &#039;&#039;aUnit&#039;&#039; exaUnit&lt;br /&gt;
&lt;br /&gt;
For example, if you have to work with hectoliters (units of 100 liters), which is common in europe&#039;s farming, make yourself a corresponding unit with:&lt;br /&gt;
 hlUnit := Physic::Volume liters hectoUnit.&lt;br /&gt;
 wine := hlUnit unitAmount:15.0.&lt;br /&gt;
 wine printString&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 15 hl&amp;quot;&amp;lt;/small&amp;gt;&lt;br /&gt;
 wine asCubicMeters printString&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 1.5 m³&amp;quot;&amp;lt;/small&amp;gt;&lt;br /&gt;
 wine asLiters printString&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 1500 l&amp;lt;/small&amp;gt;&lt;br /&gt;
 wine asGallonsUS printString&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 396.258078537223 US gal&amp;lt;/small&amp;gt;&lt;br /&gt;
 (wine asGallonsUS roundTo:0.01) printString&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 396.26 US gal&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To convert a given value (as opposed to a unit as above), use one of:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asPicoUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asNanoUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asMicroUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asMilliUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asCentiUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asDeciUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asHectoUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asKiloUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asMegaUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asGigaUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asTeraUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asPetaUnitValue&lt;br /&gt;
 &#039;&#039;aValue&#039;&#039; asExaUnitValue&lt;br /&gt;
&lt;br /&gt;
therefore, to force a physical value to print itself in its &#039;milli&#039; unit,&lt;br /&gt;
use asMilliUnitValue, as in:&lt;br /&gt;
 i := 1 ampere.&lt;br /&gt;
 m_i := i asMilliUnitValue.&lt;br /&gt;
&lt;br /&gt;
The asXXXUnitValue methods work on any physical value,&lt;br /&gt;
&lt;br /&gt;
However, you can also and should use the unit-specific converters, here:&lt;br /&gt;
 m_i := i asMilliAmperes&lt;br /&gt;
or with masses, as in the above example:&lt;br /&gt;
 0.01 kilo gram asMilliUnitValue&lt;br /&gt;
 0.01 kilo gram asMilliGrams&lt;br /&gt;
&lt;br /&gt;
The unit-specific methods will only work on their specific unit values (meaning that you get an error when trying to ask any non-mass value for its milligrams).&lt;br /&gt;
Thus, the later are preferable, as they provide an additional quality check&lt;br /&gt;
for your code. For a list of unit-specific converters, see below.&lt;br /&gt;
&lt;br /&gt;
==== Predefined Wellknown Units ====&lt;br /&gt;
&lt;br /&gt;
The base SI units Mass, Length, Force, etc. can be directly accessed from the Physic namespace as &amp;lt;code&amp;gt;Physic::&amp;lt;nameOfUnit&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Other derived and less frequently units can be accessed either via getters from the Physic::PhysicalUnit class, or by asking it via &amp;lt;code&amp;gt;Physic::PhysicalUnit unitNamed:&#039;nameOfUnit&#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;A list of known basic and derived SI units is retrieved with &amp;lt;code&amp;gt;Physic::PhysicalUnit knownUnits&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For details, see [https://en.wikipedia.org/wiki/United_States_customary_units US Units],&lt;br /&gt;
[https://en.wikipedia.org/wiki/Centimetre%E2%80%93gram%E2%80%93second_system_of_units CGS System], [https://en.wikipedia.org/wiki/Avoirdupois Avoirdupois] and [https://en.wikipedia.org/wiki/International_System_of_Units SI Units].&lt;br /&gt;
&lt;br /&gt;
====== Acceleration Unit ======&lt;br /&gt;
*Physic::Acceleration&lt;br /&gt;
::The base unit is &amp;quot;m/s²&amp;quot;.&lt;br /&gt;
*Physic::Acceleration &#039;&#039;&#039;gForce&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;GForce&amp;quot; converting unit (i.e. units o earth&#039;s gravitation).&lt;br /&gt;
&lt;br /&gt;
====== AmountOfSubstance Unit ======&lt;br /&gt;
*Physic::AmountOfSubstance&lt;br /&gt;
::The base unit is &amp;quot;mol&amp;quot;.&lt;br /&gt;
*Physic::AmountOfSubstance &#039;&#039;&#039;particles&#039;&#039;&#039;&lt;br /&gt;
::Returns the (number of) &amp;quot;Particles&amp;quot; converting unit.&lt;br /&gt;
&lt;br /&gt;
====== Angle Unit ======&lt;br /&gt;
*Physic::Angle&lt;br /&gt;
::The base SI unit. Prints as &amp;quot;rad&amp;quot;.&lt;br /&gt;
*Physic::Angle &#039;&#039;&#039;degrees&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;Degrees&amp;quot; converting unit. Prints its values in degrees.&lt;br /&gt;
*Physic::Angle &#039;&#039;&#039;degreeAndMinAndSec&#039;&#039;&#039;&lt;br /&gt;
::Returns a converting unit which prints its values in integer degrees plus minutes (1/60s degrees) plus seconds (1/3600s degrees).&lt;br /&gt;
*Physic::Angle &#039;&#039;&#039;gon&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;Gon&amp;quot; converting unit.&lt;br /&gt;
*Physic::Angle &#039;&#039;&#039;radians&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;Radians&amp;quot; converting unit.&lt;br /&gt;
*Physic::Angle &#039;&#039;&#039;arcMin&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;ArcMinutes&amp;quot; converting unit.&lt;br /&gt;
*Physic::Angle &#039;&#039;&#039;arcSec&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;ArcSeconds&amp;quot; converting unit.&lt;br /&gt;
*Physic::Angle &#039;&#039;&#039;arcMinAndSec&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;ArcMinutesAndSeconds&amp;quot; converting unit.&lt;br /&gt;
&lt;br /&gt;
====== Area Unit ======&lt;br /&gt;
*Physic::Area&lt;br /&gt;
::The base SI unit. Prints as square meters.&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;acre&#039;&#039;&#039;&lt;br /&gt;
::converting unit which prints as acres.&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;are&#039;&#039;&#039;&lt;br /&gt;
::Prints as ares.&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;awg&#039;&#039;&#039;&lt;br /&gt;
::converting unit which prints as American Wire Gauge.&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;hectare&#039;&#039;&#039;&lt;br /&gt;
::Prints as hectares (ha).&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;squareFoot&#039;&#039;&#039;&lt;br /&gt;
::Prints as square feet (sq ft).&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;squareMiles&#039;&#039;&#039;&lt;br /&gt;
::Prints as square miles (sq mi).&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;squareMillimeterMeters&#039;&#039;&#039;&lt;br /&gt;
::Prints as square millimeters (mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;).&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;squareCentiMeters&#039;&#039;&#039;&lt;br /&gt;
::Prints as square centimeters (cm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;).&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;squareMeters&#039;&#039;&#039;&lt;br /&gt;
::Prints as square meters (m&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;).&lt;br /&gt;
*Physic::Area &#039;&#039;&#039;squareKiloMeters&#039;&#039;&#039;&lt;br /&gt;
::Prints as square kilometers (km&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
====== Bits &amp;amp; Bytes Units ======&lt;br /&gt;
*Physic::Bytes&lt;br /&gt;
::The bytes unit. Not really an SI unit, but useful for printing file sizes.&lt;br /&gt;
*Physic::Bytes &#039;&#039;&#039;kiloBytes&#039;&#039;&#039;&lt;br /&gt;
::a converting unit; prints as &amp;quot;kB&amp;quot;.&lt;br /&gt;
*Physic::Bytes &#039;&#039;&#039;megaBytes&#039;&#039;&#039; / &#039;&#039;&#039;gigaBytes&#039;&#039;&#039; / &#039;&#039;&#039;teraBytes&#039;&#039;&#039; etc.&lt;br /&gt;
::converting units; print as &amp;quot;MB&amp;quot;, &amp;quot;GB&amp;quot;, &amp;quot;TB&amp;quot;, etc.&lt;br /&gt;
*Physic::Bytes &#039;&#039;&#039;kibiBytes&#039;&#039;&#039; / &#039;&#039;&#039;mebiBytes&#039;&#039;&#039; / &#039;&#039;&#039;gibiBytes&#039;&#039;&#039; / &#039;&#039;&#039;tebiBytes&#039;&#039;&#039; etc.&lt;br /&gt;
::converting units; print as &amp;quot;kiB&amp;quot;, &amp;quot;MiB&amp;quot;, &amp;quot;GiB&amp;quot;, &amp;quot;TiB&amp;quot;, etc.&lt;br /&gt;
*Physic::Bits&lt;br /&gt;
::The bits unit. Not really an SI unit, but useful for printing transmission speeds (bits/s).&lt;br /&gt;
*Physic::Bits &#039;&#039;&#039;kiloBits&#039;&#039;&#039;&lt;br /&gt;
::a converting unit; prints as &amp;quot;kbit&amp;quot;.&lt;br /&gt;
*Physic::Bits &#039;&#039;&#039;megaBits&#039;&#039;&#039; / &#039;&#039;&#039;gigaBits&#039;&#039;&#039; / &#039;&#039;&#039;teraBits&#039;&#039;&#039; etc.&lt;br /&gt;
::converting units; print as &amp;quot;Mbit&amp;quot;, &amp;quot;Gbit&amp;quot;, &amp;quot;Tbit&amp;quot;, etc.&lt;br /&gt;
*Physic::Bits &#039;&#039;&#039;kibiBits&#039;&#039;&#039; / &#039;&#039;&#039;mebiBits&#039;&#039;&#039; / &#039;&#039;&#039;gibiBits&#039;&#039;&#039; / &#039;&#039;&#039;tebiBits&#039;&#039;&#039; etc.&lt;br /&gt;
::converting units; print as &amp;quot;kibit&amp;quot;, &amp;quot;Mibit&amp;quot;, &amp;quot;Gibit&amp;quot;, &amp;quot;Tibit&amp;quot;, etc.&lt;br /&gt;
&lt;br /&gt;
====== Electric Charge Unit ======&lt;br /&gt;
*Physic::ElectricCharge&lt;br /&gt;
::The base SI unit. Prints as coulomb (&amp;quot;C&amp;quot;).&lt;br /&gt;
*Physic::ElectricCharge &#039;&#039;&#039;ampereSeconds&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;As&amp;quot;.&lt;br /&gt;
*Physic::ElectricCharge &#039;&#039;&#039;ampereHours&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;Ah&amp;quot;.&lt;br /&gt;
*Physic::ElectricCharge &#039;&#039;&#039;elementaryCharges&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as number of elementary charges &amp;quot;q&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
====== Electric Current Unit ======&lt;br /&gt;
*Physic::ElectricCurrent&lt;br /&gt;
::The base SI unit. Prints as ampere (&amp;quot;A&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
====== Electric Resistance Unit ======&lt;br /&gt;
*Physic::ElectricResistance&lt;br /&gt;
::The base SI unit. Prints as ohm.&lt;br /&gt;
&lt;br /&gt;
====== Energy Unit ======&lt;br /&gt;
*Physic::Energy&lt;br /&gt;
::The base SI unit. Prints as joules (&amp;quot;J&amp;quot;).&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;wattHours&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;Wh&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;kiloWattHours&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;kWh&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;megaWattHours&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;MWh&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;gigaWattHours&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;GWh&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;kiloJoules&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;kJ&amp;quot;; same as &amp;quot;Energy kiloUnit&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;megaJoules&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;MJ&amp;quot;; same as &amp;quot;Energy megaUnit&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;gigaJoules&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;GJ&amp;quot;; same as &amp;quot;Energy gigaUnit&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;btu&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;btu&amp;quot; (British Thermal Units), 1055 J  based on the ISO 31-4 definition&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;boe&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;boe&amp;quot; (Barrels of Oil Equivalent, 6117.9 MJ based on the US Internal Revenue Service)&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;toe&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;toe&amp;quot; (Tons of Oil Equivalent), 41.9 GJ&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;tce&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;tce&amp;quot; (Tons of Coal Equivalent), 29 GJ&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;calories&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;cal&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;kiloCalories&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;kcal&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;electronVolts&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;eV&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;kiloElectronVolts&#039;&#039;&#039;; same as &amp;quot;Energy electronVolts kiloUnit&amp;quot;.&lt;br /&gt;
::a converting unit which prints as &amp;quot;keV&amp;quot;&lt;br /&gt;
*Physic::Energy &#039;&#039;&#039;erg&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;erg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
====== Force Unit ======&lt;br /&gt;
*Physic::Force&lt;br /&gt;
::The base SI unit. Prints as Newton.&lt;br /&gt;
:converting units are returned by: &#039;&#039;&#039;dyne&#039;&#039;&#039;, &#039;&#039;&#039;gramForce&#039;&#039;&#039;, &#039;&#039;&#039;newtons&#039;&#039;&#039;, &#039;&#039;&#039;poundForce&#039;&#039;&#039;, &#039;&#039;&#039;tonForce&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====== Frequency Unit ======&lt;br /&gt;
*Physic::Frequency&lt;br /&gt;
::The base SI unit. Prints as Hertz.&lt;br /&gt;
:converting units are returned by: &#039;&#039;&#039;hertz&#039;&#039;&#039;, &#039;&#039;&#039;kiloHertz&#039;&#039;&#039;, &#039;&#039;&#039;megaHetz&#039;&#039;&#039;, &#039;&#039;&#039;gigaHertz&#039;&#039;&#039;, &#039;&#039;&#039;rpm&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====== Length Unit ======&lt;br /&gt;
*Physic::Length&lt;br /&gt;
::The base SI unit. Prints as Meter with a reasonable scale prefix.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;centiMeters&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;cm&amp;quot;.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;milliMeters&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;mm&amp;quot;.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;microMeters&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;µm&amp;quot;.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;nanoMeters&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;nm&amp;quot;.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;meters&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which always prints as &amp;quot;m&amp;quot;.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;kiloMeters&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;km&amp;quot;.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;inches&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;in&amp;quot;.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;feet&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;ft&amp;quot;.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;feetAndInches&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints feet and inches.&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;feetAndInchesRounded&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints feet and rounded inches; a typical format used in the US for a human&#039;s height&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;metersAndCentimeters&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints meter and rounded centimeters; a useful format a human&#039;s metric height&lt;br /&gt;
*Physic::Length &#039;&#039;&#039;yards&#039;&#039;&#039;&lt;br /&gt;
::a converting unit which prints as &amp;quot;yd&amp;quot;.&lt;br /&gt;
:additional converting units are returned by: &#039;&#039;&#039;angstrom&#039;&#039;&#039;, &#039;&#039;&#039;astronomicalUnits&#039;&#039;&#039;, &#039;&#039;&#039;parsec&#039;&#039;&#039;, &#039;&#039;&#039;awgDiameter&#039;&#039;&#039;, &#039;&#039;&#039;landMiles&#039;&#039;&#039;, &#039;&#039;&#039;lightSeconds&#039;&#039;&#039;, &#039;&#039;&#039;lightYears&#039;&#039;&#039;, &#039;&#039;&#039;meters&#039;&#039;&#039;, &#039;&#039;&#039;nauticalMiles&#039;&#039;&#039;, &#039;&#039;&#039;thous&#039;&#039;&#039;, &#039;&#039;&#039;mils&#039;&#039;&#039;, &#039;&#039;&#039;points&#039;&#039;&#039;, &#039;&#039;&#039;twips&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====== Mass Unit ======&lt;br /&gt;
*Physic::Mass&lt;br /&gt;
::The base unit (&amp;quot;kg&amp;quot;).&lt;br /&gt;
*Physic::Mass &#039;&#039;&#039;ounces&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;Ounces&amp;quot; unit; a converting unit which prints as &amp;quot;oz&amp;quot;.&lt;br /&gt;
*Physic::Mass &#039;&#039;&#039;pounds&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;Pounds&amp;quot; converting unit which prints as &amp;quot;lb&amp;quot;.&lt;br /&gt;
*Physic::Mass &#039;&#039;&#039;troyOunces&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;TroyOunces&amp;quot; converting unit.&lt;br /&gt;
*Physic::Mass &#039;&#039;&#039;carat&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;Carat&amp;quot; converting unit.&lt;br /&gt;
*Physic::Mass &#039;&#039;&#039;atomicMassUnits&#039;&#039;&#039;&lt;br /&gt;
::Returns the &amp;quot;AtomicMassUnits&amp;quot; converting unit.&lt;br /&gt;
:more mass converting units are returned by: &#039;&#039;&#039;daltons&#039;&#039;&#039;, &#039;&#039;&#039;grams&#039;&#039;&#039;, &#039;&#039;&#039;kiloGrams&#039;&#039;&#039;, &#039;&#039;&#039;kiloTonnes&#039;&#039;&#039;, &#039;&#039;&#039;megaTonnes&#039;&#039;&#039;, &#039;&#039;&#039;milliGrams&#039;&#039;&#039;, &#039;&#039;&#039;microGrams&#039;&#039;&#039;, &#039;&#039;&#039;nanoGrams&#039;&#039;&#039;, &#039;&#039;&#039;tonnes&#039;&#039;&#039;, &#039;&#039;&#039;troyPounds&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You may wonder what the kiloGrams converting unit is useful for, as the base unit&#039;s amount is already in kilograms. The difference is that the base unit will print values with a prefix (milli, micro, kilo etc.) whereas the kiloGram converting unit will always print kilograms.&lt;br /&gt;
&lt;br /&gt;
====== Power Unit ======&lt;br /&gt;
*Physic::Power&lt;br /&gt;
::The base SI unit. Prints as Watt.&lt;br /&gt;
:converting units are returned by: &#039;&#039;&#039;dBW&#039;&#039;&#039;, &#039;&#039;&#039;dBm&#039;&#039;&#039;, &#039;&#039;&#039;gigaWatt&#039;&#039;&#039;, &#039;&#039;&#039;kiloWatt&#039;&#039;&#039;, &#039;&#039;&#039;megaWatt&#039;&#039;&#039;, &#039;&#039;&#039;milliWatt&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====== Pressure Unit ======&lt;br /&gt;
*Physic::Pressure&lt;br /&gt;
::The base SI unit. Prints as Pascal.&lt;br /&gt;
:converting units are returned by: &#039;&#039;&#039;atmospheres&#039;&#039;&#039;, &#039;&#039;&#039;technicalAtmospheres&#039;&#039;&#039;, &#039;&#039;&#039;bar&#039;&#039;&#039;, &#039;&#039;&#039;hectoPascal&#039;&#039;&#039;, &#039;&#039;&#039;mH2O&#039;&#039;&#039; (meter of water), &#039;&#039;&#039;mmHg&#039;&#039;&#039; (mm of mercury), &#039;&#039;&#039;pascal&#039;&#039;&#039;, &#039;&#039;&#039;psi&#039;&#039;&#039; and &#039;&#039;&#039;torr&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====== Temperature Unit ======&lt;br /&gt;
*Physic::Temperature&lt;br /&gt;
::The base SI unit. Prints as Kelvin.&lt;br /&gt;
:converting units are returned by: &#039;&#039;&#039;celsius&#039;&#039;&#039;, &#039;&#039;&#039;fahrenheit&#039;&#039;&#039;, &#039;&#039;&#039;rankine&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====== Time Unit ======&lt;br /&gt;
:Time durations are either represented by the already existing standard Smalltalk class &amp;quot;TimeDuration&amp;quot; or by the Time unit in the Physic namespace. Mixed arithmetic operations involving TimeDurations and PhysicalValues are transparently returning correct unit values. However, TimeDuration has a limitation in that it can only represent times down to the picosecond range, which might be not enough for high energy physic computations. Please use Physic::Time in this case.&lt;br /&gt;
*Physic::Time&lt;br /&gt;
::The base SI unit. Prints as Seconds.&lt;br /&gt;
:converting units are returned by: &#039;&#039;&#039;days&#039;&#039;&#039;, &#039;&#039;&#039;microSeconds&#039;&#039;&#039;, &#039;&#039;&#039;milliSeconds&#039;&#039;&#039;, &#039;&#039;&#039;seconds&#039;&#039;&#039;, &#039;&#039;&#039;weeks&#039;&#039;&#039;, &#039;&#039;&#039;years&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====== Velocity Unit ======&lt;br /&gt;
*Physic::Velocity&lt;br /&gt;
::The base SI unit. Prints as Meter per Second.&lt;br /&gt;
:converting units are returned by: &#039;&#039;&#039;beaufort&#039;&#039;&#039;, &#039;&#039;&#039;centiMetersPerSecond&#039;&#039;&#039;, &#039;&#039;&#039;kiloMetersPerHour&#039;&#039;&#039;, &#039;&#039;&#039;kiloMetersPerSecond&#039;&#039;&#039;, &#039;&#039;&#039;knots&#039;&#039;&#039;, &#039;&#039;&#039;metersPerHour&#039;&#039;&#039;, &#039;&#039;&#039;milesPerHour&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====== Voltage Unit ======&lt;br /&gt;
*Physic::Voltage&lt;br /&gt;
::The base SI unit. Prints as Volts.&lt;br /&gt;
:converting units are returned by: &#039;&#039;&#039;milliVolts&#039;&#039;&#039;, &#039;&#039;&#039;microVolts&#039;&#039;&#039;, &#039;&#039;&#039;nanoVolts&#039;&#039;&#039;, &#039;&#039;&#039;kiloVolts&#039;&#039;&#039;, &#039;&#039;&#039;dBV&#039;&#039;&#039;, &#039;&#039;&#039;dBu&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====== Volume Unit ======&lt;br /&gt;
*Physic::Volume&lt;br /&gt;
::The base SI unit. Prints as Cubic Meter.&lt;br /&gt;
:converting units are returned by: &#039;&#039;&#039;centiLiters&#039;&#039;&#039;, &#039;&#039;&#039;cubicInches&#039;&#039;&#039;, &#039;&#039;&#039;cubicMeters&#039;&#039;&#039;, &#039;&#039;&#039;deciLiters&#039;&#039;&#039;, &#039;&#039;&#039;fluidOuncesGB&#039;&#039;&#039;, &#039;&#039;&#039;fluidOuncesUS&#039;&#039;&#039;, &#039;&#039;&#039;gallonsGB&#039;&#039;&#039;, &#039;&#039;&#039;gallonsUS&#039;&#039;&#039;, &#039;&#039;&#039;hectoLiters&#039;&#039;&#039;, &#039;&#039;&#039;liters&#039;&#039;&#039;, &#039;&#039;&#039;milliLiters&#039;&#039;&#039;, &#039;&#039;&#039;barrels&#039;&#039;&#039;, &#039;&#039;&#039;barrelsIMP&#039;&#039;&#039;, &#039;&#039;&#039;barrelsUS&#039;&#039;&#039; (barrels are oil aka &amp;quot;blue barrels&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Per Unit Detailed API ==&lt;br /&gt;
&lt;br /&gt;
Notice the receiver of expressions in the following per-unit documentation.&lt;br /&gt;
&amp;lt;br&amp;gt;If you read &amp;quot;&#039;&#039;number&#039;&#039; &#039;&#039;&#039;something&#039;&#039;&#039;&amp;quot;, it means that you can send any [[Number_API_Functions|number]] instance the &amp;quot;something&amp;quot; message.&lt;br /&gt;
&amp;lt;br&amp;gt;And you will get an instance of the corresponding unit value as result.&lt;br /&gt;
For example:&lt;br /&gt;
 2 gram&lt;br /&gt;
or&lt;br /&gt;
 3.0 gram&lt;br /&gt;
or&lt;br /&gt;
 (1/2) kiloGram&lt;br /&gt;
will all return corresponding mass value.&lt;br /&gt;
&lt;br /&gt;
If you read &amp;quot;&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;something&#039;&#039;&#039;&amp;quot;, it means that you can send the &amp;quot;something&amp;quot; message to a unit value instance (eg. a mass)&lt;br /&gt;
and get some other representation of it as result.&lt;br /&gt;
&lt;br /&gt;
Finally, if you read &amp;quot;&#039;&#039;aUnit&#039;&#039; &#039;&#039;&#039;something&#039;&#039;&#039;&amp;quot;, it means that you can send the &amp;quot;something&amp;quot; message to a physical unit  (not a physical value).&lt;br /&gt;
&lt;br /&gt;
=== Mass ===&lt;br /&gt;
&lt;br /&gt;
Mass is measured in units of Kilogram, and the default printing is in &amp;quot;kg&amp;quot;, &amp;quot;g&amp;quot;, &amp;quot;mg&amp;quot;, &amp;quot;ng&amp;quot; or whatever the print function considers appropriate. &lt;br /&gt;
&amp;lt;br&amp;gt;The following operations return an instance of a mass (i.e. a value with a unit of &amp;quot;Mass&amp;quot;) all of which will print themself as base units:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloGram&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;gram&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of n kilograms.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n kilo gram&amp;lt;/CODE&amp;gt; (using SI prefix message).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;gram&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of n grams.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milliGram&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;gram&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of n milligrams.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n milli gram&amp;lt;/CODE&amp;gt;. (using SI prefix message)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;microGram&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;gram&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of n micrograms.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n micro gram&amp;lt;/CODE&amp;gt; (using SI prefix message).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;nano&#039;&#039;&#039; &#039;&#039;&#039;gram&#039;&#039;&#039;&lt;br /&gt;
::All SI prefixes as listed above.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;pounds&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of n pounds. A pound is defined as 453.59237 gram.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;ounces&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of n ounces. An ounce is defined as 28.35 g.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;troyOunces&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;troy ounces&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of n troy ounces. These are used with metals (esp. gold) (31.1034768 g)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial&#039;&#039;&#039; &#039;&#039;&#039;ton&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of 1016.05 kg (2240 lb)&lt;br /&gt;
::Also possible: &#039;&#039;&#039;imperial&#039;&#039;&#039; &#039;&#039;&#039;barrel&#039;&#039;&#039;, &#039;&#039;&#039;bushel&#039;&#039;&#039;, &#039;&#039;&#039;cup&#039;&#039;&#039;, &#039;&#039;&#039;floz&#039;&#039;&#039;, &#039;&#039;&#039;fluidOunce&#039;&#039;&#039;, &#039;&#039;&#039;gallon&#039;&#039;&#039;, &#039;&#039;&#039;hp&#039;&#039;&#039;, &#039;&#039;&#039;nauticalMile&#039;&#039;&#039;, &#039;&#039;&#039;pint&#039;&#039;&#039;, &#039;&#039;&#039;quart&#039;&#039;&#039;, &#039;&#039;&#039;tablespoon&#039;&#039;&#039;, &#039;&#039;&#039;teaspoon&#039;&#039;&#039;, &#039;&#039;&#039;ton&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american&#039;&#039;&#039; &#039;&#039;&#039;ton&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of 907.2 kg (2000 lb)&lt;br /&gt;
::Also possible: &#039;&#039;&#039;american&#039;&#039;&#039; &#039;&#039;&#039;barrel&#039;&#039;&#039;, &#039;&#039;&#039;bushel&#039;&#039;&#039;, &#039;&#039;&#039;cup&#039;&#039;&#039;, &#039;&#039;&#039;fldr&#039;&#039;&#039;, &#039;&#039;&#039;fluidDram&#039;&#039;&#039;, &#039;&#039;&#039;floz&#039;&#039;&#039;, &#039;&#039;&#039;fluidOunce&#039;&#039;&#039;, &#039;&#039;&#039;gallon&#039;&#039;&#039;, &#039;&#039;&#039;hp&#039;&#039;&#039;, &#039;&#039;&#039;nauticalMile&#039;&#039;&#039;, &#039;&#039;&#039;pint&#039;&#039;&#039;, &#039;&#039;&#039;quart&#039;&#039;&#039;, &#039;&#039;&#039;tablespoon&#039;&#039;&#039;, &#039;&#039;&#039;teaspoon&#039;&#039;&#039;, &#039;&#039;&#039;ton&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;metric&#039;&#039;&#039; &#039;&#039;&#039;ton&#039;&#039;&#039;&lt;br /&gt;
::Generates a mass-value of 1000 kg (2204 lb)&lt;br /&gt;
::Also possible: &#039;&#039;&#039;metric&#039;&#039;&#039; &#039;&#039;&#039;hp&#039;&#039;&#039;, &#039;&#039;&#039;pint&#039;&#039;&#039;, &#039;&#039;&#039;ton&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Conversion&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asGrams&#039;&#039;&#039;&lt;br /&gt;
::Returns the original mass in a converted unit which enforces explicit printing in grams (i.e. without any SI scaling prefix).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asNanoGrams&#039;&#039;&#039;&lt;br /&gt;
::Same, but enforces explicit printing in nanograms (&amp;quot;ng&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asMicroGrams&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in micrograms (&amp;quot;µg&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asMilliGrams&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in milligrams (&amp;quot;mg&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asKiloGrams&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in kilograms (&amp;quot;kg&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asTonnes&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in (metric) tonnes (&amp;quot;t&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asKiloTonnes&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in (metric) kilotonnes (&amp;quot;kt&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asMegaTonnes&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in (metric) megatonnes (&amp;quot;Mt&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asGigaTonnes&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in (metric) gigatonnes (&amp;quot;Gt&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asPounds&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in pounds (&amp;quot;lb&amp;quot;) One pound is 453.59237 g.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asCarat&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in carat (&amp;quot;ct&amp;quot;). 1 carat is 200mg.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asOunces&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in ounces (&amp;quot;oz&amp;quot;). These are british (imperial) ounces (28.35 g)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asTroyOunces&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in troy ounces (&amp;quot;oz t&amp;quot;). These are used with metals (31.103 g)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asDaltons&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in dalton (&amp;quot;Da&amp;quot;). 1 dalton is 1/12 of the C12 atom&#039;s mass (1.66053906892e-27 kiloGram).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aMass&#039;&#039; &#039;&#039;&#039;asAtomicMassUnits&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in atomic mass units (&amp;quot;amu&amp;quot;). One amu is 1.660539066605e-27Kg.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;In a Formula&#039;&#039;&#039; (&#039;...&#039; asPhysicExpression value)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 kg&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::mass in Kilogram. Also recognized: &#039;mg&#039;, &#039;µg&#039;, &#039;ng&#039;, &#039;t&#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 lb&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::mass in pounds. Also recognized: &#039;oz&#039;, &#039;oz tr&#039;, &#039;us ton&#039;, &#039;imp ton&#039;&lt;br /&gt;
&lt;br /&gt;
=== Length ===&lt;br /&gt;
Length is measured in Meters, and the default printing is in &amp;quot;m&amp;quot;, &amp;quot;km&amp;quot;, &amp;quot;mm&amp;quot;, &amp;quot;nm&amp;quot; or whatever the print function considers appropriate.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n meters.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;centiMeter&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;centi&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n centimeters.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n centi meter&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milliMeter&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n millimeters.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n milli meter&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;microMeter&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n micrometers.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n micro meter&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;nanoMeter&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;nano&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n nanometers.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n nano meter&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloMeter&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n kilometers.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n kilo meter&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;inch&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n inches. An inch is 25.4 mm.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;inches&#039;&#039;&#039;&lt;br /&gt;
::Same as inch above (for readability)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;feet&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n feet. A foot is 12 inches or 0.3048 m.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;yards&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n yards. A yard is 36 inches or 0.9144 m.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;landMiles&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n land miles. A land mile is 5280 feet or 1609.344 m.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;nauticalMiles&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n nautical miles. A nautical mile is 1852 m (i.e. a US nautical mile, not to be confused with the obsolete british nautical mile, which is slightly longer).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;chineseMiles&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n chinese miles. A Chinese mile is 500 m.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;astronomicalUnits&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n [https://en.wikipedia.org/wiki/Astronomical_unit astronomical units]. An au is 149597870.7 km.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;lightSeconds&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n lightseconds. A ls is 299792.458 km.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;lightYears&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n [https://en.wikipedia.org/wiki/Light-year lightyears]. A ly is 9460730472580.8 km (exact by definition).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;parsec&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n [https://en.wikipedia.org/wiki/Parsec parsec]. A parsec is 3.26156377716705 ly.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;angstrom&#039;&#039;&#039;&lt;br /&gt;
::Generates a length-value of n angstroms. 1 Å = 0.1 nm = 10e−10 m.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Conversion&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asMeters&#039;&#039;&#039;&lt;br /&gt;
::Returns the original length but enforces explicit printing in meters (i.e. prevents scaling prefix when printed).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asMilliMeters&#039;&#039;&#039; / &#039;&#039;&#039;asMicroMeters&#039;&#039;&#039; / &#039;&#039;&#039;asNanoMeters&#039;&#039;&#039; / &#039;&#039;&#039;asCentiMeters&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in millimeters (&amp;quot;mm&amp;quot;), micrometers (&amp;quot;µm&amp;quot;), nanometers (&amp;quot;nm&amp;quot;) or centimeters (&amp;quot;cm&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asKiloMeters&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in kilometers (&amp;quot;km&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asAngstrom&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in angstrom (&amp;quot;Å&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asInches&#039;&#039;&#039; / &#039;&#039;&#039;asFeet&#039;&#039;&#039; / &#039;&#039;&#039;asYards&#039;&#039;&#039; / &#039;&#039;&#039;asThous&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in inches (&amp;quot;in&amp;quot;), feet (&amp;quot;ft&amp;quot;), yards (&amp;quot;yd&amp;quot;) or thous (&amp;quot;thou&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asFeetAndInches&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in feet and inches (inches rounded to 1 fractional digit).&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;&amp;quot;1.80 meter asFeetAndInches&amp;quot;&amp;lt;/code&amp;gt; will print itself as &amp;quot; 5′10.9″ &amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asFeetAndInchesRounded&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in feet and rounded inches.&amp;lt;br&amp;gt; &amp;lt;code&amp;gt;&amp;quot;1.80 meter asFeetAndInchesRounded&amp;quot;&amp;lt;/code&amp;gt; will print itself as &amp;quot; 5′11″ &amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asAWGDiameter&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in american wire gauge units (&amp;quot;AWG&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asLandMiles&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in land miles (&amp;quot;mi&amp;quot;). One land mile is 1.609344 km.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asNauticalMiles&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in nautical miles (&amp;quot;NM&amp;quot;). One nautical mile is 1.852 km.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asLightYears&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in lightyears (&amp;quot;ly&amp;quot;). A light year is 9460730472580.8 km.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asLightSeconds&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in lightseconds (&amp;quot;ls&amp;quot;). A light second is 299792.458 km.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;asAstronomicalUnits&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in astronomicalUnits (&amp;quot;au&amp;quot;). An astronomical unit is 149597870.7 km.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aLength&#039;&#039; &#039;&#039;&#039;as:&#039;&#039;&#039;(Physic::PhysicalUnit unitNamed:&#039;Mil&#039;)&lt;br /&gt;
::Enforces explicit printing in mil. A mil is 1/1000 of an inch. Usage of mils is not recommended, as it may be confused with millimeter. You can use the synonym &amp;quot;Thou&amp;quot; instead, which avoids this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;In a Formula&#039;&#039;&#039; (&#039;...&#039; asPhysicExpression value)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 m&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::length in Meter. Also recognized: &#039;km&#039;, &#039;cm&#039;, &#039;mm&#039;, &#039;µm&#039;, &#039;nm&#039;, pm&#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 mi&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::length in Miles. Also recognized: &#039;in&#039;, &#039;ft&#039;, &#039;yd&#039;, &#039;mil&#039;, &#039;twip&#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;10 Å&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::length in Angstrom.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;1 au&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::length in Astronomical Units. Also: &#039;ly&#039;, &#039;ls&#039;, &#039;pc&#039;&lt;br /&gt;
&lt;br /&gt;
=== Angle ===&lt;br /&gt;
Angles are measured in Radians, and the default printing is in &amp;quot;rad&amp;quot;. &lt;br /&gt;
&amp;lt;br&amp;gt;The following operations return an instance of angle:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;radians&#039;&#039;&#039; &lt;br /&gt;
::Generates an angle of n radians.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;degrees&#039;&#039;&#039; &lt;br /&gt;
::Generates an angle of n degrees (which prints itself as radians)&lt;br /&gt;
&lt;br /&gt;
::Notice that Number can also compute the raw value (as scalar number) with &amp;quot;&amp;lt;code&amp;gt;degreesToRadians&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;radiansToDegrees&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;anAngle&#039;&#039; &#039;&#039;&#039;asDegrees&#039;&#039;&#039;&lt;br /&gt;
::Returns the same angle but enforces explicit printing in Degrees.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anAngle&#039;&#039; &#039;&#039;&#039;asRadians&#039;&#039;&#039;&lt;br /&gt;
::Returns the same angle but enforces explicit printing in Radians (i.e. to convert back from above degrees value).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anAngle&#039;&#039; &#039;&#039;&#039;asArcSec&#039;&#039;&#039;&lt;br /&gt;
::Returns the same angle but enforces explicit printing in arc seconds.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anAngle&#039;&#039; &#039;&#039;&#039;asArcMin&#039;&#039;&#039;&lt;br /&gt;
::Returns the same angle but enforces explicit printing in arc minutes.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anAngle&#039;&#039; &#039;&#039;&#039;asDegreeAndMinAndSec&#039;&#039;&#039;&lt;br /&gt;
::Returns the same angle but enforces explicit printing as d°m′s″&amp;lt;br&amp;gt;(e.g. &amp;quot;&amp;lt;code&amp;gt;90.1234 degrees asDegreeAndMinAndSec&amp;lt;/code&amp;gt;&amp;quot; =&amp;gt; 90°7′24″).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anAngle&#039;&#039; &#039;&#039;&#039;asGon&#039;&#039;&#039;&lt;br /&gt;
::Returns the same angle but enforces explicit printing in Gon (90 degrees = 100 gon).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Trigonometric&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;anAngle&#039;&#039; &#039;&#039;&#039;sin&#039;&#039;&#039;&lt;br /&gt;
::Angles understand the typical trigonometric messages &#039;&#039;&#039;sin&#039;&#039;&#039;, &#039;&#039;&#039;cos&#039;&#039;&#039;, &#039;&#039;&#039;tan&#039;&#039;&#039;, &#039;&#039;&#039;cot&#039;&#039;&#039; (cotangent) and &#039;&#039;&#039;csc&#039;&#039;&#039; (cosecant).&lt;br /&gt;
::(Eg. you can write &amp;quot;&amp;lt;code&amp;gt;45 degrees sin&amp;lt;/code&amp;gt;&amp;quot; to get 0.707106781186547)&lt;br /&gt;
&lt;br /&gt;
=== Temperature ===&lt;br /&gt;
Temperature is measured in Kelvin, and the default printing is in &amp;quot;K&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kelvin&#039;&#039;&#039;&lt;br /&gt;
::Generates an temperature-value of n Kelvin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;degreesCelcius&#039;&#039;&#039;&lt;br /&gt;
::Generates an temperature-value of n degrees Celsius.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;degreesFahrenheit&#039;&#039;&#039;&lt;br /&gt;
::Generates an temperature-value of n degrees Fahrenheit.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;rankine&#039;&#039;&#039;&lt;br /&gt;
::Generates an temperature-value of n degrees Rankine.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aTemperature&#039;&#039; &#039;&#039;&#039;asFahrenheit&#039;&#039;&#039;&lt;br /&gt;
::Returns the original temperature but enforces explicit printing in Fahrenheit.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTemperature&#039;&#039; &#039;&#039;&#039;asCelsius&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in degrees Celsius.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTemperature&#039;&#039; &#039;&#039;&#039;asRankine&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in Rankine.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTemperature&#039;&#039; &#039;&#039;&#039;blackBodyWaveLength&#039;&#039;&#039;&lt;br /&gt;
::The wavelength corresponding to the temperature (returns a length).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;In a Formula&#039;&#039;&#039; (&#039;...&#039; asPhysicExpression value)&lt;br /&gt;
*&amp;lt;code&amp;gt;900 K&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::temperature in Kelvin.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;900 °F&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::temperature in Fahrenheit.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;900 °C&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::temperature in Celsius.&lt;br /&gt;
&lt;br /&gt;
=== Frequency ===&lt;br /&gt;
Frequency is measured in Hertz, and the default printing is in &amp;quot;Hz&amp;quot;, &amp;quot;kHz&amp;quot;, &amp;quot;MHz&amp;quot; or whatever the print function chooses. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;hertz&#039;&#039;&#039;&lt;br /&gt;
::Generates a frequency-value of n hertz.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloHertz&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;hertz&#039;&#039;&#039;&lt;br /&gt;
::Generates a frequency-value of n kilohertz.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n kilo hertz&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;megaHertz&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;mega&#039;&#039;&#039; &#039;&#039;&#039;hertz&#039;&#039;&#039;&lt;br /&gt;
::Generates a frequency-value of n megahertz.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n mega hertz&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;gigaHertz&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;giga&#039;&#039;&#039; &#039;&#039;&#039;hertz&#039;&#039;&#039;&lt;br /&gt;
::Generates a frequency-value of n gigahertz.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n giga hertz&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Physic::Frequency &#039;&#039;&#039;noteName:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039;&lt;br /&gt;
::Converts the name of a note (in international note notation) to a frequency.&amp;lt;br&amp;gt;For example, &amp;lt;code&amp;gt;Physic::Frequency noteName: &#039;A4&#039;&amp;lt;/code&amp;gt; generates 440Hz.&amp;lt;br&amp;gt;Valid note names are e.g. &#039;Bb4&#039;,&#039;C#5&#039; or &#039;Db5&#039;. I.e. the name within &#039;A&#039; through &#039;G&#039; followed by an optional &#039;b&#039; (flat) or &#039;#&#039; sharp, followed by an optional octave number.&lt;br /&gt;
&lt;br /&gt;
*Physic::Frequency &#039;&#039;&#039;midiNr:&#039;&#039;&#039; &#039;&#039;anInteger&#039;&#039;&lt;br /&gt;
::Converts a Midi note number (0..127) to a frequency.&amp;lt;br&amp;gt;For example, &amp;lt;code&amp;gt;Physic::Frequency midiNr: 69&amp;lt;/code&amp;gt; generates 440Hz.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aFrequency&#039;&#039; &#039;&#039;&#039;asKiloHertz&#039;&#039;&#039;&lt;br /&gt;
::Returns the original frequency but enforces explicit printing in kilohertz (&amp;quot;kHz&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aFrequency&#039;&#039; &#039;&#039;&#039;asMegaHertz&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in megahertz (&amp;quot;MHz&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aFrequency&#039;&#039; &#039;&#039;&#039;asGigaHertz&#039;&#039;&#039;&lt;br /&gt;
::Enforces explicit printing in gigahertz (&amp;quot;GHz&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aFrequency&#039;&#039; &#039;&#039;&#039;noteName&#039;&#039;&#039;&lt;br /&gt;
::The name of the nearest note (equal tempered).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aFrequency&#039;&#039; &#039;&#039;&#039;midiNr&#039;&#039;&#039;&lt;br /&gt;
::The nearest Midi note number.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aFrequency&#039;&#039; &#039;&#039;&#039;addSemitones:&#039;&#039;&#039; &#039;&#039;nrOfSemitones&#039;&#039;&lt;br /&gt;
::Returns the frequency &#039;&#039;nrOfSemitones&#039;&#039; higher (or lower, if negative).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aFrequency&#039;&#039; &#039;&#039;&#039;addOctaves:&#039;&#039;&#039; &#039;&#039;nrOfOctaves&#039;&#039;&lt;br /&gt;
::Returns the frequency &#039;&#039;nrOfOctaves&#039;&#039; higher (or lower, if negative).&lt;br /&gt;
&lt;br /&gt;
=== Energy ===&lt;br /&gt;
Energy is measured in Joule, and the default printing is in &amp;quot;J&amp;quot;, &amp;quot;kJ&amp;quot; or whatever the print function chooses as reasonable scale.&lt;br /&gt;
&amp;lt;br&amp;gt;Many domains have their own preferred unit to use (atom physics use electron volts, energy industry uses wattHours and the oil industry uses btu).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;joule&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n joule.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloJoule&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;joule&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n kilojoule.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n kilo joule&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;megaJoule&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;mega&#039;&#039;&#039; &#039;&#039;&#039;joule&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n megajoule.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n mega joule&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;wattHours&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n wattHours.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n watt * 1 hours&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloWattHours&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;wattHours&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n kiloWattHours.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n kilo wattHours&amp;lt;/CODE&amp;gt; and also the same as &amp;lt;CODE&amp;gt;n kilo watt * 1 hours&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;megaWattHours&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;mega&#039;&#039;&#039; &#039;&#039;&#039;wattHours&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n megaWattHours.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n mega wattHours&amp;lt;/CODE&amp;gt; and also the same as &amp;lt;CODE&amp;gt;n mega watt * 1 hours&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;electronVolts&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n electronVolts.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;calories&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n calories.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloCalories&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;calories&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n kcal.&amp;lt;br&amp;gt;Same as &amp;lt;CODE&amp;gt;n kilo calories&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;btu&#039;&#039;&#039;&lt;br /&gt;
::Generates an energy-value of n BTUs (British Thermal Units). 1 btu is 1055.06 J. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;anEnergy&#039;&#039; &#039;&#039;&#039;asElectronVolts&#039;&#039;&#039;&lt;br /&gt;
::Present (i.e. prints) as electronVolts (&amp;quot;eV&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnergy&#039;&#039; &#039;&#039;&#039;asKiloWattHours&#039;&#039;&#039;&lt;br /&gt;
::Present as kiloWattHours (&amp;quot;kWh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnergy&#039;&#039; &#039;&#039;&#039;asMegaWattHours&#039;&#039;&#039;&lt;br /&gt;
::Present as megaWattHours (&amp;quot;mWh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnergy&#039;&#039; &#039;&#039;&#039;asGigaWattHours&#039;&#039;&#039;&lt;br /&gt;
::Present as gigaWattHours (&amp;quot;gWh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnergy&#039;&#039; &#039;&#039;&#039;asCalories&#039;&#039;&#039;&lt;br /&gt;
::Present as calories (&amp;quot;cal&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnergy&#039;&#039; &#039;&#039;&#039;asKiloCalories&#039;&#039;&#039;&lt;br /&gt;
::Present as kilo calories (&amp;quot;kcal&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnergy&#039;&#039; &#039;&#039;&#039;asBTUs&#039;&#039;&#039;&lt;br /&gt;
::Present as BTUs (British Thermal Units)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnergy&#039;&#039; &#039;&#039;&#039;asTCEs&#039;&#039;&#039;&lt;br /&gt;
::Present as TCEs (Ton of Coal Equivalents)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;In a Formula&#039;&#039;&#039; (&#039;...&#039; asPhysicExpression value)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 J&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::power in joule. Also recognized: &#039;kJ&#039;, &#039;MJ&#039;, &#039;GJ&#039;, &#039;Nm&#039;, &#039;eV&#039;, &#039;keV&#039;, &#039;MeV&#039;, &#039;cal&#039;, &#039;kcal&#039;, &#039;btu&#039;, &#039;Wh&#039;, &#039;kWh&#039;, &#039;MWh&#039;, &#039;GWh&#039;, &#039;TWh&#039;&lt;br /&gt;
&lt;br /&gt;
=== Power ===&lt;br /&gt;
Power is a derived unit measured in Watt, and the default printing is in &amp;quot;W&amp;quot;, &amp;quot;kW&amp;quot; or whatever the print function chooses as reasonable scale. Instances of &amp;quot;Power&amp;quot; are returned e.g. when multiplying an electric current by a voltage. Notice that there is a difference between VA and W in alternating current circuits. Here, Watt refers to the [https://en.wikipedia.org/wiki/AC_power#Active,_reactive,_apparent,_and_complex_power_in_sinusoidal_steady-state active power] or power in direct current circuits (or instantaneous power values) .&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;watt&#039;&#039;&#039;&lt;br /&gt;
::Generates a power-value of n watt.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milliWatt&#039;&#039;&#039;&lt;br /&gt;
::Generates a power-value of n milliWatt.&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;CODE&amp;gt;n milli watt&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloWatt&#039;&#039;&#039;&lt;br /&gt;
::Generates a power-value of n kiloWatt.&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;CODE&amp;gt;n kilo watt&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;megaWatt&#039;&#039;&#039;&lt;br /&gt;
::Generates a power-value of n megaWatt.&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;CODE&amp;gt;n mega watt&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;gigaWatt&#039;&#039;&#039;&lt;br /&gt;
::Generates a power-value of n gigaWatt.&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;CODE&amp;gt;n giga watt&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;teraWatt&#039;&#039;&#039;&lt;br /&gt;
::Generates a power-value of n teraWatt.&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;CODE&amp;gt;n tera watt&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;metric&#039;&#039;&#039; &#039;&#039;&#039;hp&#039;&#039;&#039;&lt;br /&gt;
::Generates a power-value of n metric horsePower (PS). Roughly 735.5 watt.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial&#039;&#039;&#039; &#039;&#039;&#039;hp&#039;&#039;&#039;&lt;br /&gt;
::Generates a power-value of n imperial horsePower (hp). Roughly 745.7 W watt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Conversion&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPower&#039;&#039; &#039;&#039;&#039;asMicroWatt&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as µW&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPower&#039;&#039; &#039;&#039;&#039;asMilliWatt&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as mW&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPower&#039;&#039; &#039;&#039;&#039;asKiloWatt&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as kW&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPower&#039;&#039; &#039;&#039;&#039;asMegaWatt&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as MW&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPower&#039;&#039; &#039;&#039;&#039;asGigaWatt&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as GW&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPower&#039;&#039; &#039;&#039;&#039;asTeraWatt&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as TW&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPower&#039;&#039; &#039;&#039;&#039;asDBm&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as decibel based on milliwatt (1 mW is 0.0 dBm; 1 W is 30.0 dBm) &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPower&#039;&#039; &#039;&#039;&#039;asDBW&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as decibel based on watt (1 W is 0.0 dBW; 1 kW is 30.0 dBW)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;In a Formula&#039;&#039;&#039; (&#039;...&#039;asPhysicExpression value)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 W&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::power in watt. Also recognized: &#039;mW&#039;, &#039;µW&#039;, &#039;kW&#039;, &#039;MW&#039;, &#039;GW&#039;, &#039;hp imp&#039;, &#039;p metric&#039;&lt;br /&gt;
&lt;br /&gt;
=== Force ===&lt;br /&gt;
Force is measured in Newton, and by default printed as such. Instances are created e.g. when multiplying a mass by an acceleration&amp;lt;br&amp;gt;(in Smalltalk: &amp;quot;&amp;lt;code&amp;gt;1 kg * 10 meters / 1 seconds squared&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;newton&#039;&#039;&#039;&lt;br /&gt;
::Generates a force-value of n newton.&lt;br /&gt;
&lt;br /&gt;
*Physic::Force &#039;&#039;&#039;kilopond:&#039;&#039;&#039; &#039;&#039;kpNumber&#039;&#039;&lt;br /&gt;
::Force from a given Kilopond amount. Notice that the Kilopond is no longer allowed (since 1978). So this should only be used when reading/converting old historic data.&lt;br /&gt;
&lt;br /&gt;
*Physic::Force &#039;&#039;&#039;gramForce unitAmount:&#039;&#039;&#039; &#039;&#039;gfNumber&#039;&#039;&lt;br /&gt;
::Returns a force value of &#039;&#039;gfNumber&#039;&#039; gramForce (gf). Notice that the &amp;quot;gramForce&amp;quot; message sent to the Force class returns the GramForce unit (not a value). Then, that unit gets the &amp;quot;unitAmount:&amp;quot; message, which returns a physical value (gf).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Conversion&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aForce&#039;&#039; &#039;&#039;&#039;asGramForce&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as gf&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aForce&#039;&#039; &#039;&#039;&#039;asTonForce&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as tf (metric tons of force)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aForce&#039;&#039; &#039;&#039;&#039;asPoundsForce&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as lbf&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aForce&#039;&#039; &#039;&#039;&#039;asKiloNewton&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as kN&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aForce&#039;&#039; &#039;&#039;&#039;asMilliNewton&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as mN&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aForce&#039;&#039; &#039;&#039;&#039;asNewton&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as N (i.e. without scale prefix)&lt;br /&gt;
&lt;br /&gt;
=== Area ===&lt;br /&gt;
Area is a derived unit based on length in meters and measured in square meter. The default printing is in &amp;quot;m²&amp;quot;. Instances of &amp;quot;Area&amp;quot; are created e.g. when multiplying two length values or when dividing a volume by a length.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;squareMeter&#039;&#039;&#039;&lt;br /&gt;
::Generates an area-value of n square meters (m²).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;squareMilliMeter&#039;&#039;&#039;&lt;br /&gt;
::Generates an area-value of n square millimeters.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;squareKiloMeter&#039;&#039;&#039;&lt;br /&gt;
::Generates an area-value of n square kilometers (1000*1000 m²).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;hectare&#039;&#039;&#039;&lt;br /&gt;
::Generates an area-value of n hectares. Same as &amp;lt;CODE&amp;gt;n hecto are&amp;lt;/CODE&amp;gt; or 10000 m².&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;are&#039;&#039;&#039;&lt;br /&gt;
::Generates an area-value of n ares. 1 are being 100 m².&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;squareMiles&#039;&#039;&#039;&lt;br /&gt;
::Generates an area-value of n square miles. 1 sq mi being 2589988.110336 m².&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;squareFeet&#039;&#039;&#039;&lt;br /&gt;
::Generates an area-value of n square feet. 1 sq ft being 0.0929 m².&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;acres&#039;&#039;&#039;&lt;br /&gt;
::Generates an area-value of n acres. 1 acre being 4046.856 m².&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anArea&#039;&#039; &#039;&#039;&#039;asAre&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as are (1 are = 100 m²)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anArea&#039;&#039; &#039;&#039;&#039;asAWG&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as american gauge units (wire thickness)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anArea&#039;&#039; &#039;&#039;&#039;asHectare&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as hectare (&amp;quot;ha&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anArea&#039;&#039; &#039;&#039;&#039;asSquareKiloMeters&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as square kilometer (&amp;quot;km²&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anArea&#039;&#039; &#039;&#039;&#039;asSquareMeters&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as square meter (&amp;quot;m²&amp;quot;) without scale prefix&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anArea&#039;&#039; &#039;&#039;&#039;asSquareFeet&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as square feet (&amp;quot;sq ft&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anArea&#039;&#039; &#039;&#039;&#039;asAcres&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as acres (&amp;quot;ac&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anArea&#039;&#039; &#039;&#039;&#039;asSquareMiles&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as square miles (&amp;quot;sq mi&amp;quot;) (based on a land mile being 1609.344 m)&lt;br /&gt;
&lt;br /&gt;
=== Volume ===&lt;br /&gt;
Volume is a derived unit based on length in meters and measured in cubic meter. The default printing is in &amp;quot;m³&amp;quot;, although the print function may choose to print in liters &amp;quot;l&amp;quot;, or milli liters &amp;quot;ml&amp;quot; etc.&amp;lt;br&amp;gt;Instances of &amp;quot;Volume&amp;quot; are created e.g. when multiplying an area by a length or when cubing a length.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cubicMeter&#039;&#039;&#039; &amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cubic&#039;&#039;&#039; &#039;&#039;&#039;meter&#039;&#039;&#039;&lt;br /&gt;
::Generates an volume-value of n cubic meters (1000 l). The alternative &amp;quot;1 cubic meter&amp;quot; uses the &amp;quot;cubic&amp;quot; prefix.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;liter&#039;&#039;&#039;&lt;br /&gt;
::Generates an volume-value of n liters.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milliLiter&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume-value of n milliliters.&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;CODE&amp;gt;n milli liter&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;hectoLiter&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume-value of n hectoliters.&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;CODE&amp;gt;n hecto liter&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;barrel&#039;&#039;&#039; &amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american&#039;&#039;&#039; &#039;&#039;&#039;barrel&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume of n barrels (oil volume measurement). 1 (oil) barrel is 158.987 liters. This is an US oil barrel (aka &amp;quot;blue barrel&amp;quot;), which is different from an imperial barrel and also different from beer/wine barrels.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;flozIMP&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;flozGB&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;british&#039;&#039;&#039;  &#039;&#039;&#039;floz&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial&#039;&#039;&#039;  &#039;&#039;&#039;floz&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume of n imperial fluid ounces (0.02841 liter or 28.4130625 ml).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;number&#039;&#039; &#039;&#039;&#039;flozUS&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;number&#039;&#039; &#039;&#039;&#039;american&#039;&#039;&#039;  &#039;&#039;&#039;floz&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume of n US fluid ounces (0.02957 liter or 29.5735295625 ml).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;pintIMP&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;pintGB&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;british&#039;&#039;&#039;  &#039;&#039;&#039;pint&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial&#039;&#039;&#039;  &#039;&#039;&#039;pint&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume of n imperial pints (568.26125 ml).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;pintUS&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american&#039;&#039;&#039;  &#039;&#039;&#039;pint&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume of n US pints (473.176473 ml). It seems that british drinkers get more for the pint ;-)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;quartIMP&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;quartGB&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;british&#039;&#039;&#039;  &#039;&#039;&#039;quart&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial&#039;&#039;&#039;  &#039;&#039;&#039;quart&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume of n imperial quarts (1.1365 liter).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;quartUS&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american&#039;&#039;&#039;  &#039;&#039;&#039;quart&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume of n US quarts (946.353 ml).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;gallonsIMP&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;gallonsGB&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;british&#039;&#039;&#039;  &#039;&#039;&#039;gallons&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial&#039;&#039;&#039;  &#039;&#039;&#039;gallons&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume of n imperial gallons (4.5461 liter).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;gallonsUS&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american&#039;&#039;&#039;  &#039;&#039;&#039;gallons&#039;&#039;&#039;&lt;br /&gt;
::Generates a volume of n US gallons (3.7854 liter).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Converting&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asCubicMeters&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as cubic meters (&amp;quot;mˆ3&amp;quot;) (not as &amp;quot;ml&amp;quot; or &amp;quot;l&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asLiters&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as liters (&amp;quot;l&amp;quot;). (not as &amp;quot;ml&amp;quot; or &amp;quot;mˆ3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asHectoLiters&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as hectoliters (&amp;quot;hl&amp;quot;) (not as &amp;quot;ml&amp;quot;, &amp;quot;l&amp;quot; or &amp;quot;mˆ3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asMilliLiters&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as milliliters (&amp;quot;ml&amp;quot;) (not as &amp;quot;l&amp;quot; or &amp;quot;mˆ3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asCentiLiters&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as centiliters (&amp;quot;cl&amp;quot;) (not as &amp;quot;l&amp;quot; or &amp;quot;mˆ3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asDeciLiters&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as deciliters (&amp;quot;dl&amp;quot;) (not as &amp;quot;l&amp;quot; or &amp;quot;mˆ3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asCubicInches&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as cubic inches (&amp;quot;cuin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asFlozGB&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as imperial fluid ounces (&amp;quot;imp fl oz&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asFlozUS&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as US fluid ounces (&amp;quot;us fl oz&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asGallonsGB&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as imperial gallons (&amp;quot;imp ga&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVolume&#039;&#039; &#039;&#039;&#039;asGallonsUS&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as US gallons (&amp;quot;us ga&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Print Setup&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Physic::Volume &#039;&#039;&#039;literAbbrev:&#039;&#039;&#039; &#039;L&#039;&lt;br /&gt;
::configure to print &amp;quot;L&amp;quot; (upper case) instead of &amp;quot;l&amp;quot; (lower case letter &amp;quot;L&amp;quot;).&amp;lt;br&amp;gt;(NIST recommendation in US, to avoid confusion with the digit &#039;1&#039;). Other useful arguments are &#039;ℓ&#039;or &#039;ltr&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;In a Formula&#039;&#039;&#039; (&#039;...&#039;asPhysicExpression value)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 L&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::volume in Liter. Also recognized: &#039;dL&#039;, &#039;cL&#039;, &#039;ml&#039;, &#039;µL&#039;, &#039;hL&#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 gal&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::volume in US gallons. Also recognized: &#039;bbl&#039;,&#039;floz&#039;, with optional modifier: american (&#039;gal us&#039;) and imperial (&#039;gal imp&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Velocity (Speed) ===&lt;br /&gt;
Velocity is a derived unit based on length in meters and measured in meters per second. The default printing is in &amp;quot;m/s&amp;quot;. Instances of &amp;quot;Velocity&amp;quot; are created e.g. when dividing a length by a time duration.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;meterPerSecond&#039;&#039;&#039;&lt;br /&gt;
::Generates a velocity of n meters per second.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloMeterPerHour&#039;&#039;&#039;&lt;br /&gt;
::Generates a velocity of n km per hour.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milesPerHour&#039;&#039;&#039;&lt;br /&gt;
::Generates a velocity of n mph.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;knots&#039;&#039;&#039;&lt;br /&gt;
::Generates a velocity of n nautical miles per hour.&lt;br /&gt;
&lt;br /&gt;
*Physic::NatureConstants &#039;&#039;&#039;lightspeed&#039;&#039;&#039;&lt;br /&gt;
::Speed of light in vacuum&lt;br /&gt;
&lt;br /&gt;
*Physic::NatureConstants &#039;&#039;&#039;soundspeed&#039;&#039;&#039;&lt;br /&gt;
::Speed of sound (in dry air at 20°C)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVelocity&#039;&#039; &#039;&#039;&#039;asKiloMetersPerHour&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as km/h&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVelocity&#039;&#039; &#039;&#039;&#039;asMilesPerHour&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as mph&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVelocity&#039;&#039; &#039;&#039;&#039;asKnots&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as nautical knots (kn). 1 knot being 0.514 m/s or 1.852 km/h (&amp;quot;1.0 knots asKiloMetersPerHour&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;In a Formula&#039;&#039;&#039; (&#039;...&#039;asPhysicExpression value)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 m/s&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::speed in Meter per second. Also recognized: &#039;km/h&#039;, &#039;cm/s&#039;, &#039;mph&#039;, &#039;mi/h&#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 kn&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::speed in Knots.&lt;br /&gt;
&lt;br /&gt;
=== Acceleration ===&lt;br /&gt;
&lt;br /&gt;
Velocity is a derived unit based on length in meters and measured in meters per second per second. The default printing is in &amp;quot;m/s²&amp;quot;. Instances of &amp;quot;Acceleration&amp;quot; are created e.g. when dividing a velocity by a time duration.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;metersPerSecondPerSecond&#039;&#039;&#039;&lt;br /&gt;
::Generates an acceleration of n m/s².&lt;br /&gt;
&lt;br /&gt;
*Physic::NatureConstants &#039;&#039;&#039;earthGravity&#039;&#039;&#039;&lt;br /&gt;
::Returns 9.80665 m/s²&lt;br /&gt;
&lt;br /&gt;
*Physic::NatureConstants[&#039;planets&#039;][&#039;earth&#039;][&#039;gravity&#039;|&lt;br /&gt;
::also returns 9.80665 m/s²&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;anAcceleration&#039;&#039; &#039;&#039;&#039;asGForce&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;g&amp;quot; (multiples of 9.81m/s²).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queries&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;anAcceleration&#039;&#039; &#039;&#039;&#039;distanceAfter:&#039;&#039;&#039; &#039;&#039;aTimeDuration&#039;&#039;&lt;br /&gt;
::Computes the distance travelled when a constant acceleration is applied for some time.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anAcceleration&#039;&#039; &#039;&#039;&#039;speedAfter:&#039;&#039;&#039; &#039;&#039;aTimeDuration&#039;&#039;&lt;br /&gt;
::Computes the speed when a constant acceleration is applied for some time.&lt;br /&gt;
&lt;br /&gt;
=== Pressure ===&lt;br /&gt;
Pressure is a derived unit measured in Pascal. The default printing is in &amp;quot;Pa&amp;quot;. Instances of &amp;quot;Pressure&amp;quot; are created e.g. when dividing a force by an area. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;pascal&#039;&#039;&#039;&lt;br /&gt;
::Generates a pressure value of n pascal.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;hectoPascal&#039;&#039;&#039;&lt;br /&gt;
::Generates a pressure value of n hectoPascal.&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;CODE&amp;gt;n hecto pascal&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPressure&#039;&#039; &#039;&#039;&#039;asAtm&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as atm (atmospheres)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPressure&#039;&#039; &#039;&#039;&#039;asBar&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as bar&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPressure&#039;&#039; &#039;&#039;&#039;asHectoPascal&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as hPa&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPressure&#039;&#039; &#039;&#039;&#039;asPascal&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as Pa&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPressure&#039;&#039; &#039;&#039;&#039;asPSI&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as psi (pounds per square inch)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPressure&#039;&#039; &#039;&#039;&#039;asTorr&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as torr&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPressure&#039;&#039; &#039;&#039;&#039;asMmHg&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as mmHg (millimeter of mercury). Same magnitude as torr, but this is typically used in medical domains.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;In a Formula&#039;&#039;&#039; (&#039;...&#039;asPhysicExpression value)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;100 Pa&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::pressure in pascal. Also recognized: &#039;hPa&#039;, &#039;kPa&#039;, &#039;MPa&#039;, &#039;GPa&#039;, &#039;mPa&#039;, &#039;bar&#039;, &#039;atm&#039;, &#039;psi&#039;, &#039;mmH2O&#039;, &#039;mmHg&#039;, &#039;torr&#039;&lt;br /&gt;
&lt;br /&gt;
=== Voltage ===&lt;br /&gt;
Voltage is a derived unit measured in Volt. The default printing is in &amp;quot;V&amp;quot;, &amp;quot;mV&amp;quot;, &amp;quot;kV&amp;quot; as appropriate. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;volts&#039;&#039;&#039;&lt;br /&gt;
::Generates an electrical voltage of n volts.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milliVolt&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;volt&#039;&#039;&#039;&lt;br /&gt;
::Generates a voltage of n millivolt.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;microVolt&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;volt&#039;&#039;&#039;&lt;br /&gt;
::Generates a voltage of n microvolt.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloVolt&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kilo&#039;&#039;&#039; &#039;&#039;&#039;volt&#039;&#039;&#039;&lt;br /&gt;
::Generates a voltage of n kilovolt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aVoltage&#039;&#039; &#039;&#039;&#039;asDBV&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as as DBV (decibel voltage Lv)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVoltage&#039;&#039; &#039;&#039;&#039;asDBu&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as as DBu (decibel voltage Lu)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVoltage&#039;&#039; &#039;&#039;&#039;asKiloVolts&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as kV&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVoltage&#039;&#039; &#039;&#039;&#039;asMilliVolts&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as mV&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVoltage&#039;&#039; &#039;&#039;&#039;asMicroVolts&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as µV&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVoltage&#039;&#039; &#039;&#039;&#039;asNanoVolts&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as nV&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aVoltage&#039;&#039; &#039;&#039;&#039;asVolts&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as V (without scale prefix)&lt;br /&gt;
&lt;br /&gt;
=== Electric Current ===&lt;br /&gt;
A derived unit measured in Ampere. The default printing is in &amp;quot;A&amp;quot;, &amp;quot;mA&amp;quot;, &amp;quot;kA&amp;quot; as appropriate. Instances of &amp;quot;Current&amp;quot; are created e.g. when dividing an electric charge by a time duration.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;ampere&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric current of n ampere.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milliAmpere&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;milli&#039;&#039;&#039; &#039;&#039;&#039;ampere&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric current of n milliampere.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;microAmpere&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;micro&#039;&#039;&#039; &#039;&#039;&#039;ampere&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric current of n microampere.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aCurrent&#039;&#039; &#039;&#039;&#039;asKiloAmperes&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;kA&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCurrent&#039;&#039; &#039;&#039;&#039;asMilliAmperes&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;mA&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCurrent&#039;&#039; &#039;&#039;&#039;asMicroAmperes&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;uA&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCurrent&#039;&#039; &#039;&#039;&#039;asNanoAmperes&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;nA&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCurrent&#039;&#039; &#039;&#039;&#039;asPicoAmperes&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;pA&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCurrent&#039;&#039; &#039;&#039;&#039;asAmperes&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;A&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Electric Resistance ===&lt;br /&gt;
A derived unit measured in Ohm. The default printing is in &amp;quot;Ω&amp;quot;, &amp;quot;kΩ&amp;quot;, &amp;quot;MΩ&amp;quot;  as appropriate. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;ohm&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric resistance of n ohm.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;kiloOhm&#039;&#039;&#039; (or &#039;&#039;&#039;kilohm&#039;&#039;&#039;)&lt;br /&gt;
::Generates an electric resistance of n kilo Ohm.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;megaOhm&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric resistance of n megaOhm.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Physic::ElectricResistance&#039;&#039; &#039;&#039;&#039;colorCode: &#039;&#039;&#039;#(name1 name2 name3 [name4])&lt;br /&gt;
::Generates an electric resistance given a resistor&#039;s color code. The argument must be a 3 or 4 element collection (array), and the name_i elements must be color name symbols, i.e. one of {black, brown, red, orange, yellow, green, blue, violet, grey, white).&amp;lt;br&amp;gt;For example, &amp;quot;Physic::ElectricResistance&#039; colorCode:#(yellow violet red)&amp;quot; returns 4700 Ω.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aResistance&#039;&#039; &#039;&#039;&#039;asKiloOhms&#039;&#039;&#039; (or &#039;&#039;&#039;asKilohms&#039;&#039;&#039;)&lt;br /&gt;
::prints as &amp;quot;kΩ&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aResistance&#039;&#039; &#039;&#039;&#039;asMegaOhms&#039;&#039;&#039;&lt;br /&gt;
::prints as &amp;quot;MΩ&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aResistance&#039;&#039; &#039;&#039;&#039;asOhms&#039;&#039;&#039;&lt;br /&gt;
::prints as &amp;quot;Ω&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aResistance&#039;&#039; &#039;&#039;&#039;asMilliOhms&#039;&#039;&#039;&lt;br /&gt;
::prints as &amp;quot;mΩ&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Additional Arithmetic Operations&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;aResistance1&#039;&#039;&amp;amp;nbsp;&#039;&#039;&#039;|&#039;&#039;&#039;&amp;amp;nbsp;&#039;&#039;aResistance2&#039;&#039;&lt;br /&gt;
::Computes the resistance of resistors in parallel (as opposed to &amp;quot;&#039;&#039;&#039;+&#039;&#039;&#039;&amp;quot; which adds the values and thus computes resistors in series)&lt;br /&gt;
&lt;br /&gt;
=== Electric Capacitance ===&lt;br /&gt;
A derived unit measured in Farad. The default printing is in &amp;quot;F&amp;quot;, &amp;quot;uF&amp;quot;, &amp;quot;nF&amp;quot;, &amp;quot;pF&amp;quot; as appropriate.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;farad&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric capacitance of n farad.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;microFarad&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric capacitance of n microfarad.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;nanoFarad&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric capacitance of n nanofarad.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;picoFarad&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric capacitance of n picofarad.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCapacitance&#039;&#039; &#039;&#039;&#039;asMicroFarads&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;uF&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCapacitance&#039;&#039; &#039;&#039;&#039;asNanoFarads&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;nF&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCapacitance&#039;&#039; &#039;&#039;&#039;asPicoFarads&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;pF&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCapacitance&#039;&#039; &#039;&#039;&#039;asFarads&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;F&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Additional Arithmetic Operations&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;aCapacitance1&#039;&#039;&amp;amp;nbsp;&#039;&#039;&#039;|&#039;&#039;&#039;&amp;amp;nbsp;&#039;&#039;aCapacitance2&#039;&#039;&lt;br /&gt;
::Computes the capacitance of caps in parallel (same as &amp;quot;&#039;&#039;&#039;+&#039;&#039;&#039;&amp;quot; here)&lt;br /&gt;
&lt;br /&gt;
=== Electric Charge ===&lt;br /&gt;
A unit measured in Coulomb. The default printing is in &amp;quot;C&amp;quot;. Instances of &amp;quot;Charge&amp;quot; are created e.g. when multiplying an electric current by a time duration.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;coulomb&#039;&#039;&#039;&lt;br /&gt;
::Generates an electric charge of n coulomb.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aCharge&#039;&#039; &#039;&#039;&#039;asAmpereSeconds&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;As&amp;quot; (which is also a coulomb, but &amp;quot;As&amp;quot; might be preferred in some domains)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCharge&#039;&#039; &#039;&#039;&#039;asAmpereHours&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;Ah&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCharge&#039;&#039; &#039;&#039;&#039;asElementaryCharges&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;q&amp;quot;.&amp;lt;br&amp;gt;1 coulomb corresponds to 6.241e+18 elementary charges&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCharge&#039;&#039; &#039;&#039;&#039;asNumberOfElectrons&#039;&#039;&#039;&lt;br /&gt;
::Returns the above as a scalar number&lt;br /&gt;
&lt;br /&gt;
=== Inductance ===&lt;br /&gt;
A unit measured in Henry (H).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;henry&#039;&#039;&#039;&lt;br /&gt;
::Generates an inductance of n henry.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;anInductance&#039;&#039; &#039;&#039;&#039;asMilliUnitValue&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;mH&amp;quot;&lt;br /&gt;
*&#039;&#039;anInductance&#039;&#039; &#039;&#039;&#039;asMicroUnitValue&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as &amp;quot;µH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Additional Arithmetic Operations&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;anInductance1&#039;&#039;&amp;amp;nbsp;&#039;&#039;&#039;|&#039;&#039;&#039;&amp;amp;nbsp;&#039;&#039;anInductance2&#039;&#039;&lt;br /&gt;
::Computes the inductance of coils in parallel (as opposed to &amp;quot;&#039;&#039;&#039;+&#039;&#039;&#039;&amp;quot; which adds the values and thus computes coils in series)&lt;br /&gt;
&lt;br /&gt;
=== LuminousIntensity ===&lt;br /&gt;
A unit measured in Candela (cd).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;candela&#039;&#039;&#039;&lt;br /&gt;
::Generates a luminousIntensity of n candela.&lt;br /&gt;
&lt;br /&gt;
=== Luminance ===&lt;br /&gt;
A unit measured in Lux (lx). Results from dividing a luminous intensity by an area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;lux&#039;&#039;&#039;&lt;br /&gt;
::Generates a luminance of n lux.&lt;br /&gt;
&lt;br /&gt;
=== MagneticFlux ===&lt;br /&gt;
A unit measured in Weber (Wb).&amp;lt;br&amp;gt;Results from multiplying a voltage by a time.&lt;br /&gt;
&lt;br /&gt;
=== MagneticFluxDensity ===&lt;br /&gt;
A unit measured in Tesla (T).&amp;lt;br&amp;gt;Results from dividing a magnetic flux by an area.&lt;br /&gt;
&lt;br /&gt;
=== CurrentDensity ===&lt;br /&gt;
A unit measured in A/m².&amp;lt;br&amp;gt;Results from dividing an electric current by an area.&lt;br /&gt;
&lt;br /&gt;
=== Viscosity ===&lt;br /&gt;
DynamicViscosity unit measured in Poise (P) and KinematicViscosity measured in Stokes (St).&lt;br /&gt;
&lt;br /&gt;
=== Electric Conductance ===&lt;br /&gt;
A unit measured in Siemens (S) which is s³·m⁻²·kg⁻¹·A² (dimension T³·L⁻²·M⁻¹·I²).&amp;lt;br&amp;gt;This is the reciprocal of the electric resistance.&lt;br /&gt;
&lt;br /&gt;
=== Mass Density ===&lt;br /&gt;
A unit measured in kg/m³ (dimension L⁻³·M). Instances are created e.g. when dividing a mass by a volume.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conversion&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;aMassDensity&#039;&#039; &#039;&#039;&#039;asGramPerCubicCentimeter&#039;&#039;&#039;&lt;br /&gt;
::Presents itself as g/cm³. For example:&lt;br /&gt;
::: massSun := Physic::NatureConstants[&#039;sun&#039;][&#039;mass&#039;].&lt;br /&gt;
::: volumeSun := Physic::NatureConstants[&#039;sun&#039;][&#039;Volume&#039;].&lt;br /&gt;
::: (massSun / volumeSun) asGramPerCubicCentimeter&lt;br /&gt;
::::     &amp;lt;small&amp;gt;=&amp;gt; 1.41028368794326 g/cm³&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== English Engineering and Imperial Units (EEU) ==&lt;br /&gt;
&lt;br /&gt;
See [https://en.wikipedia.org/wiki/English_Engineering_Units English Engineering Units] and [https://en.wikipedia.org/wiki/Imperial_and_US_customary_measurement_systems Imperial and US customary measurement systems].&lt;br /&gt;
&lt;br /&gt;
=== EEU/Imperial Length ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Access&#039;&#039;&#039;&lt;br /&gt;
* PhysicalUnit::Length &#039;&#039;&#039;inches&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;in&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Length &#039;&#039;&#039;feet&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;ft&amp;quot;&lt;br /&gt;
  &lt;br /&gt;
* PhysicalUnit::Length &#039;&#039;&#039;yards&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;yd&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Length &#039;&#039;&#039;thous&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;thous&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Length &#039;&#039;&#039;landMiles&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;mi&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Length &#039;&#039;&#039;nauticalMiles&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;nmi&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Instance Creation&#039;&#039;&#039;&lt;br /&gt;
* (PhysicalUnit::Length &#039;&#039;&#039;feet&#039;&#039;&#039;) unitAmount: &#039;&#039;&#039;n&#039;&#039;&#039;&lt;br /&gt;
::Generates a length of n feet.&lt;br /&gt;
 &lt;br /&gt;
* &#039;&#039;someUnit&#039;&#039; unitAmount: &#039;&#039;&#039;n&#039;&#039;&#039;&lt;br /&gt;
::Once you have any units at hand, you&#039;ll get a physical value with &amp;lt;aUnit&amp;gt; unitAmount: &amp;lt;n&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Number Protocol&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;feet&#039;&#039;&#039; (prints itself with SI unit &#039;m&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;feet&#039;&#039;&#039; &#039;&#039;&#039;asFeet&#039;&#039;&#039; (prints itself with unit &#039;ft&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;inches&#039;&#039;&#039; (prints itself with SI unit &#039;m&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;inches&#039;&#039;&#039; &#039;&#039;&#039;asInches&#039;&#039;&#039; (prints itself with unit &#039;in&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;yards&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;yards&#039;&#039;&#039; &#039;&#039;&#039;asYards&#039;&#039;&#039; (prints itself with unit &#039;yd&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;landMiles&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;landMiles&#039;&#039;&#039; &#039;&#039;&#039;asLandMiles&#039;&#039;&#039; (prints itself with unit &#039;mi&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;nauticalMiles&#039;&#039;&#039; &lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;nauticalMiles&#039;&#039;&#039; &#039;&#039;&#039;asNauticalMiles&#039;&#039;&#039; (prints itself with unit &#039;nmi&#039;)&lt;br /&gt;
&lt;br /&gt;
=== EEU/Imperial Area ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Access&#039;&#039;&#039;&lt;br /&gt;
* PhysicalUnit::Area &#039;&#039;&#039;squareInches&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;sq in&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Area &#039;&#039;&#039;squareFeet&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;sq ft&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Area &#039;&#039;&#039;squareMiles&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;sq mi&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Area &#039;&#039;&#039;acres&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;acre&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Number Protocol&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;square inches&#039;&#039;&#039; (prints itself with SI unit &#039;m²&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;square inches&#039;&#039;&#039; &#039;&#039;&#039;asSquareInches&#039;&#039;&#039; (prints itself with unit &#039;sq in&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;square feet&#039;&#039;&#039; (prints itself with SI unit &#039;m²&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;square feet&#039;&#039;&#039; &#039;&#039;&#039;asSquareFeet&#039;&#039;&#039; (prints itself with unit &#039;sq ft&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;square miles&#039;&#039;&#039; (prints itself with SI unit &#039;m²&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;square miles&#039;&#039;&#039; &#039;&#039;&#039;asSquareFeet&#039;&#039;&#039; (prints itself with unit &#039;sq mi&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;acres&#039;&#039;&#039; (prints itself with SI unit &#039;m²&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;acres&#039;&#039;&#039; &#039;&#039;&#039;asAcres&#039;&#039;&#039; (prints itself with unit &#039;acre&#039;)&lt;br /&gt;
&lt;br /&gt;
=== EEU/Imperial Volume ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Access&#039;&#039;&#039;&lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;cubicInches&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;cu in&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;cubicFeet&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;cu ft&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;cubicYards&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;cu yd&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;squareMiles&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;sq mi&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;gallonsIMP&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as imperial gallons &amp;quot;imp gal&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;gallonsUS&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as US gallons &amp;quot;US gal&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;pintsIMP&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as imperial pints &amp;quot;imp pt&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;pintsUS&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as US pints &amp;quot;US pt&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;barrelsIMP&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as imperial barrels &amp;quot;bbl. imp&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Volume &#039;&#039;&#039;barrelsUS&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as US pints &amp;quot;bbl.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Number Protocol&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cubic inches&#039;&#039;&#039; (prints itself with SI unit &#039;m³&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cubic inches&#039;&#039;&#039; &#039;&#039;&#039;asCubicInches&#039;&#039;&#039; (prints itself with unit &#039;cu in&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cubic feet&#039;&#039;&#039; (prints itself with SI unit &#039;m³&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cubic feet&#039;&#039;&#039; &#039;&#039;&#039;asCubicFeet&#039;&#039;&#039; (prints itself with unit &#039;cu ft&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cubic yards&#039;&#039;&#039; (prints itself with SI unit &#039;m³&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cubic yards&#039;&#039;&#039; &#039;&#039;&#039;asCubicFeet&#039;&#039;&#039; (prints itself with unit &#039;cu yd&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial pints&#039;&#039;&#039; (prints itself with SI unit &#039;m³&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial pints&#039;&#039;&#039; &#039;&#039;&#039;asPintsIMP&#039;&#039;&#039; (prints itself with unit &#039;imp pt&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american pints&#039;&#039;&#039; (prints itself with SI unit &#039;m³&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american pints&#039;&#039;&#039; &#039;&#039;&#039;asPintsUS&#039;&#039;&#039; (prints itself with unit &#039;US pt&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial gallons&#039;&#039;&#039; (prints itself with SI unit &#039;m³&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial gallons&#039;&#039;&#039; &#039;&#039;&#039;asGallonsIMP&#039;&#039;&#039; (prints itself with unit &#039;imp gal&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american gallons&#039;&#039;&#039; (prints itself with SI unit &#039;m³&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american gallons&#039;&#039;&#039; &#039;&#039;&#039;asGallonsUS&#039;&#039;&#039; (prints itself with unit &#039;US gal&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial barrels&#039;&#039;&#039; (prints itself with SI unit &#039;m³&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;imperial barrels&#039;&#039;&#039; &#039;&#039;&#039;asBarrelsIMP&#039;&#039;&#039; (prints itself with unit &#039;bbl. imp&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american barrels&#039;&#039;&#039; (prints itself with SI unit &#039;m³&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;american barrels&#039;&#039;&#039; &#039;&#039;&#039;asBarrelsUS&#039;&#039;&#039; (prints itself with unit &#039;bbl.&#039;)&lt;br /&gt;
&lt;br /&gt;
=== EEU/Imperial Mass ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Access&#039;&#039;&#039;&lt;br /&gt;
* PhysicalUnit::Mass &#039;&#039;&#039;poundMass&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;lb&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Mass &#039;&#039;&#039;ounces&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;oz&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* PhysicalUnit::Mass &#039;&#039;&#039;troyOunces&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;oz t&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Number Protocol&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;pounds&#039;&#039;&#039; (prints itself with SI unit &#039;kg&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;pounds&#039;&#039;&#039; &#039;&#039;&#039;asPounds&#039;&#039;&#039; (prints itself with unit &#039;lb&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;troyOunces&#039;&#039;&#039;  (prints itself with unit &#039;kg&#039;)&lt;br /&gt;
* &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;troyOunces&#039;&#039;&#039; &#039;&#039;&#039;asTroyOunces&#039;&#039;&#039; (prints itself with unit &#039;oz t&#039;)&lt;br /&gt;
&lt;br /&gt;
=== EEU/Imperial Force ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Access&#039;&#039;&#039;&lt;br /&gt;
* PhysicalUnit::Mass &#039;&#039;&#039;poundForce&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;lbf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Mass &#039;&#039;&#039;poundal&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;pdl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== EEU/Imperial Power ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Access&#039;&#039;&#039;&lt;br /&gt;
* PhysicalUnit::Mass &#039;&#039;&#039;poundForce&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;lbf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Mass &#039;&#039;&#039;poundal&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;pdl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== EEU/Imperial Energy ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Access&#039;&#039;&#039;&lt;br /&gt;
* PhysicalUnit::Mass &#039;&#039;&#039;btu&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;btu&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== EEU/Imperial Temperature ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unit Access&#039;&#039;&#039;&lt;br /&gt;
* PhysicalUnit::Temperature &#039;&#039;&#039;fahrenheit&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;°F&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
* PhysicalUnit::Temperature &#039;&#039;&#039;rankine&#039;&#039;&#039;&lt;br /&gt;
::Returns a unit which represents its values as &amp;quot;°R&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Defining Additional Unit Converters ==&lt;br /&gt;
&lt;br /&gt;
You can define additional unit converters as &#039;&#039;ConvertedUnit&#039;&#039; as follows:&lt;br /&gt;
 myUnit := Physic::ConvertedUnit &lt;br /&gt;
             name:unitName &lt;br /&gt;
             baseUnit:baseUnit &lt;br /&gt;
             unitString:unitString &lt;br /&gt;
             unitValueBlock:unitValueBlock&lt;br /&gt;
             baseUnitValueBlock:baseUnitValueBlock&lt;br /&gt;
&lt;br /&gt;
Where &lt;br /&gt;
* &#039;&#039;baseUnit&#039;&#039; is the underlying base (SI) unit, &lt;br /&gt;
* &#039;&#039;unitString&#039;&#039; is the string used when printing, &lt;br /&gt;
* &#039;&#039;unitValueBlock&#039;&#039; is a Smalltalk block to compute the unit value from a base unit value and&lt;br /&gt;
* &#039;&#039;baseUnitValueBlock&#039;&#039; is a Smalltalk block to compute the base unit value from the unit value.&lt;br /&gt;
&lt;br /&gt;
==== Example: Cubic Inch Unit ==== &lt;br /&gt;
For example, to get volumes printed as cubic inches, you could define &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;:&lt;br /&gt;
 cI := Physic::ConvertedUnit&lt;br /&gt;
         name:&#039;CubicInches&#039;&lt;br /&gt;
         baseUnit:(Physic::Volume) &lt;br /&gt;
         unitString:&#039;in³&#039; &lt;br /&gt;
         unitValueBlock:[:cubicMeters | &lt;br /&gt;
                            cubicMeters * 61023.7440947323&lt;br /&gt;
                        ]&lt;br /&gt;
         baseUnitValueBlock:[:cubicInches| &lt;br /&gt;
                            cubicInches / 61023.7440947323&lt;br /&gt;
                        ]&lt;br /&gt;
&lt;br /&gt;
i.e. to convert from SI base-units, which are cubic meters, into the converted cubic inches, we have to multiply by 61023.7440947323.&amp;lt;br&amp;gt;And vice versa, we have to divide. 61023.7440947323 is the number of cubic inches per cubic meter.&lt;br /&gt;
&lt;br /&gt;
Then create a new physical value for your volume with:&lt;br /&gt;
 cI unitAmount:volumeInCubicMeters&lt;br /&gt;
&lt;br /&gt;
==== Example: Gummy Bear Unit ==== &lt;br /&gt;
Or, to present a mass in units of gummy-bears, assuming one bear weighs 1.1g &amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:,&lt;br /&gt;
 bearUnit := &lt;br /&gt;
     Physic::ConvertedUnit&lt;br /&gt;
         name:&#039;Haribo&#039;&lt;br /&gt;
         baseUnit:(Physic::Mass) &lt;br /&gt;
         unitString:&#039;bears&#039; &lt;br /&gt;
         unitValueBlock:[:kiloGram| kiloGram * 1000 / 1.1]&lt;br /&gt;
         baseUnitValueBlock:[:bears| bears * 1.1 / 1000]&lt;br /&gt;
&lt;br /&gt;
and then take a 150g bag of bears and ask it to print itself on an output stream:&lt;br /&gt;
 bagOfBears := bearUnit baseUnitAmount:0.150.   &amp;quot;/ 0.15 for 150g, because the base unit is kiloGram&lt;br /&gt;
 bagOfBears printOn:Transcript &lt;br /&gt;
gives:&lt;br /&gt;
 =&amp;gt; &amp;quot;136.363636363636 bears&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Notice, that bearUnit (&amp;quot;Haribo&amp;quot;) is still a unit of mass;&lt;br /&gt;
we can add another kilogram to those bears:&lt;br /&gt;
 bagOfBears + 1 kilo gram&lt;br /&gt;
and get more bears:&lt;br /&gt;
 =&amp;gt; 1045.45454545455 bears&lt;br /&gt;
&lt;br /&gt;
You can also convert any mass into gummy-bears:&lt;br /&gt;
 (1 kiloGram as:bearUnit) floor&lt;br /&gt;
gives:&lt;br /&gt;
 =&amp;gt; 909.0 bears&lt;br /&gt;
&lt;br /&gt;
Notes: &lt;br /&gt;
&amp;lt;br&amp;gt;1) this is only an example; you actually don&#039;t need that, as volumes already support conversion to cubicInches (see asCubicInches below)&lt;br /&gt;
&amp;lt;br&amp;gt;2) the author does not know what the actual mass of a gummy bear is ;-)&lt;br /&gt;
&lt;br /&gt;
== Instance Creation via Number Operators ==&lt;br /&gt;
The Number class hierarchy provides a number of instance creation messages for unit values. As described above, a frequency value can be created by sending a &amp;quot;hertz&amp;quot; message to any number:&lt;br /&gt;
 440 hertz&lt;br /&gt;
&lt;br /&gt;
The following lists a subset of messages which are provided in Number (for some, both abbreviations and british/US spelling versions are provided):&lt;br /&gt;
* Area&lt;br /&gt;
: acre, acres, are, hectare, squareMeter, squareCentiMeter, squareFeet, squareInches, squareKiloMeter, squareMiles, squareMilliMeter, squareYard.&lt;br /&gt;
: You can also use the &amp;quot;square&amp;quot; prefix with meter, feet, inches, yards, etc. As in &amp;quot;&amp;lt;CODE&amp;gt;10 square feet&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
* Energy&lt;br /&gt;
: btu, calories, electronVolts, wattHours, &lt;br /&gt;
* Frequency&lt;br /&gt;
: hertz, kiloHertz, megaHertz, gigaHertz, Hz, kHz, MHz, GHz&lt;br /&gt;
* Length&lt;br /&gt;
: angstrom, astronomicalUnits, centiMeter, chineseFeet, chineseMiles, feet, meter, yards, lightYears, miles, seaMiles, kiloMeter, milliMeter, ... &lt;br /&gt;
* Mass&lt;br /&gt;
: atomicMassUnits, gram, kiloGram, kg, microGram, troyPounds, troyOunces, ...&lt;br /&gt;
: You can use the &amp;quot;american&amp;quot;/&amp;quot;british&amp;quot;/&amp;quot;imperial&amp;quot;/&amp;quot;troy&amp;quot; prefixes on &amp;quot;ounces&amp;quot;. As in &amp;quot;&amp;lt;CODE&amp;gt;2 troy ounces&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
* Pressure&lt;br /&gt;
: hectoPascal, torr, ...&lt;br /&gt;
* Temperature&lt;br /&gt;
: degreesCelsius, degreesFahrenheit, kelvin, ...&lt;br /&gt;
* Velocity&lt;br /&gt;
: centiMetersPerSecond &lt;br /&gt;
* Volume&lt;br /&gt;
: gallonsGB, gallonsUS, liter, litre, hectoLiter, hectoLitre, barrel, cubicInches, cubicMeter, cubicCentiMeter, cubicMilliMeter, cubicFeet, cubicKiloMeter, flozGB, flozUS, fluidOuncesGB, fluidOuncesUS, ...&lt;br /&gt;
: You can also use the &amp;quot;cubic&amp;quot; prefix with meter, feet, inches, etc. Eg. &amp;quot;&amp;lt;CODE&amp;gt;10 cubic feet&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
: And you can use the &amp;quot;american&amp;quot;/&amp;quot;british&amp;quot;/&amp;quot;imperial&amp;quot; prefixes on &amp;quot;gallons&amp;quot;, &amp;quot;pints&amp;quot;, &amp;quot;quarts&amp;quot;. Eg. &amp;quot;&amp;lt;CODE&amp;gt;1 british pint&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
* Data&lt;br /&gt;
: bits, bytes, kiloByte, megaByte, gigaByte, kibiByte, mebiByte, gibiByte, ... &lt;br /&gt;
* Electricity&lt;br /&gt;
: volt, ampere, ohm, coulomb, farad, ampereHours, watt, voltAmpere, henry, ...&lt;br /&gt;
* Other&lt;br /&gt;
: candela, becquerel, tesla, ...&lt;br /&gt;
&lt;br /&gt;
For a full list, open a SystemBrowser, navigate to the ArithmeticValue class and select the &amp;quot;physics-unit converting&amp;quot; category.&lt;br /&gt;
&lt;br /&gt;
All of those can be used with the kilo, mega, giga etc. prefixes.&lt;br /&gt;
&lt;br /&gt;
== Arithmetic ==&lt;br /&gt;
&lt;br /&gt;
Arithmetic on physical values will generate an appropriate physical value with its own unit.&lt;br /&gt;
E.g., when multiplying a velocity by a time, you will get a distance, or when dividing a distance by a time, you will get a velocity.&lt;br /&gt;
&lt;br /&gt;
The following lists some of the possible results.&lt;br /&gt;
Be aware that the units are ignorant of any relativistic effects. They compute their values according to classical Newtonian mechanics.&lt;br /&gt;
&lt;br /&gt;
=== Velocity Arithmetic ===&lt;br /&gt;
&lt;br /&gt;
distance = velocity * time&lt;br /&gt;
&lt;br /&gt;
 3 meterPerSecond                  &amp;lt;small&amp;gt;=&amp;gt; 3 m/s &amp;lt;/small&amp;gt;&lt;br /&gt;
 1 meterPerSecond * 10 seconds     &amp;lt;small&amp;gt;=&amp;gt; 10 m &amp;lt;/small&amp;gt;&lt;br /&gt;
 10 kiloMetersPerHour * 30 minutes &amp;lt;small&amp;gt;=&amp;gt; 5000 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 30 meter / 2 seconds              &amp;lt;small&amp;gt;=&amp;gt; 15 m/s&amp;lt;/small&amp;gt;&lt;br /&gt;
 10 meter / 1 seconds * 20 seconds &amp;lt;small&amp;gt;=&amp;gt; 20 m&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Acceleration Arithmetic  ===&lt;br /&gt;
&lt;br /&gt;
speed = acceleration * time&lt;br /&gt;
&lt;br /&gt;
 1 meterPerSecondPerSecond * 10 seconds            &amp;lt;small&amp;gt;=&amp;gt; 10 m/s &amp;lt;/small&amp;gt; &lt;br /&gt;
 (1 meterPerSecondPerSecond distanceAfter:1 hours) &amp;lt;small&amp;gt;=&amp;gt; 6480.0 km&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 meterPerSecond / 10 seconds                     &amp;lt;small&amp;gt;=&amp;gt; 0.1 m/s²&amp;lt;/small&amp;gt;&lt;br /&gt;
 10 meter / 2 seconds / 5 seconds                  &amp;lt;small&amp;gt;=&amp;gt; 1 m/s²&amp;lt;/small&amp;gt;&lt;br /&gt;
 (9.81 meter / 1 seconds squared) * 1 hours        &amp;lt;small&amp;gt;=&amp;gt; 70632 m/s&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mass Arithmetic  ===&lt;br /&gt;
&lt;br /&gt;
force = mass * acceleration&lt;br /&gt;
&lt;br /&gt;
 1 kiloGram * 1 meterPerSecondPerSecond            &amp;lt;small&amp;gt;=&amp;gt; 1 N&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 kilo gram * 1 meter / 1 seconds / 1 seconds     &amp;lt;small&amp;gt;=&amp;gt; 1 N&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 kilo gram * 100 centi meter / 1 seconds squared &amp;lt;small&amp;gt;=&amp;gt; 1 N&amp;lt;/small&amp;gt;&lt;br /&gt;
 1 newton / 2 kiloGram                             &amp;lt;small&amp;gt;=&amp;gt; (1/2) m/s²&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electric Arithmetic  ===&lt;br /&gt;
current = voltage / resistance&lt;br /&gt;
&amp;lt;br&amp;gt;charge = voltage * capacitance&lt;br /&gt;
&amp;lt;br&amp;gt;charge = current * time&lt;br /&gt;
&lt;br /&gt;
 10 volt / 220 ohm                         &amp;lt;small&amp;gt;=&amp;gt; 45.45 mA&amp;lt;/small&amp;gt;&lt;br /&gt;
 150 ohm * 20 milliAmpere                  &amp;lt;small&amp;gt;=&amp;gt; 3 V &amp;lt;/small&amp;gt;&lt;br /&gt;
 0.5 ampere * 0.5 seconds                  &amp;lt;small&amp;gt;=&amp;gt; 0.25 C&amp;lt;/small&amp;gt;&lt;br /&gt;
 100.0 micro farad * 100 volt              &amp;lt;small&amp;gt;=&amp;gt; 0.01 C&amp;lt;/small&amp;gt;&lt;br /&gt;
 10.0 micro farad * 100 ohm                &amp;lt;small&amp;gt;=&amp;gt; 1.0 ms (the RC time constant)&amp;lt;/small&amp;gt;&lt;br /&gt;
 100 pico farad * 5 volt / 10 milli ampere &amp;lt;small&amp;gt;=&amp;gt; 50ns&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Energy &amp;amp; Power Arithmetic  ===&lt;br /&gt;
&lt;br /&gt;
 10 ampere * 220 volt                      &amp;lt;small&amp;gt;=&amp;gt; 2200 W &amp;lt;/small&amp;gt;&lt;br /&gt;
 10 ampere * 220 volt * 10 hours           &amp;lt;small&amp;gt;=&amp;gt; 79.2 MJ &amp;lt;/small&amp;gt;&lt;br /&gt;
 10 kiloWatt * 10 hours                    &amp;lt;small&amp;gt;=&amp;gt; 360.0 MJ &amp;lt;/small&amp;gt;&lt;br /&gt;
 (10 kiloWatt * 10 hours ) asKiloWattHours &amp;lt;small&amp;gt;=&amp;gt; 100 kWh&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Math Functions and Trigonometric ===&lt;br /&gt;
Angles respond to trigonometric operations:&amp;lt;/small&amp;gt;&lt;br /&gt;
 45 degrees sin      &amp;lt;small&amp;gt;=&amp;gt; 0.707106781186547  &amp;lt;/small&amp;gt;  &lt;br /&gt;
 Float pi radian cos &amp;lt;small&amp;gt;=&amp;gt; -1.0&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If useful, square and cubic root can be computed:&amp;lt;/small&amp;gt;&lt;br /&gt;
 25 squareFeet sqrt  &amp;lt;small&amp;gt;=&amp;gt; 1.524 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 25 squareFeet sqrt asFeet &amp;lt;small&amp;gt;=&amp;gt; 5.0 ft&amp;lt;/small&amp;gt;&lt;br /&gt;
  5 feet * 5 feet.   &amp;lt;small&amp;gt;=&amp;gt; 2.322576 m²&amp;lt;/small&amp;gt;&lt;br /&gt;
 10 liter cbrt       &amp;lt;small&amp;gt;=&amp;gt; 0.2154 m&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Comparing ===&lt;br /&gt;
If the unit&#039;s amount is a float, the usual float comparison problems arise (see chapter on  [[Numeric_Limits/en#Inexact_Float_and_Double_Numbers|comparing float numbers]]).&lt;br /&gt;
&amp;lt;br&amp;gt;You should not compare physical values for equal values; instead give an accepted error range. Either as fraction (e.g. percentage) or in the number accepted eps steps:&lt;br /&gt;
&lt;br /&gt;
 25.0 squareFeet sqrt = 5 feet                     =&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 25.0 squareFeet sqrt isAlmostEqualTo: 5 feet withError:0.00001 =&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 25.0 squareFeet sqrt isAlmostEqualTo: 5 feet nEpsilon:2.     =&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rounding &amp;amp; Truncating ===&lt;br /&gt;
Rounding and truncation operations are provided which generate a unit with the amount processed like the corresponding number operations:&lt;br /&gt;
 &lt;br /&gt;
 1.0 meter floor  &amp;lt;small&amp;gt;=&amp;gt; 1 m    &amp;lt;/small&amp;gt;&lt;br /&gt;
 1.1 meter floor  &amp;lt;small&amp;gt;=&amp;gt; 1 m    &amp;lt;/small&amp;gt;&lt;br /&gt;
 1.7 meter floor  &amp;lt;small&amp;gt;=&amp;gt; 1 m   &amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 1.0 meter ceiling  &amp;lt;small&amp;gt;=&amp;gt; 1 m    &amp;lt;/small&amp;gt;&lt;br /&gt;
 1.1 meter ceiling  &amp;lt;small&amp;gt;=&amp;gt; 2 m    &amp;lt;/small&amp;gt;&lt;br /&gt;
 1.7 meter ceiling  &amp;lt;small&amp;gt;=&amp;gt; 2 m   &amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 1.0 meter rounded  &amp;lt;small&amp;gt;=&amp;gt; 1 m    &amp;lt;/small&amp;gt;&lt;br /&gt;
 1.1 meter rounded  &amp;lt;small&amp;gt;=&amp;gt; 1 m    &amp;lt;/small&amp;gt;&lt;br /&gt;
 1.7 meter rounded  &amp;lt;small&amp;gt;=&amp;gt; 2 m   &amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 1.15 meter roundTo:0.1 &amp;lt;small&amp;gt;=&amp;gt; 1.1 m &amp;lt;/small&amp;gt;&lt;br /&gt;
 1.15 meter roundTo:0.2 &amp;lt;small&amp;gt;=&amp;gt; 1.2 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 1.15 meter roundTo:0.5 &amp;lt;small&amp;gt;=&amp;gt; 1 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 1.04 meter roundTo:0.2 &amp;lt;small&amp;gt;=&amp;gt; 1 m &amp;lt;/small&amp;gt;&lt;br /&gt;
 1.1 meter roundTo:0.2  &amp;lt;small&amp;gt;=&amp;gt; 1.2 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 2 meter negated        &amp;lt;small&amp;gt;=&amp;gt; -2 meter&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (4/3) meter roundedToScale:0 &amp;lt;small&amp;gt;=&amp;gt; 1 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 (4/3) meter roundedToScale:1 &amp;lt;small&amp;gt;=&amp;gt; 1.3 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 (4/3) meter roundedToScale:2 &amp;lt;small&amp;gt;=&amp;gt; 1.33 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 (4/3) meter roundedToScale:3 &amp;lt;small&amp;gt;=&amp;gt; 1.333 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (5/3) meter roundedToScale   &amp;lt;small&amp;gt;=&amp;gt; 1.67 m &amp;lt;/small&amp;gt;&lt;br /&gt;
 (5/3) meter roundedToScale:0 &amp;lt;small&amp;gt;=&amp;gt; 2 m   &amp;lt;/small&amp;gt;&lt;br /&gt;
 (5/3) meter roundedToScale:1 &amp;lt;small&amp;gt;=&amp;gt; 1.7 m   &amp;lt;/small&amp;gt;&lt;br /&gt;
 (5/3) meter roundedToScale:2 &amp;lt;small&amp;gt;=&amp;gt; 1.67 m   &amp;lt;/small&amp;gt;&lt;br /&gt;
 (5/3) meter roundedToScale:3 &amp;lt;small&amp;gt;=&amp;gt; 1.667 m&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be careful with roundedToScale: it will round the unit (which in the above case is meter).&lt;br /&gt;
If the value is small (i.e. in the cm range), rounding to scale 2 will round to 1/100 meter,&lt;br /&gt;
which might later print strange unexpected values.&lt;br /&gt;
Thus it is best to convert the result into a desired range (i.e. asCentiMeters) and round this:&lt;br /&gt;
eg:&lt;br /&gt;
 15.012 centiMeter                   &amp;lt;small&amp;gt;=&amp;gt; 0.15012 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 15.0120 centiMeter roundedToScale:2 &amp;lt;small&amp;gt;=&amp;gt; 0.15 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 15.0120 centiMeter asCentiMeters roundedToScale:2 &amp;lt;small&amp;gt;=&amp;gt; 15.01 cm&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Formula Evaluation ==&lt;br /&gt;
&lt;br /&gt;
Formulae can be parsed and further processed by use of the Physic::Parser class.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Physic::Parser&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;parse:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039;&amp;lt;br&amp;gt;generates a parse tree for further processing&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;aString&#039;&#039; &#039;&#039;&#039;asPhysicExpression&#039;&#039;&#039; &amp;lt;br&amp;gt;same&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Physic::Parser&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;evaluate:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039;&amp;lt;br&amp;gt;parses and evaluates&lt;br /&gt;
&lt;br /&gt;
Generated parse trees can be further processed with:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;aParseTree&#039;&#039; &#039;&#039;&#039;value&#039;&#039;&#039;&amp;lt;br&amp;gt;evaluates the tree; variables are resolved to be units or nature constants&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;aParseTree&#039;&#039; &#039;&#039;&#039;valueIn:&#039;&#039;&#039; &#039;&#039;aDictionary&#039;&#039;&amp;lt;br&amp;gt;evaluates the tree providing variable values&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;aParseTree&#039;&#039; &#039;&#039;&#039;valueWith:&#039;&#039;&#039; &#039;&#039;anAssociation&#039;&#039;&amp;lt;br&amp;gt;evaluates the tree providing a single variable value in the form &amp;quot;( &#039;name&#039; -&amp;gt; value )&amp;quot; (i.e. a Smalltalk Association instance).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;aParseTree&#039;&#039; &#039;&#039;&#039;valueWith:&#039;&#039;&#039; &#039;&#039;assoc1&#039;&#039; [ &#039;&#039;&#039;with:&#039;&#039;&#039; &#039;&#039;assoc2&#039;&#039; ...] &amp;lt;br&amp;gt;ditto, providing 2 values. Up to 4 values can be provided.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;aParseTree&#039;&#039; &#039;&#039;&#039;valueWithX:&#039;&#039;&#039; &#039;&#039;valueOfX&#039;&#039;&amp;lt;br&amp;gt;shortcut provided, since &#039;x&#039; is such a common name.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;aParseTree&#039;&#039; &#039;&#039;&#039;simplify&#039;&#039;&#039;&amp;lt;br&amp;gt;simplifies a parsed formula (if possible)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;aParseTree&#039;&#039; &#039;&#039;&#039;derivate&#039;&#039;&#039;&amp;lt;br&amp;gt;generates a derivate&lt;br /&gt;
&lt;br /&gt;
=== Formula Examples ===&lt;br /&gt;
 vars := Dictionary new.&lt;br /&gt;
 vars at:&#039;a&#039; put:10.&lt;br /&gt;
 vars at:&#039;b&#039; put:20.&lt;br /&gt;
 vars at:&#039;c&#039; put:30.&lt;br /&gt;
 (Physic::Parser parse:&#039;a*x^2 + b*x + c&#039;) valueIn:vars &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 10·x·x + 20·x + 30. (still a symbolic expression, because &#039;x&#039; is unknown)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 vars := Dictionary new.&lt;br /&gt;
 vars at:&#039;a&#039; put:10.&lt;br /&gt;
 vars at:&#039;b&#039; put:20.&lt;br /&gt;
 vars at:&#039;c&#039; put:30.&lt;br /&gt;
 vars at:&#039;x&#039; put:1.&lt;br /&gt;
 (Physic::Parser parse:&#039;a*x^2 + b*x + c&#039;) valueIn:vars &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 60 (a number)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;/ alternative (an inline object instead of a Dictionary)&lt;br /&gt;
 vars := { a: 10 . b: 20 . c: 30 . x : 2 }.&lt;br /&gt;
 (Physic::Parser parse:&#039;a*x^2 + b*x + c&#039;) valueIn:vars &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 110 (a number)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;/ alternative (individual values (up to 4 associations))&lt;br /&gt;
 (&#039;a*x^2 + b*x + c&#039; asPhysicExpression)&lt;br /&gt;
     valueWith:(&#039;a&#039; -&amp;gt; 10)&lt;br /&gt;
     with:(&#039;b&#039; -&amp;gt; 20)&lt;br /&gt;
     with:(&#039;c&#039; -&amp;gt; 30)&lt;br /&gt;
     with:(&#039;x&#039; -&amp;gt; 2). &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 110 (a number)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 (&#039;3*x^2 + 5*x + 17&#039; asPhysicExpression) valueWithX:5&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 117&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 (&#039;a*x^2 + b*x + c&#039; asPhysicExpression) derivate &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 2·a·x + b&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 (&#039;sin(a*x) + cos(b*x)&#039; asPhysicExpression) derivate &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; cos(a·x)·a - sin(b·x)·b&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Equation Solving ==&lt;br /&gt;
&lt;br /&gt;
The solver can solve simple equations (but do not expect it to be a replacement for Mathematica ;-):&lt;br /&gt;
&lt;br /&gt;
 equation := &#039;a = 5*b + c&#039; asPhysicExpression.&lt;br /&gt;
 equation solveFor:&#039;b&#039; &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; b = (a - c) / 5&amp;lt;/small&amp;gt;&lt;br /&gt;
(actually, it will give &amp;quot;b = (1/5)·(a - c)&amp;quot;, which is equivalent)&lt;br /&gt;
&lt;br /&gt;
For example, from the wellknown Formula &amp;quot;U = R * I&amp;quot;,&lt;br /&gt;
 equation := Physic::Parser parse:&#039;U = R * I&#039;.&lt;br /&gt;
we can derive:&lt;br /&gt;
 equation2 := equation solveFor:&#039;R&#039;.&lt;br /&gt;
and get &amp;quot;R = U/I&amp;quot;.&amp;lt;br&amp;gt;Of which the right side:&lt;br /&gt;
 formulaForR := equation2 rightSide &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; U/I&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Applying this formulaForR to concrete values:&lt;br /&gt;
 formulaForR valueIn:{ &#039;U&#039; -&amp;gt; 5 volt . &#039;I&#039; -&amp;gt; 20 milliAmpere }&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 250 Ω&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Providing additional Formulas ==&lt;br /&gt;
&lt;br /&gt;
The framework&#039;s knowledge database about units is defined by a set of formulas, from which result units are determined, when arithmetic operations are performed on physical values.&lt;br /&gt;
&lt;br /&gt;
This set of default formulas can be retrieved via &amp;quot;&amp;lt;code&amp;gt;PhysicalUnit formulaStrings&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Notice: we have included those formulas in the framework, so no internet access is required for these operations. Otherwise, operation in isolated networks (test labs) would be made impossible.&lt;br /&gt;
&lt;br /&gt;
You can add more knowledge by:&lt;br /&gt;
 Physic::PhysicalUnit &#039;&#039;&#039;addFormula:&#039;&#039;&#039; &#039;&#039;formulaString&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As a concrete example, the Momentum (which is Energy * Time) is predefined via:&lt;br /&gt;
 PhysicalUnit addFormula:&#039;Momentum = Energy * Time&#039;&lt;br /&gt;
the names in the formula must correspond to the unit names;&lt;br /&gt;
if new units are to be made well known, it must be defined via:&lt;br /&gt;
 Physic::PhysicalUnit addKnownUnit:aUnit&lt;br /&gt;
or&lt;br /&gt;
 Physic::PhysicalUnit addKnownUnit:aUnit as:nameInFormula&lt;br /&gt;
&lt;br /&gt;
== Nature Constants ==&lt;br /&gt;
&lt;br /&gt;
The following constants (see [https://en.wikipedia.org/wiki/International_System_of_Units#Definition]) are known to the parser and can be used in formula/equations. They can also be accessed by elementary code via the global variable &amp;quot;&amp;lt;code&amp;gt;Physic::NatureConstants&amp;lt;/code&amp;gt;&amp;quot; by index messages (i.e. &amp;quot;at:&#039;&#039;name&#039;&#039;&amp;quot; , &amp;quot;[&#039;&#039;name&#039;&#039;]&amp;quot; or simply name).&amp;lt;br&amp;gt;The values have been taken from public available data (such as Wikipedia). Some of them are measured or estimated values, which might have changed slightly by the time you read this (see below on how to update the facts database). &lt;br /&gt;
&lt;br /&gt;
==== Fundamental Constants ====&lt;br /&gt;
 BoltzmannConstant     &amp;lt;small&amp;gt;=&amp;gt; 1.380649e-23 J/K&amp;lt;/small&amp;gt;&lt;br /&gt;
 AvogadroConstant      &amp;lt;small&amp;gt;=&amp;gt; 02214076e+23 1/mol&amp;lt;/small&amp;gt;&lt;br /&gt;
 ElectronCharge        &amp;lt;small&amp;gt;=&amp;gt; -1.602176634e-19 C&amp;lt;/small&amp;gt;&lt;br /&gt;
 ElectronVolt          &amp;lt;small&amp;gt;=&amp;gt; 1.602176634e-19 J&amp;lt;/small&amp;gt;&lt;br /&gt;
 PlanckConstant        &amp;lt;small&amp;gt;=&amp;gt; 6.62607015e-34 Js&amp;lt;/small&amp;gt;&lt;br /&gt;
 PlanckTime            &amp;lt;small&amp;gt;=&amp;gt; 5.391247e-44 s&amp;lt;/small&amp;gt;&lt;br /&gt;
 PlanckMass            &amp;lt;small&amp;gt;=&amp;gt; 21.76434 µg&amp;lt;/small&amp;gt;&lt;br /&gt;
 PlanckLength          &amp;lt;small&amp;gt;=&amp;gt; 1.616255e-35 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 LightSpeed            &amp;lt;small&amp;gt;=&amp;gt; 299792.458 km/s&amp;lt;/small&amp;gt;&lt;br /&gt;
 SoundSpeed            &amp;lt;small&amp;gt;=&amp;gt; 343 m/s&amp;lt;/small&amp;gt;&lt;br /&gt;
 GravitationalConstant &amp;lt;small&amp;gt;=&amp;gt; 6.6743e-11 m³/(kg·s²)&amp;lt;/small&amp;gt;&lt;br /&gt;
 CoulombConstant       &amp;lt;small&amp;gt;=&amp;gt; 8987551782 kg·m³/(s²·C²)&amp;lt;/small&amp;gt;&lt;br /&gt;
 VacuumPermittivity    &amp;lt;small&amp;gt;=&amp;gt; 8.8541878188e-12 s⁴·A²/(m³·kg)&amp;lt;/small&amp;gt;&lt;br /&gt;
 VacuumPermeability    &amp;lt;small&amp;gt;=&amp;gt; 1.25663706212e-06 H/m&amp;lt;/small&amp;gt;&lt;br /&gt;
 MolarGasConstant      &amp;lt;small&amp;gt;=&amp;gt; 8.31446261815324 J/(mol·K)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or by their aliases:&lt;br /&gt;
 LightSpeed            c&lt;br /&gt;
 PlanckConstant        h , ℎ (#8462)&lt;br /&gt;
 ReducedPlanckConstant hbar, ℏ (#8463)&lt;br /&gt;
 GravitationalConstant G&lt;br /&gt;
 VacuumPermittivity    ε0 , epsilon_0&lt;br /&gt;
 VacuumPermeability    μ0 , mu_0&lt;br /&gt;
 ElectronCharge        e&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 Physic::NatureConstants at:&#039;GravitationalConstant&#039;&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 6.6743e-11 m³/(kg·s²)&amp;lt;/small&amp;gt;&lt;br /&gt;
 Physic::NatureConstants[&#039;GravitationalConstant&#039;]&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 6.6743e-11 m³/(kg·s²)&amp;lt;/small&amp;gt;&lt;br /&gt;
 Physic::NatureConstants GravitationalConstant&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 6.6743e-11 m³/(kg·s²)&amp;lt;/small&amp;gt;&lt;br /&gt;
 Physic::NatureConstants G&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 6.6743e-11 m³/(kg·s²)&amp;lt;/small&amp;gt;&lt;br /&gt;
or:&lt;br /&gt;
 Physic::NatureConstants at:&#039;LightSpeed&#039;&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 299792.458 km/s&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::NatureConstants ElectronCharge&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; -1.602176634e-19 C&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::NatureConstants e&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; -1.602176634e-19 C&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Elements ====  &lt;br /&gt;
 &lt;br /&gt;
 atom           =&amp;gt; database with facts about atoms&lt;br /&gt;
 atom[X],  for X in {&#039;H&#039;,&#039;He&#039;,&#039;Na&#039;,&#039;Li&#039;,&#039;C&#039;,&#039;N&#039;,&#039;O&#039;,&#039;Au&#039;,...}.&lt;br /&gt;
provides data for &#039;name&#039;, &#039;symbol&#039;, &#039;atomNr&#039;, &#039;atomWeight&#039;, &#039;meltingTemperature&#039;, &#039;boilingTemperature&#039;, &#039;protons&#039;, &#039;neutrons&#039;, &#039;density&#039;, etc.&amp;lt;br&amp;gt;For example:&lt;br /&gt;
 Physic::NatureConstants[&#039;atom&#039;]&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; dictionary indexed by atom symbol&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::NatureConstants[&#039;atom&#039;][&#039;H&#039;]&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; {&amp;quot;name&amp;quot;:&amp;quot;Hydrogen&amp;quot;,&amp;quot;symbol&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;atomNr&amp;quot;:1,&amp;quot;atomWeight&amp;quot;:...}&lt;br /&gt;
         dictionary of attributes of hydrogen&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::NatureConstants[&#039;atom&#039;][&#039;He&#039;][&#039;atomWeight&#039;]&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 4.002602 amu (atomWeight of helium)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::NatureConstants[&#039;atom&#039;][&#039;Li&#039;][&#039;density&#039;]&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 534.0 kg/m³ (density of lithium)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::NatureConstants[&#039;atom&#039;][&#039;Cu&#039;][&#039;specificResistance&#039;]&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 1.68e-08 Ω/m (specific electric resistency of copper)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
spoiler: access via messages is also possible:&lt;br /&gt;
 carbon := Physic::NatureConstants[&#039;atom&#039;][&#039;C&#039;].&lt;br /&gt;
 carbon atomWeight&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 12 amu&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::NatureConstants atom Cu specificResistance &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 1.68e-08 Ω/m (specific electric resistency of copper)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The builtin database is incomplete; you may want to fill in missing data in an initialization action, as described below. To see the information as present in your system, evaluate (in a workspace): &lt;br /&gt;
 &amp;lt;code&amp;gt;(Physic::NatureConstants[&#039;atom&#039;]) inspect&amp;lt;/code&amp;gt;.&lt;br /&gt;
and fill in values with:&lt;br /&gt;
 &amp;lt;code&amp;gt;Physic::NatureConstants[&#039;atom&#039;][&#039;Cu&#039;][&#039;soundSpeed&#039;] := 3570 meter / 1 seconds&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Astronomic Data ====  &lt;br /&gt;
 astronomicalObjects[X], for X in {&#039;earth&#039;, &#039;moon&#039;, &#039;sun&#039;, &#039;mercury&#039;, &#039;venus&#039;, &#039;mars&#039;, &#039;jupiter&#039;, &#039;saturn&#039;, &#039;neptune&#039;, &#039;uranus&#039;, &#039;pluto&#039; }&lt;br /&gt;
&#039;planets&#039; is an alias.&lt;br /&gt;
Both provide planetary data: mass, radiusMean, volume, aphelion, perihelion, escapeVelocity.&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;code&amp;gt;Physic::NatureConstants[&#039;planets&#039;][&#039;venus&#039;][&#039;mass&#039;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 Physic::NatureConstants[&#039;astronomicalObjects&#039;]&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; dictionary indexed by name&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::NatureConstants[&#039;astronomicalObjects&#039;][&#039;mars&#039;]&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; dictionary of attributes of mars&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Physic::NatureConstants[&#039;astronomicalObjects&#039;][&#039;venus&#039;][&#039;mass&#039;]&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; mass of venus&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
other useful constants are:&lt;br /&gt;
 DISTANCE_SUN_EARTH&lt;br /&gt;
 DISTANCE_EARTH_MOON&lt;br /&gt;
 AstronomicalUnit&lt;br /&gt;
 EarthGravity&lt;br /&gt;
 earth, moon, sun, mercury, venus, mars, jupiter, saturn, uranus, neptune, pluto&lt;br /&gt;
 mass[X], for X in planet-names&lt;br /&gt;
 volume[X], for X in planet-names&lt;br /&gt;
 radius[X], for X in planet-names&lt;br /&gt;
&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;earth&#039;][&#039;mass&#039;]&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;earth&#039;][&#039;massWater&#039;]&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;earth&#039;][&#039;massAtmosphere&#039;]&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;earth&#039;][&#039;surface&#039;]&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;earth&#039;][&#039;surfaceLand&#039;]&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;earth&#039;][&#039;surfaceWater&#039;]&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;sun&#039;][&#039;mass&#039;] &amp;lt;small&amp;gt;=&amp;gt; 1.9885e+30 kg&amp;lt;/small&amp;gt;&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;sun&#039;][&#039;volume&#039;] &amp;lt;small&amp;gt;=&amp;gt; 1.41e+18 km³&amp;lt;/small&amp;gt;&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;earth&#039;][&#039;mass&#039;] &amp;lt;small&amp;gt;=&amp;gt; 108.321 km³&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filling the Facts Database ====&lt;br /&gt;
The database as deployed obviously cannot provide any possible useful value for your particular application. The current set is provided for examples and only contains knowledge which is often used in physics, some chemistry and mechanical applications.&lt;br /&gt;
&lt;br /&gt;
If you expect more builtin data, please let us know.&lt;br /&gt;
If you find inexact values or wrong values due to typing errors, or if new scientific research data is available, also.&lt;br /&gt;
&lt;br /&gt;
In any case, you can fill or fix the database yourself with both missing, inexact or wrong values:&lt;br /&gt;
 Physic::NatureConstants constants[&#039;&#039;name&#039;&#039;] := &#039;&#039;newValue&#039;&#039;&lt;br /&gt;
or (the equivalent):&lt;br /&gt;
 Physic::NatureConstants constants at:&#039;&#039;name&#039;&#039; put:&#039;&#039;newValue&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For example, to add data for an atom, you could write:&lt;br /&gt;
 goldInfo := Physic::NatureConstants[&#039;atom&#039;][&#039;AU&#039;].&lt;br /&gt;
 goldInfo[&#039;meltingTemperature&#039;] := 1337.33 kelvin.&lt;br /&gt;
&lt;br /&gt;
You can also add completely new domain specific data. For example, if your machines process wood and the densities are required in your drilling setup, you may want to execute: &lt;br /&gt;
 woodData := Dictionary forCaseInsensitiveKeys.&lt;br /&gt;
 woodData[&#039;walnut&#039;]   := { density: 650 kiloGram / 1 cubicMeter }.&lt;br /&gt;
 woodData[&#039;mahogany&#039;] := { density: 600 kiloGram / 1 cubicMeter }.&lt;br /&gt;
 woodData[&#039;maple&#039;]    := { density: 700 kiloGram / 1 cubicMeter }.&lt;br /&gt;
 woodData[&#039;oak&#039;]      := { density: 770 kiloGram / 1 cubicMeter }.&lt;br /&gt;
 woodData[&#039;rosewood&#039;] := { density: 840 kiloGram / 1 cubicMeter }.&lt;br /&gt;
 woodData[&#039;cherry&#039;]   := { density: 7400 kiloGram / 1 cubicMeter }.&lt;br /&gt;
 woodData[&#039;balsa&#039;]    := { density: 120 kiloGram / 1 cubicMeter }.&lt;br /&gt;
 Physic::NatureConstants[&#039;wood&#039;] := woodData.&lt;br /&gt;
then use in your code:&lt;br /&gt;
 Physic::NatureConstants[&#039;wood&#039;][&#039;çherry&#039;][&#039;density&#039;]&lt;br /&gt;
&lt;br /&gt;
Notice that these numbers are just examples; the actual densities vary much and also depend on dryness and other factors.&lt;br /&gt;
&lt;br /&gt;
==== Examples Involving Constants ====&lt;br /&gt;
In Smalltalk (accessing the constants directly):&lt;br /&gt;
 Physic::NatureConstants[&#039;speed&#039;][&#039;sound&#039;]&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;venus&#039;]&lt;br /&gt;
 Physic::NatureConstants[&#039;planets&#039;][&#039;mars&#039;][&#039;mass&#039;]&lt;br /&gt;
 &lt;br /&gt;
 1.0 kiloGram * (Physic::NatureConstants[&#039;LightSpeed&#039;]) squared&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 89875.51 TJ&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In JavaScript:&lt;br /&gt;
 Physic::NatureConstants[&#039;speed&#039;][&#039;sound&#039;]&lt;br /&gt;
&lt;br /&gt;
In Smalltalk (using the Math language parser):&lt;br /&gt;
 Physic::Parser evaluate:&#039;1 kg * LightSpeedˆ2&#039;.&lt;br /&gt;
 Physic::Parser evaluate:&#039;1 kg * LightSpeed²&#039;&lt;br /&gt;
 Physic::Parser evaluate:&#039;mass[sun] * mass[earth] / earth[perihelion]ˆ2&#039;.&lt;br /&gt;
&lt;br /&gt;
In Math language:&lt;br /&gt;
 1 kg * LightSpeedˆ2&lt;br /&gt;
 GraviationalConstant * mass[sun] * mass[earth] / earth[perihelion]²&lt;br /&gt;
&lt;br /&gt;
== Measured Physical Values ==&lt;br /&gt;
You can combine physical values and measurement values to keep track of errors in computations.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;br&amp;gt;Assuming, that your cheap 10% accurate voltmeter measured 10 volts, this could be written as:&lt;br /&gt;
 u := (10 volt ±% 10).&lt;br /&gt;
and if that voltage was measured across a cheap 100 ohm resistor with 5% precision,&lt;br /&gt;
 r := (100.0 ohm ±% 5). &lt;br /&gt;
the current will be:&lt;br /&gt;
 i := u / r.&lt;br /&gt;
which is:&lt;br /&gt;
 (MeasurementValue value:100.0 minValue:85.7 maxValue:115.8) mA&lt;br /&gt;
and its min/max/expected values can be extracted with:&lt;br /&gt;
 i minValue  &amp;lt;small&amp;gt;=&amp;gt; 84.7 mA&amp;lt;/small&amp;gt;&lt;br /&gt;
 i maxValue  &amp;lt;small&amp;gt;=&amp;gt; 115.8 mA&amp;lt;/small&amp;gt;&lt;br /&gt;
 i expectedValue &amp;lt;small&amp;gt;=&amp;gt; 100 mA&amp;lt;/small&amp;gt;&lt;br /&gt;
 i relativeError &amp;lt;small&amp;gt;=&amp;gt; 0.15&amp;lt;/small&amp;gt;&lt;br /&gt;
or nicer:&lt;br /&gt;
 i minValue asMilliAmperes roundedToScale:2  &amp;lt;small&amp;gt;=&amp;gt; 84.71 mA&amp;lt;/small&amp;gt;&lt;br /&gt;
 i maxValue asMilliAmperes roundedToScale:2  &amp;lt;small&amp;gt;=&amp;gt; 115.79 mA&amp;lt;/small&amp;gt;&lt;br /&gt;
 i expectedValue asMilliAmperes roundedToScale:2 &amp;lt;small&amp;gt;=&amp;gt; 100 mA&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice: currently, you cannot take the plain minValue/maxValue and round them, as these are kept in baseUnits internally, which would round to 1/100 ampere instead of 1/100 milliampere. Therefore, the values are first forced into milliAmperes so that the rounding is what we want.&lt;br /&gt;
&lt;br /&gt;
== Physical Values and Numeric Precision ==&lt;br /&gt;
Physical values will use the underlying number type when computing new values. For example,&lt;br /&gt;
 10 volt / 3 ampere &amp;lt;small&amp;gt;=&amp;gt; (10/3) ohm&amp;lt;/small&amp;gt;&lt;br /&gt;
generates a fractional Ohm value *whis is exact), whereas:&lt;br /&gt;
 10.0 volt / 3 ampere &amp;lt;small&amp;gt;=&amp;gt; 3.33333 ohm&amp;lt;/small&amp;gt;&lt;br /&gt;
returns a float value (which is an approximation).&lt;br /&gt;
&lt;br /&gt;
It is usually a good idea to start with float values, and scale to the desired precision output when printing. Typically floats are used in the engineering domains, where measurements with error tolerances are involved. If your measurement and components have an error in the percent range, there is no need to compute exact or with a precision in the 10e-50 range.&lt;br /&gt;
&lt;br /&gt;
Please refer to the &amp;quot;[[Numeric_Limits/en|Numeric Limits]]&amp;quot; document for more details on number types.&lt;br /&gt;
&lt;br /&gt;
== Printing Physical Values ==&lt;br /&gt;
The printing of the amount depends on the underlying number representation.&lt;br /&gt;
As shown previously, this can be a Fraction, a Float, an Integer or any other number subtype, depending on the values from which it was computed/constructed.&lt;br /&gt;
&lt;br /&gt;
For convenient printing, fractions are usually not wanted; you can either convert the amount to a scaledDecimal when creating the value, &lt;br /&gt;
or convert the value afterwards.&lt;br /&gt;
ScaledDecimals print the value rounded to a given number of digits, but use the full internal precision for computations.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 (1/3) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;(1/3)&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 (1/3) asFloat printString &amp;lt;small&amp;gt;=&amp;gt; &#039;0.333333333333333&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 ((1/3) asScaledDecimal:2) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;0.33&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 ((1/3) asFixedDecimal:2) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;0.33&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 (2/3) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;(2/3)&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 (2/3) asFloat printString &amp;lt;small&amp;gt;=&amp;gt; &#039;0.666666666666667&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 ((2/3) asScaledDecimal:2) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;0.67&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 ((2/3) asFixedDecimal:2) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;0.67&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However:&lt;br /&gt;
 ((1/3) + (1/3)) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;(2/3)&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 ((1/3) asFloat + (1/3) asFloat) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;0.666666666666667&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 ( ((1/3) asScaledDecimal:2) + ((1/3) asScaledDecimal:2)) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;0.67&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 ( ((1/3) asFixedDecimal:2) + ((1/3) asFixedDecimal:2)) printString &amp;lt;small&amp;gt;=&amp;gt; &#039;0.66&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice the difference between scaledDecimals (which compute exact values),&lt;br /&gt;
and fixedDecimals (which compute with the printed values).&lt;br /&gt;
Only use fixedDecimals for monetary tables, where the sums of the printed numbers should sum up correctly.&lt;br /&gt;
&lt;br /&gt;
So, to print a length value of 15mm, the following can be used:&lt;br /&gt;
 15 milliMeter               &amp;lt;small&amp;gt;=&amp;gt; 15 mm&amp;lt;/small&amp;gt;&lt;br /&gt;
 15 milliMeter as:&#039;Meter&#039;    &amp;lt;small&amp;gt;=&amp;gt; (3/200) m&amp;lt;/small&amp;gt;&lt;br /&gt;
 15 milliMeter as:&#039;m&#039;        &amp;lt;small&amp;gt;=&amp;gt; (3/200) m&amp;lt;/small&amp;gt;&lt;br /&gt;
 15.0 milliMeter as:&#039;m&#039;      &amp;lt;small&amp;gt;=&amp;gt; 0.015 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 15.0 milliMeter as:&#039;cm&#039;     &amp;lt;small&amp;gt;=&amp;gt; 1.5 cm&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 (15 milliMeter as:&#039;m&#039;) asScaledDecimal:1    &amp;lt;small&amp;gt;=&amp;gt; 0.0 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 (15 milliMeter as:&#039;m&#039;) asScaledDecimal:2    &amp;lt;small&amp;gt;=&amp;gt; 0.02 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 (15 milliMeter as:&#039;m&#039;) asScaledDecimal:3    &amp;lt;small&amp;gt;=&amp;gt; 0.015 m&amp;lt;/small&amp;gt;&lt;br /&gt;
 (15 milliMeter as:&#039;m&#039;) asScaledDecimal:4    &amp;lt;small&amp;gt;=&amp;gt; 0.0150 m&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 (15 milliMeter as:&#039;cm&#039;) asScaledDecimal:1    &amp;lt;small&amp;gt;=&amp;gt; 1.5 cm&amp;lt;/small&amp;gt;&lt;br /&gt;
 (15 milliMeter as:&#039;cm&#039;) asScaledDecimal:2    &amp;lt;small&amp;gt;=&amp;gt; 1.50 cm&amp;lt;/small&amp;gt;&lt;br /&gt;
 (15 milliMeter as:&#039;cm&#039;) asScaledDecimal:3    &amp;lt;small&amp;gt;=&amp;gt; 1.500 cm&amp;lt;/small&amp;gt;&lt;br /&gt;
 (15 milliMeter as:&#039;cm&#039;) asScaledDecimal:4    &amp;lt;small&amp;gt;=&amp;gt; 1.5000 cm&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 (15 milliMeter as:&#039;in&#039;) asScaledDecimal:1    &amp;lt;small&amp;gt;=&amp;gt; 0.6 in&amp;lt;/small&amp;gt;&lt;br /&gt;
 (15 milliMeter as:&#039;in&#039;) asScaledDecimal:2    &amp;lt;small&amp;gt;=&amp;gt; 0.59 in&amp;lt;/small&amp;gt;&lt;br /&gt;
 (15 milliMeter as:&#039;in&#039;) asScaledDecimal:3    &amp;lt;small&amp;gt;=&amp;gt; 0.591 in&amp;lt;/small&amp;gt;&lt;br /&gt;
 (15 milliMeter as:&#039;in&#039;) asScaledDecimal:4    &amp;lt;small&amp;gt;=&amp;gt; 0.5906 in&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Physical Values in Activity Diagrams ==&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the arithmetic actions in the standard library were defined with pin types being &amp;quot;&amp;lt;CODE&amp;gt;Number&amp;lt;/CODE&amp;gt;&amp;quot;, instead of the more general &amp;quot;&amp;lt;CODE&amp;gt;ArithmeticValue&amp;lt;/CODE&amp;gt;&amp;quot; (of which PhysicalValues inherit). Thus, they will not accept physical values if type checking is enabled on the pin values (although the underlying primitive code would handle those types).&lt;br /&gt;
&lt;br /&gt;
We therefore provide a separate PhysicalValues library, with redefined arithmetic actions. Please use those when dealing with physical values (instead of &amp;quot;forcing&amp;quot; types or disabling type checks).&amp;lt;br&amp;gt;Late note: these actions are now found in the standard library under the &amp;quot;Arithmetic/More Arithmetic&amp;quot; category.&lt;br /&gt;
&lt;br /&gt;
Freeze values can be given either using the above listed instance creation messages on number (e.g. &amp;quot;&amp;lt;CODE&amp;gt;10 meters&amp;lt;/CODE&amp;gt;&amp;quot; or &amp;quot;&amp;lt;CODE&amp;gt;1 kilo joule&amp;lt;/CODE&amp;gt;&amp;quot;) or by using a unit suffix, possibly with an appreviated SI prefix, as in &amp;quot;&amp;lt;CODE&amp;gt;10 kV&amp;lt;/CODE&amp;gt;&amp;quot; or &amp;quot;&amp;lt;CODE&amp;gt;10 mA&amp;lt;/CODE&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Physical Values as Freeze Value ==&lt;br /&gt;
Pins of type &amp;quot;PhysicalValue&amp;quot; accept numeric values followed by a unit symbol, such as &amp;quot;&amp;lt;code&amp;gt;1 kg&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;1 fl oz&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;10 N&amp;lt;/code&amp;gt;&amp;quot;  or &amp;quot;&amp;lt;code&amp;gt;10 newton&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Physical Values in Elementary Code ==&lt;br /&gt;
&lt;br /&gt;
See examples below.&lt;br /&gt;
&lt;br /&gt;
== Math Language Workspace ==&lt;br /&gt;
You can switch the workspace (Notepad) window to accept math language syntax (instead of Smalltalk or JavaScript).&lt;br /&gt;
&lt;br /&gt;
For this, open a Notepad via &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Notepad&#039;&amp;quot;, and choose &amp;quot;&#039;&#039;Math/Physic&#039;&#039;&amp;quot; in its &amp;quot;&#039;&#039;Workspace&#039;&#039;&amp;quot; menu&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can now enter math language expressions, such as:&lt;br /&gt;
 x := 5&lt;br /&gt;
 sin(xˆ2 + 3)&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 0.270905788307869&amp;lt;/small&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
 deriv ( sin(xˆ2 + 5x), x )&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; (2·x + 5)·cos(x² + 5·x)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and evaluate them (select the text, possibly multiple lines) and click on the &amp;quot;PrintIt&amp;quot; icon or select &amp;quot;PrintIt&amp;quot; from the right-button menu. The result of the evaluation will be pasted and selected into the window, so by pressing &amp;lt;kbd&amp;gt;Delete&amp;lt;/kbd&amp;gt; or &amp;lt;kbd&amp;gt;Backspace&amp;lt;/kbd&amp;gt; or &amp;lt;kbd&amp;gt;CTRL-x&amp;lt;/kbd&amp;gt;, it can be removed quickly.&lt;br /&gt;
&lt;br /&gt;
1) Make sure that &amp;quot;&#039;&#039;Autodefine as Workspace Variable&#039;&#039;&amp;quot; is checked in the workspace&#039;s &amp;quot;&#039;&#039;Workspace&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Autodefine Variables&#039;&#039;&amp;quot; menu.&amp;lt;br&amp;gt;Otherwise assigned variables such as &amp;quot;x&amp;quot; above will only be known within one doIt.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following code snippets are plain Smalltalk code + the printed representation (as for example found in a report).&amp;lt;br&amp;gt;For JavaScript, write &amp;quot;n.X()&amp;quot; instead of &amp;quot;n X&amp;quot;&amp;lt;br&amp;gt;(eg. &amp;quot;&amp;lt;code&amp;gt;1.kiloGram() + 10.0.gram()&amp;lt;/code&amp;gt;&amp;quot; instead of &amp;quot;&amp;lt;code&amp;gt;1 kiloGram + 10.0 gram&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
The following shows the printed output of typical Smalltalk expressions.&lt;br /&gt;
Notice again, that by default, the units present themself as metric SI units (eg. &amp;quot;1 meter&amp;quot; will print as meters).&lt;br /&gt;
To force them to print as imperial or us units, use the &amp;quot;asXXX&amp;quot; message (eg. &amp;quot;1 meter asFeet&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Length Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | (1/4) inches || =&amp;gt; || 6.35 mm&lt;br /&gt;
|-&lt;br /&gt;
|(1/4) inches asInches|| =&amp;gt; || 0.25 in&lt;br /&gt;
|-&lt;br /&gt;
|10 milliMeter || =&amp;gt; || 10 mm&lt;br /&gt;
|-&lt;br /&gt;
|10 milliMeter asInches || =&amp;gt; || 0.3937 in&lt;br /&gt;
|-&lt;br /&gt;
|10 milliMeter as:&#039;in&#039; || =&amp;gt; || 0.3937 in&lt;br /&gt;
|-&lt;br /&gt;
|10 milliMeter as:&#039;ft&#039; || =&amp;gt; || 0.032808 ft&lt;br /&gt;
|-&lt;br /&gt;
|10 milli meter asInches || =&amp;gt; || 0.3937 in&lt;br /&gt;
|-&lt;br /&gt;
|10 feet || =&amp;gt; || 3.048 m&lt;br /&gt;
|-&lt;br /&gt;
|1.8 meter asFeet || =&amp;gt; || 5.905 ft&lt;br /&gt;
|-&lt;br /&gt;
|10 miles || =&amp;gt; || 16.09 km&lt;br /&gt;
|-&lt;br /&gt;
|10 nauticalMiles || =&amp;gt; || 18.52 km&lt;br /&gt;
|-&lt;br /&gt;
|1 parsec || =&amp;gt; || 3.261563777 ly&lt;br /&gt;
|-&lt;br /&gt;
|10 kiloMeters asMeters || =&amp;gt; || 10000 m&lt;br /&gt;
|-&lt;br /&gt;
|1 astronomicalUnits asMiles rounded || =&amp;gt; || 92955807 mi&lt;br /&gt;
|-&lt;br /&gt;
|1 lightYears asAstronomicalUnits rounded || =&amp;gt; || 63241 au&lt;br /&gt;
|-&lt;br /&gt;
|1000 lightYears as:(Physic::Length parsec) || =&amp;gt; || 306.6014 pc&lt;br /&gt;
|-&lt;br /&gt;
|1 micro inch || =&amp;gt; || 25.4 nm&lt;br /&gt;
|-&lt;br /&gt;
|1.80 meter asFeetAndInches || =&amp;gt; || 5′10.866&lt;br /&gt;
|-&lt;br /&gt;
|1 yards || =&amp;gt; || 0.9144 m&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 70%&amp;quot; |  e&#039;He is {(5 foot+2 inches) asFeetAndInchesRounded}...&#039; &amp;lt;sup&amp;gt;(1)&amp;lt;/sup&amp;gt;|| =&amp;gt; || &#039;He is 5′2″...&#039;&lt;br /&gt;
|-&lt;br /&gt;
|e&#039;He is {(5 foot+2 inches)}...&#039; || =&amp;gt; || &#039;He is 1.5748 m...&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10 centi meter|| =&amp;gt; || 0.1 m &amp;lt;small&amp;gt;(prints as m)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|10 centiMeter|| =&amp;gt; || 0.1 m &amp;lt;small&amp;gt;(prints as m)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Physic::PhysicalUnit centimeter unitAmount:10|| =&amp;gt; || 10 cm &amp;lt;small&amp;gt;(prints as cm)&amp;lt;/small&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;The e&#039;...&#039; is a Smalltalk string with embedded expressions.&lt;br /&gt;
&lt;br /&gt;
==== Velocity Examples ====&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 100 miles / 1 hours || =&amp;gt; || 44.704 m/s&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | (100 miles / 1 hours) as:&#039;mph&#039; || =&amp;gt; || 100 mph&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 100 kiloMeterPerHour as:&#039;mph&#039; || =&amp;gt; || 62.137119 mph&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 100 milesPerHour asKiloMetersPerHour || =&amp;gt; || 160.9344 km/h&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 1 milliMeter / 1 days || =&amp;gt; || 11.574 nm/s&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 70%&amp;quot; |  (186282 miles+698 yard+2 feet+5 inches+(21 / 127) inches) / 1 seconds|| =&amp;gt; || 299792.458 km/s&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Mass Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 70%&amp;quot; | 1 kiloGram + 10.0 gram || =&amp;gt; || 1.01 kg&lt;br /&gt;
|-&lt;br /&gt;
|(1 kiloGram + 10 gram) asGrams || =&amp;gt; || 1010 g&lt;br /&gt;
|-&lt;br /&gt;
|10 gram || =&amp;gt; || 10 g&lt;br /&gt;
|-&lt;br /&gt;
|10 gram asKiloGrams || =&amp;gt; || (1/100) kg&lt;br /&gt;
|-&lt;br /&gt;
|10.0 gram asKiloGrams || =&amp;gt; || 0.01 kg&lt;br /&gt;
|-&lt;br /&gt;
|10 gram asMilliGrams || =&amp;gt; || 10000 mg&lt;br /&gt;
|-&lt;br /&gt;
|1 microGram || =&amp;gt; || 1 µg&lt;br /&gt;
|-&lt;br /&gt;
|1 micro gram || =&amp;gt; || 1 µg&lt;br /&gt;
|-&lt;br /&gt;
|10000 gram || =&amp;gt; || 10 kg&lt;br /&gt;
|-&lt;br /&gt;
|1 pound || =&amp;gt; || 453.59237 g&lt;br /&gt;
|-&lt;br /&gt;
|1 pound asKiloGrams || =&amp;gt; || 0.45359237 kg&lt;br /&gt;
|-&lt;br /&gt;
|1 pound asPounds || =&amp;gt; || 1.0 lb&lt;br /&gt;
|-&lt;br /&gt;
|1 kiloGram asPounds || =&amp;gt; || 2.20462262184878 lb&lt;br /&gt;
|-&lt;br /&gt;
|1 atomicMassUnits asKiloGrams || =&amp;gt; || 1.66053906892e-27 kg&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Temperature Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 0 degreesCelsius || =&amp;gt; || 273.16 K&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 0 degreesCelsius asFahrenheit || =&amp;gt; || 32.018 °F&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 40 degreesFahrenheit || =&amp;gt; || 277.59 K&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 60 degreesFahrenheit asCelsius || =&amp;gt; || 15.556 °C&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 40 degreesFahrenheit asKelvin || =&amp;gt; || 277.59 K&lt;br /&gt;
|-&lt;br /&gt;
|10 kelvin || =&amp;gt; || 10 K&lt;br /&gt;
|-&lt;br /&gt;
|100 rankine || =&amp;gt; || 55.556 K&lt;br /&gt;
|-&lt;br /&gt;
|100 rankine asRankine || =&amp;gt; || 100.0 °R&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Energy Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 1 joule asElectronVolts || =&amp;gt; || 6.24150912550149E+18 eV&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 1 joule asCalories || =&amp;gt; || 0.239005736137667 cal&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 1 joule asBTUs || =&amp;gt; || 0.000947817 BTU&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 1.0 joule asKiloWattHours || =&amp;gt; || 2.77777777777778E-07 kWh&lt;br /&gt;
|-&lt;br /&gt;
|10 electronVolts || =&amp;gt; || 1.6021766208E-18 J&lt;br /&gt;
|-&lt;br /&gt;
|1 mega electronVolts asJoules || =&amp;gt; || 1.602176634E-13 J&lt;br /&gt;
|-&lt;br /&gt;
|1000 joule asKiloWattHours || =&amp;gt; || 0.000278 kWh&lt;br /&gt;
|-&lt;br /&gt;
|1000.0 kiloJoule asKiloWattHours || =&amp;gt; || 0.2778 kWh&lt;br /&gt;
|-&lt;br /&gt;
|c := Physic::NatureConstants lightspeed || =&amp;gt; || 299792.458 km/s&lt;br /&gt;
|-&lt;br /&gt;
|1 kg * c squared|| =&amp;gt; || 89875.518 TJ (E = mc²)&lt;br /&gt;
|-&lt;br /&gt;
|(1.0 kg * c squared) asGigaWattHours|| =&amp;gt; || 24965.42 GWh (get me some antimatter)&lt;br /&gt;
|-&lt;br /&gt;
|1 electronVolts|| =&amp;gt; || 1.602176634e-19 J (see [https://en.wikipedia.org/wiki/Electronvolt wikipedia])&lt;br /&gt;
|-&lt;br /&gt;
|1 electronVolts / Physic::NatureConstants c squared|| =&amp;gt; || 1.7826619216279e-36 kg (mass)&lt;br /&gt;
|-&lt;br /&gt;
|1 electronVolts / Physic::NatureConstants c|| =&amp;gt; || 5.34428599267831e-28 kg·m/s (momentum)&lt;br /&gt;
|-&lt;br /&gt;
|1 electronVolts / Physic::NatureConstants boltzmannConstant|| =&amp;gt; || 11604.5181215501 K (temperature)&lt;br /&gt;
|-&lt;br /&gt;
|Physic::NatureConstants hbar / 1 electronVolts || =&amp;gt; || 6.58211956950907e-16 s (time)&lt;br /&gt;
|-&lt;br /&gt;
|Physic::NatureConstants hbar * Physic::NatureConstants c / 1 electronVolts|| =&amp;gt; || 197.326980459302 nm (distance)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Power Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot;|1 kilo watt||=&amp;gt;||1000 W&lt;br /&gt;
|-&lt;br /&gt;
|1 imperial hp||=&amp;gt;||745.699871 W&lt;br /&gt;
|-&lt;br /&gt;
|1 metric hp||=&amp;gt;||735.49875 W&lt;br /&gt;
|-&lt;br /&gt;
|5 volt * 10 ampere||=&amp;gt;||50 W&lt;br /&gt;
|-&lt;br /&gt;
|1 mega watt||=&amp;gt;||1000 kW&lt;br /&gt;
|-&lt;br /&gt;
|70 giga watt * 10 hours||=&amp;gt;||2520 TJ&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Electricity Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot;|1 coulomb asAmpereHours||=&amp;gt;||0.000277 Ah&lt;br /&gt;
|-&lt;br /&gt;
|1.1 volt / 10 kilo ohm||=&amp;gt;||110.0 µA&lt;br /&gt;
|-&lt;br /&gt;
|100 micro farad * 10.0 volt||=&amp;gt;||0.001 C&lt;br /&gt;
|-&lt;br /&gt;
|100 ohm * 0.1 micro farad||=&amp;gt;||10.0 µs&lt;br /&gt;
|-&lt;br /&gt;
|20 milli ampere * 10 seconds||=&amp;gt;||(1/5) C&lt;br /&gt;
|-&lt;br /&gt;
|20.0 milli ampere * 10 seconds||=&amp;gt;||0.2 C&lt;br /&gt;
|-&lt;br /&gt;
|(Physic::Voltage dBu unitAmount:4) asVolts||=&amp;gt;||1.2277 V &lt;br /&gt;
|-&lt;br /&gt;
|&#039;1 / (2π × √(1 farad × 1 henry))&#039; asPhysicExpression value||=&amp;gt;||0.1591 Hz (from formula)&lt;br /&gt;
|-&lt;br /&gt;
|1 / (2 * Float pi * (1 farad * 1 henry) sqrt)||=&amp;gt;||0.1591 Hz (as Smalltalk code)&lt;br /&gt;
|-&lt;br /&gt;
|1 / (1 microFarad * 2 kiloOhm)||=&amp;gt;||500 Hz   &lt;br /&gt;
|-&lt;br /&gt;
|100 ohm &amp;amp;#124; 50.0 ohm||=&amp;gt;||33.33 Ω (two resistors in parallel)  &lt;br /&gt;
|-&lt;br /&gt;
|Physic::ElectricResistance&#039; colorCode:#(yellow violet red)||=&amp;gt;||4700 Ω  &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Volume Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 1000 liter || =&amp;gt; || 1 m³&lt;br /&gt;
|-&lt;br /&gt;
|1000 liter asLiters || =&amp;gt; || 1000 l&lt;br /&gt;
|-&lt;br /&gt;
|1000 liter asHectoLiters || =&amp;gt; || 10 hl&lt;br /&gt;
|-&lt;br /&gt;
|1000 liter asCubicInches || =&amp;gt; || 61023.744095 cuin&lt;br /&gt;
|-&lt;br /&gt;
|100.0 liter asCubicInches || =&amp;gt; || 6102.3744095 cuin&lt;br /&gt;
|-&lt;br /&gt;
|100.0 deci liter asCubicInches || =&amp;gt; || 610.23744095 cuin&lt;br /&gt;
|-&lt;br /&gt;
|1 liter asCubicInches || =&amp;gt; || 61.023744095 cuin&lt;br /&gt;
|-&lt;br /&gt;
|1 deci liter asCubicInches || =&amp;gt; || 6.1023744095 cuin&lt;br /&gt;
|-&lt;br /&gt;
|1 milli liter asCubicInches || =&amp;gt; || 0.061023744095 cuin&lt;br /&gt;
|-&lt;br /&gt;
|1 flozGB || =&amp;gt; || 28.4130625 ml&lt;br /&gt;
|-&lt;br /&gt;
|1 flozUS || =&amp;gt; || 29.5735296 ml&lt;br /&gt;
|-&lt;br /&gt;
|1 flozGB asFlozUS || =&amp;gt; || 0.960759940 US fl oz&lt;br /&gt;
|-&lt;br /&gt;
|1 flozUS asFlozGB || =&amp;gt; || 1.040842731 imp fl oz&lt;br /&gt;
|-&lt;br /&gt;
|1 flozGB asScaledDecimal:2|| =&amp;gt; || 28.41 ml&lt;br /&gt;
|-&lt;br /&gt;
|1 inch cubed || =&amp;gt; || 16.387064 ml&lt;br /&gt;
|-&lt;br /&gt;
|1 inch cubed asLiters || =&amp;gt; || 0.016387064 l&lt;br /&gt;
|-&lt;br /&gt;
|1 inch cubed asCubicInches || =&amp;gt; || 1.0 cuin&lt;br /&gt;
|-&lt;br /&gt;
|1 inch cubed asCubicInches unitString || =&amp;gt; || &#039;cuin&#039;&lt;br /&gt;
|-&lt;br /&gt;
|1 inch cubed asCubicInches unitAmount || =&amp;gt; || 1.0&lt;br /&gt;
|-&lt;br /&gt;
|1 inch cubed asCubicInches unitStringSI || =&amp;gt; || &#039;m³&#039;&lt;br /&gt;
|-&lt;br /&gt;
|1 inch cubed asCubicInches amount || =&amp;gt; || 1.6387064E-05&lt;br /&gt;
|-&lt;br /&gt;
|Volume barrels unitAmount:1 || =&amp;gt; || 1 bbl.&lt;br /&gt;
|-&lt;br /&gt;
|(Volume barrels unitAmount:1) asGallonsUS|| =&amp;gt; ||42.0 US gal&lt;br /&gt;
|-&lt;br /&gt;
|(Volume barrels unitAmount:1) asLiters||=&amp;gt;||158.987295 l&lt;br /&gt;
|-&lt;br /&gt;
|Volume barrelsIMP unitAmount:1 || =&amp;gt; || 1 bbl. Imp&lt;br /&gt;
|-&lt;br /&gt;
|(Volume barrelsIMP unitAmount:1) asLiters||=&amp;gt;||159.1131599 l&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Angle Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 10 degrees|| =&amp;gt; || 0.174533 rad&lt;br /&gt;
|-&lt;br /&gt;
|0.2 radians || =&amp;gt; || 0.2 rad&lt;br /&gt;
|-&lt;br /&gt;
|180 degrees || =&amp;gt; || 3.14159265358979 rad&lt;br /&gt;
|-&lt;br /&gt;
|180 degrees asDegrees || =&amp;gt; || 180.0 °&lt;br /&gt;
|-&lt;br /&gt;
|180 degrees asDegrees asRadians || =&amp;gt; || 3.14159265358979 rad&lt;br /&gt;
|-&lt;br /&gt;
|90 degrees asGon || =&amp;gt; || 100 gon&lt;br /&gt;
|-&lt;br /&gt;
|gonUnit := (Physic::PhysicalUnit angle gon)  || =&amp;gt; || Gon (the unit, not a value)&lt;br /&gt;
|-&lt;br /&gt;
|gonUnit unitAmount:100 || =&amp;gt; || 100 gon&lt;br /&gt;
|-&lt;br /&gt;
|(gonUnit unitAmount:100) asDegrees || =&amp;gt; || 90 °&lt;br /&gt;
|-&lt;br /&gt;
|(270 degrees + 91 degrees) = 361 degrees || =&amp;gt; || true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Force Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 10 newton|| =&amp;gt; || 10 N&lt;br /&gt;
|-&lt;br /&gt;
|1 newton asGramForce  || =&amp;gt; || 101.97 gf&lt;br /&gt;
|-&lt;br /&gt;
|(Physic::Force gramForce unitAmount:50) || =&amp;gt; || 50 gf&lt;br /&gt;
|-&lt;br /&gt;
|(Physic::Force gramForce unitAmount:50) asNewton || =&amp;gt; || 0.4903325 N&lt;br /&gt;
|-&lt;br /&gt;
|(Physic::Force gramForce unitAmount:50) as:&#039;N&#039;|| =&amp;gt; || 0.4903325 N&lt;br /&gt;
|-&lt;br /&gt;
|(Physic::Force dyne kiloUnit unitAmount:1) as:&#039;N&#039;|| =&amp;gt; || 0.01 N&lt;br /&gt;
|-&lt;br /&gt;
|(Physic::Force kilo dyne unitAmount:1) as:&#039;N&#039;|| =&amp;gt; || 0.01 N&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Pressure Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 1 kilo pascal|| =&amp;gt; || 1000 Pa&lt;br /&gt;
|-&lt;br /&gt;
|1.5 kilo pascal asTorr || =&amp;gt; || 11.25 Torr&lt;br /&gt;
|-&lt;br /&gt;
|(Physic::Pressure torr unitAmount:11.5) asPascal|| =&amp;gt; || 1533.207 Pa&lt;br /&gt;
|-&lt;br /&gt;
|(Physic::Pressure torr unitAmount:11.5) as:&#039;Pa&#039;|| =&amp;gt; || 1533.207 Pa&lt;br /&gt;
|-&lt;br /&gt;
|((Physic::PhysicalUnit unitWithUnitString:&#039;lbf/in²&#039;) unitAmount: 0.01933678) as:&#039;Pa&#039; || =&amp;gt; || 133.322404931392 Pa&lt;br /&gt;
|-&lt;br /&gt;
|((Physic::PhysicalUnit unitWithUnitString:&#039;lbf/in²&#039;) unitAmount: 0.01933678) as:&#039;mmHg&#039; || =&amp;gt; || 1.00000013138373 mmHg&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Bytes Examples: ====&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 1 kilo byte|| =&amp;gt; || 1000 byte&lt;br /&gt;
|-&lt;br /&gt;
|1 kibi byte || =&amp;gt; || 1024 byte&lt;br /&gt;
|-&lt;br /&gt;
|100 kilo byte asKibiBytes rounded || =&amp;gt; || 98 kiB     &lt;br /&gt;
|-&lt;br /&gt;
|1 kilo byte / 1 seconds || =&amp;gt; || 1000 B/s&lt;br /&gt;
|-&lt;br /&gt;
|1 kilo byte / 1 seconds * 5 minutes || =&amp;gt; || 300 kB&lt;br /&gt;
|-&lt;br /&gt;
|1 mega bits / 2 seconds || =&amp;gt; || 500000 b/s&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Misc Other Examples: ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 50%&amp;quot; | 10 candela / 1 square meter || =&amp;gt; || 10 lx&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Other (Fun) Examples: ===&lt;br /&gt;
===== Planet Distance =====&lt;br /&gt;
what is the smallest possible distance between earth and mars&lt;br /&gt;
&amp;lt;br&amp;gt;(See also: google for &amp;quot;smallest distance earth mars&amp;quot;):&lt;br /&gt;
 |earth mars minDistMarsSun maxDistEarthSun|&lt;br /&gt;
 &lt;br /&gt;
 earth := Physic::NatureConstants[&#039;planets&#039;][&#039;earth&#039;].&lt;br /&gt;
 mars := Physic::NatureConstants[&#039;planets&#039;][&#039;mars&#039;].&lt;br /&gt;
 minDistMarsSun := mars[&#039;perihelion&#039;].              &amp;quot;/ [https://en.wikipedia.org/wiki/Orbit_of_Mars See: &amp;quot;Orbit of Mars&amp;quot;]&lt;br /&gt;
    &amp;quot;/ perihelion  is the smallest distance from the sun&lt;br /&gt;
 maxDistEarthSun  := earth[&#039;aphelion&#039;].             &amp;quot;/ [https://en.wikipedia.org/wiki/Earth%27s_orbit See: &amp;quot;Orbit of Earth&amp;quot;]&lt;br /&gt;
    &amp;quot;/ aphelion    is the largest distance from the sun&lt;br /&gt;
 &lt;br /&gt;
 minDistMarsSun - maxDistEarthSun&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 54600000km (54.6 mio km)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Electric Force / Coulomb&#039;s Law =====&lt;br /&gt;
the force between two electrons at 1m distance:&lt;br /&gt;
 q := Physic::NatureConstants[&#039;ElementaryCharge&#039;].  &amp;quot;/ is: [https://en.wikipedia.org/wiki/Elementary_charge 1.60217663 × 10&amp;lt;sup&amp;gt;-19&amp;lt;/sup&amp;gt; C]&lt;br /&gt;
 k := Physic::NatureConstants[&#039;CoulombConstant&#039;].   &amp;quot;/ is: [https://en.wikipedia.org/wiki/Coulomb_constant 8987551792.3 kg·m³/(s²·C²)]&lt;br /&gt;
 r := 1 meter.&lt;br /&gt;
 f := k * q squared / r squared.&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 2.31e-28 N&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;[https://en.wikipedia.org/wiki/International_System_of_Units International System of Units (SI)]&lt;br /&gt;
&amp;lt;br&amp;gt;[https://en.wikipedia.org/wiki/United_States_customary_units US Customary Units]&lt;br /&gt;
&amp;lt;br&amp;gt;[https://en.wikipedia.org/wiki/Centimetre%E2%80%93gram%E2%80%93second_system_of_units CGS System]&lt;br /&gt;
&amp;lt;br&amp;gt;[https://en.wikipedia.org/wiki/Avoirdupois Avoirdupois]&lt;br /&gt;
&amp;lt;br&amp;gt;[https://en.wikipedia.org/wiki/Troy_weight Troy Weight]&lt;br /&gt;
&amp;lt;br&amp;gt;[https://en.wikipedia.org/wiki/Imperial_units Imperial Units]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=UsageHints/en&amp;diff=30900</id>
		<title>UsageHints/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=UsageHints/en&amp;diff=30900"/>
		<updated>2026-02-23T11:30:07Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 29.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expecco contains a number of features which might be different or unknown to other UI frameworks,&lt;br /&gt;
but which are nevertheless very useful to know.&lt;br /&gt;
&lt;br /&gt;
== General Layout ==&lt;br /&gt;
[[Bild:Expecco General Layout1.png|thumb|300px|Expecco showing a new project (nothing selected in the tree). The left part shows the project tree, the right part the editor (here none)]]&lt;br /&gt;
[[Bild:Expecco General Layout2.png|thumb|300px|Expecco with an action item selected. The right part now shows the item editor]]&lt;br /&gt;
&lt;br /&gt;
Expecco is a multi-Window and multi-Tab Application: you can open multiple main windows (via the &#039;&#039;&amp;quot;Window&amp;quot;&#039;&#039; menu) and work within the same project or in multiple projects at the same time. Each such main window presents one project. However, if two main windows are opened on the same project, they will monitor each other and update themself as required. If you started to modify an item in one window, the other will switch to &amp;quot;read only&amp;quot; mode, and update its contents once you accepted the change in the first window. &lt;br /&gt;
&lt;br /&gt;
Each main window is organized under a variable number of tabs, each presenting a selected item from the project (i.e. a test plan, activity, action or attachment).&lt;br /&gt;
&lt;br /&gt;
Each tab consists of two major parts: a project tree on the left, and an edit area at the right. The editor is specific to the kind of object being selected.&lt;br /&gt;
&lt;br /&gt;
Most often used editors are:&lt;br /&gt;
* Test plan editor: arranges actions into a sequence of test cases (which are actions)&lt;br /&gt;
* [[CompoundBlock_Editor-CompoundWorksheet_Editor/en|Compound action editor]]: to edit actions defined by an activity diagram&lt;br /&gt;
* [[Attachment_Editor/en|Attachment editor]]: to edit the contents of test data&lt;br /&gt;
&lt;br /&gt;
== Dual Use of the Tree ==&lt;br /&gt;
The tree has different behavior on Click vs. Press-and-Move.&lt;br /&gt;
* A click selects the element for editing; &lt;br /&gt;
* a press-and-move initiates a drag operation to copy or move the selected element to somewhere else (either another position inside the same tree or to another tree, or into a diagram as an action step, or into a test plan as test case).&lt;br /&gt;
&lt;br /&gt;
This behavior may be hindering, if you want to drag and drop actions from the tree.&lt;br /&gt;
For this, open a separate tree, which is used exclusively for drag&amp;amp;drop (click on the split-tree button above the tree).&lt;br /&gt;
&lt;br /&gt;
It should be noted, that once you are more experienced, you will probably no longer drag&amp;amp;drop from the tree, but instead press &amp;lt;kbd&amp;gt;CTRL-n&amp;lt;/kbd&amp;gt; in the editor, to place actions via a dialog, or press &amp;lt;kbd&amp;gt;CTRL-c&amp;lt;/kbd&amp;gt; &amp;lt;kbd&amp;gt;CTRL-v&amp;lt;/kbd&amp;gt; to copy-paste it.&lt;br /&gt;
&lt;br /&gt;
== Menus and Toolbars with Delayed Menus ==&lt;br /&gt;
Some menu funtions show a list of choices, if you click it and wait for a while (keeping the mouse button or touchpad fingers down).&lt;br /&gt;
&lt;br /&gt;
Such menus items are displayed with a &#039;&#039;greyish&#039;&#039; or lighter down-arrow beside, as for example in this toolbar menu item: &lt;br /&gt;
[[Datei:Menu Back button.png]]&lt;br /&gt;
 &lt;br /&gt;
Often a list of previous items or other history is presented by this so called &amp;quot;&#039;&#039;delayed menu&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* If you press and hold, the sub menu will appear after a short delay.&lt;br /&gt;
* If you just click, without waiting for a menu to appear, the default action will be executed.&lt;br /&gt;
* If you click on the arrow, the sub menu will appear immediately.&lt;br /&gt;
&lt;br /&gt;
== Menus and Toolbars with Regular Submenus ==&lt;br /&gt;
These are displayed with a &#039;&#039;blackish&#039;&#039; or darker arrow beside them. The menu will drop down immediately.&lt;br /&gt;
&lt;br /&gt;
== Toolbar Items which Remember the Last Choice (Quickmenus) ==&lt;br /&gt;
[[Bild:Expecco General QuickMenu1.png|thumb|150px|Quickmenu: button before]]&lt;br /&gt;
[[Bild:Expecco General QuickMenu2.png|thumb|150px|Quickmenu: Selecting an item]]&lt;br /&gt;
[[Bild:Expecco General QuickMenu3.png|thumb|150px|Quickmenu: button afterwards]]&lt;br /&gt;
The item-creation toolbar items above the left tree will remember your last choice, and keep that as default action.&lt;br /&gt;
These items are of the above described &amp;quot;&#039;&#039;delayed-menu&#039;&#039;&amp;quot; type, &lt;br /&gt;
and will change their image to reflect the previous action&#039;s choice. This will be the action performed if you click and release quickly.&lt;br /&gt;
&lt;br /&gt;
== Resize Handles (between Sub Panes) ==&lt;br /&gt;
Depending on your view style setting, these handles may only show up while the mouse pointer is hovering over it.&lt;br /&gt;
Some of them are shown with a single arrow (above and below the &#039;&#039;gritty rubber area&#039;&#039;, and others are shown with arrows pointing in opposite directions.&lt;br /&gt;
&lt;br /&gt;
If you press-and-hold the mouse button in the center area, these handles behave as known in other UI frameworks: just drag and resize the views underneath.&lt;br /&gt;
&lt;br /&gt;
If you click on one of the arrows, the views&#039; sizes will change to full size towards the arrow. As mentioned above, some only present the fullsize-option on one side.&lt;br /&gt;
&lt;br /&gt;
If one of the views is currently being resized to full size, a single click on the center (not a press-and-move) will restore the previous size, whereas a press-and-move on the handle acts as normal.&lt;br /&gt;
&lt;br /&gt;
== F8: Again in the Text Editor ==&lt;br /&gt;
&amp;lt;kbd&amp;gt;F8&amp;lt;/kbd&amp;gt; is a shortcut for the &amp;quot;&#039;&#039;Again&#039;&#039;&amp;quot; keyboard function, which repeats your last text edit operation. Be it a delete, replace, or search-and-replace.&lt;br /&gt;
A very powerful operation. In the popup menu, you&#039;ll also find &#039;&#039;&amp;quot;Again for All&amp;quot;&#039;&#039;, which repeats the operation until no more matches are found (eg. to replace or cut all occurrences of a word)&lt;br /&gt;
&lt;br /&gt;
== CTRL-V: Paste History in the Text Editor ==&lt;br /&gt;
In addition to the common paste operation (&amp;lt;kbd&amp;gt;CTRL-v&amp;lt;/kbd&amp;gt; unshifted) which pastes the last copy- or cut text,&lt;br /&gt;
expecco keeps a history of previous copy/cut texts. Press &amp;lt;kbd&amp;gt;CTRL-V&amp;lt;/kbd&amp;gt; (both SHIFT and CTRL pressed) to get a dialog from which you select the text to be pasted.&lt;br /&gt;
&lt;br /&gt;
== CTRL-O: Toggle between Overwrite and Insert Mode in the Text Editor ==&lt;br /&gt;
The title already says it: enter &amp;lt;kbd&amp;gt;CTRL-O&amp;lt;/kbd&amp;gt; (both SHIFT and CTRL pressed) to switch to overwrite mode and back. By default, text editors will insert the characters you type.&amp;lt;br&amp;gt;There is also a little indicator showing &amp;quot;I&amp;quot; or &amp;quot;O&amp;quot; at the bottom right. The indicator also has a popup menu for more options.&lt;br /&gt;
&lt;br /&gt;
== Speed Scroll ==&lt;br /&gt;
The faster you move on a touchpad, the faster will it scroll.&lt;br /&gt;
&lt;br /&gt;
== Horizontal Scroll with the Mouse Wheel ==&lt;br /&gt;
Hold the &amp;lt;kbd&amp;gt;SHIFT&amp;lt;/kbd&amp;gt; or &amp;lt;kbd&amp;gt;CMD&amp;lt;/kbd&amp;gt; key.&lt;br /&gt;
&lt;br /&gt;
== Pagewise Scroll and Jump Scroll ==&lt;br /&gt;
In a scrollbar, click below or above the so-called thumb for pagewise scrolling. This is an autorepeat operation (keep the mouse button pressed).&lt;br /&gt;
&lt;br /&gt;
Shift-click for absolute positioning.&lt;br /&gt;
&lt;br /&gt;
In a textview, press &amp;lt;kbd&amp;gt;CTRL-g&amp;lt;/kbd&amp;gt; to scroll to an absolute or relative line number.&lt;br /&gt;
&lt;br /&gt;
== Zoom In/Out with the Mouse Wheel ==&lt;br /&gt;
Hold the &amp;lt;kbd&amp;gt;CTRL&amp;lt;/kbd&amp;gt; key.&lt;br /&gt;
&lt;br /&gt;
== Info Messages at the Bottom ==&lt;br /&gt;
Some info messages at the bottom disappear after some time.&lt;br /&gt;
&amp;lt;br&amp;gt;The popup menu item &amp;quot;&#039;&#039;Previous Masseges&#039;&#039;&amp;quot; brings them back (right click in the info message area) .&lt;br /&gt;
&lt;br /&gt;
== Use the Action Finder ==&lt;br /&gt;
[[Bild:Expecco General ActionFinder1.png|thumb|250px|Action Finder: Searching for a String Splitter by Name/Tag...]]&lt;br /&gt;
[[Bild:Expecco General ActionFinder2.png|thumb|250px|Action Finder: Searching for a String Splitter by Input &amp;amp; Output...]]&lt;br /&gt;
If you need an action to perform some string or numeric operation,&lt;br /&gt;
but do not know if such a function is found in the standard library,&lt;br /&gt;
and where it might be, perform the following steps:&lt;br /&gt;
&lt;br /&gt;
: in the diagram editor, press &amp;lt;kbd&amp;gt;CTRL-n&amp;lt;/kbd&amp;gt; (i.e. &amp;quot;&#039;&#039;New Step&#039;&#039;&amp;quot;);&lt;br /&gt;
:: first try a name search, providing one or more keywords (separated by commas). &lt;br /&gt;
:: use obvious words, such as &amp;quot;string&amp;quot;, &amp;quot;plus&amp;quot;, &amp;quot;split&amp;quot;, &amp;quot;arithmetic&amp;quot;, &amp;quot;concat&amp;quot; etc.&lt;br /&gt;
: if there is nothing which seems to fit, &lt;br /&gt;
:: click on &amp;quot;&#039;&#039;Search by Result&#039;&#039;&amp;quot; to open the Action Finder &lt;br /&gt;
:: enter an example set of input values and the desired result and click on &amp;quot;&#039;&#039;Search&#039;&#039;&amp;quot;.&lt;br /&gt;
: if you are lucky, there is such an action, and you can click on &amp;quot;&#039;&#039;New Step&#039;&#039;&amp;quot; in the finder.&lt;br /&gt;
: Or it finds a textual code sequence to compute that result, and offers you to generate a new elementary action for it.&lt;br /&gt;
&lt;br /&gt;
More on the Action Finder is found [[Action_Finder/en|here]].&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Hint: in the Action Finder&#039;s top menu, select &#039;&#039;&amp;quot;Show Me How it Works&amp;quot;&#039;&#039; - &#039;&#039;&amp;quot;Find a Library Function&amp;quot;&#039;&#039;. Listen and be impressed! (you need sound output for this) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Use the File Browser ==&lt;br /&gt;
Expecco includes a number of useful tools which are actually part of the underlying IDE (Smalltalk/X, on which expecco is based, and which is part of the application).&lt;br /&gt;
The tools are found in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; menu, and one of those tools is the so called &amp;quot;&#039;File Browser&#039;&#039;&amp;quot;.&lt;br /&gt;
You can use this tool as text editor, file finder or file comparator.&lt;br /&gt;
&amp;lt;br&amp;gt;More on the File Browser is found [[File_Browser|here]].&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=File_Browser&amp;diff=30899</id>
		<title>File Browser</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=File_Browser&amp;diff=30899"/>
		<updated>2026-02-23T11:26:35Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 29.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Bundled with expecco comes a tool called &amp;quot;&#039;&#039;File Browser&#039;&#039;&amp;quot;, which can be used for typical day-to-day tasks related to file and directory management. It is operating system independent and works the same on all supported platforms. &lt;br /&gt;
&lt;br /&gt;
It can be opened via &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;File Browser In...&#039;&#039;&amp;quot;. &amp;lt;br&amp;gt;Also some popup menus offer an entry to open a File Browser (eg. a text view, in its &amp;quot;&#039;&#039;Others&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Open File Browser on It&#039;&#039;&amp;quot;) when a valid filename is selected, or a freeze value of a step in an activity diagram)&lt;br /&gt;
&lt;br /&gt;
The browser contains sophisticated search functions (by name, size, access time or contents), file difference viewer, duplicate file finder, bulk rename, deep copy or remove and other useful functions. &lt;br /&gt;
&lt;br /&gt;
It also includes a hex dump view, an image viewer for the most popular graphics formats (TIFF, GIF, PNG, JPEG and many others), a simple HTML viewer, an XML structure viewer and support for ctags for easy navigation inside source code files.&lt;br /&gt;
&lt;br /&gt;
The file browser is derived from the standard Smalltalk/X file browser, which is described in the [http://live.exept.de/doc/online/english/tools/TOP.html Smalltalk/X online documentation].&lt;br /&gt;
&lt;br /&gt;
== Editors ==&lt;br /&gt;
A double click on a file will present the file&#039;s contents in a filetype specific editor.&lt;br /&gt;
&lt;br /&gt;
=== XML Files ===&lt;br /&gt;
The XML file is parsed and a DOM tree is presented. This also includes an xpath entry field to locate elements within the document.&lt;br /&gt;
&lt;br /&gt;
=== HTML Files ===&lt;br /&gt;
A preview (not supporting style sheets or Javascript) is presented.&lt;br /&gt;
&lt;br /&gt;
=== Source Code ===&lt;br /&gt;
For some common programming languages, a tag list is shown at the right, to quickly navigate to individual fuctions within the text.&lt;br /&gt;
However, be aware that it is not meant as a replacement for power editors or IDEs.&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
If the file contains a bitmap image (JPG, PNG, GIF, TIFF, and many other formats),&lt;br /&gt;
the picture is shown in the lower area, and the area&#039;s own toolbar offers a bitmap editor to be opened on it.&lt;br /&gt;
Be aware that this editor&#039;s main task is to edit icons; i.e. small bitmaps.&lt;br /&gt;
It is not meant as a replacement for powerful image editor like gimp. &lt;br /&gt;
&lt;br /&gt;
=== Archives ===&lt;br /&gt;
Tar and zip archives are supported and the contents is listed. In addition, extraction or the preview of individual files is offered.&lt;br /&gt;
&lt;br /&gt;
== Utility Functions ==&lt;br /&gt;
== Searching ==&lt;br /&gt;
Click&lt;br /&gt;
[[Datei:SearchButton.png|search button]] to open the search tool in the lower area,&lt;br /&gt;
which offers a file-search utility with various filters and options. Files can be searched by size (eg. find files larger than a given size), by modification time, by contents (includes a string, does not include a string). Also, duplicate files can be found quickly. &lt;br /&gt;
&lt;br /&gt;
=== Opening from a Text Editor ===&lt;br /&gt;
Code editors, document editors and many other text editors provide an open-menu item, as shown in the following screenshot:&amp;lt;br&amp;gt;[[Datei:FileBrowserOpenInTextView.png|300px]]&amp;lt;br&amp;gt;&lt;br /&gt;
Notice, that the menu item is only enabled if the selection represents a filename.&lt;br /&gt;
&lt;br /&gt;
=== Opening via the Freeze Value&#039;s Menu ===&lt;br /&gt;
If an input/output pin with a type of &amp;quot;Filename&amp;quot; and it has a freeze value, the popup menu contains an &amp;quot;Open FileBrowser&amp;quot; item.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:FileBrowserOpenFromFreezeValue.png|200px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Opening via the Activitylog ===&lt;br /&gt;
If an input/output pin&#039;s value represents a filename, the pop up menu also provides this function.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:FileBrowserOpenViaActivityLog.png|300px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Personal_Settings/en&amp;diff=30898</id>
		<title>Personal Settings/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Personal_Settings/en&amp;diff=30898"/>
		<updated>2026-02-23T11:24:58Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 29.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Personal Settings =&lt;br /&gt;
All of your personal settings are stored in a settings file, which is loaded upon startup.&lt;br /&gt;
By default, the file is stored in &amp;quot;&amp;lt;code&amp;gt;~/.expecco/.expeccoSettings&amp;lt;/code&amp;gt;&amp;quot;, where &amp;quot;&amp;lt;code&amp;gt;~&amp;lt;/code&amp;gt;&amp;quot; (tilde) is your home folder on Unix/Linux/macOS systems, or the personal documents folder on Windows systems. The actual path is shown in the setting dialog&#039;s top page.&lt;br /&gt;
&lt;br /&gt;
It is possible to use different settings by starting expecco with a &amp;quot;&amp;lt;code&amp;gt;--settings &amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;&amp;quot; [[Command_Line Options#Command_Line|command line argument]].&lt;br /&gt;
&lt;br /&gt;
The settings dialog is opened via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; item in the main menu, and contains an index on the left, and individual settings editors as per selection on the right.&lt;br /&gt;
&lt;br /&gt;
Notice that changes in the settings dialog will only affect your current expecco session, unless saved via the &amp;quot;&#039;&#039;Save Settings&#039;&#039;&amp;quot; button (you will be asked when the dialog is closed).&lt;br /&gt;
&lt;br /&gt;
== Find a Settings Value by Name ==&lt;br /&gt;
The settings dialog&#039;s menu contains an entry named &amp;quot;&#039;&#039;Show Search Field&#039;&#039;&amp;quot;, which adds a textfield, into which you can type a keyword.&lt;br /&gt;
Then, all places where this keyword is encountered in either the label or its tooltip will be highlighted. For example, if you want to locate all places which relate to &amp;quot;code&amp;quot; settings, try searching for &amp;quot;code&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Settings You May Want to Change ==&lt;br /&gt;
&lt;br /&gt;
==== User interface language (English, German, French, ...) ====&lt;br /&gt;
By default, expecco uses the language as defined in the operating system&#039;s environment (i.e. $LANG shell variable or Windows setting). This can be overridden via the &amp;quot;&#039;&#039;Language&#039;&#039;&amp;quot; dialog. All language translation texts are present in external language files (found in the installation folder&#039;s &amp;quot;resources/exept/expecco&amp;quot; subfolder, and missing translations can be provided by exept via updates or even added/changed by yourself (if required).&lt;br /&gt;
&lt;br /&gt;
==== External Tools ====&lt;br /&gt;
Here, paths to external tools (such as &amp;quot;ruby&amp;quot;, &amp;quot;node.js&amp;quot; or &amp;quot;gnuplot&amp;quot;) can be redefined. By default, expecco assumes that those commands are found along your shell&#039;s PATH setting.&amp;lt;p&amp;gt;Also, the access method (http or https) for the online documentation is defined here. This will be used when clicking on a help button or selecting a help item from the menu.&lt;br /&gt;
&lt;br /&gt;
==== Automatic or Semiautomatic Updates &amp;amp; Patches ====&lt;br /&gt;
Expecco can be configured to automatically look for and optionally install updates and/or patches from the exept update server (&amp;lt;code&amp;gt;http://download.exept.de/download/expecco&amp;lt;/code&amp;gt;). Depending on your network configuration (firewalls or even totally isolated test-labs), access to this public server may or may not be possible on your machine. Then, updates can be either installed via files (which can be transported eg. via an USB stick) or by another expecco, which gets the updates via file and provides the update service for other machines inside your network. In this later setup, you&#039;ll have to manually transport the files only once (to the update service providing machine) and configure the other machines to fetch the updates from that master expecco machine.&lt;br /&gt;
&lt;br /&gt;
== Individual Settings Editors ==&lt;br /&gt;
&lt;br /&gt;
The individual settings editors are further described in:&lt;br /&gt;
&lt;br /&gt;
* [[Settings LanguageSettings/en|Language Settings]]&lt;br /&gt;
* [[Settings PrinterSettings/en|Printer Settings]]&lt;br /&gt;
* LookAndFeel Settings&lt;br /&gt;
** [[Settings TreeSettings/en|Tree Settings]]&lt;br /&gt;
** [[Settings CodeEditorSettings/en|Code Editor Settings]]&lt;br /&gt;
*** [[Settings SyntaxColorSettings/en|Syntax Color Settings]]&lt;br /&gt;
** Diagram Editor Settings&lt;br /&gt;
*** [[Settings GeneralWorksheetEditorLookSettings/en|General Worksheet Editor Look Settings]]&lt;br /&gt;
*** [[Settings WorksheetEditorElementLookSettings/en|Worksheet Editor Element Look Settings]]&lt;br /&gt;
** [[Settings TableDrivenBlock/en|Table Driven Block Settings]]&lt;br /&gt;
** [[Settings TagColorSettings/en|Tag Color Settings]]&lt;br /&gt;
** [[Settings TagIconSettings/en|Tag Icon Settings]]&lt;br /&gt;
** [[Settings StateColorSettings/en|State Color Settings]]&lt;br /&gt;
** [[Settings SoundSettings/en|Sound Settings]]&lt;br /&gt;
** [[Settings FontSettings/en|Font Settings]]&lt;br /&gt;
** [[Settings HotKeySettings/en|HotKey Settings]]&lt;br /&gt;
** [[Settings MiscLookSettings/en|MiscLook Settings]]&lt;br /&gt;
* [[Settings ProjectManagementSettings/en|Project Management Settings]]&lt;br /&gt;
** [[Settings ExpeccoNETSettings/en|Expecco ALM Settings]]&lt;br /&gt;
* [[Settings ExecutionSettings/en|Execution Settings]]&lt;br /&gt;
** [[Settings ExternalScriptInterpreterSettings/en|External Script Interpreter Settings]]&lt;br /&gt;
* [[Settings LoggingSettings/en|Logging Settings]]&lt;br /&gt;
** [[Settings DebuggerSettings/en|Debugger Settings]]&lt;br /&gt;
** [[Settings ReportSettings/en|Report Settings]]&lt;br /&gt;
* [[Settings StandardReportTemplateSettings/en|Standard Report Template Settings]]&lt;br /&gt;
** [[Settings CompanySettings/en|Company Settings]]&lt;br /&gt;
* [[Settings ExternalToolsSettings/en|External Tools Settings]]&lt;br /&gt;
* [[Settings UpdatesSettings/en|Updates Settings]]&lt;br /&gt;
* [[Settings PluginSettings/en|Plugin Settings]]&lt;br /&gt;
** [[Settings CommonJavaGUITestPluginSettings/en|Common Java GUI Test Plugin Settings]]&lt;br /&gt;
** [[Settings GUITestPlatformSettings/en|GUI Test Platform Settings]]&lt;br /&gt;
** [[Settings GembirdPluginSettings/en|Gembird Plugin Settings]]&lt;br /&gt;
** [[Settings JIRAPluginSettings/en|JIRA Plugin Settings]]&lt;br /&gt;
** [[Settings JavaBridgePluginSettings/en|Java Bridge Plugin Settings]]&lt;br /&gt;
** [[Settings ManualTestImport1PluginSettings/en|Manual Test Import1Plugin Settings]]&lt;br /&gt;
** [[Settings ManualTestImport2PluginSettings/en|Manual Test Import2Plugin Settings]]&lt;br /&gt;
** [[Settings MobileTestingSettings/en|Mobile Testing Plugin Settings]]&lt;br /&gt;
** [[Settings OpenETSGuiTestingPluginSettings/en|OpenETS GUI Testing Plugin Settings]]&lt;br /&gt;
** [[Settings PolarionPluginSettings/en|Polarion Plugin Settings]]&lt;br /&gt;
** [[Settings SAPPluginSettings/en|SAP Plugin Settings]]&lt;br /&gt;
** [[Settings SeppMedPluginSettings/en|Sepp.med Plugin Settings]]&lt;br /&gt;
** [[Settings VisualBasicScriptSettings/en|VisualBasic Scripting Settings]]&lt;br /&gt;
** [[Settings SeleniumSettings/en|Webtest Plugin Settings]] (Selenium)&lt;br /&gt;
** [[Settings WindowsAutomationPluginSettings/en|Windows Automation Plugin Settings]]&lt;br /&gt;
** [[Settings XMImportPluginSettings/en|XMImport Plugin Settings]]&lt;br /&gt;
* [[Settings LicenseInstallation/en|License Installation]]&lt;br /&gt;
&lt;br /&gt;
[[Category: Incomplete]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Settings_ExternalScriptInterpreters_Shell_and_BatchSettings/en&amp;diff=30897</id>
		<title>Settings ExternalScriptInterpreters Shell and BatchSettings/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Settings_ExternalScriptInterpreters_Shell_and_BatchSettings/en&amp;diff=30897"/>
		<updated>2026-02-23T11:23:00Z</updated>

		<summary type="html">&lt;p&gt;Sv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Shell and Batch Settings ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:ShellAndBatchSettings.png|mini]]&lt;br /&gt;
&lt;br /&gt;
=== Shell Path ===&lt;br /&gt;
Usually only needed under Windows, if you have installed a Unix-shell interpreter.&lt;br /&gt;
Only needed if your suite contains shell-script actions.&lt;br /&gt;
&lt;br /&gt;
=== Powershell Path ===&lt;br /&gt;
For powershell actions. Powershell is usually already installed under Windows, but available for Unix/Linux as well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Settings_ExternalScriptInterpreters_GroovyClassPathSettings/en|Next (Groovy Settings)]]&lt;br /&gt;
&lt;br /&gt;
[[Settings_ExternalScriptInterpreterSettings/en|Back to &amp;quot;External Script Interpreter Settings&amp;quot;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Settings/en|Back to the main page &amp;quot;Settings&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Settings]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Settings_ExternalScriptInterpreters_NodeSettings/en&amp;diff=30896</id>
		<title>Settings ExternalScriptInterpreters NodeSettings/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Settings_ExternalScriptInterpreters_NodeSettings/en&amp;diff=30896"/>
		<updated>2026-02-23T11:20:43Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 29.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Groovy Class Path Settings ==&lt;br /&gt;
&lt;br /&gt;
===== Node.js Path =====&lt;br /&gt;
&lt;br /&gt;
Defines the node interpreter to be used. We recommend using simply &amp;quot;node&amp;quot; and make sure that node is found along your path.&lt;br /&gt;
&lt;br /&gt;
=== Execute In ===&lt;br /&gt;
Defines the directory in which node actions are executed.&lt;br /&gt;
By default, it is running inside a temporary folder, where it sees the attachments as subfolder.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
See also [[Installing_additional_Frameworks/en#Node_Installation_.28for_Node.js_Actions.29|&amp;quot;Installing additional frameworks&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Settings_ExternalScriptInterpreters_PythonSettings/en|Next (Python Settings)]]&lt;br /&gt;
&lt;br /&gt;
[[Settings_ExternalScriptInterpreterSettings/en|Back to &amp;quot;External Script Interpreter Settings&amp;quot;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Settings/en|Back to the main page &amp;quot;Settings&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Settings]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Settings_ExternalScriptInterpreters_GroovyClassPathSettings/en&amp;diff=30895</id>
		<title>Settings ExternalScriptInterpreters GroovyClassPathSettings/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Settings_ExternalScriptInterpreters_GroovyClassPathSettings/en&amp;diff=30895"/>
		<updated>2026-02-23T11:17:56Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 29.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Groovy Class Path Settings ==&lt;br /&gt;
&lt;br /&gt;
===== Groovy Action Blocks and ClassPath =====&lt;br /&gt;
&lt;br /&gt;
Groovy actions are executed in a separate Java Virtual Machine (JVM). This JVM can be  started explicitly via &amp;quot;[&amp;lt;code&amp;gt;Start Java on Local Machine&amp;lt;/code&amp;gt;]&amp;quot; action blocks, via a shell script, or implicitly whenever the very first groovy action is executed.&lt;br /&gt;
&lt;br /&gt;
Explicitly (i.e. manually) started JVMs can be configured via the &amp;quot;[&amp;lt;code&amp;gt;Add JAR&amp;lt;/code&amp;gt;]&amp;quot; action to include any required class libraries (&amp;quot;.jar&amp;quot; files),&lt;br /&gt;
whereas implicitly (i.e. automatically) started JVMs get their class path from the user settings.&lt;br /&gt;
&lt;br /&gt;
=== Jar or Folder ===&lt;br /&gt;
Defines additional Jar files and paths which are passed to groovy for class resolving.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
See also [[Installing_additional_Frameworks/en#Java_Installation_.28for_Groovy_Actions.2C_Web-_and_Mobile_Testing.29|&amp;quot;Installing additional frameworks&amp;quot;]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Settings_ExternalScriptInterpreters_NodeSettings/en|Next (Node Settings)]]&lt;br /&gt;
&lt;br /&gt;
[[Settings_ExternalScriptInterpreterSettings/en|Back to &amp;quot;External Script Interpreter Settings&amp;quot;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Settings/en|Back to the main page &amp;quot;Settings&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Settings]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Hauptseite&amp;diff=30894</id>
		<title>Hauptseite</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Hauptseite&amp;diff=30894"/>
		<updated>2026-02-23T11:13:56Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 28.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Hauptseite/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
Klicken Sie links auf &#039;&#039;&amp;quot;Letzte Änderungen&amp;quot;&#039;&#039; (&amp;quot;Recent changes&amp;quot;) um die neuesten Einträge in der Dokumentation zu sehen.&amp;lt;br&amp;gt;Sie sehen dann meist, woran unsere Entwickler gerade vornehmlich arbeiten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h2&amp;gt;expecco&amp;lt;/h2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:flex; flex-wrap:wrap; padding:0; white-space:nowrap&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Für Einsteiger&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;!-- Link mit Fragezeichen funktioniert nicht, deshalb externer Link --&amp;gt;&lt;br /&gt;
			&amp;lt;!-- &amp;lt;li&amp;gt;[[Was ist expecco?|Allgemeine Informationen]]&amp;lt;/li&amp;gt; --&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[https://doc.expecco.de/w2.x/index.php?title=Was_ist_expecco%3F Allgemeine Informationen]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Expecco Usecases|Einsatzbereiche]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Features|expecco Feature-List]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Tutorials]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[usageHints/en|Hinweise zur Bedienung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Glossary|Begriffserklärung]] (Glossar)&amp;lt;/li&amp;gt;&lt;br /&gt;
 			&amp;lt;!-- &amp;lt;li&amp;gt;[[Testorganisation|Testorganisation]]&amp;lt;/li&amp;gt; --&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[FAQ]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage5.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Installation&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Installation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Installing additional Frameworks/en| Installation zusätzlicher Tools (Node, Python, ...)]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Personal Settings|Persönliche&amp;amp;nbsp;Einstellungen]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Configuration &amp;amp; Setup|Konfiguration]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Anbindung expecco ALM]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[SAP_Testing|Anbindung expecco an SAP]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Spezifische Anpassung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco UI]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_Remote_Control_App|expecco Mobile Remote App]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Probleme &amp;amp; Fehler]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage4.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Werkzeuge&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[API von Elementaraktionen]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Debugger]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Editoren]]&amp;lt;/li&amp;gt;		&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Standard Libraries/Bibliotheken]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Weitere Werkzeuge]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Weitere Funktionen]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage6.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Reportgenerierung&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Report Generation|Reportgenerierung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Errors during Execution|Fehler während der Ausführung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Secret Strings|Geheime Zeichenketten und Passwörter]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	 &amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Erweiterung_plugin.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Erweiterungen (Plugins)&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[GUI Testing]]&lt;br /&gt;
				&amp;lt;ul&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Java GUI Plugins|Java Swing/FX/SWT UI Testing]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Mobile Testing Plugin|Mobile Testing auf Android und iOS]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[WindowsAutomation Reference 2.0|UI Testing mit der Windows Automation Library]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Selenium_WebDriver_Plugin|Web Testing mit Selenium WebDriver]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                                        &amp;lt;li&amp;gt;[[VNC_Plugin_Reference|VNC UI Testing]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[GUI Testing|Weitere GUI Testing Plugins]]&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;/ul&amp;gt;&lt;br /&gt;
			&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Schnittstellen zum SUT]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[ManualTest]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;Produktivit&amp;amp;auml;t&lt;br /&gt;
				&amp;lt;ul&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[GIT Plugin]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                                        &amp;lt;li&amp;gt;[[HG Plugin (Mercurial)]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[CVS Plugin]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Anbindung expecco ALM | expeccoALM Schnittstelle]]&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;/ul&amp;gt;&lt;br /&gt;
			&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Weitere Plugins]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe;  margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage3.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Elemente der Testsuite&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Tree Elements|Tree Elemente]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Folder Element|Ordner]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Testplan Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Aktionen/Aktionsblöcke]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Datatype Element|Datentyp Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Inventory Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Skill Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Resource Element|Ressource Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Attachment Element|Anhänge]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[ReportTemplate Element|Report Templates]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color:#ecf0fe;  margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage3.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;API Referenz (Elementarbausteine)&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[API von Elementaraktionen|Übersicht]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco API#JavaScript_and_Smalltalk_Elementary_Blocks|Smalltalk &amp;amp; JavaScript]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco API#Groovy_Elementary_Blocks|Groovy]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Node.js_.28Bridged.29_Elementary_Blocks|NodeJS]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Bridged_Python_Elementary_Blocks|Python]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Bridged_Ruby_Elementary_Blocks|Ruby]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Bridged_C_Elementary_Blocks|C]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco API#VisualBasic_Elementary_Blocks|VisualBasic ]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Expecco Scripting API|Shell und Script Languages]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;p&amp;gt;&amp;amp;nbsp;&amp;lt;/p&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Useful API Functions|Useful API Functions:]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;ul&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Number API Functions|Number API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[String API Functions|String API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Collection API Functions|Collection API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Filename API Functions|Filename API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Stream API Functions|Stream API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                          &amp;lt;li&amp;gt;[[Date_and_Time_API_Functions|Date &amp;amp; Time API Functions]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;/ul&amp;gt; &lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Diagramm.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Diagramm - Elemente&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Step|Schritt]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Pins (Ein - Ausgänge)]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Code Ausführung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Connection|Verbindung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Pin|Pin Beschreibung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Annotation|Notiz]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Probe|Messfühler]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Refresh.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Sonstiges&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 25.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 24.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 23.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 22.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 21.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 20.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 19.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 18.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 2.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 1.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Future releases expecco|Zukünftige Releases]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Smalltalk]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Beispiele_icon.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Beispiele&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
                &amp;lt;span style=&amp;quot;padding:0 1em;font-size:0.9em&amp;quot;&amp;gt;Sie haben Fragen, wie ein Projekt aussieht?&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
                &lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;amp;nbsp;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Beispiele | Hier finden Sie weitere Anwendungsbeispiele.]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Expecco Code Snippets/en | Codeschnipsel]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Beispiele_icon.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Unterstützung weiterer Qualitätsmanagement Tools&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
                &lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Jira_Plugin_Reference|Jira]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[PolarionPlugin_Reference|Polarion]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Aqua_Plugin_Reference|Aqua]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Starting_expecco_via_Command_Line#Integration_with_Jenkins|Jenkins Integration]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h2 style=&amp;quot;clear:left&amp;quot;&amp;gt;expecco ALM&amp;lt;/h2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:flex; flex-wrap:wrap; padding:0; white-space:nowrap&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Sonstiges-Info.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Allgemein&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Was ist expecco ALM?]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Was ist der expecco Lizenzserver?]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Anbindung expecco ALM]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Rollen und Rechte]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Filter]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[FAQ expeccoALM/en | FAQ]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage5.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Installation/Einrichten&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Installation|Installation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Installation Patches|expecco ALM Installation Patches]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Einrichten Vorgehensweise|expecco ALM Einrichten]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM expecco Patch Service |Patchservice für expecco]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Refresh.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Plugins&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[AIDYMO Jira|Atlassian Jira]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[CustomerSpecific|Kundenspezifische Portale]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Refresh.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Sonstiges&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM App]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Installation Lizenzserver]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Release Notes|Release Notes]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Known Issues|Known Issues]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Features&amp;diff=30893</id>
		<title>Features</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Features&amp;diff=30893"/>
		<updated>2026-02-23T11:11:46Z</updated>

		<summary type="html">&lt;p&gt;Sv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Basissystem==&lt;br /&gt;
&lt;br /&gt;
* expecco IDE		&lt;br /&gt;
* Bibliotheken - StandardLib, ODBC, XML, uvm.&lt;br /&gt;
* Port Zugriff - seriell/USB/parallel/TCP&lt;br /&gt;
* Services - REST, SOAP, RPC, HTML, JSON, DLL-call&lt;br /&gt;
* Webtest - Webdriver, HTML5, Smart GWT&lt;br /&gt;
* Anbindung an Programmiersprachen und deren Bibliotheken&lt;br /&gt;
** Java/Groovy - Java Code eingeben &amp;amp; sofort ausführen sowie Code Injection in Java Programme&lt;br /&gt;
** Python - Code eingeben &amp;amp; sofort ausführen&lt;br /&gt;
** Node.js -  Code eingeben &amp;amp; sofort ausführen&lt;br /&gt;
** C/C++ - Code eingeben &amp;amp; sofort ausführen&lt;br /&gt;
** Ruby - Code eingeben &amp;amp; sofort ausführen&lt;br /&gt;
** .NET - DotNET&lt;br /&gt;
* Diverse weitere Skriptsprachen (GNUplot, Matlab/GNUOctave, TCL, Powershell uam.)		&lt;br /&gt;
* Manuelles/halbautomatisches/vollautomatisches Testen – benutzergeführter Testablauf&lt;br /&gt;
* Remotesteuerung via App unter Android, iPhone oder Webbrowser&lt;br /&gt;
* Report:&lt;br /&gt;
** Revisionssichere Testdokumentation&lt;br /&gt;
** Automatischer Report nach jedem Testlauf&lt;br /&gt;
** Individuelle Reports mit unterschiedlicher Detailtiefe generierbar&lt;br /&gt;
** Anpassbar an eigenes Layout &lt;br /&gt;
** Hinzufügen von Anhängen, Screenshots, Bildern oder Dokumenten&lt;br /&gt;
** Inhalt, Sprache und Erscheinungsbild an Zielgruppe anpassbar&lt;br /&gt;
** Mehrere Ausgabeformate möglich: PDF, HTML, XML, CSV, Text, u.v.m&lt;br /&gt;
** expecco Logfile mit allen Ablaufdaten, erneut ablauffähig&lt;br /&gt;
&lt;br /&gt;
expecco ist modular aufgebaut – das Basissystem kann jederzeit durch unsere Plugins erweitert und an Ihren individuellen Bedarf oder an den Projektfortschritt angepasst werden. Auf Anfrage erhalten unsere Partner die Möglichkeit, eigene Plugins zu entwickeln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Konzept:&lt;br /&gt;
&lt;br /&gt;
Die Grundphilosophie von expecco ist, dass Testabläufe sowohl von Entwicklern und Programmierern, als auch von Domänenexperten und Analysten erstellt, gewartet und ausgeführt werden können, ohne daß dazu spezielle Programmierkenntnisse notwendig wären. Dabei darf es aber keine Einschränkungen geben, und ein erfahrener Nutzer hat alle Mittel zur Verfügung, um eigenen Code, Scripte und erweiterte Funktionen einzubinden oder zu erstellen. &lt;br /&gt;
&lt;br /&gt;
Um beiden Anforderungen gerecht zu werden, können Abläufe in expecco sowohl als Aktivitätsdiagramm als auch als textueller code in verschiedenen Programmiersprachen definiert werden. Die ermöglicht einen &amp;quot;Best of both Worlds&amp;quot; Ansatz: einerseits können Nichtprogrammierer auf einer hohen Abstraktionsebene bestehende Aktionsbausteine mittels &amp;quot;Drag &amp;amp; Drop&amp;quot; oder Recording von GUI Aktionen zu komplexen Szenarien verbinden, andererseits ist es möglich, fehlende &lt;br /&gt;
Funktionsbausteine als Programmcode zu erstellen, und als Aktionsbaustein für andere Aktionen bereit zu stellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allgemeine Features:&lt;br /&gt;
&lt;br /&gt;
* Umfangreiche Standardbibliotheken&lt;br /&gt;
* Integrierter Rekorder&lt;br /&gt;
* Grafische Testentwicklung per drag&amp;amp;drop&lt;br /&gt;
* Direkt ausführbares grafisches Modell&lt;br /&gt;
* Laden und Speichern von Testsuiten &lt;br /&gt;
* Anlegen, Bearbeiten und Pflege von Testsuiten &lt;br /&gt;
* Testausführung&lt;br /&gt;
* Testentwicklung mit Singlestep, Breakpoints, Ausführung von Teilsequenzen &lt;br /&gt;
* Testentwicklung mit &amp;quot;Live changes while the system runs&amp;quot; &lt;br /&gt;
* Debugging auf hoher (Diagramm-) als auch auf niedriger (Script/Code) Ebene &lt;br /&gt;
* Beobachtung der Ausführung, Sammeln von Trace-, Zeit- und Logdaten &lt;br /&gt;
* Sammeln aller Datenflüsse, Nachrichtenpakete und Zwischenergebnisse zur späteren In-spektion &lt;br /&gt;
* Reportgenerierung als mensch- und maschinenlesbare Dokumente in verschiedenen Forma-ten&lt;br /&gt;
* Testbeschreibungen werden unmittelbar interpretiert, der Testablauf wird im Detail angezeigt und live animiert.&lt;br /&gt;
* Laufende Tests lassen sich anhalten, im Einzelschrittmodus ausführen und während des Ab-laufs modifizieren sowie fortsetzen.&lt;br /&gt;
* Flexible Parametrisierungen&lt;br /&gt;
* Lineare und parallele Testabläufe&lt;br /&gt;
* Testabläufe passen sich dynamisch an geänderte Konfigurationen an.&lt;br /&gt;
* Klar definierte Schnittstellen stellen sicher, dass Produktänderungen und -erweiterungen nur an einer Stelle gewartet werden müssen.&lt;br /&gt;
* Das integrierte Versionsmanagement sorgt für konsistente Datenhaltung&lt;br /&gt;
* Hohe Wiederverwendbarkeit der Testsequnzen vom Komponenten- bis zum Abnahmetest&lt;br /&gt;
* Import/Export von Spezifikationen&lt;br /&gt;
* Plattformunabhängig (Win32/64, Windows7-10; diverse Linux, MAC-OSX)&lt;br /&gt;
&lt;br /&gt;
==GUI Test==&lt;br /&gt;
Diese Erweiterung ermöglicht das Testen bzw. Einbinden und Automatisieren von graphischen Benutzeroberflächen (GUIs). Unterstützt werden derzeit folgende Technologien:&lt;br /&gt;
* Java GUIs (Swing, SWT, FX) &lt;br /&gt;
* Microsoft GUIs (via UIA2, UIA3 - Ui Automation) &lt;br /&gt;
* .NET GUIs (MFC, Forms, DevExpress)&lt;br /&gt;
* Qt&lt;br /&gt;
* Mobilgeräte (Android / iPhone / iPad)&lt;br /&gt;
* VisualWorks Smalltalk GUIs&lt;br /&gt;
* VNC (remote) und lokales Display mit Bilderkennung und OCR (Texterkennung)&lt;br /&gt;
&lt;br /&gt;
expecco bietet verschiedene Möglichkeiten um GUI Elemente zu identifizieren:&lt;br /&gt;
* Eindeutige IDs&lt;br /&gt;
* Eindeutige Texte&lt;br /&gt;
* Element-Pfad und Element-Index (XPath)&lt;br /&gt;
* Bilderkennung&lt;br /&gt;
* Absolute und relative Position&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
GUI Test Features:&lt;br /&gt;
&lt;br /&gt;
* Nahtlose Integration in die expecco-Benutzeroberfläche &lt;br /&gt;
* Ein gemeinsames Werkzeug für verschiedene UI-Technologien &lt;br /&gt;
* Gleichzeitige Bedienung mehrerer Anwendungen&lt;br /&gt;
* Visualisierung des Aufbaus der Benutzeroberfläche (Komponentenstruktur) &lt;br /&gt;
* Informationen über verschiedene Zustände und Eigenschaften der einzelnen Bedienelemente &lt;br /&gt;
* Unterstützung beim Auffinden von Bedienelemente durch Hervorhebung, Vorschaubilder und &amp;quot;Mouse-Over&amp;quot; Feedback &lt;br /&gt;
* Filterung von passenden Aktionsblöcken aus der Block-Bibliothek abhängig von der jeweiligen UI-Technologie &lt;br /&gt;
* Erstellung von Testsequenzen mittels &amp;quot;Drag and Drop&amp;quot; und/oder automatischer Aufzeichnung &lt;br /&gt;
* Experimentelles Ausprobieren von Blöcken, Testsequenzen und Bedienelement-Pfaden &lt;br /&gt;
* Übernehmen von Testsequenzen in das Testprojekt&lt;br /&gt;
&lt;br /&gt;
==Web Test==&lt;br /&gt;
Diese Erweiterung realisiert aine Schnittstelle zu WebBrowsern (Chrome, Firefox, Edge, etc) und&lt;br /&gt;
wird mit dem Basissystem ausgeliefert. Sie muss nicht separat Lizensiert werden.&lt;br /&gt;
&lt;br /&gt;
* Selenium Webdriver, steuern und auslesen&lt;br /&gt;
* Unterstützt Chrome, Firefox, Edge, Opera, Safari u.a.&lt;br /&gt;
* HTML5, Smart GWT&lt;br /&gt;
&lt;br /&gt;
Web Test Features:&lt;br /&gt;
&lt;br /&gt;
* Wiedergabe/Testlauf auf allen gängigen Browser&lt;br /&gt;
* Ein Test auf allen Browsern ablaufbar&lt;br /&gt;
* Tests können „headless“ ablaufen&lt;br /&gt;
* Testen von Windows und Linux Anwendungen in verschiedenen Browsern&lt;br /&gt;
* Komfortables Zusammenstellen neuer Aktionsblöcke mit Benutzerinteraktionen&lt;br /&gt;
* Leichte Parameterisierung von Webformularen und automatisches Anlegen von CSV Tabellen mit Eingabewerten&lt;br /&gt;
* Kombination von UI-Tests mit anderen Systemen, Messgeräten, Sensoren, Datenbanken, Mobilgeräten etc.&lt;br /&gt;
* Messung von Antwortzeiten&lt;br /&gt;
* Neu-Aufnahme (rerecording) von Teilsequenzen, ohne dass die gesamte Sitzung erneut wiederholt werden muss&lt;br /&gt;
* Hohe Wiederverwendbarkeit von Teilsequenzen durch Herausfaktorieren von gemeinsamen Aktionen (z.B. login-Sequenzen, Formulareingaben, Tabellenprüfungen etc.)&lt;br /&gt;
* Lastgenerierung und Leistungsmessungen&lt;br /&gt;
* Das Webtest-Modul basiert auf Selenium WebDriver&lt;br /&gt;
&lt;br /&gt;
==Mobile Test==&lt;br /&gt;
Diese Erweiterung realisiert die Anbindung an Mobilgeräte.&lt;br /&gt;
&lt;br /&gt;
* Unterstützt Android und iOS	&lt;br /&gt;
&lt;br /&gt;
Mobile Test Features:&lt;br /&gt;
&lt;br /&gt;
* Kein Jailbreak nötig&lt;br /&gt;
* Recording - einfache Testerstellung mit integriertem Recorder&lt;br /&gt;
* Fernsteuerung - einfache Steuerung der Geräte auch ortsunabhängig möglich&lt;br /&gt;
* Ein Test - ausführbar auf allen Geräten (Android und iOS) und Emulatoren&lt;br /&gt;
* Remotezugriff auf mehrere Mobiltelefone gleichzeitig&lt;br /&gt;
* Parallele Testausführung auf mehreren Geräten&lt;br /&gt;
* Kommunikation mit externer Hardware (Schnittstellen u.a.Bluetooth, NFC, WLAN, LTE, Feldbusse, Backend)&lt;br /&gt;
* Zugriff auf Objekte im Anwendungskontext&lt;br /&gt;
* Komplexität - die Testausführung erfolgt nicht nur starr linear, auch Reaktionen des Testablaufs auf Vorbedingungen und Zustandsänderungen der App sind möglich&lt;br /&gt;
* Parametrisierbarkeit - Eingabewerte und Geräte einfach austauschbar&lt;br /&gt;
* Automatisierung - Testen von bereits installierten Apps oder Apps zu Testbeginn automatisch installieren und am Ende deinstallieren&lt;br /&gt;
* Bausteinbibliothek - schnelle, einfache Testerstellung dank umfangreichem Vorrat an fertigen Bausteinen&lt;br /&gt;
* Wiederverwendbarkeit - Testschritte können für weitere Tests wiederverwendet werden&lt;br /&gt;
* Elementbaum inspizierbar - die Anordnung der Bedienelemente ist sichtbar, die Eigenschaften einsehbar&lt;br /&gt;
* Detailliertes Reporting&lt;br /&gt;
&lt;br /&gt;
==Embedded Test==&lt;br /&gt;
Dieses Erweiterungspaket umfasst Schnittstellen zu technischen Geräten wie sie insbesondere (aber nicht nur) im Bereich Automotive typisch bedient werden.&lt;br /&gt;
 &lt;br /&gt;
* CAN, CANoe, CANAnalyzer, MOST,  &lt;br /&gt;
* MQTT, SomeIP, USB, &lt;br /&gt;
* WSDL, REST, Remote Access,  &lt;br /&gt;
* VNC Client, etc.&lt;br /&gt;
&lt;br /&gt;
Embedded Test Features:&lt;br /&gt;
&lt;br /&gt;
* mit CANoe ist expecco hier ein übergeordnetes Testwerkzeug&lt;br /&gt;
* Zugriff auf den von CANoe und CANalyzer implementierten COM Server&lt;br /&gt;
* Steuerung der Applikationen von außen&lt;br /&gt;
* expecco liest CANoe-Projekt aus und speichert alle Variablen in einer CSV-Datei&lt;br /&gt;
* Modellieren des Testablaufs&lt;br /&gt;
* die einmal modellierten Testabläufe können für verschiedene Steuergeräte verwendet wer-den&lt;br /&gt;
* das Bestücken mit Variablen erfolgt automatisiert&lt;br /&gt;
* Tests sind parametrisierbar&lt;br /&gt;
* Dynamische (parallele) Testabläufe&lt;br /&gt;
* Varianten: generische Testfälle für Steuergeräte Varianten können definiert warden&lt;br /&gt;
* Einbindung weiterer Programme und Geräte in den Testablauf: Technologieübergreifende Tests (CANoe/ Optolyzer/ Mobile Devices in 1 Testablauf)&lt;br /&gt;
* Testautomatisierung unabhängig von der Testumgebung (wie CANoe, National Instruments, dSpace)&lt;br /&gt;
&lt;br /&gt;
==Messgeräte, Simulatoren, Schnittstellen==&lt;br /&gt;
Dieses Erweiterungspaket umfasst Schnittstellen zu technischen Geräten wie sie im Bereich Fabrik- und Geräteautomatisierung sowie Maschinenbau typisch benötigt werden.&lt;br /&gt;
&lt;br /&gt;
* PCAN, CANUSB, Profibus, Vector Hardware Interfaces &lt;br /&gt;
* REST, SOAP, XML-RPC, http, https, SNMP, TELNET, &lt;br /&gt;
* TCP/IP, UDP, SSH, (S)FTP, DLL Calls, VISA, GPIB, SCPI, OPC UA, MQTT, SomeIP&lt;br /&gt;
&lt;br /&gt;
MSS Features:&lt;br /&gt;
&lt;br /&gt;
* Direktes Steuern von Hardwareschnittstellen und Bussystemen&lt;br /&gt;
* Steuern von Applikationen zur Kontrolle von eingebetteten Systemen&lt;br /&gt;
* Analoge Ein- und Ausgänge&lt;br /&gt;
* Vielfältige Schnittstellen ermöglichen einen End2End Test&lt;br /&gt;
* Dynamisches Importieren von Informationen zur Laufzeit&lt;br /&gt;
* Tests werden automatisiert auf Änderungen am System Under Test angepasst&lt;br /&gt;
&lt;br /&gt;
==SAP==&lt;br /&gt;
&lt;br /&gt;
SAP Features:&lt;br /&gt;
&lt;br /&gt;
* Abbildung und Tests echter Unternehmensabläufe&lt;br /&gt;
* Anbindung an SAP GUI über eCATT&lt;br /&gt;
* Verbindung mit mehreren UIs gleichzeitig möglich&lt;br /&gt;
&lt;br /&gt;
==B2B==&lt;br /&gt;
&lt;br /&gt;
B2B Features:&lt;br /&gt;
&lt;br /&gt;
* Edifact; Messages lesen, parsen, generieren, prüfen, verarbeiten&lt;br /&gt;
* Struktur/Nachrichten editor&lt;br /&gt;
* Swift Messages&lt;br /&gt;
&lt;br /&gt;
==QM Schnittstellen==&lt;br /&gt;
&lt;br /&gt;
* expecco ALM, [[Jira_Plugin_Reference|Jira]], [[PolarionPlugin_Reference|Polarion]], [[Aqua_Plugin_Reference|Aqua]], HP Quality Center, Jenkins, Seppmed-MBT suite&lt;br /&gt;
&lt;br /&gt;
QM Schnittstellen Features:&lt;br /&gt;
&lt;br /&gt;
* Einfache Anbindung an bereits vorhandene Test- und Qualitätsmanagementsysteme&lt;br /&gt;
* Remote Steuerung von expecco via SOAP/REST oder Telnet&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Future_releases_expecco&amp;diff=30892</id>
		<title>Future releases expecco</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Future_releases_expecco&amp;diff=30892"/>
		<updated>2026-02-23T11:10:02Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 25.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Available for Beta-Testers / Evaluation ==&lt;br /&gt;
&lt;br /&gt;
* Feature: [[EDI/Edifact Plugin | EDI-Edifact]] plugin&lt;br /&gt;
* Feature: [[ PolarionPlugin Reference | Polarion plugin ]]&lt;br /&gt;
* Manual Tests: in expecco ALM&lt;br /&gt;
&lt;br /&gt;
== Planned for Future Releases ==&lt;br /&gt;
&lt;br /&gt;
* Compound GUI Blocks, enhanced GUI Construction Toolkit (PRO version) [-&amp;gt; [[MeasurementValueGUI|example]]]&lt;br /&gt;
* User-Constructable Control &amp;amp; Monitoring Window &lt;br /&gt;
* User-Constructable Control &amp;amp; Monitoring WebInterface &lt;br /&gt;
* Object Repository (central mapping of gui-element names - also for cross-platform tests sap)&lt;br /&gt;
* Enterprise Version (central database for team development)&lt;br /&gt;
* Manual Tests: can run in web GUI (also Android, iPad, iPhone...), control window on extra screen (Now available!)&lt;br /&gt;
* Manual Tests: generate original word document as report&lt;br /&gt;
* Expecco control window on second screen (dual screen support)&lt;br /&gt;
* Expecco control window in web GUI&lt;br /&gt;
* Separate monitor/visualisation GUI (via background action with GUI)&lt;br /&gt;
* More detail in modification history (both project and per block)&lt;br /&gt;
* Attach probe(s) to monitor views (oscilloscope and chart views)&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Installing_additional_Frameworks/en&amp;diff=30891</id>
		<title>Installing additional Frameworks/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Installing_additional_Frameworks/en&amp;diff=30891"/>
		<updated>2026-02-23T11:07:51Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 25.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
If you intent to execute actions written for Java, Node, Python, .NET, C etc.,&lt;br /&gt;
or to test Java-, Windows- or mobile applications, additional frameworks have to be installed on your machine.&lt;br /&gt;
&lt;br /&gt;
Mostly for legal reasons, but also because you will probably want to install a most up-to-date version, we do not bundle those with the expecco installation (except for a python setup, as noted below).&lt;br /&gt;
&lt;br /&gt;
Please make sure that any required framework is installed, and the commands are found by expecco&lt;br /&gt;
(although you will usually get a more or less descriptive warning from expecco later, if anything goes wrong. If in doubt, open the Transcript window and/or start expecco in a console window as &amp;quot;&amp;lt;code&amp;gt;expecco.com&amp;lt;/code&amp;gt; to see any error or warning messages). &lt;br /&gt;
&lt;br /&gt;
If they are already installed, but expecco fails to execute one of them, take a look at the PATH setting and/or the expecco &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; settings. There, click on buttons labeled &amp;quot;?&amp;quot; to verify the installed version(s). &lt;br /&gt;
&lt;br /&gt;
However, the recommendend setup is to only specify the command name in the settings, and ensure that the PATH variable is set correctly, to let expecco find the command via the PATH. &lt;br /&gt;
&amp;lt;br&amp;gt;The PATH should be set in your &amp;quot;&amp;lt;code&amp;gt;.login&amp;lt;/code&amp;gt;&amp;quot; (Unix) or &amp;quot;&amp;lt;code&amp;gt;autoexec.bat&amp;lt;/code&amp;gt;&amp;quot; (Windows) file accordingly.&lt;br /&gt;
&lt;br /&gt;
== Required Frameworks Overview ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Feature !! Required Framework(s)&lt;br /&gt;
|-&lt;br /&gt;
| Java/Groovy Actions || JRE (Java Runtime Environment)&amp;lt;br&amp;gt;or: JDK (recommended)&lt;br /&gt;
|-&lt;br /&gt;
| NodeJS Actions || node&lt;br /&gt;
|-&lt;br /&gt;
| Python Actions || Python3.x (recommended)&amp;lt;br&amp;gt;or: Python2.x (for older Python code)&lt;br /&gt;
|-&lt;br /&gt;
| Jython Actions || Java JRE (Java Runtime Environment) or JDK and Jython&lt;br /&gt;
|-&lt;br /&gt;
| Iron Python Actions || .NET CLR&amp;lt;br&amp;gt;or: Mono (on non-Windows systems)&lt;br /&gt;
|-&lt;br /&gt;
| Ruby Actions || ruby&lt;br /&gt;
|-&lt;br /&gt;
| Java GUI Automation || JRE (Java Runtime Environment)&amp;lt;br&amp;gt;or: JDK (recommended)&lt;br /&gt;
|-&lt;br /&gt;
| Windows GUI Automation || .NET CLR&lt;br /&gt;
|-&lt;br /&gt;
| WebTest (Selenium Webdriver) || JRE (Java Runtime Environment)&amp;lt;br&amp;gt;webDrivers matching your web-browser version&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Test (Appium) || JRE (Java Runtime Environment)&lt;br /&gt;
|-&lt;br /&gt;
| Bridged C Actions || C compiler toolchain (GCC, Clang, VisualC, Mingw or Borland)&lt;br /&gt;
|-&lt;br /&gt;
| Octave (Matlab scripts) || GNU Octave or a real Matlab&lt;br /&gt;
|-&lt;br /&gt;
| OCR (VNC, Screen Automation) || Tesseract&amp;lt;br&amp;gt;language specific tessdata files&lt;br /&gt;
|-&lt;br /&gt;
| Vector/Canoe Plugin || .NET CLR&lt;br /&gt;
|-&lt;br /&gt;
| OPC Library || Python3 + opcua package&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Java_Installation&amp;quot;&amp;gt;Java Installation&amp;lt;/div&amp;gt; (for Groovy Actions, Web- and Mobile Testing) ==&lt;br /&gt;
You can either install a plain Java Runtime Environment (JRE) or a full Java Development Kit (JDK). If only a JRE is installed, some functions will not work,&lt;br /&gt;
and we therefore recommend a JDK - typically at its standard location, &amp;quot;&amp;lt;CODE&amp;gt;C:\Program Files\Java\jdk-xxx&amp;lt;/CODE&amp;gt;&amp;quot; (Windows), so it will run out of the box.&lt;br /&gt;
&amp;lt;br&amp;gt;Expecco will try to figure out if and where Java was installed, but it it also possible to specify explicit paths via the settings dialog.&lt;br /&gt;
&lt;br /&gt;
Notice, that due to changed regulations by Oracle (i.e. legal restrictions), we may no longer provide a Java installation bundled with expecco;&lt;br /&gt;
you should navigate to the Oracle (or OpenJDK) website and install it from there.&lt;br /&gt;
&lt;br /&gt;
Also notice, that on most systems, a Java is already installed, but it may be a runtime environment only.&lt;br /&gt;
Please verify, that a JDK is installed for the full set of features.&lt;br /&gt;
&lt;br /&gt;
The expecco installation does include some required jar files (eg. &amp;quot;groovy.jar&amp;quot;, selenium jars and drivers etc.), but you may want to verify that they are the most up-to-date versions. &lt;br /&gt;
&lt;br /&gt;
==== Selenium WebDriver ====&lt;br /&gt;
Especially the Selenium drivers (which are used to remote-control a Webbrowser when testing or automating graphical user interfaces in a browser) depend on the concrete browser version (i.e. Chrome version, Firefox version, etc.). Older drivers do not always work with a newer browser. &lt;br /&gt;
&lt;br /&gt;
The deployed installation package includes a number of drivers for versions which were in use at that time, but especially due to automatic updates, these may be outdated on your machine. Please follow the instructions given by expecco and/or read [[Selenium_WebDriver_Plugin/en#Update_WebDriver|&amp;quot;Update WebDriver&amp;quot;]] when it encounters a problem.&lt;br /&gt;
&amp;lt;br&amp;gt;The GUIBrowser&#039;s connect dialog will check for version compatibility and offer an update function if required.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;DOTNET_Installation&amp;quot;&amp;gt;.NET Installation&amp;lt;/div&amp;gt; (for the .NET bridge, Windows Apps, IronPython Actions and some Plugins &amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
On Windows, a .NET framework is usually already installed.&lt;br /&gt;
&amp;lt;br&amp;gt;On Unix/Linux systems, you can install &amp;quot;Mono&amp;quot;, which may provide enough functionality for your needs.&lt;br /&gt;
&amp;lt;br&amp;gt;Be aware, that some functions - especially GUI functions - may not be present or may not work perfectly (if at all) under Mono.&lt;br /&gt;
&lt;br /&gt;
Mono can be downloaded from [https://www.mono-project.com/download/stable/ the Mono project web site].&lt;br /&gt;
&lt;br /&gt;
1) for example, the Vector/Canoe plugin requires .NET (among others).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Node_Installation&amp;quot;&amp;gt;Node Installation&amp;lt;/div&amp;gt; (for Node.js Actions) ==&lt;br /&gt;
&lt;br /&gt;
Goto [ https://nodejs.org/en ] or [ https://nodejs.org/de/download/ ] and select the appropriate package for your machine.&lt;br /&gt;
When asked if additional packages are to be downloaded, answer &amp;quot;yes&amp;quot;. &lt;br /&gt;
(Under Windows, VisualStudio build tools will then also be installed, in case any node module needs to be compiled from C/C++ code).&lt;br /&gt;
&lt;br /&gt;
Open the node interpreter settings (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Node&#039;&#039;&amp;quot;) and verify that the &amp;quot;&amp;lt;code&amp;gt;node&amp;lt;/code&amp;gt;&amp;quot; command is found along your &amp;lt;code&amp;gt;PATH&amp;lt;/code&amp;gt; variable settings by clicking on the &amp;quot;?&amp;quot;-button. If found, its version should be shown.&lt;br /&gt;
&lt;br /&gt;
If not found, either restart expecco (if you installed node while expecco was active), or enter the path to your node interpreter into the path field. You may even have to restart your cmd/shell session, in case the old shell environment does not contain the path to the new installed node.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Python_Installation&amp;quot;&amp;gt;Python Installation&amp;lt;/div&amp;gt; (for Python Actions) ==&lt;br /&gt;
&lt;br /&gt;
Expecco is delivered with an installation package for a relatively new Python version (currently Python 3.11.6 (expecco 23.2)), but of course, new versions are constantly released and the included Python might be outdated.&amp;lt;br&amp;gt;You can (and probably should) download other versions [ https://www.python.org/downloads/ ].&lt;br /&gt;
Notice, that there are both packages for python3.x and python2.7 available, and you may have to install both, depending on the Python code to be executed later (although python2 is more and more becoming obsolete, there may still be frameworks for that old version to be found and used).&lt;br /&gt;
&lt;br /&gt;
You can start by installing a Python3.x version only. &lt;br /&gt;
By the time of writing this document, the most recent Python version is 3.12, but expecco is known to work with older versions.&lt;br /&gt;
Be aware, that there are syntactic differences between Python2.x and Python3.x; for example &amp;quot;&amp;lt;code&amp;gt;print ...&amp;lt;/code&amp;gt;&amp;quot; is a statement in 2.x whereas &amp;quot;&amp;lt;code&amp;gt;print(...)&amp;lt;/code&amp;gt;&amp;quot; is a function call in 3.x.&lt;br /&gt;
&lt;br /&gt;
Open the Python interpreter settings (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot;) and verify that the &amp;quot;&amp;lt;code&amp;gt;python&amp;lt;/code&amp;gt;&amp;quot; command is found along your &amp;lt;code&amp;gt;PATH&amp;lt;/code&amp;gt; variable settings (click on &amp;quot;?&amp;quot;). &lt;br /&gt;
&lt;br /&gt;
[[Bild:PythonSettings.png|700px|PythonSettings]]&lt;br /&gt;
&lt;br /&gt;
=== Python Commands ===&lt;br /&gt;
&lt;br /&gt;
Notice, that there are 3 command fields, which can be set:&lt;br /&gt;
* Python Cmd Path&lt;br /&gt;
:is used if no explicit version is specified in a python action&lt;br /&gt;
* Python3 Cmd Path&lt;br /&gt;
:is used if the python action explicitly asks for python3&lt;br /&gt;
* Python2 Cmd Path&lt;br /&gt;
:is used if the python action explicitly asks for python2&lt;br /&gt;
&lt;br /&gt;
Be aware and reminded, that these are different python interpreter instances: you cannot run both Python2 and Python3 code within the same python interpreter instance.&lt;br /&gt;
&lt;br /&gt;
If not found, either restart expecco (if you installed Python while expecco was active), or enter the full path to your Python interpreter into the path field.&lt;br /&gt;
&lt;br /&gt;
Make sure that the correct Python version is displayed (2.x vs. 3.x) when you click on the &amp;quot;?&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
==== Default cmd paths ====&lt;br /&gt;
&lt;br /&gt;
If no command is specified for one of the Python versions, expecco determines a default path, which is displayed in gray in the corresponding cmd path field.&lt;br /&gt;
&lt;br /&gt;
The following sequence is used until a cmd is found:&lt;br /&gt;
&lt;br /&gt;
*Python-Cmd is empty:&lt;br /&gt;
: &#039;&#039;Python3-Cmd-Path&#039;&#039; → &#039;&#039;Python2-Cmd-Path&#039;&#039; → &#039;&#039;Windows registry entry for Python3&#039;&#039; → &#039;&#039;Windows registry entry for Python2&#039;&#039; → &amp;quot;&#039;&#039;python&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Python3-Cmd is empty:&lt;br /&gt;
: &#039;&#039;Python-Cmd-Path&#039;&#039; → &#039;&#039;Windows registry entry for Python3&#039;&#039; → &amp;quot;&#039;&#039;python3&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Python2-Cmd is empty:&lt;br /&gt;
: &#039;&#039;Python cmd path&#039;&#039; → &#039;&#039;Windows registry entry for Python2&#039;&#039; → &amp;quot;&#039;&#039;python2&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can display the effective Python version by clicking on the &amp;quot;?&amp;quot;-button.&lt;br /&gt;
&lt;br /&gt;
=== Debugging python code ===&lt;br /&gt;
&lt;br /&gt;
==== Debugging in expecco ====&lt;br /&gt;
To make your life easier, install a Python debugger; either:&lt;br /&gt;
 pip install debugpy&lt;br /&gt;
or&lt;br /&gt;
 pip install ptvsd&lt;br /&gt;
(they are more or less interchangeable, but &amp;quot;&amp;lt;code&amp;gt;ptvsd&amp;lt;/code&amp;gt;&amp;quot; is outdated (no longer maintained) and replaced by the newer &amp;quot;&amp;lt;code&amp;gt;debugpy&amp;lt;/code&amp;gt;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Without a Python debugger, breakpoints cannot be placed in bridged Python code,&lt;br /&gt;
and you will not get a debugger on Python exceptions&lt;br /&gt;
(you should then see a warning and hint to install &amp;quot;debugpy&amp;quot; on the Transcript and in the info area).&lt;br /&gt;
&lt;br /&gt;
To ensure that the breakpoints are observed, please uncheck the &amp;quot;Disable debugger&amp;quot; checkbox.&lt;br /&gt;
&lt;br /&gt;
=====Problems with debugging=====&lt;br /&gt;
&lt;br /&gt;
======Debugger does not start======&lt;br /&gt;
&lt;br /&gt;
If the path for Python is specified with the variables &amp;quot;&#039;&#039;%ProgramFiles%&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;%ProgramFiles(x86)%&#039;&#039;&amp;quot;, debugpy does not start.&lt;br /&gt;
&lt;br /&gt;
 Python: failed to enable PythonDebugger on port ..: [WinError 2] the system cannot find the file specified.&lt;br /&gt;
&lt;br /&gt;
The remedy is to use the specific path such as &amp;quot;&#039;&#039;C:\Program Files&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;C:\Program Files (x86)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
======Warnings in output======&lt;br /&gt;
&lt;br /&gt;
 Debugger warning: It seems that frozen modules are being used, which may &lt;br /&gt;
 make the debugger miss breakpoints. Please pass -Xfrozen_modules=off&lt;br /&gt;
 to python to disable frozen modules.&lt;br /&gt;
 Note: Debugging will proceed. Set PYDEVD_DISABLE_FILE_VALIDATION=1 to disable this validation.&lt;br /&gt;
&lt;br /&gt;
In Python 3.11, the core modules essential for Python startup are “frozen”. ... &lt;br /&gt;
This reduces the steps in module execution process. Interpreter startup is now 10-15% faster &lt;br /&gt;
in Python 3.11. This has a big impact for short-running programs using Python.&lt;br /&gt;
&lt;br /&gt;
It&#039;s not possible for the debugger to debug frozen modules as the filename is definitely required to hit breakpoints.&lt;br /&gt;
&lt;br /&gt;
To deactivate the warning, set the environment variable PYDEVD_DISABLE_FILE_VALIDATION to 1, as described in the warning. Notice that the bridge needs to be restarted for the environment variable change to be effective (and possibly even expecco, unless you have specified that variable in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Environment Variables&#039;&#039;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
==== Debugging in an external IDE ====&lt;br /&gt;
For more in depth debugging, you can run the Python bridge in an external IDE (like PyCharm) and use the debug features of the IDE.&lt;br /&gt;
&lt;br /&gt;
For this, you should save the Python bridge code to a file or copy it to the clipboard using the &amp;quot;&#039;&#039;Copy / Save Bridge Code...&#039;&#039;&amp;quot; button. &lt;br /&gt;
Then open this python file in the IDE, and start in debug mode. &lt;br /&gt;
&lt;br /&gt;
The Expecco Python blocks are called in the line:&lt;br /&gt;
 result = actionFn(actionArgs, actionOutPins)&lt;br /&gt;
&lt;br /&gt;
You can then step into the block code with a breakpoint at these lines.&lt;br /&gt;
&lt;br /&gt;
In order for Expecco to connect to this Python bridge (instead of starting a new one), &lt;br /&gt;
you must first tick the checkbox &amp;quot;&#039;&#039;Connect to already running bridge&#039;&#039;&amp;quot; and terminate any previously running Python bridges (via &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Shutdown all Bridge Connections&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
=== pip2 vs. pip3 vs. pip ===&lt;br /&gt;
To install Python packages, use the &amp;quot;&amp;lt;Code&amp;gt;pip&amp;lt;/Code&amp;gt;&amp;quot; command. However, this command is usually a symbolic link to either &amp;quot;&amp;lt;Code&amp;gt;pip2&amp;lt;/Code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;Code&amp;gt;pip3&amp;lt;/Code&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
You should use &amp;quot;&amp;lt;Code&amp;gt;pip3&amp;lt;/Code&amp;gt;&amp;quot; to install packages for python3, and &amp;quot;&amp;lt;Code&amp;gt;pip2&amp;lt;/Code&amp;gt;&amp;quot; for python2. Thus, it is safer to use one of those or &amp;quot;&amp;lt;Code&amp;gt;python3 -m pip install ...&amp;lt;/Code&amp;gt;&amp;quot; instead of &amp;quot;&amp;lt;Code&amp;gt;pip install ...&amp;lt;/Code&amp;gt;&amp;quot; to ensure that the module is installed for the current version.&lt;br /&gt;
&lt;br /&gt;
On some systems, no pip2 command is present by default (and installing python3 will define the &amp;quot;&amp;lt;Code&amp;gt;pip&amp;lt;/Code&amp;gt;&amp;quot; command as an alias to &amp;quot;&amp;lt;Code&amp;gt;pip3&amp;lt;/Code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
To get &amp;quot;pip2&amp;quot; on those systems, execute (on the command line):&lt;br /&gt;
 wget https://bootstrap.pypa.io/get-pip.py&lt;br /&gt;
 python2.7 get-pip.py&lt;br /&gt;
&lt;br /&gt;
Things become even more confusing, if you have multiple python versions installed (for example, python3.7 and python3.9).&amp;lt;br&amp;gt;Then, it is best invoke pip via the python command itself, eg. with:&amp;lt;br&amp;gt;&amp;quot;&amp;lt;code&amp;gt;python3.7 -m pip install ...&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Getting pip ===&lt;br /&gt;
Some Python installers seem to not install pip (at least it happened to us once, that &amp;quot;pip&amp;quot; was not found after a python installation). &lt;br /&gt;
&amp;lt;br&amp;gt;If &amp;quot;python -m pip&amp;quot; gives a warning, do the following:&lt;br /&gt;
* download &amp;quot;https://bootstrap.pypa.io/get-pip.py&amp;quot; (use &amp;quot;&#039;&#039;Save As&#039;&#039;&amp;quot; in a web browser, and save it to the desktop)&lt;br /&gt;
* open a cmd/shell window in that folder.&lt;br /&gt;
* execute &amp;quot;python get-pip.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Jython Installation ==&lt;br /&gt;
Jython is a Python interpreter which runs inside a Java virtual machine, and thus has direct access to Java classes and objects.&amp;lt;br&amp;gt;&lt;br /&gt;
As a prerequisite, Java needs to be installed on your machine.&amp;lt;br&amp;gt;Then goto [ https://www.jython.org/download.html ], download the Jython installer and run it (choose &amp;quot;standard install&amp;quot; or &amp;quot;full install&amp;quot;).&lt;br /&gt;
&amp;lt;br&amp;gt;Remember the target directory. The jython command will be found there.&lt;br /&gt;
&amp;lt;br&amp;gt;If the &amp;quot;jython&amp;quot; command is not in your PATH, enter its full path in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Jython&#039;&#039;&amp;quot; settings dialog. &lt;br /&gt;
&amp;lt;br&amp;gt;However, it is usually better to add the path to your PATH variable (eg. as setup in the Windows environment settings, autoexec.bat or Unix&#039;s login.rc), and just give &amp;quot;jython&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;Notice that previous Jython versions were 2.x Pythons, which will sooner or later become outdated. It is recommended to download or upgrade to a 3.x version (if your code is 3.x compatible).&lt;br /&gt;
&lt;br /&gt;
== Iron Python Installation ==&lt;br /&gt;
IronPython is a Python interpreter which runs inside the Common Language Runtime system, and thus has direct access to C# classes (and of yourse all other objects which live inside the CLR world).&amp;lt;br&amp;gt;&lt;br /&gt;
As a prerequisite, you&#039;ll need a .NET CLR (common language runtime) or mono (on Unix systems). On Windows systems, a reasonable CLR Version is usually already installed.&lt;br /&gt;
&amp;lt;br&amp;gt;Then go to [ https://ironpython.net/download ] or [ https://github.com/IronLanguages/ironpython3 ] and follow the instructions.&lt;br /&gt;
&lt;br /&gt;
After the download, IronPython is typically installed in &amp;quot;&amp;lt;Code&amp;gt;C:\Program Files\IronPython 3.x&amp;lt;/Code&amp;gt;&amp;quot;, and you should enter the path &amp;quot;&amp;lt;Code&amp;gt;C:\Program Files\IronPython x.y\ipy.exe&amp;lt;/Code&amp;gt;&amp;quot; into the IronPython command path field in the python settings dialog (or simply &amp;quot;ipy&amp;quot;, if it is in your PATH).&lt;br /&gt;
&amp;lt;p&amp;gt;Notice that previous IronPython versions were 2.x Pythons, which became obsolete. It is therefore recommended to download or upgrade to a 3.x version (if your code is 3.x compatible).&lt;br /&gt;
&lt;br /&gt;
== Ruby Installation ==&lt;br /&gt;
Goto [ https://rubyinstaller.org/downloads ] and install ruby.&lt;br /&gt;
Then make sure that ruby is in your &amp;lt;code&amp;gt;PATH&amp;lt;/code&amp;gt; setting or set the path to the command in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Ruby&#039;&#039;&amp;quot; settings. Typically it will look like &amp;quot;&amp;lt;code&amp;gt;C:\Ruby32-x64\bin\ruby.exe&amp;lt;/code&amp;gt;&amp;quot; on  windows.&lt;br /&gt;
&amp;lt;br&amp;gt;Create a new Ruby action and execute it to see if it works.&lt;br /&gt;
&lt;br /&gt;
== Julia Installation ==&lt;br /&gt;
Goto [ https://julialang.org/downloads] and install.&lt;br /&gt;
Then make sure that julia is in your &amp;lt;code&amp;gt;PATH&amp;lt;/code&amp;gt; setting or set the path to the command in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Other&#039;&#039;&amp;quot; settings. Typically it will look like &amp;quot;&amp;lt;code&amp;gt;%LOCALAPPDATA%\Programs\Julia-1.10.4\bin\julia.exe&amp;lt;/code&amp;gt;&amp;quot; on  windows.&lt;br /&gt;
&amp;lt;br&amp;gt;Create a new Julia action and execute it to see if it works.&lt;br /&gt;
&lt;br /&gt;
== C Compiler Toolchain Installation (for C-Actions) ==&lt;br /&gt;
&lt;br /&gt;
For a quick verify if the setup is working, create a new (default) bridged C action and execute it (it should generate a &amp;quot;Hello World&amp;quot; message).&lt;br /&gt;
&lt;br /&gt;
==== C Compiler Toolchain Installation ====&lt;br /&gt;
&lt;br /&gt;
You need a C-compiler toolchain to be installed for C-coded actions.&lt;br /&gt;
* On Unix/Linux systems, these are usually already present on the machine (try &amp;quot;&amp;lt;Code&amp;gt;cc --version&amp;lt;/Code&amp;gt;&amp;quot; in a shell window; if you get a reasonable response, you are usually ready to go).&lt;br /&gt;
* On Windows, install one of &amp;quot;Borland&amp;quot;, &amp;quot;VisualC&amp;quot;, &amp;quot;VisualC Redistributable&amp;quot; or &amp;quot;MingGW&amp;quot;.&amp;lt;br&amp;gt;We recommend MingGW.&lt;br /&gt;
* On OSX, you have to install &amp;quot;XCode&amp;quot; or the &amp;quot;Command Line Tools&amp;quot; subset.&lt;br /&gt;
&lt;br /&gt;
===== Windows + Borland (32bit) =====&lt;br /&gt;
* get the free Borland command line tools (see https://borland-c.software.informer.com/5.5) and install them (typically, under &amp;quot;&amp;lt;code&amp;gt;C:\borland\bcc55&amp;lt;/code&amp;gt;&amp;quot;)&lt;br /&gt;
* ensure that the &amp;lt;code&amp;gt;link.cfg&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bcc55.cfg&amp;lt;/code&amp;gt; files are present in the &amp;quot;&amp;lt;code&amp;gt;C:\borland\bcc55\bin&amp;lt;/code&amp;gt;&amp;quot; directory.&lt;br /&gt;
* verify the installation by typing &amp;quot;&amp;lt;code&amp;gt;bcc32&amp;lt;/code&amp;gt;&amp;quot;. A help message should appear.&lt;br /&gt;
* in the expecco settings, goto &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and select the appropriate CC-Script (&amp;quot;&amp;lt;code&amp;gt;compile_windows_bcc.bat&amp;lt;/code&amp;gt;&amp;quot;), which tells the bridge how to compile the C-action code (more below).&lt;br /&gt;
&lt;br /&gt;
===== Windows + Visual-C (32 or 64bit) =====&lt;br /&gt;
* similar to above, check for the &amp;quot;&amp;lt;code&amp;gt;cl&amp;lt;/code&amp;gt;&amp;quot; command.&lt;br /&gt;
* in the expecco settings, goto &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and select the appropriate CC-Script (&amp;quot;&amp;lt;code&amp;gt;compile_windows_vc32.bat&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;compile_windows_vc64.bat&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;compile_windows_vc64_redist.bat&amp;lt;/code&amp;gt;&amp;quot;); see below.&lt;br /&gt;
&lt;br /&gt;
===== Windows + Mingw (32 or 64bit) =====&lt;br /&gt;
* get the mingw64 compiler and install it (best is under &amp;quot;&amp;lt;code&amp;gt;c:\mingw64&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;c:\program files\mingw64&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
* verify the installation by typing &amp;quot;gcc --help&amp;quot;.&lt;br /&gt;
* in the expecco settings, goto &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and select the appropriate CC-Script (&amp;quot;&amp;lt;code&amp;gt;compile_windows_mingw32.bat&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;compile_windows_mingw64.bat&amp;lt;/code&amp;gt;&amp;quot;); see below.&lt;br /&gt;
&lt;br /&gt;
When a C-coded action is about to be executed, its C-code will be compiled &#039;&#039;just in time&#039;&#039; using that toolchain. For that, the cBridge executes a configurable batch or shell script.&amp;lt;br&amp;gt;For some commonly used toolchains, corresponding scripts are provided, but you can or may have to add your own script(s), in case you need special compile options, additional link library options or if you want to compile with a compiler not supported by the standard installation (eg. Intel compilers).&lt;br /&gt;
&lt;br /&gt;
If you get compilation errors, take a look at the &amp;quot;compile_xxx&amp;quot; scripts in &amp;quot;&amp;lt;code&amp;gt;packages/exept/expecco/bridgeFramework/cBridge/cLibrary&amp;lt;/code&amp;gt;&amp;quot; under the expecco installation folder.&lt;br /&gt;
&lt;br /&gt;
If required, add your own script to call whatever compiler you need, and select it in the cBridge settings dialog&lt;br /&gt;
(&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot;). You must also add your own script, if special compiler flags or additional standard paths are to be setup.&lt;br /&gt;
&lt;br /&gt;
Notice, that we currently do not provide compilation scripts for C++; however, by declaring entry-functions (as &amp;lt;code&amp;gt;extern &amp;quot;C&amp;quot;&amp;lt;/code&amp;gt;) in your C++ code, these can be called from C.&lt;br /&gt;
&lt;br /&gt;
If no toolchain is installed, you can still see and edit C-code actions, but obviously not execute them.&lt;br /&gt;
&lt;br /&gt;
===== Windows + Mingw32 =====&lt;br /&gt;
Same as above; recommended installation directories are &amp;quot;&amp;lt;code&amp;gt;c:\mingw32&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;c:\program files\mingw32&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== C Compiler Toolchain at Test-Execution Time ====&lt;br /&gt;
You can tell expecco to embed a pre-compiled object file into the saved &amp;quot;&amp;lt;code&amp;gt;.ets&amp;lt;/code&amp;gt;&amp;quot; suite file (&amp;quot;&#039;&#039;Store Object Files in Project&#039;&#039;&amp;quot; checkbox in the CBridge settings dialog). If checked, C-Bridge actions will be compiled by your current session (using the configured toolchain) and the generated object file(s) will be saved with the suite. When the suite is later executed, no compiler toolchain will be needed on the test machine. Make sure that all required C actions are executed at least once. &lt;br /&gt;
&lt;br /&gt;
Expecco does not include cross compilation support; that means, that only object files for the current architecture can be generated. However, if you load the suite into another architecture&#039;s expecco, additional object files for that other architecture will be generated and added to the &amp;quot;.ets&amp;quot; when saved. So afterwards, object files for both architectures will be present in the ets.&lt;br /&gt;
&lt;br /&gt;
To summarize, if you want to deploy a library with embedded C-actions, which will have to be executed on (say) both a Linux and a Windows machine, where both test-execution machines have no compiler toolchain installed, perform the following steps:&lt;br /&gt;
# load the suite on a Linux machine (with C-compiler toolchain available)&lt;br /&gt;
# ensure that the &amp;quot;&#039;&#039;Store Object Files&#039;&#039;&amp;quot; flag is checked.&lt;br /&gt;
# Save the suite&lt;br /&gt;
# load the saved &amp;quot;.ets&amp;quot; on a Windows machine (with C-toolchain available)&lt;br /&gt;
# Save it again.&lt;br /&gt;
The last saved &amp;quot;.ets&amp;quot; will now contain object files for both architectures.&lt;br /&gt;
Be aware, that you may have to repeat the steps for 32 and 64 bit architectures, if the suite is to be executed eventually on both.&lt;br /&gt;
&lt;br /&gt;
Be reminded that this procedure is not needed, if the machine which executes the tests does have a C-toolchain installed. And especially, if it is the same as your development machine.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Cling_Installation&amp;quot;&amp;gt;Cling Installation&amp;lt;/div&amp;gt; (for RootCling Actions) ==&lt;br /&gt;
&lt;br /&gt;
Support for Cling is &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot; and currently considered an &amp;quot;&#039;&#039;experimental&#039;&#039;&amp;quot; feature which is not available/enabled in the current deployed version.&lt;br /&gt;
&lt;br /&gt;
Cling (aka &amp;quot;Root Cling&amp;quot;) is a dynamic language system for C/C++.&lt;br /&gt;
Code can be entered in C++, which is dynamically (just in time) compiled to fast machine code.&lt;br /&gt;
&lt;br /&gt;
Cling can be downloaded from the [https://root.cern/cling Cern web site] and/or installed via a package installer:&lt;br /&gt;
 &lt;br /&gt;
;Linux:&lt;br /&gt;
: -- see https://root.cern/download/cling/ --&lt;br /&gt;
Download one of the tar archives and unpack the files into some folder (such as &amp;quot;/opt/cling&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
;Windows&lt;br /&gt;
: Sorry, to our knowledge, there exists no ready-to-install version for Windows at the time of writing this document.&lt;br /&gt;
&lt;br /&gt;
;OS X(Mac):&lt;br /&gt;
: &amp;lt;code&amp;gt;brew install cling&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Depending on whether cling is found along your path, or you want to select a particular version,&lt;br /&gt;
specify the cling installation folder in the cling settings dialog &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Cling&#039;&#039;&amp;quot;. &lt;br /&gt;
&amp;lt;br&amp;gt;There, click on the &amp;quot;?&amp;quot; button to verify that cling is found.&lt;br /&gt;
&lt;br /&gt;
== Smalltalk Installation ==&lt;br /&gt;
&lt;br /&gt;
Support for bridged Smalltalk is &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot;, currently disabled and is planned for a future version.&lt;br /&gt;
However, scripted Smalltalk is already available.&lt;br /&gt;
&lt;br /&gt;
== Scheme Installation ==&lt;br /&gt;
&lt;br /&gt;
Support for bridged Scheme is &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot;, currently disabled and is planned for a future version.&lt;br /&gt;
However, scripted Scheme is already available.&lt;br /&gt;
&lt;br /&gt;
You can configure expecco to either use any standard scheme interpreter (whichever is installed as &amp;quot;scheme&amp;quot; command),&lt;br /&gt;
or to use an explicit implementation. Currently, supported are ChezScheme, ChickenScheme and Racket/MZScheme.&lt;br /&gt;
&lt;br /&gt;
=== Chicken Scheme ===&lt;br /&gt;
&lt;br /&gt;
[https://code.call-cc.org Chicken] can be compiled from [https://code.call-cc.org source] or installed via a package manager.&lt;br /&gt;
&lt;br /&gt;
;Windows:&lt;br /&gt;
: https://chocolatey.org/packages/chicken/&lt;br /&gt;
: or:&lt;br /&gt;
: see https://wiki.call-cc.org/platforms#microsoft-windows-&lt;br /&gt;
&lt;br /&gt;
;Linux:&lt;br /&gt;
: see https://wiki.call-cc.org/platforms#linux&lt;br /&gt;
&lt;br /&gt;
;OS X (mac):&lt;br /&gt;
: brew install chicken&lt;br /&gt;
: or:&lt;br /&gt;
: see https://wiki.call-cc.org/platforms#mac-os-x&lt;br /&gt;
&lt;br /&gt;
=== Chez Scheme ===&lt;br /&gt;
&lt;br /&gt;
See [ https://github.com/cisco/ChezScheme ] for instructions.&lt;br /&gt;
&lt;br /&gt;
A Windows binary and sources of release 9.5.4 are found at [ https://github.com/cisco/ChezScheme/releases/tag/v9.5.4 ].&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;GnuPlot_Installation&amp;quot;&amp;gt;GnuPlot Installation&amp;lt;/div&amp;gt; (for Graph Attachments to the Report) ==&lt;br /&gt;
&lt;br /&gt;
Gnuplot makes it easy to add graphs for measurement data or statistics to the&lt;br /&gt;
report and/or to create attachments for them.&lt;br /&gt;
To install gnuplot execute (in a terminal):&lt;br /&gt;
 &lt;br /&gt;
;Linux:&lt;br /&gt;
: -- to be determined and documented --&lt;br /&gt;
: please refer to the official Gnuplot website: http://www.gnuplot.info/download.html&lt;br /&gt;
&lt;br /&gt;
;Windows:&lt;br /&gt;
: -- to be determined and documented --&lt;br /&gt;
: please refer to the official Gnuplot website: http://www.gnuplot.info/download.html&lt;br /&gt;
&lt;br /&gt;
;OS X (Mac):&lt;br /&gt;
: &amp;lt;code&amp;gt;brew install gnuplot&amp;lt;/code&amp;gt;&lt;br /&gt;
: or download a binary package eg. from:&lt;br /&gt;
: &amp;amp;nbsp;https://csml-wiki.northwestern.edu/index.php/Binary_versions_of_Gnuplot_for_OS_X&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;GNU_Octave_Installation&amp;quot;&amp;gt;GNU Octave Installation&amp;lt;/div&amp;gt; (Matlab compatible Scripting) ==&lt;br /&gt;
&lt;br /&gt;
;OS X (Mac):&lt;br /&gt;
: Download a dmg from &lt;br /&gt;
: &amp;amp;nbsp;https://wiki.octave.org/Octave_for_macOS&lt;br /&gt;
: or:&lt;br /&gt;
: &amp;amp;nbsp;https://octave-app.org&lt;br /&gt;
: or:&lt;br /&gt;
: &amp;lt;code&amp;gt;sudo port install octave&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Windows:&lt;br /&gt;
:Download from https://www.gnu.org/software/octave/download.&lt;br /&gt;
&lt;br /&gt;
Warning: octave is huge (roughly 1Gb download).&lt;br /&gt;
&amp;lt;br&amp;gt;Also notice: octave needs gnuplot to generate image files from graphs.&lt;br /&gt;
&lt;br /&gt;
If you are already using Matlab, set the path to the matlab executable in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; [[Settings ExternalToolsSettings/en#GnuOctave_Path | &amp;quot;&#039;&#039;External Script Interpreter&#039;&#039;&amp;quot;]] settings.&lt;br /&gt;
&lt;br /&gt;
==Dart Installation==&lt;br /&gt;
Goto [https://dart.dev/get-dart dart.dev] and follow the instructions there.&lt;br /&gt;
&lt;br /&gt;
==R Installation==&lt;br /&gt;
Goto [https://www.r-project.org/ www.r-project.org] and follow the instructions there.&lt;br /&gt;
&amp;lt;br&amp;gt;OpenSuse users can &amp;quot;&amp;lt;code&amp;gt;zypper install R-base R-base-devel&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Go ==&lt;br /&gt;
For downloads, go to [https://go.dev/dl/ https://go.dev/dl/]. &lt;br /&gt;
&amp;lt;br&amp;gt;OpenSuse users can &amp;quot;&amp;lt;code&amp;gt;zypper install go-devel&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Make sure that go is in your PATH or else define the full pathname to go in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039; &amp;quot;&amp;amp;#8594; &amp;quot;&#039;&#039;Others&#039;&#039;&amp;quot; settings dialog.&lt;br /&gt;
&lt;br /&gt;
== TCL, and all the others ==&lt;br /&gt;
If you use those, you probably know how to install and update them.&lt;br /&gt;
Follow the usual installation instructions and - unless the interpreter is found along your PATH setting, define the path in the expecco &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039; &amp;quot;&amp;amp;#8594; &amp;quot;&#039;&#039;Others&#039;&#039;&amp;quot; settings dialog.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;OCR&amp;quot;&amp;gt;OCR&amp;lt;/div&amp;gt; (Optical Character Recognition) ==&lt;br /&gt;
In order to extract text from bitmap images,&lt;br /&gt;
an OCR framework is needed. It is also needed if you want to automate the local screen or a VNC screen AND you need to extract text or numeric values from it.&lt;br /&gt;
&lt;br /&gt;
Both open source and commercial frameworks can be found and used.&lt;br /&gt;
Good results are achieved by the free (and open source) &amp;quot;Tesseract&amp;quot; framework,&lt;br /&gt;
which we recommended, unless you already have a more powerful non-free commercial OCR framework at hand&lt;br /&gt;
(although supported, we do NOT recommend capture2Text or GNU-ocrad; they do not provide detailed per-word information and/or delivered poor recognition results. At least at the time this document was written).&lt;br /&gt;
&lt;br /&gt;
Tesseract is hosted at [ https://github.com/tesseract-ocr/tessdoc ] and can be downloaded from [ https://github.com/tesseract-ocr/tessdoc/blob/master/Downloads.md ]. &lt;br /&gt;
&amp;lt;br&amp;gt;Follow the installation instructions there. &lt;br /&gt;
&lt;br /&gt;
;Windows and OS X&lt;br /&gt;
:binaries are found at [ https://github.com/UB-Mannheim/tesseract/wiki ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In order to recognize national language characters (eg. accents, diareses/Umlauts), you&#039;ll also need language specific Tesseract-Data files. Please also install those for German, French, etc. from [ https://github.com/tesseract-ocr/tessdata ].&lt;br /&gt;
&lt;br /&gt;
== AI (Tensorflow) ==&lt;br /&gt;
These are typically used via Python actions, and installed using a Python package manager (pip). Please refer to Tensorflow web pages for details.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Tools_ClassBrowser/en&amp;diff=30890</id>
		<title>Tools ClassBrowser/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Tools_ClassBrowser/en&amp;diff=30890"/>
		<updated>2026-02-23T11:06:09Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 25.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
The Class Browser provides full access to the underlying class library and development framework. Both existing code can be browsed (to find and understand code API functions), changed and and new classes can be added with this tool while expecco is running (i.e. &amp;quot;while-running-surgery&amp;quot; or &amp;quot;hot code swap&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
The tool&#039;s [http://live.exept.de/doc/online/english/tools/newbrowser/TOP.html documentation] is part of the official [http://live.exept.de/doc/online/english/TOP.html Smalltalk/X Online Documentation].&lt;br /&gt;
&lt;br /&gt;
This is an expert tool, useful to coders only.&lt;br /&gt;
&lt;br /&gt;
Notice, that you should have checked the &amp;quot;&#039;&#039;Install Source Code&#039;&#039;&amp;quot; toggle in the initial installation; otherwise, the browser will only be able to show the class&#039;s protocol, but not the actual source code. If you did not, please repeat the installation process, checking ONLY the &amp;quot;&#039;&#039;Install Source Code&#039;&#039;&amp;quot; toggle.&lt;br /&gt;
&lt;br /&gt;
Warning: the underlying expecco framework classes are in part open to be viewed and even modified by the Class Browser. This allows for features to be added or fixes to be made even by our customers. We offer this changeability feature as a last-level-safety feature: in a high emergency situation, it may be required to add a fix to ensure ongoing production, even if that contrasts with general engineering practices. On the other side, it opens the door to possible bugs being introduced: you should be very very careful when doing any change to any framework class, and in general, we do NOT recommend it.&lt;br /&gt;
&lt;br /&gt;
== Most Interesting Classes ==&lt;br /&gt;
&lt;br /&gt;
You should use the browser to find additional useful operations, for which no elementary blocks are found in the expecco standard library. Be aware, that there are more than 50000 more-or-less useful functions to be found and used in elementary action blocks, so take your time to investigate the system and don&#039;t get overwhelmed by the sheer number of functions.&lt;br /&gt;
&lt;br /&gt;
A few tricks help to find things quickly:&lt;br /&gt;
&lt;br /&gt;
* install the sources (without, no comments and of course, no source code is shown). The source code is very well documented, and without it, things are much harder to find. By default, the install dialog has this option enabled; unless you explicitly uncheck to toggle in the installation dialog, the sources should be available.&lt;br /&gt;
&lt;br /&gt;
* all classes are classified into groups. For example, all collection classes will be found under the &amp;quot;&#039;&#039;Collections-*&#039;&#039;&amp;quot; category, numbers under &amp;quot;&#039;&#039;Magitude-Numbers&#039;&#039;&amp;quot;, etc. The top-left pane of the browser shows the categories. Look there first.&lt;br /&gt;
&lt;br /&gt;
* if you know the name of the class (or part of it), use the &amp;quot;&#039;&#039;Find Class...&#039;&#039;&amp;quot; menu function in the category list. Use wildcards, if you only know part of the name (or guessed it). For example, &amp;quot;*Array*&amp;quot;, &amp;quot;*Stream*&amp;quot; or &amp;quot;*File*&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* if you know the name of the operation, similar search options exist. Use the &amp;quot;&#039;&#039;Find Implementors...&#039;&#039;&amp;quot; function in the top-right pane. For example, to find all operations which have something to do with hexadecimal encodings, try implementors of &amp;quot;*hex*&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* many classes provide in-code documentation. Switch to the class side (toggle the &amp;quot;&#039;&#039;Class/Instance&#039;&#039;&amp;quot; button and look for methods named &amp;quot;&#039;&#039;documentation&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;examples&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* you can find calls to a function via the &amp;quot;&#039;&#039;Senders of...&#039;&#039;&amp;quot; menu function in the top-right pane. This shows you where and especially how a particular function is used by others in the system. As a example, look for senders of &amp;quot;&#039;&#039;readFrom:*&#039;&#039;&amp;quot; to find string-to-number converters.&lt;br /&gt;
&lt;br /&gt;
=== Classes You Should Know About ===&lt;br /&gt;
&lt;br /&gt;
* [https://live.exept.de/doc/online/english/overview/basicClasses/misc.html Date, Time, Timestamp and TimeDuration]&lt;br /&gt;
&lt;br /&gt;
* [https://live.exept.de/doc/online/english/overview/basicClasses/collections.html Collection (abstract), SequenceableCollection (abstract), Array, ByteArray, CharacterArray, String, Set and Dictionary]. Especially the String class is worth knowing; and remember that it inherits a lot of functionality from its superclasses (CharacterArray, ArrayedCollection, SequentialCollection and Collection).&lt;br /&gt;
&lt;br /&gt;
* [https://live.exept.de/doc/online/english/overview/basicClasses/streams.html ReadStream, WriteStream, ExternalStream, PipeStream, Socket]. All those inherit from Stream, which you should also take a look at.&lt;br /&gt;
&lt;br /&gt;
* Files &amp;amp; Directories: look at Filename and subclasses&lt;br /&gt;
&lt;br /&gt;
* [https://live.exept.de/doc/online/english/overview/basicClasses/numeric.html Number, Float, Integer, Fraction, FixedPoint]&lt;br /&gt;
&lt;br /&gt;
* [https://live.exept.de/doc/online/english/overview/basicClasses/misc.html OperatingSystem: UnixOperatingSystem/WindowsOperatingSystem, -Registry, SocketAddress, OSProcess]&lt;br /&gt;
&lt;br /&gt;
== Interactive (Hot Code Swap) ==&lt;br /&gt;
&lt;br /&gt;
Notice that any change made to the system will be immediately effective. It is even possible to change code in the browser while the code is executing (however, the currently running function will complete its execution and new code will be called with the next invokation)&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
[http://live.exept.de/doc/online/english/TOP.html Smalltalk/X Online Documentation]&lt;br /&gt;
&amp;lt;br&amp;gt;[http://live.exept.de/doc/online/english/programming/syntaxCheatSheet.html Smalltalk/X Syntax Cheat Sheet]&lt;br /&gt;
&amp;lt;br&amp;gt;[http://live.exept.de/ClassDoc Smalltalk/X Class Documentation / Online Reference Manual]&lt;br /&gt;
&lt;br /&gt;
Back to [[Online_Documentation#Tools | Online Documentation]].&lt;br /&gt;
&lt;br /&gt;
[[Category: Tools ]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Glossary/en&amp;diff=30889</id>
		<title>Glossary/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Glossary/en&amp;diff=30889"/>
		<updated>2026-02-23T11:04:12Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 25.11.25&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Action, Step and Activity ==&lt;br /&gt;
In expecco, an &amp;quot;&#039;&#039;Action Block&#039;&#039;&amp;quot; (or &amp;quot;&#039;&#039;Action&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Block&#039;&#039;&amp;quot; for short) refers to the definition of how an action is done. It is therefore also called occasionally &amp;quot;&#039;&#039;Action Definition&#039;&#039;&amp;quot;. In the application, action definitions are found in a tree like organization at the left of the window.&lt;br /&gt;
Actions can be specified in multiple ways:&lt;br /&gt;
* as an activity diagram, with interconnected steps&lt;br /&gt;
* as a list of sequentially executed steps (either as keyword list action or in a test plan)&lt;br /&gt;
* as a piece of code in a programming language&lt;br /&gt;
* as a remote procedure call (service call)&lt;br /&gt;
&lt;br /&gt;
Actions with an activity diagram are called &amp;quot;&#039;&#039;Compound Actions&#039;&#039;&amp;quot;, and their elements are called &amp;quot;&#039;&#039;Steps&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Actions with a sequence list are called &amp;quot;&#039;&#039;Keyword Actions&#039;&#039;&amp;quot;. Test plans are also a kind of sequence list, but provide additional control for execution (looping, skipping, selecting etc.). Although their elements are also technically steps, they are typically named &amp;quot;Test Steps&amp;quot;, &amp;quot;Test Cases&amp;quot; or &amp;quot;Test Plan Items&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;All other actions are called &amp;quot;&#039;Elementary Actions&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
A step is an action being placed (instantiated) in either an activity diagram or a sequence list. &lt;br /&gt;
Notice that the same action can be placed into multiple other compound actions, keyword actions or test plans. Thus, an action definition can be resused (possibly with different parameters) in multiple places.&lt;br /&gt;
&lt;br /&gt;
When a step receives its required input values, it starts executing. For this, a so called &amp;quot;&#039;&#039;Activity&#039;&#039;&amp;quot; is created, which executes the step&#039;s action. Conceptionally, a thread (lightweight process) is created, which executes the step&#039;s action with the given parameters &amp;lt;sup&amp;gt;(1)&amp;lt;/sup&amp;gt;. Also notice, that multiple activities can be active in parallel, even executing the same step at the same time.&lt;br /&gt;
&lt;br /&gt;
Notice that in the literature, the meaning of &amp;quot;Action&amp;quot;, &amp;quot;Step&amp;quot; and &amp;quot;Activity&amp;quot; is often unclear, and the exact definition is often unclear.&lt;br /&gt;
&lt;br /&gt;
See also: [[Tree Elements/en#Action_Blocks|Action Block]] in the [[Tree Elements|&#039;&#039;Tree Elements&#039;&#039;]] documentation.&lt;br /&gt;
&lt;br /&gt;
1) technically a thread pool is used, and a free one is chosen to execute it.&lt;br /&gt;
&lt;br /&gt;
== Activity Log ==&lt;br /&gt;
Whenever expecco executes some action (block), all of its input and output values are recorded in an activity log.&lt;br /&gt;
In addition, explicit and implicit log-messages may be generated (implicit by the execution engine, explicit by calls to &amp;quot;logInfo&amp;quot;, &amp;quot;logWarning&amp;quot; etc. or action steps). In addition, the start- and execution times are recorded.&lt;br /&gt;
&lt;br /&gt;
== AIDYMO==&lt;br /&gt;
Central management system for Automation. Was previously known as expeccoALM.&lt;br /&gt;
&lt;br /&gt;
== Black Box Test ==&lt;br /&gt;
In a [https://en.wikipedia.org/wiki/Black-box_testing &amp;quot;&#039;&#039;Black Box Test&#039;&#039;&amp;quot;], the test-machine and test-application are completely separated from the System Under Test (SUT). No knowledge about the internals (data structures, object model etc.) of the SUT is known when testing. The test only operates against official external interfaces, such as input/output, data and configuration files, command line interfaces, GUI interfaces or communication protocols.&lt;br /&gt;
&lt;br /&gt;
The opposite being a [[#White Box Test|&amp;quot;White Box Test&amp;quot;]], which executes inside the SUT and has full access to all internal details (i.e. functions, data objects etc.).&lt;br /&gt;
&lt;br /&gt;
Expecco supports both, &amp;quot;Black Box&amp;quot; by various libraries which provide interfaces to commonly used external interfaces, and &amp;quot;White Box&amp;quot; via code injection mechanisms, such as &amp;quot;Groovy&amp;quot; or &amp;quot;VisualBasic&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Mixed mode testing is called [https://en.wikipedia.org/wiki/Gray_box_testing &amp;quot;Grey Box Testing&amp;quot; (wikipedia)].&lt;br /&gt;
&amp;lt;br&amp;gt;See also: [[#White Box Test|White Box Test]], [[#Gray Box Test|Gray Box Test]]&lt;br /&gt;
&lt;br /&gt;
== Bridged Actions ==&lt;br /&gt;
&lt;br /&gt;
Expecco uses &amp;quot;&#039;&#039;bridges&#039;&#039;&amp;quot; to implement action blocks written in different programming languages.&lt;br /&gt;
A bridge has two sides, one inside expecco, another inside the external scripting language interpreter, which typically communicate via a socket interprocess communication mechanism.&lt;br /&gt;
Whenever a bridged action block is to be executed, expecco packs the arguments and additional call information into a message and sends it over to the other bridge side. There, the function&#039;s code is executed and a result returned as message back to expecco. &lt;br /&gt;
&lt;br /&gt;
The bridge remains alive, as long as expecco is alive, or the bridge connection is closed explicitly (by the testsuite or via a menu function). &lt;br /&gt;
&lt;br /&gt;
All bridges support code injection, which means that action blocks can be edited inside expecco and are forwarded and installed automatically, when first called. This makes the handling of bridged actions almost transparent and identical to the way in which internal actions (Smalltalk and JavaScript) are handled. For some languages, expecco even includes a debugger with breakpoint-, single step and data inspection features.&lt;br /&gt;
Currently, bridges are provided for Java/Groovy, Node.js, DotNET/CLR, Python, remote Smalltalk and C/C++.&lt;br /&gt;
&lt;br /&gt;
== [[CompoundBlock Element|Compound Action Block]] ==&lt;br /&gt;
An action block which is defined by an activity diagram. Its execution semantics are defined by a network of interconnected steps. These themselves can be compound- or elementary steps.&lt;br /&gt;
&amp;lt;br&amp;gt;See [[CompoundBlock Element/en|Compound Block]] in the [[Tree Elements|&#039;&#039;Tree Elements&#039;&#039;]] documentation.&lt;br /&gt;
&lt;br /&gt;
== [[DiagramElements-Step|Compound Step]] ==&lt;br /&gt;
A step inside an activity diagram, whose action definition is a compound action block. When triggered, such a step will execute another activity diagram.&lt;br /&gt;
&amp;lt;br&amp;gt;See [[CompoundBlock Element/en|Compound Block]] in the [[Tree Elements|&#039;&#039;Tree Elements&#039;&#039;]] documentation.&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;.csf&amp;quot; File ==&lt;br /&gt;
&amp;quot;&#039;&#039;Connection Settings Files&#039;&#039;&amp;quot; are used by the [[Mobile Testing Plugin/en|Mobile Testing]] and [[Selenium WebDriver Plugin/en|Selenium WebDriver]] interfaces. The file is a text file contain lines with key-value pairs in the format:&lt;br /&gt;
 key: value&lt;br /&gt;
each pair specifies an attribute or required capability of the connection.&lt;br /&gt;
Typically, these are generated via the [[Expecco GUI Tests Extension Reference/en|GUI browser&#039;s]] &amp;quot;&#039;&#039;Connection&#039;&#039;&amp;quot; dialog and kept as attachments inside the suite.&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;.csv&amp;quot; File ==&lt;br /&gt;
&amp;quot;&#039;&#039;Comma Separated Values Files&#039;&#039;&amp;quot; are files as generated by Excel and other Spreadsheet programs, by databases and many other record-oriented programs for data interchange. These files represent data records as textual (i.e. human readable) text lines, where the columns (fields) are usually separated by commas (although often semicolon is used as field separator). The very first line of a &amp;quot;csv&amp;quot; file contains the column names.&lt;br /&gt;
Expecco can read and write &amp;quot;csv&amp;quot; files, eg. for parameter sets or via action blocks. It is also possible to give a CSV file to the command line, to preset top-level environment variables from it.&lt;br /&gt;
&lt;br /&gt;
== Dead Key ==&lt;br /&gt;
Prefix key used to enter diacritic characters (eg. Umlaut and accents). If enabled, the keyboard characters &amp;lt;&amp;quot;&amp;gt;, &amp;lt;&#039;&amp;gt;, &amp;lt;^&amp;gt; and &amp;lt;`&amp;gt; will be &#039;&#039;dead&#039;&#039; until a followup character is typed. Then a new character is composed (eg. &amp;lt;ä&amp;gt; from &amp;lt;&amp;quot;&amp;gt; and &amp;lt;a&amp;gt;).&lt;br /&gt;
If followed by a space or the dead key, the dead key is entered. If the combination is invalid, two characters will be entered. &amp;lt;br&amp;gt;Thus, to enter the dead key character alone, press a space as second character (or press the dead key twice). &lt;br /&gt;
&amp;lt;P&amp;gt;Because dead key processing can be inconvenient when entering program source code, they are disabled by default. This default can be changed in the settings dialog under &amp;quot;&#039;&#039;Look and Feel&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Keyboard Settings&#039;&#039;&amp;quot;. In addition, edit text windows provide a popup menu entry to enable/disable deadkey processing as a per editor. See also [https://en.wikipedia.org/wiki/Dead_key wikipedia].&lt;br /&gt;
&lt;br /&gt;
== DLL (Dynamic Link Library) ==&lt;br /&gt;
Are dynamically loadable programs or libraries. In the Unix world, these are typically called &amp;quot;shared objects&amp;quot;.&lt;br /&gt;
Expecco can call into such libraries using elementary DLL-call blocks. These should be used to call driver or utility functions inside a dll, especially if you do not have access to the function&#039;s source code or header definition files.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
See more in [[ElementaryBlock_Element/en#DLL-Calls | Elementary Blocks - DLL Calls]].&lt;br /&gt;
&lt;br /&gt;
== DUT (Device Under Test) ==&lt;br /&gt;
See [[#SUT_.28System_Under_Test.29 | System Under Test]] in this document.&lt;br /&gt;
&lt;br /&gt;
== [[ElementaryBlock Element|Elementary Block]] ==&lt;br /&gt;
An non-compound action block. I.e. any action which is not defined by an activity diagram or keyword list, but either builtin (well known to expecco), a call to an external function or application, or defined programmatically as a piece of textual program code in one of the supported programming languages.&lt;br /&gt;
&amp;lt;br&amp;gt;See [[ElementaryBlock Element/en|Elementary Block]] in the [[Tree Elements|&#039;&#039;Tree Elements&#039;&#039;]] documentation.&lt;br /&gt;
&lt;br /&gt;
== [[DiagramElements-Step|Elementary Step]] ==&lt;br /&gt;
A step inside an activity diagram, whose action definition is an elementary block. When triggered, such a step will execute either a builtin function, an existing function inside a DLL, another program or a piece of code written in one of the programming languages supported by expecco.&lt;br /&gt;
&amp;lt;br&amp;gt;See [[ElementaryBlock Element/en|Elementary Block]] in the [[Tree Elements|&#039;&#039;Tree Elements&#039;&#039;]] documentation.&lt;br /&gt;
&lt;br /&gt;
== Environment ==&lt;br /&gt;
Variables are bundled together in so called &#039;&#039;Environments&#039;&#039;, which are technically collections of key-value pairs (Dictionary/HashTable). Environments can be attached to individual compound actions, to individual testcases, to a testplan and are also attached to the suite. There are also temporary environments attached to the current execution, the current browser window and the current expecco session.&lt;br /&gt;
&lt;br /&gt;
During execution, environments are linked to form a parent-child hierarchy, and variables are fetched along this hierarchy. Thus, variables declared at the block level may shadow variables at the testplan-level, which may shadow variables declared in the current testsuite.&lt;br /&gt;
&amp;lt;br&amp;gt;Typically, the top-level suite&#039;s environment (so called &amp;quot;&#039;&#039;ProjectEnvironment&#039;&#039;&amp;quot;) is used most of the time.&lt;br /&gt;
&lt;br /&gt;
It should be noted, that command line shell variables are also held in a so called &amp;quot;environment&amp;quot;. In this Wiki, this will be named &amp;quot;shell environment&amp;quot; to avoid confusion. However, it should be noted, that the expecco top-level environment will allow for the shell environment to be referenced (as &amp;quot;$(xxx)&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
== Environment Freeze Value ==&lt;br /&gt;
A variable attached to an action step&#039;s input pin. Instead of being provided via a connection from another output pin, this provides a value from an environment variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;.elf&amp;quot; File ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;lt;code&amp;gt;elf&amp;lt;/code&amp;gt;&amp;quot; stands for &amp;quot;&#039;&#039;Expecco Log File&#039;&#039;&amp;quot; and is the native format in which result files are written. &amp;quot;&amp;lt;code&amp;gt;elf&amp;lt;/code&amp;gt;&amp;quot; files contain all of the execution, trace and data-flow information and the original suite as executed. &amp;quot;&amp;lt;code&amp;gt;elf&amp;lt;/code&amp;gt;&amp;quot;-files can be reloaded at any time into the expecco UI, values of that run be inspected and it is even possible to reexecute the original test. Also, any of the other reports can be regenerated, possibly with different report options (i.e. detail). Technically, &amp;quot;&amp;lt;code&amp;gt;elf&amp;lt;/code&amp;gt;&amp;quot; files are zip-containers containing traces, logs and the original test suite in XML-format, and any attachments (screen shots, measurement data etc.) in whatever format they were written (images usually as PNG). They can be read and processed by third party tools (i.e. unzipped, and then processed with an XSL/XSLT ruleset to generate custom reports or to transport the result to any other XML-capable QM system).&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;.ets&amp;quot; File ==&lt;br /&gt;
&amp;quot;&amp;lt;code&amp;gt;ets&amp;lt;/code&amp;gt;&amp;quot; stands for [[#TestSuite Element |&amp;quot;&#039;&#039;Expecco Test Suite&#039;&#039;&amp;quot;]]. These are technically zip-containers, containing the test suite in XML-format and any attachments in whatever format they where imported or generated. In addition, an index (manifest) is present, which allows for fast access to certain information without a need to read the whole zip archive. Also, signatures ensure that the manifest and remaining contents are in sync. Therefore, &amp;quot;&amp;lt;code&amp;gt;.ets&amp;lt;/code&amp;gt;&amp;quot; files should not be manipulated manually, as the consistency of the suite may be harmed.&lt;br /&gt;
&lt;br /&gt;
== expecco ==&lt;br /&gt;
Does the name &amp;quot;expecco&amp;quot; mean anything?&lt;br /&gt;
No, but it is a pun on the latin word &amp;quot;peccare&amp;quot;/&amp;quot;peccō&amp;quot; which means &amp;quot;to make a mistake&amp;quot;, &amp;quot;an error&amp;quot; or &amp;quot;to sin&amp;quot;. So ex-pecco is our answer to get rid of those.&lt;br /&gt;
&lt;br /&gt;
== FMI (Functional Mockup Interface) ==&lt;br /&gt;
see FMU below&lt;br /&gt;
&lt;br /&gt;
== FMU (Functional Mockup Units) ==&lt;br /&gt;
Functional Mockup Units are packaged simulation components, typically written in C (but not required to be), which can be loaded into a simulation framework. FMUs implement a standardized interface (FMI V2.0 / FMI V3.0) and are popular in areas of factory automation, automotive and robotics (see fmi-standard.org https://fmi-standard.org). Starting with release 23, Expecco supports loading, executing and interacting with FMU running both on the local or a remote host.&lt;br /&gt;
&lt;br /&gt;
== Freeze Value ==&lt;br /&gt;
A fix (static) value attached to an action step&#039;s input pin. Instead of being provided via a connection from another output pin, this provides a constant value to an action step&#039;s input.&lt;br /&gt;
Notice that starting with expecco release 19.2, variable references can be embedded inside a String-Freeze-Value using the &amp;quot;&amp;lt;code&amp;gt;$(xxx)&amp;lt;/code&amp;gt;&amp;quot; notation, where &amp;quot;&#039;&#039;xxx&#039;&#039;&amp;quot; is the name of a variable or input pin of the enclosing compound action. See also [[#Environment Freeze Value | Environment Freeze Value]] in this document.&lt;br /&gt;
&lt;br /&gt;
== FTP (File Transfer Protocol) ==&lt;br /&gt;
A [https://datatracker.ietf.org/doc/html/rfc959 standardized protocol] to transfer files between machines. &lt;br /&gt;
&lt;br /&gt;
== Functional ID (FID) ==&lt;br /&gt;
A UUID attached to every action block inside expecco. This identifier is assigned once and never changed again. Inside expecco, actions are referred to via their FID or Version ID, independent of their name. Actions with the same FID are considered to be (possibly different versions) of the same action.&lt;br /&gt;
&lt;br /&gt;
== Gray Box Test ==&lt;br /&gt;
Some knowledge about internal interfaces of the System Under Test are known. For example, data structures or function entries inside the SUT are exploited and used. The categorization of a test as white- or gray box test is vague - there is often no clear line of separation between them.&lt;br /&gt;
&amp;lt;br&amp;gt;See also [[#Black Box Test|Black Box Test]], [[#White Box Test|White Box Test]], [https://en.wikipedia.org/wiki/Gray_box_testing &amp;quot;Grey Box Testing&amp;quot;] in Wikipedia.&lt;br /&gt;
&lt;br /&gt;
== Groovy ==&lt;br /&gt;
A language interpreter which runs on top of a Java Virtual Machine (JVM), with a syntax very similar and almost compatible to Java. Used in expecco to call into Java interfaces or define required callback and listener classes, in case the SUT or the interface to the SUT require those.&lt;br /&gt;
&lt;br /&gt;
Groovy code is compiled to bytecode inside the JVM, which is further Just-in-Time compiled to fast machine code within the target JVM. Thus, it can interface to any Java code (from jar or class files) and it executes at full Java speed.&lt;br /&gt;
&lt;br /&gt;
Expecco allows for Groovy code to be executed both on the local machine (the one on which expecco itself is running) and on remote machines which are reachable via a TCP/IP connection. Multiple of these connections are possible and handled simultaneously in parallel, making it possible to interact with many hosts in a distributed system or when testing both ends of a communication protocol.&lt;br /&gt;
&amp;lt;br&amp;gt;See [[Expecco API/en#Groovy Elementary Blocks|&amp;quot;Groovy Elementary Blocks&amp;quot;]] in the &#039;&#039;Expecco API Document&#039;&#039; and [[ElementaryBlock Element/en|Elementary Block]] in the [[Tree Elements|&#039;&#039;Tree Elements&#039;&#039;]] documentation.&lt;br /&gt;
&lt;br /&gt;
== Groovy Elementary Block ==&lt;br /&gt;
An action block which is defined by an execute function which is written in the Groovy language. The block&#039;s code will be executed by a Groovy interpreter on a Java Virtual Machine (JVM). The JVM may run either on the local or on a remote machine. Expecco uses code injection techniques to implant the code into the SUT dynamically at run time. Except for sealed systems, it is normally not required to specially instrument or otherwise recompile the code in the SUT.&lt;br /&gt;
&amp;lt;br&amp;gt;You have to install &amp;quot;java&amp;quot; from the official website (due to legal reasons, we cannot provide a java interpreter with the expecco installer). &lt;br /&gt;
&amp;lt;br&amp;gt;See [[Expecco API/en#Groovy Elementary Blocks|&amp;quot;Groovy Elementary Blocks&amp;quot;]] in the &#039;&#039;Expecco API Document&#039;&#039; and [[ElementaryBlock Element/en|Elementary Block]] in the [[Tree Elements|&#039;&#039;Tree Elemens&#039;&#039;]] documentation.&lt;br /&gt;
== GUI (Graphical User Interface) ==&lt;br /&gt;
GUI tests and GUI automation refers to processes which control an/or verify an application which has a graphical user interface, such as a Windows, XWindow, Java, JavaSwing, JavaFX, VNC, QT etc. interface. This also includes mobile devices such as iPhone (IOS) and Android devices. &lt;br /&gt;
&lt;br /&gt;
== GUID (Global Unique Identifier) ==&lt;br /&gt;
A synonym for [[#UUID (Universal Unique Identifier) | UUID]].&lt;br /&gt;
&lt;br /&gt;
== Inconclusive State / Test Outcome ==&lt;br /&gt;
See [[#Verdict| &amp;quot;Verdict&amp;quot;]] in this document.&lt;br /&gt;
== IPC ==&lt;br /&gt;
Short for interprocess communication. Typically a socket, pipe or shared memory.&lt;br /&gt;
&lt;br /&gt;
== IronPython Elementary Action Block ==&lt;br /&gt;
Bridged IronPython actions are supported by expecco. IronPython is a python interpreter which runs inside a DOTNET CLR (Common Language Runtime) environment, and has therefore full access to any .NET framework/assembly. It can be used if .NET interfaces are needed, both under native Windows and under Mono (linux/unix/osx).&lt;br /&gt;
&amp;lt;br&amp;gt;You have to install &amp;quot;IronPython&amp;quot; from the official website.&lt;br /&gt;
&amp;lt;br&amp;gt;See [[Expecco_API/en#Bridged_Python_Elementary_Blocks|&amp;quot;Bridged Python Elementary Blocks&amp;quot;]] in the Expecco API document.&lt;br /&gt;
&lt;br /&gt;
== JavaScript Elementary Action Block ==&lt;br /&gt;
An action block which is defined by an execute function which is written in a JavaScript like language. The block&#039;s code will be executed inside expecco itself (as opposed to Node-Action-Blocks, which are executed by an external interpreter).&lt;br /&gt;
&amp;lt;br&amp;gt;See [[Expecco API/en#JavaScript Elementary Blocks|&amp;quot;JavaScript Elementary Blocks&amp;quot;]] in the &#039;&#039;Expecco API Document&#039;&#039; and [[ElementaryBlock Element/en|Elementary Block]] in the [[Tree Elements|&#039;&#039;Tree Elements&#039;&#039;]] documentation.&lt;br /&gt;
&lt;br /&gt;
== JSON ==&lt;br /&gt;
JSON is a common format to exchange structured data, which originated in JavaScript but is now very common and supported by many applications and in almost any programming language. JSON can represent simple (non recursive) objects as textual (i.e. human readable) text, organized as a nested object hierarchy with key-value associations.&lt;br /&gt;
Expecco can read and write JSON both via calls from elementary code and by use of actions from the standard library.&lt;br /&gt;
&amp;lt;br&amp;gt;Because JSON is often used in many other apps, expecco also provides the JSON representation in its data inspector, for easy copy-paste.&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;.json&amp;quot; File ==&lt;br /&gt;
A file containing JSON encoded data. Often used for configuration data.&lt;br /&gt;
&amp;lt;br&amp;gt;Expecco can read and write &amp;quot;json&amp;quot; files, eg. for parameter sets or via action blocks. It is also possible to give a JSON file to the command line, to preset top-level environment variables from it.&lt;br /&gt;
&lt;br /&gt;
== Jython Elementary Action Block ==&lt;br /&gt;
Bridged Jython actions are supported by expecco. Jython is a python interpreter which runs inside a JVM (Java Virtual Machine), and has therefore full access to any Java framework. It can be used as an alternative to Groovy, if Java interfaces are needed.&lt;br /&gt;
&amp;lt;br&amp;gt;You have to install &amp;quot;jython&amp;quot; from the official website.&lt;br /&gt;
&amp;lt;br&amp;gt;See [[Expecco_API/en#Bridged_Python_Elementary_Blocks|&amp;quot;Bridged Python Elementary Blocks&amp;quot;]] in the Expecco API document.&lt;br /&gt;
&lt;br /&gt;
== Node Elementary Action Block ==&lt;br /&gt;
Node.js (or &amp;quot;&#039;&#039;NodeJS&#039;&#039;&amp;quot; or simply &amp;quot;&#039;&#039;Node&#039;&#039;&amp;quot;) is a language interpreter for JavaScript, which is used in cloud computing, Alexa, IOT and other internet applications. Node is rapidly gaining interest and many packages are already available, covering a wide range of protocols, file formats and interfaces. Both bridged and scripted Node.js actions are supported, and expecco includes good support for bridged Node.js action blocks, including breakpoints and debugging with single stepping.&lt;br /&gt;
&amp;lt;br&amp;gt;You have to install &amp;quot;node&amp;quot; and &amp;quot;npm&amp;quot; from the official website: [https://nodejs.org/en/download/ https://nodejs.org/en/download].&lt;br /&gt;
&amp;lt;br&amp;gt;See [[Expecco API/en#Node.js_.28Bridged.29_Elementary_Blocks|&amp;quot;NodeJS Elementary Blocks&amp;quot;]] in the Expecco API document and [[ElementaryBlock Element/en|Elementary Block]] in the [[Tree Elements]] documentation.&lt;br /&gt;
&lt;br /&gt;
== OCR (Optical Character Recognition) ==&lt;br /&gt;
Algorithm which (tries to) extract text from a bitmap image. Expecco can use OCR to extract data from screen- and other images,&lt;br /&gt;
and also to automate screen interaction if no higher level UI-interface can be used (see GUI Browser). &lt;br /&gt;
Both commercial and free OCR frameworks can be used and configured. &lt;br /&gt;
Currently a good choice is the free tesseract OCR framework (see [[Installing_additional_Frameworks/en#OCR_.28Optical_Character_Recognition.29 |Installation notes]] and [[Settings_ExternalToolsSettings/en#External_OCR_Tools_Settings | Configuration notes]].&lt;br /&gt;
&lt;br /&gt;
== OPC-UA (Open Platform Communications Unified Architecture) ==&lt;br /&gt;
Is an industry standard for communication in factory automation and machine control. &lt;br /&gt;
See [https://opcfoundation.org/about/opc-technologies/opc-ua https://opcfoundation.org/about/opc-technologies/opc-ua/].&lt;br /&gt;
&lt;br /&gt;
== Pin - Consuming Pin ==&lt;br /&gt;
An input pin of a step, which does consume its input value when the step starts to execute.&lt;br /&gt;
Technically, this takes the next input value from the queued values pending in the input-basket.&lt;br /&gt;
Consuming pins are used when an input pin gets its value from another step&#039;s output pin.&lt;br /&gt;
&lt;br /&gt;
== Pin - Mailbox (or Telegram) Pin ==&lt;br /&gt;
An input pin of a step, which is delivered to an activity even when it is already executing. Normal pins take their value from an input basket associated with the input pin, and values which arrive after the start of the activity will be held in the basket (queued) for the next activation.&lt;br /&gt;
In contrast, mailbox pins do not enqueue their incoming values, but instead deliver them immediately to the activity - if it is already running. If the activity is not running, mailbox pins behave like regular unbuffered pins, being triggering or not (but typically, they are triggering).&amp;lt;br&amp;gt;Mailbox baskets are typically used to cancel or break out of a loop, eg. in a service providing action block. I.e. they can be used to implement a cancel-pin function, where internal cleanup actions are still needed.&lt;br /&gt;
&lt;br /&gt;
== Pin - Parameter Pin ==&lt;br /&gt;
An input pin of a step, which does not consume its input value and which does not trigger the step.&lt;br /&gt;
Used for constants and parameters, especially if the step is to be used in a loop.&lt;br /&gt;
&lt;br /&gt;
== Pin - Triggering Pin ==&lt;br /&gt;
An input pin of a step, which triggers the execution of a step.&lt;br /&gt;
A step will only start to execute, when all of its triggering pins have received a value.&lt;br /&gt;
&lt;br /&gt;
== Python Elementary Action Block ==&lt;br /&gt;
Both bridged and scripted Python actions are supported by expecco, and also both Python2.x and Python3.x can be used inside the same suite (in addition to Jython and IronPython).&lt;br /&gt;
&amp;lt;br&amp;gt;You have to install &amp;quot;python&amp;quot; and &amp;quot;pip&amp;quot; from the official website: [https://www.python.org/downloads https://www.python.org/downloads]. (see also [[Installing_additional_Frameworks/en#Python_Installation|Installing Additional Frameworks]])&lt;br /&gt;
&amp;lt;br&amp;gt;See [[Expecco_API/en#Bridged_Python_Elementary_Blocks|&amp;quot;Bridged Python Elementary Blocks&amp;quot;]] in the Expecco API document.&lt;br /&gt;
&lt;br /&gt;
== R Script Action Block ==&lt;br /&gt;
R is a programming language which emphasizes on statistics, math and graph plotting.&lt;br /&gt;
&amp;lt;br&amp;gt;You have to install &amp;quot;r&amp;quot; from the official website (see [[Installing_additional_Frameworks/en#R_Installation|Installing Additional Frameworks]]).&lt;br /&gt;
&lt;br /&gt;
== RPC (Remote Procedure Call) ==&lt;br /&gt;
A mechanism by which expecco calls into an external program, such as a Python, NodeJS or C program.&lt;br /&gt;
When a remote procedure call is performed, the name of the operation plus any arguments are packed into a message, transferred to the partner, executed there and finally any results packed again into an answer and transferred back to expecco.&amp;lt;br&amp;gt;Thus there is some overhead and the execution is slower than if directly performed by expecco. Typically a no-operation round trip executes in the order of micro- or even milliseconds, whereas internal operations execute in the order of nano- or microseconds. I.e. roughly 1000 times faster. However, if the actual processing takes long compared to the transmission overhead, or if the partner has exclusive access to some device or software framework, a remote procedure call might be the only mechanism, by which a task can be accomplished.&lt;br /&gt;
&lt;br /&gt;
== REST (Representational State Transfer) ==&lt;br /&gt;
REST is a remote procedure call mechanism based on JSON encoded packages which are typically (but not required to be) transmitted via HTTP. REST was created (probably) out of frustration of SOAP&#039;s complexity.&lt;br /&gt;
&lt;br /&gt;
== Ruby Elementary Action Block ==&lt;br /&gt;
Both bridged and scripted Ruby actions are supported by expecco.&lt;br /&gt;
&amp;lt;br&amp;gt;You have to install &amp;quot;ruby&amp;quot; from the official website [https://rubyinstaller.org/downloads https://rubyinstaller.org/downloads].&lt;br /&gt;
&amp;lt;br&amp;gt;See [[Expecco_API/en#Bridged_Ruby_Elementary_Blocks|&amp;quot;Bridged Ruby Elementary Blocks&amp;quot;]] in the Expecco API document.&lt;br /&gt;
&lt;br /&gt;
== Script Actions ==&lt;br /&gt;
&lt;br /&gt;
Script actions are actions written in one of the supported scripting languages, including Shell, Batch, Powershell, Node.js, Python, Ruby, GnuPlot, R, TCL, Go and others.&lt;br /&gt;
In contrast to &amp;quot;&#039;&#039;bridged actions&#039;&#039;&amp;quot;, these are called as host-commands, where a new interpreter is&lt;br /&gt;
started for every action invokation. This has the advantage, that any existing script can be&lt;br /&gt;
easily used/embedded into a testsuite, but the disadvantage that the action&#039;s execution is somewhat slowed down due to the startup/shutdown times of the external interpreter, and that no state (open files, connections, objects etc.) can be passed from one action to another.&lt;br /&gt;
&lt;br /&gt;
== Shell/Batch Script Elementary Block ==&lt;br /&gt;
An action block which is defined by a shell (or batch) script which is written in a shell command-line-interpreter language. The block&#039;s code will be executed outside expecco, by a script interpreter.&lt;br /&gt;
See [[ElementaryBlock_Element#Shell Script Blocks|&amp;quot;ShellScript Elementary Blocks&amp;quot;]] in the expecco [[ElementaryBlock_Element | elementary block documentation]].&lt;br /&gt;
&lt;br /&gt;
== Smalltalk Programming Language ==&lt;br /&gt;
A pure object oriented language, with sophisticated reflection and meta programming features. See [https://en.wikipedia.org/wiki/Smalltalk Smalltalk in Wikipedia]&lt;br /&gt;
&lt;br /&gt;
== Smalltalk Elementary Block ==&lt;br /&gt;
An action block which is defined by an execute function which is written in the Smalltalk language. The block&#039;s code is usually executed inside expecco itself, but it is also possible to define bridged Smalltalk actions, which execute inside another Smalltalk process (local or remote).&lt;br /&gt;
See [[Expecco_API#Smalltalk_Elementary_Blocks|&amp;quot;Smalltalk Elementary Blocks&amp;quot;]] in the Expecco API Documentation.&lt;br /&gt;
&lt;br /&gt;
== Smalltalk/X ==&lt;br /&gt;
[https://www.smalltalk-x.de Smalltalk/X] (&amp;quot;&#039;&#039;ST/X&#039;&#039;&amp;quot;) is the brand name of a Smalltalk programming language environment from exept / Claus Gittinger. Smalltalk/X is an ANSI compatible [https://en.wikipedia.org/wiki/Smalltalk Smalltalk] programming environment, and the base on which expecco and expeccoALM are built.&lt;br /&gt;
&lt;br /&gt;
== SOAP (Simple Object Access Protocol) ==&lt;br /&gt;
SOAP is a remote procedure call mechanism based on XML encoded packages which are typically (but not required to be) transmitted via HTTP. The name is a euphemism: SOAP is not (no longer) simple: to be used with ease, a huge XML framework lies underneath, which extracts details for a call from a specification written in WSDL (which is also XML with a complex structure, incl. datatype definitions).&lt;br /&gt;
&lt;br /&gt;
== SSDP(Simple Service Discovery Protocol) ==&lt;br /&gt;
Also known as UPnP, the SSDP protocol announces the availability of services via broadcast UDP packages. See [https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol Wikipedia SSDP].&lt;br /&gt;
&lt;br /&gt;
== Stderr ==&lt;br /&gt;
Short for &amp;quot;Standard Error&amp;quot;. This is any program&#039;s standard error output stream. If running in a console window, this is typically displayed there. If running without a console window it may be lost or redirected into a logfile.&lt;br /&gt;
If expecco starts other programs, you have the option of redirecting their stderr to the expecco Transcript (which is the expecco console). There, this will be prefixed by &amp;quot;2:&amp;quot; and colorized in red (to indicate that this is text from stderr, as opposed to stdout). The setting is found in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout/Stderr in Transcript&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Stdin ==&lt;br /&gt;
Short for &amp;quot;Standard Input&amp;quot;. This is any program&#039;s standard input stream. If running in a console window, your typed input is available to the program via this stream. If running without a console window, the program will typically detect an End of File (EOF) condition when reading.&lt;br /&gt;
If expecco starts other programs, you have the option of providing input to the program; either on the very lowest programatic level or via an input pin in an action step.&lt;br /&gt;
&lt;br /&gt;
== Stdout ==&lt;br /&gt;
Short for &amp;quot;Standard Output&amp;quot;. This is any program&#039;s standard output stream. If running in a console window, this is typically displayed there. If running without a console window it may be lost or redirected into a logfile.&lt;br /&gt;
If expecco starts other programs, you have the option of redirecting their stdout to the expecco Transcript (which is the expecco console). There, this will be prefixed by &amp;quot;1:&amp;quot; and colorized in blue (to indicate that this is text from stdout, as opposed to stderr). The setting is found in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout/Stderr in Transcript&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== SUT (System Under Test) ==&lt;br /&gt;
The tested system.&lt;br /&gt;
&lt;br /&gt;
Expecco interacts with this either in a pure [[#Black Box Test | Black Box]] fashion (i.e. only talking to external interfaces), or  [[#Gray Box Test|Gray Box]] or [[#White Box Test|White Box]] fashion (some or a lot of knowledge about internals of the SUT are known).&lt;br /&gt;
&lt;br /&gt;
Technically, Black Box tests interact with the SUT via (more or less official) external interfaces, such as messages, documents, communication interfaces, GUI interaction etc.&lt;br /&gt;
&lt;br /&gt;
White Box tests can access data structures and interfaces internal to the SUT.&lt;br /&gt;
&lt;br /&gt;
In expecco, White Box Tests are done by implanting code into the SUT. Depending on the type of technology and environment used, this code injection (or instrumentation) may be possible dynamically (Java, .NET, Python, Node.js) or has to be done statically by linking expecco-support libraries to the program (C, C++). Static binding is typically required for embedded devices, where the code is stored in non-writable memory. &lt;br /&gt;
&lt;br /&gt;
Some companies (especially if hardware is involved) use the alternative term &amp;quot;DUT&amp;quot; (for &amp;quot;&#039;&#039;Device under Test&#039;&#039;&amp;quot;) instead.&lt;br /&gt;
&lt;br /&gt;
== Syntactic Sugar ==&lt;br /&gt;
A feature of (typically) a programming language, which does not give you more semantic features (aka &amp;quot;&#039;&#039;functionality&#039;&#039;&amp;quot;), but instead exists for the convenience of the user.&amp;lt;br&amp;gt;Typically &amp;quot;&#039;&#039;syntactic sugar&#039;&#039;&amp;quot; designates a feature which is easier to use or shorter to write, but which could also be defined in terms of other features of the language - albeit possibly more clumsy.&amp;lt;br&amp;gt;In expecco, a number of syntactic sugar constructs are available, which could also be described in terms of regular action blocks. For example, the &amp;quot;attachment step&amp;quot;, &amp;quot;shell step&amp;quot; and even &amp;quot;Groovy&amp;quot; steps could be also defined in terms of regular elementary blocks which read a file, start a shell or talk to a JVM respectively.&amp;lt;br&amp;gt;In the Smalltalk programming language, the brace-construct &amp;quot;{ expr1 . expr2 . ... exprN }&amp;quot; is syntactic sugar for Array-instantiation &amp;quot;(Array new:sz) at:1 put:expr1; ... at:n put:exprN; yourself&amp;quot; (btw: you don&#039;t have to understand this, to use expecco).&lt;br /&gt;
&lt;br /&gt;
== Tag ==&lt;br /&gt;
A token (word) attached to an element. Multiple tags can be attached and are used to search, group or otherwise mark tree items, steps and other elements of the test suite. For example, you can define an icon to be shown in the left project tree if the item has a particular tag.&lt;br /&gt;
&lt;br /&gt;
== Tagged Value ==&lt;br /&gt;
A tuple consisting of a token plus value, and an optional type. Similar to tags, these can be attached to an element. Expecco does not use tagged values (*). They are created when suites are imported from some external tools, stored with the suite and passed back transparently to the tool.&lt;br /&gt;
&amp;lt;br&amp;gt;*) this may no longer be true, by the time of reading.&lt;br /&gt;
&lt;br /&gt;
== Testplan Element ==&lt;br /&gt;
A &amp;quot;&#039;&#039;Test Plan&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Testplan&#039;&#039;&amp;quot; is an item in the project tree, which contains a list of test case items to be executed in sequence. A test plan&#039;s items are called &amp;quot;&#039;&#039;Test Cases&#039;&#039;&amp;quot; and each is implemented by an action (elementary or compound). It is also possible to drag another test plan as item into a test plan, to combine multiple tests plans into master test plans. A suite may therefore contain multiple test plans. When started without user interaction, the test plan(s) to be executed can be chosen via the command line or via a remote service request.&lt;br /&gt;
&lt;br /&gt;
== [[TestSuite Element | Testsuite Element]] ==&lt;br /&gt;
&amp;quot;&#039;&#039;Test suite&#039;&#039;&amp;quot; or occasionally &amp;quot;&#039;&#039;Testsuite&#039;&#039;&amp;quot; is the term used for a packaged test project. It contains a collection of [[Tree_Elements| Tree Elements]] like test plans, blocks and datatypes as well as optional resources, attachments and documentation. &lt;br /&gt;
&lt;br /&gt;
Test suites can be imported into other test suites and can therefore be used as libraries for reuse. When a suite is imported into another suite, all of the imported elements are visible and usable inside the importing suite.&lt;br /&gt;
&lt;br /&gt;
Typically, suites are organized in a hierarchical fashion, and low-level functions (device control and access, protocols, data format handling etc.) are packaged into separate libraries, which are used by higher level component test and support actions, which are then further reused by system-, acceptance or end-to-end test scenarios.&lt;br /&gt;
&lt;br /&gt;
== Transcript ==&lt;br /&gt;
The &amp;quot;&#039;&#039;Transcript Window&#039;&#039;&amp;quot; is the expecco console window, which can be opened via &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Transcript&#039;&#039;&amp;quot;. If open, both information messages from expecco and explicit Transcript action messages will appear there. The standard library provides a number of action blocks eg. to send messages and to clear the transcript window. Messages can also be sent to it from elementary code (both internal and bridged).&amp;lt;br&amp;gt;If not open, those messages will be sent to &amp;quot;stderr&amp;quot; instead.&lt;br /&gt;
&lt;br /&gt;
== UI (User Interface) ==&lt;br /&gt;
Ususally a synonym for GUI (Graphical User Interface)&lt;br /&gt;
&lt;br /&gt;
== UUID (Universal Unique Identifier) ==&lt;br /&gt;
An identifier (aka name) which is generated to be globally unique (with very very high probability, to be precise). These are generated and attached to elements of the suite (actions, types, etc.) to ensure that expecco will always be able to correctly identify if two elements from different suites (and/or different people) represent the same thing or not.&lt;br /&gt;
&amp;lt;br&amp;gt;Technically, they are generated by generating a big number, containing a microsecond timestamp, the network address and a big random number, so that two separately generated UUIDs are very very likely to be different. Internally, expecco uses these IDs to reference other elements, thus being tolerant against name changes, layout changes and structure changes (added pins, for example), etc.&amp;lt;BR&amp;gt;Also, expecco can quickly determine if two objects (suites, actions, steps, runs, etc.) represent the same object or not.&lt;br /&gt;
&lt;br /&gt;
Be aware that expecco treats two projects (as loaded from an ETS file) as two versions of the same project iff they have the same functional ID (but different version IDs). Thus, simply saving a project under a different name does not create a new project, and the two cannot be imported both into another project.&lt;br /&gt;
&lt;br /&gt;
== Verdict ==&lt;br /&gt;
&lt;br /&gt;
The execution&#039;s summary-outcome-status from running a test plan, test case or action. In addition to detail information (traces, data, execution time, log-messages), every execution in expecco will always return one of 4 values as a summary status:&lt;br /&gt;
* &#039;&#039;&#039;PASSED&#039;&#039;&#039; (green)&amp;lt;br&amp;gt;if all went well, and the execution did not encounter any problems&lt;br /&gt;
* &#039;&#039;&#039;FAIL&#039;&#039;&#039; (red)&amp;lt;br&amp;gt;the execution detected an error in the [[#SUT (System Under Test)| System Under Test (SUT)]]. &lt;br /&gt;
:For example, it measured a wrong/unexpected value, detected invalid behavior, invalid protocol behavior etc.&lt;br /&gt;
:Usually, this means that the developer of the tested system is to be informed.&lt;br /&gt;
* &#039;&#039;&#039;ERROR&#039;&#039;&#039; (dark red)&amp;lt;br&amp;gt;the test itself ran into some error. &lt;br /&gt;
:This means that during the test&#039;s execution, an error occurred inside expecco or one of the user-defined action blocks. An ERROR state does not provide information about the SUT&#039;s state; instead, the test has a problem. &lt;br /&gt;
:For example, if a file containing test-data could not be found or a division by zero or an index out of bounds error occurred etc.&lt;br /&gt;
:Usually, this means that the developer of the test is to be informed.&lt;br /&gt;
* &#039;&#039;&#039;INCONCLUSIVE&#039;&#039;&#039; (gray)&amp;lt;br&amp;gt;the test had no chance to perform its testing operation(s). &lt;br /&gt;
:For example, if a machine could not be reached in the network, if it was not powered up or if a resource (operator, measurement device, test-device etc.) was not available, etc. Also, tests or actions which have not been executed (eg. skipped) are marked as inconclusive.&lt;br /&gt;
:Usually, this means that the test manager is to be informed.&lt;br /&gt;
&lt;br /&gt;
The distinction is very useful as it should be kept in mind, that a test-manager/tester has to react differently depending on the reason for a test not resulting in a PASSED state:&lt;br /&gt;
* for a FAIL, (s)he has to inform the developer of the SUT, to fix the problem in the product.&lt;br /&gt;
* for an ERROR, the test-developer/analyst has to be informed to fix the problem in the test-case&lt;br /&gt;
* for INCONCLUSIVE, the test-manager, network administrator or test-lab-manager has to check for the availability of required devices , connections, power supply etc.&lt;br /&gt;
:After that, the test can be rerun without a need to contact either the product-development, nor the test-development team.&lt;br /&gt;
&lt;br /&gt;
Notice, that many test systems/frameworks only provide PASS/NOT PASS information as final verdict. &lt;br /&gt;
&amp;lt;br&amp;gt;If expecco is to be integrated into such a framework, FAIL, ERROR and INCONCLUSIVE will all be treated as NON-PASS (e.g. when running under the control of Jenkins, QC, Polarion etc.)&lt;br /&gt;
&lt;br /&gt;
If expecco is executed under the control of expeccoALM/Aidymo, the responsible person is chosen as per verdict and informed.&lt;br /&gt;
&lt;br /&gt;
== VersionID (VID) ==&lt;br /&gt;
Every item within expecco (action, type, testcase, testplan, the suite itself etc.) has an associated unique identifier, which is guaranteed to be world-wide unique (a so called &amp;quot;&#039;&#039;UUID&#039;&#039;&amp;quot;). This guarantees, that these objects can be uniquely identified, even if renamed, or if the same name is used for an action, type etc. in two different test suites. Thus, two suites can always be merged and suites can always be imported without name conflicts.. expecco will internally always refer to any object by its ID, never by its name. The versionID is updated with every change made to an object. Thus it is guaranteed, that no two different objects have the same ID. And vice versa, that the equality (actually identity) can always be checked via the ID.&lt;br /&gt;
&lt;br /&gt;
== VisualWorks ==&lt;br /&gt;
VisualWorks (&amp;quot;&#039;&#039;VW&#039;&#039;&amp;quot;) is the brand name of a Smalltalk programming language environment from Cincom, a US based company. Starting with expecco 20.2, VisualWorks bridged blocks and VisualWorks GUI tests are supported by expecco.&lt;br /&gt;
&lt;br /&gt;
== White Box Test ==&lt;br /&gt;
Designates a test which executes within the &#039;&#039;System Under Test&#039;&#039; and/or uses or refers to (but also depends on) the internals of the [[#SUT|SUT (System Under Test)]]. The test directly creates or manipulates data objects inside the SUT and/or calls internal functions. Most unit tests are typically implemented as white box tests (but not required to be so).&lt;br /&gt;
&lt;br /&gt;
White Box Tests have both advantages and disadvantages.&lt;br /&gt;
&lt;br /&gt;
*+ because they know the internals, more of internal details can be tested, and more of existing internal utilities can be used as utility in the test. For example, data definitions, data structures, functions and interfaces etc. can be accessed from the test system. Depending on the type of test and the available frameworks which can be &amp;quot;white-boxed&amp;quot;, this may save a lot of test-development time, because those interfaces need not be reimplemented in the test system.&lt;br /&gt;
&lt;br /&gt;
*- because they know the internals, they are also more reliant on them, and may also suffer from bugs in the internal frameworks. For one, if data structures and internal interfaces change, the white box test usually has to change with it. Whereas external interfaces usually remain more stable - especially if they are based on communication or data format standards. The other downside is that if internal interfaces of the SUT are heavily used, bugs in them are also injected into the test system. This may make some of the bugs invisible and undetectable to the test system. For example, if a communication data structure (say, a message or document format) is always accessed via a white-boxed SUT interface, but never actually tested physically, any bug in that framework will go unnoticed to both the SUT and to the test system. Both the SUT and the test system may see perfect data, while the data sent to the outside world may still be completely bogus.&lt;br /&gt;
&lt;br /&gt;
In a real world test system, you would usually use a combination of whitebox and blackbox tests. The level of insider-knowledge of the whitebox test depends on the type of SUT, the risk analysis and trust in the frameworks being used.&lt;br /&gt;
&lt;br /&gt;
It is common, that modules and components are first tested by the developers using Unit Tests (which are usually White Box Tests) and then passed on to integrators to check the interaction between modules using Black Box Tests.&lt;br /&gt;
But there is no sharp boundary and often a mix of both is needed in practice (aka &amp;quot;Grey Box Tests&amp;quot;).   &lt;br /&gt;
&lt;br /&gt;
See also: [[#Black Box Test|Black Box Test]], [[#Gray Box Test|Gray Box Test]], &lt;br /&gt;
[https://en.wikipedia.org/wiki/White-box_testing &amp;quot;White-box_testing&amp;quot; (wikipedia) ]&lt;br /&gt;
&lt;br /&gt;
== Workspace (or Notepad) ==&lt;br /&gt;
&lt;br /&gt;
This is a [[Tools_Notepad/en | tool]] which is found in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Notepad&#039;&#039;&amp;quot;. The name is a bit misleading and this should not be confused with the Windows &amp;quot;Notepad&amp;quot; application (therefore, it is also named &amp;quot;Workspace&amp;quot; in the documentation, although this again may lead to confusion, as &amp;quot;workspace&amp;quot; is often used with a different meaning in other contexts, such as the Eclipse IDE).&lt;br /&gt;
&lt;br /&gt;
In expecco, a &#039;&#039;Workspace&#039;&#039; is a little text editor, which can also evaluate snippets written in either Smalltalk or JavaScript. It also provides a number of bulk string processing operations in its edit menu.&lt;br /&gt;
&lt;br /&gt;
Whenever you have to manipulate text, a workspace is a useful edit-tool to perform such tasks (of course, you can use any other editor, if you prefer so, but startup times of external editors are often much longer, than the time it takes expecco to open its internal tools).&lt;br /&gt;
&lt;br /&gt;
[[Tools_Notepad/en | Workspaces]] and all other editors in expecco (incl. the FileBrowser, Data Inspector and Elementary Action code editors) are all based on a common editor base class and have common behavior. Take a look at the popup menu to see what functionality is provided: beside the usual stuff, it can sort text, by columns, filter lines, transform lines and many more. &lt;br /&gt;
&lt;br /&gt;
Especially useful are the &amp;quot;&#039;&#039;Open FileBrowser&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Open URL&#039;&#039;&amp;quot; menu functions (found deeper down in the &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; submenu). Whenever you find a filename or URL in some text, these will quickly open the document for you.&lt;br /&gt;
&lt;br /&gt;
= Abbreviations =&lt;br /&gt;
&lt;br /&gt;
Commonly used abbreviations in this documentation Wiki are:&lt;br /&gt;
&lt;br /&gt;
* ALM - Application Lifecycle Management&lt;br /&gt;
* B2B - Business to Business&lt;br /&gt;
* BD - (Action-) Block Description&lt;br /&gt;
* CB - Compound Block&lt;br /&gt;
* &amp;quot;.csf&amp;quot; - Connection Settings File (file suffix)&lt;br /&gt;
* &amp;quot;.csv&amp;quot; - Comma Separated Values File (file suffix)&lt;br /&gt;
* DCE - Distributed Computing Environment (an RPC mechanism)&lt;br /&gt;
* DLL - Dynamic Link Library (a synonym for &amp;quot;SO&amp;quot; = Shared Object); also a file suffix &amp;quot;.dll&amp;quot;&lt;br /&gt;
* DUT - Device Under Test&lt;br /&gt;
* EB - Elementary Block&lt;br /&gt;
* &amp;quot;.elf&amp;quot; - Expecco Log File (file suffix)&lt;br /&gt;
* &amp;quot;.ets&amp;quot; - Expecco Test Suite (file suffix)&lt;br /&gt;
* FID - Functional ID&lt;br /&gt;
* FTP - File Transfer Protocol (a standard internet protocol)&lt;br /&gt;
* GUI - Graphical User Interface; also sometimes simply &amp;quot;UI&amp;quot;&lt;br /&gt;
* HTTP - Hypertext Transfer Protocol (web page transfer protocol)&lt;br /&gt;
* QM - Quality Management&lt;br /&gt;
* RPC - Remote Procedure Call&lt;br /&gt;
* &amp;quot;.png&amp;quot; - a bitmap image file format (file suffix)&lt;br /&gt;
* SO - Shared Object (a synonym for DLL); also as file suffix &amp;quot;.so&amp;quot;&lt;br /&gt;
* SOAP - Simple Object Access Protocol (a not so simple protocol)&lt;br /&gt;
* SSDP - Simple Service Discovery Protocol&lt;br /&gt;
* SUT - System Under Test&lt;br /&gt;
* UI - User Interface (often actually meaning: Graphical-UI)&lt;br /&gt;
* URL - Unified Resource Locator (typically used with web-Browsers)&lt;br /&gt;
* UUID - Universal Unique Identifier&lt;br /&gt;
* VID - Version ID&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30888</id>
		<title>Release Notes 25.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30888"/>
		<updated>2026-02-23T11:02:27Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 26.x]]&amp;lt;br /&amp;gt;&lt;br /&gt;
See also: [[Release Notes 24.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 25.2 ==&lt;br /&gt;
*Feature: DPI awareness on Windows (i.e. when shown on a &#039;&#039;&#039;high-resolution monitors&#039;&#039;&#039;) [Note: that was a lot of work...] &amp;lt;br&amp;gt; expecco can scale views and fonts according to the scale factor set in the Windows display settings and will do so as default. Scaling by expecco is not perfect yet, e.g. icons do not get scaled.&amp;lt;br&amp;gt;You can enable scaling in &#039;&#039;Settings -&amp;gt; Look&amp;amp;Feel -&amp;gt; More&#039;&#039;.&lt;br /&gt;
*Feature: groovy version 5.0.0 (needed for Java 25 and later)&lt;br /&gt;
*Feature: better bulk int, float and double receiving support in the C bridge (used to be bytes only) &lt;br /&gt;
*Feature: Treat the test result &amp;quot;Pass (Warning)&amp;quot; as &amp;quot;Pass&#039; ([[Settings_DebuggerSettings/en#Treat_test_result_&amp;amp;quot;Pass_(Warning)&amp;amp;quot;_as_&amp;amp;quot;Pass&amp;amp;quot;|Settings: DebuggerSettings]])&lt;br /&gt;
*Improvement: Inspector shows XML Dom if an inspected string starts with &#039;&amp;lt;&#039; and ends with &#039;&amp;gt;&#039; and is XML-parsable without error.&lt;br /&gt;
*Improvement: Very long index-lists (eg. 100k) are handled more gracefully&lt;br /&gt;
*Improvement: Bundled python3 installer updated to version 3.13.7&lt;br /&gt;
*Improvement: Better command and filename completion in the cmd terminal view (Windows)&lt;br /&gt;
*Fix: (Windows) reading the link info of a link file to a wide-char file returned wrong (non-wide) info&lt;br /&gt;
*Fix: blocking WebSockets with huge bulk data transfers&lt;br /&gt;
*Fix: transfer timeout in Bridges with huge data transfers&lt;br /&gt;
*Fix: (Windows): Resource Leak in Font allocation leading to running out of Windows GDI Handles (after a few thousand window openings)&lt;br /&gt;
*Fix: C-Bridge failed to load code when a virus checker has locked the file.&lt;br /&gt;
*Known Issue: When expecco is started &#039;&#039;&#039;for the first time after installation&#039;&#039;&#039;, the Windows virus scan (SmartScreen) may delay the display of the expecco window.&lt;br /&gt;
&lt;br /&gt;
== Release 25.1 ==&lt;br /&gt;
*Improvement: additional &amp;quot;Info&amp;quot; tab in inspector views&lt;br /&gt;
*Improvement: less memory usage in the activity log&lt;br /&gt;
*Improvement: better error messages and more links to settings from the activity log&#039;s error message&lt;br /&gt;
*Improvement: additional units and conversions in the [[PhysicalValues/en|physical values framework]]&lt;br /&gt;
*Improvement: more precision in the [[Numeric_Limits/en#Higher_Precision_Numbers|high precision trigonometric and math functions]]&lt;br /&gt;
*Improvement: WindowsAutomation: Plugin Update to FlaUI 5&lt;br /&gt;
*Improvement: Mobile Testing: Better Device Lock/Unlock Support&lt;br /&gt;
*Improvement: StandardLibrary: &amp;quot;File [ *CSV ]&amp;quot; blocks got an additional &amp;quot;characterEncoding&amp;quot; pin (useful for reading/writing e.g. utf-8 encoded CSV files)&lt;br /&gt;
*Improvement: ExcelLib: better documentation. Now requires the openpyxl package version &amp;gt;= 3.1.5. &lt;br /&gt;
*Improvement: better model language editor (translate and fetch-strings functions)&lt;br /&gt;
*Improvement: ODBCLibrary: improved compatibility with different database vendors (supports the CedarDB database) &lt;br /&gt;
*Feature: translate and spell check in the workspace window&lt;br /&gt;
*Feature: EditLock of suites loaded from expeccoALM / AIDYMO&lt;br /&gt;
*Feature: Start Test in expeccoALM / AIDYMO (via expecco)&lt;br /&gt;
*Feature: new library containing expeccoALM control actions (those from the AIDYMO menu)&lt;br /&gt;
*Fix: the version diff viewer (did not correctly copy changed attachment files)&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Numeric_Limits/en&amp;diff=30887</id>
		<title>Numeric Limits/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Numeric_Limits/en&amp;diff=30887"/>
		<updated>2026-02-23T10:49:19Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 15.2.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides some computer science basics, which are not specific to expecco.&lt;br /&gt;
However, in the past some users encountered problems and it is useful to provide some insight on number representations. &lt;br /&gt;
&lt;br /&gt;
Expecco supports arbitrary precision integer arithmetic,&lt;br /&gt;
arbitrary precision fractions, arbitrary and limited precision floating point numbers in various precisions and complex numbers.&lt;br /&gt;
In addition, special purpose numbers for monetary and decimal presentations.&lt;br /&gt;
&lt;br /&gt;
Being based on Smalltalk/X, expecco provides a complete set of number classes.&lt;br /&gt;
&lt;br /&gt;
== Syntax (In Smalltalk and FreezeValues) ==&lt;br /&gt;
&lt;br /&gt;
See also: &amp;quot;[[Smalltalk_Syntax_Cheat_Sheet]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
====Integers (arbitrary size)====&lt;br /&gt;
 1234567&lt;br /&gt;
 0xFF00AA  (base 16)&lt;br /&gt;
 0b01010101 (base 2)&lt;br /&gt;
 -0xAFFE&lt;br /&gt;
 3r121212 (base 3)&lt;br /&gt;
 4r123123 (base 4)&lt;br /&gt;
&lt;br /&gt;
====Fractions (arbitrary integral numerator and denominator)====&lt;br /&gt;
 (1/2)&lt;br /&gt;
 (1/101)&lt;br /&gt;
 (-1/3)&lt;br /&gt;
&lt;br /&gt;
====ScaledDecimals ====&lt;br /&gt;
 123s2&lt;br /&gt;
 123.456s2&lt;br /&gt;
&lt;br /&gt;
====Floats / Float64 (actually 64bit IEEE doubles)====&lt;br /&gt;
 12.456&lt;br /&gt;
 1e17&lt;br /&gt;
 1.0e23&lt;br /&gt;
 12e&lt;br /&gt;
 .5  -- illegal&lt;br /&gt;
 .5e -- illegal&lt;br /&gt;
&lt;br /&gt;
====LongFloats / Float80 (80bit IEEE long doubles)====&lt;br /&gt;
 12.456q&lt;br /&gt;
 1e17q&lt;br /&gt;
 1.0e23q&lt;br /&gt;
 23q&lt;br /&gt;
&lt;br /&gt;
====QuadFloats / Float128 (128bit IEEE quadruple floats)====&lt;br /&gt;
 12.456Q&lt;br /&gt;
 1e17Q&lt;br /&gt;
 1.0e23Q&lt;br /&gt;
&lt;br /&gt;
====OctupleFloats / Float256 (256bit IEEE octuple floats)====&lt;br /&gt;
 12.456QO&lt;br /&gt;
 1e17QO&lt;br /&gt;
 1.0e23QO&lt;br /&gt;
&lt;br /&gt;
====LargeFloats (arbitrary precision (defaults to 200bit) software floats)====&lt;br /&gt;
 12.456QL&lt;br /&gt;
 1e17QL&lt;br /&gt;
 1.0e23QL&lt;br /&gt;
&lt;br /&gt;
====QDoubles (4 IEEE doubles combined)====&lt;br /&gt;
 12.456QD&lt;br /&gt;
 1e17QD&lt;br /&gt;
 1.0e23QD&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Complex====&lt;br /&gt;
 1+5i&lt;br /&gt;
 4i&lt;br /&gt;
 1.23+5.67i&lt;br /&gt;
&lt;br /&gt;
== Exact Integer Numbers ==&lt;br /&gt;
&lt;br /&gt;
For integer operations, there is no overflow or error in the result for any legal operation. &lt;br /&gt;
I.e. operations on two big integers delivers a correct and exact result.&lt;br /&gt;
&lt;br /&gt;
This is a feature of the underlying Smalltalk runtime environment and in contrast to many other programming languages (especially: Java and C) which provide int (usually 32bit) and long (usually 64bit) integer types.&amp;lt;br&amp;gt;In expecco, you can write both in Smalltalk and in the builtin JavaScript syntax:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 2147483647 &amp;quot;(0x7FFFFFFF)&amp;quot; + 1&lt;br /&gt;
     -&amp;gt; 2147483648 &amp;quot;(0x80000000)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 4294967295 &amp;quot;(0xFFFFFFFF)&amp;quot; + 1&lt;br /&gt;
     -&amp;gt; 4294967296 &amp;quot;(0x100000000)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 18446744073709551615 &amp;quot;(0xFFFFFFFFFFFFFFFF)&amp;quot; + 1&lt;br /&gt;
     -&amp;gt; 18446744073709551616 &amp;quot;(0x10000000000000000)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Very large values can be computed:&lt;br /&gt;
 10000 factorial&lt;br /&gt;
     -&amp;gt; a huge number beginning with: 284625968091705451890641321211986889014....&lt;br /&gt;
&lt;br /&gt;
Smalltalk will automatically convert any result which is too large to fit into a machine-integer into a LargeInteger (with an arbitrary number of bits) and also automatically return results converted back to a small representation, if possible.&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;Thus, although the two operands to the division in the following example are large integers,&lt;br /&gt;
 rslt := (1000 factorial) / (999 factorial)&lt;br /&gt;
the result will be a small integer (since the value 1000 fits easily into a machine word).&lt;br /&gt;
&amp;lt;br&amp;gt;As a user, you do not have to care about these internals.&lt;br /&gt;
&lt;br /&gt;
Hint: Therefore, you can use a [[Tools_Notepad/en |Workspace (Notepad) window]] as a calculator with arbitrary precision.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) be aware that this only computes correct results if the elementary action is written in either Smalltalk or in the builtin JavaScript syntax.&amp;lt;br&amp;gt;Depending on the version of the external language interpreter, it may or may not be correct, if using Java/Groovy, Python, C/C++, Node.js etc.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;) the integer class provides functions which operate in the limited 32 or 64 bit range. These might be useful if you have to verify results or repeat computations as returned by corresponding C or Java operations.&lt;br /&gt;
&lt;br /&gt;
== Exact Fractions, ScaledDecimals and FixedDecimals ==&lt;br /&gt;
=== Fractions ===&lt;br /&gt;
When dividing integers, the &amp;quot;/&amp;quot; operator will deliver an exact result, possibly as a fraction:&lt;br /&gt;
 5 / 3 -&amp;gt; 5/3&lt;br /&gt;
and reduce the result (possibly returning an Integer):&lt;br /&gt;
 (5/3)*(3/2) -&amp;gt; 5/2&lt;br /&gt;
 (5/3)/(3/2) -&amp;gt; 10/9&lt;br /&gt;
 (5/3)*(9/3) -&amp;gt; 5&lt;br /&gt;
 1000 factorial / 999 factorial -&amp;gt; 1000&lt;br /&gt;
&lt;br /&gt;
There are also &#039;&#039;truncating division&#039;&#039; operators: &amp;quot;//&amp;quot;, which returns an integer truncated towards negative infinity (i.e. the next smaller integer),&lt;br /&gt;
and &amp;quot;quo:&amp;quot;. which truncates towards zero.  &amp;quot;quo:&amp;quot; is what you&#039;d get in Java or C.&lt;br /&gt;
&lt;br /&gt;
 5 // 3 -&amp;gt; 1&lt;br /&gt;
 -5 // 3 -&amp;gt; -3&lt;br /&gt;
&lt;br /&gt;
The corresponding modulo operators &amp;quot;\\&amp;quot; and &amp;quot;rem:&amp;quot; provide the remainder, such that:&lt;br /&gt;
 (a // b) + (a \\ b) = a&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;\\&amp;quot; is the standard Smalltalk remainder operator; Smalltalk/X also provides &amp;quot;%&amp;quot; as an alias.&amp;lt;br&amp;gt;Thus you can also write:&lt;br /&gt;
 (a // b) + (a % b) = a&lt;br /&gt;
&lt;br /&gt;
There is also a division operator (&amp;quot;quo:&amp;quot;) which truncates towards zero, and a corresponding remainder operator (&amp;quot;rem:&amp;quot;) , for which:&lt;br /&gt;
 (a quo: b) + (a rem: b) = a&lt;br /&gt;
&lt;br /&gt;
For positive a and b, the two operator pairs deliver the same result.&lt;br /&gt;
For negative arguments, these are different. Be aware and think about the domain of your arguments.&lt;br /&gt;
Be reminded that the Smalltalk remainder &amp;quot;%&amp;quot; returns different results as C or Java, when operands are negative.&lt;br /&gt;
&lt;br /&gt;
In addition, the usual ceiling, floor and rounding operations are available (both on fractions and on limited precision reals):&lt;br /&gt;
 (5 / 3) ceiling -&amp;gt; 2      &amp;quot;the next larger integer&amp;quot;&lt;br /&gt;
 (5 / 3) floor -&amp;gt; 1        &amp;quot;the next smaller integer&amp;quot;&lt;br /&gt;
 (5 / 3) truncated -&amp;gt; 1    &amp;quot;truncate towards zero&amp;quot;&lt;br /&gt;
 (5 / 3) rounded -&amp;gt; 2           &amp;quot;round wrt. fraction &amp;gt;= 0.5)&lt;br /&gt;
 (5 / 3) roundTo: 0.1  -&amp;gt; 1.7.&lt;br /&gt;
 (5 / 3) roundTo: 0.01  -&amp;gt; 1.67&lt;br /&gt;
&lt;br /&gt;
 (-5 / 3) ceiling -&amp;gt; -1.   &amp;quot;the next larger integer&amp;quot;&lt;br /&gt;
 (-5 / 3) floor -&amp;gt; -2      &amp;quot;the next smaller integer&amp;quot;&lt;br /&gt;
 (-5 / 3) truncated -&amp;gt; -1  &amp;quot;truncate towards zero&amp;quot;&lt;br /&gt;
 (-5 / 3) rounded -&amp;gt; -2.&lt;br /&gt;
 (-5 / 3) roundTo: 0.1 -&amp;gt; -1.7&lt;br /&gt;
&lt;br /&gt;
Fractions print themself as &amp;quot;(&#039;&#039;numerator&#039;&#039; / &#039;&#039;denominator&#039;&#039;)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== ScaledDecimal ===&lt;br /&gt;
If you prefer a decimal representation with a defined number of fractional digits,&lt;br /&gt;
use ScaledDecimals (which for backward compatibility are also called &amp;quot;FixedPoint&amp;quot; (&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
These are also exact fractions, but print differently: you can specify the number of digits to be printed and it will print itself rounded on the last digit.&lt;br /&gt;
In other words: the computation and internal value will be exact (as with Fractions), and therefore, no rounding errors will accumulate.&lt;br /&gt;
Only when printed, will the external represenatation be rounded to the specified number of decimal places.&lt;br /&gt;
&lt;br /&gt;
 (5 / 3) asScaledDecimal:2 -&amp;gt; 1.67&lt;br /&gt;
 (5 / 3) asScaledDecimal:4 -&amp;gt; 1.6667&lt;br /&gt;
 &lt;br /&gt;
 ((5 / 3) asScaledDecimal:2) * 3 -&amp;gt; 5.00&lt;br /&gt;
 &lt;br /&gt;
 1.2 asScaledDecimal:3 -&amp;gt; 1.200&lt;br /&gt;
 &lt;br /&gt;
 Float pi asScaledDecimal:5 -&amp;gt; 3.14159&lt;br /&gt;
&lt;br /&gt;
1) the class was previously called &amp;quot;FixedPoint&amp;quot; and the converters were called &amp;quot;asFixedPoint:&amp;quot;. For compatibility with other Smalltalk dialects, these have aliases &amp;quot;ScaledDecimal&amp;quot; and &amp;quot;asScaledDecimal:&amp;quot;.&amp;lt;br&amp;gt;Both the old class name and the old operators are and will be supported in the future for backward compatibility (as aliases),&lt;br /&gt;
but you should use the new name, both for compatibility with other Smalltalk dialects, and to avoid confusion with FixedDecimal numbers.&lt;br /&gt;
&lt;br /&gt;
=== FixedDecimal ===&lt;br /&gt;
As mentioned above, a ScaledDecimal keeps the exact value internally, but prints itself rounded to a given number of decimal digits.&lt;br /&gt;
Smalltalk/X provides an alternative class called &amp;quot;&#039;&#039;FixedDecimal&#039;&#039;&amp;quot; (1), which always keeps a rounded value internally. These may be better suited for monetary values, especially in computed additive sums which are printed in a table, as the sum of two FixedDecimals will always be the presented (printed) sum of two FixedDecimals. In contrast, with ScaledDecimals, you may see a sum which differs from what presented table values suggest.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 v := 50.004 asScaledDecimal:2.&lt;br /&gt;
     v printString -&amp;gt; &#039;50.00&#039;.   &amp;quot;is actually 50.004&amp;quot;&lt;br /&gt;
 v2 := v * 2.&lt;br /&gt;
     v2 printString -&amp;gt; &#039;100.01&#039;. &amp;quot;is actually 100.008&amp;quot; &lt;br /&gt;
&lt;br /&gt;
this leads to confusion, iff such numbers represent monetary values and are printed eg. in a summed-up table.&lt;br /&gt;
&lt;br /&gt;
With FixedDecimals, you&#039;ll get:&lt;br /&gt;
 v := 50.004 asFixedDecimal:2.&lt;br /&gt;
     v printString -&amp;gt; &#039;50.00&#039;.   &amp;quot;is actually 50.00&amp;quot;&lt;br /&gt;
 v2 := v * 2.&lt;br /&gt;
     v2 printString -&amp;gt; &#039;100.00&#039;. &amp;quot;is actually 100.00&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Be aware that mixed arithmetic operations will usually return an instance of the class with a higher generality, and that Floats do have a higher generality than FixedDecimals which have a higher generality than ScaledDecimals. &lt;br /&gt;
&lt;br /&gt;
Thus, when multiplying a float and a fixed decimal, you&#039;ll get a float result, whereas if you multiply an integer and a fixed decimal, the result will be a fixed decimal. Finally, when multiplying a fixed decimal and a scaled decimal, the result will be a fixed decimal.&lt;br /&gt;
&lt;br /&gt;
1) both names &amp;quot;ScaledDecimal&amp;quot; and &amp;quot;FixedDecimal&amp;quot; have been chosen a bit unwise, and may be confusing. However, these cannot easily be changed for backward and cross Smalltalk dialect compatibility reasons. We apologize.&lt;br /&gt;
&lt;br /&gt;
== Inexact Float and Double Numbers ==&lt;br /&gt;
&lt;br /&gt;
Floating point numbers are inherently inexact and almost always represent an approximated value. The error depends on the floating point number&#039;s precision, which is the number of bits with which the value is approximated. there are numbers which cannot ever be repsented as a floating point number, whatever precision is used. Even innocent looking numbers (eg. &amp;quot;0.1&amp;quot;) are of this kind.&lt;br /&gt;
&lt;br /&gt;
This is not a problem specific to expecco,&lt;br /&gt;
but inherent to the way floating point numbers are represented (in the machine). &amp;lt;br&amp;gt;See [https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html &amp;quot;What Every Computer Scientist Should Know About Floating-Point Arithmetic&amp;quot;],&lt;br /&gt;
[https://people.eecs.berkeley.edu/~wkahan/Mindless.pdf &amp;quot;Mindless Assessments of Roundoff in Floating-Point Computation&amp;quot;] and [https://www-users.math.umn.edu/~arnold/disasters &amp;quot;Some disasters attributable to bad numerical computing&amp;quot;].&amp;lt;br&amp;gt;A very impressive example of how wrong double precision IEEE arithmetic can be is described in &amp;quot;[[Do_not_trust_Floating_Point]]&amp;quot; &amp;lt;sup&amp;gt;(1)&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Floating point numbers are represented as a sum of powers of 2 (actually 1/2 + 1/4 + 1/8 +...) called the &amp;quot;&#039;&#039;mantissa&#039;&#039;&amp;quot; then multiplied by 2 raised to an exponent. I.e. &lt;br /&gt;
 value = mantissa * (2 ** exponent)&lt;br /&gt;
with the mantissa being normalized to be a sum in the interval 0.5..1 (as listed above). And the exponent stored with an offset (called &amp;quot;ebias&amp;quot;). The minimum exponent (0) is reserved for the zero number and non-normalized tiny numbers (called &amp;quot;&#039;&#039;subnormals&#039;&#039;&amp;quot;); the maximum exponent is reserved for infinities and NaNs (&amp;quot;&#039;&#039;not a number&#039;&#039;&amp;quot;). These might be returned from some operations if invalid arguments are provided (for example, trying to take a logarithm of a negative number).&lt;br /&gt;
&lt;br /&gt;
The number of exponent bits determines the largest and smallest representable magnitudes, the number of mantissa bits determines the relative error. The error depends on the value of the last mantissa bit, which depends on the exponent. This value is called &amp;quot;&#039;&#039;Unit in the Last Place&#039;&#039;&amp;quot; or &amp;quot;&#039;ULP&#039;&amp;quot; (see [https://en.wikipedia.org/wiki/Unit_in_the_last_place Wikipedia]).&amp;lt;br&amp;gt;For a large number like 1e100, one ULP is the very large 1.94266889222573e+84, whereas for a small number like 0.5, it is 1.11022302462516e-16. &lt;br /&gt;
&lt;br /&gt;
Floating point formats differ in the number of bits (single/double/extended precision etc.).&amp;lt;br&amp;gt;&lt;br /&gt;
A double precision IEEE float has 11 bits for the exponent and 53 for the mantissa (see [https://en.wikipedia.org/wiki/IEEE_754 IEEE floating point formats]).&lt;br /&gt;
&lt;br /&gt;
As a rule of thumb, the error in the last bit of a double precision IEEE float is roughly 15 to 16 orders of magnitudes smaller than the magnitude of the (double precision) floating point number. The error is larger for single precision (32bit) floats and smaller for extended floats (80, 128 or more bits).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: If you do not believe me, try the following example from one of the mentioned papers in (eg. excel) or your favourite programming language:&lt;br /&gt;
 v := 4/3.    &amp;quot;/ or maybe (4.0/3.0)&lt;br /&gt;
 w := v - 1.&lt;br /&gt;
 x := w*3.   &lt;br /&gt;
 y := x - 1.  &lt;br /&gt;
 z := (y*2)**52.    &lt;br /&gt;
&lt;br /&gt;
=== Limited Precision ===&lt;br /&gt;
Due to the limited number of bits in the mantissa, different values may end in the same floating point representation. For example, both 9223372036854776000 and 9223372036854775808 will end up being represented as the same float when converted from integer to float. The reason is that there are simply not enough bits in the mantissa.&lt;br /&gt;
&lt;br /&gt;
For example: &lt;br /&gt;
 9223372036854776000 asFloat = 9223372036854775808 asFloat&lt;br /&gt;
will return &amp;quot;true&amp;quot;, and the difference will be zero in:&lt;br /&gt;
 9223372036854776000 asFloat - 9223372036854775808 asFloat&lt;br /&gt;
in contrast to the correct result being returned when comparing/subtracting them as integers:&lt;br /&gt;
 9223372036854776000 = 9223372036854775808.&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 9223372036854776000 - 9223372036854775808.&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 192&amp;lt;/small&amp;gt;&lt;br /&gt;
Try it in a workspace window.&lt;br /&gt;
&lt;br /&gt;
Also, many numbers (actually: most numbers) cannot be exactly represented by a finite sum of powers of 2. Such numbers will have an error in the last significant bit (actually half the last bit). When floating point numbers are added or multiplied, the result is usually computed internally with a few more bits as mantissa, and then rounded on the last bit, to fit the mantissa&#039;s number of bits. Notice that this may not be immediately obvious, because the print functions (such as printf) cheat, and round again on the last bit. Thus, a result such as 0.9999999 would still be printed as &amp;quot;1.0).&lt;br /&gt;
&lt;br /&gt;
The situation may be relaxed slightly, by using more bits for the mantissa (and expecco gives you a choice of 32bit (called &amp;quot;&#039;&#039;ShortFloat&#039;&#039;&amp;quot;), 64bit (&amp;quot;&#039;&#039;Float&#039;&#039;&amp;quot;) and 80bit (&amp;quot;&#039;&#039;LongFloat&#039;&#039;&amp;quot;) and even more, which are mapped to corresponding IEEE floats (single, double and extended).&lt;br /&gt;
&lt;br /&gt;
Repeating the above example with long floats, there are enough mantissa bits and the numbers are no longer represented or considered equal,&amp;lt;br&amp;gt;thus:&lt;br /&gt;
 9223372036854776000 asLongFloat = 9223372036854775808 asLongFloat &lt;br /&gt;
yields &amp;quot;false&amp;quot; as answer, and the computation:&lt;br /&gt;
 9223372036854776000 asLongFloat - 9223372036854775808 asLongFloat &lt;br /&gt;
will give 192.0 as answer.&lt;br /&gt;
&lt;br /&gt;
However, even with more bits, the fundamental restriction remains, although appearing less frequently with higher precision. But be aware that many numbers (such as 1/10, 1/5, 1/3) can &#039;&#039;&#039;never&#039;&#039;&#039; be represented exactly, no matter how many bits are used. So even the above mentioned innocent looking &amp;quot;0.1&amp;quot; is actually an approximation and wrong in the last bit.&lt;br /&gt;
&lt;br /&gt;
The limited precision may lead to &amp;quot;strange&amp;quot; results, especially when operands are far apart; for example, when subtracting a very small value from a much larger one, as in:&lt;br /&gt;
 2.15e12 - 1.25e-5&lt;br /&gt;
Here, the operands differ by 17 orders of magnitude, and there are not enough bits to represent the result, which will be rounded to give you 2.15e12 again.&lt;br /&gt;
&amp;lt;br&amp;gt;Thus, the comparison &amp;quot;2.15e12 - 1.25e-5 = 2.15e12&amp;quot; returns true and &amp;quot;2.15e12 - (2.15e12 - 1.25e-5) = 0.0&amp;quot;, which are both obviously wrong.&lt;br /&gt;
&amp;lt;br&amp;gt; In this special case, a better result is obtained when operating with extended precision:&lt;br /&gt;
 2.15e12 asLongFloat - 1.25e-5 asLongFloat&lt;br /&gt;
which gives 2149999999999.999987 as result (still incorrect due to its 64 bit mantissa, but much better).&lt;br /&gt;
&lt;br /&gt;
If you are willing to trade speed for precision, you can use one of expecco&#039;s builtin higher precision representations or even the arbitrary precision representation, and compute with more bits of precision. The QDouble class provides a compromise between speed and precision, proving roughly 200 bits of precision or alternatively represents a combination of up to 4 arbitrarily valued doubles (i.e. it can represent the sum of a very large and a small number): &lt;br /&gt;
 (2.15e12 asQDouble) - (1.25e-5 asQDouble)&lt;br /&gt;
 (2.15e12 asQDouble) - ((2.15e12 asQDouble) - (1.25e-5 asQDouble))&lt;br /&gt;
Another representation supports an arbitrary number of precision bits (here 200):&lt;br /&gt;
 (2.15e12 asLargeFloatPrecision:200) - (1.25e-5 asLargeFloatPrecision:200)&lt;br /&gt;
 (2.15e12 asLargeFloatPrecision:200) - ((2.15e12 asLargeFloatPrecision:200) - (1.25e-5 asLargeFloatPrecision:200))&lt;br /&gt;
Both return the correct results 2149999999999.9999875 and 1.25e-5 respectively.&lt;br /&gt;
&lt;br /&gt;
Be aware, that the higher precision and arbitrary precision operations are much slower than the ones which are directly supported by the processor (which has special hardware, usually for single, double and extended precision). Also these extended classes are still being developed and not yet released for official use (meaning they may contain bugs, especially in their trigonometric and other math functions by the time of writing).&lt;br /&gt;
&lt;br /&gt;
You may use fractions, &lt;br /&gt;
 2150000000000 - (1 / 125000)&lt;br /&gt;
to compute the exact result: (268749999999999999/125000)&lt;br /&gt;
(of course, these are less convenent to read, and should probably be presented to the end-user as ScaledDecimals.&lt;br /&gt;
&lt;br /&gt;
Also, do not forget that a conversion of one number to a higher precision number cannot &#039;&#039;magically&#039;&#039; generate missing bits.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, given a 32 bit floating point number which is already an approximation (i.e. the real value cannot be represented as an exact sum of powers of 2),&lt;br /&gt;
then the conversion will give you another such approximation, with the same error.&lt;br /&gt;
Thus, &amp;quot;0.25 asLongFloat&amp;quot; will give you an exact 0.25 (because 0.25 is representable), whereas &amp;quot;0.1 asLongFloat&amp;quot; will not give an exact &amp;quot;0.1&amp;quot;.&lt;br /&gt;
Actually, the result of such a conversion will usually not give you the full possible precision.&lt;br /&gt;
&lt;br /&gt;
If you need a constant with the max. precision, either enter it as such (i.e. &amp;quot;0.1q&amp;quot; instead of &amp;quot;0.1 asLongFloat&amp;quot;) or read it from a string (i.e. LongFloat fromString:&#039;0.1&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Errors Propagate ===&lt;br /&gt;
The above rounding and last bit errors will accumulate, with every math operation performed on it (and may even do so wildly).&lt;br /&gt;
&lt;br /&gt;
For example, the already mentioned 0.1 cannot be exactly represented as a floating point number, and is actually 0.099999..X with an error in the last bit (half a ULP).&lt;br /&gt;
&amp;lt;br&amp;gt;Adding this multiple times will result in a larger and larger error in the final result:&lt;br /&gt;
 1.0 - (0.1 + 0.1 + 0.1 ...(10 times)... + 0.1) -&amp;gt; 1.11022302462516E-16&lt;br /&gt;
&lt;br /&gt;
The print functions will try to compensate for an error in the last bit(s), showing &amp;quot;0.1&amp;quot; although in reality, it is &amp;quot;0.09999...&amp;quot; (it rounds before printing).&lt;br /&gt;
Thus, even though the printed representation of such a number might look ok, it will inject more and more error when the value is used in further operations (up to the point when the error accumulates out of the last bit and print will no longer be able to cheat, and the error becomes visible).&lt;br /&gt;
&lt;br /&gt;
This is especially inconvenient, when monetary values or counts are represented as floats and a final sum is wrong in the penny value&amp;lt;br&amp;gt;(and therefore, a &#039;&#039;real programmer&#039;&#039; will &#039;&#039;&#039;never ever use floating point numbers to represent monetary values&#039;&#039;&#039;!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;As an example, try to sum an array consisting of 10 values:&lt;br /&gt;
 (Array new:10 withAll:0.1) sum printString&lt;br /&gt;
which results in &amp;quot;1.0&amp;quot; due to print&#039;s cheating,&lt;br /&gt;
&amp;lt;br&amp;gt;whereas:&lt;br /&gt;
 (Array new:100 withAll:0.1) sum printString&lt;br /&gt;
will show &#039;9.99999999999998&#039; (i.e. the error accumulated to a value too big for print&#039;s cheating to compensate). &lt;br /&gt;
&lt;br /&gt;
Expecco (actually the underlying Smalltalk) provides additional number representations which are better suited for such computations: Fraction, ScaledDecimal and FixedDecimal (in other systems, ScaledDecimals are also called &amp;quot;&#039;&#039;FixedPoint&#039;&#039;&amp;quot; numbers, and expecco knows that as an alias).&lt;br /&gt;
&lt;br /&gt;
These are exact fractions internally, but use different print strategies: Fractions print as such (i.e. &#039;1/3&#039;, &#039;2/17&#039; etc.) whereas ScaledDecimal and FixedDecimal numbers print themself as decimal expansion (i.e. &#039;0.33&#039; or &#039;0.20&#039;). ScaledDecimal constant numbers can be entered by using &amp;quot;s&amp;quot; instead of &amp;quot;e&amp;quot; (i.e. &#039;1.23s&#039; defines a scaled decimal with 2 and &#039;1.23s4&#039; which will print 4 valid digits after the decimal point).&lt;br /&gt;
&lt;br /&gt;
No such rounding errors are encountered, if fractions are used:&lt;br /&gt;
 1 - ((1/10) + (1/10) + (1/10) ...(10 times)... + (1/10)) -&amp;gt; 0&lt;br /&gt;
or if ScaledDecimal numbers are used:&lt;br /&gt;
 (Array new:100 withAll:0.1s) sum printString -&amp;gt; &#039;10.0&#039;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Number Comparison ===&lt;br /&gt;
Be aware of such errors, and do not compare floating point numbers for equality/inequality. &lt;br /&gt;
&lt;br /&gt;
As a concrete example, try:&lt;br /&gt;
 (0.2 + 0.1 - 0.3) = 0&lt;br /&gt;
which will return &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; and if you print &amp;quot;0.2 + 0.1 - 0.3&amp;quot;, you might get something like: &amp;quot;5.55111512312578e-17&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;Even increasing the precision does not really help; if we went to 200bits precision, we&#039;d still get a small error:&lt;br /&gt;
 (0.2QL + 0.1QL - 0.3QL) printString&lt;br /&gt;
gives &amp;quot;-3.111507638930570853572...e-61&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
The problem also occurs when comparing numbers with different precision. For example, consider that a float32 value is to be compared against a constant. The float32 might be read from a file or provided by a measurement device via any communication mechanism.&lt;br /&gt;
If we compare it against a higher precision value, the missing bits in the shorter float are filled with zeros. Thus:&lt;br /&gt;
 (Float32 readFrom:&#039;0.125&#039;) = 0.125&lt;br /&gt;
leads to a &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; value, whereas:&lt;br /&gt;
 (Float32 readFrom:&#039;0.123&#039;) = 0.123&lt;br /&gt;
returns &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;The reason for this is that 0.125 can be represented as exact float in both float32 and float64 formats, whereas 0.123 is non-exact and has repeated binary digits.&lt;br /&gt;
Its representation as float64 is:&lt;br /&gt;
 0 01111111011 1111011111001110110110010001011010000111001010110000&lt;br /&gt;
and:&lt;br /&gt;
 0 01111011 11110111110011101101101&lt;br /&gt;
as float32.&lt;br /&gt;
When comparing, the float32 is expanded to:&lt;br /&gt;
 0 01111011 111101111100111011011010000000000000000000000000000000&lt;br /&gt;
which is obviously different.&lt;br /&gt;
&lt;br /&gt;
Instead of comparing against a constant, either use range-compares and/or use the special &amp;quot;&#039;&#039;compare-almost-equal&#039;&#039;&amp;quot; functions, where the number of bits of acceptable error can be specified (so called: &amp;quot;&#039;&#039;ULPs&#039;&#039;&amp;quot;). Expecco provides such functions both for elementary code and in the standard action block library.&lt;br /&gt;
&lt;br /&gt;
Again, for this reason, do not compute money values using floats or doubles.&lt;br /&gt;
Instead, use instances of ScaledDecimal.&lt;br /&gt;
Otherwise you might loose a cent/penny here and there, if you use floats/doubles on big budgets.&lt;br /&gt;
&lt;br /&gt;
With scaled decimals, the result is correct:&lt;br /&gt;
 0.1s + 0.2s - 0.3s = 0.  =&amp;gt; true&lt;br /&gt;
and:&lt;br /&gt;
 (0.1 asScaledDecimal + 0.2 asScaledDecimal - 0.3 asScaledDecimal) printString =&amp;gt; 0.00&lt;br /&gt;
&lt;br /&gt;
Find further insight [https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ here]&lt;br /&gt;
&lt;br /&gt;
=== Limited Range of Float and Double Numbers ===&lt;br /&gt;
&lt;br /&gt;
Floating point numbers also have a limited range; there are smallest and largest representable values.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In expecco, the default float format is IEEE double precision format (called &amp;quot;&#039;&#039;Float&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Float64&#039;&#039;&amp;quot; in expecco).&lt;br /&gt;
Numbers with an absolute value greater than 1.79769313486232E+308 will lead to a +INF/-INF&lt;br /&gt;
(infinite) result, and numbers with absolute value smaller than 2.2250738585072E-308 will be zero. &lt;br /&gt;
&lt;br /&gt;
For IEEE single precision floats (called &amp;quot;&#039;&#039;ShortFloat&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Float32&#039;&#039;&amp;quot; in expecco), the range is much smaller, and for IEEE extended precision (called &amp;quot;&#039;&#039;LongFloat&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Float80&#039;&#039;&amp;quot; in expecco), the range is larger.&lt;br /&gt;
&lt;br /&gt;
You can ask the classes (or its instances &amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) for their limits, with: &lt;br /&gt;
* fmin (smallest representable number larger than zero) &lt;br /&gt;
* fmax (largest representable number),&lt;br /&gt;
* emin (smallest exponent; binary) &lt;br /&gt;
* emax (largest exponent binary),&lt;br /&gt;
* precision (bits in mantissa, incl. any hidden bit),&lt;br /&gt;
* decimalPrecision (digits when printed),&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;small&amp;gt;remember Float is the same as Float64&amp;lt;/small&amp;gt;&lt;br /&gt;
 Float fmin -&amp;gt; 2.2250738585072E-308&lt;br /&gt;
 Float fmax -&amp;gt; 1.79769313486232E+308&lt;br /&gt;
 Float emin -&amp;gt; -1022&lt;br /&gt;
 Float emax -&amp;gt; 1023&lt;br /&gt;
 Float precision -&amp;gt; 53&lt;br /&gt;
 Float decimalPrecision -&amp;gt; 15&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;small&amp;gt;remember ShortFloat is an alias for Float32&amp;lt;/small&amp;gt;&lt;br /&gt;
 ShortFloat fmin -&amp;gt; 1.175494e-38&lt;br /&gt;
 ShortFloat fmax -&amp;gt; 3.402823e+38&lt;br /&gt;
 ShortFloat emin -&amp;gt; -126&lt;br /&gt;
 ShortFloat emax -&amp;gt; 127&lt;br /&gt;
 ShortFloat precision -&amp;gt; 24&lt;br /&gt;
 ShortFloat decimalPrecision -&amp;gt; 7&lt;br /&gt;
  &lt;br /&gt;
 &amp;lt;small&amp;gt;remember LongFloat is an alias for Float80&amp;lt;/small&amp;gt;&lt;br /&gt;
 LongFloat fmin -&amp;gt; 3.362103143112093506E-4932&lt;br /&gt;
 LongFloat fmax -&amp;gt; 1.189731495357231765E+4932&lt;br /&gt;
 LongFloat emin -&amp;gt; -16382&lt;br /&gt;
 LongFloat emax -&amp;gt; 16383&lt;br /&gt;
 LongFloat precision -&amp;gt; 64&lt;br /&gt;
 LongFloat decimalPrecision -&amp;gt; 19&lt;br /&gt;
  &lt;br /&gt;
 &amp;lt;small&amp;gt;QuadFloat is an alias for Float128&amp;lt;/small&amp;gt;&lt;br /&gt;
 Float128 fmin -&amp;gt; 3.36210314311209350626267781732e-4932&lt;br /&gt;
 Float128 fmax -&amp;gt; 1.18973149535723176508575932662e+4932&lt;br /&gt;
 Float128 emin -&amp;gt; -16382&lt;br /&gt;
 Float128 emax -&amp;gt; 16383&lt;br /&gt;
 Float128 precision -&amp;gt; 113&lt;br /&gt;
 Float128 decimalPrecision -&amp;gt; 34&lt;br /&gt;
  &lt;br /&gt;
 &amp;lt;small&amp;gt;OctaFloat is an alias for Float256&amp;lt;/small&amp;gt;&lt;br /&gt;
 Float256 fmin -&amp;gt; 2.48242795146434978829932822291387172...5329791379e-78913&lt;br /&gt;
 Float256 fmax -&amp;gt; 1.61132571748576047361957211845200501...7125049607e+78913&lt;br /&gt;
 Float256 emin -&amp;gt; -262142&lt;br /&gt;
 Float256 emax -&amp;gt; 262143&lt;br /&gt;
 Float256 precision -&amp;gt; 237&lt;br /&gt;
 Float256 decimalPrecision -&amp;gt; 71&lt;br /&gt;
 &lt;br /&gt;
 QDouble fmin -&amp;gt; &amp;lt;small&amp;gt;same as float64&amp;lt;/small&amp;gt;&lt;br /&gt;
 QDouble fmax -&amp;gt; &amp;lt;small&amp;gt;same as float64&amp;lt;/small&amp;gt;&lt;br /&gt;
 QDouble emin -&amp;gt; &amp;lt;small&amp;gt;same as float64&amp;lt;/small&amp;gt;&lt;br /&gt;
 QDouble emax -&amp;gt; &amp;lt;small&amp;gt;same as float64&amp;lt;/small&amp;gt;&lt;br /&gt;
 QDouble precision -&amp;gt; 204&lt;br /&gt;
 QDouble decimalPrecision -&amp;gt; 61&lt;br /&gt;
 &lt;br /&gt;
 aLargeFloat fmin -&amp;gt; 0.0 &amp;lt;small&amp;gt;arbitrary small&amp;lt;/small&amp;gt; &amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
 aLargeFloat fmax -&amp;gt; inf &amp;lt;small&amp;gt;arbitrary large&amp;lt;/small&amp;gt;&lt;br /&gt;
 aLargeFloat emin -&amp;gt; -inf &amp;lt;small&amp;gt;arbitrary small&amp;lt;/small&amp;gt;&lt;br /&gt;
 aLargeFloat emax -&amp;gt; inf &amp;lt;small&amp;gt;arbitrary large&amp;lt;/small&amp;gt;&lt;br /&gt;
 aLargeFloat precision -&amp;gt; 200 &amp;lt;small&amp;gt;default; configurable&amp;lt;/small&amp;gt;&lt;br /&gt;
 aLargeFloat decimalPrecision -&amp;gt; 60 &amp;lt;small&amp;gt;default; configurable&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember that the name &amp;quot;Float&amp;quot; refers to &amp;quot;Float64&amp;quot;, which is called &amp;quot;double&amp;quot; in the C language.&lt;br /&gt;
And also remember that the name &amp;quot;ShortFloat&amp;quot; refers to &amp;quot;Float32&amp;quot;, which is called &amp;quot;float&amp;quot; in C.&lt;br /&gt;
And finally, the name &amp;quot;LongFloat&amp;quot; refers to &amp;quot;Float80&amp;quot;, which is called &amp;quot;long double&amp;quot; in C.&lt;br /&gt;
&lt;br /&gt;
As a consequence of the limits, you cannot compute very large numbers using any of the CPU supported floats, and you will have to use one of the software computed float representations.&lt;br /&gt;
&amp;lt;br&amp;gt;For example trying to compute the number of decimal digits of a huge number:&lt;br /&gt;
 10000 factorial asFloat log10 -&amp;gt; INF&lt;br /&gt;
I.e. it returns infinity, because 10000 factorial asFloat already returns INF.&lt;br /&gt;
(it could have been converted with &amp;quot;asFloatChecked&amp;quot; which raises an exception in that situation, which is probably a good idea to do.&lt;br /&gt;
However, the regular asFloat conversion uses the underlying machine&#039;s CPU support, which returns INF, and is similar to the behavior in other programming languages).&lt;br /&gt;
&lt;br /&gt;
In contrast, the integer computation does it:&lt;br /&gt;
 10000 factorial log10 -&amp;gt; 35659.454274&lt;br /&gt;
&lt;br /&gt;
Again: this is not a problem specific to expecco,&lt;br /&gt;
but inherent to the way floating point numbers are represented in the CPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;because LargeFloats have an individual number of precision (per instance), you should ask the instance, not the class. The class will return the default values (which are valid for 200 bits of resolution).&lt;br /&gt;
&lt;br /&gt;
=== Speed of Operations ===&lt;br /&gt;
Machines have builtin floating point math operations, which usually work fastest in single or double precision (actually, some modern machines work faster in double than in single precision).&lt;br /&gt;
&lt;br /&gt;
Unless you have special precision needs, it is best to stick with double precision which is also portable across machines.&lt;br /&gt;
Therefore, double precision floats (aka &amp;quot;&#039;&#039;double&#039;&#039;&amp;quot;) is the default and simply named &amp;quot;&#039;&#039;Float&#039;&#039;&amp;quot; in Smalltalk/X (and therefore also in expecco) &amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;The reason for calling them &amp;quot;Float&amp;quot; is historic. There exist smalltalk dialects where Floats are 32bit IEEE floats, and others where they are 64bit. To be able to import code from either dialect, Smalltalk/X uses double precision for &amp;quot;Float&amp;quot;.&amp;lt;br&amp;gt;To make you intention clear, it is recommended to use the explicit names &amp;quot;Float32&amp;quot;, &amp;quot;Float64&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
== Trigonometric and other Math Functions ==&lt;br /&gt;
&lt;br /&gt;
Some trigonometric and other math functions (sqrt, log, exp)&lt;br /&gt;
will first convert the number to a limited precision real number (a C-double),&lt;br /&gt;
and therefore may have a limited input value range and also generate inexact results.&lt;br /&gt;
&lt;br /&gt;
For example, you will not get a valid result for:&lt;br /&gt;
 10000 factorial sin&lt;br /&gt;
because it is not possible to represent that large number as real number.&lt;br /&gt;
(expecco will signal a domain error, as the input to sin will be +INF)&lt;br /&gt;
&lt;br /&gt;
Also, the result from:&lt;br /&gt;
 (9 / 64) sqrt&lt;br /&gt;
will be the (inexact) 0.375 (a double), instead of the exact 3/4 (a fraction).&lt;br /&gt;
(this might change in a future release and provide exact results if both numerator and denominator are perfect squares)&lt;br /&gt;
&lt;br /&gt;
You can however first convert to a higher precision float and then apply the function. These will compute using a Taylor series or Newton approximation taking the number&#039;s precision into account:&lt;br /&gt;
&lt;br /&gt;
 2 sqrt&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 1.4142135623731 (computed with float64 precision)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 2 asFloat128 sqrt&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 1.41421356237309504880168872421&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 2 asFloat256 sqrt&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 1.41421356237309504880168872420969807856967187537694807317667973799073&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (2 asLargeFloatPrecision:500) sqrt&lt;br /&gt;
 &amp;lt;small&amp;gt;=&amp;gt; 1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214971&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Complex Results==&lt;br /&gt;
By default, Smalltalk/X will raise an error if the result of a function with a real operand would return a complex result.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, computing the square root of a negative number as in:&lt;br /&gt;
 -2 sqrt&lt;br /&gt;
will raise an &amp;quot;ImaginaryResultError&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
However, this is a &#039;&#039;proceedable exception&#039;&#039; &amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;, which can be caught and if the handler proceeds, a complex result is returned:&lt;br /&gt;
 rslt := ImaginaryResultError ignoreIn:[ -2 sqrt ].&lt;br /&gt;
for readability, there is also an alias called &amp;quot;trapImaginary:&amp;quot; in the number class:&lt;br /&gt;
 rslt := Number trapImaginary:[ -2 sqrt ]&lt;br /&gt;
&lt;br /&gt;
Both of the above would return the complex result:&lt;br /&gt;
 (0+1.4142135623731 i)&lt;br /&gt;
&lt;br /&gt;
Thus,&lt;br /&gt;
 rslt := -2 sqrt squared&lt;br /&gt;
will result in an exception, whereas:&lt;br /&gt;
 rslt := Number trapImaginary:[ -2 sqrt squared]&lt;br /&gt;
will generate a result of &amp;quot;-2.0&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All operations within &amp;quot;[&amp;quot; .. &amp;quot;]&amp;quot; which would produce an ImaginaryResultError will return a complex. Thus you can write:&lt;br /&gt;
 Number trapImaginary:[ &lt;br /&gt;
    |num1 num2|&lt;br /&gt;
 &lt;br /&gt;
    num1 := -2 sqrt.&lt;br /&gt;
    num2 := -3 sqrt.&lt;br /&gt;
    Transcript showCR: (num1 + num2).&lt;br /&gt;
 ]&lt;br /&gt;
and &amp;quot;(0+3.14626436994197i)&amp;quot; will be shown.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Proceedable exceptions are among the unique features of the Smalltalk programming language; exceptions may be raised as being proceedable, and an exception handler may then &amp;quot;proceed&amp;quot; and provide an alternative return value from the failed operation. This mechanism is used here, where the exception handler - if pesent - can decide to return an imaginary result.&lt;br /&gt;
&lt;br /&gt;
== Undefined Results, NaN and Domain Errors ==&lt;br /&gt;
Similar to the way imaginary results are handled, some operations are not defined for certain values (values outside the function&#039;s domain).&lt;br /&gt;
&amp;lt;br&amp;gt;For example, the receiver of the &amp;lt;code&amp;gt;arcSin&amp;lt;/code&amp;gt; operation must be in [-1 .. 1].&lt;br /&gt;
&lt;br /&gt;
By default, these situations are also reported by raising an error, and therefore:&lt;br /&gt;
 -2 arcSin&lt;br /&gt;
will raise such a &amp;quot;DomainError&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
Similar to the above, this can be handled, although no useful value will be provided (in the above case, NaN (Not a Number) will be returned:&lt;br /&gt;
 rslt := DomainError ignoreIn:[ -2 arcSin ]&lt;br /&gt;
or:&lt;br /&gt;
 rslt := Number trapDomainError:[ -2 arcSin ].&lt;br /&gt;
&lt;br /&gt;
Both of the above would generate a NaN as result.&lt;br /&gt;
&lt;br /&gt;
Notice that if such a NaN is used in other arithmetic operations, either more exceptions or other NaNs will usually be generated (depending on the exception being handled or not).&lt;br /&gt;
&amp;lt;br&amp;gt;Thus:&lt;br /&gt;
 rslt := Number trapDomainError:[ -2 arcSin sin ].&lt;br /&gt;
will also generate a NaN as result.&lt;br /&gt;
&lt;br /&gt;
You can check for valid results with:&lt;br /&gt;
 &#039;&#039;aNumber&#039;&#039; isNaN               - true for NaN&lt;br /&gt;
 &#039;&#039;aNumber&#039;&#039; isInfinite          - true for infinities&lt;br /&gt;
 &#039;&#039;aNumber&#039;&#039; isPositiveInfinity  - true for +inf&lt;br /&gt;
 &#039;&#039;aNumber&#039;&#039; isNegativeInfinity  - true for -inf&lt;br /&gt;
 &#039;&#039;aNumber&#039;&#039; isFinite            - false for NaN or infinities (i.e. true for valid numbers)&lt;br /&gt;
&lt;br /&gt;
== Overflow ==&lt;br /&gt;
When an operation&#039;s arguments are OK, but the result falls outside the range of representable numbers [fmin..fmax], you will get an infinite result &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;.&amp;lt;br&amp;gt;Further operations on these might produce more infinities or a NaN (&amp;quot;&#039;&#039;Not a Number&#039;&#039;&amp;quot;).&lt;br /&gt;
This may be especially troublesome, if a final result gets corrupted due to an intermediate computation, as in:&lt;br /&gt;
 a := 1e+10.&lt;br /&gt;
 b := 1e+300.&lt;br /&gt;
 c := 1e+20.&lt;br /&gt;
 d := 1e+300.&lt;br /&gt;
 &lt;br /&gt;
 rslt := (a*b) / (c*d)&lt;br /&gt;
   -&amp;gt; NaN&lt;br /&gt;
Here, the final result is certainly representable, but the intermediate values (1e10 * 1e300) are out of the Float range [2.225E-308 .. 1.796e+308]. Thus, the computation will be:&lt;br /&gt;
 a := 1e+10.&lt;br /&gt;
 b := 1e+300.&lt;br /&gt;
 c := 1e+20.&lt;br /&gt;
 d := 1e+300.&lt;br /&gt;
 &lt;br /&gt;
 (a*b) -&amp;gt; INF&lt;br /&gt;
 (c*d) -&amp;gt; INF&lt;br /&gt;
 INF / INF -&amp;gt; NaN&lt;br /&gt;
If the above intermediates are computed with a higher precision, the final result will be correct:&lt;br /&gt;
 a := 1e+10.&lt;br /&gt;
 b := 1e+300.&lt;br /&gt;
 c := 1e+20.&lt;br /&gt;
 d := 1e+300.&lt;br /&gt;
 &lt;br /&gt;
 t := (a asLongFloat * b asLongFloat) / (c asLongFloat * d asLongFloat).&lt;br /&gt;
 rslt := t asFloat&lt;br /&gt;
   -&amp;gt; 1e-10&lt;br /&gt;
&lt;br /&gt;
Of course, with LongFloats, the problem is only shifted towards larger numbers; as soon as the temporary result cannot be represented by a LongFloat:&lt;br /&gt;
 a := 1q+100.&lt;br /&gt;
 b := 1q+4900.&lt;br /&gt;
 c := 1q+200.&lt;br /&gt;
 d := 1q+4900.&lt;br /&gt;
 rslt := (a * b) / (c * d).&lt;br /&gt;
   -&amp;gt; NaN&lt;br /&gt;
&lt;br /&gt;
then, you may use arbitrary precision LargeFloat numbers:&lt;br /&gt;
 t := (a asLargeFloat * b asLargeFloat) / (c asLargeFloat * d asLargeFloat).&lt;br /&gt;
 rslt := t asFloat.&lt;br /&gt;
   -&amp;gt; 1e-100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt; that is the current default behavior. Future versions may allow enabling exceptions in this situation, if there are customer requests. However, as most other programming languages behave similar in these situations, most programmers are aware of these pitfalls and avoid such problems.&lt;br /&gt;
&lt;br /&gt;
== Different Results on Different CPUs ==&lt;br /&gt;
&lt;br /&gt;
Since FLOAT32 and FLOAT64 arithmetic is performed by the underlying CPU hardware,&lt;br /&gt;
different results (in the least significant bit) may be returned from math operations on different CPUs or even different versions (steppings) of the same CPU architecture. &lt;br /&gt;
&lt;br /&gt;
This applies especially to trigonometric and other math functions. Therse are computed by Power- or Taylor-series or Newton approximations with different algorithms on different systems, leading to different results.&lt;br /&gt;
&amp;lt;br&amp;gt;Be prepared for this, and use the &amp;quot;&#039;&#039;almost-equal&#039;&#039;&amp;quot; comparison functions when results are to be verified.&lt;br /&gt;
&lt;br /&gt;
== Summary of Higher Precision Numbers ==&lt;br /&gt;
&lt;br /&gt;
Expecco supports various inexact real formats, with different precision (i.e. number of mantissa bits).&lt;br /&gt;
Some of those classes have alias names; these are provided to make Smalltalk/X code portable to other Smalltalk dialects&lt;br /&gt;
(however, within expecco, you will probably not care, as it is not planned to port it to another dialect).&lt;br /&gt;
&lt;br /&gt;
 Name              Overall   Exponent   Mantissa    Decimal    fmin                ST/X        ANSI-ST      ST80/VW    IBM VA-ST&lt;br /&gt;
                   Size      Size       Size &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;     Precision  fmax                 Name        Name &amp;lt;sup&amp;gt;4)&amp;lt;/sup&amp;gt;       Name &amp;lt;sup&amp;gt;4)&amp;lt;/sup&amp;gt;   Name &amp;lt;sup&amp;gt;4)&amp;lt;/sup&amp;gt;&lt;br /&gt;
                   Bit       Bit        Bit         Digits&lt;br /&gt;
 &lt;br /&gt;
 IEEE single          32        8        24          6          1.175494e-038      ShortFloat   FloatE       Float      -&lt;br /&gt;
                                                                3.402823e+038      FloatE&lt;br /&gt;
                                                                                   Float32&lt;br /&gt;
 &lt;br /&gt;
 IEEE double          64       11        53         15          2.225074e-308      Float        FloatD       Double    Float&lt;br /&gt;
                                                                1.797693e+308      FloatD&lt;br /&gt;
                                                                                   Float64&lt;br /&gt;
                                                                                   Double&lt;br /&gt;
 &lt;br /&gt;
 IEEE extended    80/128       15       64/112      19/34       3.362103e-4932     LongFloat    FloatQ  &amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;     -         -&lt;br /&gt;
                                                                1.189731e+4932     FloatQ  &lt;br /&gt;
                                                                                   Float80&lt;br /&gt;
                                                                                   or Float128&lt;br /&gt;
 &lt;br /&gt;
 quad double        4*64       11       204         60          1.175494e-038      QDouble       -      &amp;lt;sup&amp;gt;3)&amp;lt;/sup&amp;gt;    -         -&lt;br /&gt;
                                                                3.402823e+038 &lt;br /&gt;
 &lt;br /&gt;
 IEEE quadruple      128       15       112         34          3.362103e-4932     QuadFloat     -      &amp;lt;sup&amp;gt;3)&amp;lt;/sup&amp;gt;     -         -&lt;br /&gt;
                                                                1.189731e+4932     Float128&lt;br /&gt;
 &lt;br /&gt;
 IEEE octuple        256       19       236         71          2.482427e-78913    OctaFloat     -      &amp;lt;sup&amp;gt;3)&amp;lt;/sup&amp;gt;     -         -&lt;br /&gt;
                                                                1.611325e+78913    Float256&lt;br /&gt;
 &lt;br /&gt;
 IEEE arbitrary      any       any      any         any         any                IEEEFloat     -      &amp;lt;sup&amp;gt;3)&amp;lt;/sup&amp;gt;     -         -&lt;br /&gt;
                                                                any&lt;br /&gt;
 &lt;br /&gt;
 large float         any       any      any         any         any                LargeFloat    -      &amp;lt;sup&amp;gt;3)&amp;lt;/sup&amp;gt;     -         -&lt;br /&gt;
                                                                any&lt;br /&gt;
&lt;br /&gt;
(1) mantissa incl. any hidden bit (normalized floats)&lt;br /&gt;
&lt;br /&gt;
(2) LongFloats use the underlying CPU&#039;s long double format.&amp;lt;br&amp;gt;On x86/x64 machines, LongFloats are represented as 80bit extended floats with 64bit mantissa; on other CPUs these might be represented as 128bit quadFloats with 112 bit mantissa (eg. a SPARC CPU does this).&lt;br /&gt;
&lt;br /&gt;
(3) these are still been developed and provided as a preview feature without warranty (meaning: they may be buggy at the moment; let us know if you need them).&lt;br /&gt;
&lt;br /&gt;
(4) different Smalltalk dialects use different precisions for their floating point numbers: ST80/VW Floats are IEEE singles, V&#039;Age Floats are IEEE doubles and ST/X Floats are IEEE doubles. VW refers to Float64 as Double.&amp;lt;br&amp;gt;Later, the ANSI standard defined FloatE, FloatD and FloatQ as aliases. You can use either interchangable in expecco.  &lt;br /&gt;
&lt;br /&gt;
Notice that the use of any but double precision floats (which are directly supported by the machine) may come at a performance price.&lt;br /&gt;
&amp;lt;br&amp;gt;The speed of operations degrades from double -&amp;gt; single -&amp;gt; extended -&amp;gt; ieee128 -&amp;gt; quad double -&amp;gt; ieee256 -&amp;gt; ieee arbitrary - largeFloat.&lt;br /&gt;
&amp;lt;br&amp;gt;This is especially true for the trigonometric and math functions, where both more iterations are needed to get to the desired precision in the series computations and the individual operations are also much slower.&lt;br /&gt;
&lt;br /&gt;
Be aware that LargeFloats are super precise, but also super slow.&lt;br /&gt;
&lt;br /&gt;
== Constants ==&lt;br /&gt;
Some well known and common constants can be acquired by asking a number class such as the Float class: &lt;br /&gt;
&lt;br /&gt;
 Float pi     -&amp;gt; pi (3.14159...)&lt;br /&gt;
 Float halfPi -&amp;gt; pi / 2&lt;br /&gt;
 Float twoPi  -&amp;gt; pi * 2 &lt;br /&gt;
 Float phi    -&amp;gt; phi (golden ratio 1.6180...)&lt;br /&gt;
 Float sqrt2  -&amp;gt; square root of 2 (1.4142...)&lt;br /&gt;
 Float sqrt5  -&amp;gt; square root of 5 (2.2360...)&lt;br /&gt;
 Float ln2    -&amp;gt; natural log of 2 (0.69314...)&lt;br /&gt;
 Float ln10   -&amp;gt; natural log of 10 (2.30258...)&lt;br /&gt;
 Float e      -&amp;gt; e (2.718281...)&lt;br /&gt;
&lt;br /&gt;
Each number class will return a representation of that constant with its precision.&amp;lt;br&amp;gt;I.e. if you ask the Float class for the constant &amp;quot;pi&amp;quot;, you&#039;ll get a pi with roughly 15 digits precision, whereas if you ask QDoubles, a more accurate representation will be returned.&lt;br /&gt;
 ShortFloat pi   (= Float32 pi)      -&amp;gt; 3.141593&lt;br /&gt;
 Float pi        (= Float64 pi)      -&amp;gt; 3.14159265358979&lt;br /&gt;
 LongFloat pi    (= Float80 pi)      -&amp;gt; 3.141592653589793238&lt;br /&gt;
 QuadFloat pi    (= Float128 pi)     -&amp;gt; 3.1415926535897932384626433832795027&lt;br /&gt;
 QDouble pi      (= QDouble pi)      -&amp;gt; 3.1415926535897932384626433832795028841971693993751058209749446&lt;br /&gt;
 OctaFloat pi    (= Float256 pi)     -&amp;gt; 3.14159265358979323846264338327950288419716939937510582097494459230781639&lt;br /&gt;
 LargeFloat pi   (= LargeFloat64 pi) -&amp;gt; 3.1415926535897932384626433832795028841971693993751058209749445923078164 [many more digits...]&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
Code examples in Smalltalk syntax. Notice the float precision qualifiers:&lt;br /&gt;
 &#039;q&#039;  -&amp;gt; longFloat (= IEEE extended precision = Float80)&lt;br /&gt;
 &#039;Q&#039;  -&amp;gt; quadFloat (= IEEE quadruple precision = Float128)&lt;br /&gt;
 &#039;QO&#039; -&amp;gt; octaFloat (= IEEE octuple precision = Float256)&lt;br /&gt;
 &#039;QD&#039; -&amp;gt; qDouble&lt;br /&gt;
 &#039;QL&#039; -&amp;gt; longFloat (arbitrary precision)&lt;br /&gt;
&lt;br /&gt;
Square Root:&lt;br /&gt;
 2.0 sqrt asShortFloat           -&amp;gt; 1.414214&lt;br /&gt;
 2.0 sqrt                        -&amp;gt; 1.4142135623731&lt;br /&gt;
 2.0q sqrt                       -&amp;gt; 1.414213562373095049&lt;br /&gt;
 2.0Q sqrt                       -&amp;gt; 1.4142135623730950488016887242097&lt;br /&gt;
 2.0QD sqrt                      -&amp;gt; 1.4142135623730950488016887242096980785696718753769&lt;br /&gt;
 2.0QO sqrt                      -&amp;gt; 1.41421356237309504880168872420969807&lt;br /&gt;
                                      8569671875376948073176679737990732&lt;br /&gt;
 (2.0QL precision:200) sqrt      -&amp;gt; 1.41421356237309504880168872420969807&lt;br /&gt;
                                      8569671875376948073176679&lt;br /&gt;
 (2.0QL precision:400) sqrt      -&amp;gt; 1.41421356237309504880168872420969807&lt;br /&gt;
                                      85696718753769480731766797379907324&lt;br /&gt;
                                      78462107038850387534327641572735013&lt;br /&gt;
                                      846230912297025&lt;br /&gt;
 (2.0QL precision:800) sqrt      -&amp;gt; 1.41421356237309504880168872420969807&lt;br /&gt;
                                      85696718753769480731766797379907324&lt;br /&gt;
                                      78462107038850387534327641572735013&lt;br /&gt;
                                      84623091229702492483605585073721264&lt;br /&gt;
                                      41214970999358314132226659275055927&lt;br /&gt;
                                      55799950501152782060571470109559971&lt;br /&gt;
                                      605970274...&lt;br /&gt;
 &lt;br /&gt;
 Precision value from Wolfram:      1.41421356237309504880168872420969807&lt;br /&gt;
                                      85696718753769480731766797379907324&lt;br /&gt;
                                      78462107038850387534327641572735013&lt;br /&gt;
                                      8462309122970249248360...&lt;br /&gt;
&lt;br /&gt;
Cubic Root:&lt;br /&gt;
 2.0 cbrt asShortFloat           -&amp;gt; 1.259921&lt;br /&gt;
 2.0 cbrt                        -&amp;gt; 1.25992104989487&lt;br /&gt;
 2.0q cbrt                       -&amp;gt; 1.259921049894873165&lt;br /&gt;
 2.0Q cbrt                       -&amp;gt; 1.25992104989487316476721060727823&lt;br /&gt;
 2.0QD cbrt                      -&amp;gt; 1.25992104989487316476721060727822835&lt;br /&gt;
                                      05702514647015&lt;br /&gt;
 2.0QO cbrt                      -&amp;gt; 1.25992104989487316476721060727822835&lt;br /&gt;
                                      05702514647015079800819751121553&lt;br /&gt;
 (2.0QL precision:200) cbrt      -&amp;gt; 1.25992104989487316476721060727822835&lt;br /&gt;
                                      0570251464701507980081975&lt;br /&gt;
 (2.0QL precision:400) cbrt      -&amp;gt; 1.25992104989487316476721060727822835&lt;br /&gt;
                                      05702514647015079800819751121552996&lt;br /&gt;
                                      76513959483729396562436255094154310&lt;br /&gt;
                                      256035615665259&lt;br /&gt;
 (2.0QL precision:800) cbrt      -&amp;gt; 1.25992104989487316476721060727822835&lt;br /&gt;
                                      05702514647015079800819751121552996&lt;br /&gt;
                                      76513959483729396562436255094154310&lt;br /&gt;
                                      25603561566525939902404061373722845&lt;br /&gt;
                                      91103042693552469606426166250009774&lt;br /&gt;
                                      74526565480306867185405518689245872&lt;br /&gt;
                                      516764199373709695098382...&lt;br /&gt;
 &lt;br /&gt;
 Wolfram:                           1.25992104989487316476721060727822835&lt;br /&gt;
                                      05702514647015079800819751121552996&lt;br /&gt;
                                      76513959483729396562436255094154310&lt;br /&gt;
                                      2560356156652593990240...&lt;br /&gt;
&lt;br /&gt;
Exponentiation:&lt;br /&gt;
 2.0 exp asShortFloat            -&amp;gt; 7.389056&lt;br /&gt;
 2.0 exp                         -&amp;gt; 7.38905609893065&lt;br /&gt;
 2.0q exp                        -&amp;gt; 7.389056098930650227&lt;br /&gt;
 2.0Q exp                        -&amp;gt; 7.38905609893065022723042746057499&lt;br /&gt;
 2.0QD exp                       -&amp;gt; 7.38905609893065022723042746057500781&lt;br /&gt;
                                      31803155705518&lt;br /&gt;
 2.0QO exp                       -&amp;gt; 7.38905609893065022723042746057500781&lt;br /&gt;
                                      318031557055184732408712782252257266&lt;br /&gt;
 (2.0QL precision:200) exp       -&amp;gt; 7.38905609893065022723042746057500781&lt;br /&gt;
                                      3180315570551847324087123&lt;br /&gt;
 (2.0QL precision:400) exp       -&amp;gt; 7.38905609893065022723042746057500781&lt;br /&gt;
                                      31803155705518473240871278225225737&lt;br /&gt;
                                      96079057763384312485079121794773753&lt;br /&gt;
                                      161265478866123&lt;br /&gt;
 (2.0QL precision:800) exp       -&amp;gt; 7.38905609893065022723042746057500781&lt;br /&gt;
                                      31803155705518473240871278225225737&lt;br /&gt;
                                      96079057763384312485079121794773753&lt;br /&gt;
                                      16126547886612388460369278127337447&lt;br /&gt;
                                      83922133980777749001228956074107537&lt;br /&gt;
                                      02391330947550682086581820269647868&lt;br /&gt;
                                      208404220982255234875742...&lt;br /&gt;
 &lt;br /&gt;
 Wolfram:                           7.38905609893065022723042746057500781&lt;br /&gt;
                                      31803155705518473240871278225225737&lt;br /&gt;
                                      96079057763384312485079121794773753&lt;br /&gt;
                                      16126547886612388460369278...&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
[[Number API Functions]]&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Number_API_Functions&amp;diff=30886</id>
		<title>Number API Functions</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Number_API_Functions&amp;diff=30886"/>
		<updated>2026-02-23T10:48:19Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 15.2.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document lists most useful (and most often needed) number functions.&lt;br /&gt;
Be aware, that there are many more to be found in either the class references or via the builtin [[Tools_ClassBrowser/en | class browser]].&lt;br /&gt;
&lt;br /&gt;
See also [[Expecco_API/en#Numbers | &amp;quot;Numbers&amp;quot;]] in [[Expecco_API]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Integer Integer], [http://live.exept.de/ClassDoc/classDocOf:,Float Float], [http://live.exept.de/ClassDoc/classDocOf:,Fraction Fraction], [http://live.exept.de/ClassDoc/classDocOf:,FixedPoint ScaledDecimal], [http://live.exept.de/ClassDoc/classDocOf:,Complex Complex]&lt;br /&gt;
which all inherit from&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Number Number]&lt;br /&gt;
&lt;br /&gt;
[[Useful API Functions | Back to Useful API Functions]]&lt;br /&gt;
&lt;br /&gt;
=== Literals (i.e. Constant Numbers) ===&lt;br /&gt;
&lt;br /&gt;
Literals are constants as written in elementary Smalltalk code and also given as freeze value to a pin or initial value to a variable.&lt;br /&gt;
&lt;br /&gt;
===== Integer Literals =====&lt;br /&gt;
 1234 &lt;br /&gt;
 1234567890123456789012345678901234567890&lt;br /&gt;
 -123456789012345678901234567890&lt;br /&gt;
 0xaffe or 16rFFAA &amp;lt;small&amp;gt;(hex in C/JSON or Smalltalk syntax)&amp;lt;/small&amp;gt;&lt;br /&gt;
 -0xaffe or 16r-FFAA &amp;lt;small&amp;gt;(negative hex in C- or Smalltalk syntax)&amp;lt;/small&amp;gt;&lt;br /&gt;
 0b101010 or 2r0101 &amp;lt;small&amp;gt;(binary in C/JSON or Smalltalk syntax)&amp;lt;/small&amp;gt;&lt;br /&gt;
 0o377 or 8r377 &amp;lt;small&amp;gt;(octal)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &amp;amp;lt;&#039;&#039;N&#039;&#039;&amp;amp;gt;rXXX &amp;lt;small&amp;gt;(arbitrary radix N)&amp;lt;/small&amp;gt;&lt;br /&gt;
Integer constant; decimal, hex, binary, octal or any base &#039;&#039;N&#039;&#039;;&amp;lt;br&amp;gt;integers may be arbitrary long&lt;br /&gt;
&lt;br /&gt;
===== Floating Point Literals (Limited Precision Rationals) =====&lt;br /&gt;
 0.5&lt;br /&gt;
 1e5&lt;br /&gt;
 -1.2e-3&lt;br /&gt;
 12.6789q or 1.7e-21q &amp;lt;small&amp;gt;(extended precision)&amp;lt;/small&amp;gt;&lt;br /&gt;
 3.6789f or 2.67e5f &amp;lt;small&amp;gt;(single precision)&amp;lt;/small&amp;gt;&lt;br /&gt;
Float constant; actually IEEE double precision;&amp;lt;br&amp;gt;use &amp;quot;q&amp;quot; instead of &amp;quot;e&amp;quot; for extra precision (extended IEEE floats) or &amp;quot;f&amp;quot; for single/less precision.&lt;br /&gt;
&lt;br /&gt;
In addition to single, double and extended floats, additional precision representations (&#039;Q&#039;, &#039;QD&#039;, &#039;QL&#039; and &#039;QO&#039;) are available (see below).&lt;br /&gt;
 3.6789Q or 2.67e5Q &amp;lt;small&amp;gt;(float128)&amp;lt;/small&amp;gt;&lt;br /&gt;
 3.6789QO or 2.67e5QO &amp;lt;small&amp;gt;(float256)&amp;lt;/small&amp;gt;&lt;br /&gt;
 3.6789QD or 2.67e5QD &amp;lt;small&amp;gt;(quad double representation)&amp;lt;/small&amp;gt;&lt;br /&gt;
 3.6789QL or 2.67e5QL &amp;lt;small&amp;gt;(largeFloat representation)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Fraction Literals =====&lt;br /&gt;
 (4/3)&lt;br /&gt;
 (523423432/3)&lt;br /&gt;
 (-5/3)&lt;br /&gt;
Fraction constants (numerator / denominator); these are exact&lt;br /&gt;
&lt;br /&gt;
===== Scaled Decimal Literals =====&lt;br /&gt;
 123.456s2&lt;br /&gt;
 -33.4s2&lt;br /&gt;
 100s2&lt;br /&gt;
Scaled decimal; the number after the &amp;quot;s&amp;quot; defines the print-scale. The above numbers print themself rounded to 2 fractional digits e.g. &amp;quot;123.46&amp;quot;, &amp;quot;-33.40&amp;quot; or &amp;quot;100.00&amp;quot; (although internally, the full precision is kept for further operations).&lt;br /&gt;
&lt;br /&gt;
===== Complex Number Literals =====&lt;br /&gt;
 (4+3i) or (-5+2i) or (-10-4i)&lt;br /&gt;
 (4.3+3.1i) or (4.3 + 1i) &lt;br /&gt;
 5.0 i or 5i&lt;br /&gt;
Complex number (real part / imaginary part)&lt;br /&gt;
&lt;br /&gt;
== Wellknown Constant Numbers ==&lt;br /&gt;
A few common constants are known by name. &lt;br /&gt;
They are answered by corresponding getter messages sent to the number class of which you want the constant (i.e. these return the constants in their respective precision):&lt;br /&gt;
&lt;br /&gt;
:Float &#039;&#039;&#039;pi&#039;&#039;&#039;&lt;br /&gt;
::pi as IEEE double precision number&lt;br /&gt;
&lt;br /&gt;
:FloatD &#039;&#039;&#039;pi&#039;&#039;&#039; &lt;br /&gt;
:Float64 &#039;&#039;&#039;pi&#039;&#039;&#039;&lt;br /&gt;
::the same as above (FloatD and Float64 are aliases for the default float class &amp;quot;Float&amp;quot;)&lt;br /&gt;
:FloatQ &#039;&#039;&#039;pi&#039;&#039;&#039;&lt;br /&gt;
:Float80 &#039;&#039;&#039;pi&#039;&#039;&#039; &lt;br /&gt;
::pi as IEEE extended precision number (FloatQ and Float80 are aliases for the extended float class also known as &amp;quot;LongFloat&amp;quot;)&lt;br /&gt;
:FloatE &#039;&#039;&#039;pi&#039;&#039;&#039;&lt;br /&gt;
:Float32 &#039;&#039;&#039;pi&#039;&#039;&#039;&lt;br /&gt;
::pi as IEEE single precision number (FloatE and Float32 are aliases for the single precision float class also known as &amp;quot;ShortFloat&amp;quot;)&lt;br /&gt;
:Float128 &#039;&#039;&#039;pi&#039;&#039;&#039;&lt;br /&gt;
::pi as IEEE quadruple precision number&lt;br /&gt;
:Float256 &#039;&#039;&#039;pi&#039;&#039;&#039;&lt;br /&gt;
::pi as IEEE octuple precision number&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;FloatClass&amp;gt; &#039;&#039;&#039;ln2&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;FloatClass&amp;gt; &#039;&#039;&#039;ln10&#039;&#039;&#039;&lt;br /&gt;
:&lt;br /&gt;
:&amp;lt;FloatClass&amp;gt; &#039;&#039;&#039;sqrt2&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;FloatClass&amp;gt; &#039;&#039;&#039;sqrt3&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;FloatClass&amp;gt; &#039;&#039;&#039;e&#039;&#039;&#039;&lt;br /&gt;
:&lt;br /&gt;
:&amp;lt;FloatClass&amp;gt; &#039;&#039;&#039;NaN&#039;&#039;&#039;, &#039;&#039;&#039;infinity&#039;&#039;&#039; and &#039;&#039;&#039;negativeInfinity&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Take a look at the class in a class browser for additional useful constants.&lt;br /&gt;
&lt;br /&gt;
== Float Representations ==&lt;br /&gt;
=== Standard Float Representations ===&lt;br /&gt;
For traditional reasons, the name &amp;quot;&#039;&#039;Float&#039;&#039;&amp;quot; refers to IEEE double precision floating point numbers in expecco, whereas IEEE single precision floats are called &amp;quot;&#039;&#039;ShortFloats&#039;&#039;&amp;quot;.&lt;br /&gt;
For more readability, the float classes can also be referred to via their aliases: &lt;br /&gt;
:Float32 = FloatE (=ShortFloat), &lt;br /&gt;
:Float64 = FloatD (=Float) &lt;br /&gt;
:Float80 = FloatQ (=LongFloat).&lt;br /&gt;
&lt;br /&gt;
There is usually no need to explicitly use or refer to ShortFloats (or FloatEs): modern CPUs usually process them as fast as doubles.&amp;lt;br&amp;gt;However, you may need them to either simulate single precision arithmetic (which may show different convergence behavior in some series computations) or to exchange binary data with other systems (i.e. to generate a byteArray containing the float&#039;s bits or to write a single precision float&#039;s bits to a stream).&lt;br /&gt;
&lt;br /&gt;
====== Float / FloatD / Float64 ======&lt;br /&gt;
Floats (double precision IEEE floats) are stored in 64 bits, having an 11-bit exponent and a 52+1 bit mantissa (1 bit is hidden due to normalization).&amp;lt;br&amp;gt;This gives roughly 15 digits of precision.&amp;lt;br&amp;gt;This is the default used, if you write a float number in the code.&lt;br /&gt;
&lt;br /&gt;
====== ShortFloat / FloatE / Float32 ======&lt;br /&gt;
ShortFloats (single precision IEEE floats) are stored in 32 bits, having an 8-bit exponent and a 23+1 bit mantissa (1 bit is hidden due to normalization).&amp;lt;br&amp;gt;This gives roughly 7 digits of precision.&lt;br /&gt;
&lt;br /&gt;
====== LongFloat / FloatQ / Float80 ======&lt;br /&gt;
LongFloats (extended precision IEEE floats) are stored in 80 bits, having a 15-bit exponent and a 64 bit mantissa.&amp;lt;br&amp;gt;This gives roughly 19 digits of precision.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
By Default, Floats print themself with either a decimal point or an exponent indicator &#039;e&#039;, e.g. &amp;quot;0.5&amp;quot;, &amp;quot;10.0&amp;quot; or &amp;quot;1.3e3&amp;quot;. However, there are a number of functions provided to print numbers in other formats.&lt;br /&gt;
&lt;br /&gt;
=== Experimental Extra Float Representations ===&lt;br /&gt;
For background information on why you should not trust IEEE floating point arithmetic, and why you may need more precision in some situations,&lt;br /&gt;
please read the article &amp;quot;[[Do not trust Floating Point]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Expecco (actually its underlying Smalltalk engine) includes versions for higher precision floats. Please be careful in using them for production code, as they are still considered being &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot;, and may or may not work as expected. Especially trigonometric and other math functions are known to be slightly less precise than expected. Please use those with extra care and report any bugs.&lt;br /&gt;
&lt;br /&gt;
For now, we recommend the use of LargeFloat instead of QuadFloat/OctaFloat or QDouble if large precision is needed.&lt;br /&gt;
&lt;br /&gt;
====== LargeFloat ======&lt;br /&gt;
LargeFloats use an arbitrary (configurable) number of bits to represent floats with any precision.&amp;lt;br&amp;gt;They are completely software emulated, which makes most operations much slower than with other floats. In other languages, these are sometimes called &amp;quot;&#039;&#039;BigFloat&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Usage is similar to QDoubles as described below. However, when creating aLargeFloat, you have to give the desired precision (in bits) as argument:&lt;br /&gt;
 1.0 asLargeFloatPrecision:200&lt;br /&gt;
or in decimals:&lt;br /&gt;
 1.0 asLargeFloatDecimalPrecision:100&lt;br /&gt;
If no precision is given, a default prcision of 200 bits is used, as e.g. by:&lt;br /&gt;
 1.0 asLargeFloat&lt;br /&gt;
&lt;br /&gt;
You will get roughly 1 decimal digit of precision per 3 bits (i.e. the above 200bit precision corresponds to a decimal precision of roughly 60 digits). Be aware, that a non-present precision cannot be &#039;magically&#039; reconstructed. Thus a float64 like 0.1 (which cannot be represented exactly) will remain inexact in the original number of bits. If in doubt, convert from a string representation (i.e. &amp;lt;code&amp;gt;LargeFloat fromString:&#039;0.1&#039;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;LargeFloat fromString:&#039;0.1&#039; precision:200&amp;lt;/code&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Example &amp;lt;sup&amp;gt;(1)&amp;lt;/sup&amp;gt;:&lt;br /&gt;
 45 degrees sin&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 0.707106781186547 &lt;br /&gt;
        (a float with roughly 15 digits precision)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (45 asLargeFloatPrecision:200) degrees sin&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 0.70710678118654752440084436210484903928483593768847403658834&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 and back:&lt;br /&gt;
 (45 asLargeFloatPrecision:200) degrees sin arcSin radiansToDegrees&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 45.0&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt; the meaning of &amp;quot;degrees&amp;quot; is described in the [[PhysicalValues/en#Angle|&amp;quot;Physical Values&amp;quot;]] document.&lt;br /&gt;
&lt;br /&gt;
====== QDouble / FloatQD ======&lt;br /&gt;
QDoubles use 4 double precision floats (holding the unevaluated sum of 4 doubles) to represent a float with roughly 200 bits of precision (actually often more, depending on the values).&lt;br /&gt;
The theory is described in &amp;quot;Library for Double-Double and Quad-Double Arithmetic&amp;quot; by Yozo Hida† Xiaoye S. Li‡ David H. Bailey May 8, 2008, and the ope source code is found on github.&lt;br /&gt;
&lt;br /&gt;
QDoubles are able to represent sums/differences of up to 4 a very distant doubles (eg. a very large plus a very small value).&amp;lt;br&amp;gt;For example with regular floats (i.e. IEEE double precision):&lt;br /&gt;
 (1e200 + 1e-15) - 1e200&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 0.0&amp;lt;/small&amp;gt;&lt;br /&gt;
the small value is lost.&amp;lt;br&amp;gt;Whereas with QDoubles as in:&lt;br /&gt;
 (1e200 asQDouble + 1e-15) - 1e200&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 1e-15&amp;lt;/small&amp;gt;&lt;br /&gt;
it is preserved.&lt;br /&gt;
&lt;br /&gt;
QDoubles are thus able to represent sums of wildly distant numbers.&lt;br /&gt;
With regular floats, the following computations all deliver a wrong result:&lt;br /&gt;
 1e200 + 1e-15 + 1e-100                              &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 1E+200  (loosing 1e-15 + 1e-100)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (1e200 + 1e-15 + 1e-100) - 1e200             &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 0       (wrong; lost 1e-15 + 1e-100)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (1e200 + 1e-15 + 1e-100) - 1e200 - 1e-15&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; -1e-15  (wrong)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (1e200 + 1e-15 + 1e-100) - 1e200 - 1e-100          &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; -1E-100 (wrong)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (1e200 + 1e-15 + 1e-100) - 1e200 - 1e-15 - 1e-100   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; -1E-015 (wrong)&amp;lt;/small&amp;gt;&lt;br /&gt;
whereas with QDoubles, we get:&lt;br /&gt;
 1e200 asQDouble + 1e-15 + 1e-100                              &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 1E+200  (printed, actual value is correct)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (1e200 asQDouble + 1e-15 + 1e-100) - 1e200                    &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 1.0e-15 (correct)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (1e200 asQDouble + 1e-15 + 1e-100) - 1e200 - 1e-15            &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 1E-100  (correct)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (1e200 asQDouble + 1e-15 + 1e-100) - 1e200 - 1e-100           &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 1E-015  (correct)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (1e200 asQDouble + 1e-15 + 1e-100) - 1e200 - 1e-15 - 1e-100   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 0.0     (correct)&amp;lt;/small&amp;gt;&lt;br /&gt;
or another example:&lt;br /&gt;
 t := 1234 + 0.567890 + 0.00000012345 + 0.000000000006789.&lt;br /&gt;
 a := t - 1234.              &amp;quot;/ 0.567890123456891     (mhmh ?) &lt;br /&gt;
 b := a - 0.567890.          &amp;quot;/ 1.23456891154561E-07  (mhmh ?) &lt;br /&gt;
 c := b - 0.00000012345.     &amp;quot;/ 6.89115456081139E-12  (mhmh ?)&lt;br /&gt;
 d := c - 0.000000000006789. &amp;quot;/ 1.0215456081139E-13   (wrong)&lt;br /&gt;
whereas:&lt;br /&gt;
 t := 1234 asQDouble + 0.567890 + 0.00000012345 + 0.000000000006789.&lt;br /&gt;
 a := t - 1234.              &amp;quot;/ 0.56789012346    (mhmh ?)&lt;br /&gt;
 b := a - 0.567890.          &amp;quot;/ 1.23456789e-7    (mhmh ?)&lt;br /&gt;
 c := b - 0.00000012345.     &amp;quot;/ 6.789E-12        (correct) &lt;br /&gt;
 d := c - 0.000000000006789. &amp;quot;/ 0.0              (correct)&lt;br /&gt;
&lt;br /&gt;
However, there is no insurance, that bits are not lost. If one of the operands already needs all four doubles (because it cannot be represented exactly as a sum of 3 floats), bits from the second operand may be lost. For example:&lt;br /&gt;
 1e100 asQDouble + 1&lt;br /&gt;
will result in 1e100 (without the one), because 1e100 already uses all bits (i.e. all 4 doubles) of the QDouble.&lt;br /&gt;
If you need the full precision, you may have to use LargeFloats, although the processing overhead will usually be larger then.&lt;br /&gt;
&lt;br /&gt;
Due to the extra processing overhead, operations are slower than with doubles or extended doubles.&lt;br /&gt;
&lt;br /&gt;
:Attention:&amp;lt;br&amp;gt;Strange results seem to be generated when regular floats are converted to QDoubles iff the original float was not representable as an exact number. For example, adding the float 0.2 to the QDouble 1.0QD will result in a number different from 1.2QD, because the original 0.2 had an error in its last bit, which gets now visible when converted to QDouble.&lt;br /&gt;
Better use LargeFloat instead, if more precision is needed.&lt;br /&gt;
&lt;br /&gt;
====== QuadFloat / Float128 ======&lt;br /&gt;
QuadFloats use the 128 bit IEEE quadruple precision binary128 format, with 15 exponent bits, providing roughly 34 digits of precision.&lt;br /&gt;
&amp;lt;br&amp;gt;QuadFloats are software emulated, and thus computations are slower than with regular floats.&lt;br /&gt;
&lt;br /&gt;
:Attention:&amp;lt;br&amp;gt;Do not use Quadfloats for now, except to convert from/from binary data. Currently, they may return slightly incorrect results for trigonometric operations (rounding modes are not correctly implemented). Use &amp;lt;!-- QDouble or --&amp;gt; LargeFloat  if more precision is needed.&lt;br /&gt;
&lt;br /&gt;
====== OctaFloat / Float256 ======&lt;br /&gt;
OctaFloats use the 256 bit IEEE octuple binary256 format, with 19 exponent bits, providing roughly 70 digits of precision and a larger range for the exponent.&lt;br /&gt;
&amp;lt;br&amp;gt;OctaFloats are also software emulated by a flexible arbitrary precision IEEE algorithm, and slower than QuadFloats and QDoubles (actually often even slower than LargeFloats below).&lt;br /&gt;
&lt;br /&gt;
:Attention:&amp;lt;br&amp;gt;Do not use Octafloats for now, except to convert from/from binary data. Currently, they may return slightly incorrect results for trigonometric operations (rounding modes are not correctly implemented). Use &amp;lt;!-- QDouble or --&amp;gt; LargeFloat  if more precision is needed.&lt;br /&gt;
&lt;br /&gt;
== Fractions ==&lt;br /&gt;
Fractions are returned from integer divisions; i.e. when both &amp;quot;&#039;&#039;a&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;b&#039;&#039;&amp;quot; are integers and &amp;quot;&#039;&#039;a&#039;&#039; / &#039;&#039;b&#039;&#039;&amp;quot; does not result in an integral result.&lt;br /&gt;
&amp;lt;br&amp;gt;Fractions are exact; no precision is lost. Results of arithmetic operations are reduced and possibly yield integers. Thus:&lt;br /&gt;
 (1/3) * (1/3)&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; (1/9)&amp;lt;/small&amp;gt;&lt;br /&gt;
and:&lt;br /&gt;
 (1/3) * 9&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 3 (an exact integer)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fractions print themself as &amp;quot;(&#039;&#039;a&#039;&#039; / &#039;&#039;b&#039;&#039;)&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;They are computed in software and thus usually slower than float operations (especially with huge numerators/denominators).&lt;br /&gt;
&lt;br /&gt;
== Scaled Decimals ==&lt;br /&gt;
These &#039;&#039;&#039;print themself rounded&#039;&#039;&#039; to a specified number of fractional digits (the so called &#039;&#039;scale&#039;&#039;).&amp;lt;br&amp;gt;For example, &amp;quot;&amp;lt;code&amp;gt;1234.567 asScaledDecimal:2&amp;lt;/code&amp;gt;&amp;quot; will print itself as &amp;quot;1234.57&amp;quot; (i.e. rounded).&lt;br /&gt;
&amp;lt;br&amp;gt;However, internally the full precision is kept, so an arithmetic operation will still deliver a correct result.&lt;br /&gt;
&lt;br /&gt;
Scaled decimals are perfect to present values to a user or in a report in a &amp;quot;human friendly&amp;quot; rounded format.&lt;br /&gt;
&amp;lt;br&amp;gt;Example:&lt;br /&gt;
 a := 1234.567 asScaledDecimal:2.&lt;br /&gt;
 a print.  &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1234.57&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 b := 23.007 asScaledDecimal:2&lt;br /&gt;
 b print.  &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;23.01&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (a + b) print.&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1257.57&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is because the sum (a+b) is actually (1234.567 + 23.007 = 1257.574), which is printed as &#039;1257.57&#039; (rounded).&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;br&amp;gt;This also works for Fractions:&lt;br /&gt;
&amp;lt;br&amp;gt;Fraction example:&lt;br /&gt;
 c := (1/3) asScaledDecimal:2.&lt;br /&gt;
 c print.  &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;0.33&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 d := (2/3) asScaledDecimal:2&lt;br /&gt;
 d print.  &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;0.67&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (c + d) print.&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.00&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be aware that the output will look strange (i.e. look wrong) if monetary values are presented this way, e.g. on an invoice&#039;s summation. Here, we&#039;d expect a sum of amounts to be the sum of previously listed values (think of sales tax being computed, giving a rounded Cent-value).&lt;br /&gt;
&amp;lt;br&amp;gt;See FixedDecimal below for a better solution.&lt;br /&gt;
&lt;br /&gt;
ScaledDecimals can be rounded to their scale, so that further computation are taking that value.&lt;br /&gt;
Thus taking the above values rounded:&lt;br /&gt;
 a := a roundedToScale.&lt;br /&gt;
 b := b roundedToScale.&lt;br /&gt;
 (a + b) print.&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1257.58&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
shows the &#039;&#039;correct&#039;&#039; value in a table.&lt;br /&gt;
&lt;br /&gt;
You can also use &amp;quot;&amp;lt;code&amp;gt;truncatedToScale&amp;lt;/code&amp;gt;&amp;quot;, to continue arithmetic with the truncated value.&lt;br /&gt;
&lt;br /&gt;
== Fixed Decimals ==&lt;br /&gt;
(new with expecco 21.2)&amp;lt;br&amp;gt;Similar to ScaledDecimals; however, these do &#039;&#039;&#039;NOT&#039;&#039;&#039; hold the correct result, but instead &#039;&#039;&#039;always round&#039;&#039;&#039; to the specified scale and thus the value used for further operations is the (rounded) value printed.&amp;lt;br&amp;gt;&lt;br /&gt;
Arithmetic operations will deliver a rounded result. Fixed decimals are good to represent money, especially when computing and printing sums of monetary values e.g. in an invoice.&lt;br /&gt;
&amp;lt;br&amp;gt;Example:&lt;br /&gt;
 a := 1234.567 asFixedDecimal:2.&lt;br /&gt;
 a print.  &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1234.57&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 b := 23.007 asFixedDecimal:2&lt;br /&gt;
 b print.  &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;23.01&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 (a + b) print.&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1257.58&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
This looks correct to a human, as the values sum up correctly.&lt;br /&gt;
&lt;br /&gt;
Be aware that converting a float to a FixedDecimal and back will not necessarily return the starting number. Unlike ScaledDecimals, FixedDecimals do NOT preserve the original value.&lt;br /&gt;
&lt;br /&gt;
If you have a pre 21.2 version, the FixedDecimal behavior can be &amp;quot;simulated&amp;quot; by forcing a ScaledDecimal to round its value to the shown scale (as described above).&lt;br /&gt;
&lt;br /&gt;
== Number Ranges ==&lt;br /&gt;
These behave like collections (see there) and are typically created by one of the following:&lt;br /&gt;
 (&#039;&#039;start&#039;&#039; &#039;&#039;&#039;to:&#039;&#039;&#039; &#039;&#039;stop&#039;&#039;)&lt;br /&gt;
 (&#039;&#039;start&#039;&#039; &#039;&#039;&#039;to:&#039;&#039;&#039; &#039;&#039;stop&#039;&#039; &#039;&#039;&#039;by:&#039;&#039;&#039; &#039;&#039;step&#039;&#039;)&lt;br /&gt;
For example:&lt;br /&gt;
 (1 to:10) do:[:i |&lt;br /&gt;
   Transcript showCR: e&#039;{i} squared is {i squared}&#039;.&lt;br /&gt;
 ]&lt;br /&gt;
&lt;br /&gt;
== Complex Numbers ==&lt;br /&gt;
Are created as constants &amp;quot;&amp;lt;code&amp;gt;(&#039;&#039;a&#039;&#039; + &#039;&#039;b&#039;&#039; i)&amp;lt;/code&amp;gt;&amp;quot; or created with &amp;quot;&amp;lt;code&amp;gt;Complex real:&#039;&#039;a&#039;&#039; imaginary:&#039;&#039;b&#039;&#039;&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;An imaginary is created with the &amp;quot;&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;&amp;quot; message (e.g. &amp;quot;&amp;lt;code&amp;gt;5 i&amp;lt;/code&amp;gt;&amp;quot; yields (0 + 5 i).&lt;br /&gt;
&amp;lt;br&amp;gt;Complex numbers print themself as &amp;quot;(&#039;&#039;a&#039;&#039; + &#039;&#039;b&#039;&#039; i)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Complex results can also be returned from e.g. the square root operator (sqrt) and logarithm operations (log, ln) IFF imaginary results are trapped (which means that an exception handler for the ImaginaryResult notification is present and proceeds the exception).&amp;lt;br&amp;gt;The convenient helper &amp;quot;&amp;lt;CODE&amp;gt;trapImaginary:&amp;lt;/CODE&amp;gt;&amp;quot; does that for you:&lt;br /&gt;
 -4 sqrt&lt;br /&gt;
will report an error, whereas:&lt;br /&gt;
 Number trapImaginary:[ -4 sqrt ]&lt;br /&gt;
will return a complex result (0+2.0i).&lt;br /&gt;
&lt;br /&gt;
If imaginary results are not trapped, square root and log operators will signal an exception instead.&lt;br /&gt;
&lt;br /&gt;
== Measurement Values ==&lt;br /&gt;
These hold an error percentage in addition to the actual value. These are useful to track upper and lower bounds of a measured or estimated value. Arithmetic operations will keep this error in the result.&lt;br /&gt;
&amp;lt;br&amp;gt;They can be constructed from any number via the &amp;quot;&amp;lt;/CODE&amp;gt;±&amp;lt;/CODE&amp;gt;&amp;quot; or &amp;quot;&amp;lt;CODE&amp;gt;±%&amp;lt;/CODE&amp;gt;&amp;quot; binary operators:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;(&#039;&#039;&#039;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;±&#039;&#039;&#039; &#039;&#039;errRange&#039;&#039;&#039;&#039;&#039;)&#039;&#039;&#039;&lt;br /&gt;
:: a measurement value with ± an absolute error of &#039;&#039;errRange&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;(&#039;&#039;&#039;&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;±%&#039;&#039;&#039; &#039;&#039;percentage&#039;&#039;&#039;&#039;&#039;)&#039;&#039;&#039;&lt;br /&gt;
:: a measurement value with a relative error of &#039;&#039;percentage&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
For example, &lt;br /&gt;
&amp;lt;br&amp;gt;&amp;quot;&amp;lt;CODE&amp;gt;(50 ± 3)&amp;lt;/CODE&amp;gt;&amp;quot; represents a measurement value with 6% accuracy (i.e. the actual value is somewhere in the interval [50-3 .. 50+3]),&lt;br /&gt;
and &lt;br /&gt;
&amp;lt;br&amp;gt;&amp;quot;&amp;lt;CODE&amp;gt;(100 ±% 3)&amp;lt;/CODE&amp;gt;&amp;quot; represents a measurement value with 3% accuracy (i.e. the value is in [100-3 .. 100+3]).&lt;br /&gt;
 &lt;br /&gt;
Measurement values are not real numbers, but can in most operations be treated like one (i.e. the usual arithmetic operations are supported).&lt;br /&gt;
&lt;br /&gt;
== Physical Values ==&lt;br /&gt;
These hold a number or measurement value in addition to a unit (e.g. meter, kilogram, volt, ampere, etc.). They are documented in depth in a [[PhysicalValues/en|separate part of this wiki]].&amp;lt;br&amp;gt;Physical values are created via unit operators (&#039;meter&#039;, &#039;volt&#039;, &#039;ampere&#039; etc.).&lt;br /&gt;
&lt;br /&gt;
For example, &amp;quot;&amp;lt;CODE&amp;gt;50 volt&amp;lt;/CODE&amp;gt;&amp;quot; represents a voltage value of 50 volts.&amp;lt;br&amp;gt;Physical values are not numbers, but can in most parts be treated like one (i.e. most arithmetic operations are supported).&lt;br /&gt;
 100 volt * 3&lt;br /&gt;
yields &amp;quot;300 V&amp;quot;.&amp;lt;br&amp;gt;And:&lt;br /&gt;
 100 volt * 0.1 ampere&lt;br /&gt;
yields &amp;quot;10 W&amp;quot; (watt).&amp;lt;br&amp;gt;And:&lt;br /&gt;
 10 volt / 2 ampere&lt;br /&gt;
yields &amp;quot;5 ohm&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Physical values can also be combined with measurement values:&lt;br /&gt;
 100 volt ±% 3&lt;br /&gt;
represents a measured voltage with 3% possible error (i.e. &amp;quot;(100 ± 3) V&amp;quot;). &amp;lt;br&amp;gt;And:&lt;br /&gt;
 10 volt ± 2 volt&lt;br /&gt;
represents a measured voltage with 20% error (i.e. value in [8 .. 12] V&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
See details in the [[PhysicalValues/en|&amp;quot;Physical Values&amp;quot;]] document.&lt;br /&gt;
&lt;br /&gt;
== Operations with Mixed Types ==&lt;br /&gt;
&lt;br /&gt;
Normally, there is no need for explicit conversion between number types. The result of mixed operations is computed with the type of the operand which has the higher &amp;quot;&#039;&#039;generality&#039;&#039;&amp;quot;. This conversion is called &amp;quot;&#039;&#039;coercion&#039;&#039;&amp;quot; - i.e. the operand with the lower generality is &#039;&#039;coerced&#039;&#039; into the type of the other before the operation is performed.&lt;br /&gt;
&lt;br /&gt;
The order of generalities is:&lt;br /&gt;
 Integer &amp;lt; Fraction &amp;lt; ScaledDecimal &amp;lt; FixedDecimal &lt;br /&gt;
    &amp;lt; Float32 &amp;lt; Float64 &amp;lt; Float80 &amp;lt; Float128 &amp;lt; Float256 &amp;lt; LargeFloat &amp;lt; Complex&lt;br /&gt;
Thus, when a calculation involves both an integer and a fraction, the result will be a fraction (unless the result can be reduced to an integer).&lt;br /&gt;
&amp;lt;br&amp;gt;When an operation involves a float and an integer or fraction, the result will be a float.&lt;br /&gt;
&amp;lt;br&amp;gt;When either one is a complex, the result will also be.&lt;br /&gt;
&lt;br /&gt;
When two floats are involved, the result will be generated with the higher precision. &lt;br /&gt;
&lt;br /&gt;
==== Errors Propagate when Converting ====&lt;br /&gt;
But you should not be fooled by that: we do not get previously lost bits back, when a lower precision float is converted to a higher precision; the missing bits are simply assumed to be zero. In other words: &amp;quot;&amp;lt;CODE&amp;gt;ShortFloat pi asFloat&amp;lt;/CODE&amp;gt;&amp;quot; will still only have roughly 7 digits of precision (which the original short float had), whereas &amp;quot;&amp;lt;CODE&amp;gt;Float pi&amp;lt;/CODE&amp;gt;&amp;quot; will have its 15 digits.&lt;br /&gt;
&lt;br /&gt;
This is a possible trap and a source for unexpected errors: be aware, that &amp;quot;0.1&amp;quot; (a double) is only an approximation to &amp;quot;0.1&amp;quot; (to about 15 digits).&lt;br /&gt;
I.e. this &amp;quot;0.1&amp;quot; has an error in the 1e-15 order, which &amp;quot;0.1&amp;quot; asFloat128 will also have.&lt;br /&gt;
&amp;lt;br&amp;gt;You cannot get a &amp;quot;0.1&amp;quot; with a smaller error from another float which already has this error.&lt;br /&gt;
&lt;br /&gt;
Thus, either use &amp;quot;&amp;lt;code&amp;gt;0.1Q&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;(&amp;lt;code&amp;gt;QuadFloat fromString:&#039;0.1&#039;)&amp;lt;/code&amp;gt;&amp;quot; or compute it with &amp;quot;&amp;lt;code&amp;gt;(1.0Q / 10.0Q)&amp;lt;/code&amp;gt;&amp;quot;, to get that 0.1 with 128bit precision.&lt;br /&gt;
&lt;br /&gt;
==== Mixed Operations with MeasurementValues ====&lt;br /&gt;
Automatic conversion is also performed when MeasurementValues are involved:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aMeasurementValue&#039;&#039; &#039;&#039;&#039;+&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;   =&amp;gt; MeasurementValue&lt;br /&gt;
:&#039;&#039;aMeasurementValue&#039;&#039; &#039;&#039;&#039;-&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;   =&amp;gt; MeasurementValue&lt;br /&gt;
::the result will have the same error as the receiver. &lt;br /&gt;
::E.g. (10 ± 1) + 10 =&amp;gt; (20 ± 1).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
:&#039;&#039;aMeasurementValue&#039;&#039; &#039;&#039;&#039;*&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;   =&amp;gt; MeasurementValue&lt;br /&gt;
:&#039;&#039;aMeasurementValue&#039;&#039; &#039;&#039;&#039;/&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;   =&amp;gt; MeasurementValue&lt;br /&gt;
::the error will also be scaled by &#039;&#039;aNumber&#039;&#039;. &lt;br /&gt;
::E.g. (10 ± 1) * 10 =&amp;gt; (100 ± 10).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Mixed Operations with PhysicalValues ====&lt;br /&gt;
PhysicalValues can be scaled by a scalar or multiplied by another physical value (possibly resulting in a value with a different unit). Addition and subtraction are only allowed if the arguments have the same base type:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aPhysicalValue&#039;&#039; &#039;&#039;&#039;+&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;   =&amp;gt; error&lt;br /&gt;
:&#039;&#039;aPhysicalValue&#039;&#039; &#039;&#039;&#039;-&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;   =&amp;gt; error&lt;br /&gt;
::not allowed&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aPhysicalValue&#039;&#039; &#039;&#039;&#039;*&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;   =&amp;gt; PhysicalValue&lt;br /&gt;
:&#039;&#039;aPhysicalValue&#039;&#039; &#039;&#039;&#039;/&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;   =&amp;gt; PhysicalValue&lt;br /&gt;
::for example, &amp;lt;CODE&amp;gt;10 volt * 10&amp;lt;/CODE&amp;gt; =&amp;gt; &amp;lt;CODE&amp;gt;100 volt&amp;lt;/CODE&amp;gt;,&lt;br /&gt;
::and &amp;lt;CODE&amp;gt;10 volt / 1000&amp;lt;/CODE&amp;gt; =&amp;gt; 10 milliVolt&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Most Common/Useful Operations ==&lt;br /&gt;
=== Testing ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;isNaN&#039;&#039;&#039;    =&amp;gt; Boolean&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;isNaN&#039;&#039;&#039;()  (in JS syntax)&lt;br /&gt;
::Check if number is NaN (&amp;quot;&#039;&#039;Not a Number&#039;&#039;&amp;quot;). Notice that there are multiple representations of &amp;quot;NaN&amp;quot;: &amp;quot;&amp;lt;CODE&amp;gt;Float32 NaN&amp;lt;/CODE&amp;gt;&amp;quot;, &amp;quot;&amp;lt;CODE&amp;gt;Float64 NaN&amp;lt;/CODE&amp;gt;&amp;quot; etc.&amp;lt;br&amp;gt;Therefore, you should not compare against NaN with an identity compare operations (i.e. you should use isNaN to test, not compare for identity against another NaN) &lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;isFinite&#039;&#039;&#039;    =&amp;gt; Boolean&lt;br /&gt;
::Check if number is not infinity and not NaN. As with NaN, there are multiple such &amp;quot;infinities&amp;quot;; one in each float class.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;isInfinite&#039;&#039;&#039;  =&amp;gt; Boolean&lt;br /&gt;
::Check if number is either positive infinity (INF) or negative infinity (-INF).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;isPositiveInfinity&#039;&#039;&#039;  =&amp;gt; Boolean&lt;br /&gt;
::Check if number is the positive infinity (+INF).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;isNegativeInfinity&#039;&#039;&#039;  =&amp;gt; Boolean&lt;br /&gt;
::Check if number is the negative infinity (-INF).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;isInteger&#039;&#039;&#039;    =&amp;gt; Boolean&lt;br /&gt;
::Check if number is an integral number.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;isFraction&#039;&#039;&#039;    =&amp;gt; Boolean&lt;br /&gt;
::Check if number is a fractional number.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;isFloat&#039;&#039;&#039;    =&amp;gt; Boolean&lt;br /&gt;
::Check if number is any float number (Float32, Float64, Float128, etc.).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;exponent&#039;&#039;&#039;  =&amp;gt; Integer&lt;br /&gt;
::For floats only: returns the exponent, such that the number&#039;s value is:&amp;lt;br&amp;gt; &amp;quot;mantissa * (2 ^ exponent)&amp;quot;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;mantissa&#039;&#039;&#039;  =&amp;gt; Integer&lt;br /&gt;
::For floats only: returns the mantissa, such that the number&#039;s value is:&amp;lt;br&amp;gt; &amp;quot;mantissa * (2 ^ exponent)&amp;quot;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;precision&#039;&#039;&#039;  =&amp;gt; Integer&lt;br /&gt;
::For floats only: returns the number of bits in the number&#039;s mantissa.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;decimalPrecision&#039;&#039;&#039;  =&amp;gt; Integer&lt;br /&gt;
::For floats only: returns the number of digits in the number&#039;s mantissa.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;floatClass&#039;&#039; &#039;&#039;&#039;fmin&#039;&#039;&#039;  =&amp;gt; float&lt;br /&gt;
::For float classes only: returns the smallest representable (normalized) number of that class.&amp;lt;br&amp;gt;For example, &amp;quot;&amp;lt;CODE&amp;gt;FloatD fmin&amp;lt;/CODE&amp;gt;&amp;quot; would return 2.2250738585072e-308. Any operation which would generate a smaller number will deliver -INF.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;floatClass&#039;&#039; &#039;&#039;&#039;fmax&#039;&#039;&#039;  =&amp;gt; float&lt;br /&gt;
::For float classes only: returns the largest representable number of that class.&amp;lt;br&amp;gt;For example, &amp;quot;&amp;lt;CODE&amp;gt;FloatD fmax&amp;lt;/CODE&amp;gt;&amp;quot; would return 1.79769313486232e+308. Any operation which would generate a larger number will deliver +INF.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;floatClass&#039;&#039; &#039;&#039;&#039;emin&#039;&#039;&#039; / &#039;&#039;&#039;emax&#039;&#039;&#039; =&amp;gt; integer&lt;br /&gt;
::For float classes only: returns the smallest and largest possible exponent representable by numbers of that class.&amp;lt;br&amp;gt;For example, &amp;quot;&amp;lt;CODE&amp;gt;FloatD emin&amp;lt;/CODE&amp;gt;&amp;quot; would return -1022. Notice that this is the exponent of the power-of-two; the corresponding decimal min/max exponent can be computed by multiplying it by log10(2).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;isComplex&#039;&#039;&#039;    =&amp;gt; Boolean&lt;br /&gt;
::Check if number is a complex number.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;negative&#039;&#039;&#039; =&amp;gt; Boolean&lt;br /&gt;
::same as &amp;lt;code&amp;gt;&#039;&#039;aNumber&#039;&#039; &amp;lt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;positive&#039;&#039;&#039; =&amp;gt; Boolean&lt;br /&gt;
::same as &amp;lt;code&amp;gt;&#039;&#039;aNumber&#039;&#039; &amp;gt;= 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;strictlyPositive&#039;&#039;&#039; =&amp;gt; Boolean&lt;br /&gt;
::same as &amp;lt;code&amp;gt;&#039;&#039;aNumber&#039;&#039; &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;anInteger&#039;&#039; &#039;&#039;&#039;isPrime&#039;&#039;&#039; =&amp;gt; Boolean&lt;br /&gt;
::true if the number is a prime (integer) number&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;anInteger&#039;&#039; &#039;&#039;&#039;isPowerOf2&#039;&#039;&#039;  =&amp;gt; Boolean&lt;br /&gt;
::true if there exists an n, such that 2ˆn equals the number&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;anInteger&#039;&#039; &#039;&#039;&#039;isPowerOf:&#039;&#039;&#039; &#039;&#039;b&#039;&#039; =&amp;gt; Boolean&lt;br /&gt;
::true if there exists an n, such that bˆn equals the number&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
=== Arithmetic ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;+&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;  =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;-&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;  =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;*&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;  =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;/&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;  =&amp;gt; Number&lt;br /&gt;
::The usual arithmetic operators.&amp;lt;br&amp;gt;&lt;br /&gt;
::All of the above allow operands of any number type, and will generate a result as appropriate. When dividing integers, an exact result is returned (either integer or fraction). If any of the arguments is inexact (i.e. a floating point number), the result will be inexact. If both are exact, the result will be exact. Fractional results are reduced to the greatest common divisor as denominator.&lt;br /&gt;
::[[Datei:point_right.png|20px]] Notice, that Smalltalk evaluates them left to right, without special precedences.&amp;lt;br&amp;gt;Thus you should always use parentheses to group expressions when there are two or more operators in an arithmetic expression. It is good practice to use parentheses even in expressions where the evaluation order gives the correct result.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;**&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;raisedTo:&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;  =&amp;gt; Number&lt;br /&gt;
::exponentiation (raising to a power)&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
  2 ** 20&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 1048576&amp;lt;/small&amp;gt;&lt;br /&gt;
  4 ** 3.5&lt;br /&gt;
      =&amp;gt; 128.0&lt;br /&gt;
  100 ** 0.5&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 10.0&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;//&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;  =&amp;gt; Integer&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;\\&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;  =&amp;gt; Integer&lt;br /&gt;
::Truncated result and remainder (towards the next smaller integer i.e. towards negative infinity).&amp;lt;br&amp;gt;The following equation holds: &amp;lt;code&amp;gt;(a // b) * b + (a \\ b) = a&amp;lt;/code&amp;gt;&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
  100 // 3&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 33&amp;lt;/small&amp;gt;&lt;br /&gt;
  100 \\ 3&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 1&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  -100 // 3&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; -34&amp;lt;/small&amp;gt;&lt;br /&gt;
  -100 \\ 3&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;quo:&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;  =&amp;gt; Integer&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;rem:&#039;&#039;&#039; &#039;&#039;aNumber&#039;&#039;  =&amp;gt; Integer&lt;br /&gt;
::Truncated result (towards zero) and corresponding remainder.&amp;lt;br&amp;gt;For positive arguments, this is the same as the above, for negative args, a different result is returned.&amp;lt;br&amp;gt;However, the equation is similar to above: &amp;lt;code&amp;gt;(a quo: b) * b + (a rem: b) = a&amp;lt;/code&amp;gt; &lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
  100 quo: 3&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 33&amp;lt;/small&amp;gt;&lt;br /&gt;
  100 rem: 3&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 1&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  -100 quo: 3&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; -33&amp;lt;/small&amp;gt;&lt;br /&gt;
  -100 rem: 3&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; -1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;abs&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::the absolute value.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;negated&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::the negated value.&lt;br /&gt;
&lt;br /&gt;
=== Mathematical and Trigonometric Functions ===&lt;br /&gt;
The usual operations are provided as unary messages to the number:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;ln&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;log10&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;log2&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;log:&#039;&#039;&#039; &#039;&#039;base&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;integerLog10&#039;&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;integerLog2&#039;&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::logarithm (natural, base10, base2 or arbitrary base).&lt;br /&gt;
::These are not restricted to floats; they can also be applied to big integers,&amp;lt;br&amp;gt;as in: &amp;quot;&amp;lt;code&amp;gt;1000 factorial ln&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
::By default, an error is reported for negative numbers;&lt;br /&gt;
::to get a complex result, use &amp;quot;&amp;lt;code&amp;gt;Complex trapImaginary:[ aNumber ln ]&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;sqrt&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;anInteger&#039;&#039; &#039;&#039;&#039;integerSqrt&#039;&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::square root and truncated square root&amp;lt;br&amp;gt;By default, an error is reported for negative numbers;&amp;lt;br&amp;gt;to get a complex result, use &amp;quot;&amp;lt;code&amp;gt;Complex trapImaginary:[ aNumber sqrt ]&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cbrt&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;anInteger&#039;&#039; &#039;&#039;&#039;integerCbrt&#039;&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::cubic root and truncated cubic root.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;nthRoot:&#039;&#039;&#039; &#039;&#039;n&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::the nth root.&amp;lt;br&amp;gt;&amp;quot;&amp;lt;code&amp;gt;n nthRoot:2&amp;lt;/code&amp;gt;&amp;quot; gives the same result as &amp;quot;&amp;lt;code&amp;gt;sqrt&amp;lt;/code&amp;gt;&amp;quot;&amp;lt;br&amp;gt;and &amp;quot;&amp;lt;code&amp;gt;n nthRoot:3&amp;lt;/code&amp;gt;&amp;quot; the same as the cubic root.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;exp&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;number1&#039;&#039; &#039;&#039;&#039;raisedTo:&#039;&#039;&#039; &#039;&#039;number2&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;number1&#039;&#039; &#039;&#039;&#039;**&#039;&#039;&#039; &#039;&#039;number2&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::exponentiation; the &amp;quot;&amp;lt;code&amp;gt;**&amp;lt;/code&amp;gt;&amp;quot; binary operator is an alias for &amp;quot;&amp;lt;code&amp;gt;raisedTo:&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;sin&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cos&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;tan&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cot&#039;&#039;&#039; =&amp;gt; Number (cotangent)&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;sec&#039;&#039;&#039; =&amp;gt; Number (secant)&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;csc&#039;&#039;&#039; =&amp;gt; Number (cosecant)&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;arcSin&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;arcCos&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;arcTan&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;arcTan2:&#039;&#039;&#039; &#039;&#039;x&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::trigonometric functions&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;sinh&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;cosh&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;tanh&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;arSinh&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;arCosh&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;arTanh&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::hyperbolic functions&lt;br /&gt;
&lt;br /&gt;
=== Truncation and Rounding ===&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;ceiling&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::returns the next larger integer (unless aNumber is integral).&amp;lt;br&amp;gt;E.g. truncates towards positive infinity.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;floor&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::returns the next smaller integer (unless aNumber is integral).&amp;lt;br&amp;gt;E.g. truncates towards negative infinity.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;truncated&#039;&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::truncates towards zero&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;truncateTo:&#039;&#039;&#039; &#039;&#039;grid&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::truncates towards the nearest multiple of &#039;&#039;grid&#039;&#039;. &amp;lt;br&amp;gt;E.g. &amp;quot;&amp;lt;code&amp;gt;1.284 truncateTo:0.1&amp;lt;/code&amp;gt;&amp;quot; yields &amp;quot;1.2&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;rounded&#039;&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::rounds up/down towards the nearest integer&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;roundTo:&#039;&#039;&#039; &#039;&#039;grid&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::rounds up/down towards the nearest multiple of &#039;&#039;grid&#039;&#039;. &amp;lt;br&amp;gt;E.g. &amp;quot;&amp;lt;code&amp;gt;1.284 roundTo:0.1&amp;lt;/code&amp;gt;&amp;quot; yields &amp;quot;1.3&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;523 roundTo:5&amp;lt;/code&amp;gt;&amp;quot; yields &amp;quot;525&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;roundToNumberOfDigits:&#039;&#039;&#039; &#039;&#039;n&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::rounds up/down for n valid digits. &amp;lt;br&amp;gt;E.g. &amp;quot;&amp;lt;code&amp;gt;1.284 roundToNumberOfDigits:2&amp;lt;/code&amp;gt;&amp;quot; yields &amp;quot;1.3&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;5234 roundToNumberOfDigits:2&amp;lt;/code&amp;gt;&amp;quot; yields &amp;quot;5200&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;roundToPrecision:&#039;&#039;&#039; &#039;&#039;n&#039;&#039; =&amp;gt; Number&lt;br /&gt;
::rounds up/down for n decimal fraction digits. &amp;lt;br&amp;gt;E.g. &amp;quot;&amp;lt;code&amp;gt;1.284 roundToPrecision:2&amp;lt;/code&amp;gt;&amp;quot; yields &amp;quot;1.28&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;5234.356 roundToPrecision:2&amp;lt;/code&amp;gt;&amp;quot; yields &amp;quot;5234.36&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Statistical / Combinatorical Functions ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;anInteger&#039;&#039; &#039;&#039;&#039;factorial&#039;&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::the factorial; i.e. &amp;quot;&amp;lt;code&amp;gt;n factorial&amp;lt;/code&amp;gt;&amp;quot; is 2*3*4...*n&amp;quot;. Huge numbers are to be expected (try &amp;quot;&amp;lt;code&amp;gt;1000 factorial inspect&amp;lt;/code&amp;gt;&amp;quot; in a workspace).&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;n&#039;&#039; &#039;&#039;&#039;binomialCoefficient:&#039;&#039;&#039; &#039;&#039;k&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
:&#039;&#039;n&#039;&#039; &#039;&#039;&#039;binco:&#039;&#039;&#039; &#039;&#039;k&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::the binomial coefficient (aka. &#039;&#039;n over k&#039;&#039; or the number of ways of picking k unordered outcomes from n possibilities)&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;n&#039;&#039; &#039;&#039;&#039;agm:&#039;&#039;&#039; &#039;&#039;y&#039;&#039; =&amp;gt; Float&lt;br /&gt;
::the arithmetic-geometric mean&lt;br /&gt;
&lt;br /&gt;
=== Other Special Functions ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;gcd:&#039;&#039;&#039; &#039;&#039;integer2&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::the greatest common divisor of integer1 and integer2.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;lcm:&#039;&#039;&#039; &#039;&#039;integer2&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::the least common multiple of integer1 and integer2.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;anInteger&#039;&#039; &#039;&#039;&#039;fib&#039;&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::the nth Fibonacci number. Huge numbers are to be expected (try &amp;quot;&amp;lt;code&amp;gt;1000 fib inspect&amp;lt;/code&amp;gt;&amp;quot; in a workspace).&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;fib_binet&#039;&#039;&#039; =&amp;gt; Float&lt;br /&gt;
::an approximation of the nth Fibonacci number according to Binet.&amp;lt;br&amp;gt;For example, &amp;quot;&amp;lt;code&amp;gt;5000 fib_binet&amp;lt;/code&amp;gt;&amp;quot; gives: &amp;quot;1.0777734893072974780...e+10449&amp;quot; (by default with 200 bits precision)&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;erf&#039;&#039;&#039; =&amp;gt; Float&lt;br /&gt;
::the error function&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;gamma&#039;&#039;&#039; =&amp;gt; Float&lt;br /&gt;
::the gamma function&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;anInteger&#039;&#039; &#039;&#039;&#039;nextPrime&#039;&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::the next prime number.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;anInteger&#039;&#039; &#039;&#039;&#039;primeFactors&#039;&#039;&#039; =&amp;gt; Collection&lt;br /&gt;
::the prime factors. Can take a long time for big numbers.&lt;br /&gt;
&lt;br /&gt;
=== Bitwise Operators ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;bitAnd:&#039;&#039;&#039; &#039;&#039;integer2&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;bitOr:&#039;&#039;&#039; &#039;&#039;integer2&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;bitXor:&#039;&#039;&#039; &#039;&#039;integer2&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::bitwise and, or and exclusive or&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;bitShift:&#039;&#039;&#039; &#039;&#039;count&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::left shift if count is positive; right shift if negative&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;leftShift:&#039;&#039;&#039; &#039;&#039;count&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::left shift by count&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;rightShift:&#039;&#039;&#039; &#039;&#039;count&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::right shift by count&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;bitTest:&#039;&#039;&#039; &#039;&#039;integer2&#039;&#039; =&amp;gt; Boolean&lt;br /&gt;
::integer2 is used as a &#039;&#039;mask&#039;&#039; (i.e. bitTest returns true if any bit in the mask is set in the left operand i.e. (i1 &amp;amp; i2) not equal 0&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;bitAt:&#039;&#039;&#039; &#039;&#039;bitNr&#039;&#039; =&amp;gt; integer (0 or 1)&lt;br /&gt;
::extract the nth bit, with bitNr starting at 1&lt;br /&gt;
:&#039;&#039;integer1&#039;&#039; &#039;&#039;&#039;lowBits:&#039;&#039;&#039; &#039;&#039;count&#039;&#039; =&amp;gt; integer&lt;br /&gt;
::extract count lowest bits&lt;br /&gt;
:&#039;&#039;integer&#039;&#039; &#039;&#039;&#039;highBit&#039;&#039;&#039; =&amp;gt; integer (1..)&lt;br /&gt;
::the bit number of the highest bit, with bitNr starting at 1; zero if no bit is set&lt;br /&gt;
:&#039;&#039;integer&#039;&#039; &#039;&#039;&#039;lowBit&#039;&#039;&#039; =&amp;gt; integer (1..)&lt;br /&gt;
::the bit number of the lowest bit, with bitNr starting at 1; zero if no bit is set&lt;br /&gt;
&lt;br /&gt;
=== Printing ===&lt;br /&gt;
&lt;br /&gt;
Numbers can print themself on an output stream, or convert themself to a string:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printOn:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; =&amp;gt; void&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printOn:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;radix:&#039;&#039;&#039; &#039;&#039;base&#039;&#039; =&amp;gt; void&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printOn:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;leftPaddedTo:&#039;&#039;&#039; &#039;&#039;length&#039;&#039; =&amp;gt; void&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printOn:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;leftPaddedTo:&#039;&#039;&#039; &#039;&#039;length&#039;&#039; &#039;&#039;&#039;with:&#039;&#039;&#039; &#039;&#039;padCharacter&#039;&#039; =&amp;gt; void&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printOn:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;paddedTo:&#039;&#039;&#039; &#039;&#039;length&#039;&#039; =&amp;gt; void&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printOn:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;paddedTo:&#039;&#039;&#039; &#039;&#039;length&#039;&#039; &#039;&#039;&#039;with:&#039;&#039;&#039; &#039;&#039;padCharacter&#039;&#039; =&amp;gt; void&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printString&#039;&#039;&#039; =&amp;gt; String&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printStringRadix:&#039;&#039;&#039; &#039;&#039;base&#039;&#039; =&amp;gt; String&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printStringLeftPaddedTo:&#039;&#039;&#039; &#039;&#039;length&#039;&#039; =&amp;gt; String&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printStringLeftPaddedTo:&#039;&#039;&#039; &#039;&#039;length&#039;&#039; &#039;&#039;&#039;with:&#039;&#039;&#039; &#039;&#039;padCharacter&#039;&#039; =&amp;gt; String&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printStringPaddedTo:&#039;&#039;&#039; &#039;&#039;length&#039;&#039; =&amp;gt; String&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printStringPaddedTo:&#039;&#039;&#039; &#039;&#039;length&#039;&#039; &#039;&#039;&#039;with:&#039;&#039;&#039; &#039;&#039;padCharacter&#039;&#039; =&amp;gt; String&lt;br /&gt;
::The above generate a standard format, which should fit most needs. The padded variants fill with either space or the explicit padCharacter. The printOn: variants will send the string to an output stream; the printString variants will return the string.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;formatString&#039;&#039; &#039;&#039;&#039;printf:&#039;&#039;&#039; { &#039;&#039;arg&#039;&#039;... } &#039;&#039;&#039;on:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; =&amp;gt; void&lt;br /&gt;
:&#039;&#039;formatString&#039;&#039; &#039;&#039;&#039;printf:&#039;&#039;&#039; { &#039;&#039;arg&#039;&#039;... } =&amp;gt; String&lt;br /&gt;
::More fine control is available via the printf functions, which also offer a range of options to fill left or right, to control printing of the sign and to fill with zeros.&lt;br /&gt;
::These two interpret the receiver as a C-printf-style format string, and an argument vector as first argument (use a [[Smalltalk_Syntax_Cheat_Sheet#Expressions | brace-array constructor]] or pass a collection as argument).&amp;lt;br&amp;gt;Thus, multiple values are printed as in the following example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&lt;br /&gt;
 &#039;%04x %3d %+4.3f\n&#039; printf:{ 123 . 4 . 3.14159 } on:Transcript&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
::Individual conversions (to a string) can also be done with:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&lt;br /&gt;
 &#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printfPrintString:&#039;&#039;&#039; &#039;&#039;formatString&#039;&#039; =&amp;gt; String&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&lt;br /&gt;
 &#039;% .4f&#039; printf:{Float pi}         =&amp;gt; &#039; 3.1416&#039; (space after % ensures space for sign)&lt;br /&gt;
 &#039;% .4f&#039; printf:{Float pi negated} =&amp;gt; &#039;-3.1416&#039; (space after % ensures space for sign)&lt;br /&gt;
 &#039;%+.4f&#039; printf:{Float pi}         =&amp;gt; &#039;+3.1416&#039; (&#039;+&#039; after % enforces sign)&lt;br /&gt;
 &#039;%+.4f&#039; printf:{Float pi negated} =&amp;gt; &#039;-3.1416&#039; (&#039;+&#039; after % enforces sign)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:: Please refer to a C-printf manual page (e.g. https://en.wikipedia.org/wiki/Printf_format_string).&lt;br /&gt;
:: Notice that printf accepts C-style character escapes (which is not the case in general with Smalltalk string constants)&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;printRomanOn:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; =&amp;gt; void&lt;br /&gt;
::roman style&lt;br /&gt;
&lt;br /&gt;
=== Reading from Streams / Converting from Strings ===&lt;br /&gt;
&lt;br /&gt;
Numbers can be read from a stream or converted from a string. There are slight differences between them:&lt;br /&gt;
* when reading from a stream of characters, the stream will be positioned after the number. So any non-digit character(s) after the number&#039;s characters will be returned by future read operations. The stream can be an internal or external (i.e. file-, pipe- or socket-) stream.&lt;br /&gt;
* when converting from a string, no extra characters are expected/allowed after the number&#039;s digits, except for whitespace. Thus you&#039;ll usually get an error when trying to convert a string with garbage characters after the number (which is not the case when reading from a stream).&lt;br /&gt;
&lt;br /&gt;
Therefore, if you want to read a number from a string which may have garbage characters after the digits, you should first create a read-stream on the string, and then read the number from the stream (i.e. use &amp;quot;&amp;lt;code&amp;gt;Number readFrom:(&#039;&#039;someString&#039;&#039; readStream)&amp;lt;/code&amp;gt;&amp;quot; instead of &amp;quot;&amp;lt;code&amp;gt;Number fromString:&#039;&#039;someString&#039;&#039;&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Numbers are read by sending the Number-class or one of its subclasses one of the &amp;quot;&amp;lt;code&amp;gt;readFrom:&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;fromString:&amp;lt;/code&amp;gt;&amp;quot; messages.&lt;br /&gt;
&lt;br /&gt;
If the class is the abstract class Number, then the read code will itself figure out, what kind of number to return. If the class is a concrete class (Float, Integer, Fraction etc.), you will get an instance of that class, unless the characters do not represent a valid number (of that class). In that case, an error is reported.&lt;br /&gt;
&lt;br /&gt;
By default, errors are reported by raising an exception, unless you provide an error-handler as argument to the reader; more on that below.&lt;br /&gt;
 &lt;br /&gt;
:Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; =&amp;gt; someNumber or error&lt;br /&gt;
:: this can return an instance of any of the number types&lt;br /&gt;
:Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;onError:&#039;&#039;&#039;[ &#039;&#039;errorValue&#039;&#039; ] =&amp;gt; someNumber or errorValue&lt;br /&gt;
:: errorValue can be a constant, an arbitrary Smalltalk expression or even show a warn dialog or do whatever you like. In case of an error, the value returned from the read method will be the value provided by the error-block. Notice, that numbers themself respond to the &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; message and will return themself. Thus you can also provide a replacement value instead of an error block.&lt;br /&gt;
:Number &#039;&#039;&#039;fromString:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039; =&amp;gt; someNumber or error&lt;br /&gt;
:Number &#039;&#039;&#039;fromString:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039; &#039;&#039;&#039;onError:&#039;&#039;&#039;[ &#039;&#039;errorValue&#039;&#039; ]&amp;lt;/code&amp;gt; =&amp;gt; someNumber or fallBackValue&lt;br /&gt;
:: similar, but does not allow for garbage characters after the number (except spaces)&lt;br /&gt;
&lt;br /&gt;
:Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039;&lt;br /&gt;
:Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;onError:&#039;&#039;&#039;[...]&lt;br /&gt;
:Float &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039;&lt;br /&gt;
:Float &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;onError:&#039;&#039;&#039;[...]&lt;br /&gt;
:Integer &#039;&#039;&#039;fromString:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039;&lt;br /&gt;
:Integer &#039;&#039;&#039;fromString:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;onError:&#039;&#039;&#039;[...]&lt;br /&gt;
:Float &#039;&#039;&#039;fromString:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039;&lt;br /&gt;
:Float &#039;&#039;&#039;fromString:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; &#039;&#039;&#039;onError:&#039;&#039;&#039;[...]&lt;br /&gt;
:: similar to the above, but these will return a correspondingly typed number (i.e. an instance of Integer, Float, etc.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;formatString&#039;&#039; &#039;&#039;&#039;sscanf:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039; =&amp;gt; collection&lt;br /&gt;
:: &#039;&#039;formatString&#039;&#039; is a printf/scanf-like format string; reads items from &#039;&#039;aString&#039;&#039; and returns a collection (i.e. an Array) of scanned objects.&amp;lt;br&amp;gt;For example,&amp;lt;br&amp;gt;&amp;lt;code&amp;gt; &#039;%d %x %f&#039; sscanf: &#039;1234 FF 3.1415&#039;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;will return an array-like collection with 3 elements, the integer 1234, the integer 255 and the float 3.14159. &lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;formatString&#039;&#039; &#039;&#039;&#039;scanf:&#039;&#039;&#039; &#039;&#039;aStream&#039;&#039; =&amp;gt; collection&lt;br /&gt;
:: like above, but the elements will be read from a character stream&lt;br /&gt;
&lt;br /&gt;
:To read binary numbers, refer to the stream API.&lt;br /&gt;
&lt;br /&gt;
=== Conversion ===&lt;br /&gt;
&lt;br /&gt;
In certain situations, it may be desirable to convert explicitly to a particular type, for example when binary data has to be verified or filled into a byte-buffer.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asInteger&#039;&#039;&#039; =&amp;gt; Integer&lt;br /&gt;
::truncates to an integer (i.e. same as &amp;quot;truncated&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFloat&#039;&#039;&#039; =&amp;gt; Float64&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFloat64&#039;&#039;&#039; =&amp;gt; Float64&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFloatD&#039;&#039;&#039; =&amp;gt; Float64&lt;br /&gt;
::generates a double precision float; may generate +/- INF if the value cannot be represented as a double IEEE float (i.e. is out of range). asFloat64 and asFloatD are aliases for compatibility.&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFloatChecked&#039;&#039;&#039; =&amp;gt; Float64 or error&lt;br /&gt;
::same as above, but reports an error if the value cannot be represented (instead of returning INF).&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asShortFloat&#039;&#039;&#039; =&amp;gt; Float32&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFloat32&#039;&#039;&#039; =&amp;gt; Float32&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFloatE&#039;&#039;&#039; =&amp;gt; Float32&lt;br /&gt;
::generates a single precision float; may generate +/- INF if the value cannot be represented as a single IEEE float. asFloat32 and asFloatE are aliases.&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asShortFloatChecked&#039;&#039;&#039; =&amp;gt; Float32 or error&lt;br /&gt;
::same as above, but reports an error if the value cannot be represented (instead of returning INF).&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asLongFloat&#039;&#039;&#039; =&amp;gt; Float80&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFloatQ&#039;&#039;&#039; =&amp;gt; Float80&lt;br /&gt;
::generates an extended precision float; may generate +/- INF if the value cannot be represented as an extended IEEE float.&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asLongFloatChecked&#039;&#039;&#039; =&amp;gt; Float80 or error&lt;br /&gt;
::same as above, but reports an error if the value cannot be represented (instead of returning INF).&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asQDouble&#039;&#039;&#039; =&amp;gt; QDouble&lt;br /&gt;
::generates a qDouble&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asQuadFloat&#039;&#039;&#039; =&amp;gt; QuadFloat&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFloat128&#039;&#039;&#039; =&amp;gt; QuadFloat&lt;br /&gt;
::generates a quadruple precision float (float128)&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asOctaFloat&#039;&#039;&#039; =&amp;gt; OctaFloat&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFloat256&#039;&#039;&#039; =&amp;gt; QuadFloat&lt;br /&gt;
::generates an octuple precision float (float256)&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asLargeFloatPrecision:&#039;&#039;&#039; &#039;&#039;numBits&#039;&#039; =&amp;gt; LargeFloat&lt;br /&gt;
::generates an large float with numBits precision&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asLargeFloatDecimalPrecision:&#039;&#039;&#039; &#039;&#039;numDigits&#039;&#039; =&amp;gt; LargeFloat&lt;br /&gt;
::generates an large float with numDigits precision&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asLargeFloat&#039;&#039;&#039;  =&amp;gt; LargeFloat&lt;br /&gt;
::generates an large float with the same precision as aNumber&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFraction&#039;&#039;&#039; =&amp;gt; Fraction&lt;br /&gt;
::generates a fraction (from a float)&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asScaledDecimal:&#039;&#039;&#039; &#039;&#039;scale&#039;&#039; =&amp;gt; ScaledDecimal&lt;br /&gt;
::generates a scaled decimal which presents &#039;&#039;scale&#039;&#039; fractional digits&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asFixedDecimal:&#039;&#039;&#039; &#039;&#039;scale&#039;&#039; =&amp;gt; FixedDecimal&lt;br /&gt;
::generates a fixed decimal which rounds on and presents &#039;&#039;scale&#039;&#039; fractional digits&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;asComplex&#039;&#039;&#039; =&amp;gt; Complex&lt;br /&gt;
::generates a complex (with 0 as imaginary part, same as &amp;quot;&#039;&#039;nr&#039;&#039; + 0i&amp;quot;)&lt;br /&gt;
:&#039;&#039;aNumber&#039;&#039; &#039;&#039;&#039;i&#039;&#039;&#039; =&amp;gt; Complex (that is a lower case i)&lt;br /&gt;
::generates a complex (with 0 as real part, e.g. as in &amp;quot;0 + &#039;&#039;nr&#039;&#039; i&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
==== Square root of 2 with different precision ====&lt;br /&gt;
 nr := 2.0 sqrt.&lt;br /&gt;
 &#039;%.15g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.4142135623731&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%.30g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.414213562373095101065700873732&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%.50g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.41421356237309510106570087373256683349609375&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
Be reminded that these floats (which are IEEE doubles) only provide 15 digits of accuracy (&amp;quot;Float decimalPrecision&amp;quot; returns 15). Thus the above attempts to generate more digits are useless and excess digits are more or less random.&lt;br /&gt;
&lt;br /&gt;
More valid digits are returned by QDoubles (&amp;quot;QDouble decimalPrecision&amp;quot; returns 61):&lt;br /&gt;
 nr := 2.0 asQDouble sqrt.&lt;br /&gt;
 &#039;%.30g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.41421356237309504880168872421&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%.50g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.4142135623730950488016887242096980785696718753769&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%.100g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.414213562373095048801688724209698078569671875376948073176679737988424424484343089516915416653038211&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
Here again, digits after the 60th are wrong.&lt;br /&gt;
&lt;br /&gt;
With octuple precision floats (&amp;quot;OctaFloat decimalPrecision&amp;quot; returns 71) we get:&lt;br /&gt;
 nr := 2.0 asOctaFloat sqrt.&lt;br /&gt;
 &#039;%.30g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.41421356237309504880168872421&#039; (a quadruple precision float)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%.50g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.4142135623730950488016887242096980785696718753769&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%.100g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.41421356237309504880168872420969807856967187537694807317667973799073247801160833747418698891953623&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, an arbitrary number of digits can be computed with LargeFloats (here we use a precision of 1000 bits for roughly 300 digits):&lt;br /&gt;
 nr := (2.0 asLargeFloatPrecision:1000) sqrt.&lt;br /&gt;
 &#039;%.30g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.41421356237309504880168872421&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%.50g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.4142135623730950488016887242096980785696718753769&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%.100g&#039; printf:{nr}   &lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; &#039;1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In most situations, double precision is sufficient. However, some computations generate intermediate results which are outside the precision or range of IEEE doubles. See &amp;quot;[[Do not trust Floating Point]]&amp;quot; for a classic (surprising) example.&lt;br /&gt;
&lt;br /&gt;
==== Reading Numbers ====&lt;br /&gt;
&lt;br /&gt;
readFrom: will not accept garbage characters after the number iff the argument is a string:&lt;br /&gt;
 in := &#039;123.456abc&#039;.&lt;br /&gt;
 Number readFrom: in.&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; error due to garbage after number (&#039;abc&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, it behaves different, if the argument is a stream.&amp;lt;br&amp;gt;Then the stream will be left positioned after the number&#039;s string:&lt;br /&gt;
 Number readFrom: (in readstream).&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; 123.456&lt;br /&gt;
     (stream will be left positioned at the &#039;abc&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
here, reading the rest after the number&#039;s digits:&lt;br /&gt;
 s := in readstream.&lt;br /&gt;
 val := Number readFrom: s.&lt;br /&gt;
 rest := s upToEnd.&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; val: 123.456&lt;br /&gt;
        rest: &#039;abc&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
you can provide an error-value:&lt;br /&gt;
 val := Number readFrom:&#039;bla&#039; onError:[0]&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; val: 0&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or perform any action inside the onError arg block:&lt;br /&gt;
 val := Number readFrom:&#039;blabla&#039; onError:[ Dialog warn:&#039;bad input&#039;. nil ]&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; (Dialog shown)&lt;br /&gt;
        val: nil&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an alternative to &amp;quot;readFrom:&amp;quot; is scanf, which can also read multiple values from a stream:&lt;br /&gt;
 row := &#039;%d %f %s&#039; scanf:(ReadStream on:&#039;1234 1111.2345 Fritz&#039;).&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; OrderedCollection(1234 1111.2345 &#039;Fritz&#039;)&lt;br /&gt;
        i.e. an integer, a float and a string&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or from a string:&lt;br /&gt;
 myString := &#039;1234 1111.2345 Fritz&#039;.&lt;br /&gt;
 row := &#039;%d %f %s&#039; scanf: myString.&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; OrderedCollection(1234 1111.2345 &#039;Fritz&#039;)&lt;br /&gt;
        i.e. same as above&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
scanf can also be used to extract numbers which are not delimited by spaces (you have to specify the field length in the format):&lt;br /&gt;
 myString := &#039;1.234.5679875679&#039;.&lt;br /&gt;
 &#039;%4f %5f %3d %4d&#039; scanf:myString&lt;br /&gt;
     &amp;lt;small&amp;gt;=&amp;gt; OrderedCollection(1.23 4.567 987 5679)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Printf Format Specifier ==&lt;br /&gt;
&lt;br /&gt;
Characters not escaped by a &#039;%&#039; are printed as-is. &lt;br /&gt;
Following a &#039;%&#039; there can be:&lt;br /&gt;
* optional: &#039;-&#039; (POSIX refers to this as the &amp;lt;&amp;lt;flags&amp;gt;&amp;gt;)&lt;br /&gt;
* optional: positive number or &#039;*&#039; (POSIX: &amp;lt;&amp;lt;width&amp;gt;&amp;gt;)&lt;br /&gt;
* optional: period followed by positive number or * (POSIX: &amp;lt;&amp;lt;precision&amp;gt;&amp;gt;)&lt;br /&gt;
* optional: an h or l to indicate size of data (POSIX: &amp;lt;&amp;lt;length&amp;gt;&amp;gt;)&lt;br /&gt;
* required: character describing output behavior (POSIX: &amp;lt;&amp;lt;conversion specifier&amp;gt;&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
The format follows the &#039;&#039;official&#039;&#039; C-library printf formats; however, there are differences in&lt;br /&gt;
the various printf implementations:&lt;br /&gt;
 &lt;br /&gt;
ANSI standards up through C99:&lt;br /&gt;
* more flags: &#039;+&#039; &#039; &#039; &#039;0&#039; &#039;#&#039;&lt;br /&gt;
* more lengths: &#039;L&#039; &#039;hh&#039; &#039;ll&#039; &#039;j&#039; &#039;z&#039; &#039;t&#039;&lt;br /&gt;
* more conversions: &#039;F&#039; &#039;a&#039; &#039;A&#039; &#039;n&#039;&lt;br /&gt;
&lt;br /&gt;
The POSIX specification of printf added:&lt;br /&gt;
* positional parameters to identify argument indices&lt;br /&gt;
* more flags: &#039;&#039;&#039; (single quote)&lt;br /&gt;
* more conversions: &#039;C&#039; &#039;S&#039;&lt;br /&gt;
* clarifications regarding corner cases and &#039;undefined behavior&#039;&lt;br /&gt;
&lt;br /&gt;
BSD implementations added:&lt;br /&gt;
* more lengths: &#039;q&#039;&lt;br /&gt;
* more conversions: &#039;D&#039; &#039;U&#039; &#039;O&#039;&lt;br /&gt;
&lt;br /&gt;
glibc (GNU) added:&lt;br /&gt;
* more lengths: &#039;Z&#039;&lt;br /&gt;
* more conversions: &#039;m&#039;&lt;br /&gt;
&lt;br /&gt;
Windows C Runtime (CRT) added:&lt;br /&gt;
* more lengths: &#039;I&#039; &#039;I32&#039; &#039;I64&#039; &#039;w&#039;&lt;br /&gt;
&lt;br /&gt;
glibc and CRT both added length &#039;Z&#039;. &lt;br /&gt;
* glibc uses &#039;Z&#039; for the length size_t. &lt;br /&gt;
* CRT uses Z as a conversion for length-prefixed strings. &lt;br /&gt;
&lt;br /&gt;
The expecco/Smalltalk implementation handles &#039;Z&#039; in the same way as &#039;z&#039;.&lt;br /&gt;
&lt;br /&gt;
BSD and IBM C library both added &#039;D&#039;. &lt;br /&gt;
* BSD uses D as a conversion, namely as an alias of &#039;ld&#039;. &lt;br /&gt;
* IBM uses &#039;D&#039; for the length for _Decimal64, a decimal floating point type, &lt;br /&gt;
* in accordance with ISO/IEC TR 24732. &lt;br /&gt;
The Smalltalk implementation takes the former approach.&lt;br /&gt;
&lt;br /&gt;
The expecco/Smalltalkimplementation also adds new conversions:&lt;br /&gt;
&lt;br /&gt;
* &#039;b&#039; and &#039;B&#039; for binary (base-2) integer renderings&lt;br /&gt;
* &#039;y&#039; and &#039;Y&#039; for true/false and yes/no Boolean conversions&lt;br /&gt;
* &#039;J&#039; for JSON (assuming that the object can be JSON-encoded)&lt;br /&gt;
* &#039;T&#039; and &#039;V&#039; for JS typeof and valueOf inspection&lt;br /&gt;
* &#039;S&#039; for store-string (of any object)&lt;br /&gt;
* &#039;P&#039; for print-string (of any object)&lt;br /&gt;
&lt;br /&gt;
Prefixes:&lt;br /&gt;
* &#039; &#039;     fill with spaces&lt;br /&gt;
* &#039;0&#039;     fill with zeros&lt;br /&gt;
* &#039;+&#039;     print the sign&lt;br /&gt;
* &#039;-&#039;     left justified&lt;br /&gt;
* &#039;#&#039;     depends:&lt;br /&gt;
** %o, %x, %b: print base prefix&lt;br /&gt;
** %e always show decimal point&lt;br /&gt;
** %e, %E, %f, %g always show decimal point&lt;br /&gt;
&lt;br /&gt;
Conversions:&lt;br /&gt;
* &#039;a&#039;     (not implemented) hex floating point exp form&lt;br /&gt;
* &#039;b&#039;     binary (base 2)&lt;br /&gt;
* &#039;c&#039;     character or (first char of string)&lt;br /&gt;
* &#039;d&#039;     integer&lt;br /&gt;
* &#039;e&#039;     base-10 floating point exp form (scientific)&lt;br /&gt;
* &#039;f&#039;     base-10 floating point decimal form (non-scientific)&lt;br /&gt;
* &#039;g&#039;     &#039;e&#039; or &#039;f&#039;, whichever looks more appropriate (based on the float-value)&lt;br /&gt;
* &#039;i&#039;     integer (alias for &#039;d&#039;)&lt;br /&gt;
* &#039;j&#039;     (not implemented) use &#039;J&#039; for JSON format&lt;br /&gt;
* &#039;n&#039;     (not implemented) stores number of characters written so far into arg &lt;br /&gt;
* &#039;o&#039;     base-8 octal&lt;br /&gt;
* &#039;p&#039;     (not implemented) pointer &lt;br /&gt;
* &#039;s&#039;     string&lt;br /&gt;
* &#039;t&#039;     type (i.e. class name)&lt;br /&gt;
* &#039;u&#039;     (not implemented) unsigned (negative values are converted)&lt;br /&gt;
* &#039;v&#039;     (not implemented) store string&lt;br /&gt;
* &#039;x&#039;     base-16 hex&lt;br /&gt;
* &#039;X&#039;     base-16 hex upper case&lt;br /&gt;
&lt;br /&gt;
Parameter selection (not implemented):&lt;br /&gt;
* &amp;lt;n&amp;gt;$    take n&#039;th parameter&lt;br /&gt;
&lt;br /&gt;
Dynamic width/precision (consumed in order as presented):&lt;br /&gt;
* &amp;quot;*&amp;quot;     take width/parameter from next argument&lt;br /&gt;
&lt;br /&gt;
Special output specifier:&lt;br /&gt;
* &amp;lt;n&amp;gt;!    if the number&#039;s string is larger than the field width &amp;lt;n&amp;gt;, it will be filled with &#039;#&#039;s. Useful if you want to ensure tabular data to remain aligned. This is not a posix printf specified, but a Smalltalk/X extension. &lt;br /&gt;
&lt;br /&gt;
Examples &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;:&lt;br /&gt;
 &#039;|%d|&#039;   printf: { 123 }         -&amp;gt; &amp;lt;small&amp;gt;&#039;|123|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%5d|&#039;  printf: { 123 }         -&amp;gt; &amp;lt;small&amp;gt;&#039;|  123|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%-5d|&#039; printf: { 123 }         -&amp;gt; &amp;lt;small&amp;gt;&#039;|123  |&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &#039;|%s|&#039;  printf: { &#039;abc&#039; }        -&amp;gt; &amp;lt;small&amp;gt;&#039;|abc|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%5s|&#039; printf: { &#039;abc&#039; }        -&amp;gt; &amp;lt;small&amp;gt;&#039;|  abc|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%*s|&#039; printf: { 5 . &#039;abc&#039; }    -&amp;gt; &amp;lt;small&amp;gt;&#039;|  abc|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &#039;|%f|&#039;    printf: { 1.234 }       -&amp;gt; &amp;lt;small&amp;gt;&#039;|1.234|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%#f|&#039;   printf: { 1.234 }       -&amp;gt; &amp;lt;small&amp;gt;&#039;|1.234000|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &#039;|%8f|&#039; printf: { 1.234 }        -&amp;gt; &amp;lt;small&amp;gt;&#039;|   1.234|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%*f|&#039; printf: { 8 . 1.234 }    -&amp;gt; &amp;lt;small&amp;gt;&#039;|   1.234|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%10f|&#039;  printf: { 1.234 }       -&amp;gt; &amp;lt;small&amp;gt;&#039;|     1.234|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%#10f|&#039; printf: { 1.234 }       -&amp;gt; &amp;lt;small&amp;gt;&#039;|  1.234000|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Negative width will fill at the right:&lt;br /&gt;
 &#039;|%5s|&#039;  printf: { &#039;abc&#039; }       -&amp;gt; &amp;lt;small&amp;gt;&#039;|  abc|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%-5s|&#039; printf: { &#039;abc&#039; }       -&amp;gt; &amp;lt;small&amp;gt;&#039;|abc  |&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%-*s|&#039; printf: { 5 . &#039;abc&#039; }   -&amp;gt; &amp;lt;small&amp;gt;&#039;|abc  |&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%*s|&#039;  printf: { -5 . &#039;abc&#039; }  -&amp;gt; &amp;lt;small&amp;gt;&#039;|abc  |&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &#039;|%-8f|&#039; printf: { 1.234 }       -&amp;gt; &amp;lt;small&amp;gt;&#039;|1.234   |&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%*f|&#039;  printf: { -8 . 1.234 }  -&amp;gt; &amp;lt;small&amp;gt;&#039;|1.234   |&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%-*f|&#039; printf: { 8 . 1.234 }   -&amp;gt; &amp;lt;small&amp;gt;&#039;|1.234   |&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%-*f|&#039; printf: { -8 . 1.234 }  -&amp;gt; &amp;lt;small&amp;gt;&#039;|1.234   |&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
A Zero as fill character (only at the left):&lt;br /&gt;
 &#039;|%05s|&#039;  printf: { &#039;abc&#039; }      -&amp;gt; &amp;lt;small&amp;gt;&#039;|00abc|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%05d|&#039;  printf: { 123 }        -&amp;gt; &amp;lt;small&amp;gt;&#039;|00123|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Field width overflow:&lt;br /&gt;
 &#039;|%4d|&#039; printf: { 123456 }       -&amp;gt; &amp;lt;small&amp;gt;&#039;|123456|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;|%4!d|&#039; printf: { 123456 }      -&amp;gt; &amp;lt;small&amp;gt;&#039;|####|&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The case (upper vs. lower) of the float-format character affects printing of Nan, Infinity and exponent separator:&lt;br /&gt;
 &#039;%f&#039; printf: { 1.234 }                 -&amp;gt; &amp;lt;small&amp;gt;&#039;1.234000&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%F&#039; printf: { 1.234 }                 -&amp;gt; &amp;lt;small&amp;gt;&#039;1.234000&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%e&#039; printf: { 1.234 }                 -&amp;gt; &amp;lt;small&amp;gt;&#039;1.234e0&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%E&#039; printf: { 1.234 }                 -&amp;gt; &amp;lt;small&amp;gt;&#039;1.234E0&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%f&#039; printf: {Float NaN}               -&amp;gt; &amp;lt;small&amp;gt;&#039;nan&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%F&#039; printf: {Float NaN}               -&amp;gt; &amp;lt;small&amp;gt;&#039;NAN&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%f&#039; printf: {Float infinity}          -&amp;gt; &amp;lt;small&amp;gt;&#039;inf&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%F&#039; printf: {Float infinity}          -&amp;gt; &amp;lt;small&amp;gt;&#039;INF&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%f&#039; printf: {Float negativeInfinity}  -&amp;gt; &amp;lt;small&amp;gt;&#039;-inf&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%F&#039; printf: {Float negativeInfinity}  -&amp;gt; &amp;lt;small&amp;gt;&#039;-INF&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%-F&#039; printf: {Float infinity}         -&amp;gt; &amp;lt;small&amp;gt;&#039;+INF&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%-F&#039; printf: {Float negativeInfinity} -&amp;gt; &amp;lt;small&amp;gt;&#039;-INF&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;% F&#039; printf: {Float infinity}         -&amp;gt; &amp;lt;small&amp;gt;&#039; INF&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;% F&#039; printf: {Float negativeInfinity} -&amp;gt; &amp;lt;small&amp;gt;&#039;-INF&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
1) Reminder: the &amp;quot;{ ... }&amp;quot; syntax in Smalltalk generates an Array containing the elements (expressions) separated by periods. I.e. &amp;quot;{ 1+2 . 3+4 }&amp;quot; would generate an array with 2 elements: 3 and 7.&amp;lt;br&amp;gt;With constant arguments, this is (almost) equivalent to #( el1 el2) (without periods). Except for the fact, that constant arrays are immutable (readonly), whereas the brace construct instantiates a new array which is mutable.&lt;br /&gt;
&lt;br /&gt;
== Scanf Format Specifier ==&lt;br /&gt;
     &lt;br /&gt;
The Smalltalk implementation adds new conversions:&lt;br /&gt;
&lt;br /&gt;
Conversions (upper case same as lower case):&lt;br /&gt;
* &#039;b&#039;     binary (base 2)&lt;br /&gt;
* &#039;c&#039;     character or (first char of string)&lt;br /&gt;
* &#039;d&#039;     decimal&lt;br /&gt;
* &#039;e&#039;     float&lt;br /&gt;
* &#039;f&#039;     float&lt;br /&gt;
* &#039;g&#039;     float&lt;br /&gt;
* &#039;i&#039;     integer (alias for &#039;d&#039;)&lt;br /&gt;
* &#039;o&#039;     base-8 octal&lt;br /&gt;
* &#039;s&#039;     string&lt;br /&gt;
* &#039;u&#039;     integer&lt;br /&gt;
* &#039;x&#039;     base-16 hex&lt;br /&gt;
* &#039;n&#039;     any number&lt;br /&gt;
* &#039;J&#039;     JSON object (upper case &#039;J&#039; only)&lt;br /&gt;
&lt;br /&gt;
Length prefix:&lt;br /&gt;
&lt;br /&gt;
* &#039;h&#039;     with float formats: reads as ShortFloat&lt;br /&gt;
* &#039;L&#039;     with float formats: reads as LongFloat&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 &#039;%d %x&#039; sscanf:&#039;1234 ff00&#039;         &amp;lt;small&amp;gt;-&amp;gt; OrderedCollection(1234 65280)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%d %s&#039; sscanf:&#039;1234 ff00&#039;         &amp;lt;small&amp;gt;-&amp;gt; OrderedCollection(1234 &#039;ff00&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &#039;%d %x %b&#039; sscanf:&#039;1234 ff00 1001&#039; &amp;lt;small&amp;gt;-&amp;gt; OrderedCollection(1234 65280 9)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 (&#039;%f&#039; sscanf:&#039;1234&#039;) first         &amp;lt;small&amp;gt;-&amp;gt; 1234.0 (Float i.e. an IEEE double)&amp;lt;/small&amp;gt;&lt;br /&gt;
 (&#039;%lf&#039; sscanf:&#039;1234&#039;) first        &amp;lt;small&amp;gt;-&amp;gt; 1234.0 (Float i.e. an IEEE double)&amp;lt;/small&amp;gt;&lt;br /&gt;
 (&#039;%llf&#039; sscanf:&#039;1234&#039;) first       &amp;lt;small&amp;gt;-&amp;gt; 1234.0 (Float i.e. an IEEE double)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 (&#039;%hf&#039; sscanf:&#039;1234&#039;) first        &amp;lt;small&amp;gt;-&amp;gt; 1234.0 (ShortFloat i.e. an IEEE single)&amp;lt;/small&amp;gt;&lt;br /&gt;
 (&#039;%Lf&#039; sscanf:&#039;1234&#039;) first        &amp;lt;small&amp;gt;-&amp;gt; 1234.0 (LongFloat i.e. an IEEE extended)&amp;lt;/small&amp;gt;&lt;br /&gt;
 (&#039;%LLf&#039; sscanf:&#039;1234&#039;) first       &amp;lt;small&amp;gt;-&amp;gt; 1234.0 (QDouble)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
&lt;br /&gt;
[[Numeric Limits/en|Numeric Limits]] provides additional info on precision, ranges and problems with floating point numbers.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=String_API_Functions&amp;diff=30885</id>
		<title>String API Functions</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=String_API_Functions&amp;diff=30885"/>
		<updated>2026-02-23T10:46:54Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 16.2.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document lists most useful (and most often needed) string functions.&lt;br /&gt;
Be aware, that there are many more to be found in either the class references or via the builtin [[Tools_ClassBrowser/en | class browser]].&lt;br /&gt;
&lt;br /&gt;
See also [[Expecco_API/en#String_Handling | &amp;quot;String Handling&amp;quot;]] in [[Expecco_API]].&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,String String]&lt;br /&gt;
inherits from: [http://live.exept.de/ClassDoc/classDocOf:,CharacterArray CharacterArray]&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Collection Collection]&lt;br /&gt;
&lt;br /&gt;
[[Useful API Functions | Back to Useful API Functions]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Notice: unless written otherwise, all indices are 1-based. Valid indices range from 1 to the string&#039;s size.&lt;br /&gt;
&lt;br /&gt;
== Literals (i.e. Constant Strings) ==&lt;br /&gt;
&lt;br /&gt;
Literals are constants in the source code or in expressions entered into a workspace for immediate execution.&lt;br /&gt;
Literal objects are created at compile time and are immutable. That means that an exception will be raised, if the program tries to modify the contents of a literal string at execution time.&lt;br /&gt;
&lt;br /&gt;
Tradititionally, Smalltalk supported only one type of literal string constant,&lt;br /&gt;
which does not support special character escapes (i.e. it was consequently following the philosophy of &amp;quot;&#039;&#039;no surprises&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;what you see is exacty what you get&#039;&#039;&amp;quot;). This has some charm and might be easier to understand for beginners, but makes life of programmers hard at times (think of newlines or tab characters inside a string).&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
For this reason, the underlying Smalltalk/X has been extended to support C-like escaped strings, strings with embedded expressions and international strings which are automatically translated to a national language. Syntaxwise, extended string literals have a prefix such as &#039;c&#039;, &#039;e&#039; or &#039;i&#039;.&lt;br /&gt;
&amp;lt;P&amp;gt;&lt;br /&gt;
Notice that the Python language provides aimilar mechanisms, but has the C-style as default, and the untranslated literal as so-called &amp;quot;&#039;&#039;raw&#039;&#039;&amp;quot; string literal prefixed by an &#039;r&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Traditional String Literals (&#039;&#039;what you see is what you get&#039;&#039;) =====&lt;br /&gt;
:&#039;...&#039; &lt;br /&gt;
::Smalltalk style string (as is; no escapes for special characters). Be aware, that this is inconvenient, if newlines, tabs or other non-graphical characters are to be in the string. Notice that Smalltalk&#039;s plain strings are similar to Python&#039;s &amp;quot;&#039;&#039;Raw Strings&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== C-Style String Literals (with C escapes) =====&lt;br /&gt;
:c&#039;...&#039; &lt;br /&gt;
::C style string (supports the usual C-escapes, such as &amp;quot;\n&amp;quot; for newline, &amp;quot;\t&amp;quot; for tab or &amp;quot;\xHH&amp;quot; and &amp;quot;\uHHHH&amp;quot; for hex codes). Backslashes and single quotes must be prefixed by a backslash (which is especially needed when a string represents a Windows pathname). For example, the literal &amp;lt;code&amp;gt;c&#039;abc\u2021def&#039;&amp;lt;/code&amp;gt; represents the characters &amp;quot;abc‡def&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== Expression Strings (with sliced in expressions) =====&lt;br /&gt;
&lt;br /&gt;
:e&#039;...{expr}...&#039;&lt;br /&gt;
:: C style with embedded expressions. In addition to C-style escapes, expressions in braces are embedded. These expressions are evaluated (at execution time) and their string representation (i.e. the &#039;&#039;printString&#039;&#039;, which is Smalltalk&#039;s equivalent of &#039;&#039;toString&#039;&#039; in JS) sliced into the string.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
 a := 1234.&lt;br /&gt;
 b := true.&lt;br /&gt;
 c := &#039;hello&#039;.&lt;br /&gt;
 foo := e&#039;{c}; this string contains embedded exprs.\nYes, {b} and {a} are there.&#039;&lt;br /&gt;
 foo&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; &#039;hello; this string contains embedded exprs.&lt;br /&gt;
        Yes, true and 1234 are there.&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
::Strictly speaking, these are not literals. Instead, the Smalltalk compiler generates code which expands these at execution time.&lt;br /&gt;
::Semantically, they are equal to a &amp;quot;bindWith:&amp;quot; message (see String class), sent to a string with &amp;quot;%&amp;quot; markers.&lt;br /&gt;
::(Don&#039;t care, if that is too technical).&lt;br /&gt;
&lt;br /&gt;
===== National Language Strings =====&lt;br /&gt;
:i&#039;...{expr}...&#039;&lt;br /&gt;
:: C style with embedded expressions and automatic nationalization. First, it is expanded as a C-style string. Then a translation is looked up in the currently loaded language resources. The template searched has successive expression positions replaced by &amp;quot;%i&amp;quot;.&lt;br /&gt;
::For example, the literal &amp;quot;&amp;lt;code&amp;gt;i&#039;Hello {name}&#039;&amp;lt;/code&amp;gt;&amp;quot; will look for a translation of &amp;quot;Hello %1&amp;quot; in the language pack, and may find one of &amp;quot;Hallo %1&amp;quot;, &amp;quot;Hola %1&amp;quot;, etc. depending on your current language setting. Then the variable &amp;quot;name&amp;quot; is converted to a string and sliced in, finally generating &amp;quot;Hallo Tom&amp;quot; or &amp;quot;Hola Tom&amp;quot; etc.&lt;br /&gt;
::Translations are loaded from resource files in the &amp;quot;resources&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
===== Regex Literals =====&lt;br /&gt;
:r&#039;...&#039;&lt;br /&gt;
:: these are implemented, but not yet officially released to the public. Don&#039;t use for now, instead use the normal regex messages as described below.&lt;br /&gt;
&lt;br /&gt;
== Protocol (String API) ==&lt;br /&gt;
&lt;br /&gt;
String provides a huge amount of functionality, both in the String class itself and also due to inheritance from a number of Collection classes (be reminded that a string is a sequencable collection of characters, therefore all of the API implemented in collections which support an integer index and those implemented for any generic collection is also provided. Worth mentioning are the enumeration methods, the search, and the substring methods).&lt;br /&gt;
&amp;lt;P&amp;gt;Use a SystemBrowser and/or the MethodFinder to get a feeling. There is usually an existingsolution for most needs.&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;size&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.size()&#039;&#039;&#039; [JS]&lt;br /&gt;
::Returns the number of characters in the string (i.e. the string&#039;s length).&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
 &#039;hello world&#039; size&amp;lt;/code&amp;gt;&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 11&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;bitsPerCharacter&#039;&#039;&#039;&lt;br /&gt;
::Returns one of {8, 16, 32}.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;isWideString&#039;&#039;&#039;&lt;br /&gt;
::Same as &amp;quot;&amp;lt;code&amp;gt;aString bitsPerCharacter &amp;gt; 8&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;containsNon7BitAscii&#039;&#039;&#039;&#039;&lt;br /&gt;
::true if aString is either a wide string, or contains any character above the 7bit Ascii range (i.e. a national character in the ISO8859 charset)&lt;br /&gt;
&lt;br /&gt;
=== Accessing ===&lt;br /&gt;
&lt;br /&gt;
The general access methods for any collection in Smalltalk are &amp;quot;&amp;lt;CODE&amp;gt;at:&amp;lt;/CODE&amp;gt;&#039;&#039;index&#039;&#039;&amp;quot; and &amp;quot;&amp;lt;CODE&amp;gt;at:&amp;lt;/CODE&amp;gt;&#039;&#039;index&#039;&#039; &amp;lt;CODE&amp;gt;put:&amp;lt;/CODE&amp;gt;&#039;&#039;anObject&#039;&#039;&amp;quot; (i.e. the at: and at:put: messages).&lt;br /&gt;
&amp;lt;br&amp;gt;However, for your convenience, the Smalltalk compiler also supports square brackets as used in most other languages.&lt;br /&gt;
Semantically, these are the same, as the compiler generates the corresponding accessor calls for bracket indexes.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;at:&#039;&#039;&#039; &#039;&#039;index&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039; &#039;&#039;[&#039;&#039;&#039; &#039;&#039;índex&#039;&#039; &#039;&#039;&#039;]&#039;&#039;&#039; &amp;amp;nbsp; [ST/X]&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039; &#039;&#039;[&#039;&#039;&#039; &#039;&#039;índex&#039;&#039; &#039;&#039;&#039;]&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Returns the character at an index (1-based; valid indices are [1 .. size]).&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; at:2&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; $e&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;at:&#039;&#039;&#039; &#039;&#039;index&#039;&#039; &#039;&#039;&#039;put:&#039;&#039;&#039; &#039;&#039;char&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039; &#039;&#039;[&#039;&#039;&#039; &#039;&#039;índex&#039;&#039; &#039;&#039;&#039;]&#039;&#039;&#039; := &#039;&#039;char&#039;&#039; &amp;amp;nbsp; [ST/X]&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039; &#039;&#039;[&#039;&#039;&#039; &#039;&#039;índex&#039;&#039; &#039;&#039;&#039;]&#039;&#039;&#039; = &#039;&#039;char&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Changes the character at an index (1-based; valid indices are [1 .. size]).&amp;lt;br&amp;gt;Notice that string constants (and freeze values) are immutable (i.e. readonly strings). Only strings which have been created dynamically can be modified.&lt;br /&gt;
&lt;br /&gt;
:1) this non-ANSI-Smalltalk syntax is supported by Smalltalk/X and thus also valid in expecco.&lt;br /&gt;
&lt;br /&gt;
=== Copying ===&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copy&#039;&#039;&#039; &lt;br /&gt;
::Generates a mutable copy.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; copy at:1 &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; $h&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copyFrom:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; &#039;&#039;&#039;to:&#039;&#039;&#039; &#039;&#039;endIndex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.copyFrom_to(&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;, &#039;&#039;endIndex&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies characters from a start index to an end index (1-based; valid indices are [1 .. size]).&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; copyFrom:1 to:5. &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;hello&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copyFrom:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; &#039;&#039;&#039;count:&#039;&#039;&#039; &#039;&#039;numChars&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.copyFrom_count(&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;, &#039;&#039;numChars&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies a number of characters starting at the given index.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; copyFrom:7 count:3. &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;wor&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copyFrom:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.copyFrom(&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies from the given index to the end.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; copyFrom:6. &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039; world&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copyTo:&#039;&#039;&#039; &#039;&#039;endIndex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.copyTo(&#039;&#039;&#039; &#039;&#039;endIndex&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies from the start to the given index.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; copyTo:6. &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;hello &#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copyLast:&#039;&#039;&#039; &#039;&#039;count&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&amp;lt;&#039;&#039;&#039;.copyLast(&#039;&#039;&#039; &#039;&#039;count&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies the last count characters.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; copyLast:4. &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;world &#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copyButFirst:&#039;&#039;&#039; &#039;&#039;count&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.copyButFirst(&#039;&#039;&#039; &#039;&#039;count&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies except for the first count characters.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; copyButFirst:4. &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;o world&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copyButLast:&#039;&#039;&#039; &#039;&#039;count&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.copyButLast(&#039;&#039;&#039; &#039;&#039;count&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies except for the last count characters.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; copyButLast:4. &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;hello w&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copyBetween:&#039;&#039;&#039; &#039;&#039;leftString&#039;&#039; &#039;&#039;&#039;and:&#039;&#039;&#039; &#039;&#039;rightString&#039;&#039; &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.copyBetween_and_caseSensitive(&#039;&#039;&#039; &#039;&#039;leftString&#039;&#039;, &#039;&#039;rightString&#039;&#039;, &#039;&#039;boolean&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Finds two substrings and copies the part between them.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello small world&#039; copyBetween:&#039;hello&#039; and:&#039;world&#039; caseSensitive:true&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039; small &#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;helloworld&#039; copyBetween:&#039;hello&#039; and:&#039;world&#039; caseSensitive:true&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &amp;amp;apos;&amp;amp;apos; (an empty string)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello small World&#039; copyBetween:&#039;hello&#039; and:&#039;world&#039; caseSensitive:true&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; nil&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello small World&#039; copyBetween:&#039;hello&#039; and:&#039;world&#039; caseSensitive:false&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039; small &#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;copyReplaceString:&#039;&#039;&#039; &#039;&#039;oldString&#039;&#039; &#039;&#039;&#039;withString:&#039;&#039;&#039; &#039;&#039;newString&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.copyReplaceString_withString(&#039;&#039;&#039; &#039;&#039;oldString&#039;&#039;, &#039;&#039;newString&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello small world&#039; copyReplaceString:&#039;small&#039; withString:&#039;big&#039; &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039; hello big world &#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello small world&#039; copyReplaceString:&#039;big&#039; withString:&#039;bigger&#039; &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039; hello small world &#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;withoutPrefix:&#039;&#039;&#039; &#039;&#039;prefixString&#039;&#039; [ &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039; ]&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.withoutPrefix[_caseSensitive](&#039;&#039;&#039; &#039;&#039;prefixString&#039;&#039; [, &#039;&#039;boolean&#039;&#039; ]&#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::If string starts with a prefix-string, return a copy without it. Otherwise return the original string.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello small world&#039; withoutPrefix:&#039;hello &#039; &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039; small world &#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;small world&#039; withoutPrefix:&#039;hello &#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039; small world &#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;withoutSuffix:&#039;&#039;&#039; &#039;&#039;suffixString&#039;&#039; [ &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039; ]&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.withoutSuffix[_ caseSensitive](&#039;&#039;&#039; &#039;&#039;suffixString&#039;&#039; [, &#039;&#039;boolean&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::If string ends with a prefix-string, return a copy without it. Otherwise return the original string.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello small world&#039; withoutSuffix:&#039; world&#039; &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039; hello small&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello small&#039; withoutSuffix:&#039; world&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039; hello small &#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Concatenation ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt; &#039;&#039;string2&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; &#039;&#039;string2&#039;&#039; [JS]&lt;br /&gt;
::the Smalltalk comma operator&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; and the JavaScript plus operator concatenate two strings&lt;br /&gt;
::Example (Smalltalk):&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello&#039; , &#039; &#039; , &#039;world&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;hello world&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
::Example (JavaScript):&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;quot;hello&amp;quot; + &amp;quot; &amp;quot; + &amp;quot;world&amp;quot;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &amp;quot;hello world&amp;quot;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;string&#039;&#039; &amp;lt;code&amp;gt;,*&amp;lt;/code&amp;gt; &#039;&#039;integer&#039;&#039;&lt;br /&gt;
::the Smalltalk comma-star operator generates a new string by repeating the first string a number of times&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;abc&#039; ,* 5&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;abcabcabcabcabc&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Although in theory, the plus operator could have been overloaded in Smalltalk as well, this was not done for readability and debuggability reasons: using a comma makes it clear that the intention is string concatenation and not addition.&lt;br /&gt;
Also notice, that the JavaScript semantics can be considered unclean, as it concatenates strings if either operand is a string. Thus, you have to be careful if addition is attempted, and either incoming operand could possibly be a string. &lt;br /&gt;
&amp;lt;br&amp;gt;In contrast, Smalltalk will report an error if you try to concatenate or add strings and numbers.&lt;br /&gt;
&amp;lt;br&amp;gt;it is not inconvenience - its a feature to protect you from stupid and hard to find errors!&lt;br /&gt;
&lt;br /&gt;
=== Splitting ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;splitBy:&#039;&#039;&#039; &#039;&#039;aCharacter&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.splitBy(&#039;&#039;&#039; &#039;&#039;aCharacter&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; [JS]&lt;br /&gt;
::Splits a string into pieces, given a splitting character. The result is a collection containing the parts.&amp;lt;br&amp;gt;&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world here are six words&#039; splitBy: $      &amp;lt;- trailing invisible space here&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello&#039; &#039;world&#039; &#039;here&#039; &#039;are&#039; &#039;six&#039; &#039;words&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello world here are six words&#039; splitBy: (Character space) &amp;lt;- no invisible space&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello&#039; &#039;world&#039; &#039;here&#039; &#039;are&#039; &#039;six&#039; &#039;words&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello-world here are six-words&#039; splitBy: $-&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello&#039; &#039;world here are six&#039; &#039;words&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;splitOn:&#039;&#039;&#039; &#039;&#039;aCharacter&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;splitOn:&#039;&#039;&#039; &#039;&#039;string2&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;splitOn:&#039;&#039;&#039; &#039;&#039;regex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;splitOn:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039;:&#039;&#039;char&#039;&#039; &#039;&#039;&#039;|&#039;&#039;&#039; &#039;&#039;&amp;lt;condition-expression on char&amp;gt;&#039;&#039; &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;splitOn:&#039;&#039;&#039; #&#039;&#039;&amp;lt;name of condition-expression on char&amp;gt;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.splitOn(&#039;&#039;&#039; &#039;&#039;aCharacter&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;string1&#039;&#039;&#039;&#039;&#039;.splitOn(&#039;&#039;&#039; &#039;&#039;string2&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.splitOn(&#039;&#039;&#039; (&#039;&#039;char&#039;&#039;) =&amp;gt; &#039;&#039;&amp;lt;condition-expression on char&amp;gt;&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Splits a string into pieces, given a splitter.&amp;lt;br&amp;gt;The splitter may be a single character, a string, a regular expression or a block/the name of an element-method, which returns true to split.&amp;lt;br&amp;gt;This is a more general version of the above &amp;quot;splitBy:&amp;quot;, for complex splits.&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello here are five words&#039; splitOn: $      &amp;lt;- trailing space here&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello&#039; &#039;here&#039; &#039;are&#039; &#039;five&#039; &#039;words&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello here are five words&#039; splitOn:(Character space)      &amp;lt;- the same, but readable&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello&#039; &#039;here&#039; &#039;are&#039; &#039;five&#039; &#039;words&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello-world here are six-words&#039; splitOn: $-&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello&#039; &#039;world here are six&#039; &#039;words&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello world and goodbye world&#039; splitOn: &#039; and &#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello world&#039; &#039;goodbye world&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello, commas and semis; here&#039; splitOn: [:ch | (ch == $,) or:[ ch == $; ]]&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello&#039; &#039;commas and semis&#039; &#039;here&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello, commas and semis; here&#039; splitOn: [:ch | &#039;,;&#039; includes:ch ]] &amp;lt;- same functionality as above&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello&#039; &#039;commas and semis&#039; &#039;here&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;aWordWithCamelCase&#039; splitOn: [:ch | ch isUppercase ]&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;a&#039; &#039;Word&#039; &#039;With&#039; &#039;Camel&#039; &#039;Case&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;aWordWithCamelCase&#039; splitOn: #isUppercase&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;a&#039; &#039;Word&#039; &#039;With&#039; &#039;Camel&#039; &#039;Case&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  c&#039;some text\twith\ndifferent separators&#039; splitOn: #isSeparator&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;some&#039; &#039;text&#039; &#039;with&#039; &#039;different&#039; &#039;separators&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;123abc456def789&#039; splitOn:&#039;[a-z]*&#039; asRegex &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #(&#039;123&#039; &#039;456&#039; &#039;789&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 JS examples:&lt;br /&gt;
  &amp;quot;hello here are five words&amp;quot;.splitOn( $&#039; &#039; )    &amp;lt;- space character here&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; [ &amp;quot;hello&amp;quot; , &amp;quot;here&amp;quot; , &amp;quot;are&amp;quot; , &amp;quot;five&amp;quot; , &amp;quot;words&amp;quot; ]&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &amp;quot;hello here are five words&amp;quot;.splitOn( &#039; &#039; )    &amp;lt;- string with a space here&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; [ &amp;quot;hello&amp;quot; , &amp;quot;here&amp;quot; , &amp;quot;are&amp;quot; , &amp;quot;five&amp;quot; , &amp;quot;words&amp;quot; ]&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &amp;quot;hello world and goodbye world&amp;quot;.splitOn(&amp;quot; and &amp;quot;)&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; [ &amp;quot;hello world&amp;quot; , &amp;quot;goodbye world&amp;quot;]&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &amp;quot;123abc456def789&amp;quot;.splitOn(&amp;quot;[a-z]*&amp;quot; asRegex) &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; [ &amp;quot;123&amp;quot; &amp;quot;456&amp;quot; &amp;quot;789&amp;quot; ]&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &amp;quot;hello-world, commas and semis; here&amp;quot;.splitOn( (ch) =&amp;gt; (ch == $&#039;,&#039;) || ( ch == $&#039;;&#039;) )&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; [ &amp;quot;hello-world&amp;quot; , &amp;quot;çommas and semis&amp;quot; , &amp;quot;here&amp;quot;]&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Case Conversion ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;asLowercase&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;asUppercase&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;asUppercaseFirst&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.asUppercase()&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.asLowercase()&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;aString&#039;&#039;&#039;&#039;&#039;.asUppercaseFirst()&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Covert to lowercase, uppercase&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO&#039; asLowercase&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;hello&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello&#039; asUppercase&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;HELLO&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello&#039; asUppercaseFirst&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;Hello&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
::Be aware that these functions do not care for some special cases in the Unicode character set, where a single character has to be replaced by two characters or by a different character depending on the position (and most, even native programmers do not know about them!).&lt;br /&gt;
::The german &amp;quot;ß&amp;quot; (usually up-cased as &amp;quot;SS&amp;quot;) is one example of the first kind, the greek sigma which has to be down-cased differently depending on its position within a string is one of the second kind.&lt;br /&gt;
::&lt;br /&gt;
::If your test depends on such specifics, it must handle that itself (the 2008 Unicode standard does however include an upper-case eszet, which is handled by those functions).&lt;br /&gt;
&lt;br /&gt;
=== Comparing ===&lt;br /&gt;
&lt;br /&gt;
Be reminded that there are multiple possible definitions of &amp;quot;&#039;&#039;being equal&#039;&#039;&amp;quot; w.r.t. strings; identity, equality and case-insensitive equalitiy.&lt;br /&gt;
&amp;lt;br&amp;gt;Identity is about two objects being the identical object (instance), and handled by the  &amp;quot;==&amp;quot; operator in Smalltalk.&lt;br /&gt;
&amp;lt;br&amp;gt;Equality means being of the same type of object and having the same contents is handled by the &amp;quot;=&amp;quot; operator.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;= &#039;&#039;&#039; &#039;&#039;string2&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039;&#039;&#039;&#039;== &#039;&#039;&#039; &#039;&#039;string2&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Compares two strings for equal contents, NOT ignoring case.&amp;lt;br&amp;gt;Notice that &amp;quot;==&amp;quot; in Smalltalk is an identity compare, which is &amp;quot;===&amp;quot; in JavaScript,&amp;lt;br&amp;gt;and &amp;quot;=&amp;quot; in Smalltalk is a &amp;quot;same contents&amp;quot; compare, whereas its assignment in JS.&amp;lt;br&amp;gt;Keep that in mind to avoid hard to find bugs.&lt;br /&gt;
&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO&#039; = &#039;HeLlo&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello&#039; = &#039;hello&#039; copy&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello&#039; == &#039;hello&#039; copy&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello&#039; = &#039;hello&#039; asUnicode16String&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;sameAs:&#039;&#039;&#039; &#039;&#039;string2&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039;&#039;&#039;&#039;.sameAs(&#039;&#039;&#039; &#039;&#039;string2&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Compares two strings, ignoring case.&amp;lt;br&amp;gt;&amp;quot;&#039;&#039;&#039;caselessEqual:&#039;&#039;&#039;&amp;quot; is an alias which performs the same operation (and may be more self describing).&lt;br /&gt;
&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO&#039; sameAs: &#039;HeLlo&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELxO&#039; sameAs: &#039;HeLlo&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO&#039; caselessEqual: &#039;HeLlo&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;caselessBefore:&#039;&#039;&#039; &#039;&#039;string2&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;caselessAfter:&#039;&#039;&#039; &#039;&#039;string2&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;caselessEqual:&#039;&#039;&#039; &#039;&#039;string2&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039;&#039;&#039;&#039;.caselessBefore(&#039;&#039;&#039; &#039;&#039;string2&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;string1&#039;&#039;&#039;&#039;&#039;.caselessAfter(&#039;&#039;&#039; &#039;&#039;string2&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Compare two strings, ignoring case.&amp;lt;br&amp;gt;Returns true if string1 is smaller, same or larger than string2.&amp;lt;br&amp;gt;Does not care for national characters (i.e. the compare is based on the unicode points)&lt;br /&gt;
&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO&#039; caselessBefore: &#039;world&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;bce&#039; caselessBefore: &#039;abc&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;startsWith:&#039;&#039;&#039; &#039;&#039;prefixString&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;startsWith:&#039;&#039;&#039; &#039;&#039;prefixString&#039;&#039; &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039;&#039;&#039;&#039;.startsWith(&#039;&#039;&#039; &#039;&#039;prefixString&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;string1&#039;&#039;&#039;&#039;&#039;.startsWith_caseSensitive(&#039;&#039;&#039; &#039;&#039;prefixString&#039;&#039;, &#039;&#039;boolean&#039;&#039; &#039;&#039;&#039;)&#039;&#039;&#039; &amp;amp;nbsp; [JS]&lt;br /&gt;
::Checks if a string starts with another string.&lt;br /&gt;
::Comes in two variants, one being strict, the other with optional case-insensitivity.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello&#039; startsWith: &#039;hel&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;Hello&#039; startsWith: &#039;hel&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;Hello&#039; startsWith: &#039;hel&#039; caseSensitive: false&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;Hexlo&#039; startsWith: &#039;hel&#039; caseSensitive: false&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;endsWith:&#039;&#039;&#039; &#039;&#039;prefixString&#039;&#039;&lt;br /&gt;
:&#039;&#039;string1&#039;&#039; &#039;&#039;&#039;endsWith:&#039;&#039;&#039; &#039;&#039;prefixString&#039;&#039; &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039;&lt;br /&gt;
::Checks if a string ends with another string.&amp;lt;br&amp;gt;Comes in two variants, one being strict, the other with optional case-insensitivity.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello&#039; endsWith: &#039;lo&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;Hello&#039; endsWith: &#039;Lo&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;Hello&#039; endsWith: &#039;Lo&#039; caseSensitive: false&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;Hexlo&#039; endsWith: &#039;LX&#039; caseSensitive: false&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Searching ===&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;indexOf:&#039;&#039;&#039; &#039;&#039;aCharacter&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;lastIndexOf:&#039;&#039;&#039; &#039;&#039;aCharacter&#039;&#039;&lt;br /&gt;
::Returns the first/last index of an element (a character). The index is 1-based; returns 0 if not found.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO&#039; indexOf: $L&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 3&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO&#039; indexOf: $x&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 0&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO&#039; lastIndexOf: $L&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;indexOf:&#039;&#039;&#039; &#039;&#039;aCharacter&#039;&#039; &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;lastIndexOf:&#039;&#039;&#039; &#039;&#039;aCharacter&#039;&#039; &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
::Returns the next/previous index of an element (a character) given a search start index .&amp;lt;br&amp;gt;Returns 0 if not found.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO WORLD&#039; indexOf: $O startingAt: 6&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 8&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO WORLD&#039; indexOf: $x startingAt: 6&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 0&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO WORLD&#039; indexOf: $L startingAt: 6&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 0&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO WORLD&#039; lastIndexOf: $O startingAt: 7&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 5&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;indexOfAny:&#039;&#039;&#039; &#039;&#039;aCollectionOfCharacters&#039;&#039; [ &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; ]&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;lastIndexOfAny:&#039;&#039;&#039; &#039;&#039;aCollectionOfCharacters&#039;&#039; [ &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; ] &lt;br /&gt;
::Similar to the above, but searches for any element in the given argument collection. This may be a string (of characters) or an array or any other collection of characters.&amp;lt;br&amp;gt;Returns 0 if not found.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO, WORLD&#039; indexOfAny: &#039;,;&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 6&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO; WORLD&#039; indexOfAny: &#039;,;&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 6&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO; WORLD&#039; indexOfAny: #( $, $; )&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 6&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO. WORLD&#039; indexOfAny: #( $, $; )&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 0&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;indexOfSeparator&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;indexOfSeparatorStartingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;lastIndexOfSeparator&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;lastIndexOfSeparatorStartingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
::Searches for the first/last whitespace character (Space, Tab, CR or NL).&amp;lt;br&amp;gt;Returns 0 if not found.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO WORLD&#039; indexOfSeparator&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 6&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO WORLD&#039; indexOfSeparatorStartingAt: 7&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 0&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO abc World&#039; lastIndexOfSeparator&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 10&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO abc World&#039; lastIndexOfSeparatorStartingAt:10&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 10&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO abc World&#039; lastIndexOfSeparatorStartingAt:9&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 6&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;indexOfString:&#039;&#039;&#039; &#039;&#039;aSubstring&#039;&#039; [ &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; ]&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;lastIndexOfString:&#039;&#039;&#039; &#039;&#039;aSubstring&#039;&#039; [ &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; ]&lt;br /&gt;
::Returns the first/last index of an element (a character). Returns 0 if not found.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO&#039; indexOfString:&#039;LL&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 3&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO&#039; indexOfString: &#039;LX&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 0&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO BELLO&#039; lastIndexOfString: &#039;LL&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 9&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;includesString:&#039;&#039;&#039; &#039;&#039;aSubstring&#039;&#039; [ &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039; ]&lt;br /&gt;
::Returns true if &#039;&#039;aString&#039;&#039; contains the sub-string &#039;&#039;aSubstring&#039;&#039;; false otherwise.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO&#039; includesString:&#039;LL&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO&#039; includesString: &#039;ll&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO&#039; includesString: &#039;ll&#039; caseSensitive: false &lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pattern Matching ===&lt;br /&gt;
&lt;br /&gt;
Be reminded that there are two match algorithms available: the simpler GLOB pattern matcher (which resembles the way shell and cmd.com do filename matching), and the more complicated but also much more powerful REGEX matcher.&lt;br /&gt;
The most obvious difference is that in GLOB, the star &amp;quot;&amp;lt;CODE&amp;gt;*&amp;lt;/CODE&amp;gt;&amp;quot; matches any string, including the empty string, whereas in REGEX, the star matches the PREVIOUS pattern zero or multiple times.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Thus, the simple GLOB pattern &amp;quot;&amp;lt;CODE&amp;gt;*.c&amp;lt;/CODE&amp;gt;&amp;quot; (to match C-filenames) has to be written as &amp;quot;&amp;lt;CODE&amp;gt;.*\.c&amp;lt;/CODE&amp;gt;&amp;quot; in REGEX&lt;br /&gt;
(because in regex, &amp;quot;&amp;lt;CODE&amp;gt;.&amp;lt;/CODE&amp;gt;&amp;quot; matches ANY character, the star repeats it, and the next &amp;quot;&amp;lt;CODE&amp;gt;.&amp;lt;/CODE&amp;gt;&amp;quot; has to be escaped because it would otherwise stand for &amp;quot;any character&amp;quot;).&lt;br /&gt;
&amp;lt;br&amp;gt;If you are new to these concepts, please read the documentation on [[Regex Pattern Info#GLOB_Patterns|GLOB]] and [[Regex Pattern Info#Regex_Patterns|REGEX]] patterns.&lt;br /&gt;
&amp;lt;P&amp;gt;&lt;br /&gt;
The following are the most useful API entries (but the browser will show a few more):&lt;br /&gt;
&amp;lt;P&amp;gt;&lt;br /&gt;
==== GLOB Pattern Matching ====&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;matches:&#039;&#039;&#039; &#039;&#039;patternString&#039;&#039; [ &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039; ]&lt;br /&gt;
::True if a string matches a [[Regex Pattern Info|GLOB match pattern]].&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO world&#039; matches: &#039;HE*&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO world&#039; matches: &#039;he*&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO world&#039; matches: &#039;he*&#039; caseSensitive: false&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;patternStrings&#039;&#039; &#039;&#039;&#039;compoundMatch:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039; [ &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039; ]&lt;br /&gt;
::True if a string matches any pattern in patternStrings, which contains multiple [[Regex Pattern Info|GLOB match patterns]] separated by semicolon.&lt;br /&gt;
::Useful eg. to verify a string against multiple file extensions (eg. &amp;lt;code&amp;gt;&#039;*.txt;*.doc;*.pdf&#039; compoundMatch: aFilename&amp;lt;/code&amp;gt;).&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;f*;b*&#039; compoundMatch:&#039;foo&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;f*;b*&#039; compoundMatch:&#039;bar&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;f*;b*&#039; compoundMatch:&#039;xxx&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== REGEX Pattern Matching ====&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;matchesRegex:&#039;&#039;&#039; &#039;&#039;patternString&#039;&#039; [ &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039; ]&lt;br /&gt;
::True if a string matches a [[Regex Pattern Info|regex pattern]].&lt;br /&gt;
::Example&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO world&#039; matchesRegex: &#039;H.*O&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO world&#039; matchesRegex: &#039;h.*o&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; false&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO world&#039; matchesRegex: &#039;h.*o&#039; caseSensitive: false&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  (&#039;myFile.txt&#039; asFilename contents) select:[:line |&lt;br /&gt;
     line matchesRegex:&#039;[0-9]+\:.*&#039; &lt;br /&gt;
  ]&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; all lines from the file which start with a number followed by a colon.&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;patternString&#039;&#039; &#039;&#039;&#039;regexMatchesIn:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039;&lt;br /&gt;
::Returns a collection containing all [[Regex Pattern Info|regex]] matching substrings.&lt;br /&gt;
::Example&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;[0-9]+&#039; regexMatchesIn: &#039;1234 abcd 3456 defg&#039;&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; OrderedCollection(&#039;1234&#039; &#039;3456&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;subExpressionsInRegex:&#039;&#039;&#039; &#039;&#039;patternString&#039;&#039; &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039;&lt;br /&gt;
::Returns a collection containing the individual partial matches. Partials are [[Regex Pattern Info|regex]] subexpressions in parentheses.&lt;br /&gt;
::Example&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;1234abc3456&#039; subExpressionsInRegex: &#039;([0-9]+)abc([0-9]+)&#039; caseSensitive:false&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; OrderedCollection(&#039;1234&#039; &#039;3456&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;123 abc xyz :bla&#039; subExpressionsInRegex: &#039;([0-9]+).*(\:.*)&#039; caseSensitive:false&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; OrderedCollection(&#039;123&#039; &#039;bla&#039;)&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
::Notice that &#039;:&#039; is a special character in the pattern and must therefore be escaped with a backslash.&lt;br /&gt;
&lt;br /&gt;
=== Converting ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;asByteArray&#039;&#039;&#039;&lt;br /&gt;
::Returns a byte array containing the codePoints (Unicode codes).&lt;br /&gt;
::The characters should be within the ISO8859 range 0x00 .. 0xFF.&lt;br /&gt;
::If they are not, a byte array containing the wide characters is returned (to be exact: in the machine&#039;s native byte order, which is low byte first on x86 cpus).&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;abc123&#039; asByteArray&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #[97 98 99 49 50 51]&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; asByteArray&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #[228 246 252]&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  c&#039;abc\u2022123&#039; asByteArray&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #[97 0 98 0 99 0 34 32 49 0 50 0 51 0]&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;asFilename&#039;&#039;&#039;&lt;br /&gt;
::Returns a filename instance, which provides functions to operate on files and directories.&amp;lt;br&amp;gt;See [[#Filename | &amp;quot;Filename protocol&amp;quot;]] for its functions.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;c:\data.txt&#039; asFilename modificationTime&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; 2017-07-28 10:31:23&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;/etc&#039; asFilename exists&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; true&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aStringWithMultipleLines&#039;&#039; &#039;&#039;&#039;asCollectionOfLines&#039;&#039;&#039;&lt;br /&gt;
::Returns a collection of strings, each containing one line from the original string. Handles any combination of CR, LF or CRLF as line separator. The resulting line-collection can then be further processed using functions from the [[#Collection | Collection protocol]].&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;data.txt&#039; asFilename contents asCollectionOfLines&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;line1&#039; &#039;line2&#039; &#039;line3&#039; ... )&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;asCollectionOfWords&#039;&#039;&#039;&lt;br /&gt;
::Returns a collection of strings, each containing one word from the original string. Words are separated by whitespace (space, tab or CR/LF).&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello bla bla world&#039; asCollectionOfWords&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #( &#039;hello&#039; &#039;bla&#039; &#039;bla&#039; &#039;world&#039; )&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Encoding / Decoding ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;utf8Encoded&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;utf8Decoded&#039;&#039;&#039;&lt;br /&gt;
::Encode / decode into/from utf8 encoding.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; utf8Encoded&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;Ã¤Ã¶Ã¼&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; utf8Encoded asByteArray&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #[195 164 195 182 195 188]&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; utf8Encoded utf8Decoded&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;utf16Encoded&#039;&#039;&#039;&lt;br /&gt;
::Encode into an utf16 encoded two byte string (ie. still a vector of characters), caring for characters above codepoint 0xFFFF. This can then be further converted to a vector of bytes in BE (big end) or LE (low end) order (see below).&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello &amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; utf16Encoded encodeInto:#utfLE16&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #[104 0 101 0 108 0 108 0 111 0 32 0 228 0 246 0 252 0]&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;encodeInto:&#039;&#039;&#039; &#039;&#039;nameOfEncoding&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;decodeFrom:&#039;&#039;&#039; &#039;&#039;nameOfEncoding&#039;&#039;&lt;br /&gt;
::Similar to the above, but &#039;&#039;nameOfEncoding&#039;&#039; gives the encoding&#039;s name (as symbol). Supported encodings are: #utf, #utf16BE, #utf16LE, #iso8859-1 to #iso8859-8, #iso8859-15, #iso8859-16, #koi7, #cp437, #cp850, #cp1250, #cp1252, #jis7, #gb, #big5, #ebcdic. &lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;encodeFrom:&#039;&#039;&#039; &#039;&#039;nameOfEncoding1&#039;&#039; &#039;&#039;&#039;into:&#039;&#039;&#039; &#039;&#039;nameOfEncoding2&#039;&#039;&lt;br /&gt;
::to transcode from one encoding into another. E.g. &amp;quot;someString encodeFrom:#cp850 into:#koi7&amp;quot; would recode from the Windows codepage 850 into cyrillic koi7.&lt;br /&gt;
&lt;br /&gt;
:aString&#039;&#039; &#039;&#039;&#039;base64Encoded&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;base64Decoded&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aString&#039;&#039; &#039;&#039;&#039;base64DecodedString&#039;&#039;&#039;&lt;br /&gt;
::Encode / decode into/from base64 encoding.&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; base64Encoded&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;5Pb8&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; base64Encoded asByteArray&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #[53 80 98 56]&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; base64Encoded base64Decoded&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; #[228 246 252]&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; base64Encoded base64DecodedString&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039; base64Encoded base64Decoded asString&lt;br /&gt;
      &amp;lt;small&amp;gt;=&amp;gt; &#039;&amp;amp;auml;&amp;amp;ouml;&amp;amp;uuml;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hashing ===&lt;br /&gt;
&lt;br /&gt;
See [[Cryptographic_API_Functions/en|Cryptographic API Functions]].&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Collection_API_Functions&amp;diff=30884</id>
		<title>Collection API Functions</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Collection_API_Functions&amp;diff=30884"/>
		<updated>2026-02-23T10:45:34Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 16.2.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document lists most useful (and most often needed) functions.&lt;br /&gt;
Be aware, that there are many more to be found in either the class references or via the builtin [[Tools_ClassBrowser/en | class browser]].&lt;br /&gt;
&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Collection Collection]&lt;br /&gt;
&lt;br /&gt;
[[Useful API Functions | Back to Useful API Functions]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Notice: except when written otherwise, all indices are 1-based. Valid indices range from 1 to the collection&#039;s size (as eg. in Mathematica, but not as in C, Java or Python).&lt;br /&gt;
&amp;lt;br&amp;gt;In Smalltalk, the first element has number 1, and the N&#039;th element of a collection has number N.&lt;br /&gt;
&amp;lt;br&amp;gt;Also notice: String and ByteArray are subclasses of Collection, which means that most of the functions listed below can also be applied to sequences of characters and bytes.&lt;br /&gt;
&lt;br /&gt;
== Most Useful Subclasses ==&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Array&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:: a collection of (references to) other objects. An array can hold on any other object type, even mixed, which means that the elements of an array can be instances of different classes. Technically an array holds references (aka pointers) to its elements,  not their contents. Arrays are fixed in size; this means that once created, you cannot add or remove elements (1).&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;CODE&amp;gt;OrderedCollection&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:: similar to an Array, these allow fast add- and removal at either end. They can therefore also be used as Stacks or Queues (although there are subclasses named &amp;quot;Queue&amp;quot; and &amp;quot;Stack&amp;quot;, which solely exist to make their purpose clear and explicitly documented).&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;CODE&amp;gt;String&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:: a sequence of characters. Expecco supports 8, 16 and 32 bit strings. The internal encoding of all strings is always Unicode. Internally, strings are never kept in any compressed UTF8 or similar fashion. Only when loaded from or stored into external files or streams will there be an encoding. A number of encoders is found under the CharacterEncoder class.&amp;lt;br&amp;gt;Although Strings look like Arrays of Characters to the outside world, they use a more compact internal storage format (1, 2 or 4 byte per character, instead of the 4 or 8 byte pointer as used by Array).&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;CODE&amp;gt;ByteArray&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:: a sequence of small unsigned 8 bit numbers (aka &amp;quot;bytes&amp;quot;). The class side protocol adds a number of instance creation methods, for example to read a hex encoded or Base64 encoded string. They also use a more compact storage format (1 byte per element).&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Float32Array&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;Float64Array&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:: a sequence of IEEE floating point numbers. These are mostly used to store bulk data, such as mesurement values and/or for data interchange with bridges.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Dictionary&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:: a dictionary (also known as &amp;quot;HashTable&amp;quot; in other languages) will associate values to keys, where the key can be an arbitrary object. There are a number of specialized subclasses, such as CacheDictionary, CacheDictionaryWithLimitedLifeTime, IdentityDictionary, Virtual- and PluggableDictionary. The last one lets you specify your own configurable hash- and compare functions. The VirtualDictionary is a complete mock, where you can plug in any action (Smalltalk-block) for access.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Interval&amp;lt;/CODE&amp;gt;&lt;br /&gt;
:: an interval (also known as &amp;quot;Range&amp;quot; in eg. Python) mimics a collection on the outside, but only keeps the first and last element inside, computing all elements on the fly. There is also a companion class called &amp;quot;GeometricSeries&amp;quot; which behaves similar, but computes elements via a multiplication factor instead of an addition step.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Tree&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;Queue&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;PriorityQueue&amp;lt;/CODE&amp;gt; &amp;lt;CODE&amp;gt;SharedQueue&amp;lt;/CODE&amp;gt;, ...&lt;br /&gt;
:: there are many other collections for special uses. We recommend you to open a systemBrowser and look at the examples provided on the class side (typically found under documentation - examples).&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
1) it is actually possible to add or remove elements. However, for array instances, this is a very expensive operation and you will therefore get a harsh warning on the Transcript if you do.&lt;br /&gt;
&lt;br /&gt;
== Common Protocol ==&lt;br /&gt;
This common protocol is ortogonally understood by all subclasses, including regular Array, ByteArray, Dictionary (Hashtable), Set and String. Although, some functions might be redefined in subclasses for performance reasons.&lt;br /&gt;
&lt;br /&gt;
=== Creation ===&lt;br /&gt;
Collection instances are created by sending a variant of the &amp;quot;&amp;lt;code&amp;gt;new&amp;lt;/code&amp;gt;&amp;quot; message to the class,&lt;br /&gt;
or by converting from another collection class.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Array&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;new:&#039;&#039;&#039; &#039;&#039;size&#039;&#039;&lt;br /&gt;
:&amp;lt;CODE&amp;gt;ByteArray&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;new:&#039;&#039;&#039; &#039;&#039;size&#039;&#039; (and many others)&lt;br /&gt;
:&amp;lt;CODE&amp;gt;OrderedCollection&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;new&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;CODE&amp;gt;SortedCollection&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;new&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Set&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;new&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Dictionary&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;new&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Dictionary&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;forCaseInsensitiveKeys&#039;&#039;&#039;&lt;br /&gt;
::OrderedCollection and Dictionary and their subclasses also understand the &#039;&#039;&#039;new:&#039;&#039;&#039; message with a size argument,&lt;br /&gt;
::[[Datei:point_right.png|20px]] but notice the different behavior as compared to Array&#039;s behavior:&lt;br /&gt;
:::for &amp;lt;CODE&amp;gt;Array&amp;lt;/CODE&amp;gt; (and its subclasses), the size argument defines the size of the instantiated Array (which is fixed thereafter); and the array is filled wirth nils.&lt;br /&gt;
:::for &amp;lt;CODE&amp;gt;OrderedCollection&amp;lt;/CODE&amp;gt; and&amp;lt;CODE&amp;gt;Dictionary&amp;lt;/CODE&amp;gt; (and their subclasses), the size argument defines the number of preallocated slots in the collection; however, the logical size of it is zero (i.e. it is empty).&lt;br /&gt;
::[[Datei:point_right.png|20px]] In general:&lt;br /&gt;
:::if the collection class has a variable number of elements, the size given to the &amp;lt;code&amp;gt;new:&amp;lt;/code&amp;gt; method is the preallocation size, whereas for fixed size collections, its the actual size (and the elements are initialized with nil or zero in the number containers).&lt;br /&gt;
::&lt;br /&gt;
::This is a somewhat irritating behavior due to historic reasons within the Smalltalk language (backward compatibility).&lt;br /&gt;
:: Use &#039;&#039;&#039;newWithSize:&#039;&#039;&#039; to get the same behavior:&lt;br /&gt;
:&amp;lt;CODE&amp;gt;OrderedCollection&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;newWithSize:&#039;&#039;&#039; &#039;&#039;size&#039;&#039;&lt;br /&gt;
::creates a new ordered collection instance with &#039;&#039;size&#039;&#039; nil elements inside.&lt;br /&gt;
&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  a := Array new:5.&lt;br /&gt;
  a&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; #(nil nil nil nil nil)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  oc := OrderedCollection new:5.&lt;br /&gt;
  oc&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; OrderedCollection()&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  oc := OrderedCollection newWithSize:5.&lt;br /&gt;
  oc&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; OrderedCollection(nil nil nil nil nil)&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Creation is also possible with an initial fill value:&lt;br /&gt;
:&amp;lt;CODE&amp;gt;Array&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;new:&#039;&#039;&#039; &#039;&#039;size&#039;&#039; &#039;&#039;&#039;withAll:&#039;&#039;&#039; &#039;&#039;initialValue&#039;&#039;&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  a := Array new:3 withAll:0.&lt;br /&gt;
  a&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; #(0 0 0)&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or by taking the contents from another collection:&lt;br /&gt;
:&amp;lt;CODE&amp;gt;OrderedCollection&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;newFrom:&#039;&#039;&#039; &#039;&#039;anotherCollection&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ByteArray offers a few extra instance creators:&lt;br /&gt;
:&amp;lt;CODE&amp;gt;ByteArray&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;fromHexString:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039;&lt;br /&gt;
:: eg. &amp;lt;CODE&amp;gt;ByteArray fromHexString:&#039;01FF02EE03AF&#039;&amp;lt;/CODE&amp;gt;&lt;br /&gt;
::     &amp;lt;small&amp;gt;=&amp;gt; #[1 255 2 238 3 175]&amp;lt;/small&amp;gt;&lt;br /&gt;
:&amp;lt;CODE&amp;gt;ByteArray&amp;lt;/CODE&amp;gt; &#039;&#039;&#039;fromHexString:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039; &#039;&#039;&#039;withSeparator:&#039;&#039;&#039; &#039;&#039;sepChar&#039;&#039;&lt;br /&gt;
:: eg. &amp;lt;CODE&amp;gt;ByteArray fromHexString:&#039;12:34:FE:FF&#039; withSeparator:$:&amp;lt;/CODE&amp;gt;&lt;br /&gt;
::     &amp;lt;small&amp;gt;=&amp;gt; #[18 52 254 255]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Accessing ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;size&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;size&#039;&#039;&#039;() [JS]&lt;br /&gt;
::Returns the number of elements in the collection (i.e. its length).&lt;br /&gt;
::Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; size&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 11&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  #(1 2 3) size&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;at:&#039;&#039;&#039; &#039;&#039;index&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; &#039;&#039;índex&#039;&#039; &#039;&#039;&#039;]&#039;&#039;&#039; &amp;amp;nbsp; [JS or ST]&lt;br /&gt;
::Returns the element at an index (1 based).&lt;br /&gt;
::Depending on the type of collection, this will be a numeric index (Array, OrderedCollection) or a general access key (Dictionary, OrderedDictionary).&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; at:2&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; $e &amp;quot;/ (Notice: the dollar-char notation represents a character constant in Smalltalk)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;hello world&#039;[5]&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; $o&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  #(90 4 50 20 99) asSortedCollection at:2&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; 20&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Datei:point_right.png|20px]] Be reminded: indices are 1-based. Valid indices range from 1 to the collection&#039;s size.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;at:&#039;&#039;&#039; &#039;&#039;index&#039;&#039; &#039;&#039;&#039;put:&#039;&#039;&#039; &#039;&#039;newValue&#039;&#039; =&amp;gt; void&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; &#039;&#039;índex&#039;&#039; &#039;&#039;&#039;]&#039;&#039;&#039; := &#039;&#039;newValue&#039;&#039;&amp;amp;nbsp; [ST]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; &#039;&#039;índex&#039;&#039; &#039;&#039;&#039;]&#039;&#039;&#039; = &#039;&#039;newValue&#039;&#039;&amp;amp;nbsp; [JS]&lt;br /&gt;
::Changes the element at an index (1 based).&lt;br /&gt;
::Depending on the type of collection, this will be a numeric index (Array, OrderedCollection) or a general access key (Dictionary, OrderedDictionary).&lt;br /&gt;
;;&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  s := &#039;hello world&#039; copy. &amp;lt;SMALL&amp;gt;&amp;quot;/ (Notice: use a copy here, because constants are immutable)&amp;lt;/SMALL&amp;gt;&lt;br /&gt;
  s at:2 put:$*.&lt;br /&gt;
  s&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; &#039;h*llo world&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  c := #(90 4 50 20 99) asOrderedCollection.&lt;br /&gt;
  c at:2 put:-1.&lt;br /&gt;
  c&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; OrderedCollection(90 -1 50 20 99)&amp;lt;/small&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  s := &#039;hello world&#039; copy. &amp;lt;SMALL&amp;gt;&amp;quot;/ (Notice: use a copy here, because constants are immutable)&amp;lt;/SMALL&amp;gt;&lt;br /&gt;
  s[5] := $O.&lt;br /&gt;
  s&lt;br /&gt;
    &amp;lt;small&amp;gt;=&amp;gt; &#039;hellO world&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Notice: It is in general not a good idea to use the value returned by &amp;quot;at:put: calls; it will be the stored value, not the collection. So do not write &amp;quot;coll := (Array new:1) at:1 put:something.&amp;quot;, unless you want &#039;&#039;something&#039;&#039; to be stored in &#039;&#039;coll&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Copy and Replacing ===&lt;br /&gt;
These are functional (i.e. non-destructive) operations, meaning that a new collection instance is returned and the original is not modified.&lt;br /&gt;
&amp;lt;br&amp;gt;There are also destructive variants (without a &#039;copy&#039; in the name), which are not documented here, as their use is considered to be &amp;quot;bad style&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyReplaceAll:&#039;&#039;&#039; &#039;&#039;element&#039;&#039; &#039;&#039;&#039;with:&#039;&#039;&#039; &#039;&#039;newElement&#039;&#039;&lt;br /&gt;
::returns a copy of &#039;&#039;aCollection&#039;&#039; where all occurrences of &#039;&#039;oldElement&#039;&#039; have been replaced by &#039;&#039;newElement&#039;&#039;.&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;abcdefabc&#039; copyReplaceAll: $a with: $A   &lt;br /&gt;
      =&amp;gt;  &#039;AbcdefAbc&#039;&lt;br /&gt;
 &lt;br /&gt;
  #(1 2 3 4) copyReplaceAll: 1 with: 100 &lt;br /&gt;
      =&amp;gt;  #(100 2 3 4)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyReplaceAll:&#039;&#039;&#039; &#039;&#039;element&#039;&#039; &#039;&#039;&#039;withAll:&#039;&#039;&#039; &#039;&#039;newElements&#039;&#039;&lt;br /&gt;
::returns a copy of &#039;&#039;aCollection&#039;&#039; where &#039;&#039;newElements&#039;&#039; have been sliced in, whereever &#039;&#039;oldElement&#039;&#039; was encountered.&lt;br /&gt;
::Giving an empty replacement collection has the same effect as &#039;&#039;&#039;copyWithout:&#039;&#039;&#039;.&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
 &#039;abcdefabc&#039; copyReplaceAll: $a withAll: &#039;XXX&#039;&lt;br /&gt;
      =&amp;gt;  &#039;XXXbcdefXXXbc&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039;abcdefabc&#039; copyReplaceAll: $a withAll: &#039;&#039;&lt;br /&gt;
      =&amp;gt;  &#039;bcdefbc&#039;&lt;br /&gt;
 &lt;br /&gt;
  #(1 2 3 4) copyReplaceAll: 1 withAll: #(100 200 300)&lt;br /&gt;
      =&amp;gt;  #(100 200 300 2 3 4)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyWithout:&#039;&#039;&#039; &#039;&#039;element&#039;&#039;&lt;br /&gt;
::returns a copy of &#039;&#039;aCollection&#039;&#039; where &#039;&#039;element&#039;&#039; have been removed.&lt;br /&gt;
::Examples:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
 &#039;abcdefabc&#039; copyWithout: $a&lt;br /&gt;
      =&amp;gt;  &#039;bcdefbc&#039;&lt;br /&gt;
 &lt;br /&gt;
  #(1 2 3 4) copyWithout: 1&lt;br /&gt;
      =&amp;gt;  #(2 3 4)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Copying by Numeric Index ===&lt;br /&gt;
These functions are applicable to collections with a numeric index (i.e. Array, OrderedCollection, ByteArray, String, SortedCollection, FloatArray, DoubleArray, etc.).&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyFrom:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; &#039;&#039;&#039;to:&#039;&#039;&#039; &#039;&#039;endIndex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;copyFrom_to&#039;&#039;&#039;( &#039;&#039;startIndex&#039;&#039;, &#039;&#039;endIndex&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies elements from a start index to an end index (both being 1-based indices).&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;hello world&#039; copyFrom:1 to:5. &lt;br /&gt;
  =&amp;gt; &#039;hello&#039;&lt;br /&gt;
 &lt;br /&gt;
  #(10 20 30 40 50 60 70) copyFrom:1 to:5. &lt;br /&gt;
  =&amp;gt; #(10 20 30 40 50)&lt;br /&gt;
 &lt;br /&gt;
  (10 to: 100 by: 10) copyFrom:1 to:3. &lt;br /&gt;
  =&amp;gt; #(10 20 30)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyFrom:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; &#039;&#039;&#039;count:&#039;&#039;&#039; &#039;&#039;numChars&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;copyFrom_count&#039;&#039;&#039;( &#039;&#039;startIndex&#039;&#039;, &#039;&#039;numChars&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies a number of elements starting at the given index.&lt;br /&gt;
::Example: see example in [[String API Functions | String]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyFrom:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;copyFrom&#039;&#039;&#039;( &#039;&#039;startIndex&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies from the given index to the end.&lt;br /&gt;
::Example: see example in [[String API Functions | String]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyTo:&#039;&#039;&#039; &#039;&#039;endIndex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;copyTo&#039;&#039;&#039;( &#039;&#039;endIndex&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies from the start to the given index.&lt;br /&gt;
::Example: see example in [[String API Functions | String]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyLast:&#039;&#039;&#039; &#039;&#039;count&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;copyLast&#039;&#039;&#039;( &#039;&#039;count&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies the last count characters.&lt;br /&gt;
::Example: see example in [[String API Functions | String]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyButFirst:&#039;&#039;&#039; &#039;&#039;count&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;copyButFirst&#039;&#039;&#039;( &#039;&#039;count&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies except for the first count characters.&lt;br /&gt;
::Example: see example in [[String API Functions | String]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;copyButLast:&#039;&#039;&#039; &#039;&#039;count&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;copyButLast&#039;&#039;&#039;( &#039;&#039;count&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Copies except for the last count characters.&lt;br /&gt;
::Example: see example in [[String API Functions | String]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;collection1&#039;&#039; &#039;&#039;&#039;,&#039;&#039;&#039; &#039;&#039;collection2&#039;&#039; (&amp;lt;SMALL&amp;gt;The comma operator in Smalltalk&amp;lt;/SMALL&amp;gt;)&lt;br /&gt;
::Concatenates arbitrary collections&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  #[10 20 30 40] , #[50 60 70 80]&lt;br /&gt;
  =&amp;gt; #[10 20 30 40 50 60 70 80]&lt;br /&gt;
 &lt;br /&gt;
  &#039;Hello&#039; , &#039;World&#039;&lt;br /&gt;
  =&amp;gt; &#039;Hello World&#039;&lt;br /&gt;
 &lt;br /&gt;
  (1 to:5) , (20 to:25) , #(88 99)&lt;br /&gt;
  =&amp;gt; OrderedCollection(1 2 3 4 5 20 21 22 23 24 25 88 99)&lt;br /&gt;
 &lt;br /&gt;
  (2 to:10 by:2) , (20 to:10 by:-2)&lt;br /&gt;
  =&amp;gt; OrderedCollection(2 4 6 8 10 20 18 16 14 12 10)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Splitting ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;splitBy:&#039;&#039;&#039; &#039;&#039;anElement&#039;&#039; =&amp;gt; collection&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;splitBy&#039;&#039;&#039;( &#039;&#039;anElement&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Splits a collection into pieces, given a splitting element.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  #(10 11 12 0 20 22 24 0 1 2 3 0 50) splitBy: 0&lt;br /&gt;
  =&amp;gt; #( #(10 11 12)  #(20 22 24) #(1 2 3) #(50) ).  &amp;lt;- this is an array of arrays&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;splitForSize:&#039;&#039;&#039; &#039;&#039;pieceSize&#039;&#039; =&amp;gt; collection&lt;br /&gt;
::Splits a collection into pieces of a given size (the last returned piece might be smaller).&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  #(10 11 12 0 20 22 24 0 1 99) splitForSize: 3&lt;br /&gt;
  =&amp;gt; #( #(10 11 12)  #(0 20 22) #(24 0 1) #(99) ).  &amp;lt;- this is an array of arrays&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;splitOn:&#039;&#039;&#039; &#039;&#039;element&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;splitOn:&#039;&#039;&#039; &#039;&#039;splitCollection&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;splitOn:&#039;&#039;&#039; [ :el | &#039;&#039;&amp;lt;condition-expression on el&amp;gt;&#039;&#039; ]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;splitOn&#039;&#039;&#039;( &#039;&#039;element&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;splitOn&#039;&#039;&#039;( &#039;&#039;splitCollection&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;splitOn&#039;&#039;&#039;( (el) =&amp;gt; &#039;&#039;&amp;lt;condition-expression on el&amp;gt;&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Splits a collection into pieces, given a splitter.&lt;br /&gt;
::The splitter may be a single element, a collection of elements or a block, which returns true to split.&lt;br /&gt;
::This is a more general version of the above &amp;quot;splitBy:&amp;quot;, for complex splits.&lt;br /&gt;
&lt;br /&gt;
=== Comparing ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;startsWith:&#039;&#039;&#039; &#039;&#039;prefixCollection&#039;&#039; [ &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;bool&#039;&#039; ] =&amp;gt; bool&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;startsWith&#039;&#039;&#039;( &#039;&#039;prefixCollection&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;startsWith_caseSensitive&#039;&#039;&#039;( &#039;&#039;prefixCollection&#039;&#039;, &#039;&#039;bool&#039;&#039; ) [JS]&lt;br /&gt;
::Checks if a collection starts with the same elements as another collection.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;endsWith:&#039;&#039;&#039; &#039;&#039;suffixCollection&#039;&#039; [ &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;bool&#039;&#039; ] =&amp;gt; bool&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;endsWith&#039;&#039;&#039;( &#039;&#039;suffixCollection&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Checks if a collection ends with the same elements as another collection.&lt;br /&gt;
&lt;br /&gt;
=== Searching ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;indexOf:&#039;&#039;&#039; &#039;&#039;element&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;lastIndexOf:&#039;&#039;&#039; &#039;&#039;element&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;indexOf&#039;&#039;&#039;( &#039;&#039;element&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;lastIndexOf&#039;&#039;&#039;( &#039;&#039;element&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Returns the first/last index of an element. Returns 0 if not found.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO&#039; indexOf: $L&lt;br /&gt;
  =&amp;gt; 3&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO&#039; indexOf: $x&lt;br /&gt;
  =&amp;gt; 0&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO&#039; lastIndexOf: $L&lt;br /&gt;
  =&amp;gt; 4&lt;br /&gt;
 &lt;br /&gt;
  #(1 2 3 1 2 3 1 2 3) lastIndexOf:2&lt;br /&gt;
  =&amp;gt; 8&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;indexOf:&#039;&#039;&#039; &#039;&#039;element&#039;&#039; &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;lastIndexOf:&#039;&#039;&#039; &#039;&#039;element&#039;&#039; &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;indexOf_startingAt&#039;&#039;&#039;( &#039;&#039;element&#039;&#039;, &#039;&#039;startIndex&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;lastIndexOf_startingAt&#039;&#039;&#039;( &#039;&#039;element&#039;&#039;, &#039;&#039;startIndex&#039;&#039; ) &amp;amp;nbsp; [JS]&lt;br /&gt;
::Returns the next/previous index of an element given a search start index .&lt;br /&gt;
::Returns 0 if not found.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO WORLD&#039; indexOf: $O startingAt: 6&lt;br /&gt;
  =&amp;gt; 8&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO WORLD&#039; indexOf: $x startingAt: 6&lt;br /&gt;
  =&amp;gt; 0&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO WORLD&#039; indexOf: $L startingAt: 6&lt;br /&gt;
  =&amp;gt; 0&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO WORLD&#039; lastIndexOf: $O startingAt: 7&lt;br /&gt;
  =&amp;gt; 5&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;indexOfAny:&#039;&#039;&#039; &#039;&#039;aCollectionOfElements&#039;&#039; [ &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; ]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;lastIndexOfAny:&#039;&#039;&#039; &#039;&#039;aCollectionOfElements&#039;&#039; [ &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; ]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;indexOfAny&#039;&#039;&#039;( &#039;&#039;aCollectionOfElements&#039;&#039; ) [JS]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;indexOfAny_startingAt&#039;&#039;&#039;( &#039;&#039;aCollectionOfElements&#039;&#039;, &#039;&#039;startIndex&#039;&#039; ) [JS]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;lastIndexOfAny&#039;&#039;&#039;( &#039;&#039;aCollectionOfElements&#039;&#039; ) [JS]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;lastIndexOfAny_startingAt&#039;&#039;&#039;( &#039;&#039;aCollectionOfElements&#039;&#039;, &#039;&#039;startIndex&#039;&#039; ) [JS]&lt;br /&gt;
::Similar to the above, but searches for any element in the given argument collection.&lt;br /&gt;
::This may be a string (of characters) or an array or any other collection of characters. Returns 0 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;indexOfString:&#039;&#039;&#039; &#039;&#039;aSubString&#039;&#039; [ &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;boolean&#039;&#039; ] [ &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; ]&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;lastIndexOfString:&#039;&#039;&#039; &#039;&#039;aSubString&#039;&#039; [ &#039;&#039;&#039;startingAt:&#039;&#039;&#039; &#039;&#039;startIndex&#039;&#039; ]&lt;br /&gt;
::Searches for a substring.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;HELLO WORLD Hello&#039; indexOfString: &#039;LL&#039;&lt;br /&gt;
  =&amp;gt; 3&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO WORLD Hello&#039; indexOfString: &#039;ll&#039;&lt;br /&gt;
  =&amp;gt; 0&lt;br /&gt;
 &lt;br /&gt;
  &#039;HELLO WORLD Hello&#039; indexOfString: &#039;ll&#039; caseSensitive: false&lt;br /&gt;
  =&amp;gt; 3&lt;br /&gt;
  &lt;br /&gt;
  &#039;HELLO WORLD hello&#039; indexOfString: &#039;ll&#039; caseSensitive: false startingAt: 4 &lt;br /&gt;
  =&amp;gt; 15&lt;br /&gt;
  &lt;br /&gt;
  &#039;Hello World Hello&#039; lastIndexOfString: &#039;ll&#039;&lt;br /&gt;
  =&amp;gt; 15&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Search &amp;amp; Extract ===&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;withoutPrefix:&#039;&#039;&#039; &#039;&#039;prefixCollection&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;withoutPrefix:&#039;&#039;&#039; &#039;&#039;prefixCollection&#039;&#039; &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;aBoolean&#039;&#039; &amp;lt;SMALL&amp;gt;(Strings only)&amp;lt;/SMALL&amp;gt;&lt;br /&gt;
::If &#039;&#039;aCollection&#039;&#039; starts with &#039;&#039;prefixCollection&#039;&#039;, a copy of the remaining (right) elements is returned. Otherwise, the original collection is returned.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;SomeLongerString&#039; withoutPrefix: &#039;Some&#039;&lt;br /&gt;
  =&amp;gt; &#039;LongerString&#039;&lt;br /&gt;
 &lt;br /&gt;
  &#039;SomeLongerString&#039; withoutPrefix: &#039;some&#039;&lt;br /&gt;
  =&amp;gt; &#039;SomeLongerString&#039;&lt;br /&gt;
 &lt;br /&gt;
  &#039;SomeLongerString&#039; withoutPrefix: &#039;some&#039; caseSensitive: false&lt;br /&gt;
  =&amp;gt; &#039;LongerString&#039;&lt;br /&gt;
 &lt;br /&gt;
  &#039;anotherString&#039; withoutPrefix: &#039;Some&#039;&lt;br /&gt;
  =&amp;gt; &#039;anotherString&#039;&lt;br /&gt;
  &lt;br /&gt;
  #(0 7 1 4 2 0 0 7 42) withoutPrefix: #(0 7 1 4 2)&lt;br /&gt;
  =&amp;gt; #(0 0 7 42)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;withoutSuffix:&#039;&#039;&#039; &#039;&#039;suffixCollection&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;withoutSuffix:&#039;&#039;&#039; &#039;&#039;suffixCollection&#039;&#039; &#039;&#039;&#039;caseSensitive:&#039;&#039;&#039; &#039;&#039;aBoolean&#039;&#039; &amp;lt;SMALL&amp;gt;(Strings only)&amp;lt;/SMALL&amp;gt;&lt;br /&gt;
::If &#039;&#039;aCollection&#039;&#039; ends with &#039;&#039;suffixCollection&#039;&#039;, a copy of the left part is returned. Otherwise, the original collection is returned.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;foo.bar.baz&#039; withoutSuffix: &#039;.baz&#039;&lt;br /&gt;
  =&amp;gt; &#039;foo.bar&#039;&lt;br /&gt;
 &lt;br /&gt;
  &#039;foo.bar.x&#039; withoutSuffix: &#039;.baz&#039;&lt;br /&gt;
  =&amp;gt; &#039;foo.bar.x&#039;&lt;br /&gt;
  &amp;lt;SMALL&amp;gt;Notice, for filenames, use &#039;&#039;withoutSuffix&#039;&#039;.&amp;lt;/SMALL&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;upTo:&#039;&#039;&#039; &#039;&#039;elementToSearch&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;restAfter:&#039;&#039;&#039; &#039;&#039;elementToSearch&#039;&#039;&lt;br /&gt;
::Searches &#039;&#039;elementToSearch&#039;&#039; in &#039;&#039;aCollection&#039;&#039; and returns a copy of the left/right part.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;foo.bar.baz&#039; upTo: $.&lt;br /&gt;
  =&amp;gt; &#039;foo&#039;&lt;br /&gt;
 &lt;br /&gt;
  &#039;foo.bar.x&#039; restAfter: $.&lt;br /&gt;
  =&amp;gt; &#039;bar.x&#039;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;upToAny:&#039;&#039;&#039; &#039;&#039;elementsToSearch&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;restAfterAny:&#039;&#039;&#039; &#039;&#039;elementsToSearch&#039;&#039;&lt;br /&gt;
::Searches &#039;&#039;aCollection&#039;&#039; for any element in &#039;&#039;elementsToSearch&#039;&#039; and returns a copy of the left/right part.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;foo;bar.baz&#039; upToAny: &#039;.,;&#039;&lt;br /&gt;
  =&amp;gt; &#039;foo&#039;&lt;br /&gt;
 &lt;br /&gt;
  &#039;foo bar.x&#039; restAfterAny: &#039;.,;&#039;&lt;br /&gt;
  =&amp;gt; &#039;x&#039;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;upToAll:&#039;&#039;&#039; &#039;&#039;sliceToSearch&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;restAfterAll:&#039;&#039;&#039; &#039;&#039;sliceToSearch&#039;&#039;&lt;br /&gt;
::Searches for the &#039;&#039;sliceToSearch&#039;&#039; sequence in &#039;&#039;aCollection&#039;&#039; and returns a copy of the left/right part.&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &#039;name: foo age: 124&#039; upToAll: &#039;age:&#039;&lt;br /&gt;
  =&amp;gt; &#039;name: foo &#039;&lt;br /&gt;
 &lt;br /&gt;
  &#039;name: foo age: 124&#039; restAfterAll: &#039;age:&#039;&lt;br /&gt;
  =&amp;gt; &#039; 124&#039;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Converting ===&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;asByteArray&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;asByteArray&#039;&#039;&#039;() [JS]&lt;br /&gt;
::Returns a byte array containing the elements which must be integers in the ISO8859 range 0x00 .. 0xFF.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;asSet&#039;&#039;&#039;&lt;br /&gt;
::Returns a set containing each element at most once.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;asOrderedCollection&#039;&#039;&#039;&lt;br /&gt;
::Returns an ordered collection (that is a resizable dynamic array) containing the elements in the same order.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;asSortedCollection&#039;&#039;&#039;&lt;br /&gt;
::Returns a sorted collection (that is a resizable dynamic collection which automatically sorts in additional elements).&lt;br /&gt;
&lt;br /&gt;
=== Sorting ===&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;sorted&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;sortedBy:&#039;&#039;&#039; &#039;&#039;compareBlock&#039;&#039;&lt;br /&gt;
::Returns a sorted copy of the collection (no side effect on the collection).&lt;br /&gt;
::If a condition argument (a block) is given, that should return true if the first argument is to come before the second. I.e. without a condition, the behavior is the same as &amp;quot;sortedBy:[:elA :elB | elA &amp;lt; elB]&amp;quot;.&lt;br /&gt;
::Examples&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt; &lt;br /&gt;
 &#039;&#039;hello world&#039;&#039; &#039;&#039;&#039;sorted&#039;&#039;&#039;&lt;br /&gt;
  =&amp;gt; &#039; dehllloorw&#039;&lt;br /&gt;
 &lt;br /&gt;
 #(10 2 99 17 -5 100) &#039;&#039;&#039;sorted&#039;&#039;&#039;&lt;br /&gt;
  =&amp;gt; #(-5 2 10 17 99 100)&lt;br /&gt;
 &lt;br /&gt;
 #(10 2 99 17 -5 100) &#039;&#039;&#039;sortedBy:[:a :b | a &amp;gt; b]&#039;&#039;&#039;&lt;br /&gt;
  =&amp;gt; #(100 99 17 10 2 -5)&lt;br /&gt;
 &lt;br /&gt;
 #(&#039;Paul&#039; &#039;paula&#039;  &#039;Thomas&#039; &#039;James&#039;  &#039;Emma&#039;) sorted&lt;br /&gt;
  =&amp;gt; #(&#039;Emma&#039; &#039;James&#039; &#039;Paul&#039; &#039;Thomas&#039; &#039;paula&#039;)&lt;br /&gt;
 &lt;br /&gt;
 #(&#039;Paul&#039; &#039;paula&#039;  &#039;Thomas&#039; &#039;James&#039;  &#039;Emma&#039;) sorted:[:a :b | a &amp;gt; b]&lt;br /&gt;
  =&amp;gt; #(&#039;paula&#039; &#039;Thomas&#039; &#039;Paul&#039; &#039;James&#039; &#039;Emma&#039;)&lt;br /&gt;
 &lt;br /&gt;
 #(&#039;Paul&#039; &#039;paula&#039;  &#039;Thomas&#039; &#039;James&#039;  &#039;Emma&#039;) sorted:[:a :b | a &amp;lt; b]&lt;br /&gt;
  =&amp;gt; OrderedCollection(&#039;Emma&#039; &#039;James&#039; &#039;Paul&#039; &#039;Thomas&#039; &#039;paula&#039;)&lt;br /&gt;
 &lt;br /&gt;
 #(&#039;Paul&#039; &#039;paula&#039;  &#039;Thomas&#039; &#039;James&#039;  &#039;Emma&#039;) sorted:[:a :b | a caselessBefore: b]&lt;br /&gt;
  =&amp;gt; #(&#039;Emma&#039; &#039;James&#039; &#039;Paul&#039; &#039;paula&#039; &#039;Thomas&#039;)&lt;br /&gt;
 &lt;br /&gt;
 #(&#039;Paul&#039; &#039;paula&#039;  &#039;Thomas&#039; &#039;James&#039;  &#039;Emma&#039;) sorted:[:a :b | b caselessBefore: a]&lt;br /&gt;
  =&amp;gt; #(&#039;Thomas&#039; &#039;paula&#039; &#039;Paul&#039; &#039;James&#039; &#039;Emma&#039;)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;sort&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;sort:&#039;&#039;&#039; &#039;&#039;compareBlock&#039;&#039;&lt;br /&gt;
::Sorts the collection in place (i.e. has a side effect on the collection).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;reversed&#039;&#039;&#039;&lt;br /&gt;
::Returns a copy with elements in reverse oerder&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;reverse&#039;&#039;&#039;&lt;br /&gt;
::Inplace reverts the elements (i.e. modifies the collection)&lt;br /&gt;
&lt;br /&gt;
=== Enumerating ===&lt;br /&gt;
:In Smalltalk there is almost never a need to program a loop which fetches and processes elements. You should use the provided enumeration functions for that, both for readability and because some of them are highly optimized.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;do:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;do:&#039;&#039;&#039; ( function(el) { ... } ) [JS] &amp;lt;SMALL&amp;gt;(Function notation)&amp;lt;/SMALL&amp;gt;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;do:&#039;&#039;&#039; ( (el) -&amp;gt; ...) [JS] &amp;lt;SMALL&amp;gt;(Lambda notation)&amp;lt;/SMALL&amp;gt;&lt;br /&gt;
::evaluates the argument block for each element in the collection. The &amp;quot;do:&amp;quot; method is supported by all collections and even some non-collections (for example some widgets which present lists or text lines may also support the do: message to enumerate their contents).&lt;br /&gt;
::Examples&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt; &lt;br /&gt;
  #(10 5 4 20 99) do:[:eachElement |&lt;br /&gt;
     Transcript showCR: eachElement.&lt;br /&gt;
     myFile nextPutLine:(eachElement hexPrintString).&lt;br /&gt;
  ]&lt;br /&gt;
 &lt;br /&gt;
  #(10 5 4 20 99) sorted do:[:eachElement |&lt;br /&gt;
     Transcript showCR: eachElement.&lt;br /&gt;
  ]&lt;br /&gt;
 &lt;br /&gt;
  &amp;quot;/ info: &amp;quot;(nr1 to: nr2)&amp;quot; generates a range collection &lt;br /&gt;
  &amp;quot;/ (called &#039;&#039;Interval&#039;&#039; in Smalltalk)&lt;br /&gt;
  (1 to:10) do:[:each |&lt;br /&gt;
     Transcript printf:&#039;%3d: %4d\n&#039; with:each with:(each * each).&lt;br /&gt;
  ]&lt;br /&gt;
 &lt;br /&gt;
  &amp;quot;/ a kind of &amp;quot;ls&amp;quot; implementation: lists files of the current folder &lt;br /&gt;
  &#039;.&#039; asFilename files do:[:eachFile |&lt;br /&gt;
     Transcript showCR: eachFile.&lt;br /&gt;
  ]&lt;br /&gt;
 &lt;br /&gt;
  &amp;quot;/ this prints the contents of each file&lt;br /&gt;
  &#039;.&#039;asFilename files do:[:eachFile |&lt;br /&gt;
     Transcript showCR: eachFile.&lt;br /&gt;
     eachFile contents do:[:eachLine |&lt;br /&gt;
         Transcript showCR: eachLine.&lt;br /&gt;
     ]&lt;br /&gt;
  ]&lt;br /&gt;
 &lt;br /&gt;
  &amp;quot;/ the same but shorter and even faster...&lt;br /&gt;
  &#039;.&#039;asFilename files do:[:eachFile |&lt;br /&gt;
     Transcript showCR: eachFile.&lt;br /&gt;
     Transcript showCR: eachFile contents.&lt;br /&gt;
  ]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;keysAndValuesDo:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :k :el | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;doWithIndex:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el :k  | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
::evaluates the 2-argument block for each key and element in the collection. This is supported by all indexable collections. For arrays and other collections with a numeric index, that is provided as key. For dictionaries, the lookup key is provided.&lt;br /&gt;
::The &#039;&#039;doWithIndex:&#039;&#039; variant performs the same function, but provides the argument in reverse order into the block (syntactic sugar for readability).&lt;br /&gt;
::Examples&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt; &lt;br /&gt;
  #(10 5 4 20 99) keysAndValuesDo:[:eachIndex :eachElement |&lt;br /&gt;
     Transcript show: eachIndex.&lt;br /&gt;
     Transcript show:&#039; -&amp;gt; &#039;.&lt;br /&gt;
     Transcript showCR: eachElement.&lt;br /&gt;
  ] &lt;br /&gt;
 &lt;br /&gt;
  d := Dictionary new.&lt;br /&gt;
  d at:&#039;foo&#039; put:123.&lt;br /&gt;
  d at:&#039;bar&#039; put:999.&lt;br /&gt;
  d keysAndValuesDo:[:eachKey :eachElement |&lt;br /&gt;
     Transcript show: eachKey .&lt;br /&gt;
     Transcript show:&#039; -&amp;gt; &#039;.&lt;br /&gt;
     Transcript showCR: eachElement.&lt;br /&gt;
  ] &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;collect:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
::evaluates the argument block for each element in the collection and collects the results, returning a new collection with all results (this is called &amp;quot;map&amp;quot; in other languages).&lt;br /&gt;
::Examples&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt; &lt;br /&gt;
  &#039;.&#039; asFilename files collect:[:eachFile | eachFile fileSize].&lt;br /&gt;
 &lt;br /&gt;
  Transcript showCR:&lt;br /&gt;
     (1 to:10) collect:[:nr | nr * nr]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;select:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
::evaluates the boolean argument block for each element in the collection and collects those elements for which the block returns true. I.e. this is filtering elements by a boolean condition.&lt;br /&gt;
::Examples&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;quot;/ lists files larger than 10000 bytes &lt;br /&gt;
  &#039;.&#039; asFilename files select:[:eachFile | eachFile fileSize &amp;gt; 10000].&lt;br /&gt;
 &lt;br /&gt;
  Transcript&lt;br /&gt;
     showCR: &#039;even numbers:&#039;; &lt;br /&gt;
     showCR: (1 to:100) select:[:nr | nr even]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;reject:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
::similar to select, but this returns the complement: a new collection without elements for which the boolean argument block returns true.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;count:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
::counts for how many elements the boolean argument block returns true.&lt;br /&gt;
::Examples&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;quot;/ how many files are larger than 10000 bytes &lt;br /&gt;
  &#039;.&#039; asFilename files count:[:eachFile | eachFile fileSize &amp;gt; 10000].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;detect:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
::find and return the first element for which the boolean argument block returns true. If none is found, an error is reported.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;detect:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el | ... &#039;&#039;&#039;]&#039;&#039;&#039; &#039;&#039;&#039;ifNone:&#039;&#039;&#039; &#039;&#039;replacementBlock&#039;&#039;&lt;br /&gt;
::find and return the first element for which the boolean argument block returns true. If none is found, replacementBlock is evaluated and its value returned.&lt;br /&gt;
::Examples&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  #(1 2 3 4 5) detect:[:el | el &amp;gt; 10]&lt;br /&gt;
    =&amp;gt; reports an error: no such element&lt;br /&gt;
 &lt;br /&gt;
  #(1 2 3 4 5) detect:[:el | el &amp;gt; 10] ifNone:[99]&lt;br /&gt;
    =&amp;gt; 99&lt;br /&gt;
 &lt;br /&gt;
  #(1 2 3 4 5) detect:[:el | el &amp;gt; 10] ifNone:[ Dialog warn:&#039;No such element&#039;. nil]&lt;br /&gt;
    =&amp;gt; nil. (after the warning is shown)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;findFirst:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;aCollection&#039;&#039; &#039;&#039;&#039;findLast:&#039;&#039;&#039; &#039;&#039;&#039;[&#039;&#039;&#039; :el | ... &#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
::find the index of the first/last element for which the boolean condition block returns true. Returns 0 if no element matches the condition.&lt;br /&gt;
::Examples&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 4em;&amp;quot;&amp;gt;&lt;br /&gt;
  #(15 2 -3 44 5.3) findFirst:[:el | el &amp;gt; 20]&lt;br /&gt;
    =&amp;gt; 4 &amp;lt;SMALL&amp;gt;(the index of the found element)&amp;lt;/SMALL&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &#039;Hello World&#039; findFirst:[:ch | ch isSeparator]&lt;br /&gt;
    =&amp;gt; 6&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:There are many more (hundreds) of additional useful enumeration messages to be found in the collection hierarchy. For example to enumerate in groups, stepping over elements, enumerating multiple collections together, enumerating in reverse order etc.&lt;br /&gt;
:For details, open a System Browser (via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; menu) and take look at the collection class and its subclasses.&lt;br /&gt;
&lt;br /&gt;
:Also notice that Strings, NumberVectors, ByteArrays etc. also inherit from Collection; thus, all of those functions can also be applied to them.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Useful_API_Functions&amp;diff=30883</id>
		<title>Useful API Functions</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Useful_API_Functions&amp;diff=30883"/>
		<updated>2026-02-23T10:43:05Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 16.2.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document lists most useful (and most often needed) classes and functions.&lt;br /&gt;
Be aware, that there are many more to be found in either the class references or via the builtin [[Tools_ClassBrowser/en | class browser]].&lt;br /&gt;
&lt;br /&gt;
== [[String API Functions | String]] ==&lt;br /&gt;
&lt;br /&gt;
Strings are sequences of characters. Expecco uses and supports the Unicode encoding standard and supports the whole unicode range. &amp;lt;br&amp;gt;However, not all fonts will contain all characters, resulting in some missing characters being drawn with a replacement char (typically a box-like rectangle) in text windows.&amp;lt;br&amp;gt;The concrete details depend on the operating system and the set of installed fonts.&lt;br /&gt;
&lt;br /&gt;
String instances inherit a lot of functionality from String&#039;s superclasses: SequenceableCollection and Collection. Thus, all functions found there (enumeration, mapping, filtering, searching etc.) can also be applied to strings.&lt;br /&gt;
&lt;br /&gt;
Read more: [[String_API_Functions|String API Functions]]&amp;lt;br&amp;gt;&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,String String]&lt;br /&gt;
inherits from: [http://live.exept.de/ClassDoc/classDocOf:,CharacterArray CharacterArray] and&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,SequenceableCollection SequenceableCollection] and [http://live.exept.de/ClassDoc/classDocOf:,Collection Collection]&lt;br /&gt;
&lt;br /&gt;
== [[Collection API Functions |  Collection]] ==&lt;br /&gt;
&lt;br /&gt;
Collection is an abstract class, serving as a superclass for a number of useful concrete classes (such as Array, ByteArray, Set, Dictionary, Tree, SortedCollection, String etc.)&lt;br /&gt;
It is useful to get a feeling of the set of operations provided there (there are a lot!), so you should not have to reinvent the wheel.&lt;br /&gt;
&lt;br /&gt;
Read more: [[Collection_API_Functions|Collection API Functions]]&amp;lt;br&amp;gt;&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Collection Collection]&lt;br /&gt;
&lt;br /&gt;
== [[Filename API Functions |  Filename]] ==&lt;br /&gt;
&lt;br /&gt;
Although strings could be used to represent file names and paths, expecco uses instances of a specialized class called &amp;quot;&#039;&#039;Filename&#039;&#039;&amp;quot; to represent those. Filename instances know about any details of the underlying operating system (such as the directory separator, any naming restrictions etc.) and also provide a number of useful functions for file and directory access. Filename provides a portable representation, so that code can run on both Windows and Unix unchanged (that is: use &amp;quot;/&amp;quot; in filenames when possible. On a Windows machine, these will be replaced internally by &amp;quot;\&amp;quot; characters).&lt;br /&gt;
&lt;br /&gt;
Of course, there are still many differences between the systems, the most obvius being different pathes. For that, the Filiename class provides a number of accessors, for example to get the path to the home directory, the path to the temp folder etc. Do not hardcode any pathnames into your code or testSuite; instead either use the above mentioned accessors, or place the pathes into a global variable, so they can be both easily found and also easily overwritten by eg. the command line or a config file.&lt;br /&gt;
&lt;br /&gt;
Read more: [[Filename_API_Functions|Filename API Functions]]&amp;lt;br&amp;gt;&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Filename Filename]&lt;br /&gt;
&lt;br /&gt;
== [[Stream API Functions |  Stream]] ==&lt;br /&gt;
&lt;br /&gt;
Streams can be internal (eg. reading from a String) or external (eg. a file stream, pipe or socket). Streams can be used to read bytewiese, character wise (with optional UTF decoding/encoding) or object-wise.&lt;br /&gt;
Most uses are with external streams, which are byte or character oriented: FileStream, PipeStream, Socket are examples.&lt;br /&gt;
&lt;br /&gt;
Read more: [[Stream_API_Functions|Stream API Functions]]&amp;lt;br&amp;gt;&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Stream Stream]&lt;br /&gt;
&lt;br /&gt;
== [[Number API Functions | Number]] ==&lt;br /&gt;
&lt;br /&gt;
Expecco supports a full numeric stack of numbers; both exact (integers and fractions) and inexact (IEEE floats in various precisions). Integer operations do not overflow or loose bits: expecco will automatically choose an appropriate representation to eg. be able to represent huge numbers.&lt;br /&gt;
&lt;br /&gt;
Read more: [[Number_API_Functions|Number API Functions]]&amp;lt;br&amp;gt;&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Number Number] and its subclasses&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Integer Integer],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Float Float],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Fraction Fraction],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,FixedPoint ScaledDecimal],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Complex Complex]&lt;br /&gt;
&lt;br /&gt;
== [[Date &amp;amp; Time]] ==&lt;br /&gt;
Expecco provides a number of time related support classes: TimeDuration, Time, Date and Timestamp (aka. &#039;&#039;TimeAndDate&#039;&#039;) for local, UTC and time zone specific. Although timestamps support picosecond precision, current operating systems will only provide milli- or microsecond resolution timestamps. However finer resolution values may come from exact measurement devices or be computed in technical/physical processes.&lt;br /&gt;
&lt;br /&gt;
Read more: [[Date_and_Time_API_Functions|Date and Time API Functions]]&amp;lt;br&amp;gt;&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Date Date],  [http://live.exept.de/ClassDoc/classDocOf:,Time Time],  [http://live.exept.de/ClassDoc/classDocOf:,Timestamp Timestamp], [http://live.exept.de/ClassDoc/classDocOf:,UtcTimestamp UtcTimestamp], [http://live.exept.de/ClassDoc/classDocOf:,TZTimestamp TZTimestamp],  [http://live.exept.de/ClassDoc/classDocOf:,TimeDuration TimeDuration].&lt;br /&gt;
&lt;br /&gt;
== [[PhysicalValues/en|Physical Values]] ==&lt;br /&gt;
Since 20.1, expecco supports an additional framework to represent physical values, such as mass (in kg), length (in meters), velocity, [[PhysicalValues/en#Acceleration|acceleration]], voltage, electric current etc.&lt;br /&gt;
&amp;lt;br&amp;gt;Beside being able to do arithmetic as in &amp;lt;code&amp;gt;3.0 kiloMeter / 20 minutes&amp;lt;/code&amp;gt; (which gives &amp;quot;2.5 m/s&amp;quot;) they can also be used for conversion between metric and imperial unit systems (eg. &amp;quot;&amp;lt;code&amp;gt;10 nauticalMiles asMeters&amp;lt;/code&amp;gt;&amp;quot; gives the answer &amp;quot;18520 m&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;15 inches asMilliMeters&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;381 mm&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Read more: [[PhysicalValues/en|PhysicalValues]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== [[Cryptographic_API_Functions/en | Cryptography]] ==&lt;br /&gt;
&lt;br /&gt;
Algorithms for hashing, encryption and decryption, certificate handling etc.&lt;br /&gt;
&lt;br /&gt;
Read more: [[Cryptographic_API_Functions/en|Cryptographic API Functions]]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Datatype_Editor/en&amp;diff=30882</id>
		<title>Datatype Editor/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Datatype_Editor/en&amp;diff=30882"/>
		<updated>2026-02-23T10:40:42Z</updated>

		<summary type="html">&lt;p&gt;Sv: Änderung übernommen aus altem Wiki von cg, 16.2.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
[[Datatype Element | Datatypes]] are attached to pins and environment variables, and usually presented by name in a datatype definition pull-down menu. &lt;br /&gt;
There are both builtin (hardwired) and user defined data types in expecco.&lt;br /&gt;
User defined datatypes are shown in those pull-down lists in a separate submenu of the type menu.&lt;br /&gt;
&lt;br /&gt;
This editor is used to define new [[Datatype Element | datatypes]].&amp;lt;br&amp;gt;Builtin types cannot be modified.&lt;br /&gt;
&lt;br /&gt;
==Type Kinds==&lt;br /&gt;
The &#039;&#039;kind&#039;&#039; specifies the kind of type and &#039;&#039;&#039;how&#039;&#039;&#039; it is defined. For example, there are vector types, enum types, struct types etc. These are described in more detail below.&lt;br /&gt;
&lt;br /&gt;
There are multiple &#039;&#039;&#039;conceptional&#039;&#039;&#039; ways to define a new datatype:&lt;br /&gt;
* by enumerating its elements (enums; i.e. a set of values)&lt;br /&gt;
* as a subtype of an existing type (enum, range types)&lt;br /&gt;
* by combining elements of existing types (tuple, array, structure or union types)&lt;br /&gt;
* by explicit definition as a class or data structure (C-type, ST/X-class type)&lt;br /&gt;
* by referring to an existing class of the underlying framework (primary types)&lt;br /&gt;
&lt;br /&gt;
Also, there are various &#039;&#039;&#039;syntactical&#039;&#039;&#039; representations, in which a type may be presented or imported:&lt;br /&gt;
* expecco type definition syntax&lt;br /&gt;
* XML / XSD / DTD / IDL&lt;br /&gt;
* C language struct syntax&lt;br /&gt;
* COBOL Copybook, Sun RPC IDL, COM-IDL, ASN.1&lt;br /&gt;
&lt;br /&gt;
The set of options available in the editor depends on the expecco version (basic, pro, enterprise) and the set of available plugins (SWIFT, ASN.1, etc.), as some import formats are provided by additional plugins.&lt;br /&gt;
&lt;br /&gt;
To define a type, first create a new datatype tree item, then choose an appropriate representation in the editor&#039;s &amp;quot;&#039;&#039;Type-Kind&#039;&#039;&amp;quot; list. A template showing the syntax of this type will be shown. &lt;br /&gt;
&lt;br /&gt;
Change the template and press &amp;quot;&#039;&#039;Accept&#039;&#039;&amp;quot; to install the type. The second tab in the editor labeled &amp;quot;&#039;&#039;Type Description&#039;&#039;&amp;quot; shows the type&#039;s definition in expecco&#039;s internal type description language, which is usually only of interest to validate a type&#039;s correctness if an alien format was used to import a type definition. This format is described [[ #Formal BNF Description of the Expecco Type Syntax | below ]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:typeEditor1.png|600px|Datatype Editor]]&lt;br /&gt;
&lt;br /&gt;
==Type Kinds (Semantic)==&lt;br /&gt;
&lt;br /&gt;
===Primary Types===&lt;br /&gt;
These are builtin types (classes) of the underlying Smalltalk execution framework. For example, &amp;quot;&amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Array&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Set&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Btree&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Dictionary&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt;&amp;quot; to name a few. There are thousands of classes available, but you will usually get along happily with only a few - if at all. However, you might need to know some, when referring to a framework inside expecco&#039;s underlying Smalltalk environment.&amp;lt;br&amp;gt;For example, there are packages and classes to support protocols like FTP, HTTP, etc. or to process data, parse special file formats or provide cryptographic operations. Also, some expecco plugins and extensions come bundled with additional useful classes.&amp;lt;br&amp;gt;These classes usually provide many additional API functions than provided in the standard library (it would be immensly big otherwise).&amp;lt;br&amp;gt;And sometimes you can use these additional functions, so its good to know a little more.&lt;br /&gt;
&lt;br /&gt;
The most common primary types are shortly listed in the [[Datatype Element | &amp;quot;Datatype documentation&amp;quot; ]].&lt;br /&gt;
For more details, please refer to the Smalltalk documentation, especially the [http://live.exept.de/doc/online/english/overview/basicClasses/TOP.html  &amp;quot;Basic Classes Introduction&amp;quot;] and the [http://live.exept.de/ClassDoc &amp;quot;Online Class Documentation&amp;quot;] (containing full lists and documentation of all classes).&lt;br /&gt;
&lt;br /&gt;
Even better: you can also open a class browser (found in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot;) and look at the source code which often includes examples in their method comment.&amp;lt;br&amp;gt;Another useful tool is the &amp;quot;MethodFinder&amp;quot; which lets you find functions which generate a particulal output (i.e. if you know what input you have, and what output you want, but you don&#039;t know where to search, this  is the tool for you).&lt;br /&gt;
&lt;br /&gt;
A number of primary types is available directly via the datatype menus, and there is no need to define them as a user type.&lt;br /&gt;
These predefined primary types include &amp;quot;&amp;lt;code&amp;gt;Integer&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Boolean&amp;lt;/code&amp;gt;&amp;quot; along with a few other often used types.&lt;br /&gt;
All other primary types can be defined as a &#039;&#039;user defined type&#039;&#039; in a textual type definition, where the class name is written in angle brackets, as in:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    &amp;lt;String&amp;gt;&lt;br /&gt;
&amp;lt;/PRE&amp;gt;or:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    &amp;lt;Socket&amp;gt;&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Enumeration Types===&lt;br /&gt;
Data items are symbolic and members of a list of enumerated values (symbolic).&lt;br /&gt;
Unless quoted in single quotes, these names must consist of letters or digits or underline characters, and should start with a non-digit (to avoid confusion).&lt;br /&gt;
&lt;br /&gt;
Typical examples are:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    enum( red | green | blue)&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
or:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    enum( male | female)&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
or:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    enum( &#039;foo-a&#039; | &#039;foo-b&#039; | &#039;foo-c&#039; | &#039;bar-a&#039; | &#039;bar-b&#039; )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
The last example uses quotes around the element names, as these contain a special (non-alphanumeric) character.&lt;br /&gt;
&lt;br /&gt;
===== Enum in Input Dialogs ===== &lt;br /&gt;
When used as a freeze value or environment variable value, a combo list presenting only the valid enum elements is shown. By default, the values are sorted alphabetically in one single list. If your type consists of a large number of values, you may want to specify a grouping scheme. &lt;br /&gt;
[[Datei:Datatype enumOrder.png|mini]]&lt;br /&gt;
For example, the last of the above examples could be presented as either a single list with 5 items, or as a 2-item list (&#039;foo&#039; and &#039;bar&#039;) with submenus for each prefix. The menu/combolist grouping is specified in the datatype editor (at the bottom right of the editor).&lt;br /&gt;
&lt;br /&gt;
===== Numeric Value of an Enum =====&lt;br /&gt;
Enum values can have an associated integer value, which is useful, if the type is actually a mapping of a corresponding C or Java type.&amp;lt;br&amp;gt;For this, add an &amp;quot;&amp;lt;code&amp;gt;= &amp;lt;integerValue&amp;gt;&amp;lt;/code&amp;gt;&amp;quot; after the element&#039;s name to the above definition. Eg.:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
enum ( foo | bar = 20 | baz | bla = 30 )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
Will assign integer values to the enum elements. &lt;br /&gt;
Without explicit integer value, elements get auto-incremented values, starting with 0 (zero) or the next value from the previous enum element.&amp;lt;br&amp;gt;Thus, in the above, &amp;quot;baz&amp;quot; will get the numeric value 21 assigned.&lt;br /&gt;
&lt;br /&gt;
Elementary code can retrieve this integer value via &amp;quot;&amp;lt;code&amp;gt;&amp;amp;lt;type&amp;amp;gt; integerValueOf: x&amp;lt;/code&amp;gt;&amp;quot; in Smalltalk,&lt;br /&gt;
or &amp;quot;&amp;lt;code&amp;gt;&amp;amp;lt;type&amp;amp;gt;.integerValueOf(x)&amp;lt;/code&amp;gt;&amp;quot; in Javascript. There is also a standard library action to retrieve the numeric value (&amp;quot;&amp;lt;code&amp;gt;Convert [Enum-to-Integer]&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
These will return the following integer values:&lt;br /&gt;
0 (for x = &#039;foo&#039;), 20 (for x = &#039;bar&#039;), 21 for (x = &#039;baz&#039;) and 30 (for x = &#039;bla&#039;)&lt;br /&gt;
&lt;br /&gt;
The reverse mapping from integer to symbolic is performed with&lt;br /&gt;
&amp;quot;&amp;lt;code&amp;gt;&amp;amp;lt;type&amp;amp;gt; symbolicValueOf: x&amp;lt;/code&amp;gt;&amp;quot; (Smalltalk), &lt;br /&gt;
&amp;quot;&amp;lt;code&amp;gt;&amp;amp;lt;type&amp;amp;gt;.symbolicValueOf(x)&amp;lt;/code&amp;gt;&amp;quot; (Javascript), or the library action&lt;br /&gt;
&amp;quot;&amp;lt;code&amp;gt;Convert [Integer-to-Enum]&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Be aware that enum-typed datums are always string-like objects (actually: instances of Smalltalk&#039;s &amp;lt;code&amp;gt;Symbol&amp;lt;/code&amp;gt; class). Thus, although the elements look like integers in a definition like &amp;quot;&amp;lt;code&amp;gt;(1 | 2 | 3)&amp;lt;/code&amp;gt;&amp;quot;, they are actually string like with an associated integer. Consider using a subrange or subset type, as described below, if you need integer datums.&lt;br /&gt;
&lt;br /&gt;
Although not recommended, the same numeric value can be assigned to more than one symbol. However, a reverse mapping from numeric value to symbolic is then no longer possible.&lt;br /&gt;
&lt;br /&gt;
===== Enum Definition pasted from a C-Header File =====&lt;br /&gt;
New in 18.2:&amp;lt;br&amp;gt; &lt;br /&gt;
In addition to the above definition format, enum types can also be defined as a list of C-define directives.&lt;br /&gt;
This makes it easier, to copy-paste a list of values from a C-header file. The format is described [[#Enum_Type_Definition_from_C-define_Directives  | below]].&lt;br /&gt;
&lt;br /&gt;
===Range Types===&lt;br /&gt;
A subrange of &amp;lt;code&amp;gt;Integer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Character&amp;lt;/code&amp;gt; or Enum values. Used to limit the set of valid elements, given a previously defined or buitin base type. For example, a byte could be defined as:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    range( &amp;lt;Integer&amp;gt; : 0 .. 255 )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
and the set of lowercase letters can be defined as:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    range( &amp;lt;Character&amp;gt; : $a .. $z )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
[[Datei:point_right.png|20px]] Notice the dollar prefix, which designates a character constant in the Smalltalk language.&lt;br /&gt;
&lt;br /&gt;
===Subset Types===&lt;br /&gt;
A subset of &amp;lt;code&amp;gt;Integer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Character&amp;lt;/code&amp;gt; or Enum values. This is similar to a subrange, but allows for multiple ranges or individual elements to be listed.&lt;br /&gt;
&lt;br /&gt;
For example, the set of alphanumeric characters plus underline could be defined as:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    subset( &amp;lt;Character&amp;gt; : $a .. %z , $A .. $Z , $_ , $0 .. $9 )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type which can take character values limited to the set of English vowels could be defined as:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    subset( &amp;lt;Character&amp;gt; : $A , $E , $I , $O , $U , $a , $e , $i , $o , $u )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Again, notice the dollar prefix, which designates a character constant.&lt;br /&gt;
&lt;br /&gt;
===Pattern Types===&lt;br /&gt;
(new with expecco 21.2)&amp;lt;br&amp;gt;&lt;br /&gt;
A constraint subset of &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; values. Constraint may be that the string matches&lt;br /&gt;
a glob or regex pattern, and/or that its size (number of characters) is within some limits.&lt;br /&gt;
&lt;br /&gt;
For example, a type for strings not longer than 10 characters could be defined as:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    String( maxLength: 10 )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type for a string which starts with a letter can be defined as ([https://en.wikipedia.org/wiki/Glob_(programming) GLOB] pattern):&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    String( match: &#039;[a-z]*&#039;)&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or alternatively, using a [https://en.wikipedia.org/wiki/Regular_expression Regex] (instead of a GLOB pattern) as:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    String( regex: &#039;[a-z].*&#039;)&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The constraint can be one of:&lt;br /&gt;
* &#039;&#039;&#039;minLength&#039;&#039;&#039;: &amp;lt;n&amp;gt;&lt;br /&gt;
:the string must consist of at least &amp;lt;n&amp;gt; characters&lt;br /&gt;
* &#039;&#039;&#039;maxLength&#039;&#039;&#039;: &amp;lt;n&amp;gt;&lt;br /&gt;
:may not be longer than &amp;lt;n&amp;gt; characters&lt;br /&gt;
* &#039;&#039;&#039;match&#039;&#039;&#039;: &#039;&amp;lt;glob pattern&amp;gt;&#039;&lt;br /&gt;
: the strings must match the [https://en.wikipedia.org/wiki/Glob_(programming) GLOB] pattern&lt;br /&gt;
* &#039;&#039;&#039;regex&#039;&#039;&#039;: &#039;&amp;lt;pattern&amp;gt;&#039;&lt;br /&gt;
: must match the [https://en.wikipedia.org/wiki/Regular_expression Regex] pattern&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Be aware of the difference between GLOB and Regex patterns.&lt;br /&gt;
&lt;br /&gt;
===Array Types===&lt;br /&gt;
Are defined as a homogeneous collection of elements, which are all of the same baseType. The number of elements is variable among instances.&lt;br /&gt;
The elements are accessible by a numeric index which is 1 based (both for Smalltalk and JavaScript elementary blocks). The standard library also provides 0-based indexing blocks, which is sometimes more convenient for C/Java programmers.&lt;br /&gt;
&amp;lt;!-- thisis no longer the case&lt;br /&gt;
&amp;lt;br&amp;gt;For compatibility to other JavaScript systems, a few builtin functions behave differently, depending on the language context inside an elementary block&#039;s code; most notably, these are the indexOf/lastIndexOf functions.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a textual definition, array types consist of a basetype followed by &amp;quot;[]&amp;quot;, as in:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    &amp;lt;String&amp;gt;[]    -- an array of Strings&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
or:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    &amp;lt;Number&amp;gt;[]    -- an array of Numbers&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
Notice that these are type Arrays, in contrast to the Smalltalk primary Array type, which allows any object as element. Event mixed within one array.&lt;br /&gt;
&lt;br /&gt;
===Tuple Types===&lt;br /&gt;
Are defined as a non-homogeneous, fixed size vector of elements. Each element has a predefined type. The types may be different among elements, but all instances of the tuple type have the same number of elements and the same type of element at corresponding positions.&lt;br /&gt;
&lt;br /&gt;
The elements are accessible by index (1..). Tuples are similar to compound types as described below. The difference is that tuples address the elements by index, whereas compounds address them by name. Tuples are also similar to array types, however, the number of elements is fixed in a tuple, whereas arrays can have an arbitrary number of elements, and the element types may be different if its a primary array or an array of Any), Otherwise in a typed array, all elements are of the same type.&lt;br /&gt;
&lt;br /&gt;
In a textual description, a tuple is defined by listing the individual element types in parentheses.&lt;br /&gt;
For example, a tuple which might represent a 3D coordinate, could be defined as:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    [ &amp;lt;Number&amp;gt; , &amp;lt;Number&amp;gt; , &amp;lt;Number&amp;gt; ]&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
or, a tuple which associates a name with an age and gender might be:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    [ &amp;lt;String&amp;gt; , &amp;lt;Integer&amp;gt; , enum(M | F) ]&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
For the last example, it would probably be better to use a compound, which names the slots.&lt;br /&gt;
&amp;lt;P&amp;gt;&lt;br /&gt;
[[Datei:point_right.png|20px]] Notice, in previous versions of expecco, tuple types could also be defined in parenthesis &amp;quot;(...)&amp;quot;, as opposed to brackets &amp;quot;[...]&amp;quot;.&lt;br /&gt;
This is still supported in future versions, but not recommended for new type definitions (read the documentation on union types for an explanation).&lt;br /&gt;
No ambiguity exists if the definition starts with &#039;tuple&#039;, as in:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    tuple( &amp;lt;Number&amp;gt; , &amp;lt;Number&amp;gt; , &amp;lt;Number&amp;gt; )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Class Types===&lt;br /&gt;
A user defined class. Includes the instance&#039;s private slots (also called &amp;quot;&#039;&#039;instance variables&#039;&#039;&amp;quot;), and a set of operations (usually called &amp;quot;&#039;&#039;methods&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;virtual functions&#039;&#039;&amp;quot;). All of this information is stored with the test suite.&lt;br /&gt;
Instance slots are accessible by getter/setter method invocations.&lt;br /&gt;
Class types are defined by entering the class definition in a programming language (either expecco&#039;s JavaScript dialect or Smalltalk).&lt;br /&gt;
&lt;br /&gt;
Private class definitions allow for almost any functionality to be defined, but require some programming skills. For an introduction to programming, please refer to the [http://live.exept.de/doc/online/english/TOP.html &amp;quot;Online Documentation&amp;quot;],&lt;br /&gt;
the [http://live.exept.de/doc/online/english/getstart/tutorial.html &amp;quot;Beginners Introduction &amp;amp; Tutorial&amp;quot;],&lt;br /&gt;
and the [http://live.exept.de/doc/books/JoyOfST/IntroToST.html &amp;quot;Smalltalk Tutorial&amp;quot;],.&lt;br /&gt;
&lt;br /&gt;
===Compound Types===&lt;br /&gt;
A collection of named slots. Is similar to a Class Type without operations (actually, that is how the system represents them internally).&lt;br /&gt;
The elements are accessible by name or keyed access, using the name as key (i.e. like a dictionary/hashtable).&lt;br /&gt;
&lt;br /&gt;
In a textual definition, list the names and types of the individual elements in braces; for example, a person record might be defined as:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        firstame : &amp;lt;String&amp;gt;&lt;br /&gt;
        lastName : &amp;lt;String&amp;gt;&lt;br /&gt;
        age      : &amp;lt;Integer&amp;gt;&lt;br /&gt;
        gender   : enum(M | F)&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Field definitions may optionally be terminated by a &amp;quot;;&amp;quot; (semicolon) character to make the definition more readable.&lt;br /&gt;
I.e. the following defines the same type as the above:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        firstame : &amp;lt;String&amp;gt;;&lt;br /&gt;
        lastName : &amp;lt;String&amp;gt;;&lt;br /&gt;
        age      : &amp;lt;Integer&amp;gt;;&lt;br /&gt;
        gender   : enum(M | F);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
Also, for backward compatibility, a terminating &amp;quot;,&amp;quot; (comma) character is allowed, but no longer recommended.&lt;br /&gt;
&lt;br /&gt;
Compound type definitions can also be imported from various other formats, such as DTD, XML, C-header files etc.&lt;br /&gt;
&lt;br /&gt;
==== Getters ====&lt;br /&gt;
In elementary code blocks, field values of an instance are accessed via getter calls which are named like the field. &lt;br /&gt;
&amp;lt;br&amp;gt;For example, given an instance of the above named &amp;quot;&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;&amp;quot;, the &amp;quot;&#039;&#039;lastName&#039;&#039;&amp;quot; field can be fetched in Smalltalk code with any of:&lt;br /&gt;
 c lastName        &amp;quot;/ calling the getter&lt;br /&gt;
 c at:&#039;lastName&#039;   &amp;quot;/ using collection protocol&lt;br /&gt;
 c[&#039;lastName&#039;]     &amp;quot;/ using collection protocol&lt;br /&gt;
or in JavaScript code with:&lt;br /&gt;
 c.lastName()      // calling the getter&lt;br /&gt;
 c.lastName        // (virtual) slot access&lt;br /&gt;
 c[&#039;lastName&#039;]     // using collection protocol&lt;br /&gt;
 c[&amp;quot;lastName&amp;quot;]     // using collection protocol&lt;br /&gt;
Notice, that double quotes in Smalltalk are comment delimiters, whereas in JavaScript they are also string delimiters.&lt;br /&gt;
&lt;br /&gt;
==== Setters ====&lt;br /&gt;
Elementary code can change a field&#039;s value via setter calls. &lt;br /&gt;
&amp;lt;br&amp;gt;For the above example, these would be in Smalltalk:&lt;br /&gt;
 c lastName:&amp;lt;I&amp;gt;newValue&amp;lt;/i&amp;gt;&lt;br /&gt;
 c at:&#039;lastName&#039; put:&amp;lt;I&amp;gt;newValue&amp;lt;/i&amp;gt;&lt;br /&gt;
 c[&#039;lastName&#039;] := &amp;lt;I&amp;gt;newValue&amp;lt;/i&amp;gt;&lt;br /&gt;
and in JavaScript:&lt;br /&gt;
 c.lastName(&amp;lt;I&amp;gt;newValue&amp;lt;/I&amp;gt;)&lt;br /&gt;
 c[&#039;lastName&#039;] := &amp;lt;I&amp;gt;newValue&amp;lt;/i&amp;gt;&lt;br /&gt;
 c[&amp;quot;lastName&amp;quot;] := &amp;lt;I&amp;gt;newValue&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Generating Action Blocks to Access Fields and Create Instances ====&lt;br /&gt;
[[Datei:CompoundCreateActions.png|mini]]&lt;br /&gt;
[[Datei:CompoundCreateActions2.png|mini]]&lt;br /&gt;
The tree-item menu of a compound type contains entries to generate field-setter, field getter and creation actions (under &amp;quot;&#039;&#039;Refactoring&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Generate&#039;&#039;&amp;quot;).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
After that, you&#039;ll find actions to create an instance, to extract and to set fields. &lt;br /&gt;
&lt;br /&gt;
These are elementary actions, which use the above listed getter/setter calls. They can of course be further modified if additional checks or processing is needed. Notice that to access fields of a compound object, you can also use the &amp;quot;&#039;&#039;Collection [elementAt]&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Collection [elementAtPut]&#039;&#039;&amp;quot; actions, using the field names as index.&lt;br /&gt;
&lt;br /&gt;
===Union Types===&lt;br /&gt;
The instance can be an instance from a number of other types.&lt;br /&gt;
In a textual definition, list the possible element types, separated by a vetical bar, as in:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
    ( &amp;lt;Filename&amp;gt; | &amp;lt;String&amp;gt; | &amp;lt;URL&amp;gt; )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
or, alternatively:&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
   union ( &amp;lt;Filename&amp;gt; | &amp;lt;String&amp;gt; | &amp;lt;URL&amp;gt; )&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
there is no explicit discriminator stored with the value. However, due to the run-time type information, it is possible in an elementary block to determine the type of value passed in, via the &amp;lt;CODE&amp;gt;class&amp;lt;/CODE&amp;gt; or &amp;lt;CODE&amp;gt;isXXX&amp;lt;/CODE&amp;gt; or &amp;lt;CODE&amp;gt;isKindOf:&amp;lt;/CODE&amp;gt; protocols.&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Notice that for a single element union type (eg. &amp;quot;&amp;lt;code&amp;gt;( String )&amp;lt;/code&amp;gt;&amp;quot;) the interpretation was ambiguous in previous expecco versions, as it could also be interpreted as a tuple with a single String element. Therefore, the syntax for tuple types was changed to use square brackets, but still supporting the previous regular parentheses syntax. There is no ambiguity when more than one element is present; however, for single element types, the datatype parser will (currently) read this as a single-type union type.&lt;br /&gt;
&lt;br /&gt;
To avoid this ambiguity, the old parenthesis-syntax should no longer be used for tuples (prefixing with &#039;union&#039; also solves this).&lt;br /&gt;
&lt;br /&gt;
=== Additional Special Types ===&lt;br /&gt;
&lt;br /&gt;
==== Datatype Type ====&lt;br /&gt;
Instances are datatypes known to the project. Datatype-types are typically used as input pin type of collection-instantiation blocks.&lt;br /&gt;
As a freeze value, the list of known types is presented in a combolist.&lt;br /&gt;
In a textual definition, the keyword &amp;quot;&amp;lt;code&amp;gt;datatype&amp;lt;/code&amp;gt;&amp;quot; is used:&lt;br /&gt;
 datatype&lt;br /&gt;
&lt;br /&gt;
==== Constraint Datatype Type ====&lt;br /&gt;
A datatype type can be constraint to a subset of types, by defining it as:&lt;br /&gt;
 datatype ( &amp;lt;constraint&amp;gt; )&lt;br /&gt;
where &amp;lt;constraint&amp;gt; is either the name of another type:&lt;br /&gt;
* &amp;lt;compatTypeName&amp;gt; - constraint to types which are compatible with a type named &amp;lt;compatTypeName&amp;gt;&lt;br /&gt;
or a selector from one of:&lt;br /&gt;
* &amp;lt;code&amp;gt;isArrayType&amp;lt;/code&amp;gt; - for types which have integer-indexable slots&lt;br /&gt;
* &amp;lt;code&amp;gt;isCTypeType&amp;lt;/code&amp;gt; - for C-defined types&lt;br /&gt;
* &amp;lt;code&amp;gt;isCEnumType&amp;lt;/code&amp;gt; - for C enum types&lt;br /&gt;
* &amp;lt;code&amp;gt;isCStructType&amp;lt;/code&amp;gt; - for C-defined struct types&lt;br /&gt;
* &amp;lt;code&amp;gt;isCUnionType&amp;lt;/code&amp;gt; - for C-defined union types&lt;br /&gt;
* &amp;lt;code&amp;gt;isCollectionPrimaryType&amp;lt;/code&amp;gt; - for subtypes of Collection (i.e. Dictionary, Set, OrderedCollection etc.)&lt;br /&gt;
* &amp;lt;code&amp;gt;isCompoundType&amp;lt;/code&amp;gt; - for compound types&lt;br /&gt;
* &amp;lt;code&amp;gt;isEnumType&amp;lt;/code&amp;gt; - for enum types&lt;br /&gt;
* &amp;lt;code&amp;gt;isNumberPrimaryType&amp;lt;/code&amp;gt; - for subtypes of Number (i.e. Float, Integer, Fraction, FixedPoint)&lt;br /&gt;
* &amp;lt;code&amp;gt;isPrimaryType&amp;lt;/code&amp;gt; - for any primary type&lt;br /&gt;
* &amp;lt;code&amp;gt;isStreamPrimaryType&amp;lt;/code&amp;gt; - for subtypes of Stream&lt;br /&gt;
* &amp;lt;code&amp;gt;isTupleType&amp;lt;/code&amp;gt; - for any tuple type&lt;br /&gt;
* &amp;lt;code&amp;gt;isUnionType&amp;lt;/code&amp;gt; - for any union type&lt;br /&gt;
* &amp;lt;code&amp;gt;isUserDefinedDatatype&amp;lt;/code&amp;gt; - for all user defined types (i.e. those in the current suite)&lt;br /&gt;
* &amp;lt;code&amp;gt;isWellKnownDatatype&amp;lt;/code&amp;gt; - for all builtin (i.e. not user defined) types. These types will always be present, whereas user defined types are those defined in the current suite&lt;br /&gt;
&lt;br /&gt;
or a selector plus string argument from one of:&lt;br /&gt;
* &amp;lt;code&amp;gt;nameMatches:&amp;lt;/code&amp;gt; &#039;&#039;globPattern&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;nameMatchesRegex:&amp;lt;/code&amp;gt; &#039;&#039;regexPattern&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Constrained datatypes should be used by the StandardLibraries only, and are used to limit the input values of some instance creation actions.&lt;br /&gt;
For example, the &amp;quot;New Collection&amp;quot; action has an input pin, which defines the type of collection to be created. &lt;br /&gt;
This pin has the type: &amp;quot;&amp;lt;code&amp;gt;datatype( isCollectionPrimaryType )&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 datatype ( Integer ) -- a type whose instances are all datatypes which are compatible with the Integer class&lt;br /&gt;
 datatype ( isCTypeType ) -- a type whose instances are all known C-types&lt;br /&gt;
 datatype ( isCStructType ) -- a type representing all known C struct types&lt;br /&gt;
 datatype ( nameMatches: &#039;DPU*&#039; ) -- a type representing all types which match this name&lt;br /&gt;
&lt;br /&gt;
Notice that the freeze value of a datatype-typed pin (and also values flowing in and out of such pins) are data types; not values (although datatypes are also objects/values in the technical sense).&lt;br /&gt;
&lt;br /&gt;
==== Monitor Types ====&lt;br /&gt;
A monitor is a special builtin object which observes an object and sends out change notifications to interested stakeholders when it changes its contents. Monitors are used to allow external QA systems (such as expecco ALM) to monitor and display changing expecco variables in real time.&lt;br /&gt;
&lt;br /&gt;
==== Resource, Skill, Library and ActivityLog Types ====&lt;br /&gt;
Represent instances of resources and skills. These are builtin types used by expecco itself.&lt;br /&gt;
&lt;br /&gt;
==== Port Types ====&lt;br /&gt;
These are not yet used but present for future TTCN3 support.&lt;br /&gt;
&lt;br /&gt;
==Type Popup-Menu Organisation==&lt;br /&gt;
In addition to the definition of the type, the editor provides control on&lt;br /&gt;
where and how the type will be presented in type popup menus and pull down lists.&lt;br /&gt;
===Group===&lt;br /&gt;
If you attach a group name to the type, it will be grouped into a such-named submenu below a pin&#039;s or variable&#039;s datatype popup menu.&lt;br /&gt;
&lt;br /&gt;
===Enum Freeze-Value Menu Organisation===&lt;br /&gt;
When freezing an enum-typed pin or choosing an enum variable&#039;s default value,&lt;br /&gt;
by default the elements are presented in one list. This list may get long and you may want to organize them into a hierarchical set of submenus and/or control how they are sorted.&lt;br /&gt;
&lt;br /&gt;
For example, if the enum elements represent commands to a controller, they might be named after commands, like &amp;quot;power_on&amp;quot;, &amp;quot;power_off&amp;quot;, &amp;quot;power_low&amp;quot;, &amp;quot;turn_left&amp;quot;, &amp;quot;turn_right&amp;quot; etc.&lt;br /&gt;
&amp;lt;br&amp;gt;In this case, you may want to organize the freeze menu into two submenus, one for all &amp;quot;power_XXX&amp;quot; values, another for all &amp;quot;turn_XXX&amp;quot;values etc.&lt;br /&gt;
&lt;br /&gt;
The editor&#039;s &amp;quot;&#039;&#039;Freeze Menu Organization&#039;&#039;&amp;quot; at the lower right gives you a number of options to organize your menus and how to sort the elements. Use that, if you have more than (say) 10 or 15 elements in an enum. Click on the &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; button to see how the menu will be shown later.&lt;br /&gt;
=====Sort Order=====&lt;br /&gt;
By default, elements will be presented in the order of the type definition.&lt;br /&gt;
&amp;lt;br&amp;gt;The choices are:&lt;br /&gt;
* normal - use the default sort order&lt;br /&gt;
* sortAlphabetical - sort by name&lt;br /&gt;
* sortNatural - numeric suffixes are sorted by value (i.e. &#039;a10&#039; comes after &#039;a2&#039;)&lt;br /&gt;
* sortByValue - sort by the associated value; not the symbolic name&lt;br /&gt;
=====Hierarchical Menu=====&lt;br /&gt;
The other options control where the symbolic names are split and grouped into submenus.&lt;br /&gt;
&lt;br /&gt;
==Type Representation (Syntax)==&lt;br /&gt;
&lt;br /&gt;
Various textual representations are possible; some are already built into the base expecco system, others are addons and present if certain plugins are installed.&lt;br /&gt;
&lt;br /&gt;
=== Formal BNF Description of the Expecco Type Syntax ===&lt;br /&gt;
&lt;br /&gt;
Expecco provides its own native type-description language, with an easy to understand and use syntax:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 type ::= &amp;lt;nonArrayType&amp;gt; | &amp;lt;arrayType&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 arrayType ::= &amp;lt;nonArrayType&amp;gt; &#039;[&#039; &#039;]&#039;&lt;br /&gt;
 &lt;br /&gt;
 nonArrayType ::= &amp;lt;tupleType&amp;gt; | &amp;lt;unionType&amp;gt; | &amp;lt;compoundType&amp;gt; &lt;br /&gt;
                              | &amp;lt;enumType&amp;gt; | &amp;lt;rangeType&amp;gt; | &amp;lt;patternType&amp;gt;  &lt;br /&gt;
                              | &amp;lt;primaryType&amp;gt; | &amp;lt;simpleType&amp;gt; | &amp;lt;specialType&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 tupleType ::= &#039;[&#039; &amp;lt;elementType1&amp;gt; [&#039;,&#039;] &amp;lt;elementType2&amp;gt; .. &amp;lt;elementTypeN&amp;gt; &#039;]&#039;&lt;br /&gt;
 elementType ::= &amp;lt;type&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 unionType ::= &#039;(&#039; &amp;lt;alternativeType1&amp;gt; &#039;|&#039; &amp;lt;alternativeType2 &amp;gt; &#039;|&#039; .. &amp;lt;alternativeTypeN&amp;gt; &#039;)&#039;&lt;br /&gt;
 alternativeType ::= &amp;lt;type&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 enumType ::= &#039;enum&#039; &#039;(&#039; &amp;lt;enumValue1&amp;gt; &#039;|&#039; &amp;lt;enumValue2&amp;gt; &#039;|&#039; ... &amp;lt;enumValueN&amp;gt; &#039;)&#039;&lt;br /&gt;
 enumValue ::= ( &amp;lt;identifier&amp;gt; | &amp;lt;quoted-string&amp;gt; | &amp;lt;dquoted-string&amp;gt; ) [ &#039;=&#039; &amp;lt;integer-constant&amp;gt; ]&lt;br /&gt;
 &lt;br /&gt;
 rangeType ::= &#039;range&#039; &#039;(&#039; &amp;lt;baseType&amp;gt; &#039;:&#039; &amp;lt;minValue&amp;gt; &#039;..&#039; &amp;lt;maxValue&amp;gt; &#039;)&#039;&lt;br /&gt;
 minValue ::= &amp;lt;constant&amp;gt;&lt;br /&gt;
 maxValue ::= &amp;lt;constant&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 subsetType ::= &#039;subset&#039; &#039;(&#039; &amp;lt;baseType&amp;gt; &#039;:&#039; &amp;lt;range1&amp;gt; [&#039;,&#039; &amp;lt;range2&amp;gt;]... &#039;)&#039;&lt;br /&gt;
 range ::= &amp;lt;minValue&amp;gt; &#039;..&#039; &amp;lt;maxValue&amp;gt; | &amp;lt;constant&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 patternType ::= &#039;String&#039; &#039;(&#039; &amp;lt;patternConstraint&amp;gt; [ &#039;,&#039; &amp;lt;patternConstraint&amp;gt; ]... &#039;)&#039;&lt;br /&gt;
 patternConstraint ::= &#039;match:&#039; &amp;lt;stringConstant&amp;gt;&lt;br /&gt;
                       | &#039;regex:&#039; &amp;lt;stringConstant&amp;gt;&lt;br /&gt;
                       | &#039;minLength:&#039; &amp;lt;integerConstant&amp;gt;&lt;br /&gt;
                       | &#039;maxLength:&#039; &amp;lt;stringConstant&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 compoundType ::= &#039;{&#039; &amp;lt;fieldSpec1&amp;gt; &amp;lt;fieldSpec2&amp;gt; ... &amp;lt;fieldSpecN&amp;gt; &#039;}&#039;&lt;br /&gt;
 &lt;br /&gt;
 fieldSpec ::= &amp;lt;fieldIdentifier&amp;gt; &#039;:&#039; &amp;lt;fieldType&amp;gt; [ &#039;=&#039; &amp;lt;defaultValue&amp;gt; ] [&#039;;&#039;]&lt;br /&gt;
 fieldType ::= &amp;lt;type&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 primaryType ::= &#039;&amp;lt;&#039; &amp;lt;BuiltIn-Classname&amp;gt; &#039;&amp;gt;&#039;&lt;br /&gt;
 BuiltIn-Classname ::= &amp;lt;identifier&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 simpleType ::= &amp;lt;anyType&amp;gt; | &amp;lt;templateType&amp;gt; | &amp;lt;constraintTemplateType&amp;gt; | &amp;lt;namedType&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 anyType ::= &#039;*&#039;&lt;br /&gt;
 &lt;br /&gt;
 templateType ::= &#039;#&#039; &amp;lt;templateIdentifier&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
 constraintTemplateType ::= &#039;#&#039; &amp;lt;templateIdentifier&amp;gt; &amp;lt;setOfConstraintTypes&amp;gt;&lt;br /&gt;
 setOfConstraintTypes ::= &amp;lt;unionType&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;namedType&amp;gt; ::= &#039;any&#039; | &#039;struct&#039; | &amp;lt;typeName_in_project&amp;gt; | &amp;lt;Smalltalk-Classname&amp;gt;&lt;br /&gt;
 typeName_in_project ::= &amp;lt;identifier&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 specialType ::= &amp;lt;monitorType&amp;gt; | &amp;lt;portType&amp;gt; | &amp;lt;datatypeType&amp;gt; | &amp;lt;performerType&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 monitorType ::= &#039;monitor&#039; &#039;(&#039; &amp;lt;baseType&amp;gt;&#039;)&#039;&lt;br /&gt;
 &lt;br /&gt;
 portType ::= &#039;port&#039; &#039;(&#039; &amp;lt;baseType&amp;gt;&#039;)&#039;&lt;br /&gt;
 &lt;br /&gt;
 datatypeType ::= &#039;datatype&#039; [ &#039;(&#039; &amp;lt;constraint&amp;gt; &#039;)&#039; ]&lt;br /&gt;
 &lt;br /&gt;
 constraint ::= &amp;lt;primaryTypeName&amp;gt; |&lt;br /&gt;
                &#039;isUserDefinedType&#039; | &#039;isWellKnownType&#039; | &lt;br /&gt;
                &#039;isPrimaryType&#039; | &lt;br /&gt;
                &#039;isNumberPrimaryType&#039; | &#039;isCollectionPrimaryType&#039; | &#039;isStreamPrimaryType&#039;&lt;br /&gt;
                &#039;isArrayType&#039; | &#039;isCTypeType&#039;&lt;br /&gt;
                &#039;isCompoundType&#039; | &#039;isEnumType&#039; | &#039;isTupleType&#039; | &#039;isUnionType&#039;&lt;br /&gt;
 &lt;br /&gt;
 performerType ::= &#039;performer&#039; [ &#039;(&#039; interfaceSpec &#039;)&#039; ]&lt;br /&gt;
 &lt;br /&gt;
 interfaceSpec ::= &amp;lt;identifier&amp;gt; |&lt;br /&gt;
                &#039;&amp;quot;&#039; id-string &#039;&amp;quot;&#039;&#039; |&lt;br /&gt;
                &#039;interface:&#039; uuid&lt;br /&gt;
&lt;br /&gt;
Notes:&amp;lt;br&amp;gt;&lt;br /&gt;
The separating commas in the tuple- and compound definitions are optional.&lt;br /&gt;
&amp;lt;br&amp;gt;This format is used if you select &amp;quot;Defined&amp;quot; type in the editor. It is also expected if you select &amp;quot;Define...&amp;quot; in one of the type menus (Pin-Type, Veriable-Type, Skill-Type).&lt;br /&gt;
Support for this representation is part of the base expecco system.&lt;br /&gt;
&lt;br /&gt;
===DTD Type Definition===&lt;br /&gt;
A DTD definition can also be used to specify a compound type. For this, choose &amp;quot;&#039;&#039;Compound (DTD-Defined)&#039;&#039;&amp;quot;, and paste the DTD into the text area.&lt;br /&gt;
Support for this representation is part of the base expecco system.&lt;br /&gt;
&lt;br /&gt;
===C Language Type Definition===&lt;br /&gt;
A C language code fragment can also be used to specify a compound or union type. For this, choose &amp;quot;&#039;&#039;CType (C-Defined)&#039;&#039;&amp;quot;, and paste the C type definition into the text area.&lt;br /&gt;
Instances of this type are especially useful when calling external DLL functions.&lt;br /&gt;
Support for this representation is part of the base expecco system.&lt;br /&gt;
&lt;br /&gt;
A typical C language definition looks like:&lt;br /&gt;
 /* C: */&lt;br /&gt;
 struct {&lt;br /&gt;
     int i1;&lt;br /&gt;
     float f1;&lt;br /&gt;
     double d1;&lt;br /&gt;
     char c[20];&lt;br /&gt;
 };&lt;br /&gt;
Notice, that the definition must begin with a &amp;quot;/* C: */&amp;quot; comment.&lt;br /&gt;
&lt;br /&gt;
For more details, please refer to the [[ Datatype_Element/en#CTypes | Datatype - CTypes document ]].&lt;br /&gt;
&lt;br /&gt;
===Enum Type Definition from C-define Directives===&lt;br /&gt;
An enum type can also be defined from a list of C-#define directives. These can be conveniently copy-pasted from a C-header file.&lt;br /&gt;
For this, choose &amp;quot;&#039;&#039;Enum (from C-defines)&#039;&#039;&amp;quot;, and paste the defines into the text area.&lt;br /&gt;
Support for this representation is part of the base expecco system.&lt;br /&gt;
&lt;br /&gt;
As an example, the following list of C-defines:&lt;br /&gt;
&lt;br /&gt;
 #define STATUS_OK 0&lt;br /&gt;
 #define STATUS_ERR_CONNECT 1&lt;br /&gt;
 #define STATUS_ERR_BROKEN 2&lt;br /&gt;
&lt;br /&gt;
will generate the following enum type:&lt;br /&gt;
&lt;br /&gt;
 enum(STATUS_OK=0 , STATUS_ERR_CONNECT, STATUS_ERR_BROKEN)&lt;br /&gt;
&lt;br /&gt;
The define values can be decimal integers, hex integers (0xXXXX), octal integers (0XXX) or binary integers (0bXXXX).&lt;br /&gt;
&lt;br /&gt;
===XSD Type Definition===&lt;br /&gt;
A definition in XSD-XML. An XSD definition can also be used to specify a type. &lt;br /&gt;
&lt;br /&gt;
This is an extension provided by a plugin. Please read the corresponding plugin documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;usage: to be documented&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===COBOL Copybook Definition===&lt;br /&gt;
Parses a COBOL Copybook type-definition.&lt;br /&gt;
&lt;br /&gt;
This is only available as plugin. &lt;br /&gt;
Please read the corresponding plugin documentation for details.&lt;br /&gt;
&lt;br /&gt;
===ASN.1 Type Definiton===&lt;br /&gt;
Parses an ASN.1 type-definition.&lt;br /&gt;
&lt;br /&gt;
This is only available as plugin. Please read the corresponding plugin documentation for details.&lt;br /&gt;
&lt;br /&gt;
===Sun RPC IDL Type Definiton===&lt;br /&gt;
Parses a Sun RPC type-definition, which is used for example in the NFS file-system or in VISA lab equipment interfaces.&lt;br /&gt;
This is only available as plugin. Please read the corresponding plugin documentation for details.&lt;br /&gt;
&lt;br /&gt;
===Microsoft COM/DCOM-IDL Type Definition===&lt;br /&gt;
Parses a COM/DCOM IDL type-definition.&lt;br /&gt;
This is only available as plugin. Please read the corresponding plugin documentation for details.&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
[[Datatype Element/en|Datatype Element]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- {{Languages}} --&amp;gt;&lt;br /&gt;
[[Category:Editors]] with more detail on primitive types and C-data types&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30870</id>
		<title>Release Notes 25.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30870"/>
		<updated>2025-10-23T14:43:19Z</updated>

		<summary type="html">&lt;p&gt;Sv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 24.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 25.2 ==&lt;br /&gt;
*Improvement: Inspector shows XML Dom if it starts with &#039;&amp;lt;&#039; and ends with &#039;&amp;gt;&#039; and is parsable without error.&lt;br /&gt;
*Improvement: Handles very long index-lists (eg. 100k) more graceful&lt;br /&gt;
*Improvement: Bundled python3 installer updated to version 3.13.7&lt;br /&gt;
*Feature: Qt-Plugin supports Qt6.8 ([[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Delivered versions for QT and build environment]])&lt;br /&gt;
*Feature: groovy version 5.0.0 (needed for Java 25 and later)&lt;br /&gt;
&lt;br /&gt;
== Release 25.1 ==&lt;br /&gt;
*Improvement: additional &amp;quot;Info&amp;quot; tab in inspector views&lt;br /&gt;
*Improvement: less memory usage in the activity log&lt;br /&gt;
*Improvement: better error messages and more links to settings from the activity log&#039;s error message&lt;br /&gt;
*Improvement: additional units and conversions in the [[PhysicalValues/en|physical values framework]]&lt;br /&gt;
*Improvement: more precision in the [[Numeric_Limits/en#Higher_Precision_Numbers|high precision trigonometric and math functions]]&lt;br /&gt;
*Improvement: WindowsAutomation: Plugin Update to FlaUI 5&lt;br /&gt;
*Improvement: Mobile Testing: Better Device Lock/Unlock Support&lt;br /&gt;
*Improvement: StandardLibrary: &amp;quot;File [ *CSV ]&amp;quot; blocks got an additional &amp;quot;characterEncoding&amp;quot; pin (useful for reading/writing e.g. utf-8 encoded CSV files)&lt;br /&gt;
*Improvement: ExcelLib: better documentation. Now requires the openpyxl package version &amp;gt;= 3.1.5. &lt;br /&gt;
*Improvement: better model language editor (translate and fetch-strings functions)&lt;br /&gt;
*Improvement: ODBCLibrary: improved compatibility with different database vendors (supports the CedarDB database) &lt;br /&gt;
*Feature: translate and spell check in the workspace window&lt;br /&gt;
*Feature: EditLock of suites loaded from expeccoALM / AIDYMO&lt;br /&gt;
*Feature: Start Test in expeccoALM / AIDYMO (via expecco)&lt;br /&gt;
*Feature: new library containing expeccoALM control actions (those from the AIDYMO menu)&lt;br /&gt;
*Fix: the version diff viewer (did not correctly copy changed attachment files)&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Installing_additional_Frameworks/en&amp;diff=30843</id>
		<title>Installing additional Frameworks/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Installing_additional_Frameworks/en&amp;diff=30843"/>
		<updated>2025-09-12T14:20:03Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Iron Python Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
If you intent to execute actions written for Java, Node, Python, .NET, C etc.,&lt;br /&gt;
or to test Java-, Windows- or mobile applications, additional frameworks have to be installed on your machine.&lt;br /&gt;
&lt;br /&gt;
Mostly for legal reasons, but also because you will probably want to install a most up-to-date version, we do not bundle those with the expecco installation (except for a python setup, as noted below).&lt;br /&gt;
&lt;br /&gt;
Please make sure that any required framework is installed, and the commands are found by expecco. &lt;br /&gt;
&lt;br /&gt;
If they are already installed, but expecco fails to execute one of them, take a look at the PATH setting and/or the expecco &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; settings. There, click on buttons labeled &amp;quot;?&amp;quot; to verify the installed version(s). &lt;br /&gt;
&lt;br /&gt;
However, the recommendend setup is to only specify the command name in the settings, and ensure that the PATH variable is set correctly, to let expecco find the command via the PATH. &lt;br /&gt;
&amp;lt;br&amp;gt;The PATH should be set in your &amp;quot;.login&amp;quot; (Unix) or &amp;quot;autoexec.bat&amp;quot; (Windows) file accordingly.&lt;br /&gt;
&lt;br /&gt;
== Required Frameworks Overview ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Feature !! Required Framework(s)&lt;br /&gt;
|-&lt;br /&gt;
| Java/Groovy Actions || JRE (Java Runtime Environment)&amp;lt;br&amp;gt;or: JDK (recommended)&lt;br /&gt;
|-&lt;br /&gt;
| NodeJS Actions || node&lt;br /&gt;
|-&lt;br /&gt;
| Python Actions || Python3.x (recommended)&amp;lt;br&amp;gt;or: Python2.x (for older Python code)&lt;br /&gt;
|-&lt;br /&gt;
| Jython Actions || Java JRE (Java Runtime Environment) or JDK and Jython&lt;br /&gt;
|-&lt;br /&gt;
| Iron Python Actions || .NET CLR&amp;lt;br&amp;gt;or: Mono (on non-Windows systems)&lt;br /&gt;
|-&lt;br /&gt;
| Ruby Actions || ruby&lt;br /&gt;
|-&lt;br /&gt;
| Java GUI Automation || JRE (Java Runtime Environment)&amp;lt;br&amp;gt;or: JDK (recommended)&lt;br /&gt;
|-&lt;br /&gt;
| Windows GUI Automation || .NET CLR&lt;br /&gt;
|-&lt;br /&gt;
| WebTest (Selenium Webdriver) || JRE (Java Runtime Environment)&amp;lt;br&amp;gt;webDrivers matching your web-browser version&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Test (Appium) || JRE (Java Runtime Environment)&lt;br /&gt;
|-&lt;br /&gt;
| Bridged C Actions || C compiler toolchain (GCC, Clang, VisualC, Mingw or Borland)&lt;br /&gt;
|-&lt;br /&gt;
| Octave (Matlab scripts) || GNU Octave or a real Matlab&lt;br /&gt;
|-&lt;br /&gt;
| OCR (VNC, Screen Automation) || Tesseract&amp;lt;br&amp;gt;language specific tessdata files&lt;br /&gt;
|-&lt;br /&gt;
| Vector/Canoe Plugin || .NET CLR&lt;br /&gt;
|-&lt;br /&gt;
| OPC Library || Python3 + opcua package&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Java_Installation&amp;quot;&amp;gt;Java Installation&amp;lt;/div&amp;gt; (for Groovy Actions, Web- and Mobile Testing) ==&lt;br /&gt;
You can either install a plain Java Runtime Environment (JRE) or a full Java Development Kit (JDK). If only a JRE is installed, some functions will not work,&lt;br /&gt;
and we therefore recommend a JDK to be installed - typically at its standard location, &amp;quot;&amp;lt;CODE&amp;gt;C:\Program Files\Java\jdk-xxx&amp;lt;/CODE&amp;gt;&amp;quot; (Windows), so it will run out of the box.&lt;br /&gt;
Expecco will try to figure out if and where Java was installed, but it it also possible to specify explicit pathes via the settings dialog.&lt;br /&gt;
&lt;br /&gt;
Notice, that due to changed regulations by Oracle (i.e. legal restrictions), we may no longer provide a Java installation bundled with expecco;&lt;br /&gt;
you should navigate to the Oracle (or OpenJDK) website and install it from there.&lt;br /&gt;
&lt;br /&gt;
Also notice, that on most systems, a Java is already installed, but it may be a runtime environment only.&lt;br /&gt;
Please verify, that a JDK is installed for the full set of features.&lt;br /&gt;
&lt;br /&gt;
The expecco installation does include some required jar files (eg. groovy.jar, selenium jars and drivers etc.), but you may want to verify that they are the most up-to-date versions. &lt;br /&gt;
&lt;br /&gt;
==== Selenium WebDriver ====&lt;br /&gt;
Especially the Selenium drivers (which are used to remote-control a Webbrowser when testing or automating graphical user interfaces in a browser) depend on the concrete browser version (i.e. Chrome version, Firefox version, etc.). Older drivers do not always work with a newer browser. &lt;br /&gt;
&lt;br /&gt;
The deployed installation package includes a number of drivers for versions which were in use at that time, but especially due to automatic updates, these may be outdated on your machine. Please follow the instructions given by expecco and/or read [[Selenium_WebDriver_Plugin/en#Update_WebDriver|&amp;quot;Update WebDriver&amp;quot;]] when it encounters a problem.&lt;br /&gt;
&amp;lt;br&amp;gt;The GUIBrowser&#039;s connect dialog will check for version compatibility and offer an update function if required.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;DOTNET_Installation&amp;quot;&amp;gt;.NET Installation&amp;lt;/div&amp;gt; (for the .NET bridge, Windows Apps, IronPython Actions and some Plugins &amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
On Windows, a .NET framework is usually already installed.&lt;br /&gt;
&amp;lt;br&amp;gt;On Unix/Linux systems, you can install &amp;quot;Mono&amp;quot;, which may provide enough functionality for your needs.&lt;br /&gt;
&amp;lt;br&amp;gt;Be aware, that some functions - especially GUI functions - may not be present or may not work perfectly (if at all) under Mono.&lt;br /&gt;
&lt;br /&gt;
Mono can be downloaded from [https://www.mono-project.com/download/stable/ the Mono project web site].&lt;br /&gt;
&lt;br /&gt;
1) for example, the Vector/Canoe plugin requires .NET (among others).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Node_Installation&amp;quot;&amp;gt;Node Installation&amp;lt;/div&amp;gt; (for Node.js Actions) ==&lt;br /&gt;
&lt;br /&gt;
Goto [ https://nodejs.org/en ] or [ https://nodejs.org/de/download/ ] and select the appropriate package for your machine.&lt;br /&gt;
When asked if additional packages are to be downloaded, answer &amp;quot;yes&amp;quot;. &lt;br /&gt;
(Under Windows, VisualStudio build tools will then also be installed, in case any node module needs to be compiled from C/C++ code).&lt;br /&gt;
&lt;br /&gt;
Open the node interpreter settings (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Node&#039;&#039;&amp;quot;) and verify that the &amp;quot;node&amp;quot; command is found along your PATH variable settings by clicking on the &amp;quot;?&amp;quot;-button. If found, its version should be shown.&lt;br /&gt;
&lt;br /&gt;
If not found, either restart expecco (if you installed node while expecco was active), or enter the path to your node interpreter into the path field. You may even have to restart your cmd/shell session, in case the old shell environment does not contain the path to the new installed node.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Python_Installation&amp;quot;&amp;gt;Python Installation&amp;lt;/div&amp;gt; (for Python Actions) ==&lt;br /&gt;
&lt;br /&gt;
Expecco is delivered with an installation package for a relatively new Python version (currently Python 3.11.6 (expecco 23.2)), but of course, new versions are constantly released and the included Python might be outdated.&amp;lt;br&amp;gt;You can (and probably should) download other versions [ https://www.python.org/downloads/ ].&lt;br /&gt;
Notice, that there are both packages for python3.x and python2.7 available, and you may have to install both, depending on the Python code to be executed later (although python2 is more and more becoming obsolete, there may still be frameworks for that old version to be found and used).&lt;br /&gt;
&lt;br /&gt;
You can start by installing a Python3.x version only. &lt;br /&gt;
By the time of writing this document, the most recent Python version is 3.12, but expecco is known to work with older versions.&lt;br /&gt;
Be aware, that there are syntactic differences between Python2.x and Python3.x; for example &amp;quot;print ...&amp;quot; is a statement in 2.x whereas &amp;quot;print(...)&amp;quot; is a function call in 3.x.&lt;br /&gt;
&lt;br /&gt;
Open the Python interpreter settings (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot;) and verify that the &amp;quot;python&amp;quot; command is found along your PATH variable settings (click on &amp;quot;?&amp;quot;). &lt;br /&gt;
&lt;br /&gt;
[[Bild:PythonSettings.png|700px|PythonSettings]]&lt;br /&gt;
&lt;br /&gt;
=== Python Commands ===&lt;br /&gt;
&lt;br /&gt;
Notice, that there are 3 command fields, which can be set:&lt;br /&gt;
* Python Cmd Path&lt;br /&gt;
:is used if no explicit version is specified in a python action&lt;br /&gt;
* Python3 Cmd Path&lt;br /&gt;
:is used if the python action explicitly asks for python3&lt;br /&gt;
* Python2 Cmd Path&lt;br /&gt;
:is used if the python action explicitly asks for python2&lt;br /&gt;
&lt;br /&gt;
Be aware and reminded, that these are different python interpreter instances: you cannot run both Python2 and Python3 code within the same python interpreter instance.&lt;br /&gt;
&lt;br /&gt;
If not found, either restart expecco (if you installed Python while expecco was active), or enter the full path to your Python interpreter into the path field.&lt;br /&gt;
&lt;br /&gt;
Make sure that the correct Python version is displayed (2.x vs. 3.x) when you click on the &amp;quot;?&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
==== Default cmd paths ====&lt;br /&gt;
&lt;br /&gt;
If no command is specified for one of the Python versions, expecco determines a default path, which is displayed in gray in the corresponding cmd path field.&lt;br /&gt;
&lt;br /&gt;
The following sequence is used until a set cmd path is found:&lt;br /&gt;
&lt;br /&gt;
*Python-Cmd is empty:&lt;br /&gt;
: &#039;&#039;Python3-Cmd-Path&#039;&#039; → &#039;&#039;Python2-Cmd-Path&#039;&#039; → &#039;&#039;Windows registry entry for Python3&#039;&#039; → &#039;&#039;Windows registry entry for Python2&#039;&#039; → &amp;quot;&#039;&#039;python&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Python3-Cmd is empty:&lt;br /&gt;
: &#039;&#039;Python-Cmd-Path&#039;&#039; → &#039;&#039;Windows registry entry for Python3&#039;&#039; → &amp;quot;&#039;&#039;python3&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Python2-Cmd is empty:&lt;br /&gt;
: &#039;&#039; Python cmd path&#039;&#039; → &#039;&#039;Windows registry entry for Python2&#039;&#039; → &amp;quot;&#039;&#039;python2&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can display the effective Python version by clicking on the &amp;quot;?&amp;quot;-button.&lt;br /&gt;
&lt;br /&gt;
=== Debugging python code ===&lt;br /&gt;
&lt;br /&gt;
==== Debugging in expecco ====&lt;br /&gt;
To make your life easier, install a Python debugger; either:&lt;br /&gt;
 pip install debugpy&lt;br /&gt;
or&lt;br /&gt;
 pip install ptvsd&lt;br /&gt;
(they are more or less interchangeable, but &amp;quot;&amp;lt;code&amp;gt;ptvsd&amp;lt;/code&amp;gt;&amp;quot; is outdated (no longer maintained) and replaced by the newer &amp;quot;&amp;lt;code&amp;gt;debugpy&amp;lt;/code&amp;gt;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Without a Python debugger, breakpoints cannot be placed in bridged Python code,&lt;br /&gt;
and you will not get a debugger on Python exceptions&lt;br /&gt;
(you should then see a warning and hint to install &amp;quot;debugpy&amp;quot; on the Transcript and in the info area).&lt;br /&gt;
&lt;br /&gt;
To ensure that the breakpoints are observed, please uncheck the &amp;quot;Disable debugger&amp;quot; checkbox.&lt;br /&gt;
&lt;br /&gt;
=====Problems with debugging=====&lt;br /&gt;
&lt;br /&gt;
======Debugger does not start======&lt;br /&gt;
&lt;br /&gt;
If the path for Python is specified with the variables &amp;quot;&#039;&#039;%ProgramFiles%&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;%ProgramFiles(x86)%&#039;&#039;&amp;quot;, debugpy does not start.&lt;br /&gt;
&lt;br /&gt;
 Python: failed to enable PythonDebugger on port ..: [WinError 2] the system cannot find the file specified.&lt;br /&gt;
&lt;br /&gt;
The remedy is to use the specific path such as &amp;quot;&#039;&#039;C:\Program Files&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;C:\Program Files (x86)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
======Warnings in output======&lt;br /&gt;
&lt;br /&gt;
 Debugger warning: It seems that frozen modules are being used, which may &lt;br /&gt;
 make the debugger miss breakpoints. Please pass -Xfrozen_modules=off&lt;br /&gt;
 to python to disable frozen modules.&lt;br /&gt;
 Note: Debugging will proceed. Set PYDEVD_DISABLE_FILE_VALIDATION=1 to disable this validation.&lt;br /&gt;
&lt;br /&gt;
In Python 3.11, the core modules essential for Python startup are “frozen”. ... &lt;br /&gt;
This reduces the steps in module execution process. Interpreter startup is now 10-15% faster &lt;br /&gt;
in Python 3.11. This has a big impact for short-running programs using Python.&lt;br /&gt;
&lt;br /&gt;
It&#039;s not possible for the debugger to debug frozen modules as the filename is definitely required to hit breakpoints.&lt;br /&gt;
&lt;br /&gt;
To deactivate the warning, set the environment variable PYDEVD_DISABLE_FILE_VALIDATION to 1, as described in the warning. Notice that the bridge needs to be restarted for the environment variable change to be effective (and possibly even expecco, unless you have specified that variable in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Environment Variables&#039;&#039;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
==== Debugging in an external IDE ====&lt;br /&gt;
For more in depth debugging, you can run the Python bridge in an external IDE (like PyCharm) and use the debug features of the IDE.&lt;br /&gt;
&lt;br /&gt;
For this, you should save the Python bridge code to a file or copy it to the clipboard using the &amp;quot;&#039;&#039;Copy / Save Bridge Code...&#039;&#039;&amp;quot; button. &lt;br /&gt;
Then open this python file in the IDE, and start in debug mode. &lt;br /&gt;
&lt;br /&gt;
The Expecco Python blocks are called in the line:&lt;br /&gt;
 result = actionFn(actionArgs, actionOutPins)&lt;br /&gt;
&lt;br /&gt;
You can then step into the block code with a breakpoint at these lines.&lt;br /&gt;
&lt;br /&gt;
In order for Expecco to connect to this Python bridge (instead of starting a new one), &lt;br /&gt;
you must first tick the checkbox &amp;quot;&#039;&#039;Connect to already running bridge&#039;&#039;&amp;quot; and terminate any previously running Python bridges (via &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Shutdown all Bridge Connections&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
=== pip2 vs. pip3 vs. pip ===&lt;br /&gt;
To install Python packages, use the &amp;quot;&amp;lt;Code&amp;gt;pip&amp;lt;/Code&amp;gt;&amp;quot; command. However, this command is usually a symbolic link to either &amp;quot;&amp;lt;Code&amp;gt;pip2&amp;lt;/Code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;Code&amp;gt;pip3&amp;lt;/Code&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
You should use &amp;quot;&amp;lt;Code&amp;gt;pip3&amp;lt;/Code&amp;gt;&amp;quot; to install packages for python3, and &amp;quot;&amp;lt;Code&amp;gt;pip2&amp;lt;/Code&amp;gt;&amp;quot; for python2. Thus, it is safer to use one of those or &amp;quot;&amp;lt;Code&amp;gt;python3 -m pip install ...&amp;lt;/Code&amp;gt;&amp;quot; instead of &amp;quot;&amp;lt;Code&amp;gt;pip install ...&amp;lt;/Code&amp;gt;&amp;quot; to ensure that the module is installed for the current version.&lt;br /&gt;
&lt;br /&gt;
On some systems, no pip2 command is present by default (and installing python3 will define the &amp;quot;&amp;lt;Code&amp;gt;pip&amp;lt;/Code&amp;gt;&amp;quot; command as an alias to &amp;quot;&amp;lt;Code&amp;gt;pip3&amp;lt;/Code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
To get &amp;quot;pip2&amp;quot; on those systems, execute (on the command line):&lt;br /&gt;
 wget https://bootstrap.pypa.io/get-pip.py&lt;br /&gt;
 python2.7 get-pip.py&lt;br /&gt;
&lt;br /&gt;
Things become even more confusing, if you have multiple python versions installed (for example, python3.7 and python3.9).&amp;lt;br&amp;gt;Then, it is best invoke pip via the python command itself, eg. with:&amp;lt;br&amp;gt;&amp;quot;&amp;lt;code&amp;gt;python3.7 -m pip install ...&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Getting pip ===&lt;br /&gt;
Some Python installers seem to not install pip (at least it happened to us once, that &amp;quot;pip&amp;quot; was not found after a python installation). &lt;br /&gt;
&amp;lt;br&amp;gt;If &amp;quot;python -m pip&amp;quot; gives a warning, do the following:&lt;br /&gt;
* download &amp;quot;https://bootstrap.pypa.io/get-pip.py&amp;quot; (use &amp;quot;Save As&amp;quot; in a web browser, and save it to the desktop)&lt;br /&gt;
* open a cmd/shell window in that folder.&lt;br /&gt;
* execute &amp;quot;python get-pip.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Jython Installation ==&lt;br /&gt;
Jython is a Python interpreter which runs inside a Java virtual machine, and thus has direct access to Java classes and objects.&amp;lt;br&amp;gt;&lt;br /&gt;
As a prerequisite, Java needs to be installed on your machine.&amp;lt;br&amp;gt;Then goto [ https://www.jython.org/download.html ], download the Jython installer and run it (choose &amp;quot;standard install&amp;quot; or &amp;quot;full install&amp;quot;).&lt;br /&gt;
&amp;lt;br&amp;gt;Remember the target directory. The jython command will be found there.&lt;br /&gt;
&amp;lt;br&amp;gt;If the &amp;quot;jython&amp;quot; command is not in your PATH, enter its full path in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Jython&#039;&#039;&amp;quot; settings dialog. &lt;br /&gt;
&amp;lt;br&amp;gt;However, it is usually better to add the path to your PATH variable (eg. as setup in the Windows environment settings, autoexec.bat or Unix&#039;s login.rc), and just give &amp;quot;jython&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;Notice that previous Jython versions were 2.x Pythons, which will sooner or later become outdated. It is recommended to download or upgrade to a 3.x version (if your code is 3.x compatible).&lt;br /&gt;
&lt;br /&gt;
== Iron Python Installation ==&lt;br /&gt;
IronPython is a Python interpreter which runs inside the Common Language Runtime system, and thus has direct access to C# classes (and of yourse all other objects which live inside the CLR world).&amp;lt;br&amp;gt;&lt;br /&gt;
As a prerequisite, you&#039;ll need a .NET CLR (common language runtime) or mono (on Unix systems). On Windows systems, a reasonable CLR Version is usually already installed.&lt;br /&gt;
&amp;lt;br&amp;gt;Then go to [ https://ironpython.net/download ] or [ https://github.com/IronLanguages/ironpython3 ] and follow the instructions.&lt;br /&gt;
&lt;br /&gt;
After the download, IronPython is typically installed in &amp;quot;&amp;lt;Code&amp;gt;C:\Program Files\IronPython 3.x&amp;lt;/Code&amp;gt;&amp;quot;, and you should enter the path &amp;quot;&amp;lt;Code&amp;gt;C:\Program Files\IronPython x.y\ipy.exe&amp;lt;/Code&amp;gt;&amp;quot; into the IronPython command path field in the python settings dialog (or simply &amp;quot;ipy&amp;quot;, if it is in your PATH).&lt;br /&gt;
&amp;lt;p&amp;gt;Notice that previous IronPython versions were 2.x Pythons, which became obsolete. It is therefore recommended to download or upgrade to a 3.x version (if your code is 3.x compatible).&lt;br /&gt;
&lt;br /&gt;
== Ruby Installation ==&lt;br /&gt;
Goto [ https://rubyinstaller.org/downloads ] and install ruby.&lt;br /&gt;
Then make sure that ruby is in your PATH setting or set the path to the command in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Ruby&#039;&#039;&amp;quot; settings. Typically it will look like &amp;quot;C:\Ruby32-x64\bin\ruby.exe&amp;quot; on  windows.&lt;br /&gt;
&amp;lt;br&amp;gt;Create a new Ruby action and execute it to see if it works.&lt;br /&gt;
&lt;br /&gt;
== Julia Installation ==&lt;br /&gt;
Goto [ https://julialang.org/downloads] and install.&lt;br /&gt;
Then make sure that julia is in your PATH setting or set the path to the command in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Other&#039;&#039;&amp;quot; settings. Typically it will look like &amp;quot;%LOCALAPPDATA%\Programs\Julia-1.10.4\bin\julia.exe&amp;quot; on  windows.&lt;br /&gt;
&amp;lt;br&amp;gt;Create a new Julia action and execute it to see if it works.&lt;br /&gt;
&lt;br /&gt;
== C Compiler Toolchain Installation (for C-Actions) ==&lt;br /&gt;
&lt;br /&gt;
For a quick verify if the setup is working, create a new (default) bridged C action and execute it (it should generate a &amp;quot;Hello World&amp;quot; message).&lt;br /&gt;
&lt;br /&gt;
==== C Compiler Toolchain Installation ====&lt;br /&gt;
&lt;br /&gt;
You need a C-compiler toolchain to be installed for C-coded actions.&lt;br /&gt;
* On Unix/Linux systems, these are usually already present on the machine (try &amp;quot;&amp;lt;Code&amp;gt;cc --version&amp;lt;/Code&amp;gt;&amp;quot; in a shell window; if you get a reasonable response, you are usually ready to go).&lt;br /&gt;
* On Windows, install one of &amp;quot;Borland&amp;quot;, &amp;quot;VisualC&amp;quot;, &amp;quot;VisualC Redistributable&amp;quot; or &amp;quot;MingGW&amp;quot;.&amp;lt;br&amp;gt;We recommend MingGW.&lt;br /&gt;
* On OSX, you have to install &amp;quot;XCode&amp;quot; or the &amp;quot;Command Line Tools&amp;quot; subset.&lt;br /&gt;
&lt;br /&gt;
===== Windows + Borland (32bit) =====&lt;br /&gt;
* get the free Borland command line tools (see https://borland-c.software.informer.com/5.5) and install them (typically, under &amp;quot;C:\borland\bcc55&amp;quot;)&lt;br /&gt;
* ensure that the link.cfg and bcc55.cfg files are present in the &amp;quot;C:\borland\bcc55\bin&amp;quot; directory.&lt;br /&gt;
* verify the installation by typing &amp;quot;bcc32&amp;quot;. A help message should appear.&lt;br /&gt;
* in the expecco settings, goto &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and select the appropriate CC-Script (&amp;quot;compile_windows_bcc.bat&amp;quot;), which tells the bridge how to compile the C-action code (more below).&lt;br /&gt;
 &lt;br /&gt;
===== Windows + Visual-C (32 or 64bit) =====&lt;br /&gt;
* similar to above, check for the &amp;quot;cl&amp;quot; command.&lt;br /&gt;
* in the expecco settings, goto &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and select the appropriate CC-Script (&amp;quot;compile_windows_vc32.bat&amp;quot;, &amp;quot;compile_windows_vc64.bat&amp;quot; or &amp;quot;compile_windows_vc64_redist.bat&amp;quot;); see below.&lt;br /&gt;
&lt;br /&gt;
===== Windows + Mingw (32 or 64bit) =====&lt;br /&gt;
* get the mingw64 compiler and install it (best is under &amp;quot;c:\mingw64&amp;quot; or &amp;quot;c:\program files\mingw64&amp;quot;).&lt;br /&gt;
* verify the installation by typing &amp;quot;gcc --help&amp;quot;.&lt;br /&gt;
* in the expecco settings, goto &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and select the appropriate CC-Script (&amp;quot;compile_windows_mingw32.bat&amp;quot; or &amp;quot;compile_windows_mingw64.bat&amp;quot;); see below.&lt;br /&gt;
&lt;br /&gt;
When a C-coded action is about to be executed, its C-code will be compiled &#039;&#039;just in time&#039;&#039; using that toolchain. For that, the cBridge executes a configurable batch or shell script.&amp;lt;br&amp;gt;For some commonly used toolchains, corresponding scripts are provided, but you can or may have to add your own script(s), in case you need special compile options, additional link library options or if you want to compile with a compiler not supported by the standard installation (eg. Intel compilers).&lt;br /&gt;
&lt;br /&gt;
If you get compilation errors, take a look at the &amp;quot;compile_xxx&amp;quot; scripts in &amp;quot;&amp;lt;code&amp;gt;packages/exept/expecco/bridgeFramework/cBridge/cLibrary&amp;lt;/code&amp;gt;&amp;quot; under the expecco installation folder.&lt;br /&gt;
&lt;br /&gt;
If required, add your own script to call whatever compiler you need, and select it in the cBridge settings dialog&lt;br /&gt;
(&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot;). You must also add your own script, if special compiler flags or additional standard pathes are to be setup.&lt;br /&gt;
&lt;br /&gt;
Notice, that we currently do not provide compilation scripts for C++; however, by declaring entry-functions (extern &amp;quot;C&amp;quot;) in your C++ code, these can be called from C.&lt;br /&gt;
&lt;br /&gt;
If no toolchain is installed, you can still see and edit C-code actions, but obviously not execute them.&lt;br /&gt;
&lt;br /&gt;
===== Windows + Mingw32 =====&lt;br /&gt;
Same as above; recommended installation directories are &amp;quot;c:\mingw32&amp;quot; or &amp;quot;c:\program files\mingw32&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== C Compiler Toolchain at Test-Execution Time ====&lt;br /&gt;
You can tell expecco to embed a pre-compiled object file into the saved &amp;quot;.ets&amp;quot; suite file (&amp;quot;&#039;&#039;Store Object Files in Project&#039;&#039;&amp;quot; checkbox in the CBridge settings dialog). If checked, C-Bridge actions will be compiled by your current session (using the configured toolchain) and the generated object file(s) will be saved with the suite. When the suite is later executed, no compiler toolchain will be needed on the test machine. Make sure that all required C actions are executed at least once. &lt;br /&gt;
&lt;br /&gt;
Expecco does not include cross compilation support; that means, that only object files for the current architecture can be generated. However, if you load the suite into another architecture&#039;s expecco, additional object files for that other architecture will be generated and added to the &amp;quot;.ets&amp;quot; when saved. So afterwards, object files for both architectures will be present in the ets.&lt;br /&gt;
&lt;br /&gt;
To summarize, if you want to deploy a library with embedded C-actions, which will have to be executed on (say) both a Linux and a Windows machine, where both test-execution machines have no compiler toolchain installed, perform the following steps:&lt;br /&gt;
# load the suite on a Linux machine (with C-compiler toolchain available)&lt;br /&gt;
# ensure that the &amp;quot;&#039;&#039;Store Object Files&#039;&#039;&amp;quot; flag is checked.&lt;br /&gt;
# Save the suite&lt;br /&gt;
# load the saved &amp;quot;.ets&amp;quot; on a Windows machine (with C-toolchain available)&lt;br /&gt;
# Save it again.&lt;br /&gt;
The last saved &amp;quot;.ets&amp;quot; will now contain object files for both architectures.&lt;br /&gt;
Be aware, that you may have to repeat the steps for 32 and 64 bit architectures, if the suite is to be executed eventually on both.&lt;br /&gt;
&lt;br /&gt;
Be reminded that this procedure is not needed, if the machine which executes the tests does have a C-toolchain installed. And especially, if it is the same as your development machine.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Cling_Installation&amp;quot;&amp;gt;Cling Installation&amp;lt;/div&amp;gt; (for RootCling Actions) ==&lt;br /&gt;
&lt;br /&gt;
Support for Cling is &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot; and currently considered an &amp;quot;&#039;&#039;experimental&#039;&#039;&amp;quot; feature which is not available/enabled in the current deployed version.&lt;br /&gt;
&lt;br /&gt;
Cling (aka &amp;quot;Root Cling&amp;quot;) is a dynamic language system for C/C++.&lt;br /&gt;
Code can be entered in C++, which is dynamically (just in time) compiled to fast machine code.&lt;br /&gt;
&lt;br /&gt;
Cling can be downloaded from the [https://root.cern/cling Cern web site] and/or installed via a package installer:&lt;br /&gt;
 &lt;br /&gt;
;Linux:&lt;br /&gt;
: -- see https://root.cern/download/cling/ --&lt;br /&gt;
Download one of the tar archives and unpack the files into some folder (such as &amp;quot;/opt/cling&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
;Windows&lt;br /&gt;
: Sorry, to our knowledge, there exists no ready-to-install version for Windows at the time of writing this document.&lt;br /&gt;
&lt;br /&gt;
;OS X(Mac):&lt;br /&gt;
: &amp;lt;code&amp;gt;brew install cling&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Depending on whether cling is found along your path, or you want to select a particular version,&lt;br /&gt;
specify the cling installation folder in the cling settings dialog &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Cling&#039;&#039;&amp;quot;. &lt;br /&gt;
&amp;lt;br&amp;gt;There, click on the &amp;quot;?&amp;quot; button to verify that cling is found.&lt;br /&gt;
&lt;br /&gt;
== Smalltalk Installation ==&lt;br /&gt;
&lt;br /&gt;
Support for bridged Smalltalk is &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot;, currently disabled and is planned for a future version.&lt;br /&gt;
However, scripted Smalltalk is already available.&lt;br /&gt;
&lt;br /&gt;
== Scheme Installation ==&lt;br /&gt;
&lt;br /&gt;
Support for bridged Scheme is &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot;, currently disabled and is planned for a future version.&lt;br /&gt;
However, scripted Scheme is already available.&lt;br /&gt;
&lt;br /&gt;
You can configure expecco to either use any standard scheme interpreter (whichever is installed as &amp;quot;scheme&amp;quot; command),&lt;br /&gt;
or to use an explicit implementation. Currently, supported are ChezScheme, ChickenScheme and Racket/MZScheme.&lt;br /&gt;
&lt;br /&gt;
=== Chicken Scheme ===&lt;br /&gt;
&lt;br /&gt;
[https://code.call-cc.org Chicken] can be compiled from [https://code.call-cc.org source] or installed via a package manager.&lt;br /&gt;
&lt;br /&gt;
;Windows:&lt;br /&gt;
: https://chocolatey.org/packages/chicken/&lt;br /&gt;
: or:&lt;br /&gt;
: see https://wiki.call-cc.org/platforms#microsoft-windows-&lt;br /&gt;
&lt;br /&gt;
;Linux:&lt;br /&gt;
: see https://wiki.call-cc.org/platforms#linux&lt;br /&gt;
&lt;br /&gt;
;OS X (mac):&lt;br /&gt;
: brew install chicken&lt;br /&gt;
: or:&lt;br /&gt;
: see https://wiki.call-cc.org/platforms#mac-os-x&lt;br /&gt;
&lt;br /&gt;
=== Chez Scheme ===&lt;br /&gt;
&lt;br /&gt;
See [ https://github.com/cisco/ChezScheme ] for instructions.&lt;br /&gt;
&lt;br /&gt;
A Windows binary and sources of release 9.5.4 are found at [ https://github.com/cisco/ChezScheme/releases/tag/v9.5.4 ].&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;GnuPlot_Installation&amp;quot;&amp;gt;GnuPlot Installation&amp;lt;/div&amp;gt; (for Graph Attachments to the Report) ==&lt;br /&gt;
&lt;br /&gt;
Gnuplot makes it easy to add graphs for measurement data or statistics to the&lt;br /&gt;
report and/or to create attachments for them.&lt;br /&gt;
To install gnuplot execute (in a terminal):&lt;br /&gt;
 &lt;br /&gt;
;Linux:&lt;br /&gt;
: -- to be determined and documented --&lt;br /&gt;
: please refer to the official Gnuplot website: http://www.gnuplot.info/download.html&lt;br /&gt;
&lt;br /&gt;
;Windows:&lt;br /&gt;
: -- to be determined and documented --&lt;br /&gt;
: please refer to the official Gnuplot website: http://www.gnuplot.info/download.html&lt;br /&gt;
&lt;br /&gt;
;OS X (Mac):&lt;br /&gt;
: &amp;lt;code&amp;gt;brew install gnuplot&amp;lt;/code&amp;gt;&lt;br /&gt;
: or download a binary package eg. from:&lt;br /&gt;
: &amp;amp;nbsp;https://csml-wiki.northwestern.edu/index.php/Binary_versions_of_Gnuplot_for_OS_X&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;GNU_Octave_Installation&amp;quot;&amp;gt;GNU Octave Installation&amp;lt;/div&amp;gt; (Matlab compatible Scripting) ==&lt;br /&gt;
&lt;br /&gt;
;OS X (Mac):&lt;br /&gt;
: Download a dmg from &lt;br /&gt;
: &amp;amp;nbsp;https://wiki.octave.org/Octave_for_macOS&lt;br /&gt;
: or:&lt;br /&gt;
: &amp;amp;nbsp;https://octave-app.org&lt;br /&gt;
: or:&lt;br /&gt;
: &amp;lt;code&amp;gt;sudo port install octave&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Windows:&lt;br /&gt;
:Download from https://www.gnu.org/software/octave/download.&lt;br /&gt;
&lt;br /&gt;
Warning: octave is huge (roughly 1Gb download).&lt;br /&gt;
&amp;lt;br&amp;gt;Also notice: octave needs gnuplot to generate image files from graphs.&lt;br /&gt;
&lt;br /&gt;
If you are already using Matlab, set the path to the matlab executable in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; [[Settings ExternalToolsSettings/en#GnuOctave_Path | &amp;quot;&#039;&#039;External Script Interpreter&#039;&#039;&amp;quot;]] settings.&lt;br /&gt;
&lt;br /&gt;
==Dart Installation==&lt;br /&gt;
Goto [https://dart.dev/get-dart dart.dev] and follow the instructions there.&lt;br /&gt;
&lt;br /&gt;
==R Installation==&lt;br /&gt;
Goto [https://www.r-project.org/ www.r-project.org] and follow the instructions there.&lt;br /&gt;
&amp;lt;br&amp;gt;OpenSuse users can &amp;quot;&amp;lt;code&amp;gt;zypper install R-base R-base-devel&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Go ==&lt;br /&gt;
For downloads, go to [https://go.dev/dl/ https://go.dev/dl/]. &lt;br /&gt;
&amp;lt;br&amp;gt;OpenSuse users can &amp;quot;&amp;lt;code&amp;gt;zypper install go-devel&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Make sure that go is in your PATH or else define the full pathname to go in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039; &amp;quot;&amp;amp;#8594; &amp;quot;&#039;&#039;Others&#039;&#039;&amp;quot; settings dialog.&lt;br /&gt;
&lt;br /&gt;
== TCL, and all the others ==&lt;br /&gt;
If you use those, you probably know how to install and update them.&lt;br /&gt;
Follow the usual installation instructions and - unless the interpreter is found along your PATH setting, define the path in the expecco &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039; &amp;quot;&amp;amp;#8594; &amp;quot;&#039;&#039;Others&#039;&#039;&amp;quot; settings dialog.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;OCR&amp;quot;&amp;gt;OCR&amp;lt;/div&amp;gt; (Optical Character Recognition) ==&lt;br /&gt;
In order to extract text from bitmap images,&lt;br /&gt;
an OCR framework is needed. It is also needed if you want to automate the local screen or a VNC screen AND you need to extract text or numeric values from it.&lt;br /&gt;
&lt;br /&gt;
Both open source and commercial frameworks can be found and used.&lt;br /&gt;
Good results are achieved by the free (and open source) &amp;quot;Tesseract&amp;quot; framework,&lt;br /&gt;
which we recommended, unless you already have a more powerful non-free commercial OCR framework at hand&lt;br /&gt;
(although supported, we do NOT recommend capture2Text or GNU-ocrad; they do not provide detailed per-word information and/or delivered poor recognition results. At least at the time this document was written).&lt;br /&gt;
&lt;br /&gt;
Tesseract is hosted at [ https://github.com/tesseract-ocr/tessdoc ] and can be downloaded from [ https://github.com/tesseract-ocr/tessdoc/blob/master/Downloads.md ]. &lt;br /&gt;
&amp;lt;br&amp;gt;Follow the installation instructions there. &lt;br /&gt;
&lt;br /&gt;
;Windows and OS X&lt;br /&gt;
:binaries are found at [ https://github.com/UB-Mannheim/tesseract/wiki ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In order to recognize national language characters (eg. accents, diareses/Umlauts), you&#039;ll also need language specific Tesseract-Data files. Please also install those for German, French, etc. from [ https://github.com/tesseract-ocr/tessdata ].&lt;br /&gt;
&lt;br /&gt;
== AI (Tensorflow) ==&lt;br /&gt;
These are typically used via Python actions, and installed using a Python package manager (pip). Please refer to Tensorflow web pages for details.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Installing_additional_Frameworks/en&amp;diff=30842</id>
		<title>Installing additional Frameworks/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Installing_additional_Frameworks/en&amp;diff=30842"/>
		<updated>2025-09-12T14:18:53Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Jython Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
If you intent to execute actions written for Java, Node, Python, .NET, C etc.,&lt;br /&gt;
or to test Java-, Windows- or mobile applications, additional frameworks have to be installed on your machine.&lt;br /&gt;
&lt;br /&gt;
Mostly for legal reasons, but also because you will probably want to install a most up-to-date version, we do not bundle those with the expecco installation (except for a python setup, as noted below).&lt;br /&gt;
&lt;br /&gt;
Please make sure that any required framework is installed, and the commands are found by expecco. &lt;br /&gt;
&lt;br /&gt;
If they are already installed, but expecco fails to execute one of them, take a look at the PATH setting and/or the expecco &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; settings. There, click on buttons labeled &amp;quot;?&amp;quot; to verify the installed version(s). &lt;br /&gt;
&lt;br /&gt;
However, the recommendend setup is to only specify the command name in the settings, and ensure that the PATH variable is set correctly, to let expecco find the command via the PATH. &lt;br /&gt;
&amp;lt;br&amp;gt;The PATH should be set in your &amp;quot;.login&amp;quot; (Unix) or &amp;quot;autoexec.bat&amp;quot; (Windows) file accordingly.&lt;br /&gt;
&lt;br /&gt;
== Required Frameworks Overview ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Feature !! Required Framework(s)&lt;br /&gt;
|-&lt;br /&gt;
| Java/Groovy Actions || JRE (Java Runtime Environment)&amp;lt;br&amp;gt;or: JDK (recommended)&lt;br /&gt;
|-&lt;br /&gt;
| NodeJS Actions || node&lt;br /&gt;
|-&lt;br /&gt;
| Python Actions || Python3.x (recommended)&amp;lt;br&amp;gt;or: Python2.x (for older Python code)&lt;br /&gt;
|-&lt;br /&gt;
| Jython Actions || Java JRE (Java Runtime Environment) or JDK and Jython&lt;br /&gt;
|-&lt;br /&gt;
| Iron Python Actions || .NET CLR&amp;lt;br&amp;gt;or: Mono (on non-Windows systems)&lt;br /&gt;
|-&lt;br /&gt;
| Ruby Actions || ruby&lt;br /&gt;
|-&lt;br /&gt;
| Java GUI Automation || JRE (Java Runtime Environment)&amp;lt;br&amp;gt;or: JDK (recommended)&lt;br /&gt;
|-&lt;br /&gt;
| Windows GUI Automation || .NET CLR&lt;br /&gt;
|-&lt;br /&gt;
| WebTest (Selenium Webdriver) || JRE (Java Runtime Environment)&amp;lt;br&amp;gt;webDrivers matching your web-browser version&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Test (Appium) || JRE (Java Runtime Environment)&lt;br /&gt;
|-&lt;br /&gt;
| Bridged C Actions || C compiler toolchain (GCC, Clang, VisualC, Mingw or Borland)&lt;br /&gt;
|-&lt;br /&gt;
| Octave (Matlab scripts) || GNU Octave or a real Matlab&lt;br /&gt;
|-&lt;br /&gt;
| OCR (VNC, Screen Automation) || Tesseract&amp;lt;br&amp;gt;language specific tessdata files&lt;br /&gt;
|-&lt;br /&gt;
| Vector/Canoe Plugin || .NET CLR&lt;br /&gt;
|-&lt;br /&gt;
| OPC Library || Python3 + opcua package&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Java_Installation&amp;quot;&amp;gt;Java Installation&amp;lt;/div&amp;gt; (for Groovy Actions, Web- and Mobile Testing) ==&lt;br /&gt;
You can either install a plain Java Runtime Environment (JRE) or a full Java Development Kit (JDK). If only a JRE is installed, some functions will not work,&lt;br /&gt;
and we therefore recommend a JDK to be installed - typically at its standard location, &amp;quot;&amp;lt;CODE&amp;gt;C:\Program Files\Java\jdk-xxx&amp;lt;/CODE&amp;gt;&amp;quot; (Windows), so it will run out of the box.&lt;br /&gt;
Expecco will try to figure out if and where Java was installed, but it it also possible to specify explicit pathes via the settings dialog.&lt;br /&gt;
&lt;br /&gt;
Notice, that due to changed regulations by Oracle (i.e. legal restrictions), we may no longer provide a Java installation bundled with expecco;&lt;br /&gt;
you should navigate to the Oracle (or OpenJDK) website and install it from there.&lt;br /&gt;
&lt;br /&gt;
Also notice, that on most systems, a Java is already installed, but it may be a runtime environment only.&lt;br /&gt;
Please verify, that a JDK is installed for the full set of features.&lt;br /&gt;
&lt;br /&gt;
The expecco installation does include some required jar files (eg. groovy.jar, selenium jars and drivers etc.), but you may want to verify that they are the most up-to-date versions. &lt;br /&gt;
&lt;br /&gt;
==== Selenium WebDriver ====&lt;br /&gt;
Especially the Selenium drivers (which are used to remote-control a Webbrowser when testing or automating graphical user interfaces in a browser) depend on the concrete browser version (i.e. Chrome version, Firefox version, etc.). Older drivers do not always work with a newer browser. &lt;br /&gt;
&lt;br /&gt;
The deployed installation package includes a number of drivers for versions which were in use at that time, but especially due to automatic updates, these may be outdated on your machine. Please follow the instructions given by expecco and/or read [[Selenium_WebDriver_Plugin/en#Update_WebDriver|&amp;quot;Update WebDriver&amp;quot;]] when it encounters a problem.&lt;br /&gt;
&amp;lt;br&amp;gt;The GUIBrowser&#039;s connect dialog will check for version compatibility and offer an update function if required.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;DOTNET_Installation&amp;quot;&amp;gt;.NET Installation&amp;lt;/div&amp;gt; (for the .NET bridge, Windows Apps, IronPython Actions and some Plugins &amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
On Windows, a .NET framework is usually already installed.&lt;br /&gt;
&amp;lt;br&amp;gt;On Unix/Linux systems, you can install &amp;quot;Mono&amp;quot;, which may provide enough functionality for your needs.&lt;br /&gt;
&amp;lt;br&amp;gt;Be aware, that some functions - especially GUI functions - may not be present or may not work perfectly (if at all) under Mono.&lt;br /&gt;
&lt;br /&gt;
Mono can be downloaded from [https://www.mono-project.com/download/stable/ the Mono project web site].&lt;br /&gt;
&lt;br /&gt;
1) for example, the Vector/Canoe plugin requires .NET (among others).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Node_Installation&amp;quot;&amp;gt;Node Installation&amp;lt;/div&amp;gt; (for Node.js Actions) ==&lt;br /&gt;
&lt;br /&gt;
Goto [ https://nodejs.org/en ] or [ https://nodejs.org/de/download/ ] and select the appropriate package for your machine.&lt;br /&gt;
When asked if additional packages are to be downloaded, answer &amp;quot;yes&amp;quot;. &lt;br /&gt;
(Under Windows, VisualStudio build tools will then also be installed, in case any node module needs to be compiled from C/C++ code).&lt;br /&gt;
&lt;br /&gt;
Open the node interpreter settings (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Node&#039;&#039;&amp;quot;) and verify that the &amp;quot;node&amp;quot; command is found along your PATH variable settings by clicking on the &amp;quot;?&amp;quot;-button. If found, its version should be shown.&lt;br /&gt;
&lt;br /&gt;
If not found, either restart expecco (if you installed node while expecco was active), or enter the path to your node interpreter into the path field. You may even have to restart your cmd/shell session, in case the old shell environment does not contain the path to the new installed node.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Python_Installation&amp;quot;&amp;gt;Python Installation&amp;lt;/div&amp;gt; (for Python Actions) ==&lt;br /&gt;
&lt;br /&gt;
Expecco is delivered with an installation package for a relatively new Python version (currently Python 3.11.6 (expecco 23.2)), but of course, new versions are constantly released and the included Python might be outdated.&amp;lt;br&amp;gt;You can (and probably should) download other versions [ https://www.python.org/downloads/ ].&lt;br /&gt;
Notice, that there are both packages for python3.x and python2.7 available, and you may have to install both, depending on the Python code to be executed later (although python2 is more and more becoming obsolete, there may still be frameworks for that old version to be found and used).&lt;br /&gt;
&lt;br /&gt;
You can start by installing a Python3.x version only. &lt;br /&gt;
By the time of writing this document, the most recent Python version is 3.12, but expecco is known to work with older versions.&lt;br /&gt;
Be aware, that there are syntactic differences between Python2.x and Python3.x; for example &amp;quot;print ...&amp;quot; is a statement in 2.x whereas &amp;quot;print(...)&amp;quot; is a function call in 3.x.&lt;br /&gt;
&lt;br /&gt;
Open the Python interpreter settings (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot;) and verify that the &amp;quot;python&amp;quot; command is found along your PATH variable settings (click on &amp;quot;?&amp;quot;). &lt;br /&gt;
&lt;br /&gt;
[[Bild:PythonSettings.png|700px|PythonSettings]]&lt;br /&gt;
&lt;br /&gt;
=== Python Commands ===&lt;br /&gt;
&lt;br /&gt;
Notice, that there are 3 command fields, which can be set:&lt;br /&gt;
* Python Cmd Path&lt;br /&gt;
:is used if no explicit version is specified in a python action&lt;br /&gt;
* Python3 Cmd Path&lt;br /&gt;
:is used if the python action explicitly asks for python3&lt;br /&gt;
* Python2 Cmd Path&lt;br /&gt;
:is used if the python action explicitly asks for python2&lt;br /&gt;
&lt;br /&gt;
Be aware and reminded, that these are different python interpreter instances: you cannot run both Python2 and Python3 code within the same python interpreter instance.&lt;br /&gt;
&lt;br /&gt;
If not found, either restart expecco (if you installed Python while expecco was active), or enter the full path to your Python interpreter into the path field.&lt;br /&gt;
&lt;br /&gt;
Make sure that the correct Python version is displayed (2.x vs. 3.x) when you click on the &amp;quot;?&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
==== Default cmd paths ====&lt;br /&gt;
&lt;br /&gt;
If no command is specified for one of the Python versions, expecco determines a default path, which is displayed in gray in the corresponding cmd path field.&lt;br /&gt;
&lt;br /&gt;
The following sequence is used until a set cmd path is found:&lt;br /&gt;
&lt;br /&gt;
*Python-Cmd is empty:&lt;br /&gt;
: &#039;&#039;Python3-Cmd-Path&#039;&#039; → &#039;&#039;Python2-Cmd-Path&#039;&#039; → &#039;&#039;Windows registry entry for Python3&#039;&#039; → &#039;&#039;Windows registry entry for Python2&#039;&#039; → &amp;quot;&#039;&#039;python&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Python3-Cmd is empty:&lt;br /&gt;
: &#039;&#039;Python-Cmd-Path&#039;&#039; → &#039;&#039;Windows registry entry for Python3&#039;&#039; → &amp;quot;&#039;&#039;python3&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Python2-Cmd is empty:&lt;br /&gt;
: &#039;&#039; Python cmd path&#039;&#039; → &#039;&#039;Windows registry entry for Python2&#039;&#039; → &amp;quot;&#039;&#039;python2&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can display the effective Python version by clicking on the &amp;quot;?&amp;quot;-button.&lt;br /&gt;
&lt;br /&gt;
=== Debugging python code ===&lt;br /&gt;
&lt;br /&gt;
==== Debugging in expecco ====&lt;br /&gt;
To make your life easier, install a Python debugger; either:&lt;br /&gt;
 pip install debugpy&lt;br /&gt;
or&lt;br /&gt;
 pip install ptvsd&lt;br /&gt;
(they are more or less interchangeable, but &amp;quot;&amp;lt;code&amp;gt;ptvsd&amp;lt;/code&amp;gt;&amp;quot; is outdated (no longer maintained) and replaced by the newer &amp;quot;&amp;lt;code&amp;gt;debugpy&amp;lt;/code&amp;gt;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Without a Python debugger, breakpoints cannot be placed in bridged Python code,&lt;br /&gt;
and you will not get a debugger on Python exceptions&lt;br /&gt;
(you should then see a warning and hint to install &amp;quot;debugpy&amp;quot; on the Transcript and in the info area).&lt;br /&gt;
&lt;br /&gt;
To ensure that the breakpoints are observed, please uncheck the &amp;quot;Disable debugger&amp;quot; checkbox.&lt;br /&gt;
&lt;br /&gt;
=====Problems with debugging=====&lt;br /&gt;
&lt;br /&gt;
======Debugger does not start======&lt;br /&gt;
&lt;br /&gt;
If the path for Python is specified with the variables &amp;quot;&#039;&#039;%ProgramFiles%&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;%ProgramFiles(x86)%&#039;&#039;&amp;quot;, debugpy does not start.&lt;br /&gt;
&lt;br /&gt;
 Python: failed to enable PythonDebugger on port ..: [WinError 2] the system cannot find the file specified.&lt;br /&gt;
&lt;br /&gt;
The remedy is to use the specific path such as &amp;quot;&#039;&#039;C:\Program Files&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;C:\Program Files (x86)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
======Warnings in output======&lt;br /&gt;
&lt;br /&gt;
 Debugger warning: It seems that frozen modules are being used, which may &lt;br /&gt;
 make the debugger miss breakpoints. Please pass -Xfrozen_modules=off&lt;br /&gt;
 to python to disable frozen modules.&lt;br /&gt;
 Note: Debugging will proceed. Set PYDEVD_DISABLE_FILE_VALIDATION=1 to disable this validation.&lt;br /&gt;
&lt;br /&gt;
In Python 3.11, the core modules essential for Python startup are “frozen”. ... &lt;br /&gt;
This reduces the steps in module execution process. Interpreter startup is now 10-15% faster &lt;br /&gt;
in Python 3.11. This has a big impact for short-running programs using Python.&lt;br /&gt;
&lt;br /&gt;
It&#039;s not possible for the debugger to debug frozen modules as the filename is definitely required to hit breakpoints.&lt;br /&gt;
&lt;br /&gt;
To deactivate the warning, set the environment variable PYDEVD_DISABLE_FILE_VALIDATION to 1, as described in the warning. Notice that the bridge needs to be restarted for the environment variable change to be effective (and possibly even expecco, unless you have specified that variable in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Environment Variables&#039;&#039;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
==== Debugging in an external IDE ====&lt;br /&gt;
For more in depth debugging, you can run the Python bridge in an external IDE (like PyCharm) and use the debug features of the IDE.&lt;br /&gt;
&lt;br /&gt;
For this, you should save the Python bridge code to a file or copy it to the clipboard using the &amp;quot;&#039;&#039;Copy / Save Bridge Code...&#039;&#039;&amp;quot; button. &lt;br /&gt;
Then open this python file in the IDE, and start in debug mode. &lt;br /&gt;
&lt;br /&gt;
The Expecco Python blocks are called in the line:&lt;br /&gt;
 result = actionFn(actionArgs, actionOutPins)&lt;br /&gt;
&lt;br /&gt;
You can then step into the block code with a breakpoint at these lines.&lt;br /&gt;
&lt;br /&gt;
In order for Expecco to connect to this Python bridge (instead of starting a new one), &lt;br /&gt;
you must first tick the checkbox &amp;quot;&#039;&#039;Connect to already running bridge&#039;&#039;&amp;quot; and terminate any previously running Python bridges (via &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Shutdown all Bridge Connections&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
=== pip2 vs. pip3 vs. pip ===&lt;br /&gt;
To install Python packages, use the &amp;quot;&amp;lt;Code&amp;gt;pip&amp;lt;/Code&amp;gt;&amp;quot; command. However, this command is usually a symbolic link to either &amp;quot;&amp;lt;Code&amp;gt;pip2&amp;lt;/Code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;Code&amp;gt;pip3&amp;lt;/Code&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
You should use &amp;quot;&amp;lt;Code&amp;gt;pip3&amp;lt;/Code&amp;gt;&amp;quot; to install packages for python3, and &amp;quot;&amp;lt;Code&amp;gt;pip2&amp;lt;/Code&amp;gt;&amp;quot; for python2. Thus, it is safer to use one of those or &amp;quot;&amp;lt;Code&amp;gt;python3 -m pip install ...&amp;lt;/Code&amp;gt;&amp;quot; instead of &amp;quot;&amp;lt;Code&amp;gt;pip install ...&amp;lt;/Code&amp;gt;&amp;quot; to ensure that the module is installed for the current version.&lt;br /&gt;
&lt;br /&gt;
On some systems, no pip2 command is present by default (and installing python3 will define the &amp;quot;&amp;lt;Code&amp;gt;pip&amp;lt;/Code&amp;gt;&amp;quot; command as an alias to &amp;quot;&amp;lt;Code&amp;gt;pip3&amp;lt;/Code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
To get &amp;quot;pip2&amp;quot; on those systems, execute (on the command line):&lt;br /&gt;
 wget https://bootstrap.pypa.io/get-pip.py&lt;br /&gt;
 python2.7 get-pip.py&lt;br /&gt;
&lt;br /&gt;
Things become even more confusing, if you have multiple python versions installed (for example, python3.7 and python3.9).&amp;lt;br&amp;gt;Then, it is best invoke pip via the python command itself, eg. with:&amp;lt;br&amp;gt;&amp;quot;&amp;lt;code&amp;gt;python3.7 -m pip install ...&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Getting pip ===&lt;br /&gt;
Some Python installers seem to not install pip (at least it happened to us once, that &amp;quot;pip&amp;quot; was not found after a python installation). &lt;br /&gt;
&amp;lt;br&amp;gt;If &amp;quot;python -m pip&amp;quot; gives a warning, do the following:&lt;br /&gt;
* download &amp;quot;https://bootstrap.pypa.io/get-pip.py&amp;quot; (use &amp;quot;Save As&amp;quot; in a web browser, and save it to the desktop)&lt;br /&gt;
* open a cmd/shell window in that folder.&lt;br /&gt;
* execute &amp;quot;python get-pip.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Jython Installation ==&lt;br /&gt;
Jython is a Python interpreter which runs inside a Java virtual machine, and thus has direct access to Java classes and objects.&amp;lt;br&amp;gt;&lt;br /&gt;
As a prerequisite, Java needs to be installed on your machine.&amp;lt;br&amp;gt;Then goto [ https://www.jython.org/download.html ], download the Jython installer and run it (choose &amp;quot;standard install&amp;quot; or &amp;quot;full install&amp;quot;).&lt;br /&gt;
&amp;lt;br&amp;gt;Remember the target directory. The jython command will be found there.&lt;br /&gt;
&amp;lt;br&amp;gt;If the &amp;quot;jython&amp;quot; command is not in your PATH, enter its full path in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Jython&#039;&#039;&amp;quot; settings dialog. &lt;br /&gt;
&amp;lt;br&amp;gt;However, it is usually better to add the path to your PATH variable (eg. as setup in the Windows environment settings, autoexec.bat or Unix&#039;s login.rc), and just give &amp;quot;jython&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;Notice that previous Jython versions were 2.x Pythons, which will sooner or later become outdated. It is recommended to download or upgrade to a 3.x version (if your code is 3.x compatible).&lt;br /&gt;
&lt;br /&gt;
== Iron Python Installation ==&lt;br /&gt;
JIronPython is a Python interbreter which runs inside the Common Language Runtime system, and thus has direct access to C# classes (and of yourse all other objects which live inside the CLR world).&amp;lt;br&amp;gt;&lt;br /&gt;
As a prerequisite, you&#039;ll need a .NET CLR (common language runtime) or mono (on Unix systems). On Windows systems, a reasonable CLR Version is usually already installed.&lt;br /&gt;
&amp;lt;br&amp;gt;Then go to [ https://ironpython.net/download ] or [ https://github.com/IronLanguages/ironpython3 ] and follow the instructions.&lt;br /&gt;
&lt;br /&gt;
After the download, IronPython is typically installed in &amp;quot;&amp;lt;Code&amp;gt;C:\Program Files\IronPython 3.x&amp;lt;/Code&amp;gt;&amp;quot;, and you should enter the path &amp;quot;&amp;lt;Code&amp;gt;C:\Program Files\IronPython x.y\ipy.exe&amp;lt;/Code&amp;gt;&amp;quot; into the IronPython command path field in the python settings dialog (or simply &amp;quot;ipy&amp;quot;, if it is in your PATH).&lt;br /&gt;
&amp;lt;p&amp;gt;Notice that previous IronPython versions were 2.x Pythons, which became obsolete. It is therefore recommended to download or upgrade to a 3.x version (if your code is 3.x compatible).&lt;br /&gt;
&lt;br /&gt;
== Ruby Installation ==&lt;br /&gt;
Goto [ https://rubyinstaller.org/downloads ] and install ruby.&lt;br /&gt;
Then make sure that ruby is in your PATH setting or set the path to the command in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Ruby&#039;&#039;&amp;quot; settings. Typically it will look like &amp;quot;C:\Ruby32-x64\bin\ruby.exe&amp;quot; on  windows.&lt;br /&gt;
&amp;lt;br&amp;gt;Create a new Ruby action and execute it to see if it works.&lt;br /&gt;
&lt;br /&gt;
== Julia Installation ==&lt;br /&gt;
Goto [ https://julialang.org/downloads] and install.&lt;br /&gt;
Then make sure that julia is in your PATH setting or set the path to the command in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Other&#039;&#039;&amp;quot; settings. Typically it will look like &amp;quot;%LOCALAPPDATA%\Programs\Julia-1.10.4\bin\julia.exe&amp;quot; on  windows.&lt;br /&gt;
&amp;lt;br&amp;gt;Create a new Julia action and execute it to see if it works.&lt;br /&gt;
&lt;br /&gt;
== C Compiler Toolchain Installation (for C-Actions) ==&lt;br /&gt;
&lt;br /&gt;
For a quick verify if the setup is working, create a new (default) bridged C action and execute it (it should generate a &amp;quot;Hello World&amp;quot; message).&lt;br /&gt;
&lt;br /&gt;
==== C Compiler Toolchain Installation ====&lt;br /&gt;
&lt;br /&gt;
You need a C-compiler toolchain to be installed for C-coded actions.&lt;br /&gt;
* On Unix/Linux systems, these are usually already present on the machine (try &amp;quot;&amp;lt;Code&amp;gt;cc --version&amp;lt;/Code&amp;gt;&amp;quot; in a shell window; if you get a reasonable response, you are usually ready to go).&lt;br /&gt;
* On Windows, install one of &amp;quot;Borland&amp;quot;, &amp;quot;VisualC&amp;quot;, &amp;quot;VisualC Redistributable&amp;quot; or &amp;quot;MingGW&amp;quot;.&amp;lt;br&amp;gt;We recommend MingGW.&lt;br /&gt;
* On OSX, you have to install &amp;quot;XCode&amp;quot; or the &amp;quot;Command Line Tools&amp;quot; subset.&lt;br /&gt;
&lt;br /&gt;
===== Windows + Borland (32bit) =====&lt;br /&gt;
* get the free Borland command line tools (see https://borland-c.software.informer.com/5.5) and install them (typically, under &amp;quot;C:\borland\bcc55&amp;quot;)&lt;br /&gt;
* ensure that the link.cfg and bcc55.cfg files are present in the &amp;quot;C:\borland\bcc55\bin&amp;quot; directory.&lt;br /&gt;
* verify the installation by typing &amp;quot;bcc32&amp;quot;. A help message should appear.&lt;br /&gt;
* in the expecco settings, goto &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and select the appropriate CC-Script (&amp;quot;compile_windows_bcc.bat&amp;quot;), which tells the bridge how to compile the C-action code (more below).&lt;br /&gt;
 &lt;br /&gt;
===== Windows + Visual-C (32 or 64bit) =====&lt;br /&gt;
* similar to above, check for the &amp;quot;cl&amp;quot; command.&lt;br /&gt;
* in the expecco settings, goto &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and select the appropriate CC-Script (&amp;quot;compile_windows_vc32.bat&amp;quot;, &amp;quot;compile_windows_vc64.bat&amp;quot; or &amp;quot;compile_windows_vc64_redist.bat&amp;quot;); see below.&lt;br /&gt;
&lt;br /&gt;
===== Windows + Mingw (32 or 64bit) =====&lt;br /&gt;
* get the mingw64 compiler and install it (best is under &amp;quot;c:\mingw64&amp;quot; or &amp;quot;c:\program files\mingw64&amp;quot;).&lt;br /&gt;
* verify the installation by typing &amp;quot;gcc --help&amp;quot;.&lt;br /&gt;
* in the expecco settings, goto &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and select the appropriate CC-Script (&amp;quot;compile_windows_mingw32.bat&amp;quot; or &amp;quot;compile_windows_mingw64.bat&amp;quot;); see below.&lt;br /&gt;
&lt;br /&gt;
When a C-coded action is about to be executed, its C-code will be compiled &#039;&#039;just in time&#039;&#039; using that toolchain. For that, the cBridge executes a configurable batch or shell script.&amp;lt;br&amp;gt;For some commonly used toolchains, corresponding scripts are provided, but you can or may have to add your own script(s), in case you need special compile options, additional link library options or if you want to compile with a compiler not supported by the standard installation (eg. Intel compilers).&lt;br /&gt;
&lt;br /&gt;
If you get compilation errors, take a look at the &amp;quot;compile_xxx&amp;quot; scripts in &amp;quot;&amp;lt;code&amp;gt;packages/exept/expecco/bridgeFramework/cBridge/cLibrary&amp;lt;/code&amp;gt;&amp;quot; under the expecco installation folder.&lt;br /&gt;
&lt;br /&gt;
If required, add your own script to call whatever compiler you need, and select it in the cBridge settings dialog&lt;br /&gt;
(&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot;). You must also add your own script, if special compiler flags or additional standard pathes are to be setup.&lt;br /&gt;
&lt;br /&gt;
Notice, that we currently do not provide compilation scripts for C++; however, by declaring entry-functions (extern &amp;quot;C&amp;quot;) in your C++ code, these can be called from C.&lt;br /&gt;
&lt;br /&gt;
If no toolchain is installed, you can still see and edit C-code actions, but obviously not execute them.&lt;br /&gt;
&lt;br /&gt;
===== Windows + Mingw32 =====&lt;br /&gt;
Same as above; recommended installation directories are &amp;quot;c:\mingw32&amp;quot; or &amp;quot;c:\program files\mingw32&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== C Compiler Toolchain at Test-Execution Time ====&lt;br /&gt;
You can tell expecco to embed a pre-compiled object file into the saved &amp;quot;.ets&amp;quot; suite file (&amp;quot;&#039;&#039;Store Object Files in Project&#039;&#039;&amp;quot; checkbox in the CBridge settings dialog). If checked, C-Bridge actions will be compiled by your current session (using the configured toolchain) and the generated object file(s) will be saved with the suite. When the suite is later executed, no compiler toolchain will be needed on the test machine. Make sure that all required C actions are executed at least once. &lt;br /&gt;
&lt;br /&gt;
Expecco does not include cross compilation support; that means, that only object files for the current architecture can be generated. However, if you load the suite into another architecture&#039;s expecco, additional object files for that other architecture will be generated and added to the &amp;quot;.ets&amp;quot; when saved. So afterwards, object files for both architectures will be present in the ets.&lt;br /&gt;
&lt;br /&gt;
To summarize, if you want to deploy a library with embedded C-actions, which will have to be executed on (say) both a Linux and a Windows machine, where both test-execution machines have no compiler toolchain installed, perform the following steps:&lt;br /&gt;
# load the suite on a Linux machine (with C-compiler toolchain available)&lt;br /&gt;
# ensure that the &amp;quot;&#039;&#039;Store Object Files&#039;&#039;&amp;quot; flag is checked.&lt;br /&gt;
# Save the suite&lt;br /&gt;
# load the saved &amp;quot;.ets&amp;quot; on a Windows machine (with C-toolchain available)&lt;br /&gt;
# Save it again.&lt;br /&gt;
The last saved &amp;quot;.ets&amp;quot; will now contain object files for both architectures.&lt;br /&gt;
Be aware, that you may have to repeat the steps for 32 and 64 bit architectures, if the suite is to be executed eventually on both.&lt;br /&gt;
&lt;br /&gt;
Be reminded that this procedure is not needed, if the machine which executes the tests does have a C-toolchain installed. And especially, if it is the same as your development machine.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;Cling_Installation&amp;quot;&amp;gt;Cling Installation&amp;lt;/div&amp;gt; (for RootCling Actions) ==&lt;br /&gt;
&lt;br /&gt;
Support for Cling is &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot; and currently considered an &amp;quot;&#039;&#039;experimental&#039;&#039;&amp;quot; feature which is not available/enabled in the current deployed version.&lt;br /&gt;
&lt;br /&gt;
Cling (aka &amp;quot;Root Cling&amp;quot;) is a dynamic language system for C/C++.&lt;br /&gt;
Code can be entered in C++, which is dynamically (just in time) compiled to fast machine code.&lt;br /&gt;
&lt;br /&gt;
Cling can be downloaded from the [https://root.cern/cling Cern web site] and/or installed via a package installer:&lt;br /&gt;
 &lt;br /&gt;
;Linux:&lt;br /&gt;
: -- see https://root.cern/download/cling/ --&lt;br /&gt;
Download one of the tar archives and unpack the files into some folder (such as &amp;quot;/opt/cling&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
;Windows&lt;br /&gt;
: Sorry, to our knowledge, there exists no ready-to-install version for Windows at the time of writing this document.&lt;br /&gt;
&lt;br /&gt;
;OS X(Mac):&lt;br /&gt;
: &amp;lt;code&amp;gt;brew install cling&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Depending on whether cling is found along your path, or you want to select a particular version,&lt;br /&gt;
specify the cling installation folder in the cling settings dialog &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Language Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Cling&#039;&#039;&amp;quot;. &lt;br /&gt;
&amp;lt;br&amp;gt;There, click on the &amp;quot;?&amp;quot; button to verify that cling is found.&lt;br /&gt;
&lt;br /&gt;
== Smalltalk Installation ==&lt;br /&gt;
&lt;br /&gt;
Support for bridged Smalltalk is &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot;, currently disabled and is planned for a future version.&lt;br /&gt;
However, scripted Smalltalk is already available.&lt;br /&gt;
&lt;br /&gt;
== Scheme Installation ==&lt;br /&gt;
&lt;br /&gt;
Support for bridged Scheme is &amp;quot;&#039;&#039;work in progress&#039;&#039;&amp;quot;, currently disabled and is planned for a future version.&lt;br /&gt;
However, scripted Scheme is already available.&lt;br /&gt;
&lt;br /&gt;
You can configure expecco to either use any standard scheme interpreter (whichever is installed as &amp;quot;scheme&amp;quot; command),&lt;br /&gt;
or to use an explicit implementation. Currently, supported are ChezScheme, ChickenScheme and Racket/MZScheme.&lt;br /&gt;
&lt;br /&gt;
=== Chicken Scheme ===&lt;br /&gt;
&lt;br /&gt;
[https://code.call-cc.org Chicken] can be compiled from [https://code.call-cc.org source] or installed via a package manager.&lt;br /&gt;
&lt;br /&gt;
;Windows:&lt;br /&gt;
: https://chocolatey.org/packages/chicken/&lt;br /&gt;
: or:&lt;br /&gt;
: see https://wiki.call-cc.org/platforms#microsoft-windows-&lt;br /&gt;
&lt;br /&gt;
;Linux:&lt;br /&gt;
: see https://wiki.call-cc.org/platforms#linux&lt;br /&gt;
&lt;br /&gt;
;OS X (mac):&lt;br /&gt;
: brew install chicken&lt;br /&gt;
: or:&lt;br /&gt;
: see https://wiki.call-cc.org/platforms#mac-os-x&lt;br /&gt;
&lt;br /&gt;
=== Chez Scheme ===&lt;br /&gt;
&lt;br /&gt;
See [ https://github.com/cisco/ChezScheme ] for instructions.&lt;br /&gt;
&lt;br /&gt;
A Windows binary and sources of release 9.5.4 are found at [ https://github.com/cisco/ChezScheme/releases/tag/v9.5.4 ].&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;GnuPlot_Installation&amp;quot;&amp;gt;GnuPlot Installation&amp;lt;/div&amp;gt; (for Graph Attachments to the Report) ==&lt;br /&gt;
&lt;br /&gt;
Gnuplot makes it easy to add graphs for measurement data or statistics to the&lt;br /&gt;
report and/or to create attachments for them.&lt;br /&gt;
To install gnuplot execute (in a terminal):&lt;br /&gt;
 &lt;br /&gt;
;Linux:&lt;br /&gt;
: -- to be determined and documented --&lt;br /&gt;
: please refer to the official Gnuplot website: http://www.gnuplot.info/download.html&lt;br /&gt;
&lt;br /&gt;
;Windows:&lt;br /&gt;
: -- to be determined and documented --&lt;br /&gt;
: please refer to the official Gnuplot website: http://www.gnuplot.info/download.html&lt;br /&gt;
&lt;br /&gt;
;OS X (Mac):&lt;br /&gt;
: &amp;lt;code&amp;gt;brew install gnuplot&amp;lt;/code&amp;gt;&lt;br /&gt;
: or download a binary package eg. from:&lt;br /&gt;
: &amp;amp;nbsp;https://csml-wiki.northwestern.edu/index.php/Binary_versions_of_Gnuplot_for_OS_X&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;GNU_Octave_Installation&amp;quot;&amp;gt;GNU Octave Installation&amp;lt;/div&amp;gt; (Matlab compatible Scripting) ==&lt;br /&gt;
&lt;br /&gt;
;OS X (Mac):&lt;br /&gt;
: Download a dmg from &lt;br /&gt;
: &amp;amp;nbsp;https://wiki.octave.org/Octave_for_macOS&lt;br /&gt;
: or:&lt;br /&gt;
: &amp;amp;nbsp;https://octave-app.org&lt;br /&gt;
: or:&lt;br /&gt;
: &amp;lt;code&amp;gt;sudo port install octave&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Windows:&lt;br /&gt;
:Download from https://www.gnu.org/software/octave/download.&lt;br /&gt;
&lt;br /&gt;
Warning: octave is huge (roughly 1Gb download).&lt;br /&gt;
&amp;lt;br&amp;gt;Also notice: octave needs gnuplot to generate image files from graphs.&lt;br /&gt;
&lt;br /&gt;
If you are already using Matlab, set the path to the matlab executable in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; [[Settings ExternalToolsSettings/en#GnuOctave_Path | &amp;quot;&#039;&#039;External Script Interpreter&#039;&#039;&amp;quot;]] settings.&lt;br /&gt;
&lt;br /&gt;
==Dart Installation==&lt;br /&gt;
Goto [https://dart.dev/get-dart dart.dev] and follow the instructions there.&lt;br /&gt;
&lt;br /&gt;
==R Installation==&lt;br /&gt;
Goto [https://www.r-project.org/ www.r-project.org] and follow the instructions there.&lt;br /&gt;
&amp;lt;br&amp;gt;OpenSuse users can &amp;quot;&amp;lt;code&amp;gt;zypper install R-base R-base-devel&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Go ==&lt;br /&gt;
For downloads, go to [https://go.dev/dl/ https://go.dev/dl/]. &lt;br /&gt;
&amp;lt;br&amp;gt;OpenSuse users can &amp;quot;&amp;lt;code&amp;gt;zypper install go-devel&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Make sure that go is in your PATH or else define the full pathname to go in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039; &amp;quot;&amp;amp;#8594; &amp;quot;&#039;&#039;Others&#039;&#039;&amp;quot; settings dialog.&lt;br /&gt;
&lt;br /&gt;
== TCL, and all the others ==&lt;br /&gt;
If you use those, you probably know how to install and update them.&lt;br /&gt;
Follow the usual installation instructions and - unless the interpreter is found along your PATH setting, define the path in the expecco &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039; &amp;quot;&amp;amp;#8594; &amp;quot;&#039;&#039;Others&#039;&#039;&amp;quot; settings dialog.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div id=&amp;quot;OCR&amp;quot;&amp;gt;OCR&amp;lt;/div&amp;gt; (Optical Character Recognition) ==&lt;br /&gt;
In order to extract text from bitmap images,&lt;br /&gt;
an OCR framework is needed. It is also needed if you want to automate the local screen or a VNC screen AND you need to extract text or numeric values from it.&lt;br /&gt;
&lt;br /&gt;
Both open source and commercial frameworks can be found and used.&lt;br /&gt;
Good results are achieved by the free (and open source) &amp;quot;Tesseract&amp;quot; framework,&lt;br /&gt;
which we recommended, unless you already have a more powerful non-free commercial OCR framework at hand&lt;br /&gt;
(although supported, we do NOT recommend capture2Text or GNU-ocrad; they do not provide detailed per-word information and/or delivered poor recognition results. At least at the time this document was written).&lt;br /&gt;
&lt;br /&gt;
Tesseract is hosted at [ https://github.com/tesseract-ocr/tessdoc ] and can be downloaded from [ https://github.com/tesseract-ocr/tessdoc/blob/master/Downloads.md ]. &lt;br /&gt;
&amp;lt;br&amp;gt;Follow the installation instructions there. &lt;br /&gt;
&lt;br /&gt;
;Windows and OS X&lt;br /&gt;
:binaries are found at [ https://github.com/UB-Mannheim/tesseract/wiki ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In order to recognize national language characters (eg. accents, diareses/Umlauts), you&#039;ll also need language specific Tesseract-Data files. Please also install those for German, French, etc. from [ https://github.com/tesseract-ocr/tessdata ].&lt;br /&gt;
&lt;br /&gt;
== AI (Tensorflow) ==&lt;br /&gt;
These are typically used via Python actions, and installed using a Python package manager (pip). Please refer to Tensorflow web pages for details.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30841</id>
		<title>Release Notes 25.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30841"/>
		<updated>2025-09-11T14:07:44Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Release 25.2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 24.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 25.2 ==&lt;br /&gt;
*Improvement: Inspector shows XML Dom if it starts with &#039;&amp;lt;&#039; and ends with &#039;&amp;gt;&#039; and is parsable without error.&lt;br /&gt;
*Improvement: Handles very long index-lists (eg. 100k) more graceful&lt;br /&gt;
*Improvement: Bundled python3 installer updated to version 3.13.7&lt;br /&gt;
&lt;br /&gt;
== Release 25.1 ==&lt;br /&gt;
*Improvement: additional &amp;quot;Info&amp;quot; tab in inspector views&lt;br /&gt;
*Improvement: less memory usage in the activity log&lt;br /&gt;
*Improvement: better error messages and more links to settings from the activity log&#039;s error message&lt;br /&gt;
*Improvement: additional units and conversions in the [[PhysicalValues/en|physical values framework]]&lt;br /&gt;
*Improvement: more precision in the [[Numeric_Limits/en#Higher_Precision_Numbers|high precision trigonometric and math functions]]&lt;br /&gt;
*Improvement: WindowsAutomation: Plugin Update to FlaUI 5&lt;br /&gt;
*Improvement: Mobile Testing: Better Device Lock/Unlock Support&lt;br /&gt;
*Improvement: StandardLibrary: &amp;quot;File [ *CSV ]&amp;quot; blocks got an additional &amp;quot;characterEncoding&amp;quot; pin (useful for reading/writing e.g. utf-8 encoded CSV files)&lt;br /&gt;
*Improvement: ExcelLib: better documentation. Now requires the openpyxl package version &amp;gt;= 3.1.5. &lt;br /&gt;
*Improvement: better model language editor (translate and fetch-strings functions)&lt;br /&gt;
*Improvement: ODBCLibrary: improved compatibility with different database vendors (supports the CedarDB database) &lt;br /&gt;
*Feature: translate and spell check in the workspace window&lt;br /&gt;
*Feature: EditLock of suites loaded from expeccoALM / AIDYMO&lt;br /&gt;
*Feature: Start Test in expeccoALM / AIDYMO (via expecco)&lt;br /&gt;
*Feature: new library containing expeccoALM control actions (those from the AIDYMO menu)&lt;br /&gt;
*Fix: the version diff viewer (did not correctly copy changed attachment files)&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Lizenzserver_expecco_ALM&amp;diff=30838</id>
		<title>Lizenzserver expecco ALM</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Lizenzserver_expecco_ALM&amp;diff=30838"/>
		<updated>2025-09-04T08:48:23Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Übersicht==&lt;br /&gt;
&lt;br /&gt;
Der expecco Lizenzserver dient der zentralen Verwaltung von expecco Lizenzen. Durch den Lizenzserver kann expecco auf verschiedenen Rechnern (sowohl Entwicklungs- als auch reine Testausführungsrechner) ohne Dongle und lokale Lizenzdatei auf allen erreichbaren Rechnern im Netz installiert und ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Lizenzen werden dabei von den expecco-Rechnern vom Lizenzserver angefordert, im Lizenzserver reserviert,&lt;br /&gt;
und nach der Sitzung bzw. Testlauf wieder zurückgegeben. Damit können mehr Nutzer (allerdings nicht gleichzeitig) mit expecco arbeiten als Lizenzen erworben wurden.&lt;br /&gt;
&lt;br /&gt;
Lizenzen sind kryptographisch gesicherte Dateien, welche nur in Verbindung mit einem von eXept gelieferten Lizenzserver-Dongle gelesen bzw. genutzt werden können. Lizenzen sind Dongle-spezifisch. Es ist also nicht notwendig, Maßnahmen zum Schutz vor Diebstahl oder Kopieren von Lizenzdateien zu ergreifen. Allerdings ist ein Verlust des Dongles aus nahe liegenden Gründen zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
{{SEITENTITEL:Lizenzservice Installation}}&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Wir empfehlen expecco ALM auf einem durchgehend verfügbaren Server mit Windows Server 2012 / Windows 10 oder höher zu installieren. Die Installation auf anderen Betriebssystemen (wie z.B. Linux) wäre bei Bedarf auch möglich. Ebenso ist die Installation in einer Cloud möglich, dort ist der Betrieb ohne Dongle möglich.&lt;br /&gt;
&lt;br /&gt;
Damit expecco ALM flüssig arbeiten kann, werden folgende Hardware-Anforderungen an den Server gestellt:&lt;br /&gt;
&amp;lt;br&amp;gt;- ein &amp;quot;dezidierter&amp;quot; Prozessor mit mindestens 2 GHz&lt;br /&gt;
&amp;lt;br&amp;gt;- mindestens 1 GB Arbeitsspeicher (ausschließlich für expecco ALM)&lt;br /&gt;
&amp;lt;br&amp;gt;- mindestens 10 GB Festplattenspeicher (je nach Größe der Daten die expecco ALM verwalten soll)&lt;br /&gt;
&lt;br /&gt;
Stellen Sie sicher, dass dieser Server für alle Clients erreichbar ist. Clients sind alle Rechner der expecco ALM Benutzer, Rechner die expecco ALM zur Testausführung dienen und Rechner mit &amp;quot;Floating&amp;quot; lizenziertem expecco. Bei Problemen bezüglich der Erreichbarkeit wenden Sie sich bitte an Ihren Netzwerkadministrator.&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
Bitte halten Sie Ihre Lizenzdatei und ggfs. den Dongle für die Installation von expecco ALM bereit.&amp;lt;br&amp;gt;&lt;br /&gt;
Für die Installation in der Cloud benötigen Sie keinen Dongle; wir liefern dann eine Lizenzdatei, die an die MAC-Adresse des Servers gebunden ist. Falls sich der Server und damit dessen MAC-Adresse ändert, erhalten Sie eine neue angepasste Lizenzdatei von uns.&lt;br /&gt;
&lt;br /&gt;
Ihre Lizenzdatei und eine Verknüpfung zum aktuellen expecco ALM Setup haben wir Ihnen per E-Mail zu kommen lassen. Der Installer hat folgenden Namen &amp;quot;expecco ALM 24.2.0 Setup.exe&amp;quot;, wobei die Versionsnummer abweichen kann. Den Dongle haben wir per Post an Sie versendet (es sei denn Sie evaluieren expecco ALM oder nutzen die Cloud Variante mit der MAC-Adressen-Bindung).&lt;br /&gt;
&lt;br /&gt;
Gehen Sie bitte wie folgt vor:&lt;br /&gt;
* Laden Sie den expecco ALM Installer auf dem Server, auf dem expecco ALM künftig laufen soll, herunter&lt;br /&gt;
* Legen Sie Ihre Lizenzdatei ebenfalls auf dem Server ab&lt;br /&gt;
* Verbinden Sie Ihren Dongle mit dem Server (Wenn Sie expecco ALM evaluieren oder die Cloud Variante mit der MAC-Adressen-Bindung nutzen, überspringen Sie diesen Schritt)&lt;br /&gt;
* Führen Sie den expecco ALM Installer (&amp;quot;expecco ALM ?.?.?.? Setup.exe&amp;quot; bzw. unter Linux &amp;quot;expecco ALM ?.?.?.? Setup.package&amp;quot;) aus&lt;br /&gt;
&lt;br /&gt;
Für Linux werden zusätzliche Pakete der Linux-Distribution benötigt. Diese sind [[Installation#Installation_von_expecco_auf_Linux|hier]] aufgeführt.&lt;br /&gt;
&lt;br /&gt;
Nachdem der Installer erfolgreich ausgeführt wurde, läuft expecco ALM bereits als Service. Auf Ihrem Desktop wurde eine Verknüpfung zu expecco ALM angelegt. Es wurde auch ein Ordner für expecco ALM in Ihrem Startmenü erstellt. Dort können Sie unter &amp;quot;Konfiguration&amp;quot; den Port ändern (Standard ist Port 8081) oder über die &amp;quot;Logdatei&amp;quot; eventuelle Probleme feststellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:InstallAlmLicense.png|mini|Anhang 1]]&lt;br /&gt;
Über die Verknüpfung auf Ihrem Desktop lässt sich expecco ALM mit Ihrem Standardbrowser öffnen. Es wird eine Seite zum Installieren Ihrer expecco ALM Lizenz angezeigt (Anhang 1). Über &amp;quot;Lizenzdatei installieren&amp;quot; können Sie Ihre Lizenzdatei (die Sie bereits auf dem Server abgelegt haben) auswählen. Nach dem expecco ALM Ihre Lizenzdatei akzeptiert hat, können Sie diese entfernen. Wenn bereits eine gültige Lizenz installiert ist, wird stattdessen die Anmeldeseite angezeigt. Falls es sich bei Ihnen um eine Erstinstallation handelt, können Sie sich mit Anmeldenamen &amp;quot;admin&amp;quot; und Kennwort &amp;quot;admin&amp;quot; anmelden.&lt;br /&gt;
&lt;br /&gt;
Falls eine leere Seite oder eine Fehlerseite angezeigt wird, probieren Sie einen anderen Port aus und/oder schauen Sie in der Logdatei nach Fehlermeldungen.&lt;br /&gt;
&lt;br /&gt;
== SSL-Verschlüsselung / Proxy-Server ==&lt;br /&gt;
expecco ALM unterstützt aktuell noch nicht direkt SSL-Verschlüsselung. Über einen Proxy-Server ist diese aber problemlos einzurichten, z.B. über einen Apache-Server. Falls auf ihrem Server weitere Webseiten gehostet werden, ist dies ja ohnehin erforderlich, da sich nicht mehrere Prozesse gleichzeitig an den Port 443 binden können.&lt;br /&gt;
&lt;br /&gt;
Eine Apache2 VirtualHost-Konfiguration würde entsprechend so aussehen (angenommen expecco ALM läuft mit Port 8465 - erforderliche Anpassung für ihre Konfiguration fett):&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
   ServerName &amp;lt;b&amp;gt;expeccoalm.xyz.de&amp;lt;/b&amp;gt;&lt;br /&gt;
   ServerAdmin &amp;lt;b&amp;gt;webmaster@xyz.de&amp;lt;/b&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   Include &amp;lt;b&amp;gt;/etc/letsencrypt/ssl-xyz.de.conf&amp;lt;/b&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   SSLProxyEngine On&lt;br /&gt;
   &lt;br /&gt;
   RewriteEngine on&lt;br /&gt;
   RewriteCond %{HTTP:Upgrade} =websocket [NC]&lt;br /&gt;
   RewriteRule /(.*)           ws://localhost:&amp;lt;b&amp;gt;8465&amp;lt;/b&amp;gt;/$1 [P,L]&lt;br /&gt;
   RewriteCond %{HTTP:Upgrade} !=websocket [NC]&lt;br /&gt;
   &lt;br /&gt;
   ProxyPass /               http://localhost:&amp;lt;b&amp;gt;8465&amp;lt;/b&amp;gt;/ nocanon&lt;br /&gt;
   ProxyPassReverse /        http://localhost:&amp;lt;b&amp;gt;8465&amp;lt;/b&amp;gt;/&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die SSL-Parameter mit dem Pfaden zu Ihren Zertifkaten uns Schlüsseln würden in diesem Konfigurations-Beispiel in der Apache-globalen Datei /etc/letsencrypt/ssl-xyz.de.conf liegen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Lizenzierung ==&lt;br /&gt;
Wenn Sie expecco ALM erworben haben, erhalten Sie einen Dongle und eine Lizenzdatei. Falls Sie expecco ALM evaluieren, erhalten Sie ausschließlich die Lizenzdatei. Die Lizenzdatei beinhaltet eine für Sie individuelle expecco ALM Lizenz. So sind zum Beispiel: Der Name Ihrer Firma, für Sie freigeschaltete Module oder die Gültigkeitsdauer in der Lizenz hinterlegt. Der Dongle muss (insofern Sie expecco ALM erworben haben) ständig mit dem Server, auf dem expecco ALM ausgeführt wird, verbunden sein. Falls Sie den Dongle während des Betriebs abziehen, wird expecco ALM seinen Dienst einstellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Lizenz wechseln ==&lt;br /&gt;
[[Datei:ChangeAlmLicense.png|mini|Anhang 2]]&lt;br /&gt;
Falls Sie eine aktuelle expecco ALM Version haben, können Sie eine neue Lizenzdatei &amp;quot;expecco ALM Lizenz *.lic&amp;quot; über das Webinterface von expecco ALM einspielen. Betrachten Sie dazu den angehängten Screenshot (Anhang 2).&lt;br /&gt;
&lt;br /&gt;
Fall Sie eine ältere expecco ALM Version haben, müssen Sie folgendermaßen vorgehen:&lt;br /&gt;
&amp;lt;br&amp;gt;- Da Sie expecco ALM später neustarten müssen, tätigen Sie entsprechende Vorsorgemaßnahmen (Bspw. Benutzer abmelden, Datenbank sichern usw.)&lt;br /&gt;
&amp;lt;br&amp;gt;- Melden Sie sich auf dem Computer, der expecco ALM betreibt an&lt;br /&gt;
&amp;lt;br&amp;gt;- Begeben Sie sich in folgendes Verzeichnis &amp;quot;C:\Windows\SysWOW64\config\systemprofile\AppData\Roaming\expecco_ALM&amp;quot; oder falls es sich um ein 32Bit Betriebssystem handelt &amp;quot;C:\Windows\system32\config\systemprofile\AppData\Roaming\expecco_ALM&amp;quot; und löschen Sie die Datei &amp;quot;expecco_ALM.lic&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;- Starten Sie den expecco ALM Service über den Windows-Service-Manager neu oder beenden Sie über den Windows-Task-Manager den Prozess &amp;quot;expecco_ALM.exe&amp;quot;, in letzterem Fall wird der Windows-Service-Manager expecco ALM automatisch neustarten.&lt;br /&gt;
&amp;lt;br&amp;gt;- Nun können Sie das expecco ALM Webinterface aufrufen. Es wird eine Seite zum Installieren Ihrer expecco ALM Lizenz angezeigt (Anhang 1). Über &amp;quot;Lizenzdatei installieren&amp;quot; können Sie Ihre Lizenzdatei. auswählen. Nach dem expecco ALM Ihre Lizenzdatei akzeptiert hat, können Sie diese entfernen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Einbringen von expecco Floating-Lizenzen ==&lt;br /&gt;
Der Lizenzservice von expecco ALM vergibt verfügbare expecco Floating-Lizenzen aus einem bestimmten Pool.&amp;lt;br&amp;gt;&lt;br /&gt;
In diesen zunächst leeren Pool können von eXept erworbene expecco Floating-Lizenzen eingebracht werden.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Diese expecco Floating-Lizenzen erhalten Sie als Lizenzdatei(en) üblicherweise per E-Mail.&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Lizenzdatei kann eine oder mehrere expecco Floating-Lizenzen auch für verschiedene Komponenten (Basissystem, Plugins und Erweiterungen) enthalten.&amp;lt;br&amp;gt;&lt;br /&gt;
Sie können auch jederzeit weitere expecco Floating-Lizenzen erwerben und in den Pool einbringen.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
expecco Floating-Lizenzen werden immer spezifisch für eine expecco ALM Lizenz erstellt und sind nur mit dieser und deren Dongle nutzbar.&amp;lt;br&amp;gt;&lt;br /&gt;
Es ist also nicht notwendig solche Lizenzdateien unter Verschluss zu halten oder über eine sichere Verbindung auszutauschen.&amp;lt;br&amp;gt;&lt;br /&gt;
Allerdings sollten Sie den Dongle sicher aufbewahren bzw. Diebstahl vorbeugen.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Zur Einbringen einer expecco Floating-Lizenz öffnen Sie expecco ALM und melden Sie sich an.&amp;lt;br&amp;gt;&lt;br /&gt;
Jetzt navigieren Sie über die obere Hauptnavigationsleiste zum &amp;quot;Lizenzservice&amp;quot; Modul.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Sie befinden sich nun im Lizenzservice und Ihnen wird die Liste der installierten expecco Floating-Lizenzen angezeigt.&amp;lt;br&amp;gt;&lt;br /&gt;
Wechseln Sie zur Registerkarte &amp;quot;expecco Lizenzdateien&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Navigieren Sie mithilfe des Navigationsmenüs auf der linken Seite zu &amp;quot;Hochladen/Upload&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können Sie nun durch ein einfaches Hochladen Ihrer expecco Floating-Lizenzen selbige in den Pool einbringen.&amp;lt;br&amp;gt;&lt;br /&gt;
In der zuvor genannte Liste werden nun die eben hochgeladenen expecco Floating-Lizenzen anzeigt.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese sind von nun an auch von entfernten expecco Clients abrufbar.&amp;lt;br&amp;gt;&lt;br /&gt;
Sie können auch jederzeit weitere expecco Floating-Lizenzen erwerben und in den Pool einbringen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Lizenz Übersicht ==&lt;br /&gt;
Welche einzelnen expecco Floating-Lizenzen verfügbar oder vergeben sind, &amp;lt;br&amp;gt;&lt;br /&gt;
erfahren Sie indem Sie zur Registerkarte &amp;quot;expecco Lizenzen&amp;quot; wechseln.&amp;lt;br&amp;gt;&lt;br /&gt;
Insbesondere ist hieraus ersichtlich, welcher Rechner/Benutzer welche expecco Floating-Lizenz aktuell nutzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Dies ist beispielsweise sinnvoll, wenn ein expecco Client seine Sitzung versehentlich nicht beendet hat,&amp;lt;br&amp;gt;&lt;br /&gt;
und andere Nutzer eine entsprechende Lizenz benötigen.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Installation&amp;diff=30837</id>
		<title>Installation</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Installation&amp;diff=30837"/>
		<updated>2025-09-04T08:38:38Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Auslösen einer Floating-Lizenz */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Installation/en#Additional_Packages_and_Frameworks| English Version]]&lt;br /&gt;
&lt;br /&gt;
== Installation von expecco auf Windows ==&lt;br /&gt;
&lt;br /&gt;
Sie erhalten eine E-Mail mit dem Link zu der expecco-Installationsdatei. Die Installationsdatei hat z.B. den Namen:&lt;br /&gt;
&lt;br /&gt;
* expeccoSetup64-23.1.0.50.exe -&amp;gt; für die expecco-Basisinstallation&lt;br /&gt;
&lt;br /&gt;
wobei hier 23.1.0 der Versionsnummer von expecco entspricht und 50 der Build-Nummer (&amp;quot;23.1.0.50&amp;quot; entspricht hier der Version zum Zeitpunkt der Erstellung dieses Dokuments - Sie werden mit Sicherheit eine andere Versionsnummer sehen).&lt;br /&gt;
&lt;br /&gt;
Bitte laden Sie das Installationsprogramm auf Ihren Rechner.&lt;br /&gt;
&lt;br /&gt;
=== Windows SmartScreen / Blockierte Ausführung ===&lt;br /&gt;
&lt;br /&gt;
Führen Sie das Installationsprogramm für die expecco-Basisinstallation aus (&#039;&#039;expeccoSetup64-***.exe&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Es kann vorkommen, dass Ihr Anti-Virus-Programm wie bspw. der [https://de.wikipedia.org/wiki/SmartScreen-Filter], die Installation blockiert. Dies ist bei neuen oder Vorab-expecco-Versionen vermutlich damit begründet, dass Ihr Anti-Virus-Programm unsere Software noch nicht gut genug kennt. Bitte stellen Sie in dem Fall sicher, dass die Installationsdatei ausschließlich aus einer der folgenden Quellen heruntergeladen wurde https://exept.de/*, https://download.exept.de/*, https://cloud.exept.de/*. Wenn Sie sich sicher sind, dass die Installationsdatei von uns stammt, können Sie ohne Bedenken die Blockierung Ihres Anti-Virus-Programms ignorieren. Unsere Installationsprogramme sind auch mit einem Zertifikat der eXept Software AG signiert.&lt;br /&gt;
&lt;br /&gt;
Die Installationsdatei für expecco sowie die expecco Programme sind mit dem digitalen Zertifikat von eXept Software AG signiert.&lt;br /&gt;
&lt;br /&gt;
Im Falle vom [https://de.wikipedia.org/wiki/SmartScreen-Filter], gehen Sie bitte auf &amp;quot;Weitere Informationen&amp;quot; und dann auf &amp;quot;Trotzdem ausführen&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Windows_SmartScreen.png|300px|Report Settings]] [[Bild:Windows_SmartScreen_Trozdem_ausführen.png|300px|Report Settings]]&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Anti-Virus-Programm haben, informieren Sie sich bitte wie man dort die Blockierung ignorieren oder die Installationsdatei als Ausnahme definieren kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Folgen Sie dabei dem Installationsassistenten.&lt;br /&gt;
Sie können hier das Laufwerk und das Verzeichnis angeben, unter dem expecco installiert werden soll.&lt;br /&gt;
Außerdem können Sie die Komponenten angeben, die Sie installieren wollen.&lt;br /&gt;
&lt;br /&gt;
Falls Sie Plugins für expecco lizenziert haben, können Sie bei der Installation die entsprechenden expecco-Plugins auswählen.&lt;br /&gt;
Angeboten werden alle Plugins - auch solche für die Sie keine Lizenzen erworben haben.&lt;br /&gt;
Falls Sie nicht lizenzierte Plugins installieren, ist deren Funktion in expecco nicht verfügbar und entsprechende Menu-Einträge entweder unsichtbar oder ausgegraut.&lt;br /&gt;
&amp;lt;br&amp;gt;Installierte, aber nicht lizenzierte Plugins sind erst dann verfügbar, wenn die dazu passenden Lizenzen (nach-)installiert wurden.&lt;br /&gt;
Ansonsten belegen Sie nur Platz auf der Festplatte.&lt;br /&gt;
Weitere Plugins können auch jederzeit nachträglich installiert werden. Auch können auch weitere Lizenzen jederzeit später erworben werden.&lt;br /&gt;
&lt;br /&gt;
Nach der Installation finden Sie auf Ihrem Desktop das expecco-Symbol.&lt;br /&gt;
Über dieses Symbol können Sie expecco nun starten.&lt;br /&gt;
Beim erstmaligen Ausführen, erscheint ein Fenster, in dem eine Lizenz verlangt wird.&lt;br /&gt;
Je nachdem, ob Sie eine Einzellizenz oder eine Floating-Lizenz (per Lizenzserver) nutzen, müssen Sie die Lizenz entsprechend nachfolgender Beschreibung installieren.&lt;br /&gt;
&lt;br /&gt;
=== Automatische Installation von expecco via Commandline (Windows) ===&lt;br /&gt;
&lt;br /&gt;
Sie können expecco über die Kommandozeile, via Batchdatei oder ähnlichem installieren. Führen Sie dazu expecco wie folgt aus:&lt;br /&gt;
    expeccoSetup-x.x.exe /S&lt;br /&gt;
Das &amp;quot;/S&amp;quot; steht für &amp;quot;&#039;&#039;Silent&#039;&#039;&amp;quot; und expecco installiert sich ohne GUI und ohne Fragen zu stellen.&lt;br /&gt;
Sie können optional auch ein spezifisches Installationsverzeichnis angeben:&lt;br /&gt;
    expeccoSetup-x.x.exe /S /D=&amp;quot;C:\Program Files (x86)\exept&amp;quot;&lt;br /&gt;
Damit expecco nach der Installation direkt starten kann, muss sichergestellt werden, dass eine Lizenz auf dem Zielrechner vorhanden ist. Hierfür kommen folgende Varianten in Frage.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lizenz aus lokaler Lizenzdatei und Dongle&#039;&#039;&#039;:&amp;lt;br&amp;gt;&lt;br /&gt;
Stecken Sie den Dongle in den Zielrechner. Kopieren Sie Ihre Lizenzdatei in Ihr Benutzerverzeichnis bspw. &amp;quot;&amp;lt;code&amp;gt;C:\Users\IhrBenutzername\&amp;lt;/code&amp;gt;&amp;quot; unter dem Namen &amp;quot;&amp;lt;code&amp;gt;.expeccoLicense&amp;lt;/code&amp;gt;&amp;quot;, sodass die Datei &amp;quot;&amp;lt;code&amp;gt;C:\Users\IhrBenutzername\.expeccoLicense&amp;lt;/code&amp;gt;&amp;quot; Ihrer Lizenzdatei entspricht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lizenz vom Lizenzserver&#039;&#039;&#039;:&lt;br /&gt;
Hier müssen zunächst eine &amp;quot;Template&amp;quot; Lizenzdatei und &amp;quot;Template&amp;quot; expecco Einstellungen-Datei erstellt werden. Sie benötigen dafür ein laufendes expecco, welches mit Ihrem Lizenzserver verbunden ist. Starten Sie dieses expecco und konfigurieren Sie unter &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenz vom Lizenzserver&#039;&#039;&amp;quot; Ihre &amp;quot;Template&amp;quot; Lizenzdatei. Diese sollte alle Plugins, die auf dem Zielrechner für die automatisierte expecco Installation über Commandline benötigt werden, enthalten. Fordern Sie diese Lizenz vom Lizenzserver an. Setzen Sie den Haken &amp;quot;Lizenzserver nutzen&amp;quot; und drücken Sie anschließend &amp;quot;Sichern&amp;quot;. expecco hat nun die benötigten Template Dateien unter &amp;quot;&amp;lt;code&amp;gt;C:\Users\IhrBenutzername\AppData\Roaming\expecco&amp;lt;/code&amp;gt;&amp;quot; angelegt. Kopieren Sie die &amp;quot;&amp;lt;code&amp;gt;.expeccoPreferences&amp;lt;/code&amp;gt;&amp;quot; und die &amp;quot;&amp;lt;code&amp;gt;expeccoLicenseServerLicense&amp;lt;/code&amp;gt;&amp;quot; Datei vor der automatischen expecco Installation in das entsprechende Verzeichnis auf Ihrem Zielrechner. expecco kann somit direkt nach der automatischen Installation starten.&lt;br /&gt;
&lt;br /&gt;
=== Autostart von expecco ===&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie dazu mit der &amp;lt;kbd&amp;gt;Windows-Taste&amp;lt;/KBD&amp;gt; + &amp;lt;KBD&amp;gt;&amp;quot;R&amp;quot;&amp;lt;/KBD&amp;gt; ein Ausführungs-Fenster. Geben Sie dort &amp;quot;shell:startup&amp;quot; ein. Danach öffnet sich der Autostart-Ordner. Kopieren Sie die expecco-Verknüpfung vom Desktop in diesen Ordner. Nun wird expecco, nachdem sich dieser Benutzer angemeldet hat, automatisch gestartet. Folgend können Sie konfigurieren, dass sich dieser Benutzer automatisch anmeldet, wenn der Rechner angeschaltet wird. Drücken Sie dazu erneut &amp;lt;KBD&amp;gt;Windows-Taste&amp;lt;/KBD&amp;gt; + &amp;lt;KBD&amp;gt;&amp;quot;R&amp;quot;&amp;lt;/KBD&amp;gt;. Geben Sie nun &amp;quot;netplwiz&amp;quot; ein. Es öffnet sich der Benutzerkonten-Dialog. In diesem können Sie den Haken &amp;quot;Benutzer müssen Benutzernamen und Kennwort eingeben&amp;quot; abwählen. Diese Einstellung gilt nur für das Anmelden nachdem der Rechner hochgefahren ist.&lt;br /&gt;
&lt;br /&gt;
Übrigens können diverse Parameter auf der [[Command Line Options|expecco-Kommandozeile]] angegeben werden. Hier sind insbesondere die Optionen [[Command Line Options#Startup|&amp;quot;--licenseFile&amp;quot;]], [[Command Line Options#Startup|&amp;quot;--licenseServer&amp;quot;]] und [[Command Line Options#Startup|&amp;quot;--licenseServerPort&amp;quot;]] zu erwähnen.&lt;br /&gt;
&lt;br /&gt;
=== expecco Einstellungen vordefinieren ===&lt;br /&gt;
&lt;br /&gt;
Es kann in bestimmten Fällen Sinn machen, die expecco Einstellungen für neue Windows-Benutzerkonten vorzudefinieren.&lt;br /&gt;
Z.B. könnte man die Adresse des Lizenzserver und die benötigten Pluginlizenzen vordefinieren.&lt;br /&gt;
Dies hätte den Vorteil, dass neue Benutzer direkt mit expecco loslegen können.&lt;br /&gt;
&lt;br /&gt;
Gehen Sie zum Vordefinieren der expecco Einstellungen für neue Windows-Benutzerkonten folgendermaßen vor:&lt;br /&gt;
* starten Sie expecco auf einem bereits vorhandenen Benutzerkonto (kann auch ein anderer Windows Rechner sein)&lt;br /&gt;
* stellen Sie dessen expecco Einstellungen (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot;) wie zur Vorlage gewünscht ein und speichern Sie über &amp;quot;&#039;&#039;Sichern&#039;&#039;&amp;quot;&lt;br /&gt;
* navigieren Sie zu dem Verzeichnis &amp;quot;C:\Users\{IhrBenutzer}\AppData\Roaming\expecco\&amp;quot; und kopieren Sie die 2 Dateien &amp;quot;.expeccoPreferences&amp;quot; und &amp;quot;expeccoLicenseServerLicense&amp;quot;&lt;br /&gt;
* begeben Sie sich zum Zielrechner und erstellen Sie einen Ordner &amp;quot;expecco&amp;quot; unter &amp;quot;C:\Users\Default\AppData\Roaming\&amp;quot;&lt;br /&gt;
* fügen Sie die 2 kopierten Dateien auf dem Zielrechner unter &amp;quot;C:\Users\Default\AppData\Roaming\expecco\&amp;quot; ein&lt;br /&gt;
&lt;br /&gt;
Jetzt werden alle neuen Windows-Benutzerkonten diese Einstellungen als Ausgangseinstellungen verwenden. Sie können diese Einstellungen auch bereits existierenden Windows-Benutzerkonten zuweisen. Hierfür fügen Sie die 2 Dateien in die entsprechenden Benutzerverzeichnisse auf dem Zielrechner &amp;quot;C:\Users\{ExistierenderBenutzer}\AppData\Roaming\expecco\&amp;quot; ein.&lt;br /&gt;
&lt;br /&gt;
ACHTUNG: damit werden alle bereits getätigen Einstellungen der Benutzer überschrieben.&lt;br /&gt;
&lt;br /&gt;
=== Update Installation von expecco (Windows) ===&lt;br /&gt;
&lt;br /&gt;
Wie bei der Erstinstallation erhalten eine E-Mail mit dem Link zu den neuen expecco-Installationsdateien.&lt;br /&gt;
Bitte laden Sie die Installationsprogramme herunter.&lt;br /&gt;
Bei der Ausführung des Basis-Installationsprogramms &amp;quot;&amp;lt;code&amp;gt;expeccoSetup-xxx.exe&amp;lt;/code&amp;gt;&amp;quot; erkennt expecco, dass es bereits installiert ist, und zeigt einen Dialog an, in dem Sie um eine Bestätigung gebeten werden, dass die alte expecco-Version deinstalliert werden darf.&lt;br /&gt;
Bestätigen Sie bitte diesen Dialog. Die alte expecco-Version wird mit allen Plugins deinstalliert.&lt;br /&gt;
Ihre Einstellungen, Lizenzdateien und Ihre Testsuiten bleiben erhalten.&lt;br /&gt;
Anschließend wird die neue expecco-Version wie bei der Erstinstallation (s.o.) installiert.&lt;br /&gt;
&lt;br /&gt;
=== Lizenz installieren ===&lt;br /&gt;
&lt;br /&gt;
Beim erstmaligen Ausführen erscheint ein Fenster, in dem eine Lizenz verlangt wird. Je nachdem, ob Sie eine Einzellizenz oder eine Floating-Lizenz (per Lizenzserver) nutzen, können Sie die Lizenz konfigurieren.&lt;br /&gt;
&lt;br /&gt;
[[#Konfiguration der Einzellizenz | Konfiguration der Einzellizenz]]&lt;br /&gt;
&lt;br /&gt;
[[#Konfiguration der Floating-Lizenz | Konfiguration der Floating-Lizenz]]&lt;br /&gt;
&lt;br /&gt;
== Installation von expecco auf Linux ==&lt;br /&gt;
&lt;br /&gt;
expecco läuft auf allen aktuellen Linux-Distributionen (Ubuntu, RedHat, Fedora, Oracle Linux, Debian, (Open-)SuSE, ...).&lt;br /&gt;
&lt;br /&gt;
=== Benötigte Linux Softwarepakete ===&lt;br /&gt;
&lt;br /&gt;
expecco läuft sowohl auf 32- als auch auf 64-bit Linux Systemen. Sie können expecco wahlweise als 64-bit-Version oder 32-bit-Version installieren.&lt;br /&gt;
Falls sie ein 64-bit Linux einsetzten (das ist mittlerweile der Standard) empfehlen wir die 64-bit expecco-Version.&amp;lt;br&amp;gt;&#039;&#039;&#039;Die 32-bit Linux-Version liefern wir nur noch auf Anfrage aus.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es wird eine glibc in der Version &amp;gt;= 2.14 benötigt.&lt;br /&gt;
&lt;br /&gt;
Installieren Sie über Ihren Paketmanager Ihrer Linux-Distribution folgende Pakete:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;libXinerama&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;libxrandr&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;libXft&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;libusb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;unixODBC&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;odbcinst&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;libglib-2_0-0&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;gnuplot&amp;lt;/code&amp;gt; (optional - falls Plot/Graph Aktionen benötigt)&lt;br /&gt;
&lt;br /&gt;
Diese Pakete hängen von weiteren Paketen ab, die der Paketmanager automatisch mit installiert.&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;Ubuntu (ab 15.04)&#039;&#039;&#039; installieren Sie die Pakete mit dem Kommando:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install -y \&lt;br /&gt;
        libxinerama1 libxft2 libxrandr2 unixodbc odbcinst libusb-1.0.0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;OpenSUSE (Leap 15.x)&#039;&#039;&#039; installieren Sie die Pakete mit:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;code&amp;gt;sudo zypper install unixODBC libXinerama1 libXrandr2 libXft2 libusb-0_1-4 libusb-1_0-0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Installation von 32-bit expecco auf 64-bit Linux (nicht empfohlen!) ====&lt;br /&gt;
&lt;br /&gt;
Diese Konfiguration empfehlen wir nicht. Nutzen Sie stattdessen besser die 64-bit expecco Version. &lt;br /&gt;
Falls Sie expecco-32-bit doch auf 64-bit-Linux installieren wollen, benötigen Sie die Pakete in der 32-bit Ausführung.&lt;br /&gt;
&lt;br /&gt;
Es wird eine glibc in der Version &amp;gt;= 2.10 benötigt.&lt;br /&gt;
&lt;br /&gt;
In Ubuntu 64bit (ab 15.04 64-bit) für ein 32-bit expecco installieren Sie die Pakete mit dem Kommando:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install -y \&lt;br /&gt;
        libxinerama1:i386 libxft2:i386 libxrandr2:i386 unixodbc:i386 odbcinst:i386 libusb-1.0.0:i386&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Installation von expecco (Linux) ===&lt;br /&gt;
&lt;br /&gt;
Sie erhalten eine E-Mail mit dem Link zu der expecco-Installationsdatei. Die Installationsdatei hat z.B. den Namen:&lt;br /&gt;
&lt;br /&gt;
* expecco-23.2.0.69.package&lt;br /&gt;
&lt;br /&gt;
wobei hier 23.2.0 der Versionsnummer von expecco entspricht und 69 der Build-Nummer. Die Installationsdatei enthält das expecco-Basispaket sowie die Plugins.&lt;br /&gt;
&lt;br /&gt;
Für die Installation benötigen Sie bei einer erstmaligen Installation außerdem noch das &#039;&#039;autopackage&#039;&#039; Paket. Sie können es hier herunterladen: https://download.exept.de/transfer/autopackage/x86_64/autopackage.tar.bz2. Entpacken Sie das Archive und installieren Sie dieses durch das Ausführen der INSTALL Datei im Root Verzeichnis des Archives. Sie werden ggf. gefragt ob die GUI Komponenten vom &amp;quot;Autopackage&amp;quot; herunter geladen und installiert werden sollen. Wählen Sie &amp;quot;NEIN&amp;quot; aus, da diese nicht benötigt werden und unter Umständen zu Fehlern führen können. &lt;br /&gt;
&lt;br /&gt;
Laden Sie die expecco-Installationsdatei und ggf. &#039;&#039;autopackage.tar.bz2&#039;&#039; in dasselbe Verzeichnis auf Ihrem Rechner.&lt;br /&gt;
&lt;br /&gt;
Sie können die Installation als Benutzer &#039;&#039;root&#039;&#039; oder als normaler Benutzer ausführen. Wenn Sie expecco als Benutzer &#039;&#039;root&#039;&#039; installieren, wird expecco im Verzeichnis &#039;&#039;/opt/expecco/bin&#039;&#039; installiert. Bei einer Installation als normaler Benutzer, wird expecco in Ihrem Home-Verzeichnis nach &#039;&#039;.local/bin&#039;&#039; installiert. &lt;br /&gt;
&lt;br /&gt;
Führen Sie aus:&lt;br /&gt;
    bash ./expecco-23.2.0.69.package&lt;br /&gt;
&lt;br /&gt;
expecco wird daraufhin installiert, es erscheint folgende Ausgabe:&lt;br /&gt;
 # Preparing package: expecco - Graphical Test Modeling&lt;br /&gt;
 # Checking for required C library versions ... passed&lt;br /&gt;
 This may take a moment, please wait ... done&lt;br /&gt;
 # Installing package: expecco - Graphical Test Modeling (package 1 of 1)&lt;br /&gt;
 # 100%[==================================================] Extracting&lt;br /&gt;
 # Copying files to /opt/expecco/plugin&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/technologyBridge&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/technologyBridge/javaBridge&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/technologyBridge/javaBridge/javaBridge_Server_Client&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/packages/stx/libsnmp&lt;br /&gt;
 # Copying files to /opt/expecco/packages/stx/libsnmp/net-snmp-5.7.2/mibs&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/testsuites/libraries&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/bin&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/lib&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/expecco/doc&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/testsuites/libraries&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/testsuites/examples&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/expecco/reportGenerator/tools&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/pdf/afm&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Installing USB Dongle access...&lt;br /&gt;
 # Updating package database...&lt;br /&gt;
 The following package was successfully installed:&lt;br /&gt;
 * expecco - Graphical Test Modeling&lt;br /&gt;
 This installation used 478.74 MiB (502.00 MB) of disk space.&lt;br /&gt;
 Remove this package by running package remove expecco from the command line.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Installations-Optionen ===&lt;br /&gt;
&lt;br /&gt;
Sie können das Verzeichnis, in das expecco installiert wird, wie folgt festlegen:&lt;br /&gt;
&lt;br /&gt;
    bash expecco-23.2.0.69.package&lt;br /&gt;
             Installation als root nach /opt/expecco (Starten mit: /opt/expecco/bin/expecco)&lt;br /&gt;
&lt;br /&gt;
    bash expecco-23.2.0.69.package --prefix /opt/expecco-23.2&lt;br /&gt;
             Installation als root nach /opt/expecco-23.2 (Starten mit: /opt/expecco-23.2/bin/expecco)&lt;br /&gt;
&lt;br /&gt;
    bash expecco-23.2.0.69.package --local-only&lt;br /&gt;
             Installation als Benutzer nach $HOME/.local (Starten mit ~/.local/bin/expecco)&lt;br /&gt;
&lt;br /&gt;
    bash expecco-23.2.0.69.package --local-only --prefix ~/expecco&lt;br /&gt;
             Installation als Benutzer nach $HOME/expecco (Starten mit ~/expecco/bin/expecco)&lt;br /&gt;
&lt;br /&gt;
=== Update Installation von expecco (Linux) ===&lt;br /&gt;
&lt;br /&gt;
Wie bei der Erstinstallation erhalten eine E-Mail mit dem Link zu der neuen expecco-Installationsdatei.&lt;br /&gt;
Bitte laden Sie das Installationsprogramme herunter. Bei der Ausführung des Installationsprogramms &#039;&#039;bash expecco-***.package&#039;&#039; erkennt expecco, dass eine andere Version bereits installiert wurde. Die alte expecco-Version wird mit allen Plugins automatisch deinstalliert. Ihre Einstellungen, Lizenzdateien und Ihre Testsuiten bleiben erhalten. Anschließend wird die neue expecco-Version wie bei der Erstinstallation (s.o.) installiert.&lt;br /&gt;
&lt;br /&gt;
=== Deinstallieren ===&lt;br /&gt;
&lt;br /&gt;
    autopackage uninstall expecco&lt;br /&gt;
&lt;br /&gt;
=== Lizenz installieren ===&lt;br /&gt;
&lt;br /&gt;
Installieren Sie die Lizenz wie im nächsten Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
== Installation von expecco auf OS X ==&lt;br /&gt;
&lt;br /&gt;
Achtung: die OS X-Version ist z.Z. im Beta Test und auf Anfrage verfügbar.&lt;br /&gt;
&lt;br /&gt;
=== Benötigte macOS Softwarepakete ===&lt;br /&gt;
&lt;br /&gt;
expecco läuft auf 64-bit x64_64 mac OS X Systemen (eine Version für ältere 32bit Maschinen ist nur noch auf Anfrage erhältlich; beachten Sie, dass die neueren OS X Versionen 32bit Programme nicht mehr unterstützen).&lt;br /&gt;
Es wird mindestens OS X 10.6 benötigt.&lt;br /&gt;
&lt;br /&gt;
expecco benötigt XQuartz. Dieses sollten Sie vorher vom Apple Store oder [https://www.xquartz.org/ xquartz.org] installieren, falls nicht bereits vorinstalliert (kostenlos).&lt;br /&gt;
&lt;br /&gt;
=== Installation von expecco (OS X) ===&lt;br /&gt;
&lt;br /&gt;
Sie erhalten eine E-Mail mit dem Link zu der expecco-Installationsdatei. Die Installationsdatei hat z.B. den Namen:&lt;br /&gt;
&lt;br /&gt;
* expecco-2.11.0.1.dmg&lt;br /&gt;
&lt;br /&gt;
wobei hier 2.11.0 der Versionsnummer von expecco entspricht und 1 der Build-Nummer. Die Installationsdatei enthält das expecco-Basispaket sowie die Plugins.&lt;br /&gt;
&lt;br /&gt;
Zur Installation öffnen Sie die &amp;quot;&amp;lt;code&amp;gt;dmg&amp;lt;/code&amp;gt;&amp;quot;-Datei und verschieben &amp;quot;&amp;lt;code&amp;gt;expecco.app&amp;lt;/code&amp;gt;&amp;quot; in den &amp;quot;&amp;lt;code&amp;gt;Application&amp;lt;/code&amp;gt;&amp;quot;-Ordner (oder Ihren privaten &amp;quot;&amp;lt;code&amp;gt;Application&amp;lt;/code&amp;gt;&amp;quot;-Ordner, oder jeden beliebigen anderen Ordner).&lt;br /&gt;
&lt;br /&gt;
=== Deinstallation von expecco (OS X) ===&lt;br /&gt;
Sämtliche Dateien von expecco, mit Ausnahme Ihrer eigenen Suiten und Einstellungen sind im expecco.app Ordner. Löschen Sie diesen Ordner (und entleeren den Papierkorb) um expecco zu deinstallieren.&lt;br /&gt;
Ihre eigenen Einstellungen befinden sich im Homeverzeichnis unter &amp;quot;.expecco&amp;quot;; Ihre Suiten sind im Documentsordner, falls nicht explizit an anderer Stelle gespeichert.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration der Lizenz ==&lt;br /&gt;
&lt;br /&gt;
Beim erstmaligen Ausführen erscheint ein Fenster, in dem eine Lizenz verlangt wird. Falls Sie bereits eine Lizenz installiert haben und diese wechseln möchten können Sie den selben Dialog unter &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot; öffnen, allerdings müssen Sie in diesem Fall nach dem Wechseln der Lizenz expecco neu starten.&lt;br /&gt;
&lt;br /&gt;
Fall Sie expecco auf einem Computer ohne GUI installiert haben, kann das zuvor erwähnte Fenster nicht geöffnet werden. In dem Fall müssen Sie expecco auch auf einem Computer mit GUI installieren und dort den Dialog ausfüllen. Danach kopieren Sie die Settingsdatei &amp;quot;&amp;lt;code&amp;gt;~/.expecco/.expeccoPreferences&amp;lt;/code&amp;gt;&amp;quot; oder &amp;quot;&amp;lt;code&amp;gt;C:\users\IhrBenutzer\AppData\Roaming\expecco\.expeccoPreferences&amp;lt;/code&amp;gt;&amp;quot; und die Lizenzdatei &amp;quot;&amp;lt;code&amp;gt;~/.expecco/expeccoLicenseServerLicense&amp;lt;/code&amp;gt;&amp;quot; oder &amp;quot;&amp;lt;code&amp;gt;C:\users\IhrBenutzer\AppData\Roaming\expecco\expeccoLicenseServerLicense&amp;lt;/code&amp;gt;&amp;quot; auf den Computer ohne GUI. &lt;br /&gt;
&lt;br /&gt;
[[#Konfiguration der Einzellizenz | Konfiguration der Einzellizenz]]&lt;br /&gt;
&lt;br /&gt;
[[#Konfiguration der Floating-Lizenz | Konfiguration der Floating-Lizenz]]&lt;br /&gt;
&lt;br /&gt;
[[#Auslösen einer Floating-Lizenz | Auslösen einer Floating-Lizenz]]&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration der Einzellizenz ===&lt;br /&gt;
&lt;br /&gt;
Einzellizenzen werden üblicherweise mit einem USB-Dongle genutzt.&lt;br /&gt;
Ausnahmsweise können auch zeitlich limitierte Einzellizenzen ohne Dongle verwendet werden (sog. &amp;quot;&#039;&#039;Demo Lizenz&#039;&#039;&amp;quot;).&lt;br /&gt;
In beiden Fällen erhalten Sie eine Lizenzdatei.&lt;br /&gt;
Lizenzdateien und Dongle müssen jeweils zusammenpassen, wobei eine Lizenzdatei auch zu mehreren Dongles desselben Kunden passen kann.&lt;br /&gt;
&lt;br /&gt;
# falls Sie einen Dongle erhalten haben, stecken Sie ihn in einen freien USB-Port in Ihrem Rechner.&lt;br /&gt;
# Speichern Sie die Lizenzdatei auf Ihrem Rechner&lt;br /&gt;
# Ziehen Sie dann entweder die Datei mit der Maus aus dem Windows-Explorer in den Lizenzdialog, oder Sie wählen im Lizenzdialog Ihre Lizenzdatei direkt aus.&lt;br /&gt;
# Sie werden aufgefordert, expecco neu zu starten. Nach dem Neustart können Sie expecco nutzen.&lt;br /&gt;
&lt;br /&gt;
Lizenzdateien ohne Dongle sind zeitlich beschränkt.&lt;br /&gt;
Wenn Sie versehentlich den expecco-Dongle nicht in Ihren Rechner eingesteckt haben und expecco starten, erhalten Sie einen Hinweis, dass die Lizenz abgelaufen sei.&lt;br /&gt;
Sobald Sie den Dongle einstecken (bevor Sie expecco starten), erscheint dieser Hinweis beim Start von expecco nicht mehr.&lt;br /&gt;
&lt;br /&gt;
Solange Sie mit expecco arbeiten, wird überwacht, ob der Dongle vorhanden ist.&lt;br /&gt;
Wenn Sie den Dongle währenddessen aus Ihrem Rechner entfernen, erhalten Sie einen Hinweis und können keine Tests mehr ausführen oder verändern.&lt;br /&gt;
Sie können allerdings die gerade bearbeitete Testsuite noch abspeichern, so dass keine Änderungen verloren gehen.&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration der Floating-Lizenz ===&lt;br /&gt;
&lt;br /&gt;
Um eine Floating-Lizenz zu nutzen, benötigen Sie einen expecco-Lizenzserver. Diesen (bzw. den Downloadlink) erhalten Sie von uns mit den Floatinglizenzen. Der Lizenzserver ist eine HTTP-Serviceanwendung, die auf einem beliebigen Rechner in einer Cloud oder Ihrer Firma oder Abteilung installiert wird. Sie läuft ohne eigenes Fenster, und wird über einen beliebigen WebBrowser bedient.&lt;br /&gt;
&lt;br /&gt;
Der Lizenzserver ist unter einem Rechnername bzw. IP-Adresse und einer Portnummer zu erreichen.&lt;br /&gt;
Der Administrator des Lizenzservers kann Ihnen diese Informationen geben, falls er eine andere als die default-Portnummer konfiguriert hat.&lt;br /&gt;
Es muss sichergestellt sein, dass eine TCP-Verbindung zum entsprechenden Port im Lizenzserver aufgebaut werden kann.&lt;br /&gt;
Router und Firewalls sind gegebenenfalls entsprechend zu konfigurieren bzw. Ports freizuschalten.&lt;br /&gt;
&lt;br /&gt;
Beim Start von expecco öffnet sich der Lizenzdialog.&lt;br /&gt;
Wählen Sie hier die Lizenzserver-Kachel aus.&lt;br /&gt;
Tragen Sie den Rechnernamen bzw. die IP-Adresse sowie die Portnummer des Lizenzservers ein.&lt;br /&gt;
Im allgemeinen kann die vorgeschlagene default Portnummer unverändert übernommen werden.&lt;br /&gt;
Lediglich in Netzwerken, bei denen nur bestimmte Ports durch Firewalls oder Router durchgeschaltet werden ist es u.U. notwendig, eine andere Portnummer zu verwenden.&lt;br /&gt;
Der Administrator des Lizenzservers kann Ihnen in diesem Fall diese Informationen geben&lt;br /&gt;
&lt;br /&gt;
Sie können jetzt auswählen, welche expecco-Ausprägung Sie verwenden wollen: &#039;&#039;expecco-developer&#039;&#039; oder &#039;&#039;expecco-runtime&#039;&#039;.&lt;br /&gt;
Über die Schaltfläche &amp;quot;&#039;&#039;Plugin-Liste vom Server aktualisieren&#039;&#039;&amp;quot; erhalten Sie die verfügbaren Plugins (bzw. Plugins für die noch Floating-Lizenzen verfügbar sind).&lt;br /&gt;
Wählen Sie die Plugins aus, die Sie für Ihre Tests benötigen.&lt;br /&gt;
Von den meisten Plugins benötigen Sie nur eine Lizenz.&lt;br /&gt;
Einzelne Plugins können für auf mehrere Rechner verteilte Tests mehr als eine Lizenz von einem Plugin benötigen - Sie können das für derartige Plugins angeben.&lt;br /&gt;
Im Dialog wird angezeigt, wie viele Lizenzen für ein bestimmtes Plugin auf dem Lizenzserver momentan noch zur Verfügung stehen.&lt;br /&gt;
Per Tooltip können Sie auch in Erfahrung bringen, wie viele Lizenzen generell vorhanden sind.&lt;br /&gt;
Die Differenz sind die momentan von anderen Benutzern verwendeten Lizenzen.&lt;br /&gt;
&lt;br /&gt;
Über die Schaltfläche &amp;quot;&#039;&#039;Lizenzdatei installieren&#039;&#039;&amp;quot; werden die Lizenzen vom Lizenzserver abonniert.&lt;br /&gt;
Starten Sie jetzt expecco neu, damit die lizenzierten Plugins geladen werden.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco beendet wird, werden alle Lizenzen wieder an den Lizenzserver zurück gegeben.&lt;br /&gt;
Expecco erneuert regelmäßig die Lizenzen vom Lizenzserver.&lt;br /&gt;
Wenn der Lizenzserver über einen gewissen Zeitraum nicht mehr erreichbar sein sollte (ca. 15 Minuten), wird expecco gesperrt, so dass keine Tests mehr ausgeführt oder verändert werden können. Geänderte Testsuiten können aber noch abgespeichert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco nicht regulär beendet wurde, z.B. wenn der Rechner einfach ausgeschaltet wird, fallen die Lizenzen nach diesem Zeitraum an den Lizenzserver zurück und können dann von anderen Benutzern genutzt werden.&lt;br /&gt;
&lt;br /&gt;
expecco merkt sich, welche Lizenzen zuletzt abonniert wurden.&lt;br /&gt;
Wenn expecco gestartet wird, versucht es, die zuletzt abonnierten Lizenzen wieder zu erhalten.&lt;br /&gt;
Sollte das nicht möglich sein, da alle Lizenzen momentan vergeben sind, erscheint der Lizenzdialog, in dem die nicht oder nur teilweise erhaltenen Lizenzen rot unterlegt sind.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie neue Lizenzen benötigen oder bisher verwendete Lizenzen nicht mehr benötigen, können Sie die anzufordernden Lizenzen jederzeit über den Lizenzdialog anpassen.&lt;br /&gt;
Sie erreichen ihn über das Menü &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Auslösen einer Floating-Lizenz ===&lt;br /&gt;
&lt;br /&gt;
Floatinglizenzen können auch ohne bestehende Verbindung zum Lizenzserver ausgelöst werden (sog. &amp;quot;&#039;&#039;road warrior&#039;&#039; Lizenzen&amp;quot;). Dies ermöglicht es Ihnen, auch zuhause, bei Kunden oder in isolierten Labors mit expecco zu arbeiten, ohne dass dafür ein Dongle benötigt wird.&lt;br /&gt;
&lt;br /&gt;
Auch wenn Ihr expecco keine Netzwerkverbindung hat, ist es möglich expecco mit einer Floating-Lizenz zu betreiben. Die Lizenz für expecco wird für eine bestimmte Zeitspanne ausgelöst. Nachdem diese Zeitspanne verstrichen ist, wird die ausgelöste Lizenz automatisch wieder zurückgegeben (eingegliedert). Bitte beachten Sie, dass es &#039;&#039;&#039;keine Möglichkeit gibt, eine ausgelöste Lizenz vor ihrem Ablauf wieder zurückzugeben!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hierfür brauchen Sie einen Lizenzservice (expecco ALM), aus welchem die Floating-Lizenz ausgelöst wird. Der Lizenzserver benötigt einen speziellen Dongle, der die Funktion unterstützt. &#039;&#039;&#039;Falls der Lizenzserver ohne Dongle an eine MAC-Adresse gebunden ist, steht diese Funktion nicht zur Verfügung!&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Zum Auslösen einer Floating-Lizenz starten Sie expecco und rufen Sie den Lizenzdialog unter &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot; auf (beim erstmaligem Start erscheint dieser automatisch) und navigieren Sie in den Reiter &amp;quot;Ausgelöste Floating-Lizenz&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Dort haben Sie folgende Möglichkeiten:&lt;br /&gt;
==== Eine Anfrage zum Auslösen einer Floating-Lizenz erstellen ====&lt;br /&gt;
Stellen Sie sich Ihre gewünschte Lizenz zusammen. Definieren Sie den Typ (Runtime / Pro), die Plugins und wie lange Sie die Lizenz auslösen möchten. Sie können Ihre Anfrage dann entweder in eine Datei speichern oder in die Zwischenablage legen.&lt;br /&gt;
&lt;br /&gt;
Rufen Sie nun das Web-Interface des Lizenzservices (expecco ALM) in einem Webbrowser auf. Navigieren Sie in expecco ALM zu &amp;quot;&#039;&#039;Lizenzservice&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;expecco Lizenzen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenz auslösen&#039;&#039;&amp;quot;. Dort können Sie dann Ihre Anfrage entweder über Datei hochladen oder aus der Zwischenablage in das freie Feld einfügen.&lt;br /&gt;
&lt;br /&gt;
Nach dem erfolgreichen Einspielen Ihrer Anfrage wird Ihnen Ihre Anfrage zur Gegenprüfung im Detail angezeigt. Sie können hier die Dauer der Auslösung ggf. erneut anpassen. Über den Knopf &amp;quot;Auslösen bestätigen&amp;quot; wird die Lizenz endgültig ausgelöst. Danach ist diese Lizenz bis zum Ablauf der Dauer ausschließlich für das expecco, von welchem die Anfrage erstellt wurde reserviert. Ihnen wird anschließend der Bestätigungsschlüssel angezeigt. Diesen können Sie wiederum als Datei speichern oder über Rechtsklick &amp;quot;Kopieren&amp;quot; in die Zwischenablage legen.&lt;br /&gt;
&lt;br /&gt;
Jetzt müssen Sie diesen Bestätigungsschlüssel an expecco übertragen (über USB-Stick, Zuruf, Telefon usw.) und eingeben oder die Datei auswählen.&lt;br /&gt;
&lt;br /&gt;
==== Eine bereits ausgelöste Floating-Lizenz in Betrieb nehmen ====&lt;br /&gt;
Falls Sie expecco aus Versehen während dem Prozess des Auslösens geschlossen haben oder der Prozess durch etwas ähnlich unterbrochen wurde, ist die ausgelöste Lizenz nicht verloren. Sie können diese Lizenz anhand Ihrer Anfrage und zugehörigem Bestätigungsschlüssel jederzeit in expecco aktivieren.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie dazu den Lizenzservice (expecco ALM) und navigieren Sie nach &amp;quot;&#039;&#039;Lizenzservice&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;expecco Lizenzen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Im Einsatz&#039;&#039;&amp;quot;. Suchen Sie in dieser Liste nach einer passenden Lizenz. Eine passende Lizenz erkennen Sie bspw. an der Spalte &amp;quot;Rechnername&amp;quot;, diese Spalte sollte mit dem Rechnernamen auf dem expecco installiert ist übereinstimmen. Übertragen Sie die Anfrage sowie den Bestätigungsschlüssel aus den Spalten &amp;quot;Auslöse-Anfrage-Datei&amp;quot; und &amp;quot;Auslösungsschlüssel&amp;quot; zu expecco.&lt;br /&gt;
&lt;br /&gt;
In expecco müssen Sie die Auslöse-Anfrage-Datei auswählen und diese dann mit dem Bestätigungsschlüssel aktivieren.&lt;br /&gt;
&lt;br /&gt;
==== Die aktuell verwendete ausgelöste Floating-Lizenz verlängern ====&lt;br /&gt;
&lt;br /&gt;
Das Verlängern einer ausgelösten Floating-Lizenz ist nur möglich, solange diese noch gültig ist. Nach dem Ablauf einer ausgelösten Lizenz wird diese im Lizenzserver gelöscht und Sie müssen diese durch eine neue Anfrage erneuern (i.e. eine neue Lizenz auslösen).&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie dazu den Lizenzservice (expecco ALM) und navigieren Sie nach &amp;quot;&#039;&#039;Lizenzservice&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;expecco Lizenzen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Im Einsatz&#039;&#039;&amp;quot;. Suchen Sie in dieser Liste nach einer passenden Lizenz. Eine passende Lizenz erkennen Sie bspw. an der Spalte &amp;quot;Rechnername&amp;quot;. Diese Spalte sollte mit dem Rechnernamen, auf dem expecco installiert ist, übereinstimmen.&lt;br /&gt;
&lt;br /&gt;
Klicken Sie nun auf &amp;quot;Verlängern&amp;quot;. Sie werden automatisch auf die Seite &amp;quot;Lizenz verlängern&amp;quot; weitergeleitet. Ihre Lizenz ist bereits vorselektiert. Sie können nun das gewünschte Datum eingeben. Danach wird Ihnen ein neuer Bestätigungsschlüssel angezeigt, diesen müssen Sie in expecco eingeben.&lt;br /&gt;
&lt;br /&gt;
=== Änderung des Lizenztyps nach der Installation ===&lt;br /&gt;
&lt;br /&gt;
Über das Menü &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot; können Sie die Lizenz nachträglich ändern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Die Änderung des Lizenztyps werden permanent gespeichert, wenn Sie die Einstellung mit der Schaltfläche &amp;quot;Sichern&amp;quot; abspeichern.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Weitere Hilfspakete und Frameworks ==&lt;br /&gt;
&lt;br /&gt;
Die Basisinstallation wie oben beschrieben beinhaltet bereits die meisten normalerweise benötigten Komponenten. Abhängig von später durchzuführenden Tests und benötigter Software können (sollten) weitere Pakete ebenfalls installiert werden. Hinweise dazu finden Sie im Dokument: [[Installing_additional_Frameworks/en | &amp;quot;Installing additional Frameworks&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
Wir empfehlen folgende Pakete:&lt;br /&gt;
* [[Installing_additional_Frameworks/en#Java_Installation_.28for_Groovy_Actions.2C_Web-_and_Mobile_Testing.29|Java Runtime or JDK]]&lt;br /&gt;
* [[Installing_additional_Frameworks/en#Python_Installation_.28for_Python_Actions.29|Python]]&lt;br /&gt;
* [[Installing_additional_Frameworks/en#OCR_.28Optical_Character_Recognition.29|Tesseract]]&amp;lt;br&amp;gt;falls Sie OCR (Optical Character Recognition) zum Extrahieren von Texten aus Bildern und Bildschirmabzügen benötigen.&lt;br /&gt;
&lt;br /&gt;
Ausserdem sinnvoll (aber seltener benötigt):&lt;br /&gt;
* [[Installing_additional_Frameworks/en#Node_Installation_.28for_Node.js_Actions.29|Node]]&lt;br /&gt;
&lt;br /&gt;
Falls Sie Aktionen in C or C++ schreiben wollen (müssen):&lt;br /&gt;
* [[Installing_additional_Frameworks/en#C_Compiler_Toolchain_Installation_.28for_C-Actions.29|C Compiler Toolchain]]&lt;br /&gt;
&lt;br /&gt;
== Patches und Aktualisierungen ==&lt;br /&gt;
&lt;br /&gt;
Exept stellt  auch zwischen zwei Major Releases zu Verfügung in unregelmäßigen Abständen oder auf Anfrage Patches und Erweiterungen.&lt;br /&gt;
&lt;br /&gt;
Patches sind versionsabhängig; d.h. ein Patch für expecco Version 23.1 ist nicht für andere Versionen zu verwenden.&lt;br /&gt;
Normalerweise beinhaltet jede neue Major Release (z.B. 24.1) alle Patches aller Vorgängerversionen.&lt;br /&gt;
Oft sogar mehr Funktionalität. Alte Patches sollten daher nicht in neuere Versionen eingespielt werden,&lt;br /&gt;
und expecco lehnt auch solche Patches ab. Es besteht also keine Gefahr, dass diese aus Versehen eingespielt werden.&lt;br /&gt;
&lt;br /&gt;
Die Patches kommen in Dateien paarweise: eine &amp;quot;.expeccoPatch&amp;quot; und eine &amp;quot;.info&amp;quot; Datei.&lt;br /&gt;
Letztere beinhaltet eine textuelle Beschreibung; erstere den eigentlichen Patch.&lt;br /&gt;
Die Patches sind signiert, und expecco wird nur patch Dateien welche von exept signiert sind akzeptieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die patch Dateien können auf mehrere Arten sowohl manuell als auch automatisch heruntergeladen und eingespielt werden.&lt;br /&gt;
Sie befinden sich physikalisch auf dem download host von exept, unter &amp;quot;http://dowloads.exept.de&amp;quot; und &amp;quot;ftp://ftp.exept.de/downloads&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Automatisch vom Exept Download Server ===&lt;br /&gt;
&lt;br /&gt;
Wenn sie Zugriff aufs Internet mit http (port80) oder https (port 443) haben,&lt;br /&gt;
gehen sie zu &amp;quot;Extras&amp;quot; - &amp;quot;Einstellungen&amp;quot; - &amp;quot;Software Aktualisierung&amp;quot;.&lt;br /&gt;
Und verifizieren die Einstellungen zu &amp;quot;Patch Server&amp;quot;.&lt;br /&gt;
Zum Test der Verbindung klicken sie auf &amp;quot;Jetzt nach Updates suchen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Sie können oben auswählen, wann und wie oft expecco nach Updates schauen soll.&lt;br /&gt;
&lt;br /&gt;
=== Automatisch von einem hauseigenen Download Server ===&lt;br /&gt;
&lt;br /&gt;
Falls ihr Testrechner keinen Zugriff aufs Internet hat, aber ein anderer Rechner im Hausnetz erreichbar ist, können sie die Patches auch wie unten beschrieben auf diese Maschine herunterladen und von ihren Testrechnern die Patches dort abholen.&lt;br /&gt;
Dies hat den Vorteil, dass der download nur einmal durchgeführt werden muss, und sie selbst Kontrolle über die Patches haben.&lt;br /&gt;
&lt;br /&gt;
Gehen sie dazu wie oben beschrieben zum Einstellungsdialog, und geben den Namen und Pfad ihres Servers ein. Dort sollte dann ein Dateiservice mit unten beschriebener Dateistruktur zu finden sein (z.B. ein entsprechen aufgesetzter apache Server).&lt;br /&gt;
&lt;br /&gt;
=== Automatisch von einem hauseigenen Lizenz Server ===&lt;br /&gt;
&lt;br /&gt;
Wenn Sie keinen apache Server aufsetzen wollen oder können, aber einen Lizenzserver verwenden, können sie die patches auch auf dessen Rechner unter einem beliebigen Verzeichnis ablegen und den Lizenzserver entsprechend konfigurieren.&lt;br /&gt;
&lt;br /&gt;
Im Lizenzserver (AIDYMO) gehen sie zu den &amp;quot;Einstellungen&amp;quot; - &amp;quot;System&amp;quot;, und finden unten in der Maske unter &amp;quot;Sonstige&amp;quot; eine Checkbox &amp;quot;Patches Service&amp;quot;. Schalten sie diese Box ein, und geben darunter den Pfad zu dem patches Verzeichnis (auf dem Rechner des Lizenzservers).&lt;br /&gt;
Die Orderstruktur darunter entspricht der unten beschriebenen unter &amp;quot;expecco&amp;quot;. I.e. &amp;quot;&amp;lt;versionsNr&amp;gt;/patches/...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Manuell ===&lt;br /&gt;
&lt;br /&gt;
Falls ihr Testrechner isoliert vom Internet oder dem Hausnetz arbeitet (z.B. in einem Cleanroom oder Prüfstand),&lt;br /&gt;
müssen die Patches zunächst auf den Rechner gebracht werden. Dies kann z.B. über ein Medium (USB-Stick) oder ein Netzlaufwerk erfolgen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Unter dem jeweiligen Hauptverzeichnis (siehe oben) befindet sich ein Ordner per Release, und darunter die patch- und info Dateien.&lt;br /&gt;
Also z.B.:&lt;br /&gt;
    https://download/expecco/23.2.0/patches&lt;br /&gt;
        0001_fix1.expeccoPatch&lt;br /&gt;
        0001_fix1.info&lt;br /&gt;
        0002_feature1.expeccoPatch&lt;br /&gt;
        0002_feature1.info&lt;br /&gt;
    https://download/expecco/24.1.0/patches&lt;br /&gt;
        0001_fix2.expeccoPatch&lt;br /&gt;
        0001_fix2.info&lt;br /&gt;
    usw.&lt;br /&gt;
&lt;br /&gt;
Falls der automatische update versagt, können Sie die Dateien als fallback im Browser herunterladen (sichern als),&lt;br /&gt;
in einem Ordner sammeln und wie unten beschrieben manuell einspielen.&lt;br /&gt;
&lt;br /&gt;
Falls es sich um einen Individualpatch für Sie persönlich handelt, kann er ihnen auch per email zugesandt, oder in AIDYMO als Anhang übergeben werden.&lt;br /&gt;
&lt;br /&gt;
Bringen sie dazu die &amp;quot;.expeccoPatch&amp;quot; Dateien auf den Testhost (z.B. in ein Temp Verzeichnis), und&lt;br /&gt;
wählen im &amp;quot;Extras&amp;quot; -&amp;gt; &amp;quot;Maintenance&amp;quot; -&amp;gt; &amp;quot;Install Patch from File&amp;quot;.&lt;br /&gt;
Im geöffneten Dialog wählen Sie die entsprechen(n) Datei(en) an und bestätigen sie.&lt;br /&gt;
&lt;br /&gt;
Diesen Vorgang müssen Sie nur einmal durchführen; mit jedem Neustart werden die Patches automatisch neu installiert.&lt;br /&gt;
Die temporären Dateien können sie nach der Installation löschen; sie werden nicht mehr gebraucht.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30820</id>
		<title>Release Notes 25.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30820"/>
		<updated>2025-07-22T08:12:10Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Release 25.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 24.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 25.1 ==&lt;br /&gt;
*Improvement: additional &amp;quot;Info&amp;quot; tab in inspector views&lt;br /&gt;
*Improvement: less memory usage in the activity log&lt;br /&gt;
*Improvement: better error messages and more links to settings from the activity log&#039;s error message&lt;br /&gt;
*Improvement: additional units and conversions in the [[PhysicalValues/en|physical values framework]]&lt;br /&gt;
*Improvement: more precision in the [[Numeric_Limits/en#Higher_Precision_Numbers|high precision trigonometric and math functions]]&lt;br /&gt;
*Improvement: WindowsAutomation: Plugn Update to FlaUI 5&lt;br /&gt;
*Improvement: Mobile Testing: Better Device Lock/Unlock Support&lt;br /&gt;
*Improvement: StandardLibrary: &amp;quot;File [ *CSV ]&amp;quot; blocks got an additional &amp;quot;characterEncodeing&amp;quot; pin (useful for reading/writing e.g. utf-8 encoded CSV files)&lt;br /&gt;
*Improvement: ExcelLib: better documentation. Now requires the openpyxl package version &amp;gt;= 3.1.5. &lt;br /&gt;
*Improvement: better model language editor (translate and fetch-strings functions)&lt;br /&gt;
*Improvement: ODBClibrary: improved compatibility with different database vendors (supports the CedarDB database) &lt;br /&gt;
*Feature: translate and spell check in the workspace window&lt;br /&gt;
*Feature: EditLock of suites loaded from expeccoALM / AIDYMO&lt;br /&gt;
*Feature: Start Test in expeccoALM / AIDYMO (via expecco)&lt;br /&gt;
*Feature: new library containing expeccoALM control actions (those from the AIDYMO menu)&lt;br /&gt;
*Fix: the version diff viewer (did not correctly copy changed attachment files)&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Lizenzserver_expecco_ALM&amp;diff=30817</id>
		<title>Lizenzserver expecco ALM</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Lizenzserver_expecco_ALM&amp;diff=30817"/>
		<updated>2025-07-09T08:41:35Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Übersicht==&lt;br /&gt;
&lt;br /&gt;
Der expecco Lizenzserver dient der zentralen Verwaltung von expecco Lizenzen. Durch den Lizenzserver kann expecco auf verschiedenen Rechnern (sowohl Entwicklungs- als auch reine Testausführungsrechner) ohne Dongle und lokale Lizenzdatei auf allen erreichbaren Rechnern im Netz installiert und ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Lizenzen werden dabei von den expecco-Rechnern vom Lizenzserver angefordert, im Lizenzserver reserviert,&lt;br /&gt;
und nach der Sitzung bzw. Testlauf wieder zurückgegeben. Damit können mehr Nutzer (allerdings nicht gleichzeitig) mit expecco arbeiten als Lizenzen erworben wurden.&lt;br /&gt;
&lt;br /&gt;
Lizenzen sind kryptographisch gesicherte Dateien, welche nur in Verbindung mit einem von eXept gelieferten Lizenzserver-Dongle gelesen bzw. genutzt werden können. Lizenzen sind Dongle-spezifisch. Es ist also nicht notwendig, Maßnahmen zum Schutz vor Diebstahl oder Kopieren von Lizenzdateien zu ergreifen. Allerdings ist ein Verlust des Dongles aus nahe liegenden Gründen zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
{{SEITENTITEL:Lizenzservice Installation}}&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Wir empfehlen expecco ALM auf einem durchgehend verfügbaren Server mit Windows Server 2012 / Windows 10 oder höher zu installieren. Die Installation auf anderen Betriebssystemen (wie z.B. Linux) wäre bei Bedarf auch möglich. Ebenso ist die Installation in einer Cloud möglich, dort ist der Betrieb ohne Dongle möglich.&lt;br /&gt;
&lt;br /&gt;
Damit expecco ALM flüssig arbeiten kann, werden folgende Hardware-Anforderungen an den Server gestellt:&lt;br /&gt;
&amp;lt;br&amp;gt;- ein &amp;quot;dezidierter&amp;quot; Prozessor mit mindestens 2 GHz&lt;br /&gt;
&amp;lt;br&amp;gt;- mindestens 1 GB Arbeitsspeicher (ausschließlich für expecco ALM)&lt;br /&gt;
&amp;lt;br&amp;gt;- mindestens 10 GB Festplattenspeicher (je nach Größe der Daten die expecco ALM verwalten soll)&lt;br /&gt;
&lt;br /&gt;
Stellen Sie sicher, dass dieser Server für alle Clients erreichbar ist. Clients sind alle Rechner der expecco ALM Benutzer, Rechner die expecco ALM zur Testausführung dienen und Rechner mit &amp;quot;Floating&amp;quot; lizenziertem expecco. Bei Problemen bezüglich der Erreichbarkeit wenden Sie sich bitte an Ihren Netzwerkadministrator.&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
Bitte halten Sie Ihre Lizenzdatei und Ihren Dongle für die Installation von expecco ALM bereit.&amp;lt;br&amp;gt;&lt;br /&gt;
Für die Installation in der Cloud liefern wir eine Lizenzdatei mit entsprechender Mac-Adresse.&lt;br /&gt;
&lt;br /&gt;
Ihre Lizenzdatei und eine Verknüpfung zum aktuellen expecco ALM Setup haben wir Ihnen per E-Mail zu kommen lassen. Der Installer hat folgenden Namen &amp;quot;expecco ALM 1.9.0.1 Setup.exe&amp;quot;, wobei die Versionsnummer abweichen kann. Ihren Dongle haben wir per Post an Sie versendet (es sei denn Sie evaluieren expecco ALM oder nutzen die Cloud Variante mit der Mac-Adressen-Bindung).&lt;br /&gt;
&lt;br /&gt;
Gehen Sie bitte wie folgt vor:&lt;br /&gt;
* Laden Sie den expecco ALM Installer auf dem Server, auf dem expecco ALM künftig laufen soll, herunter&lt;br /&gt;
* Legen Sie Ihre Lizenzdatei ebenfalls auf dem Server ab&lt;br /&gt;
* Verbinden Sie Ihren Dongle mit dem Server (Wenn Sie expecco ALM evaluieren oder die Cloud Variante mit der Mac-Adressen-Bindung nutzen, überspringen Sie diesen Schritt)&lt;br /&gt;
* Führen Sie den expecco ALM Installer (&amp;quot;expecco ALM ?.?.?.? Setup.exe&amp;quot; bzw. unter Linux &amp;quot;expecco ALM ?.?.?.? Setup.package&amp;quot;) aus&lt;br /&gt;
&lt;br /&gt;
Für Linux werden zusätzliche Pakete der Linux-Distribution benötigt. Diese sind [[Installation#Installation_von_expecco_auf_Linux|hier]] aufgeführt.&lt;br /&gt;
&lt;br /&gt;
Nachdem der Installer erfolgreich ausgeführt wurde, läuft expecco ALM bereits als Service. Auf Ihrem Desktop wurde eine Verknüpfung zu expecco ALM angelegt. Es wurde auch ein Ordner für expecco ALM in Ihrem Startmenü erstellt. Dort können Sie unter &amp;quot;Konfiguration&amp;quot; den Port ändern (Standard ist Port 8081) oder über die &amp;quot;Logdatei&amp;quot; eventuelle Probleme feststellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:InstallAlmLicense.png|mini|Anhang 1]]&lt;br /&gt;
Über die Verknüpfung auf Ihrem Desktop lässt sich expecco ALM mit Ihrem Standardbrowser öffnen. Es wird eine Seite zum Installieren Ihrer expecco ALM Lizenz angezeigt (Anhang 1). Über &amp;quot;Lizenzdatei installieren&amp;quot; können Sie Ihre Lizenzdatei (die Sie bereits auf dem Server abgelegt haben) auswählen. Nach dem expecco ALM Ihre Lizenzdatei akzeptiert hat, können Sie diese entfernen. Wenn bereits eine gültige Lizenz installiert ist, wird stattdessen die Anmeldeseite angezeigt. Falls es sich bei Ihnen um eine Erstinstallation handelt, können Sie sich mit Anmeldenamen &amp;quot;admin&amp;quot; und Kennwort &amp;quot;admin&amp;quot; anmelden.&lt;br /&gt;
&lt;br /&gt;
Falls eine leere Seite oder eine Fehlerseite angezeigt wird, probieren Sie einen anderen Port aus und/oder schauen Sie in der Logdatei nach Fehlermeldungen.&lt;br /&gt;
&lt;br /&gt;
== SSL-Verschlüsselung / Proxy-Server ==&lt;br /&gt;
expecco ALM unterstützt aktuell noch nicht direkt SSL-Verschlüsselung. Über einen Proxy-Server ist diese aber problemlos einzurichten, z.B. über einen Apache-Server. Falls auf ihrem Server weitere Webseiten gehostet werden, ist dies ja ohnehin erforderlich, da sich nicht mehrere Prozesse gleichzeitig an den Port 443 binden können.&lt;br /&gt;
&lt;br /&gt;
Eine Apache2 VirtualHost-Konfiguration würde entsprechend so aussehen (angenommen expecco ALM läuft mit Port 8465 - erforderliche Anpassung für ihre Konfiguration fett):&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
   ServerName &amp;lt;b&amp;gt;expeccoalm.xyz.de&amp;lt;/b&amp;gt;&lt;br /&gt;
   ServerAdmin &amp;lt;b&amp;gt;webmaster@xyz.de&amp;lt;/b&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   Include &amp;lt;b&amp;gt;/etc/letsencrypt/ssl-xyz.de.conf&amp;lt;/b&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   SSLProxyEngine On&lt;br /&gt;
   &lt;br /&gt;
   RewriteEngine on&lt;br /&gt;
   RewriteCond %{HTTP:Upgrade} =websocket [NC]&lt;br /&gt;
   RewriteRule /(.*)           ws://localhost:&amp;lt;b&amp;gt;8465&amp;lt;/b&amp;gt;/$1 [P,L]&lt;br /&gt;
   RewriteCond %{HTTP:Upgrade} !=websocket [NC]&lt;br /&gt;
   &lt;br /&gt;
   ProxyPass /               http://localhost:&amp;lt;b&amp;gt;8465&amp;lt;/b&amp;gt;/ nocanon&lt;br /&gt;
   ProxyPassReverse /        http://localhost:&amp;lt;b&amp;gt;8465&amp;lt;/b&amp;gt;/&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die SSL-Parameter mit dem Pfaden zu Ihren Zertifkaten uns Schlüsseln würden in diesem Konfigurations-Beispiel in der Apache-globalen Datei /etc/letsencrypt/ssl-xyz.de.conf liegen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Lizenzierung ==&lt;br /&gt;
Wenn Sie expecco ALM erworben haben, erhalten Sie einen Dongle und eine Lizenzdatei. Falls Sie expecco ALM evaluieren, erhalten Sie ausschließlich die Lizenzdatei. Die Lizenzdatei beinhaltet eine für Sie individuelle expecco ALM Lizenz. So sind zum Beispiel: Der Name Ihrer Firma, für Sie freigeschaltete Module oder die Gültigkeitsdauer in der Lizenz hinterlegt. Der Dongle muss (insofern Sie expecco ALM erworben haben) ständig mit dem Server, auf dem expecco ALM ausgeführt wird, verbunden sein. Falls Sie den Dongle während des Betriebs abziehen, wird expecco ALM seinen Dienst einstellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Lizenz wechseln ==&lt;br /&gt;
[[Datei:ChangeAlmLicense.png|mini|Anhang 2]]&lt;br /&gt;
Falls Sie eine aktuelle expecco ALM Version haben, können Sie eine neue Lizenzdatei &amp;quot;expecco ALM Lizenz *.lic&amp;quot; über das Webinterface von expecco ALM einspielen. Betrachten Sie dazu den angehängten Screenshot (Anhang 2).&lt;br /&gt;
&lt;br /&gt;
Fall Sie eine ältere expecco ALM Version haben, müssen Sie folgendermaßen vorgehen:&lt;br /&gt;
&amp;lt;br&amp;gt;- Da Sie expecco ALM später neustarten müssen, tätigen Sie entsprechende Vorsorgemaßnahmen (Bspw. Benutzer abmelden, Datenbank sichern usw.)&lt;br /&gt;
&amp;lt;br&amp;gt;- Melden Sie sich auf dem Computer, der expecco ALM betreibt an&lt;br /&gt;
&amp;lt;br&amp;gt;- Begeben Sie sich in folgendes Verzeichnis &amp;quot;C:\Windows\SysWOW64\config\systemprofile\AppData\Roaming\expecco_ALM&amp;quot; oder falls es sich um ein 32Bit Betriebssystem handelt &amp;quot;C:\Windows\system32\config\systemprofile\AppData\Roaming\expecco_ALM&amp;quot; und löschen Sie die Datei &amp;quot;expecco_ALM.lic&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;- Starten Sie den expecco ALM Service über den Windows-Service-Manager neu oder beenden Sie über den Windows-Task-Manager den Prozess &amp;quot;expecco_ALM.exe&amp;quot;, in letzterem Fall wird der Windows-Service-Manager expecco ALM automatisch neustarten.&lt;br /&gt;
&amp;lt;br&amp;gt;- Nun können Sie das expecco ALM Webinterface aufrufen. Es wird eine Seite zum Installieren Ihrer expecco ALM Lizenz angezeigt (Anhang 1). Über &amp;quot;Lizenzdatei installieren&amp;quot; können Sie Ihre Lizenzdatei. auswählen. Nach dem expecco ALM Ihre Lizenzdatei akzeptiert hat, können Sie diese entfernen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Einbringen von expecco Floating-Lizenzen ==&lt;br /&gt;
Der Lizenzservice von expecco ALM vergibt verfügbare expecco Floating-Lizenzen aus einem bestimmten Pool.&amp;lt;br&amp;gt;&lt;br /&gt;
In diesen zunächst leeren Pool können von eXept erworbene expecco Floating-Lizenzen eingebracht werden.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Diese expecco Floating-Lizenzen erhalten Sie als Lizenzdatei(en) üblicherweise per E-Mail.&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Lizenzdatei kann eine oder mehrere expecco Floating-Lizenzen auch für verschiedene Komponenten (Basissystem, Plugins und Erweiterungen) enthalten.&amp;lt;br&amp;gt;&lt;br /&gt;
Sie können auch jederzeit weitere expecco Floating-Lizenzen erwerben und in den Pool einbringen.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
expecco Floating-Lizenzen werden immer spezifisch für eine expecco ALM Lizenz erstellt und sind nur mit dieser und deren Dongle nutzbar.&amp;lt;br&amp;gt;&lt;br /&gt;
Es ist also nicht notwendig solche Lizenzdateien unter Verschluss zu halten oder über eine sichere Verbindung auszutauschen.&amp;lt;br&amp;gt;&lt;br /&gt;
Allerdings sollten Sie den Dongle sicher aufbewahren bzw. Diebstahl vorbeugen.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Zur Einbringen einer expecco Floating-Lizenz öffnen Sie expecco ALM und melden Sie sich an.&amp;lt;br&amp;gt;&lt;br /&gt;
Jetzt navigieren Sie über die obere Hauptnavigationsleiste zum &amp;quot;Lizenzservice&amp;quot; Modul.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Sie befinden sich nun im Lizenzservice und Ihnen wird die Liste der installierten expecco Floating-Lizenzen angezeigt.&amp;lt;br&amp;gt;&lt;br /&gt;
Wechseln Sie zur Registerkarte &amp;quot;expecco Lizenzdateien&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Navigieren Sie mithilfe des Navigationsmenüs auf der linken Seite zu &amp;quot;Hochladen/Upload&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können Sie nun durch ein einfaches Hochladen Ihrer expecco Floating-Lizenzen selbige in den Pool einbringen.&amp;lt;br&amp;gt;&lt;br /&gt;
In der zuvor genannte Liste werden nun die eben hochgeladenen expecco Floating-Lizenzen anzeigt.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese sind von nun an auch von entfernten expecco Clients abrufbar.&amp;lt;br&amp;gt;&lt;br /&gt;
Sie können auch jederzeit weitere expecco Floating-Lizenzen erwerben und in den Pool einbringen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Lizenz Übersicht ==&lt;br /&gt;
Welche einzelnen expecco Floating-Lizenzen verfügbar oder vergeben sind, &amp;lt;br&amp;gt;&lt;br /&gt;
erfahren Sie indem Sie zur Registerkarte &amp;quot;expecco Lizenzen&amp;quot; wechseln.&amp;lt;br&amp;gt;&lt;br /&gt;
Insbesondere ist hieraus ersichtlich, welcher Rechner/Benutzer welche expecco Floating-Lizenz aktuell nutzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Dies ist beispielsweise sinnvoll, wenn ein expecco Client seine Sitzung versehentlich nicht beendet hat,&amp;lt;br&amp;gt;&lt;br /&gt;
und andere Nutzer eine entsprechende Lizenz benötigen.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Lizenzserver_expecco_ALM&amp;diff=30816</id>
		<title>Lizenzserver expecco ALM</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Lizenzserver_expecco_ALM&amp;diff=30816"/>
		<updated>2025-07-09T08:41:02Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Übersicht==&lt;br /&gt;
&lt;br /&gt;
Der expecco Lizenzserver dient der zentralen Verwaltung von expecco Lizenzen. Durch den Lizenzserver kann expecco auf verschiedenen Rechnern (sowohl Entwicklungs- als auch reine Testausführungsrechner) ohne Dongle und lokale Lizenzdatei auf allen erreichbaren Rechnern im Netz installiert und ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Lizenzen werden dabei von den expecco-Rechnern vom Lizenzserver angefordert, im Lizenzserver reserviert,&lt;br /&gt;
und nach der Sitzung bzw. Testlauf wieder zurückgegeben. Damit können mehr Nutzer (allerdings nicht gleichzeitig) mit expecco arbeiten als Lizenzen erworben wurden.&lt;br /&gt;
&lt;br /&gt;
Lizenzen sind kryptographisch gesicherte Dateien, welche nur in Verbindung mit einem von eXept gelieferten Lizenzserver-Dongle gelesen bzw. genutzt werden können. Lizenzen sind Dongle-spezifisch. Es ist also nicht notwendig, Maßnahmen zum Schutz vor Diebstahl oder Kopieren von Lizenzdateien zu ergreifen. Allerdings ist ein Verlust des Dongles aus nahe liegenden Gründen zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
{{SEITENTITEL:Lizenzservice Installation}}&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Wir empfehlen expecco ALM auf einem durchgehend verfügbaren Server mit Windows Server 2012 / Windows 10 oder höher zu installieren. Die Installation auf anderen Betriebssystemen (wie z.B. Linux) wäre bei Bedarf auch möglich. Ebenso ist die Installation in einer Cloud möglich, dort ist der Betrieb ohne Dongle möglich.&lt;br /&gt;
&lt;br /&gt;
Damit expecco ALM flüssig arbeiten kann, werden folgende Hardware-Anforderungen an den Server gestellt:&lt;br /&gt;
&amp;lt;br&amp;gt;- ein &amp;quot;dezidierter&amp;quot; Prozessor mit mindestens 2 GHz&lt;br /&gt;
&amp;lt;br&amp;gt;- mindestens 1 GB Arbeitsspeicher (ausschließlich für expecco ALM)&lt;br /&gt;
&amp;lt;br&amp;gt;- mindestens 10 GB Festplattenspeicher (je nach Größe der Daten die expecco ALM verwalten soll)&lt;br /&gt;
&lt;br /&gt;
Stellen Sie sicher, dass dieser Server für alle Clients erreichbar ist. Clients sind alle Rechner der expecco ALM Benutzer, Rechner die expecco ALM zur Testausführung dienen und Rechner mit &amp;quot;Floating&amp;quot; lizenziertem expecco. Bei Problemen bezüglich der Erreichbarkeit wenden Sie sich bitte an Ihren Netzwerkadministrator.&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
Bitte halten Sie Ihre Lizenzdatei und Ihren Dongle für die Installation von expecco ALM bereit.&amp;lt;br&amp;gt;&lt;br /&gt;
Für die Installation in der Cloud liefern wir eine Lizenzdatei mit entsprechender Mac-Adresse.&lt;br /&gt;
&lt;br /&gt;
Ihre Lizenzdatei und eine Verknüpfung zum aktuellen expecco ALM Setup haben wir Ihnen per E-Mail zu kommen lassen. Der Installer hat folgenden Namen &amp;quot;expecco ALM 1.9.0.1 Setup.exe&amp;quot;, wobei die Versionsnummer abweichen kann. Ihren Dongle haben wir per Post an Sie versendet (es sei denn Sie evaluieren expecco ALM oder nutzen die Cloud Variante mit der Mac-Adressen-Bindung).&lt;br /&gt;
&lt;br /&gt;
Gehen Sie bitte wie folgt vor:&lt;br /&gt;
* Laden Sie den expecco ALM Installer auf dem Server, auf dem expecco ALM künftig laufen soll, herunter&lt;br /&gt;
* Legen Sie Ihre Lizenzdatei ebenfalls auf dem Server ab&lt;br /&gt;
* Verbinden Sie Ihren Dongle mit dem Server (Wenn Sie expecco ALM evaluieren oder die Cloud Variante mit der Mac-Adressen-Bindung nutzen, überspringen Sie diesen Schritt)&lt;br /&gt;
* Führen Sie den expecco ALM Installer (&amp;quot;expecco ALM ?.?.?.? Setup.exe&amp;quot; bzw. unter Linux &amp;quot;expecco ALM ?.?.?.? Setup.package&amp;quot;) aus&lt;br /&gt;
&lt;br /&gt;
Für Linux werden zusätzliche Pakete der Linux-Distribution benötigt. Diese werden [[Installation#Installation_von_expecco_auf_Linux|hier]] aufgeführt.&lt;br /&gt;
&lt;br /&gt;
Nachdem der Installer erfolgreich ausgeführt wurde, läuft expecco ALM bereits als Service. Auf Ihrem Desktop wurde eine Verknüpfung zu expecco ALM angelegt. Es wurde auch ein Ordner für expecco ALM in Ihrem Startmenü erstellt. Dort können Sie unter &amp;quot;Konfiguration&amp;quot; den Port ändern (Standard ist Port 8081) oder über die &amp;quot;Logdatei&amp;quot; eventuelle Probleme feststellen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:InstallAlmLicense.png|mini|Anhang 1]]&lt;br /&gt;
Über die Verknüpfung auf Ihrem Desktop lässt sich expecco ALM mit Ihrem Standardbrowser öffnen. Es wird eine Seite zum Installieren Ihrer expecco ALM Lizenz angezeigt (Anhang 1). Über &amp;quot;Lizenzdatei installieren&amp;quot; können Sie Ihre Lizenzdatei (die Sie bereits auf dem Server abgelegt haben) auswählen. Nach dem expecco ALM Ihre Lizenzdatei akzeptiert hat, können Sie diese entfernen. Wenn bereits eine gültige Lizenz installiert ist, wird stattdessen die Anmeldeseite angezeigt. Falls es sich bei Ihnen um eine Erstinstallation handelt, können Sie sich mit Anmeldenamen &amp;quot;admin&amp;quot; und Kennwort &amp;quot;admin&amp;quot; anmelden.&lt;br /&gt;
&lt;br /&gt;
Falls eine leere Seite oder eine Fehlerseite angezeigt wird, probieren Sie einen anderen Port aus und/oder schauen Sie in der Logdatei nach Fehlermeldungen.&lt;br /&gt;
&lt;br /&gt;
== SSL-Verschlüsselung / Proxy-Server ==&lt;br /&gt;
expecco ALM unterstützt aktuell noch nicht direkt SSL-Verschlüsselung. Über einen Proxy-Server ist diese aber problemlos einzurichten, z.B. über einen Apache-Server. Falls auf ihrem Server weitere Webseiten gehostet werden, ist dies ja ohnehin erforderlich, da sich nicht mehrere Prozesse gleichzeitig an den Port 443 binden können.&lt;br /&gt;
&lt;br /&gt;
Eine Apache2 VirtualHost-Konfiguration würde entsprechend so aussehen (angenommen expecco ALM läuft mit Port 8465 - erforderliche Anpassung für ihre Konfiguration fett):&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
   ServerName &amp;lt;b&amp;gt;expeccoalm.xyz.de&amp;lt;/b&amp;gt;&lt;br /&gt;
   ServerAdmin &amp;lt;b&amp;gt;webmaster@xyz.de&amp;lt;/b&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   Include &amp;lt;b&amp;gt;/etc/letsencrypt/ssl-xyz.de.conf&amp;lt;/b&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   SSLProxyEngine On&lt;br /&gt;
   &lt;br /&gt;
   RewriteEngine on&lt;br /&gt;
   RewriteCond %{HTTP:Upgrade} =websocket [NC]&lt;br /&gt;
   RewriteRule /(.*)           ws://localhost:&amp;lt;b&amp;gt;8465&amp;lt;/b&amp;gt;/$1 [P,L]&lt;br /&gt;
   RewriteCond %{HTTP:Upgrade} !=websocket [NC]&lt;br /&gt;
   &lt;br /&gt;
   ProxyPass /               http://localhost:&amp;lt;b&amp;gt;8465&amp;lt;/b&amp;gt;/ nocanon&lt;br /&gt;
   ProxyPassReverse /        http://localhost:&amp;lt;b&amp;gt;8465&amp;lt;/b&amp;gt;/&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die SSL-Parameter mit dem Pfaden zu Ihren Zertifkaten uns Schlüsseln würden in diesem Konfigurations-Beispiel in der Apache-globalen Datei /etc/letsencrypt/ssl-xyz.de.conf liegen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Lizenzierung ==&lt;br /&gt;
Wenn Sie expecco ALM erworben haben, erhalten Sie einen Dongle und eine Lizenzdatei. Falls Sie expecco ALM evaluieren, erhalten Sie ausschließlich die Lizenzdatei. Die Lizenzdatei beinhaltet eine für Sie individuelle expecco ALM Lizenz. So sind zum Beispiel: Der Name Ihrer Firma, für Sie freigeschaltete Module oder die Gültigkeitsdauer in der Lizenz hinterlegt. Der Dongle muss (insofern Sie expecco ALM erworben haben) ständig mit dem Server, auf dem expecco ALM ausgeführt wird, verbunden sein. Falls Sie den Dongle während des Betriebs abziehen, wird expecco ALM seinen Dienst einstellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Lizenz wechseln ==&lt;br /&gt;
[[Datei:ChangeAlmLicense.png|mini|Anhang 2]]&lt;br /&gt;
Falls Sie eine aktuelle expecco ALM Version haben, können Sie eine neue Lizenzdatei &amp;quot;expecco ALM Lizenz *.lic&amp;quot; über das Webinterface von expecco ALM einspielen. Betrachten Sie dazu den angehängten Screenshot (Anhang 2).&lt;br /&gt;
&lt;br /&gt;
Fall Sie eine ältere expecco ALM Version haben, müssen Sie folgendermaßen vorgehen:&lt;br /&gt;
&amp;lt;br&amp;gt;- Da Sie expecco ALM später neustarten müssen, tätigen Sie entsprechende Vorsorgemaßnahmen (Bspw. Benutzer abmelden, Datenbank sichern usw.)&lt;br /&gt;
&amp;lt;br&amp;gt;- Melden Sie sich auf dem Computer, der expecco ALM betreibt an&lt;br /&gt;
&amp;lt;br&amp;gt;- Begeben Sie sich in folgendes Verzeichnis &amp;quot;C:\Windows\SysWOW64\config\systemprofile\AppData\Roaming\expecco_ALM&amp;quot; oder falls es sich um ein 32Bit Betriebssystem handelt &amp;quot;C:\Windows\system32\config\systemprofile\AppData\Roaming\expecco_ALM&amp;quot; und löschen Sie die Datei &amp;quot;expecco_ALM.lic&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;- Starten Sie den expecco ALM Service über den Windows-Service-Manager neu oder beenden Sie über den Windows-Task-Manager den Prozess &amp;quot;expecco_ALM.exe&amp;quot;, in letzterem Fall wird der Windows-Service-Manager expecco ALM automatisch neustarten.&lt;br /&gt;
&amp;lt;br&amp;gt;- Nun können Sie das expecco ALM Webinterface aufrufen. Es wird eine Seite zum Installieren Ihrer expecco ALM Lizenz angezeigt (Anhang 1). Über &amp;quot;Lizenzdatei installieren&amp;quot; können Sie Ihre Lizenzdatei. auswählen. Nach dem expecco ALM Ihre Lizenzdatei akzeptiert hat, können Sie diese entfernen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Einbringen von expecco Floating-Lizenzen ==&lt;br /&gt;
Der Lizenzservice von expecco ALM vergibt verfügbare expecco Floating-Lizenzen aus einem bestimmten Pool.&amp;lt;br&amp;gt;&lt;br /&gt;
In diesen zunächst leeren Pool können von eXept erworbene expecco Floating-Lizenzen eingebracht werden.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Diese expecco Floating-Lizenzen erhalten Sie als Lizenzdatei(en) üblicherweise per E-Mail.&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Lizenzdatei kann eine oder mehrere expecco Floating-Lizenzen auch für verschiedene Komponenten (Basissystem, Plugins und Erweiterungen) enthalten.&amp;lt;br&amp;gt;&lt;br /&gt;
Sie können auch jederzeit weitere expecco Floating-Lizenzen erwerben und in den Pool einbringen.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
expecco Floating-Lizenzen werden immer spezifisch für eine expecco ALM Lizenz erstellt und sind nur mit dieser und deren Dongle nutzbar.&amp;lt;br&amp;gt;&lt;br /&gt;
Es ist also nicht notwendig solche Lizenzdateien unter Verschluss zu halten oder über eine sichere Verbindung auszutauschen.&amp;lt;br&amp;gt;&lt;br /&gt;
Allerdings sollten Sie den Dongle sicher aufbewahren bzw. Diebstahl vorbeugen.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Zur Einbringen einer expecco Floating-Lizenz öffnen Sie expecco ALM und melden Sie sich an.&amp;lt;br&amp;gt;&lt;br /&gt;
Jetzt navigieren Sie über die obere Hauptnavigationsleiste zum &amp;quot;Lizenzservice&amp;quot; Modul.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Sie befinden sich nun im Lizenzservice und Ihnen wird die Liste der installierten expecco Floating-Lizenzen angezeigt.&amp;lt;br&amp;gt;&lt;br /&gt;
Wechseln Sie zur Registerkarte &amp;quot;expecco Lizenzdateien&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Navigieren Sie mithilfe des Navigationsmenüs auf der linken Seite zu &amp;quot;Hochladen/Upload&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können Sie nun durch ein einfaches Hochladen Ihrer expecco Floating-Lizenzen selbige in den Pool einbringen.&amp;lt;br&amp;gt;&lt;br /&gt;
In der zuvor genannte Liste werden nun die eben hochgeladenen expecco Floating-Lizenzen anzeigt.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese sind von nun an auch von entfernten expecco Clients abrufbar.&amp;lt;br&amp;gt;&lt;br /&gt;
Sie können auch jederzeit weitere expecco Floating-Lizenzen erwerben und in den Pool einbringen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Lizenz Übersicht ==&lt;br /&gt;
Welche einzelnen expecco Floating-Lizenzen verfügbar oder vergeben sind, &amp;lt;br&amp;gt;&lt;br /&gt;
erfahren Sie indem Sie zur Registerkarte &amp;quot;expecco Lizenzen&amp;quot; wechseln.&amp;lt;br&amp;gt;&lt;br /&gt;
Insbesondere ist hieraus ersichtlich, welcher Rechner/Benutzer welche expecco Floating-Lizenz aktuell nutzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Dies ist beispielsweise sinnvoll, wenn ein expecco Client seine Sitzung versehentlich nicht beendet hat,&amp;lt;br&amp;gt;&lt;br /&gt;
und andere Nutzer eine entsprechende Lizenz benötigen.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Installation&amp;diff=30815</id>
		<title>Installation</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Installation&amp;diff=30815"/>
		<updated>2025-07-09T08:31:49Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Benötigte Linux Softwarepakete */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Installation/en#Additional_Packages_and_Frameworks| English Version]]&lt;br /&gt;
&lt;br /&gt;
== Installation von expecco auf Windows ==&lt;br /&gt;
&lt;br /&gt;
Sie erhalten eine E-Mail mit dem Link zu der expecco-Installationsdatei. Die Installationsdatei hat z.B. den Namen:&lt;br /&gt;
&lt;br /&gt;
* expeccoSetup64-23.1.0.50.exe -&amp;gt; für die expecco-Basisinstallation&lt;br /&gt;
&lt;br /&gt;
wobei hier 23.1.0 der Versionsnummer von expecco entspricht und 50 der Build-Nummer (&amp;quot;23.1.0.50&amp;quot; entspricht hier der Version zum Zeitpunkt der Erstellung dieses Dokuments - Sie werden mit Sicherheit eine andere Versionsnummer sehen).&lt;br /&gt;
&lt;br /&gt;
Bitte laden Sie das Installationsprogramm auf Ihren Rechner.&lt;br /&gt;
&lt;br /&gt;
=== Windows SmartScreen / Blockierte Ausführung ===&lt;br /&gt;
&lt;br /&gt;
Führen Sie das Installationsprogramm für die expecco-Basisinstallation aus (&#039;&#039;expeccoSetup64-***.exe&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Es kann vorkommen, dass Ihr Anti-Virus-Programm wie bspw. der [https://de.wikipedia.org/wiki/SmartScreen-Filter], die Installation blockiert. Dies ist bei neuen oder Vorab-expecco-Versionen vermutlich damit begründet, dass Ihr Anti-Virus-Programm unsere Software noch nicht gut genug kennt. Bitte stellen Sie in dem Fall sicher, dass die Installationsdatei ausschließlich aus einer der folgenden Quellen heruntergeladen wurde https://exept.de/*, https://download.exept.de/*, https://cloud.exept.de/*. Wenn Sie sich sicher sind, dass die Installationsdatei von uns stammt, können Sie ohne Bedenken die Blockierung Ihres Anti-Virus-Programms ignorieren. Unsere Installationsprogramme sind auch mit einem Zertifikat der eXept Software AG signiert.&lt;br /&gt;
&lt;br /&gt;
Die Installationsdatei für expecco sowie die expecco Programme sind mit dem digitalen Zertifikat von eXept Software AG signiert.&lt;br /&gt;
&lt;br /&gt;
Im Falle vom [https://de.wikipedia.org/wiki/SmartScreen-Filter], gehen Sie bitte auf &amp;quot;Weitere Informationen&amp;quot; und dann auf &amp;quot;Trotzdem ausführen&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Windows_SmartScreen.png|300px|Report Settings]] [[Bild:Windows_SmartScreen_Trozdem_ausführen.png|300px|Report Settings]]&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Anti-Virus-Programm haben, informieren Sie sich bitte wie man dort die Blockierung ignorieren oder die Installationsdatei als Ausnahme definieren kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Folgen Sie dabei dem Installationsassistenten.&lt;br /&gt;
Sie können hier das Laufwerk und das Verzeichnis angeben, unter dem expecco installiert werden soll.&lt;br /&gt;
Außerdem können Sie die Komponenten angeben, die Sie installieren wollen.&lt;br /&gt;
&lt;br /&gt;
Falls Sie Plugins für expecco lizenziert haben, können Sie bei der Installation die entsprechenden expecco-Plugins auswählen.&lt;br /&gt;
Angeboten werden alle Plugins - auch solche für die Sie keine Lizenzen erworben haben.&lt;br /&gt;
Falls Sie nicht lizenzierte Plugins installieren, ist deren Funktion in expecco nicht verfügbar und entsprechende Menu-Einträge entweder unsichtbar oder ausgegraut.&lt;br /&gt;
&amp;lt;br&amp;gt;Installierte, aber nicht lizenzierte Plugins sind erst dann verfügbar, wenn die dazu passenden Lizenzen (nach-)installiert wurden.&lt;br /&gt;
Ansonsten belegen Sie nur Platz auf der Festplatte.&lt;br /&gt;
Weitere Plugins können auch jederzeit nachträglich installiert werden. Auch können auch weitere Lizenzen jederzeit später erworben werden.&lt;br /&gt;
&lt;br /&gt;
Nach der Installation finden Sie auf Ihrem Desktop das expecco-Symbol.&lt;br /&gt;
Über dieses Symbol können Sie expecco nun starten.&lt;br /&gt;
Beim erstmaligen Ausführen, erscheint ein Fenster, in dem eine Lizenz verlangt wird.&lt;br /&gt;
Je nachdem, ob Sie eine Einzellizenz oder eine Floating-Lizenz (per Lizenzserver) nutzen, müssen Sie die Lizenz entsprechend nachfolgender Beschreibung installieren.&lt;br /&gt;
&lt;br /&gt;
=== Automatische Installation von expecco via Commandline (Windows) ===&lt;br /&gt;
&lt;br /&gt;
Sie können expecco über die Kommandozeile, via Batchdatei oder ähnlichem installieren. Führen Sie dazu expecco wie folgt aus:&lt;br /&gt;
    expeccoSetup-x.x.exe /S&lt;br /&gt;
Das &amp;quot;/S&amp;quot; steht für &amp;quot;&#039;&#039;Silent&#039;&#039;&amp;quot; und expecco installiert sich ohne GUI und ohne Fragen zu stellen.&lt;br /&gt;
Sie können optional auch ein spezifisches Installationsverzeichnis angeben:&lt;br /&gt;
    expeccoSetup-x.x.exe /S /D=&amp;quot;C:\Program Files (x86)\exept&amp;quot;&lt;br /&gt;
Damit expecco nach der Installation direkt starten kann, muss sichergestellt werden, dass eine Lizenz auf dem Zielrechner vorhanden ist. Hierfür kommen folgende Varianten in Frage.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lizenz aus lokaler Lizenzdatei und Dongle&#039;&#039;&#039;:&amp;lt;br&amp;gt;&lt;br /&gt;
Stecken Sie den Dongle in den Zielrechner. Kopieren Sie Ihre Lizenzdatei in Ihr Benutzerverzeichnis bspw. &amp;quot;&amp;lt;code&amp;gt;C:\Users\IhrBenutzername\&amp;lt;/code&amp;gt;&amp;quot; unter dem Namen &amp;quot;&amp;lt;code&amp;gt;.expeccoLicense&amp;lt;/code&amp;gt;&amp;quot;, sodass die Datei &amp;quot;&amp;lt;code&amp;gt;C:\Users\IhrBenutzername\.expeccoLicense&amp;lt;/code&amp;gt;&amp;quot; Ihrer Lizenzdatei entspricht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lizenz vom Lizenzserver&#039;&#039;&#039;:&lt;br /&gt;
Hier müssen zunächst eine &amp;quot;Template&amp;quot; Lizenzdatei und &amp;quot;Template&amp;quot; expecco Einstellungen-Datei erstellt werden. Sie benötigen dafür ein laufendes expecco, welches mit Ihrem Lizenzserver verbunden ist. Starten Sie dieses expecco und konfigurieren Sie unter &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenz vom Lizenzserver&#039;&#039;&amp;quot; Ihre &amp;quot;Template&amp;quot; Lizenzdatei. Diese sollte alle Plugins, die auf dem Zielrechner für die automatisierte expecco Installation über Commandline benötigt werden, enthalten. Fordern Sie diese Lizenz vom Lizenzserver an. Setzen Sie den Haken &amp;quot;Lizenzserver nutzen&amp;quot; und drücken Sie anschließend &amp;quot;Sichern&amp;quot;. expecco hat nun die benötigten Template Dateien unter &amp;quot;&amp;lt;code&amp;gt;C:\Users\IhrBenutzername\AppData\Roaming\expecco&amp;lt;/code&amp;gt;&amp;quot; angelegt. Kopieren Sie die &amp;quot;&amp;lt;code&amp;gt;.expeccoPreferences&amp;lt;/code&amp;gt;&amp;quot; und die &amp;quot;&amp;lt;code&amp;gt;expeccoLicenseServerLicense&amp;lt;/code&amp;gt;&amp;quot; Datei vor der automatischen expecco Installation in das entsprechende Verzeichnis auf Ihrem Zielrechner. expecco kann somit direkt nach der automatischen Installation starten.&lt;br /&gt;
&lt;br /&gt;
=== Autostart von expecco ===&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie dazu mit der &amp;lt;kbd&amp;gt;Windows-Taste&amp;lt;/KBD&amp;gt; + &amp;lt;KBD&amp;gt;&amp;quot;R&amp;quot;&amp;lt;/KBD&amp;gt; ein Ausführungs-Fenster. Geben Sie dort &amp;quot;shell:startup&amp;quot; ein. Danach öffnet sich der Autostart-Ordner. Kopieren Sie die expecco-Verknüpfung vom Desktop in diesen Ordner. Nun wird expecco, nachdem sich dieser Benutzer angemeldet hat, automatisch gestartet. Folgend können Sie konfigurieren, dass sich dieser Benutzer automatisch anmeldet, wenn der Rechner angeschaltet wird. Drücken Sie dazu erneut &amp;lt;KBD&amp;gt;Windows-Taste&amp;lt;/KBD&amp;gt; + &amp;lt;KBD&amp;gt;&amp;quot;R&amp;quot;&amp;lt;/KBD&amp;gt;. Geben Sie nun &amp;quot;netplwiz&amp;quot; ein. Es öffnet sich der Benutzerkonten-Dialog. In diesem können Sie den Haken &amp;quot;Benutzer müssen Benutzernamen und Kennwort eingeben&amp;quot; abwählen. Diese Einstellung gilt nur für das Anmelden nachdem der Rechner hochgefahren ist.&lt;br /&gt;
&lt;br /&gt;
Übrigens können diverse Parameter auf der [[Command Line Options|expecco-Kommandozeile]] angegeben werden. Hier sind insbesondere die Optionen [[Command Line Options#Startup|&amp;quot;--licenseFile&amp;quot;]], [[Command Line Options#Startup|&amp;quot;--licenseServer&amp;quot;]] und [[Command Line Options#Startup|&amp;quot;--licenseServerPort&amp;quot;]] zu erwähnen.&lt;br /&gt;
&lt;br /&gt;
=== expecco Einstellungen vordefinieren ===&lt;br /&gt;
&lt;br /&gt;
Es kann in bestimmten Fällen Sinn machen, die expecco Einstellungen für neue Windows-Benutzerkonten vorzudefinieren.&lt;br /&gt;
Z.B. könnte man die Adresse des Lizenzserver und die benötigten Pluginlizenzen vordefinieren.&lt;br /&gt;
Dies hätte den Vorteil, dass neue Benutzer direkt mit expecco loslegen können.&lt;br /&gt;
&lt;br /&gt;
Gehen Sie zum Vordefinieren der expecco Einstellungen für neue Windows-Benutzerkonten folgendermaßen vor:&lt;br /&gt;
* starten Sie expecco auf einem bereits vorhandenen Benutzerkonto (kann auch ein anderer Windows Rechner sein)&lt;br /&gt;
* stellen Sie dessen expecco Einstellungen (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot;) wie zur Vorlage gewünscht ein und speichern Sie über &amp;quot;&#039;&#039;Sichern&#039;&#039;&amp;quot;&lt;br /&gt;
* navigieren Sie zu dem Verzeichnis &amp;quot;C:\Users\{IhrBenutzer}\AppData\Roaming\expecco\&amp;quot; und kopieren Sie die 2 Dateien &amp;quot;.expeccoPreferences&amp;quot; und &amp;quot;expeccoLicenseServerLicense&amp;quot;&lt;br /&gt;
* begeben Sie sich zum Zielrechner und erstellen Sie einen Ordner &amp;quot;expecco&amp;quot; unter &amp;quot;C:\Users\Default\AppData\Roaming\&amp;quot;&lt;br /&gt;
* fügen Sie die 2 kopierten Dateien auf dem Zielrechner unter &amp;quot;C:\Users\Default\AppData\Roaming\expecco\&amp;quot; ein&lt;br /&gt;
&lt;br /&gt;
Jetzt werden alle neuen Windows-Benutzerkonten diese Einstellungen als Ausgangseinstellungen verwenden. Sie können diese Einstellungen auch bereits existierenden Windows-Benutzerkonten zuweisen. Hierfür fügen Sie die 2 Dateien in die entsprechenden Benutzerverzeichnisse auf dem Zielrechner &amp;quot;C:\Users\{ExistierenderBenutzer}\AppData\Roaming\expecco\&amp;quot; ein.&lt;br /&gt;
&lt;br /&gt;
ACHTUNG: damit werden alle bereits getätigen Einstellungen der Benutzer überschrieben.&lt;br /&gt;
&lt;br /&gt;
=== Update Installation von expecco (Windows) ===&lt;br /&gt;
&lt;br /&gt;
Wie bei der Erstinstallation erhalten eine E-Mail mit dem Link zu den neuen expecco-Installationsdateien.&lt;br /&gt;
Bitte laden Sie die Installationsprogramme herunter.&lt;br /&gt;
Bei der Ausführung des Basis-Installationsprogramms &amp;quot;&amp;lt;code&amp;gt;expeccoSetup-xxx.exe&amp;lt;/code&amp;gt;&amp;quot; erkennt expecco, dass es bereits installiert ist, und zeigt einen Dialog an, in dem Sie um eine Bestätigung gebeten werden, dass die alte expecco-Version deinstalliert werden darf.&lt;br /&gt;
Bestätigen Sie bitte diesen Dialog. Die alte expecco-Version wird mit allen Plugins deinstalliert.&lt;br /&gt;
Ihre Einstellungen, Lizenzdateien und Ihre Testsuiten bleiben erhalten.&lt;br /&gt;
Anschließend wird die neue expecco-Version wie bei der Erstinstallation (s.o.) installiert.&lt;br /&gt;
&lt;br /&gt;
=== Lizenz installieren ===&lt;br /&gt;
&lt;br /&gt;
Beim erstmaligen Ausführen erscheint ein Fenster, in dem eine Lizenz verlangt wird. Je nachdem, ob Sie eine Einzellizenz oder eine Floating-Lizenz (per Lizenzserver) nutzen, können Sie die Lizenz konfigurieren.&lt;br /&gt;
&lt;br /&gt;
[[#Konfiguration der Einzellizenz | Konfiguration der Einzellizenz]]&lt;br /&gt;
&lt;br /&gt;
[[#Konfiguration der Floating-Lizenz | Konfiguration der Floating-Lizenz]]&lt;br /&gt;
&lt;br /&gt;
== Installation von expecco auf Linux ==&lt;br /&gt;
&lt;br /&gt;
expecco läuft auf allen aktuellen Linux-Distributionen (Ubuntu, RedHat, Fedora, Oracle Linux, Debian, (Open-)SuSE, ...).&lt;br /&gt;
&lt;br /&gt;
=== Benötigte Linux Softwarepakete ===&lt;br /&gt;
&lt;br /&gt;
expecco läuft sowohl auf 32- als auch auf 64-bit Linux Systemen. Sie können expecco wahlweise als 64-bit-Version oder 32-bit-Version installieren.&lt;br /&gt;
Falls sie ein 64-bit Linux einsetzten (das ist mittlerweile der Standard) empfehlen wir die 64-bit expecco-Version.&amp;lt;br&amp;gt;&#039;&#039;&#039;Die 32-bit Linux-Version liefern wir nur noch auf Anfrage aus.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es wird eine glibc in der Version &amp;gt;= 2.14 benötigt.&lt;br /&gt;
&lt;br /&gt;
Installieren Sie über Ihren Paketmanager Ihrer Linux-Distribution folgende Pakete:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;libXinerama&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;libxrandr&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;libXft&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;libusb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;unixODBC&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;odbcinst&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;libglib-2_0-0&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;gnuplot&amp;lt;/code&amp;gt; (optional - falls Plot/Graph Aktionen benötigt)&lt;br /&gt;
&lt;br /&gt;
Diese Pakete hängen von weiteren Paketen ab, die der Paketmanager automatisch mit installiert.&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;Ubuntu (ab 15.04)&#039;&#039;&#039; installieren Sie die Pakete mit dem Kommando:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install -y \&lt;br /&gt;
        libxinerama1 libxft2 libxrandr2 unixodbc odbcinst libusb-1.0.0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;OpenSUSE (Leap 15.x)&#039;&#039;&#039; installieren Sie die Pakete mit:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;code&amp;gt;sudo zypper install unixODBC libXinerama1 libXrandr2 libXft2 libusb-0_1-4 libusb-1_0-0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Installation von 32-bit expecco auf 64-bit Linux (nicht empfohlen!) ====&lt;br /&gt;
&lt;br /&gt;
Diese Konfiguration empfehlen wir nicht. Nutzen Sie stattdessen besser die 64-bit expecco Version. &lt;br /&gt;
Falls Sie expecco-32-bit doch auf 64-bit-Linux installieren wollen, benötigen Sie die Pakete in der 32-bit Ausführung.&lt;br /&gt;
&lt;br /&gt;
Es wird eine glibc in der Version &amp;gt;= 2.10 benötigt.&lt;br /&gt;
&lt;br /&gt;
In Ubuntu 64bit (ab 15.04 64-bit) für ein 32-bit expecco installieren Sie die Pakete mit dem Kommando:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;code&amp;gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install -y \&lt;br /&gt;
        libxinerama1:i386 libxft2:i386 libxrandr2:i386 unixodbc:i386 odbcinst:i386 libusb-1.0.0:i386&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Installation von expecco (Linux) ===&lt;br /&gt;
&lt;br /&gt;
Sie erhalten eine E-Mail mit dem Link zu der expecco-Installationsdatei. Die Installationsdatei hat z.B. den Namen:&lt;br /&gt;
&lt;br /&gt;
* expecco-23.2.0.69.package&lt;br /&gt;
&lt;br /&gt;
wobei hier 23.2.0 der Versionsnummer von expecco entspricht und 69 der Build-Nummer. Die Installationsdatei enthält das expecco-Basispaket sowie die Plugins.&lt;br /&gt;
&lt;br /&gt;
Für die Installation benötigen Sie bei einer erstmaligen Installation außerdem noch das &#039;&#039;autopackage&#039;&#039; Paket. Sie können es hier herunterladen: https://download.exept.de/transfer/autopackage/x86_64/autopackage.tar.bz2. Entpacken Sie das Archive und installieren Sie dieses durch das Ausführen der INSTALL Datei im Root Verzeichnis des Archives. Sie werden ggf. gefragt ob die GUI Komponenten vom &amp;quot;Autopackage&amp;quot; herunter geladen und installiert werden sollen. Wählen Sie &amp;quot;NEIN&amp;quot; aus, da diese nicht benötigt werden und unter Umständen zu Fehlern führen können. &lt;br /&gt;
&lt;br /&gt;
Laden Sie die expecco-Installationsdatei und ggf. &#039;&#039;autopackage.tar.bz2&#039;&#039; in dasselbe Verzeichnis auf Ihrem Rechner.&lt;br /&gt;
&lt;br /&gt;
Sie können die Installation als Benutzer &#039;&#039;root&#039;&#039; oder als normaler Benutzer ausführen. Wenn Sie expecco als Benutzer &#039;&#039;root&#039;&#039; installieren, wird expecco im Verzeichnis &#039;&#039;/opt/expecco/bin&#039;&#039; installiert. Bei einer Installation als normaler Benutzer, wird expecco in Ihrem Home-Verzeichnis nach &#039;&#039;.local/bin&#039;&#039; installiert. &lt;br /&gt;
&lt;br /&gt;
Führen Sie aus:&lt;br /&gt;
    bash ./expecco-23.2.0.69.package&lt;br /&gt;
&lt;br /&gt;
expecco wird daraufhin installiert, es erscheint folgende Ausgabe:&lt;br /&gt;
 # Preparing package: expecco - Graphical Test Modeling&lt;br /&gt;
 # Checking for required C library versions ... passed&lt;br /&gt;
 This may take a moment, please wait ... done&lt;br /&gt;
 # Installing package: expecco - Graphical Test Modeling (package 1 of 1)&lt;br /&gt;
 # 100%[==================================================] Extracting&lt;br /&gt;
 # Copying files to /opt/expecco/plugin&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/technologyBridge&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/technologyBridge/javaBridge&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/technologyBridge/javaBridge/javaBridge_Server_Client&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/packages/stx/libsnmp&lt;br /&gt;
 # Copying files to /opt/expecco/packages/stx/libsnmp/net-snmp-5.7.2/mibs&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/testsuites/libraries&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/bin&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/lib&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/expecco/doc&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/testsuites/libraries&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/testsuites/examples&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/expecco/reportGenerator/tools&lt;br /&gt;
 # Copying files to /opt/expecco/packages/exept/pdf/afm&lt;br /&gt;
 # 100%[==================================================] Copying&lt;br /&gt;
 # Installing USB Dongle access...&lt;br /&gt;
 # Updating package database...&lt;br /&gt;
 The following package was successfully installed:&lt;br /&gt;
 * expecco - Graphical Test Modeling&lt;br /&gt;
 This installation used 478.74 MiB (502.00 MB) of disk space.&lt;br /&gt;
 Remove this package by running package remove expecco from the command line.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Installations-Optionen ===&lt;br /&gt;
&lt;br /&gt;
Sie können das Verzeichnis, in das expecco installiert wird, wie folgt festlegen:&lt;br /&gt;
&lt;br /&gt;
    bash expecco-23.2.0.69.package&lt;br /&gt;
             Installation als root nach /opt/expecco (Starten mit: /opt/expecco/bin/expecco)&lt;br /&gt;
&lt;br /&gt;
    bash expecco-23.2.0.69.package --prefix /opt/expecco-23.2&lt;br /&gt;
             Installation als root nach /opt/expecco-23.2 (Starten mit: /opt/expecco-23.2/bin/expecco)&lt;br /&gt;
&lt;br /&gt;
    bash expecco-23.2.0.69.package --local-only&lt;br /&gt;
             Installation als Benutzer nach $HOME/.local (Starten mit ~/.local/bin/expecco)&lt;br /&gt;
&lt;br /&gt;
    bash expecco-23.2.0.69.package --local-only --prefix ~/expecco&lt;br /&gt;
             Installation als Benutzer nach $HOME/expecco (Starten mit ~/expecco/bin/expecco)&lt;br /&gt;
&lt;br /&gt;
=== Update Installation von expecco (Linux) ===&lt;br /&gt;
&lt;br /&gt;
Wie bei der Erstinstallation erhalten eine E-Mail mit dem Link zu der neuen expecco-Installationsdatei.&lt;br /&gt;
Bitte laden Sie das Installationsprogramme herunter. Bei der Ausführung des Installationsprogramms &#039;&#039;bash expecco-***.package&#039;&#039; erkennt expecco, dass eine andere Version bereits installiert wurde. Die alte expecco-Version wird mit allen Plugins automatisch deinstalliert. Ihre Einstellungen, Lizenzdateien und Ihre Testsuiten bleiben erhalten. Anschließend wird die neue expecco-Version wie bei der Erstinstallation (s.o.) installiert.&lt;br /&gt;
&lt;br /&gt;
=== Deinstallieren ===&lt;br /&gt;
&lt;br /&gt;
    autopackage uninstall expecco&lt;br /&gt;
&lt;br /&gt;
=== Lizenz installieren ===&lt;br /&gt;
&lt;br /&gt;
Installieren Sie die Lizenz wie im nächsten Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
== Installation von expecco auf OS X ==&lt;br /&gt;
&lt;br /&gt;
Achtung: die OS X-Version ist z.Z. im Beta Test und auf Anfrage verfügbar.&lt;br /&gt;
&lt;br /&gt;
=== Benötigte macOS Softwarepakete ===&lt;br /&gt;
&lt;br /&gt;
expecco läuft auf 64-bit x64_64 mac OS X Systemen (eine Version für ältere 32bit Maschinen ist nur noch auf Anfrage erhältlich; beachten Sie, dass die neueren OS X Versionen 32bit Programme nicht mehr unterstützen).&lt;br /&gt;
Es wird mindestens OS X 10.6 benötigt.&lt;br /&gt;
&lt;br /&gt;
expecco benötigt XQuartz. Dieses sollten Sie vorher vom Apple Store oder [https://www.xquartz.org/ xquartz.org] installieren, falls nicht bereits vorinstalliert (kostenlos).&lt;br /&gt;
&lt;br /&gt;
=== Installation von expecco (OS X) ===&lt;br /&gt;
&lt;br /&gt;
Sie erhalten eine E-Mail mit dem Link zu der expecco-Installationsdatei. Die Installationsdatei hat z.B. den Namen:&lt;br /&gt;
&lt;br /&gt;
* expecco-2.11.0.1.dmg&lt;br /&gt;
&lt;br /&gt;
wobei hier 2.11.0 der Versionsnummer von expecco entspricht und 1 der Build-Nummer. Die Installationsdatei enthält das expecco-Basispaket sowie die Plugins.&lt;br /&gt;
&lt;br /&gt;
Zur Installation öffnen Sie die &amp;quot;&amp;lt;code&amp;gt;dmg&amp;lt;/code&amp;gt;&amp;quot;-Datei und verschieben &amp;quot;&amp;lt;code&amp;gt;expecco.app&amp;lt;/code&amp;gt;&amp;quot; in den &amp;quot;&amp;lt;code&amp;gt;Application&amp;lt;/code&amp;gt;&amp;quot;-Ordner (oder Ihren privaten &amp;quot;&amp;lt;code&amp;gt;Application&amp;lt;/code&amp;gt;&amp;quot;-Ordner, oder jeden beliebigen anderen Ordner).&lt;br /&gt;
&lt;br /&gt;
=== Deinstallation von expecco (OS X) ===&lt;br /&gt;
Sämtliche Dateien von expecco, mit Ausnahme Ihrer eigenen Suiten und Einstellungen sind im expecco.app Ordner. Löschen Sie diesen Ordner (und entleeren den Papierkorb) um expecco zu deinstallieren.&lt;br /&gt;
Ihre eigenen Einstellungen befinden sich im Homeverzeichnis unter &amp;quot;.expecco&amp;quot;; Ihre Suiten sind im Documentsordner, falls nicht explizit an anderer Stelle gespeichert.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration der Lizenz ==&lt;br /&gt;
&lt;br /&gt;
Beim erstmaligen Ausführen erscheint ein Fenster, in dem eine Lizenz verlangt wird. Falls Sie bereits eine Lizenz installiert haben und diese wechseln möchten können Sie den selben Dialog unter &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot; öffnen, allerdings müssen Sie in diesem Fall nach dem Wechseln der Lizenz expecco neu starten.&lt;br /&gt;
&lt;br /&gt;
Fall Sie expecco auf einem Computer ohne GUI installiert haben, kann das zuvor erwähnte Fenster nicht geöffnet werden. In dem Fall müssen Sie expecco auch auf einem Computer mit GUI installieren und dort den Dialog ausfüllen. Danach kopieren Sie die Settingsdatei &amp;quot;&amp;lt;code&amp;gt;~/.expecco/.expeccoPreferences&amp;lt;/code&amp;gt;&amp;quot; oder &amp;quot;&amp;lt;code&amp;gt;C:\users\IhrBenutzer\AppData\Roaming\expecco\.expeccoPreferences&amp;lt;/code&amp;gt;&amp;quot; und die Lizenzdatei &amp;quot;&amp;lt;code&amp;gt;~/.expecco/expeccoLicenseServerLicense&amp;lt;/code&amp;gt;&amp;quot; oder &amp;quot;&amp;lt;code&amp;gt;C:\users\IhrBenutzer\AppData\Roaming\expecco\expeccoLicenseServerLicense&amp;lt;/code&amp;gt;&amp;quot; auf den Computer ohne GUI. &lt;br /&gt;
&lt;br /&gt;
[[#Konfiguration der Einzellizenz | Konfiguration der Einzellizenz]]&lt;br /&gt;
&lt;br /&gt;
[[#Konfiguration der Floating-Lizenz | Konfiguration der Floating-Lizenz]]&lt;br /&gt;
&lt;br /&gt;
[[#Auslösen einer Floating-Lizenz | Auslösen einer Floating-Lizenz]]&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration der Einzellizenz ===&lt;br /&gt;
&lt;br /&gt;
Einzellizenzen werden üblicherweise mit einem USB-Dongle genutzt.&lt;br /&gt;
Ausnahmsweise können auch zeitlich limitierte Einzellizenzen ohne Dongle verwendet werden (sog. &amp;quot;&#039;&#039;Demo Lizenz&#039;&#039;&amp;quot;).&lt;br /&gt;
In beiden Fällen erhalten Sie eine Lizenzdatei.&lt;br /&gt;
Lizenzdateien und Dongle müssen jeweils zusammenpassen, wobei eine Lizenzdatei auch zu mehreren Dongles desselben Kunden passen kann.&lt;br /&gt;
&lt;br /&gt;
# falls Sie einen Dongle erhalten haben, stecken Sie ihn in einen freien USB-Port in Ihrem Rechner.&lt;br /&gt;
# Speichern Sie die Lizenzdatei auf Ihrem Rechner&lt;br /&gt;
# Ziehen Sie dann entweder die Datei mit der Maus aus dem Windows-Explorer in den Lizenzdialog, oder Sie wählen im Lizenzdialog Ihre Lizenzdatei direkt aus.&lt;br /&gt;
# Sie werden aufgefordert, expecco neu zu starten. Nach dem Neustart können Sie expecco nutzen.&lt;br /&gt;
&lt;br /&gt;
Lizenzdateien ohne Dongle sind zeitlich beschränkt.&lt;br /&gt;
Wenn Sie versehentlich den expecco-Dongle nicht in Ihren Rechner eingesteckt haben und expecco starten, erhalten Sie einen Hinweis, dass die Lizenz abgelaufen sei.&lt;br /&gt;
Sobald Sie den Dongle einstecken (bevor Sie expecco starten), erscheint dieser Hinweis beim Start von expecco nicht mehr.&lt;br /&gt;
&lt;br /&gt;
Solange Sie mit expecco arbeiten, wird überwacht, ob der Dongle vorhanden ist.&lt;br /&gt;
Wenn Sie den Dongle währenddessen aus Ihrem Rechner entfernen, erhalten Sie einen Hinweis und können keine Tests mehr ausführen oder verändern.&lt;br /&gt;
Sie können allerdings die gerade bearbeitete Testsuite noch abspeichern, so dass keine Änderungen verloren gehen.&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration der Floating-Lizenz ===&lt;br /&gt;
&lt;br /&gt;
Um eine Floating-Lizenz zu nutzen, benötigen Sie einen expecco-Lizenzserver. Diesen (bzw. den Downloadlink) erhalten Sie von uns mit den Floatinglizenzen. Der Lizenzserver ist eine HTTP-Serviceanwendung, die auf einem beliebigen Rechner in einer Cloud oder Ihrer Firma oder Abteilung installiert wird. Sie läuft ohne eigenes Fenster, und wird über einen beliebigen WebBrowser bedient.&lt;br /&gt;
&lt;br /&gt;
Der Lizenzserver ist unter einem Rechnername bzw. IP-Adresse und einer Portnummer zu erreichen.&lt;br /&gt;
Der Administrator des Lizenzservers kann Ihnen diese Informationen geben, falls er eine andere als die default-Portnummer konfiguriert hat.&lt;br /&gt;
Es muss sichergestellt sein, dass eine TCP-Verbindung zum entsprechenden Port im Lizenzserver aufgebaut werden kann.&lt;br /&gt;
Router und Firewalls sind gegebenenfalls entsprechend zu konfigurieren bzw. Ports freizuschalten.&lt;br /&gt;
&lt;br /&gt;
Beim Start von expecco öffnet sich der Lizenzdialog.&lt;br /&gt;
Wählen Sie hier die Lizenzserver-Kachel aus.&lt;br /&gt;
Tragen Sie den Rechnernamen bzw. die IP-Adresse sowie die Portnummer des Lizenzservers ein.&lt;br /&gt;
Im allgemeinen kann die vorgeschlagene default Portnummer unverändert übernommen werden.&lt;br /&gt;
Lediglich in Netzwerken, bei denen nur bestimmte Ports durch Firewalls oder Router durchgeschaltet werden ist es u.U. notwendig, eine andere Portnummer zu verwenden.&lt;br /&gt;
Der Administrator des Lizenzservers kann Ihnen in diesem Fall diese Informationen geben&lt;br /&gt;
&lt;br /&gt;
Sie können jetzt auswählen, welche expecco-Ausprägung Sie verwenden wollen: &#039;&#039;expecco-developer&#039;&#039; oder &#039;&#039;expecco-runtime&#039;&#039;.&lt;br /&gt;
Über die Schaltfläche &amp;quot;&#039;&#039;Plugin-Liste vom Server aktualisieren&#039;&#039;&amp;quot; erhalten Sie die verfügbaren Plugins (bzw. Plugins für die noch Floating-Lizenzen verfügbar sind).&lt;br /&gt;
Wählen Sie die Plugins aus, die Sie für Ihre Tests benötigen.&lt;br /&gt;
Von den meisten Plugins benötigen Sie nur eine Lizenz.&lt;br /&gt;
Einzelne Plugins können für auf mehrere Rechner verteilte Tests mehr als eine Lizenz von einem Plugin benötigen - Sie können das für derartige Plugins angeben.&lt;br /&gt;
Im Dialog wird angezeigt, wie viele Lizenzen für ein bestimmtes Plugin auf dem Lizenzserver momentan noch zur Verfügung stehen.&lt;br /&gt;
Per Tooltip können Sie auch in Erfahrung bringen, wie viele Lizenzen generell vorhanden sind.&lt;br /&gt;
Die Differenz sind die momentan von anderen Benutzern verwendeten Lizenzen.&lt;br /&gt;
&lt;br /&gt;
Über die Schaltfläche &amp;quot;&#039;&#039;Lizenzdatei installieren&#039;&#039;&amp;quot; werden die Lizenzen vom Lizenzserver abonniert.&lt;br /&gt;
Starten Sie jetzt expecco neu, damit die lizenzierten Plugins geladen werden.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco beendet wird, werden alle Lizenzen wieder an den Lizenzserver zurück gegeben.&lt;br /&gt;
Expecco erneuert regelmäßig die Lizenzen vom Lizenzserver.&lt;br /&gt;
Wenn der Lizenzserver über einen gewissen Zeitraum nicht mehr erreichbar sein sollte (ca. 15 Minuten), wird expecco gesperrt, so dass keine Tests mehr ausgeführt oder verändert werden können. Geänderte Testsuiten können aber noch abgespeichert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco nicht regulär beendet wurde, z.B. wenn der Rechner einfach ausgeschaltet wird, fallen die Lizenzen nach diesem Zeitraum an den Lizenzserver zurück und können dann von anderen Benutzern genutzt werden.&lt;br /&gt;
&lt;br /&gt;
expecco merkt sich, welche Lizenzen zuletzt abonniert wurden.&lt;br /&gt;
Wenn expecco gestartet wird, versucht es, die zuletzt abonnierten Lizenzen wieder zu erhalten.&lt;br /&gt;
Sollte das nicht möglich sein, da alle Lizenzen momentan vergeben sind, erscheint der Lizenzdialog, in dem die nicht oder nur teilweise erhaltenen Lizenzen rot unterlegt sind.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie neue Lizenzen benötigen oder bisher verwendete Lizenzen nicht mehr benötigen, können Sie die anzufordernden Lizenzen jederzeit über den Lizenzdialog anpassen.&lt;br /&gt;
Sie erreichen ihn über das Menü &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Auslösen einer Floating-Lizenz ===&lt;br /&gt;
&lt;br /&gt;
Floatinglizenzen können auch ohne bestehende Verbindung zum Lizenzserver ausgelöst werden (sog. &amp;quot;&#039;&#039;road warrior&#039;&#039; Lizenzen&amp;quot;). Dies ermöglicht es Ihnen, auch zuhause, bei Kunden oder in isolierten Labors mit expecco zu arbeiten, ohne dass dafür ein Dongle benötigt wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Verfügbar ab expecco Version 2.10.x.x&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Auch wenn Ihr expecco keine Netzwerkverbindung hat, ist es möglich expecco mit einer Floating-Lizenz zu betreiben. Die Lizenz für expecco wird für eine bestimmte Zeitspanne ausgelöst. Nachdem diese Zeitspanne verstrichen ist, wird die ausgelöste Lizenz automatisch wieder zurückgegeben (eingegliedert). Bitte beachten Sie, dass es &#039;&#039;&#039;keine Möglichkeit gibt, eine ausgelöste Lizenz vor ihrem Ablauf wieder zurückzugeben!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hierfür brauchen Sie einen Lizenzservice (expecco ALM), aus welchem die Floating-Lizenz ausgelöst wird.&lt;br /&gt;
&lt;br /&gt;
Zum Auslösen einer Floating-Lizenz starten Sie expecco und rufen Sie den Lizenzdialog unter &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot; auf (beim erstmaligem Start erscheint dieser automatisch) und navigieren Sie in den Reiter &amp;quot;Ausgelöste Floating-Lizenz&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Dort haben Sie folgende Möglichkeiten:&lt;br /&gt;
==== Eine Anfrage zum Auslösen einer Floating-Lizenz erstellen ====&lt;br /&gt;
Stellen Sie sich Ihre gewünschte Lizenz zusammen. Definieren Sie den Typ (Runtime / Pro), die Plugins und wie lange Sie die Lizenz auslösen möchten. Sie können Ihre Anfrage dann entweder in eine Datei speichern oder in die Zwischenablage legen.&lt;br /&gt;
&lt;br /&gt;
Rufen Sie nun das Web-Interface des Lizenzservices (expecco ALM) in einem Webbrowser auf. Navigieren Sie in expecco ALM zu &amp;quot;&#039;&#039;Lizenzservice&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;expecco Lizenzen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenz auslösen&#039;&#039;&amp;quot;. Dort können Sie dann Ihre Anfrage entweder über Datei hochladen oder aus der Zwischenablage in das freie Feld einfügen.&lt;br /&gt;
&lt;br /&gt;
Nach dem erfolgreichen Einspielen Ihrer Anfrage wird Ihnen Ihre Anfrage zur Gegenprüfung im Detail angezeigt. Sie können hier die Dauer der Auslösung ggf. erneut anpassen. Über den Knopf &amp;quot;Auslösen bestätigen&amp;quot; wird die Lizenz endgültig ausgelöst. Danach ist diese Lizenz bis zum Ablauf der Dauer ausschließlich für das expecco, von welchem die Anfrage erstellt wurde reserviert. Ihnen wird anschließend der Bestätigungsschlüssel angezeigt. Diesen können Sie wiederum als Datei speichern oder über Rechtsklick &amp;quot;Kopieren&amp;quot; in die Zwischenablage legen.&lt;br /&gt;
&lt;br /&gt;
Jetzt müssen Sie diesen Bestätigungsschlüssel an expecco übertragen (über USB-Stick, Zuruf, Telefon usw.) und eingeben oder die Datei auswählen.&lt;br /&gt;
&lt;br /&gt;
==== Eine bereits ausgelöste Floating-Lizenz in Betrieb nehmen ====&lt;br /&gt;
Falls Sie expecco aus Versehen während dem Prozess des Auslösens geschlossen haben oder der Prozess durch etwas ähnlich unterbrochen wurde, ist die ausgelöste Lizenz nicht verloren. Sie können diese Lizenz anhand Ihrer Anfrage und zugehörigem Bestätigungsschlüssel jederzeit in expecco aktivieren.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie dazu den Lizenzservice (expecco ALM) und navigieren Sie nach &amp;quot;&#039;&#039;Lizenzservice&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;expecco Lizenzen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Im Einsatz&#039;&#039;&amp;quot;. Suchen Sie in dieser Liste nach einer passenden Lizenz. Eine passende Lizenz erkennen Sie bspw. an der Spalte &amp;quot;Rechnername&amp;quot;, diese Spalte sollte mit dem Rechnernamen auf dem expecco installiert ist übereinstimmen. Übertragen Sie die Anfrage sowie den Bestätigungsschlüssel aus den Spalten &amp;quot;Auslöse-Anfrage-Datei&amp;quot; und &amp;quot;Auslösungsschlüssel&amp;quot; zu expecco.&lt;br /&gt;
&lt;br /&gt;
In expecco müssen Sie die Auslöse-Anfrage-Datei auswählen und diese dann mit dem Bestätigungsschlüssel aktivieren.&lt;br /&gt;
&lt;br /&gt;
==== Die aktuell verwendete ausgelöste Floating-Lizenz verlängern ====&lt;br /&gt;
&lt;br /&gt;
Das Verlängern einer ausgelösten Floating-Lizenz ist nur möglich, solange diese noch gültig ist. Nach dem Ablauf einer ausgelösten Lizenz wird diese im Lizenzserver gelöscht und Sie müssen diese durch eine neue Anfrage erneuern (i.e. eine neue Lizenz auslösen).&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie dazu den Lizenzservice (expecco ALM) und navigieren Sie nach &amp;quot;&#039;&#039;Lizenzservice&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;expecco Lizenzen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Im Einsatz&#039;&#039;&amp;quot;. Suchen Sie in dieser Liste nach einer passenden Lizenz. Eine passende Lizenz erkennen Sie bspw. an der Spalte &amp;quot;Rechnername&amp;quot;. Diese Spalte sollte mit dem Rechnernamen, auf dem expecco installiert ist, übereinstimmen.&lt;br /&gt;
&lt;br /&gt;
Klicken Sie nun auf &amp;quot;Verlängern&amp;quot;. Sie werden automatisch auf die Seite &amp;quot;Lizenz verlängern&amp;quot; weitergeleitet. Ihre Lizenz ist bereits vorselektiert. Sie können nun das gewünschte Datum eingeben. Danach wird Ihnen ein neuer Bestätigungsschlüssel angezeigt, diesen müssen Sie in expecco eingeben.&lt;br /&gt;
&lt;br /&gt;
=== Änderung des Lizenztyps nach der Installation ===&lt;br /&gt;
&lt;br /&gt;
Über das Menü &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Lizenzinstallation&#039;&#039;&amp;quot; können Sie die Lizenz nachträglich ändern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Die Änderung des Lizenztyps werden permanent gespeichert, wenn Sie die Einstellung mit der Schaltfläche &amp;quot;Sichern&amp;quot; abspeichern.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Weitere Hilfspakete und Frameworks ==&lt;br /&gt;
&lt;br /&gt;
Die Basisinstallation wie oben beschrieben beinhaltet bereits die meisten normalerweise benötigten Komponenten. Abhängig von später durchzuführenden Tests und benötigter Software können (sollten) weitere Pakete ebenfalls installiert werden. Hinweise dazu finden Sie im Dokument: [[Installing_additional_Frameworks/en | &amp;quot;Installing additional Frameworks&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
Wir empfehlen folgende Pakete:&lt;br /&gt;
* [[Installing_additional_Frameworks/en#Java_Installation_.28for_Groovy_Actions.2C_Web-_and_Mobile_Testing.29|Java Runtime or JDK]]&lt;br /&gt;
* [[Installing_additional_Frameworks/en#Python_Installation_.28for_Python_Actions.29|Python]]&lt;br /&gt;
* [[Installing_additional_Frameworks/en#OCR_.28Optical_Character_Recognition.29|Tesseract]]&amp;lt;br&amp;gt;falls Sie OCR (Optical Character Recognition) zum Extrahieren von Texten aus Bildern und Bildschirmabzügen benötigen.&lt;br /&gt;
&lt;br /&gt;
Ausserdem sinnvoll (aber seltener benötigt):&lt;br /&gt;
* [[Installing_additional_Frameworks/en#Node_Installation_.28for_Node.js_Actions.29|Node]]&lt;br /&gt;
&lt;br /&gt;
Falls Sie Aktionen in C or C++ schreiben wollen (müssen):&lt;br /&gt;
* [[Installing_additional_Frameworks/en#C_Compiler_Toolchain_Installation_.28for_C-Actions.29|C Compiler Toolchain]]&lt;br /&gt;
&lt;br /&gt;
== Patches und Aktualisierungen ==&lt;br /&gt;
&lt;br /&gt;
Exept stellt  auch zwischen zwei Major Releases zu Verfügung in unregelmäßigen Abständen oder auf Anfrage Patches und Erweiterungen.&lt;br /&gt;
&lt;br /&gt;
Patches sind versionsabhängig; d.h. ein Patch für expecco Version 23.1 ist nicht für andere Versionen zu verwenden.&lt;br /&gt;
Normalerweise beinhaltet jede neue Major Release (z.B. 24.1) alle Patches aller Vorgängerversionen.&lt;br /&gt;
Oft sogar mehr Funktionalität. Alte Patches sollten daher nicht in neuere Versionen eingespielt werden,&lt;br /&gt;
und expecco lehnt auch solche Patches ab. Es besteht also keine Gefahr, dass diese aus Versehen eingespielt werden.&lt;br /&gt;
&lt;br /&gt;
Die Patches kommen in Dateien paarweise: eine &amp;quot;.expeccoPatch&amp;quot; und eine &amp;quot;.info&amp;quot; Datei.&lt;br /&gt;
Letztere beinhaltet eine textuelle Beschreibung; erstere den eigentlichen Patch.&lt;br /&gt;
Die Patches sind signiert, und expecco wird nur patch Dateien welche von exept signiert sind akzeptieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die patch Dateien können auf mehrere Arten sowohl manuell als auch automatisch heruntergeladen und eingespielt werden.&lt;br /&gt;
Sie befinden sich physikalisch auf dem download host von exept, unter &amp;quot;http://dowloads.exept.de&amp;quot; und &amp;quot;ftp://ftp.exept.de/downloads&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Automatisch vom Exept Download Server ===&lt;br /&gt;
&lt;br /&gt;
Wenn sie Zugriff aufs Internet mit http (port80) oder https (port 443) haben,&lt;br /&gt;
gehen sie zu &amp;quot;Extras&amp;quot; - &amp;quot;Einstellungen&amp;quot; - &amp;quot;Software Aktualisierung&amp;quot;.&lt;br /&gt;
Und verifizieren die Einstellungen zu &amp;quot;Patch Server&amp;quot;.&lt;br /&gt;
Zum Test der Verbindung klicken sie auf &amp;quot;Jetzt nach Updates suchen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Sie können oben auswählen, wann und wie oft expecco nach Updates schauen soll.&lt;br /&gt;
&lt;br /&gt;
=== Automatisch von einem hauseigenen Download Server ===&lt;br /&gt;
&lt;br /&gt;
Falls ihr Testrechner keinen Zugriff aufs Internet hat, aber ein anderer Rechner im Hausnetz erreichbar ist, können sie die Patches auch wie unten beschrieben auf diese Maschine herunterladen und von ihren Testrechnern die Patches dort abholen.&lt;br /&gt;
Dies hat den Vorteil, dass der download nur einmal durchgeführt werden muss, und sie selbst Kontrolle über die Patches haben.&lt;br /&gt;
&lt;br /&gt;
Gehen sie dazu wie oben beschrieben zum Einstellungsdialog, und geben den Namen und Pfad ihres Servers ein. Dort sollte dann ein Dateiservice mit unten beschriebener Dateistruktur zu finden sein (z.B. ein entsprechen aufgesetzter apache Server).&lt;br /&gt;
&lt;br /&gt;
=== Automatisch von einem hauseigenen Lizenz Server ===&lt;br /&gt;
&lt;br /&gt;
Wenn Sie keinen apache Server aufsetzen wollen oder können, aber einen Lizenzserver verwenden, können sie die patches auch auf dessen Rechner unter einem beliebigen Verzeichnis ablegen und den Lizenzserver entsprechend konfigurieren.&lt;br /&gt;
&lt;br /&gt;
Im Lizenzserver (AIDYMO) gehen sie zu den &amp;quot;Einstellungen&amp;quot; - &amp;quot;System&amp;quot;, und finden unten in der Maske unter &amp;quot;Sonstige&amp;quot; eine Checkbox &amp;quot;Patches Service&amp;quot;. Schalten sie diese Box ein, und geben darunter den Pfad zu dem patches Verzeichnis (auf dem Rechner des Lizenzservers).&lt;br /&gt;
Die Orderstruktur darunter entspricht der unten beschriebenen unter &amp;quot;expecco&amp;quot;. I.e. &amp;quot;&amp;lt;versionsNr&amp;gt;/patches/...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Manuell ===&lt;br /&gt;
&lt;br /&gt;
Falls ihr Testrechner isoliert vom Internet oder dem Hausnetz arbeitet (z.B. in einem Cleanroom oder Prüfstand),&lt;br /&gt;
müssen die Patches zunächst auf den Rechner gebracht werden. Dies kann z.B. über ein Medium (USB-Stick) oder ein Netzlaufwerk erfolgen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Unter dem jeweiligen Hauptverzeichnis (siehe oben) befindet sich ein Ordner per Release, und darunter die patch- und info Dateien.&lt;br /&gt;
Also z.B.:&lt;br /&gt;
    https://download/expecco/23.2.0/patches&lt;br /&gt;
        0001_fix1.expeccoPatch&lt;br /&gt;
        0001_fix1.info&lt;br /&gt;
        0002_feature1.expeccoPatch&lt;br /&gt;
        0002_feature1.info&lt;br /&gt;
    https://download/expecco/24.1.0/patches&lt;br /&gt;
        0001_fix2.expeccoPatch&lt;br /&gt;
        0001_fix2.info&lt;br /&gt;
    usw.&lt;br /&gt;
&lt;br /&gt;
Falls der automatische update versagt, können Sie die Dateien als fallback im Browser herunterladen (sichern als),&lt;br /&gt;
in einem Ordner sammeln und wie unten beschrieben manuell einspielen.&lt;br /&gt;
&lt;br /&gt;
Falls es sich um einen Individualpatch für Sie persönlich handelt, kann er ihnen auch per email zugesandt, oder in AIDYMO als Anhang übergeben werden.&lt;br /&gt;
&lt;br /&gt;
Bringen sie dazu die &amp;quot;.expeccoPatch&amp;quot; Dateien auf den Testhost (z.B. in ein Temp Verzeichnis), und&lt;br /&gt;
wählen im &amp;quot;Extras&amp;quot; -&amp;gt; &amp;quot;Maintenance&amp;quot; -&amp;gt; &amp;quot;Install Patch from File&amp;quot;.&lt;br /&gt;
Im geöffneten Dialog wählen Sie die entsprechen(n) Datei(en) an und bestätigen sie.&lt;br /&gt;
&lt;br /&gt;
Diesen Vorgang müssen Sie nur einmal durchführen; mit jedem Neustart werden die Patches automatisch neu installiert.&lt;br /&gt;
Die temporären Dateien können sie nach der Installation löschen; sie werden nicht mehr gebraucht.&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Hauptseite&amp;diff=30814</id>
		<title>Hauptseite</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Hauptseite&amp;diff=30814"/>
		<updated>2025-06-23T10:18:38Z</updated>

		<summary type="html">&lt;p&gt;Sv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Hauptseite/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
Klicken Sie links auf &#039;&#039;&amp;quot;Letzte Änderungen&amp;quot;&#039;&#039; (&amp;quot;Recent changes&amp;quot;) um die neuesten Einträge in der Dokumentation zu sehen.&amp;lt;br&amp;gt;Sie sehen dann meist, woran unsere Entwickler gerade vornehmlich arbeiten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h2&amp;gt;expecco&amp;lt;/h2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:flex; flex-wrap:wrap; padding:0; white-space:nowrap&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Für Einsteiger&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;!-- Link mit Fragezeichen funktioniert nicht, deshalb externer Link --&amp;gt;&lt;br /&gt;
			&amp;lt;!-- &amp;lt;li&amp;gt;[[Was ist expecco?|Allgemeine Informationen]]&amp;lt;/li&amp;gt; --&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[https://doc.expecco.de/w2.x/index.php?title=Was_ist_expecco%3F Allgemeine Informationen]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Expecco Usecases|Einsatzbereiche]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Features|expecco Feature-List]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Tutorials]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[usageHints/en|Hinweise zur Bedienung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Glossary|Begriffserklärung]] (Glossar)&amp;lt;/li&amp;gt;&lt;br /&gt;
 			&amp;lt;!-- &amp;lt;li&amp;gt;[[Testorganisation|Testorganisation]]&amp;lt;/li&amp;gt; --&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[FAQ]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage5.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Installation&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Installation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Installing additional Frameworks/en| Installation zusätzlicher Tools (Node, Python, ...)]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Personal Settings|Persönliche&amp;amp;nbsp;Einstellungen]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Configuration &amp;amp; Setup|Konfiguration]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Anbindung expecco ALM]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[SAP_Testing|Anbindung expecco an SAP]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Spezifische Anpassung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco UI]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_Remote_Control_App|expecco Mobile Remote App]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Probleme &amp;amp; Fehler]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage4.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Werkzeuge&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[API von Elementaraktionen]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Debugger]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Editoren]]&amp;lt;/li&amp;gt;		&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Standard Libraries/Bibliotheken]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Weitere Werkzeuge]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Weitere Funktionen]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage6.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Reportgenerierung&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Report Generation|Reportgenerierung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Errors during Execution|Fehler während der Ausführung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Secret Strings|Geheime Zeichenketten und Passwörter]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	 &amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Erweiterung_plugin.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Erweiterungen (Plugins)&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[GUI Testing]]&lt;br /&gt;
				&amp;lt;ul&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Java GUI Plugins|Java Swing/FX/SWT UI Testing]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Mobile Testing Plugin|Mobile Testing auf Android und iOS]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[WindowsAutomation Reference 2.0|UI Testing mit der Windows Automation Library]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Selenium_WebDriver_Plugin|Web Testing mit Selenium WebDriver]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                                        &amp;lt;li&amp;gt;[[VNC_Plugin_Reference|VNC UI Testing]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[GUI Testing|Weitere GUI Testing Plugins]]&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;/ul&amp;gt;&lt;br /&gt;
			&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Schnittstellen zum SUT]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[ManualTest]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;Produktivit&amp;amp;auml;t&lt;br /&gt;
				&amp;lt;ul&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[GIT Plugin]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                                        &amp;lt;li&amp;gt;[[HG Plugin (Mercurial)]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[CVS Plugin]]&amp;lt;/li&amp;gt;&lt;br /&gt;
					&amp;lt;li&amp;gt;[[Anbindung expecco ALM | expeccoALM Schnittstelle]]&amp;lt;/li&amp;gt;&lt;br /&gt;
				&amp;lt;/ul&amp;gt;&lt;br /&gt;
			&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Weitere Plugins]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe;  margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage3.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Elemente der Testsuite&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Tree Elements|Tree Elemente]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Folder Element|Ordner]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Testplan Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Aktionen/Aktionsblöcke]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Datatype Element|Datentyp Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Inventory Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Skill Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Resource Element|Ressource Element]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Attachment Element|Anhänge]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[ReportTemplate Element|Report Templates]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color:#ecf0fe;  margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage3.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;API Referenz (Elementarbausteine)&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[API von Elementaraktionen|Übersicht]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco API#JavaScript_and_Smalltalk_Elementary_Blocks|Smalltalk &amp;amp; JavaScript]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco API#Groovy_Elementary_Blocks|Groovy]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Node.js_.28Bridged.29_Elementary_Blocks|NodeJS]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Bridged_Python_Elementary_Blocks|Python]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Bridged_Ruby_Elementary_Blocks|Ruby]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco_API#Bridged_C_Elementary_Blocks|C]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Expecco API#VisualBasic_Elementary_Blocks|VisualBasic ]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Expecco Scripting API|Shell und Script Languages]]&amp;lt;/li&amp;gt; &lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Diagramm.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Diagramm - Elemente&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Step|Schritt]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Pins (Ein - Ausgänge)]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Code Ausführung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Connection|Verbindung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Pin|Pin Beschreibung]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Annotation|Notiz]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[DiagramElements-Probe|Messfühler]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Refresh.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Sonstiges&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 25.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 24.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 23.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 22.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 21.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 20.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 19.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 18.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 2.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Release Notes 1.x]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Future releases expecco|Zukünftige Releases]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Smalltalk]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Beispiele_icon.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Beispiele&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
                &amp;lt;span style=&amp;quot;padding:0 1em;font-size:0.9em&amp;quot;&amp;gt;Sie haben Fragen, wie ein Projekt aussieht?&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
                &lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;amp;nbsp;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Beispiele | Hier finden Sie weitere Anwendungsbeispiele.]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Expecco Code Snippets/en | Codeschnipsel]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Beispiele_icon.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Unterstützung weiterer Qualitätsmanagement Tools&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
                &lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Jira_Plugin_Reference|Jira]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[PolarionPlugin_Reference|Polarion]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Aqua_Plugin_Reference|Aqua]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Starting_expecco_via_Command_Line#Integration_with_Jenkins|Jenkins Integration]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h2 style=&amp;quot;clear:left&amp;quot;&amp;gt;expecco ALM&amp;lt;/h2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:flex; flex-wrap:wrap; padding:0; white-space:nowrap&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Sonstiges-Info.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Allgemein&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		&amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Was ist expecco ALM?]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Was ist der expecco Lizenzserver?]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Anbindung expecco ALM]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Rollen und Rechte]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[Filter]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[FAQ expeccoALM/en | FAQ]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Icon_Landingpage5.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Installation/Einrichten&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Installation|Installation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Installation Patches|expecco ALM Installation Patches]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Einrichten Vorgehensweise|expecco ALM Einrichten]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM expecco Patch Service |Patchservice für expecco]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Refresh.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Plugins&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[AIDYMO Jira|Atlassian Jira]]&amp;lt;/li&amp;gt;&lt;br /&gt;
                        &amp;lt;li&amp;gt;[[CustomerSpecific|Kundenspezifische Portale]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;div style=&amp;quot;background-color:#ecf0fe; margin:12px 8px 0 0; flex:1 0 auto&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		 &amp;lt;span style=&amp;quot;padding-left:0.6em&amp;quot;&amp;gt;[[Datei:Refresh.png|30px]]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;padding:0 1em&amp;quot;&amp;gt;Sonstiges&amp;lt;/span&amp;gt;&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		  &amp;lt;ul style=&amp;quot;font-size:0.8em; padding:0.7em 1em 1em 2.4em&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM App]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[Installation Lizenzserver]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Release Notes|Release Notes]]&amp;lt;/li&amp;gt;&lt;br /&gt;
			&amp;lt;li&amp;gt;[[expecco ALM Known Issues|Known Issues]]&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;/ul&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30813</id>
		<title>Release Notes 25.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30813"/>
		<updated>2025-06-23T10:17:26Z</updated>

		<summary type="html">&lt;p&gt;Sv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 24.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 25.1 (Scheduled for June 2025) ==&lt;br /&gt;
*Improvement: additional &amp;quot;Info&amp;quot; tab in inspector views&lt;br /&gt;
*Improvement: less memory usage in the activity log&lt;br /&gt;
*Improvement: better error messages and more links to settings from the activity log&#039;s error message&lt;br /&gt;
*Improvement: additional units and conversions in the [[PhysicalValues/en|physical values framework]]&lt;br /&gt;
*Improvement: more precision in the [[Numeric_Limits/en#Higher_Precision_Numbers|high precision trigonometric and math functions]]&lt;br /&gt;
*Improvement: WindowsAutomation: Plugn Update to FlaUI 5&lt;br /&gt;
*Improvement: Mobile Testing: Better Device Lock/Unlock Support&lt;br /&gt;
*Improvement: StandardLibrary: &amp;quot;File [ *CSV ]&amp;quot; blocks got an additional &amp;quot;characterEncodeing&amp;quot; pin (useful for reading/writing e.g. utf-8 encoded CSV files)&lt;br /&gt;
*Improvement: ExcelLib: better documentation. Now requires the openpyxl package version &amp;gt;= 3.1.5. &lt;br /&gt;
*Improvement: better model language editor (translate and fetch-strings functions)&lt;br /&gt;
*Improvement: ODBClibrary: improved compatibility with different database vendors (supports the CedarDB database) &lt;br /&gt;
*Feature: translate and spell check in the workspace window&lt;br /&gt;
*Feature: EditLock of suites loaded from expeccoALM / AIDYMO&lt;br /&gt;
*Feature: Start Test in expeccoALM / AIDYMO (via expecco)&lt;br /&gt;
*Feature: new library containing expeccoALM control actions (those from the AIDYMO menu)&lt;br /&gt;
*Fix: the version diff viewer (did not correctly copy changed attachment files)&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30812</id>
		<title>Release Notes 25.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_25.x&amp;diff=30812"/>
		<updated>2025-06-23T10:03:40Z</updated>

		<summary type="html">&lt;p&gt;Sv: /* Release 25.1 (Scheduled for May 2025) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 24.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 25.1 (Scheduled for May 2025) ==&lt;br /&gt;
*Improvement: additional &amp;quot;Info&amp;quot; tab in inspector views&lt;br /&gt;
*Improvement: less memory usage in the activity log&lt;br /&gt;
*Improvement: better error messages and more links to settings from the activity log&#039;s error message&lt;br /&gt;
*Improvement: additional units and conversions in the [[PhysicalValues/en|physical values framework]]&lt;br /&gt;
*Improvement: more precision in the [[Numeric_Limits/en#Higher_Precision_Numbers|high precision trigonometric and math functions]]&lt;br /&gt;
*Improvement: WindowsAutomation: Plugn Update to FlaUI 5&lt;br /&gt;
*Improvement: Mobile Testing: Better Device Lock/Unlock Support&lt;br /&gt;
*Improvement: StandardLibrary&lt;br /&gt;
*Improvement: better model language editor (translate and fetch-strings functions)&lt;br /&gt;
&lt;br /&gt;
*Feature: translate and spell check in the workspace window&lt;br /&gt;
*Feature: EditLock of suites loaded from expeccoALM / AIDYMO&lt;br /&gt;
*Feature: Start Test in expeccoALM / AIDYMO (via expecco)&lt;br /&gt;
*Feature: new library containing expeccoALM control actions (those from the AIDYMO menu)&lt;br /&gt;
*Fix: the version diff viewer (did not correctly copy changed attachment files)&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
</feed>