Aggiunta scheda "Storia Puntate" con aggiornamento live
Introdotta una nuova scheda "Storia Puntate" nel pannello dell'asta selezionata, che mostra la cronologia delle ultime puntate in tempo reale. La scheda utilizza un `TabControl` con due `TabItem`: uno per gli utenti e uno per la storia delle puntate. - Creata la classe `BidHistoryEntry` per rappresentare una singola puntata, con proprietà come `Price`, `BidType`, `Timestamp`, e calcoli formattati. - Aggiunte proprietà `RecentBids` in `AuctionInfo` e `RecentBidsHistory` in `AuctionState` per gestire i dati della cronologia. - Modificato il parsing API in `BidooApiClient` per includere la cronologia delle puntate. - Aggiornato il monitor delle aste (`AuctionMonitor.cs`) per sincronizzare i dati della cronologia con il backend. - Aggiunta la proprietà `BidHistoryEntries` in `AuctionViewModel` per il binding della griglia. - Modificata la UI (`AuctionMonitorControl.xaml`) per includere la nuova scheda e personalizzare gli stili. - Aggiornata la logica di aggiornamento UI in `MainWindow.xaml.cs` per gestire i dati della cronologia. - Documentata la funzionalità in `FEATURE_BID_HISTORY_TAB.md`. - Aggiunto uno screenshot (`Screenshot 2025-11-25 113552.png`). Questa funzionalità migliora la trasparenza e fornisce agli utenti informazioni dettagliate sulle attività recenti, aiutandoli a prendere decisioni strategiche durante le aste.
This commit is contained in:
@@ -248,6 +248,12 @@ namespace AutoBidder.Services
|
||||
}
|
||||
|
||||
auction.PollingLatencyMs = state.PollingLatencyMs;
|
||||
|
||||
// ? NUOVO: Aggiorna storia puntate da API
|
||||
if (state.RecentBidsHistory != null && state.RecentBidsHistory.Count > 0)
|
||||
{
|
||||
auction.RecentBids = state.RecentBidsHistory;
|
||||
}
|
||||
|
||||
if (state.Status == AuctionStatus.EndedWon ||
|
||||
state.Status == AuctionStatus.EndedLost ||
|
||||
|
||||
@@ -273,8 +273,12 @@ namespace AutoBidder.Services
|
||||
return null;
|
||||
}
|
||||
var auctionData = mainData.Substring(bracketStart + 1, bracketEnd - bracketStart - 1);
|
||||
var firstSeparator = auctionData.IndexOfAny(new[] { '|', ',' });
|
||||
var coreData = firstSeparator > 0 ? auctionData.Substring(0, firstSeparator) : auctionData;
|
||||
|
||||
// Separa dati principali dalla storia puntate
|
||||
var pipeIndex = auctionData.IndexOf('|');
|
||||
var coreData = pipeIndex > 0 ? auctionData.Substring(0, pipeIndex) : auctionData;
|
||||
var historyData = pipeIndex > 0 ? auctionData.Substring(pipeIndex + 1) : "";
|
||||
|
||||
var fields = coreData.Split(';');
|
||||
if (fields.Length < 5)
|
||||
{
|
||||
@@ -304,9 +308,16 @@ namespace AutoBidder.Services
|
||||
state.LastBidder = fields[4].Trim();
|
||||
state.IsMyBid = !string.IsNullOrEmpty(_session.Username) &&
|
||||
state.LastBidder.Equals(_session.Username, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
// ✅ NUOVO: Parse storia puntate
|
||||
// Formato: 42;fedekikka2323;3,42;fedekikka2323;1764068204;3|41;chamorro1984;1764068194;3|...
|
||||
if (!string.IsNullOrEmpty(historyData))
|
||||
{
|
||||
state.RecentBidsHistory = ParseBidHistory(historyData, fields[3]);
|
||||
}
|
||||
|
||||
state.ParsingSuccess = true;
|
||||
// Log only summary on success
|
||||
Log($"[PARSE SUCCESS] Timer: {state.Timer:F2}s, Price: €{state.Price:F2}, Bidder: {state.LastBidder}, Status: {state.Status}", auctionId);
|
||||
Log($"[PARSE SUCCESS] Timer: {state.Timer:F2}s, Price: €{state.Price:F2}, Bidder: {state.LastBidder}, Status: {state.Status}, History: {state.RecentBidsHistory?.Count ?? 0} bids", auctionId);
|
||||
return state;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -315,6 +326,74 @@ namespace AutoBidder.Services
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse la storia delle ultime puntate dalla risposta API
|
||||
/// Formato: 41;chamorro1984;1764068194;3|40;fedekikka2323;1764068184;3|...
|
||||
/// </summary>
|
||||
private List<BidHistoryEntry>? ParseBidHistory(string historyData, string currentPriceStr)
|
||||
{
|
||||
try
|
||||
{
|
||||
var entries = new List<BidHistoryEntry>();
|
||||
|
||||
// Il primo record è spesso il prezzo corrente con dati duplicati, lo saltiamo
|
||||
var records = historyData.Split('|');
|
||||
|
||||
// Parsing prezzo corrente per calcolare i prezzi precedenti
|
||||
if (!int.TryParse(currentPriceStr, out var currentPriceIndex))
|
||||
return null;
|
||||
|
||||
foreach (var record in records)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(record))
|
||||
continue;
|
||||
|
||||
var parts = record.Split(';');
|
||||
if (parts.Length < 4)
|
||||
continue;
|
||||
|
||||
// Formato: priceIndex;username;timestamp;bidType
|
||||
// Es: 41;chamorro1984;1764068194;3
|
||||
|
||||
if (!int.TryParse(parts[0], out var priceIndex))
|
||||
continue;
|
||||
|
||||
var username = parts[1].Trim();
|
||||
|
||||
if (!long.TryParse(parts[2], out var timestamp))
|
||||
continue;
|
||||
|
||||
var bidTypeCode = parts.Length > 3 ? parts[3].Trim() : "0";
|
||||
|
||||
// Determina tipo puntata: 3 = Auto, 1 = Manuale
|
||||
string bidType = bidTypeCode switch
|
||||
{
|
||||
"3" => "Auto",
|
||||
"1" => "Manuale",
|
||||
_ => "Auto"
|
||||
};
|
||||
|
||||
var entry = new BidHistoryEntry
|
||||
{
|
||||
Price = priceIndex * 0.01m,
|
||||
BidType = bidType,
|
||||
Timestamp = timestamp,
|
||||
Username = username,
|
||||
IsMyBid = !string.IsNullOrEmpty(_session.Username) &&
|
||||
username.Equals(_session.Username, StringComparison.OrdinalIgnoreCase)
|
||||
};
|
||||
|
||||
entries.Add(entry);
|
||||
}
|
||||
|
||||
return entries.Count > 0 ? entries : null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateUserInfoAsync()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user