Files
it/MinimalAPI/Services/ComparisonService.cs
2025-11-03 17:03:57 +08:00

271 lines
9.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MinimalAPI.Data;
using MinimalAPI.Models;
using MinimalAPI.Models.DTOs;
namespace MinimalAPI.Services
{
public class ComparisonService : IComparisonService
{
private readonly AppDbContext _context;
private readonly IMapper _mapper;
public ComparisonService(AppDbContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public async Task<object> CompareProductsAsync(List<int> productIds)
{
// 验证输入
if (productIds == null || productIds.Count < 2 || productIds.Count > 4)
{
return null;
}
// 获取产品
var products = await _context.Products
.Include(p => p.Category)
.Where(p => productIds.Contains(p.Id))
.ToListAsync();
if (products.Count != productIds.Count)
{
return null;
}
// 检查是否所有产品属于同一类别
var categoryIds = products.Select(p => p.CategoryId).Distinct().ToList();
if (categoryIds.Count > 1)
{
return null;
}
// 获取性能分数
var productIdsList = products.Select(p => p.Id).ToList();
var performanceScores = await _context.PerformanceScores
.Where(ps => productIdsList.Contains(ps.ProductId))
.ToListAsync();
// 获取规格参数
var specifications = await _context.Specifications
.Where(s => productIdsList.Contains(s.ProductId))
.ToListAsync();
// 创建产品DTO列表
var productDtos = products.Select(p => {
var dto = _mapper.Map<ProductDto>(p);
dto.PerformanceScores = performanceScores
.Where(ps => ps.ProductId == p.Id)
.ToList();
dto.Specifications = specifications
.Where(s => s.ProductId == p.Id)
.ToList();
return dto;
}).ToList();
// 生成对比矩阵
var comparisonMatrix = GenerateComparisonMatrix(productDtos);
return new
{
Products = productDtos,
Comparison = comparisonMatrix
};
}
private List<Dictionary<string, object>> GenerateComparisonMatrix(List<ProductDto> products)
{
var matrix = new List<Dictionary<string, object>>();
// 添加基本信息行
matrix.Add(new Dictionary<string, object> { ["指标"] = "产品名称", ["类型"] = "基本信息" });
foreach (var product in products)
{
matrix[0][$"{product.Name}"] = product.Name;
}
// 添加制造商行
matrix.Add(new Dictionary<string, object> { ["指标"] = "制造商", ["类型"] = "基本信息" });
foreach (var product in products)
{
matrix[1][$"{product.Name}"] = product.Manufacturer;
}
// 添加型号行
matrix.Add(new Dictionary<string, object> { ["指标"] = "型号", ["类型"] = "基本信息" });
foreach (var product in products)
{
matrix[2][$"{product.Name}"] = product.Model;
}
// 添加排名行
matrix.Add(new Dictionary<string, object> { ["指标"] = "当前排名", ["类型"] = "性能指标" });
foreach (var product in products)
{
matrix[3][$"{product.Name}"] = product.CurrentRank;
}
// 添加发布日期行
matrix.Add(new Dictionary<string, object> { ["指标"] = "发布日期", ["类型"] = "基本信息" });
foreach (var product in products)
{
matrix[4][$"{product.Name}"] = product.ReleaseDate.ToString("yyyy-MM-dd");
}
// 添加价格行
matrix.Add(new Dictionary<string, object> { ["指标"] = "价格", ["类型"] = "基本信息" });
foreach (var product in products)
{
matrix[5][$"{product.Name}"] = product.Price?.ToString("C") ?? "N/A";
}
// 添加性能分数行
var benchmarkTypes = products
.SelectMany(p => p.PerformanceScores)
.Select(ps => ps.BenchmarkType)
.Distinct()
.ToList();
foreach (var benchmarkType in benchmarkTypes)
{
var rowIndex = matrix.Count;
matrix.Add(new Dictionary<string, object> { ["指标"] = benchmarkType, ["类型"] = "性能指标" });
foreach (var product in products)
{
var score = product.PerformanceScores
.FirstOrDefault(ps => ps.BenchmarkType == benchmarkType)?.Score;
matrix[rowIndex][$"{product.Name}"] = score?.ToString() ?? "N/A";
}
}
// 添加规格参数行
var specNames = products
.SelectMany(p => p.Specifications)
.Select(s => s.Name)
.Distinct()
.ToList();
foreach (var specName in specNames)
{
var rowIndex = matrix.Count;
matrix.Add(new Dictionary<string, object> { ["指标"] = specName, ["类型"] = "规格参数" });
foreach (var product in products)
{
var specValue = product.Specifications
.FirstOrDefault(s => s.Name == specName)?.Value;
matrix[rowIndex][$"{product.Name}"] = specValue ?? "N/A";
}
}
// 标记最优和最差值
MarkBestAndWorstValues(matrix, products);
return matrix;
}
private void MarkBestAndWorstValues(List<Dictionary<string, object>> matrix, List<ProductDto> products)
{
// 对于排名,越小越好
var rankRow = matrix.FirstOrDefault(m => m["指标"].ToString() == "当前排名");
if (rankRow != null)
{
var ranks = products.Select(p => p.CurrentRank).ToList();
var minRank = ranks.Min();
var maxRank = ranks.Max();
foreach (var product in products)
{
var rank = product.CurrentRank;
if (rank == minRank)
{
rankRow[$"{product.Name}_isBest"] = true;
}
else if (rank == maxRank)
{
rankRow[$"{product.Name}_isWorst"] = true;
}
}
}
// 对于价格,越小越好
var priceRow = matrix.FirstOrDefault(m => m["指标"].ToString() == "价格");
if (priceRow != null)
{
var prices = products.Where(p => p.Price.HasValue).Select(p => p.Price!.Value).ToList();
if (prices.Any())
{
var minPrice = prices.Min();
var maxPrice = prices.Max();
foreach (var product in products)
{
if (product.Price.HasValue)
{
if (product.Price == minPrice)
{
priceRow[$"{product.Name}_isBest"] = true;
}
else if (product.Price == maxPrice)
{
priceRow[$"{product.Name}_isWorst"] = true;
}
}
}
}
}
// 对于性能分数,越大越好
var performanceRows = matrix.Where(m => m["类型"].ToString() == "性能指标" &&
m["指标"].ToString() != "当前排名").ToList();
foreach (var row in performanceRows)
{
var benchmarkType = row["指标"].ToString();
var scores = new List<decimal?>();
foreach (var product in products)
{
var scoreStr = row[$"{product.Name}"]?.ToString();
if (decimal.TryParse(scoreStr, out var score))
{
scores.Add(score);
}
else
{
scores.Add(null);
}
}
var validScores = scores.Where(s => s.HasValue).Select(s => s!.Value).ToList();
if (validScores.Any())
{
var maxScore = validScores.Max();
var minScore = validScores.Min();
for (int i = 0; i < products.Count; i++)
{
if (scores[i].HasValue)
{
if (scores[i] == maxScore)
{
row[$"{products[i].Name}_isBest"] = true;
}
else if (scores[i] == minScore)
{
row[$"{products[i].Name}_isWorst"] = true;
}
}
}
}
}
}
}
}