1using CommunityToolkit.Mvvm.ComponentModel;
2using System.Collections;
3using System.Collections.ObjectModel;
4using System.ComponentModel;
38 private ObservableCollection<Person>
_personList {
get;
set; }
59 _personList.CollectionChanged += _personList_CollectionChanged;
60 _fileService = fileService;
70 _scoreService = scoreService;
80 _competitionService = competitionService;
90 _raceService = raceService;
103 public async Task<bool>
Load(
string path, CancellationToken cancellationToken)
105 bool importingResult =
false;
106 Exception exception =
null;
111 if (!File.Exists(path))
121 return PropertyNameLocalizedStringHelper.FindProperty(typeof(
Person), header);
124 _personList.CollectionChanged += _personList_CollectionChanged;
125 foreach (
Person person
in list)
135 importingResult =
true;
137 catch (OperationCanceledException)
139 importingResult =
false;
147 if (exception !=
null) {
throw exception; }
148 return importingResult;
159 public async Task<bool>
Save(CancellationToken cancellationToken,
string path =
"")
163 bool saveResult =
false;
164 Exception exception =
null;
169 _fileService.SaveToCsv(path,
_personList.ToList(), cancellationToken,
OnFileProgress, (data, parentObject, currentProperty) =>
171 if (data is bool dataBool)
174 bool isActive = true;
175 switch (currentProperty.Name)
177 case nameof(Person.Breaststroke): isActive = (parentObject as Person)?.Starts[SwimmingStyles.Breaststroke]?.IsActive ?? true; break;
178 case nameof(Person.Freestyle): isActive = (parentObject as Person)?.Starts[SwimmingStyles.Freestyle]?.IsActive ?? true; break;
179 case nameof(Person.Backstroke): isActive = (parentObject as Person)?.Starts[SwimmingStyles.Backstroke]?.IsActive ?? true; break;
180 case nameof(Person.Butterfly): isActive = (parentObject as Person)?.Starts[SwimmingStyles.Butterfly]?.IsActive ?? true; break;
181 case nameof(Person.Medley): isActive = (parentObject as Person)?.Starts[SwimmingStyles.Medley]?.IsActive ?? true; break;
182 case nameof(Person.WaterFlea): isActive = (parentObject as Person)?.Starts[SwimmingStyles.WaterFlea]?.IsActive ?? true; break;
184 return dataBool ? (isActive ?
"X" : Person.START_INACTIVE_MARKER_STRING) :
"";
186 else if (data is Enum dataEnum)
188 return EnumCoreLocalizedStringHelper.Convert(dataEnum);
190 else if (data is IList dataList)
192 return string.Join(
",", dataList.Cast<
object>().Select(d => d.ToString()));
196 return data.ToString();
201 return PropertyNameLocalizedStringHelper.Convert(typeof(
Person), header);
207 catch (OperationCanceledException)
217 if (exception !=
null) {
throw exception; }
237 _personList.CollectionChanged += _personList_CollectionChanged;
264 _competitionService.UpdateAllCompetitionsForPerson();
265 _raceService.ReassignAllPersonStarts();
277 _personList.CollectionChanged += _personList_CollectionChanged;
306 private bool _isupdatingScores =
false;
317 if (e.PropertyName == nameof(
Person.
Starts) && sender is
Person senderPerson && _scoreService !=
null && !_isupdatingScores)
319 _isupdatingScores =
true;
320 _scoreService.UpdateScoresForPerson(senderPerson);
321 _isupdatingScores =
false;
324 switch (e.PropertyName)
336 _competitionService.UpdateAllCompetitionsForPerson(sender as
Person);
347 private void _personList_CollectionChanged(
object sender,
System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
349 UpdateHasDuplicatesForPersons();
350 OnPropertyChanged(nameof(PersonCount));
351 OnPropertyChanged(nameof(PersonStarts));
352 OnPropertyChanged(nameof(HasUnsavedChanges));
371 IEnumerable<IGrouping<Person, Person>> duplicateGroups =
_personList.GroupBy(p => p, basicPersonComparer).Where(g => g.Count() > 1);
377 foreach (IGrouping<Person, Person> duplicateGroup
in duplicateGroups)
379 foreach (
Person person
in duplicateGroup) { person.HasDuplicates =
true; }
400 List<PersonStart> allPersonStarts =
new List<PersonStart>();
403 allPersonStarts.AddRange(person.
Starts.Values.Cast<
PersonStart>().Where(s => s !=
null));
408 allPersonStarts = allPersonStarts.Where(s => s.IsActive && s.IsCompetitionObjAssigned).ToList();
414 return allPersonStarts;
417 return allPersonStarts.Where(s => personBasicComparer.
Equals(s.PersonObj, (
Person)filterParameter)).ToList();
419 return allPersonStarts.Where(s => s.Style == (
SwimmingStyles)filterParameter).ToList();
421 return allPersonStarts.Where(s => s.CompetitionObj !=
null && s.CompetitionObj.Id == (
int)filterParameter).ToList();
422 default:
return allPersonStarts;
428 #region Friend Management
446 List<Person> friends =
_personList.Where(p => p != person &&
449 person.
Friends?.AddRange(friends);
452 foreach (
RacesVariant racesVariant
in _raceService.AllRacesVariants)
Comparer that only uses the most basic properties of a Person to determine equality:
bool Equals(Person x, Person y)
Check if two Person objects are equal based on basic properties.
Class describing a person.
string FirstName
First name of the person.
ObservableCollection< int > FriendGroupIDs
IDs of the friend groups the person belongs to.
List< Person > Friends
Friends of the person.
UInt16 BirthYear
Birth year of the person.
string Name
Last name of the person.
Genders Gender
Gender of the person.
Dictionary< SwimmingStyles, PersonStart > Starts
Dictionary with all starts of the person.
static void SetPropertyFromString(Person dataObj, string propertyName, string value)
Set the requested property in the Person object by parsing the given string value.
Class describing a start of a person.
Class that represents a combination variant of all single races.
double CalculateScore()
Recalculate all scores.
bool HasUnsavedChanges
Check if the list of Person has not saved changed.
ObservableCollection< Person > GetPersons()
Return all available Persons.
int PersonCount
Return the number of Person
List< PersonStart > GetAllPersonStarts(PersonStartFilters filter=PersonStartFilters.None, object filterParameter=null, bool onlyValidStarts=false)
Get all PersonStart objects for all Person objects that are not null.
void SetCompetitionServiceObj(ICompetitionService competitionService)
Save the reference to the ICompetitionService object.
ObservableCollection< Person > _personList
List with all people.
int PersonStarts
Return the total number of starts of all persons.
EventHandler OnFileFinished
Event that is raised when the file operation is finished.
void SetScoreServiceObj(IScoreService scoreService)
Save the reference to the IScoreService object.
async Task< bool > Save(CancellationToken cancellationToken, string path="")
Save the list of Persons to a file.
List< Person > _personListOnLoad
List with all people at the time the Load(string, CancellationToken) method was called.
void ResetToLoadedState()
Reset the list of Persons to the state when the Load(string, CancellationToken) method was called.
ProgressDelegate OnFileProgress
Event that is raised when the file operation progress changes.
int NumberFriendGroups
Return the number of friend groups.
void SetRaceServiceObj(IRaceService raceService)
Save the reference to the IRaceService object.
async Task< bool > Load(string path, CancellationToken cancellationToken)
Load a list of Persons to the _personList.
PersonService(IFileService fileService)
Constructor.
void ClearAll()
Clear all Persons.
void UpdateAllFriendReferencesFromFriendGroupIDs()
Loop all Person objects and update their friend references (Person.Friends) from the friend group IDs...
string PersistentPath
Path to the person file.
void AddPerson(Person person)
Add a new Person to the list of Persons.
void RemovePerson(Person person)
Remove the given Person from the list of Persons.
void UpdateHasDuplicatesForPersons()
Find all duplicate Person objects and update the Person.HasDuplicates flags.
void Person_PropertyChanged(object sender, PropertyChangedEventArgs e)
Event that is raised when a property of a Person changes.
Interface for a service used to get and store a list of objects.
Interface for a service that handles file operations.
Interface for a service used to get and store a list of Person objects.
Interface for a service used to manage Race and RacesVariant objects.
Interface for a service used to calculate the scores for all persons.
delegate void ProgressDelegate(object sender, float progress, string currentStep="")
Delegate void for progress changes.
SwimmingStyles
Available swimming styles.
PersonStartFilters
Available filters for PersonStart objects.
@ Person
Filter by Person object.