- Rimosse funzionalità legacy legate a WebView2. - Introdotto uno stile globale per i pulsanti. - Semplificata l'interfaccia con gestione tramite griglia unica. - Aggiunti comandi per avviare, mettere in pausa e fermare aste. - Introdotta gestione manuale dei cookie tramite dialog. - Aggiunti dialog per configurare sessione e aggiungere aste. - Migliorata la persistenza con salvataggio sicuro (DPAPI). - Rifattorizzate statistiche per utilizzare `BidHistory` e `BidderStats`. - Ottimizzato il polling per ridurre il carico di sistema. - Aggiornata esportazione CSV con dati più dettagliati. - Introdotti nuovi modelli dati per utente e banner aste. - Rimossi file di test manuale e codice obsoleto. - Aggiornata documentazione per riflettere le modifiche. - Aggiunta nuova icona dell'applicazione. - Migliorata la sicurezza eliminando il salvataggio in chiaro dei cookie.
129 lines
5.0 KiB
C#
129 lines
5.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace AutoBidder.Models
|
|
{
|
|
/// <summary>
|
|
/// Statistiche aggregate di un'asta per dashboard e export
|
|
/// </summary>
|
|
public class AuctionStatistics
|
|
{
|
|
public string AuctionId { get; set; } = "";
|
|
public string Name { get; set; } = "";
|
|
|
|
// Tempo monitoraggio
|
|
public DateTime MonitoringStarted { get; set; }
|
|
public TimeSpan MonitoringDuration { get; set; }
|
|
|
|
// Contatori
|
|
public int TotalBids { get; set; }
|
|
public int MyBids { get; set; }
|
|
public int OpponentBids { get; set; }
|
|
public int Resets { get; set; }
|
|
public int UniqueBidders { get; set; }
|
|
|
|
// Prezzi
|
|
public double StartPrice { get; set; }
|
|
public double CurrentPrice { get; set; }
|
|
public double MinPrice { get; set; }
|
|
public double MaxPrice { get; set; }
|
|
public double AvgPrice { get; set; }
|
|
|
|
// Timer
|
|
public double AvgTimerAtBid { get; set; }
|
|
public double MinTimerReached { get; set; }
|
|
|
|
// Latenza
|
|
public int AvgPollingLatencyMs { get; set; }
|
|
public int AvgClickLatencyMs { get; set; }
|
|
public int MinClickLatencyMs { get; set; }
|
|
public int MaxClickLatencyMs { get; set; }
|
|
|
|
// Rate
|
|
public double BidsPerMinute { get; set; }
|
|
public double ResetsPerHour { get; set; }
|
|
|
|
// Competitor analysis
|
|
public string MostActiveBidder { get; set; } = "";
|
|
public int MostActiveBidderCount { get; set; }
|
|
public Dictionary<string, int> BidderRanking { get; set; } = new();
|
|
|
|
// Success rate
|
|
public double MyBidSuccessRate { get; set; } // % mie puntate sul totale
|
|
|
|
// Calcola statistiche da BidHistory
|
|
public static AuctionStatistics Calculate(AuctionInfo auction)
|
|
{
|
|
var stats = new AuctionStatistics
|
|
{
|
|
AuctionId = auction.AuctionId,
|
|
Name = auction.Name,
|
|
MonitoringStarted = auction.AddedAt,
|
|
MonitoringDuration = DateTime.UtcNow - auction.AddedAt,
|
|
// MyBids calcolato dalle entry in BidHistory
|
|
MyBids = auction.BidHistory.Count(h => h.EventType == BidEventType.MyBid),
|
|
Resets = auction.ResetCount,
|
|
UniqueBidders = auction.BidderStats?.Count ?? 0,
|
|
BidderRanking = (auction.BidderStats ?? new Dictionary<string, BidderInfo>())
|
|
.ToDictionary(k => k.Key, v => v.Value.BidCount)
|
|
};
|
|
|
|
if (auction.BidHistory.Any())
|
|
{
|
|
var prices = auction.BidHistory.Select(h => h.Price).Where(p => p > 0).ToList();
|
|
if (prices.Any())
|
|
{
|
|
stats.StartPrice = prices.First();
|
|
stats.CurrentPrice = prices.Last();
|
|
stats.MinPrice = prices.Min();
|
|
stats.MaxPrice = prices.Max();
|
|
stats.AvgPrice = prices.Average();
|
|
}
|
|
|
|
stats.TotalBids = auction.BidHistory.Count(h => h.EventType == BidEventType.MyBid || h.EventType == BidEventType.OpponentBid);
|
|
stats.OpponentBids = stats.TotalBids - stats.MyBids;
|
|
|
|
var timers = auction.BidHistory.Select(h => h.Timer).ToList();
|
|
if (timers.Any())
|
|
{
|
|
stats.AvgTimerAtBid = timers.Average();
|
|
stats.MinTimerReached = timers.Min();
|
|
}
|
|
|
|
var latencies = auction.BidHistory.Where(h => h.EventType == BidEventType.MyBid).Select(h => h.LatencyMs).ToList();
|
|
if (latencies.Any())
|
|
{
|
|
stats.AvgClickLatencyMs = (int)latencies.Average();
|
|
stats.MinClickLatencyMs = latencies.Min();
|
|
stats.MaxClickLatencyMs = latencies.Max();
|
|
}
|
|
|
|
if (stats.MonitoringDuration.TotalMinutes > 0)
|
|
{
|
|
stats.BidsPerMinute = stats.TotalBids / stats.MonitoringDuration.TotalMinutes;
|
|
}
|
|
|
|
if (stats.MonitoringDuration.TotalHours > 0)
|
|
{
|
|
stats.ResetsPerHour = stats.Resets / stats.MonitoringDuration.TotalHours;
|
|
}
|
|
|
|
if (stats.TotalBids > 0)
|
|
{
|
|
stats.MyBidSuccessRate = (double)stats.MyBids / stats.TotalBids * 100;
|
|
}
|
|
}
|
|
|
|
if (auction.BidderStats != null && auction.BidderStats.Any())
|
|
{
|
|
var top = auction.BidderStats.OrderByDescending(b => b.Value.BidCount).First();
|
|
stats.MostActiveBidder = top.Key;
|
|
stats.MostActiveBidderCount = top.Value.BidCount;
|
|
}
|
|
|
|
return stats;
|
|
}
|
|
}
|
|
}
|