Merge branch 'master' into dev

This commit is contained in:
Axel Uhl (Server) committed 2013-02-26 04:20:41 +01:00
commit d281463633
15 files changed
+339 -25

No files matched your search

+10 -1
View File
@@ -2,10 +2,16 @@
# this holds for default installation
USER_HOME=~
echo PROJECT_HOME is $PROJECT_HOME
if [ "$PROJECT_HOME" = "" ]; then
PROJECT_HOME=$USER_HOME/git
fi
if [ ! -d $PROJECT_HOME/.git ]; then
echo "Could not identify $PROJECT_HOME as git repository. Please make sure to set PROJECT_HOME to the right one."
exit
fi
echo PROJECT_HOME is $PROJECT_HOME
SERVERS_HOME=$USER_HOME/servers
# x86 or x86_64 should work for most cases
@@ -20,7 +26,9 @@ active_branch=$(git symbolic-ref -q HEAD)
active_branch=`basename $active_branch`
ACDIR=$SERVERS_HOME/$active_branch
MAVEN_SETTINGS=$PROJECT_HOME/configuration/maven-settings.xml
MAVEN_SETTINGS_PROXY=$PROJECT_HOME/configuration/maven-settings-proxy.xml
gwtcompile=1
testing=1
@@ -101,6 +109,7 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
if [ $proxy -eq 1 ]; then
echo "INFO: Activating proxy profile"
extra="$extra -P no-debug.with-proxy"
MAVEN_SETTINGS=$MAVEN_SETTINGS_PROXY
else
extra="$extra -P no-debug.without-proxy"
fi
+39
View File
@@ -0,0 +1,39 @@
<settings>
<servers>
<server>
<id>ssh-repository</id>
<filePermissions>664</filePermissions>
<directoryPermissions>775</directoryPermissions>
</server>
</servers>
<proxies>
<proxy>
<active>true</active>
<protocol>http</protocol>
<host>proxy.wdf.sap.corp</host>
<port>8080</port>
<nonProxyHosts>localhost|*.sap.corp</nonProxyHosts>
</proxy>
</proxies>
<profiles>
<profile>
<id>sailing.analytics</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!-- Leave empty, if no proxy is needed in your environment! -->
<parameters.proxy>
</parameters.proxy>
<!-- Change the configuration file to the one you like to use for the tests. -->
<parameters.integration-tests>
-Dselenium.test.environment.configuration=ci-test-environment.xml
</parameters.integration-tests>
</properties>
</profile>
</profiles>
</settings>
+29 -21
View File
@@ -6,31 +6,39 @@ sn=sailing
SERVERS_DIR=/home/trac/servers
# options
tmux set-option default-path /home/trac/
tmux set-option default-shell /bin/bash
TMUX_ACTIVE=`tmux has-session -t $sn 2>/dev/null`
if [ $? -eq 0 ]; then
echo "Session exists...not configuring a new one"
else
echo "Session does not exist...creating a new one with name $sn"
cd /home/trac/git
tmux new-session -s "$sn" -n "BUILD" -d
cd /home/trac/git
tmux new-session -s "$sn" -n "BUILD" -d "bash -c 'git symbolic-ref -q HEAD && echo \"./buildAndUpdateProduct.sh install\"'; bash"
counter=1
for dir in dev test prod1 prod2; do
cd $SERVERS_DIR/$dir
tmux new-window -t "$sn:$counter" -n `basename $dir` "bash -c './start'; bash"
counter=$[counter + 1]
done
counter=1
for dir in dev test prod1 prod2; do
cd $SERVERS_DIR/$dir
tmux new-window -t "$sn:$counter" -n `basename $dir` "bash -c 'start'; bash"
counter=$[counter + 1]
done
cd /home/trac/servers/prod1
tmux new-window -t "$sn:$counter" -n "UDP" "bash -c './udpmirror -v 2012 localhost 2010 localhost 2011 localhost 2013 localhost 2014'; bash"
cd /home/trac/servers/prod1
tmux new-window -t "$sn:$counter" -n "UDP" "bash -c 'echo \"./udpmirror -v 2012 localhost 2010 localhost 2011 localhost 2013 localhost 2014\"'; bash"
cd /opt/mongodb/bin
tmux new-window -t "$sn:$[counter+1]" -n "GOAccess" "bash -c 'goaccess -f /var/log/httpd/access_log'; bash"
cd /opt/mongodb/bin
tmux new-window -t "$sn:$[counter+1]" -n "MongoDf" "bash -c './mongod --dbpath ../data/mongodb-default'; bash"
cd /opt/
tmux new-window -t "$sn:$[counter+2]" -n "ATop" "bash -c 'apachetop -f /var/log/httpd/access_log'; bash"
cd /opt/
tmux new-window -t "$sn:$[counter+2]" -n "ATop" "bash -c 'apachetop -f /var/log/httpd/access_log'; bash"
cd /home/trac/servers
tmux new-window -t "$sn:$[counter+3]" -n "Logs" "bash -c 'ls -lah'; bash"
cd /home/trac/servers
tmux new-window -t "$sn:$[counter+4]" -n "Logs" "bash -c 'ls -lah'; bash"
cd /home/trac/servers/prod1
tmux new-window -t "$sn:$[counter+4]" -n "STListener" "bash -c './swisstiminglistener 3500 3501'; bash"
tmux select-window -t "$sn:0"
tmux -2 attach-session -t "$sn"
tmux select-window -t "$sn:0"
fi
if [[ "$1" != "unattended" ]]; then
tmux -2 attach-session -t "$sn"
fi
@@ -28,6 +28,7 @@ public enum DetailType implements Serializable {
TOTAL_TIME_SAILED_UPWIND_IN_SECONDS(1, ASCENDING),
TOTAL_TIME_SAILED_REACHING_IN_SECONDS(1, ASCENDING),
MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS(1, DESCENDING),
TOTAL_DISTANCE_TRAVELED(0, ASCENDING), TOTAL_AVERAGE_SPEED_OVER_GROUND(2, DESCENDING),
TOTAL_TIME_SAILED_IN_SECONDS(1, ASCENDING), RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS(2, DESCENDING);
private int precision;
@@ -8,6 +8,7 @@ import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.Named;
@@ -354,7 +355,17 @@ public interface Leaderboard extends Named {
* races attached to this leaderboard
*/
Long getTotalTimeSailedInMilliseconds(Competitor competitor, TimePoint timePoint);
/**
* Computes the distance the <code>competitor</code> has sailed in the tracked races in this leaderboard, starting
* to count in each race when the competitor passes the start line, aggregating up to <code>timePoint</code> or the
* end of the last race, whichever is first.
*
* @return <code>null</code> if the <code>competitor</code> hasn't sailed any distance in any tracked race in this
* leaderboard
*/
Distance getTotalDistanceTraveled(Competitor competitor, TimePoint timePoint);
/**
* Same as {@link #getTotalPoints(Competitor, RaceColumn, TimePoint)}, only that for determining the discarded
* results only <code>raceColumnsToConsider</code> are considered.
@@ -17,6 +17,7 @@ import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.NoWindException;
@@ -661,6 +662,24 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
return result;
}
@Override
public Distance getTotalDistanceTraveled(Competitor competitor, TimePoint timePoint) {
Distance result = null;
for (TrackedRace trackedRace : getTrackedRaces()) {
if (Util.contains(trackedRace.getRace().getCompetitors(), competitor)) {
Distance distanceSailedInRace = trackedRace.getDistanceTraveled(competitor, timePoint);
if (distanceSailedInRace != null) {
if (result == null) {
result = distanceSailedInRace;
} else {
result = result.add(distanceSailedInRace);
}
}
}
}
return result;
}
protected RaceColumnListeners getRaceColumnListeners() {
return raceColumnListeners;
}
@@ -388,6 +388,9 @@ public interface TrackedRace extends Serializable {
void removeListener(RaceChangeListener listener);
/**
* @return <code>null</code> if there are no mark passings for the <code>competitor</code> in this race
*/
Distance getDistanceTraveled(Competitor competitor, TimePoint timePoint);
Distance getWindwardDistanceToOverallLeader(Competitor competitor, TimePoint timePoint) throws NoWindException;
@@ -69,6 +69,8 @@ public class DetailTypeFormatter {
return stringMessages.averageCrossTrackErrorInMeters();
case MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS:
return stringMessages.maximumSpeedOverGroundInKnots();
case TOTAL_DISTANCE_TRAVELED:
return stringMessages.totalDistanceTraveled();
case TOTAL_TIME_SAILED_DOWNWIND_IN_SECONDS:
return stringMessages.totalTimeSailedDownwindInSeconds();
case TOTAL_TIME_SAILED_UPWIND_IN_SECONDS:
@@ -77,6 +79,8 @@ public class DetailTypeFormatter {
return stringMessages.totalTimeSailedReachingInSeconds();
case TOTAL_TIME_SAILED_IN_SECONDS:
return stringMessages.totalTimeSailedInSeconds();
case TOTAL_AVERAGE_SPEED_OVER_GROUND:
return stringMessages.totalAverageSpeedOverGround();
case AVERAGE_MANEUVER_LOSS_IN_METERS:
return stringMessages.averageManeuverLossInMeters();
case AVERAGE_TACK_LOSS_IN_METERS:
@@ -103,6 +107,7 @@ public class DetailTypeFormatter {
case RACE_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS:
case VELOCITY_MADE_GOOD_IN_KNOTS:
case AVERAGE_SPEED_OVER_GROUND_IN_KNOTS:
case TOTAL_AVERAGE_SPEED_OVER_GROUND:
return stringMessages.knotsUnit();
case WINDWARD_DISTANCE_TO_OVERALL_LEADER:
@@ -115,6 +120,7 @@ public class DetailTypeFormatter {
case AVERAGE_MANEUVER_LOSS_IN_METERS:
case AVERAGE_CROSS_TRACK_ERROR_IN_METERS:
case RACE_AVERAGE_CROSS_TRACK_ERROR_IN_METERS:
case TOTAL_DISTANCE_TRAVELED:
return stringMessages.metersUnit();
case GAP_TO_LEADER_IN_SECONDS:
@@ -229,6 +235,10 @@ public class DetailTypeFormatter {
return stringMessages.totalTimeSailedReachingInSecondsTooltip();
case TOTAL_TIME_SAILED_UPWIND_IN_SECONDS:
return stringMessages.totalTimeSailedUpwindInSecondsTooltip();
case TOTAL_DISTANCE_TRAVELED:
return stringMessages.totalDistanceTraveledTooltip();
case TOTAL_AVERAGE_SPEED_OVER_GROUND:
return stringMessages.totalAverageSpeedOverGroundTooltip();
case WINDWARD_DISTANCE_TO_GO_IN_METERS:
return stringMessages.windwardDistanceToGoInMetersTooltip();
}
@@ -504,4 +504,8 @@ public interface StringMessages extends Messages {
String angleAndTotalNumberOfDataPoints(int angle, int numberOfDataPoints);
String buoyZone();
String radiusInMeters();
String totalDistanceTraveled();
String totalDistanceTraveledTooltip();
String totalAverageSpeedOverGround();
String totalAverageSpeedOverGroundTooltip();
}
@@ -416,6 +416,10 @@ totalTimeSailedReachingInSeconds=Total time reaching
totalTimeSailedReachingInSecondsTooltip=The total time the competitor sailed on reaching legs in the regatta.
totalTimeSailedInSeconds=Total time
totalTimeSailedInSecondsTooltip=The total time the competitor sailed in the regatta.
totalDistanceTraveled=Total distance
totalDistanceTraveledTooltip=The total distance sailed in the regatta.
totalAverageSpeedOverGround=\u2205 SOG
totalAverageSpeedOverGroundTooltip=Average speed over ground across the regatta.
hhmmssUnit=hh:mm:ss
actionAddWindData=Add wind data
valueMustBeBetweenMinMax=The value of ''{0}'' must be between {1} and {2}.
@@ -505,4 +509,4 @@ histogram=Histogram
numberOfDataPoints=Number of data points
angleAndTotalNumberOfDataPoints=Angle: {0}; Total number of data-points: {1}
buoyZone=Buoy zone
radiusInMeters=Radius (m)
radiusInMeters=Radius (m)
@@ -417,6 +417,10 @@ totalTimeSailedReachingInSeconds=Gesamtzeit Holeschlag
totalTimeSailedReachingInSecondsTooltip=Gesamtzeit, die der Teilnehmer in der Regatta auf Holeschlägen gesegelt ist.
totalTimeSailedInSeconds=Gesamtzeit
totalTimeSailedInSecondsTooltip=Gesamtzeit, die der Teilnehmer für die Regatta gebraucht hat.
totalDistanceTraveled=Gesamtdistanz
totalDistanceTraveledTooltip=Gesamtdistanz, die der Teilnehmer in der Regatta zurückgelegt hat.
totalAverageSpeedOverGround=\u2205 FüG
totalAverageSpeedOverGroundTooltip=Durchschnittliche Fahrt über Grund über die gesamte Regatta.
hhmmssUnit=hh:mm:ss
actionAddWindData=Winddaten hinzufügen
valueMustBeBetweenMinMax=Der Wert von ''{0}'' muß zwischen {1} und {2} sein.
@@ -51,6 +51,7 @@ import com.google.gwt.view.client.SelectionModel;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.InvertibleComparator;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.Mile;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.SortingOrder;
@@ -781,7 +782,9 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
}
public static DetailType[] getAvailableOverallDetailColumnTypes() {
return new DetailType[] { DetailType.TOTAL_TIME_SAILED_DOWNWIND_IN_SECONDS,
return new DetailType[] { DetailType.TOTAL_DISTANCE_TRAVELED,
DetailType.TOTAL_AVERAGE_SPEED_OVER_GROUND,
DetailType.TOTAL_TIME_SAILED_DOWNWIND_IN_SECONDS,
DetailType.TOTAL_TIME_SAILED_UPWIND_IN_SECONDS,
DetailType.TOTAL_TIME_SAILED_REACHING_IN_SECONDS,
DetailType.TOTAL_TIME_SAILED_IN_SECONDS, DetailType.MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS };
@@ -1403,6 +1406,20 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
raceNameForDefaultSorting = settings.getNameOfRaceToSort();
}
private static class TotalDistanceTraveledInMetersField implements LegDetailField<Double> {
@Override
public Double get(LeaderboardRowDTO row) {
return row.totalDistanceTraveledInMeters;
}
}
private static class TotalAverageSpeedOverGroundField implements LegDetailField<Double> {
@Override
public Double get(LeaderboardRowDTO row) {
return row.totalDistanceTraveledInMeters / row.totalTimeSailedInSeconds / Mile.METERS_PER_NAUTICAL_MILE * 3600;
}
}
private static class KingOfTheDownwindField implements LegDetailField<Double> {
@Override
public Double get(LeaderboardRowDTO row) {
@@ -1433,6 +1450,14 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
private Map<DetailType, SortableColumn<LeaderboardRowDTO, ?>> createOverallDetailColumnMap() {
Map<DetailType, SortableColumn<LeaderboardRowDTO, ?>> result = new HashMap<DetailType, SortableColumn<LeaderboardRowDTO, ?>>();
result.put(DetailType.TOTAL_DISTANCE_TRAVELED,
new FormattedDoubleDetailTypeColumn(DetailType.TOTAL_DISTANCE_TRAVELED,
new TotalDistanceTraveledInMetersField(), RACE_COLUMN_HEADER_STYLE, RACE_COLUMN_STYLE));
result.put(DetailType.TOTAL_AVERAGE_SPEED_OVER_GROUND,
new FormattedDoubleDetailTypeColumn(DetailType.TOTAL_AVERAGE_SPEED_OVER_GROUND,
new TotalAverageSpeedOverGroundField(), RACE_COLUMN_HEADER_STYLE, RACE_COLUMN_STYLE));
result.put(DetailType.MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS, new MaxSpeedOverallColumn(RACE_COLUMN_HEADER_STYLE,
RACE_COLUMN_STYLE));
@@ -620,6 +620,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
row.totalTimeSailedReachingInSeconds = totalTimeSailedReachingInMilliseconds==null?null:1./1000.*totalTimeSailedReachingInMilliseconds;
final Long totalTimeSailedInMilliseconds = leaderboard.getTotalTimeSailedInMilliseconds(competitor, timePoint);
row.totalTimeSailedInSeconds = totalTimeSailedInMilliseconds==null?null:1./1000.*totalTimeSailedInMilliseconds;
final Distance totalDistanceTraveledInMeters = leaderboard.getTotalDistanceTraveled(competitor, timePoint);
row.totalDistanceTraveledInMeters = totalDistanceTraveledInMeters==null?null:totalDistanceTraveledInMeters.getMeters();
}
private List<CompetitorDTO> getCompetitorDTOList(List<Competitor> competitors) {
@@ -21,6 +21,7 @@ public class LeaderboardRowDTO implements IsSerializable {
public Date whenMaximumSpeedOverGroundWasAchieved;
public Double totalTimeSailedUpwindInSeconds;
public Double totalTimeSailedReachingInSeconds;
public Double totalDistanceTraveledInMeters;
@Override
public int hashCode() {
+174
View File
@@ -0,0 +1,174 @@
**Scoring software:**
***
Altura:
***
Cyber Altura is free Windows software covering all options of ORC scoring. It does not have any limit in fleet size, number of events, number of races etc.
All outputs can be configured, adding or removing fields that appear in the listings. Boat data can be imported through RMS files which are immediately updated by every new certificate issued by any Rating Office. A fully functional version is available for download, but expect occasional updates or newer improved versions.
Cyber Altura can be downloaded for free from its website, where there are also all explanations and instructions.
[Cyber Altura](http://www.cyberaltura.com/orc/inicio/inicio_en.php)
Velumn:
***
Velum software is fully-compatible with ISAF and ORC scoring rules and can import data from RMS files. It is based on 30 years experience in 300 software licenses worldwide, countless regattas, numerous high-ranking championships, and is used in some of the world’s largest regattas (Nordsee-Woche, Kieler-Woche, Travemünder-Woche, etc.). Velum offers huge flexibility in defining the scoring groups: a yacht can be scored in many different ways and in different scoring groups that may also include other subgroups. Velum is available on its website for a certain fee depending on using the full version or just an update.
[Velumn](http://www.velumng.com/index.html)
**Scoring:**
***
**Time on distance:**
***
Corrected time is calculated as follows:
Corrected time = Elapsed time – (ToD * Distance)
With Time-on-Distance (ToD) scoring, the coefficient of time allowance of one boat will not change with wind velocity, but will change with the length of the course. One boat will always give to another the same handicap in sec/mi, and it is easy to calculate the difference in elapsed time between two boats needed to determine a winner in corrected time.
A special ToD coefficient calculated with an average crew weight of 170 kg is available for double handed racing as well as one calculated for non-spinnaker racing.
Where is it shown on the certificate?
![certificate](http://www.orc.org/images/certificates/2013/time%20on%20distance.png)
Time on Distance scoring coefficients on simple scoring options on
ORC International and ORC Club certificates
**How is it calculated?**
***
Offshore Time on Distance scoring coefficient also known as OSN (offshore single number) is calculated as a weighted average of the predicted boat speeds in following conditions:
The resulting time allowances at wind of 8 knots will be accounted with 25 %, the one at 12 knots with 50% and that at 16 knots with 25%.
The above scheme takes into account more windward/leeward directions in light winds, which is gradually reduced to have more reaching as the wind increases.
Double handed coefficient is calculated using the same OSN method with crew weight of 170 kg, while non-spinnaker rating is calculated for boat's performance without spinnaker.
**Inshore Time on Distance** scoring coefficients is calculated as the average of windward/leeward course (50 - 50 %) time allowances in three conditions multiplied by their respective weights:
- 25 % of Windward/Leeward at 8 knots
- 40 % of Windward/Leeward at 12 knots
- 35 % of Windward/Leeward at 16 knots
**Time on time:**
Corrected time is calculated as follows:
**Corrected time = ToT * Elapsed time**
With Time-On-Time (ToT) scoring, the time allowance will increase progressively as the wind velocity increases. Course distance has no effect on the results and need not be measured. Corrected time will depend only on the elapsed time, and the difference between boats may be seen in seconds depending of the duration of the races. The longer the race in time, the larger the handicap.
Where is it shown in the certificate ?
![Certificate](http://www.orc.org/images/certificates/2013/time%20on%20time.png)
**How is it calculated?**
Offshore Time on Time scoring coefficient is calculated as:
600 / Offshore ToD
Inshore Time on Time scoring coefficient is calculated as:
675 / Inshore ToD
**Performance Line:**
**Corrected time is calculated as follows:**
**Corrected time = (PLT * Elapsed time) – (PLD * Distance)**
With the time coefficient PLT and distance coefficient PLD, two boats may be rated differently in light or heavy wind conditions, and it is possible that one boat is giving a handicap to another in light wind conditions, while the opposite may be true in heavy wind conditions.
**Where is it shown in the certificate?**
![Certificate](http://www.orc.org/images/certificates/2013/performance%20line.png)
**How is it calculated?**
Performance Line Scoring is a simplified variation of Performance Curve Scoring, where the curve of time allowances as a function of seven wind speeds is simplified by a straight line intercepting the performance points at 8 and 16 knots of wind for a given course. This is shown as follows:
![Certficate](http://www.orc.org/images/certificates/2013/perfline.JPG)
Offshore Performance Line coefficients are calculated using time allowances for the Ocean type of pre-selected course.
Inshore Performance Line coefficients are calculated using time allowances for the Windward/leeward type of pre-selected course.
**Performance Curve Scoring:**
***
**Performance Curve Scoring:**is the most powerful engine of the ORC International (ORCi) rating system. It is this unique feature which makes this rule fundamentally different from any other handicap system, as it recognizes that yachts of varied design perform differently when conditions change.
This means that yachts of different designs will have different time allowances in each race depending on the weather conditions and the course configuration for that particular race. For example, heavy under-canvassed boats are slow in light airs but fast in strong winds, boats with deep keels go well to windward, and light boats with small keels will go fast downwind.
**Where is it shown in the certificate**?
![Certificate](http://www.orc.org/images/certificates/2013/Performance%20Curve%20Scoring.png)
An ORCi certificate provides a range of ratings (time allowances expressed in s/NM) for wind conditions in the range of 6 – 20 knots of true wind speed, and at angles varying from an optimum VMG beat to 52, 60, 75, 90, 110, 120, 135, 150 degrees of true wind angle, as well as the optimum VMG run angle.
Windward/Leeward (up and down) is a conventional course around windward and leeward marks where the race course consists of 50% upwind and 50% downwind legs.
Circular Random is a hypothetical course type in which the boat circumnavigates a circular island with the true wind direction held constant.
Ocean for PCS is a composite course, the content of which varies progressively with true wind velocity from 30% Windward/Leeward, 70% Circular Random at 6 knots to 100% Circular Random at 12 knots and 20% Circular Random, 80% reach at 20 knots.
**How is it calculated**?
The use of PCS is not as complicated as it may appear. It requires the Race Committee provide only a little more data in addition to their usual work of setting up the course, following the wind changes, making starts and taking finishing times. There are different varieties of Scoring software that will do all calculations, which enables results to be ready as soon as the elapsed times of the race are entered.
**Step 1: Define the curse**
Course may be selected from one of 4 Pre-defined types above or simply constructed with following parameters for each leg:
- distance
- course bearing
- wind direction
![Course](http://www.orc.org/images/certificates/2013/course.JPG)
Typical course definition. Distance and bearings of each leg are entered, as is the approximate wind direction. Note wind speed is not entered.
Current velocity and direction can also be entered for each leg, if it is known
**Step 2: Prepare the scratch sheet**
For any of the selected courses described above, the true wind angle is calculated as being the difference between the wind direction and compass bearing of each leg. With this information, a table is made for each boat that describes the theoretical speed of the boat over that course for a variety of wind conditions. With this data a curve can be plotted which represents the predicted optimum performance along a scale of wind speeds. This curve is called the Performance Curve, and for each yacht this curve is different for any different course sailed.
**Step 3: Calculate implied Wind**
Performance curve for each boat:
![Curve](http://www.orc.org/images/certificates/2013/pcs1.JPG)
![Curve](http://www.orc.org/images/certificates/2013/pcs2.JPG)
In a typical Performance Curve plot, the vertical axis represents the speed achieved in the race, expressed in seconds per mile. The horizontal axis represents the wind speed in knots. When the finishing time of Yacht A is known, its elapsed time is divided by the distance of the course to determine the average speed in seconds per mile. This number is represented by point A on the vertical axis. The computer then finds the point on the horizontal axis that corresponds for that course to the average speed obtained.
This results in point Aw, the so-called “Implied Wind.” This means that the yacht has completed the course “as if” it has encountered that wind speed. The faster the boat has sailed, the higher the Implied Wind, which is the primary index used for scoring: the yacht with the highest Implied Wind wins the race. The Implied Wind can then be transformed into a corrected time.
The Implied Wind is intended as an interpolation between time allowances, not an extrapolation. This means that when the Implied Wind drops below 6 knots or raises above 20 knots, the time allowances used for calculating the corrected times will be those of 6 knots and 20 knots respectively. This does not mean that ORC races need to be stopped (or not started) with wind below 6 knots or above 20. When the “implied wind” results calculate to be lass than 6 knots or more than 20, the corrected time values at these wind speeds are then used.
In order to present the result of the race in a comprehensive format we use a “Scratch Boat” (Figure 2). In most cases this is the potentially fastest boat of the fleet, shown in the example as yacht B. Being the fastest, her Performance Curve is the lowest in the figure. From the point where the vertical line yacht A intersects with the curve of the Scratch Boat, a horizontal line is drawn to the left towards the vertical axis. This point, Ac, produces the corrected time when the seconds per mile are multiplied by the distance of the course in miles. The corrected time of the Scratch Boat is, by definition, the same as its elapsed time. This exercise produces corrected times, expressed in hours, minutes and seconds, a familiar format for most sailors.
“Implied Wind” for the winning boat is thus normally in the range of the actual average wind strength for the race. However, in cases where the “Implied Wind” does not fairly represent the real wind strength during a race, the Fixed Wind method may be used to enter the performance curve with the predominant wind speed at the horizontal axis, thus obtaining the appropriate Time allowance at the vertical axis. Such a time allowance can then be used as a single number Time-on-Distance coefficient.