176 lines
5.3 KiB
C#
176 lines
5.3 KiB
C#
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;
|
|
}
|
|
} |