- Introdotta la classe `BidooApiClient` per interagire con le API Bidoo. - Aggiunto `SessionManager` per la gestione sicura delle sessioni. - Creato `TestBidooApi` per test manuali delle API. - Implementato `CsvExporter` per esportare dati e statistiche in CSV. - Aggiunto `PersistenceManager` per salvare e caricare aste in JSON. - Introdotto `AuctionViewModel` per supportare il pattern MVVM. - Migliorata l'interfaccia utente con layout moderno e stili dinamici. - Aggiornata la documentazione in `README.md` per riflettere le nuove funzionalità. - Aggiunte classi per rappresentare informazioni, stato e storico delle aste. - Ottimizzate le richieste HTTP per simulare un browser reale.
127 lines
4.7 KiB
C#
127 lines
4.7 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 = auction.MyClicks,
|
|
Resets = auction.ResetCount,
|
|
UniqueBidders = auction.Bidders.Count,
|
|
BidderRanking = auction.Bidders
|
|
};
|
|
|
|
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.Bidders.Any())
|
|
{
|
|
var topBidder = auction.Bidders.OrderByDescending(b => b.Value).First();
|
|
stats.MostActiveBidder = topBidder.Key;
|
|
stats.MostActiveBidderCount = topBidder.Value;
|
|
}
|
|
|
|
return stats;
|
|
}
|
|
}
|
|
}
|