Merge branch 'bug3016' into ubilabs--rcapp--develop

This commit is contained in:
Peter Siegmund committed 2015-06-26 15:51:52 +02:00
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>
@@ -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());
}
@@ -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);
}
}
@@ -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;
}
}
}
@@ -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();
}
}
}