Files
Mimante/Mimante/Controls/SettingsControl.xaml
T
Alby96andClaude Fable 5.1 9177b31bd5 Due database, interruttore dell'apprendimento, barre a icone; via kill-switch, esportazioni e voci deprecate
Tutto ciò che l'applicazione registra sta ora in due file SQLite in
%LocalAppData%\AutoBidder\Database: autobidder.sqlite per le osservazioni e
esercizio.sqlite per i documenti d'esercizio (aste nel monitor, prodotti, promozioni,
modelli appresi con prefisso ml/) e per i registri applicativo e del riscatto puntate.
Il motore comune è SqliteDatabase; i file JSON e la cartella Apprendimento delle
versioni precedenti vengono importati la prima volta e lasciati dove sono. La cartella
si cambia dalle Impostazioni: al salvataggio si chiede se spostare i file, e si riavvia.
Le cartelle Dati/Statistiche/Registri, i registri su file, le misure dell'anticipo e
le impostazioni morte (LogBids, AutoApplyProductDefaults, NewAuctionLimitsPriority…)
non esistono più.

Il kill-switch se ne va: al suo posto un solo interruttore in barra, accanto ad
Avvia/Osserva/Ferma, che spegne l'apprendimento. Spento, il motore punta solo entro i
limiti dell'utente (prezzo, puntate, budget, fascia oraria, rischio) con l'anticipo
fisso: niente valore atteso, regime, duello, bandit, anticipo adattivo. Le aste vengono
comunque registrate e studiate.

Tre difetti visti osservando il motore dal vivo per un'ora, in Osserva:
- la copertura «Compralo Ora» con V lasciato al listino azzerava la perdita coperta e
  il motore diceva BID a ogni scadenza con P dell'1%: ora vale solo per i prodotti con
  «Valore reale €» scritto, altrimenti la puntata si conta persa e P decide;
- la chiusura di un'asta arrivava due volte (fine, poi rimozione dal monitor) e di
  nuovo al riavvio: modello, profilo, bandit e statistiche per prodotto contavano ogni
  asta due volte. Il monitor la comunica una volta sola, l'apprendimento salta le aste
  già apprese, e le schede prodotto vengono ricostruite una volta dallo storico;
- la pagina delle ricompense veniva scambiata per la pagina di accesso perché porta un
  collegamento a /login.php: prima si guarda se è la pagina delle ricompense.

Interfaccia: la scheda Esporta e tutto il suo codice sono tolti; le esportazioni
chiedono sempre dove salvare. Prodotti, Storico e Apprendimento hanno barre a sole
icone con tooltip che dicono esattamente cosa succede, colorate come il monitor, con
i nuovi pulsanti di pulizia (spegni tutte le stelline, togli i non seguiti, pulizia
completa; seleziona tutte / elimina le selezionate / svuota lo storico). Impostazioni:
sezione Database, Manutenzione con «Elimina tutti i dati (tranne la login)» e
«Impostazioni di fabbrica», esportazione dei registri in testo. Modifiche.txt, il
prompt ormai realizzato, esce dal repository.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 13:58:08 +02:00

826 lines
60 KiB
XML
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.
<UserControl x:Class="AutoBidder.Controls.SettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ctl="clr-namespace:AutoBidder.Controls"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="1200"
Background="{DynamicResource Brush.Bg}">
<!-- Stili centralizzati in Themes/Controls.xaml -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Scrollable Content -->
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto">
<StackPanel Margin="30,20">
<!-- SEZIONE 0: Aspetto -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Aspetto"
Margin="0,0,0,14"
Help="Scegli il tema dell'interfaccia. Il cambiamento è immediato."/>
<StackPanel Orientation="Horizontal">
<RadioButton x:Name="ThemeDarkRadio"
Content="Scuro"
GroupName="AppTheme"
IsChecked="True"
Checked="ThemeDarkRadio_Checked"
ToolTip="Tema scuro (consigliato per sessioni lunghe)"/>
<RadioButton x:Name="ThemeLightRadio"
Content="Chiaro"
GroupName="AppTheme"
Checked="ThemeLightRadio_Checked"
ToolTip="Tema chiaro"/>
</StackPanel>
</StackPanel>
</Border>
<!-- SEZIONE 0-quater: Fascia oraria e pulizia dell'elenco -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Fascia oraria sospesa e pulizia dell'elenco"
Margin="0,0,0,14"
Help="Fascia oraria: su 6060 aste concluse la stessa asta chiude al 4,6% del valore alle 12 e al 5,3% fra le 10 e le 13, ma all&apos;8,6% a mezzanotte e al 9,7% alle 9 — quasi il doppio, e con 26-29 puntate per vincere invece di 21-24. Nella fascia le puntate si sospendono ma l&apos;asta resta Attiva e riprende da sola. Inizio incluso, fine esclusa; una fascia a cavallo di mezzanotte (22-6) funziona; inizio uguale a fine spegne il filtro.&#10;&#10;Pulizia dell&apos;elenco: le aste concluse spariscono da sole dal monitor, tranne quelle che vale la pena riguardare."/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<CheckBox x:Name="QuietHoursCheckBox" Content="Sospendi le puntate dalle" VerticalAlignment="Center"/>
<TextBox x:Name="QuietHoursStartTextBox" Text="0" Width="56" Margin="8,0" VerticalAlignment="Center"/>
<TextBlock Text="alle" VerticalAlignment="Center" Foreground="{DynamicResource Brush.Text}"/>
<TextBox x:Name="QuietHoursEndTextBox" Text="10" Width="56" Margin="8,0" VerticalAlignment="Center"/>
<TextBlock Text="(ore, 0-23)" VerticalAlignment="Center" Foreground="{DynamicResource Brush.TextMuted}"/>
</StackPanel>
<CheckBox x:Name="AutoRemoveFinishedCheckBox" Content="Togli da sole le aste concluse dall'elenco" Margin="0,4"/>
<CheckBox x:Name="AutoRemoveKeepMyBidsCheckBox" Content="…ma trattieni quelle su cui ho puntato" Margin="20,2,0,0"
ToolTip="Sono le uniche con il costo reale dentro: restano per controllarle a mano."/>
<CheckBox x:Name="AutoRemoveKeepWonCheckBox" Content="…ma trattieni quelle vinte" Margin="20,2,0,0"
ToolTip="C'è da confermare l'acquisto su Bidoo: una vittoria sparita dall'elenco è il modo più semplice di dimenticarsene."/>
<CheckBox x:Name="AutoRemoveKeepUnclearCheckBox" Content="…ma trattieni quelle di cui non si è vista la fine" Margin="20,2,0,0"
ToolTip="Esito da controllare: sono esattamente quelle da guardare."/>
</StackPanel>
</Border>
<!-- SEZIONE 0-bis: Sessione / Autenticazione -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Sessione Bidoo (Autenticazione)"
Margin="0,0,0,14"
Help="Accedi dalla scheda Browser: il cookie viene rilevato e importato da solo, e vale per tutta l&apos;applicazione. La sessione resta salvata e protetta con DPAPI, quindi l&apos;accesso non va rifatto a ogni avvio.&#10;&#10;Un solo modo di accedere e nessun campo per il cookie a mano: due strade vorrebbero dire due sessioni possibili, e la domanda &quot;quale sta usando?&quot; senza risposta."/>
<!-- Stato corrente -->
<Border Background="{DynamicResource Brush.SurfaceAlt}"
BorderBrush="{DynamicResource Brush.Border}"
BorderThickness="1"
CornerRadius="6"
Padding="12,10"
Margin="0,0,0,14">
<StackPanel>
<TextBlock x:Name="SessionStatusText"
Text="Non connesso"
Foreground="{DynamicResource Brush.Danger}"
FontWeight="SemiBold"/>
<TextBlock x:Name="SessionStatusDetail"
Text="Nessuna sessione attiva."
Foreground="{DynamicResource Brush.TextMuted}"
FontSize="11.5"
Margin="0,3,0,0"
TextWrapping="Wrap"/>
</StackPanel>
</Border>
<StackPanel Orientation="Horizontal">
<Button Content="Apri Browser per il login"
Background="{DynamicResource Brush.Accent}"
Foreground="{DynamicResource Brush.TextOnAccent}"
Style="{StaticResource SmallRoundedButton}"
Click="OpenBrowserLoginButton_Click"
Margin="0,0,8,0"/>
<Button x:Name="ConnectSessionButton"
Content="Verifica connessione"
Background="{DynamicResource Brush.SurfaceAlt}"
Foreground="{DynamicResource Brush.Text}"
Style="{StaticResource SmallRoundedButton}"
ToolTip="Ricontrolla la sessione salvata contro il sito"
Click="ConnectSessionButton_Click"
Margin="0,0,8,0"/>
<Button x:Name="DisconnectSessionButton"
Content="Disconnetti"
Background="{DynamicResource Brush.SurfaceAlt}"
Foreground="{DynamicResource Brush.Text}"
Style="{StaticResource SmallRoundedButton}"
Click="DisconnectSessionButton_Click"/>
</StackPanel>
</StackPanel>
</Border>
<!-- SEZIONE 1: Impostazioni Predefinite Aste -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Impostazioni Predefinite Aste"
Margin="0,0,0,14"
Help="Valgono per ogni asta nuova che non abbia limiti propri. I limiti scritti nella scheda Prodotti hanno sempre la precedenza su questi."/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Anticipo deciso dalla rete" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Acceso: l'anticipo lo sceglie il modello di latenza — margine di sicurezza più la coda alta del ping di questa sessione — e si corregge da solo a ogni puntata tardiva. Si muove solo fra il minimo e il massimo qui sotto.&#10;&#10;Spento: vale l'anticipo fisso della riga seguente.&#10;&#10;In entrambi i casi un anticipo scritto a mano su una singola asta vince sempre."/>
<CheckBox Grid.Row="0" Grid.Column="1" x:Name="AdaptiveLeadCheckBox" Margin="10,10" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Anticipo minimo (ms)" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Il modello non scende mai sotto questo valore. Sotto i 300 ms un picco di rete fa arrivare la puntata a giochi chiusi: il ping tocca 444 ms nel p99,9."/>
<TextBox Grid.Row="1" Grid.Column="1" x:Name="LeadMinMsTextBox" Text="300" Margin="10,10"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Anticipo massimo (ms)" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Il modello non sale mai sopra questo valore. Ogni millisecondo in più è tempo regalato agli avversari: dalla rigiocata di 2.095 aste, sotto il secondo basta in mediana 1 puntata per asta, sotto i 2 s ne servono 15."/>
<TextBox Grid.Row="2" Grid.Column="1" x:Name="LeadMaxMsTextBox" Text="1500" Margin="10,10"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Anticipo fisso (millisecondi)" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Usato quando l'anticipo deciso dalla rete è spento, e come punto di partenza finché il modello non ha misurato abbastanza ping. Quanti millisecondi prima della scadenza parte la puntata: il motore punta solo nei cicli che arrivano fin qui senza che nessun altro abbia puntato."/>
<TextBox Grid.Row="3" Grid.Column="1" x:Name="DefaultBidBeforeDeadlineMsTextBox" Text="500" Margin="10,10"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Prezzo Minimo (€)" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"/>
<TextBox Grid.Row="5" Grid.Column="1" x:Name="DefaultMinPriceTextBox" Text="0" Margin="10,10"/>
<TextBlock Grid.Row="6" Grid.Column="0" Text="Prezzo Massimo (€)" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"/>
<TextBox Grid.Row="6" Grid.Column="1" x:Name="DefaultMaxPriceTextBox" Text="0" Margin="10,10"/>
<TextBlock Grid.Row="7" Grid.Column="0" Text="Max Click" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Quante puntate al massimo spendere su una singola asta. Entra anche nel calcolo dei limiti consigliati per prodotto: ogni puntata in più è denaro che non si può mettere sul prezzo. 0 = illimitate."/>
<TextBox Grid.Row="7" Grid.Column="1" x:Name="DefaultMaxClicksTextBox" Text="0" Margin="10,10"/>
</Grid>
</StackPanel>
</Border>
<!-- SEZIONE: Limiti consigliati per prodotto -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Limiti Consigliati per Prodotto"
Margin="0,0,0,14"
Help="La scheda Prodotti propone, per ogni articolo, un prezzo minimo e uno massimo ricavati da come sono andate le sue aste finora.&#10;&#10;Il massimo nasce da due vincoli e vince il più stretto: il prezzo che copre la quota di chiusure impostata qui sotto, e quanto si può spendere — valore del prodotto, meno il costo delle puntate massime. Il minimo è il decimo percentile delle chiusure: sotto quel prezzo l'asta non si chiude quasi mai, quindi puntare lì è quasi sempre speso a vuoto.&#10;&#10;Perché non basta la moda: il prezzo a cui un articolo si aggiudica più spesso copre fra il 15% e il 44% delle sue aste, a seconda del prodotto. Fermandosi lì si resterebbe fuori dalla maggior parte delle occasioni."/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Copertura delle chiusure (%)"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="In quante aste passate saresti stato ancora in gioco fermandoti al massimo consigliato.&#10;&#10;Alzarla vuol dire restare in corsa più spesso ma spingersi su prezzi più alti; abbassarla vuol dire puntare solo sulle occasioni buone e lasciar perdere le altre. Fascia sensata: 5095."/>
<TextBox Grid.Row="0" Grid.Column="1" x:Name="SuggestedCoverageTextBox"
Text="85" Margin="10,10"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Costo medio di una puntata (€)"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="Quanto ti costa una puntata. Serve a calcolare il tetto di spesa: valore del prodotto meno le puntate massime moltiplicate per questo costo.&#10;&#10;Il valore predefinito è 0,20 €, cioè il pacchetto meno vantaggioso in vendita su Bidoo: tenerlo così fa stimare per eccesso, e una stima per eccesso al massimo ti fa rinunciare a un affare, mentre una per difetto ti fa spendere più del valore del prodotto.&#10;&#10;Se compri pacchetti più grandi, abbassalo al costo che paghi davvero."/>
<TextBox Grid.Row="1" Grid.Column="1" x:Name="AverageBidCostTextBox"
Text="0,20" Margin="10,10"/>
</Grid>
</StackPanel>
</Border>
<!-- SEZIONE 2: Stato Iniziale Aste -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Stato Iniziale Aste"
Margin="0,0,0,14"
Help="Come si comportano le aste quando vengono caricate o aggiunte.
• Fermata: non viene monitorata fino all'avvio manuale.
• Osserva: viene seguita (prezzo, scadenza, avversari) ma non punta mai. Utile per studiarla prima di entrare.
• Attiva: viene monitorata e punta da sola quando serve.
• Ricorda Stato: ogni asta riprende lo stato che aveva alla chiusura, e sovrascrive le altre opzioni.
Consiglio: usa Fermata per caricare senza avviare, poi avvia a mano quelle che vuoi."/>
<!-- Stato all'apertura applicazione -->
<TextBlock Text="Stato aste al caricamento dell'applicazione"
Style="{StaticResource FieldLabel}"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,20">
<RadioButton x:Name="LoadAuctionsStopped"
Content="Fermate"
GroupName="LoadState"
IsChecked="True"
ToolTip="Le aste salvate verranno caricate in stato fermo"/>
<RadioButton x:Name="LoadAuctionsPaused"
Content="Osserva"
GroupName="LoadState"
ToolTip="Le aste salvate seguiranno prezzo e scadenza senza mai puntare"/>
<RadioButton x:Name="LoadAuctionsActive"
Content="Attive"
GroupName="LoadState"
ToolTip="Le aste salvate verranno avviate automaticamente all'apertura"/>
<RadioButton x:Name="LoadAuctionsRemember"
Content="Ricorda Stato"
GroupName="LoadState"
ToolTip="Ogni asta ripristina lo stato che aveva alla chiusura (attiva/pausa/ferma)"/>
</StackPanel>
<!-- Stato nuove aste -->
<TextBlock Text="Stato iniziale di una nuova asta aggiunta"
Style="{StaticResource FieldLabel}"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<RadioButton x:Name="NewAuctionStopped"
Content="Fermata"
GroupName="NewAuctionState"
IsChecked="True"
ToolTip="Le nuove aste verranno aggiunte in stato fermo"/>
<RadioButton x:Name="NewAuctionPaused"
Content="Osserva"
GroupName="NewAuctionState"
ToolTip="Le nuove aste seguiranno prezzo e scadenza senza mai puntare"/>
<RadioButton x:Name="NewAuctionActive"
Content="Attiva"
GroupName="NewAuctionState"
ToolTip="Le nuove aste verranno avviate automaticamente"/>
</StackPanel>
<!-- Info Box -->
</StackPanel>
</Border>
<!-- SEZIONE: Motore di precisione -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Motore di Precisione"
Margin="0,0,0,14"
Help="Ogni asta ha il proprio motore indipendente e interroga Bidoo al massimo che la rete concede: nessuna cadenza da impostare. Se il server chiede di rallentare (429/503) il motore frena da solo e riparte appena può."/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Limite richieste al secondo" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="0 = nessun tetto (consigliato: si va al massimo che la rete concede). Le puntate hanno corsia preferenziale e non sono mai soggette a questo limite."/>
<TextBox Grid.Row="0" Grid.Column="1" x:Name="MaxRequestsPerSecondTextBox" Text="0" Margin="10,10"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Timer di sistema a 1 ms" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Senza, ogni attesa può sforare di ~15 ms e l'anticipo perde significato"/>
<CheckBox Grid.Row="1" Grid.Column="1" x:Name="PrecisionTimerCheckBox" Margin="10,10" VerticalAlignment="Center" IsChecked="True"/>
</Grid>
<Border Style="{StaticResource InfoBox}" Margin="0,15,0,0">
<StackPanel>
<TextBlock Text="Diagnostica motore"
FontWeight="Bold"
Foreground="{DynamicResource Brush.Accent}"
Margin="0,0,0,10"/>
<TextBlock x:Name="EngineDiagnosticsText"
Text="Monitoraggio non avviato."
TextWrapping="Wrap"
Foreground="{DynamicResource Brush.Text}"
FontSize="12"
LineHeight="18"/>
</StackPanel>
</Border>
</StackPanel>
</Border>
<!-- SEZIONE: Prodotti seguiti (aggiunta automatica) -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Prodotti Seguiti (aggiunta automatica)"
Margin="0,0,0,14"
Help="Bidoo rimette all'asta lo stesso articolo di continuo. Con la stellina in Esplora segui un prodotto: le aste nuove di quell'articolo entrano nel monitor da sole.
Perché il valore consigliato è Osserva: un'asta che entra da sola e comincia subito a puntare spenderebbe puntate vere senza che tu l'abbia mai vista.
L'elenco dei prodotti è nella scheda Prodotti: lì ogni articolo ha la stellina e i limiti suoi — prezzo, puntate, orizzonte e stato d'ingresso — che vincono su questi."/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Aggiungi le aste nuove da solo"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"/>
<CheckBox Grid.Row="0" Grid.Column="1" x:Name="AutoAddEnabledCheckBox"
Margin="10,10" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Stato delle aste aggiunte"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="Con cosa entrano nel monitor le aste trovate dalla sorveglianza"/>
<ComboBox Grid.Row="1" Grid.Column="1" x:Name="AutoAddStateCombo"
Margin="10,10" VerticalAlignment="Center">
<ComboBoxItem Content="Osserva (consigliato)" Tag="Watch"/>
<ComboBoxItem Content="Ferma" Tag="Stopped"/>
<ComboBoxItem Content="Attiva — punta subito" Tag="Active"/>
</ComboBox>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Cerca aste nuove ogni (secondi)"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"/>
<TextBox Grid.Row="2" Grid.Column="1" x:Name="AutoAddScanSecondsTextBox"
Text="90" Margin="10,10"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Massimo aste aggiunte insieme"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="0 = nessun limite"/>
<TextBox Grid.Row="3" Grid.Column="1" x:Name="AutoAddMaxAuctionsTextBox"
Text="20" Margin="10,10"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="Solo se cominciano entro (minuti)"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="Un'asta che comincia oltre questo tempo non viene aggiunta ancora: verrà ripresa alla scansione successiva, quando sarà più vicina. Serve a non riempire il monitor di aste che non succederanno per mezza giornata, consumando il tetto qui sopra. A mano puoi sempre aggiungere qualunque asta. 0 = nessun limite."/>
<TextBox Grid.Row="4" Grid.Column="1" x:Name="AutoAddMaxStartMinutesTextBox"
Text="60" Margin="10,10"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Solo aste non ancora cominciate"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="Aggiungi da solo soltanto le aste su cui nessuno ha ancora puntato, per poterle seguire dal primo istante all&apos;ultimo.&#10;&#10;Un&apos;asta presa a metà si può seguire, ma la sua storia è già scritta per buona parte: non si sa quanto è durata davvero, chi c&apos;era prima, come è salito il prezzo. Le statistiche che ne escono sono monche e la registrazione racconta solo la seconda metà.&#10;&#10;Il prezzo da pagare è che si perdono le occasioni già in corso."/>
<CheckBox Grid.Row="5" Grid.Column="1" x:Name="AutoAddOnlyNotStartedCheckBox"
Margin="10,10" VerticalAlignment="Center"/>
<TextBlock Grid.Row="6" Grid.Column="0" Text="Quante aste percorrere nella ricerca"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="Il listato è ordinato per scadenza: le aste che devono ancora aprire stanno in fondo. Un valore alto è ciò che permette di prenderle prima che inizino. Abbassarlo fa risparmiare richieste, ma le aste vengono prese solo quando sono già cominciate."/>
<TextBox Grid.Row="6" Grid.Column="1" x:Name="AutoAddScanDepthTextBox"
Text="2500" Margin="10,10"/>
</Grid>
</StackPanel>
</Border>
<!-- SEZIONE: Aste programmate -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Aste Programmate"
Margin="0,0,0,14"
Help="Un'asta che comincia fra ore non va interrogata ogni due secondi: fino all'apertura non succede nulla. La cadenza si allarga in proporzione all'attesa e torna normale poco prima dell'inizio, così il motore è comunque pronto a puntare."/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Rallenta prima dell'apertura"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"/>
<CheckBox Grid.Row="0" Grid.Column="1" x:Name="ScheduledBackoffCheckBox"
Margin="10,10" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Oltre un'ora, ogni (secondi)"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" x:Name="ScheduledPollFarTextBox"
Text="1200" Margin="10,10"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Fra 10 e 60 minuti, ogni (secondi)"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"/>
<TextBox Grid.Row="2" Grid.Column="1" x:Name="ScheduledPollMidTextBox"
Text="120" Margin="10,10"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Torna normale (secondi prima)"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="Margine di sicurezza per non perdere l'apertura"/>
<TextBox Grid.Row="3" Grid.Column="1" x:Name="ScheduledPollWakeTextBox"
Text="120" Margin="10,10"/>
</Grid>
</StackPanel>
</Border>
<!-- SEZIONE: Notifiche -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Notifiche"
Margin="0,0,0,14"
Help="Avvisi di Windows per gli eventi che vale la pena vedere anche a finestra chiusa."/>
<CheckBox x:Name="NotifyOnWinCheckBox" Content="Avvisami quando vinco un'asta"
IsChecked="True" Margin="0,4"/>
<CheckBox x:Name="NotifyOnLossCheckBox"
Content="Avvisami anche quando perdo un'asta su cui avevo puntato"
Margin="0,4"/>
</StackPanel>
</Border>
<!-- SEZIONE: Database -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Database"
Margin="0,0,0,14"
Help="Tutto ciò che l'applicazione registra sta in due file SQLite in questa cartella: le osservazioni (aste, puntate, interrogazioni, decisioni, misure) e l'esercizio (aste nel monitor, prodotti seguiti, modelli appresi, registri). Le impostazioni e la login restano nelle loro cartelle.&#10;&#10;Se cambi cartella, al salvataggio ti chiedo se spostare i database esistenti; in ogni caso l'applicazione si riavvia. Mai una cartella sincronizzata (OneDrive, Dropbox): un database aperto sotto sincronizzazione si corrompe."/>
<TextBlock Text="Cartella dei database" Style="{StaticResource FieldLabel}"/>
<Grid Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" x:Name="DatabaseFolderTextBox"/>
<Button Grid.Column="1" Content="Sfoglia…" Margin="8,0,0,0"
Style="{StaticResource SmallRoundedButton}"
Background="{DynamicResource Brush.SurfaceAlt}"
Foreground="{DynamicResource Brush.Text}"
Click="BrowseDatabaseFolderButton_Click"/>
<Button Grid.Column="2" Margin="6,0,0,0"
Style="{StaticResource IconButton}"
ToolTip="Apri la cartella dei database"
Click="OpenDatabaseFolderButton_Click">
<TextBlock FontFamily="Segoe MDL2 Assets" Text="&#xE838;"/>
</Button>
</Grid>
</StackPanel>
</Border>
<!-- SEZIONE: Manutenzione -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Manutenzione"
Margin="0,0,0,14"
Help="Le due operazioni estreme. «Elimina tutti i dati» cancella i database, le copie di sicurezza e la vecchia cartella Dati: restano la login e le impostazioni. «Impostazioni di fabbrica» cancella solo il file delle impostazioni: i dati e la login restano. Entrambe chiedono conferma e riavviano l'applicazione."/>
<StackPanel Orientation="Horizontal">
<Button Content="Elimina tutti i dati (tranne la login)" Style="{StaticResource SmallRoundedButton}"
Background="{DynamicResource Brush.Danger}"
Foreground="{DynamicResource Brush.TextOnAccent}"
Margin="0,0,8,0" Padding="14,6"
ToolTip="Cancella i due database (aste, puntate, decisioni, prodotti seguiti, aste nel monitor, modelli appresi, registri), le copie di sicurezza e la vecchia cartella Dati. Restano sessione, riferimenti del sito, browser e impostazioni. Doppia conferma, poi riavvio."
Click="WipeAllDataButton_Click"/>
<Button Content="Impostazioni di fabbrica" Style="{StaticResource SmallRoundedButton}"
Background="{DynamicResource Brush.SurfaceAlt}"
Foreground="{DynamicResource Brush.Danger}"
Margin="0,0,8,0" Padding="14,6"
ToolTip="Cancella il file delle impostazioni e riavvia: tutto torna ai predefiniti. Dati e login non vengono toccati."
Click="ResetSettingsButton_Click"/>
</StackPanel>
</StackPanel>
</Border>
<!-- SEZIONE: Registri su file -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Registri"
Margin="0,0,0,14"
Help="I registri si scrivono mentre l'applicazione lavora, nel database d'esercizio: quello che vedi nelle schede è già sul disco. Servono a rileggere cosa è successo mentre non guardavi. Si esportano in testo con il pulsante qui sotto e scadono dopo il numero di giorni indicato."/>
<CheckBox x:Name="WriteAppLogCheckBox" IsChecked="True" Margin="0,4"
Content="Registro applicativo nel database"/>
<CheckBox x:Name="WriteFreeBidsLogCheckBox" IsChecked="True" Margin="0,4"
Content="Registro del riscatto puntate nel database"/>
<CheckBox x:Name="WriteDossiersCheckBox" IsChecked="True" Margin="0,4"
Content="Registra ogni asta seguita nel database (puntate di ogni utente, reset, mie puntate, decisioni)"/>
<CheckBox x:Name="RawPollsCheckBox" IsChecked="True" Margin="0,4"
Content="Registra anche le interrogazioni a Bidoo (una riga quando cambia qualcosa, e almeno una al secondo)"
ToolTip="Risoluzione massima: prezzo, timer e ping a ogni poll. Nella finestra critica sono quattro righe al secondo, quindi i file crescono in fretta."/>
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Cancella i registri dopo (giorni)"
Foreground="{DynamicResource Brush.Text}" Margin="0,10"
VerticalAlignment="Center"
ToolTip="0 = tienili per sempre"/>
<TextBox Grid.Column="1" x:Name="LogRetentionTextBox" Text="90" Margin="10,10"/>
</Grid>
<Button Content="Esporta i registri in testo…" Style="{StaticResource SmallRoundedButton}"
Background="{DynamicResource Brush.SurfaceAlt}"
Foreground="{DynamicResource Brush.Text}"
HorizontalAlignment="Left" Margin="0,6,0,0" Padding="14,5"
ToolTip="Scrive il registro applicativo e quello del riscatto puntate in due file di testo, nella cartella che scegli."
Click="ExportAppLogButton_Click"/>
</StackPanel>
</Border>
<!-- SEZIONE: Catalogo Esplora -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Catalogo (scheda Esplora)"
Margin="0,0,0,14"
Help="L'app scende nel listato pagina per pagina, come il sito quando scorri verso il basso: cinquanta aste per richiesta, fino al tetto impostato qui. L'ordine è per scadenza, quindi le prime pagine sono le aste che chiudono prima. Alzare il tetto allarga la vista ma aggiunge una richiesta ogni cinquanta aste."/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Aste da caricare per categoria"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="Da 20 a 5000. Una richiesta ogni 50 aste; le categorie piccole finiscono prima e si fermano da sole."/>
<TextBox Grid.Row="0" Grid.Column="1" x:Name="CatalogMaxAuctionsTextBox"
Text="500" Margin="10,10"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Aggiorna prezzi mentre guardi"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="Acceso, prezzi e timer cambiano sotto gli occhi mentre stai leggendo"/>
<CheckBox Grid.Row="1" Grid.Column="1" x:Name="CatalogAutoRefreshCheckBox"
Margin="10,10" VerticalAlignment="Center"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Riusa le aste scaricate per (secondi)"
Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center"
ToolTip="0 = nessuna cache. Evita di riscaricare tutte le pagine a ogni cambio categoria."/>
<TextBox Grid.Row="2" Grid.Column="1" x:Name="CatalogCacheSecondsTextBox"
Text="60" Margin="10,10"/>
</Grid>
</StackPanel>
</Border>
<!-- SEZIONE 3: Protezione Account -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Protezione Account"
Margin="0,0,0,14"
Help="Tiene da parte un cuscinetto di puntate sull'account.
Se il valore è maggiore di zero, il sistema non punta quando le puntate residue scenderebbero sotto la soglia. Nel banner principale compare un indicatore: verde oltre le +10 dal limite, giallo entro 10, rosso al limite o sotto (puntate bloccate). Zero = nessun limite."/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Puntate Minime da Mantenere -->
<TextBlock Grid.Row="0" Grid.Column="0"
Text="Puntate Minime da Mantenere"
Foreground="{DynamicResource Brush.Text}"
Margin="0,10"
VerticalAlignment="Center"
ToolTip="Numero minimo di puntate residue da mantenere sull'account. Se > 0, non punterà se scende sotto questa soglia (0 = nessun limite)"/>
<TextBox Grid.Row="0" Grid.Column="1"
x:Name="MinimumRemainingBidsTextBox"
Text="0"
Margin="10,10"/>
</Grid>
<!-- Info Box -->
</StackPanel>
</Border>
<!-- SEZIONE: Gestione del rischio -->
<Border Style="{StaticResource CardBlock}">
<StackPanel>
<ctl:HelpHeader Title="Gestione del rischio"
Margin="0,0,0,14"
Help="I paletti duri che nessuna strategia può scavalcare. Ogni puntata dal vivo passa da qui prima di partire.&#10;&#10;Il tetto di spesa del giorno ferma le puntate per oggi e domani si riparte. Lo stop-loss (perdita netta del giorno) e il drawdown (discesa dal picco del saldo cumulato) mettono invece il sistema in HALT: resta fermo anche dopo un riavvio, finché non lo togli tu da qui. Le vincite si contano al valore reale del prodotto (colonna «Valore reale» nella scheda Prodotti), meno prezzo, fee e spedizione.&#10;&#10;La copertura «Compralo Ora» presume che, perdendo, si compri al listino recuperando le puntate come credito: la perdita si limita a listino valore reale. Per i buoni al nominale copre tutto dal primo centesimo, e il modello punterà più spesso. Se non intendi esercitarla, spegnila."/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Tetti di puntate attivi" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Applica i due tetti di puntate qui sotto (per asta e per sessione)."/>
<CheckBox Grid.Row="0" Grid.Column="1" x:Name="BankrollEnabledCheckBox" Margin="10,10" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Puntate massime per asta" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="0 = nessun limite. Vale per le aste senza un tetto proprio."/>
<TextBox Grid.Row="1" Grid.Column="1" x:Name="MaxBidsPerAuctionTextBox" Text="0" Margin="10,10"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Puntate massime per sessione" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="0 = nessun limite. Si azzera a ogni avvio."/>
<TextBox Grid.Row="2" Grid.Column="1" x:Name="MaxBidsPerSessionTextBox" Text="0" Margin="10,10"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Tetto di spesa del giorno (€)" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Quanto spendere in puntate al massimo in un giorno. 0 = nessun limite. Non è un HALT: domani si riparte."/>
<TextBox Grid.Row="3" Grid.Column="1" x:Name="DailyBudgetTextBox" Text="0" Margin="10,10"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="Stop-loss del giorno (€)" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Perdita netta del giorno (puntate spese meno vincite) oltre la quale il sistema entra in HALT. 0 = mai."/>
<TextBox Grid.Row="4" Grid.Column="1" x:Name="DailyStopLossTextBox" Text="0" Margin="10,10"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Drawdown massimo (€)" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Discesa del saldo cumulato dal suo picco oltre la quale il sistema entra in HALT. 0 = mai."/>
<TextBox Grid.Row="5" Grid.Column="1" x:Name="MaxDrawdownTextBox" Text="0" Margin="10,10"/>
<TextBlock Grid.Row="6" Grid.Column="0" Text="Aste in gioco insieme" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Su quante aste al massimo spendere nello stesso momento. Un'asta è «in gioco» quando ha già ricevuto una tua puntata in questa sessione. 0 = nessun limite."/>
<TextBox Grid.Row="6" Grid.Column="1" x:Name="MaxConcurrentTextBox" Text="0" Margin="10,10"/>
<TextBlock Grid.Row="7" Grid.Column="0" Text="Fee di transazione (€)" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Quanto Bidoo aggiunge alla vincita. Entra nel valore atteso di ogni puntata e nel conto delle vincite."/>
<TextBox Grid.Row="7" Grid.Column="1" x:Name="TransactionFeeTextBox" Text="1,00" Margin="10,10"/>
<TextBlock Grid.Row="8" Grid.Column="0" Text="Copertura «Compralo Ora»" Foreground="{DynamicResource Brush.Text}" Margin="0,10" VerticalAlignment="Center" ToolTip="Vedi la spiegazione della sezione. Accesa: le puntate oltre la perdita coperta (Compralo Ora meno valore reale) non costano nulla nel ramo di sconfitta.&#10;&#10;Vale solo per i prodotti con «Valore reale €» scritto nella scheda Prodotti: senza, il valore coinciderebbe con il listino, la perdita coperta sarebbe zero e ogni puntata risulterebbe gratis — si punterebbe sempre."/>
<CheckBox Grid.Row="8" Grid.Column="1" x:Name="HedgeCheckBox" Margin="10,10" VerticalAlignment="Center" IsChecked="True"/>
</Grid>
<Border Style="{StaticResource InfoBox}" Margin="0,15,0,0">
<StackPanel>
<TextBlock x:Name="RiskStatusText" TextWrapping="Wrap"
Foreground="{DynamicResource Brush.Text}"
FontSize="12" LineHeight="18"
Text="Nessun HALT in corso."/>
<Button x:Name="ResumeHaltButton" Content="Togli l'HALT e riparti" Margin="0,10,0,0"
HorizontalAlignment="Left" Padding="14,5" Visibility="Collapsed"
Style="{StaticResource SmallRoundedButton}"
Background="{DynamicResource Brush.Danger}"
Foreground="{DynamicResource Brush.TextOnAccent}"
Click="ResumeHaltButton_Click"/>
</StackPanel>
</Border>
</StackPanel>
</Border>
<!-- SEZIONE 4: Limiti Log -->
<Border Background="{DynamicResource Brush.Surface}"
BorderBrush="{DynamicResource Brush.Border}"
BorderThickness="1"
CornerRadius="4"
Padding="20">
<StackPanel>
<ctl:HelpHeader Title="Limiti Log"
Margin="0,0,0,14"
Help="Quante righe di registro tenere in memoria. Le più vecchie vengono scartate al raggiungimento del limite.
Valori bassi = meno memoria, meno storico a video. Valori alti = più storico, più memoria. Consigliati: 5001000 per asta, 10002000 per il registro globale.
Riguarda solo la memoria: sul file i registri vengono scritti comunque per intero."/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
Text="Max Righe Log per Asta"
Foreground="{DynamicResource Brush.Text}"
Margin="0,10"
VerticalAlignment="Center"
ToolTip="Numero massimo di righe di log da mantenere per ogni singola asta (raccomandato: 500-1000)"/>
<TextBox Grid.Row="0" Grid.Column="1"
x:Name="MaxLogLinesPerAuctionTextBox"
Text="500"
Margin="10,10"/>
<TextBlock Grid.Row="1" Grid.Column="0"
Text="Max Righe Log Globale"
Foreground="{DynamicResource Brush.Text}"
Margin="0,10"
VerticalAlignment="Center"
ToolTip="Numero massimo di righe di log da mantenere nel log globale dell'applicazione (raccomandato: 1000-2000)"/>
<TextBox Grid.Row="1" Grid.Column="1"
x:Name="MaxGlobalLogLinesTextBox"
Text="1000"
Margin="10,10"/>
<!-- 📊 NUOVO: Max Storia Puntate -->
<TextBlock Grid.Row="2" Grid.Column="0"
Text="Max Puntate da Visualizzare"
Foreground="{DynamicResource Brush.Text}"
Margin="0,10"
VerticalAlignment="Center"
ToolTip="Numero massimo di puntate da mostrare nella scheda Storia Puntate (raccomandato: 20-50, 0 = tutte)"/>
<TextBox Grid.Row="2" Grid.Column="1"
x:Name="MaxBidHistoryEntriesTextBox"
Text="20"
Margin="10,10"/>
</Grid>
<!-- Info Box -->
</StackPanel>
</Border>
<!-- SEZIONE 5: Livello di Dettaglio Log -->
<Border Background="{DynamicResource Brush.Surface}"
BorderBrush="{DynamicResource Brush.Border}"
BorderThickness="1"
CornerRadius="4"
Padding="20"
Margin="0,20,0,0">
<StackPanel>
<ctl:HelpHeader Title="Livello di Dettaglio Log"
Margin="0,0,0,14"
Help="Livello minimo dei messaggi mostrati a video. Il file di registro li riceve tutti comunque, perché serve proprio quando il messaggio utile è uno di quelli nascosti.
• Solo Errori: in esercizio, per vedere solo i problemi critici.
• Normale: uso giornaliero. Errori e avvisi importanti.
• Informativo: segue le operazioni principali (aste aggiunte, puntate).
• Debug: parametri delle chiamate e valori interni.
• Trace: ogni singola chiamata. Molto verboso.
Colori: rosso = errori, arancione = avvisi, blu = informazioni, verde = operazioni riuscite, magenta = debug, grigio = trace."/>
<!-- Radio Buttons per livello log -->
<StackPanel>
<RadioButton x:Name="LogLevelErrorOnly"
Content="Solo Errori"
GroupName="LogLevel"
Margin="0,5"
ToolTip="Mostra solo errori critici (uso minimo per produzione)"/>
<RadioButton x:Name="LogLevelNormal"
Content="Normale (Errori + Avvisi)"
GroupName="LogLevel"
IsChecked="True"
Margin="0,5"
ToolTip="Mostra errori e avvisi (uso giornaliero raccomandato)"/>
<RadioButton x:Name="LogLevelInformational"
Content="Informativo (Include operazioni completate)"
GroupName="LogLevel"
Margin="0,5"
ToolTip="Mostra anche messaggi informativi e conferme (uso dettagliato)"/>
<RadioButton x:Name="LogLevelDebug"
Content="Debug (Include dettagli tecnici)"
GroupName="LogLevel"
Margin="0,5"
ToolTip="Mostra anche messaggi di debug per sviluppo"/>
<RadioButton x:Name="LogLevelTrace"
Content="Trace (Tutto - molto verboso)"
GroupName="LogLevel"
Margin="0,5"
ToolTip="Mostra ogni singola operazione (debug avanzato)"/>
</StackPanel>
<!-- Info Box -->
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
<!-- Fixed Bottom Bar with Save/Cancel -->
<Border Grid.Row="1"
Background="{DynamicResource Brush.SurfaceAlt}"
BorderBrush="{DynamicResource Brush.Border}"
BorderThickness="0,1,0,0"
Padding="30,15">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Salva"
Background="{DynamicResource Brush.Success}"
Style="{StaticResource ModernButton}"
Margin="0,0,10,0"
Padding="40,10"
Click="SaveAllSettings_Click" Foreground="{DynamicResource Brush.TextOnAccent}"/>
<Button Content="Annulla"
Background="{DynamicResource Brush.SurfaceAlt}"
Style="{StaticResource ModernButton}"
Padding="40,10"
Click="CancelAllSettings_Click"/>
</StackPanel>
</Border>
</Grid>
</UserControl>