mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-19 04:05:36 +00:00
show "running" races instead of dependent races in race selection and abort the correct races
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/abort_hint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingRight="24dp"
|
||||
android:text="@string/abort_hint"
|
||||
android:textAppearance="?attr/textSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/abort_summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingRight="24dp"
|
||||
tools:text="Lorem ipsum dolor sit amet, consetetur sadipscing elitr..." />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/abort_list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="100dp"
|
||||
android:layout_above="@id/abort_summary"
|
||||
android:layout_below="@id/abort_hint"
|
||||
android:scrollbars="vertical"
|
||||
android:textAppearance="?attr/textSmall" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeightSmall"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingRight="24dp">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/abort_checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/abort_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/abort_checkbox"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?textSmall"
|
||||
tools:text="Lorem ipsum..." />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -498,4 +498,8 @@
|
||||
<string name="preference_non_public_events_header">Zeige nicht öffentliche Events</string>
|
||||
<string name="preference_non_public_events_summary">Lade alle Events, auch die nicht öffentlichen.</string>
|
||||
|
||||
<string name="abort_title">Rennen abbrechen</string>
|
||||
<string name="abort_hint">Welche laufenden Rennen möchten Sie abbrechen?</string>
|
||||
<string name="abort_dismiss">Verwerfen</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
<dimen name="competitor_edit_width">200dp</dimen>
|
||||
<dimen name="dialog_top_padding">24dp</dimen>
|
||||
|
||||
<dimen name="abort_dialog_height">215dp</dimen>
|
||||
|
||||
<!-- custom dimens (float, integer) -->
|
||||
<item name="picker_scale" format="float" type="integer">1</item>
|
||||
<item name="flag_size" format="integer" type="integer">32</item>
|
||||
|
||||
@@ -525,4 +525,9 @@
|
||||
|
||||
<string name="preference_non_public_events_header">Show Non Public Events</string>
|
||||
<string name="preference_non_public_events_summary">Load all events including the no public one.</string>
|
||||
|
||||
<string name="abort_title">Abort Races</string>
|
||||
<string name="abort_hint">Which running races do you want to abort?</string>
|
||||
<string name="abort_dismiss">Dismiss</string>
|
||||
|
||||
</resources>
|
||||
|
||||
+12
@@ -484,6 +484,18 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
|
||||
return list;
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, ManagedRace> getRunningRaces() {
|
||||
LinkedHashMap<String, ManagedRace> list = new LinkedHashMap<>();
|
||||
for (ManagedRace race : lastSeenRaces) {
|
||||
if (RaceLogRaceStatus.RUNNING.equals(race.getStatus())) {
|
||||
if (!list.containsKey(race.getId())) {
|
||||
list.put(race.getId(), race);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void setOverflowIcon() {
|
||||
// Required to set overflow icon
|
||||
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package com.sap.sailing.racecommittee.app.ui.adapters;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult;
|
||||
import com.sap.sailing.racecommittee.app.R;
|
||||
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
|
||||
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class AbortNovemberAdapter extends RecyclerView.Adapter<AbortNovemberAdapter.ViewHolder> {
|
||||
|
||||
private List<ManagedRace> mRaces = new ArrayList<>();
|
||||
private List<ManagedRace> mSelected = new ArrayList<>();
|
||||
private ManagedRace mCurrentRace;
|
||||
|
||||
public AbortNovemberAdapter(LinkedHashMap<String, ManagedRace> races, ManagedRace currentRace) {
|
||||
mCurrentRace = currentRace;
|
||||
mSelected.add(mCurrentRace);
|
||||
Iterator<String> iterator = races.keySet().iterator();
|
||||
ManagedRace race;
|
||||
while (iterator.hasNext()) {
|
||||
race = races.get(iterator.next());
|
||||
mRaces.add(race);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.race_november_item, parent, false);
|
||||
return new ViewHolder(layout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final ViewHolder holder, int position) {
|
||||
final ManagedRace race = mRaces.get(position);
|
||||
boolean selected = (getRace(race) != null);
|
||||
|
||||
holder.race.setText(RaceHelper.getShortReverseRaceName(race, " / ", mCurrentRace));
|
||||
holder.race.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
holder.selected.setChecked(!holder.selected.isChecked());
|
||||
}
|
||||
});
|
||||
holder.selected.setChecked(selected);
|
||||
holder.selected.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
remove(race);
|
||||
if (isChecked) {
|
||||
int pos = getParentPos(race);
|
||||
if (pos == mSelected.size()) {
|
||||
pos = getFirstChild(race);
|
||||
}
|
||||
mSelected.add(pos, race);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mRaces.size();
|
||||
}
|
||||
|
||||
public List<ManagedRace> getSelected() {
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
private int getFirstChild(ManagedRace race) {
|
||||
int pos = 0;
|
||||
for (ManagedRace item : mSelected) {
|
||||
StartTimeFinderResult result = item.getState().getStartTimeFinderResult();
|
||||
if (result.isDependentStartTime()) {
|
||||
if (RaceHelper.getSimpleRaceLogIdentifier(race).equals(Util.get(result.getRacesDependingOn(), 0))) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private int getParentPos(ManagedRace race) {
|
||||
int pos = 0;
|
||||
StartTimeFinderResult result = race.getState().getStartTimeFinderResult();
|
||||
if (result.isDependentStartTime()) {
|
||||
for (ManagedRace item : mSelected) {
|
||||
pos++;
|
||||
if (RaceHelper.getSimpleRaceLogIdentifier(item).equals(Util.get(result.getRacesDependingOn(), 0))) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private boolean remove(ManagedRace race) {
|
||||
for (ManagedRace item : mSelected) {
|
||||
if (item.equals(race)) {
|
||||
mSelected.remove(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private ManagedRace getRace(ManagedRace race) {
|
||||
for (ManagedRace item : mSelected) {
|
||||
if (item.equals(race)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public TextView race;
|
||||
public CheckBox selected;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
||||
race = (TextView) itemView.findViewById(R.id.abort_text);
|
||||
selected = (CheckBox) itemView.findViewById(R.id.abort_checkbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
+81
-67
@@ -1,18 +1,25 @@
|
||||
package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.util.ViewHelper;
|
||||
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.RaceState;
|
||||
import com.sap.sailing.domain.common.racelog.Flags;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
|
||||
@@ -23,12 +30,13 @@ import com.sap.sailing.racecommittee.app.logging.LogEvent;
|
||||
import com.sap.sailing.racecommittee.app.ui.activities.RacingActivity;
|
||||
import com.sap.sailing.racecommittee.app.ui.adapters.AbortFlagsAdapter;
|
||||
import com.sap.sailing.racecommittee.app.ui.adapters.AbortFlagsAdapter.AbortFlagItemClick;
|
||||
import com.sap.sailing.racecommittee.app.ui.adapters.AbortNovemberAdapter;
|
||||
import com.sap.sailing.racecommittee.app.ui.fragments.RaceFragment;
|
||||
import com.sap.sailing.racecommittee.app.ui.fragments.RaceListFragment;
|
||||
import com.sap.sailing.racecommittee.app.ui.layouts.HeaderLayout;
|
||||
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class AbortFlagsFragment extends RaceFragment implements AbortFlagItemClick {
|
||||
@@ -61,7 +69,7 @@ public class AbortFlagsFragment extends RaceFragment implements AbortFlagItemCli
|
||||
HeaderLayout header = ViewHelper.get(layout, R.id.header);
|
||||
if (header != null) {
|
||||
header.setHeaderText(getArguments().getString(HEADER_TEXT, getString(R.string.not_available)));
|
||||
header.setOnClickListener(new View.OnClickListener() {
|
||||
header.setHeaderOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
sendIntent(AppConstants.INTENT_ACTION_CLEAR_TOGGLE);
|
||||
@@ -90,7 +98,7 @@ public class AbortFlagsFragment extends RaceFragment implements AbortFlagItemCli
|
||||
|
||||
case NOVEMBER:
|
||||
logFlag(flag);
|
||||
abortChildRaces(now, state, flag);
|
||||
abortRunningRaces(now, flag);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -134,79 +142,85 @@ public class AbortFlagsFragment extends RaceFragment implements AbortFlagItemCli
|
||||
sendIntent(AppConstants.INTENT_ACTION_TIME_SHOW);
|
||||
}
|
||||
|
||||
private void abortChildRaces(final TimePoint now, final RaceState state, final Flags flag) {
|
||||
RacingActivity activity = (RacingActivity) getActivity();
|
||||
final List<ManagedRace> races = activity
|
||||
.getChildRaces(getRace(), new RaceLogRaceStatus[] { RaceLogRaceStatus.STARTPHASE, RaceLogRaceStatus.RUNNING });
|
||||
|
||||
if (races.size() > 0) {
|
||||
final ArrayList<String> raceList = new ArrayList<>();
|
||||
for (ManagedRace race : races) {
|
||||
raceList.add(RaceHelper.getShortReverseRaceName(race, " / ", getRace()));
|
||||
}
|
||||
final ArrayList<ManagedRace> raceChecked = new ArrayList<>();
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AppTheme_AlertDialog);
|
||||
builder.setTitle(getArguments().getString(HEADER_TEXT, getString(R.string.not_available)) + " " + getString(R.string.flags_dependent_races));
|
||||
builder.setMultiChoiceItems(raceList.toArray(new String[raceList.size()]), null, new DialogInterface.OnMultiChoiceClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
|
||||
ManagedRace race = races.get(which);
|
||||
if (raceChecked.contains(race)) {
|
||||
raceChecked.remove(race);
|
||||
}
|
||||
if (isChecked) {
|
||||
raceChecked.add(race);
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
for (ManagedRace race : races) {
|
||||
RaceState raceState = race.getState();
|
||||
if (raceChecked.contains(race)) {
|
||||
private void abortRunningRaces(final TimePoint now, final Flags flag) {
|
||||
final RacingActivity activity = (RacingActivity) getActivity();
|
||||
final LinkedHashMap<String, ManagedRace> races = activity.getRunningRaces();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity, R.style.AppTheme_AlertDialog);
|
||||
View layout = LayoutInflater.from(builder.getContext()).inflate(R.layout.race_november_dialog, null);
|
||||
RecyclerView recyclerView = (RecyclerView) layout.findViewById(R.id.abort_list);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
|
||||
final AbortNovemberAdapter adapter = new AbortNovemberAdapter(races, getRace());
|
||||
recyclerView.setAdapter(adapter);
|
||||
builder.setTitle(R.string.abort_title);
|
||||
builder.setView(layout);
|
||||
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
List<ManagedRace> selectedRaces = adapter.getSelected();
|
||||
for (ManagedRace race : selectedRaces) {
|
||||
List<ManagedRace> racesToAbort = activity
|
||||
.getChildRaces(race, new RaceLogRaceStatus[] { RaceLogRaceStatus.STARTPHASE, RaceLogRaceStatus.RUNNING });
|
||||
for (ManagedRace abort : racesToAbort) {
|
||||
if (!isSelected(selectedRaces, abort)) {
|
||||
RaceState raceState = abort.getState();
|
||||
Duration startTimeDiff = raceState.getStartTimeFinderResult().getStartTimeDiff();
|
||||
raceState.setAborted(now, /* postponed */ false, flag);
|
||||
raceState.setAdvancePass(now);
|
||||
raceState.forceNewDependentStartTime(now, startTimeDiff, RaceHelper.getSimpleRaceLogIdentifier(getRace()));
|
||||
} else {
|
||||
raceState.forceNewStartTime(now, raceState.getStartTimeFinderResult().getStartTime());
|
||||
SimpleRaceLogIdentifier parent = Util.get(raceState.getStartTimeFinderResult().getRacesDependingOn(), 0);
|
||||
abortRace(raceState);
|
||||
raceState.forceNewDependentStartTime(now, startTimeDiff, parent);
|
||||
}
|
||||
}
|
||||
abortRace(now, state, flag);
|
||||
|
||||
List<ManagedRace> racesToLeave = activity
|
||||
.getChildRaces(race, new RaceLogRaceStatus[] { RaceLogRaceStatus.FINISHING, RaceLogRaceStatus.FINISHED });
|
||||
for (ManagedRace leave : racesToLeave) {
|
||||
leave.getState().forceNewStartTime(now, leave.getState().getStartTimeFinderResult().getStartTime());
|
||||
}
|
||||
if (!getRace().equals(race)) {
|
||||
abortRace(race.getState());
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
abortRace(now, state, flag);
|
||||
if (flag != Flags.NONE) {
|
||||
setProtestTime();
|
||||
}
|
||||
});
|
||||
builder.setCancelable(false);
|
||||
builder.show();
|
||||
} else {
|
||||
abortRace(now, state, flag);
|
||||
}
|
||||
abortRace(getRaceState());
|
||||
}
|
||||
|
||||
private void abortRace(RaceState raceState) {
|
||||
raceState.setAborted(now, /* postponed */ false, flag);
|
||||
raceState.setAdvancePass(now);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.abort_dismiss, null);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
||||
lp.copyFrom(dialog.getWindow().getAttributes());
|
||||
int maxItemHeight = (int) getItemHeight(activity) * races.size() + getActivity().getResources().getDimensionPixelSize(R.dimen.abort_dialog_height);
|
||||
lp.height = Math.min(maxItemHeight, (int) getMaxScreenHeight(activity));
|
||||
dialog.getWindow().setAttributes(lp);
|
||||
}
|
||||
|
||||
private void abortRace(TimePoint now, RaceState state, Flags flag) {
|
||||
fixStartTime(now);
|
||||
state.setAborted(now, /* postponed */ false, flag);
|
||||
if (flag != Flags.NONE) {
|
||||
setProtestTime();
|
||||
private boolean isSelected(List<ManagedRace> selectedRaces, ManagedRace race) {
|
||||
for (ManagedRace selected : selectedRaces) {
|
||||
if (selected.equals(race)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
state.setAdvancePass(now);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void fixStartTime(TimePoint now) {
|
||||
RacingActivity activity = (RacingActivity) getActivity();
|
||||
List<ManagedRace> races = activity
|
||||
.getChildRaces(getRace(), new RaceLogRaceStatus[] { RaceLogRaceStatus.PRESCHEDULED, RaceLogRaceStatus.SCHEDULED,
|
||||
RaceLogRaceStatus.FINISHING, RaceLogRaceStatus.FINISHED });
|
||||
private float getItemHeight(Activity activity) {
|
||||
TypedValue value = new android.util.TypedValue();
|
||||
activity.getTheme().resolveAttribute(android.R.attr.listPreferredItemHeight, value, true);
|
||||
TypedValue.coerceToString(value.type, value.data);
|
||||
DisplayMetrics metrics = new android.util.DisplayMetrics();
|
||||
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
return value.getDimension(metrics);
|
||||
}
|
||||
|
||||
for (ManagedRace race : races) {
|
||||
race.getState().forceNewStartTime(now, race.getState().getStartTimeFinderResult().getStartTime());
|
||||
}
|
||||
private float getMaxScreenHeight(Activity activity) {
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
return metrics.heightPixels * 0.85f;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ public class RaceHelper {
|
||||
raceName += seriesName;
|
||||
}
|
||||
if (maxElements >= 3) {
|
||||
raceName += groupName;
|
||||
raceName += delimiter + groupName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user