initial commit
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
using System.ComponentModel;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Solicitors.CacheBuild;
|
||||
using Solicitors.Core;
|
||||
using Solicitors.Core.Misc;
|
||||
using Solicitors.Core.Models;
|
||||
using Solicitors.Data;
|
||||
using Solicitors.Data.RepositorySetup.Sqlite;
|
||||
using Solicitors.HtmlParsing;
|
||||
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddOpenApi();
|
||||
builder.Services.AddCore();
|
||||
builder.Services.AddData(new SqliteDbSetupOptions("demo"));
|
||||
builder.Services.AddCacheBuild();
|
||||
builder.Services.AddHtmlParsing();
|
||||
builder.Services.AddHttpClient();
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.MapOpenApi();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseCors();
|
||||
|
||||
app.MapGet(
|
||||
"/conveyancors",
|
||||
(
|
||||
[FromServices] IReadOnlySolicitorService solicitorService,
|
||||
CancellationToken cancellationToken,
|
||||
[FromQuery] uint pageNumber = 1,
|
||||
[FromQuery] uint pageSize = 20,
|
||||
[FromQuery] string? nameFilter = null,
|
||||
[FromQuery] decimal minRating = 0,
|
||||
[FromQuery] string[]? cities = null,
|
||||
[FromQuery] string ratingsProvider = "Solicitors.com",
|
||||
[FromQuery] string? orderingType = null) =>
|
||||
{
|
||||
IFilter<Solicitor>? filter = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(nameFilter))
|
||||
filter = new WrapperFilter<Solicitor>(filter, solicitor => solicitor.Name.Contains(nameFilter));
|
||||
|
||||
if (cities is not null && cities.Length > 0)
|
||||
filter = new WrapperFilter<Solicitor>(filter, solicitor => cities.Any(city => solicitor.Cities.Any(solCity => solCity.Name == city)));
|
||||
|
||||
if (minRating > 0)
|
||||
filter = new WrapperFilter<Solicitor>(
|
||||
filter,
|
||||
solicitor => solicitor.Ratings.Any(rating => (rating.Provider == ratingsProvider) && (rating.Value / rating.Maximum >= minRating / 5.0m)));
|
||||
|
||||
IComparer<Solicitor>? ordering = orderingType switch
|
||||
{
|
||||
"rating-asc" => new RatingComparer(ratingsProvider, true),
|
||||
"rating-desc" => new RatingComparer(ratingsProvider, false),
|
||||
"alphabet-asc" => new NameComparer(true),
|
||||
"alphabet-desc" => new NameComparer(false),
|
||||
_ => null
|
||||
};
|
||||
|
||||
return solicitorService.GetSolicitorSummariesAsync(
|
||||
new Pagination(pageNumber, pageSize),
|
||||
ratingsProvider,
|
||||
filter,
|
||||
ordering,
|
||||
cancellationToken: cancellationToken);
|
||||
}
|
||||
);
|
||||
|
||||
app.MapGet(
|
||||
"/cities",
|
||||
(
|
||||
[FromServices] IReadOnlyCitiesService citiesService,
|
||||
CancellationToken cancellationToken) =>
|
||||
{
|
||||
return citiesService.GetAllCitiesAsync(cancellationToken);
|
||||
}
|
||||
);
|
||||
|
||||
app.MapGet(
|
||||
"/conveyancors/{id}",
|
||||
(
|
||||
[FromServices] IReadOnlySolicitorService solicitorService,
|
||||
[FromRoute] Guid id,
|
||||
CancellationToken cancellationToken
|
||||
) => solicitorService.GetSolicitorInfoByIdAsync(id, cancellationToken)
|
||||
);
|
||||
|
||||
app.MapGet(
|
||||
"/ratingsProviders",
|
||||
(
|
||||
[FromServices] IRatingsProviderService service,
|
||||
CancellationToken cancellationToken
|
||||
) =>
|
||||
{
|
||||
return service.GetRatingsProvidersAsync(cancellationToken);
|
||||
}
|
||||
);
|
||||
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var solicitors = scope.ServiceProvider.GetRequiredService<ISolicitorService>();
|
||||
var first = await solicitors
|
||||
.GetSolicitorSummariesAsync(
|
||||
new Pagination(1, 1),
|
||||
"Solicitors.com",
|
||||
cancellationToken: CancellationToken.None);
|
||||
if (first.Data.Length == 0)
|
||||
await scope.ServiceProvider
|
||||
.GetRequiredService<ISolicitorImporter>()
|
||||
.RunFullImport(CancellationToken.None);
|
||||
}
|
||||
|
||||
app.Run();
|
||||
|
||||
public class RatingComparer(string ratingsProvider, bool ascending) : IComparer<Solicitor>
|
||||
{
|
||||
public int Compare(Solicitor? x, Solicitor? y)
|
||||
{
|
||||
var xRating = x?.Ratings?.FirstOrDefault(r => r.Provider == ratingsProvider);
|
||||
var yRating = y?.Ratings?.FirstOrDefault(r => r.Provider == ratingsProvider);
|
||||
|
||||
decimal compare;
|
||||
|
||||
if (xRating is null)
|
||||
compare = yRating is null ? 0 : 1;
|
||||
else if (yRating is null)
|
||||
compare = -1;
|
||||
else
|
||||
{
|
||||
compare = (xRating.Value / xRating.Maximum) - (yRating.Value / yRating.Maximum);
|
||||
|
||||
if (!ascending)
|
||||
compare *= -1;
|
||||
}
|
||||
|
||||
if (compare >= 0)
|
||||
return (int)Math.Ceiling(compare);
|
||||
else
|
||||
return (int)Math.Floor(compare);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class NameComparer(bool ascending) : IComparer<Solicitor>
|
||||
{
|
||||
public int Compare(Solicitor? x, Solicitor? y)
|
||||
{
|
||||
int compare;
|
||||
if (ReferenceEquals(x, y))
|
||||
compare = 0;
|
||||
else if (y is null)
|
||||
compare = 1;
|
||||
else if (x is null)
|
||||
compare = -1;
|
||||
else
|
||||
{
|
||||
compare = string.Compare(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (!ascending)
|
||||
compare *= -1;
|
||||
}
|
||||
|
||||
return compare;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:5084",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "https://localhost:7128;http://localhost:5084",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.9">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\libs\Solicitors.CacheBuild\Solicitors.CacheBuild.csproj" />
|
||||
<ProjectReference Include="..\libs\Solicitors.Core\Solicitors.Core.csproj" />
|
||||
<ProjectReference Include="..\libs\Solicitors.Data\Solicitors.Data.csproj" />
|
||||
<ProjectReference Include="..\libs\Solicitors.HtmlParsing\Solicitors.HtmlParsing.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
@SolicitorsApi_HostAddress = http://localhost:5084
|
||||
|
||||
GET {{SolicitorsApi_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
Reference in New Issue
Block a user