diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInEventTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInEventTest.java
new file mode 100755
index 00000000000..c3cd343db13
--- /dev/null
+++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInEventTest.java
@@ -0,0 +1,65 @@
+package com.sap.sailing.domain.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
+import com.sap.sailing.domain.tractracadapter.DomainFactory;
+import com.sap.sailing.domain.tractracadapter.RaceTracker;
+import com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl;
+
+public class MultipleClassesInEventTest {
+ private DomainFactory domainFactory;
+
+ @Before
+ public void setUp() {
+ domainFactory = new DomainFactoryImpl();
+ }
+
+ @Test
+ public void testLoadTwoRacesWithEqualEventNameButDifferentClasses() throws MalformedURLException, FileNotFoundException, URISyntaxException {
+ RaceTracker kiwotest1 = domainFactory
+ .createRaceTracker(
+ new URL(
+ "http://germanmaster.traclive.dk/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=cce678c8-97e6-11e0-9aed-406186cbf87c"),
+ new URI("tcp://germanmaster.traclive.dk:4400"), new URI("tcp://germanmaster.traclive.dk:4401"),
+ EmptyWindStore.INSTANCE);
+ RaceTracker kiwotest2 = domainFactory
+ .createRaceTracker(
+ new URL(
+ "http://germanmaster.traclive.dk/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=11290bd6-97e7-11e0-9aed-406186cbf87c"),
+ new URI("tcp://germanmaster.traclive.dk:4400"), new URI("tcp://germanmaster.traclive.dk:4401"),
+ EmptyWindStore.INSTANCE);
+ RaceTracker kiwotest3 = domainFactory
+ .createRaceTracker(
+ new URL(
+ "http://germanmaster.traclive.dk/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=39635b24-97e7-11e0-9aed-406186cbf87c"),
+ new URI("tcp://germanmaster.traclive.dk:4400"), new URI("tcp://germanmaster.traclive.dk:4401"),
+ EmptyWindStore.INSTANCE);
+ RaceTracker weym470may112014_2 = domainFactory
+ .createRaceTracker(
+ new URL(
+ "http://germanmaster.traclive.dk/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=04498426-7dfd-11e0-8236-406186cbf87c"),
+ new URI("tcp://germanmaster.traclive.dk:4400"), new URI("tcp://germanmaster.traclive.dk:4401"),
+ EmptyWindStore.INSTANCE);
+
+ assertEquals("STG", kiwotest1.getEvent().getBoatClass().getName());
+ assertEquals("505", kiwotest2.getEvent().getBoatClass().getName());
+ assertEquals("49er", kiwotest3.getEvent().getBoatClass().getName());
+ assertEquals("STG", weym470may112014_2.getEvent().getBoatClass().getName());
+ assertSame(weym470may112014_2.getEvent(), kiwotest1.getEvent());
+ assertNotSame(kiwotest1.getEvent(), kiwotest2.getEvent());
+ assertNotSame(kiwotest1.getEvent(), kiwotest3.getEvent());
+ assertNotSame(kiwotest2.getEvent(), kiwotest3.getEvent());
+ }
+}
diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java
index 8bb08afc795..f4e232b2603 100755
--- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java
+++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java
@@ -24,8 +24,12 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.TrackedEvent;
+import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.WindStore;
+import com.sap.sailing.domain.tracking.WindTrack;
+import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl;
+import com.sap.sailing.domain.tractracadapter.impl.RaceCourseReceiver;
import com.tractrac.clientmodule.Competitor;
import com.tractrac.clientmodule.CompetitorClass;
import com.tractrac.clientmodule.ControlPoint;
@@ -70,9 +74,34 @@ public interface DomainFactory {
/**
* Creates an {@link com.sap.sailing.domain.base.Event event} from a
* TracTrac event description. It doesn't have {@link RaceDefinition}s yet.
+ * A new {@link com.sap.sailing.domain.base.Event} is created if no event by
+ * an equal name with a boat class with an equal name as the event's
+ * boat class exists yet.
*/
com.sap.sailing.domain.base.Event createEvent(Event event);
+ /**
+ * Creates a race tracked for the specified URL/URIs and starts receiving all available existing and future push
+ * data from there. Receiving continues until {@link RaceTracker#stop()} is called.
+ *
+ *
+ * A race tracker uses the paramURL for the TracTrac Java client to register for push data about one
+ * race. The {@link RaceDefinition} for that race, however, isn't created until the {@link Course} has been
+ * received. Therefore, the {@link RaceCourseReceiver} will create the {@link RaceDefinition} and will add it to the
+ * {@link com.sap.sailing.domain.base.Event}.
+ *
+ * + * The link to the {@link RaceDefinition} is created in the {@link DomainFactory} when the + * {@link RaceCourseReceiver} creates the {@link TrackedRace} object. Starting then, the {@link DomainFactory} will + * respond with the {@link RaceDefinition} when its {@link DomainFactory#getRace(Event)} is called with the TracTrac + * {@link Event} as argument that is used for its tracking. + *
+ *
+ * @param windStore
+ * Provides the capability to obtain the {@link WindTrack}s for the different wind sources. A trivial
+ * implementation is {@link EmptyWindStore} which simply provides new, empty tracks. This is always
+ * available but loses track of the wind, e.g., during server restarts.
+ */
RaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, WindStore windStore) throws MalformedURLException,
FileNotFoundException, URISyntaxException;
diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java
index cc9a3b5ad15..6d487d75d7d 100755
--- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java
+++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java
@@ -61,6 +61,7 @@ import com.sap.sailing.domain.tractracadapter.JSONService;
import com.sap.sailing.domain.tractracadapter.RaceTracker;
import com.sap.sailing.domain.tractracadapter.Receiver;
import com.sap.sailing.domain.tractracadapter.ReceiverType;
+import com.sap.sailing.util.Util.Pair;
import com.tractrac.clientmodule.CompetitorClass;
import com.tractrac.clientmodule.ControlPoint;
import com.tractrac.clientmodule.Race;
@@ -99,10 +100,10 @@ public class DomainFactoryImpl implements DomainFactory {
private final Map