Several bug fixes of the recent app implementation

This commit is contained in:
Armin Zamani committed 2013-04-07 16:31:59 +02:00
1 parent 6c68ae868c
commit 78f70a0134
10 files changed
+546 -523

No files matched your search

@@ -60,6 +60,7 @@
<string name="racelist_scheduled">Scheduled for %s</string>
<string name="racelist_startphase">Start at %s in progress</string>
<string name="racelist_running">Running since %s</string>
<string name="racelist_finishing">Finishing</string>
<string name="racelist_finished">Finished</string>
<string name="racelist_unknown">Unknown</string>
<string name="currentlyLoading">Currently loading &#8230;</string>
@@ -8,7 +8,7 @@ import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.SetStartTimeRaceF
public class AppConstants {
public static final boolean IS_DATA_OFFLINE = true;
public static final boolean IS_DATA_OFFLINE = false;
public final static String ApplicationVersion = "2.0 Beta 1 - Jumbotron";
@@ -12,6 +12,7 @@ import com.sap.sailing.domain.racelog.PassAwareRaceLog;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.ManagedRaceIdentifier;
import com.sap.sailing.racecommittee.app.domain.startprocedure.impl.ExtremeSailingSeriesStartProcedure;
import com.sap.sailing.racecommittee.app.domain.state.RaceState;
import com.sap.sailing.racecommittee.app.domain.state.impl.RaceStateImpl;
@@ -25,7 +26,8 @@ public class ManagedRaceImpl implements ManagedRace {
private Iterable<Competitor> competitors;
public ManagedRaceImpl(ManagedRaceIdentifier identifier, PassAwareRaceLog raceLog, Iterable<Competitor> competitors) {
this(identifier, new RaceStateImpl(raceLog, null), competitors);
//TODO To be changed when the start procedure for a regatta/leaderboard can be selected in the GWT Admin Console on backend side
this(identifier, new RaceStateImpl(raceLog, new ExtremeSailingSeriesStartProcedure(raceLog)), competitors);
}
public ManagedRaceImpl(
@@ -83,15 +83,21 @@ public class RaceStateImpl implements RaceState, RaceLogChangedListener {
RaceLogRaceStatus oldStatus = this.status;
this.status = newStatus;
if (oldStatus != newStatus) {
notifyListeners();
notifyListenersAboutStateChange();
}
}
private void notifyListeners() {
private void notifyListenersAboutStateChange() {
for (RaceStateChangedListener listener : stateChangedListeners) {
listener.onRaceStateChanged(this);
}
}
private void notifyListenersAboutStartTimeChange(TimePoint newStartTime) {
for (RaceStateChangedListener listener : stateChangedListeners) {
listener.onStartTimeChanged(newStartTime);
}
}
public void registerListener(RaceStateChangedListener listener) {
stateChangedListeners.add(listener);
@@ -116,6 +122,7 @@ public class RaceStateImpl implements RaceState, RaceLogChangedListener {
RaceLogEvent event = RaceLogEventFactory.INSTANCE.createStartTimeEvent(eventTime, UUID.randomUUID(),
Collections.<Competitor> emptyList(), raceLog.getCurrentPassId(), newStartTime);
this.raceLog.add(event);
notifyListenersAboutStartTimeChange(newStartTime);
}
public TimePoint getFinishedTime() {
@@ -17,6 +17,7 @@ import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
@@ -160,7 +161,7 @@ public class RaceStateService extends Service {
return;
}
TimePoint eventTime = (TimePoint) intent.getSerializableExtra(AppConstants.RACING_EVENT_TIME);
TimePoint eventTime = new MillisecondsTimePoint(intent.getExtras().getLong(AppConstants.RACING_EVENT_TIME));
if (getString(R.string.intentActionAlarmAction).equals(action)) {
race.getState().getStartProcedure().dispatchFiredEventTimePoint(race.getState().getStartTime(), eventTime);
@@ -208,8 +209,6 @@ public class RaceStateService extends Service {
this.registeredLogListeners.put(race, logListener);
this.registeredStateListeners.put(race, stateListener);
ExLog.i(TAG, "Race " + race.getId() + " is scheduled now.");
} else {
ExLog.i(TAG, "Race " + race.getId() + " was already registered. Ignoring.");
}
@@ -235,6 +234,7 @@ public class RaceStateService extends Service {
for (TimePoint eventFireTimePoint : fireTimePoints) {
scheduleEventTime(race, eventFireTimePoint);
}
ExLog.i(TAG, "Race " + race.getId() + " is scheduled now.");
}
private void scheduleEventTime(ManagedRace race, TimePoint eventFireTimePoint) {
@@ -1,169 +1,180 @@
package com.sap.sailing.racecommittee.app.services.sending;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.logging.ExLog;
import com.sap.sailing.racecommittee.app.utils.FileHandlerUtils;
public class EventPersistenceManager {
private final static String TAG = EventPersistenceManager.class.getName();
private final static String delayedEventFileName = "delayedEvents.txt";
private Context context;
private String fileContent;
public EventPersistenceManager(Context context) {
this.context = context;
fileContent = "";
initializeFile();
}
public boolean areIntentsDelayed() {
return !fileContent.isEmpty();
}
public void persistIntent(Intent intent) {
Bundle extras = intent.getExtras();
Serializable serializedEvent = extras.getSerializable(AppConstants.EXTRAS_JSON_KEY);
String raceUuid = extras.getSerializable(AppConstants.RACE_ID_KEY).toString();
persistEvent(raceUuid, serializedEvent);
}
private void persistEvent(String raceUuid, Serializable serializedEvent) {
String eventLine = String.format("%s;%s\n", raceUuid, serializedEvent);
ExLog.i(TAG, "Called to persist following event " + eventLine);
if (!fileContent.isEmpty()) {
if (fileContent.contains(eventLine)) {
ExLog.i(TAG, "The event to persist exists already in file");
return;
}
}
writeEventToFile(eventLine);
}
public void removeIntent(Intent intent) {
Bundle extras = intent.getExtras();
String serializedEvent = extras.getString(AppConstants.EXTRAS_JSON_KEY);
String raceUuid = extras.getString(AppConstants.RACE_ID_KEY);
removeEvent(raceUuid, serializedEvent);
}
private void removeEvent(String raceUuid, String serializedEvent) {
if (fileContent.isEmpty())
return;
ExLog.i(TAG, "removeEvent is called for " + raceUuid + ", serializedEvent " + serializedEvent);
String eventLine = String.format("%s;%s\n", raceUuid, serializedEvent);
removeEntryInFileContent(eventLine);
}
/**
* @param eventLine
*/
private void removeEntryInFileContent(String eventLine) {
if (fileContent.contains(eventLine)) {
fileContent = fileContent.replace(eventLine, "");
writeFileContentToFile();
ExLog.i(TAG, "Entry " + eventLine + " is removed from fileContent");
}
}
public int getEventCount() {
if (fileContent.isEmpty()) {
return 0;
}
return fileContent.split("\n").length;
}
public List<Intent> restoreEvents() {
List<Intent> delayedIntents = new ArrayList<Intent>();
if (!fileContent.isEmpty()) {
String[] eventLines = fileContent.split("\n");
for (String line : eventLines) {
String[] lineParts = line.split(";");
Intent eventIntent = EventSendingService.createEventIntent(context, lineParts[0], lineParts[1]);
delayedIntents.add(eventIntent);
}
}
ExLog.i(TAG, "Restored " + delayedIntents.size() + " events");
return delayedIntents;
}
/**
* @return
* @throws FileNotFoundException
*/
private String getFileContent() throws FileNotFoundException {
String fileContent = "";
FileInputStream inputStream;
try {
inputStream = context.openFileInput(delayedEventFileName);
fileContent = FileHandlerUtils.convertStreamToString(inputStream);
inputStream.close();
} catch (IOException e) {
ExLog.e(TAG, "In Method getFileContent(): " + e.getMessage() + " fileContent is empty");
}
return fileContent;
}
private void writeEventToFile(String eventLine) {
fileContent += eventLine;
writeFileContentToFile();
ExLog.i(TAG, "Wrote event to file: " + eventLine);
}
private void writeFileContentToFile() {
writeToFile(fileContent, Context.MODE_PRIVATE);
ExLog.i(TAG, "Wrote file content to file: " + fileContent);
}
private void initializeFile() {
try {
fileContent = getFileContent();
} catch (FileNotFoundException e) {
ExLog.w(TAG, "persistence file not found in internal storage. The file will be created.");
clearFileContent();
}
ExLog.i(TAG, "Initialized file");
}
private void clearFileContent() {
fileContent = "";
writeFileContentToFile();
}
private void writeToFile(String content, int mode) {
try {
FileOutputStream outputStream = context.openFileOutput(delayedEventFileName, mode);
outputStream.write(content.getBytes());
outputStream.close();
} catch (IOException e) {
ExLog.e(TAG, "In Method writeToFile: " + e.getMessage() + " with content " + content + " and mode " + mode);
}
}
}
package com.sap.sailing.racecommittee.app.services.sending;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.logging.ExLog;
import com.sap.sailing.racecommittee.app.utils.FileHandlerUtils;
public class EventPersistenceManager {
private final static String TAG = EventPersistenceManager.class.getName();
private final static String delayedEventFileName = "delayedEvents.txt";
private Context context;
private String fileContent;
public EventPersistenceManager(Context context) {
this.context = context;
fileContent = "";
initializeFile();
}
public boolean areIntentsDelayed() {
return !fileContent.isEmpty();
}
public void persistIntent(Intent intent) {
Bundle extras = intent.getExtras();
Serializable serializedEvent = extras.getSerializable(AppConstants.EXTRAS_JSON_KEY);
String raceUuid = extras.getSerializable(AppConstants.RACE_ID_KEY).toString();
persistEvent(raceUuid, serializedEvent);
}
private void persistEvent(String raceUuid, Serializable serializedEvent) {
String eventLine = String.format("%s;%s\n", raceUuid, serializedEvent);
ExLog.i(TAG, "Called to persist following event " + eventLine);
if (!fileContent.isEmpty()) {
if (fileContent.contains(eventLine)) {
ExLog.i(TAG, "The event to persist exists already in file");
return;
}
}
writeEventToFile(eventLine);
}
public void removeIntent(Intent intent) {
Bundle extras = intent.getExtras();
String serializedEvent = extras.getString(AppConstants.EXTRAS_JSON_KEY);
String raceUuid = extras.getString(AppConstants.RACE_ID_KEY);
removeEvent(raceUuid, serializedEvent);
}
private void removeEvent(String raceUuid, String serializedEvent) {
if (fileContent.isEmpty())
return;
ExLog.i(TAG, "removeEvent is called for " + raceUuid + ", serializedEvent " + serializedEvent);
String eventLine = String.format("%s;%s\n", raceUuid, serializedEvent);
removeEntryInFileContent(eventLine);
}
/**
* @param eventLine
*/
private void removeEntryInFileContent(String eventLine) {
if (fileContent.contains(eventLine)) {
fileContent = fileContent.replace(eventLine + "\n", "");
writeFileContentToFile();
ExLog.i(TAG, "Entry " + eventLine + " is removed from fileContent");
}
}
public int getEventCount() {
if (fileContent.isEmpty()) {
return 0;
}
return fileContent.split("\n").length;
}
public List<Intent> restoreEvents() {
List<Intent> delayedIntents = new ArrayList<Intent>();
List<String> fileEntriesToBeRemoved = new ArrayList<String>(); //These file entries may be too old. No appropriate race id has been found for this event.
if (!fileContent.isEmpty()) {
String[] eventLines = fileContent.split("\n");
for (String line : eventLines) {
if (!line.isEmpty()) {
String[] lineParts = line.split(";");
Intent eventIntent = EventSendingService.createEventIntent(context, lineParts[0], lineParts[1]);
if (eventIntent != null) {
delayedIntents.add(eventIntent);
} else {
fileEntriesToBeRemoved.add(line);
}
}
}
}
for (String lineToBeRemoved : fileEntriesToBeRemoved) {
removeEntryInFileContent(lineToBeRemoved);
}
ExLog.i(TAG, "Restored " + delayedIntents.size() + " events");
return delayedIntents;
}
/**
* @return
* @throws FileNotFoundException
*/
private String getFileContent() throws FileNotFoundException {
String fileContent = "";
FileInputStream inputStream;
try {
inputStream = context.openFileInput(delayedEventFileName);
fileContent = FileHandlerUtils.convertStreamToString(inputStream);
inputStream.close();
} catch (IOException e) {
ExLog.e(TAG, "In Method getFileContent(): " + e.getMessage() + " fileContent is empty");
}
return fileContent;
}
private void writeEventToFile(String eventLine) {
fileContent += eventLine;
writeFileContentToFile();
ExLog.i(TAG, "Wrote event to file: " + eventLine);
}
private void writeFileContentToFile() {
writeToFile(fileContent, Context.MODE_PRIVATE);
ExLog.i(TAG, "Wrote file content to file: " + fileContent);
}
private void initializeFile() {
try {
fileContent = getFileContent();
} catch (FileNotFoundException e) {
ExLog.w(TAG, "persistence file not found in internal storage. The file will be created.");
clearFileContent();
}
ExLog.i(TAG, "Initialized file");
}
private void clearFileContent() {
fileContent = "";
writeFileContentToFile();
}
private void writeToFile(String content, int mode) {
try {
FileOutputStream outputStream = context.openFileOutput(delayedEventFileName, mode);
outputStream.write(content.getBytes());
outputStream.close();
} catch (IOException e) {
ExLog.e(TAG, "In Method writeToFile: " + e.getMessage() + " with content " + content + " and mode " + mode);
}
}
}
@@ -1,232 +1,231 @@
package com.sap.sailing.racecommittee.app.ui.adapters.racelist;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.comparators.RaceListDataTypeElementComparator;
import com.sap.sailing.racecommittee.app.ui.comparators.RaceListDataTypeTitleComparator;
public class RaceListAdapter extends ArrayAdapter<RaceListDataType> {
public interface JuryFlagClickedListener {
public void onJuryFlagClicked(BoatClassSeriesDataFleet clickedItem);
}
public static final int VIEW_TYPE_COUNT = 2;
public static final int VIEW_BOAT_GROUP = 0;
public static final int VIEW_RACE = 1;
private LayoutInflater mInflater;
private JuryFlagClickedListener juryListener;
private RaceFilter filter;
private final Object mLock = new Object();
private List<RaceListDataType> items;
private List<RaceListDataType> originalItems;
public RaceListAdapter(Context context, int textViewResourceId,
List<RaceListDataType> objects, JuryFlagClickedListener juryListener) {
super(context, textViewResourceId, objects);
this.items = objects;
this.originalItems = new ArrayList<RaceListDataType>();
this.juryListener = juryListener;
mInflater = (LayoutInflater) (getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE));
}
@Override
public int getCount() {
synchronized(mLock) {
return items!=null ? items.size() : 0;
}
}
@Override
public RaceListDataType getItem(int position) {
RaceListDataType element = null;
synchronized(mLock) {
element = items!=null ? items.get(position) : null;
}
return element;
}
@Override
public int getItemViewType(int position) {
return (getItem(position) instanceof RaceListDataTypeTitle ? VIEW_BOAT_GROUP
: VIEW_RACE);
}
@Override
public int getViewTypeCount() {
return VIEW_TYPE_COUNT;
}
@Override
public boolean isEnabled(int position) {
return (getItem(position) instanceof RaceListDataTypeElement);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
RaceListDataType raceListElement = null;
raceListElement = getItem(position);
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
if (type == VIEW_BOAT_GROUP) {
convertView = mInflater.inflate(R.layout.welter_one_row_no_image_label, null);
holder.line1 = (TextView) convertView.findViewById(R.id.Welter_Cell_OneRowNoImageLabel_txtTitle);
holder.button1 = (ImageButton) convertView.findViewById(R.id.Welter_Cell_OneRowNoImageLabel_btnJury);
} else if (type == VIEW_RACE) {
convertView = mInflater.inflate(R.layout.welter_two_row_no_image, null);
holder.line1 = (TextView) convertView.findViewById(R.id.Welter_Cell_TwoRowNoImage_lineOne);
holder.line2 = (TextView) convertView.findViewById(R.id.Welter_Cell_TwoRowNoImage_lineTwo);
holder.updateLabel = (ImageView) convertView.findViewById(R.id.Welter_Cell_UpdateLabel);
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (type == VIEW_BOAT_GROUP) {
final RaceListDataTypeTitle title = (RaceListDataTypeTitle) raceListElement;
holder.line1.setText(title.toString());
holder.button1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
juryListener.onJuryFlagClicked(title.getBoatClassSeriesDataFleet());
}
});
} else if (type == VIEW_RACE) {
RaceListDataTypeElement element = (RaceListDataTypeElement) raceListElement;
holder.line1.setText(element.getRaceName());
holder.line2.setText(element.getStatus());
if (element.isUpdateIndicatorVisible()) {
holder.updateLabel.setVisibility(View.VISIBLE);
}
}
return convertView;
}
@Override
public Filter getFilter() {
if (filter == null) {
filter = new RaceFilter();
}
return filter;
}
public List<RaceListDataType> getItems() {
return items;
}
static class ViewHolder {
TextView line1, line2;
ImageButton button1;
ImageView updateLabel;
}
private class RaceFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
// Initiate our results object
FilterResults results = new FilterResults();
List<RaceListDataType> dataTypeList = new ArrayList<RaceListDataType>();
if (originalItems.isEmpty()) {
originalItems = new ArrayList<RaceListDataType>(items.size());
for (RaceListDataType type : items) {
originalItems.add(type);
}
}
if (originalItems.isEmpty()) {
results.values = items;
results.count = items.size();
} else {
Map<RaceListDataTypeTitle, List<RaceListDataTypeElement>> elementMap
= new TreeMap<RaceListDataTypeTitle, List<RaceListDataTypeElement>>(new RaceListDataTypeTitleComparator());
RaceListDataTypeTitle currentTitle = null;
for (RaceListDataType element : originalItems) {
if (element instanceof RaceListDataTypeTitle) {
currentTitle = (RaceListDataTypeTitle) element;
elementMap.put(currentTitle, new ArrayList<RaceListDataTypeElement>());
} else if (element instanceof RaceListDataTypeElement) {
RaceListDataTypeElement listElement = (RaceListDataTypeElement) element;
if (elementMap.containsKey(currentTitle)) {
elementMap.get(currentTitle).add(listElement);
}
}
}
for (RaceListDataTypeTitle title : elementMap.keySet()) {
dataTypeList.add(title);
List<RaceListDataTypeElement> elementList = elementMap.get(title);
Collections.sort(elementList, new RaceListDataTypeElementComparator());
RaceListDataTypeElement lastFinishedRace = null;
int numberOfUnscheduledRaces = 0;
/// TODO: new status FINISHING?!?!?!
for (RaceListDataTypeElement dataElement : elementList) {
if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.FINISHED)) {
lastFinishedRace = dataElement;
}
}
for (RaceListDataTypeElement dataElement : elementList) {
if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.UNSCHEDULED)) {
numberOfUnscheduledRaces++;
if (numberOfUnscheduledRaces > 1)
continue;
} else if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.FINISHED)) {
if (!dataElement.equals(lastFinishedRace)) {
continue;
}
}
dataTypeList.add(dataElement);
}
}
results.values = dataTypeList;
results.count = dataTypeList.size();
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
synchronized(mLock) {
items = (List<RaceListDataType>) results.values;
notifyDataSetChanged();
}
}
}
}
package com.sap.sailing.racecommittee.app.ui.adapters.racelist;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.comparators.RaceListDataTypeElementComparator;
import com.sap.sailing.racecommittee.app.ui.comparators.RaceListDataTypeTitleComparator;
public class RaceListAdapter extends ArrayAdapter<RaceListDataType> {
public interface JuryFlagClickedListener {
public void onJuryFlagClicked(BoatClassSeriesDataFleet clickedItem);
}
public static final int VIEW_TYPE_COUNT = 2;
public static final int VIEW_BOAT_GROUP = 0;
public static final int VIEW_RACE = 1;
private LayoutInflater mInflater;
private JuryFlagClickedListener juryListener;
private RaceFilter filter;
private final Object mLock = new Object();
private List<RaceListDataType> items;
private List<RaceListDataType> originalItems;
public RaceListAdapter(Context context, int textViewResourceId,
List<RaceListDataType> objects, JuryFlagClickedListener juryListener) {
super(context, textViewResourceId, objects);
this.items = objects;
this.originalItems = new ArrayList<RaceListDataType>();
this.juryListener = juryListener;
mInflater = (LayoutInflater) (getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE));
}
@Override
public int getCount() {
synchronized(mLock) {
return items!=null ? items.size() : 0;
}
}
@Override
public RaceListDataType getItem(int position) {
RaceListDataType element = null;
synchronized(mLock) {
element = items!=null ? items.get(position) : null;
}
return element;
}
@Override
public int getItemViewType(int position) {
return (getItem(position) instanceof RaceListDataTypeTitle ? VIEW_BOAT_GROUP
: VIEW_RACE);
}
@Override
public int getViewTypeCount() {
return VIEW_TYPE_COUNT;
}
@Override
public boolean isEnabled(int position) {
return (getItem(position) instanceof RaceListDataTypeElement);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
RaceListDataType raceListElement = null;
raceListElement = getItem(position);
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
if (type == VIEW_BOAT_GROUP) {
convertView = mInflater.inflate(R.layout.welter_one_row_no_image_label, null);
holder.line1 = (TextView) convertView.findViewById(R.id.Welter_Cell_OneRowNoImageLabel_txtTitle);
holder.button1 = (ImageButton) convertView.findViewById(R.id.Welter_Cell_OneRowNoImageLabel_btnJury);
} else if (type == VIEW_RACE) {
convertView = mInflater.inflate(R.layout.welter_two_row_no_image, null);
holder.line1 = (TextView) convertView.findViewById(R.id.Welter_Cell_TwoRowNoImage_lineOne);
holder.line2 = (TextView) convertView.findViewById(R.id.Welter_Cell_TwoRowNoImage_lineTwo);
holder.updateLabel = (ImageView) convertView.findViewById(R.id.Welter_Cell_UpdateLabel);
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (type == VIEW_BOAT_GROUP) {
final RaceListDataTypeTitle title = (RaceListDataTypeTitle) raceListElement;
holder.line1.setText(title.toString());
holder.button1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
juryListener.onJuryFlagClicked(title.getBoatClassSeriesDataFleet());
}
});
} else if (type == VIEW_RACE) {
RaceListDataTypeElement element = (RaceListDataTypeElement) raceListElement;
holder.line1.setText(element.getRaceName());
holder.line2.setText(element.getStatus());
if (element.isUpdateIndicatorVisible()) {
holder.updateLabel.setVisibility(View.VISIBLE);
}
}
return convertView;
}
@Override
public Filter getFilter() {
if (filter == null) {
filter = new RaceFilter();
}
return filter;
}
public List<RaceListDataType> getItems() {
return items;
}
static class ViewHolder {
TextView line1, line2;
ImageButton button1;
ImageView updateLabel;
}
private class RaceFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
// Initiate our results object
FilterResults results = new FilterResults();
List<RaceListDataType> dataTypeList = new ArrayList<RaceListDataType>();
if (originalItems.isEmpty()) {
originalItems = new ArrayList<RaceListDataType>(items.size());
for (RaceListDataType type : items) {
originalItems.add(type);
}
}
if (originalItems.isEmpty()) {
results.values = items;
results.count = items.size();
} else {
Map<RaceListDataTypeTitle, List<RaceListDataTypeElement>> elementMap
= new TreeMap<RaceListDataTypeTitle, List<RaceListDataTypeElement>>(new RaceListDataTypeTitleComparator());
RaceListDataTypeTitle currentTitle = null;
for (RaceListDataType element : originalItems) {
if (element instanceof RaceListDataTypeTitle) {
currentTitle = (RaceListDataTypeTitle) element;
elementMap.put(currentTitle, new ArrayList<RaceListDataTypeElement>());
} else if (element instanceof RaceListDataTypeElement) {
RaceListDataTypeElement listElement = (RaceListDataTypeElement) element;
if (elementMap.containsKey(currentTitle)) {
elementMap.get(currentTitle).add(listElement);
}
}
}
for (RaceListDataTypeTitle title : elementMap.keySet()) {
dataTypeList.add(title);
List<RaceListDataTypeElement> elementList = elementMap.get(title);
Collections.sort(elementList, new RaceListDataTypeElementComparator());
RaceListDataTypeElement lastFinishedRace = null;
int numberOfUnscheduledRaces = 0;
for (RaceListDataTypeElement dataElement : elementList) {
if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.FINISHED)) {
lastFinishedRace = dataElement;
}
}
for (RaceListDataTypeElement dataElement : elementList) {
if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.UNSCHEDULED)) {
numberOfUnscheduledRaces++;
if (numberOfUnscheduledRaces > 1)
continue;
} else if (dataElement.getRace().getStatus().equals(RaceLogRaceStatus.FINISHED)) {
if (!dataElement.equals(lastFinishedRace)) {
continue;
}
}
dataTypeList.add(dataElement);
}
}
results.values = dataTypeList;
results.count = dataTypeList.size();
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
synchronized(mLock) {
items = (List<RaceListDataType>) results.values;
notifyDataSetChanged();
}
}
}
}
@@ -1,111 +1,114 @@
package com.sap.sailing.racecommittee.app.ui.adapters.racelist;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Locale;
import android.app.Fragment;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
public class RaceListDataTypeElement extends RaceListDataType {
private boolean updateIndicatorVisible = false;
private ManagedRace race;
private RaceLogRaceStatus currentRaceStatus;
private static String unscheduledTemplate;
private static String scheduldedTemplate;
private static String startPhaseTemplate;
private static String runningTemplate;
private static String finishedTemplate;
private static String unknownTemplate;
private Format scheduleFormatter = new SimpleDateFormat("HH:mm", Locale.US);
public static void initializeTemplates(Fragment fragment) {
unscheduledTemplate = fragment.getString(R.string.racelist_unscheduled);
scheduldedTemplate = fragment.getString(R.string.racelist_scheduled);
startPhaseTemplate = fragment.getString(R.string.racelist_startphase);
runningTemplate = fragment.getString(R.string.racelist_running);
finishedTemplate = fragment.getString(R.string.racelist_finished);
unknownTemplate = fragment.getString(R.string.racelist_unknown);
}
public RaceListDataTypeElement(ManagedRace race) {
setRace(race);
}
public ManagedRace getRace() {
return race;
}
public void setRace(ManagedRace race) {
this.race = race;
this.currentRaceStatus = race.getStatus();
}
public void setUpdateIndicator(boolean visible) {
this.updateIndicatorVisible = visible;
}
public boolean isUpdateIndicatorVisible() {
return updateIndicatorVisible;
}
public String getRaceName() {
if (race == null) {
return "Invalid race";
}
return race.getName();
}
public String getStatus() {
if (race == null) {
return "Invalid race";
}
return getStatusString(race.getStatus());
}
public RaceLogRaceStatus getPreviousRaceStatus() {
return currentRaceStatus;
}
public void setPreviousRaceStatus(RaceLogRaceStatus status) {
this.currentRaceStatus = status;
}
private String getStatusString(RaceLogRaceStatus status) {
switch (status) {
case UNSCHEDULED:
return unscheduledTemplate;
case SCHEDULED:
return String.format(scheduldedTemplate, formatStartTime());
case STARTPHASE:
return String.format(startPhaseTemplate, formatStartTime());
case RUNNING:
case FINISHING:
return String.format(runningTemplate, formatStartTime());
case FINISHED:
return finishedTemplate;
default:
return unknownTemplate;
}
}
private String formatStartTime() {
TimePoint startTime = race.getState().getStartTime();
if (startTime == null)
{
return unknownTemplate;
}
return scheduleFormatter.format(startTime.asDate());
}
}
package com.sap.sailing.racecommittee.app.ui.adapters.racelist;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Locale;
import android.app.Fragment;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
public class RaceListDataTypeElement extends RaceListDataType {
private boolean updateIndicatorVisible = false;
private ManagedRace race;
private RaceLogRaceStatus currentRaceStatus;
private static String unscheduledTemplate;
private static String scheduldedTemplate;
private static String startPhaseTemplate;
private static String runningTemplate;
private static String finishingTemplate;
private static String finishedTemplate;
private static String unknownTemplate;
private Format scheduleFormatter = new SimpleDateFormat("HH:mm", Locale.US);
public static void initializeTemplates(Fragment fragment) {
unscheduledTemplate = fragment.getString(R.string.racelist_unscheduled);
scheduldedTemplate = fragment.getString(R.string.racelist_scheduled);
startPhaseTemplate = fragment.getString(R.string.racelist_startphase);
runningTemplate = fragment.getString(R.string.racelist_running);
finishingTemplate = fragment.getString(R.string.racelist_finishing);
finishedTemplate = fragment.getString(R.string.racelist_finished);
unknownTemplate = fragment.getString(R.string.racelist_unknown);
}
public RaceListDataTypeElement(ManagedRace race) {
setRace(race);
}
public ManagedRace getRace() {
return race;
}
public void setRace(ManagedRace race) {
this.race = race;
this.currentRaceStatus = race.getStatus();
}
public void setUpdateIndicator(boolean visible) {
this.updateIndicatorVisible = visible;
}
public boolean isUpdateIndicatorVisible() {
return updateIndicatorVisible;
}
public String getRaceName() {
if (race == null) {
return "Invalid race";
}
return race.getName();
}
public String getStatus() {
if (race == null) {
return "Invalid race";
}
return getStatusString(race.getStatus());
}
public RaceLogRaceStatus getPreviousRaceStatus() {
return currentRaceStatus;
}
public void setPreviousRaceStatus(RaceLogRaceStatus status) {
this.currentRaceStatus = status;
}
private String getStatusString(RaceLogRaceStatus status) {
switch (status) {
case UNSCHEDULED:
return unscheduledTemplate;
case SCHEDULED:
return String.format(scheduldedTemplate, formatStartTime());
case STARTPHASE:
return String.format(startPhaseTemplate, formatStartTime());
case RUNNING:
return String.format(runningTemplate, formatStartTime());
case FINISHING:
return finishingTemplate;
case FINISHED:
return finishedTemplate;
default:
return unknownTemplate;
}
}
private String formatStartTime() {
TimePoint startTime = race.getState().getStartTime();
if (startTime == null)
{
return unknownTemplate;
}
return scheduleFormatter.format(startTime.asDate());
}
}