Skip to content

Commit

Permalink
fix warning and use primary constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
phmatray committed Nov 20, 2023
1 parent 02eb091 commit 5d7c59a
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 99 deletions.
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,49 @@
# Geometrix
A web api to generate geometric images

Geometrix is a web API that generates geometric images based on user-defined parameters. It uses a combination of mirror power, cell group length, cell width pixel, seed, and color themes to create unique and visually appealing geometric patterns.

![A generated image](geometrix-api/Geometrix.WebApi/wwwroot/Images/4-42-F-2-2-dark-indigo-64.png)

## Features

- Generate geometric images with customizable parameters
- Save generated images as PNG files
- Retrieve saved images

## Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.

### Prerequisites

- .NET 8.0 or later
- A suitable IDE such as JetBrains Rider or Visual Studio

### Installing

1. Clone the repository ```git clone https://github.com/phmatray/Geometrix.git```
2. Navigate to the project directory ```cd Geometrix```
3. Restore the packages ```dotnet restore```
4. Build the project ```dotnet build```
5. Run the project ```dotnet run --project Geometrix.WebApi/Geometrix.WebApi.csproj```

## Usage

To generate an image, make a POST request to `/api/GenerateImage` with the following parameters:

- `mirrorPowerHorizontal`: (integer) The mirror power in the horizontal direction.
- `mirrorPowerVertical`: (integer) The mirror power in the vertical direction.
- `cellGroupLength`: (integer) The length of the cell group.
- `cellWidthPixel`: (integer) The width of the cell in pixels.
- `includeEmptyAndFill`: (boolean) Whether to include empty and fill cells.
- `seed`: (integer) The seed for the random number generator.
- `backgroundColor`: (string) The background color in hexadecimal format.
- `foregroundColor`: (string) The foreground color in hexadecimal format.

## Contributing

Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.

## License

This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
using Geometrix.Application.Services;
using Geometrix.Domain;
using Geometrix.Domain.Patterns;
using Geometrix.Domain.ValueObjects;

namespace Geometrix.Application.UseCases.GenerateImage;

public sealed class GenerateImageUseCase : IGenerateImageUseCase
public sealed class GenerateImageUseCase(
IImageCreation imageCreationService,
IFileStorageService fileStorageService,
IImageDescriptionFactory imageDescriptionFactory)
: IGenerateImageUseCase
{
private readonly IImageCreation _imageCreationService;
private readonly IFileStorageService _fileStorageService;
private readonly IImageDescriptionFactory _imageDescriptionFactory;
private IOutputPort _outputPort;

public GenerateImageUseCase(
IImageCreation imageCreationService,
IFileStorageService fileStorageService,
IImageDescriptionFactory imageDescriptionFactory)
{
_imageCreationService = imageCreationService;
_fileStorageService = fileStorageService;
_imageDescriptionFactory = imageDescriptionFactory;
_outputPort = new GenerateImagePresenter();
}
private IOutputPort _outputPort = new GenerateImagePresenter();

public Task Execute(
int mirrorPowerHorizontal,
Expand All @@ -33,7 +22,7 @@ public Task Execute(
string backgroundColor,
string foregroundColor)
{
var pattern = _imageDescriptionFactory
var pattern = imageDescriptionFactory
.NewPattern(
mirrorPowerHorizontal, mirrorPowerVertical, cellGroupLength,
includeEmptyAndFill, seed);
Expand All @@ -43,18 +32,18 @@ public Task Execute(
new ThemeColor(backgroundColor),
new ThemeColor(foregroundColor));

var imageDescription = _imageDescriptionFactory
var imageDescription = imageDescriptionFactory
.NewImage(pattern, imageConfiguration);

return GeneratePng(imageDescription);
}

private async Task GeneratePng(ImageDescription imageDescription)
{
var bytes = await _imageCreationService
var bytes = await imageCreationService
.CreateImageAsync(imageDescription);

var fileName = await _fileStorageService
var fileName = await fileStorageService
.SaveFileAsync(bytes, imageDescription.Id, ".png");

if (fileName is null)
Expand Down
4 changes: 1 addition & 3 deletions geometrix-api/Geometrix.Domain/IImageDescription.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
namespace Geometrix.Domain;

public interface IImageDescription
{
}
public interface IImageDescription;
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
namespace Geometrix.Infrastructure.DataAccess.Repositories;

public sealed class ImageRepository
{
}
public sealed class ImageRepository;
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
using Geometrix.Application.Services;
using Geometrix.Domain;
using Geometrix.Domain.Patterns;
using Geometrix.Domain.ValueObjects;

namespace Geometrix.Infrastructure.ImageCreation;

public sealed class ImageCreationService : IImageCreation
public sealed class ImageCreationService(ImageEditionService imageEdition)
: IImageCreation
{
private readonly ImageEditionService _imageEdition;

public ImageCreationService(ImageEditionService imageEdition)
{
_imageEdition = imageEdition;
}

public async Task<byte[]> CreateImageAsync(ImageDescription imageDescription)
{
var (pattern, settings, imageWidthPixel, imageHeightPixel) = imageDescription;
using var image = new Image<Rgba32>(imageWidthPixel, imageHeightPixel);
_imageEdition.EditImage(image, pattern, settings);
imageEdition.EditImage(image, pattern, settings);
return await GetImageBytes(image);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,8 @@

namespace Geometrix.Infrastructure.ImageCreation;

public sealed class ImageEditionService
public sealed class ImageEditionService(TriangleService triangleService)
{
private readonly TriangleService _triangleService;

public ImageEditionService(TriangleService triangleService)
{
_triangleService = triangleService;
}

public void EditImage(
Image<Rgba32> image,
Pattern pattern,
Expand All @@ -37,15 +30,11 @@ private static void SetPolygons(Image<Rgba32> image, Color foreground, List<Poly
}
}

private static void SetPolygon(Image<Rgba32> image, Color foreground, Polygon polygon)
{
image.Mutate(context => context.Fill(foreground, polygon));
}
private static void SetPolygon(Image<Rgba32> image, Color foreground, Polygon polygon)
=> image.Mutate(context => context.Fill(foreground, polygon));

private static void SetBackground(Image<Rgba32> image, Color background)
{
image.Mutate(context => context.BackgroundColor(background));
}
=> image.Mutate(context => context.BackgroundColor(background));

private static Color ConvertToSixLaborsColor(ThemeColor color)
=> color switch
Expand All @@ -63,22 +52,15 @@ private static Color ConvertToSixLaborsColor(ThemeColor color)
};

private List<Polygon> ConvertToPolygons(Pattern pattern, int cellWidthPixel)
{
// var polygons = from cell in pattern.Cells
// let x = cell.X * cellWidthPixel
// let y = cell.Y * cellWidthPixel
// let direction = cell.TriangleDirection
// select _triangleService.GetTriangle(direction, x, y, cellWidthPixel);

return pattern.Cells
=> pattern.Cells
.Select(cell => new
{
X = cell.X * cellWidthPixel,
Y = cell.Y * cellWidthPixel,
Direction = cell.TriangleDirection
})
.Select(cell => _triangleService.GetTriangle(cell.Direction, cell.X, cell.Y, cellWidthPixel))
.Select(cell => triangleService.GetTriangle(cell.Direction, cell.X, cell.Y, cellWidthPixel))
.Where(polygon => polygon is not null)
.Cast<Polygon>()
.ToList();
}
}
6 changes: 6 additions & 0 deletions geometrix-api/Geometrix.WebApi/Geometrix.WebApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,10 @@
<ProjectReference Include="..\Geometrix.Infrastructure\Geometrix.Infrastructure.csproj" />
</ItemGroup>

<ItemGroup>
<Content Include="..\..\README.md">
<Link>README.md</Link>
</Content>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static IServiceCollection AddAuthentication(
x.DefaultChallengeScheme = "Test";
})
.AddScheme<AuthenticationSchemeOptions, TestAuthenticationHandler>(
"Test", options => { });
"Test", _ => { });
}

return services;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,9 @@ namespace Geometrix.WebApi.Modules.Common.FeatureFlags;
/// <summary>
/// Custom Controller Feature Provider.
/// </summary>
public sealed class CustomControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
public sealed class CustomControllerFeatureProvider(IFeatureManager featureManager)
: IApplicationFeatureProvider<ControllerFeature>
{
private readonly IFeatureManager _featureManager;

/// <summary>
/// Custom Controller Feature Provider constructor.
/// </summary>
public CustomControllerFeatureProvider(IFeatureManager featureManager) => _featureManager = featureManager;

/// <summary>
/// Populate Features.
/// </summary>
Expand All @@ -27,35 +21,39 @@ public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeatur
for (var i = feature.Controllers.Count - 1; i >= 0; i--)
{
var controller = feature.Controllers[i].AsType();
foreach (var customAttribute in controller.CustomAttributes)
{
if (customAttribute.AttributeType.FullName != typeof(FeatureGateAttribute).FullName)
{
continue;
}
ProcessController(controller, feature, i);
}
}

var constructorArgument = customAttribute.ConstructorArguments.First();
if (constructorArgument.Value is not IEnumerable arguments)
{
continue;
}
private void ProcessController(Type controller, ControllerFeature feature, int index)
{
if (controller.CustomAttributes.Any(ShouldRemoveController))
{
feature.Controllers.RemoveAt(index);
}
}

foreach (var argumentValue in arguments)
{
var typedArgument = (CustomAttributeTypedArgument)argumentValue!;
var typedArgumentValue = (CustomFeature)(int)typedArgument.Value!;
var isFeatureEnabled = _featureManager
.IsEnabledAsync(typedArgumentValue.ToString())
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
private bool ShouldRemoveController(CustomAttributeData customAttribute)
{
if (customAttribute.AttributeType.FullName != typeof(FeatureGateAttribute).FullName)
{
return false;
}

if (!isFeatureEnabled)
{
feature.Controllers.RemoveAt(i);
}
}
}
var constructorArgument = customAttribute.ConstructorArguments.First();
if (constructorArgument.Value is not IEnumerable arguments)
{
return false;
}

return arguments.Cast<CustomAttributeTypedArgument>()
.Any(argument => !IsFeatureEnabled((CustomFeature)(int)argument.Value!));
}

private bool IsFeatureEnabled(CustomFeature feature)
=> featureManager
.IsEnabledAsync(feature.ToString())
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5d7c59a

Please sign in to comment.