Merge branch 'MapWindRotation' into 'master'

Map wind rotation

Note: we'd like to generate a realistic course layout, that can vary from race to race (but not within a race, for now.) The generated layout must be sent through the API in the format given by the race.xml section of the AC35 Streaming Data Interface Specification. The AC35 Protocol (sections 31.4 and 31.5) specifies the requirements for a course:

*    First leg of the course (from start line to first mark) must be a reaching leg
*    Next legs are windward/leeward, and boats complete either two or three laps of this section
*    Final leg to finish line may be a reaching leg
*    A boat should take around 25 minutes to complete the course in the wind conditions at the start of the race (AC35 protocol, section 31.5)

You should assume that the windward/leeward marks and start/finish lines are always compounds of two marks.

Acceptance criteria:

 *   The layout must be sent over the API in a race.xml message, plus boat location messages for the marks as required, before any other boat location messages are sent.
 *   Each mark must be defined using boat "SourceID"s (see definition of race.xml) so their positions can be adjusted later.
 *   The course must meet the requirements given in the AC35 Protocol.
 *   The course limits should be set to clear all marks by at least several boat-lengths.
 *   The entire race area within the limits must be on the water.

See merge request !22
This commit is contained in:
Joseph Gardner
2017-08-17 13:50:21 +12:00
31 changed files with 2119 additions and 54 deletions
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Race>
<RaceID>5326</RaceID>
<RaceType>FLEET</RaceType>
<CreationTimeDate>2017-08-03T02:13:14+1200</CreationTimeDate>
<RaceStartTime Postpone="false" Time="2017-08-03T02:08:10+1200"/>
<Participants>
<Yacht SourceID="125"/>
</Participants>
<CompoundMarkSequence>
<Corner CompoundMarkID="1" SeqID="1" Rounding="SP" ZoneSize="3"/>
<Corner CompoundMarkID="2" SeqID="2" Rounding="Port" ZoneSize="3"/>
<Corner CompoundMarkID="4" SeqID="3" Rounding="Port" ZoneSize="3"/>
<Corner CompoundMarkID="3" SeqID="4" Rounding="Port" ZoneSize="3"/>
<Corner CompoundMarkID="4" SeqID="5" Rounding="Port" ZoneSize="3"/>
<Corner CompoundMarkID="5" SeqID="6" Rounding="SP" ZoneSize="3"/>
</CompoundMarkSequence>
<Course>
<CompoundMark CompoundMarkID="1" Name="Start Line">
<Mark SeqId="1" Name="PRO" TargetLat="32.296577" TargetLng="-64.854304" SourceID="101"/>
<Mark SeqId="2" Name="PIN" TargetLat="32.293771" TargetLng="-64.855242" SourceID="102"/>
</CompoundMark>
<CompoundMark CompoundMarkID="2" Name="Marker 1">
<Mark Name="Marker1" TargetLat="32.293039" TargetLng="-64.843983" SourceID="103"/>
</CompoundMark>
<CompoundMark CompoundMarkID="3" Name="Windward Gate">
<Mark Name="WGL" SeqId="1" TargetLat="32.28468" TargetLng="-64.850045" SourceID="104"/>
<Mark Name="WGR" SeqId="2" TargetLat="32.280164" TargetLng="-64.847591" SourceID="105"/>
</CompoundMark>
<CompoundMark CompoundMarkID="4" Name="Leeward Gate">
<Mark Name="LGL" SeqId="1" TargetLat="32.309693" TargetLng="-64.835249" SourceID="106"/>
<Mark Name="LGR" SeqId="2" TargetLat="32.308046" TargetLng="-64.831785" SourceID="107"/>
</CompoundMark>
<CompoundMark CompoundMarkID="5" Name="Finish Line">
<Mark Name="FL" SeqId="1" TargetLat="32.317379" TargetLng="-64.839291" SourceID="108"/>
<Mark Name="FR" SeqId="2" TargetLat="32.317257" TargetLng="-64.83626" SourceID="109"/>
</CompoundMark>
</Course>
<CourseLimit>
<Limit Lat="32.313922" Lon="-64.837168" SeqID="1"/>
<Limit Lat="32.317379" Lon="-64.839291" SeqID="2"/>
<Limit Lat="32.317911" Lon="-64.836996" SeqID="3"/>
<Limit Lat="32.317257" Lon="-64.83626" SeqID="4"/>
<Limit Lat="32.304273" Lon="-64.822834" SeqID="5"/>
<Limit Lat="32.279097" Lon="-64.841545" SeqID="6"/>
<Limit Lat="32.279604" Lon="-64.849871" SeqID="7"/>
<Limit Lat="32.289545" Lon="-64.854162" SeqID="8"/>
<Limit Lat="32.290198" Lon="-64.858711" SeqID="9"/>
<Limit Lat="32.297164" Lon="-64.856394" SeqID="10"/>
<Limit Lat="32.296148" Lon="-64.849184" SeqID="11"/>
</CourseLimit>
</Race>
@@ -2,8 +2,8 @@
<Race>
<RaceID>5326</RaceID>
<RaceType>FLEET</RaceType>
<CreationTimeDate>CREATION_TIME</CreationTimeDate>
<RaceStartTime Postpone="false" Time="START_TIME"/>
<CreationTimeDate>2017-08-03T02:13:14+1200</CreationTimeDate>
<RaceStartTime Postpone="false" Time="2017-08-03T02:08:10+1200"/>
<Participants>
<Yacht SourceID="126"/>
</Participants>
@@ -2,8 +2,8 @@
<Race>
<RaceID>5326</RaceID>
<RaceType>FLEET</RaceType>
<CreationTimeDate>CREATION_TIME</CreationTimeDate>
<RaceStartTime Postpone="false" Time="START_TIME"/>
<CreationTimeDate>2017-08-03T02:13:14+1200</CreationTimeDate>
<RaceStartTime Postpone="false" Time="2017-08-03T02:08:10+1200"/>
<Participants>
<Yacht SourceID="121"/>
<Yacht SourceID="122"/>
@@ -0,0 +1,6 @@
<jaxb:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
</jaxb:bindings>
@@ -0,0 +1,17 @@
<jxb:bindings version="1.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jxb:extensionBindingPrefixes="xjc">
<jxb:bindings schemaLocation="raceSchema.xsd" node="/xs:schema">
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName prefix="XML"/>
<jxb:anonymousTypeName prefix="XML"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
<jxb:globalBindings localScoping="toplevel"/>
</jxb:bindings>
</jxb:bindings>
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Race">
<xs:complexType>
<xs:sequence>
<xs:element name="RaceID" type="xs:int"/>
<xs:element name="RaceType" type="xs:string"/>
<xs:element name="CreationTimeDate" type="xs:string"/>
<xs:element name="RaceStartTime">
<xs:complexType>
<xs:attribute name="Postpone" type="xs:string" use="required"/>
<xs:attribute name="Time" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="Participants">
<xs:complexType>
<xs:sequence>
<xs:element name="Yacht" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="SourceID" type="xs:int" use="required"/>
<xs:attribute name="Entry" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CompoundMarkSequence">
<xs:complexType>
<xs:sequence>
<xs:element name="Corner" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="CompoundMarkID" type="xs:int" use="required"/>
<xs:attribute name="SeqID" type="xs:int" use="required"/>
<xs:attribute name="Rounding" type="xs:string" use="required"/>
<xs:attribute name="ZoneSize" type="xs:int" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Course">
<xs:complexType>
<xs:sequence>
<xs:element name="CompoundMark" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Mark" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="SeqId" type="xs:int"/>
<xs:attribute name="Name" type="xs:string" use="required"/>
<xs:attribute name="TargetLat" type="xs:double" use="required"/>
<xs:attribute name="TargetLng" type="xs:double" use="required"/>
<xs:attribute name="SourceID" type="xs:int" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="CompoundMarkID" type="xs:int" use="required"/>
<xs:attribute name="Name" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CourseLimit">
<xs:complexType>
<xs:sequence>
<xs:element name="Limit" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="Lat" type="xs:double" use="required"/>
<xs:attribute name="Lon" type="xs:double" use="required"/>
<xs:attribute name="SeqID" type="xs:int" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>