show "running" races instead of dependent races in race selection and abort the correct races

This commit is contained in:
Peter Siegmund
2016-04-06 14:45:07 +02:00
parent cb2f69afcb
commit f77ed4e89e
9 changed files with 312 additions and 68 deletions
@@ -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>
@@ -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
@@ -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);
}
}
}
@@ -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;
}
}
@@ -108,7 +108,7 @@ public class RaceHelper {
raceName += seriesName;
}
if (maxElements >= 3) {
raceName += groupName;
raceName += delimiter + groupName;
}
}