17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 03:59:19 +02:00

Add vehicle graph core: .vhg loader, logic and cab blocks, -graph-run and -graph-catalog

This commit is contained in:
2026-10-13 10:55:53 +02:00
parent c26041f2e7
commit 70abf879b3
42 changed files with 4693 additions and 1 deletions

View File

@@ -57,7 +57,9 @@ file(GLOB HEADERS "*.h"
"model/*.h"
"utilities/*.h"
"world/*.h"
"vehicle/*.h")
"vehicle/*.h"
"vehicle/graph/*.h"
"vehicle/graph/blocks/*.h")
set(GLOBAL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(GLOBAL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/global_include")
@@ -109,6 +111,15 @@ set(SOURCES
"vehicle/Driver.cpp"
"application/driverhints.cpp"
"vehicle/DynObj.cpp"
"vehicle/graph/graph_types.cpp"
"vehicle/graph/graph_block.cpp"
"vehicle/graph/graph_catalog.cpp"
"vehicle/graph/graph_format.cpp"
"vehicle/graph/graph_template.cpp"
"vehicle/graph/graph_instance.cpp"
"vehicle/graph/graph_standalone.cpp"
"vehicle/graph/blocks/logic.cpp"
"vehicle/graph/blocks/cab.cpp"
"EU07.cpp"
"export_e3d_standalone.cpp"
"export_btf_standalone.cpp"

View File

@@ -20,6 +20,7 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others
#include "application/application.h"
#include "utilities/Logs.h"
#include "vehicle/graph/graph_standalone.h"
#include <cstdlib>
#ifdef WITHDUMPGEN
#ifdef _WIN32
@@ -130,6 +131,22 @@ int main(int argc, char *argv[])
fflush(stderr);
std::_Exit(result);
}
// standalone check and run of a vehicle graph: -graph-run <file.vhg> [-script <events>] [-o <results.csv>] [-dt <step>] [-t <duration>] [-every <steps>]
else if (argc >= 2 && std::string(argv[1]) == "-graph-run")
{
auto const result{vgraph::graph_run_standalone(argc, argv)};
fflush(stdout);
fflush(stderr);
std::_Exit(result);
}
// export of the vehicle graph block catalog for the external editor: -graph-catalog [-o <file.json>]
else if (argc >= 2 && std::string(argv[1]) == "-graph-catalog")
{
auto const result{vgraph::graph_catalog_standalone(argc >= 4 && std::string(argv[2]) == "-o" ? argv[3] : "")};
fflush(stdout);
fflush(stderr);
std::_Exit(result);
}
else
{
try

View File

@@ -0,0 +1,107 @@
# Vehicle graph (.vhg)
A vehicle graph describes a vehicle as connected blocks, in place of the `.fiz` file. The graph holds the cab
controls and indicators, the logic, the sounds and, in the following stages, the electrical, mechanical and
pneumatic systems of the vehicle. The simulator code is in `vehicle/graph/`.
Current stage: the core of the graph with logic and cab blocks, available through the command line tools below.
Vehicles aren't loaded from `.vhg` files yet.
## File format, version 2
A `.vhg` file is JSON. Comments (`//`, `/* */`) are allowed.
```json
{
"format": "maszyna-vehicle-graph",
"version": 2,
"vehicle": { "name": "ET22" },
"settings": { "low_voltage_simulation": false },
"body": { },
"profiles": { "brake_pipe": 1 },
"nodes": [
{ "id": "bat", "type": "cab.switch", "title": "Battery", "params": { "behaviour": "bistable", "submodel": "battery_sw:" } },
{ "id": "lamp", "type": "fb.lamp", "params": { "color": "red" } }
],
"connections": [
{ "from": "bat.pos", "to": "lamp.on" }
],
"layout": { }
}
```
- `nodes[].id`: letters, digits, `_` and `-`; unique in the file.
- `nodes[].type`: block type from the catalog (see `-graph-catalog`).
- `nodes[].params`: typed values. Numbers are JSON numbers, switches are `true`/`false`, choices are ASCII ids
from the catalog (e.g. `"bistable"`, `"rotate"`, `"ne"`). Parameters left out take their default values.
- `connections`: `"node.port"` of an output to `"node.port"` of an input. An output can feed many inputs; an input
has at most one source. Unconnected inputs see their default value.
- `settings.low_voltage_simulation`: when enabled, blocks with low voltage ports simulate the voltages and currents
of the control circuits (e.g. a lamp needs enough voltage and draws current). When disabled, low voltage
connections have no effect and the apparatus behaves as if always powered.
- `body`, `profiles`: parameters of the vehicle body and standard interfaces between vehicles; used by the next stages.
- `layout`: positions of the blocks in the editor; ignored by the simulator.
### Ports and domains
Signal ports carry one value (bool, int or float; booleans are 0 and 1). Physical ports carry a pair of values
in opposite directions:
| domain | forward | back |
|---|---|---|
| `high_voltage`, `low_voltage` | voltage [V] | current [A] |
| `aux_ac` | voltage [V] | power [W] |
| `drive` | demand [0-1] | power [W] |
| `mechanical` | torque [Nm] | rotational speed [rad/s] |
| `traction` | force at the wheel rim [N] | velocity [m/s] |
| `air`, `brake_pipe`, `feed_pipe` | pressure [bar] | flow |
### Order of evaluation
Blocks are evaluated once per step in the order given by the connections. A loop of connections has to pass through
a deferred block (`logic.sr`, `logic.ton`, `logic.tof`, `logic.delay`), whose outputs change in the next step; other
loops are rejected when the file is loaded. Back values of physical connections are always taken from the previous
step. The graph has no other source of time or randomness, so the same inputs give the same results.
## Command line tools
```
eu07 -graph-catalog [-o <catalog.json>]
eu07 -graph-run <file.vhg> [-script <events>] [-o <results.csv>] [-dt <step, s>] [-t <duration, s>] [-every <steps>]
```
`-graph-catalog` writes the description of all block types, ports and parameters, for the external editor.
`-graph-run` loads and checks the graph, reports problems, and runs it without the simulator. The results are
the values of all signal outputs and the states of the blocks (e.g. `lamp:lit`), separated with `;`.
The script lists events, one per line:
```
# <time, s> <operation> <target> [value]
0.0 toggle bat
6.0 press ws_on
6.3 release ws_on
11.0 inc reverser
21.0 set lever 10
1.1 force x.q 3
1.7 unforce x.q
```
Operations on cab switches: `press`, `release`, `toggle`, `inc`, `dec`, `set <position>`, `value <value>`.
Operations on signal ports: `force <node.port> <value>`, `unforce <node.port>`.
On Windows the simulator runs without a console, so use `-o` for the results, and redirect the output to a file
to see the messages, e.g. `eu07.exe -graph-run test.vhg > log.txt`.
## Tests
```
python3 tools/vehicle_graph/run_tests.py <path to the simulator executable> [--update]
```
- `tests/*.vhg` start with `// expect: ok`, `// expect: error <text>` or `// expect: warning <text>`;
- every `.vhg` with a `.script` is run twice; both runs have to give identical results, equal to `.expected.csv`.
`--update` replaces the expected results with the current ones, after checking the change.
`examples/` holds the cab logic of two vehicles, modelled after the 303E (ET22, resistor starting) and Vectron
(induction motors) `.fiz` files.

View File

@@ -0,0 +1,181 @@
time;bat.pos;bat.index;pant_f.pos;pant_f.index;pant_r.pos;pant_r.index;ws_on.pos;ws_on.index;ws_off.pos;ws_off.index;conv_sw.pos;conv_sw.index;comp_sw.pos;comp_sw.index;reverser.pos;reverser.index;mainctrl.pos;mainctrl.index;pant_any.q;pant_air.q;pant_up.q;hv_nominal.q;hv.q;hv_ok.q;ws_close.q;ws_close2.q;ws_lost.q;ws_open.q;ws.q;ws_lamp_on.q;conv_run.q;conv.q;conv_lamp_on.q;comp.q;dir_set.q;power_req.q;line_req.q;line.q;line_lamp_on.q;bat:position;pant_f:position;pant_r:position;ws_on:position;ws_off:position;conv_sw:position;comp_sw:position;reverser:position;mainctrl:position;pant_up:elapsed;ws:state;conv:elapsed;lamp_ws:lit;lamp_conv:lit;lamp_line:lit;v_hv:value;snd_conv:playing;snd_conv:volume;snd_conv:pitch;snd_comp:playing;snd_comp:volume;snd_comp:pitch
0.1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;0;0;0;0;0;0;1;0;0;0;0;1;1;1;0;0;1;1;0;1;1
0.2;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;0;0;0;0;0;0;1;0;0;0;0;1;1;1;0;0;1;1;0;1;1
0.3;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;0;0;0;0;0;0;1;0;0;0;0;1;1;1;0;0;1;1;0;1;1
0.4;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;0;0;0;0;0;0;1;0;0;0;0;1;1;1;0;0;1;1;0;1;1
0.5;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;0;0;0;0;0;0;1;0;0;0;0;1;1;1;0;0;1;1;0;1;1
0.6;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;0.1;0;0;1;1;1;0;0;1;1;0;1;1
0.7;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;0.2;0;0;1;1;1;0;0;1;1;0;1;1
0.8;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;0.3;0;0;1;1;1;0;0;1;1;0;1;1
0.9;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;0.4;0;0;1;1;1;0;0;1;1;0;1;1
1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;0.5;0;0;1;1;1;0;0;1;1;0;1;1
1.1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;0.6;0;0;1;1;1;0;0;1;1;0;1;1
1.2;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;0.7;0;0;1;1;1;0;0;1;1;0;1;1
1.3;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;0.8;0;0;1;1;1;0;0;1;1;0;1;1
1.4;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;0.9;0;0;1;1;1;0;0;1;1;0;1;1
1.5;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1;0;0;1;1;1;0;0;1;1;0;1;1
1.6;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1.1;0;0;1;1;1;0;0;1;1;0;1;1
1.7;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1.2;0;0;1;1;1;0;0;1;1;0;1;1
1.8;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1.3;0;0;1;1;1;0;0;1;1;0;1;1
1.9;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1.4;0;0;1;1;1;0;0;1;1;0;1;1
2;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1.5;0;0;1;1;1;0;0;1;1;0;1;1
2.1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1.6;0;0;1;1;1;0;0;1;1;0;1;1
2.2;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1.7;0;0;1;1;1;0;0;1;1;0;1;1
2.3;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1.8;0;0;1;1;1;0;0;1;1;0;1;1
2.4;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;1.9;0;0;1;1;1;0;0;1;1;0;1;1
2.5;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2;0;0;1;1;1;0;0;1;1;0;1;1
2.6;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2.1;0;0;1;1;1;0;0;1;1;0;1;1
2.7;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2.2;0;0;1;1;1;0;0;1;1;0;1;1
2.8;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2.3;0;0;1;1;1;0;0;1;1;0;1;1
2.9;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2.4;0;0;1;1;1;0;0;1;1;0;1;1
3;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2.5;0;0;1;1;1;0;0;1;1;0;1;1
3.1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2.6;0;0;1;1;1;0;0;1;1;0;1;1
3.2;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2.7;0;0;1;1;1;0;0;1;1;0;1;1
3.3;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2.8;0;0;1;1;1;0;0;1;1;0;1;1
3.4;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;2.9;0;0;1;1;1;0;0;1;1;0;1;1
3.5;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3;0;0;1;1;1;0;0;1;1;0;1;1
3.6;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3.1;0;0;1;1;1;0;0;1;1;0;1;1
3.7;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3.2;0;0;1;1;1;0;0;1;1;0;1;1
3.8;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3.3;0;0;1;1;1;0;0;1;1;0;1;1
3.9;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3.4;0;0;1;1;1;0;0;1;1;0;1;1
4;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3.5;0;0;1;1;1;0;0;1;1;0;1;1
4.1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3.6;0;0;1;1;1;0;0;1;1;0;1;1
4.2;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3.7;0;0;1;1;1;0;0;1;1;0;1;1
4.3;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3.8;0;0;1;1;1;0;0;1;1;0;1;1
4.4;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;3.9;0;0;1;1;1;0;0;1;1;0;1;1
4.5;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;0;0;1;1;0;1;1
4.6;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
4.7;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
4.8;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
4.9;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5.1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5.2;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5.3;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5.4;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5.5;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5.6;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5.7;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5.8;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
5.9;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
6;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;0;0;1;1;1;3000;0;1;1;0;1;1
6.1;1;1;1;1;0;0;1;1;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;1;1;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;1;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
6.2;1;1;1;1;0;0;1;1;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;1;1;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;1;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
6.3;1;1;1;1;0;0;1;1;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;1;1;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;1;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
6.4;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
6.5;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
6.6;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
6.7;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
6.8;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
6.9;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
7;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;0;0;1;0;0;0;0;0;1;1;1;0;0;0;0;0;1;0;4;1;0;0;1;1;3000;0;1;1;0;1;1
7.1;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;0.1;0;1;1;3000;0;1;1;0;1;1
7.2;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;0.2;0;1;1;3000;0;1;1;0;1;1
7.3;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;0.3;0;1;1;3000;0;1;1;0;1;1
7.4;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;0.4;0;1;1;3000;0;1;1;0;1;1
7.5;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;0.5;0;1;1;3000;0;1;1;0;1;1
7.6;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;0.6;0;1;1;3000;0;1;1;0;1;1
7.7;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;0.7;0;1;1;3000;0;1;1;0;1;1
7.8;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;0.8;0;1;1;3000;0;1;1;0;1;1
7.9;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;0.9;0;1;1;3000;0;1;1;0;1;1
8;1;1;1;1;0;0;0;0;0;0;1;1;0;0;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;0;1;0;4;1;1;0;1;1;3000;0;1;1;0;1;1
8.1;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;1.1;0;1;1;3000;0;1;1;0;1;1
8.2;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;1.2;0;1;1;3000;0;1;1;0;1;1
8.3;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;1.3;0;1;1;3000;0;1;1;0;1;1
8.4;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;1.4;0;1;1;3000;0;1;1;0;1;1
8.5;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;1.5;0;1;1;3000;0;1;1;0;1;1
8.6;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;1.6;0;1;1;3000;0;1;1;0;1;1
8.7;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;1.7;0;1;1;3000;0;1;1;0;1;1
8.8;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;1.8;0;1;1;3000;0;1;1;0;1;1
8.9;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;1.9;0;1;1;3000;0;1;1;0;1;1
9;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2;0;1;1;3000;0;1;1;0;1;1
9.1;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2.1;0;1;1;3000;0;1;1;0;1;1
9.2;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2.2;0;1;1;3000;0;1;1;0;1;1
9.3;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2.3;0;1;1;3000;0;1;1;0;1;1
9.4;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2.4;0;1;1;3000;0;1;1;0;1;1
9.5;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2.5;0;1;1;3000;0;1;1;0;1;1
9.6;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2.6;0;1;1;3000;0;1;1;0;1;1
9.7;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2.7;0;1;1;3000;0;1;1;0;1;1
9.8;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2.8;0;1;1;3000;0;1;1;0;1;1
9.9;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;2.9;0;1;1;3000;0;1;1;0;1;1
10;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;0;1;0;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;1;1;3000;0;1;1;0;1;1
10.1;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
10.2;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
10.3;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
10.4;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
10.5;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
10.6;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
10.7;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
10.8;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
10.9;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
11;1;1;1;1;0;0;0;0;0;0;1;1;1;1;0;1;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;0;0;0;0;1;1;1;0;0;0;1;1;1;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
11.1;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;0;0;0;1;1;1;0;0;0;1;1;2;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
11.2;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;0;0;0;1;1;1;0;0;0;1;1;2;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
11.3;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;0;0;0;1;1;1;0;0;0;1;1;2;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
11.4;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;0;0;0;1;1;1;0;0;0;1;1;2;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
11.5;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;0;0;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;0;0;0;1;1;1;0;0;0;1;1;2;0;4;1;3;0;0;1;3000;1;1;1;1;1;1
11.6;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;1;1;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;1;4;1;3;0;0;0;3000;1;1;1;1;1;1
11.7;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
11.8;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
11.9;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12.1;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12.2;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12.3;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12.4;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12.5;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12.6;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12.7;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12.8;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
12.9;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13.1;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13.2;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13.3;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13.4;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13.5;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13.6;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13.7;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13.8;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
13.9;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
14;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;0;1;1;0;0;0;1;1;2;2;4;1;3;0;0;0;3000;1;1;1;1;1;1
14.1;1;1;1;1;0;0;0;0;1;1;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;1;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;1;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
14.2;1;1;1;1;0;0;0;0;1;1;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;1;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;1;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
14.3;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;0;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
14.4;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;0;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
14.5;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;0;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
14.6;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;0;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
14.7;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;0;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
14.8;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;0;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
14.9;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;0;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
15;1;1;1;1;0;0;0;0;0;0;1;1;1;1;1;2;2;2;1;1;1;3000;3000;1;0;0;0;0;0;1;0;0;1;0;1;1;1;0;1;1;1;0;0;0;1;1;2;2;4;0;0;1;1;1;3000;0;1;1;0;1;1
15.1;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
15.2;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
15.3;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
15.4;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
15.5;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
15.6;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
15.7;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
15.8;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
15.9;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16.1;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16.2;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16.3;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16.4;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16.5;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16.6;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16.7;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16.8;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
16.9;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17;1;1;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;1;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17.1;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17.2;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17.3;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17.4;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17.5;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17.6;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17.7;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17.8;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
17.9;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
18;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;2;2;2;0;0;0;3000;0;0;0;0;1;1;0;1;0;0;1;0;1;1;1;0;1;0;0;0;0;0;1;1;2;2;0;0;0;1;1;1;0;0;1;1;0;1;1
1 time bat.pos bat.index pant_f.pos pant_f.index pant_r.pos pant_r.index ws_on.pos ws_on.index ws_off.pos ws_off.index conv_sw.pos conv_sw.index comp_sw.pos comp_sw.index reverser.pos reverser.index mainctrl.pos mainctrl.index pant_any.q pant_air.q pant_up.q hv_nominal.q hv.q hv_ok.q ws_close.q ws_close2.q ws_lost.q ws_open.q ws.q ws_lamp_on.q conv_run.q conv.q conv_lamp_on.q comp.q dir_set.q power_req.q line_req.q line.q line_lamp_on.q bat:position pant_f:position pant_r:position ws_on:position ws_off:position conv_sw:position comp_sw:position reverser:position mainctrl:position pant_up:elapsed ws:state conv:elapsed lamp_ws:lit lamp_conv:lit lamp_line:lit v_hv:value snd_conv:playing snd_conv:volume snd_conv:pitch snd_comp:playing snd_comp:volume snd_comp:pitch
2 0.1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 0 1 1
3 0.2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 0 1 1
4 0.3 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 0 1 1
5 0.4 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 0 1 1
6 0.5 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 0 1 1
7 0.6 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0.1 0 0 1 1 1 0 0 1 1 0 1 1
8 0.7 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0.2 0 0 1 1 1 0 0 1 1 0 1 1
9 0.8 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0.3 0 0 1 1 1 0 0 1 1 0 1 1
10 0.9 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0.4 0 0 1 1 1 0 0 1 1 0 1 1
11 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0.5 0 0 1 1 1 0 0 1 1 0 1 1
12 1.1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0.6 0 0 1 1 1 0 0 1 1 0 1 1
13 1.2 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0.7 0 0 1 1 1 0 0 1 1 0 1 1
14 1.3 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0.8 0 0 1 1 1 0 0 1 1 0 1 1
15 1.4 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0.9 0 0 1 1 1 0 0 1 1 0 1 1
16 1.5 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 1 0 1 1
17 1.6 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1.1 0 0 1 1 1 0 0 1 1 0 1 1
18 1.7 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1.2 0 0 1 1 1 0 0 1 1 0 1 1
19 1.8 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1.3 0 0 1 1 1 0 0 1 1 0 1 1
20 1.9 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1.4 0 0 1 1 1 0 0 1 1 0 1 1
21 2 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1.5 0 0 1 1 1 0 0 1 1 0 1 1
22 2.1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1.6 0 0 1 1 1 0 0 1 1 0 1 1
23 2.2 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1.7 0 0 1 1 1 0 0 1 1 0 1 1
24 2.3 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1.8 0 0 1 1 1 0 0 1 1 0 1 1
25 2.4 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1.9 0 0 1 1 1 0 0 1 1 0 1 1
26 2.5 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2 0 0 1 1 1 0 0 1 1 0 1 1
27 2.6 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2.1 0 0 1 1 1 0 0 1 1 0 1 1
28 2.7 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2.2 0 0 1 1 1 0 0 1 1 0 1 1
29 2.8 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2.3 0 0 1 1 1 0 0 1 1 0 1 1
30 2.9 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2.4 0 0 1 1 1 0 0 1 1 0 1 1
31 3 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2.5 0 0 1 1 1 0 0 1 1 0 1 1
32 3.1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2.6 0 0 1 1 1 0 0 1 1 0 1 1
33 3.2 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2.7 0 0 1 1 1 0 0 1 1 0 1 1
34 3.3 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2.8 0 0 1 1 1 0 0 1 1 0 1 1
35 3.4 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 2.9 0 0 1 1 1 0 0 1 1 0 1 1
36 3.5 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3 0 0 1 1 1 0 0 1 1 0 1 1
37 3.6 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3.1 0 0 1 1 1 0 0 1 1 0 1 1
38 3.7 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3.2 0 0 1 1 1 0 0 1 1 0 1 1
39 3.8 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3.3 0 0 1 1 1 0 0 1 1 0 1 1
40 3.9 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3.4 0 0 1 1 1 0 0 1 1 0 1 1
41 4 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3.5 0 0 1 1 1 0 0 1 1 0 1 1
42 4.1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3.6 0 0 1 1 1 0 0 1 1 0 1 1
43 4.2 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3.7 0 0 1 1 1 0 0 1 1 0 1 1
44 4.3 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3.8 0 0 1 1 1 0 0 1 1 0 1 1
45 4.4 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 3.9 0 0 1 1 1 0 0 1 1 0 1 1
46 4.5 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 0 0 1 1 0 1 1
47 4.6 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
48 4.7 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
49 4.8 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
50 4.9 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
51 5 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
52 5.1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
53 5.2 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
54 5.3 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
55 5.4 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
56 5.5 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
57 5.6 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
58 5.7 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
59 5.8 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
60 5.9 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
61 6 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 0 0 1 1 1 3000 0 1 1 0 1 1
62 6.1 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 1 1 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 1 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
63 6.2 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 1 1 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 1 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
64 6.3 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 1 1 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 1 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
65 6.4 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
66 6.5 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
67 6.6 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
68 6.7 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
69 6.8 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
70 6.9 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
71 7 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 4 1 0 0 1 1 3000 0 1 1 0 1 1
72 7.1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 0.1 0 1 1 3000 0 1 1 0 1 1
73 7.2 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 0.2 0 1 1 3000 0 1 1 0 1 1
74 7.3 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 0.3 0 1 1 3000 0 1 1 0 1 1
75 7.4 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 0.4 0 1 1 3000 0 1 1 0 1 1
76 7.5 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 0.5 0 1 1 3000 0 1 1 0 1 1
77 7.6 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 0.6 0 1 1 3000 0 1 1 0 1 1
78 7.7 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 0.7 0 1 1 3000 0 1 1 0 1 1
79 7.8 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 0.8 0 1 1 3000 0 1 1 0 1 1
80 7.9 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 0.9 0 1 1 3000 0 1 1 0 1 1
81 8 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 4 1 1 0 1 1 3000 0 1 1 0 1 1
82 8.1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 1.1 0 1 1 3000 0 1 1 0 1 1
83 8.2 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 1.2 0 1 1 3000 0 1 1 0 1 1
84 8.3 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 1.3 0 1 1 3000 0 1 1 0 1 1
85 8.4 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 1.4 0 1 1 3000 0 1 1 0 1 1
86 8.5 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 1.5 0 1 1 3000 0 1 1 0 1 1
87 8.6 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 1.6 0 1 1 3000 0 1 1 0 1 1
88 8.7 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 1.7 0 1 1 3000 0 1 1 0 1 1
89 8.8 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 1.8 0 1 1 3000 0 1 1 0 1 1
90 8.9 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 1.9 0 1 1 3000 0 1 1 0 1 1
91 9 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2 0 1 1 3000 0 1 1 0 1 1
92 9.1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2.1 0 1 1 3000 0 1 1 0 1 1
93 9.2 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2.2 0 1 1 3000 0 1 1 0 1 1
94 9.3 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2.3 0 1 1 3000 0 1 1 0 1 1
95 9.4 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2.4 0 1 1 3000 0 1 1 0 1 1
96 9.5 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2.5 0 1 1 3000 0 1 1 0 1 1
97 9.6 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2.6 0 1 1 3000 0 1 1 0 1 1
98 9.7 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2.7 0 1 1 3000 0 1 1 0 1 1
99 9.8 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2.8 0 1 1 3000 0 1 1 0 1 1
100 9.9 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 2.9 0 1 1 3000 0 1 1 0 1 1
101 10 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 1 1 3000 0 1 1 0 1 1
102 10.1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
103 10.2 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
104 10.3 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
105 10.4 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
106 10.5 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
107 10.6 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
108 10.7 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
109 10.8 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
110 10.9 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
111 11 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
112 11.1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 1 1 1 0 0 0 1 1 2 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
113 11.2 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 1 1 1 0 0 0 1 1 2 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
114 11.3 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 1 1 1 0 0 0 1 1 2 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
115 11.4 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 1 1 1 0 0 0 1 1 2 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
116 11.5 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 0 0 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 1 1 1 0 0 0 1 1 2 0 4 1 3 0 0 1 3000 1 1 1 1 1 1
117 11.6 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 1 1 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 1 4 1 3 0 0 0 3000 1 1 1 1 1 1
118 11.7 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
119 11.8 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
120 11.9 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
121 12 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
122 12.1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
123 12.2 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
124 12.3 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
125 12.4 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
126 12.5 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
127 12.6 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
128 12.7 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
129 12.8 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
130 12.9 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
131 13 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
132 13.1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
133 13.2 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
134 13.3 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
135 13.4 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
136 13.5 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
137 13.6 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
138 13.7 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
139 13.8 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
140 13.9 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
141 14 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 1 2 2 4 1 3 0 0 0 3000 1 1 1 1 1 1
142 14.1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
143 14.2 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
144 14.3 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
145 14.4 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
146 14.5 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
147 14.6 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
148 14.7 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
149 14.8 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
150 14.9 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
151 15 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 1 1 3000 3000 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 2 2 4 0 0 1 1 1 3000 0 1 1 0 1 1
152 15.1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
153 15.2 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
154 15.3 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
155 15.4 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
156 15.5 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
157 15.6 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
158 15.7 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
159 15.8 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
160 15.9 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
161 16 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
162 16.1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
163 16.2 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
164 16.3 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
165 16.4 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
166 16.5 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
167 16.6 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
168 16.7 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
169 16.8 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
170 16.9 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
171 17 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
172 17.1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
173 17.2 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
174 17.3 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
175 17.4 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
176 17.5 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
177 17.6 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
178 17.7 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
179 17.8 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
180 17.9 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1
181 18 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 0 0 0 3000 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 2 2 0 0 0 1 1 1 0 0 1 1 0 1 1

View File

@@ -0,0 +1,17 @@
# events for: -graph-run 303e-logic.vhg -script 303e-logic.script
# <time, s> <operation> <target> [value]
# operations on cab switches: press, release, toggle, inc, dec, set <position>, value <value>
# operations on signals: force <node.port> <value>, unforce <node.port>
0.0 toggle bat
0.5 toggle pant_f
6.0 press ws_on
6.3 release ws_on
7.0 toggle conv_sw
8.0 toggle comp_sw
11.0 inc reverser
11.5 inc mainctrl
11.6 inc mainctrl
14.0 press ws_off
14.2 release ws_off
15.0 toggle pant_f
17.0 toggle bat

View File

@@ -0,0 +1,95 @@
// cab logic of an electric locomotive with resistor starting, modelled after the 303E (ET22) .fiz.
// stage 1 of the vehicle graph: only logic and cab blocks are available, so the pantographs and the high voltage
// are represented by timers and constants. the physical blocks replace them in the next stages
{
"format": "maszyna-vehicle-graph",
"version": 2,
"vehicle": { "name": "303E (logic test)" },
"settings": { "low_voltage_simulation": false },
"nodes": [
{ "id": "bat", "type": "cab.switch", "title": "Battery", "params": { "behaviour": "bistable", "submodel": "battery_sw:", "command": "batterytoggle" } },
{ "id": "pant_f", "type": "cab.switch", "title": "Front pantograph", "params": { "behaviour": "bistable", "submodel": "pantfront_sw:", "command": "pantographtogglefront" } },
{ "id": "pant_r", "type": "cab.switch", "title": "Rear pantograph", "params": { "behaviour": "bistable", "submodel": "pantrear_sw:", "command": "pantographtogglerear" } },
{ "id": "ws_on", "type": "cab.switch", "title": "Line breaker on", "params": { "behaviour": "monostable", "animation": "move", "step": 4, "submodel": "main_on_bt:", "command": "linebreakerclose" } },
{ "id": "ws_off", "type": "cab.switch", "title": "Line breaker off", "params": { "behaviour": "monostable", "animation": "move", "step": 4, "submodel": "main_off_bt:", "command": "linebreakeropen" } },
{ "id": "conv_sw", "type": "cab.switch", "title": "Converter", "params": { "behaviour": "bistable", "submodel": "converter_sw:", "command": "convertertoggle" } },
{ "id": "comp_sw", "type": "cab.switch", "title": "Compressor", "params": { "behaviour": "bistable", "submodel": "compressor_sw:", "command": "compressortoggle" } },
{ "id": "reverser", "type": "cab.switch", "title": "Reverser", "params": { "behaviour": "multi", "positions": 3, "min": -1, "max": 1, "default": 0, "labels": "back;0;forward", "step": 45, "offset": -45, "submodel": "dirkey:" } },
{ "id": "mainctrl", "type": "cab.switch", "title": "Master controller", "params": { "behaviour": "multi", "positions": 44, "min": 0, "max": 43, "default": 0, "step": 6, "submodel": "mainctrl:" } },
{ "id": "pant_any", "type": "logic.or", "title": "Any pantograph selected" },
{ "id": "pant_air", "type": "logic.and", "title": "Pantograph valve powered" },
{ "id": "pant_up", "type": "logic.ton", "title": "Pantograph raising", "params": { "time": 4.0 } },
{ "id": "hv_nominal", "type": "logic.const", "title": "Catenary voltage", "params": { "value": 3000 } },
{ "id": "hv", "type": "logic.math", "title": "Voltage behind the pantographs", "params": { "op": "mul" } },
{ "id": "hv_ok", "type": "logic.hyst", "title": "Voltage above minimum", "params": { "lo": 1800, "hi": 1900 } },
{ "id": "ws_close", "type": "logic.and", "title": "Closing allowed" },
{ "id": "ws_close2", "type": "logic.and", "title": "Closing with voltage" },
{ "id": "ws_lost", "type": "logic.nand", "title": "Battery or voltage missing" },
{ "id": "ws_open", "type": "logic.or", "title": "Opening" },
{ "id": "ws", "type": "logic.sr", "title": "Line breaker", "params": { "reset_priority": true } },
{ "id": "ws_lamp_on", "type": "logic.not", "title": "Line breaker open" },
{ "id": "conv_run", "type": "logic.and", "title": "Converter powered" },
{ "id": "conv", "type": "logic.ton", "title": "Converter starting", "params": { "time": 3.0 } },
{ "id": "conv_lamp_on", "type": "logic.not", "title": "Converter off" },
{ "id": "comp", "type": "logic.and", "title": "Compressor running" },
{ "id": "dir_set", "type": "logic.compare", "title": "Direction selected", "params": { "op": "ne", "value": 0 } },
{ "id": "power_req", "type": "logic.compare", "title": "Controller above zero", "params": { "op": "gt", "value": 0 } },
{ "id": "line_req", "type": "logic.and", "title": "Line contactors requested" },
{ "id": "line", "type": "logic.and", "title": "Line contactors closed" },
{ "id": "line_lamp_on", "type": "logic.not", "title": "Line contactors open" },
{ "id": "lamp_ws", "type": "fb.lamp", "title": "Line breaker lamp", "params": { "color": "red", "submodel": "i-mainbreaker:" } },
{ "id": "lamp_conv", "type": "fb.lamp", "title": "Converter lamp", "params": { "color": "yellow", "submodel": "i-converteroverload:" } },
{ "id": "lamp_line", "type": "fb.lamp", "title": "Line contactors lamp", "params": { "color": "green", "submodel": "i-stlinoff:" } },
{ "id": "v_hv", "type": "fb.gauge", "title": "High voltage", "params": { "min": 0, "max": 4000, "unit": "V", "angle_min": 0, "angle_max": 270, "submodel": "hvoltage:" } },
{ "id": "snd_conv", "type": "fb.sound", "title": "Converter", "params": { "file": "przetwornica.wav", "placement": "engine", "loop": true } },
{ "id": "snd_comp", "type": "fb.sound", "title": "Compressor", "params": { "file": "sprezarka.wav", "placement": "engine", "loop": true } }
],
"connections": [
{ "from": "pant_f.pos", "to": "pant_any.a" },
{ "from": "pant_r.pos", "to": "pant_any.b" },
{ "from": "pant_any.q", "to": "pant_air.a" },
{ "from": "bat.pos", "to": "pant_air.b" },
{ "from": "pant_air.q", "to": "pant_up.a" },
{ "from": "hv_nominal.q", "to": "hv.a" },
{ "from": "pant_up.q", "to": "hv.b" },
{ "from": "hv.q", "to": "hv_ok.a" },
{ "from": "hv.q", "to": "v_hv.value" },
{ "from": "ws_on.pos", "to": "ws_close.a" },
{ "from": "bat.pos", "to": "ws_close.b" },
{ "from": "ws_close.q", "to": "ws_close2.a" },
{ "from": "hv_ok.q", "to": "ws_close2.b" },
{ "from": "bat.pos", "to": "ws_lost.a" },
{ "from": "hv_ok.q", "to": "ws_lost.b" },
{ "from": "ws_off.pos", "to": "ws_open.a" },
{ "from": "ws_lost.q", "to": "ws_open.b" },
{ "from": "ws_close2.q", "to": "ws.s" },
{ "from": "ws_open.q", "to": "ws.r" },
{ "from": "ws.q", "to": "ws_lamp_on.a" },
{ "from": "ws_lamp_on.q", "to": "lamp_ws.on" },
{ "from": "ws.q", "to": "conv_run.a" },
{ "from": "conv_sw.pos", "to": "conv_run.b" },
{ "from": "conv_run.q", "to": "conv.a" },
{ "from": "conv.q", "to": "conv_lamp_on.a" },
{ "from": "conv_lamp_on.q", "to": "lamp_conv.on" },
{ "from": "conv.q", "to": "comp.a" },
{ "from": "comp_sw.pos", "to": "comp.b" },
{ "from": "conv.q", "to": "snd_conv.play" },
{ "from": "comp.q", "to": "snd_comp.play" },
{ "from": "reverser.pos", "to": "dir_set.a" },
{ "from": "mainctrl.pos", "to": "power_req.a" },
{ "from": "dir_set.q", "to": "line_req.a" },
{ "from": "power_req.q", "to": "line_req.b" },
{ "from": "line_req.q", "to": "line.a" },
{ "from": "ws.q", "to": "line.b" },
{ "from": "line.q", "to": "line_lamp_on.a" },
{ "from": "line_lamp_on.q", "to": "lamp_line.on" }
]
}

View File

@@ -0,0 +1,253 @@
time;bat.pos;bat.index;pant_sel.pos;pant_sel.index;pant_raise.pos;pant_raise.index;pant_lower.pos;pant_lower.index;main_sw.pos;main_sw.index;reverser.pos;reverser.index;lever.pos;lever.index;pant_cmd.q;pant_cmd_on.q;pant_cmd_off.q;no_lower.q;pant_up.q;hv_nominal.q;hv.q;hv_ok.q;ms_on_req.q;ms_off_req.q;ms_init.q;ms_close.q;ms_lost.q;ms_open.q;ms.q;ms_lamp_on.q;zero.q;minus_one.q;lever_pos.q;lever_neg.q;lever_brake.q;dir_set.q;drive_ok.q;traction.q;ed_brake.q;pant_moving.q;pant_not_up.q;snd_base.q;snd_gain.q;bat:position;pant_sel:position;pant_raise:position;pant_lower:position;main_sw:position;reverser:position;lever:position;pant_cmd:state;pant_up:elapsed;ms_init:elapsed;ms:state;lamp_ms:lit;lamp_pant:lit;v_hv:value;v_demand:value;snd_inverter:playing;snd_inverter:volume;snd_inverter:pitch
0.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
0.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
0.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
0.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
0.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
0.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
0.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
0.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
0.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;0;1;0.3;0.3;1;1;0;0;1;1;15;0;0;0;0;1;0;0;0;0;0.300000012;1
1.1;1;1;1;1;1;1;0;0;0;1;0;1;0;15;1;1;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;1;0;1;1;15;1;0.09;0;0;1;1;0;0;0;0.300000012;1
1.2;1;1;1;1;1;1;0;0;0;1;0;1;0;15;1;1;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;1;0;1;1;15;1;0.19;0;0;1;1;0;0;0;0.300000012;1
1.3;1;1;1;1;1;1;0;0;0;1;0;1;0;15;1;1;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;1;0;1;1;15;1;0.29;0;0;1;1;0;0;0;0.300000012;1
1.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;0.39;0;0;1;1;0;0;0;0.300000012;1
1.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;0.49;0;0;1;0;0;0;0;0.300000012;1
1.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;0.59;0;0;1;0;0;0;0;0.300000012;1
1.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;0.69;0;0;1;0;0;0;0;0.300000012;1
1.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;0.79;0;0;1;0;0;0;0;0.300000012;1
1.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;0.89;0;0;1;0;0;0;0;0.300000012;1
2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;0.99;0;0;1;1;0;0;0;0.300000012;1
2.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.09;0;0;1;1;0;0;0;0.300000012;1
2.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.19;0;0;1;1;0;0;0;0.300000012;1
2.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.29;0;0;1;1;0;0;0;0.300000012;1
2.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.39;0;0;1;1;0;0;0;0.300000012;1
2.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.49;0;0;1;1;0;0;0;0.300000012;1
2.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.59;0;0;1;0;0;0;0;0.300000012;1
2.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.69;0;0;1;0;0;0;0;0.300000012;1
2.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.79;0;0;1;0;0;0;0;0.300000012;1
2.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.89;0;0;1;0;0;0;0;0.300000012;1
3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;1.99;0;0;1;0;0;0;0;0.300000012;1
3.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.09;0;0;1;1;0;0;0;0.300000012;1
3.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.19;0;0;1;1;0;0;0;0.300000012;1
3.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.29;0;0;1;1;0;0;0;0.300000012;1
3.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.39;0;0;1;1;0;0;0;0.300000012;1
3.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.49;0;0;1;1;0;0;0;0.300000012;1
3.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.59;0;0;1;0;0;0;0;0.300000012;1
3.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.69;0;0;1;0;0;0;0;0.300000012;1
3.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.79;0;0;1;0;0;0;0;0.300000012;1
3.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.89;0;0;1;0;0;0;0;0.300000012;1
4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;2.99;0;0;1;0;0;0;0;0.300000012;1
4.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.09;0;0;1;1;0;0;0;0.300000012;1
4.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.19;0;0;1;1;0;0;0;0.300000012;1
4.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.29;0;0;1;1;0;0;0;0.300000012;1
4.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.39;0;0;1;1;0;0;0;0.300000012;1
4.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.49;0;0;1;1;0;0;0;0.300000012;1
4.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.59;0;0;1;0;0;0;0;0.300000012;1
4.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.69;0;0;1;0;0;0;0;0.300000012;1
4.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.79;0;0;1;0;0;0;0;0.300000012;1
4.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.89;0;0;1;0;0;0;0;0.300000012;1
5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;3.99;0;0;1;0;0;0;0;0.300000012;1
5.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.09;0;0;1;1;0;0;0;0.300000012;1
5.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.19;0;0;1;1;0;0;0;0.300000012;1
5.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.29;0;0;1;1;0;0;0;0.300000012;1
5.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.39;0;0;1;1;0;0;0;0.300000012;1
5.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.49;0;0;1;1;0;0;0;0.300000012;1
5.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.59;0;0;1;0;0;0;0;0.300000012;1
5.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.69;0;0;1;0;0;0;0;0.300000012;1
5.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.79;0;0;1;0;0;0;0;0.300000012;1
5.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.89;0;0;1;0;0;0;0;0.300000012;1
6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0;0;0;0;0;0;1;1;0.3;0.3;1;1;0;0;1;1;15;1;4.99;0;0;1;0;0;0;0;0.300000012;1
6.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.08;0;1;0;3000;0;0;0.300000012;1
6.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.18;0;1;0;3000;0;0;0.300000012;1
6.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.28;0;1;0;3000;0;0;0.300000012;1
6.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.38;0;1;0;3000;0;0;0.300000012;1
6.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.48;0;1;0;3000;0;0;0.300000012;1
6.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.58;0;1;0;3000;0;0;0.300000012;1
6.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.68;0;1;0;3000;0;0;0.300000012;1
6.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.78;0;1;0;3000;0;0;0.300000012;1
6.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.88;0;1;0;3000;0;0;0.300000012;1
7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;0.98;0;1;0;3000;0;0;0.300000012;1
7.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.08;0;1;0;3000;0;0;0.300000012;1
7.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.18;0;1;0;3000;0;0;0.300000012;1
7.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.28;0;1;0;3000;0;0;0.300000012;1
7.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.38;0;1;0;3000;0;0;0.300000012;1
7.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.48;0;1;0;3000;0;0;0.300000012;1
7.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.58;0;1;0;3000;0;0;0.300000012;1
7.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.68;0;1;0;3000;0;0;0.300000012;1
7.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.78;0;1;0;3000;0;0;0.300000012;1
7.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.88;0;1;0;3000;0;0;0.300000012;1
8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;1.98;0;1;0;3000;0;0;0.300000012;1
8.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.08;0;1;0;3000;0;0;0.300000012;1
8.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.18;0;1;0;3000;0;0;0.300000012;1
8.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.28;0;1;0;3000;0;0;0.300000012;1
8.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.38;0;1;0;3000;0;0;0.300000012;1
8.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.48;0;1;0;3000;0;0;0.300000012;1
8.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.58;0;1;0;3000;0;0;0.300000012;1
8.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.68;0;1;0;3000;0;0;0.300000012;1
8.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.78;0;1;0;3000;0;0;0.300000012;1
8.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.88;0;1;0;3000;0;0;0.300000012;1
9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;2.98;0;1;0;3000;0;0;0.300000012;1
9.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.08;0;1;0;3000;0;0;0.300000012;1
9.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.18;0;1;0;3000;0;0;0.300000012;1
9.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.28;0;1;0;3000;0;0;0.300000012;1
9.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.38;0;1;0;3000;0;0;0.300000012;1
9.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.48;0;1;0;3000;0;0;0.300000012;1
9.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.58;0;1;0;3000;0;0;0.300000012;1
9.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.68;0;1;0;3000;0;0;0.300000012;1
9.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.78;0;1;0;3000;0;0;0.300000012;1
9.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.88;0;1;0;3000;0;0;0.300000012;1
10;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;3.98;0;1;0;3000;0;0;0.300000012;1
10.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.08;0;1;0;3000;0;0;0.300000012;1
10.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.18;0;1;0;3000;0;0;0.300000012;1
10.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.28;0;1;0;3000;0;0;0.300000012;1
10.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.38;0;1;0;3000;0;0;0.300000012;1
10.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.48;0;1;0;3000;0;0;0.300000012;1
10.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.58;0;1;0;3000;0;0;0.300000012;1
10.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.68;0;1;0;3000;0;0;0.300000012;1
10.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.78;0;1;0;3000;0;0;0.300000012;1
10.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.88;0;1;0;3000;0;0;0.300000012;1
11;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;4.98;0;1;0;3000;0;0;0.300000012;1
11.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.08;0;1;0;3000;0;0;0.300000012;1
11.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.18;0;1;0;3000;0;0;0.300000012;1
11.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.28;0;1;0;3000;0;0;0.300000012;1
11.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.38;0;1;0;3000;0;0;0.300000012;1
11.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.48;0;1;0;3000;0;0;0.300000012;1
11.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.58;0;1;0;3000;0;0;0.300000012;1
11.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.68;0;1;0;3000;0;0;0.300000012;1
11.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.78;0;1;0;3000;0;0;0.300000012;1
11.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.88;0;1;0;3000;0;0;0.300000012;1
12;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;5.98;0;1;0;3000;0;0;0.300000012;1
12.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.08;0;1;0;3000;0;0;0.300000012;1
12.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.18;0;1;0;3000;0;0;0.300000012;1
12.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.28;0;1;0;3000;0;0;0.300000012;1
12.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.38;0;1;0;3000;0;0;0.300000012;1
12.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.48;0;1;0;3000;0;0;0.300000012;1
12.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.58;0;1;0;3000;0;0;0.300000012;1
12.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.68;0;1;0;3000;0;0;0.300000012;1
12.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.78;0;1;0;3000;0;0;0.300000012;1
12.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.88;0;1;0;3000;0;0;0.300000012;1
13;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;6.98;0;1;0;3000;0;0;0.300000012;1
13.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.08;0;1;0;3000;0;0;0.300000012;1
13.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.18;0;1;0;3000;0;0;0.300000012;1
13.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.28;0;1;0;3000;0;0;0.300000012;1
13.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.38;0;1;0;3000;0;0;0.300000012;1
13.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.48;0;1;0;3000;0;0;0.300000012;1
13.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.58;0;1;0;3000;0;0;0.300000012;1
13.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.68;0;1;0;3000;0;0;0.300000012;1
13.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.78;0;1;0;3000;0;0;0.300000012;1
13.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.88;0;1;0;3000;0;0;0.300000012;1
14;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;7.98;0;1;0;3000;0;0;0.300000012;1
14.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.08;0;1;0;3000;0;0;0.300000012;1
14.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.18;0;1;0;3000;0;0;0.300000012;1
14.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.28;0;1;0;3000;0;0;0.300000012;1
14.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.38;0;1;0;3000;0;0;0.300000012;1
14.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.48;0;1;0;3000;0;0;0.300000012;1
14.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.58;0;1;0;3000;0;0;0.300000012;1
14.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.68;0;1;0;3000;0;0;0.300000012;1
14.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.78;0;1;0;3000;0;0;0.300000012;1
14.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.88;0;1;0;3000;0;0;0.300000012;1
15;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;8.98;0;1;0;3000;0;0;0.300000012;1
15.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.08;0;1;0;3000;0;0;0.300000012;1
15.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.18;0;1;0;3000;0;0;0.300000012;1
15.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.28;0;1;0;3000;0;0;0.300000012;1
15.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.38;0;1;0;3000;0;0;0.300000012;1
15.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.48;0;1;0;3000;0;0;0.300000012;1
15.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.58;0;1;0;3000;0;0;0.300000012;1
15.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.68;0;1;0;3000;0;0;0.300000012;1
15.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.78;0;1;0;3000;0;0;0.300000012;1
15.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.88;0;1;0;3000;0;0;0.300000012;1
16;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;0;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;9.98;0;1;0;3000;0;0;0.300000012;1
16.1;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
16.2;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
16.3;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
16.4;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
16.5;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
16.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
16.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
16.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
16.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
17;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;0;1;0;3000;0;0;0.300000012;1
17.1;1;1;1;1;0;0;0;0;1;2;0;1;0;15;1;0;0;1;1;3000;3000;1;1;0;1;1;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;2;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
17.2;1;1;1;1;0;0;0;0;1;2;0;1;0;15;1;0;0;1;1;3000;3000;1;1;0;1;1;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;2;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
17.3;1;1;1;1;0;0;0;0;1;2;0;1;0;15;1;0;0;1;1;3000;3000;1;1;0;1;1;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;2;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
17.4;1;1;1;1;0;0;0;0;1;2;0;1;0;15;1;0;0;1;1;3000;3000;1;1;0;1;1;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;2;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
17.5;1;1;1;1;0;0;0;0;1;2;0;1;0;15;1;0;0;1;1;3000;3000;1;1;0;1;1;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;2;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
17.6;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
17.7;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
17.8;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
17.9;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18;1;1;1;1;0;0;0;0;0;1;0;1;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;0;0;0;0;0;0;0.3;0.3;1;1;0;0;1;1;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18.1;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18.2;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18.3;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18.4;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18.5;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18.6;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18.7;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18.8;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
18.9;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
19;1;1;1;1;0;0;0;0;0;1;1;2;0;15;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0;0;1;1;0;0;0;0;0.3;0.3;1;1;0;0;1;2;15;1;5;10;1;0;0;3000;0;1;0.300000012;1
19.1;1;1;1;1;0;0;0;0;0;1;1;2;0.0666666667;16;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.0666666667;-0.0666666667;0;1;1;0.0666666667;0;0;0;0.3;0.366666667;1;1;0;0;1;2;16;1;5;10;1;0;0;3000;0.0666666701;1;0.366666675;1
19.2;1;1;1;1;0;0;0;0;0;1;1;2;0.133333333;17;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.133333333;-0.133333333;0;1;1;0.133333333;0;0;0;0.3;0.433333333;1;1;0;0;1;2;17;1;5;10;1;0;0;3000;0.13333334;1;0.433333337;1
19.3;1;1;1;1;0;0;0;0;0;1;1;2;0.2;18;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.2;-0.2;0;1;1;0.2;0;0;0;0.3;0.5;1;1;0;0;1;2;18;1;5;10;1;0;0;3000;0.200000003;1;0.5;1
19.4;1;1;1;1;0;0;0;0;0;1;1;2;0.266666667;19;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.266666667;-0.266666667;0;1;1;0.266666667;0;0;0;0.3;0.566666667;1;1;0;0;1;2;19;1;5;10;1;0;0;3000;0.266666681;1;0.566666663;1
19.5;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
19.6;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
19.7;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
19.8;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
19.9;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20.1;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20.2;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20.3;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20.4;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20.5;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20.6;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20.7;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20.8;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
20.9;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
21;1;1;1;1;0;0;0;0;0;1;1;2;0.333333333;20;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0.333333333;-0.333333333;0;1;1;0.333333333;0;0;0;0.3;0.633333333;1;1;0;0;1;2;20;1;5;10;1;0;0;3000;0.333333343;1;0.633333325;1
21.1;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
21.2;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
21.3;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
21.4;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
21.5;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
21.6;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
21.7;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
21.8;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
21.9;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22.1;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22.2;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22.3;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22.4;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22.5;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22.6;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22.7;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22.8;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
22.9;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
23;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;1;0;0;-1;0;0.333333333;0.333333333;1;1;0;0.333333333;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;1;0;0;3000;0;1;0.300000012;1
23.1;1;1;1;1;0;0;0;0;-1;0;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;1;1;0;0;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;0;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
23.2;1;1;1;1;0;0;0;0;-1;0;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;1;1;0;0;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;0;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
23.3;1;1;1;1;0;0;0;0;-1;0;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;1;1;0;0;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;0;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
23.4;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
23.5;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
23.6;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
23.7;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
23.8;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
23.9;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
24;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;1;0;0;1;1;3000;3000;1;0;0;1;0;0;0;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;0;0.3;0.3;1;1;0;0;1;2;10;1;5;10;0;1;0;3000;0;0;0.300000012;1
24.1;1;1;1;1;0;0;1;1;0;1;1;2;-0.333333333;10;0;0;1;0;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;1;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
24.2;1;1;1;1;0;0;1;1;0;1;1;2;-0.333333333;10;0;0;1;0;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;1;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
24.3;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
24.4;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
24.5;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
24.6;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
24.7;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
24.8;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
24.9;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
25;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
25.1;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
25.2;1;1;1;1;0;0;0;0;0;1;1;2;-0.333333333;10;0;0;0;1;0;3000;0;0;0;0;0;0;1;1;0;1;0;-1;0;0.333333333;0.333333333;1;0;0;0;0;1;0.3;0.3;1;1;0;0;1;2;10;0;0;0;0;1;0;0;0;0;0.300000012;1
1 time bat.pos bat.index pant_sel.pos pant_sel.index pant_raise.pos pant_raise.index pant_lower.pos pant_lower.index main_sw.pos main_sw.index reverser.pos reverser.index lever.pos lever.index pant_cmd.q pant_cmd_on.q pant_cmd_off.q no_lower.q pant_up.q hv_nominal.q hv.q hv_ok.q ms_on_req.q ms_off_req.q ms_init.q ms_close.q ms_lost.q ms_open.q ms.q ms_lamp_on.q zero.q minus_one.q lever_pos.q lever_neg.q lever_brake.q dir_set.q drive_ok.q traction.q ed_brake.q pant_moving.q pant_not_up.q snd_base.q snd_gain.q bat:position pant_sel:position pant_raise:position pant_lower:position main_sw:position reverser:position lever:position pant_cmd:state pant_up:elapsed ms_init:elapsed ms:state lamp_ms:lit lamp_pant:lit v_hv:value v_demand:value snd_inverter:playing snd_inverter:volume snd_inverter:pitch
2 0.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
3 0.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
4 0.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
5 0.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
6 0.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
7 0.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
8 0.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
9 0.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
10 0.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
11 1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 0 1 0.3 0.3 1 1 0 0 1 1 15 0 0 0 0 1 0 0 0 0 0.300000012 1
12 1.1 1 1 1 1 1 1 0 0 0 1 0 1 0 15 1 1 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 1 0 1 1 15 1 0.09 0 0 1 1 0 0 0 0.300000012 1
13 1.2 1 1 1 1 1 1 0 0 0 1 0 1 0 15 1 1 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 1 0 1 1 15 1 0.19 0 0 1 1 0 0 0 0.300000012 1
14 1.3 1 1 1 1 1 1 0 0 0 1 0 1 0 15 1 1 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 1 0 1 1 15 1 0.29 0 0 1 1 0 0 0 0.300000012 1
15 1.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 0.39 0 0 1 1 0 0 0 0.300000012 1
16 1.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 0.49 0 0 1 0 0 0 0 0.300000012 1
17 1.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 0.59 0 0 1 0 0 0 0 0.300000012 1
18 1.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 0.69 0 0 1 0 0 0 0 0.300000012 1
19 1.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 0.79 0 0 1 0 0 0 0 0.300000012 1
20 1.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 0.89 0 0 1 0 0 0 0 0.300000012 1
21 2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 0.99 0 0 1 1 0 0 0 0.300000012 1
22 2.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.09 0 0 1 1 0 0 0 0.300000012 1
23 2.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.19 0 0 1 1 0 0 0 0.300000012 1
24 2.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.29 0 0 1 1 0 0 0 0.300000012 1
25 2.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.39 0 0 1 1 0 0 0 0.300000012 1
26 2.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.49 0 0 1 1 0 0 0 0.300000012 1
27 2.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.59 0 0 1 0 0 0 0 0.300000012 1
28 2.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.69 0 0 1 0 0 0 0 0.300000012 1
29 2.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.79 0 0 1 0 0 0 0 0.300000012 1
30 2.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.89 0 0 1 0 0 0 0 0.300000012 1
31 3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 1.99 0 0 1 0 0 0 0 0.300000012 1
32 3.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.09 0 0 1 1 0 0 0 0.300000012 1
33 3.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.19 0 0 1 1 0 0 0 0.300000012 1
34 3.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.29 0 0 1 1 0 0 0 0.300000012 1
35 3.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.39 0 0 1 1 0 0 0 0.300000012 1
36 3.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.49 0 0 1 1 0 0 0 0.300000012 1
37 3.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.59 0 0 1 0 0 0 0 0.300000012 1
38 3.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.69 0 0 1 0 0 0 0 0.300000012 1
39 3.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.79 0 0 1 0 0 0 0 0.300000012 1
40 3.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.89 0 0 1 0 0 0 0 0.300000012 1
41 4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 2.99 0 0 1 0 0 0 0 0.300000012 1
42 4.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.09 0 0 1 1 0 0 0 0.300000012 1
43 4.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.19 0 0 1 1 0 0 0 0.300000012 1
44 4.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.29 0 0 1 1 0 0 0 0.300000012 1
45 4.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.39 0 0 1 1 0 0 0 0.300000012 1
46 4.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.49 0 0 1 1 0 0 0 0.300000012 1
47 4.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.59 0 0 1 0 0 0 0 0.300000012 1
48 4.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.69 0 0 1 0 0 0 0 0.300000012 1
49 4.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.79 0 0 1 0 0 0 0 0.300000012 1
50 4.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.89 0 0 1 0 0 0 0 0.300000012 1
51 5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 3.99 0 0 1 0 0 0 0 0.300000012 1
52 5.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.09 0 0 1 1 0 0 0 0.300000012 1
53 5.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.19 0 0 1 1 0 0 0 0.300000012 1
54 5.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.29 0 0 1 1 0 0 0 0.300000012 1
55 5.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.39 0 0 1 1 0 0 0 0.300000012 1
56 5.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.49 0 0 1 1 0 0 0 0.300000012 1
57 5.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.59 0 0 1 0 0 0 0 0.300000012 1
58 5.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.69 0 0 1 0 0 0 0 0.300000012 1
59 5.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.79 0 0 1 0 0 0 0 0.300000012 1
60 5.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.89 0 0 1 0 0 0 0 0.300000012 1
61 6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0 0 0 0 0 0 1 1 0.3 0.3 1 1 0 0 1 1 15 1 4.99 0 0 1 0 0 0 0 0.300000012 1
62 6.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.08 0 1 0 3000 0 0 0.300000012 1
63 6.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.18 0 1 0 3000 0 0 0.300000012 1
64 6.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.28 0 1 0 3000 0 0 0.300000012 1
65 6.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.38 0 1 0 3000 0 0 0.300000012 1
66 6.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.48 0 1 0 3000 0 0 0.300000012 1
67 6.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.58 0 1 0 3000 0 0 0.300000012 1
68 6.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.68 0 1 0 3000 0 0 0.300000012 1
69 6.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.78 0 1 0 3000 0 0 0.300000012 1
70 6.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.88 0 1 0 3000 0 0 0.300000012 1
71 7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 0.98 0 1 0 3000 0 0 0.300000012 1
72 7.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.08 0 1 0 3000 0 0 0.300000012 1
73 7.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.18 0 1 0 3000 0 0 0.300000012 1
74 7.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.28 0 1 0 3000 0 0 0.300000012 1
75 7.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.38 0 1 0 3000 0 0 0.300000012 1
76 7.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.48 0 1 0 3000 0 0 0.300000012 1
77 7.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.58 0 1 0 3000 0 0 0.300000012 1
78 7.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.68 0 1 0 3000 0 0 0.300000012 1
79 7.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.78 0 1 0 3000 0 0 0.300000012 1
80 7.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.88 0 1 0 3000 0 0 0.300000012 1
81 8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 1.98 0 1 0 3000 0 0 0.300000012 1
82 8.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.08 0 1 0 3000 0 0 0.300000012 1
83 8.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.18 0 1 0 3000 0 0 0.300000012 1
84 8.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.28 0 1 0 3000 0 0 0.300000012 1
85 8.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.38 0 1 0 3000 0 0 0.300000012 1
86 8.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.48 0 1 0 3000 0 0 0.300000012 1
87 8.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.58 0 1 0 3000 0 0 0.300000012 1
88 8.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.68 0 1 0 3000 0 0 0.300000012 1
89 8.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.78 0 1 0 3000 0 0 0.300000012 1
90 8.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.88 0 1 0 3000 0 0 0.300000012 1
91 9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 2.98 0 1 0 3000 0 0 0.300000012 1
92 9.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.08 0 1 0 3000 0 0 0.300000012 1
93 9.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.18 0 1 0 3000 0 0 0.300000012 1
94 9.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.28 0 1 0 3000 0 0 0.300000012 1
95 9.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.38 0 1 0 3000 0 0 0.300000012 1
96 9.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.48 0 1 0 3000 0 0 0.300000012 1
97 9.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.58 0 1 0 3000 0 0 0.300000012 1
98 9.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.68 0 1 0 3000 0 0 0.300000012 1
99 9.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.78 0 1 0 3000 0 0 0.300000012 1
100 9.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.88 0 1 0 3000 0 0 0.300000012 1
101 10 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 3.98 0 1 0 3000 0 0 0.300000012 1
102 10.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.08 0 1 0 3000 0 0 0.300000012 1
103 10.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.18 0 1 0 3000 0 0 0.300000012 1
104 10.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.28 0 1 0 3000 0 0 0.300000012 1
105 10.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.38 0 1 0 3000 0 0 0.300000012 1
106 10.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.48 0 1 0 3000 0 0 0.300000012 1
107 10.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.58 0 1 0 3000 0 0 0.300000012 1
108 10.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.68 0 1 0 3000 0 0 0.300000012 1
109 10.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.78 0 1 0 3000 0 0 0.300000012 1
110 10.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.88 0 1 0 3000 0 0 0.300000012 1
111 11 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 4.98 0 1 0 3000 0 0 0.300000012 1
112 11.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.08 0 1 0 3000 0 0 0.300000012 1
113 11.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.18 0 1 0 3000 0 0 0.300000012 1
114 11.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.28 0 1 0 3000 0 0 0.300000012 1
115 11.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.38 0 1 0 3000 0 0 0.300000012 1
116 11.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.48 0 1 0 3000 0 0 0.300000012 1
117 11.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.58 0 1 0 3000 0 0 0.300000012 1
118 11.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.68 0 1 0 3000 0 0 0.300000012 1
119 11.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.78 0 1 0 3000 0 0 0.300000012 1
120 11.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.88 0 1 0 3000 0 0 0.300000012 1
121 12 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 5.98 0 1 0 3000 0 0 0.300000012 1
122 12.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.08 0 1 0 3000 0 0 0.300000012 1
123 12.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.18 0 1 0 3000 0 0 0.300000012 1
124 12.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.28 0 1 0 3000 0 0 0.300000012 1
125 12.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.38 0 1 0 3000 0 0 0.300000012 1
126 12.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.48 0 1 0 3000 0 0 0.300000012 1
127 12.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.58 0 1 0 3000 0 0 0.300000012 1
128 12.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.68 0 1 0 3000 0 0 0.300000012 1
129 12.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.78 0 1 0 3000 0 0 0.300000012 1
130 12.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.88 0 1 0 3000 0 0 0.300000012 1
131 13 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 6.98 0 1 0 3000 0 0 0.300000012 1
132 13.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.08 0 1 0 3000 0 0 0.300000012 1
133 13.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.18 0 1 0 3000 0 0 0.300000012 1
134 13.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.28 0 1 0 3000 0 0 0.300000012 1
135 13.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.38 0 1 0 3000 0 0 0.300000012 1
136 13.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.48 0 1 0 3000 0 0 0.300000012 1
137 13.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.58 0 1 0 3000 0 0 0.300000012 1
138 13.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.68 0 1 0 3000 0 0 0.300000012 1
139 13.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.78 0 1 0 3000 0 0 0.300000012 1
140 13.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.88 0 1 0 3000 0 0 0.300000012 1
141 14 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 7.98 0 1 0 3000 0 0 0.300000012 1
142 14.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.08 0 1 0 3000 0 0 0.300000012 1
143 14.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.18 0 1 0 3000 0 0 0.300000012 1
144 14.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.28 0 1 0 3000 0 0 0.300000012 1
145 14.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.38 0 1 0 3000 0 0 0.300000012 1
146 14.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.48 0 1 0 3000 0 0 0.300000012 1
147 14.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.58 0 1 0 3000 0 0 0.300000012 1
148 14.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.68 0 1 0 3000 0 0 0.300000012 1
149 14.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.78 0 1 0 3000 0 0 0.300000012 1
150 14.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.88 0 1 0 3000 0 0 0.300000012 1
151 15 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 8.98 0 1 0 3000 0 0 0.300000012 1
152 15.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.08 0 1 0 3000 0 0 0.300000012 1
153 15.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.18 0 1 0 3000 0 0 0.300000012 1
154 15.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.28 0 1 0 3000 0 0 0.300000012 1
155 15.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.38 0 1 0 3000 0 0 0.300000012 1
156 15.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.48 0 1 0 3000 0 0 0.300000012 1
157 15.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.58 0 1 0 3000 0 0 0.300000012 1
158 15.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.68 0 1 0 3000 0 0 0.300000012 1
159 15.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.78 0 1 0 3000 0 0 0.300000012 1
160 15.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.88 0 1 0 3000 0 0 0.300000012 1
161 16 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 9.98 0 1 0 3000 0 0 0.300000012 1
162 16.1 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
163 16.2 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
164 16.3 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
165 16.4 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
166 16.5 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
167 16.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
168 16.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
169 16.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
170 16.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
171 17 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 0 1 0 3000 0 0 0.300000012 1
172 17.1 1 1 1 1 0 0 0 0 1 2 0 1 0 15 1 0 0 1 1 3000 3000 1 1 0 1 1 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 2 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
173 17.2 1 1 1 1 0 0 0 0 1 2 0 1 0 15 1 0 0 1 1 3000 3000 1 1 0 1 1 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 2 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
174 17.3 1 1 1 1 0 0 0 0 1 2 0 1 0 15 1 0 0 1 1 3000 3000 1 1 0 1 1 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 2 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
175 17.4 1 1 1 1 0 0 0 0 1 2 0 1 0 15 1 0 0 1 1 3000 3000 1 1 0 1 1 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 2 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
176 17.5 1 1 1 1 0 0 0 0 1 2 0 1 0 15 1 0 0 1 1 3000 3000 1 1 0 1 1 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 2 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
177 17.6 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
178 17.7 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
179 17.8 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
180 17.9 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
181 18 1 1 1 1 0 0 0 0 0 1 0 1 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0.3 0.3 1 1 0 0 1 1 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
182 18.1 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
183 18.2 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
184 18.3 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
185 18.4 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
186 18.5 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
187 18.6 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
188 18.7 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
189 18.8 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
190 18.9 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
191 19 1 1 1 1 0 0 0 0 0 1 1 2 0 15 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0 0 1 1 0 0 0 0 0.3 0.3 1 1 0 0 1 2 15 1 5 10 1 0 0 3000 0 1 0.300000012 1
192 19.1 1 1 1 1 0 0 0 0 0 1 1 2 0.0666666667 16 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.0666666667 -0.0666666667 0 1 1 0.0666666667 0 0 0 0.3 0.366666667 1 1 0 0 1 2 16 1 5 10 1 0 0 3000 0.0666666701 1 0.366666675 1
193 19.2 1 1 1 1 0 0 0 0 0 1 1 2 0.133333333 17 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.133333333 -0.133333333 0 1 1 0.133333333 0 0 0 0.3 0.433333333 1 1 0 0 1 2 17 1 5 10 1 0 0 3000 0.13333334 1 0.433333337 1
194 19.3 1 1 1 1 0 0 0 0 0 1 1 2 0.2 18 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.2 -0.2 0 1 1 0.2 0 0 0 0.3 0.5 1 1 0 0 1 2 18 1 5 10 1 0 0 3000 0.200000003 1 0.5 1
195 19.4 1 1 1 1 0 0 0 0 0 1 1 2 0.266666667 19 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.266666667 -0.266666667 0 1 1 0.266666667 0 0 0 0.3 0.566666667 1 1 0 0 1 2 19 1 5 10 1 0 0 3000 0.266666681 1 0.566666663 1
196 19.5 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
197 19.6 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
198 19.7 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
199 19.8 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
200 19.9 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
201 20 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
202 20.1 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
203 20.2 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
204 20.3 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
205 20.4 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
206 20.5 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
207 20.6 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
208 20.7 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
209 20.8 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
210 20.9 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
211 21 1 1 1 1 0 0 0 0 0 1 1 2 0.333333333 20 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0.333333333 -0.333333333 0 1 1 0.333333333 0 0 0 0.3 0.633333333 1 1 0 0 1 2 20 1 5 10 1 0 0 3000 0.333333343 1 0.633333325 1
212 21.1 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
213 21.2 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
214 21.3 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
215 21.4 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
216 21.5 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
217 21.6 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
218 21.7 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
219 21.8 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
220 21.9 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
221 22 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
222 22.1 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
223 22.2 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
224 22.3 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
225 22.4 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
226 22.5 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
227 22.6 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
228 22.7 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
229 22.8 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
230 22.9 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
231 23 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 1 0 0 -1 0 0.333333333 0.333333333 1 1 0 0.333333333 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 1 0 0 3000 0 1 0.300000012 1
232 23.1 1 1 1 1 0 0 0 0 -1 0 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 1 1 0 0 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 0 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
233 23.2 1 1 1 1 0 0 0 0 -1 0 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 1 1 0 0 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 0 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
234 23.3 1 1 1 1 0 0 0 0 -1 0 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 1 1 0 0 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 0 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
235 23.4 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
236 23.5 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
237 23.6 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
238 23.7 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
239 23.8 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
240 23.9 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
241 24 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 1 0 0 1 1 3000 3000 1 0 0 1 0 0 0 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 0 0.3 0.3 1 1 0 0 1 2 10 1 5 10 0 1 0 3000 0 0 0.300000012 1
242 24.1 1 1 1 1 0 0 1 1 0 1 1 2 -0.333333333 10 0 0 1 0 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 1 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
243 24.2 1 1 1 1 0 0 1 1 0 1 1 2 -0.333333333 10 0 0 1 0 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 1 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
244 24.3 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
245 24.4 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
246 24.5 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
247 24.6 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
248 24.7 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
249 24.8 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
250 24.9 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
251 25 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
252 25.1 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1
253 25.2 1 1 1 1 0 0 0 0 0 1 1 2 -0.333333333 10 0 0 0 1 0 3000 0 0 0 0 0 0 1 1 0 1 0 -1 0 0.333333333 0.333333333 1 0 0 0 0 1 0.3 0.3 1 1 0 0 1 2 10 0 0 0 0 1 0 0 0 0 0.300000012 1

View File

@@ -0,0 +1,17 @@
# events for: -graph-run vectron-logic.vhg -script vectron-logic.script
0.0 toggle bat
1.0 press pant_raise
1.3 release pant_raise
17.0 inc main_sw
17.5 release main_sw
18.0 inc reverser
19.0 inc lever
19.1 inc lever
19.2 inc lever
19.3 inc lever
19.4 inc lever
21.0 set lever 10
23.0 dec main_sw
23.3 release main_sw
24.0 press pant_lower
24.2 release pant_lower

View File

@@ -0,0 +1,112 @@
// cab logic of an electric locomotive with induction motors, modelled after the Vectron .fiz.
// stage 1 of the vehicle graph: only logic and cab blocks are available, so the pantograph, the main circuit
// and the inverters are represented by timers and constants. the combined power/brake lever is split into
// a traction demand and an electrodynamic brake demand, which will drive the inverter blocks in the next stages
{
"format": "maszyna-vehicle-graph",
"version": 2,
"vehicle": { "name": "Vectron (logic test)" },
"settings": { "low_voltage_simulation": false },
"nodes": [
{ "id": "bat", "type": "cab.switch", "title": "Battery", "params": { "behaviour": "bistable", "submodel": "battery_sw:", "command": "batterytoggle" } },
{ "id": "pant_sel", "type": "cab.switch", "title": "Pantograph selector", "params": { "behaviour": "multi", "positions": 4, "min": 0, "max": 3, "default": 1, "labels": "rear;front;both;rear", "step": 30, "submodel": "pantselect_sw:" } },
{ "id": "pant_raise", "type": "cab.switch", "title": "Raise pantographs", "params": { "behaviour": "monostable", "animation": "move", "step": 4, "submodel": "pantselectedraise_bt:", "command": "pantographraiseselected" } },
{ "id": "pant_lower", "type": "cab.switch", "title": "Lower pantographs", "params": { "behaviour": "monostable", "animation": "move", "step": 4, "submodel": "pantselectedlower_bt:", "command": "pantographlowerselected" } },
{ "id": "main_sw", "type": "cab.switch", "title": "Main switch", "params": { "behaviour": "multi", "positions": 3, "min": -1, "max": 1, "default": 0, "spring": true, "labels": "off;0;on", "step": 40, "offset": -40, "submodel": "main_sw:" } },
{ "id": "reverser", "type": "cab.switch", "title": "Direction", "params": { "behaviour": "multi", "positions": 3, "min": -1, "max": 1, "default": 0, "labels": "back;0;forward", "step": 45, "offset": -45, "submodel": "dirkey:" } },
{ "id": "lever", "type": "cab.switch", "title": "Power/brake lever", "params": { "behaviour": "multi", "positions": 31, "min": -1, "max": 1, "default": 0, "step": 2, "offset": -30, "submodel": "jointctrl:" } },
{ "id": "pant_cmd", "type": "logic.sr", "title": "Pantographs commanded up" },
{ "id": "pant_cmd_on", "type": "logic.and", "title": "Raising with battery" },
{ "id": "pant_cmd_off", "type": "logic.nand", "title": "Lowering or battery off" },
{ "id": "no_lower", "type": "logic.not", "title": "Lower button released" },
{ "id": "pant_up", "type": "logic.ton", "title": "Pantograph raising", "params": { "time": 5.0 } },
{ "id": "hv_nominal", "type": "logic.const", "title": "Catenary voltage", "params": { "value": 3000 } },
{ "id": "hv", "type": "logic.math", "title": "Voltage behind the pantograph", "params": { "op": "mul" } },
{ "id": "hv_ok", "type": "logic.hyst", "title": "Voltage above minimum", "params": { "lo": 1800, "hi": 1900 } },
{ "id": "ms_on_req", "type": "logic.compare", "title": "Main switch to on", "params": { "op": "gt", "value": 0 } },
{ "id": "ms_off_req", "type": "logic.compare", "title": "Main switch to off", "params": { "op": "lt", "value": 0 } },
{ "id": "ms_init", "type": "logic.ton", "title": "Main circuit initialisation", "params": { "time": 10.0 } },
{ "id": "ms_close", "type": "logic.and", "title": "Closing allowed" },
{ "id": "ms_lost", "type": "logic.nand", "title": "Battery or voltage missing" },
{ "id": "ms_open", "type": "logic.or", "title": "Opening" },
{ "id": "ms", "type": "logic.sr", "title": "Main circuit breaker" },
{ "id": "ms_lamp_on", "type": "logic.not", "title": "Main circuit open" },
{ "id": "zero", "type": "logic.const", "title": "Zero", "params": { "value": 0 } },
{ "id": "minus_one", "type": "logic.const", "title": "Minus one", "params": { "value": -1 } },
{ "id": "lever_pos", "type": "logic.math", "title": "Traction part", "params": { "op": "max" } },
{ "id": "lever_neg", "type": "logic.math", "title": "Lever inverted", "params": { "op": "mul" } },
{ "id": "lever_brake", "type": "logic.math", "title": "Brake part", "params": { "op": "max" } },
{ "id": "dir_set", "type": "logic.compare", "title": "Direction selected", "params": { "op": "ne", "value": 0 } },
{ "id": "drive_ok", "type": "logic.and", "title": "Ready to drive" },
{ "id": "traction", "type": "logic.select", "title": "Traction demand" },
{ "id": "ed_brake", "type": "logic.select", "title": "ED brake demand" },
{ "id": "lamp_ms", "type": "fb.lamp", "title": "Main circuit lamp", "params": { "color": "red", "submodel": "i-mainbreaker:" } },
{ "id": "lamp_pant", "type": "fb.lamp", "title": "Pantograph lamp", "params": { "color": "yellow", "blink": true, "blink_period": 1.0, "submodel": "i-pantraising:" } },
{ "id": "pant_moving", "type": "logic.and", "title": "Pantograph moving" },
{ "id": "pant_not_up", "type": "logic.not", "title": "Pantograph not up yet" },
{ "id": "v_hv", "type": "fb.gauge", "title": "Catenary voltage", "params": { "min": 0, "max": 4000, "unit": "V", "angle_min": 0, "angle_max": 270, "submodel": "hvoltage:" } },
{ "id": "v_demand", "type": "fb.gauge", "title": "Traction demand", "params": { "min": 0, "max": 1, "angle_min": 0, "angle_max": 270, "submodel": "tractionforce:" } },
{ "id": "snd_base", "type": "logic.const", "title": "Idle volume", "params": { "value": 0.3 } },
{ "id": "snd_gain", "type": "logic.math", "title": "Volume rising with demand", "params": { "op": "add" } },
{ "id": "snd_inverter", "type": "fb.sound", "title": "Inverters", "params": { "file": "vectron-inverter.wav", "placement": "engine", "loop": true } }
],
"connections": [
{ "from": "pant_raise.pos", "to": "pant_cmd_on.a" },
{ "from": "bat.pos", "to": "pant_cmd_on.b" },
{ "from": "pant_lower.pos", "to": "no_lower.a" },
{ "from": "no_lower.q", "to": "pant_cmd_off.a" },
{ "from": "bat.pos", "to": "pant_cmd_off.b" },
{ "from": "pant_cmd_on.q", "to": "pant_cmd.s" },
{ "from": "pant_cmd_off.q", "to": "pant_cmd.r" },
{ "from": "pant_cmd.q", "to": "pant_up.a" },
{ "from": "hv_nominal.q", "to": "hv.a" },
{ "from": "pant_up.q", "to": "hv.b" },
{ "from": "hv.q", "to": "hv_ok.a" },
{ "from": "hv.q", "to": "v_hv.value" },
{ "from": "pant_up.q", "to": "pant_not_up.a" },
{ "from": "pant_cmd.q", "to": "pant_moving.a" },
{ "from": "pant_not_up.q", "to": "pant_moving.b" },
{ "from": "pant_moving.q", "to": "lamp_pant.on" },
{ "from": "main_sw.pos", "to": "ms_on_req.a" },
{ "from": "main_sw.pos", "to": "ms_off_req.a" },
{ "from": "hv_ok.q", "to": "ms_init.a" },
{ "from": "ms_on_req.q", "to": "ms_close.a" },
{ "from": "ms_init.q", "to": "ms_close.b" },
{ "from": "bat.pos", "to": "ms_lost.a" },
{ "from": "hv_ok.q", "to": "ms_lost.b" },
{ "from": "ms_off_req.q", "to": "ms_open.a" },
{ "from": "ms_lost.q", "to": "ms_open.b" },
{ "from": "ms_close.q", "to": "ms.s" },
{ "from": "ms_open.q", "to": "ms.r" },
{ "from": "ms.q", "to": "ms_lamp_on.a" },
{ "from": "ms_lamp_on.q", "to": "lamp_ms.on" },
{ "from": "lever.pos", "to": "lever_pos.a" },
{ "from": "zero.q", "to": "lever_pos.b" },
{ "from": "lever.pos", "to": "lever_neg.a" },
{ "from": "minus_one.q", "to": "lever_neg.b" },
{ "from": "lever_neg.q", "to": "lever_brake.a" },
{ "from": "zero.q", "to": "lever_brake.b" },
{ "from": "reverser.pos", "to": "dir_set.a" },
{ "from": "dir_set.q", "to": "drive_ok.a" },
{ "from": "ms.q", "to": "drive_ok.b" },
{ "from": "drive_ok.q", "to": "traction.sel" },
{ "from": "zero.q", "to": "traction.a" },
{ "from": "lever_pos.q", "to": "traction.b" },
{ "from": "drive_ok.q", "to": "ed_brake.sel" },
{ "from": "zero.q", "to": "ed_brake.a" },
{ "from": "lever_brake.q", "to": "ed_brake.b" },
{ "from": "traction.q", "to": "v_demand.value" },
{ "from": "ms.q", "to": "snd_inverter.play" },
{ "from": "snd_base.q", "to": "snd_gain.a" },
{ "from": "traction.q", "to": "snd_gain.b" },
{ "from": "snd_gain.q", "to": "snd_inverter.volume" }
]
}

View File

@@ -0,0 +1,96 @@
#!/usr/bin/env python3
"""Tests of the vehicle graph core, run through the simulator's -graph-run command.
usage: run_tests.py <simulator executable> [--update]
- every tests/*.vhg file starts with a line "// expect: ok", "// expect: error <text>" or "// expect: warning <text>",
and is checked against the output of -graph-run;
- every <name>.vhg with a <name>.script, in both directories, is run twice, and both results have to be identical (determinism)
and equal to <name>.expected.csv. --update writes the current results as the expected ones.
"""
import pathlib
import subprocess
import sys
import tempfile
ROOT = pathlib.Path(__file__).resolve().parent
def run(executable, *arguments):
result = subprocess.run([str(executable), "-graph-run", *map(str, arguments)], capture_output=True, text=True)
return result.returncode, result.stdout + result.stderr
def check_file(executable, path):
first = path.read_text(encoding="utf-8").splitlines()[0]
if not first.startswith("// expect:"):
return f"{path.name}: missing '// expect:' line"
expectation = first[len("// expect:"):].strip()
kind, _, text = expectation.partition(" ")
code, output = run(executable, path)
if kind == "ok":
if code != 0 or "error" in output:
return f"{path.name}: expected no errors, got:\n{output}"
elif kind == "error":
if code == 0 or text not in output:
return f"{path.name}: expected error containing '{text}', got (exit {code}):\n{output}"
elif kind == "warning":
if code != 0 or "warning" not in output or text not in output:
return f"{path.name}: expected warning containing '{text}', got (exit {code}):\n{output}"
else:
return f"{path.name}: unknown expectation '{expectation}'"
return None
def check_example(executable, path, update):
script = path.with_suffix(".script")
expected = path.with_suffix(".expected.csv")
results = []
with tempfile.TemporaryDirectory() as directory:
for attempt in range(2):
output = pathlib.Path(directory) / f"run{attempt}.csv"
code, log = run(executable, path, "-script", script, "-every", 10, "-o", output)
if code != 0:
return f"{path.name}: run failed:\n{log}"
# git may check the expected files out with windows line endings
results.append(output.read_bytes().replace(b"\r\n", b"\n"))
if results[0] != results[1]:
return f"{path.name}: two runs gave different results"
if update:
expected.write_bytes(results[0])
return None
if not expected.exists():
return f"{path.name}: missing {expected.name}, run with --update to create it"
if expected.read_bytes().replace(b"\r\n", b"\n") != results[0]:
return f"{path.name}: results differ from {expected.name}"
return None
def main():
if len(sys.argv) < 2:
print(__doc__)
return 2
executable = pathlib.Path(sys.argv[1]).resolve()
update = "--update" in sys.argv[2:]
failures = []
count = 0
for path in sorted((ROOT / "tests").glob("*.vhg")):
count += 1
problem = check_file(executable, path)
if problem:
failures.append(problem)
for path in sorted((ROOT / "tests").glob("*.vhg")) + sorted((ROOT / "examples").glob("*.vhg")):
if path.with_suffix(".script").exists():
count += 1
problem = check_example(executable, path, update)
if problem:
failures.append(problem)
for problem in failures:
print("FAIL", problem)
print(f"{count - len(failures)} of {count} passed")
return 1 if failures else 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -0,0 +1,2 @@
// expect: error has to be one of
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [ { "id": "sw", "type": "cab.switch", "params": { "behaviour": "bistabilny" } } ] }

View File

@@ -0,0 +1,2 @@
// expect: error has to be a number
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [ { "id": "sw", "type": "cab.switch", "params": { "positions": "3" } } ] }

View File

@@ -0,0 +1,36 @@
time;x.q;y.q;and.q;or.q;xor.q;nand.q;nor.q;not.q;sr.q;sr_set.q;ton.q;tof.q;delay.q;hyst.q;le.q;div.q;min.q;sel.q;button.pos;button.index;lever.pos;lever.index;sr:state;sr_set:state;ton:elapsed;tof:elapsed;button:position;lever:position
0.1;1;0;0;1;1;1;0;0;1;1;0;1;1;0;1;0;0;1;0;0;0;2;1;1;0.1;0;0;2
0.2;1;0;0;1;1;1;0;0;1;1;0;1;1;0;1;0;0;1;0;0;0;2;1;1;0.2;0;0;2
0.3;1;0;0;1;1;1;0;0;1;1;0;1;1;0;1;0;0;1;0;0;0;2;1;1;0.3;0;0;2
0.4;1;1;1;1;0;0;0;0;0;1;0;1;1;0;1;1;1;1;0;0;0;2;0;1;0.4;0;0;2
0.5;1;1;1;1;0;0;0;0;0;1;1;1;1;0;1;1;1;1;0;0;0;2;0;1;0.5;0;0;2
0.6;1;1;1;1;0;0;0;0;0;1;1;1;1;0;1;1;1;1;0;0;0;2;0;1;0.5;0;0;2
0.7;0;1;0;1;1;1;0;1;0;0;0;1;0;0;1;0;0;0;0;0;0;2;0;0;0;0.1;0;2
0.8;0;1;0;1;1;1;0;1;0;0;0;1;0;0;1;0;0;2;1;1;2;4;0;0;0;0.2;1;4
0.9;0;1;0;1;1;1;0;1;0;0;0;1;0;0;1;0;0;2;1;1;2;4;0;0;0;0.3;1;4
1;0;1;0;1;1;1;0;1;0;0;0;1;0;0;1;0;0;0;0;0;2;4;0;0;0;0.4;0;4
1.1;0;1;0;1;1;1;0;1;0;0;0;0;0;0;1;0;0;0;0;0;0;2;0;0;0;0.5;0;2
1.2;3;1;1;1;0;0;0;0;0;1;0;1;3;0;1;3;1;3;0;0;0;2;0;1;0.1;0;0;2
1.3;5;1;1;1;0;0;0;0;0;1;0;1;5;1;0;5;1;5;0;0;0;2;0;1;0.2;0;0;2
1.4;2.5;1;1;1;0;0;0;0;0;1;0;1;2.5;1;1;2.5;1;2.5;0;0;0;2;0;1;0.3;0;0;2
1.5;1;1;1;1;0;0;0;0;0;1;0;1;1;0;1;1;1;1;0;0;0;2;0;1;0.4;0;0;2
1.6;1;0;0;1;1;1;0;0;1;1;1;1;1;0;1;0;0;1;0;0;0;2;1;1;0.5;0;0;2
1.7;1;0;0;1;1;1;0;0;1;1;1;1;1;0;1;0;0;1;0;0;-2;0;1;1;0.5;0;0;0
1.8;0;0;0;0;0;1;1;1;1;1;0;1;0;0;1;0;0;0;0;0;-2;0;1;1;0;0.1;0;0
1.9;0;0;0;0;0;1;1;1;1;1;0;1;0;0;1;0;0;0;0;0;-2;0;1;1;0;0.2;0;0
2;0;0;0;0;0;1;1;1;1;1;0;1;0;0;1;0;0;0;0;0;-2;0;1;1;0;0.3;0;0
2.1;0;0;0;0;0;1;1;1;1;1;0;1;0;0;1;0;0;0;0;0;-2;0;1;1;0;0.4;0;0
2.2;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;0;0;0;-2;0;1;1;0;0.5;0;0
2.3;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;0;0;0;-2;0;1;1;0;0.5;0;0
2.4;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;0;0;0;-2;0;1;1;0;0.5;0;0
2.5;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;0;0;0;-2;0;1;1;0;0.5;0;0
2.6;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
2.7;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
2.8;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
2.9;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
3;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
3.1;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
3.2;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
3.3;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
3.4;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
3.5;0;0;0;0;0;1;1;1;1;1;0;0;0;0;1;0;0;-2;1;1;-2;0;1;1;0;0.5;1;0
1 time x.q y.q and.q or.q xor.q nand.q nor.q not.q sr.q sr_set.q ton.q tof.q delay.q hyst.q le.q div.q min.q sel.q button.pos button.index lever.pos lever.index sr:state sr_set:state ton:elapsed tof:elapsed button:position lever:position
2 0.1 1 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 0 2 1 1 0.1 0 0 2
3 0.2 1 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 0 2 1 1 0.2 0 0 2
4 0.3 1 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 0 2 1 1 0.3 0 0 2
5 0.4 1 1 1 1 0 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 0 2 0 1 0.4 0 0 2
6 0.5 1 1 1 1 0 0 0 0 0 1 1 1 1 0 1 1 1 1 0 0 0 2 0 1 0.5 0 0 2
7 0.6 1 1 1 1 0 0 0 0 0 1 1 1 1 0 1 1 1 1 0 0 0 2 0 1 0.5 0 0 2
8 0.7 0 1 0 1 1 1 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 2 0 0 0 0.1 0 2
9 0.8 0 1 0 1 1 1 0 1 0 0 0 1 0 0 1 0 0 2 1 1 2 4 0 0 0 0.2 1 4
10 0.9 0 1 0 1 1 1 0 1 0 0 0 1 0 0 1 0 0 2 1 1 2 4 0 0 0 0.3 1 4
11 1 0 1 0 1 1 1 0 1 0 0 0 1 0 0 1 0 0 0 0 0 2 4 0 0 0 0.4 0 4
12 1.1 0 1 0 1 1 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0.5 0 2
13 1.2 3 1 1 1 0 0 0 0 0 1 0 1 3 0 1 3 1 3 0 0 0 2 0 1 0.1 0 0 2
14 1.3 5 1 1 1 0 0 0 0 0 1 0 1 5 1 0 5 1 5 0 0 0 2 0 1 0.2 0 0 2
15 1.4 2.5 1 1 1 0 0 0 0 0 1 0 1 2.5 1 1 2.5 1 2.5 0 0 0 2 0 1 0.3 0 0 2
16 1.5 1 1 1 1 0 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 0 2 0 1 0.4 0 0 2
17 1.6 1 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 2 1 1 0.5 0 0 2
18 1.7 1 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 -2 0 1 1 0.5 0 0 0
19 1.8 0 0 0 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 -2 0 1 1 0 0.1 0 0
20 1.9 0 0 0 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 -2 0 1 1 0 0.2 0 0
21 2 0 0 0 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 -2 0 1 1 0 0.3 0 0
22 2.1 0 0 0 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 -2 0 1 1 0 0.4 0 0
23 2.2 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 0 -2 0 1 1 0 0.5 0 0
24 2.3 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 0 -2 0 1 1 0 0.5 0 0
25 2.4 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 0 -2 0 1 1 0 0.5 0 0
26 2.5 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 0 -2 0 1 1 0 0.5 0 0
27 2.6 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0
28 2.7 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0
29 2.8 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0
30 2.9 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0
31 3 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0
32 3.1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0
33 3.2 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0
34 3.3 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0
35 3.4 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0
36 3.5 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 -2 1 1 -2 0 1 1 0 0.5 1 0

View File

@@ -0,0 +1,16 @@
0.0 force x.q 1
0.3 force y.q 1
0.6 force x.q 0
0.7 press button
0.71 inc lever
0.72 inc lever
0.9 release button
1.0 release lever
1.1 force x.q 3
1.2 force x.q 5
1.3 force x.q 2.5
1.4 force x.q 1
1.5 force y.q 0
1.6 value lever -1.9
1.7 unforce x.q
2.5 toggle button

View File

@@ -0,0 +1,39 @@
// expect: ok
// every logic block driven by forced inputs; see blocks.script
{
"format": "maszyna-vehicle-graph", "version": 2,
"nodes": [
{ "id": "x", "type": "logic.const", "params": { "value": 0 } },
{ "id": "y", "type": "logic.const", "params": { "value": 0 } },
{ "id": "and", "type": "logic.and" }, { "id": "or", "type": "logic.or" }, { "id": "xor", "type": "logic.xor" },
{ "id": "nand", "type": "logic.nand" }, { "id": "nor", "type": "logic.nor" }, { "id": "not", "type": "logic.not" },
{ "id": "sr", "type": "logic.sr" },
{ "id": "sr_set", "type": "logic.sr", "params": { "reset_priority": false } },
{ "id": "ton", "type": "logic.ton", "params": { "time": 0.5 } },
{ "id": "tof", "type": "logic.tof", "params": { "time": 0.5 } },
{ "id": "delay", "type": "logic.delay", "params": { "initial": 7 } },
{ "id": "hyst", "type": "logic.hyst", "params": { "lo": 2, "hi": 4 } },
{ "id": "le", "type": "logic.compare", "params": { "op": "le", "value": 3 } },
{ "id": "div", "type": "logic.math", "params": { "op": "div" } },
{ "id": "min", "type": "logic.math", "params": { "op": "min" } },
{ "id": "sel", "type": "logic.select" },
{ "id": "button", "type": "cab.switch", "params": { "behaviour": "monostable" } },
{ "id": "lever", "type": "cab.switch", "params": { "behaviour": "multi", "positions": 5, "min": -2, "max": 2, "default": 0, "spring": true } }
],
"connections": [
{ "from": "x.q", "to": "and.a" }, { "from": "y.q", "to": "and.b" },
{ "from": "x.q", "to": "or.a" }, { "from": "y.q", "to": "or.b" },
{ "from": "x.q", "to": "xor.a" }, { "from": "y.q", "to": "xor.b" },
{ "from": "x.q", "to": "nand.a" }, { "from": "y.q", "to": "nand.b" },
{ "from": "x.q", "to": "nor.a" }, { "from": "y.q", "to": "nor.b" },
{ "from": "x.q", "to": "not.a" },
{ "from": "x.q", "to": "sr.s" }, { "from": "y.q", "to": "sr.r" },
{ "from": "x.q", "to": "sr_set.s" }, { "from": "y.q", "to": "sr_set.r" },
{ "from": "x.q", "to": "ton.a" }, { "from": "x.q", "to": "tof.a" },
{ "from": "x.q", "to": "delay.a" },
{ "from": "x.q", "to": "hyst.a" }, { "from": "x.q", "to": "le.a" },
{ "from": "x.q", "to": "div.a" }, { "from": "y.q", "to": "div.b" },
{ "from": "x.q", "to": "min.a" }, { "from": "y.q", "to": "min.b" },
{ "from": "button.pos", "to": "sel.sel" }, { "from": "x.q", "to": "sel.a" }, { "from": "lever.pos", "to": "sel.b" }
]
}

View File

@@ -0,0 +1,3 @@
// expect: error joins different domains
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [ { "id": "a", "type": "cab.switch" }, { "id": "lamp", "type": "fb.lamp" } ],
"connections": [ { "from": "a.pos", "to": "lamp.supply" } ] }

View File

@@ -0,0 +1,2 @@
// expect: error duplicate node id
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [ { "id": "a", "type": "logic.not" }, { "id": "a", "type": "logic.not" } ] }

View File

@@ -0,0 +1,15 @@
// expect: ok
// the same self-holding circuit as loop.vhg, closed through a unit delay
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [
{ "id": "start", "type": "cab.switch" },
{ "id": "hold", "type": "logic.or" },
{ "id": "coil", "type": "logic.and" },
{ "id": "stop", "type": "logic.const", "params": { "value": 1 } },
{ "id": "contact", "type": "logic.delay" }
], "connections": [
{ "from": "start.pos", "to": "hold.a" },
{ "from": "contact.q", "to": "hold.b" },
{ "from": "hold.q", "to": "coil.a" },
{ "from": "stop.q", "to": "coil.b" },
{ "from": "coil.q", "to": "contact.a" }
] }

View File

@@ -0,0 +1,12 @@
// expect: error loop without a deferred block
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [
{ "id": "start", "type": "cab.switch" },
{ "id": "hold", "type": "logic.or" },
{ "id": "coil", "type": "logic.and" },
{ "id": "stop", "type": "logic.const", "params": { "value": 1 } }
], "connections": [
{ "from": "start.pos", "to": "hold.a" },
{ "from": "coil.q", "to": "hold.b" },
{ "from": "hold.q", "to": "coil.a" },
{ "from": "stop.q", "to": "coil.b" }
] }

View File

@@ -0,0 +1,2 @@
// expect: error malformed file
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [ { "id": 5, "type": "logic.not" } ] }

View File

@@ -0,0 +1,4 @@
// expect: error has more than one source
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [
{ "id": "a", "type": "cab.switch" }, { "id": "b", "type": "cab.switch" }, { "id": "n", "type": "logic.not" }
], "connections": [ { "from": "a.pos", "to": "n.a" }, { "from": "b.pos", "to": "n.a" } ] }

View File

@@ -0,0 +1,2 @@
// expect: warning required input "a" isn't connected
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [ { "id": "n", "type": "logic.not" } ] }

View File

@@ -0,0 +1,2 @@
// expect: error unknown block type
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [ { "id": "x", "type": "el.flux_capacitor" } ] }

View File

@@ -0,0 +1,2 @@
// expect: error unsupported file version 1
{ "format": "maszyna-vehicle-graph", "version": 1, "nodes": [] }

View File

@@ -0,0 +1,3 @@
// expect: error isn't an output
{ "format": "maszyna-vehicle-graph", "version": 2, "nodes": [ { "id": "a", "type": "logic.not" }, { "id": "b", "type": "logic.not" } ],
"connections": [ { "from": "a.a", "to": "b.a" } ] }

View File

@@ -0,0 +1,381 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "vehicle/graph/blocks/cab.h"
#include "vehicle/graph/graph_catalog.h"
#include <algorithm>
#include <cmath>
namespace vgraph
{
namespace
{
std::vector<std::string> split_labels(std::string const &Text)
{
std::vector<std::string> result;
if (Text.empty())
{
return result;
}
std::string::size_type start{0};
while (true)
{
auto const separator{Text.find(';', start)};
result.emplace_back(Text.substr(start, separator == std::string::npos ? std::string::npos : separator - start));
if (separator == std::string::npos)
{
break;
}
start = separator + 1;
}
return result;
}
} // namespace
// cab_switch
cab_switch::cab_switch(block_setup const &Setup)
: block(Setup), m_behaviour(static_cast<behaviour_type>(choice(Setup, param::behaviour))),
m_positioncount(std::max(1, static_cast<int>(std::lround(number(Setup, param::positions))))), m_min(number(Setup, param::min)), m_max(number(Setup, param::max)),
m_spring(boolean(Setup, param::spring)), m_labels(split_labels(text(Setup, param::labels))), m_animation(static_cast<animation_type>(choice(Setup, param::animation))),
m_step(number(Setup, param::step)), m_offset(number(Setup, param::offset)), m_smoothing(number(Setup, param::smoothing)), m_submodel(text(Setup, param::submodel)),
m_keyincrease(text(Setup, param::key_inc)), m_keydecrease(text(Setup, param::key_dec)), m_command(text(Setup, param::command)), m_hardwarename(text(Setup, param::hw_name))
{
// the default is given as a value, as the author sees it; the switch starts at the position closest to it
auto const defaultvalue{number(Setup, param::default_value)};
if (m_positioncount > 1 && m_max != m_min)
{
m_defaultposition = clamp_position(static_cast<int>(std::lround((defaultvalue - m_min) / (m_max - m_min) * (m_positioncount - 1))));
}
m_position = m_defaultposition;
}
int cab_switch::clamp_position(int const Position) const
{
return std::clamp(Position, 0, m_positioncount - 1);
}
double cab_switch::value_at(int const Position) const
{
if (m_positioncount < 2)
{
return m_min;
}
return m_min + (m_max - m_min) * clamp_position(Position) / (m_positioncount - 1);
}
std::string cab_switch::label(int const Position) const
{
return (Position >= 0 && Position < static_cast<int>(m_labels.size()) ? m_labels[Position] : std::string{});
}
void cab_switch::update(frame &Frame)
{
set(Frame, port::value, value_at(m_position));
set(Frame, port::index, m_position);
}
void cab_switch::increase()
{
m_position = clamp_position(m_position + 1);
}
void cab_switch::decrease()
{
m_position = clamp_position(m_position - 1);
}
void cab_switch::toggle()
{
switch (m_behaviour)
{
case behaviour_type::monostable:
{
// a momentary switch can't stay toggled; a toggle is treated as pressing it, the release brings it back
press();
break;
}
default:
{
auto const other{m_defaultposition == m_positioncount - 1 ? 0 : m_positioncount - 1};
m_position = (m_position == m_defaultposition ? other : m_defaultposition);
break;
}
}
}
void cab_switch::press()
{
switch (m_behaviour)
{
case behaviour_type::multi:
{
// levers are moved with increase and decrease; pressing them has no meaning
break;
}
case behaviour_type::monostable:
{
m_position = (m_defaultposition == m_positioncount - 1 ? 0 : m_positioncount - 1);
break;
}
default:
{
toggle();
break;
}
}
}
void cab_switch::release()
{
if (m_behaviour == behaviour_type::monostable || (m_behaviour == behaviour_type::multi && m_spring))
{
m_position = m_defaultposition;
}
}
void cab_switch::set_position(int const Position)
{
m_position = clamp_position(Position);
}
void cab_switch::set_value(double const Value)
{
if (m_positioncount < 2 || m_max == m_min)
{
return;
}
set_position(static_cast<int>(std::lround((Value - m_min) / (m_max - m_min) * (m_positioncount - 1))));
}
block_type cab_switch::describe()
{
block_type type;
type.id = "cab.switch";
type.category = "cab";
type.name = "Switch";
type.description = "Switch, button or lever of the cab. Its behaviour and animation are defined here, and its value can be connected to any block.";
type.origin = block_origin::cab;
type.ports = {signal_out("pos", value_type::real), signal_out("index", value_type::integer)};
type.params = {
choice_param("behaviour", {"bistable", "monostable", "multi"}, "bistable"),
number_param("positions", 2.0),
number_param("min", 0.0),
number_param("max", 1.0),
number_param("default", 0.0),
boolean_param("spring", false),
text_param("labels"),
choice_param("animation", {"rotate", "move"}, "rotate"),
number_param("step", 45.0, "deg/mm"),
number_param("offset", 0.0, "deg/mm"),
number_param("smoothing", 0.2, "s"),
text_param("submodel"),
text_param("key_inc"),
text_param("key_dec"),
text_param("command"),
text_param("hw_name"),
};
type.create = make_block<cab_switch>;
return type;
}
// cab_lamp
cab_lamp::cab_lamp(block_setup const &Setup)
: block(Setup), m_supplied(is_connected(Setup, port::supply)), m_blink(boolean(Setup, param::blink)), m_blinkperiod(std::max(0.01, number(Setup, param::blink_period))),
m_minvoltage(number(Setup, param::min_voltage)), m_power(std::max(0.0, number(Setup, param::power))), m_submodel(text(Setup, param::submodel))
{
}
void cab_lamp::update(frame &Frame)
{
// without low voltage simulation, or without the supply connected, the lamp is assumed to be powered
auto const lowvoltage{Frame.low_voltage && m_supplied};
auto const voltage{lowvoltage ? forward_in(Frame, port::supply) : 0.0};
auto const powered{false == lowvoltage || voltage >= m_minvoltage};
auto lit{powered && get_bool(Frame, port::on)};
if (lit && m_blink)
{
// blinking follows the time of the graph, so all lamps of the vehicle blink in step
lit = std::fmod(Frame.time, m_blinkperiod) < 0.5 * m_blinkperiod;
}
m_lit = lit;
if (lowvoltage && m_lit && voltage > 1.0)
{
add_back(Frame, port::supply, m_power / voltage);
}
}
block_type cab_lamp::describe()
{
block_type type;
type.id = "fb.lamp";
type.category = "indicators";
type.name = "Lamp";
type.description = "Indicator lamp. With low voltage simulation enabled and the supply connected, it needs enough voltage to light, and draws current.";
type.origin = block_origin::cab;
type.ports = {signal_in("on", value_type::boolean), physical_in("supply", domain::low_voltage, true)};
type.params = {
choice_param("color", {"green", "yellow", "red", "white", "blue"}, "green"),
boolean_param("blink", false),
number_param("blink_period", 1.0, "s"),
number_param("min_voltage", 70.0, "V"),
number_param("power", 2.0, "W"),
text_param("submodel"),
};
type.create = make_block<cab_lamp>;
return type;
}
// cab_gauge
cab_gauge::cab_gauge(block_setup const &Setup, bool const Twoneedles)
: block(Setup), m_twoneedles(Twoneedles), m_min(number(Setup, param::min)), m_max(number(Setup, param::max)), m_anglemin(number(Setup, param::angle_min)),
m_anglemax(number(Setup, param::angle_max)), m_smoothing(number(Setup, param::smoothing)), m_submodel(text(Setup, param::submodel)),
m_submodel2(Twoneedles ? text(Setup, param::submodel2) : std::string{})
{
m_values[0] = m_values[1] = static_cast<float>(std::min(m_min, m_max));
}
void cab_gauge::update(frame &Frame)
{
// the needle stops at the ends of the scale
auto const low{std::min(m_min, m_max)};
auto const high{std::max(m_min, m_max)};
m_values[0] = static_cast<float>(std::clamp(get(Frame, port::value), low, high));
if (m_twoneedles)
{
m_values[1] = static_cast<float>(std::clamp(get(Frame, port::value2), low, high));
}
}
block_type cab_gauge::describe(bool const Twoneedles)
{
block_type type;
type.category = "indicators";
type.origin = block_origin::cab;
if (Twoneedles)
{
type.id = "fb.manometer";
type.name = "Two needle gauge";
type.description = "Gauge with two needles, e.g. pressure gauge of the brake pipe (black) and the main reservoir (red).";
type.ports = {signal_in("black", value_type::real, 0.0, "bar"), signal_in("red", value_type::real, 0.0, "bar", true)};
}
else
{
type.id = "fb.gauge";
type.name = "Gauge";
type.description = "Needle gauge: voltmeter, ammeter, speedometer.";
type.ports = {signal_in("value", value_type::real)};
}
type.params = {
number_param("min", 0.0),
number_param("max", Twoneedles ? 10.0 : 100.0),
text_param("unit", Twoneedles ? "bar" : ""),
number_param("angle_min", -135.0, "deg"),
number_param("angle_max", 135.0, "deg"),
number_param("smoothing", 0.3, "s"),
text_param("submodel"),
};
if (Twoneedles)
{
type.params.push_back(text_param("submodel2"));
}
if (Twoneedles)
{
type.create = [](block_setup const &Setup) -> std::unique_ptr<block> { return std::make_unique<cab_gauge>(Setup, true); };
}
else
{
type.create = [](block_setup const &Setup) -> std::unique_ptr<block> { return std::make_unique<cab_gauge>(Setup, false); };
}
return type;
}
// vehicle_sound
vehicle_sound::vehicle_sound(block_setup const &Setup)
: block(Setup), m_file(text(Setup, param::file)), m_basevolume(number(Setup, param::volume)), m_basepitch(number(Setup, param::pitch)), m_loop(boolean(Setup, param::loop)),
m_placement(static_cast<placement_type>(choice(Setup, param::placement))), m_range(number(Setup, param::range)),
m_offset{number(Setup, param::offset_x), number(Setup, param::offset_y), number(Setup, param::offset_z)}
{
}
void vehicle_sound::update(frame &Frame)
{
m_playing = get_bool(Frame, port::play);
m_volume = static_cast<float>(std::max(0.0, m_basevolume * get(Frame, port::volume)));
m_pitch = static_cast<float>(std::max(0.0, m_basepitch * get(Frame, port::pitch)));
}
char const *vehicle_sound::state_name(std::size_t const Index) const
{
switch (Index)
{
case 0:
return "playing";
case 1:
return "volume";
default:
return "pitch";
}
}
double vehicle_sound::state_value(std::size_t const Index) const
{
switch (Index)
{
case 0:
return m_playing ? 1.0 : 0.0;
case 1:
return m_volume;
default:
return m_pitch;
}
}
block_type vehicle_sound::describe()
{
block_type type;
type.id = "fb.sound";
type.category = "indicators";
type.name = "Sound";
type.description = "Sound of the vehicle or of its cab. Volume and pitch are the parameters multiplied by the inputs; looped sounds play while the play input is on.";
type.origin = block_origin::cab;
type.ports = {signal_in("play", value_type::boolean), signal_in("volume", value_type::real, 1.0, "", true), signal_in("pitch", value_type::real, 1.0, "", true)};
type.params = {
text_param("file"),
number_param("volume", 1.0),
number_param("pitch", 1.0),
boolean_param("loop", true),
choice_param("placement", {"general", "internal", "engine", "external", "external_ambient"}, "internal"),
number_param("range", -1.0, "m"),
number_param("offset_x", 0.0, "m"),
number_param("offset_y", 0.0, "m"),
number_param("offset_z", 0.0, "m"),
};
type.create = make_block<vehicle_sound>;
return type;
}
void register_cab_blocks(catalog &Catalog)
{
Catalog.add(cab_switch::describe());
Catalog.add(cab_lamp::describe());
Catalog.add(cab_gauge::describe(false));
Catalog.add(cab_gauge::describe(true));
Catalog.add(vehicle_sound::describe());
}
} // namespace vgraph

441
vehicle/graph/blocks/cab.h Normal file
View File

@@ -0,0 +1,441 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "vehicle/graph/graph_block.h"
#include <string>
#include <vector>
// cab controls and indicators. the blocks hold the logic and the values; the cab (TTrain) creates the animated
// submodels from their parameters and binds them to the values these blocks expose
namespace vgraph
{
// switch, button or lever of the cab. its behaviour and animation are defined in the graph, and its value
// is available to the other blocks
class cab_switch final : public block
{
public:
struct port
{
enum : std::size_t
{
value, // "pos": value of the current position, between min and max
index // number of the current position, from 0
};
};
struct param
{
enum : std::size_t
{
behaviour,
positions,
min,
max,
default_value,
spring,
labels,
animation,
step,
offset,
smoothing,
submodel,
key_inc,
key_dec,
command,
hw_name
};
};
enum class behaviour_type
{
bistable, // stays where it was put
monostable, // returns to the default position when released, e.g. a push button
multi // several positions; with the spring enabled it returns to the default position when released
};
enum class animation_type
{
rotate,
move
};
explicit cab_switch(block_setup const &Setup);
void update(frame &Frame) override;
std::size_t state_count() const override
{
return 1;
}
char const *state_name(std::size_t) const override
{
return "position";
}
double state_value(std::size_t) const override
{
return m_position;
}
// operations of the player, AI or hardware. they take effect in the next update
void increase();
void decrease();
void toggle();
void press();
void release();
void set_position(int Position);
// moves to the position with the value closest to the specified one, e.g. for hardware levers
void set_value(double Value);
int position() const
{
return m_position;
}
int position_count() const
{
return m_positioncount;
}
int default_position() const
{
return m_defaultposition;
}
double value_at(int Position) const;
behaviour_type behaviour() const
{
return m_behaviour;
}
bool spring() const
{
return m_spring;
}
// description of the specified position, from the labels parameter; empty if not specified
std::string label(int Position) const;
// animation of the submodel: offset + step * position, in degrees or millimetres
animation_type animation() const
{
return m_animation;
}
double step() const
{
return m_step;
}
double offset() const
{
return m_offset;
}
double smoothing() const
{
return m_smoothing;
}
std::string const &submodel() const
{
return m_submodel;
}
// bindings: keys, existing simulator command, name for the hardware desk
std::string const &key_increase() const
{
return m_keyincrease;
}
std::string const &key_decrease() const
{
return m_keydecrease;
}
std::string const &command() const
{
return m_command;
}
std::string const &hardware_name() const
{
return m_hardwarename;
}
static block_type describe();
private:
int clamp_position(int Position) const;
behaviour_type const m_behaviour;
int const m_positioncount;
double const m_min;
double const m_max;
int m_defaultposition{0};
bool const m_spring;
std::vector<std::string> m_labels;
animation_type const m_animation;
double const m_step;
double const m_offset;
double const m_smoothing;
std::string const m_submodel;
std::string const m_keyincrease;
std::string const m_keydecrease;
std::string const m_command;
std::string const m_hardwarename;
int m_position{0};
};
// indicator lamp. when the graph simulates low voltage circuits and the supply input is connected, the lamp lights
// only with enough voltage, and draws current from the supply
class cab_lamp final : public block
{
public:
struct port
{
enum : std::size_t
{
on,
supply
};
};
struct param
{
enum : std::size_t
{
color,
blink,
blink_period,
min_voltage,
power,
submodel
};
};
explicit cab_lamp(block_setup const &Setup);
void update(frame &Frame) override;
std::size_t state_count() const override
{
return 1;
}
char const *state_name(std::size_t) const override
{
return "lit";
}
double state_value(std::size_t) const override
{
return m_lit ? 1.0 : 0.0;
}
// stable address of the state, for TButton::AssignBool
bool const *lit_state() const
{
return &m_lit;
}
std::string const &submodel() const
{
return m_submodel;
}
static block_type describe();
private:
bool const m_supplied; // whether the supply input is connected
bool const m_blink;
double const m_blinkperiod;
double const m_minvoltage;
double const m_power;
std::string const m_submodel;
bool m_lit{false};
};
// needle gauge with one or two needles: voltmeter, ammeter, speedometer, pressure gauge
class cab_gauge final : public block
{
public:
struct port
{
enum : std::size_t
{
value,
value2
};
};
struct param
{
enum : std::size_t
{
min,
max,
unit,
angle_min,
angle_max,
smoothing,
submodel,
submodel2
};
};
cab_gauge(block_setup const &Setup, bool Twoneedles);
void update(frame &Frame) override;
std::size_t state_count() const override
{
return m_twoneedles ? 2 : 1;
}
char const *state_name(std::size_t Index) const override
{
return Index == 0 ? "value" : "value2";
}
double state_value(std::size_t Index) const override
{
return m_values[Index];
}
// stable addresses of the values shown by the needles, clamped to the scale, for TGauge::AssignFloat
float *value_state(std::size_t Needle)
{
return &m_values[Needle];
}
bool two_needles() const
{
return m_twoneedles;
}
double min() const
{
return m_min;
}
double max() const
{
return m_max;
}
double angle_min() const
{
return m_anglemin;
}
double angle_max() const
{
return m_anglemax;
}
double smoothing() const
{
return m_smoothing;
}
std::string const &submodel(std::size_t Needle) const
{
return Needle == 0 ? m_submodel : m_submodel2;
}
static block_type describe(bool Twoneedles);
private:
bool const m_twoneedles;
double const m_min;
double const m_max;
double const m_anglemin;
double const m_anglemax;
double const m_smoothing;
std::string const m_submodel;
std::string const m_submodel2;
float m_values[2]{0.f, 0.f};
};
// sound of the vehicle or of its cab. sounds of a graph vehicle are defined in the graph instead of the .mmd file
class vehicle_sound final : public block
{
public:
struct port
{
enum : std::size_t
{
play,
volume,
pitch
};
};
struct param
{
enum : std::size_t
{
file,
volume,
pitch,
loop,
placement,
range,
offset_x,
offset_y,
offset_z
};
};
// the same placements as sound_placement of the audio subsystem
enum class placement_type
{
general,
internal,
engine,
external,
external_ambient
};
explicit vehicle_sound(block_setup const &Setup);
void update(frame &Frame) override;
std::size_t state_count() const override
{
return 3;
}
char const *state_name(std::size_t Index) const override;
double state_value(std::size_t Index) const override;
bool playing() const
{
return m_playing;
}
// volume and pitch: parameter multiplied by the input
float volume() const
{
return m_volume;
}
float pitch() const
{
return m_pitch;
}
std::string const &file() const
{
return m_file;
}
bool loop() const
{
return m_loop;
}
placement_type placement() const
{
return m_placement;
}
double range() const
{
return m_range;
}
double offset_x() const
{
return m_offset[0];
}
double offset_y() const
{
return m_offset[1];
}
double offset_z() const
{
return m_offset[2];
}
static block_type describe();
private:
std::string const m_file;
double const m_basevolume;
double const m_basepitch;
bool const m_loop;
placement_type const m_placement;
double const m_range;
double const m_offset[3];
bool m_playing{false};
float m_volume{0.f};
float m_pitch{1.f};
};
} // namespace vgraph

View File

@@ -0,0 +1,625 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "vehicle/graph/graph_catalog.h"
#include <algorithm>
#include <cmath>
// generic logic and arithmetic blocks. boolean signals are stored as 0 and 1, and read as true above 0.5
namespace vgraph
{
namespace
{
// tolerance of the equality comparisons; switch positions and constants are compared, not results of long computations
double constexpr equality_tolerance{1e-6};
block_type make_type(std::string Id, std::string Name, std::string Description)
{
block_type type;
type.id = std::move(Id);
type.category = "logic";
type.name = std::move(Name);
type.description = std::move(Description);
type.origin = block_origin::primitive;
return type;
}
class logic_compare final : public block
{
public:
struct port
{
enum : std::size_t
{
a,
q
};
};
struct param
{
enum : std::size_t
{
op,
value
};
};
enum class operation
{
ne,
eq,
lt,
le,
gt,
ge
};
explicit logic_compare(block_setup const &Setup) : block(Setup), m_operation(static_cast<operation>(choice(Setup, param::op))), m_value(number(Setup, param::value)) {}
void update(frame &Frame) override
{
auto const a{get(Frame, port::a)};
auto result{false};
switch (m_operation)
{
case operation::ne:
result = std::abs(a - m_value) > equality_tolerance;
break;
case operation::eq:
result = std::abs(a - m_value) <= equality_tolerance;
break;
case operation::lt:
result = a < m_value;
break;
case operation::le:
result = a <= m_value + equality_tolerance;
break;
case operation::gt:
result = a > m_value;
break;
case operation::ge:
result = a >= m_value - equality_tolerance;
break;
}
set_bool(Frame, port::q, result);
}
static block_type describe()
{
auto type{make_type("logic.compare", "Compare", "Compares the input with a constant value.")};
type.ports = {signal_in("a", value_type::real), signal_out("q", value_type::boolean)};
type.params = {choice_param("op", {"ne", "eq", "lt", "le", "gt", "ge"}, "ne"), number_param("value", 0.0)};
type.create = make_block<logic_compare>;
return type;
}
private:
operation const m_operation;
double const m_value;
};
enum class gate
{
and_,
or_,
xor_,
nand_,
nor_
};
class logic_gate final : public block
{
public:
struct port
{
enum : std::size_t
{
a,
b,
q
};
};
logic_gate(block_setup const &Setup, gate const Gate) : block(Setup), m_gate(Gate) {}
void update(frame &Frame) override
{
auto const a{get_bool(Frame, port::a)};
auto const b{get_bool(Frame, port::b)};
auto result{false};
switch (m_gate)
{
case gate::and_:
result = a && b;
break;
case gate::or_:
result = a || b;
break;
case gate::xor_:
result = a != b;
break;
case gate::nand_:
result = false == (a && b);
break;
case gate::nor_:
result = false == (a || b);
break;
}
set_bool(Frame, port::q, result);
}
template <gate Gate_> static std::unique_ptr<block> create(block_setup const &Setup)
{
return std::make_unique<logic_gate>(Setup, Gate_);
}
template <gate Gate_> static block_type describe(std::string Id, std::string Name, double const Default)
{
// unconnected inputs default to the neutral value of the gate, so a gate can be used with one input
auto type{make_type(std::move(Id), std::move(Name), "Logic gate.")};
type.ports = {signal_in("a", value_type::boolean, Default), signal_in("b", value_type::boolean, Default, "", true), signal_out("q", value_type::boolean)};
type.create = create<Gate_>;
return type;
}
private:
gate const m_gate;
};
class logic_not final : public block
{
public:
struct port
{
enum : std::size_t
{
a,
q
};
};
explicit logic_not(block_setup const &Setup) : block(Setup) {}
void update(frame &Frame) override
{
set_bool(Frame, port::q, false == get_bool(Frame, port::a));
}
static block_type describe()
{
auto type{make_type("logic.not", "NOT", "Negation.")};
type.ports = {signal_in("a", value_type::boolean), signal_out("q", value_type::boolean)};
type.create = make_block<logic_not>;
return type;
}
};
// set-reset latch. it's deferred, so it can close loops, e.g. self-holding contactor circuits
class logic_sr final : public block
{
public:
struct port
{
enum : std::size_t
{
s,
r,
q
};
};
struct param
{
enum : std::size_t
{
reset_priority,
initial
};
};
explicit logic_sr(block_setup const &Setup) : block(Setup), m_resetpriority(boolean(Setup, param::reset_priority)), m_state(boolean(Setup, param::initial)) {}
void update(frame &Frame) override
{
auto const s{get_bool(Frame, port::s)};
auto const r{get_bool(Frame, port::r)};
if (s && r)
{
m_state = (false == m_resetpriority);
}
else if (s)
{
m_state = true;
}
else if (r)
{
m_state = false;
}
}
void commit(frame &Frame) override
{
set_bool(Frame, port::q, m_state);
}
std::size_t state_count() const override
{
return 1;
}
char const *state_name(std::size_t) const override
{
return "state";
}
double state_value(std::size_t) const override
{
return m_state ? 1.0 : 0.0;
}
static block_type describe()
{
auto type{make_type("logic.sr", "SR latch", "Set sets the output, reset clears it. The output changes in the next step, so the block can close loops.")};
type.deferred = true;
type.ports = {signal_in("s", value_type::boolean), signal_in("r", value_type::boolean, 0.0, "", true), signal_out("q", value_type::boolean)};
type.params = {boolean_param("reset_priority", true), boolean_param("initial", false)};
type.create = make_block<logic_sr>;
return type;
}
private:
bool const m_resetpriority;
bool m_state;
};
// on-delay (TON) and off-delay (TOF) timers
class logic_timer final : public block
{
public:
struct port
{
enum : std::size_t
{
a,
q
};
};
struct param
{
enum : std::size_t
{
time
};
};
logic_timer(block_setup const &Setup, bool const Ondelay) : block(Setup), m_ondelay(Ondelay), m_delay(std::max(0.0, number(Setup, param::time))) {}
void update(frame &Frame) override
{
auto const a{get_bool(Frame, port::a)};
if (a == m_ondelay)
{
m_elapsed = std::min(m_elapsed + Frame.dt, m_delay);
}
else
{
m_elapsed = 0.0;
}
auto const expired{m_elapsed >= m_delay};
m_output = (m_ondelay ? (a && expired) : (a || false == expired));
}
void commit(frame &Frame) override
{
set_bool(Frame, port::q, m_output);
}
std::size_t state_count() const override
{
return 1;
}
char const *state_name(std::size_t) const override
{
return "elapsed";
}
double state_value(std::size_t) const override
{
return m_elapsed;
}
template <bool Ondelay_> static std::unique_ptr<block> create(block_setup const &Setup)
{
return std::make_unique<logic_timer>(Setup, Ondelay_);
}
template <bool Ondelay_> static block_type describe()
{
auto type{Ondelay_ ? make_type("logic.ton", "On delay", "The output follows the input switching on after the specified time, and switching off immediately.")
: make_type("logic.tof", "Off delay", "The output follows the input switching on immediately, and switching off after the specified time.")};
type.deferred = true;
type.ports = {signal_in("a", value_type::boolean), signal_out("q", value_type::boolean)};
type.params = {number_param("time", 1.0, "s")};
type.create = create<Ondelay_>;
return type;
}
private:
bool const m_ondelay;
double const m_delay;
// for the on-delay: time the input is on; for the off-delay: time the input is off
// (both start expired for the off-delay, so the output is off until the input is switched on)
double m_elapsed{m_ondelay ? 0.0 : m_delay};
bool m_output{false};
};
// delays the signal by one step; the explicit way to close a loop
class logic_delay final : public block
{
public:
struct port
{
enum : std::size_t
{
a,
q
};
};
struct param
{
enum : std::size_t
{
initial
};
};
explicit logic_delay(block_setup const &Setup) : block(Setup), m_value(number(Setup, param::initial)) {}
void update(frame &Frame) override
{
m_value = get(Frame, port::a);
}
void commit(frame &Frame) override
{
set(Frame, port::q, m_value);
}
static block_type describe()
{
auto type{make_type("logic.delay", "Unit delay", "Passes the input to the output one step later. Use it to close loops.")};
type.deferred = true;
type.ports = {signal_in("a", value_type::real), signal_out("q", value_type::real)};
type.params = {number_param("initial", 0.0)};
type.create = make_block<logic_delay>;
return type;
}
private:
double m_value;
};
class logic_hysteresis final : public block
{
public:
struct port
{
enum : std::size_t
{
a,
q
};
};
struct param
{
enum : std::size_t
{
lo,
hi,
initial
};
};
explicit logic_hysteresis(block_setup const &Setup)
: block(Setup), m_low(number(Setup, param::lo)), m_high(number(Setup, param::hi)), m_state(boolean(Setup, param::initial))
{
}
void update(frame &Frame) override
{
auto const a{get(Frame, port::a)};
if (a >= m_high)
{
m_state = true;
}
else if (a <= m_low)
{
m_state = false;
}
set_bool(Frame, port::q, m_state);
}
static block_type describe()
{
auto type{make_type("logic.hyst", "Hysteresis", "Switches on when the input reaches the upper threshold, and off when it drops to the lower one.")};
type.ports = {signal_in("a", value_type::real), signal_out("q", value_type::boolean)};
type.params = {number_param("lo", 0.0), number_param("hi", 1.0), boolean_param("initial", false)};
type.create = make_block<logic_hysteresis>;
return type;
}
private:
double const m_low;
double const m_high;
bool m_state;
};
class logic_const final : public block
{
public:
struct port
{
enum : std::size_t
{
q
};
};
struct param
{
enum : std::size_t
{
value
};
};
explicit logic_const(block_setup const &Setup) : block(Setup), m_value(number(Setup, param::value)) {}
void update(frame &Frame) override
{
set(Frame, port::q, m_value);
}
static block_type describe()
{
auto type{make_type("logic.const", "Constant", "Constant value.")};
type.ports = {signal_out("q", value_type::real)};
type.params = {number_param("value", 1.0)};
type.create = make_block<logic_const>;
return type;
}
private:
double const m_value;
};
class logic_math final : public block
{
public:
struct port
{
enum : std::size_t
{
a,
b,
q
};
};
struct param
{
enum : std::size_t
{
op
};
};
enum class operation
{
add,
sub,
mul,
div,
min,
max
};
explicit logic_math(block_setup const &Setup) : block(Setup), m_operation(static_cast<operation>(choice(Setup, param::op))) {}
void update(frame &Frame) override
{
auto const a{get(Frame, port::a)};
auto const b{get(Frame, port::b)};
auto result{0.0};
switch (m_operation)
{
case operation::add:
result = a + b;
break;
case operation::sub:
result = a - b;
break;
case operation::mul:
result = a * b;
break;
case operation::div:
// division by zero gives zero rather than infinity, which would spread through the whole graph
result = (b != 0.0 ? a / b : 0.0);
break;
case operation::min:
result = std::min(a, b);
break;
case operation::max:
result = std::max(a, b);
break;
}
set(Frame, port::q, result);
}
static block_type describe()
{
auto type{make_type("logic.math", "Arithmetic", "Arithmetic operation on two inputs. Division by zero gives zero.")};
type.ports = {signal_in("a", value_type::real), signal_in("b", value_type::real, 1.0), signal_out("q", value_type::real)};
type.params = {choice_param("op", {"add", "sub", "mul", "div", "min", "max"}, "mul")};
type.create = make_block<logic_math>;
return type;
}
private:
operation const m_operation;
};
class logic_select final : public block
{
public:
struct port
{
enum : std::size_t
{
sel,
a,
b,
q
};
};
explicit logic_select(block_setup const &Setup) : block(Setup) {}
void update(frame &Frame) override
{
set(Frame, port::q, get_bool(Frame, port::sel) ? get(Frame, port::b) : get(Frame, port::a));
}
static block_type describe()
{
auto type{make_type("logic.select", "Select", "Passes input a when sel is off, and input b when sel is on.")};
type.ports = {signal_in("sel", value_type::boolean), signal_in("a", value_type::real), signal_in("b", value_type::real), signal_out("q", value_type::real)};
type.create = make_block<logic_select>;
return type;
}
};
} // namespace
void register_logic_blocks(catalog &Catalog)
{
Catalog.add(logic_compare::describe());
Catalog.add(logic_gate::describe<gate::and_>("logic.and", "AND", 1.0));
Catalog.add(logic_gate::describe<gate::or_>("logic.or", "OR", 0.0));
Catalog.add(logic_gate::describe<gate::xor_>("logic.xor", "XOR", 0.0));
Catalog.add(logic_gate::describe<gate::nand_>("logic.nand", "NAND", 1.0));
Catalog.add(logic_gate::describe<gate::nor_>("logic.nor", "NOR", 0.0));
Catalog.add(logic_not::describe());
Catalog.add(logic_sr::describe());
Catalog.add(logic_timer::describe<true>());
Catalog.add(logic_timer::describe<false>());
Catalog.add(logic_delay::describe());
Catalog.add(logic_hysteresis::describe());
Catalog.add(logic_const::describe());
Catalog.add(logic_math::describe());
Catalog.add(logic_select::describe());
}
} // namespace vgraph

View File

@@ -0,0 +1,49 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "vehicle/graph/graph_block.h"
#include "vehicle/graph/graph_catalog.h"
namespace vgraph
{
block::block(block_setup const &Setup) : m_type(Setup.type), m_slots(Setup.slots) {}
double block::number(block_setup const &Setup, std::size_t const Param)
{
return Setup.params[Param].number;
}
bool block::boolean(block_setup const &Setup, std::size_t const Param)
{
return Setup.params[Param].boolean;
}
std::string const &block::text(block_setup const &Setup, std::size_t const Param)
{
return Setup.params[Param].text;
}
int block::choice(block_setup const &Setup, std::size_t const Param)
{
auto const &choices{Setup.type.params[Param].choices};
auto const &value{Setup.params[Param].text};
for (std::size_t idx = 0; idx < choices.size(); ++idx)
{
if (choices[idx] == value)
{
return static_cast<int>(idx);
}
}
// the loader rejects values outside of the list, so this only happens with a broken catalog
return 0;
}
} // namespace vgraph

150
vehicle/graph/graph_block.h Normal file
View File

@@ -0,0 +1,150 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "vehicle/graph/graph_types.h"
#include <cstdint>
#include <memory>
#include <vector>
namespace vgraph
{
struct block_type;
// state of a physical connection. the output writes the forward value; every connected input adds its share
// of the back value to back_next, which becomes visible to the output in the next step. thanks to this one step lag
// the back channel never constrains the order of evaluation, and the result doesn't depend on the order of the inputs
struct link_state
{
double forward{0.0};
double back{0.0};
double back_next{0.0};
};
// data shared by all blocks of one graph instance during a single step
struct frame
{
double dt{0.0};
double time{0.0}; // time elapsed since the start of the instance, after this step
bool low_voltage{false}; // graph wide switch: simulate the low voltage circuits, or treat them as always powered
double *signals{nullptr};
std::uint8_t const *forced{nullptr}; // signal slots with value forced from outside, writes from blocks are ignored
link_state *links{nullptr};
};
// everything a block factory needs to create a block of the given node
struct block_setup
{
block_type const &type;
std::vector<param_value> const &params; // in the order of the type's parameter definitions
std::vector<int> const &slots; // in the order of the type's port definitions; signal slot or link index
std::vector<std::uint8_t> const &connected; // in the order of the type's port definitions
};
// base of all blocks. a block reads and writes its ports through slot indices resolved when the graph was compiled
class block
{
public:
explicit block(block_setup const &Setup);
virtual ~block() = default;
// called once per step in the order resolved from the connections
virtual void update(frame &Frame) = 0;
// called after all blocks were updated, by the blocks of types marked as deferred. a deferred block publishes its
// outputs here, so they become visible to other blocks in the next step; this is what allows feedback loops
virtual void commit(frame &) {}
// internal state shown by the inspector and written by the standalone runner, e.g. whether a lamp is lit
virtual std::size_t state_count() const
{
return 0;
}
virtual char const *state_name(std::size_t) const
{
return "";
}
virtual double state_value(std::size_t) const
{
return 0.0;
}
block_type const &type() const
{
return m_type;
}
protected:
// signal ports
double get(frame const &Frame, std::size_t Port) const
{
return Frame.signals[m_slots[Port]];
}
bool get_bool(frame const &Frame, std::size_t Port) const
{
return Frame.signals[m_slots[Port]] > 0.5;
}
void set(frame &Frame, std::size_t Port, double const Value) const
{
auto const slot{m_slots[Port]};
if (Frame.forced[slot] == 0)
{
Frame.signals[slot] = Value;
}
}
void set_bool(frame &Frame, std::size_t Port, bool const Value) const
{
set(Frame, Port, Value ? 1.0 : 0.0);
}
// physical inputs
double forward_in(frame const &Frame, std::size_t Port) const
{
return Frame.links[m_slots[Port]].forward;
}
void add_back(frame &Frame, std::size_t Port, double const Value) const
{
Frame.links[m_slots[Port]].back_next += Value;
}
// physical outputs
void set_forward(frame &Frame, std::size_t Port, double const Value) const
{
Frame.links[m_slots[Port]].forward = Value;
}
double back_out(frame const &Frame, std::size_t Port) const
{
return Frame.links[m_slots[Port]].back;
}
// whether the port has a connection; known when the block is created
static bool is_connected(block_setup const &Setup, std::size_t Port)
{
return Setup.connected[Port] != 0;
}
// parameters, read when the block is created
static double number(block_setup const &Setup, std::size_t Param);
static bool boolean(block_setup const &Setup, std::size_t Param);
static std::string const &text(block_setup const &Setup, std::size_t Param);
// index of the parameter's value in the list of choices of its definition
static int choice(block_setup const &Setup, std::size_t Param);
private:
block_type const &m_type;
std::vector<int> m_slots;
};
using block_factory = std::unique_ptr<block> (*)(block_setup const &);
template <class Block_> std::unique_ptr<block> make_block(block_setup const &Setup)
{
return std::make_unique<Block_>(Setup);
}
} // namespace vgraph

View File

@@ -0,0 +1,273 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "vehicle/graph/graph_catalog.h"
#include <nlohmann/json.hpp>
namespace vgraph
{
std::string_view to_string(block_origin const Origin)
{
switch (Origin)
{
case block_origin::cab:
return "cab";
case block_origin::simulator:
return "simulator";
case block_origin::extracted:
return "extracted";
case block_origin::native:
return "native";
case block_origin::interface_profile:
return "interface";
case block_origin::script:
return "script";
default:
return "primitive";
}
}
int block_type::port_index(std::string_view const Key) const
{
for (std::size_t idx = 0; idx < ports.size(); ++idx)
{
if (ports[idx].key == Key)
{
return static_cast<int>(idx);
}
}
return -1;
}
int block_type::param_index(std::string_view const Key) const
{
for (std::size_t idx = 0; idx < params.size(); ++idx)
{
if (params[idx].key == Key)
{
return static_cast<int>(idx);
}
}
return -1;
}
catalog const &catalog::get()
{
static catalog const instance{[]() {
catalog result;
register_logic_blocks(result);
register_cab_blocks(result);
return result;
}()};
return instance;
}
block_type const *catalog::find(std::string_view const Id) const
{
for (auto const &type : m_types)
{
if (type.id == Id)
{
return &type;
}
}
return nullptr;
}
void catalog::add(block_type Type)
{
m_types.emplace_back(std::move(Type));
}
namespace
{
nlohmann::json to_json(param_value const &Value)
{
switch (Value.type)
{
case param_type::boolean:
return Value.boolean;
case param_type::text:
case param_type::choice:
return Value.text;
default:
return Value.number;
}
}
} // namespace
std::string catalog::export_json() const
{
nlohmann::ordered_json root;
root["format"] = "maszyna-vehicle-graph-catalog";
root["version"] = 1;
root["graph_format"] = std::string{file_format};
root["graph_version"] = file_version;
auto &domains = (root["domains"] = nlohmann::ordered_json::array());
for (std::size_t idx = 0; idx < static_cast<std::size_t>(domain::count_); ++idx)
{
auto const &domaininfo{info(static_cast<domain>(idx))};
nlohmann::ordered_json item;
item["id"] = std::string{domaininfo.id};
item["physical"] = domaininfo.physical;
item["forward"] = std::string{domaininfo.forward};
item["forward_unit"] = std::string{domaininfo.forward_unit};
if (domaininfo.physical)
{
item["back"] = std::string{domaininfo.back};
item["back_unit"] = std::string{domaininfo.back_unit};
}
domains.push_back(std::move(item));
}
auto &blocks = (root["blocks"] = nlohmann::ordered_json::array());
for (auto const &type : m_types)
{
nlohmann::ordered_json item;
item["id"] = type.id;
item["category"] = type.category;
item["name"] = type.name;
item["description"] = type.description;
item["origin"] = std::string{to_string(type.origin)};
item["deferred"] = type.deferred;
auto &ports = (item["ports"] = nlohmann::ordered_json::array());
for (auto const &port : type.ports)
{
nlohmann::ordered_json portitem;
portitem["key"] = port.key;
portitem["direction"] = (port.direction == port_direction::in ? "in" : "out");
portitem["domain"] = std::string{info(port.dom).id};
if (port.dom == domain::signal)
{
portitem["type"] = std::string{to_string(port.type)};
}
if (false == port.unit.empty())
{
portitem["unit"] = port.unit;
}
if (port.direction == port_direction::in)
{
portitem["optional"] = port.optional;
if (port.dom == domain::signal)
{
portitem["default"] = port.default_value;
}
}
ports.push_back(std::move(portitem));
}
auto &params = (item["params"] = nlohmann::ordered_json::array());
for (auto const &param : type.params)
{
nlohmann::ordered_json paramitem;
paramitem["key"] = param.key;
paramitem["type"] = std::string{to_string(param.type)};
if (false == param.unit.empty())
{
paramitem["unit"] = param.unit;
}
paramitem["default"] = to_json(param.default_value);
if (param.type == param_type::choice)
{
paramitem["choices"] = param.choices;
}
params.push_back(std::move(paramitem));
}
blocks.push_back(std::move(item));
}
return root.dump(1, '\t');
}
port_def signal_in(std::string Key, value_type const Type, double const Default, std::string Unit, bool const Optional)
{
port_def result;
result.key = std::move(Key);
result.direction = port_direction::in;
result.dom = domain::signal;
result.type = Type;
result.unit = std::move(Unit);
result.optional = Optional;
result.default_value = Default;
return result;
}
port_def signal_out(std::string Key, value_type const Type, std::string Unit)
{
port_def result;
result.key = std::move(Key);
result.direction = port_direction::out;
result.dom = domain::signal;
result.type = Type;
result.unit = std::move(Unit);
return result;
}
port_def physical_in(std::string Key, domain const Domain, bool const Optional)
{
port_def result;
result.key = std::move(Key);
result.direction = port_direction::in;
result.dom = Domain;
result.optional = Optional;
return result;
}
port_def physical_out(std::string Key, domain const Domain)
{
port_def result;
result.key = std::move(Key);
result.direction = port_direction::out;
result.dom = Domain;
return result;
}
param_def number_param(std::string Key, double const Default, std::string Unit)
{
param_def result;
result.key = std::move(Key);
result.type = param_type::number;
result.unit = std::move(Unit);
result.default_value = param_value::make_number(Default);
return result;
}
param_def boolean_param(std::string Key, bool const Default)
{
param_def result;
result.key = std::move(Key);
result.type = param_type::boolean;
result.default_value = param_value::make_boolean(Default);
return result;
}
param_def text_param(std::string Key, std::string Default)
{
param_def result;
result.key = std::move(Key);
result.type = param_type::text;
result.default_value = param_value::make_text(std::move(Default));
return result;
}
param_def choice_param(std::string Key, std::vector<std::string> Choices, std::string Default)
{
param_def result;
result.key = std::move(Key);
result.type = param_type::choice;
result.choices = std::move(Choices);
result.default_value = param_value::make_choice(std::move(Default));
return result;
}
} // namespace vgraph

View File

@@ -0,0 +1,90 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "vehicle/graph/graph_block.h"
#include <string>
#include <string_view>
#include <vector>
namespace vgraph
{
// where the behaviour of a block comes from; shown by the editor
enum class block_origin : std::uint8_t
{
primitive, // generic building block of the graph
cab, // cab control or indicator
simulator, // wraps existing simulator code without changing it
extracted, // simulator code extracted from Mover, shared with the .fiz vehicles
native, // part of the simulator the graph connects to (vehicle body, couplers)
interface_profile, // standard interface between vehicles, or between the vehicle and the AI
script // lua function block
};
std::string_view to_string(block_origin Origin);
struct block_type
{
std::string id; // e.g. "logic.and"; stored in the .vhg files, never change it once released
std::string category;
std::string name;
std::string description;
block_origin origin{block_origin::primitive};
// outputs of a deferred block are published after the whole step, so connections leaving it don't take part
// in ordering the blocks, and loops passing through it are allowed
bool deferred{false};
std::vector<port_def> ports;
std::vector<param_def> params;
block_factory create{nullptr};
int port_index(std::string_view Key) const;
int param_index(std::string_view Key) const;
};
// registry of all block types known to the simulator. it's also exported for the external editor
class catalog
{
public:
static catalog const &get();
block_type const *find(std::string_view Id) const;
std::vector<block_type> const &types() const
{
return m_types;
}
// description of all block types and domains, for the editor
std::string export_json() const;
// used by the block registration functions
void add(block_type Type);
private:
catalog() = default;
std::vector<block_type> m_types;
};
// helpers for the definitions of block types
port_def signal_in(std::string Key, value_type Type, double Default = 0.0, std::string Unit = "", bool Optional = false);
port_def signal_out(std::string Key, value_type Type, std::string Unit = "");
port_def physical_in(std::string Key, domain Domain, bool Optional = false);
port_def physical_out(std::string Key, domain Domain);
param_def number_param(std::string Key, double Default, std::string Unit = "");
param_def boolean_param(std::string Key, bool Default);
param_def text_param(std::string Key, std::string Default = "");
param_def choice_param(std::string Key, std::vector<std::string> Choices, std::string Default);
// registration functions of the block families, called once when the catalog is built
void register_logic_blocks(catalog &Catalog);
void register_cab_blocks(catalog &Catalog);
} // namespace vgraph

View File

@@ -0,0 +1,282 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "vehicle/graph/graph_format.h"
#include <fstream>
#include <iterator>
#include <set>
#include <nlohmann/json.hpp>
namespace vgraph
{
namespace
{
using json = nlohmann::json;
void report(std::vector<diagnostic> &Diagnostics, severity const Level, std::string Node, std::string Message)
{
Diagnostics.push_back({Level, std::move(Node), std::move(Message)});
}
bool is_valid_id(std::string const &Id)
{
if (Id.empty())
{
return false;
}
return std::all_of(std::begin(Id), std::end(Id), [](char const Char) {
return (Char >= 'a' && Char <= 'z') || (Char >= 'A' && Char <= 'Z') || (Char >= '0' && Char <= '9') || Char == '_' || Char == '-';
});
}
// reads a json scalar as a parameter value. text values become choices later, if their definition says so
bool read_value(json const &Value, param_value &Result)
{
if (Value.is_boolean())
{
Result = param_value::make_boolean(Value.get<bool>());
return true;
}
if (Value.is_number())
{
Result = param_value::make_number(Value.get<double>());
return true;
}
if (Value.is_string())
{
Result = param_value::make_text(Value.get<std::string>());
return true;
}
return false;
}
void read_values(json const &Object, std::vector<named_value> &Values, std::vector<diagnostic> &Diagnostics, std::string const &Node, std::string const &What)
{
for (auto const &item : Object.items())
{
param_value value;
if (read_value(item.value(), value))
{
Values.emplace_back(item.key(), std::move(value));
}
else
{
report(Diagnostics, severity::error, Node, What + " \"" + item.key() + "\" has to be a number, a boolean or a text");
}
}
}
// splits "node.port" into its parts
bool split_endpoint(json const &Value, std::string &Node, std::string &Port)
{
if (false == Value.is_string())
{
return false;
}
auto const text{Value.get<std::string>()};
auto const dot{text.find('.')};
if (dot == std::string::npos || dot == 0 || dot + 1 == text.size())
{
return false;
}
Node = text.substr(0, dot);
Port = text.substr(dot + 1);
return true;
}
bool parse_document_(std::string const &Text, document &Document, std::vector<diagnostic> &Diagnostics)
{
auto const errorcount{std::count_if(std::begin(Diagnostics), std::end(Diagnostics), [](diagnostic const &Diagnostic) { return Diagnostic.level == severity::error; })};
// comments are allowed, to make hand editing of the files easier
auto const root = json::parse(Text, nullptr, false, true);
if (root.is_discarded() || false == root.is_object())
{
report(Diagnostics, severity::error, "", "the file isn't a valid json object");
return false;
}
if (root.value("format", std::string{}) != file_format)
{
report(Diagnostics, severity::error, "", "the file isn't a vehicle graph (missing \"format\": \"" + std::string{file_format} + "\")");
return false;
}
auto const version{root.value("version", 0)};
if (version != file_version)
{
report(Diagnostics, severity::error, "", "unsupported file version " + std::to_string(version) + ", expected " + std::to_string(file_version) +
(version < file_version ? "; open and save the file in the current editor to convert it" : ""));
return false;
}
if (root.contains("vehicle") && root["vehicle"].is_object())
{
Document.name = root["vehicle"].value("name", "");
}
if (root.contains("settings"))
{
auto const &settings = root["settings"];
if (settings.is_object())
{
for (auto const &item : settings.items())
{
if (item.key() == "low_voltage_simulation" && item.value().is_boolean())
{
Document.low_voltage_simulation = item.value().get<bool>();
}
else
{
report(Diagnostics, severity::warning, "", "unknown or malformed setting \"" + item.key() + "\" was ignored");
}
}
}
else
{
report(Diagnostics, severity::error, "", "\"settings\" has to be an object");
}
}
if (root.contains("body"))
{
if (root["body"].is_object())
{
read_values(root["body"], Document.body, Diagnostics, "", "body parameter");
}
else
{
report(Diagnostics, severity::error, "", "\"body\" has to be an object");
}
}
if (root.contains("profiles"))
{
if (root["profiles"].is_object())
{
for (auto const &item : root["profiles"].items())
{
if (item.value().is_number_integer())
{
Document.profiles.emplace_back(item.key(), item.value().get<int>());
}
else
{
report(Diagnostics, severity::error, "", "version of the interface profile \"" + item.key() + "\" has to be an integer");
}
}
}
else
{
report(Diagnostics, severity::error, "", "\"profiles\" has to be an object");
}
}
// nodes
if (false == root.contains("nodes") || false == root["nodes"].is_array())
{
report(Diagnostics, severity::error, "", "missing \"nodes\" array");
return false;
}
std::set<std::string> ids;
for (auto const &item : root["nodes"])
{
if (false == item.is_object())
{
report(Diagnostics, severity::error, "", "every entry of \"nodes\" has to be an object");
continue;
}
node_desc node;
node.id = item.value("id", "");
node.type = item.value("type", "");
node.title = item.value("title", "");
if (false == is_valid_id(node.id))
{
report(Diagnostics, severity::error, node.id, "node id has to be made of letters, digits, '_' and '-'");
continue;
}
if (false == ids.insert(node.id).second)
{
report(Diagnostics, severity::error, node.id, "duplicate node id");
continue;
}
if (node.type.empty())
{
report(Diagnostics, severity::error, node.id, "missing block type");
continue;
}
if (item.contains("params"))
{
if (item["params"].is_object())
{
read_values(item["params"], node.params, Diagnostics, node.id, "parameter");
}
else
{
report(Diagnostics, severity::error, node.id, "\"params\" has to be an object");
}
}
Document.nodes.emplace_back(std::move(node));
}
// connections
if (root.contains("connections"))
{
if (root["connections"].is_array())
{
for (auto const &item : root["connections"])
{
connection_desc connection;
if (false == item.is_object() || false == split_endpoint(item.value("from", json{}), connection.from_node, connection.from_port) ||
false == split_endpoint(item.value("to", json{}), connection.to_node, connection.to_port))
{
report(Diagnostics, severity::error, "", "malformed connection " + item.dump() + ", expected {\"from\": \"node.port\", \"to\": \"node.port\"}");
continue;
}
Document.connections.emplace_back(std::move(connection));
}
}
else
{
report(Diagnostics, severity::error, "", "\"connections\" has to be an array");
}
}
// "layout" holds the positions of the blocks in the editor and is of no interest to the simulator
return errorcount == std::count_if(std::begin(Diagnostics), std::end(Diagnostics), [](diagnostic const &Diagnostic) { return Diagnostic.level == severity::error; });
}
} // namespace
bool parse_document(std::string const &Text, document &Document, std::vector<diagnostic> &Diagnostics)
{
try
{
return parse_document_(Text, Document, Diagnostics);
}
catch (json::exception const &Error)
{
// values of unexpected type, e.g. a number where the id should be
report(Diagnostics, severity::error, "", std::string{"malformed file: "} + Error.what());
return false;
}
}
bool load_document(std::string const &Path, document &Document, std::vector<diagnostic> &Diagnostics)
{
std::ifstream file{Path, std::ios::binary};
if (false == file.is_open())
{
report(Diagnostics, severity::error, "", "can't open file \"" + Path + "\"");
return false;
}
std::string const text{std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
return parse_document(text, Document, Diagnostics);
}
} // namespace vgraph

View File

@@ -0,0 +1,58 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "vehicle/graph/graph_types.h"
#include <string>
#include <string_view>
#include <utility>
#include <vector>
namespace vgraph
{
using named_value = std::pair<std::string, param_value>;
struct node_desc
{
std::string id;
std::string type;
std::string title;
std::vector<named_value> params; // as stored in the file; checked against the catalog when the graph is compiled
};
struct connection_desc
{
std::string from_node;
std::string from_port;
std::string to_node;
std::string to_port;
};
// content of a .vhg file, before it's checked against the block catalog
struct document
{
std::string name;
// when enabled, blocks with low voltage ports simulate the voltages and currents of the control circuits.
// when disabled, low voltage connections are ignored and the apparatus behaves as if always powered
bool low_voltage_simulation{false};
std::vector<named_value> body; // parameters of the vehicle body (mass, dimensions, axles...); used by the simulator integration
std::vector<std::pair<std::string, int>> profiles; // standard interfaces used by the vehicle, with their versions
std::vector<node_desc> nodes;
std::vector<connection_desc> connections;
};
// parses the content of a .vhg file. problems are appended to the diagnostics; returns false on errors
bool parse_document(std::string const &Text, document &Document, std::vector<diagnostic> &Diagnostics);
// reads and parses the specified .vhg file
bool load_document(std::string const &Path, document &Document, std::vector<diagnostic> &Diagnostics);
} // namespace vgraph

View File

@@ -0,0 +1,92 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "vehicle/graph/graph_instance.h"
#include "vehicle/graph/graph_catalog.h"
namespace vgraph
{
graph_instance::graph_instance(std::shared_ptr<graph_template const> Template)
: m_template(std::move(Template)), m_signals(m_template->signal_defaults()), m_forced(m_signals.size(), 0), m_links(m_template->link_count())
{
auto const &nodes{m_template->nodes()};
m_blocks.reserve(nodes.size());
for (auto const &node : nodes)
{
block_setup const setup{*node.type, node.params, node.slots, node.connected};
m_blocks.emplace_back(node.type->create(setup));
}
m_order.reserve(nodes.size());
for (auto const nodeindex : m_template->order())
{
m_order.push_back(m_blocks[nodeindex].get());
if (nodes[nodeindex].type->deferred)
{
m_deferred.push_back(m_blocks[nodeindex].get());
}
}
// deferred blocks publish their initial state, so the blocks they feed don't see zeros in the first step
auto frame{make_frame(0.0)};
for (auto *item : m_deferred)
{
item->commit(frame);
}
}
frame graph_instance::make_frame(double const Deltatime)
{
frame result;
result.dt = Deltatime;
result.time = m_time;
result.low_voltage = m_template->low_voltage_simulation();
result.signals = m_signals.data();
result.forced = m_forced.data();
result.links = m_links.data();
return result;
}
void graph_instance::update(double const Deltatime)
{
m_time += Deltatime;
auto frame{make_frame(Deltatime)};
for (auto *item : m_order)
{
item->update(frame);
}
for (auto *item : m_deferred)
{
item->commit(frame);
}
for (auto &link : m_links)
{
link.back = link.back_next;
link.back_next = 0.0;
}
}
block *graph_instance::find_block(std::string_view const Id)
{
auto const nodeindex{m_template->find_node(Id)};
return (nodeindex >= 0 ? m_blocks[nodeindex].get() : nullptr);
}
void graph_instance::force(int const Slot, double const Value)
{
m_signals[Slot] = Value;
m_forced[Slot] = 1;
}
void graph_instance::release(int const Slot)
{
m_forced[Slot] = 0;
}
} // namespace vgraph

View File

@@ -0,0 +1,78 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "vehicle/graph/graph_block.h"
#include "vehicle/graph/graph_template.h"
#include <memory>
#include <string_view>
#include <vector>
namespace vgraph
{
// simulation state of the graph of a single vehicle
class graph_instance
{
public:
explicit graph_instance(std::shared_ptr<graph_template const> Template);
// advances the graph by the specified time. the order of evaluation is fixed, and there's no other source
// of time or randomness, so the same inputs always produce the same results
void update(double Deltatime);
graph_template const &definition() const
{
return *m_template;
}
double time() const
{
return m_time;
}
// block of the node with the specified index (see graph_template::nodes())
block &node_block(std::size_t Index)
{
return *m_blocks[Index];
}
block const &node_block(std::size_t Index) const
{
return *m_blocks[Index];
}
// block of the node with the specified id, or null
block *find_block(std::string_view Id);
double signal(int Slot) const
{
return m_signals[Slot];
}
// keeps the slot at the specified value regardless of what its block writes, until released
void force(int Slot, double Value);
void release(int Slot);
bool is_forced(int Slot) const
{
return m_forced[Slot] != 0;
}
private:
frame make_frame(double Deltatime);
std::shared_ptr<graph_template const> m_template;
std::vector<std::unique_ptr<block>> m_blocks; // in the order of the template's nodes
std::vector<block *> m_order; // blocks in the order of evaluation
std::vector<block *> m_deferred; // blocks publishing their outputs after the step
std::vector<double> m_signals;
std::vector<std::uint8_t> m_forced;
std::vector<link_state> m_links;
double m_time{0.0};
};
} // namespace vgraph

View File

@@ -0,0 +1,318 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "vehicle/graph/graph_standalone.h"
#include "vehicle/graph/graph_catalog.h"
#include "vehicle/graph/graph_instance.h"
#include "vehicle/graph/blocks/cab.h"
#include <cmath>
#include <cstdio>
#include <fstream>
#include <sstream>
// command line tools of the vehicle graph. they run without the rest of the simulator; the log service doesn't run
// in this mode, so the results are reported directly to the console
namespace vgraph
{
namespace
{
struct script_event
{
double time{0.0};
std::string operation;
std::string target;
double value{0.0};
int line{0};
};
bool load_script(std::string const &Path, std::vector<script_event> &Events)
{
std::ifstream file{Path};
if (false == file.is_open())
{
std::printf("can't open script file \"%s\"\n", Path.c_str());
return false;
}
std::string line;
int linenumber{0};
while (std::getline(file, line))
{
++linenumber;
auto const comment{line.find('#')};
if (comment != std::string::npos)
{
line.erase(comment);
}
std::istringstream stream{line};
script_event event;
event.line = linenumber;
if (false == static_cast<bool>(stream >> event.time))
{
// empty line
continue;
}
if (false == static_cast<bool>(stream >> event.operation >> event.target))
{
std::printf("%s:%d: expected: <time> <operation> <target> [value]\n", Path.c_str(), linenumber);
return false;
}
auto const needsvalue{event.operation == "set" || event.operation == "value" || event.operation == "force"};
if (needsvalue && false == static_cast<bool>(stream >> event.value))
{
std::printf("%s:%d: operation \"%s\" needs a value\n", Path.c_str(), linenumber, event.operation.c_str());
return false;
}
Events.push_back(event);
}
std::stable_sort(std::begin(Events), std::end(Events), [](script_event const &Left, script_event const &Right) { return Left.time < Right.time; });
return true;
}
bool apply_event(graph_instance &Instance, script_event const &Event)
{
if (Event.operation == "force" || Event.operation == "unforce")
{
auto const slot{Instance.definition().find_signal(Event.target)};
if (slot < 0)
{
std::printf("script line %d: unknown signal port \"%s\"\n", Event.line, Event.target.c_str());
return false;
}
if (Event.operation == "force")
{
Instance.force(slot, Event.value);
}
else
{
Instance.release(slot);
}
return true;
}
auto *control{dynamic_cast<cab_switch *>(Instance.find_block(Event.target))};
if (control == nullptr)
{
std::printf("script line %d: \"%s\" isn't a cab switch\n", Event.line, Event.target.c_str());
return false;
}
if (Event.operation == "press")
{
control->press();
}
else if (Event.operation == "release")
{
control->release();
}
else if (Event.operation == "toggle")
{
control->toggle();
}
else if (Event.operation == "inc")
{
control->increase();
}
else if (Event.operation == "dec")
{
control->decrease();
}
else if (Event.operation == "set")
{
control->set_position(static_cast<int>(std::lround(Event.value)));
}
else if (Event.operation == "value")
{
control->set_value(Event.value);
}
else
{
std::printf("script line %d: unknown operation \"%s\"\n", Event.line, Event.operation.c_str());
return false;
}
return true;
}
std::string format_number(double const Value)
{
char buffer[32];
// negative zero is written as zero, so equal results give equal files
std::snprintf(buffer, sizeof(buffer), "%.9g", Value == 0.0 ? 0.0 : Value);
return buffer;
}
} // namespace
int graph_catalog_standalone(std::string const &Output)
{
auto const text{catalog::get().export_json()};
if (Output.empty())
{
std::printf("%s\n", text.c_str());
return 0;
}
std::ofstream file{Output, std::ios::binary};
if (false == file.is_open())
{
std::printf("can't create file \"%s\"\n", Output.c_str());
return 1;
}
file << text << '\n';
std::printf("block catalog written to %s (%zu block types)\n", Output.c_str(), catalog::get().types().size());
return 0;
}
int graph_run_standalone(int const Argc, char *Argv[])
{
// -graph-run <file.vhg> [-script <events.txt>] [-o <results.csv>] [-dt <step>] [-t <duration>] [-every <steps>]
if (Argc < 3)
{
std::printf("usage: -graph-run <file.vhg> [-script <events.txt>] [-o <results.csv>] [-dt <step, s>] [-t <duration, s>] [-every <steps>]\n");
return 1;
}
std::string const input{Argv[2]};
std::string script;
std::string output;
double deltatime{0.01};
double duration{0.0};
int every{1};
for (int idx = 3; idx + 1 < Argc; idx += 2)
{
std::string const option{Argv[idx]};
std::string const value{Argv[idx + 1]};
if (option == "-script")
{
script = value;
}
else if (option == "-o")
{
output = value;
}
else if (option == "-dt")
{
deltatime = std::atof(value.c_str());
}
else if (option == "-t")
{
duration = std::atof(value.c_str());
}
else if (option == "-every")
{
every = std::max(1, std::atoi(value.c_str()));
}
else
{
std::printf("unknown option \"%s\"\n", option.c_str());
return 1;
}
}
if (deltatime <= 0.0)
{
std::printf("the step has to be positive\n");
return 1;
}
std::vector<diagnostic> diagnostics;
auto const graph{load_graph(input, diagnostics)};
for (auto const &entry : diagnostics)
{
std::printf("%s: %s\n", input.c_str(), to_string(entry).c_str());
}
if (graph == nullptr)
{
return 1;
}
std::printf("%s: %zu blocks, %zu signals, %zu links\n", input.c_str(), graph->nodes().size(), graph->signal_defaults().size(), graph->link_count());
std::vector<script_event> events;
if (false == script.empty() && false == load_script(script, events))
{
return 1;
}
if (duration <= 0.0 && false == events.empty())
{
// by default run a second past the last event
duration = events.back().time + 1.0;
}
if (duration <= 0.0)
{
return 0;
}
graph_instance instance{graph};
auto const signals{graph->signal_outputs()};
std::ostringstream results;
results << "time";
for (auto const &signal : signals)
{
results << ';' << signal.first;
}
for (std::size_t nodeindex = 0; nodeindex < graph->nodes().size(); ++nodeindex)
{
auto const &item{instance.node_block(nodeindex)};
for (std::size_t stateindex = 0; stateindex < item.state_count(); ++stateindex)
{
results << ';' << graph->nodes()[nodeindex].id << ':' << item.state_name(stateindex);
}
}
results << '\n';
auto const stepcount{static_cast<long long>(std::ceil(duration / deltatime - 1e-9))};
std::size_t nextevent{0};
for (long long step = 0; step < stepcount; ++step)
{
// events take effect at the beginning of the first step which starts at or after their time
auto const steptime{step * deltatime};
while (nextevent < events.size() && events[nextevent].time <= steptime + 1e-9)
{
if (false == apply_event(instance, events[nextevent]))
{
return 1;
}
++nextevent;
}
instance.update(deltatime);
if ((step + 1) % every != 0 && step + 1 != stepcount)
{
continue;
}
results << format_number((step + 1) * deltatime);
for (auto const &signal : signals)
{
results << ';' << format_number(instance.signal(signal.second));
}
for (std::size_t nodeindex = 0; nodeindex < graph->nodes().size(); ++nodeindex)
{
auto const &item{instance.node_block(nodeindex)};
for (std::size_t stateindex = 0; stateindex < item.state_count(); ++stateindex)
{
results << ';' << format_number(item.state_value(stateindex));
}
}
results << '\n';
}
if (output.empty())
{
std::printf("%s", results.str().c_str());
return 0;
}
std::ofstream file{output, std::ios::binary};
if (false == file.is_open())
{
std::printf("can't create file \"%s\"\n", output.c_str());
return 1;
}
file << results.str();
std::printf("%lld steps written to %s\n", stepcount, output.c_str());
return 0;
}
} // namespace vgraph

View File

@@ -0,0 +1,24 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <string>
namespace vgraph
{
// -graph-catalog [<file.json>]: writes the description of all block types, for the external editor.
// returns: 0 on success, 1 otherwise
int graph_catalog_standalone(std::string const &Output);
// -graph-run <file.vhg> [options]: checks the graph and runs it without the simulator, driven by a script of events.
// returns: 0 on success, 1 otherwise
int graph_run_standalone(int Argc, char *Argv[]);
} // namespace vgraph

View File

@@ -0,0 +1,417 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "vehicle/graph/graph_template.h"
#include "vehicle/graph/graph_catalog.h"
#include <functional>
#include <queue>
#include <unordered_map>
namespace vgraph
{
namespace
{
void report(std::vector<diagnostic> &Diagnostics, severity const Level, std::string Node, std::string Message)
{
Diagnostics.push_back({Level, std::move(Node), std::move(Message)});
}
std::string join_choices(std::vector<std::string> const &Choices)
{
std::string result;
for (auto const &choice : Choices)
{
if (false == result.empty())
{
result += ", ";
}
result += choice;
}
return result;
}
// checks a value read from the file against the parameter definition; text values become choices here
bool resolve_param(param_def const &Definition, param_value const &Value, param_value &Result, std::string &Problem)
{
switch (Definition.type)
{
case param_type::number:
{
if (Value.type != param_type::number)
{
Problem = "has to be a number";
return false;
}
Result = Value;
return true;
}
case param_type::boolean:
{
if (Value.type != param_type::boolean)
{
Problem = "has to be true or false";
return false;
}
Result = Value;
return true;
}
case param_type::text:
{
if (Value.type != param_type::text)
{
Problem = "has to be a text";
return false;
}
Result = Value;
return true;
}
case param_type::choice:
{
if (Value.type != param_type::text || std::find(std::begin(Definition.choices), std::end(Definition.choices), Value.text) == std::end(Definition.choices))
{
Problem = "has to be one of: " + join_choices(Definition.choices);
return false;
}
Result = param_value::make_choice(Value.text);
return true;
}
default:
{
Problem = "has unsupported type";
return false;
}
}
}
struct endpoint
{
int node{-1};
int port{-1};
};
} // namespace
std::shared_ptr<graph_template const> graph_template::compile(document const &Document, catalog const &Catalog, std::vector<diagnostic> &Diagnostics)
{
auto const errorcount{std::count_if(std::begin(Diagnostics), std::end(Diagnostics), [](diagnostic const &Diagnostic) { return Diagnostic.level == severity::error; })};
auto result{std::make_shared<graph_template>()};
result->m_name = Document.name;
result->m_lowvoltage = Document.low_voltage_simulation;
result->m_body = Document.body;
result->m_profiles = Document.profiles;
// nodes and their parameters
std::unordered_map<std::string, int> nodeindices;
std::unordered_map<std::string, bool> unresolvednodes; // nodes of unknown types, to avoid reporting their connections again
for (auto const &desc : Document.nodes)
{
auto const *type{Catalog.find(desc.type)};
if (type == nullptr)
{
report(Diagnostics, severity::error, desc.id, "unknown block type \"" + desc.type + "\"");
unresolvednodes.emplace(desc.id, true);
continue;
}
node_entry node;
node.id = desc.id;
node.title = desc.title;
node.type = type;
node.params.reserve(type->params.size());
for (auto const &definition : type->params)
{
node.params.push_back(definition.default_value);
}
for (auto const &param : desc.params)
{
auto const paramindex{type->param_index(param.first)};
if (paramindex < 0)
{
report(Diagnostics, severity::warning, desc.id, "unknown parameter \"" + param.first + "\" of block type \"" + type->id + "\" was ignored");
continue;
}
std::string problem;
if (false == resolve_param(type->params[paramindex], param.second, node.params[paramindex], problem))
{
report(Diagnostics, severity::error, desc.id, "parameter \"" + param.first + "\" " + problem);
}
}
nodeindices.emplace(node.id, static_cast<int>(result->m_nodes.size()));
result->m_nodes.emplace_back(std::move(node));
}
auto &nodes{result->m_nodes};
auto &signaldefaults{result->m_signaldefaults};
auto &linkcount{result->m_linkcount};
// outputs own their slots and links
for (auto &node : nodes)
{
node.slots.assign(node.type->ports.size(), -1);
node.connected.assign(node.type->ports.size(), 0);
for (std::size_t portindex = 0; portindex < node.type->ports.size(); ++portindex)
{
auto const &port{node.type->ports[portindex]};
if (port.direction != port_direction::out)
{
continue;
}
if (port.dom == domain::signal)
{
node.slots[portindex] = static_cast<int>(signaldefaults.size());
signaldefaults.push_back(0.0);
}
else
{
node.slots[portindex] = static_cast<int>(linkcount++);
}
}
}
// connections
std::vector<std::vector<endpoint>> sources(nodes.size());
for (std::size_t nodeindex = 0; nodeindex < nodes.size(); ++nodeindex)
{
sources[nodeindex].resize(nodes[nodeindex].type->ports.size());
}
std::vector<std::vector<int>> edges(nodes.size()); // ordering constraints: source node -> consumer node
bool lowvoltageignored{false};
for (auto const &connection : Document.connections)
{
auto const label{connection.from_node + "." + connection.from_port + " -> " + connection.to_node + "." + connection.to_port};
auto const fromlookup{nodeindices.find(connection.from_node)};
auto const tolookup{nodeindices.find(connection.to_node)};
if (fromlookup == nodeindices.end() || tolookup == nodeindices.end())
{
auto const &missing{fromlookup == nodeindices.end() ? connection.from_node : connection.to_node};
if (unresolvednodes.find(missing) == unresolvednodes.end())
{
report(Diagnostics, severity::error, "", "connection " + label + " refers to unknown node \"" + missing + "\"");
}
continue;
}
auto const fromnode{fromlookup->second};
auto const tonode{tolookup->second};
auto const &fromtype{*nodes[fromnode].type};
auto const &totype{*nodes[tonode].type};
auto const fromport{fromtype.port_index(connection.from_port)};
auto const toport{totype.port_index(connection.to_port)};
if (fromport < 0 || fromtype.ports[fromport].direction != port_direction::out)
{
report(Diagnostics, severity::error, connection.from_node, "connection " + label + ": \"" + connection.from_port + "\" isn't an output of block type \"" + fromtype.id + "\"");
continue;
}
if (toport < 0 || totype.ports[toport].direction != port_direction::in)
{
report(Diagnostics, severity::error, connection.to_node, "connection " + label + ": \"" + connection.to_port + "\" isn't an input of block type \"" + totype.id + "\"");
continue;
}
auto const fromdomain{fromtype.ports[fromport].dom};
auto const todomain{totype.ports[toport].dom};
if (fromdomain != todomain)
{
report(Diagnostics, severity::error, connection.to_node,
"connection " + label + " joins different domains: " + std::string{info(fromdomain).id} + " and " + std::string{info(todomain).id});
continue;
}
if (sources[tonode][toport].node >= 0)
{
report(Diagnostics, severity::error, connection.to_node, "input \"" + connection.to_port + "\" has more than one source; use a junction block to join them");
continue;
}
if (fromdomain == domain::low_voltage && false == result->m_lowvoltage)
{
lowvoltageignored = true;
}
sources[tonode][toport] = {fromnode, fromport};
nodes[fromnode].connected[fromport] = 1;
nodes[tonode].connected[toport] = 1;
if (false == fromtype.deferred)
{
edges[fromnode].push_back(tonode);
}
}
if (lowvoltageignored)
{
report(Diagnostics, severity::warning, "", "low voltage connections have no effect, because low voltage simulation is disabled in the graph settings");
}
// inputs read their sources, or slots of their own holding the default values
for (std::size_t nodeindex = 0; nodeindex < nodes.size(); ++nodeindex)
{
auto &node{nodes[nodeindex]};
for (std::size_t portindex = 0; portindex < node.type->ports.size(); ++portindex)
{
auto const &port{node.type->ports[portindex]};
if (port.direction != port_direction::in)
{
continue;
}
auto const &source{sources[nodeindex][portindex]};
if (source.node >= 0)
{
node.slots[portindex] = nodes[source.node].slots[source.port];
continue;
}
if (false == port.optional)
{
report(Diagnostics, severity::warning, node.id, "required input \"" + port.key + "\" isn't connected");
}
if (port.dom == domain::signal)
{
node.slots[portindex] = static_cast<int>(signaldefaults.size());
signaldefaults.push_back(port.default_value);
}
else
{
node.slots[portindex] = static_cast<int>(linkcount++);
}
}
}
// order of evaluation. ties are resolved by the order of nodes in the file, so the result is stable
std::vector<int> indegree(nodes.size(), 0);
for (auto const &targets : edges)
{
for (auto const target : targets)
{
++indegree[target];
}
}
std::priority_queue<int, std::vector<int>, std::greater<int>> ready;
for (std::size_t nodeindex = 0; nodeindex < nodes.size(); ++nodeindex)
{
if (indegree[nodeindex] == 0)
{
ready.push(static_cast<int>(nodeindex));
}
}
while (false == ready.empty())
{
auto const nodeindex{ready.top()};
ready.pop();
result->m_order.push_back(nodeindex);
for (auto const target : edges[nodeindex])
{
if (--indegree[target] == 0)
{
ready.push(target);
}
}
}
if (result->m_order.size() != nodes.size())
{
// strip nodes merely fed by a loop, so the report lists only the nodes the loops pass through
std::vector<bool> remaining(nodes.size(), false);
for (std::size_t nodeindex = 0; nodeindex < nodes.size(); ++nodeindex)
{
remaining[nodeindex] = (indegree[nodeindex] > 0);
}
bool changed{true};
while (changed)
{
changed = false;
for (std::size_t nodeindex = 0; nodeindex < nodes.size(); ++nodeindex)
{
if (false == remaining[nodeindex])
{
continue;
}
auto const feedsloop{std::any_of(std::begin(edges[nodeindex]), std::end(edges[nodeindex]), [&](int const Target) { return remaining[Target]; })};
if (false == feedsloop)
{
remaining[nodeindex] = false;
changed = true;
}
}
}
std::string loop;
for (std::size_t nodeindex = 0; nodeindex < nodes.size(); ++nodeindex)
{
if (remaining[nodeindex])
{
loop += (loop.empty() ? "" : ", ") + nodes[nodeindex].id;
}
}
report(Diagnostics, severity::error, "",
"connections form a loop without a deferred block (e.g. logic.sr, logic.delay, logic.ton), so the order of evaluation can't be resolved; nodes in the loop: " + loop);
}
auto const failed{errorcount != std::count_if(std::begin(Diagnostics), std::end(Diagnostics), [](diagnostic const &Diagnostic) { return Diagnostic.level == severity::error; })};
if (failed)
{
return nullptr;
}
return result;
}
int graph_template::find_node(std::string_view const Id) const
{
for (std::size_t idx = 0; idx < m_nodes.size(); ++idx)
{
if (m_nodes[idx].id == Id)
{
return static_cast<int>(idx);
}
}
return -1;
}
int graph_template::find_signal(std::string_view const Endpoint) const
{
auto const dot{Endpoint.find('.')};
if (dot == std::string_view::npos)
{
return -1;
}
auto const nodeindex{find_node(Endpoint.substr(0, dot))};
if (nodeindex < 0)
{
return -1;
}
auto const &node{m_nodes[nodeindex]};
auto const portindex{node.type->port_index(Endpoint.substr(dot + 1))};
if (portindex < 0 || node.type->ports[portindex].dom != domain::signal)
{
return -1;
}
return node.slots[portindex];
}
std::shared_ptr<graph_template const> load_graph(std::string const &Path, std::vector<diagnostic> &Diagnostics)
{
document graph;
if (false == load_document(Path, graph, Diagnostics))
{
return nullptr;
}
return graph_template::compile(graph, catalog::get(), Diagnostics);
}
std::vector<std::pair<std::string, int>> graph_template::signal_outputs() const
{
std::vector<std::pair<std::string, int>> result;
for (auto const &node : m_nodes)
{
for (std::size_t portindex = 0; portindex < node.type->ports.size(); ++portindex)
{
auto const &port{node.type->ports[portindex]};
if (port.direction == port_direction::out && port.dom == domain::signal)
{
result.emplace_back(node.id + "." + port.key, node.slots[portindex]);
}
}
}
return result;
}
} // namespace vgraph

View File

@@ -0,0 +1,102 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "vehicle/graph/graph_format.h"
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
namespace vgraph
{
struct block_type;
class catalog;
// graph checked against the catalog and resolved to flat arrays: node parameters in definition order, ports bound to
// signal slots or physical links, and the order of evaluation. it holds no simulation state and is shared by all
// vehicles of the same type
class graph_template
{
public:
struct node_entry
{
std::string id;
std::string title;
block_type const *type{nullptr};
std::vector<param_value> params; // in the order of the type's parameter definitions
std::vector<int> slots; // in the order of the type's port definitions: signal slot, or link index for physical ports
std::vector<std::uint8_t> connected; // in the order of the type's port definitions: whether the port has a connection
};
// checks the document and builds the template. problems are appended to the diagnostics; returns null on errors
static std::shared_ptr<graph_template const> compile(document const &Document, catalog const &Catalog, std::vector<diagnostic> &Diagnostics);
std::string const &name() const
{
return m_name;
}
bool low_voltage_simulation() const
{
return m_lowvoltage;
}
std::vector<node_entry> const &nodes() const
{
return m_nodes;
}
// node indices in the order of evaluation
std::vector<int> const &order() const
{
return m_order;
}
// initial values of all signal slots; for unconnected inputs these are the values the blocks will see
std::vector<double> const &signal_defaults() const
{
return m_signaldefaults;
}
std::size_t link_count() const
{
return m_linkcount;
}
std::vector<named_value> const &body() const
{
return m_body;
}
std::vector<std::pair<std::string, int>> const &profiles() const
{
return m_profiles;
}
// index of the node with the specified id, or -1
int find_node(std::string_view Id) const;
// signal slot of the specified port, given as "node.port", or -1 if there's no such signal port
int find_signal(std::string_view Endpoint) const;
// names of signal outputs in "node.port" form, with their slots, in the order of nodes and ports
std::vector<std::pair<std::string, int>> signal_outputs() const;
private:
std::string m_name;
bool m_lowvoltage{false};
std::vector<node_entry> m_nodes;
std::vector<int> m_order;
std::vector<double> m_signaldefaults;
std::size_t m_linkcount{0};
std::vector<named_value> m_body;
std::vector<std::pair<std::string, int>> m_profiles;
};
// loads the specified .vhg file and compiles it against the simulator's catalog.
// problems are appended to the diagnostics; returns null on errors
std::shared_ptr<graph_template const> load_graph(std::string const &Path, std::vector<diagnostic> &Diagnostics);
} // namespace vgraph

View File

@@ -0,0 +1,131 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "vehicle/graph/graph_types.h"
#include <algorithm>
#include <array>
namespace vgraph
{
namespace
{
std::array<domain_info, static_cast<std::size_t>(domain::count_)> const domains{{
{"signal", "value", "", "", "", false},
{"high_voltage", "voltage", "V", "current", "A", true},
{"low_voltage", "voltage", "V", "current", "A", true},
{"aux_ac", "voltage", "V", "power", "W", true},
{"drive", "demand", "", "power", "W", true},
{"mechanical", "torque", "Nm", "rotational speed", "rad/s", true},
{"traction", "force", "N", "velocity", "m/s", true},
{"air", "pressure", "bar", "flow", "", true},
{"brake_pipe", "pressure", "bar", "flow", "", true},
{"feed_pipe", "pressure", "bar", "flow", "", true},
}};
} // namespace
domain_info const &info(domain const Domain)
{
return domains[static_cast<std::size_t>(Domain)];
}
bool parse_domain(std::string_view const Text, domain &Domain)
{
for (std::size_t idx = 0; idx < domains.size(); ++idx)
{
if (domains[idx].id == Text)
{
Domain = static_cast<domain>(idx);
return true;
}
}
return false;
}
std::string_view to_string(value_type const Type)
{
switch (Type)
{
case value_type::boolean:
return "bool";
case value_type::integer:
return "int";
default:
return "float";
}
}
std::string_view to_string(param_type const Type)
{
switch (Type)
{
case param_type::boolean:
return "bool";
case param_type::text:
return "text";
case param_type::choice:
return "choice";
default:
return "number";
}
}
param_value param_value::make_number(double const Value)
{
param_value result;
result.type = param_type::number;
result.number = Value;
return result;
}
param_value param_value::make_boolean(bool const Value)
{
param_value result;
result.type = param_type::boolean;
result.boolean = Value;
return result;
}
param_value param_value::make_text(std::string Value)
{
param_value result;
result.type = param_type::text;
result.text = std::move(Value);
return result;
}
param_value param_value::make_choice(std::string Value)
{
param_value result;
result.type = param_type::choice;
result.text = std::move(Value);
return result;
}
bool has_errors(std::vector<diagnostic> const &Diagnostics)
{
return std::any_of(std::begin(Diagnostics), std::end(Diagnostics), [](diagnostic const &Diagnostic) { return Diagnostic.level == severity::error; });
}
std::string to_string(diagnostic const &Diagnostic)
{
std::string result{Diagnostic.level == severity::error ? "error" : "warning"};
if (false == Diagnostic.node.empty())
{
result += " [" + Diagnostic.node + "]";
}
result += ": " + Diagnostic.message;
return result;
}
} // namespace vgraph

133
vehicle/graph/graph_types.h Normal file
View File

@@ -0,0 +1,133 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
// vehicle graph: block based description of vehicle logic and physics, loaded from .vhg files
// in place of .fiz. the core of the graph depends only on the standard library and nlohmann json
// (the latter only in the .cpp files), so it can be built and tested without the rest of the simulator
namespace vgraph
{
// format identification of the .vhg (vehicle graph) files
inline constexpr std::string_view file_format{"maszyna-vehicle-graph"};
inline constexpr int file_version{2};
inline constexpr std::string_view file_extension{".vhg"};
// signal ports pass one value in one direction. physical ports pass a pair of values in opposite directions,
// e.g. voltage from the source towards the load and current from the load back towards the source
enum class domain : std::uint8_t
{
signal,
high_voltage, // U [V] forward, I [A] back
low_voltage, // U [V] forward, I [A] back; only simulated when the graph enables low voltage simulation
aux_ac, // U [V] forward, P [W] back
drive, // demand [0-1] forward, P [W] back
mechanical, // torque [Nm] forward, rotational speed [rad/s] back
traction, // force at the wheel rim [N] forward, velocity [m/s] back
air, // pressure [bar] forward, flow back
brake_pipe, // pressure [bar] forward, flow back
feed_pipe, // pressure [bar] forward, flow back
count_
};
enum class value_type : std::uint8_t
{
boolean,
integer,
real
};
enum class port_direction : std::uint8_t
{
in,
out
};
struct domain_info
{
std::string_view id;
std::string_view forward; // quantity passed from the output towards the inputs
std::string_view forward_unit;
std::string_view back; // quantity passed from the inputs back towards the output
std::string_view back_unit;
bool physical;
};
domain_info const &info(domain Domain);
bool parse_domain(std::string_view Text, domain &Domain);
std::string_view to_string(value_type Type);
enum class param_type : std::uint8_t
{
number,
boolean,
text,
choice
};
std::string_view to_string(param_type Type);
// value of a block parameter, as read from the file or taken from the catalog default
struct param_value
{
param_type type{param_type::number};
double number{0.0};
bool boolean{false};
std::string text; // also holds the choice id
static param_value make_number(double Value);
static param_value make_boolean(bool Value);
static param_value make_text(std::string Value);
static param_value make_choice(std::string Value);
};
struct port_def
{
std::string key;
port_direction direction{port_direction::in};
domain dom{domain::signal};
value_type type{value_type::real}; // signal ports only
std::string unit;
bool optional{false}; // inputs only; unconnected required inputs are reported as warnings
double default_value{0.0}; // signal inputs only; value seen by the block when the input isn't connected
};
struct param_def
{
std::string key;
param_type type{param_type::number};
std::string unit;
param_value default_value;
std::vector<std::string> choices; // choice parameters only, stable ascii ids
};
enum class severity : std::uint8_t
{
warning,
error
};
// problem found while loading or compiling a graph. the node is empty for problems of the whole file
struct diagnostic
{
severity level{severity::error};
std::string node;
std::string message;
};
bool has_errors(std::vector<diagnostic> const &Diagnostics);
std::string to_string(diagnostic const &Diagnostic);
} // namespace vgraph