Merge branch 'master' into dataMining

Conflicts:
	java/com.sap.sailing.gwt.ui/SailingGWT.launch
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java
This commit is contained in:
Lennart Hensler committed 2013-11-05 17:02:44 +01:00
commit 93594fa380
55 files changed
+65103 -434

No files matched your search

+9 -4
View File
@@ -12,8 +12,8 @@ find_project_home ()
PARENT_DIR=`cd $1/..;pwd`
OUTPUT=$(find_project_home $PARENT_DIR)
if [ "$OUTPUT" = "" ] && [ -d "$PARENT_DIR/code" ] && [ -d "$PARENT_DIR/code/.git" ]; then
OUTPUT="$PARENT_DIR/code"
if [ "$OUTPUT" = "" ] && [ -d "$PARENT_DIR/$CODE_DIRECTORY" ] && [ -d "$PARENT_DIR/$CODE_DIRECTORY/.git" ]; then
OUTPUT="$PARENT_DIR/$CODE_DIRECTORY"
fi
echo $OUTPUT
return 0
@@ -329,8 +329,12 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
extra="$extra -P no-debug.without-proxy"
fi
echo "Using following command: mvn $extra -fae -s $MAVEN_SETTINGS $clean install"
mvn $extra -fae -s $MAVEN_SETTINGS $clean install 2>&1 | tee $START_DIR/build.log
# make sure to honour the service configuration
# needed to make sure that tests use the right servers
APP_PARAMETERS="-Dmongo.host=$MONGODB_HOST -Dmongo.port=$MONGODB_PORT -Dexpedition.udp.port=$EXPEDITION_PORT -Dreplication.exchangeHost=$REPLICATION_HOST -Dreplication.exchangeName=$REPLICATION_CHANNEL"
echo "Using following command: mvn $extra -DargLine=\"$APP_PARAMETERS\" -fae -s $MAVEN_SETTINGS $clean install"
mvn $extra -DargLine="$APP_PARAMETERS" -fae -s $MAVEN_SETTINGS $clean install 2>&1 | tee $START_DIR/build.log
if [ $gwtcompile -eq 1 ]; then
# Now move back the backup .gwt.xml files before they were (maybe) patched
@@ -393,6 +397,7 @@ if [[ "$@" == "install" ]] || [[ "$@" == "all" ]]; then
cp -v $PROJECT_HOME/java/target/start $ACDIR/
cp -v $PROJECT_HOME/java/target/stop $ACDIR/
cp -v $PROJECT_HOME/java/target/status $ACDIR/
cp -v $PROJECT_HOME/java/target/shouldIBuildOrShouldIGo.sh $ACDIR/
if [ ! -f "$ACDIR/env.sh" ]; then
cp -v $PROJECT_HOME/java/target/env.sh $ACDIR/
File diff suppressed because it is too large. Load diff
@@ -166,62 +166,10 @@ public class DeclinationStore {
Calendar cal = new GregorianCalendar(year, month, /* dayOfMonth */ 1);
TimePoint timePoint = new MillisecondsTimePoint(cal.getTimeInMillis());
for (double lat = 0; lat < 90; lat += grid) {
System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat);
for (double lng = 0; lng < 180; lng += grid) {
Position point = new DegreePosition(lat, lng);
Declination existingDeclinationRecord;
synchronized (storedDeclinations) {
existingDeclinationRecord = storedDeclinations.get(point);
}
if (existingDeclinationRecord == null
|| DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord
.getPosition().getDistance(point), timePoint, existingDeclinationRecord
.getTimePoint()) > 0.1) {
// less than ~6 nautical miles and/or ~.6 months off
fetchAndAppendDeclination(timePoint, point, importer, out);
}
}
for (double lng = -grid; lng > -180; lng -= grid) {
Position point = new DegreePosition(lat, lng);
Declination existingDeclinationRecord;
synchronized (storedDeclinations) {
existingDeclinationRecord = storedDeclinations.get(point);
}
if (existingDeclinationRecord == null
|| DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord
.getPosition().getDistance(point), timePoint, existingDeclinationRecord
.getTimePoint()) > 0.1) {
// less than ~6 nautical miles and/or ~.6 months off
fetchAndAppendDeclination(timePoint, point, importer, out);
}
}
fetchAndAppendDeclinationForLatitude(grid, importer, year, storedDeclinations, out, month, timePoint, lat);
}
for (double lat = -grid; lat > -90; lat -= grid) {
System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat);
for (double lng = 0; lng < 180; lng += grid) {
Position point = new DegreePosition(lat, lng);
Declination existingDeclinationRecord;
synchronized (storedDeclinations) {
existingDeclinationRecord = storedDeclinations.get(point);
}
if (DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point),
timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) {
// less than ~6 nautical miles and/or ~.6 months off
fetchAndAppendDeclination(timePoint, point, importer, out);
}
}
for (double lng = -grid; lng > -180; lng -= grid) {
Position point = new DegreePosition(lat, lng);
Declination existingDeclinationRecord;
synchronized (storedDeclinations) {
existingDeclinationRecord = storedDeclinations.get(point);
}
if (DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point),
timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) {
// less than ~6 nautical miles and/or ~.6 months off
fetchAndAppendDeclination(timePoint, point, importer, out);
}
}
fetchAndAppendDeclinationForLatitude(grid, importer, year, storedDeclinations, out, month, timePoint, lat);
}
out.close();
}
@@ -229,6 +177,33 @@ public class DeclinationStore {
}
}
private void fetchAndAppendDeclinationForLatitude(double grid, NOAAImporter importer, int year,
QuadTree<Declination> storedDeclinations, Writer out, int month, TimePoint timePoint, double lat)
throws IOException {
System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat);
for (double lng = 0; lng < 180; lng += grid) {
fetchAndAppendDeclination(importer, storedDeclinations, out, timePoint, lat, lng);
}
for (double lng = -grid; lng > -180; lng -= grid) {
fetchAndAppendDeclination(importer, storedDeclinations, out, timePoint, lat, lng);
}
}
private void fetchAndAppendDeclination(NOAAImporter importer, QuadTree<Declination> storedDeclinations, Writer out,
TimePoint timePoint, double lat, double lng) throws IOException {
Position point = new DegreePosition(lat, lng);
final Declination existingDeclinationRecord;
synchronized (storedDeclinations) {
existingDeclinationRecord = storedDeclinations.get(point);
}
if (existingDeclinationRecord == null
|| DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point),
timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) {
// less than ~6 nautical miles and/or ~.6 months off
fetchAndAppendDeclination(timePoint, point, importer, out);
}
}
/**
* Launches the importer, writing to resources/declination-year.txt (where "year" represents the year for which the
* values are stored in the file) the declinations downloaded online for the years <code>args[0]</code> to
@@ -476,7 +476,8 @@ public class ClientParamsPHP {
}
public Race getRace() {
return new Race(UUID.fromString(properties.get("RaceID")));
final String raceId = properties.get("RaceID");
return raceId == null ? null : new Race(UUID.fromString(raceId));
}
public Event getEvent() {
@@ -284,41 +284,47 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
final ClientParamsPHP clientParams;
try {
clientParams = new ClientParamsPHP(paramURL, new InputStreamReader(paramURL.openStream()));
List<Pair<com.sap.sailing.domain.base.ControlPoint, NauticalSide>> newCourseControlPointsWithPassingSide = getControlPointsWithPassingSide(clientParams,
new ControlPointProducer<com.sap.sailing.domain.base.ControlPoint>() {
@Override
public com.sap.sailing.domain.base.ControlPoint produceControlPoint(TracTracControlPoint ttControlPoint) {
return domainFactory.getOrCreateControlPoint(ttControlPoint);
}
});
if (getRaces() == null || getRaces().isEmpty()) {
// create race definition / tracked race and add to event
final String raceName = clientParams.getRace().getName();
logger.log(Level.INFO, "Found data for non-existing race "+raceName+" in "+paramURL+". Creating RaceDefinition.");
final Iterable<Competitor> competitors = getCompetitors(clientParams);
final Iterable<com.sap.sailing.domain.tractracadapter.impl.ClientParamsPHP.Competitor> competitorsInClientParams = clientParams.getCompetitors();
List<Pair<TracTracControlPoint, NauticalSide>> ttControlPointsAndPassingSide = getControlPointsWithPassingSide(clientParams,
new ControlPointProducer<TracTracControlPoint>() {
@Override
public TracTracControlPoint produceControlPoint(TracTracControlPoint ttControlPoint) {
return ttControlPoint;
if (clientParams.getRace() != null) {
List<Pair<com.sap.sailing.domain.base.ControlPoint, NauticalSide>> newCourseControlPointsWithPassingSide = getControlPointsWithPassingSide(
clientParams, new ControlPointProducer<com.sap.sailing.domain.base.ControlPoint>() {
@Override
public com.sap.sailing.domain.base.ControlPoint produceControlPoint(
TracTracControlPoint ttControlPoint) {
return domainFactory.getOrCreateControlPoint(ttControlPoint);
}
});
if (getRaces() == null || getRaces().isEmpty()) {
// create race definition / tracked race and add to event
final String raceName = clientParams.getRace().getName();
logger.log(Level.INFO, "Found data for non-existing race " + raceName + " in " + paramURL
+ ". Creating RaceDefinition.");
final Iterable<Competitor> competitors = getCompetitors(clientParams);
final Iterable<com.sap.sailing.domain.tractracadapter.impl.ClientParamsPHP.Competitor> competitorsInClientParams = clientParams
.getCompetitors();
List<Pair<TracTracControlPoint, NauticalSide>> ttControlPointsAndPassingSide = getControlPointsWithPassingSide(
clientParams, new ControlPointProducer<TracTracControlPoint>() {
@Override
public TracTracControlPoint produceControlPoint(TracTracControlPoint ttControlPoint) {
return ttControlPoint;
}
});
Course course = domainFactory.createCourse(clientParams.getRace().getDefaultRoute()
.getDescription(), ttControlPointsAndPassingSide);
List<Sideline> sidelines = domainFactory.createSidelines(clientParams.getRace().getMetadata(),
clientParams.getEvent().getControlPointList());
DynamicTrackedRace trackedRace = domainFactory.getOrCreateRaceDefinitionAndTrackedRace(
getTrackedRegatta(), clientParams.getRace().getId(), raceName, competitors,
getDominantBoatClass(competitorsInClientParams), course, sidelines, windStore,
delayToLiveInMillis, WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, /* raceDefinitionSetToUpdate */
this, tracTracUpdateURI, tractracEvent.getId(), tracTracUsername, tracTracPassword);
if (simulator != null) {
simulator.setTrackedRace(trackedRace);
}
});
Course course = domainFactory.createCourse(clientParams.getRace().getDefaultRoute().getDescription(), ttControlPointsAndPassingSide);
List<Sideline> sidelines = domainFactory.createSidelines(
clientParams.getRace().getMetadata(), clientParams.getEvent().getControlPointList());
DynamicTrackedRace trackedRace = domainFactory.getOrCreateRaceDefinitionAndTrackedRace(
getTrackedRegatta(), clientParams.getRace().getId(), raceName, competitors,
getDominantBoatClass(competitorsInClientParams), course, sidelines, windStore, delayToLiveInMillis,
WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, /* raceDefinitionSetToUpdate */ this, tracTracUpdateURI,
tractracEvent.getId(), tracTracUsername, tracTracPassword);
if (simulator != null) {
simulator.setTrackedRace(trackedRace);
}
compareAndUpdateCourseIfNecessary(newCourseControlPointsWithPassingSide);
updateStartStopTimesAndLiveDelay(clientParams, simulator);
updateMarkPositionsIfNoPositionsReceivedYet(clientParams);
}
compareAndUpdateCourseIfNecessary(newCourseControlPointsWithPassingSide);
updateStartStopTimesAndLiveDelay(clientParams, simulator);
updateMarkPositionsIfNoPositionsReceivedYet(clientParams);
} catch (Exception e) {
logger.info("Exception " + e.getMessage() + " while trying to read clientparams.php for races " + getRaces());
logger.log(Level.SEVERE, "scheduleClientParamsPHPPoller.run", e);
@@ -5,7 +5,6 @@
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
<listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/>
<listEntry value="com.sap.sailing.gwt.ui.DataMining"/>
</listAttribute>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/AdminConsole.html"/>
@@ -14,7 +14,6 @@ import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
@@ -146,9 +145,9 @@ public class ReplicationPanel extends FlowPanel {
private void addReplication() {
AddReplicationDialog dialog = new AddReplicationDialog(null,
new DialogCallback<Triple<Pair<String, String>, Integer, Integer>>() {
new DialogCallback<Triple<Triple<String, String, String>, Integer, Integer>>() {
@Override
public void ok(final Triple<Pair<String, String>, Integer, Integer> masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber) {
public void ok(final Triple<Triple<String, String, String>, Integer, Integer> masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber) {
registeredMasters.removeRow(0);
registeredMasters.insertRow(0);
registeredMasters.setWidget(0, 0, new Label(stringMessages.loading()));
@@ -156,6 +155,7 @@ public class ReplicationPanel extends FlowPanel {
stopReplicationButton.setEnabled(false);
sailingService.startReplicatingFromMaster(masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber.getA().getA(),
masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber.getA().getB(),
masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber.getA().getC(),
masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber.getC(),
masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber.getB(), new AsyncCallback<Void>() {
@Override
@@ -275,17 +275,19 @@ public class ReplicationPanel extends FlowPanel {
* @author Axel Uhl (d043530)
*
*/
private class AddReplicationDialog extends DataEntryDialog<Triple<Pair<String, String>, Integer, Integer>> {
private class AddReplicationDialog extends DataEntryDialog<Triple<Triple<String, String, String>, Integer, Integer>> {
private final TextBox hostnameEntryField;
private final TextBox exchangeHostnameEntryField;
private final TextBox exchangenameEntryField;
private final IntegerBox messagingPortField;
private final IntegerBox servletPortField;
public AddReplicationDialog(final Validator<Triple<Pair<String, String>, Integer, Integer>> validator,
final DialogCallback<Triple<Pair<String, String>, Integer, Integer>> callback) {
public AddReplicationDialog(final Validator<Triple<Triple<String, String, String>, Integer, Integer>> validator,
final DialogCallback<Triple<Triple<String, String, String>, Integer, Integer>> callback) {
super(stringMessages.connect(), stringMessages.enterMaster(),
stringMessages.ok(), stringMessages.cancel(), validator, callback);
hostnameEntryField = createTextBox("localhost");
exchangeHostnameEntryField = createTextBox("localhost");
exchangenameEntryField = createTextBox("sapsailinganalytics");
messagingPortField = createIntegerBox(0, /* visible length */ 5);
servletPortField = createIntegerBox(8888, /* visibleLength */ 5);
@@ -297,19 +299,26 @@ public class ReplicationPanel extends FlowPanel {
*/
@Override
protected Widget getAdditionalWidget() {
Grid grid = new Grid(8, 2);
Grid grid = new Grid(10, 2);
grid.setWidget(0, 0, new Label(stringMessages.hostname()));
grid.setWidget(0, 1, hostnameEntryField);
grid.setWidget(1, 0, new Label(stringMessages.explainReplicationHostname()));
grid.setWidget(2, 0, new Label(stringMessages.exchangeName()));
grid.setWidget(2, 1, exchangenameEntryField);
grid.setWidget(3, 0, new Label(stringMessages.explainReplicationExchangeName()));
grid.setWidget(4, 0, new Label(stringMessages.messagingPortNumber()));
grid.setWidget(4, 1, messagingPortField);
grid.setWidget(5, 0, new Label(stringMessages.explainReplicationExchangePort()));
grid.setWidget(6, 0, new Label(stringMessages.servletPortNumber()));
grid.setWidget(6, 1, servletPortField);
grid.setWidget(7, 0, new Label(stringMessages.explainReplicationServletPort()));
grid.setWidget(2, 0, new Label(stringMessages.exchangeHost()));
grid.setWidget(2, 1, exchangeHostnameEntryField);
grid.setWidget(3, 0, new Label(stringMessages.explainExchangeHostName()));
grid.setWidget(4, 0, new Label(stringMessages.exchangeName()));
grid.setWidget(4, 1, exchangenameEntryField);
grid.setWidget(5, 0, new Label(stringMessages.explainReplicationExchangeName()));
grid.setWidget(6, 0, new Label(stringMessages.messagingPortNumber()));
grid.setWidget(6, 1, messagingPortField);
grid.setWidget(7, 0, new Label(stringMessages.explainReplicationExchangePort()));
grid.setWidget(8, 0, new Label(stringMessages.servletPortNumber()));
grid.setWidget(8, 1, servletPortField);
grid.setWidget(9, 0, new Label(stringMessages.explainReplicationServletPort()));
return grid;
}
@@ -320,9 +329,9 @@ public class ReplicationPanel extends FlowPanel {
}
@Override
protected Triple<Pair<String, String>, Integer, Integer> getResult() {
return new Triple<Pair<String, String>, Integer, Integer>(
new Pair<String, String>(hostnameEntryField.getText(), exchangenameEntryField.getText()),
protected Triple<Triple<String, String, String>, Integer, Integer> getResult() {
return new Triple<Triple<String, String, String>, Integer, Integer>(
new Triple<String, String, String>(exchangeHostnameEntryField.getText(), hostnameEntryField.getText(), exchangenameEntryField.getText()),
messagingPortField.getValue(), servletPortField.getValue());
}
}
@@ -239,7 +239,7 @@ public interface SailingService extends RemoteService {
ReplicationStateDTO getReplicaInfo();
void startReplicatingFromMaster(String masterName, String exchangeName, int servletPort, int messagingPort) throws Exception;
void startReplicatingFromMaster(String messagingHost, String masterHost, String exchangeName, int servletPort, int messagingPort) throws Exception;
void updateRaceDelayToLive(RegattaAndRaceIdentifier regattaAndRaceIdentifier, long delayToLiveInMs);
@@ -305,7 +305,7 @@ public interface SailingServiceAsync {
void getReplicaInfo(AsyncCallback<ReplicationStateDTO> callback);
void startReplicatingFromMaster(String masterName, String exchangeName, int servletPort, int messagingPort,
void startReplicatingFromMaster(String messagingHost, String masterName, String exchangeName, int servletPort, int messagingPort,
AsyncCallback<Void> callback);
void getEvents(AsyncCallback<List<EventDTO>> callback);
@@ -845,5 +845,7 @@ public interface StringMessages extends Messages {
String raceTimeUpwindTooltip();
String queryNotValidBecause();
String dataMining();
String exchangeHost();
String explainExchangeHostName();
String errorRunningDataMiningQuery();
}
@@ -684,7 +684,9 @@ firstRaceIsNonDiscardableCarryForward=Starts with non-discardable carry-forward
addReplicationMaster=Connect to replication master server
connect=Connect
connectToMaster=Connect to Master
explainReplicationHostname=Hostname where the replication master is running on. This is also the host where the messaging queue is running on.
exchangeHost=Messaging Hostname
explainExchangeHostName=Hostname where the messaging queue is running on.
explainReplicationHostname=Hostname where the replication master is running on.
explainReplicationExchangeName=The name of the exchange queue. It must be the same as configured in master.
explainReplicationExchangePort=The port of the messaging exchange queue. This is used for all data after initial load.
explainReplicationServletPort=Servlet port number that is used to connect to register this replica and receive initial load.
@@ -838,4 +840,4 @@ noDimensionToGroupBySelectedError=No dimension to group by is selected
noGrouperSelectedError=No grouper type is selected
queryNotValidBecause=No query possible, because
dataMining=Data Mining
errorRunningDataMiningQuery=An error occured running the query
errorRunningDataMiningQuery=An error occured running the query
@@ -681,9 +681,11 @@ importSuccess=Erfolg\nEs wurden {0} leaderboard group(s) und {1} leaderboard(s)
addReplicationMaster=Verbindung mit Master herstellen
connect=Verbinden
connectToMaster=Mit einem Master verbinden
explainReplicationHostname=Der Name oder die IP des Servers auf dem der Master und die Queue laufen.
exchangeHost=Queue Server
explainExchangeHostName=Name oder IP des Servers auf dem die Queue läuft.
explainReplicationHostname=Der Name oder die IP des Servers auf dem der Master Java Server läuft.
explainReplicationExchangeName=Name der Messaging Queue.
explainReplicationExchangePort=Port der Messaging Queue.
explainReplicationExchangePort=Port des Messaging Queue Servers.
explainReplicationServletPort=Servlet Port.
explainReplicasRegistered=Registrierte Replicas (dieser Server ist der Master):
explainConnectionsToMaster=Verbindungen zu einem Master (dieser Server ist eine Replica)
@@ -834,4 +836,4 @@ noDimensionToGroupBySelectedError=Keine Gruppierungs-Dimension ausgewählt ist
noGrouperSelectedError=Kein Gruppierungs-Typ ausgewählt ist
queryNotValidBecause=Keine Datenabfrage möglich, da
dataMining=Data Mining
errorRunningDataMiningQuery=Es ist ein Felher bei der Datenabfrage aufgetreten
errorRunningDataMiningQuery=Es ist ein Felher bei der Datenabfrage aufgetreten
@@ -2534,11 +2534,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
@Override
public void startReplicatingFromMaster(String masterName, String exchangeName, int servletPort, int messagingPort) throws IOException, ClassNotFoundException, InterruptedException {
public void startReplicatingFromMaster(String messagingHost, String masterHost, String exchangeName, int servletPort, int messagingPort) throws IOException, ClassNotFoundException, InterruptedException {
// the queue name must be always the same for this server. in order to achieve
// this we're using the unique server identifier
getReplicationService().startToReplicateFrom(
ReplicationFactory.INSTANCE.createReplicationMasterDescriptor(masterName, exchangeName, servletPort, messagingPort,
ReplicationFactory.INSTANCE.createReplicationMasterDescriptor(messagingHost, masterHost, exchangeName, servletPort, messagingPort,
getReplicationService().getServerIdentifier().toString()));
}
@@ -58,6 +58,10 @@ public class CourseAreaDescriptor {
return radius;
}
public double getRadiusInMeters() {
return (radius*1852.0);
}
public LatLng getCenterPos() {
return centerPos;
}
@@ -0,0 +1,89 @@
package com.sap.sailing.gwt.ui.simulator;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.Point;
import com.google.gwt.maps.client.events.center.CenterChangeMapEvent;
import com.google.gwt.maps.client.events.center.CenterChangeMapHandler;
import com.google.gwt.resources.client.ImageResource;
import com.sap.sailing.gwt.ui.client.shared.racemap.ImageTransformer;
import com.sap.sailing.gwt.ui.shared.racemap.CanvasOverlayV3;
public class ImageCanvasOverlay extends CanvasOverlayV3 {
private int canvasWidth;
private int canvasHeight;
private int oLeft;
private int oTop;
private double bearing = 0.0;
private ImageTransformer imgTrafo;
public ImageCanvasOverlay(MapWidget map, int zIndex, ImageResource img) {
super(map, zIndex);
canvasWidth = 100;
canvasHeight = 100;
if(getCanvas() != null) {
//setCanvasPosition(map.getAbsoluteLeft(), map.getAbsoluteTop());
getCanvas().setWidth(String.valueOf(canvasWidth));
getCanvas().setHeight(String.valueOf(canvasHeight));
getCanvas().setCoordinateSpaceWidth(canvasWidth);
getCanvas().setCoordinateSpaceHeight(canvasHeight);
}
imgTrafo = new ImageTransformer(img);
getMap().addCenterChangeHandler(new CenterChangeMapHandler() {
@Override
public void onEvent(CenterChangeMapEvent event) {
// TODO Auto-generated method stub
setPosition();
};
});
}
public void addToMap() {
super.addToMap();
}
public void setPosition() {
if (mapProjection != null) {
Point sw = mapProjection.fromLatLngToDivPixel(getMap().getBounds().getSouthWest());
Point ne = mapProjection.fromLatLngToDivPixel(getMap().getBounds().getNorthEast());
double pLeft = Math.min(sw.getX(), ne.getX()) - 25 + oLeft;
double pTop = Math.min(sw.getY(), ne.getY()) - 25 + oTop;
setCanvasPosition(pLeft, pTop);
}
}
public void setOffset(int offsetLeft, int offsetTop) {
this.oLeft = offsetLeft;
this.oTop = offsetTop;
}
@Override
protected void draw() {
if(mapProjection != null) {
setPosition();
imgTrafo.drawToCanvas(getCanvas(), bearing, 1.0);
}
}
public void setBearing(double bearing) {
this.bearing = bearing;
}
}
@@ -18,6 +18,7 @@ import com.google.gwt.maps.client.geometrylib.SphericalUtils;
import com.google.gwt.maps.client.overlays.Marker;
import com.sap.sailing.domain.common.Mile;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
import com.sap.sailing.simulator.util.SailingSimulatorConstants;
/**
* This class implements the layer to display the race course on the map. Currently the course only consists of the
@@ -30,6 +31,7 @@ public class RaceCourseCanvasOverlay extends FullCanvasOverlay {
private String racecourseColor = "White";
private double racecourseBuoySize = 5;
private char mode;
// TODO: make private!!!
public char raceCourseDirection;
@@ -55,9 +57,10 @@ public class RaceCourseCanvasOverlay extends FullCanvasOverlay {
}
}
public RaceCourseCanvasOverlay(MapWidget map, int zIndex) {
public RaceCourseCanvasOverlay(MapWidget map, int zIndex, char mode) {
super(map, zIndex);
this.mode = mode;
startPoint = null;
endPoint = null;
startMarker = null;
@@ -65,37 +68,41 @@ public class RaceCourseCanvasOverlay extends FullCanvasOverlay {
getCanvas().getElement().setClassName("raceCourse");
map.addClickHandler(new ClickMapHandler() {
@Override
public void onEvent(ClickMapEvent event) {
if (startPoint == null) {
startPoint = event.getMouseEvent().getLatLng();
logger.fine("Clicked startPoint here " + startPoint);
if (startPoint != null) {
if (this.mode == SailingSimulatorConstants.ModeFreestyle) {
setCanvasSettings();
// drawCanvas();
setStartPoint(startPoint);
registeredRaceCourseMouseMoveHandler = getMap().addMouseMoveHandler(new RaceCourseMapMouseMoveHandler());
}
}
}
});
map.addClickHandler(new ClickMapHandler() {
@Override
public void onEvent(ClickMapEvent event) {
if (startPoint == null) {
startPoint = event.getMouseEvent().getLatLng();
logger.fine("Clicked startPoint here " + startPoint);
if (startPoint != null) {
setCanvasSettings();
// drawCanvas();
setStartPoint(startPoint);
registeredRaceCourseMouseMoveHandler = getMap().addMouseMoveHandler(new RaceCourseMapMouseMoveHandler());
}
}
}
});
map.addDblClickHandler(new DblClickMapHandler() {
@Override
public void onEvent(DblClickMapEvent event) {
if (isSelected) {
endPoint = event.getMouseEvent().getLatLng();
logger.info("Clicked endPoint " + "here " + endPoint);
if (endPoint != null) {
setEndPoint(endPoint);
center();
registeredRaceCourseMouseMoveHandler.removeHandler();
}
}
}
});
}
map.addDblClickHandler(new DblClickMapHandler() {
@Override
public void onEvent(DblClickMapEvent event) {
if (isSelected) {
endPoint = event.getMouseEvent().getLatLng();
logger.info("Clicked endPoint " + "here " + endPoint);
if (endPoint != null) {
setEndPoint(endPoint);
center();
registeredRaceCourseMouseMoveHandler.removeHandler();
}
}
}
});
}
public void reset() {
@@ -121,66 +128,15 @@ public class RaceCourseCanvasOverlay extends FullCanvasOverlay {
int zoomLevel = map.getZoom();
racecourseBuoySize = 1.0 + (5.0 - 1.0)*(zoomLevel - 10.0)/(14.0 - 10.0);
setStartPoint(startPoint);
setEndPoint(endPoint);
setEndPoint(endPoint);
}
private void setStartPoint(LatLng startPoint) {
this.startPoint = startPoint;
if (startPoint != null) {
Point point = mapProjection.fromLatLngToDivPixel(startPoint);
drawCircleWithText(point.getX() - getWidgetPosLeft(), point.getY() - getWidgetPosTop(), racecourseBuoySize,
racecourseColor, "Start");
if (startMarker != null) {
startMarker.setPosition(startPoint);
} else {
// default markers are too large cluttering race display
/*
* startMarker = new Marker(startPoint); map.addOverlay(startMarker); /*
* startMarker.addMarkerMouseOverHandler(new MarkerMouseOverHandler () {
*
* @Override public void onMouseOver(MarkerMouseOverEvent event) { InfoWindowContent content = new
* InfoWindowContent("Start"); map.getInfoWindow().open(startMarker, content); }
*
* });
*
* startMarker.addMarkerMouseOutHandler(new MarkerMouseOutHandler () {
*
* @Override public void onMouseOut(MarkerMouseOutEvent event) { map.getInfoWindow().close(); }
*
* });
*/
}
}
}
private void setEndPoint(LatLng endPoint) {
this.endPoint = endPoint;
if (endPoint != null) {
Point point = mapProjection.fromLatLngToDivPixel(endPoint);
drawCircleWithText(point.getX() - getWidgetPosLeft(), point.getY() - getWidgetPosTop(), racecourseBuoySize,
racecourseColor, "End");
if (endMarker != null) {
endMarker.setPosition(endPoint);
} else {
// default markers are too large cluttering race display
/*
* endMarker = new Marker(endPoint); map.addOverlay(endMarker);
*
* endMarker.addMarkerMouseOverHandler(new RaceCourseMarkerMouseOverHandler());
*
* endMarker.addMarkerMouseOutHandler(new MarkerMouseOutHandler() {
*
* @Override public void onMouseOut(MarkerMouseOutEvent event) { map.getInfoWindow().close(); }
*
* });
*/
}
}
}
@Override
@@ -188,6 +144,59 @@ public class RaceCourseCanvasOverlay extends FullCanvasOverlay {
if(mapProjection != null && startPoint != null && endPoint != null) {
setCanvasSettings();
setStartEndPoint(startPoint, endPoint);
if (startPoint != null) {
Point point = mapProjection.fromLatLngToDivPixel(startPoint);
drawCircleWithText(point.getX() - getWidgetPosLeft(), point.getY() - getWidgetPosTop(), racecourseBuoySize,
racecourseColor, "Start");
if (startMarker != null) {
startMarker.setPosition(startPoint);
} else {
// default markers are too large cluttering race display
/*
* startMarker = new Marker(startPoint); map.addOverlay(startMarker); /*
* startMarker.addMarkerMouseOverHandler(new MarkerMouseOverHandler () {
*
* @Override public void onMouseOver(MarkerMouseOverEvent event) { InfoWindowContent content = new
* InfoWindowContent("Start"); map.getInfoWindow().open(startMarker, content); }
*
* });
*
* startMarker.addMarkerMouseOutHandler(new MarkerMouseOutHandler () {
*
* @Override public void onMouseOut(MarkerMouseOutEvent event) { map.getInfoWindow().close(); }
*
* });
*/
}
}
if (endPoint != null) {
Point point = mapProjection.fromLatLngToDivPixel(endPoint);
drawCircleWithText(point.getX() - getWidgetPosLeft(), point.getY() - getWidgetPosTop(), racecourseBuoySize,
racecourseColor, "End");
if (endMarker != null) {
endMarker.setPosition(endPoint);
} else {
// default markers are too large cluttering race display
/*
* endMarker = new Marker(endPoint); map.addOverlay(endMarker);
*
* endMarker.addMarkerMouseOverHandler(new RaceCourseMarkerMouseOverHandler());
*
* endMarker.addMarkerMouseOutHandler(new MarkerMouseOutHandler() {
*
* @Override public void onMouseOut(MarkerMouseOutEvent event) { map.getInfoWindow().close(); }
*
* });
*/
}
}
drawLine(endPoint, racecourseColor);
}
}
@@ -2,74 +2,119 @@ package com.sap.sailing.gwt.ui.simulator;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.Context2d.TextAlign;
import com.google.gwt.core.client.GWT;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.base.Point;
import com.google.gwt.maps.client.events.click.ClickMapEvent;
import com.google.gwt.maps.client.events.click.ClickMapHandler;
import com.google.gwt.maps.client.events.mouseout.MouseOutMapEvent;
import com.google.gwt.maps.client.events.mouseout.MouseOutMapHandler;
import com.google.gwt.maps.client.events.idle.IdleMapEvent;
import com.google.gwt.maps.client.events.idle.IdleMapHandler;
import com.google.gwt.maps.client.overlays.Circle;
import com.google.gwt.maps.client.overlays.CircleOptions;
import com.sap.sailing.gwt.ui.client.shared.racemap.ImageTransformer;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
import com.sap.sailing.gwt.ui.simulator.util.SimulatorResources;
import com.sap.sailing.simulator.util.SailingSimulatorConstants;
public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
private static SimulatorResources resources = GWT.create(SimulatorResources.class);
private SimulatorMap simulatorMap;
private RaceCourseCanvasOverlay raceCourseCanvasOverlay;
private VenueDescriptor venue;
private CourseAreaDescriptor currentCourseArea = null;
private boolean pan;
private boolean initial;
private boolean mapPan = false;
private double raceBearing = 0.0;
private double diffBearing = 0.0;
private ImageTransformer windRoseBackground;
private ImageTransformer windRoseNeedle;
public RegattaAreaCanvasOverlay(MapWidget map, int zIndex, char event) {
super(map, zIndex);
public RegattaAreaCanvasOverlay(MapWidget map, int zIndex, char event, final SimulatorMap simulatorMap) {
super(map, zIndex);
this.simulatorMap = simulatorMap;
this.venue = VenueDescriptorFactory.createVenue(event);
this.currentCourseArea = this.venue.getDefaultCourseArea();
/*getMap().addZoomChangeHandler(new ZoomChangeMapHandler() {
@Override
public void onEvent(ZoomChangeMapEvent event) {
// TODO Auto-generated method stub
simulatorMap.windRoseCanvasOverlay.removeFromMap();
simulatorMap.windNeedleCanvasOverlay.removeFromMap();
mapPan = true;
}
});
getMap().addDragStartHandler(new DragStartMapHandler() {
@Override
public void onEvent(DragStartMapEvent event) {
// TODO Auto-generated method stub
simulatorMap.windRoseCanvasOverlay.removeFromMap();
simulatorMap.windNeedleCanvasOverlay.removeFromMap();
}
});
getMap().addDragEndHandler(new DragEndMapHandler() {
@Override
public void onEvent(DragEndMapEvent event) {
// TODO Auto-generated method stub
simulatorMap.windRoseCanvasOverlay.addToMap();
simulatorMap.windNeedleCanvasOverlay.addToMap();
}
});*/
getMap().addIdleHandler(new IdleMapHandler() {
@Override
public void onEvent(IdleMapEvent event) {
// TODO Auto-generated method stub
if (mapPan) {
//System.out.println("Map Idle Event Handler.");
simulatorMap.getWindRoseCanvasOverlay().addToMap();
simulatorMap.getWindNeedleCanvasOverlay().addToMap();
mapPan = false;
}
}
});
windRoseBackground = new ImageTransformer(resources.windRoseBackground());
windRoseNeedle = new ImageTransformer(resources.windRoseNeedle());
}
@Override
public void addToMap() {
super.addToMap();
// TODO MigrationV3:
// getPane().add(windRoseBackground.getCanvas(), getWidgetPosLeft() + windBackgroundOffset, getWidgetPosTop());
// getPane().add(windRoseNeedle.getCanvas(), getWidgetPosLeft() + windBackgroundOffset + windNeedleOffset,
// getWidgetPosTop() + windNeedleOffset);
int counter = 1;
int counter = 0;
for (CourseAreaDescriptor courseArea : venue.getCourseAreas()) {
drawCircleFromRadius(counter++, courseArea);
}
map.panTo(venue.getCenterPos());
this.initial = true;
}
@Override
protected void draw() {
super.draw();
if(mapProjection != null) {
// TODO MigrationV3:
// getPane().setWidgetPosition(windRoseBackground.getCanvas(), getWidgetPosLeft() + windBackgroundOffset,
// getWidgetPosTop());
// getPane().setWidgetPosition(windRoseNeedle.getCanvas(),
// getWidgetPosLeft() + windBackgroundOffset + windNeedleOffset, getWidgetPosTop() + windNeedleOffset);
clearCanvas();
drawRegattaAreas();
if (this.initial) {
updateRaceCourse(0, 0);
this.initial = false;
}
}
}
@@ -79,8 +124,6 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
}
protected void drawRegattaAreas() {
windRoseBackground.drawTransformedImage(0.0, 1.0);
windRoseNeedle.drawTransformedImage(raceBearing + 180.0, 1.0);
LatLng cPos = LatLng.newInstance(54.4344, 10.19659167);
Point centerPoint = mapProjection.fromLatLngToDivPixel(cPos);
@@ -101,6 +144,7 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
// TODO MigrationV3: This is not the right place to create Circles being not drawn to the canvas -> move to SimulatorMap
public void drawCircleFromRadius(int regIdx, CourseAreaDescriptor courseArea) {
CircleOptions circleOptions = CircleOptions.newInstance();
circleOptions.setStrokeColor("white");
circleOptions.setStrokeWeight(1);
@@ -109,51 +153,47 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
circleOptions.setFillOpacity(0.0);
circleOptions.setCenter(courseArea.getCenterPos());
Circle circle = Circle.newInstance(circleOptions);
circle.setRadius(courseArea.getRadius());
circle.setRadius(courseArea.getRadiusInMeters());
final int regIdxFinal = regIdx;
circle.addClickHandler(new ClickMapHandler() {
public void onEvent(ClickMapEvent e) {
// System.out.println("Click: "+currentRegArea.name);
//System.out.println("Click: "+currentCourseArea.getName());
CourseAreaDescriptor newRegArea = venue.getCourseAreas().get(regIdxFinal);
if (newRegArea != currentCourseArea) {
currentCourseArea = newRegArea;
// simulatorMap.clearOverlays();
simulatorMap.clearOverlays();
simulatorMap.getWindRoseCanvasOverlay().removeFromMap();
simulatorMap.getWindNeedleCanvasOverlay().removeFromMap();
updateRaceCourse(0, 0);
raceCourseCanvasOverlay.draw();
}
pan = true;
map.panTo(currentCourseArea.getCenterPos());
mapPan = true;
if (map.getZoom() < 14) {
map.setZoom(14);
}
}
});
circle.setMap(getMap());
getMap().addMouseOutMoveHandler(new MouseOutMapHandler() {
public void onEvent(MouseOutMapEvent event) {
if (pan) {
pan = false;
if (map.getZoom() < 14) {
map.setZoom(14);
}
}
};
});
}
protected void updateRaceCourse(int type, double bearing) {
if (type == 1) {
raceBearing = bearing;
windRoseNeedle.drawTransformedImage(raceBearing + 180.0, 1.0);
simulatorMap.getWindNeedleCanvasOverlay().setBearing(raceBearing + 180.0);
} else if (type == 2) {
diffBearing = bearing;
}
if (currentCourseArea != null) {
// simulatorMap.getMainPanel().setUpdateButtonEnabled(true);
simulatorMap.getMainPanel().setUpdateButtonEnabled(true);
LatLng startPoint;
LatLng endPoint;
if (raceCourseCanvasOverlay.raceCourseDirection == SailingSimulatorConstants.LegTypeDownwind) {
@@ -165,7 +205,7 @@ public class RegattaAreaCanvasOverlay extends FullCanvasOverlay {
}
raceCourseCanvasOverlay.setStartEndPoint(startPoint, endPoint);
} else {
// simulatorMap.getMainPanel().setUpdateButtonEnabled(false);
simulatorMap.getMainPanel().setUpdateButtonEnabled(false);
}
}
@@ -147,14 +147,16 @@ public class SimulatorMainPanel extends SimplePanel {
if (setting.getDisplayName().equals("Base Bearing (Degrees)")) {
simulatorMap.clearOverlays();
//System.out.println("Wind Base Bearing: "+setting.getValue());
simulatorMap.regattaAreaCanvasOverlay.updateRaceCourse(1, (Double) setting.getValue());
simulatorMap.raceCourseCanvasOverlay.draw();
simulatorMap.getRegattaAreaCanvasOverlay().updateRaceCourse(1, (Double) setting.getValue());
simulatorMap.getRaceCourseCanvasOverlay().draw();
simulatorMap.getWindNeedleCanvasOverlay().draw();
}
if (setting.getDisplayName().equals("Race Course Diff (Degrees)")) {
simulatorMap.clearOverlays();
//System.out.println("Wind Base Bearing: "+setting.getValue());
simulatorMap.regattaAreaCanvasOverlay.updateRaceCourse(2, (Double) setting.getValue());
simulatorMap.raceCourseCanvasOverlay.draw();
simulatorMap.getRegattaAreaCanvasOverlay().updateRaceCourse(2, (Double) setting.getValue());
simulatorMap.getRaceCourseCanvasOverlay().draw();
simulatorMap.getWindNeedleCanvasOverlay().draw();
}
if (autoUpdate) {
update();
@@ -834,7 +836,7 @@ public class SimulatorMainPanel extends SimplePanel {
simulatorMap.refreshView(SimulatorMap.ViewName.WINDDISPLAY, currentWPDisplay, selection, true);
} else if (summaryButton.getValue()) {
showTimePanel(false);
simulatorMap.regattaAreaCanvasOverlay.draw();
simulatorMap.getRegattaAreaCanvasOverlay().draw();
simulatorMap.refreshView(SimulatorMap.ViewName.SUMMARY, currentWPDisplay, selection, true);
} else if (replayButton.getValue()) {
showTimePanel(true);
@@ -6,6 +6,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.maps.client.LoadApi;
@@ -42,6 +43,7 @@ import com.sap.sailing.gwt.ui.shared.racemap.GoogleMapAPIKey;
import com.sap.sailing.gwt.ui.shared.racemap.GoogleMapStyleHelper;
import com.sap.sailing.gwt.ui.simulator.util.ColorPalette;
import com.sap.sailing.gwt.ui.simulator.util.ColorPaletteGenerator;
import com.sap.sailing.gwt.ui.simulator.util.SimulatorResources;
import com.sap.sailing.gwt.ui.simulator.windpattern.WindPatternDisplay;
import com.sap.sailing.simulator.util.SailingSimulatorConstants;
@@ -52,6 +54,9 @@ import com.sap.sailing.simulator.util.SailingSimulatorConstants;
*
*/
public class SimulatorMap extends AbsolutePanel implements RequiresDataInitialization, TimeListenerWithStoppingCriteria {
private static SimulatorResources resources = GWT.create(SimulatorResources.class);
private MapWidget map;
private boolean dataInitialized;
private boolean overlaysInitialized;
@@ -62,11 +67,13 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
private WindFieldCanvasOverlay windFieldCanvasOverlay;
private WindGridCanvasOverlay windGridCanvasOverlay;
private WindLineCanvasOverlay windLineCanvasOverlay;
// TODO MigrationV3: should not be public
public RegattaAreaCanvasOverlay regattaAreaCanvasOverlay;
private RegattaAreaCanvasOverlay regattaAreaCanvasOverlay;
private ImageCanvasOverlay windRoseCanvasOverlay;
private ImageCanvasOverlay windNeedleCanvasOverlay;
private List<PathCanvasOverlay> replayPathCanvasOverlays;
// TODO MigrationV3: should not be public
public RaceCourseCanvasOverlay raceCourseCanvasOverlay;
private RaceCourseCanvasOverlay raceCourseCanvasOverlay;
private PathLegendCanvasOverlay legendCanvasOverlay;
private List<TimeListenerWithStoppingCriteria> timeListeners;
@@ -216,6 +223,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
refreshWindFieldOverlay(windFieldDTO);
timeListeners.clear();
if (windParams.isShowArrows()) {
timeListeners.add(windFieldCanvasOverlay);
}
@@ -381,22 +389,31 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
}
};
LoadApi.go(onLoad, loadLibraries, sensor, "key="+GoogleMapAPIKey.V2_APIKey);
LoadApi.go(onLoad, loadLibraries, sensor, "key="+GoogleMapAPIKey.V2_APIKey);
}
private void initializeOverlays() {
if (mode == SailingSimulatorConstants.ModeEvent) {
if (regattaAreaCanvasOverlay == null) {
regattaAreaCanvasOverlay = new RegattaAreaCanvasOverlay(map, SimulatorMapOverlaysZIndexes.REGATTA_AREA_ZINDEX, getMainPanel().getEvent());
regattaAreaCanvasOverlay = new RegattaAreaCanvasOverlay(map, SimulatorMapOverlaysZIndexes.REGATTA_AREA_ZINDEX, getMainPanel().getEvent(), this);
regattaAreaCanvasOverlay.addToMap();
int offsetLeft = 50;
int offsetTop = 25;
windRoseCanvasOverlay = new ImageCanvasOverlay(map, SimulatorMapOverlaysZIndexes.WIND_ROSE_ZINDEX, resources.windRoseBackground());
windRoseCanvasOverlay.setOffset(offsetLeft, offsetTop);
windRoseCanvasOverlay.addToMap();
windNeedleCanvasOverlay = new ImageCanvasOverlay(map, SimulatorMapOverlaysZIndexes.WIND_ROSE_ZINDEX, resources.windRoseNeedle());
windNeedleCanvasOverlay.setOffset(offsetLeft, offsetTop);
windNeedleCanvasOverlay.setBearing(180.0);
windNeedleCanvasOverlay.addToMap();
}
}
raceCourseCanvasOverlay = new RaceCourseCanvasOverlay(map, SimulatorMapOverlaysZIndexes.RACE_COURSE_ZINDEX);
raceCourseCanvasOverlay = new RaceCourseCanvasOverlay(map, SimulatorMapOverlaysZIndexes.RACE_COURSE_ZINDEX, mode);
if (mode == SailingSimulatorConstants.ModeEvent) {
regattaAreaCanvasOverlay.setRaceCourseCanvas(raceCourseCanvasOverlay);
regattaAreaCanvasOverlay.updateRaceCourse(0, 0);
}
if (windParams.isShowArrows()) {
@@ -460,6 +477,8 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
windParams.setxRes(xRes);
windParams.setyRes(yRes);
busyIndicator.setBusy(true);
timer.setTime(windParams.getStartTime().getTime());
simulatorService.getWindField(windParams, windPatternDisplay, new AsyncCallback<WindFieldDTO>() {
@Override
public void onFailure(Throwable message) {
@@ -526,7 +545,6 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
}
}
this.timer.setTime(this.windParams.getStartTime().getTime());
if (this.windParams.isShowArrows()) {
this.windFieldCanvasOverlay.draw();
}
@@ -563,6 +581,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
windParams.setyRes(yRes);
busyIndicator.setBusy(true);
timer.setTime(windParams.getStartTime().getTime());
simulatorService.getSimulatorResults(mode, raceCourseDirection, windParams, windPatternDisplay, true, selection, new ResultManager(summaryView));
@@ -848,9 +867,27 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
raceCourseCanvasOverlay.raceCourseDirection = raceCourseDirection;
regattaAreaCanvasOverlay.updateRaceCourse(0, 0);
raceCourseCanvasOverlay.draw();
windNeedleCanvasOverlay.draw();
}
public WindFieldGenParamsDTO getWindParams() {
return windParams;
}
public RegattaAreaCanvasOverlay getRegattaAreaCanvasOverlay() {
return regattaAreaCanvasOverlay;
}
public ImageCanvasOverlay getWindRoseCanvasOverlay() {
return windRoseCanvasOverlay;
}
public ImageCanvasOverlay getWindNeedleCanvasOverlay() {
return windNeedleCanvasOverlay;
}
public RaceCourseCanvasOverlay getRaceCourseCanvasOverlay() {
return raceCourseCanvasOverlay;
}
}
@@ -11,12 +11,13 @@ public interface SimulatorMapOverlaysZIndexes {
public static int REGATTA_AREA_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 1;
public static int RACE_COURSE_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 2;
public static int WINDFIELD_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 3;
public static int WINDSTREAMLETS_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 4;
public static int WINDGRID_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 5;
public static int WINDGRID_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 3;
public static int WINDFIELD_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 4;
public static int WINDSTREAMLETS_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 5;
public static int WINDLINE_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 6;
public static int PATH_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 7;
public static int PATHLEGEND_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 8;
public static int WIND_ROSE_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 8;
public static int PATHLEGEND_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 9;
/** the z-index of the info window should always be higher than the rest */
public static int INFO_WINDOW_ZINDEX = BASE_CANVAS_OVERLAY_ZINDEX + 50;
@@ -21,7 +21,6 @@ import com.sap.sailing.gwt.ui.shared.WindFieldDTO;
import com.sap.sailing.gwt.ui.shared.WindFieldGenParamsDTO;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
import com.sap.sailing.gwt.ui.simulator.util.ToolTip;
import com.sap.sailing.gwt.ui.simulator.util.WindFieldMapMouseMoveHandler;
/**
* A google map overlay based on a HTML5 canvas for drawing a wind field. The overlay covers the whole map and displays
@@ -44,8 +43,6 @@ public class WindFieldCanvasOverlay extends FullCanvasOverlay implements TimeLis
protected Map<ToolTip, SimulatorWindDTO> windFieldPoints;
protected String arrowColor = "Blue";
protected String arrowHeadColor = "Blue";
protected WindFieldMapMouseMoveHandler mmHandler;
protected double arrowLength = 15;
protected WindFieldGenParamsDTO windParams = null;
@@ -93,11 +90,7 @@ public class WindFieldCanvasOverlay extends FullCanvasOverlay implements TimeLis
@Override
public void addToMap() {
super.addToMap();
if(mmHandler == null) {
mmHandler = new WindFieldMapMouseMoveHandler(this);
}
mmHandler.setWindFieldPoints(windFieldPoints);
mouseMoveHandlerRegistration = addMouseMoveHandler(mmHandler);
if (timer != null) {
timer.addTimeListener(this);
}
@@ -127,7 +120,6 @@ public class WindFieldCanvasOverlay extends FullCanvasOverlay implements TimeLis
canvas.getContext2d().clearRect(0.0 /*canvas.getAbsoluteLeft()*/, 0.0/*canvas.getAbsoluteTop()*/,
canvas.getCoordinateSpaceWidth(), canvas.getCoordinateSpaceHeight());
windFieldPoints.clear();
mmHandler.clear();
}
protected void drawWindField() {
@@ -12,7 +12,6 @@ import java.util.TreeMap;
import java.util.logging.Logger;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.base.Point;
@@ -23,7 +22,6 @@ import com.sap.sailing.gwt.ui.shared.SimulatorWindDTO;
import com.sap.sailing.gwt.ui.shared.WindFieldDTO;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
import com.sap.sailing.gwt.ui.simulator.util.ToolTip;
import com.sap.sailing.gwt.ui.simulator.util.WindFieldMapMouseMoveHandler;
/**
* A google map overlay based on a HTML5 canvas for drawing a wind field. The overlay covers the whole map and displays
@@ -33,7 +31,7 @@ import com.sap.sailing.gwt.ui.simulator.util.WindFieldMapMouseMoveHandler;
*
*/
public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements TimeListenerWithStoppingCriteria {
/** The wind field that is to be displayed in the overlay */
private WindFieldDTO windFieldDTO;
@@ -46,8 +44,6 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
private Map<ToolTip, SimulatorWindDTO> windFieldPoints;
private String arrowColor = "Black";
private String arrowHeadColor = "Blue";
private HandlerRegistration mouseMoveHandlerRegistration;
private WindFieldMapMouseMoveHandler windFieldMapMouseMoveHandler;
private int xRes;
private Timer timer;
@@ -59,10 +55,9 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
this.timer = timer;
this.xRes = xRes;
windFieldDTO = null;
windFieldPoints = new HashMap<ToolTip, SimulatorWindDTO>();
windFieldMapMouseMoveHandler = new WindFieldMapMouseMoveHandler(this);
timePointWindDTOMap = new TreeMap<Long, List<SimulatorWindDTO>>();
}
@@ -75,9 +70,6 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
public void addToMap() {
super.addToMap();
windFieldMapMouseMoveHandler.setWindFieldPoints(windFieldPoints);
mouseMoveHandlerRegistration = map.addMouseMoveHandler(windFieldMapMouseMoveHandler);
if (timer != null) {
timer.addTimeListener(this);
}
@@ -87,8 +79,6 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
public void removeFromMap() {
super.removeFromMap();
mouseMoveHandlerRegistration.removeHandler();
if (timer != null) {
timer.removeTimeListener(this);
}
@@ -126,7 +116,6 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti
canvas.getContext2d().clearRect(0.0 /*canvas.getAbsoluteLeft()*/, 0.0/*canvas.getAbsoluteTop()*/,
canvas.getCoordinateSpaceWidth(), canvas.getCoordinateSpaceHeight());
windFieldPoints.clear();
windFieldMapMouseMoveHandler.clear();
}
protected void drawWindField() {
@@ -7,6 +7,8 @@ import com.google.gwt.core.client.Scheduler;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.base.Point;
import com.google.gwt.maps.client.events.center.CenterChangeMapEvent;
import com.google.gwt.maps.client.events.center.CenterChangeMapHandler;
import com.google.gwt.user.client.ui.RequiresResize;
import com.sap.sailing.domain.common.dto.PositionDTO;
import com.sap.sailing.gwt.ui.shared.SimulatorWindDTO;
@@ -35,6 +37,23 @@ public abstract class FullCanvasOverlay extends CanvasOverlayV3 implements Requi
public FullCanvasOverlay(MapWidget map, int zIndex) {
super(map, zIndex);
/*getMap().addDragEndHandler( new DragEndMapHandler() {
@Override
public void onEvent(DragEndMapEvent event) {
// TODO Auto-generated method stub
draw();
};
});*/
getMap().addCenterChangeHandler(new CenterChangeMapHandler() {
@Override
public void onEvent(CenterChangeMapEvent event) {
// TODO Auto-generated method stub
draw();
};
});
}
/**
@@ -1,79 +0,0 @@
/**
*
*/
package com.sap.sailing.gwt.ui.simulator.util;
import java.util.Map;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.ImageData;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.base.Point;
import com.google.gwt.maps.client.events.mousemove.MouseMoveMapEvent;
import com.google.gwt.maps.client.events.mousemove.MouseMoveMapHandler;
import com.sap.sailing.gwt.ui.shared.SimulatorWindDTO;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
/**
* To handle MouseMoveEvent to display tool tips around SimulatorWindDTO objects in a wind field
*
* @author Nidhi Sawhney(D054070)
*
*/
public class WindFieldMapMouseMoveHandler implements MouseMoveMapHandler {
private final FullCanvasOverlay canvasOverlay;
private Map<ToolTip, SimulatorWindDTO> windFieldPoints = null;
private ImageData lastImageData = null;
private double lastToolx;
private double lastTooly;
public WindFieldMapMouseMoveHandler(final FullCanvasOverlay canvasOverlay) {
super();
this.canvasOverlay = canvasOverlay;
}
public void clear() {
lastImageData = null;
}
public void setWindFieldPoints(final Map<ToolTip, SimulatorWindDTO> windFieldPoints) {
this.windFieldPoints = windFieldPoints;
}
@Override
public void onEvent(final MouseMoveMapEvent event) {
if (windFieldPoints != null) {
final LatLng latLng = event.getMouseEvent().getLatLng();
final Point pointP = canvasOverlay.getMapProjection().fromLatLngToDivPixel(latLng);
final double x = pointP.getX() - canvasOverlay.getWidgetPosLeft();
final double y = pointP.getY() - canvasOverlay.getWidgetPosTop();
final ToolTip point = new ToolTip(x, y);
final Context2d context2d = canvasOverlay.getCanvas().getContext2d();
if (lastImageData != null) {
context2d.putImageData(lastImageData, lastToolx, lastTooly);
}
if (windFieldPoints.containsKey(point)) {
lastToolx = x;
lastTooly = y;
lastImageData = context2d.getImageData(x, y, ToolTip.toolRectW, ToolTip.toolRectH);
final SimulatorWindDTO windDTO = windFieldPoints.get(point);
context2d.setFillStyle("#4f4f4f");
context2d.fillRect(x, y, ToolTip.toolRectW, ToolTip.toolRectH);
context2d.setFillStyle("#FFFFFF");
context2d.fillRect(x + 3, y + 3, ToolTip.toolRectW - 6, ToolTip.toolRectH - 6);
context2d.setFillStyle("Blue");
final String speedStr = NumberFormat.getFormat("#.00").format(windDTO.trueWindSpeedInKnots);
final String bearingStr = NumberFormat.getFormat("#.00").format(windDTO.trueWindBearingDeg);
final String ttMsg = speedStr + " kn " + bearingStr + "�";
context2d.fillText(ttMsg, x+10,y+15,60);
}
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -31,7 +31,7 @@ public abstract class AbstractMongoDBTest {
}
protected Mongo newMongo() throws UnknownHostException, MongoException {
return new Mongo(System.getProperty("mongo.host", "127.0.0.1"), dbConfiguration.getPort());
return new Mongo(dbConfiguration.getHostName(), dbConfiguration.getPort());
}
@Before
@@ -60,7 +60,7 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive
}
private Mongo newMongo() throws UnknownHostException, MongoException {
return new Mongo(System.getProperty("mongo.host", "127.0.0.1"),
return new Mongo(dbConfiguration.getHostName(),
dbConfiguration.getPort());
}
@@ -19,16 +19,46 @@ public class MongoDBConfiguration {
private String databaseName;
public static MongoDBConfiguration getDefaultConfiguration() {
String defaultHostName = System.getProperty(MONGO_HOSTNAME, "127.0.0.1");
int defaultPort = Integer.valueOf(System.getProperty(MONGO_PORT, "27017"));
String defaultHostName = "127.0.0.1";
if (System.getProperty(MONGO_HOSTNAME) != null) {
defaultHostName = System.getProperty(MONGO_HOSTNAME);
} else {
if (System.getenv("MONGODB_HOST") != null) {
defaultHostName = System.getenv("MONGODB_HOST");
}
}
int defaultPort = 27017;
if (System.getProperty(MONGO_PORT) != null) {
defaultPort = Integer.valueOf(System.getProperty(MONGO_PORT).trim());
} else {
if (System.getenv("MONGODB_PORT") != null) {
defaultPort = Integer.valueOf(System.getenv("MONGODB_PORT").trim());
}
}
String defaultDatabaseName = System.getProperty(MONGO_DB_NAME, DEFAULT_DB_NAME);
return new MongoDBConfiguration(defaultHostName, defaultPort, defaultDatabaseName);
}
public static MongoDBConfiguration getDefaultTestConfiguration() {
String defaultHostName = System.getProperty(MONGO_HOSTNAME, "127.0.0.1");
int defaultPort = Integer.valueOf(System.getProperty(MONGO_PORT, "27017"));
String defaultHostName = "127.0.0.1";
if (System.getProperty(MONGO_HOSTNAME) != null) {
defaultHostName = System.getProperty(MONGO_HOSTNAME);
} else {
if (System.getenv("MONGODB_HOST") != null) {
defaultHostName = System.getenv("MONGODB_HOST");
}
}
int defaultPort = 27017;
if (System.getProperty(MONGO_PORT) != null) {
defaultPort = Integer.valueOf(System.getProperty(MONGO_PORT).trim());
} else {
if (System.getenv("MONGODB_PORT") != null) {
defaultPort = Integer.valueOf(System.getenv("MONGODB_PORT").trim());
}
}
String defaultDatabaseName = System.getProperty(MONGO_DB_NAME, DEFAULT_TEST_DB_NAME);
return new MongoDBConfiguration(defaultHostName, defaultPort, defaultDatabaseName);
@@ -110,6 +110,10 @@ public class ESS40ResultsAsCSVServlet extends AbstractCSVHttpServlet {
csvLine.add(maxPointsReason.name());
csvLine.add(totalRacePoints);
}
} else {
/* Make sure to also include null columns */
csvLine.add(0);
csvLine.add(0);
}
}
}
@@ -28,6 +28,7 @@ import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sailing.server.replication.ReplicationMasterDescriptor;
import com.sap.sailing.server.replication.ReplicationService;
import com.sap.sailing.server.replication.impl.Activator;
import com.sap.sailing.server.replication.impl.ReplicaDescriptor;
import com.sap.sailing.server.replication.impl.ReplicationInstancesManager;
import com.sap.sailing.server.replication.impl.ReplicationMasterDescriptorImpl;
@@ -72,8 +73,11 @@ public abstract class AbstractServerReplicationTest {
*/
protected Pair<ReplicationServiceTestImpl, ReplicationMasterDescriptor> basicSetUp(
boolean dropDB, RacingEventServiceImpl master, RacingEventServiceImpl replica) throws IOException, InterruptedException {
final String exchangeName = "test-sapsailinganalytics-exchange";
final String exchangeHost = "localhost";
String exchangeName = "test-sapsailinganalytics-exchange";
String exchangeHost = "localhost";
if (System.getenv(Activator.REPLICATION_HOST) != null) {
exchangeHost = System.getenv(Activator.REPLICATION_HOST);
}
final UUID serverUuid = UUID.randomUUID();
final MongoDBService mongoDBService = MongoDBService.INSTANCE;
if (dropDB) {
@@ -94,7 +98,9 @@ public abstract class AbstractServerReplicationTest {
masterReplicator = new ReplicationServiceImpl(exchangeName, exchangeHost, rim, this.master);
replicaDescriptor = new ReplicaDescriptor(InetAddress.getLocalHost(), serverUuid, "");
masterReplicator.registerReplica(replicaDescriptor);
masterDescriptor = new ReplicationMasterDescriptorImpl("localhost", exchangeName, SERVLET_PORT, 0, UUID.randomUUID().toString());
// connect to exchange host and local server running as master
// master server and exchange host can be two different hosts
masterDescriptor = new ReplicationMasterDescriptorImpl(exchangeHost, "localhost", exchangeName, SERVLET_PORT, 0, UUID.randomUUID().toString());
ReplicationServiceTestImpl replicaReplicator = new ReplicationServiceTestImpl(exchangeName, exchangeHost, resolveAgainst, rim,
replicaDescriptor, this.replica, this.master, masterReplicator, masterDescriptor);
Pair<ReplicationServiceTestImpl, ReplicationMasterDescriptor> result = new Pair<>(replicaReplicator, masterDescriptor);
@@ -49,12 +49,12 @@ public class ConnectionResetAndReconnectTest extends AbstractServerReplicationTe
static class MasterReplicationDescriptorMock extends ReplicationMasterDescriptorImpl {
public MasterReplicationDescriptorMock(String hostname, String exchangeName, int servletPort, int messagingPort) {
super(hostname, exchangeName, servletPort, messagingPort, UUID.randomUUID().toString());
public MasterReplicationDescriptorMock(String messagingHost, String hostname, String exchangeName, int servletPort, int messagingPort) {
super(messagingHost, hostname, exchangeName, servletPort, messagingPort, UUID.randomUUID().toString());
}
public static MasterReplicationDescriptorMock from(ReplicationMasterDescriptor obj) {
return new MasterReplicationDescriptorMock(obj.getHostname(), obj.getExchangeName(), obj.getServletPort(), obj.getMessagingPort());
return new MasterReplicationDescriptorMock(obj.getMessagingHostname(), obj.getHostname(), obj.getExchangeName(), obj.getServletPort(), obj.getMessagingPort());
}
@Override
@@ -5,5 +5,5 @@ import com.sap.sailing.server.replication.impl.ReplicationFactoryImpl;
public interface ReplicationFactory {
static ReplicationFactory INSTANCE = new ReplicationFactoryImpl();
ReplicationMasterDescriptor createReplicationMasterDescriptor(String hostname, String exchangeName, int servletPort, int jmsPort, String jmsQueueName);
ReplicationMasterDescriptor createReplicationMasterDescriptor(String messagingHostname, String hostname, String exchangeName, int servletPort, int jmsPort, String jmsQueueName);
}
@@ -38,4 +38,6 @@ public interface ReplicationMasterDescriptor {
String getExchangeName();
void stopConnection();
String getMessagingHostname();
}
@@ -12,6 +12,9 @@ public class Activator implements BundleActivator {
private static final String PROPERTY_NAME_EXCHANGE_NAME = "replication.exchangeName";
private static final String PROPERTY_NAME_EXCHANGE_HOST = "replication.exchangeHost";
public static final String REPLICATION_CHANNEL = "REPLICATION_CHANNEL";
public static final String REPLICATION_HOST = "REPLICATION_HOST";
private ReplicationInstancesManager replicationInstancesManager;
@@ -22,15 +25,23 @@ public class Activator implements BundleActivator {
String exchangeName = bundleContext.getProperty(PROPERTY_NAME_EXCHANGE_NAME);
String exchangeHost = bundleContext.getProperty(PROPERTY_NAME_EXCHANGE_HOST);
if (exchangeName == null) {
exchangeName = "sapsailinganalytics";
if (System.getenv(REPLICATION_CHANNEL) == null) {
exchangeName = "sapsailinganalytics";
} else {
exchangeName = System.getenv(REPLICATION_CHANNEL);
}
}
if (exchangeHost == null) {
exchangeHost = "localhost";
if (System.getenv(REPLICATION_HOST) == null) {
exchangeHost = "localhost";
} else {
exchangeHost = System.getenv(REPLICATION_HOST);
}
}
replicationInstancesManager = new ReplicationInstancesManager();
ReplicationService serverReplicationMasterService = new ReplicationServiceImpl(exchangeName, exchangeHost, replicationInstancesManager);
bundleContext.registerService(ReplicationService.class, serverReplicationMasterService, null);
logger.info("Registered replication service "+serverReplicationMasterService+" using exchange name "+exchangeName);
logger.info("Registered replication service "+serverReplicationMasterService+" using exchange name "+exchangeName+" on host "+exchangeHost);
}
public void stop(BundleContext bundleContext) throws Exception {
@@ -5,8 +5,8 @@ import com.sap.sailing.server.replication.ReplicationMasterDescriptor;
public class ReplicationFactoryImpl implements ReplicationFactory {
@Override
public ReplicationMasterDescriptor createReplicationMasterDescriptor(String hostname, String exchangeName, int servletPort, int messagingPort, String queueName) {
return new ReplicationMasterDescriptorImpl(hostname, exchangeName, servletPort, messagingPort, queueName);
public ReplicationMasterDescriptor createReplicationMasterDescriptor(String messagingHostname, String hostname, String exchangeName, int servletPort, int messagingPort, String queueName) {
return new ReplicationMasterDescriptorImpl(messagingHostname, hostname, exchangeName, servletPort, messagingPort, queueName);
}
}
@@ -20,6 +20,7 @@ public class ReplicationMasterDescriptorImpl implements ReplicationMasterDescrip
private final String hostname;
private final String exchangeName;
private final int servletPort;
private final String messagingHostname;
private final int messagingPort;
private final String queueName;
@@ -28,8 +29,9 @@ public class ReplicationMasterDescriptorImpl implements ReplicationMasterDescrip
/**
* @param messagingPort 0 means use default port
*/
public ReplicationMasterDescriptorImpl(String hostname, String exchangeName, int servletPort, int messagingPort, String queueName) {
public ReplicationMasterDescriptorImpl(String messagingHostname, String hostname, String exchangeName, int servletPort, int messagingPort, String queueName) {
this.hostname = hostname;
this.messagingHostname = messagingHostname;
this.servletPort = servletPort;
this.messagingPort = messagingPort;
this.exchangeName = exchangeName;
@@ -39,7 +41,7 @@ public class ReplicationMasterDescriptorImpl implements ReplicationMasterDescrip
@Override
public URL getReplicationRegistrationRequestURL(UUID uuid, String additional) throws MalformedURLException, UnsupportedEncodingException {
return new URL("http", hostname, servletPort, REPLICATION_SERVLET + "?" + ReplicationServlet.ACTION + "="
return new URL("http", getHostname(), servletPort, REPLICATION_SERVLET + "?" + ReplicationServlet.ACTION + "="
+ ReplicationServlet.Action.REGISTER.name()
+ "&" + ReplicationServlet.SERVER_UUID + "=" + uuid.toString()
+ "&" + ReplicationServlet.ADDITIONAL_INFORMATION + "=" + java.net.URLEncoder.encode(BuildVersion.getBuildVersion(), "UTF-8"));
@@ -47,21 +49,21 @@ public class ReplicationMasterDescriptorImpl implements ReplicationMasterDescrip
@Override
public URL getReplicationDeRegistrationRequestURL(UUID uuid) throws MalformedURLException {
return new URL("http", hostname, servletPort, REPLICATION_SERVLET + "?" + ReplicationServlet.ACTION + "="
return new URL("http", getHostname(), servletPort, REPLICATION_SERVLET + "?" + ReplicationServlet.ACTION + "="
+ ReplicationServlet.Action.DEREGISTER.name()
+ "&" + ReplicationServlet.SERVER_UUID + "=" + uuid.toString());
}
@Override
public URL getInitialLoadURL() throws MalformedURLException {
return new URL("http", hostname, servletPort, REPLICATION_SERVLET + "?" + ReplicationServlet.ACTION + "="
return new URL("http", getHostname(), servletPort, REPLICATION_SERVLET + "?" + ReplicationServlet.ACTION + "="
+ ReplicationServlet.Action.INITIAL_LOAD.name());
}
@Override
public synchronized QueueingConsumer getConsumer() throws IOException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(getHostname());
connectionFactory.setHost(getMessagingHostname());
int port = getMessagingPort();
if (port != 0) {
connectionFactory.setPort(port);
@@ -137,6 +139,11 @@ public class ReplicationMasterDescriptorImpl implements ReplicationMasterDescrip
public int getMessagingPort() {
return messagingPort;
}
@Override
public String getMessagingHostname() {
return messagingHostname;
}
@Override
public int getServletPort() {
@@ -18,7 +18,7 @@
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console -clean"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dfile.encoding=cp1252&#13;&#10;-Dexpedition.udp.port=2010 -Xmx6000m -Dhttp.proxyHost=proxy.wdf.sap.corp -Dhttp.proxyPort=8080 -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -Dkiwo.results=${project_loc:com.sap.sailing.kiworesultimport.test}/resources -XX:+UseMembar"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dfile.encoding=cp1252 -Dexpedition.udp.port=2010 -Xmx6000m -Dhttp.proxyHost=proxy.wdf.sap.corp -Dhttp.proxyPort=8080 -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -Dkiwo.results=${project_loc:com.sap.sailing.kiworesultimport.test}/resources -XX:+UseMembar"/>
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc}"/>
<stringAttribute key="pde.version" value="3.3"/>
<booleanAttribute key="show_selected_only" value="false"/>
@@ -9,7 +9,9 @@ public interface SailingSimulatorConstants {
public static final char LegTypeUpwind = 'u'; // leg type: 'u'pwind
public static final char LegTypeDownwind = 'd'; // leg type: 'd'ownwind
public static final char EventDummy = '0'; // used in cases where race course is defined as URL parameter
public static final char EventKielerWoche = 'k'; // event: 'k'ieler woche
public static final char EventTravemuenderWoche = 't'; // event: 't'ravemünder woche
public static final char EventX40Cardiff = 'c'; // event: 'c'ardiff extreme sailing series
}
+26
View File
@@ -22,9 +22,27 @@ REPLICATE_MASTER_SERVLET_PORT=
REPLICATE_MASTER_QUEUE_HOST=
REPLICATE_MASTER_QUEUE_PORT=
# Automatic build and test configuration
DEPLOY_TO=
BUILD_BEFORE_START=False
BUILD_FROM=master
COMPILE_GWT=True
RUN_TESTS=False
CODE_DIRECTORY=code
BUILD_COMPLETE_NOTIFY=simon.marcel.pamies@sap.com
# Specify an email address that should be notified
# whenever the server has been started
SERVER_STARTUP_NOTIFY=
INSTANCE_ID="$SERVER_NAME:$SERVER_PORT"
ADDITIONAL_JAVA_ARGS="-XX:+UseMembar"
JAVA_HOME=$HOME/jdk1.7.0_02
if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then
JAVA_HOME=`/usr/libexec/java_home`
echo "Setting JAVA_HOME to discovered $JAVA_HOME"
fi
# Make it possible to overwrite configuration
# by using user-data that is injected into an instance
@@ -36,5 +54,13 @@ if [[ ! -z "$ON_AMAZON" ]]; then
echo $var
export $var
done
# set directory where to deploy code to
# this is fixed on EC2 instances
DEPLOY_TO=server
INSTANCE_NAME=`ec2-metadata -i | cut -f2 -d " "`
INSTANCE_IP4=`ec2-metadata -v | cut -f2 -d " "`
INSTANCE_DNS=`ec2-metadata -p | cut -f2 -d " "`
INSTANCE_ID="$INSTANCE_NAME ($INSTANCE_IP4)"
fi
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
#!/bin/sh
target="`dirname \"$0\"`"
pwd=`pwd`
echo "$target" | grep "^/"
if [ "$0" != "0" ]; then
# no leading slash, therefore no absolute path; prepend pwd
target="$pwd/$target"
fi
echo target is $target
pluginsdir="$target/../com.sap.sailing.feature.p2build/bin/products/raceanalysis.product.id/win32/win32/x86_64/plugins"
mkdir resources
classpath="`find $pluginsdir -name 'com.sap.sailing.domain_*.jar' | sort | tail -1`:`find $pluginsdir -name 'com.sap.sailing.domain.common_*.jar' | sort | tail -1`:`find $pluginsdir -name 'com.sap.sailing.domain.shared.android_*.jar' | sort | tail -1`:`find $pluginsdir -name 'com.sap.sailing.declination*.jar' | sort | tail -1`"
echo Using classpath $classpath
"$JAVA_HOME/bin/java" -cp "$classpath" -Djava.util.logging.config.file=$target/configuration/logging.properties com.sap.sailing.declination.impl.DeclinationStore $*
+96
View File
@@ -0,0 +1,96 @@
#!/bin/sh
. `pwd`/env.sh
checks ()
{
USER_HOME=~
START_DIR=`pwd`
PROJECT_HOME=$(find_project_home $START_DIR)
# needed for maven on sapsailing.com to work correctly
if [ -f $USER_HOME/.bash_profile ]; then
source $USER_HOME/.bash_profile
fi
JAVA_BINARY=$JAVA_HOME/bin/java
if [[ ! -d "$JAVA_HOME" ]]; then
echo "Could not find $JAVA_BINARY set in env.sh. Trying to find the correct one..."
JAVA_VERSION=$(java -version 2>&1 | sed 's/java version "\(.*\)\.\(.*\)\..*"/\1\2/; 1q')
if [ "$JAVA_VERSION" -lt 17 ]; then
echo "The current Java version ($JAVA_VERSION) does not match the requirements (>= 1.7)."
exit 10
fi
JAVA_BINARY=`which java`
echo "Using Java from $JAVA_BINARY"
fi
}
find_project_home ()
{
if [[ $1 == '/' ]] || [[ $1 == "" ]]; then
echo ""
return 0
fi
if [ ! -d "$1/.git" ]; then
PARENT_DIR=`cd $1/..;pwd`
OUTPUT=$(find_project_home $PARENT_DIR)
if [ "$OUTPUT" = "" ] && [ -d "$PARENT_DIR/$CODE_DIRECTORY" ] && [ -d "$PARENT_DIR/$CODE_DIRECTORY/.git" ]; then
OUTPUT="$PARENT_DIR/$CODE_DIRECTORY"
fi
echo $OUTPUT
return 0
fi
echo $1 | sed -e 's/\/cygdrive\/\([a-zA-Z]\)/\1:/'
}
checkout_code ()
{
cd $PROJECT_HOME
GIT_BINARY=`which git`
if [[ $COMPILE_GWT == "True" ]]; then
# only reset if GWT gets compiled
# if not p2build will not work
$GIT_BINARY reset --hard
fi
$GIT_BINARY checkout $BUILD_FROM
$GIT_BINARY pull
}
build ()
{
cd $PROJECT_HOME
TESTS="-t"
if [[ $RUN_TESTS == "True" ]]; then
TESTS=""
fi
GWT="-g"
if [[ $COMPILE_GWT == "True" ]]; then
GWT=""
fi
$PROJECT_HOME/configuration/buildAndUpdateProduct.sh $TESTS $GWT -u build
STATUS=$?
if [ $STATUS -eq 0 ]; then
echo "Build Successful"
else
echo "Build Failed"
exit 10
fi
}
deploy ()
{
cd $PROJECT_HOME
if [[ $DEPLOY_TO != "" ]]; then
DEPLOY="-s $DEPLOY_TO"
fi
$PROJECT_HOME/configuration/buildAndUpdateProduct.sh -u $DEPLOY install
}
checks
checkout_code
build
deploy
+41 -4
View File
@@ -3,6 +3,31 @@
# source variables
. `pwd`/env.sh
# check if automatic tests and build should be executed
# before starting up the server
if [[ $BUILD_BEFORE_START == "True" ]]; then
# check for available memory - build can not be started with less than 1GB
MEM_TOTAL=`free -mt | grep Total | awk '{print $2}'`
if [ $MEM_TOTAL -lt 924 ]; then
echo "Could not start build process with less than 1GB of RAM!"
echo "Not enough RAM for completing the build process! You need at least 1GB. Instance NOT started!" | `which mail` -r simon.marcel.pamies@sap.com -s "Build of $INSTANCE_ID failed" $BUILD_COMPLETE_NOTIFY
exit 10
fi
echo "Build process has been started - it can take 5 to 20 minutes until your instance is ready." | `which mail` -r simon.marcel.pamies@sap.com -s "Build of $INSTANCE_ID starting" $BUILD_COMPLETE_NOTIFY
`pwd`/shouldIBuildOrShouldIGo.sh &> last_automatic_build.txt
STATUS=$?
if [ $STATUS -eq 0 ]; then
echo "Deployment Successful"
echo "OK" | `which mail` -a last_automatic_build.txt -r simon.marcel.pamies@sap.com -s "Build of $INSTANCE_ID complete" $BUILD_COMPLETE_NOTIFY
else
echo "Deployment Failed"
echo "ERROR" | `which mail` -a last_automatic_build.txt -r simon.marcel.pamies@sap.com -s "Build of $INSTANCE_ID failed" $BUILD_COMPLETE_NOTIFY
exit
fi
fi
PARAM=$@
# make some checks
@@ -54,12 +79,16 @@ REPLICATION_PARAMETERS="-Dreplication.start=$REPLICATE_ON_START -Dreplicate.mast
if [[ $PARAM == "" ]]; then
nohup $JAVA_BINARY -D$SERVER_NAME $ADDITIONAL_JAVA_ARGS -Dcom.sap.sailing.server.name=$SERVER_NAME $APP_PARAMETERS $REPLICATION_PARAMETERS -Djava.io.tmpdir=`pwd`/tmp -Dfile.encoding=cp1252 -Djetty.home=$scriptdir/configuration/jetty -Djava.util.logging.config.file=$scriptdir/configuration/logging.properties -Djava.library.path=$LIB_DIR -Xmx$MEMORY -jar plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar -console $TELNET_PORT -configuration ./ -clean 2>/dev/null >/dev/null &
echo "Starting server..."
JAVA_PID=$!
echo "Starting server... (PID: $JAVA_PID)"
sleep 10
TELNET_ACTIVE=`netstat -tlnp 2>/dev/null | grep ":$TELNET_PORT"`
if [[ $TELNET_PORT == "" ]] || [[ $TELNET_ACTIVE == "" ]]; then
SERVER_ACTIVE=`netstat -tlnp 2>/dev/null | grep ":$SERVER_PORT"`
if [[ $SERVER_PORT == "" ]] || [[ $SERVER_ACTIVE == "" ]]; then
echo "Something went wrong with startup. Please check the logs..."
if [[ $SERVER_STARTUP_NOTIFY != "" ]]; then
echo "Startup of java server failed - check the logs" | `which mail` -r simon.marcel.pamies@sap.com -s "Server $INSTANCE_ID startup failed!" $SERVER_STARTUP_NOTIFY
fi
exit
fi
@@ -72,8 +101,16 @@ if [[ $PARAM == "" ]]; then
echo "EXPEDITION_PORT: $EXPEDITION_PORT"
echo "REPLICATION_CHANNEL: $REPLICATION_CHANNEL"
echo "Started $SERVER_NAME - use telnet localhost $TELNET_PORT to connect to the OSGi console. Logs should be found in logs/sailing0.log.0"
if [[ $SERVER_STARTUP_NOTIFY != "" ]]; then
if [[ ! -z "$ON_AMAZON" ]]; then
echo "Go to http://$INSTANCE_DNS:$SERVER_PORT to reach your instance!" | `which mail` -s "Server $INSTANCE_ID started up!" -a env.sh $SERVER_STARTUP_NOTIFY
else
echo "OK" | `which mail` -s "Server $INSTANCE_ID started up!" -a env.sh $SERVER_STARTUP_NOTIFY
fi
fi
elif [[ $PARAM == "debug" ]]; then
echo "Starting remote debugging session on port 8000"
echo "Starting remote debugging session on port 8000 - make sure this port is open"
$JAVA_BINARY -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=y -D$SERVER_NAME $ADDITIONAL_JAVA_ARGS -Dcom.sap.sailing.server.name=$SERVER_NAME $APP_PARAMETERS $REPLICATION_PARAMETERS -Djava.io.tmpdir=`pwd`/tmp -Dfile.encoding=cp1252 -Djetty.home=$scriptdir/configuration/jetty -Djava.util.logging.config.file=$scriptdir/configuration/logging.properties -Djava.library.path=$LIB_DIR -Xmx$MEMORY -jar plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar -console -configuration ./ -clean
elif [[ $PARAM == "fg" ]]; then
$JAVA_BINARY -D$SERVER_NAME $ADDITIONAL_JAVA_ARGS -Dcom.sap.sailing.server.name=$SERVER_NAME $APP_PARAMETERS $REPLICATION_PARAMETERS -Djava.io.tmpdir=`pwd`/tmp -Dfile.encoding=cp1252 -Djetty.home=$scriptdir/configuration/jetty -Djava.util.logging.config.file=$scriptdir/configuration/logging.properties -Djava.library.path=$LIB_DIR -Xmx$MEMORY -jar plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar -console -configuration ./ -clean
+6
View File
@@ -5,6 +5,9 @@
TELNET_ACTIVE=`netstat -tlnp 2>/dev/null | grep ":$TELNET_PORT"`
if [[ $TELNET_PORT == "" ]] || [[ $TELNET_ACTIVE == "" ]]; then
echo "Could not find server on telnet port $TELNET_PORT. Perhaps server is not running?"
if [[ $SERVER_STARTUP_NOTIFY != "" ]]; then
echo "Stopped" | `which mail` -s "Server $SERVER_NAME could not be stopped!" $SERVER_STARTUP_NOTIFY
fi
exit
fi
@@ -12,3 +15,6 @@ NC_CMD="nc -t 127.0.0.1 $TELNET_PORT"
echo -n exit | $NC_CMD > /dev/null
echo "Stopped server $SERVER_NAME"
if [[ $SERVER_STARTUP_NOTIFY != "" ]]; then
echo "OK" | `which mail` -s "Server $SERVER_NAME stopped successfully!" $SERVER_STARTUP_NOTIFY
fi
+10 -27
View File
@@ -3,29 +3,25 @@
The following screenshots will help you creating a new Amazon application instance. An application instance is the container for exactly one Java application server. Each instance is configured using so called "user data". This configuration will then be read by the java server.
## AMI Selection
In the "Classic Wizard" select "My AMIs"
In the "Classic Wizard" select "My AMIs" and then select "Sailing Analytics Java Server"
<img src="/wiki/images/amazon/StartInstance1.JPG" width="70%" height="70%"/>
Make sure to select the AMI with the name "App"
Then select an instance type that matches what you want - be aware of the fact that t1.micro is not suitable for build process.
<img src="/wiki/images/amazon/StartInstance2.JPG" width="70%" height="70%"/>
Select a subnet that matches the one of the database server
Select a subnet that matches the one of the database server (in most cases this will be eu-west-1c). Leave other options untouched but scroll down to get to the "Advanced Options". There fill the user data field.
<img src="/wiki/images/amazon/StartInstance3.JPG" width="70%" height="70%"/>
Select the correct instance type. Micro also works if you don't want to put that much load on your server.
<img src="/wiki/images/amazon/StartInstance4.JPG" width="70%" height="70%"/>
Leave Kernel and RAM disk to Default. Then put the configuration for this server into the text area labeled "User Data". This configuration should at least contain `MONGODB_*` and `REPLICATION_*` parameters. Here one example:
<pre>
BUILD_BEFORE_START=True
BUILD_FROM=master
RUN_TESTS=False
SERVER_STARTUP-NOTIFY=simon.marcel.pamies@sap.com
BUILD_COMPLETE_NOTIFY=simon.marcel.pamies@sap.com
SERVER_NAME=LIVE1
MEMORY=1024m
REPLICATION_HOST=172.31.25.253
@@ -40,36 +36,23 @@ REPLICATE_MASTER_SERVLET_HOST=
REPLICATE_MASTER_SERVLET_PORT=
REPLICATE_MASTER_QUEUE_HOST=
REPLICATE_MASTER_QUEUE_PORT=
SERVER_STARTUP_NOTIFY=
</pre>
It does not really matter which SERVER_PORTS you use because there is only one app per instance. But this makes it easier to configure instances for Apache, a Load Balancer or other uses. If you want to create a cluster that is self-replicating and has a load balancer in front of it then make sure that all your instances are running on the same port.
It does not really matter which SERVER_PORT you use because there is only one app per instance. But this makes it easier to configure instances for Apache, a Load Balancer or other uses. If you want to create a cluster that is self-replicating and has a load balancer in front of it then make sure that all your instances are running on the same port!
Provide your instance with an useful name.
<img src="/wiki/images/amazon/StartInstance5.JPG" width="70%" height="70%"/>
Use a new interface for your Network. Do not change any other field.
Make absolutely sure to select the right Security Group. If you do not select the group "Sailing Analytics App" your server won't be able to access any database.
<img src="/wiki/images/amazon/StartInstance6.JPG" width="70%" height="70%"/>
Now make sure to click on the "Edit" button
Configure the key. Make sure to always use the "Administrator" key.
<img src="/wiki/images/amazon/StartInstance7.JPG" width="70%" height="70%"/>
In order to select "Delete on Termination" for your root volume
<img src="/wiki/images/amazon/StartInstance8.JPG" width="70%" height="70%"/>
Then give your instance a meaningful name by inserting a value for the tag "Name"
<img src="/wiki/images/amazon/StartInstance9.JPG" width="70%" height="70%"/>
Use the existing "Administrator" Key. Do NOT generate your own key - this won't work. In order to access instances you should've got two private keys. If not then contact one of the administrators.
<img src="/wiki/images/amazon/StartInstance10.JPG" width="70%" height="70%"/>
Then select the preconfigured security group "Sailing Analytics App". Do NOT select anything other than that or create your own.
<img src="/wiki/images/amazon/StartInstance11.JPG" width="70%" height="70%"/>
Your instance is now launching. You can create alarms if you want to monitor the state of the application. Be aware that monitoring is costy.
<img src="/wiki/images/amazon/StartInstance12.JPG" width="70%" height="70%"/>
+55 -11
View File
@@ -45,47 +45,53 @@ The architecture is divided into logical tiers. These are represented by firewal
<td><b>Name</b></td>
<td><b>Access Key(s)</b></td>
<td><b>Security Group</b></td>
<td><b>Open Ports</b></td>
<td><b>Services</b></td>
<td><b>Description</b></td>
</tr>
<tr>
<td>Webserver (Elastic IP: 54.229.94.254)</td>
<td>Administrator</td>
<td>IN: 20, 80, 443, 2010-2015<br/>OUT: ALL</td>
<td>Webserver</td>
<td>Apache, GIT, Piwik, Bugzilla</td>
<td>Apache, GIT, Piwik, Bugzilla, Wiki</td>
<td>This tier holds one instance that has one public Elastic IP associated. This instance manages all domains and subdomains associated with this project. It also contains the public GIT repository.</td>
</tr>
<tr>
<td>DB & Messaging</td>
<td>Administrator</td>
<td>IN: 22, 5672, 10200-10210, 27017<br/>OUT: ALL</td>
<td>Database and Messaging</td>
<td>MongoDB, MySQL</td>
<td>MongoDB, MySQL, RabbitMQ</td>
<td>All databases needed by either the Analytics applications or tools like Piwik and Bugzilla are managed by this instance.</td>
</tr>
<tr>
<td>Archive</td>
<td>Administrator, Sailing User</td>
<td>IN: 22, 2010-2015, 8880-8899<br/>OUT: ALL</td>
<td>Sailing Analytics App</td>
<td>Java App</td>
<td>Instance handling the access to all historical races.</td>
</tr>
<tr>
<td>Build and Test</td>
<td>Administrator, Sailing User</td>
<td>Sailing Analytics App</td>
<td>X11,Firefox,Hudson</td>
<td>Instance that can be used to run tests</td>
</tr>
</table>
## HowTo
### Create a new Analytics application instance
### Create a new Analytics application instance ready for production
Create a new Analytics instance as described in detail here [[wiki/amazon-ec2-create-new-app-instance]]. You should use a configuration like the following. If you want to bring the code to a defined level then make sure to specify the BUILD-FROM and BUILD-COMPLETE_NOTIFY variables. If you leave them empty the instance will start using a very old build.
Create a new Analytics instance as described in detail here [[wiki/amazon-ec2-create-new-app-instance]]. You should use a configuration like the following. If you want to bring the code to a defined level then make sure to specify the BUILD_FROM and BUILD_COMPLETE_NOTIFY variables. If you leave them empty the instance will start using a very old build.
Attention: You can not start the building process on t1.micro instances having less than 1.5 GB of RAM!
<pre>
BUILD_BEFORE_START=True
BUILD_FROM=master
RUN_TESTS=False
SERVER_STARTUP_NOTIFY=simon.marcel.pamies@sap.com
COMPILE_GWT=True
BUILD_COMPLETE_NOTIFY=simon.marcel.pamies@sap.com
SERVER_NAME=LIVE1
MEMORY=1024m
REPLICATION_HOST=172.31.25.253
@@ -100,15 +106,53 @@ REPLICATE_MASTER_SERVLET_HOST=
REPLICATE_MASTER_SERVLET_PORT=
REPLICATE_MASTER_QUEUE_HOST=
REPLICATE_MASTER_QUEUE_PORT=
SERVER_STARTUP_NOTIFY=
</pre>
After your instance has been started (and build and tests are through) it will be publicly reachable if you chose a port between 8090 and 8099. If you filled the SERVER-STARTUP-NOTIFY field then you will get an email once the server has been started.
After your instance has been started (and build and tests are through) it will be publicly reachable if you chose a port between 8090 and 8099. If you filled the BUILD_COMPLETE_NOTIFY field then you will get an email once the server has been built. You can also add your email address to the field SERVER_STARTUP_NOTIFY to get an email whenever the server has been started.
You can now access this instance by either using the Administrator key (for root User) or the Sailing User key (for user sailing):
<pre>
ssh -i .ssh/Administrator.pem root@ec2-54-246-247-194.eu-west-1.compute.amazonaws.com
</pre>
or
<pre>
ssh -i .ssh/SailingUser.pem sailing@ec2-54-246-247-194.eu-west-1.compute.amazonaws.com
</pre>
If you want to connect your instance to a subdomain then log onto the main webserver with the Administrator key as root, open the file `/etc/httpd/conf.d/001-events.conf` and put something like this there. As you can see you have to specify the IP address and the port the java server is running on. Make sure to always use the internal IP.
<pre>
Use Spectator idm.sapsailing.com "505 IDM 2013" 172.31.22.12 8888
</pre>
### Testing code on a server
Starting a test is as easy as starting up a new instance. Just make sure that you fill the field RUN_TESTS and set it to `True`. Also set the field BUILD_FROM to a gitspec that matches the code branch that you want to test. After tests has been run and the server has been started you will get an email giving you all the details. You can then access your instance or simply shut it down.
### Setup replicated instances with ELB
The main concept behind ELB is that there is one instance that you configure in the "Load Balancers" tab that serves as the main entry point for all requests going to your application. This instance can be told to pass through requests from one port to another. In order to make this ELB instance aware of the Analytics EC2 Instances it should balance over you need to add all instances that should be part of the setup to the ELB instance.
A closer look reveals that an ELB instance consists itself of many other invisible instances. These are behind a DNS round robin configuration that redirects each incoming request to one of these instances. These invisible instances then decide upon the rules you've created how and where to distribute this request to one of the associated instances.
### Access build server and tests
Here are the steps to create a load balanced setup:
- Create a master instance holding all data
- Create `n` instances that are configured to connect to the master server
- Create a load balancer that redirects everything from port 80 to let's say port 8888.
- Associate all your instances
- Connect your domain with the IP of the load balancer. It could be a good idea to use an Elastic IP that always stays the same for the domain and associate it with your load balancer. That way you can also easily switch between a load balancer and a single instance setup.
Two things are still needed before this setup can be executed:
- Make it possible to configure instances that way that they automatically connect to a master upon start
- Check what happens if the ELB acts as a transparent proxy not revealing the underlying instance name and address (should be)
Amazon ELB is designed to handle unlimited concurrent requests per second with “gradually increasing” load pattern (although it's initial capacity is described to reach 20k requests/secs). It is not designed to handle heavy sudden spike of load or flash traffic because of it's internal structure where it needs to fire up more instances when load increases. ELB's can be pre-warmed though by writing to the AWS Support Team.
### Access MongoDB database
Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 340 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 531 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 410 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 432 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 414 KiB

+21
View File
@@ -0,0 +1,21 @@
# ORC/IRC support
## Rationale
## Purpose
Providing...
## Features
* Support for different handicap scoring systems
* Time On Time
* Time On Distance
* Performance Curve
* Performance Line
## Synergies
## Risks
+15 -1
View File
@@ -148,4 +148,18 @@ Competitor c = competitorDeserializer.deserialize(json);
3. Whenever you add a Domain Object to an instance, it somehow has to be replicated to the other instances. To do so, create an Operation which you can then `apply()` to the `RacingEventService`, which will then replicate it to other intsances (the operations are basically commands as in the Command pattern, with the added difficulty of operational transformation to provide a uniform final state when operations are applied in different orders on different instances). Internally, the apply-mechanism writes to an `ObjectOutputStream`, which on the other side is evaluated by an `ObjectInputStreamResolvingAgainstDomainFactory`. For this reason, all objects implementing the `IsManagedBySharedDomainFactory` interface are resolved against the domain factory via their `resolve()` implementation. This removes the chance of duplicate instances representing the same actual object.
4. Also, whenever a replica (slave) instance registers with the master instance, it is provided with the current state of the master as an initial load. To do so, the master instance exports its state via the `serializeForInitialReplication()` method in the `RacintEventServiceImpl`, while the replica recieves the object stream output by the master via the `initiallyFillFrom()` method. Again, an `ObjectInputStreamResolvingAgainstDomainFactory` is used.
4. Also, whenever a replica (slave) instance registers with the master instance, it is provided with the current state of the master as an initial load. To do so, the master instance exports its state via the `serializeForInitialReplication()` method in the `RacintEventServiceImpl`, while the replica recieves the object stream output by the master via the `initiallyFillFrom()` method. Again, an `ObjectInputStreamResolvingAgainstDomainFactory` is used.
## Import Another Year of Magnetic Declination Values
Under java/com.sap.sailing.declination/resources we store magnetic declination values, using one file per year. The resolution at which we usually store those is one degree of latitude and longitude, each. When for a year those values aren't found in a file, an online request is performed to the [NOAA Service](http://www.ngdc.noaa.gov/geomag-web/) which can be time and bandwidth consuming. Therefore, it is a good idea to keep a file with cached declination values around for the current year.
To produce such a file, use the `main(...)` method of class `com.sap.sailing.declination.impl.DeclinationStore`. There are pre-defined launch configurations in place in the com.sap.sailing.declination bundle project. Adjust the from/to year parameters for the current year. The process usually takes several hours to complete at a one-degree resolution. Don't forget to commit the resulting resources/declination-<year> file to git.
Experience has shown that sometimes the SAP HTTP proxy doesn't properly resolve the NOAA service. In those cases, it is more convenient to run the process from either sapsailing.com or stg.sailtracks.de, using something like following command from a server's plugins/ directory after creating the resources/ subdirectory:
`java -cp com.sap.sailing.domain_*.jar:com.sap.sailing.domain.common_*.jar:com.sap.sailing.declination_*.jar:com.sap.sailing.domain.shared.android_*.jar com.sap.sailing.declination.impl.DeclinationStore 2014 2014 1`
Run this inside a tmux window to be sure that logging off does not interrupt the process. After the process completes, copy the resulting declination-<year> file to your git workspace to `java/com.sap.sailing.declination/resources` and commit.
There is also a script java/target/importdeclination that automates these steps.