Files
Mimante/Mimante/Models/AuctionInfo.cs
Alberto Balbo a0ec72f6c0 Refactor: solo SQLite, limiti auto, UI statistiche nuova
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.
2026-01-23 16:56:03 +01:00

219 lines
7.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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; } = "";
}
}