Sostituisci le euristiche a soglia con regime e anticipo adattivi; un solo archivio per asta
Le strategie a numero fisso (calore, ritiro morbido, anti-bot, avversari aggressivi, puntata probabilistica, velocità del prezzo, esaurimento, concorrenza) e le impostazioni morte (cadenze di polling, finestra critica, database, log avanzati, suggerimenti sull'anticipo, schede dettagliate) non ci sono più: rigiocate sui dossier non fermavano una puntata sbagliata senza fermarne anche di giuste, e i loro numeri andavano tarati a mano. Restano i paletti dell'utente (tetti, budget, fascia oraria) e il duello. Al loro posto due componenti che imparano dalla sessione in corso, dentro i paletti: - CompetitionRegime per asta (Calmo / Sfogo / Sondaggio) guidato dal valore atteso appreso: tre negativi di fila e si lascia sfogare gli altri, si rientra con una puntata di prova dopo abbastanza cicli buoni, e se viene coperta subito la pazienza raddoppia. È il "capire da soli quando tornare a puntare". - LatencyModel per l'anticipo: margine + p99 della latenza misurata adesso, tenuto fra LeadMinMs e LeadMaxMs; una puntata tardiva alza il margine subito, venti in tempo lo abbassano piano. Un anticipo scritto a mano su un'asta vince sempre (BidLeadIsManual). Archiviazione: l'archivio mensile aste-AAAA-MM.jsonl (95 MB) duplicava il riepilogo che ogni dossier ha già in coda. AuctionDetailStore ora legge testa e coda dei dossier, con cache: 6349 file in 6 s la prima volta. Pulsanti per svuotare le esportazioni e per azzerare le statistiche voce per voce (lo storico passa dalla copia di sicurezza). Scheda Apprendimento: sezione "Autonomia sul momento" con il modello di latenza e il regime di ogni asta seguita. Ml/LEGGIMI.md descrive l'algoritmo per intero. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
<Window x:Class="AutoBidder.Dialogs.WipeStatsDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Azzera le statistiche"
|
||||
Width="600" SizeToContent="Height"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
ShowInTaskbar="False"
|
||||
Background="{DynamicResource Brush.Bg}">
|
||||
|
||||
<StackPanel Margin="22,18">
|
||||
|
||||
<TextBlock Text="Cosa azzerare"
|
||||
FontSize="{StaticResource Font.Size.Lg}" FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource Brush.Text}"/>
|
||||
|
||||
<TextBlock Style="{StaticResource Hint}" Margin="0,6,0,14"
|
||||
Text="Accanto a ogni voce c'è quanto spazio occupa adesso. Niente viene toccato finché non premi Azzera. Lo storico delle aste concluse viene copiato nella cartella dei backup prima di sparire; il resto no."/>
|
||||
|
||||
<CheckBox x:Name="ChkHistory" Margin="0,4" IsChecked="True"
|
||||
Foreground="{DynamicResource Brush.Text}"
|
||||
ToolTip="Il file completed-auctions.json: una riga per asta conclusa. È la base di tutto il resto — griglia Storico, statistiche per prodotto, limiti consigliati. Viene copiato nei backup prima di essere cancellato."
|
||||
Checked="Option_Changed" Unchecked="Option_Changed"/>
|
||||
|
||||
<CheckBox x:Name="ChkProducts" Margin="0,4" IsChecked="True"
|
||||
Foreground="{DynamicResource Brush.Text}"
|
||||
ToolTip="I totali per prodotto (aste viste, prezzi medi, puntate del vincitore). Le opzioni scelte nella scheda Prodotti restano: si azzerano i numeri, non le scelte."
|
||||
Checked="Option_Changed" Unchecked="Option_Changed"/>
|
||||
|
||||
<CheckBox x:Name="ChkBidLead" Margin="0,4" IsChecked="True"
|
||||
Foreground="{DynamicResource Brush.Text}"
|
||||
ToolTip="Le misure dell'anticipo effettivo di ogni puntata (bid-lead-stats.json)."
|
||||
Checked="Option_Changed" Unchecked="Option_Changed"/>
|
||||
|
||||
<CheckBox x:Name="ChkExports" Margin="0,4" IsChecked="True"
|
||||
Foreground="{DynamicResource Brush.Text}"
|
||||
ToolTip="Tutti i file nella cartella Esportazioni. Sono copie: si rigenerano in qualunque momento dalla scheda Esporta."
|
||||
Checked="Option_Changed" Unchecked="Option_Changed"/>
|
||||
|
||||
<CheckBox x:Name="ChkLegacy" Margin="0,4" IsChecked="True"
|
||||
Foreground="{DynamicResource Brush.Text}"
|
||||
ToolTip="Gli archivi mensili aste-AAAA-MM.jsonl delle versioni precedenti: erano una copia del riepilogo che ogni dossier ha già in coda, e l'applicazione non li scrive né li legge più."
|
||||
Checked="Option_Changed" Unchecked="Option_Changed"/>
|
||||
|
||||
<CheckBox x:Name="ChkLearning" Margin="0,4" IsChecked="False"
|
||||
Foreground="{DynamicResource Brush.Text}"
|
||||
ToolTip="Il modello appreso, il profilo per prodotto e ora, il modello di latenza e l'elenco dei dossier già studiati. Non si perde niente di irrecuperabile: al prossimo avvio l'applicazione ristudia tutti i dossier da capo (qualche minuto in sottofondo)."
|
||||
Checked="Option_Changed" Unchecked="Option_Changed"/>
|
||||
|
||||
<Border Style="{StaticResource InfoBox}" Margin="0,14,0,0">
|
||||
<StackPanel>
|
||||
<TextBlock x:Name="SummaryText" TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Brush.Text}"
|
||||
FontSize="{StaticResource Font.Size.Sm}" LineHeight="18"
|
||||
Text="Calcolo…"/>
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,8,0,0"
|
||||
Foreground="{DynamicResource Brush.TextMuted}"
|
||||
FontSize="{StaticResource Font.Size.Sm}" LineHeight="17"
|
||||
Text="I dossier delle aste (cartella Registri\Aste) non vengono toccati da qui: sono i dati grezzi da cui tutto il resto si ricostruisce. Per liberare quello spazio usa la scheda Dati."/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,18,0,0">
|
||||
<Button x:Name="WipeButton" Content="Azzera" Padding="26,7" Margin="0,0,10,0"
|
||||
Style="{StaticResource ModernButton}"
|
||||
Background="{DynamicResource Brush.Danger}"
|
||||
Foreground="{DynamicResource Brush.TextOnAccent}"
|
||||
Click="Wipe_Click"/>
|
||||
<Button Content="Annulla" Padding="20,7" IsCancel="True"
|
||||
Style="{StaticResource ModernButton}"
|
||||
Background="{DynamicResource Brush.SurfaceAlt}"
|
||||
Foreground="{DynamicResource Brush.Text}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using AutoBidder.Utilities;
|
||||
|
||||
namespace AutoBidder.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Sceglie quali statistiche azzerare e le azzera.
|
||||
///
|
||||
/// <para>Accanto a ogni voce c'è quanto pesa adesso: cancellare è irreversibile, e
|
||||
/// l'unico modo di renderlo una decisione informata è dire cosa sparisce e quanto è.
|
||||
/// Lo storico delle aste concluse è l'unica voce con copia di sicurezza automatica:
|
||||
/// è il solo archivio che non si ricostruisce da nient'altro.</para>
|
||||
/// </summary>
|
||||
public partial class WipeStatsDialog : Window
|
||||
{
|
||||
private StatsWipe.Sizes _sizes;
|
||||
|
||||
public WipeStatsDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += (_, _) => { _sizes = StatsWipe.Measure(); Refresh(); };
|
||||
}
|
||||
|
||||
/// <summary>Il rapporto dell'azzeramento, dopo la conferma. Null se annullato.</summary>
|
||||
public StatsWipe.Report? Result { get; private set; }
|
||||
|
||||
private StatsWipe.Options ReadOptions() => new()
|
||||
{
|
||||
History = ChkHistory.IsChecked == true,
|
||||
ProductStats = ChkProducts.IsChecked == true,
|
||||
BidLeadMeasures = ChkBidLead.IsChecked == true,
|
||||
Exports = ChkExports.IsChecked == true,
|
||||
LegacyArchives = ChkLegacy.IsChecked == true,
|
||||
Learning = ChkLearning.IsChecked == true
|
||||
};
|
||||
|
||||
private void Option_Changed(object sender, RoutedEventArgs e) => Refresh();
|
||||
|
||||
private void Refresh()
|
||||
{
|
||||
if (!IsLoaded) return;
|
||||
|
||||
ChkHistory.Content = $"Storico delle aste concluse ({_sizes.HistoryAuctions} aste, {Fmt(_sizes.HistoryBytes)})";
|
||||
ChkProducts.Content = $"Statistiche per prodotto ({Fmt(_sizes.ProductsBytes)})";
|
||||
ChkBidLead.Content = $"Misure dell'anticipo effettivo ({_sizes.BidLeadSamples} misure, {Fmt(_sizes.BidLeadBytes)})";
|
||||
ChkExports.Content = $"Esportazioni ({_sizes.ExportFiles} file, {Fmt(_sizes.ExportBytes)})";
|
||||
ChkLegacy.Content = $"Archivi mensili delle versioni precedenti ({_sizes.LegacyFiles} file, {Fmt(_sizes.LegacyBytes)})";
|
||||
ChkLearning.Content = $"Apprendimento: modello, profilo, latenza ({Fmt(_sizes.LearningBytes)})";
|
||||
|
||||
var o = ReadOptions();
|
||||
long totale = 0;
|
||||
if (o.History) totale += _sizes.HistoryBytes;
|
||||
if (o.ProductStats) totale += _sizes.ProductsBytes;
|
||||
if (o.BidLeadMeasures) totale += _sizes.BidLeadBytes;
|
||||
if (o.Exports) totale += _sizes.ExportBytes;
|
||||
if (o.LegacyArchives) totale += _sizes.LegacyBytes;
|
||||
if (o.Learning) totale += _sizes.LearningBytes;
|
||||
|
||||
SummaryText.Text = o.Nothing
|
||||
? "Nessuna voce scelta."
|
||||
: $"Si liberano circa {Fmt(totale)}." +
|
||||
(o.History ? " Lo storico viene prima copiato nei backup." : "") +
|
||||
(o.Learning ? " L'apprendimento ripartirà da zero e ristudierà i dossier al prossimo avvio." : "");
|
||||
|
||||
WipeButton.IsEnabled = !o.Nothing;
|
||||
}
|
||||
|
||||
private void Wipe_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var o = ReadOptions();
|
||||
if (o.Nothing) return;
|
||||
|
||||
var answer = MessageBox.Show(this,
|
||||
"Le voci scelte vengono cancellate. L'operazione non è reversibile" +
|
||||
(o.History ? ", salvo la copia dello storico nei backup" : "") + ".\n\nProcedo?",
|
||||
"Azzera le statistiche", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
|
||||
if (answer != MessageBoxResult.Yes) return;
|
||||
|
||||
try
|
||||
{
|
||||
Result = StatsWipe.Run(o);
|
||||
DialogResult = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(this, $"Azzeramento non riuscito: {ex.Message}",
|
||||
"Azzera le statistiche", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Fmt(long bytes) =>
|
||||
bytes >= 1L << 30 ? $"{bytes / (double)(1L << 30):F2} GB"
|
||||
: bytes >= 1L << 20 ? $"{bytes / (double)(1L << 20):F1} MB"
|
||||
: bytes >= 1L << 10 ? $"{bytes / (double)(1L << 10):F0} KB"
|
||||
: $"{bytes} B";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user