Units

A few notes on units. As much as possible, the units used are completely arbitrary. I will refer to them as sim-units below. I have used inches at one time, then converted everything to 1/10 inches, and the simulator scales automatically. Units are used for track lengths, distances along tracks for sensors and trains, and length of trains.

The graphical units (for offsets and absolute positions) are screen pixels. Microsoft Windows allows units for coordinates to be scaled; this would be a worthwhile quick adjustment for future development. (This would allow defining a drawing area of say, 1000x500, and then scale to the available window.) For now, pixel coordinates are NOT scaled. However, simulator units for train and sensor positions are scaled to match the absolute track coordinates.

Configuration Files

As documented in the code, there are currently seven configuration files. These are hardcoded as constants at the top of simwin.cpp, currently all residing within a "configs" directory. All config files are read using the ConfigReader class; this means that they accept #-marked comments and blank lines, and yield vectors of ints from each line. Therefore, each of these config files has lines with whitespace separated fields.

First, 4 files for the Simulator class:

simsensors.txt
Fields: id, trackid, distance. Specify the sensorid, the trackid it resides on, and the distance from the zero-end on that track in sim-units. The id is how the outside API will reference the sensor.

# id trackid pos
0 2 670
1 9 160
2 1 180

simtracks.txt
Two required fields: id, length. Track IDs are only used internally, since these track segments are only relevant to the simulator. However, every other device refers to tracks by these IDs. Length is in simunits. There may be any number of additional fields, in pairs. These specify an end and the connecting track's id, for defining permanent connections (turnout connections do not need to be specified here).

# id length [end connecttrackid [end connecttrackid ...]]
1 840
2 870
3 380
4 350
5 310 1 2
6 600 0 2 1 3

simtrains.txt
Seven fields: carID, trainID, length, trackid, heading, distance, speedmultiplier. Trains are specified as distinct cars, actual trains are created as needed (so there is no need to define all cars for one train together, although it is advised for readability). Specify a track and distance (end of car that is closest to 0 on the track). Speed multiplier is used to adjust scale/dirtiness of the trains "real" speed. Currently, the equation is: (speed / speedmult) in TrainCar::move(). As with all other configuration fields, this currently must be an int.

# carid trainid length trackid heading closerdist [speedmult]
101 1 30 2 1 82 1
102 1 30 2 1 77 1
201 2 40 5 0 5 5

simturnouts.txt
Seven fields: id, rootid, rootend, pos_id, pos_end, neg_id, neg_end. See the documentation for the TurnOut class, basically root is the output of a turnout, pos is the end that is connected when the TurnOut is on(), and neg is connected when off(). Each end/id pair specifies the trackid and track end that is attached to that arm of the TurnOut.

#id rootid rootend posid posend negid negend
0 9 1 11 0 10 0
1 1 0 9 0 2 1

Next, 3 files for the Display classes:

displaysensors.txt
Five fields: id, trackid, dist, x-offset, y-offset. The first three fields correspond to simsensors.txt. Absolute pixel position is calculated by the graphical classes. The x and y offsets allow adjustments to place the sensor to one side or the other of the actual track so it is visible (a few pixels is usually sufficient)

#id trackid dist xoff yoff
0 2 670 0 5
1 9 160 0 5
2 1 180 0 5

displaytracks.txt
This is the most complex configuration file. Each line consists of 6 fields: id, startx, starty, endx, endy, simlength. These add a part (DisplayTrack::addPart()) to a display track object, allowing curves etc to be built up from several distinct lines. simlength is easiest to define for just one part of the Track, and leave the rest as zero. All simlengths for a trackID are added up and then distributed along the parts of the track fairly evenly. The order in which parts are defined matters: parts for a given ID will be traversed by a train in the order they are defined.

# id startx starty endx endy simlength
# 1-4 are the outer loop
1 20 190 20 150 840
1 20 150 60 60 0
1 60 60 150 20 0
1 150 20 450 20 0
2 450 320 150 320 870
2 150 320 60 280 0
2 60 280 20 190 0
3 620 170 620 190 380
3 620 190 580 280 0
3 580 280 490 320 0
3 490 320 450 320 0
4 450 20 490 20 350
4 490 20 580 60 0
4 580 60 620 150 0
4 620 150 620 170 0

displayturnouts.txt
Five fields: id, posx, posy, negx, negy. Simply defines x,y pixel coordinates for the two status indicators. The indicator at posx,posy will be green when the TurnOut is switch to pos (on()), and vice versa.

# id posx posy negx negy
0 170 290 172 302
1 26 190 15 195
2 445 27 440 12

That is the extent of the configuration files. Changes in the future might be to have an overall config file, containing the filenames of each of these, so that alternate configurations could easily be loaded at runtime. For now, renaming/swapping the configs directory has been sufficient.

Also, configuration files for other underlying settings might considered, such as the timer milliseconds or a random setting for turnout/sensor failure.