Rimosso completamente il supporto a PostgreSQL: ora tutte le statistiche e i dati persistenti usano solo SQLite, con percorso configurabile tramite DATA_PATH per Docker/volumi. Aggiunta gestione avanzata delle statistiche per prodotto, limiti consigliati calcolati automaticamente e applicabili dalla UI. Rinnovata la pagina Statistiche con tabelle aste recenti e prodotti, rimosso il supporto a grafici legacy e a "Puntate Gratuite". Migliorata la ricerca e la gestione delle aste nel browser, aggiunta diagnostica avanzata e logging dettagliato per il database. Aggiornati Dockerfile e docker-compose: l'app è ora self-contained e pronta per l'uso senza database esterni.
219 lines
7.9 KiB
C#
219 lines
7.9 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text.Json.Serialization;
|
||
|
||
namespace AutoBidder.Models
|
||
{
|
||
/// <summary>
|
||
/// Informazioni base di un'asta monitorata
|
||
/// Solo HTTP, nessuna modalità, browser o multi-click
|
||
/// </summary>
|
||
public class AuctionInfo
|
||
{
|
||
/// <summary>
|
||
/// Numero massimo di righe di log da mantenere per ogni asta
|
||
/// </summary>
|
||
private const int MAX_LOG_LINES = 500;
|
||
|
||
public string AuctionId { get; set; } = "";
|
||
public string Name { get; set; } = ""; // Opzionale, può essere lasciato vuoto
|
||
public string OriginalUrl { get; set; } = ""; // URL completo dell'asta (per referer)
|
||
|
||
// Configurazione asta
|
||
/// <summary>
|
||
/// Millisecondi prima della scadenza (deadline) per inviare la puntata.
|
||
/// Es: 200ms = punta 200ms prima che il timer raggiunga 0.
|
||
/// </summary>
|
||
public int BidBeforeDeadlineMs { get; set; } = 200;
|
||
|
||
/// <summary>
|
||
/// Se true, verifica che l'asta sia ancora aperta prima di piazzare la puntata.
|
||
/// Aggiunge una chiamata API extra ma aumenta la sicurezza.
|
||
/// </summary>
|
||
public bool CheckAuctionOpenBeforeBid { get; set; } = false;
|
||
|
||
public double MinPrice { get; set; } = 0;
|
||
public double MaxPrice { get; set; } = 0;
|
||
public int MinResets { get; set; } = 0; // Numero minimo reset prima di puntare
|
||
public int MaxResets { get; set; } = 0; // Numero massimo reset (0 = illimitati)
|
||
|
||
/// <summary>
|
||
/// [OBSOLETO] Numero massimo di puntate consentite - Non più utilizzato nell'UI
|
||
/// Mantenuto per retrocompatibilità con salvataggi JSON esistenti
|
||
/// </summary>
|
||
[Obsolete("MaxClicks non è più utilizzato. Usa invece la logica di limiti per prodotto.")]
|
||
[JsonPropertyName("MaxClicks")]
|
||
public int MaxClicks { get; set; } = 0;
|
||
|
||
// Stato asta
|
||
public bool IsActive { get; set; } = true;
|
||
public bool IsPaused { get; set; } = false;
|
||
|
||
// Contatori
|
||
public int ResetCount { get; set; } = 0;
|
||
|
||
/// <summary>
|
||
/// Puntate residue totali dell'utente (aggiornate dopo ogni puntata su questa asta)
|
||
/// </summary>
|
||
[JsonPropertyName("RemainingBids")]
|
||
public int? RemainingBids { get; set; }
|
||
|
||
/// <summary>
|
||
/// Puntate usate specificamente su questa asta (da risposta server)
|
||
/// </summary>
|
||
[JsonPropertyName("BidsUsedOnThisAuction")]
|
||
public int? BidsUsedOnThisAuction { get; set; }
|
||
|
||
// Timestamp
|
||
public DateTime AddedAt { get; set; } = DateTime.UtcNow;
|
||
public DateTime? LastClickAt { get; set; }
|
||
|
||
// Storico
|
||
public List<BidHistory> BidHistory { get; set; } = new List<BidHistory>();
|
||
public Dictionary<string, BidderInfo> BidderStats { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
||
|
||
/// <summary>
|
||
/// Storia delle ultime puntate effettuate sull'asta (da API)
|
||
/// Questa è la fonte UFFICIALE per il conteggio puntate per utente
|
||
/// </summary>
|
||
[JsonPropertyName("RecentBids")]
|
||
public List<BidHistoryEntry> RecentBids { get; set; } = new List<BidHistoryEntry>();
|
||
|
||
// Log per-asta (non serializzato)
|
||
[System.Text.Json.Serialization.JsonIgnore]
|
||
public List<string> AuctionLog { get; set; } = new();
|
||
|
||
// Flag runtime: indica che è in corso un'operazione di final attack per questa asta
|
||
[System.Text.Json.Serialization.JsonIgnore]
|
||
public bool IsAttackInProgress { get; set; } = false;
|
||
|
||
// === INFORMAZIONI PRODOTTO PER CALCOLO VALORE ===
|
||
|
||
/// <summary>
|
||
/// Prezzo "Compra Subito" del prodotto (valore nominale)
|
||
/// </summary>
|
||
public double? BuyNowPrice { get; set; }
|
||
|
||
/// <summary>
|
||
/// Spese di spedizione per questo prodotto
|
||
/// </summary>
|
||
public double? ShippingCost { get; set; }
|
||
|
||
/// <summary>
|
||
/// Indica se c'è un limite di vincita per questo prodotto (1 volta ogni X giorni)
|
||
/// </summary>
|
||
public bool HasWinLimit { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// Descrizione del limite di vincita (es: "1 volta ogni 30 giorni")
|
||
/// </summary>
|
||
public string? WinLimitDescription { get; set; }
|
||
|
||
/// <summary>
|
||
/// Costo medio per puntata da utilizzare nei calcoli (default: 0.20€)
|
||
/// </summary>
|
||
public double BidCost { get; set; } = 0.20;
|
||
|
||
/// <summary>
|
||
/// Ultimo valore calcolato del prodotto (costo reale considerando puntate)
|
||
/// Null se non ancora calcolato
|
||
/// </summary>
|
||
[JsonIgnore]
|
||
public ProductValue? CalculatedValue { get; set; }
|
||
|
||
/// <summary>
|
||
/// Ultimo stato ricevuto dal monitor per questa asta
|
||
/// </summary>
|
||
[JsonIgnore]
|
||
public AuctionState? LastState { get; set; }
|
||
|
||
/// <summary>
|
||
/// Aggiunge una voce al log dell'asta con limite automatico di righe
|
||
/// </summary>
|
||
/// <param name="message">Messaggio da aggiungere al log</param>
|
||
/// <param name="maxLines">Numero massimo di righe da mantenere (default: 500)</param>
|
||
public void AddLog(string message, int maxLines = 500)
|
||
{
|
||
var entry = $"{DateTime.Now:HH:mm:ss.fff} - {message}";
|
||
AuctionLog.Add(entry);
|
||
|
||
// Mantieni solo gli ultimi maxLines log
|
||
if (AuctionLog.Count > maxLines)
|
||
{
|
||
// Rimuovi i log più vecchi per mantenere la dimensione sotto controllo
|
||
int excessCount = AuctionLog.Count - maxLines;
|
||
AuctionLog.RemoveRange(0, excessCount);
|
||
}
|
||
}
|
||
|
||
public int PollingLatencyMs { get; set; } = 0; // Ultima latenza polling ms
|
||
}
|
||
|
||
/// <summary>
|
||
/// Rappresenta il valore calcolato di un prodotto all'asta
|
||
/// </summary>
|
||
public class ProductValue
|
||
{
|
||
/// <summary>
|
||
/// Prezzo attuale dell'asta in euro
|
||
/// </summary>
|
||
public double CurrentPrice { get; set; }
|
||
|
||
/// <summary>
|
||
/// Numero totale di puntate effettuate sull'asta
|
||
/// </summary>
|
||
public int TotalBids { get; set; }
|
||
|
||
/// <summary>
|
||
/// Numero di puntate effettuate dall'utente
|
||
/// </summary>
|
||
public int MyBids { get; set; }
|
||
|
||
/// <summary>
|
||
/// Costo delle puntate dell'utente (MyBids × BidCost)
|
||
/// </summary>
|
||
public double MyBidsCost { get; set; }
|
||
|
||
/// <summary>
|
||
/// Costo totale per l'utente se vince (CurrentPrice + MyBidsCost + ShippingCost)
|
||
/// </summary>
|
||
public double TotalCostIfWin { get; set; }
|
||
|
||
/// <summary>
|
||
/// Prezzo "Compra Subito" del prodotto
|
||
/// </summary>
|
||
public double? BuyNowPrice { get; set; }
|
||
|
||
/// <summary>
|
||
/// Spese di spedizione
|
||
/// </summary>
|
||
public double? ShippingCost { get; set; }
|
||
|
||
/// <summary>
|
||
/// Risparmio rispetto al prezzo "Compra Subito" (può essere negativo)
|
||
/// </summary>
|
||
public double? Savings { get; set; }
|
||
|
||
/// <summary>
|
||
/// Percentuale di risparmio rispetto al prezzo "Compra Subito"
|
||
/// </summary>
|
||
public double? SavingsPercentage { get; set; }
|
||
|
||
/// <summary>
|
||
/// Indica se conviene continuare (risparmio positivo)
|
||
/// </summary>
|
||
public bool IsWorthIt { get; set; }
|
||
|
||
/// <summary>
|
||
/// Timestamp del calcolo
|
||
/// </summary>
|
||
public DateTime CalculatedAt { get; set; }
|
||
|
||
/// <summary>
|
||
/// Messaggio riassuntivo del valore
|
||
/// </summary>
|
||
public string Summary { get; set; } = "";
|
||
}
|
||
}
|