Skip to content

Commit

Permalink
Implement ProfileCreator interface, validator, some services and all …
Browse files Browse the repository at this point in the history
…that
  • Loading branch information
Neakita committed Sep 17, 2023
1 parent 6c68823 commit 94db6c0
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 3 deletions.
6 changes: 6 additions & 0 deletions SightKeeper.Application/Profile/Creating/NewProfileData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace SightKeeper.Application;

public interface NewProfileData : ProfileData
{

}
25 changes: 25 additions & 0 deletions SightKeeper.Application/Profile/Creating/NewProfileDataDTO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Collections.Immutable;
using SightKeeper.Domain.Model;
using SightKeeper.Domain.Model.Common;

namespace SightKeeper.Application;

public sealed class NewProfileDataDTO : NewProfileData
{
public string Name { get; }
public string Description { get; }
public float DetectionThreshold { get; }
public float MouseSensitivity { get; }
public Weights Weights { get; }
public IReadOnlyList<ItemClass> ItemClasses { get; }

public NewProfileDataDTO(string name, string description, float detectionThreshold, float mouseSensitivity, Weights weights, IEnumerable<ItemClass> itemClasses)
{
Name = name;
Description = description;
DetectionThreshold = detectionThreshold;
MouseSensitivity = mouseSensitivity;
Weights = weights;
ItemClasses = itemClasses.ToImmutableList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using FluentValidation;
using SightKeeper.Domain.Services;

namespace SightKeeper.Application;

public sealed class NewProfileDataValidator : AbstractValidator<NewProfileData>
{
private readonly ProfilesDataAccess _profilesDataAccess;

public NewProfileDataValidator(IValidator<ProfileData> profileDataValidator, ProfilesDataAccess profilesDataAccess)
{
_profilesDataAccess = profilesDataAccess;
Include(profileDataValidator);
RuleFor(data => data.Name)
.MustAsync(NameIsUnique);
}

private async Task<bool> NameIsUnique(string name, CancellationToken cancellationToken)
{
var profiles = await _profilesDataAccess.LoadAllProfiles(cancellationToken);
return profiles.All(profile => profile.Name != name);
}
}
27 changes: 27 additions & 0 deletions SightKeeper.Application/Profile/Creating/ProfileCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using FluentValidation;
using SightKeeper.Domain.Model;
using SightKeeper.Domain.Services;

namespace SightKeeper.Application;

public sealed class ProfileCreator
{
public ProfileCreator(IValidator<NewProfileData> validator, ProfilesDataAccess profilesDataAccess)
{
_validator = validator;
_profilesDataAccess = profilesDataAccess;
}

public async Task<Profile> CreateProfile(NewProfileDataDTO data)
{
await _validator.ValidateAndThrowAsync(data);
Profile profile = new(data.Name, data.Description, data.DetectionThreshold, data.MouseSensitivity, data.Weights);
foreach (var itemClass in data.ItemClasses)
profile.AddItemClass(itemClass);
await _profilesDataAccess.AddProfile(profile);
return profile;
}

private readonly IValidator<NewProfileData> _validator;
private readonly ProfilesDataAccess _profilesDataAccess;
}
14 changes: 14 additions & 0 deletions SightKeeper.Application/Profile/ProfileData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using SightKeeper.Domain.Model;
using SightKeeper.Domain.Model.Common;

namespace SightKeeper.Application;

public interface ProfileData
{
string Name { get; }
string Description { get; }
float DetectionThreshold { get; }
float MouseSensitivity { get; }
Weights? Weights { get; }
IReadOnlyList<ItemClass> ItemClasses { get; }
}
23 changes: 23 additions & 0 deletions SightKeeper.Application/Profile/ProfileDataValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using FluentValidation;
using SightKeeper.Commons.Validation;

namespace SightKeeper.Application;

public sealed class ProfileDataValidator : AbstractValidator<ProfileData>
{
public ProfileDataValidator()
{
RuleFor(data => data.Name)
.NotEmpty();
RuleFor(data => data.DetectionThreshold)
.ExclusiveBetween(0, 1);
RuleFor(data => data.MouseSensitivity)
.GreaterThan(0);
RuleFor(data => data.Weights)
.NotNull();
RuleForEach(data => data.ItemClasses)
.Must((data, profileItemClass) => profileItemClass.DataSet == data.Weights!.Library.DataSet)
.When(data => data.Weights != null);
RuleFor(data => data.ItemClasses).NoDuplicates();
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=profile/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=profile_005Ccreating/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=profile_005Cediting/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=training_005Cclassifier/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=training_005Cdetector/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
6 changes: 6 additions & 0 deletions SightKeeper.Data/Services/DbProfilesDataAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ public Task RemoveProfile(Profile profile, CancellationToken cancellationToken =
}, cancellationToken);
}

public Task<IReadOnlyCollection<Profile>> LoadAllProfiles(CancellationToken cancellationToken) => Task.Run(() =>
{
lock (_dbContext)
return (IReadOnlyCollection<Profile>)_dbContext.Profiles.ToList();
}, cancellationToken);

public IObservable<Profile> LoadProfiles()
{
return Observable.Create<Profile>(observer =>
Expand Down
4 changes: 4 additions & 0 deletions SightKeeper.Data/SightKeeper.Data.csproj.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cprofile/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
6 changes: 4 additions & 2 deletions SightKeeper.Domain.Model/Profile/Profile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ public Profile(string name, string description, float detectionThreshold, float
_itemClasses = new List<ProfileItemClass>();
}

public void AddItemClass(ItemClass itemClass)
public ProfileItemClass AddItemClass(ItemClass itemClass)
{
if (!Weights.Library.DataSet.ItemClasses.Contains(itemClass))
ThrowHelper.ThrowArgumentException(nameof(itemClass), $"Item class \"{itemClass}\" not found in dataset \"{Weights}\"");
if (_itemClasses.Any(orderedItemClass => orderedItemClass.ItemClass == itemClass))
ThrowHelper.ThrowArgumentException($"Item class {itemClass} already added to profile {this}");
_itemClasses.Add(new ProfileItemClass(itemClass, (byte)_itemClasses.Count));
var profileItemClass = new ProfileItemClass(itemClass, (byte)_itemClasses.Count);
_itemClasses.Add(profileItemClass);
return profileItemClass;
}

public void RemoveItemClass(ItemClass itemClass)
Expand Down
1 change: 1 addition & 0 deletions SightKeeper.Domain.Services/ProfilesDataAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ public interface ProfilesDataAccess

Task AddProfile(Profile profile, CancellationToken cancellationToken = default);
Task RemoveProfile(Profile profile, CancellationToken cancellationToken = default);
Task<IReadOnlyCollection<Profile>> LoadAllProfiles(CancellationToken cancellationToken = default);
IObservable<Profile> LoadProfiles();
}

0 comments on commit 94db6c0

Please sign in to comment.