Ottimizzazioni UI e performance click handler

- Rimosse righe inutilizzate e semplificato layout in `MainWindow.xaml`.
- Aggiunti pulsanti di navigazione accanto alla barra indirizzi.
- Convertite operazioni UI in asincrone con `Dispatcher.BeginInvoke`.
- Introdotto aggiornamento griglia bidder ogni 2 secondi per ridurre lag.
- Migliorata gestione log con `AppendText` e controllo dimensione ottimizzato.
- Ridotto polling dinamico per timer bassi (minimo 20ms).
- Ottimizzato script di click con cache bottone e timeout ridotto (500ms).
- Implementato multi-click parallelo con delay minimo (20ms).
- Parsing JSON e lettura impostazioni resi più efficienti.
- Rimosso codice obsoleto e semplificata gestione eventi.
This commit is contained in:
Alberto Balbo
2025-10-14 12:26:51 +02:00
parent b12b57be81
commit 28ef09d91f
2 changed files with 171 additions and 119 deletions

View File

@@ -95,11 +95,9 @@
<RowDefinition Height="Auto" /> <!-- Start --> <RowDefinition Height="Auto" /> <!-- Start -->
<RowDefinition Height="Auto" /> <!-- Pause --> <RowDefinition Height="Auto" /> <!-- Pause -->
<RowDefinition Height="Auto" /> <!-- Stop --> <RowDefinition Height="Auto" /> <!-- Stop -->
<RowDefinition Height="Auto" /> <!-- Back/Refresh/Clear -->
<RowDefinition Height="Auto" /> <!-- Stats --> <RowDefinition Height="Auto" /> <!-- Stats -->
<RowDefinition Height="Auto" /> <!-- Settings Row 1 --> <RowDefinition Height="Auto" /> <!-- Settings Row 1 -->
<RowDefinition Height="Auto" /> <!-- Settings Row 2 --> <RowDefinition Height="Auto" /> <!-- Settings Row 2 -->
<RowDefinition Height="Auto" /> <!-- Advanced timing control -->
<RowDefinition Height="Auto" /> <!-- Bidders label with clear button --> <RowDefinition Height="Auto" /> <!-- Bidders label with clear button -->
<RowDefinition Height="Auto" /> <!-- Bidders grid --> <RowDefinition Height="Auto" /> <!-- Bidders grid -->
<RowDefinition Height="Auto" /> <!-- Log label with clear button --> <RowDefinition Height="Auto" /> <!-- Log label with clear button -->
@@ -112,23 +110,8 @@
<Button x:Name="StopButton" Grid.Row="2" Style="{StaticResource StopButtonStyle}" Click="StopButton_Click" IsEnabled="False" Margin="12,6,12,0">Stop</Button> <Button x:Name="StopButton" Grid.Row="2" Style="{StaticResource StopButtonStyle}" Click="StopButton_Click" IsEnabled="False" Margin="12,6,12,0">Stop</Button>
<!-- Back / Refresh / ClearStats on same line -->
<Grid Grid.Row="3" Margin="12,6,12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="BackButton" Grid.Column="0" Style="{StaticResource RefreshButtonStyle}" Click="BackButton_Click" Height="36">Indietro</Button>
<Button x:Name="RefreshButton" Grid.Column="2" Style="{StaticResource RefreshButtonStyle}" Click="RefreshButton_Click" Height="36">Aggiorna</Button>
<Button x:Name="ClearStatsButton" Grid.Column="4" Style="{StaticResource RefreshButtonStyle}" Click="ClearStatsButton_Click" Height="36">Pulisci</Button>
</Grid>
<!-- Stats con prezzo corrente e Multi-Click --> <!-- Stats con prezzo corrente e Multi-Click -->
<Grid Grid.Row="4" Margin="12,8,12,0"> <Grid Grid.Row="3" Margin="12,8,12,0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@@ -156,7 +139,7 @@
</Grid> </Grid>
<!-- Settings Row 1: Max Clicks, Max Resets, Min Price, Max Price --> <!-- Settings Row 1: Max Clicks, Max Resets, Min Price, Max Price -->
<Grid Grid.Row="5" Margin="12,8,12,0"> <Grid Grid.Row="4" Margin="12,8,12,0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="8" /> <ColumnDefinition Width="8" />
@@ -193,8 +176,8 @@
</StackPanel> </StackPanel>
</Grid> </Grid>
<!-- Settings Row 2: Timer Click, Ritardo, Multi-Click --> <!-- Settings Row 2: Timer Click, Ritardo -->
<Grid Grid.Row="6" Margin="12,6,12,0"> <Grid Grid.Row="5" Margin="12,6,12,0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="8" /> <ColumnDefinition Width="8" />
@@ -215,12 +198,12 @@
<!-- Ritardo --> <!-- Ritardo -->
<StackPanel Grid.Row="0" Grid.Column="2" Orientation="Vertical"> <StackPanel Grid.Row="0" Grid.Column="2" Orientation="Vertical">
<TextBlock Text="Ritardo (ms)" FontSize="11" /> <TextBlock Text="Ritardo (ms)" FontSize="11" />
<TextBox x:Name="ClickDelayBox" Style="{StaticResource NumericBoxStyle}" Text="100" Width="Auto" ToolTip="Ritardo aggiuntivo in millisecondi" TextChanged="ClickDelayBox_TextChanged" /> <TextBox x:Name="ClickDelayBox" Style="{StaticResource NumericBoxStyle}" Text="0" Width="Auto" ToolTip="Ritardo aggiuntivo in millisecondi (0 = massima velocità)" TextChanged="ClickDelayBox_TextChanged" />
</StackPanel> </StackPanel>
</Grid> </Grid>
<!-- Bidders section header with clear button --> <!-- Bidders section header with clear button -->
<Grid Grid.Row="8" Margin="12,8,12,4"> <Grid Grid.Row="6" Margin="12,8,12,4">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@@ -239,7 +222,7 @@
</Button> </Button>
</Grid> </Grid>
<DataGrid x:Name="BiddersGrid" Grid.Row="9" Margin="12,0,12,0" AutoGenerateColumns="False" HeadersVisibility="Column" CanUserAddRows="False" IsReadOnly="True" Height="90" Background="#091018" RowBackground="#0B1220" AlternatingRowBackground="#081016" Foreground="#E6EDF3" GridLinesVisibility="None"> <DataGrid x:Name="BiddersGrid" Grid.Row="7" Margin="12,0,12,0" AutoGenerateColumns="False" HeadersVisibility="Column" CanUserAddRows="False" IsReadOnly="True" Height="90" Background="#091018" RowBackground="#0B1220" AlternatingRowBackground="#081016" Foreground="#E6EDF3" GridLinesVisibility="None">
<DataGrid.Resources> <DataGrid.Resources>
<Style TargetType="DataGridColumnHeader"> <Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="#0F1720" /> <Setter Property="Background" Value="#0F1720" />
@@ -258,7 +241,7 @@
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
<Grid Grid.Row="10" Margin="12,6,12,4"> <Grid Grid.Row="8" Margin="12,6,12,4">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@@ -277,7 +260,7 @@
</Button> </Button>
</Grid> </Grid>
<TextBox x:Name="LogBox" Grid.Row="11" Margin="12,0,12,12" IsReadOnly="True" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" AcceptsReturn="True" Style="{StaticResource LogBoxStyle}" /> <TextBox x:Name="LogBox" Grid.Row="9" Margin="12,0,12,12" IsReadOnly="True" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" AcceptsReturn="True" Style="{StaticResource LogBoxStyle}" />
</Grid> </Grid>
</Border> </Border>
@@ -291,20 +274,50 @@
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Address bar --> <!-- Address bar con pulsanti navigazione -->
<Grid Grid.Row="0" Margin="12,12,12,6"> <Grid Grid.Row="0" Margin="12,12,12,6">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBox x:Name="AddressBar" Grid.Column="0" Style="{StaticResource AddressBarStyle}" <!-- Pulsante Indietro -->
<Button x:Name="BackButton" Grid.Column="0" Content="Indietro" Click="BackButton_Click"
Background="#374151" Foreground="White" Padding="12,8" Margin="0,0,6,0"
BorderThickness="0" FontWeight="SemiBold" FontSize="13" MinWidth="70" Height="38" IsEnabled="False">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" CornerRadius="6" SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<!-- Pulsante Aggiorna -->
<Button x:Name="RefreshButton" Grid.Column="1" Content="Aggiorna" Click="RefreshButton_Click"
Background="#0EA5E9" Foreground="White" Padding="12,8" Margin="0,0,8,0"
BorderThickness="0" FontWeight="SemiBold" FontSize="13" MinWidth="80" Height="38">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" CornerRadius="6" SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<!-- Barra indirizzo -->
<TextBox x:Name="AddressBar" Grid.Column="2" Style="{StaticResource AddressBarStyle}"
Text="https://it.bidoo.com" KeyDown="AddressBar_KeyDown" Text="https://it.bidoo.com" KeyDown="AddressBar_KeyDown"
ToolTip="Inserisci URL di Bidoo (es: https://it.bidoo.com/asta/...)" /> ToolTip="Inserisci URL di Bidoo (es: https://it.bidoo.com/asta/...)" />
<Button x:Name="NavigateButton" Grid.Column="1" Content="Vai" Click="NavigateButton_Click" <!-- Pulsante Vai -->
Background="#16A34A" Foreground="White" Padding="38,10" Margin="8,0,0,0" <Button x:Name="NavigateButton" Grid.Column="3" Content="Vai" Click="NavigateButton_Click"
BorderThickness="0" FontWeight="Bold" FontSize="14" MinWidth="90"> Background="#16A34A" Foreground="White" Padding="28,10" Margin="8,0,0,0"
BorderThickness="0" FontWeight="Bold" FontSize="14" MinWidth="80" Height="38">
<Button.Template> <Button.Template>
<ControlTemplate TargetType="Button"> <ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" CornerRadius="6" SnapsToDevicePixels="True"> <Border Background="{TemplateBinding Background}" CornerRadius="6" SnapsToDevicePixels="True">

View File

@@ -69,7 +69,6 @@ namespace AutoBidder
StartButton.Opacity = 1.0; StartButton.Opacity = 1.0;
StopButton.IsEnabled = false; StopButton.IsEnabled = false;
StopButton.Opacity = 0.5; StopButton.Opacity = 0.5;
BackButton.IsEnabled = false;
webView.NavigationCompleted += WebView_NavigationCompleted; webView.NavigationCompleted += WebView_NavigationCompleted;
webView.NavigationStarting += WebView_NavigationStarting; webView.NavigationStarting += WebView_NavigationStarting;
@@ -170,9 +169,13 @@ namespace AutoBidder
{ {
try try
{ {
BackButton.IsEnabled = webView.CoreWebView2 != null && webView.CoreWebView2.CanGoBack; // ⚡ OTTIMIZZAZIONE: Update UI asincrono
Dispatcher.BeginInvoke(() =>
{
try try
{ {
BackButton.IsEnabled = webView.CoreWebView2 != null && webView.CoreWebView2.CanGoBack;
var url = webView.CoreWebView2?.Source ?? webView.Source?.ToString(); var url = webView.CoreWebView2?.Source ?? webView.Source?.ToString();
if (!string.IsNullOrEmpty(url)) if (!string.IsNullOrEmpty(url))
{ {
@@ -181,6 +184,7 @@ namespace AutoBidder
} }
} }
catch { } catch { }
});
} }
catch { } catch { }
} }
@@ -290,15 +294,6 @@ namespace AutoBidder
private void ClickTimerBox_TextChanged(object sender, TextChangedEventArgs e) => Log("Impostazione Click Timer cambiata: " + ClickTimerBox.Text); private void ClickTimerBox_TextChanged(object sender, TextChangedEventArgs e) => Log("Impostazione Click Timer cambiata: " + ClickTimerBox.Text);
private void ClickDelayBox_TextChanged(object sender, TextChangedEventArgs e) => Log("Impostazione Click Delay cambiata: " + ClickDelayBox.Text); private void ClickDelayBox_TextChanged(object sender, TextChangedEventArgs e) => Log("Impostazione Click Delay cambiata: " + ClickDelayBox.Text);
private void ClearStatsButton_Click(object sender, RoutedEventArgs e)
{
ClickCountText.Text = "0";
ResetCountText.Text = "0";
Log("Statistiche resettate dall'utente");
_bidders.Clear();
UpdateBiddersGrid();
}
private void ClearBiddersButton_Click(object sender, RoutedEventArgs e) private void ClearBiddersButton_Click(object sender, RoutedEventArgs e)
{ {
try try
@@ -333,11 +328,21 @@ namespace AutoBidder
catch { } catch { }
} }
private DateTime _lastBiddersUpdate = DateTime.MinValue;
private void UpdateBiddersGrid() private void UpdateBiddersGrid()
{ {
try try
{ {
Dispatcher.Invoke(() => // ⚡ OTTIMIZZAZIONE: Aggiorna solo ogni 2 secondi per evitare lag
var now = DateTime.UtcNow;
if ((now - _lastBiddersUpdate).TotalMilliseconds < 2000)
return;
_lastBiddersUpdate = now;
// ⚡ USA BeginInvoke ASINCRONO invece di Invoke per non bloccare
Dispatcher.BeginInvoke(() =>
{ {
var grid = FindName("BiddersGrid") as DataGrid; var grid = FindName("BiddersGrid") as DataGrid;
if (grid != null) if (grid != null)
@@ -350,11 +355,20 @@ namespace AutoBidder
catch { } catch { }
} }
private string _lastPriceText = "";
private void SetCurrentPriceText(string text) private void SetCurrentPriceText(string text)
{ {
try try
{ {
Dispatcher.Invoke(() => // ⚡ OTTIMIZZAZIONE: Non aggiornare se il prezzo non è cambiato
if (_lastPriceText == text)
return;
_lastPriceText = text;
// ⚡ USA BeginInvoke ASINCRONO
Dispatcher.BeginInvoke(() =>
{ {
var tb = FindName("CurrentPriceText") as TextBlock; var tb = FindName("CurrentPriceText") as TextBlock;
if (tb != null) tb.Text = text; if (tb != null) tb.Text = text;
@@ -368,20 +382,22 @@ namespace AutoBidder
var entry = $"{DateTime.Now:HH:mm:ss} - {message}{Environment.NewLine}"; var entry = $"{DateTime.Now:HH:mm:ss} - {message}{Environment.NewLine}";
try try
{ {
Dispatcher.Invoke(() => // ⚡ OTTIMIZZAZIONE CRITICA: USA BeginInvoke per non bloccare MAI il thread di automazione
Dispatcher.BeginInvoke(() =>
{ {
if (LogBox != null) if (LogBox != null)
{ {
// Gestione performance: limita numero righe log // ⚡ Semplifica: AppendText direttamente senza split pesante ogni volta
var lines = LogBox.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None); LogBox.AppendText(entry);
if (lines.Length > MAX_LOG_LINES)
// ⚡ Controlla dimensione log solo ogni 100 righe circa
if (LogBox.LineCount > MAX_LOG_LINES + 100)
{ {
// Mantieni solo le ultime MAX_LOG_LINES righe var lines = LogBox.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
var recentLines = lines.Skip(lines.Length - MAX_LOG_LINES + 50).ToArray(); var recentLines = lines.Skip(lines.Length - MAX_LOG_LINES).ToArray();
LogBox.Text = string.Join(Environment.NewLine, recentLines); LogBox.Text = string.Join(Environment.NewLine, recentLines);
} }
LogBox.AppendText(entry);
LogBox.ScrollToEnd(); LogBox.ScrollToEnd();
} }
else else
@@ -647,18 +663,22 @@ namespace AutoBidder
try { result = JsonSerializer.Deserialize<string>(result) ?? result; } catch { } try { result = JsonSerializer.Deserialize<string>(result) ?? result; } catch { }
} }
// Read limits // ⚡ OTTIMIZZAZIONE CRITICA: Lettura impostazioni veloce
int maxClicks = int.MaxValue, maxResets = int.MaxValue; int maxClicks = int.MaxValue, maxResets = int.MaxValue;
double minPrice = 0.0, maxPrice = double.MaxValue; double minPrice = 0.0, maxPrice = double.MaxValue;
try try
{ {
await Dispatcher.InvokeAsync(() => var settingsOp = Dispatcher.InvokeAsync(() =>
{ {
if (int.TryParse(MaxClicksBox.Text, out var mc) && mc > 0) maxClicks = mc; if (int.TryParse(MaxClicksBox.Text, out var mc) && mc > 0) maxClicks = mc;
if (int.TryParse(MaxResetsBox.Text, out var mr) && mr > 0) maxResets = mr; if (int.TryParse(MaxResetsBox.Text, out var mr) && mr > 0) maxResets = mr;
if (double.TryParse(MinPriceBox.Text.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var mp)) minPrice = mp; if (double.TryParse(MinPriceBox.Text.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var mp)) minPrice = mp;
if (double.TryParse(MaxPriceBox.Text.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var mpx) && mpx > 0) maxPrice = mpx; if (double.TryParse(MaxPriceBox.Text.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var mpx) && mpx > 0) maxPrice = mpx;
}); });
// ⚡ Usa valori default se timeout
var opStatus = settingsOp.Wait(TimeSpan.FromMilliseconds(10));
if (opStatus == System.Windows.Threading.DispatcherOperationStatus.Completed)
await settingsOp.Task;
} }
catch { } catch { }
@@ -675,9 +695,11 @@ namespace AutoBidder
// ⭐ LOG quando cambia il bidder E REGISTRA IMMEDIATAMENTE // ⭐ LOG quando cambia il bidder E REGISTRA IMMEDIATAMENTE
if (!string.IsNullOrWhiteSpace(currentBidder) && currentBidder != lastKnownBidder) if (!string.IsNullOrWhiteSpace(currentBidder) && currentBidder != lastKnownBidder)
{ {
Log($"👤 Puntata di: {currentBidder}"); // ⚡ OTTIMIZZAZIONE: Log e registrazione separati per non bloccare
var bidderToLog = currentBidder;
Task.Run(() => Log($"👤 Puntata di: {bidderToLog}"));
// ⭐ REGISTRA SUBITO LA PUNTATA NELLA LISTA // ⭐ REGISTRA SUBITO LA PUNTATA NELLA LISTA (senza bloccare)
RegisterBidder(currentBidder); RegisterBidder(currentBidder);
lastKnownBidder = currentBidder; lastKnownBidder = currentBidder;
@@ -772,11 +794,13 @@ namespace AutoBidder
if (currentTimer > prevTimer + 0.5 && prevTimer < 30) if (currentTimer > prevTimer + 0.5 && prevTimer < 30)
{ {
resetCount++; resetCount++;
await Dispatcher.InvokeAsync(() => ResetCountText.Text = resetCount.ToString()); // ⚡ OTTIMIZZAZIONE: UI update asincrono
Dispatcher.BeginInvoke(() => ResetCountText.Text = resetCount.ToString());
// ⭐ Usa currentBidder invece di fare una nuova query // ⭐ Usa currentBidder invece di fare una nuova query
var winnerName = !string.IsNullOrWhiteSpace(currentBidder) ? currentBidder : "Sconosciuto"; var winnerName = !string.IsNullOrWhiteSpace(currentBidder) ? currentBidder : "Sconosciuto";
Log($"🔄 Reset #{resetCount} - Winner: {winnerName}"); var cnt = resetCount;
Task.Run(() => Log($"🔄 Reset #{cnt} - Winner: {winnerName}"));
if (resetCount >= maxResets) if (resetCount >= maxResets)
{ {
@@ -797,12 +821,17 @@ namespace AutoBidder
try try
{ {
await Dispatcher.InvokeAsync(() => // ⚡ OTTIMIZZAZIONE: Lettura veloce con timeout minimo
var clickSettingsOp = Dispatcher.InvokeAsync(() =>
{ {
if (int.TryParse(ClickTimerBox.Text, out var ctv) && ctv >= 0 && ctv <= 8) clickTimerValue = ctv; if (int.TryParse(ClickTimerBox.Text, out var ctv) && ctv >= 0 && ctv <= 8) clickTimerValue = ctv;
if (int.TryParse(ClickDelayBox.Text, out var cdm) && cdm >= 0 && cdm <= 2000) clickDelayMs = cdm; if (int.TryParse(ClickDelayBox.Text, out var cdm) && cdm >= 0 && cdm <= 2000) clickDelayMs = cdm;
multiClickEnabled = MultiClickCheckBox.IsChecked == true; multiClickEnabled = MultiClickCheckBox.IsChecked == true;
}); });
// ⚡ Timeout velocissimo: se non risponde in 5ms usa default
var opStatus = clickSettingsOp.Wait(TimeSpan.FromMilliseconds(5));
if (opStatus == System.Windows.Threading.DispatcherOperationStatus.Completed)
await clickSettingsOp.Task;
} }
catch { } catch { }
@@ -825,18 +854,27 @@ namespace AutoBidder
if (clickSuccess) if (clickSuccess)
{ {
clickCount++; clickCount++;
await Dispatcher.InvokeAsync(() => ClickCountText.Text = clickCount.ToString()); // ⚡ OTTIMIZZAZIONE: Update UI asincrono non bloccante
Dispatcher.BeginInvoke(() => ClickCountText.Text = clickCount.ToString());
// ⭐ Usa il nome utente corrente (mai AutoBidder se abbiamo il nome) // ⭐ Usa il nome utente corrente (mai AutoBidder se abbiamo il nome)
if (!string.IsNullOrWhiteSpace(_currentUserName)) if (!string.IsNullOrWhiteSpace(_currentUserName))
{ {
RegisterBidder(_currentUserName); RegisterBidder(_currentUserName);
Log($"✅ Click #{clickCount} ({_currentUserName}) - Timer: {timerValue}s (Delay: {clickDelayMs}ms)"); // ⚡ Log asincrono
var userName = _currentUserName;
var cnt = clickCount;
var timer = timerValue;
var delay = clickDelayMs;
Task.Run(() => Log($"✅ Click #{cnt} ({userName}) - Timer: {timer}s (Delay: {delay}ms)"));
} }
else else
{ {
// ⭐ NON registrare AutoBidder nella lista, solo nel log // ⭐ NON registrare AutoBidder nella lista, solo nel log
Log($"✅ Click #{clickCount} (AutoBidder) - Timer: {timerValue}s (Delay: {clickDelayMs}ms)"); var cnt = clickCount;
var timer = timerValue;
var delay = clickDelayMs;
Task.Run(() => Log($"✅ Click #{cnt} (AutoBidder) - Timer: {timer}s (Delay: {delay}ms)"));
} }
if (clickCount >= maxClicks) if (clickCount >= maxClicks)
@@ -849,7 +887,8 @@ namespace AutoBidder
} }
else else
{ {
Log($"⚠️ Click fallito - Timer: {timerValue}s"); var timer = timerValue;
Task.Run(() => Log($"⚠️ Click fallito - Timer: {timer}s"));
} }
} }
else if ((DateTime.UtcNow - lastDecisionLog) > TimeSpan.FromSeconds(3)) else if ((DateTime.UtcNow - lastDecisionLog) > TimeSpan.FromSeconds(3))
@@ -863,34 +902,41 @@ namespace AutoBidder
continue; continue;
} }
// ⚡ POLLING DINAMICO ULTRA-AGGRESSIVO per evitare micro-lag
int pollDelay; int pollDelay;
if (double.TryParse(timerValue, NumberStyles.Any, CultureInfo.InvariantCulture, out var timerDouble)) if (double.TryParse(timerValue, NumberStyles.Any, CultureInfo.InvariantCulture, out var timerDouble))
{ {
if (timerDouble < 2.0) if (timerDouble < 1.5)
{ {
pollDelay = 30; // ⚡ ULTRA-CRITICO: polling ogni 20ms
pollDelay = 20;
} }
else if (timerDouble < 3.0) else if (timerDouble < 2.5)
{
// ⚡ CRITICO: polling ogni 40ms
pollDelay = 40;
}
else if (timerDouble < 3.5)
{
pollDelay = 80;
}
else if (timerDouble < 5.0)
{
pollDelay = 150;
}
else if (timerDouble < 8.0)
{
pollDelay = 250;
}
else
{
pollDelay = 400;
}
}
else
{ {
pollDelay = 100; pollDelay = 100;
} }
else if (timerDouble < 4.0)
{
pollDelay = 150;
}
else if (timerDouble < 6.0)
{
pollDelay = 200;
}
else
{
pollDelay = 300;
}
}
else
{
pollDelay = 150;
}
await Task.Delay(pollDelay, token); await Task.Delay(pollDelay, token);
} }
@@ -943,11 +989,17 @@ namespace AutoBidder
private async Task<bool> PerformOptimizedClick(int delayMs, bool multiClickEnabled, CancellationToken token) private async Task<bool> PerformOptimizedClick(int delayMs, bool multiClickEnabled, CancellationToken token)
{ {
// Script click ultra-veloce e affidabile // Script click ULTRA-VELOCE con cache del bottone
const string optimizedClickScript = @" const string optimizedClickScript = @"
(function(){ (function(){
try { try {
var btn = document.querySelector('a.auction-btn-bid:not([disabled]), .auction-btn-bid:not([disabled])'); // ⚡ Cache del bottone per velocità
var btn = window._cachedBidBtn;
var now = Date.now();
// ⚡ Riusa cache se recente (< 500ms)
if (!btn || !document.contains(btn) || (window._cachedBidBtnTime && now - window._cachedBidBtnTime > 500)) {
btn = document.querySelector('a.auction-btn-bid:not([disabled]), .auction-btn-bid:not([disabled])');
if(!btn) { if(!btn) {
var btns = document.querySelectorAll('a, button'); var btns = document.querySelectorAll('a, button');
@@ -958,23 +1010,17 @@ namespace AutoBidder
} }
} }
window._cachedBidBtn = btn;
window._cachedBidBtnTime = now;
}
if(!btn) return JSON.stringify({success: false}); if(!btn) return JSON.stringify({success: false});
// Click tripli rapidi per massima affidabilità // Click diretto SENZA focus (più veloce)
btn.focus();
btn.click();
btn.click();
btn.click(); btn.click();
// Mouse event per compatibilità // ⚡ Secondo click immediato per affidabilità
var r = btn.getBoundingClientRect(); btn.click();
var evt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
clientX: r.left + r.width/2,
clientY: r.top + r.height/2
});
btn.dispatchEvent(evt);
return JSON.stringify({success: true}); return JSON.stringify({success: true});
@@ -985,19 +1031,19 @@ namespace AutoBidder
try try
{ {
// Applica delay se configurato // ⚡ OTTIMIZZAZIONE: Delay solo se > 50ms (sotto è irrilevante)
if (delayMs > 0) if (delayMs > 50)
{ {
await Task.Delay(delayMs, token); await Task.Delay(delayMs, token);
} }
// Esegui click // Esegui click con timeout ULTRA-CORTO (500ms invece di 2s)
string? clickResult = null; string? clickResult = null;
try try
{ {
var clickOp = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(optimizedClickScript)); var clickOp = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(optimizedClickScript));
var clickTask = await clickOp.Task.ConfigureAwait(false); var clickTask = await clickOp.Task.ConfigureAwait(false);
clickResult = await clickTask.WaitAsync(TimeSpan.FromSeconds(2), token).ConfigureAwait(false); clickResult = await clickTask.WaitAsync(TimeSpan.FromMilliseconds(500), token).ConfigureAwait(false);
} }
catch (TimeoutException) catch (TimeoutException)
{ {
@@ -1011,15 +1057,16 @@ namespace AutoBidder
if (string.IsNullOrEmpty(clickResult)) if (string.IsNullOrEmpty(clickResult))
return false; return false;
if (!string.IsNullOrEmpty(clickResult) && clickResult.Length >= 2 && clickResult[0] == '"' && clickResult[^1] == '"' ) // ⚡ Parsing veloce
if (clickResult.Length >= 2 && clickResult[0] == '"' && clickResult[^1] == '"')
{ {
try { clickResult = JsonSerializer.Deserialize<string>(clickResult); } catch { } try { clickResult = JsonSerializer.Deserialize<string>(clickResult); } catch { }
} }
JsonDocument? clickDoc = null; // ⚡ Verifica successo rapida
try try
{ {
clickDoc = JsonDocument.Parse(clickResult); using var clickDoc = JsonDocument.Parse(clickResult);
var success = clickDoc.RootElement.GetProperty("success").GetBoolean(); var success = clickDoc.RootElement.GetProperty("success").GetBoolean();
if (!success) if (!success)
@@ -1029,29 +1076,21 @@ namespace AutoBidder
{ {
return false; return false;
} }
finally
{
clickDoc?.Dispose();
}
// Multi-click se abilitato // Multi-click PARALLELO (non sequenziale) per velocità
if (multiClickEnabled) if (multiClickEnabled)
{ {
for (int i = 0; i < 2; i++) _ = Task.Run(async () =>
{ {
await Task.Delay(30, token); // Delay ridotto per multi-click await Task.Delay(20, token);
try try
{ {
var multiOp = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(optimizedClickScript)); var multiOp = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(optimizedClickScript));
var multiTask = await multiOp.Task.ConfigureAwait(false); var multiTask = await multiOp.Task.ConfigureAwait(false);
await multiTask.WaitAsync(TimeSpan.FromSeconds(1), token).ConfigureAwait(false); await multiTask.WaitAsync(TimeSpan.FromMilliseconds(300), token).ConfigureAwait(false);
}
catch
{
break;
}
} }
catch { }
}, token);
} }
return true; return true;