mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-10 14:20:55 +00:00
Merge branch 'bug3016' into ubilabs--rcapp--develop
This commit is contained in:
commit
437e32d652
7 files changed
+414
-299
No files matched your search
@@ -405,7 +405,7 @@
|
||||
<string name="theme_changed_message">Die Änderung am Theme wird nach einem Neustart der App wirksam.</string>
|
||||
<string name="url_refresh_title">Die Server URL wurde geändert</string>
|
||||
<string name="url_refresh_message">Bitte melden Sie sich vom aktuellen Event ab, um die Daten des neuen Servers zu laden.</string>
|
||||
<string name="until_xray_removed">XRAY wird eingeholt in #TIME#</string>
|
||||
<string name="until_xray_removed">XRAY wird eingeholt in %s</string>
|
||||
<string name="send_photos">Fotos senden</string>
|
||||
<string name="error_wrong_degree_value_title">Fehler</string>
|
||||
<string name="error_wrong_degree_value_message">Bitte geben Sie einen Wert zwischen 0 und 360 an.</string>
|
||||
|
||||
@@ -426,7 +426,7 @@
|
||||
<string name="theme_changed_message">Changes to the theme will take action after an app restart.</string>
|
||||
<string name="url_refresh_title">Server URL Changed</string>
|
||||
<string name="url_refresh_message">Please logout from the current event to load the data from the new server.</string>
|
||||
<string name="until_xray_removed">XRAY will be removed in #TIME#</string>
|
||||
<string name="until_xray_removed">XRAY will be removed in %s</string>
|
||||
<string name="send_photos">Send Photos</string>
|
||||
<string name="error_wrong_degree_value_title">Error</string>
|
||||
<string name="error_wrong_degree_value_message">Please provide a value between 0 and 360</string>
|
||||
|
||||
+9
-2
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.racecommittee.app.services;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
@@ -8,6 +9,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Pair;
|
||||
@@ -259,11 +261,16 @@ public class RaceStateService extends Service {
|
||||
intent.putExtra(AppConstants.EXTRAS_RACE_STATE_EVENT, event);
|
||||
return PendingIntent.getService(this, alarmManagerRequestCode++, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
public void setAlarm(ManagedRace race, RaceStateEvent event) {
|
||||
PendingIntent intent = createAlarmPendingIntent(race, event);
|
||||
managedIntents.get(race.getId()).add(Pair.create(intent, event.getEventName()));
|
||||
alarmManager.set(AlarmManager.RTC_WAKEUP, event.getTimePoint().asMillis(), intent);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
alarmManager.setExact(AlarmManager.RTC_WAKEUP, event.getTimePoint().asMillis(), intent);
|
||||
} else {
|
||||
alarmManager.set(AlarmManager.RTC_WAKEUP, event.getTimePoint().asMillis(), intent);
|
||||
}
|
||||
ExLog.i(this, TAG, "The alarm " + event.getEventName() + " will be fired at " + event.getTimePoint());
|
||||
}
|
||||
|
||||
|
||||
+86
-78
@@ -1,15 +1,10 @@
|
||||
package com.sap.sailing.racecommittee.app.ui.adapters.racelist;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -19,10 +14,11 @@ import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.util.ViewHolder;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.RaceState;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.FlagPoleState;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedure;
|
||||
import com.sap.sailing.domain.common.racelog.FlagPole;
|
||||
import com.sap.sailing.domain.common.racelog.Flags;
|
||||
import com.sap.sailing.racecommittee.app.AppConstants;
|
||||
@@ -32,11 +28,17 @@ import com.sap.sailing.racecommittee.app.ui.adapters.racelist.RaceFilter.FilterS
|
||||
import com.sap.sailing.racecommittee.app.ui.utils.FlagsResources;
|
||||
import com.sap.sailing.racecommittee.app.utils.BitmapHelper;
|
||||
import com.sap.sailing.racecommittee.app.utils.ThemeHelper;
|
||||
import com.sap.sailing.racecommittee.app.utils.TimeUtils;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
|
||||
public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> implements FilterSubscriber {
|
||||
|
||||
private final static String TAG = ManagedRaceListAdapter.class.getName();
|
||||
private final static int FLAG_SIZE = 48;
|
||||
private final Object mLockObject = new Object();
|
||||
private List<RaceListDataType> mAllViewItems;
|
||||
private RaceFilter mFilter;
|
||||
@@ -71,15 +73,6 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
|
||||
dateFormat = new SimpleDateFormat("HH:mm", getContext().getResources().getConfiguration().locale);
|
||||
}
|
||||
|
||||
public String fill2(int value) {
|
||||
String erg = String.valueOf(value);
|
||||
|
||||
if (erg.length() < 2) {
|
||||
erg = "0" + erg;
|
||||
}
|
||||
return erg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
synchronized (mLockObject) {
|
||||
@@ -87,46 +80,6 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
|
||||
}
|
||||
}
|
||||
|
||||
public String getDuration(Date date1, Date date2) {
|
||||
TimeUnit timeUnit = TimeUnit.SECONDS;
|
||||
|
||||
long diffInMilli = date2.getTime() - date1.getTime();
|
||||
long s = timeUnit.convert(diffInMilli, TimeUnit.MILLISECONDS);
|
||||
|
||||
long days = s / (24 * 60 * 60);
|
||||
long rest = s - (days * 24 * 60 * 60);
|
||||
long hrs = rest / (60 * 60);
|
||||
long rest1 = rest - (hrs * 60 * 60);
|
||||
long min = rest1 / 60;
|
||||
long sec = s % 60;
|
||||
|
||||
String dates = "";
|
||||
if (days < 0 || hrs < 0 || min < 0 || sec < 0) {
|
||||
dates += "-";
|
||||
if (days < 0) {
|
||||
days *= -1;
|
||||
}
|
||||
if (hrs < 0) {
|
||||
hrs *= -1;
|
||||
}
|
||||
if (min < 0) {
|
||||
min *= -1;
|
||||
}
|
||||
if (sec < 0) {
|
||||
sec *= -1;
|
||||
}
|
||||
}
|
||||
if (days != 0) {
|
||||
dates = days + ":";
|
||||
}
|
||||
|
||||
dates += (days != 0 || hrs != 0) ? fill2((int) hrs) + ":" : "";
|
||||
dates += fill2((int) min) + ":";
|
||||
dates += fill2((int) sec);
|
||||
|
||||
return dates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceFilter getFilter() {
|
||||
if (mFilter == null) {
|
||||
@@ -157,6 +110,7 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
|
||||
raceListElement = getItem(position);
|
||||
|
||||
int type = getItemViewType(position);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
|
||||
if (convertView == null) {
|
||||
if (type == ViewType.HEADER.index) {
|
||||
@@ -186,7 +140,7 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
|
||||
fleetSeries += header.getSeries().getName();
|
||||
}
|
||||
fleet_series.setText(fleetSeries);
|
||||
protest_image.setImageDrawable(FlagsResources.getFlagDrawable(getContext(), Flags.BRAVO.name(), 48));
|
||||
protest_image.setImageDrawable(FlagsResources.getFlagDrawable(getContext(), Flags.BRAVO.name(), FLAG_SIZE));
|
||||
protest_image.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -220,7 +174,7 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
|
||||
String startTime = mResources.getString(startRes, dateFormat.format(state.getStartTime().asDate()));
|
||||
race_started.setText(startTime);
|
||||
if (state.getFinishedTime() == null) {
|
||||
String duration = getDuration(state.getStartTime().asDate(), Calendar.getInstance().getTime());
|
||||
String duration = TimeUtils.formatDuration(now, state.getStartTime());
|
||||
time.setText(duration);
|
||||
float textSize = getContext().getResources().getDimension(R.dimen.textSize_40);
|
||||
if (!TextUtils.isEmpty(duration) && duration.length() >= 6) {
|
||||
@@ -248,7 +202,7 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
|
||||
update_badge.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
updateFlag(race.getRace());
|
||||
updateFlag(race.getRace(), now);
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
@@ -323,32 +277,86 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFlag(ManagedRace race) {
|
||||
private void updateFlag(ManagedRace race, TimePoint now) {
|
||||
RaceState state = race.getState();
|
||||
if (state == null || state.getStartTime() == null) {
|
||||
return;
|
||||
}
|
||||
FlagPoleState flagPoleState = state.getTypedRacingProcedure()
|
||||
.getActiveFlags(state.getStartTime(), MillisecondsTimePoint.now());
|
||||
List<FlagPole> flagChanges = flagPoleState.computeUpcomingChanges();
|
||||
if (!flagChanges.isEmpty()) {
|
||||
TimePoint changeAt = flagPoleState.getNextStateValidFrom();
|
||||
FlagPole changePole = FlagPoleState.getMostInterestingFlagPole(flagChanges);
|
||||
|
||||
if (changeAt != null) {
|
||||
current_flag.setImageDrawable(
|
||||
FlagsResources.getFlagDrawable(getContext(), changePole.getUpperFlag().name(), 48));
|
||||
String text = getDuration(changeAt.asDate(), Calendar.getInstance().getTime());
|
||||
flag_timer.setText(text.replace("-", ""));
|
||||
Drawable arrow;
|
||||
if (changePole.isDisplayed()) {
|
||||
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_up);
|
||||
} else {
|
||||
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_down);
|
||||
RacingProcedure procedure = state.getTypedRacingProcedure();
|
||||
LayerDrawable flag = null;
|
||||
Drawable arrow = null;
|
||||
String timer = null;
|
||||
if (!procedure.isIndividualRecallDisplayed()) {
|
||||
FlagPoleState poleState = state.getRacingProcedure().getActiveFlags(state.getStartTime(), now);
|
||||
List<FlagPole> currentState = poleState.getCurrentState();
|
||||
List<FlagPole> upcoming = poleState.computeUpcomingChanges();
|
||||
FlagPole nextPole = FlagPoleState.getMostInterestingFlagPole(upcoming);
|
||||
TimePoint change = poleState.getNextStateValidFrom();
|
||||
Flags currentFlag;
|
||||
|
||||
if (change != null) {
|
||||
for (FlagPole pole : currentState) {
|
||||
int isNext = 0;
|
||||
|
||||
currentFlag = pole.getUpperFlag();
|
||||
if (isNextFlag(currentFlag, nextPole)) {
|
||||
isNext = 1;
|
||||
} else {
|
||||
currentFlag = pole.getLowerFlag();
|
||||
if (!Flags.NONE.equals(currentFlag)) {
|
||||
if (isNextFlag(currentFlag, nextPole)) {
|
||||
isNext = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isNext != 0) {
|
||||
flag = FlagsResources.getFlagDrawable(getContext(), currentFlag.name(), FLAG_SIZE);
|
||||
switch (isNext) {
|
||||
case 1:
|
||||
if (nextPole.isDisplayed()) {
|
||||
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_up);
|
||||
} else {
|
||||
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_down);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_up);
|
||||
break;
|
||||
|
||||
default:
|
||||
ExLog.i(getContext(), TAG, "unknown flag");
|
||||
}
|
||||
timer = TimeUtils.formatDuration(now, poleState.getNextStateValidFrom());
|
||||
}
|
||||
}
|
||||
arrow_direction.setImageDrawable(arrow);
|
||||
race_flag.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
TimePoint flagDown = procedure.getIndividualRecallRemovalTime();
|
||||
if (now.before(flagDown)) {
|
||||
flag = FlagsResources.getFlagDrawable(getContext(), Flags.XRAY.name(), FLAG_SIZE);
|
||||
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_down);
|
||||
timer = TimeUtils.formatDuration(now, flagDown);
|
||||
}
|
||||
}
|
||||
if (timer != null) {
|
||||
timer = timer.replace("-", "");
|
||||
}
|
||||
showFlag(flag, arrow, timer);
|
||||
}
|
||||
|
||||
private boolean isNextFlag(Flags flag, FlagPole pole) {
|
||||
return pole != null && flag.equals(pole.getUpperFlag());
|
||||
}
|
||||
|
||||
private void showFlag(LayerDrawable flag, Drawable arrow, String timer) {
|
||||
if (flag != null && arrow != null && timer != null) {
|
||||
current_flag.setImageDrawable(flag);
|
||||
arrow_direction.setImageDrawable(arrow);
|
||||
flag_timer.setText(timer);
|
||||
race_flag.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+103
-42
@@ -9,6 +9,8 @@ import android.widget.*;
|
||||
import com.sap.sailing.android.shared.util.ViewHolder;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.FlagPoleState;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedure;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ReadonlyRacingProcedure;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl.BaseRacingProcedureChangedListener;
|
||||
import com.sap.sailing.domain.common.racelog.FlagPole;
|
||||
import com.sap.sailing.domain.common.racelog.Flags;
|
||||
import com.sap.sailing.racecommittee.app.R;
|
||||
@@ -32,8 +34,12 @@ public class RaceFlagViewerFragment extends BaseFragment {
|
||||
private TextView mXrayCountdown;
|
||||
private Button mXrayButton;
|
||||
|
||||
public RaceFlagViewerFragment() {
|
||||
private ProcedureChangedListener mProcedureListener;
|
||||
private FlagsCache mFlagCache;
|
||||
|
||||
public RaceFlagViewerFragment() {
|
||||
mProcedureListener = new ProcedureChangedListener();
|
||||
mFlagCache = null;
|
||||
}
|
||||
|
||||
public static RaceFlagViewerFragment newInstance() {
|
||||
@@ -69,6 +75,20 @@ public class RaceFlagViewerFragment extends BaseFragment {
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
getRaceState().getRacingProcedure().addChangedListener(mProcedureListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
getRaceState().getRacingProcedure().removeChangedListener(mProcedureListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyTick(TimePoint now) {
|
||||
super.notifyTick(now);
|
||||
@@ -76,7 +96,7 @@ public class RaceFlagViewerFragment extends BaseFragment {
|
||||
updateFlags(now);
|
||||
}
|
||||
|
||||
private void updateFlags(TimePoint timePoint) {
|
||||
private void updateFlags(TimePoint now) {
|
||||
if (getRace() == null || getRaceState() == null || getRaceState().getStartTime() == null) {
|
||||
return;
|
||||
}
|
||||
@@ -87,42 +107,57 @@ public class RaceFlagViewerFragment extends BaseFragment {
|
||||
if (mRecall != null) {
|
||||
mRecall.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
RacingProcedure procedure = getRaceState().getTypedRacingProcedure();
|
||||
if (!procedure.isIndividualRecallDisplayed()) {
|
||||
if (mLayout != null) {
|
||||
mLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
FlagPoleState poleState = getRaceState().getRacingProcedure().getActiveFlags(getRaceState().getStartTime(), timePoint);
|
||||
List<FlagPole> currentState = poleState.getCurrentState();
|
||||
List<FlagPole> upcoming = poleState.computeUpcomingChanges();
|
||||
FlagPole nextPole = FlagPoleState.getMostInterestingFlagPole(upcoming);
|
||||
mLayout.removeAllViews();
|
||||
int size = 0;
|
||||
Flags flag;
|
||||
for (FlagPole flagPole : currentState) {
|
||||
size++;
|
||||
flag = flagPole.getUpperFlag();
|
||||
mLayout.addView(renderFlag(timePoint, poleState, flag, isNextFlag(flag, nextPole), currentState.size() == size, flagPole.isDisplayed(), UPPER_FLAG));
|
||||
if (!flagPole.getLowerFlag().equals(Flags.NONE)) {
|
||||
flag = flagPole.getLowerFlag();
|
||||
mLayout.addView(renderFlag(timePoint, poleState, flag, isNextFlag(flag, nextPole), currentState.size() == size, false, LOWER_FLAG));
|
||||
if (mFlagCache == null) {
|
||||
mLayout.removeAllViews();
|
||||
FlagPoleState poleState = getRaceState().getRacingProcedure().getActiveFlags(getRaceState().getStartTime(), now);
|
||||
List<FlagPole> currentState = poleState.getCurrentState();
|
||||
List<FlagPole> upcoming = poleState.computeUpcomingChanges();
|
||||
FlagPole nextPole = FlagPoleState.getMostInterestingFlagPole(upcoming);
|
||||
mFlagCache = new FlagsCache(poleState.getNextStateValidFrom());
|
||||
int size = 0;
|
||||
Flags flag;
|
||||
boolean nextFlag;
|
||||
for (FlagPole flagPole : currentState) {
|
||||
size++;
|
||||
flag = flagPole.getUpperFlag();
|
||||
nextFlag = isNextFlag(flag, nextPole);
|
||||
if (nextFlag) {
|
||||
mFlagCache.nextFlag = size;
|
||||
}
|
||||
mLayout.addView(createFlagView(now, poleState, flag, nextFlag, currentState.size() == size, flagPole.isDisplayed(), UPPER_FLAG));
|
||||
if (!flagPole.getLowerFlag().equals(Flags.NONE)) {
|
||||
flag = flagPole.getLowerFlag();
|
||||
nextFlag = isNextFlag(flag, nextPole);
|
||||
if (nextFlag) {
|
||||
mFlagCache.nextFlag = size;
|
||||
}
|
||||
mLayout.addView(createFlagView(now, poleState, flag, nextFlag, currentState.size() == size, false, LOWER_FLAG));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mLayout != null) {
|
||||
int nextFlag = 0;
|
||||
for (int i = 0; i < mLayout.getChildCount(); i++) {
|
||||
if (mFlagCache.nextFlag == ++nextFlag) {
|
||||
updateFlagView(now, mLayout.getChildAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String time = getString(R.string.until_xray_removed);
|
||||
if (mXrayCountdown != null) {
|
||||
if (mXrayCountdown != null && mRecall != null) {
|
||||
TimePoint flagDown = procedure.getIndividualRecallRemovalTime();
|
||||
if (timePoint.before(flagDown)) {
|
||||
time = time.replace("#TIME#", TimeUtils.formatDurationUntil(flagDown.minus(timePoint.asMillis()).asMillis()).replace("-", ""));
|
||||
mXrayCountdown.setText(time);
|
||||
} else {
|
||||
procedure.removeIndividualRecall(timePoint);
|
||||
if (now.before(flagDown)) {
|
||||
mRecall.setVisibility(View.VISIBLE);
|
||||
mXrayCountdown.setText(getString(R.string.until_xray_removed, TimeUtils.formatDuration(now, flagDown, false)));
|
||||
}
|
||||
}
|
||||
|
||||
if (mRecall != null) {
|
||||
mRecall.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,17 +165,28 @@ public class RaceFlagViewerFragment extends BaseFragment {
|
||||
return pole != null && flag.equals(pole.getUpperFlag());
|
||||
}
|
||||
|
||||
private RelativeLayout renderFlag(TimePoint timePoint, FlagPoleState poleState, final Flags flag, boolean isNext, boolean lastEntry, boolean isDisplayed, int flagType) {
|
||||
private View updateFlagView(TimePoint now, View flagView) {
|
||||
TimePoint change = mFlagCache.mChange;
|
||||
if (change != null) {
|
||||
TextView flag_text = ViewHolder.get(flagView, R.id.flag_text);
|
||||
String timer = TimeUtils.formatDuration(now, change, false);
|
||||
flag_text.setText(timer);
|
||||
}
|
||||
return flagView;
|
||||
}
|
||||
|
||||
private RelativeLayout createFlagView(TimePoint now, FlagPoleState poleState, final Flags flag, boolean isNext, boolean lastEntry,
|
||||
boolean isDisplayed, int flagType) {
|
||||
RelativeLayout layout = (RelativeLayout) getActivity().getLayoutInflater().inflate(R.layout.race_flag, mLayout, false);
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
|
||||
layout.setLayoutParams(layoutParams);
|
||||
|
||||
TimePoint changeAt = poleState.getNextStateValidFrom();
|
||||
ImageView flagView = (ImageView) layout.findViewById(R.id.flag);
|
||||
TextView textView = (TextView) layout.findViewById(R.id.flag_text);
|
||||
View downView = layout.findViewById(R.id.arrow_down);
|
||||
View upView = layout.findViewById(R.id.arrow_up);
|
||||
View line = layout.findViewById(R.id.line);
|
||||
ImageView flagView = ViewHolder.get(layout, R.id.flag);
|
||||
TextView textView = ViewHolder.get(layout, R.id.flag_text);
|
||||
View downView = ViewHolder.get(layout, R.id.arrow_down);
|
||||
View upView = ViewHolder.get(layout, R.id.arrow_up);
|
||||
View line = ViewHolder.get(layout, R.id.line);
|
||||
if (lastEntry) {
|
||||
line.setVisibility(View.GONE);
|
||||
}
|
||||
@@ -159,12 +205,7 @@ public class RaceFlagViewerFragment extends BaseFragment {
|
||||
textView.setText("");
|
||||
if (changeAt != null && isNext) {
|
||||
textView.setVisibility(View.VISIBLE);
|
||||
String timer;
|
||||
if (changeAt.after(timePoint)) {
|
||||
timer = TimeUtils.formatDurationUntil(changeAt.minus(timePoint.asMillis()).asMillis());
|
||||
} else {
|
||||
timer = TimeUtils.formatDurationSince(timePoint.minus(changeAt.asMillis()).asMillis());
|
||||
}
|
||||
String timer = TimeUtils.formatDuration(now, changeAt);
|
||||
textView.setText(timer.replace("-", ""));
|
||||
if (flagType == UPPER_FLAG) {
|
||||
if (isDisplayed) {
|
||||
@@ -192,7 +233,27 @@ public class RaceFlagViewerFragment extends BaseFragment {
|
||||
}
|
||||
|
||||
private int getFleetColorId() {
|
||||
Util.Triple<Integer, Integer, Integer> rgb = getRace().getFleet().getColor() == null ? new Util.Triple<>(0, 0, 0) : getRace().getFleet().getColor().getAsRGB();
|
||||
Util.Triple<Integer, Integer, Integer> rgb =
|
||||
getRace().getFleet().getColor() == null ? new Util.Triple<>(0, 0, 0) : getRace().getFleet().getColor().getAsRGB();
|
||||
return Color.rgb(rgb.getA(), rgb.getB(), rgb.getC());
|
||||
}
|
||||
|
||||
private class ProcedureChangedListener extends BaseRacingProcedureChangedListener {
|
||||
|
||||
@Override
|
||||
public void onActiveFlagsChanged(ReadonlyRacingProcedure racingProcedure) {
|
||||
super.onActiveFlagsChanged(racingProcedure);
|
||||
|
||||
mFlagCache = null;
|
||||
}
|
||||
}
|
||||
|
||||
private class FlagsCache {
|
||||
private TimePoint mChange;
|
||||
private int nextFlag = 0;
|
||||
|
||||
public FlagsCache(TimePoint change) {
|
||||
mChange = change;
|
||||
}
|
||||
}
|
||||
}
|
||||
+190
-166
@@ -1,166 +1,190 @@
|
||||
package com.sap.sailing.racecommittee.app.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.View;
|
||||
import android.widget.NumberPicker;
|
||||
import android.widget.TextView;
|
||||
import com.sap.sailing.racecommittee.app.R;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class TimeUtils {
|
||||
|
||||
private TimeUtils() {
|
||||
// only static methods
|
||||
}
|
||||
|
||||
public static long timeUntil(TimePoint targetTime) {
|
||||
return targetTime.asMillis() - MillisecondsTimePoint.now().asMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats your time to 'kk:mm:ss'.
|
||||
*
|
||||
* @param timePoint timestamp to format
|
||||
*/
|
||||
public static String formatTime(TimePoint timePoint) {
|
||||
return formatTime(timePoint, "kk:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats your time with the help of {@link DateFormat}.
|
||||
*
|
||||
* @param timePoint timestamp to format
|
||||
* @param format format as defined by {@link DateFormat}
|
||||
* @return timestamp formatted as {@link String}
|
||||
*/
|
||||
public static String formatTime(TimePoint timePoint, String format) {
|
||||
return DateFormat.format(format, timePoint.asDate()).toString();
|
||||
}
|
||||
|
||||
public static String formatDurationSince(long milliseconds) {
|
||||
int secondsTillStart = (int) Math.floor(milliseconds / 1000f);
|
||||
return formatDuration(secondsTillStart);
|
||||
}
|
||||
|
||||
public static String formatDurationUntil(long milliseconds) {
|
||||
int secondsTillStart = (int) Math.ceil(milliseconds / 1000f);
|
||||
return formatDuration(secondsTillStart);
|
||||
}
|
||||
|
||||
public static String calcDuration(Calendar from, Calendar to) {
|
||||
String retValue;
|
||||
|
||||
long millis = to.getTimeInMillis() - from.getTimeInMillis();
|
||||
|
||||
long min = millis / (1000 * 60);
|
||||
long sec = (millis - (min * 60 * 1000)) / 1000;
|
||||
|
||||
retValue = String.valueOf(sec) + "\"";
|
||||
if (retValue.length() == 2) {
|
||||
retValue = "0" + retValue;
|
||||
}
|
||||
if (min > 0) {
|
||||
retValue = String.valueOf(min) + "' " + retValue;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
public static Calendar floorTime(Calendar calendar) {
|
||||
if (calendar == null) {
|
||||
calendar = Calendar.getInstance();
|
||||
}
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
return calendar;
|
||||
}
|
||||
|
||||
public static int daysBetween(Calendar day1, Calendar day2) {
|
||||
Calendar dayOne = (Calendar) day1.clone();
|
||||
Calendar dayTwo = (Calendar) day2.clone();
|
||||
|
||||
if (dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR)) {
|
||||
return dayOne.get(Calendar.DAY_OF_YEAR) - dayTwo.get(Calendar.DAY_OF_YEAR);
|
||||
} else {
|
||||
if (dayTwo.get(Calendar.YEAR) > dayOne.get(Calendar.YEAR)) {
|
||||
//swap them
|
||||
Calendar temp = dayOne;
|
||||
dayOne = dayTwo;
|
||||
dayTwo = temp;
|
||||
}
|
||||
int extraDays = 0;
|
||||
|
||||
while (dayOne.get(Calendar.YEAR) > dayTwo.get(Calendar.YEAR)) {
|
||||
dayOne.add(Calendar.YEAR, -1);
|
||||
// getActualMaximum() important for leap years
|
||||
extraDays += dayOne.getActualMaximum(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
|
||||
return extraDays - dayTwo.get(Calendar.DAY_OF_YEAR) + dayOne.get(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatDuration(int secondsTillStart) {
|
||||
int hours = secondsTillStart / 3600;
|
||||
int minutes = (secondsTillStart % 3600) / 60;
|
||||
int seconds = (secondsTillStart % 60);
|
||||
boolean negative = (hours < 0 || minutes < 0 || seconds < 0);
|
||||
String timePattern = ((negative) ? "-" : "") + "%s:%s:%s";
|
||||
String secondsString = seconds < 10 ? "0" + Math.abs(seconds) : "" + Math.abs(seconds);
|
||||
String minutesString = minutes < 10 ? "0" + Math.abs(minutes) : "" + Math.abs(minutes);
|
||||
String hoursString = hours < 10 ? "0" + Math.abs(hours) : "" + Math.abs(hours);
|
||||
return String.format(timePattern, hoursString, minutesString, secondsString);
|
||||
}
|
||||
|
||||
public static void initDatePicker(Context context, NumberPicker datePicker, Calendar time, int pastDays, int futureDays) {
|
||||
initDatePicker(context, datePicker, time, pastDays, futureDays, true);
|
||||
}
|
||||
|
||||
public static void initDatePicker(Context context, NumberPicker datePicker, Calendar time, int pastDays, int futureDays, boolean useWords) {
|
||||
java.text.DateFormat dateFormat = java.text.DateFormat.getDateInstance();
|
||||
ArrayList<String> dates = new ArrayList<>();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(time.getTime());
|
||||
// Past
|
||||
calendar.add(Calendar.DAY_OF_MONTH, pastDays);
|
||||
for (int i = pastDays; i < -1; i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
if (useWords) {
|
||||
dates.add(context.getString(R.string.yesterday));
|
||||
dates.add(context.getString(R.string.today));
|
||||
dates.add(context.getString(R.string.tomorrow));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 3);
|
||||
} else {
|
||||
for (int i = (pastDays == 0 ? pastDays : -1); i < (futureDays < 2 ? futureDays + 1 : 2); i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
}
|
||||
// Future
|
||||
for (int i = 2; i <= futureDays; i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
datePicker.setDisplayedValues(dates.toArray(new String[dates.size()]));
|
||||
datePicker.setMinValue(0);
|
||||
datePicker.setMaxValue(dates.size() - 1);
|
||||
datePicker.setWrapSelectorWheel(false);
|
||||
datePicker.setValue(TimeUtils.daysBetween(calendar, Calendar.getInstance()) + Math.abs(pastDays));
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
TextView date = new TextView(context);
|
||||
date.setText(dateFormat.format(calendar.getTime()));
|
||||
int padding = context.getResources().getDimensionPixelSize(R.dimen.default_padding_half);
|
||||
date.setPadding(padding, padding, padding, padding);
|
||||
date.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
||||
datePicker.getLayoutParams().width = date.getMeasuredWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.racecommittee.app.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.View;
|
||||
import android.widget.NumberPicker;
|
||||
import android.widget.TextView;
|
||||
import com.sap.sailing.racecommittee.app.R;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class TimeUtils {
|
||||
|
||||
private TimeUtils() {
|
||||
// only static methods
|
||||
}
|
||||
|
||||
public static long timeUntil(TimePoint targetTime) {
|
||||
return targetTime.asMillis() - MillisecondsTimePoint.now().asMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats your time to 'kk:mm:ss'.
|
||||
*
|
||||
* @param timePoint timestamp to format
|
||||
*/
|
||||
public static String formatTime(TimePoint timePoint) {
|
||||
return formatTime(timePoint, "kk:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats your time with the help of {@link DateFormat}.
|
||||
*
|
||||
* @param timePoint timestamp to format
|
||||
* @param format format as defined by {@link DateFormat}
|
||||
* @return timestamp formatted as {@link String}
|
||||
*/
|
||||
public static String formatTime(TimePoint timePoint, String format) {
|
||||
return DateFormat.format(format, timePoint.asDate()).toString();
|
||||
}
|
||||
|
||||
public static String formatDuration(TimePoint now, TimePoint timePoint) {
|
||||
return formatDuration(now, timePoint, true);
|
||||
}
|
||||
|
||||
public static String formatDuration(TimePoint now, TimePoint timePoint, boolean inclSign) {
|
||||
String duration;
|
||||
if (timePoint.after(now)) {
|
||||
String sign = (inclSign) ? "-" : "";
|
||||
duration = sign + TimeUtils.formatDurationUntil(timePoint.minus(now.asMillis()).asMillis(), false);
|
||||
} else {
|
||||
duration = TimeUtils.formatDurationSince(now.minus(timePoint.asMillis()).asMillis(), false);
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
||||
public static String formatDurationSince(long milliseconds) {
|
||||
return formatDurationSince(milliseconds, true);
|
||||
}
|
||||
|
||||
public static String formatDurationSince(long milliseconds, boolean emptyHours) {
|
||||
int secondsTillStart = (int) Math.floor(milliseconds / 1000f);
|
||||
return formatDuration(secondsTillStart, emptyHours);
|
||||
}
|
||||
|
||||
public static String formatDurationUntil(long milliseconds) {
|
||||
return formatDurationUntil(milliseconds, true);
|
||||
}
|
||||
|
||||
public static String formatDurationUntil(long milliseconds, boolean emptyHours) {
|
||||
int secondsTillStart = (int) Math.ceil(milliseconds / 1000f);
|
||||
return formatDuration(secondsTillStart, emptyHours);
|
||||
}
|
||||
|
||||
public static String calcDuration(Calendar from, Calendar to) {
|
||||
String retValue;
|
||||
|
||||
long millis = to.getTimeInMillis() - from.getTimeInMillis();
|
||||
|
||||
long min = millis / (1000 * 60);
|
||||
long sec = (millis - (min * 60 * 1000)) / 1000;
|
||||
|
||||
retValue = String.valueOf(sec) + "\"";
|
||||
if (retValue.length() == 2) {
|
||||
retValue = "0" + retValue;
|
||||
}
|
||||
if (min > 0) {
|
||||
retValue = String.valueOf(min) + "' " + retValue;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
public static Calendar floorTime(Calendar calendar) {
|
||||
if (calendar == null) {
|
||||
calendar = Calendar.getInstance();
|
||||
}
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
return calendar;
|
||||
}
|
||||
|
||||
public static int daysBetween(Calendar day1, Calendar day2) {
|
||||
Calendar dayOne = (Calendar) day1.clone();
|
||||
Calendar dayTwo = (Calendar) day2.clone();
|
||||
|
||||
if (dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR)) {
|
||||
return dayOne.get(Calendar.DAY_OF_YEAR) - dayTwo.get(Calendar.DAY_OF_YEAR);
|
||||
} else {
|
||||
if (dayTwo.get(Calendar.YEAR) > dayOne.get(Calendar.YEAR)) {
|
||||
//swap them
|
||||
Calendar temp = dayOne;
|
||||
dayOne = dayTwo;
|
||||
dayTwo = temp;
|
||||
}
|
||||
int extraDays = 0;
|
||||
|
||||
while (dayOne.get(Calendar.YEAR) > dayTwo.get(Calendar.YEAR)) {
|
||||
dayOne.add(Calendar.YEAR, -1);
|
||||
// getActualMaximum() important for leap years
|
||||
extraDays += dayOne.getActualMaximum(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
|
||||
return extraDays - dayTwo.get(Calendar.DAY_OF_YEAR) + dayOne.get(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatDuration(int secondsTillStart, boolean emptyHours) {
|
||||
int hours = secondsTillStart / 3600;
|
||||
int minutes = (secondsTillStart % 3600) / 60;
|
||||
int seconds = (secondsTillStart % 60);
|
||||
boolean negative = (hours < 0 || minutes < 0 || seconds < 0);
|
||||
String timePattern = ((negative) ? "-" : "") + "%s%s:%s";
|
||||
String secondsString = seconds < 10 ? "0" + Math.abs(seconds) : "" + Math.abs(seconds);
|
||||
String minutesString = minutes < 10 ? "0" + Math.abs(minutes) : "" + Math.abs(minutes);
|
||||
String hoursString = hours < 10 ? "0" + Math.abs(hours) : "" + Math.abs(hours);
|
||||
hoursString = !emptyHours && hoursString.equals("00") ? "" : hoursString + ":";
|
||||
return String.format(timePattern, hoursString, minutesString, secondsString);
|
||||
}
|
||||
|
||||
public static void initDatePicker(Context context, NumberPicker datePicker, Calendar time, int pastDays, int futureDays) {
|
||||
initDatePicker(context, datePicker, time, pastDays, futureDays, true);
|
||||
}
|
||||
|
||||
public static void initDatePicker(Context context, NumberPicker datePicker, Calendar time, int pastDays, int futureDays, boolean useWords) {
|
||||
java.text.DateFormat dateFormat = java.text.DateFormat.getDateInstance();
|
||||
ArrayList<String> dates = new ArrayList<>();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(time.getTime());
|
||||
// Past
|
||||
calendar.add(Calendar.DAY_OF_MONTH, pastDays);
|
||||
for (int i = pastDays; i < -1; i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
if (useWords) {
|
||||
dates.add(context.getString(R.string.yesterday));
|
||||
dates.add(context.getString(R.string.today));
|
||||
dates.add(context.getString(R.string.tomorrow));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 3);
|
||||
} else {
|
||||
for (int i = (pastDays == 0 ? pastDays : -1); i < (futureDays < 2 ? futureDays + 1 : 2); i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
}
|
||||
// Future
|
||||
for (int i = 2; i <= futureDays; i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
datePicker.setDisplayedValues(dates.toArray(new String[dates.size()]));
|
||||
datePicker.setMinValue(0);
|
||||
datePicker.setMaxValue(dates.size() - 1);
|
||||
datePicker.setWrapSelectorWheel(false);
|
||||
datePicker.setValue(TimeUtils.daysBetween(calendar, Calendar.getInstance()) + Math.abs(pastDays));
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
TextView date = new TextView(context);
|
||||
date.setText(dateFormat.format(calendar.getTime()));
|
||||
int padding = context.getResources().getDimensionPixelSize(R.dimen.default_padding_half);
|
||||
date.setPadding(padding, padding, padding, padding);
|
||||
date.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
||||
datePicker.getLayoutParams().width = date.getMeasuredWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user