Merge remote-tracking branch 'origin/master' into bug4134_2

This commit is contained in:
Alessandro Stoltenberg
2018-08-21 10:42:48 +02:00
37 changed files with 251 additions and 45 deletions
+12 -4
View File
@@ -18,7 +18,7 @@ BACKUP_DIRECTORIES="/etc /var/log/mongodb"
PREFIX="database"
# Directory for temporary files
TARGET_DIR=/var/lib/mysql/backup
TARGET_DIR=/var/lib/mongodb/backup
# Configuration for MongoDB backup
MONGO_PORTS="10202 10201"
@@ -26,7 +26,7 @@ MONGO_INSTALLATION=/opt/mongodb-linux-x86_64-2.6.7
MONGO_CMD=$MONGO_INSTALLATION/bin/mongo
MONGOEXPORT_CMD=$MONGO_INSTALLATION/bin/mongoexport
MONGODB_COLLECTION_WIND="WIND_TRACKS"
MONGODB_COLLECTION_LOCAL="local"
MONGODB_EXCLUDE_DBS="local 29erWorlds2016 29erWorlds2016-replica 49er-n17-euros2017 49er-n17-euros2017-replica 49erEuros2015 49erEuros2016 49erEuros2016-replica 49erJWC2015 49erWorlds_2016 49erWorlds_2016-replica 49erWorlds_2016-replica2 49erWorlds_2016-replica3 49erworlds2015 505-2017 505-2017-replica 505-2017-replica-1 505-2017-replica-2 505Worlds2016 505Worlds2016-replica 505_WORLDS_2015 6mworlds2017 6mworlds2017-replica 8MWORLDS2017 8MWORLDS2017-replica AustrianLeague2015 Bodenseewoche_2015 Championsleague_2015 Championsleague_2015-Replica DANISHLEAGUE2017 DANISHLEAGUE2017-replica DUTCH_LEAGUE_2017 DUTCH_LEAGUE_2017-replica DanishSailingLeague_2015 DutchSailingLeague_2015 FinnishSailingLeague_2015 GermanSailingLeague_2015 GermanSailingLeague_2015-Replica HANSESAIL2017 IDMFINN2017 KW2015 KW2015-replica KW2015-replica2 KW2017 KW2017-replica Norwegianleague_2015 POLISHLEAGUE2017 RosAtomCup_2015 SAPOPTICUP2015 SCL2017 SCL2017-replica SGCN_Smartphone_2016 SGCN_Smartphone_2016-replica SPEEDSAILING2016 SWC2016-Melbourne SWC2016-Melbourne-replica SWC2016-Qingdao SWC2016-Qingdao-replica SWC2017-Aarhus SWC2017-HYERES SWC2017-HYERES-replica SWC2017-Miami SWC2017-Miami-replica SWC2017-SANTANDER SWC2017-SANTANDER-replica SWEDISHLEAGUE2017 SWEDISHLEAGUE2017-replica TW2015 TW2015-REPLICA TW2015-test-replica TW2017 TW2017-replica WORLDCUPSYLT2015 YES2015 YES2015-REPLICA YES2015-REPLICA2 allsvenskan2015 austrianleague2016 austrianleague2017 bartsbash2015 bundesliga2-2017 bundesliga2-2017-replica bundesliga2016 bundesliga2016-replica bundesliga2016_2 bundesliga2017 bundesliga2017-replica crw2016 crw2016-replica danishleague2016 danishleague2016-replica dsl-pokal2017 dutchleague2016 dutchleague2016-replica ess2015 ess2016 ess2017 ess2017_foiling_test ess40-2015-replica2 finnishleague2016 finnishleague2017 forumvostok2016 frenchleague2017 germanleague2016-replica idmstar2016 isafwc2014 kielerwoche2016 kielerwoche2016-replica kiellauf2017 northsearegatta2017 northstreamrace2017 norwegianleague2016 norwegianleague2016-replica norwegianleague2017 norwegianleague2017-replica rsc2016 scl2016 scl2016-replica swedishleague2016 swedishleague2016-replica tw2016 tw2016-replica usoda2016 wmrt2016"
# Configuration for MySQL
MYSQL_DATABASES="bugs mysql"
@@ -40,7 +40,8 @@ BACKUP_SERVER="backup@172.31.25.136"
BACKUP_DATE=`date +%s`
# Aliases
BUP_CMD="/opt/bup/bup"
BUP_DIR=/var/lib/mongodb/backup/bup
BUP_CMD="/opt/bup/bup -d $BUP_DIR"
BUP_ADDITIONAL="-r $BACKUP_SERVER:/home/backup/$PREFIX"
BUP_IGNORES='--exclude-rx=/war/$'
BUP_CMD_INDEX="$BUP_CMD index $BUP_IGNORES"
@@ -92,7 +93,14 @@ show collections" | $MONGO_CMD --port $MONGO_PORT | tail -n +4 | grep -v "^syste
else
DB_DIR=$TARGET_DIR/mongodb-$MONGO_PORT$WIND_SUFFIX
fi
if [ "$i" != "$MONGODB_COLLECTION_LOCAL" -a \( "$i" != "$MONGODB_COLLECTION_WIND" -o "$PARAM" = "weekly" \) ]; then
exclude=0
for exclude_collection in $MONGODB_EXCLUDE_DBS; do
if [ "$i" = "$exclude_collection" ]; then
echo "Excluding $i from backup based on exclude list"
exclude=1
fi
done
if [ "$exclude" = "0" -a \( "$j" != "$MONGODB_COLLECTION_WIND" -o "$PARAM" = "weekly" \) ]; then
echo " Backing up collection $j in MongoDB $i running on port $MONGO_PORT"
echo "$MONGOEXPORT_CMD --port $MONGO_PORT -d $i -c $j > $DB_DIR/$j.json"
mkdir -p $DB_DIR
@@ -14,6 +14,7 @@ import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Logger;
import java.util.regex.Pattern;
@@ -184,7 +185,16 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest i
getSemaphor().wait();
}
}
logger.info("Stored data has been loaded for " + race.getName());
logger.info("Stored data has been loaded for " + race.getName()+". Waiting for receivers to process it...");
final CountDownLatch latch = new CountDownLatch(receivers.size());
for (Receiver receiver : receivers) {
receiver.callBackWhenLoadingQueueIsDone(r->{
latch.countDown();
logger.info(receiver+" done loading");
});
}
latch.await();
logger.info("Stored data has been processed by receivers");
for (Receiver receiver : receivers) {
logger.info("Stopping receiver "+receiver);
receiver.stopAfterNotReceivingEventsForSomeTime(/* timeoutInMilliseconds */ 5000l);
@@ -2684,11 +2684,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
private List<Maneuver> computeManeuvers(Competitor competitor, ManeuverDetector maneuverDetector)
throws NoWindException {
logger.finest("computeManeuvers(" + competitor.getName() + ") called in tracked race " + this);
logger.info("computeManeuvers(" + competitor.getName() + ") called in tracked race " + this);
long startedAt = System.currentTimeMillis();
// compute the maneuvers for competitor
List<Maneuver> result = maneuverDetector.detectManeuvers();
logger.finest("computeManeuvers(" + competitor.getName() + ") called in tracked race " + this + " took "
logger.info("computeManeuvers(" + competitor.getName() + ") called in tracked race " + this + " took "
+ (System.currentTimeMillis() - startedAt) + "ms");
return result;
}
@@ -0,0 +1,132 @@
<!DOCTYPE html>
<html>
<body>
<div id="mainContent">
<h4 class="articleHeadline">What's New - SAP Sailing Race Manager</h4>
<div class="innerContent">
<h5 class="articleSubheadline">July 2016</h5>
<ul class="bulletList">
<li>Finishing races in the TimePanel show the race duration of the "first ship home."</li>
</ul>
<h5 class="articleSubheadline">June 2016</h5>
<ul class="bulletList">
<li>The start time editing screen has now a "Sync to minute" button, which replaces
the both buttons beside the countdown. This button sets the countdown to the nearest
minute and after "Set time" the new start time will be sent to the server.</li>
<li>The "Set Time" button in the start time editing screen remains disabled now until
the user actually makes a change. This also helps to identify that "Set Time"
needs to be tapped in order to transmit a change carried out using the
"Sync to minute" button.</li>
<li>Changing the server, signing out, changing hidden event visibility,
and changing the regatta now properly ensures that the
content is refreshed based on the new settings.</li>
</ul>
<h5 class="articleSubheadline">May 2016</h5>
<ul class="bulletList">
<li>A bug related to entering the passing instructions for a waypoint in the "by-marks"
course designer has been fixed. At the same time, for now the passing instructions
"Offset" and "Fixed Bearing" are no longer offered until the application really offers
support for them, particularly during mark passing calculation.</li>
<li>Swiping the start time button to the left to reach the other buttons for entering
the racing procedure, start mode flag, etc. now works reliably, also in case
of multi-touch which may have made the app crash before.</li>
<li>Regatta-specific preferences now properly take precedence over the device configuration.
They are updated from the server when the regatta content is refreshed.</li>
</ul>
<h5 class="articleSubheadline">April 2016</h5>
<ul class="bulletList">
<li>Whether or not result entry during or after the finishing phase is offered is now
a preference under "REGATTA CONFIGURATION (DEFAULT)." The device configuration managed
on the server can remotely manage this configuration setting. With this, it is possible
to configure up-front whether a race officer is offered the possibility to manage
results directly from the Race Manager app. This should <em>not</em> be used if an
external, official regatta management system is being used to capture and manage
the official scores.</li>
</ul>
<h5 class="articleSubheadline">March 2016</h5>
<ul class="bulletList">
<li>Added sign in/sign out into the app. The user has to be create in the backend, with leaderboard
permission. Without the permission, the user can't send data to the server.</li>
<li>We changed the QR Code, so it includes the user's access token. There is also a possibility to manual login into
the app, if no QR Code is available. <b>The app doesn't store username and password.</b></li>
<li>The behavior of the red share icon has also slightly changed. If it is red and tapped, it will call the server
to check, if the users access token is still valid. If not the server response with a 401 error code and the user
has to enter his credentials.</li>
<li>You can force a user sign out within the overflow menu, if you need other user credentials.</li>
</ul>
<h5 class="articleSubheadline">February 2016</h5>
<ul class="bulletList">
<li>Added responsive design. You can now use the app on every tablet as well as on <b>mobile phones</b>.</li>
<li>We returned the group races switch to ESS races. It's located in the left panel bar (or top on phones).</li>
<li>The behavior of ESS course designer is compact in two lists. The marks and rounding can be easily changed by tapping on it.</li>
</ul>
<h5 class="articleSubheadline">August 2015</h5>
<ul class="bulletList">
<li>Fixes for Android Lollipop were deployed. They solve font size and other display issues.
</li>
<li>The true wind direction provided during wind entry in the app is now interpreted to be a
direction based on magnetic north, not true north. This is common practice as wind readings
are typically produced on a start vessel based on a magnetic compass device.
</li>
</ul>
<h5 class="articleSubheadline">July 2015</h5>
<ul class="bulletList">
<li>Added support for dependent start times. Races can set their start time relative
to another race's start time. Caveat: Currently, when aborting races on which other
races depend, requires either aborting the dependent races before or setting an
absolute start time on the dependent races.
</li>
</ul>
<h5 class="articleSubheadline">June 2015</h5>
<ul class="bulletList">
<li>Major overhaul of the entire race committee app. The app has a completely new user interface
with a light and a dark theme. The functionality generally remained unchanged.
</li>
</ul>
<h5 class="articleSubheadline">July 2014</h5>
<ul class="bulletList">
<li>The race list is now ordered by fleets. This means we display the same order of our backend system in the RCApp.
Now the race officials can easily use the order which is displayed and do not have to care about the fleet color order.</li>
</ul>
<h5 class="articleSubheadline">March 2014</h5>
<ul class="bulletList">
<li>Moved away from using a label to create a course and introduced a big button that
eases the input of courses.</li>
<li>Added a new countdown button for ESS and RRS26 start configurations. Using this
button one can easily set the start time of a race to exactly the time the countdown starts.</li>
</ul>
<h5 class="articleSubheadline">January 2014</h5>
<ul class="bulletList">
<li>Server-based device configuration</li>
<li>Device initialization with QR codes</li>
<li>Automatic upgrades and downgrades to match server software version</li>
<li>Multiple devices can work on the same race (e.g., start vessel, finishing vessel, shore control)</li>
</ul>
</div>
</div>
</body>
</html>
@@ -108,7 +108,7 @@ public class TestWindEstimationFromManeuversOnAFew505Races extends OnlineTracTra
CreateModelException, NotEnoughDataHasBeenAddedException {
setUp("event_20110609_KielerWoch-505_race_4");
Wind average = getManeuverBasedAverageWind();
assertEquals(270, average.getFrom().getDegrees(), 9.0);
assertEquals(265, average.getFrom().getDegrees(), 9.0);
}
@Test
@@ -156,7 +156,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
this.weightedAverageMiddleCOGForManeuverType = new HashMap<>();
long start = System.currentTimeMillis();
Triple<Set<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>>, List<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>>, List<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>>> clusterStructure = analyzeRace(waitForLatest);
logger.fine("Computed virtual wind fixes from maneuvers for race " + trackedRace.getRace().getName() + " in "
logger.info("Computed virtual wind fixes from maneuvers for race " + trackedRace.getRace().getName() + " in "
+ (System.currentTimeMillis() - start) + "ms");
clusters = clusterStructure.getA();
tackClusters = clusterStructure.getB();
@@ -387,7 +387,9 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
*/
private Triple<Set<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>>, List<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>>, List<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>>> analyzeRace(
boolean waitForLatest) throws NotEnoughDataHasBeenAddedException {
logger.info("Starting wind estimation");
final Map<Maneuver, CompetitorAndBoat> maneuvers = getAllManeuvers(waitForLatest);
logger.info("Maneuvers fixed have been queried");
// cluster into eight clusters by middle COG first, then aggregate tack likelihoods for each, and jibe
// likelihoods for opposite cluster
final int numberOfClusters = 16;
@@ -403,7 +405,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
IntStream.range(0, numberOfClusters / 2).mapToObj(
(i) -> new Pair<>(new DegreeBearingImpl(((double) i) * 360. / (double) numberOfClusters
/ 2), -45.))));
logger.fine("K-Means maneuver clusterer for wind estimation took " + clusterer.getNumberOfIterations()
logger.info("K-Means maneuver clusterer for wind estimation took " + clusterer.getNumberOfIterations()
+ " iterations");
final Set<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> clusters = clusterer
.getClusters();
Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

@@ -54,8 +54,7 @@
<RelativeLayout
android:id="@+id/start_time_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true">
android:layout_height="wrap_content">
<TextView
android:id="@+id/time_start"
@@ -97,7 +96,6 @@
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/side_padding"
android:layout_toRightOf="@+id/start_time_container">
@@ -115,8 +113,22 @@
android:visibility="invisible"
tools:text="@string/time"
tools:visibility="visible" />
</RelativeLayout>
<TextView
android:id="@+id/first_vessel_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/start_time_container"
android:layout_centerHorizontal="true"
android:layout_marginLeft="@dimen/side_padding"
android:drawableLeft="?attr/flag_18dp"
android:drawablePadding="6dp"
android:textColor="?attr/white"
android:textSize="@dimen/panel_button_caption_size"
android:visibility="gone"
tools:text="0h 23m 14s"
tools:visibility="visible" />
</RelativeLayout>
</RelativeLayout>
@@ -136,4 +148,4 @@
tools:visibility="visible" />
</LinearLayout>
</com.sap.sailing.racecommittee.app.ui.layouts.TimePanelHeaderLayout>
</RelativeLayout>
</RelativeLayout>
@@ -49,8 +49,7 @@
<RelativeLayout
android:id="@+id/start_time_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true">
android:layout_height="wrap_content">
<TextView
android:id="@+id/time_start"
@@ -91,7 +90,6 @@
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/side_padding"
android:layout_toRightOf="@+id/start_time_container">
@@ -108,7 +106,22 @@
android:visibility="invisible"
tools:text="@string/time"
tools:visibility="visible" />
</RelativeLayout>
<TextView
android:id="@+id/first_vessel_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/start_time_container"
android:layout_centerHorizontal="true"
android:layout_marginLeft="@dimen/side_padding"
android:drawableLeft="?attr/flag_24dp"
android:drawablePadding="6dp"
android:textAppearance="?attr/textSmall"
android:visibility="gone"
tools:text="0h 23m 14s"
tools:visibility="visible" />
</RelativeLayout>
</RelativeLayout>
@@ -128,4 +141,4 @@
tools:visibility="visible" />
</LinearLayout>
</com.sap.sailing.racecommittee.app.ui.layouts.TimePanelHeaderLayout>
</RelativeLayout>
</RelativeLayout>
@@ -365,7 +365,7 @@
<string name="race_summary_wind_direction_value">aus %.0f°</string>
<string name="race_summary_wind_speed">Durchschnittliche Windgeschwindigkeit</string>
<string name="record_voice">Stimme aufzeichnen</string>
<string name="finishing_started">Erstes Schiff im Ziel um %s</string>
<string name="finishing_started">Erster im Ziel um %1$s</string>
<string name="finishing_started_since">(%s)</string>
<string name="finishing_done">Jetzt runter</string>
<string name="finished_edit">Liste bearbeiten</string>
@@ -71,6 +71,8 @@
<attr name="course_updown_48dp" format="reference" />
<attr name="course_updown_64dp" format="reference" />
<attr name="dns" format="reference" />
<attr name="flag_18dp" format="reference" />
<attr name="flag_24dp" format="reference" />
<attr name="hearing" format="reference" />
<attr name="link_24dp" format="reference" />
<attr name="list_24dp" format="reference" />
@@ -386,7 +386,7 @@
<string name="race_summary_individual_recalls">Individual Recalls</string>
<string name="race_summary_time" translatable="false">%s min</string>
<string name="record_voice">Record Voice</string>
<string name="finishing_started">First vessel in finish at %s</string>
<string name="finishing_started">First in finish at %1$s</string>
<string name="finishing_started_since">(%s)</string>
<string name="finishing_done">Down now</string>
@@ -81,6 +81,8 @@
<item name="course_updown_48dp">@drawable/course_updown_48dp_dark</item>
<item name="course_updown_64dp">@drawable/course_updown_64dp_dark</item>
<item name="dns">@drawable/ic_dns_white</item>
<item name="flag_18dp">@drawable/ic_flag_white_18dp</item>
<item name="flag_24dp">@drawable/ic_flag_white_24dp</item>
<item name="hearing">@drawable/ic_hearing_white</item>
<item name="link_24dp">@drawable/ic_link_white_24dp</item>
<item name="list_both_24dp">@drawable/ic_list_both_white_24dp</item>
@@ -90,6 +90,8 @@
<item name="course_updown_48dp">@drawable/course_updown_48dp_light</item>
<item name="course_updown_64dp">@drawable/course_updown_64dp_light</item>
<item name="dns">@drawable/ic_dns_black</item>
<item name="flag_18dp">@drawable/ic_flag_black_18dp</item>
<item name="flag_24dp">@drawable/ic_flag_black_24dp</item>
<item name="hearing">@drawable/ic_hearing_black</item>
<item name="link_24dp">@drawable/ic_link_black_24dp</item>
<item name="list_both_24dp">@drawable/ic_list_both_black_24dp</item>
@@ -298,7 +298,7 @@ public class FlagPanelFragment extends BasePanelFragment {
break;
case FINISHING:
mBlueLastText.setText(TimeUtils.formatDurationSince(now.minus(getRaceState().getFinishingTime().asMillis()).asMillis()));
mBlueLastText.setText(TimeUtils.formatTimeAgo(getActivity(), now.minus(getRaceState().getFinishingTime().asMillis()).asMillis()));
changeVisibility(mRecallLock, mRecallLayer, View.VISIBLE);
break;
@@ -1,8 +1,17 @@
package com.sap.sailing.racecommittee.app.ui.fragments.panels;
import static com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult.ResolutionFailed.NO_START_TIME_SET;
import java.text.SimpleDateFormat;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.android.shared.util.BroadcastManager;
@@ -30,22 +39,13 @@ import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import static com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult.ResolutionFailed.NO_START_TIME_SET;
public class TimePanelFragment extends BasePanelFragment {
public final static String TOGGLED = "toggled";
private final static String TOGGLED = "toggled";
private RaceStateChangedListener mStateListener;
private IntentReceiver mReceiver;
@@ -58,10 +58,12 @@ public class TimePanelFragment extends BasePanelFragment {
private TextView mCurrentTime;
private TextView mHeaderTime;
private TextView mTimeStart;
private TextView mFirstVesselDuration;
private ImageView mLinkIcon;
private Boolean mLinkedRace = null;
private CompetitorPanelClick mClickListener;
private TimePoint mLastFinishingTime = null;
public TimePanelFragment() {
mReceiver = new IntentReceiver();
@@ -95,6 +97,7 @@ public class TimePanelFragment extends BasePanelFragment {
mHeaderTime = ViewHelper.get(layout, R.id.timer_text);
mTimeStart = ViewHelper.get(layout, R.id.time_start);
mLinkIcon = ViewHelper.get(layout, R.id.linked_race);
mFirstVesselDuration = ViewHelper.get(layout, R.id.first_vessel_duration);
if (getArguments().getBoolean(TOGGLED, false)) {
toggleMarker(layout, R.id.time_marker);
@@ -195,6 +198,14 @@ public class TimePanelFragment extends BasePanelFragment {
if (mLinkedRace != null && mLinkIcon != null) {
mLinkIcon.setVisibility(mLinkedRace ? View.VISIBLE : View.GONE);
}
if (mFirstVesselDuration != null && mFirstVesselDuration.getVisibility() == View.VISIBLE) {
if (!getRaceState().getFinishingTime().equals(mLastFinishingTime)) {
mLastFinishingTime = getRaceState().getFinishingTime();
String raceDuration = TimeUtils.formatTimeAgo(getActivity(), mLastFinishingTime.minus(getRaceState().getStartTime().asMillis()).asMillis());
mFirstVesselDuration.setText(raceDuration);
}
}
}
private void uncheckMarker(View view) {
@@ -214,34 +225,42 @@ public class TimePanelFragment extends BasePanelFragment {
switch (getRace().getStatus()) {
case UNSCHEDULED:
changeVisibility(mTimeLock, null, View.GONE);
changeVisibility(mFirstVesselDuration, null, View.GONE);
break;
case PRESCHEDULED:
changeVisibility(mTimeLock, null, View.GONE);
changeVisibility(mFirstVesselDuration, null, View.GONE);
break;
case SCHEDULED:
changeVisibility(mTimeLock, null, View.GONE);
changeVisibility(mFirstVesselDuration, null, View.GONE);
break;
case STARTPHASE:
changeVisibility(mTimeLock, null, View.GONE);
changeVisibility(mFirstVesselDuration, null, View.GONE);
break;
case RUNNING:
changeVisibility(mTimeLock, null, View.VISIBLE);
changeVisibility(mFirstVesselDuration, null, View.GONE);
break;
case FINISHING:
changeVisibility(mTimeLock, null, View.VISIBLE);
changeVisibility(mFirstVesselDuration, null, View.VISIBLE);
break;
case FINISHED:
changeVisibility(mTimeLock, null, View.VISIBLE);
changeVisibility(mFirstVesselDuration, null, View.VISIBLE);
break;
default:
changeVisibility(mTimeLock, null, View.VISIBLE);
changeVisibility(mFirstVesselDuration, null, View.GONE);
break;
}
}
@@ -75,7 +75,7 @@ public class RaceFinishingFragment extends BaseFragment {
super.notifyTick(now);
if (mFinishingSince != null && getRaceState().getFinishingTime() != null) {
String timeDiff = TimeUtils.formatDurationSince(now.minus(getRaceState().getFinishingTime().asMillis()).asMillis());
String timeDiff = TimeUtils.formatTimeAgo(getActivity(), now.minus(getRaceState().getFinishingTime().asMillis()).asMillis());
mFinishingSince.setText(getString(R.string.finishing_started_since, timeDiff));
}
}
@@ -506,8 +506,8 @@ public class StartTimeFragment extends BaseFragment
mTimePicker.setIs24HourView(true);
int hours = time.get(Calendar.HOUR_OF_DAY);
int minutes = time.get(Calendar.MINUTE);
if (getArguments() != null && getArguments().getInt(START_MODE, START_MODE_PRESETUP) != MODE_TIME_PANEL && mRaceId == null
&& mStartTimeOffset == null) {
if (getArguments() != null && getArguments().getInt(START_MODE, START_MODE_PRESETUP) != MODE_TIME_PANEL
&& getArguments().getSerializable(MainScheduleFragment.START_TIME) == null) {
// In 10 minutes from now, but always a 5-minute-mark.
time.add(Calendar.MINUTE, 10);
hours = time.get(Calendar.HOUR_OF_DAY);
@@ -515,6 +515,7 @@ public class StartTimeFragment extends BaseFragment
minutes = (int) (Math.ceil((minutes / 5.0)) * 5.0);
if (minutes >= 60) {
hours++;
minutes = 0;
}
}
mTimePicker.setCurrentHour(hours);
@@ -623,7 +624,7 @@ public class StartTimeFragment extends BaseFragment
break;
case R.id.set_start_time_relative:
changeFragment(MillisecondsTimePoint.now(), new MillisecondsDurationImpl(mTimeOffset.getValue() * 60 * 1000), identifier);
changeFragment(mStartTime, new MillisecondsDurationImpl(mTimeOffset.getValue() * 60 * 1000), identifier);
break;
case R.id.sync_to_minute:
@@ -772,9 +773,12 @@ public class StartTimeFragment extends BaseFragment
viewId = R.id.race_content;
}
args.putAll(getArguments());
args.putSerializable(MainScheduleFragment.START_TIME, startTime);
args.putSerializable(MainScheduleFragment.START_TIME_DIFF, startTimeDiff);
args.putSerializable(MainScheduleFragment.DEPENDENT_RACE, identifier);
if (startTimeDiff == null) {
args.putSerializable(MainScheduleFragment.START_TIME, startTime);
} else {
args.putSerializable(MainScheduleFragment.START_TIME_DIFF, startTimeDiff);
args.putSerializable(MainScheduleFragment.DEPENDENT_RACE, identifier);
}
}
fragment.setArguments(args);
transaction.replace(viewId, fragment);