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? filter = null; if (!string.IsNullOrEmpty(nameFilter)) filter = new WrapperFilter(filter, solicitor => solicitor.Name.Contains(nameFilter)); if (cities is not null && cities.Length > 0) filter = new WrapperFilter(filter, solicitor => cities.Any(city => solicitor.Cities.Any(solCity => solCity.Name == city))); if (minRating > 0) filter = new WrapperFilter( filter, solicitor => solicitor.Ratings.Any(rating => (rating.Provider == ratingsProvider) && (rating.Value / rating.Maximum >= minRating / 5.0m))); IComparer? 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(); var first = await solicitors .GetSolicitorSummariesAsync( new Pagination(1, 1), "Solicitors.com", cancellationToken: CancellationToken.None); if (first.Data.Length == 0) await scope.ServiceProvider .GetRequiredService() .RunFullImport(CancellationToken.None); } app.Run(); public class RatingComparer(string ratingsProvider, bool ascending) : IComparer { 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 { 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; } }