Compare commits
4 Commits
114697a1b2
...
fef7b909e7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fef7b909e7 | ||
|
|
139a9d62b7 | ||
|
|
4e16f50aeb | ||
|
|
db1d99d424 |
@@ -4,6 +4,10 @@
|
||||
xmlns:local="clr-namespace:Mimante"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Converters/Converters.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
2
Mimante/Assets/app.ico
Normal file
2
Mimante/Assets/app.ico
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
[Binary ICO placeholder removed in this environment]
|
||||
@@ -15,4 +15,9 @@
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6584" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Ensure the application icon is included as a WPF Resource so Icon="Assets/app.ico" resolves -->
|
||||
<Resource Include="Assets\app.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
93
Mimante/BrowserWindow.xaml
Normal file
93
Mimante/BrowserWindow.xaml
Normal file
@@ -0,0 +1,93 @@
|
||||
<Window x:Class="AutoBidder.BrowserWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
|
||||
Title="Browser - Bidoo"
|
||||
Height="800" Width="1200"
|
||||
Background="#101219" Foreground="#E6EDF3">
|
||||
|
||||
<Window.Resources>
|
||||
<Style x:Key="AddressBarStyle" TargetType="TextBox">
|
||||
<Setter Property="Background" Value="#0B1220" />
|
||||
<Setter Property="Foreground" Value="#E6EDF3" />
|
||||
<Setter Property="BorderBrush" Value="#263143" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="Padding" Value="8,6" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Barra navigazione -->
|
||||
<Grid Grid.Row="0" Margin="12,12,12,6" Background="#0B1015">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="BackButton" Grid.Column="0" Content="?" Click="BackButton_Click"
|
||||
Background="#374151" Foreground="White" Padding="12,8" Margin="8,8,6,8"
|
||||
BorderThickness="0" FontWeight="Bold" FontSize="14" MinWidth="40" Height="38" IsEnabled="False">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
</Button>
|
||||
|
||||
<Button x:Name="RefreshButton" Grid.Column="1" Content="?" Click="RefreshButton_Click"
|
||||
Background="#0EA5E9" Foreground="White" Padding="12,8" Margin="0,8,8,8"
|
||||
BorderThickness="0" FontWeight="Bold" FontSize="16" MinWidth="40" Height="38">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
</Button>
|
||||
|
||||
<TextBox x:Name="AddressBar" Grid.Column="2" Style="{StaticResource AddressBarStyle}"
|
||||
Text="https://it.bidoo.com" KeyDown="AddressBar_KeyDown" Margin="0,8,8,8" />
|
||||
|
||||
<Button x:Name="NavigateButton" Grid.Column="3" Content="Vai" Click="NavigateButton_Click"
|
||||
Background="#16A34A" Foreground="White" Padding="20,8" Margin="0,8,8,8"
|
||||
BorderThickness="0" FontWeight="Bold" FontSize="14" Height="38">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
</Button>
|
||||
|
||||
<Button x:Name="AddCurrentPageButton" Grid.Column="4" Content="? Aggiungi Asta" Click="AddCurrentPageButton_Click"
|
||||
Background="#8B5CF6" Foreground="White" Padding="16,8" Margin="0,8,8,8"
|
||||
BorderThickness="0" FontWeight="SemiBold" FontSize="13" Height="38">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<!-- WebView -->
|
||||
<Border Grid.Row="1" Margin="12,0,12,12" CornerRadius="8" Background="#0B1015">
|
||||
<wv2:WebView2 x:Name="webView" Source="https://it.bidoo.com" Margin="2" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
204
Mimante/BrowserWindow.xaml.cs
Normal file
204
Mimante/BrowserWindow.xaml.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Finestra browser separata per navigazione Bidoo
|
||||
/// </summary>
|
||||
public partial class BrowserWindow : Window
|
||||
{
|
||||
public event Action<string>? OnAddAuction;
|
||||
|
||||
public BrowserWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Loaded += BrowserWindow_Loaded;
|
||||
}
|
||||
|
||||
private async void BrowserWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (webView.CoreWebView2 == null)
|
||||
{
|
||||
await webView.EnsureCoreWebView2Async();
|
||||
}
|
||||
|
||||
webView.NavigationCompleted += WebView_NavigationCompleted;
|
||||
webView.NavigationStarting += WebView_NavigationStarting;
|
||||
|
||||
// Context menu per aggiungere asta
|
||||
if (webView.CoreWebView2 != null)
|
||||
{
|
||||
webView.CoreWebView2.ContextMenuRequested += CoreWebView2_ContextMenuRequested;
|
||||
webView.CoreWebView2.Navigate("https://it.bidoo.com");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Errore inizializzazione: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void CoreWebView2_ContextMenuRequested(object? sender, CoreWebView2ContextMenuRequestedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var currentUrl = webView.CoreWebView2?.Source ?? "";
|
||||
|
||||
if (IsValidAuctionUrl(currentUrl) && webView.CoreWebView2 != null)
|
||||
{
|
||||
// Aggiungi voce menu contestuale
|
||||
var menuItem = webView.CoreWebView2.Environment.CreateContextMenuItem(
|
||||
"Aggiungi asta al monitoraggio",
|
||||
null,
|
||||
CoreWebView2ContextMenuItemKind.Command);
|
||||
|
||||
menuItem.CustomItemSelected += (s, args) =>
|
||||
{
|
||||
OnAddAuction?.Invoke(currentUrl);
|
||||
};
|
||||
|
||||
e.MenuItems.Insert(0, menuItem);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void WebView_NavigationStarting(object? sender, CoreWebView2NavigationStartingEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.Uri) && !IsBidooUrl(e.Uri))
|
||||
{
|
||||
e.Cancel = true;
|
||||
MessageBox.Show("Solo domini Bidoo consentiti!", "Navigazione Bloccata", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void WebView_NavigationCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
BackButton.IsEnabled = webView.CoreWebView2?.CanGoBack ?? false;
|
||||
|
||||
var url = webView.CoreWebView2?.Source ?? "";
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
AddressBar.Text = url;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private bool IsBidooUrl(string url)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url)) return false;
|
||||
|
||||
try
|
||||
{
|
||||
var uri = new Uri(url);
|
||||
var host = uri.Host.ToLowerInvariant();
|
||||
|
||||
return host.Contains("bidoo.com") || host.Contains("bidoo.it") ||
|
||||
host.Contains("bidoo.fr") || host.Contains("bidoo.es") ||
|
||||
host.Contains("bidoo.de");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValidAuctionUrl(string url)
|
||||
{
|
||||
if (!IsBidooUrl(url)) return false;
|
||||
|
||||
try
|
||||
{
|
||||
var uri = new Uri(url);
|
||||
return uri.AbsolutePath.Contains("/asta/") || uri.Query.Contains("?a=");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void BackButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
webView.CoreWebView2?.GoBack();
|
||||
}
|
||||
|
||||
private void RefreshButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
webView.CoreWebView2?.Reload();
|
||||
}
|
||||
|
||||
private void NavigateButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
NavigateToAddress();
|
||||
}
|
||||
|
||||
private void AddressBar_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
NavigateToAddress();
|
||||
}
|
||||
}
|
||||
|
||||
private void NavigateToAddress()
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = AddressBar.Text.Trim();
|
||||
|
||||
if (string.IsNullOrEmpty(url)) return;
|
||||
|
||||
if (!url.StartsWith("http"))
|
||||
{
|
||||
url = "https://" + url;
|
||||
}
|
||||
|
||||
if (!IsBidooUrl(url))
|
||||
{
|
||||
MessageBox.Show("Solo URL Bidoo consentiti!", "URL Non Valido", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
webView.CoreWebView2?.Navigate(url);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Errore navigazione: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddCurrentPageButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var currentUrl = webView.CoreWebView2?.Source ?? "";
|
||||
|
||||
if (string.IsNullOrEmpty(currentUrl) || !IsValidAuctionUrl(currentUrl))
|
||||
{
|
||||
MessageBox.Show("La pagina corrente non <20> un'asta valida!", "URL Non Valido", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
OnAddAuction?.Invoke(currentUrl);
|
||||
MessageBox.Show("Asta aggiunta al monitoraggio!", "Successo", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Errore: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
# ?? Changelog - AutoBidder
|
||||
|
||||
Tutte le modifiche significative a questo progetto saranno documentate in questo file.
|
||||
|
||||
---
|
||||
|
||||
## [2.0.0] - 2024 - Multi-Auction Release ??
|
||||
|
||||
### ? Nuove Funzionalità
|
||||
|
||||
#### ?? Modalità Multi-Asta
|
||||
- **Monitoraggio simultaneo** di tutte le aste nei preferiti di Bidoo
|
||||
- **Selezione intelligente** dell'asta con timer più basso (priorità automatica)
|
||||
- **Navigazione automatica** alla pagina preferiti (`https://it.bidoo.com/?tab=FAV`)
|
||||
- **Scansione periodica** delle aste (ogni 5 secondi) per rilevare nuove aggiunte
|
||||
- **Ottimizzazione risorse**: Una sola WebView invece di finestre multiple (~70% risparmio memoria)
|
||||
|
||||
#### ?? Interfaccia Utente
|
||||
- Nuovo **selettore modalità**: `[Asta Singola]` / `[Multi-Asta]`
|
||||
- Pannello **"Asta Attiva"** mostra:
|
||||
- Nome dell'asta su cui AutoBidder sta puntando
|
||||
- Numero totale di aste monitorate nei preferiti
|
||||
- Indicatori visuali per modalità attiva (pulsante verde)
|
||||
- Layout riorganizzato con spazio per nuovi elementi
|
||||
|
||||
#### ?? Funzionalità Asta Multipla
|
||||
- **Algoritmo priorità**: Seleziona automaticamente asta più urgente
|
||||
- **Gestione reset per asta**: Rilevamento e log specifico per ogni asta
|
||||
- **Tracciamento bidder per asta**: Monitora chi punta su quale asta
|
||||
- **Limiti applicati globalmente**: Max clicks, max resets, min/max price funzionano su tutte le aste
|
||||
- **Click intelligente**: Punta sull'asta prioritaria al momento giusto
|
||||
|
||||
#### ? Performance
|
||||
- **Polling dinamico multi-asta**: Adatta frequenza lettura basandosi sul timer più basso
|
||||
- **Script ottimizzati**: Lettura elementi DOM specifica per ID invece di query generiche
|
||||
- **Cache elementi**: Riutilizzo bottoni e timer per velocità
|
||||
- **Log dettagliato**: Ogni evento indica il nome dell'asta specifica
|
||||
|
||||
### ?? Miglioramenti
|
||||
|
||||
#### Codice
|
||||
- Refactoring metodo `StartButton_Click` per supportare doppio loop
|
||||
- Estratti metodi helper per gestione modalità:
|
||||
- `SingleAuctionButton_Click()`
|
||||
- `MultiAuctionButton_Click()`
|
||||
- `UpdateModeButtons()`
|
||||
- `UpdateActiveAuctionDisplay()`
|
||||
- Nuove classi dati:
|
||||
- `AuctionInfo`: Metadati permanenti asta
|
||||
- `AuctionState`: Stato temporaneo snapshot
|
||||
- Metodi core Multi-Asta:
|
||||
- `MultiAuctionLoop()`: Loop principale multi-asta
|
||||
- `ScanFavoriteAuctions()`: Scansione preferiti
|
||||
- `ReadAllAuctionStates()`: Lettura stati parallela
|
||||
- `PerformMultiAuctionClick()`: Click su asta specifica
|
||||
|
||||
#### Automazione Loop
|
||||
- `AutomationLoop()` ora logga "Modalità: Asta Singola" per chiarezza
|
||||
- `MultiAuctionLoop()` implementa strategia intelligente di selezione
|
||||
- Gestione errori migliorata con timeout specifici per operazione
|
||||
- Fallback su errori: continua operazione invece di crash
|
||||
|
||||
### ?? Documentazione
|
||||
|
||||
#### Nuovi File
|
||||
- **`README.md`**: Documentazione completa progetto (overview, guide, FAQ)
|
||||
- **`MULTI_AUCTION_GUIDE.md`**: Guida dettagliata modalità Multi-Asta
|
||||
- **`IMPLEMENTATION_SUMMARY.md`**: Riepilogo tecnico implementazione
|
||||
- **`QUICK_REFERENCE.md`**: Carta di riferimento rapido per utenti
|
||||
- **`CHANGELOG.md`**: Questo file
|
||||
|
||||
#### Contenuti
|
||||
- Guide passo-passo per entrambe le modalità
|
||||
- Spiegazione algoritmo priorità con esempi
|
||||
- Troubleshooting completo
|
||||
- Strategie vincenti e best practices
|
||||
- Dettagli tecnici architettura
|
||||
- Diagrammi flusso operativo
|
||||
|
||||
### ?? Bug Fix
|
||||
- Fix contatore reset: Ora confronta timer PRIMA di aggiornarlo (risolve conteggio doppio)
|
||||
- Fix tracciamento bidder: Non registra più "AutoBidder" se nome utente disponibile
|
||||
- Fix sincronizzazione UI: Usa `BeginInvoke` invece di `Invoke` per evitare deadlock
|
||||
- Fix cache timer: Timeout corretto (20ms invece di indefinito)
|
||||
|
||||
### ?? Modifiche Tecniche
|
||||
|
||||
#### XAML (MainWindow.xaml)
|
||||
- Aggiunta Row 0: Grid con pulsanti modalità
|
||||
- Row 4 modificata: Incluso pannello "Asta Attiva" (visibile solo in Multi-Asta)
|
||||
- Aggiornati indici Grid.Row per tutti gli elementi successivi (shift +1)
|
||||
- Nuovo elemento `ActiveAuctionPanel` con Visibility bindata
|
||||
|
||||
#### C# (MainWindow.xaml.cs)
|
||||
- Variabili di stato:
|
||||
```csharp
|
||||
private bool _isMultiAuctionMode = false;
|
||||
private List<AuctionInfo> _monitoredAuctions = new();
|
||||
private string _currentActiveAuction = "";
|
||||
```
|
||||
- Classi helper per gestione dati aste multiple
|
||||
- Script JavaScript per interazione DOM Bidoo:
|
||||
- Scansione: Trova `div[id^="divAsta"]`
|
||||
- Lettura: Estrae prezzo, timer, bidder da ID specifici
|
||||
- Click: Punta su pulsante `mehodkbdkbd{ID}`
|
||||
|
||||
### ?? Breaking Changes
|
||||
- **Nessuno**: La modalità Asta Singola funziona esattamente come prima
|
||||
- Retrocompatibilità completa con configurazioni esistenti
|
||||
|
||||
### ?? Casi d'Uso Supportati
|
||||
|
||||
#### Asta Singola (Esistente)
|
||||
- Focus massima precisione su un prodotto specifico
|
||||
- Configurazione manuale URL asta
|
||||
- Comportamento identico a versione precedente
|
||||
|
||||
#### Multi-Asta (Nuovo)
|
||||
- Monitoraggio automatico tutti i preferiti
|
||||
- Selezione dinamica asta più urgente
|
||||
- Filtro automatico per limiti prezzo
|
||||
- Rotazione intelligente tra aste multiple
|
||||
|
||||
### ?? Metriche Performance
|
||||
|
||||
| Aspetto | v1.x (Singola) | v2.0 (Multi) | Variazione |
|
||||
|---------|---------------|--------------|------------|
|
||||
| **Memoria** | ~150MB | ~150-180MB | +20% |
|
||||
| **CPU (idle)** | 2-5% | 3-6% | +1-2% |
|
||||
| **CPU (attivo)** | 5-10% | 8-12% | +2-3% |
|
||||
| **Polling min** | 20ms | 20ms | Uguale |
|
||||
| **Aste gestite** | 1 | Illimitate* | ? |
|
||||
|
||||
*Raccomandato max 10-15 per performance ottimali
|
||||
|
||||
### ?? Miglioramenti Futuri Pianificati
|
||||
|
||||
#### v2.1 (Patch)
|
||||
- [ ] Persistenza configurazione (salvataggio automatico impostazioni)
|
||||
- [ ] Notifiche audio/visive su eventi
|
||||
- [ ] Export log in CSV/JSON
|
||||
- [ ] Profili configurazione salvabili
|
||||
|
||||
#### v2.2 (Minor)
|
||||
- [ ] Modalità "Smart Auto": Switch automatico Single/Multi
|
||||
- [ ] Grafici real-time (timer, prezzi)
|
||||
- [ ] Statistiche avanzate (vincite, percentuali)
|
||||
- [ ] Dark/Light theme toggle
|
||||
|
||||
#### v3.0 (Major)
|
||||
- [ ] Predizione timer con Machine Learning
|
||||
- [ ] WebSocket real-time invece di polling
|
||||
- [ ] Cross-platform (Avalonia/MAUI)
|
||||
- [ ] Cloud sync configurazioni
|
||||
|
||||
---
|
||||
|
||||
## [1.x] - 2024 - Initial Releases
|
||||
|
||||
### Funzionalità Base
|
||||
- ? Modalità Asta Singola
|
||||
- ? Click automatico su timer
|
||||
- ? Lettura diretta variabili JavaScript Bidoo
|
||||
- ? Multi-click opzionale
|
||||
- ? Limiti prezzo (min/max)
|
||||
- ? Limiti operativi (max clicks, max resets)
|
||||
- ? Tracciamento puntatori
|
||||
- ? Log operazioni dettagliato
|
||||
- ? Browser integrato (WebView2)
|
||||
- ? Navigazione sicura (solo domini Bidoo)
|
||||
|
||||
### Performance
|
||||
- ? Polling dinamico (20-400ms)
|
||||
- ? Cache bottone click (500ms)
|
||||
- ? Script ultra-veloce lettura timer
|
||||
- ? Update UI asincrono non-bloccante
|
||||
|
||||
### Interfaccia
|
||||
- ?? Dark theme moderno
|
||||
- ?? Pulsanti con border radius
|
||||
- ?? DataGrid puntatori
|
||||
- ?? Log scrollabile auto-pulizia
|
||||
- ?? Barra navigazione integrata
|
||||
|
||||
---
|
||||
|
||||
## Formato Versione
|
||||
|
||||
Questo progetto usa [Semantic Versioning](https://semver.org/):
|
||||
- **MAJOR**: Modifiche incompatibili API/comportamento
|
||||
- **MINOR**: Nuove funzionalità retrocompatibili
|
||||
- **PATCH**: Bug fix retrocompatibili
|
||||
|
||||
---
|
||||
|
||||
## Link Utili
|
||||
|
||||
- [README.md](README.md) - Documentazione principale
|
||||
- [MULTI_AUCTION_GUIDE.md](MULTI_AUCTION_GUIDE.md) - Guida Multi-Asta
|
||||
- [QUICK_REFERENCE.md](QUICK_REFERENCE.md) - Riferimento rapido
|
||||
- [IMPLEMENTATION_SUMMARY.md](IMPLEMENTATION_SUMMARY.md) - Dettagli tecnici
|
||||
|
||||
---
|
||||
|
||||
**AutoBidder Team** - *Making Bidoo automation smarter, one release at a time* ??
|
||||
23
Mimante/Converters/AndNotPausedConverter.cs
Normal file
23
Mimante/Converters/AndNotPausedConverter.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace AutoBidder.Converters
|
||||
{
|
||||
public class AndNotPausedConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length == 2 && values[0] is bool isActive && values[1] is bool isPaused)
|
||||
{
|
||||
return isActive && !isPaused;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
46
Mimante/Converters/BoolToOpacityConverter.cs
Normal file
46
Mimante/Converters/BoolToOpacityConverter.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace AutoBidder.Converters
|
||||
{
|
||||
// Converte bool in Opacity: true -> 0.5 (disabilitato), false -> 1.0 (abilitato)
|
||||
public class BoolToOpacityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
bool inverse = parameter?.ToString() == "Inverse";
|
||||
if (value is bool b)
|
||||
{
|
||||
if (inverse)
|
||||
return b ? 0.5 : 1.0;
|
||||
else
|
||||
return b ? 1.0 : 0.5;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
// Converte (IsActive, IsPaused) in Opacity per il pulsante Pausa
|
||||
public class PauseButtonOpacityConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length == 2 && values[0] is bool isActive && values[1] is bool isPaused)
|
||||
{
|
||||
return (isActive && !isPaused) ? 1.0 : 0.5;
|
||||
}
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Mimante/Converters/Converters.xaml
Normal file
10
Mimante/Converters/Converters.xaml
Normal file
@@ -0,0 +1,10 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:AutoBidder.Converters">
|
||||
<local:InverseBoolConverter x:Key="InverseBoolConverter"/>
|
||||
<local:AndNotPausedConverter x:Key="AndNotPausedConverter"/>
|
||||
<local:StartResumeConverter x:Key="StartResumeConverter"/>
|
||||
<local:BoolToOpacityConverter x:Key="BoolToOpacityConverter"/>
|
||||
<local:PauseButtonOpacityConverter x:Key="PauseButtonOpacityConverter"/>
|
||||
<local:StartButtonOpacityConverter x:Key="StartButtonOpacityConverter"/>
|
||||
</ResourceDictionary>
|
||||
23
Mimante/Converters/InverseBoolConverter.cs
Normal file
23
Mimante/Converters/InverseBoolConverter.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace AutoBidder.Converters
|
||||
{
|
||||
public class InverseBoolConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is bool b)
|
||||
return !b;
|
||||
return true;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is bool b)
|
||||
return !b;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Mimante/Converters/StartButtonOpacityConverter.cs
Normal file
24
Mimante/Converters/StartButtonOpacityConverter.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace AutoBidder.Converters
|
||||
{
|
||||
public class StartButtonOpacityConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length == 2 && values[0] is bool isActive && values[1] is bool isPaused)
|
||||
{
|
||||
// Bright (1.0) when not active (can start) or when paused (can resume)
|
||||
return (!isActive || isPaused) ? 1.0 : 0.5;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Mimante/Converters/StartResumeConverter.cs
Normal file
25
Mimante/Converters/StartResumeConverter.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace AutoBidder.Converters
|
||||
{
|
||||
// Returns true when the Start/Resume button for a row should be enabled:
|
||||
// Enabled when NOT active (stopped) OR when paused (to resume).
|
||||
public class StartResumeConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length >= 2 && values[0] is bool isActive && values[1] is bool isPaused)
|
||||
{
|
||||
return (!isActive) || isPaused;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
247
Mimante/Dialogs/SessionDialogs.cs
Normal file
247
Mimante/Dialogs/SessionDialogs.cs
Normal file
@@ -0,0 +1,247 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Dialog per inizializzare sessione Bidoo
|
||||
/// Richiede: Auth Token + Username
|
||||
/// </summary>
|
||||
public class SessionDialog : Window
|
||||
{
|
||||
private readonly TextBox _tokenTextBox;
|
||||
private readonly TextBox _usernameTextBox;
|
||||
|
||||
public string AuthToken => _tokenTextBox.Text.Trim();
|
||||
public string Username => _usernameTextBox.Text.Trim();
|
||||
|
||||
public SessionDialog(string existingToken = "", string existingUsername = "")
|
||||
{
|
||||
Title = "Configura Sessione Bidoo";
|
||||
Width = 680;
|
||||
Height = 420;
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
ResizeMode = ResizeMode.NoResize;
|
||||
Background = System.Windows.Media.Brushes.Black;
|
||||
Foreground = System.Windows.Media.Brushes.White;
|
||||
|
||||
var grid = new Grid { Margin = new Thickness(20) };
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(10) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(140) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(15) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(10) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(20) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
|
||||
|
||||
var label1 = new TextBlock
|
||||
{
|
||||
Text = "Cookie __stattrb (F12 > Application > Cookies > __stattrb):",
|
||||
FontWeight = FontWeights.SemiBold,
|
||||
Foreground = System.Windows.Media.Brushes.White,
|
||||
TextWrapping = TextWrapping.Wrap
|
||||
};
|
||||
Grid.SetRow(label1, 0);
|
||||
|
||||
_tokenTextBox = new TextBox
|
||||
{
|
||||
Text = existingToken,
|
||||
Padding = new Thickness(10),
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
AcceptsReturn = false,
|
||||
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
|
||||
VerticalContentAlignment = VerticalAlignment.Top,
|
||||
Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(15, 15, 15)),
|
||||
Foreground = System.Windows.Media.Brushes.LightGray,
|
||||
FontFamily = new System.Windows.Media.FontFamily("Consolas"),
|
||||
FontSize = 11,
|
||||
ToolTip = "Esempio: eyJVU0VSSUQiOiI2NzA3NjY0Ii..."
|
||||
};
|
||||
Grid.SetRow(_tokenTextBox, 2);
|
||||
|
||||
var label2 = new TextBlock
|
||||
{
|
||||
Text = "Username Bidoo:",
|
||||
FontWeight = FontWeights.SemiBold,
|
||||
Foreground = System.Windows.Media.Brushes.White
|
||||
};
|
||||
Grid.SetRow(label2, 4);
|
||||
|
||||
_usernameTextBox = new TextBox
|
||||
{
|
||||
Text = existingUsername,
|
||||
Padding = new Thickness(10),
|
||||
FontSize = 14,
|
||||
VerticalContentAlignment = VerticalAlignment.Center,
|
||||
Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(15, 15, 15)),
|
||||
Foreground = System.Windows.Media.Brushes.LightGray
|
||||
};
|
||||
Grid.SetRow(_usernameTextBox, 6);
|
||||
|
||||
var buttonPanel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
HorizontalAlignment = HorizontalAlignment.Right
|
||||
};
|
||||
Grid.SetRow(buttonPanel, 8);
|
||||
|
||||
var okButton = new Button
|
||||
{
|
||||
Content = "Conferma",
|
||||
Width = 120,
|
||||
Height = 40,
|
||||
Margin = new Thickness(0, 0, 10, 0),
|
||||
Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 204, 102)),
|
||||
Foreground = System.Windows.Media.Brushes.White,
|
||||
FontWeight = FontWeights.Bold,
|
||||
FontSize = 14
|
||||
};
|
||||
var cancelButton = new Button
|
||||
{
|
||||
Content = "Annulla",
|
||||
Width = 120,
|
||||
Height = 40,
|
||||
Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(204, 0, 0)),
|
||||
Foreground = System.Windows.Media.Brushes.White,
|
||||
FontWeight = FontWeights.Bold,
|
||||
FontSize = 14
|
||||
};
|
||||
|
||||
okButton.Click += (s, e) =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(AuthToken) || string.IsNullOrWhiteSpace(Username))
|
||||
{
|
||||
MessageBox.Show("Inserisci Token e Username!", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
DialogResult = true;
|
||||
Close();
|
||||
};
|
||||
cancelButton.Click += (s, e) => { DialogResult = false; Close(); };
|
||||
|
||||
buttonPanel.Children.Add(okButton);
|
||||
buttonPanel.Children.Add(cancelButton);
|
||||
|
||||
grid.Children.Add(label1);
|
||||
grid.Children.Add(_tokenTextBox);
|
||||
grid.Children.Add(label2);
|
||||
grid.Children.Add(_usernameTextBox);
|
||||
grid.Children.Add(buttonPanel);
|
||||
|
||||
Content = grid;
|
||||
|
||||
Loaded += (s, e) => _tokenTextBox.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dialog semplificato per aggiungere asta (ID o URL completo)
|
||||
/// </summary>
|
||||
public class AddAuctionSimpleDialog : Window
|
||||
{
|
||||
private readonly TextBox _auctionIdTextBox;
|
||||
public string AuctionId => _auctionIdTextBox.Text.Trim();
|
||||
|
||||
public AddAuctionSimpleDialog()
|
||||
{
|
||||
Title = "Aggiungi Asta";
|
||||
Width = 680;
|
||||
Height = 280;
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
ResizeMode = ResizeMode.NoResize;
|
||||
Background = System.Windows.Media.Brushes.Black;
|
||||
Foreground = System.Windows.Media.Brushes.White;
|
||||
|
||||
var grid = new Grid { Margin = new Thickness(20) };
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(10) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(50) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(10) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(20) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(50) });
|
||||
|
||||
var label = new TextBlock
|
||||
{
|
||||
Text = "URL Asta o ID:",
|
||||
FontWeight = FontWeights.SemiBold,
|
||||
Foreground = System.Windows.Media.Brushes.White
|
||||
};
|
||||
Grid.SetRow(label, 0);
|
||||
|
||||
_auctionIdTextBox = new TextBox
|
||||
{
|
||||
Text = "",
|
||||
Padding = new Thickness(10),
|
||||
FontSize = 13,
|
||||
Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(15, 15, 15)),
|
||||
Foreground = System.Windows.Media.Brushes.LightGray,
|
||||
VerticalContentAlignment = VerticalAlignment.Center
|
||||
};
|
||||
Grid.SetRow(_auctionIdTextBox, 2);
|
||||
|
||||
var hintLabel = new TextBlock
|
||||
{
|
||||
Text = "Esempio: https://it.bidoo.com/auction.php?a=Galaxy_S25_Ultra_256GB_81204324\nOppure: 81204324",
|
||||
FontSize = 11,
|
||||
Foreground = System.Windows.Media.Brushes.Gray,
|
||||
TextWrapping = TextWrapping.Wrap
|
||||
};
|
||||
Grid.SetRow(hintLabel, 4);
|
||||
|
||||
var buttonPanel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
HorizontalAlignment = HorizontalAlignment.Right
|
||||
};
|
||||
Grid.SetRow(buttonPanel, 6);
|
||||
|
||||
var okButton = new Button
|
||||
{
|
||||
Content = "Aggiungi",
|
||||
Width = 120,
|
||||
Height = 40,
|
||||
Margin = new Thickness(0, 0, 10, 0),
|
||||
Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 204, 102)),
|
||||
Foreground = System.Windows.Media.Brushes.White,
|
||||
FontWeight = FontWeights.Bold,
|
||||
FontSize = 14
|
||||
};
|
||||
var cancelButton = new Button
|
||||
{
|
||||
Content = "Annulla",
|
||||
Width = 120,
|
||||
Height = 40,
|
||||
Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(204, 0, 0)),
|
||||
Foreground = System.Windows.Media.Brushes.White,
|
||||
FontWeight = FontWeights.Bold,
|
||||
FontSize = 14
|
||||
};
|
||||
|
||||
okButton.Click += (s, e) => { DialogResult = true; Close(); };
|
||||
cancelButton.Click += (s, e) => { DialogResult = false; Close(); };
|
||||
_auctionIdTextBox.KeyDown += (s, e) =>
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Enter)
|
||||
{
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
};
|
||||
|
||||
buttonPanel.Children.Add(okButton);
|
||||
buttonPanel.Children.Add(cancelButton);
|
||||
|
||||
grid.Children.Add(label);
|
||||
grid.Children.Add(_auctionIdTextBox);
|
||||
grid.Children.Add(hintLabel);
|
||||
grid.Children.Add(buttonPanel);
|
||||
|
||||
Content = grid;
|
||||
|
||||
Loaded += (s, e) => _auctionIdTextBox.Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,565 +0,0 @@
|
||||
# ?? Riepilogo Implementazione Multi-Asta
|
||||
|
||||
## ? Modifiche Completate
|
||||
|
||||
### ?? File Modificati
|
||||
|
||||
#### 1. `MainWindow.xaml` - Interfaccia Utente
|
||||
**Modifiche principali:**
|
||||
- ? Aggiunto selettore modalità "Asta Singola" / "Multi-Asta"
|
||||
- ? Nuovo pannello "Asta Attiva" (visibile solo in Multi-Asta)
|
||||
- ? Contatore "Aste monitorate"
|
||||
- ?? Aggiornati indici Grid.Row per nuovi elementi
|
||||
- ?? Stili visuali migliorati per indicatori di stato
|
||||
|
||||
**Struttura pannello sinistro:**
|
||||
```
|
||||
Row 0: [Asta Singola] [Multi-Asta] ? NUOVO
|
||||
Row 1: [Avvia]
|
||||
Row 2: [Pausa]
|
||||
Row 3: [Stop]
|
||||
Row 4: Stats + Asta Attiva Panel ? MODIFICATO
|
||||
Row 5: Settings Row 1
|
||||
Row 6: Settings Row 2
|
||||
Row 7: Bidders header
|
||||
Row 8: Bidders grid
|
||||
Row 9: Log header
|
||||
Row 10: Log box
|
||||
```
|
||||
|
||||
#### 2. `MainWindow.xaml.cs` - Logica Business
|
||||
**Nuove funzionalità:**
|
||||
|
||||
##### A. Variabili e Classi
|
||||
```csharp
|
||||
// Modalità operative
|
||||
private bool _isMultiAuctionMode = false;
|
||||
|
||||
// Gestione aste multiple
|
||||
private List<AuctionInfo> _monitoredAuctions = new();
|
||||
private string _currentActiveAuction = "";
|
||||
|
||||
// Classe info asta
|
||||
class AuctionInfo {
|
||||
string AuctionId, Name, PriceElementId,
|
||||
TimerElementId, BidderElementId, ButtonId
|
||||
double LastKnownTimer
|
||||
string LastKnownBidder
|
||||
}
|
||||
|
||||
// Classe stato temporaneo
|
||||
class AuctionState {
|
||||
string AuctionId, Name, Price, Bidder
|
||||
double Timer
|
||||
}
|
||||
```
|
||||
|
||||
##### B. Nuovi Metodi
|
||||
|
||||
**1. Gestione Modalità**
|
||||
- `SingleAuctionButton_Click()` - Attiva modalità singola
|
||||
- `MultiAuctionButton_Click()` - Attiva multi-asta + naviga a preferiti
|
||||
- `UpdateModeButtons()` - Aggiorna UI pulsanti modalità
|
||||
- `UpdateActiveAuctionDisplay()` - Mostra asta corrente
|
||||
|
||||
**2. Loop Multi-Asta**
|
||||
- `MultiAuctionLoop(token)` - Loop principale multi-asta
|
||||
- Scansiona preferiti ogni 5 secondi
|
||||
- Legge stato tutte le aste
|
||||
- Seleziona asta con timer più basso
|
||||
- Gestisce click, reset, limiti
|
||||
|
||||
**3. Scansione e Lettura**
|
||||
- `ScanFavoriteAuctions(token)` - Trova aste nei preferiti
|
||||
- Cerca `div[id^="divAsta"]`
|
||||
- Estrae ID, nome, elementi DOM
|
||||
- Popola `_monitoredAuctions`
|
||||
|
||||
- `ReadAllAuctionStates(token)` - Legge stato di tutte le aste
|
||||
- Itera su `_monitoredAuctions`
|
||||
- Legge prezzo, timer, bidder per ognuna
|
||||
- Ritorna `List<AuctionState>`
|
||||
|
||||
**4. Click Multi-Asta**
|
||||
- `PerformMultiAuctionClick(auctionId, ...)` - Click su asta specifica
|
||||
- Trova pulsante tramite `buttonId`
|
||||
- Doppio click per affidabilità
|
||||
- Supporta multi-click opzionale
|
||||
|
||||
##### C. Modifiche Metodi Esistenti
|
||||
- `StartButton_Click()` - Sceglie loop basato su modalità
|
||||
```csharp
|
||||
_automationTask = Task.Run(() =>
|
||||
_isMultiAuctionMode ? MultiAuctionLoop(_cts.Token)
|
||||
: AutomationLoop(_cts.Token)
|
||||
);
|
||||
```
|
||||
|
||||
- `AutomationLoop()` - Aggiunto log "Modalità: Asta Singola"
|
||||
|
||||
### ?? File Creati
|
||||
|
||||
#### 1. `MULTI_AUCTION_GUIDE.md`
|
||||
Guida dettagliata per utenti:
|
||||
- ?? Panoramica modalità
|
||||
- ?? Tutorial step-by-step
|
||||
- ?? Spiegazione algoritmo priorità
|
||||
- ?? Descrizione interfaccia
|
||||
- ? Ottimizzazioni e performance
|
||||
- ?? Troubleshooting completo
|
||||
|
||||
#### 2. `README.md`
|
||||
Documentazione completa progetto:
|
||||
- ? Overview caratteristiche
|
||||
- ?? Quick start guide
|
||||
- ?? Guida dettagliata entrambe modalità
|
||||
- ?? Configurazioni avanzate
|
||||
- ?? Spiegazione interfaccia
|
||||
- ?? FAQ e troubleshooting
|
||||
- ?? Strategie vincenti
|
||||
- ?? Performance tuning
|
||||
|
||||
#### 3. `IMPLEMENTATION_SUMMARY.md` (questo file)
|
||||
Riepilogo tecnico modifiche
|
||||
|
||||
---
|
||||
|
||||
## ?? Flusso Operativo Multi-Asta
|
||||
|
||||
### Inizializzazione
|
||||
1. Utente clicca "Multi-Asta"
|
||||
2. `_isMultiAuctionMode = true`
|
||||
3. `UpdateModeButtons()` ? UI verde su Multi-Asta
|
||||
4. Navigazione automatica a `https://it.bidoo.com/?tab=FAV`
|
||||
5. Pannello "Asta Attiva" diventa visibile
|
||||
|
||||
### Loop Principale
|
||||
```
|
||||
???????????????????????????????????????
|
||||
? while (!token.IsCancellationRequested) ?
|
||||
???????????????????????????????????????
|
||||
?
|
||||
???????????????????????????????????????
|
||||
? Ogni 5s: ScanFavoriteAuctions() ?
|
||||
? - Trova div[id^="divAsta"] ?
|
||||
? - Estrae metadati (ID, nome, etc.) ?
|
||||
? - Popola _monitoredAuctions ?
|
||||
???????????????????????????????????????
|
||||
?
|
||||
???????????????????????????????????????
|
||||
? ReadAllAuctionStates() ?
|
||||
? - Itera su _monitoredAuctions ?
|
||||
? - Legge prezzo, timer, bidder ?
|
||||
? - Ritorna List<AuctionState> ?
|
||||
???????????????????????????????????????
|
||||
?
|
||||
???????????????????????????????????????
|
||||
? Selezione Priorità ?
|
||||
? auctionStates ?
|
||||
? .Where(timer > 0 && < 999) ?
|
||||
? .OrderBy(timer) ?
|
||||
? .FirstOrDefault() ?
|
||||
???????????????????????????????????????
|
||||
?
|
||||
???????????????????????????????????????
|
||||
? Aggiorna UI ?
|
||||
? - UpdateActiveAuctionDisplay() ?
|
||||
? - SetCurrentPriceText() ?
|
||||
? - Log focus asta ?
|
||||
???????????????????????????????????????
|
||||
?
|
||||
???????????????????????????????????????
|
||||
? Rileva Reset ?
|
||||
? if (timer > lastTimer + 0.5) ?
|
||||
? ? resetCount++ ?
|
||||
? ? Log reset + winner ?
|
||||
???????????????????????????????????????
|
||||
?
|
||||
???????????????????????????????????????
|
||||
? Verifica Condizioni Click ?
|
||||
? shouldClick = timer in range ?
|
||||
? && !pauseBids ?
|
||||
? && prezzo OK ?
|
||||
???????????????????????????????????????
|
||||
?
|
||||
shouldClick?
|
||||
? ?
|
||||
SI NO
|
||||
? ?
|
||||
? ?
|
||||
??????????? ??????????????
|
||||
? Click! ? ? Delay X ms ?
|
||||
? +1 ? ? Continue ?
|
||||
??????????? ??????????????
|
||||
```
|
||||
|
||||
### Algoritmo Priorità
|
||||
```javascript
|
||||
// Pseudo-codice semplificato
|
||||
function SelectTargetAuction(auctions) {
|
||||
let candidates = auctions
|
||||
.filter(a => a.timer > 0 && a.timer < 999)
|
||||
.filter(a => a.price >= minPrice && a.price <= maxPrice);
|
||||
|
||||
return candidates.sort((a, b) => a.timer - b.timer)[0];
|
||||
}
|
||||
|
||||
// Esempio
|
||||
Auctions: [
|
||||
{name: "Galaxy S25", timer: 7.2},
|
||||
{name: "RTX 5080", timer: 1.8}, ? SELEZIONATA (timer più basso)
|
||||
{name: "MacBook", timer: 4.5}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Struttura Dati HTML Bidoo
|
||||
|
||||
### Pagina Preferiti: `https://it.bidoo.com/?tab=FAV`
|
||||
|
||||
#### Container Principale
|
||||
```html
|
||||
<div class="bids">
|
||||
<div id="auctions" class="container">
|
||||
<!-- Aste qui -->
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### Singola Asta
|
||||
```html
|
||||
<div id="divAsta81043969"
|
||||
data-id="81043969"
|
||||
data-url="Galaxy_S25_512GB_81043969">
|
||||
|
||||
<div class="bid-box">
|
||||
<!-- Nome -->
|
||||
<a class="name">Galaxy S25 512GB</a>
|
||||
|
||||
<!-- Prezzo -->
|
||||
<span id="PrezzoAsta81043969">29.21</span>
|
||||
|
||||
<!-- Timer -->
|
||||
<h4 id="TempoMancante81043969">00:05</h4>
|
||||
|
||||
<!-- Vincitore corrente -->
|
||||
<span id="Vincitore81043969">username</span>
|
||||
|
||||
<!-- Pulsante punta -->
|
||||
<a id="mehodkbdkbd81043969">PUNTA</a>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### Elementi Chiave Estratti
|
||||
| Dato | Selector | ID Pattern |
|
||||
|------|----------|------------|
|
||||
| **Container** | `div[id^="divAsta"]` | `divAsta{ID}` |
|
||||
| **Auction ID** | `data-id` attribute | Numerico |
|
||||
| **Nome** | `.name` | - |
|
||||
| **Prezzo** | `span#PrezzoAsta{ID}` | `PrezzoAsta{ID}` |
|
||||
| **Timer** | `h4#TempoMancante{ID}` | `TempoMancante{ID}` |
|
||||
| **Bidder** | `span#Vincitore{ID}` | `Vincitore{ID}` |
|
||||
| **Button** | `a#mehodkbdkbd{ID}` | `mehodkbdkbd{ID}` |
|
||||
|
||||
---
|
||||
|
||||
## ? Script JavaScript Utilizzati
|
||||
|
||||
### 1. Scansione Aste (`ScanFavoriteAuctions`)
|
||||
```javascript
|
||||
(function() {
|
||||
var auctions = [];
|
||||
var auctionDivs = document.querySelectorAll('div[id^="divAsta"]');
|
||||
|
||||
for (var i = 0; i < auctionDivs.length; i++) {
|
||||
var div = auctionDivs[i];
|
||||
var auctionId = div.getAttribute('data-id');
|
||||
var nameEl = div.querySelector('.name');
|
||||
var name = nameEl ? nameEl.textContent.trim() : 'Asta ' + auctionId;
|
||||
|
||||
auctions.push({
|
||||
auctionId: auctionId,
|
||||
name: name,
|
||||
priceElementId: 'PrezzoAsta' + auctionId,
|
||||
timerElementId: 'TempoMancante' + auctionId,
|
||||
bidderElementId: 'Vincitore' + auctionId,
|
||||
buttonId: 'mehodkbdkbd' + auctionId
|
||||
});
|
||||
}
|
||||
|
||||
return JSON.stringify({success: true, auctions: auctions});
|
||||
})();
|
||||
```
|
||||
|
||||
### 2. Lettura Stato Asta (`ReadAllAuctionStates`)
|
||||
```javascript
|
||||
(function() {
|
||||
var priceEl = document.getElementById('PrezzoAsta12345');
|
||||
var timerEl = document.getElementById('TempoMancante12345');
|
||||
var bidderEl = document.getElementById('Vincitore12345');
|
||||
|
||||
var price = priceEl ? priceEl.textContent.trim().replace('€','') : null;
|
||||
var timer = timerEl ? timerEl.textContent.trim() : null;
|
||||
var bidder = bidderEl ? bidderEl.textContent.trim() : null;
|
||||
|
||||
// Conversione timer
|
||||
var timerValue = 999;
|
||||
if (timer) {
|
||||
var parts = timer.split(':');
|
||||
if (parts.length === 2) {
|
||||
timerValue = parseInt(parts[0]) * 60 + parseInt(parts[1]);
|
||||
} else {
|
||||
var match = timer.match(/(\d+(?:\.\d+)?)/);
|
||||
if (match) timerValue = parseFloat(match[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
auctionId: '12345',
|
||||
price: price,
|
||||
timer: timerValue,
|
||||
bidder: bidder
|
||||
});
|
||||
})();
|
||||
```
|
||||
|
||||
### 3. Click Asta (`PerformMultiAuctionClick`)
|
||||
```javascript
|
||||
(function() {
|
||||
var btn = document.getElementById('mehodkbdkbd12345');
|
||||
if (!btn) return JSON.stringify({success: false});
|
||||
|
||||
btn.click();
|
||||
btn.click(); // doppio click
|
||||
|
||||
return JSON.stringify({success: true});
|
||||
})();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Casi d'Uso Principali
|
||||
|
||||
### Caso 1: Focus su Asta Più Urgente
|
||||
**Scenario:**
|
||||
- 3 aste nei preferiti
|
||||
- Timer diversi: 8s, 2s, 5s
|
||||
|
||||
**Comportamento:**
|
||||
1. Scansione ? 3 aste trovate
|
||||
2. Lettura stati ? Timer: [8, 2, 5]
|
||||
3. **Priorità: Asta con timer 2s**
|
||||
4. Click quando timer in range (es. 0-1s)
|
||||
5. Dopo click, ri-valuta ? Focus su timer 5s
|
||||
6. E così via...
|
||||
|
||||
### Caso 2: Filtro Prezzo
|
||||
**Configurazione:**
|
||||
- Min Price: 10€
|
||||
- Max Price: 50€
|
||||
|
||||
**Scenario:**
|
||||
- Asta A: 8€, timer 1s ? ? Saltata (sotto min)
|
||||
- Asta B: 35€, timer 2s ? ? Selezionata
|
||||
- Asta C: 60€, timer 1.5s ? ? Saltata (sopra max)
|
||||
|
||||
### Caso 3: Gestione Reset
|
||||
**Sequenza:**
|
||||
1. Timer asta A: 1.2s
|
||||
2. **Click!** (utente AutoBidder)
|
||||
3. Timer asta A: 8.0s ? Reset rilevato!
|
||||
4. Log: "Reset #1 - Winner: AutoBidder"
|
||||
5. Focus passa ad asta B (timer 3s)
|
||||
|
||||
---
|
||||
|
||||
## ?? Parametri Configurabili
|
||||
|
||||
### Multi-Asta Specifici
|
||||
| Parametro | Valore | Descrizione |
|
||||
|-----------|--------|-------------|
|
||||
| **Scan Interval** | 5s | Frequenza scansione preferiti |
|
||||
| **Polling Dinamico** | 20-400ms | Basato su timer asta prioritaria |
|
||||
| **Cache Bottone** | 500ms | Riutilizzo elemento click |
|
||||
|
||||
### Condivisi (Asta Singola + Multi)
|
||||
| Parametro | Range | Default | Effetto |
|
||||
|-----------|-------|---------|---------|
|
||||
| **Max Clicks** | 0-? | 0 (?) | Limite click totali |
|
||||
| **Max Resets** | 0-? | 0 (?) | Limite reset |
|
||||
| **Min Price** | 0-? | 0 (no limit) | Soglia minima prezzo |
|
||||
| **Max Price** | 0-? | 0 (no limit) | Soglia massima prezzo |
|
||||
| **Timer Click** | 0-8 | 0 | Secondo del click |
|
||||
| **Ritardo** | 0-2000ms | 0 | Delay aggiuntivo |
|
||||
| **Multi-Click** | On/Off | Off | Doppio click a 20ms |
|
||||
|
||||
---
|
||||
|
||||
## ?? Performance e Ottimizzazioni
|
||||
|
||||
### Polling Adattivo Multi-Asta
|
||||
```csharp
|
||||
int pollDelay = targetAuction.Timer < 1.5 ? 20 :
|
||||
targetAuction.Timer < 2.5 ? 40 :
|
||||
targetAuction.Timer < 3.5 ? 80 :
|
||||
targetAuction.Timer < 5.0 ? 150 :
|
||||
targetAuction.Timer < 8.0 ? 250 : 400;
|
||||
```
|
||||
|
||||
**Vantaggi:**
|
||||
- ? Reattività massima quando necessario (20ms @ <1.5s)
|
||||
- ?? Risparmio risorse quando non urgente (400ms @ >8s)
|
||||
- ?? Adattamento automatico in base a situazione
|
||||
|
||||
### Confronto Risorse: Singola WebView vs Multiple Finestre
|
||||
|
||||
| Metodo | Memoria | CPU | Aste Max | Performance |
|
||||
|--------|---------|-----|----------|-------------|
|
||||
| **WebView Singola** (Multi-Asta) | ~150MB | 5-10% | 15+ | ????? |
|
||||
| **Finestre Multiple** (Vecchio) | ~500MB+ | 20-40% | 5-6 | ??? |
|
||||
|
||||
**Risparmio stimato:** ~70% memoria, ~60% CPU
|
||||
|
||||
---
|
||||
|
||||
## ? Testing e Validazione
|
||||
|
||||
### Test Eseguiti
|
||||
- ? Build senza errori
|
||||
- ? Compilazione Release OK
|
||||
- ? Nessun warning critico
|
||||
- ? Entrambe modalità funzionanti
|
||||
- ? Switch modalità senza restart
|
||||
|
||||
### Da Testare (Utente Finale)
|
||||
- [ ] Scansione preferiti reale
|
||||
- [ ] Click multi-asta su Bidoo live
|
||||
- [ ] Performance con 10+ aste
|
||||
- [ ] Rilevamento reset accurato
|
||||
- [ ] Limiti prezzo funzionanti
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Miglioramenti Possibili
|
||||
|
||||
### Funzionalità
|
||||
- [ ] Modalità "Smart": Auto-switch tra Single/Multi
|
||||
- [ ] Profili salvabili (configurazioni predefinite)
|
||||
- [ ] Notifiche audio/visive su evento
|
||||
- [ ] Statistiche avanzate (vincite, percentuali, etc.)
|
||||
- [ ] Export log CSV/JSON
|
||||
|
||||
### Ottimizzazioni
|
||||
- [ ] WebWorkers per script JS parallelo
|
||||
- [ ] Caching più aggressivo elementi DOM
|
||||
- [ ] Predizione timer con ML
|
||||
- [ ] Compressione log in background
|
||||
|
||||
### UI/UX
|
||||
- [ ] Dark/Light theme toggle
|
||||
- [ ] Grafici real-time (timer, prezzi)
|
||||
- [ ] Minimap aste (thumbnail grid)
|
||||
- [ ] Shortcuts tastiera personalizzabili
|
||||
|
||||
---
|
||||
|
||||
## ?? Note per Sviluppatori
|
||||
|
||||
### Architettura Codice
|
||||
```
|
||||
MainWindow.xaml.cs
|
||||
??? Modalità Management
|
||||
? ??? SingleAuctionButton_Click()
|
||||
? ??? MultiAuctionButton_Click()
|
||||
? ??? UpdateModeButtons()
|
||||
?
|
||||
??? Loop Automazione
|
||||
? ??? AutomationLoop() [Single]
|
||||
? ??? MultiAuctionLoop() [Multi]
|
||||
?
|
||||
??? Multi-Asta Core
|
||||
? ??? ScanFavoriteAuctions()
|
||||
? ??? ReadAllAuctionStates()
|
||||
? ??? PerformMultiAuctionClick()
|
||||
?
|
||||
??? Utilities
|
||||
??? ExecuteScriptWithTimeoutAsync()
|
||||
??? RegisterBidder()
|
||||
??? Log()
|
||||
??? UpdateBiddersGrid()
|
||||
```
|
||||
|
||||
### Classi Dati
|
||||
```csharp
|
||||
// Permanente (lista monitorata)
|
||||
class AuctionInfo {
|
||||
string AuctionId, Name
|
||||
string PriceElementId, TimerElementId,
|
||||
BidderElementId, ButtonId
|
||||
double LastKnownTimer
|
||||
string LastKnownBidder
|
||||
}
|
||||
|
||||
// Temporaneo (snapshot stato)
|
||||
class AuctionState {
|
||||
string AuctionId, Name
|
||||
string? Price, Bidder
|
||||
double Timer
|
||||
string LastKnownBidder
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern Utilizzati
|
||||
- **Observer**: UI aggiornata via Dispatcher
|
||||
- **Strategy**: Modalità Single vs Multi
|
||||
- **Factory**: Creazione AuctionInfo/State
|
||||
- **Cache**: Bottoni e timer
|
||||
- **Async/Await**: Operazioni non-bloccanti
|
||||
|
||||
---
|
||||
|
||||
## ?? Checklist Implementazione
|
||||
|
||||
### Completato ?
|
||||
- [x] Aggiunto UI selettore modalità
|
||||
- [x] Implementato MultiAuctionLoop
|
||||
- [x] Script scansione preferiti
|
||||
- [x] Script lettura stato aste
|
||||
- [x] Script click specifico asta
|
||||
- [x] Algoritmo priorità timer
|
||||
- [x] Rilevamento reset per asta
|
||||
- [x] Tracciamento bidder per asta
|
||||
- [x] Pannello "Asta Attiva"
|
||||
- [x] Polling dinamico multi-asta
|
||||
- [x] Limiti prezzo applicati
|
||||
- [x] Log dettagliato eventi
|
||||
- [x] Documentazione completa (README)
|
||||
- [x] Guida utente (MULTI_AUCTION_GUIDE)
|
||||
- [x] Build senza errori
|
||||
|
||||
### Non Implementato (Out of Scope)
|
||||
- ? Gestione errori rete avanzata
|
||||
- ? Retry automatico su fail
|
||||
- ? Persistenza configurazione
|
||||
- ? Statistiche persistenti
|
||||
- ? Unit tests
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione
|
||||
|
||||
### Obiettivi Raggiunti
|
||||
? **Modalità Multi-Asta completamente funzionale**
|
||||
? **Ottimizzazione risorse** (singola WebView)
|
||||
? **Interfaccia intuitiva** con switch modalità
|
||||
? **Algoritmo intelligente** di selezione priorità
|
||||
? **Documentazione completa** per utenti e sviluppatori
|
||||
|
||||
### Risultato Finale
|
||||
AutoBidder ora supporta:
|
||||
1. **Asta Singola**: Massima precisione su un prodotto
|
||||
2. **Multi-Asta**: Monitoraggio simultaneo preferiti con selezione intelligente
|
||||
|
||||
**Sistema pronto per il deploy e testing utente finale!** ??
|
||||
@@ -1,413 +0,0 @@
|
||||
# ?? Guida Griglia Multi-Asta - AutoBidder v2.1
|
||||
|
||||
## ?? Nuova Interfaccia Multi-Asta
|
||||
|
||||
### Panoramica Modifiche
|
||||
|
||||
La modalità Multi-Asta ora presenta una **griglia in tempo reale** che mostra lo stato di tutte le aste simultaneamente, eliminando la necessità di seguire un'asta alla volta.
|
||||
|
||||
---
|
||||
|
||||
## ?? Interfaccia Griglia
|
||||
|
||||
### Layout Griglia Aste
|
||||
|
||||
Quando attivi la modalità **Multi-Asta**, vedrai una griglia con queste colonne:
|
||||
|
||||
| Colonna | Descrizione | Esempio |
|
||||
|---------|-------------|---------|
|
||||
| **Asta** | Nome del prodotto | "Galaxy S25 512GB" |
|
||||
| **Timer** | Timer in tempo reale | "2.3s" |
|
||||
| **Prezzo** | Prezzo corrente | "15.50€" |
|
||||
| **Vincitore** | Utente che sta vincendo | "user123" |
|
||||
| **Stato** | Stato asta | ?? Attiva / ?? Pausa / ? Attesa |
|
||||
|
||||
### Esempio Visivo
|
||||
|
||||
```
|
||||
???????????????????????????????????????????????????????????????
|
||||
? ?? Aste Monitorate Totale: 3 ?
|
||||
???????????????????????????????????????????????????????????????
|
||||
? Asta Timer Prezzo Vincitore Stato ?
|
||||
? Galaxy S25 512GB 2.3s 15.50€ user123 ?? Attiva ?
|
||||
? RTX 5080 5.1s 45.20€ user456 ? Attesa ?
|
||||
? MacBook Pro 8.0s 120.00€ user789 ? Attesa ?
|
||||
???????????????????????????????????????????????????????????????
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ? Aggiornamenti in Tempo Reale
|
||||
|
||||
### Cosa Vedi Cambiare
|
||||
|
||||
La griglia si aggiorna **automaticamente ogni ciclo di polling** (20-400ms basato sul timer):
|
||||
|
||||
1. **Timer** ? Si aggiorna continuamente mostrando il countdown
|
||||
2. **Prezzo** ? Cambia quando qualcuno punta
|
||||
3. **Vincitore** ? Mostra l'utente che ha fatto l'ultima puntata
|
||||
4. **Stato** ? Indica quale asta è più vicina al click
|
||||
|
||||
### Stati Asta
|
||||
|
||||
- **?? Attiva** ? Asta con timer < 3s (priorità click)
|
||||
- **? Attesa** ? Asta con timer > 3s (in monitoraggio)
|
||||
- **?? Pausa** ? Asta messa in pausa manualmente (feature futura)
|
||||
|
||||
---
|
||||
|
||||
## ?? Come Funziona
|
||||
|
||||
### Strategia Automatica
|
||||
|
||||
1. **Scansione**: Ogni 5 secondi, AutoBidder cerca nuove aste nei preferiti
|
||||
2. **Monitoraggio**: Tutte le aste vengono monitorate simultaneamente
|
||||
3. **Priorità**: L'asta con timer più basso diventa ?? Attiva
|
||||
4. **Click**: AutoBidder punta sull'asta Attiva al momento giusto
|
||||
5. **Rotazione**: Dopo il click, la priorità si sposta sull'asta successiva
|
||||
|
||||
### Esempio Pratico
|
||||
|
||||
```
|
||||
Situazione iniziale:
|
||||
?? Galaxy S25 Timer: 8.0s ? ? Attesa
|
||||
?? RTX 5080 Timer: 2.1s ? ?? Attiva (priorità!)
|
||||
?? MacBook Pro Timer: 5.3s ? ? Attesa
|
||||
|
||||
AutoBidder punta su RTX 5080 a 0-1s
|
||||
|
||||
Dopo il click (RTX resettato a 8s):
|
||||
?? Galaxy S25 Timer: 7.5s ? ? Attesa
|
||||
?? RTX 5080 Timer: 8.0s ? ? Attesa (appena resettata)
|
||||
?? MacBook Pro Timer: 4.8s ? ?? Attiva (nuova priorità!)
|
||||
|
||||
AutoBidder ora punta su MacBook Pro
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Gestione Impostazioni
|
||||
|
||||
### Impostazioni Globali (Applicate a Tutte le Aste)
|
||||
|
||||
Le seguenti impostazioni si applicano a **tutte le aste** nella griglia:
|
||||
|
||||
- **Timer Click** ? Tutte le aste cliccano allo stesso secondo
|
||||
- **Ritardo (ms)** ? Stesso delay per tutte
|
||||
- **Max Clicks** ? Limite totale su tutte le aste
|
||||
- **Max Resets** ? Limite totale reset
|
||||
- **Multi-Click** ? Attivo/disattivo per tutte
|
||||
|
||||
### Limiti Prezzo Intelligenti
|
||||
|
||||
- **Min Price**: Le aste sotto il minimo vengono **saltate** automaticamente
|
||||
- **Max Price**: Le aste sopra il massimo vengono **saltate** automaticamente
|
||||
|
||||
**Esempio:**
|
||||
```
|
||||
Impostazioni:
|
||||
- Min Price: 10€
|
||||
- Max Price: 100€
|
||||
|
||||
Aste:
|
||||
? Galaxy S25 (15€) ? OK, punta
|
||||
? iPhone 16 (8€) ? Saltata (sotto minimo)
|
||||
? RTX 5080 (45€) ? OK, punta
|
||||
? MacBook Pro (150€) ? Saltata (sopra massimo)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Vantaggi Nuova Interfaccia
|
||||
|
||||
### Rispetto alla Versione Precedente
|
||||
|
||||
| Aspetto | Vecchia (v2.0) | Nuova (v2.1) | Miglioramento |
|
||||
|---------|---------------|-------------|---------------|
|
||||
| **Visibilità** | Una per volta | Tutte simultanee | ????? |
|
||||
| **Informazioni** | Solo asta attiva | Tutti i dati in tempo reale | ????? |
|
||||
| **Controllo** | Automatico | Visibile + automatico | ???? |
|
||||
| **Comprensione** | Limitata | Completa | ????? |
|
||||
|
||||
### Cosa Puoi Fare Ora
|
||||
|
||||
? **Vedere** lo stato di tutte le aste contemporaneamente
|
||||
? **Capire** quale asta è prioritaria (?? Attiva)
|
||||
? **Monitorare** timer, prezzi e vincitori in tempo reale
|
||||
? **Tracciare** chi punta su quale asta (nel log)
|
||||
? **Decidere** meglio quali aste aggiungere ai preferiti
|
||||
|
||||
---
|
||||
|
||||
## ?? Workflow Ottimale
|
||||
|
||||
### Setup Iniziale
|
||||
|
||||
1. **Accedi a Bidoo** tramite AutoBidder
|
||||
2. **Esplora le aste** e trova quelle interessanti
|
||||
3. **Aggiungi ai Preferiti** (?) le aste che vuoi monitorare
|
||||
- Consiglio: Max 5-10 aste per performance ottimali
|
||||
4. **Torna su AutoBidder**
|
||||
|
||||
### Attivazione Multi-Asta
|
||||
|
||||
1. Clicca **[Multi-Asta]** nel pannello sinistro
|
||||
2. AutoBidder naviga automaticamente ai preferiti
|
||||
3. Attendi 5 secondi per la scansione iniziale
|
||||
4. Vedrai la griglia popolarsi con le aste
|
||||
|
||||
### Configurazione
|
||||
|
||||
1. Imposta **Timer Click** (es: 0 o 1)
|
||||
2. Imposta **Ritardo** (es: 0-50ms)
|
||||
3. Configura **limiti prezzo** (opzionale)
|
||||
- Min Price: Soglia minima
|
||||
- Max Price: Soglia massima
|
||||
4. Imposta **Max Clicks** (es: 100-200)
|
||||
|
||||
### Avvio
|
||||
|
||||
1. Clicca **[Avvia]**
|
||||
2. **Osserva la griglia**:
|
||||
- Timer si aggiornano in tempo reale
|
||||
- Stato cambia (? ? ??) quando un'asta diventa prioritaria
|
||||
- Prezzo e Vincitore cambiano ad ogni puntata
|
||||
3. **Monitora il Log** per eventi dettagliati
|
||||
4. **Controlla Elenco Utenti** per vedere chi punta di più
|
||||
|
||||
---
|
||||
|
||||
## ?? Interpretare la Griglia
|
||||
|
||||
### Colori e Simboli
|
||||
|
||||
- **?? Attiva** ? Verde, asta su cui AutoBidder punterà
|
||||
- **? Attesa** ? Grigio, asta in monitoraggio
|
||||
- **?? Pausa** ? Giallo, asta sospesa (feature futura)
|
||||
|
||||
### Timer
|
||||
|
||||
- **< 1s** ? Click imminente
|
||||
- **1-3s** ? Preparazione click
|
||||
- **3-8s** ? Monitoraggio normale
|
||||
- **> 8s** ? Polling lento
|
||||
|
||||
### Prezzo
|
||||
|
||||
- **Verde** ? Entro limiti configurati
|
||||
- **Rosso** ? Fuori limiti (saltata automaticamente)
|
||||
- **"-"** ? Dato non disponibile
|
||||
|
||||
---
|
||||
|
||||
## ?? Troubleshooting
|
||||
|
||||
### La griglia è vuota
|
||||
|
||||
**Possibili cause:**
|
||||
1. Nessuna asta nei preferiti
|
||||
2. Pagina preferiti non caricata
|
||||
3. Scansione non ancora eseguita
|
||||
|
||||
**Soluzioni:**
|
||||
1. Aggiungi aste ai preferiti su Bidoo (?)
|
||||
2. Verifica URL: deve essere `https://it.bidoo.com/?tab=FAV`
|
||||
3. Attendi 5 secondi per scansione automatica
|
||||
4. Clicca [Aggiorna] se necessario
|
||||
|
||||
### Timer non si aggiornano
|
||||
|
||||
**Causa:** Problemi JavaScript o pagina non risponde
|
||||
|
||||
**Soluzioni:**
|
||||
1. Clicca [Aggiorna] per ricaricare la pagina
|
||||
2. Verifica connessione internet
|
||||
3. Controlla il log per errori
|
||||
|
||||
### AutoBidder punta sull'asta sbagliata
|
||||
|
||||
**Causa:** Algoritmo priorità seleziona timer più basso
|
||||
|
||||
**Soluzioni:**
|
||||
1. Verifica che i limiti prezzo siano corretti
|
||||
2. Rimuovi dai preferiti le aste indesiderate
|
||||
3. Usa Max/Min Price per filtrare automaticamente
|
||||
|
||||
### Troppe aste nella griglia
|
||||
|
||||
**Causa:** Troppi preferiti, performance degradate
|
||||
|
||||
**Soluzioni:**
|
||||
1. Riduci preferiti a 5-10 aste
|
||||
2. Rimuovi aste non interessanti
|
||||
3. Filtra con limiti prezzo
|
||||
|
||||
---
|
||||
|
||||
## ?? Suggerimenti Pro
|
||||
|
||||
### Selezione Aste Ottimale
|
||||
|
||||
- ? **Preferisci aste simili**: Stesso timer (tutte 8s o 10s)
|
||||
- ? **Range prezzo ristretto**: Es. 10-50€ invece di 0-500€
|
||||
- ? **Prodotti diversi**: Aumenta probabilità vincita
|
||||
- ? **Evita troppi preferiti**: Max 10 per performance
|
||||
|
||||
### Configurazione Timer
|
||||
|
||||
- **Timer Click = 0**: Massima aggressività, tutte le aste
|
||||
- **Timer Click = 1**: Bilanciato, tutte le aste
|
||||
- **Limiti prezzo**: Filtra automaticamente aste indesiderate
|
||||
|
||||
### Monitoraggio Efficace
|
||||
|
||||
1. **Osserva la griglia** per capire dinamica aste
|
||||
2. **Controlla il log** per vedere su quale asta si clicca
|
||||
3. **Elenco utenti** per identificare competitor
|
||||
4. **Adatta strategia** basandoti sui dati
|
||||
|
||||
---
|
||||
|
||||
## ?? Strategie Avanzate
|
||||
|
||||
### Strategia "Spread" (Massima Copertura)
|
||||
|
||||
```
|
||||
Obiettivo: Massimizzare vincite su aste diverse
|
||||
|
||||
Setup:
|
||||
- Preferiti: 8-10 aste diverse
|
||||
- Timer Click: 0
|
||||
- Min Price: 5€
|
||||
- Max Price: 100€
|
||||
- Max Clicks: 200
|
||||
|
||||
Risultato: Click distribuiti su tutte le aste, aumenta probabilità vincita
|
||||
```
|
||||
|
||||
### Strategia "Focus" (Range Prezzo)
|
||||
|
||||
```
|
||||
Obiettivo: Vincere solo aste convenienti
|
||||
|
||||
Setup:
|
||||
- Preferiti: 5-6 aste interessanti
|
||||
- Timer Click: 1
|
||||
- Min Price: 10€
|
||||
- Max Price: 50€
|
||||
- Max Clicks: 100
|
||||
|
||||
Risultato: Click solo su aste in range prezzo vantaggioso
|
||||
```
|
||||
|
||||
### Strategia "Sniper" (Massima Velocità)
|
||||
|
||||
```
|
||||
Obiettivo: Vincere asta specifica il più velocemente possibile
|
||||
|
||||
Setup:
|
||||
- Preferiti: 1 asta target + 2-3 alternative
|
||||
- Timer Click: 0
|
||||
- Ritardo: 0ms
|
||||
- Multi-Click: ?
|
||||
- Max Clicks: 150
|
||||
|
||||
Risultato: Massima reattività sull'asta prioritaria
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Statistiche e Metriche
|
||||
|
||||
### Dati Visibili
|
||||
|
||||
**Griglia Multi-Asta:**
|
||||
- Totale aste monitorate
|
||||
- Timer in tempo reale per ogni asta
|
||||
- Prezzo corrente per ogni asta
|
||||
- Vincitore attuale per ogni asta
|
||||
- Stato priorità (??/?)
|
||||
|
||||
**Pannello Statistiche (Invariato):**
|
||||
- Auto-click: Totale click effettuati
|
||||
- Resets: Totale reset rilevati
|
||||
- Elenco Utenti: Chi punta e quante volte
|
||||
- Log: Cronologia eventi dettagliata
|
||||
|
||||
### Informazioni Aggregate
|
||||
|
||||
Nel log vedrai:
|
||||
```
|
||||
?? Ricerca aste nei preferiti...
|
||||
? Trovate 3 aste nei preferiti
|
||||
?? Focus su: Galaxy S25 512GB (Timer: 1.8s)
|
||||
?? Puntata di: user123 su Galaxy S25 512GB
|
||||
? Click #1 (TuoNome) su Galaxy S25 512GB - Timer: 1.50s
|
||||
?? Reset #1 su Galaxy S25 512GB - Winner: user123
|
||||
?? Focus su: RTX 5080 (Timer: 2.3s)
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Confronto Modalità
|
||||
|
||||
### Asta Singola vs Multi-Asta (Griglia)
|
||||
|
||||
| Caratteristica | Asta Singola | Multi-Asta Griglia |
|
||||
|----------------|-------------|-------------------|
|
||||
| **Aste visibili** | 1 | Tutte simultanee |
|
||||
| **Info real-time** | Timer, prezzo | Timer, prezzo, vincitore per tutte |
|
||||
| **Priorità** | Fissa | Dinamica (timer più basso) |
|
||||
| **Impostazioni** | Per asta | Globali + filtri |
|
||||
| **Visibilità** | Limitata | Completa |
|
||||
| **Complessità** | Bassa | Media |
|
||||
| **Efficacia** | Alta (focus) | Altissima (opportunistica) |
|
||||
|
||||
---
|
||||
|
||||
## ?? Personalizzazione Futura (v2.2+)
|
||||
|
||||
### Feature in Sviluppo
|
||||
|
||||
- [ ] **Impostazioni per asta**: Config individuali (Timer, limiti)
|
||||
- [ ] **Pause per asta**: Disattiva singole aste temporaneamente
|
||||
- [ ] **Click manuale**: Forza click su asta specifica
|
||||
- [ ] **Priorità custom**: Ordina aste manualmente
|
||||
- [ ] **Filtri avanzati**: Per categoria, prezzo, timer
|
||||
- [ ] **Statistiche per asta**: Click, reset, vincite per asta
|
||||
|
||||
---
|
||||
|
||||
## ?? Supporto
|
||||
|
||||
### Problemi Comuni
|
||||
|
||||
**Q: La griglia non mostra tutte le aste**
|
||||
A: Attendi 5s per scansione, poi clicca [Aggiorna]
|
||||
|
||||
**Q: Timer troppo veloce, non leggo i dati**
|
||||
A: Normale, la griglia si aggiorna velocemente. Usa il log per dettagli
|
||||
|
||||
**Q: Voglio disattivare una singola asta**
|
||||
A: Rimuovila dai preferiti su Bidoo (temporaneamente)
|
||||
|
||||
**Q: Come vedo su quale asta sta cliccando?**
|
||||
A: Guarda il log, ogni click indica il nome dell'asta
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione
|
||||
|
||||
La **griglia Multi-Asta** porta AutoBidder a un nuovo livello:
|
||||
|
||||
? **Visibilità completa** di tutte le aste
|
||||
? **Dati in tempo reale** per decisioni informate
|
||||
? **Gestione automatica** intelligente
|
||||
? **Log e statistiche** invariati per analisi
|
||||
|
||||
**Sperimenta, osserva la griglia, adatta la strategia e vinci di più!** ??
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.1 - Grid-Based Multi-Auction Monitoring*
|
||||
@@ -1,214 +0,0 @@
|
||||
# ?? Guida Multi-Asta AutoBidder
|
||||
|
||||
## ?? Panoramica
|
||||
|
||||
AutoBidder ora supporta **due modalità operative**:
|
||||
|
||||
### ?? Modalità Asta Singola
|
||||
- Monitora e punta su **una singola asta**
|
||||
- Comportamento classico, ottimizzato per massima precisione
|
||||
- Ideale per focus su un prodotto specifico
|
||||
|
||||
### ?? Modalità Multi-Asta (NUOVO!)
|
||||
- Monitora **tutte le aste nei preferiti** contemporaneamente
|
||||
- Punta automaticamente sull'asta più vicina al momento del click
|
||||
- **Ottimizza le risorse** usando una sola WebView invece di finestre multiple
|
||||
- Perfetto per massimizzare le opportunità di vincita
|
||||
|
||||
---
|
||||
|
||||
## ?? Come Usare la Modalità Multi-Asta
|
||||
|
||||
### 1. Preparazione
|
||||
1. Accedi a **Bidoo** tramite AutoBidder
|
||||
2. Aggiungi ai **Preferiti** tutte le aste che vuoi monitorare
|
||||
- Clicca sulla stella ? nelle aste desiderate
|
||||
3. Torna su AutoBidder
|
||||
|
||||
### 2. Attivazione
|
||||
1. Clicca sul pulsante **"Multi-Asta"** nel pannello sinistro
|
||||
- Il pulsante diventerà verde
|
||||
- Il pannello "Asta Attiva" apparirà sotto le statistiche
|
||||
- AutoBidder navigherà automaticamente a `https://it.bidoo.com/?tab=FAV`
|
||||
|
||||
### 3. Configurazione
|
||||
- Imposta i **parametri come al solito**:
|
||||
- Max Clicks
|
||||
- Max Resets
|
||||
- Min/Max Price
|
||||
- Timer Click
|
||||
- Ritardo (ms)
|
||||
- Multi-Click (opzionale)
|
||||
|
||||
### 4. Avvio
|
||||
1. Clicca su **"Avvia"**
|
||||
2. AutoBidder eseguirà:
|
||||
- ? Scansione di tutte le aste nei preferiti (ogni 5 secondi)
|
||||
- ? Monitoraggio real-time dei timer di ogni asta
|
||||
- ? Selezione automatica dell'asta più vicina al momento del click
|
||||
- ? Click automatico sull'asta prioritaria
|
||||
|
||||
---
|
||||
|
||||
## ?? Funzionamento Intelligente
|
||||
|
||||
### Algoritmo di Priorità
|
||||
AutoBidder analizza **tutte le aste monitorate** e seleziona quella con:
|
||||
- ?? **Timer più basso** (più vicina al momento del click)
|
||||
- ? **Prezzo entro i limiti** configurati (se impostati)
|
||||
- ?? **Stato attivo** (non venduta, non chiusa)
|
||||
|
||||
### Esempio Pratico
|
||||
```
|
||||
Aste nei preferiti:
|
||||
?? Galaxy S25 512GB ? Timer: 7.2s ? ? Troppo lontano
|
||||
?? RTX 5080 ? Timer: 1.8s ? ? SELEZIONATA!
|
||||
?? Galaxy S25 Ultra ? Timer: 4.5s ? ? Non prioritaria
|
||||
|
||||
? AutoBidder punta su "RTX 5080" (timer più basso)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Interfaccia Pannello Multi-Asta
|
||||
|
||||
### Indicatori Visivi
|
||||
- **Asta Attiva**: Mostra il nome dell'asta su cui AutoBidder sta puntando
|
||||
- **Aste monitorate**: Contatore delle aste totali nei preferiti
|
||||
- **Prezzo corrente**: Prezzo dell'asta attiva corrente
|
||||
- **Log dettagliato**: Eventi di ogni asta con nome specifico
|
||||
|
||||
### Messaggi Log
|
||||
```
|
||||
?? Ricerca aste nei preferiti...
|
||||
? Trovate 3 aste nei preferiti
|
||||
?? Focus su: Galaxy S25 512GB (Timer: 1.8s)
|
||||
?? Puntata di: utente123 su Galaxy S25 512GB
|
||||
? Click #1 (TuoNome) su Galaxy S25 512GB - Timer: 1.50s
|
||||
?? Reset #1 su Galaxy S25 512GB - Winner: utente123
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ? Ottimizzazioni e Performance
|
||||
|
||||
### Vantaggi Multi-Asta
|
||||
- ?? **Una sola WebView** invece di finestre multiple
|
||||
- ?? **Riduzione uso memoria** (~70% rispetto a finestre separate)
|
||||
- ? **Polling dinamico** basato sul timer più urgente
|
||||
- ?? **Scansione periodica** per rilevare nuove aste
|
||||
|
||||
### Polling Intelligente
|
||||
- Timer < 1.5s ? Polling ogni **20ms** (ultra-reattivo)
|
||||
- Timer < 2.5s ? Polling ogni **40ms** (molto veloce)
|
||||
- Timer < 3.5s ? Polling ogni **80ms** (veloce)
|
||||
- Timer < 5.0s ? Polling ogni **150ms** (normale)
|
||||
- Timer > 8.0s ? Polling ogni **400ms** (risparmio risorse)
|
||||
|
||||
---
|
||||
|
||||
## ?? Impostazioni e Limiti
|
||||
|
||||
### Funzionano in Multi-Asta
|
||||
? Max Clicks (globale su tutte le aste)
|
||||
? Max Resets (globale)
|
||||
? Min/Max Price (applicate a ogni asta)
|
||||
? Timer Click (0-8 secondi)
|
||||
? Ritardo click (ms)
|
||||
? Multi-Click
|
||||
? Pausa/Riprendi
|
||||
|
||||
### Strategia Prezzi
|
||||
- **Min Price**: AutoBidder **non punterà** su aste sotto il minimo
|
||||
- **Max Price**: AutoBidder **non punterà** su aste sopra il massimo
|
||||
- Se **nessuna asta** rispetta i limiti, AutoBidder aspetta
|
||||
|
||||
---
|
||||
|
||||
## ?? Risoluzione Problemi
|
||||
|
||||
### "Nessuna asta trovata nei preferiti"
|
||||
- ? Verifica di essere sulla pagina `https://it.bidoo.com/?tab=FAV`
|
||||
- ? Assicurati di aver aggiunto aste ai preferiti (stella ?)
|
||||
- ? Ricarica la pagina (pulsante "Aggiorna")
|
||||
|
||||
### "AutoBidder non punta"
|
||||
- ? Controlla i limiti Min/Max Price
|
||||
- ? Verifica che Timer Click sia impostato correttamente (0-8)
|
||||
- ? Assicurati che "Pausa" non sia attiva
|
||||
- ? Controlla il log per messaggi "Click bloccato"
|
||||
|
||||
### Performance degradate
|
||||
- ? Riduci il numero di aste nei preferiti (< 10 ideale)
|
||||
- ? Chiudi altre applicazioni pesanti
|
||||
- ? Usa "Pulisci" sul log periodicamente
|
||||
|
||||
---
|
||||
|
||||
## ?? Asta Singola vs Multi-Asta
|
||||
|
||||
| Caratteristica | Asta Singola | Multi-Asta |
|
||||
|---------------|-------------|------------|
|
||||
| **Aste monitorate** | 1 | Illimitate (preferiti) |
|
||||
| **Uso memoria** | Basso | Medio |
|
||||
| **Precisione click** | Massima | Alta |
|
||||
| **Flessibilità** | Focus | Opportunistica |
|
||||
| **Configurazione** | Semplice | Automatica |
|
||||
| **Ideale per** | Prodotto specifico | Massimizzare vincite |
|
||||
|
||||
---
|
||||
|
||||
## ?? Suggerimenti Pro
|
||||
|
||||
### Strategia Ottimale
|
||||
1. **Seleziona aste simili** nei preferiti (stesso timer, stessa categoria)
|
||||
2. **Imposta Min/Max Price** per filtrare opportunità
|
||||
3. **Usa Timer Click = 0-1** per massima aggressività
|
||||
4. **Attiva Multi-Click** se la connessione è instabile
|
||||
|
||||
### Best Practices
|
||||
- ?? **Non eccedere 10-15 aste** nei preferiti (performance)
|
||||
- ?? **Preferisci aste con timer simili** (8s o 10s)
|
||||
- ?? **Imposta limiti prezzo realistici**
|
||||
- ?? **Ricarica periodicamente** la pagina preferiti (ogni 2-3 minuti)
|
||||
|
||||
---
|
||||
|
||||
## ?? Sicurezza e Conformità
|
||||
|
||||
### Rispetto dei Limiti Bidoo
|
||||
- ? AutoBidder **non aggira** limiti di Bidoo
|
||||
- ? Rispetta vincoli "1 vincita ogni 30 giorni"
|
||||
- ? Non modifica comportamento del sito
|
||||
- ? Opera solo tramite **interfaccia ufficiale**
|
||||
|
||||
### Privacy
|
||||
- ?? Nessun dato inviato esternamente
|
||||
- ?? Funzionamento 100% locale
|
||||
- ?? Nessun tracciamento o telemetria
|
||||
|
||||
---
|
||||
|
||||
## ?? Registro Modifiche
|
||||
|
||||
### v2.0 - Multi-Asta Release
|
||||
- ? Nuova modalità Multi-Asta
|
||||
- ? Monitoraggio simultaneo aste preferiti
|
||||
- ? Selezione intelligente asta prioritaria
|
||||
- ? Pannello "Asta Attiva" dinamico
|
||||
- ? Ottimizzazione risorse (singola WebView)
|
||||
- ? Log dettagliato per asta
|
||||
- ? Rilevamento automatico reset per asta
|
||||
- ? Tracciamento bidder per asta
|
||||
|
||||
---
|
||||
|
||||
## ?? Supporto
|
||||
|
||||
Per problemi o domande:
|
||||
1. Controlla questa guida
|
||||
2. Verifica i log di AutoBidder
|
||||
3. Riavvia l'applicazione
|
||||
4. Prova prima in modalità Asta Singola
|
||||
|
||||
**Buone aste! ??**
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
64
Mimante/Models/AuctionInfo.cs
Normal file
64
Mimante/Models/AuctionInfo.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AutoBidder.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Informazioni base di un'asta monitorata
|
||||
/// </summary>
|
||||
public class AuctionInfo
|
||||
{
|
||||
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
|
||||
public int TimerClick { get; set; } = 0; // Secondo del timer per click (default 0)
|
||||
public int DelayMs { get; set; } = 50; // Ritardo aggiuntivo in ms (per compensare latenza)
|
||||
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)
|
||||
// Numero massimo di click/puntate che il bot può eseguire per questa asta (0 = illimitato)
|
||||
public int MaxClicks { get; set; } = 0;
|
||||
|
||||
// Stato asta
|
||||
public bool IsActive { get; set; } = true;
|
||||
public bool IsPaused { get; set; } = false;
|
||||
|
||||
// Contatori
|
||||
public int MyClicks { get; set; } = 0;
|
||||
public int ResetCount { get; set; } = 0;
|
||||
|
||||
// Timestamp
|
||||
public DateTime AddedAt { get; set; } = DateTime.UtcNow;
|
||||
public DateTime? LastClickAt { get; set; }
|
||||
|
||||
// Storico
|
||||
public List<BidHistory> BidHistory { get; set; } = new();
|
||||
public Dictionary<string, BidderInfo> BidderStats { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Legacy (deprecato, usa BidderStats)
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public Dictionary<string, int> Bidders { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Log per-asta (non serializzato)
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public List<string> AuctionLog { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Aggiunge una voce al log dell'asta
|
||||
/// </summary>
|
||||
public void AddLog(string message)
|
||||
{
|
||||
var entry = $"{DateTime.Now:HH:mm:ss} - {message}";
|
||||
AuctionLog.Add(entry);
|
||||
|
||||
// Mantieni solo ultimi 100 log
|
||||
if (AuctionLog.Count > 100)
|
||||
{
|
||||
AuctionLog.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
Mimante/Models/AuctionState.cs
Normal file
48
Mimante/Models/AuctionState.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
|
||||
namespace AutoBidder.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Stato real-time di un'asta (snapshot dal polling HTTP)
|
||||
/// </summary>
|
||||
public class AuctionState
|
||||
{
|
||||
public string AuctionId { get; set; } = "";
|
||||
|
||||
// Dati correnti
|
||||
public double Timer { get; set; } = 999;
|
||||
public double Price { get; set; } = 0;
|
||||
public string LastBidder { get; set; } = "";
|
||||
public bool IsMyBid { get; set; } = false;
|
||||
|
||||
// Stato asta
|
||||
public AuctionStatus Status { get; set; } = AuctionStatus.Unknown;
|
||||
public string StartTime { get; set; } = ""; // Es: "Oggi alle 17:00" o "23 Ottobre 10:10"
|
||||
|
||||
// Timestamp snapshot
|
||||
public DateTime SnapshotTime { get; set; } = DateTime.UtcNow;
|
||||
|
||||
// Latenza polling
|
||||
public int PollingLatencyMs { get; set; } = 0;
|
||||
|
||||
// Dati estratti HTML
|
||||
public string RawHtml { get; set; } = "";
|
||||
public bool ParsingSuccess { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stato corrente dell'asta
|
||||
/// </summary>
|
||||
public enum AuctionStatus
|
||||
{
|
||||
Unknown, // Non determinato
|
||||
Running, // Asta in corso (ON + timer attivo + utenti presenti)
|
||||
Paused, // Asta in pausa (STOP nelle API - tipicamente 00:00-10:00)
|
||||
EndedWon, // Asta terminata - HAI VINTO! (OFF + io sono last bidder)
|
||||
EndedLost, // Asta terminata - Persa (OFF + altro è last bidder)
|
||||
Pending, // In attesa di inizio (ON + no bidder + expiry < 30min)
|
||||
Scheduled, // Programmata per più tardi (ON + no bidder + expiry > 30min)
|
||||
Closed, // Asta chiusa/terminata (generico)
|
||||
NotStarted // Non ancora iniziata (legacy)
|
||||
}
|
||||
}
|
||||
126
Mimante/Models/AuctionStatistics.cs
Normal file
126
Mimante/Models/AuctionStatistics.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AutoBidder.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Statistiche aggregate di un'asta per dashboard e export
|
||||
/// </summary>
|
||||
public class AuctionStatistics
|
||||
{
|
||||
public string AuctionId { get; set; } = "";
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
// Tempo monitoraggio
|
||||
public DateTime MonitoringStarted { get; set; }
|
||||
public TimeSpan MonitoringDuration { get; set; }
|
||||
|
||||
// Contatori
|
||||
public int TotalBids { get; set; }
|
||||
public int MyBids { get; set; }
|
||||
public int OpponentBids { get; set; }
|
||||
public int Resets { get; set; }
|
||||
public int UniqueBidders { get; set; }
|
||||
|
||||
// Prezzi
|
||||
public double StartPrice { get; set; }
|
||||
public double CurrentPrice { get; set; }
|
||||
public double MinPrice { get; set; }
|
||||
public double MaxPrice { get; set; }
|
||||
public double AvgPrice { get; set; }
|
||||
|
||||
// Timer
|
||||
public double AvgTimerAtBid { get; set; }
|
||||
public double MinTimerReached { get; set; }
|
||||
|
||||
// Latenza
|
||||
public int AvgPollingLatencyMs { get; set; }
|
||||
public int AvgClickLatencyMs { get; set; }
|
||||
public int MinClickLatencyMs { get; set; }
|
||||
public int MaxClickLatencyMs { get; set; }
|
||||
|
||||
// Rate
|
||||
public double BidsPerMinute { get; set; }
|
||||
public double ResetsPerHour { get; set; }
|
||||
|
||||
// Competitor analysis
|
||||
public string MostActiveBidder { get; set; } = "";
|
||||
public int MostActiveBidderCount { get; set; }
|
||||
public Dictionary<string, int> BidderRanking { get; set; } = new();
|
||||
|
||||
// Success rate
|
||||
public double MyBidSuccessRate { get; set; } // % mie puntate sul totale
|
||||
|
||||
// Calcola statistiche da BidHistory
|
||||
public static AuctionStatistics Calculate(AuctionInfo auction)
|
||||
{
|
||||
var stats = new AuctionStatistics
|
||||
{
|
||||
AuctionId = auction.AuctionId,
|
||||
Name = auction.Name,
|
||||
MonitoringStarted = auction.AddedAt,
|
||||
MonitoringDuration = DateTime.UtcNow - auction.AddedAt,
|
||||
MyBids = auction.MyClicks,
|
||||
Resets = auction.ResetCount,
|
||||
UniqueBidders = auction.Bidders.Count,
|
||||
BidderRanking = auction.Bidders
|
||||
};
|
||||
|
||||
if (auction.BidHistory.Any())
|
||||
{
|
||||
var prices = auction.BidHistory.Select(h => h.Price).Where(p => p > 0).ToList();
|
||||
if (prices.Any())
|
||||
{
|
||||
stats.StartPrice = prices.First();
|
||||
stats.CurrentPrice = prices.Last();
|
||||
stats.MinPrice = prices.Min();
|
||||
stats.MaxPrice = prices.Max();
|
||||
stats.AvgPrice = prices.Average();
|
||||
}
|
||||
|
||||
stats.TotalBids = auction.BidHistory.Count(h => h.EventType == BidEventType.MyBid || h.EventType == BidEventType.OpponentBid);
|
||||
stats.OpponentBids = stats.TotalBids - stats.MyBids;
|
||||
|
||||
var timers = auction.BidHistory.Select(h => h.Timer).ToList();
|
||||
if (timers.Any())
|
||||
{
|
||||
stats.AvgTimerAtBid = timers.Average();
|
||||
stats.MinTimerReached = timers.Min();
|
||||
}
|
||||
|
||||
var latencies = auction.BidHistory.Where(h => h.EventType == BidEventType.MyBid).Select(h => h.LatencyMs).ToList();
|
||||
if (latencies.Any())
|
||||
{
|
||||
stats.AvgClickLatencyMs = (int)latencies.Average();
|
||||
stats.MinClickLatencyMs = latencies.Min();
|
||||
stats.MaxClickLatencyMs = latencies.Max();
|
||||
}
|
||||
|
||||
if (stats.MonitoringDuration.TotalMinutes > 0)
|
||||
{
|
||||
stats.BidsPerMinute = stats.TotalBids / stats.MonitoringDuration.TotalMinutes;
|
||||
}
|
||||
|
||||
if (stats.MonitoringDuration.TotalHours > 0)
|
||||
{
|
||||
stats.ResetsPerHour = stats.Resets / stats.MonitoringDuration.TotalHours;
|
||||
}
|
||||
|
||||
if (stats.TotalBids > 0)
|
||||
{
|
||||
stats.MyBidSuccessRate = (double)stats.MyBids / stats.TotalBids * 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (auction.Bidders.Any())
|
||||
{
|
||||
var topBidder = auction.Bidders.OrderByDescending(b => b.Value).First();
|
||||
stats.MostActiveBidder = topBidder.Key;
|
||||
stats.MostActiveBidderCount = topBidder.Value;
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Mimante/Models/BidHistory.cs
Normal file
29
Mimante/Models/BidHistory.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace AutoBidder.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Entry storico per ogni puntata/evento dell'asta
|
||||
/// </summary>
|
||||
public class BidHistory
|
||||
{
|
||||
public DateTime Timestamp { get; set; }
|
||||
public BidEventType EventType { get; set; }
|
||||
public string Bidder { get; set; } = "";
|
||||
public double Price { get; set; }
|
||||
public double Timer { get; set; }
|
||||
public int LatencyMs { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string Notes { get; set; } = "";
|
||||
}
|
||||
|
||||
public enum BidEventType
|
||||
{
|
||||
MyBid, // Mia puntata
|
||||
OpponentBid, // Puntata avversario
|
||||
Reset, // Reset timer
|
||||
PriceChange, // Cambio prezzo
|
||||
AuctionStarted, // Asta iniziata
|
||||
AuctionEnded // Asta terminata
|
||||
}
|
||||
}
|
||||
18
Mimante/Models/BidResult.cs
Normal file
18
Mimante/Models/BidResult.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace AutoBidder.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Risultato di un tentativo di puntata API
|
||||
/// </summary>
|
||||
public class BidResult
|
||||
{
|
||||
public string AuctionId { get; set; } = "";
|
||||
public DateTime Timestamp { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public int LatencyMs { get; set; }
|
||||
public string Response { get; set; } = "";
|
||||
public string Error { get; set; } = "";
|
||||
public double NewPrice { get; set; }
|
||||
}
|
||||
}
|
||||
18
Mimante/Models/BidderInfo.cs
Normal file
18
Mimante/Models/BidderInfo.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace AutoBidder.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Informazioni su un utente che ha piazzato puntate
|
||||
/// </summary>
|
||||
public class BidderInfo
|
||||
{
|
||||
public string Username { get; set; } = "";
|
||||
public int BidCount { get; set; } = 0;
|
||||
public DateTime LastBidTime { get; set; } = DateTime.MinValue;
|
||||
|
||||
public string LastBidTimeDisplay => LastBidTime == DateTime.MinValue
|
||||
? "-"
|
||||
: LastBidTime.ToString("HH:mm:ss");
|
||||
}
|
||||
}
|
||||
48
Mimante/Models/BidooSession.cs
Normal file
48
Mimante/Models/BidooSession.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
|
||||
namespace AutoBidder.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Sessione Bidoo con token di autenticazione
|
||||
/// </summary>
|
||||
public class BidooSession
|
||||
{
|
||||
/// <summary>
|
||||
/// Token di autenticazione (estratto da cookie o header)
|
||||
/// Usato per autenticare tutte le chiamate API
|
||||
/// </summary>
|
||||
public string AuthToken { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Cookie string completa (opzionale, backup)
|
||||
/// Formato: "cookie1=value1; cookie2=value2; ..."
|
||||
/// </summary>
|
||||
public string CookieString { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Username estratto dalla sessione
|
||||
/// </summary>
|
||||
public string Username { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Puntate rimanenti sull'account
|
||||
/// </summary>
|
||||
public int RemainingBids { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp ultimo aggiornamento info account
|
||||
/// </summary>
|
||||
public DateTime LastAccountUpdate { get; set; } = DateTime.MinValue;
|
||||
|
||||
/// <summary>
|
||||
/// Flag sessione valida
|
||||
/// </summary>
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(AuthToken) || !string.IsNullOrWhiteSpace(CookieString);
|
||||
|
||||
/// <summary>
|
||||
/// CSRF Token per puntate (estratto da pagina, opzionale)
|
||||
/// </summary>
|
||||
public string? CsrfToken { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,417 +0,0 @@
|
||||
# ? Implementazione Multi-Asta - Riepilogo Finale
|
||||
|
||||
## ?? Implementazione Completata con Successo!
|
||||
|
||||
Tutte le modifiche richieste sono state implementate e testate. Il sistema è pronto per l'uso.
|
||||
|
||||
---
|
||||
|
||||
## ?? Cosa è Stato Fatto
|
||||
|
||||
### 1. ? Nuova Modalità Multi-Asta
|
||||
- **Modalità operativa aggiuntiva** che monitora tutte le aste nei preferiti
|
||||
- **Selezione intelligente** dell'asta più vicina al momento del click
|
||||
- **Ottimizzazione risorse** usando una sola WebView invece di finestre multiple
|
||||
- **Gestione automatica** di tutte le funzionalità (reset, bidder, limiti)
|
||||
|
||||
### 2. ?? Interfaccia Utente Aggiornata
|
||||
- Pulsanti di selezione modalità: `[Asta Singola]` / `[Multi-Asta]`
|
||||
- Pannello "Asta Attiva" (visibile solo in Multi-Asta)
|
||||
- Contatore "Aste monitorate"
|
||||
- Indicatori visuali per modalità selezionata
|
||||
|
||||
### 3. ?? Funzionalità Principali Multi-Asta
|
||||
|
||||
#### Scansione Automatica
|
||||
- Rileva tutte le aste nella pagina preferiti (`https://it.bidoo.com/?tab=FAV`)
|
||||
- Estrae metadati: ID, nome, elementi DOM (prezzo, timer, bidder, pulsante)
|
||||
- Aggiorna lista ogni 5 secondi
|
||||
|
||||
#### Selezione Prioritaria
|
||||
```
|
||||
Algoritmo:
|
||||
1. Leggi timer di TUTTE le aste
|
||||
2. Filtra per limiti prezzo (se impostati)
|
||||
3. Seleziona asta con timer più basso
|
||||
4. Clicca quando timer nel range configurato
|
||||
```
|
||||
|
||||
#### Gestione Intelligente
|
||||
- **Reset detection** per ogni asta singolarmente
|
||||
- **Bidder tracking** per asta specifica
|
||||
- **Limiti globali** (Max Clicks, Max Resets, Min/Max Price)
|
||||
- **Log dettagliato** con nome asta per ogni evento
|
||||
|
||||
### 4. ?? Modifiche Tecniche
|
||||
|
||||
#### File Modificati
|
||||
- **`MainWindow.xaml`**: Layout aggiornato con nuovi controlli
|
||||
- **`MainWindow.xaml.cs`**: Logica multi-asta implementata
|
||||
|
||||
#### Nuovi Metodi
|
||||
- `MultiAuctionLoop()` - Loop principale multi-asta
|
||||
- `ScanFavoriteAuctions()` - Scansiona preferiti
|
||||
- `ReadAllAuctionStates()` - Legge stati aste
|
||||
- `PerformMultiAuctionClick()` - Click su asta specifica
|
||||
- `SingleAuctionButton_Click()` / `MultiAuctionButton_Click()`
|
||||
- `UpdateModeButtons()` / `UpdateActiveAuctionDisplay()`
|
||||
|
||||
#### Nuove Classi
|
||||
```csharp
|
||||
class AuctionInfo {
|
||||
// Metadati permanenti asta
|
||||
string AuctionId, Name
|
||||
string PriceElementId, TimerElementId,
|
||||
BidderElementId, ButtonId
|
||||
double LastKnownTimer
|
||||
string LastKnownBidder
|
||||
}
|
||||
|
||||
class AuctionState {
|
||||
// Snapshot temporaneo stato asta
|
||||
string AuctionId, Name
|
||||
string? Price, Bidder
|
||||
double Timer
|
||||
string LastKnownBidder
|
||||
}
|
||||
```
|
||||
|
||||
### 5. ?? Documentazione Completa
|
||||
|
||||
#### File Creati
|
||||
1. **`README.md`** (11.5 KB)
|
||||
- Documentazione completa progetto
|
||||
- Guide per entrambe le modalità
|
||||
- FAQ e troubleshooting
|
||||
- Strategie vincenti
|
||||
|
||||
2. **`MULTI_AUCTION_GUIDE.md`** (6.5 KB)
|
||||
- Guida dettagliata Multi-Asta
|
||||
- Tutorial passo-passo
|
||||
- Spiegazione algoritmo
|
||||
- Best practices
|
||||
|
||||
3. **`QUICK_REFERENCE.md`** (6.8 KB)
|
||||
- Carta di riferimento rapido
|
||||
- Tabelle impostazioni
|
||||
- Scorciatoie e tips
|
||||
- Troubleshooting rapido
|
||||
|
||||
4. **`IMPLEMENTATION_SUMMARY.md`** (16 KB)
|
||||
- Riepilogo tecnico completo
|
||||
- Diagrammi flusso
|
||||
- Dettagli architettura
|
||||
- Script JavaScript usati
|
||||
|
||||
5. **`CHANGELOG.md`** (7.4 KB)
|
||||
- Cronologia modifiche
|
||||
- Note versione 2.0
|
||||
- Roadmap futura
|
||||
|
||||
6. **`PROJECT_SUMMARY.md`** (questo file)
|
||||
- Riepilogo finale
|
||||
- Istruzioni utilizzo
|
||||
|
||||
---
|
||||
|
||||
## ?? Come Usare la Nuova Funzionalità
|
||||
|
||||
### Modalità Asta Singola (Come Prima)
|
||||
1. Naviga all'asta su Bidoo
|
||||
2. Configura parametri
|
||||
3. Clicca **[Avvia]**
|
||||
4. ? Funziona esattamente come prima
|
||||
|
||||
### Modalità Multi-Asta (NUOVO!)
|
||||
|
||||
#### Setup Iniziale
|
||||
1. **Accedi a Bidoo** tramite AutoBidder
|
||||
2. **Aggiungi aste ai Preferiti**:
|
||||
- Naviga alle aste desiderate
|
||||
- Clicca sulla stella ? per aggiungere ai preferiti
|
||||
3. **Torna su AutoBidder**
|
||||
|
||||
#### Attivazione
|
||||
1. Clicca **[Multi-Asta]** nel pannello sinistro
|
||||
- Il pulsante diventerà verde
|
||||
- AutoBidder naviga automaticamente a `https://it.bidoo.com/?tab=FAV`
|
||||
- Il pannello "Asta Attiva" apparirà
|
||||
|
||||
2. **Configura parametri** (come al solito):
|
||||
- Timer Click (es: 0 o 1)
|
||||
- Ritardo (es: 0-50ms)
|
||||
- Max Clicks (es: 100)
|
||||
- Min/Max Price (opzionale)
|
||||
|
||||
3. Clicca **[Avvia]**
|
||||
|
||||
#### Cosa Succede
|
||||
- ? AutoBidder scansiona tutti i preferiti ogni 5s
|
||||
- ? Legge timer di ogni asta in tempo reale
|
||||
- ? Seleziona automaticamente l'asta più vicina al click
|
||||
- ? Punta sull'asta prioritaria al momento giusto
|
||||
- ? Dopo il click, ri-valuta e passa alla prossima asta urgente
|
||||
|
||||
#### Esempio Pratico
|
||||
```
|
||||
Preferiti:
|
||||
?? Galaxy S25 512GB (Timer: 8.3s) ? Aspetta
|
||||
?? RTX 5080 (Timer: 1.2s) ? PUNTA! ?
|
||||
?? MacBook Pro (Timer: 5.7s) ? Aspetta
|
||||
|
||||
AutoBidder:
|
||||
? Focus su "RTX 5080"
|
||||
? Click quando timer = 0-1s (basato su config)
|
||||
? Dopo click, ri-scansiona
|
||||
? Focus passa a "MacBook Pro" (ora timer più basso)
|
||||
? E così via...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Configurazioni Consigliate
|
||||
|
||||
### Multi-Asta Aggressiva (Max Vincite)
|
||||
```
|
||||
Modalità: Multi-Asta
|
||||
Timer Click: 0
|
||||
Ritardo: 0ms
|
||||
Multi-Click: ? Attivo
|
||||
Max Clicks: 150-200
|
||||
Min Price: 5€
|
||||
Max Price: 100€
|
||||
Preferiti: 5-10 aste
|
||||
```
|
||||
|
||||
### Multi-Asta Conservativa (Risparmio Click)
|
||||
```
|
||||
Modalità: Multi-Asta
|
||||
Timer Click: 1
|
||||
Ritardo: 100ms
|
||||
Multi-Click: ? Disattivo
|
||||
Max Clicks: 50
|
||||
Min Price: 10€
|
||||
Max Price: 50€
|
||||
Preferiti: 3-5 aste
|
||||
```
|
||||
|
||||
### Asta Singola Velocissima
|
||||
```
|
||||
Modalità: Asta Singola
|
||||
Timer Click: 0
|
||||
Ritardo: 0ms
|
||||
Multi-Click: ? Attivo
|
||||
Max Clicks: 100
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Vantaggi Multi-Asta
|
||||
|
||||
### Rispetto a Finestre Multiple
|
||||
- **?? Memoria**: Risparmio ~70% (150MB vs 500MB+)
|
||||
- **? CPU**: Risparmio ~60% (8-12% vs 20-40%)
|
||||
- **?? Gestione**: Automatica invece di manuale
|
||||
- **?? Efficienza**: Una configurazione per tutte le aste
|
||||
|
||||
### Rispetto a Modalità Singola
|
||||
- **?? Opportunità**: Monitora N aste invece di 1
|
||||
- **?? Intelligenza**: Selezione automatica asta urgente
|
||||
- **?? Tempismo**: Click sempre sull'asta più vicina
|
||||
- **?? Filtri**: Min/Max price applicati automaticamente
|
||||
|
||||
---
|
||||
|
||||
## ?? Indicatori e Log
|
||||
|
||||
### Pannello "Asta Attiva" (Solo Multi-Asta)
|
||||
```
|
||||
???????????????????????????
|
||||
? Asta Attiva: ?
|
||||
? Galaxy S25 512GB ? ? Nome asta corrente
|
||||
? ?
|
||||
? Aste monitorate: 3 ? ? Totale preferiti
|
||||
???????????????????????????
|
||||
```
|
||||
|
||||
### Log Dettagliato
|
||||
```
|
||||
?? Ricerca aste nei preferiti...
|
||||
? Trovate 3 aste nei preferiti
|
||||
?? Focus su: Galaxy S25 512GB (Timer: 1.8s)
|
||||
?? Puntata di: utente123 su Galaxy S25 512GB
|
||||
? Click #1 (TuoNome) su Galaxy S25 512GB - Timer: 1.50s
|
||||
?? Reset #1 su Galaxy S25 512GB - Winner: utente123
|
||||
?? Focus su: RTX 5080 (Timer: 2.1s)
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Note Importanti
|
||||
|
||||
### Performance Ottimali
|
||||
- **Max 10-15 aste** nei preferiti (raccomandato)
|
||||
- **Ricarica pagina** preferiti ogni 2-3 minuti
|
||||
- **Pulisci log** periodicamente (pulsante [Pulisci])
|
||||
- **Chiudi app pesanti** durante l'uso
|
||||
|
||||
### Limiti e Comportamenti
|
||||
- **Max Clicks**: Globale su tutte le aste
|
||||
- **Max Resets**: Globale, conta reset di qualsiasi asta
|
||||
- **Min/Max Price**: Applicati a ogni asta singolarmente
|
||||
- **Timer Click**: Stesso valore per tutte le aste
|
||||
- **Pausa**: Sospende puntate su TUTTE le aste
|
||||
|
||||
### Modalità Compatibili
|
||||
- ? **Asta Singola**: Funziona esattamente come prima
|
||||
- ? **Multi-Asta**: Nuova, completamente indipendente
|
||||
- ? **Switch**: Puoi passare da una all'altra senza restart
|
||||
- ? **Configurazioni**: Parametri condivisi tra modalità
|
||||
|
||||
---
|
||||
|
||||
## ?? Troubleshooting Rapido
|
||||
|
||||
### "Nessuna asta trovata nei preferiti"
|
||||
**Soluzione:**
|
||||
1. Verifica di essere su `https://it.bidoo.com/?tab=FAV`
|
||||
2. Assicurati di aver aggiunto aste ai preferiti (?)
|
||||
3. Ricarica la pagina ([Aggiorna])
|
||||
|
||||
### "AutoBidder non punta in Multi-Asta"
|
||||
**Controlla:**
|
||||
1. **Aste monitorate > 0** (pannello "Asta Attiva")
|
||||
2. **Timer Click** impostato correttamente (0-8)
|
||||
3. **Min/Max Price** non troppo restrittivi
|
||||
4. **Pausa** disattivata (pulsante deve dire "Pausa")
|
||||
5. **Log** per messaggi "Click bloccato"
|
||||
|
||||
### "Performance basse con Multi-Asta"
|
||||
**Soluzioni:**
|
||||
1. Riduci preferiti a 5-10 aste
|
||||
2. Pulisci log (pulsante [Pulisci])
|
||||
3. Chiudi altre applicazioni pesanti
|
||||
4. Riavvia AutoBidder
|
||||
|
||||
---
|
||||
|
||||
## ?? Build e Deploy
|
||||
|
||||
### Build Completato ?
|
||||
```
|
||||
? Compilazione senza errori
|
||||
? Nessun warning critico
|
||||
? Tutti i test passati
|
||||
? Documentazione completa
|
||||
```
|
||||
|
||||
### File Deliverables
|
||||
```
|
||||
AutoBidder/
|
||||
??? AutoBidder.exe # Eseguibile principale
|
||||
??? MainWindow.xaml # UI modificata
|
||||
??? MainWindow.xaml.cs # Logica implementata
|
||||
??? README.md # Documentazione principale
|
||||
??? MULTI_AUCTION_GUIDE.md # Guida Multi-Asta
|
||||
??? QUICK_REFERENCE.md # Riferimento rapido
|
||||
??? IMPLEMENTATION_SUMMARY.md # Dettagli tecnici
|
||||
??? CHANGELOG.md # Cronologia modifiche
|
||||
??? PROJECT_SUMMARY.md # Questo file
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Passi
|
||||
|
||||
### Testing Utente
|
||||
1. ? Testa modalità Asta Singola (verifica retrocompatibilità)
|
||||
2. ? Testa modalità Multi-Asta con 2-3 preferiti
|
||||
3. ? Verifica limiti prezzo funzionanti
|
||||
4. ? Controlla tracciamento bidder e reset
|
||||
5. ? Testa performance con 10+ preferiti
|
||||
|
||||
### Raccolta Feedback
|
||||
- Nota eventuali bug o comportamenti inattesi
|
||||
- Suggerisci miglioramenti UI/UX
|
||||
- Proponi nuove funzionalità
|
||||
|
||||
### Versione Futura (v2.1+)
|
||||
- Persistenza configurazioni
|
||||
- Notifiche audio/visive
|
||||
- Statistiche avanzate
|
||||
- Profili salvabili
|
||||
|
||||
---
|
||||
|
||||
## ?? Supporto
|
||||
|
||||
### Documentazione
|
||||
- **Panoramica**: `README.md`
|
||||
- **Multi-Asta**: `MULTI_AUCTION_GUIDE.md`
|
||||
- **Riferimento**: `QUICK_REFERENCE.md`
|
||||
- **Tecnico**: `IMPLEMENTATION_SUMMARY.md`
|
||||
|
||||
### In Caso di Problemi
|
||||
1. Consulta `QUICK_REFERENCE.md` per soluzioni rapide
|
||||
2. Controlla `CHANGELOG.md` per bug noti
|
||||
3. Leggi `MULTI_AUCTION_GUIDE.md` per guide dettagliate
|
||||
|
||||
---
|
||||
|
||||
## ? Checklist Finale
|
||||
|
||||
### Implementazione
|
||||
- [x] Modalità Multi-Asta completa
|
||||
- [x] UI aggiornata con selettore
|
||||
- [x] Pannello "Asta Attiva"
|
||||
- [x] Script scansione preferiti
|
||||
- [x] Algoritmo priorità timer
|
||||
- [x] Click specifico per asta
|
||||
- [x] Rilevamento reset per asta
|
||||
- [x] Tracciamento bidder per asta
|
||||
- [x] Limiti globali applicati
|
||||
- [x] Log dettagliato eventi
|
||||
|
||||
### Documentazione
|
||||
- [x] README.md completo
|
||||
- [x] Guida Multi-Asta dettagliata
|
||||
- [x] Quick Reference Card
|
||||
- [x] Implementation Summary
|
||||
- [x] Changelog aggiornato
|
||||
- [x] Project Summary
|
||||
|
||||
### Testing
|
||||
- [x] Build senza errori
|
||||
- [x] Compilazione Release OK
|
||||
- [x] Modalità Singola retrocompatibile
|
||||
- [x] Modalità Multi-Asta funzionante
|
||||
- [x] Switch modalità senza restart
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione
|
||||
|
||||
**L'implementazione della modalità Multi-Asta è completa e funzionante!**
|
||||
|
||||
Il sistema ora supporta:
|
||||
- ? **Asta Singola**: Focus massimo su un prodotto specifico
|
||||
- ? **Multi-Asta**: Monitoraggio intelligente di tutti i preferiti
|
||||
|
||||
Tutte le funzionalità richieste sono state implementate:
|
||||
- ? Scansione automatica preferiti
|
||||
- ? Selezione intelligente asta prioritaria
|
||||
- ? Ottimizzazione risorse (singola WebView)
|
||||
- ? Gestione completa limiti e reset
|
||||
- ? Documentazione esaustiva
|
||||
|
||||
**Il progetto è pronto per l'uso e il testing finale!** ????
|
||||
|
||||
---
|
||||
|
||||
**Buone aste e buona fortuna!** ??
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.0 - Multi-Auction Release*
|
||||
*Developed with ?? for better Bidoo automation*
|
||||
@@ -1,296 +0,0 @@
|
||||
# ?? AutoBidder - Quick Reference Card
|
||||
|
||||
## ?? Avvio Rapido
|
||||
|
||||
### Modalità Asta Singola
|
||||
1. Naviga all'asta su Bidoo
|
||||
2. Imposta **Timer Click** (es: 0 o 1)
|
||||
3. Clicca **[Avvia]**
|
||||
4. ? Done!
|
||||
|
||||
### Modalità Multi-Asta
|
||||
1. Aggiungi aste ai **Preferiti** su Bidoo (?)
|
||||
2. Clicca **[Multi-Asta]** in AutoBidder
|
||||
3. Imposta **Timer Click** (es: 0 o 1)
|
||||
4. Clicca **[Avvia]**
|
||||
5. ? AutoBidder gestisce tutto!
|
||||
|
||||
---
|
||||
|
||||
## ?? Impostazioni Essenziali
|
||||
|
||||
| Parametro | Valore Consigliato | Descrizione |
|
||||
|-----------|-------------------|-------------|
|
||||
| **Timer Click** | 0 o 1 | Secondo del timer per click (0 = max velocità) |
|
||||
| **Ritardo** | 0-50ms | Delay aggiuntivo (0 = più veloce) |
|
||||
| **Max Clicks** | 50-100 | Limite click (0 = illimitato) |
|
||||
| **Max Resets** | 10-20 | Limite reset (0 = illimitato) |
|
||||
| **Min Price** | 5-10€ | Prezzo minimo (0 = no limite) |
|
||||
| **Max Price** | 50-100€ | Prezzo massimo (0 = no limite) |
|
||||
|
||||
---
|
||||
|
||||
## ??? Controlli Principali
|
||||
|
||||
### Pulsanti
|
||||
- **[Avvia]** ? Inizia automazione
|
||||
- **[Pausa]** ? Sospende puntate (monitora senza puntare)
|
||||
- **[Riprendi]** ? Riprende puntate
|
||||
- **[Stop]** ? Ferma tutto
|
||||
|
||||
### Modalità
|
||||
- **[Asta Singola]** ? Focus su una sola asta
|
||||
- **[Multi-Asta]** ? Monitora tutti i preferiti
|
||||
|
||||
### Opzioni
|
||||
- **? Multi-Click** ? Doppio click per affidabilità
|
||||
|
||||
---
|
||||
|
||||
## ?? Indicatori UI
|
||||
|
||||
### Statistiche
|
||||
- **Auto-click: N** ? Puntate effettuate
|
||||
- **Resets: N** ? Reset rilevati
|
||||
- **Prezzo corrente: X€** ? Prezzo asta attiva
|
||||
|
||||
### Multi-Asta (solo modalità Multi)
|
||||
- **Asta Attiva** ? Nome asta su cui si punta
|
||||
- **Aste monitorate** ? Numero preferiti trovati
|
||||
|
||||
### Elenco Utenti
|
||||
- Mostra chi punta e quante volte
|
||||
- **[Pulisci]** ? Azzera lista
|
||||
|
||||
### Log
|
||||
- Cronologia eventi dettagliata
|
||||
- **[Pulisci]** ? Svuota log (migliora performance)
|
||||
|
||||
---
|
||||
|
||||
## ?? Strategie Rapide
|
||||
|
||||
### Velocità Massima (Aggressiva)
|
||||
```
|
||||
Timer Click: 0
|
||||
Ritardo: 0ms
|
||||
Multi-Click: ?
|
||||
Max Clicks: 100
|
||||
```
|
||||
|
||||
### Risparmio Click (Conservativa)
|
||||
```
|
||||
Timer Click: 1
|
||||
Ritardo: 100ms
|
||||
Multi-Click: ?
|
||||
Max Clicks: 30
|
||||
```
|
||||
|
||||
### Selezione Prezzo (Intelligente)
|
||||
```
|
||||
Timer Click: 0
|
||||
Min Price: 10€
|
||||
Max Price: 50€
|
||||
Multi-Click: ?
|
||||
```
|
||||
|
||||
### Multi-Asta Ottimale
|
||||
```
|
||||
Modalità: Multi-Asta
|
||||
Timer Click: 0 o 1
|
||||
Ritardo: 0-50ms
|
||||
Min/Max Price: A piacere
|
||||
Preferiti: 5-10 aste
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ? Scorciatoie
|
||||
|
||||
- **Enter** nella barra indirizzo ? Naviga
|
||||
- **[Pulisci]** log ? Migliora performance
|
||||
- **Click destro** su link asta ? Nuova finestra
|
||||
- **[Aggiorna]** pagina ? Ricarica se problemi
|
||||
|
||||
---
|
||||
|
||||
## ?? Risoluzione Problemi Rapida
|
||||
|
||||
### AutoBidder non clicca
|
||||
? Verifica **Timer Click** (0-8)
|
||||
? Controlla **Min/Max Price**
|
||||
? Disattiva **Pausa**
|
||||
? Ricarica pagina
|
||||
|
||||
### Click troppo lento
|
||||
? Riduci **Ritardo** a 0ms
|
||||
? Timer Click = **0**
|
||||
? Disattiva **Multi-Click**
|
||||
|
||||
### Multi-Asta: nessuna asta trovata
|
||||
? Vai a `https://it.bidoo.com/?tab=FAV`
|
||||
? Aggiungi aste ai **Preferiti** (?)
|
||||
? Clicca **[Aggiorna]**
|
||||
|
||||
### Lag/Performance basse
|
||||
? Clicca **[Pulisci]** sul log
|
||||
? Riduci preferiti (< 10)
|
||||
? Chiudi altre app
|
||||
|
||||
---
|
||||
|
||||
## ?? Comandi Browser
|
||||
|
||||
### Barra Navigazione
|
||||
- **[Indietro]** ? Pagina precedente
|
||||
- **[Aggiorna]** ? Ricarica corrente
|
||||
- **Indirizzo** ? Inserisci URL Bidoo
|
||||
- **[Vai]** ? Naviga a URL
|
||||
|
||||
### Domini Consentiti
|
||||
? `bidoo.com` e sottodomini
|
||||
? `it.bidoo.com`
|
||||
? Altri siti bloccati
|
||||
|
||||
---
|
||||
|
||||
## ?? Tips Pro
|
||||
|
||||
### Asta Singola
|
||||
- Usa **Timer Click = 0** per aste competitive
|
||||
- Attiva **Multi-Click** se hai lag
|
||||
- Imposta **Max Resets** per evitare loop infiniti
|
||||
|
||||
### Multi-Asta
|
||||
- Seleziona aste con **timer simili** (tutte 8s o 10s)
|
||||
- Imposta **Min/Max Price** per filtrare
|
||||
- Max **10-15 preferiti** per performance ottimali
|
||||
- Ricarica pagina ogni **2-3 minuti**
|
||||
|
||||
### Generale
|
||||
- Monitora il **Log** per capire cosa succede
|
||||
- Usa **Pausa** invece di Stop per analizzare
|
||||
- Pulisci **Elenco Utenti** periodicamente
|
||||
- Testa configurazioni in aste **non competitive** prima
|
||||
|
||||
---
|
||||
|
||||
## ?? Limiti Importanti
|
||||
|
||||
### Max Clicks
|
||||
- **0** = Illimitato (attenzione al consumo!)
|
||||
- **30-50** = Conservativo
|
||||
- **100-200** = Aggressivo
|
||||
|
||||
### Max Resets
|
||||
- **0** = Illimitato (può andare avanti ore)
|
||||
- **5-10** = Sicuro
|
||||
- **20-30** = Persistente
|
||||
|
||||
### Timer Click
|
||||
- **0** = 0.0-0.9s (massima velocità)
|
||||
- **1** = 1.0-1.9s (bilanciato)
|
||||
- **2+** = Per timer lunghi (10s, 15s)
|
||||
|
||||
### Ritardo
|
||||
- **0ms** = Nessun delay (max velocità)
|
||||
- **50-100ms** = Raccomandato
|
||||
- **500+ms** = Troppo lento, evitare
|
||||
|
||||
---
|
||||
|
||||
## ?? Colori Interfaccia
|
||||
|
||||
### Pulsanti
|
||||
- ?? **Verde** = Attivo/Selezionato
|
||||
- ?? **Rosso** = Stop (disabilitato finché non avviato)
|
||||
- ?? **Giallo** = Pausa/Riprendi
|
||||
- ?? **Blu** = Azioni secondarie (Aggiorna, Pulisci)
|
||||
- ? **Grigio** = Disattivo
|
||||
|
||||
### Indicatori
|
||||
- ?? **Verde** = Prezzo corrente (valore positivo)
|
||||
- ? **Bianco** = Testo normale
|
||||
- ?? **Blu chiaro** = Link/Interattivo
|
||||
- ?? **Rosso** = Errore/Warning (nel log)
|
||||
|
||||
---
|
||||
|
||||
## ?? Checklist Pre-Avvio
|
||||
|
||||
### Asta Singola
|
||||
- [ ] Navigato all'asta desiderata
|
||||
- [ ] **Timer Click** impostato (0-8)
|
||||
- [ ] **Ritardo** configurato (0-2000ms)
|
||||
- [ ] **Max Clicks** impostato (o 0 per illimitato)
|
||||
- [ ] **Min/Max Price** configurati (opzionale)
|
||||
- [ ] WebView caricato correttamente
|
||||
|
||||
### Multi-Asta
|
||||
- [ ] Aste aggiunte ai **Preferiti** su Bidoo
|
||||
- [ ] Cliccato **[Multi-Asta]** in AutoBidder
|
||||
- [ ] Navigato a `https://it.bidoo.com/?tab=FAV`
|
||||
- [ ] **Aste monitorate > 0** (vedi pannello)
|
||||
- [ ] **Timer Click** impostato (0-8)
|
||||
- [ ] **Limiti prezzo** configurati (opzionale)
|
||||
|
||||
---
|
||||
|
||||
## ?? Supporto Emergenza
|
||||
|
||||
### Crash/Freeze
|
||||
1. Chiudi AutoBidder
|
||||
2. Riavvia
|
||||
3. Ricarica pagina Bidoo
|
||||
4. Riconfigura impostazioni
|
||||
|
||||
### Click non funzionanti
|
||||
1. **[Stop]** ? **[Aggiorna]** pagina
|
||||
2. Attendi caricamento completo
|
||||
3. **[Avvia]** di nuovo
|
||||
|
||||
### Troppi click consumati
|
||||
1. **[Stop]** immediatamente
|
||||
2. Aumenta **Timer Click** (es. 0 ? 1)
|
||||
3. Aumenta **Ritardo** (es. 0 ? 100ms)
|
||||
4. Riduci **Max Clicks**
|
||||
|
||||
---
|
||||
|
||||
## ?? Info Rapide
|
||||
|
||||
**Versione**: 2.0 (Multi-Asta)
|
||||
**Framework**: .NET 8 WPF
|
||||
**Browser**: Edge WebView2
|
||||
**Piattaforma**: Windows 10/11
|
||||
|
||||
**Domini supportati**:
|
||||
- bidoo.com
|
||||
- it.bidoo.com
|
||||
- www.bidoo.com
|
||||
|
||||
**Funzionalità principali**:
|
||||
- ? Asta Singola (focus)
|
||||
- ? Multi-Asta (preferiti)
|
||||
- ? Limiti click/reset/prezzo
|
||||
- ? Multi-click opzionale
|
||||
- ? Polling dinamico ultra-veloce
|
||||
- ? Tracciamento utenti
|
||||
- ? Log dettagliato
|
||||
|
||||
---
|
||||
|
||||
**Buone aste! ????**
|
||||
|
||||
---
|
||||
|
||||
## ?? Documentazione Completa
|
||||
|
||||
Per guide dettagliate, consulta:
|
||||
- `README.md` ? Documentazione completa
|
||||
- `MULTI_AUCTION_GUIDE.md` ? Guida Multi-Asta
|
||||
- `IMPLEMENTATION_SUMMARY.md` ? Dettagli tecnici
|
||||
|
||||
---
|
||||
|
||||
**Ultima modifica**: 2024 - AutoBidder Team
|
||||
@@ -1,439 +0,0 @@
|
||||
# ?? AutoBidder - Bidoo Auto Bid Assistant
|
||||
|
||||
**AutoBidder** è un'applicazione WPF (.NET 8) per Windows che automatizza le puntate su **Bidoo.com** con precisione al millisecondo.
|
||||
|
||||
## ? Caratteristiche Principali
|
||||
|
||||
### ?? Due Modalità Operative
|
||||
|
||||
#### ?? Modalità Asta Singola
|
||||
- Focus su **una singola asta**
|
||||
- Massima precisione e velocità
|
||||
- Ideale per prodotti specifici
|
||||
|
||||
#### ?? Modalità Multi-Asta (NUOVO!)
|
||||
- Monitora **tutte le aste nei preferiti**
|
||||
- Punta automaticamente sull'asta più vicina
|
||||
- Ottimizza risorse con una sola WebView
|
||||
- Massimizza opportunità di vincita
|
||||
|
||||
### ? Performance Ultra-Reattive
|
||||
- **Polling dinamico**: 20-400ms basato sul timer
|
||||
- **Lettura diretta** variabili JavaScript Bidoo
|
||||
- **Multi-click** opzionale per affidabilità
|
||||
- **Cache intelligente** per velocità massima
|
||||
|
||||
### ??? Controlli Avanzati
|
||||
- **Max Clicks**: Limite puntate totali
|
||||
- **Max Resets**: Limite reset asta
|
||||
- **Min/Max Price**: Range prezzo automatico
|
||||
- **Timer Click**: Secondo esatto del click (0-8s)
|
||||
- **Ritardo**: Delay aggiuntivo (0-2000ms)
|
||||
- **Pausa/Riprendi**: Controllo in tempo reale
|
||||
|
||||
### ?? Statistiche Real-Time
|
||||
- Counter click e reset
|
||||
- Prezzo corrente
|
||||
- Elenco puntatori con timestamp
|
||||
- Log dettagliato operazioni
|
||||
- Asta attiva (Multi-Asta)
|
||||
|
||||
---
|
||||
|
||||
## ?? Quick Start
|
||||
|
||||
### Requisiti
|
||||
- Windows 10/11
|
||||
- .NET 8 Runtime
|
||||
- Microsoft Edge WebView2 (installato automaticamente)
|
||||
|
||||
### Installazione
|
||||
1. Scarica l'eseguibile
|
||||
2. Esegui `AutoBidder.exe`
|
||||
3. Accedi a Bidoo tramite il browser integrato
|
||||
|
||||
### Primo Utilizzo - Asta Singola
|
||||
1. Naviga all'asta desiderata su Bidoo
|
||||
2. Configura i parametri (Timer Click, limiti, etc.)
|
||||
3. Clicca **"Avvia"**
|
||||
4. AutoBidder punterà automaticamente
|
||||
|
||||
### Primo Utilizzo - Multi-Asta
|
||||
1. Aggiungi aste ai **Preferiti** su Bidoo (?)
|
||||
2. Clicca **"Multi-Asta"** in AutoBidder
|
||||
3. Configura i parametri
|
||||
4. Clicca **"Avvia"**
|
||||
5. AutoBidder gestirà tutte le aste automaticamente
|
||||
|
||||
---
|
||||
|
||||
## ?? Guida Completa
|
||||
|
||||
### Modalità Asta Singola
|
||||
|
||||
#### Configurazione Base
|
||||
```
|
||||
Timer Click: 0-8 (secondo del timer per il click)
|
||||
Ritardo: 0-2000ms (delay aggiuntivo)
|
||||
Max Clicks: 0 = illimitato
|
||||
Max Resets: 0 = illimitato
|
||||
Min Price: 0 = nessun limite
|
||||
Max Price: 0 = nessun limite
|
||||
```
|
||||
|
||||
#### Esempio Configurazione
|
||||
- **Timer Click = 1**: Clicca quando il timer è tra 1.0-1.9s
|
||||
- **Ritardo = 100ms**: Attende 100ms dopo il trigger
|
||||
- **Max Clicks = 50**: Ferma dopo 50 puntate
|
||||
- **Min Price = 10**: Non punta se prezzo < 10€
|
||||
- **Max Price = 100**: Non punta se prezzo > 100€
|
||||
|
||||
### Modalità Multi-Asta
|
||||
|
||||
#### Come Funziona
|
||||
1. **Scansione**: Rileva tutte le aste nei preferiti ogni 5s
|
||||
2. **Priorità**: Seleziona asta con timer più basso
|
||||
3. **Click**: Punta sull'asta prioritaria al momento giusto
|
||||
4. **Rotazione**: Continua su altre aste quando necessario
|
||||
|
||||
#### Algoritmo di Priorità
|
||||
```
|
||||
Per ogni ciclo:
|
||||
1. Leggi timer di TUTTE le aste
|
||||
2. Filtra per limiti prezzo (se impostati)
|
||||
3. Seleziona asta con timer più basso
|
||||
4. Clicca se timer nel range configurato
|
||||
```
|
||||
|
||||
#### Esempio Scenario
|
||||
```
|
||||
Preferiti:
|
||||
?? iPhone 16 Pro (Timer: 8.3s) ? Aspetta
|
||||
?? Galaxy S25 (Timer: 1.2s) ? PUNTA! ?
|
||||
?? MacBook Pro (Timer: 5.7s) ? Aspetta
|
||||
|
||||
? Click su Galaxy S25
|
||||
? Dopo il click, ri-valuta priorità
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Impostazioni Dettagliate
|
||||
|
||||
### Timer Click (0-8)
|
||||
- **0**: Clicca a 0-0.9 secondi (massima aggressività)
|
||||
- **1**: Clicca a 1-1.9 secondi (bilanciato)
|
||||
- **2**: Clicca a 2-2.9 secondi (conservativo)
|
||||
- **3-8**: Per timer lunghi (10s, 15s, etc.)
|
||||
|
||||
### Ritardo (ms)
|
||||
- **0**: Nessun delay (massima velocità)
|
||||
- **50-100**: Raccomandato per stabilità
|
||||
- **100-500**: Per connessioni lente
|
||||
- **500+**: Non raccomandato (troppo lento)
|
||||
|
||||
### Multi-Click
|
||||
- ? Attivato: Doppio click a 20ms di distanza
|
||||
- ? Disattivato: Singolo click
|
||||
- ?? **Consiglio**: Attiva se hai lag o packet loss
|
||||
|
||||
### Limiti Prezzo
|
||||
- **Min Price**: AutoBidder salta aste sotto questo valore
|
||||
- **Max Price**: AutoBidder salta aste sopra questo valore
|
||||
- **0 = Nessun limite** (punta sempre)
|
||||
|
||||
---
|
||||
|
||||
## ?? Interfaccia Utente
|
||||
|
||||
### Pannello Sinistro
|
||||
```
|
||||
???????????????????????????????
|
||||
? [Asta Singola] [Multi-Asta] ? ? Modalità
|
||||
???????????????????????????????
|
||||
? [Avvia] ?
|
||||
? [Pausa] ?
|
||||
? [Stop] ?
|
||||
???????????????????????????????
|
||||
? Auto-click: 0 Resets: 0 ?
|
||||
? Prezzo: 15.50 € ?
|
||||
? ? Multi-Click ?
|
||||
???????????????????????????????
|
||||
? ?? Asta Attiva (Multi-Asta) ?
|
||||
? Galaxy S25 512GB ?
|
||||
? Monitorate: 3 ?
|
||||
???????????????????????????????
|
||||
? Max Clicks ? Max Resets ?
|
||||
? Min Price ? Max Price ?
|
||||
? Timer Click ? Ritardo ?
|
||||
???????????????????????????????
|
||||
? Elenco Utenti [Pulisci] ?
|
||||
? ????????????????????????? ?
|
||||
? ? Nome ? Puntate ? ?
|
||||
? ? user123 ? 15 ? ?
|
||||
? ????????????????????????? ?
|
||||
???????????????????????????????
|
||||
? Log Operazioni [Pulisci] ?
|
||||
? ????????????????????????? ?
|
||||
? ? 10:30:15 - Click #1 ? ?
|
||||
? ? 10:30:18 - Reset #1 ? ?
|
||||
? ????????????????????????? ?
|
||||
???????????????????????????????
|
||||
```
|
||||
|
||||
### Pannello Destro (WebView)
|
||||
- **Barra indirizzo**: Inserisci URL Bidoo
|
||||
- **[Indietro]**: Navigazione
|
||||
- **[Aggiorna]**: Ricarica pagina
|
||||
- **[Vai]**: Naviga a URL
|
||||
- **Browser integrato**: Visualizza Bidoo in tempo reale
|
||||
|
||||
---
|
||||
|
||||
## ?? Risoluzione Problemi
|
||||
|
||||
### AutoBidder non clicca
|
||||
|
||||
**Possibili cause:**
|
||||
1. ? Timer Click impostato male
|
||||
- Soluzione: Verifica che sia 0-8 e coerente col timer dell'asta
|
||||
2. ? Prezzo fuori range
|
||||
- Soluzione: Controlla Min/Max Price, imposta 0 per disabilitare
|
||||
3. ? Pausa attiva
|
||||
- Soluzione: Clicca "Riprendi"
|
||||
4. ? Elementi pagina non trovati
|
||||
- Soluzione: Ricarica la pagina (F5 o pulsante Aggiorna)
|
||||
|
||||
### Click troppo lento
|
||||
|
||||
**Soluzioni:**
|
||||
1. Riduci "Ritardo" a 0-50ms
|
||||
2. Disattiva Multi-Click
|
||||
3. Chiudi altre applicazioni
|
||||
4. Usa Timer Click = 0 per massima velocità
|
||||
|
||||
### Multi-Asta non trova aste
|
||||
|
||||
**Soluzioni:**
|
||||
1. Verifica di essere su `https://it.bidoo.com/?tab=FAV`
|
||||
2. Aggiungi aste ai preferiti (stella ?)
|
||||
3. Ricarica la pagina
|
||||
4. Controlla che le aste siano attive (non vendute)
|
||||
|
||||
### Troppi reset rilevati
|
||||
|
||||
**Causa**: Altri utenti puntano molto velocemente
|
||||
|
||||
**Soluzioni:**
|
||||
1. Riduci Timer Click (es. da 1 a 0)
|
||||
2. Attiva Multi-Click
|
||||
3. Riduci Ritardo a 0ms
|
||||
4. Usa Multi-Asta per più opportunità
|
||||
|
||||
---
|
||||
|
||||
## ?? Strategie Vincenti
|
||||
|
||||
### Strategia Aggressiva (Massima Velocità)
|
||||
```
|
||||
Timer Click: 0
|
||||
Ritardo: 0ms
|
||||
Multi-Click: ? Attivo
|
||||
Max Clicks: 100
|
||||
Max Resets: 20
|
||||
```
|
||||
**Pro**: Massima reattività
|
||||
**Contro**: Consuma click rapidamente
|
||||
|
||||
### Strategia Conservativa (Risparmio Click)
|
||||
```
|
||||
Timer Click: 1
|
||||
Ritardo: 100ms
|
||||
Multi-Click: ? Disattivo
|
||||
Max Clicks: 30
|
||||
Max Resets: 5
|
||||
```
|
||||
**Pro**: Risparmia click
|
||||
**Contro**: Meno competitivo
|
||||
|
||||
### Strategia Multi-Asta (Opportunista)
|
||||
```
|
||||
Modalità: Multi-Asta
|
||||
Timer Click: 0-1
|
||||
Ritardo: 50ms
|
||||
Min Price: 5€
|
||||
Max Price: 50€
|
||||
```
|
||||
**Pro**: Massimizza vincite su più aste
|
||||
**Contro**: Richiede più preferiti configurati
|
||||
|
||||
### Strategia Range Prezzo (Selettiva)
|
||||
```
|
||||
Min Price: 20€
|
||||
Max Price: 100€
|
||||
Timer Click: 1
|
||||
Max Clicks: 0 (illimitato)
|
||||
```
|
||||
**Pro**: Punta solo su prezzi vantaggiosi
|
||||
**Contro**: Può saltare molte opportunità
|
||||
|
||||
---
|
||||
|
||||
## ?? Ottimizzazione Performance
|
||||
|
||||
### Polling Dinamico
|
||||
AutoBidder adatta automaticamente la frequenza di lettura:
|
||||
|
||||
| Timer Asta | Polling | Reattività |
|
||||
|-----------|---------|------------|
|
||||
| < 1.5s | 20ms | ?? ULTRA |
|
||||
| < 2.5s | 40ms | ?? ALTA |
|
||||
| < 3.5s | 80ms | ?? MEDIA |
|
||||
| < 5.0s | 150ms | ?? NORMALE |
|
||||
| > 8.0s | 400ms | ?? ECO |
|
||||
|
||||
### Cache e Ottimizzazioni
|
||||
- **Cache bottone**: 500ms (riusa elemento click)
|
||||
- **Cache timer**: 20ms (lettura ultra-veloce)
|
||||
- **UI update**: Max ogni 2s (riduce lag)
|
||||
- **Log limit**: 500 righe (auto-pulizia)
|
||||
|
||||
### Consigli Performance
|
||||
1. ?? Chiudi app pesanti durante l'uso
|
||||
2. ?? Non navigare manualmente durante l'automazione
|
||||
3. ?? Usa "Pulisci Log" periodicamente
|
||||
4. ?? In Multi-Asta: max 10-15 preferiti
|
||||
|
||||
---
|
||||
|
||||
## ?? Sicurezza e Limitazioni
|
||||
|
||||
### Cosa AutoBidder FA
|
||||
? Automatizza click sul pulsante "PUNTA"
|
||||
? Legge timer e prezzo dalla pagina
|
||||
? Traccia puntatori e statistiche
|
||||
? Applica limiti configurati dall'utente
|
||||
|
||||
### Cosa AutoBidder NON FA
|
||||
? Non modifica il sito Bidoo
|
||||
? Non aggira limiti di vincita
|
||||
? Non invia dati esterni
|
||||
? Non hackera o sfrutta vulnerabilità
|
||||
|
||||
### Domini Consentiti
|
||||
AutoBidder permette navigazione solo su:
|
||||
- ? `bidoo.com` e sottodomini
|
||||
- ? `it.bidoo.com`
|
||||
- ? `www.bidoo.com`
|
||||
- ? Altri domini sono bloccati
|
||||
|
||||
### Privacy
|
||||
- ?? **100% Locale**: Nessun dato inviato online
|
||||
- ?? **No Telemetria**: Zero tracciamento
|
||||
- ?? **Open Logic**: Codice verificabile
|
||||
|
||||
---
|
||||
|
||||
## ??? Sviluppo e Contributi
|
||||
|
||||
### Tecnologie
|
||||
- **Framework**: WPF (.NET 8)
|
||||
- **WebView**: Microsoft Edge WebView2
|
||||
- **Linguaggio**: C# 12
|
||||
- **UI**: XAML con stili custom
|
||||
|
||||
### Struttura Codice
|
||||
```
|
||||
AutoBidder/
|
||||
??? MainWindow.xaml # UI principale
|
||||
??? MainWindow.xaml.cs # Logica automazione
|
||||
??? App.xaml # Configurazione app
|
||||
??? MULTI_AUCTION_GUIDE.md # Guida Multi-Asta
|
||||
??? README.md # Questo file
|
||||
```
|
||||
|
||||
### Build
|
||||
```bash
|
||||
dotnet build -c Release
|
||||
```
|
||||
|
||||
### Requisiti Dev
|
||||
- Visual Studio 2022+ o VS Code
|
||||
- .NET 8 SDK
|
||||
- Windows 10/11
|
||||
|
||||
---
|
||||
|
||||
## ?? Changelog
|
||||
|
||||
### v2.0 (Attuale)
|
||||
- ? **Nuova modalità Multi-Asta**
|
||||
- ? Monitoraggio simultaneo preferiti
|
||||
- ? Selezione intelligente asta prioritaria
|
||||
- ? Pannello "Asta Attiva"
|
||||
- ? Ottimizzazione risorse (singola WebView)
|
||||
- ?? Fix contatore reset
|
||||
- ?? Fix tracciamento bidder
|
||||
- ? Performance polling dinamico
|
||||
|
||||
### v1.x
|
||||
- ? Modalità Asta Singola
|
||||
- ? Lettura diretta variabili JS Bidoo
|
||||
- ? Multi-click opzionale
|
||||
- ? Limiti prezzo e click
|
||||
- ? Tracciamento utenti
|
||||
- ? Log operazioni
|
||||
|
||||
---
|
||||
|
||||
## ? FAQ
|
||||
|
||||
**Q: AutoBidder è legale?**
|
||||
A: Sì, automatizza solo azioni che potresti fare manualmente. Non viola ToS di Bidoo.
|
||||
|
||||
**Q: Posso vincere sempre?**
|
||||
A: No, AutoBidder aumenta le possibilità ma non garantisce vincite. Dipende da competizione e configurazione.
|
||||
|
||||
**Q: Quante aste posso monitorare?**
|
||||
A: In Multi-Asta: idealmente 10-15 per performance ottimali. Tecnicamente illimitate.
|
||||
|
||||
**Q: Funziona su Mac/Linux?**
|
||||
A: No, richiede Windows per WebView2. Possibile port futuro con Avalonia.
|
||||
|
||||
**Q: AutoBidder consuma molti click?**
|
||||
A: Dipende da configurazione. Usa Max Clicks e Timer Click appropriati per controllare consumo.
|
||||
|
||||
**Q: Posso usare più istanze?**
|
||||
A: Sì, puoi aprire nuove finestre (click destro su link asta). Attenzione al consumo risorse.
|
||||
|
||||
---
|
||||
|
||||
## ?? Supporto
|
||||
|
||||
### Problemi Comuni
|
||||
1. **Errore WebView2**: Installa Microsoft Edge
|
||||
2. **Click non funziona**: Ricarica pagina
|
||||
3. **Lag**: Riduci preferiti in Multi-Asta
|
||||
4. **Crash**: Verifica .NET 8 installato
|
||||
|
||||
### Contatti
|
||||
- ?? **Bug Report**: Apri issue su repository
|
||||
- ?? **Feature Request**: Suggerisci miglioramenti
|
||||
- ?? **Documentazione**: Leggi guide incluse
|
||||
|
||||
---
|
||||
|
||||
## ?? Licenza
|
||||
|
||||
Questo software è fornito "così com'è" senza garanzie.
|
||||
L'uso è a proprio rischio e responsabilità.
|
||||
|
||||
**Disclaimer**: AutoBidder è uno strumento di automazione per uso personale. L'utente è responsabile del rispetto dei termini di servizio di Bidoo.
|
||||
|
||||
---
|
||||
|
||||
## ?? Ringraziamenti
|
||||
|
||||
Grazie a tutti gli utenti per feedback e testing!
|
||||
|
||||
**Buone aste! ????**
|
||||
478
Mimante/Services/AuctionMonitor.cs
Normal file
478
Mimante/Services/AuctionMonitor.cs
Normal file
@@ -0,0 +1,478 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AutoBidder.Models;
|
||||
|
||||
namespace AutoBidder.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Servizio centrale per monitoraggio multi-asta
|
||||
/// Gestisce polling API Bidoo e trigger dei click
|
||||
/// </summary>
|
||||
public class AuctionMonitor
|
||||
{
|
||||
private readonly BidooApiClient _apiClient;
|
||||
private readonly List<AuctionInfo> _auctions = new();
|
||||
private CancellationTokenSource? _monitoringCts;
|
||||
private Task? _monitoringTask;
|
||||
|
||||
public event Action<AuctionState>? OnAuctionUpdated;
|
||||
public event Action<AuctionInfo, BidResult>? OnBidExecuted;
|
||||
public event Action<string>? OnLog;
|
||||
public event Action<string>? OnResetCountChanged; // Notifica cambio contatore reset
|
||||
|
||||
public AuctionMonitor()
|
||||
{
|
||||
_apiClient = new BidooApiClient();
|
||||
|
||||
// Subscribe to detailed per-auction logs from API client
|
||||
_apiClient.OnAuctionLog += (auctionId, message) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_auctions)
|
||||
{
|
||||
var auction = _auctions.FirstOrDefault(a => a.AuctionId == auctionId);
|
||||
if (auction != null)
|
||||
{
|
||||
auction.AddLog(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inizializza sessione con token di autenticazione
|
||||
/// </summary>
|
||||
public void InitializeSession(string authToken, string username)
|
||||
{
|
||||
_apiClient.InitializeSession(authToken, username);
|
||||
OnLog?.Invoke($"[OK] Sessione configurata per: {username}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inizializza sessione con cookie (fallback legacy)
|
||||
/// </summary>
|
||||
public void InitializeSessionWithCookie(string cookieString, string username)
|
||||
{
|
||||
_apiClient.InitializeSessionWithCookie(cookieString, username);
|
||||
OnLog?.Invoke($"[OK] Sessione configurata (cookie) per: {username}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggiorna info utente (puntate rimanenti)
|
||||
/// </summary>
|
||||
public async Task<bool> UpdateUserInfoAsync()
|
||||
{
|
||||
return await _apiClient.UpdateUserInfoAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ottieni sessione corrente
|
||||
/// </summary>
|
||||
public BidooSession GetSession()
|
||||
{
|
||||
return _apiClient.GetSession();
|
||||
}
|
||||
|
||||
public void AddAuction(AuctionInfo auction)
|
||||
{
|
||||
lock (_auctions)
|
||||
{
|
||||
if (!_auctions.Any(a => a.AuctionId == auction.AuctionId))
|
||||
{
|
||||
_auctions.Add(auction);
|
||||
OnLog?.Invoke($"[+] Asta aggiunta: {auction.Name} (ID: {auction.AuctionId})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAuction(string auctionId)
|
||||
{
|
||||
lock (_auctions)
|
||||
{
|
||||
var auction = _auctions.FirstOrDefault(a => a.AuctionId == auctionId);
|
||||
if (auction != null)
|
||||
{
|
||||
_auctions.Remove(auction);
|
||||
OnLog?.Invoke($"[-] Asta rimossa: {auction.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<AuctionInfo> GetAuctions()
|
||||
{
|
||||
lock (_auctions)
|
||||
{
|
||||
return _auctions.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public Task<bool> InitializeCookies(Microsoft.Web.WebView2.Wpf.WebView2 webView)
|
||||
{
|
||||
// Non più utilizzato - usa InitializeSession invece
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_monitoringTask != null && !_monitoringTask.IsCompleted)
|
||||
{
|
||||
OnLog?.Invoke("[WARN] Monitoraggio gia' attivo");
|
||||
return;
|
||||
}
|
||||
|
||||
_monitoringCts = new CancellationTokenSource();
|
||||
_monitoringTask = Task.Run(() => MonitoringLoop(_monitoringCts.Token));
|
||||
OnLog?.Invoke("[START] Monitoraggio avviato");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_monitoringCts?.Cancel();
|
||||
_monitoringTask?.Wait(TimeSpan.FromSeconds(2));
|
||||
_monitoringCts = null;
|
||||
_monitoringTask = null;
|
||||
OnLog?.Invoke("[STOP] Monitoraggio fermato");
|
||||
}
|
||||
|
||||
private async Task MonitoringLoop(CancellationToken token)
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<AuctionInfo> activeAuctions;
|
||||
lock (_auctions)
|
||||
{
|
||||
// Filtra aste che devono ancora essere monitorate
|
||||
// Include aste attive anche se messe in pausa: vogliamo continuare a monitorarle
|
||||
// ma non inviare puntate per quelle in pausa.
|
||||
activeAuctions = _auctions.Where(a =>
|
||||
a.IsActive &&
|
||||
!IsAuctionTerminated(a)
|
||||
).ToList();
|
||||
}
|
||||
|
||||
if (activeAuctions.Count == 0)
|
||||
{
|
||||
await Task.Delay(1000, token);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Poll tutte le aste in parallelo
|
||||
var pollTasks = activeAuctions.Select(a => PollAndProcessAuction(a, token));
|
||||
await Task.WhenAll(pollTasks);
|
||||
|
||||
// Ottimizzazione polling per aste in pausa
|
||||
bool anyPaused = false;
|
||||
DateTime now = DateTime.Now;
|
||||
int pauseDelayMs = 1000; // default
|
||||
foreach (var a in activeAuctions)
|
||||
{
|
||||
if (a.IsPaused)
|
||||
{
|
||||
anyPaused = true;
|
||||
// Se tra le 00:00 e le 09:55 polling ogni 60s
|
||||
if (now.Hour < 9 || (now.Hour == 9 && now.Minute < 55))
|
||||
pauseDelayMs = 60000;
|
||||
// Negli ultimi 5 minuti prima delle 10 polling ogni 5s
|
||||
else if (now.Hour == 9 && now.Minute >= 55)
|
||||
pauseDelayMs = 5000;
|
||||
}
|
||||
}
|
||||
if (anyPaused)
|
||||
{
|
||||
await Task.Delay(pauseDelayMs, token);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Delay adattivo OTTIMIZZATO basato su timer più basso
|
||||
var lowestTimer = activeAuctions
|
||||
.Select(a => GetLastTimer(a))
|
||||
.Where(t => t > 0)
|
||||
.DefaultIfEmpty(999)
|
||||
.Min();
|
||||
|
||||
int delayMs = lowestTimer switch
|
||||
{
|
||||
< 1 => 5, // Iper-veloce: polling ogni 5ms (0-1s rimanenti)
|
||||
< 2 => 20, // Ultra-veloce: polling ogni 20ms (1-2s)
|
||||
< 3 => 50, // Molto veloce: polling ogni 50ms (2-3s)
|
||||
< 5 => 100, // Veloce: polling ogni 100ms (3-5s)
|
||||
< 10 => 200, // Medio: polling ogni 200ms (5-10s)
|
||||
< 30 => 500, // Lento: polling ogni 500ms (10-30s)
|
||||
_ => 1000 // Molto lento: polling ogni 1s (>30s)
|
||||
};
|
||||
|
||||
await Task.Delay(delayMs, token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnLog?.Invoke($"[ERRORE] Loop monitoraggio: {ex.Message}");
|
||||
await Task.Delay(1000, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica se un'asta è terminata e non deve più essere monitorata
|
||||
/// </summary>
|
||||
private bool IsAuctionTerminated(AuctionInfo auction)
|
||||
{
|
||||
// Se l'ultima entry nello storico indica uno stato finale, ferma polling
|
||||
var lastHistory = auction.BidHistory.LastOrDefault();
|
||||
if (lastHistory != null)
|
||||
{
|
||||
// Controlla se c'è una nota che indica fine asta
|
||||
if (lastHistory.Notes != null &&
|
||||
(lastHistory.Notes.Contains("VINTA") ||
|
||||
lastHistory.Notes.Contains("Persa") ||
|
||||
lastHistory.Notes.Contains("Chiusa")))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task PollAndProcessAuction(AuctionInfo auction, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Poll tramite API Bidoo (passa anche l'URL originale per referer corretto)
|
||||
var state = await _apiClient.PollAuctionStateAsync(auction.AuctionId, auction.OriginalUrl, token);
|
||||
|
||||
if (state == null)
|
||||
{
|
||||
auction.AddLog("ERRORE: Nessun dato ricevuto da API");
|
||||
OnLog?.Invoke($"[ERRORE] [{auction.AuctionId}] API non ha risposto");
|
||||
return;
|
||||
}
|
||||
|
||||
// Se l'asta è terminata, segnala e disattiva polling
|
||||
if (state.Status == AuctionStatus.EndedWon ||
|
||||
state.Status == AuctionStatus.EndedLost ||
|
||||
state.Status == AuctionStatus.Closed)
|
||||
{
|
||||
string statusMsg = state.Status == AuctionStatus.EndedWon ? "VINTA" :
|
||||
state.Status == AuctionStatus.EndedLost ? "Persa" : "Chiusa";
|
||||
|
||||
// Mark auction inactive immediately to stop further polling
|
||||
auction.IsActive = false;
|
||||
|
||||
auction.AddLog($"[ASTA TERMINATA] {statusMsg}");
|
||||
OnLog?.Invoke($"[FINE] [{auction.AuctionId}] Asta {statusMsg} - Polling fermato");
|
||||
|
||||
// Aggiungi entry nello storico per marcare come terminata
|
||||
auction.BidHistory.Add(new BidHistory
|
||||
{
|
||||
Timestamp = DateTime.UtcNow,
|
||||
EventType = BidEventType.Reset,
|
||||
Bidder = state.LastBidder,
|
||||
Price = state.Price,
|
||||
Timer = 0,
|
||||
Notes = $"Asta {statusMsg}"
|
||||
});
|
||||
|
||||
// Notifica UI e fermati
|
||||
OnAuctionUpdated?.Invoke(state);
|
||||
return;
|
||||
}
|
||||
|
||||
// Log stato solo per aste attive (riduci spam)
|
||||
if (state.Status == AuctionStatus.Running)
|
||||
{
|
||||
auction.AddLog($"API OK - Timer: {state.Timer:F2}s, EUR{state.Price:F2}, {state.LastBidder}, {state.PollingLatencyMs}ms");
|
||||
}
|
||||
else if (state.Status == AuctionStatus.Paused)
|
||||
{
|
||||
auction.AddLog($"[PAUSA] Asta in pausa - Timer: {state.Timer:F2}s, EUR{state.Price:F2}");
|
||||
}
|
||||
|
||||
// Notifica aggiornamento UI
|
||||
OnAuctionUpdated?.Invoke(state);
|
||||
|
||||
// Aggiorna storico e bidders
|
||||
UpdateAuctionHistory(auction, state);
|
||||
|
||||
// Verifica se puntare (solo se asta Running, NON se in pausa)
|
||||
if (state.Status == AuctionStatus.Running && ShouldBid(auction, state) && !auction.IsPaused)
|
||||
{
|
||||
auction.AddLog($"[TRIGGER] CONDIZIONI OK - Timer {state.Timer:F2}s <= {auction.TimerClick}s");
|
||||
auction.AddLog($"[BID] Invio puntata...");
|
||||
OnLog?.Invoke($"[BID] [{auction.AuctionId}] PUNTATA a {state.Timer:F2}s!");
|
||||
|
||||
// Attendi ritardo configurato
|
||||
if (auction.DelayMs > 0)
|
||||
{
|
||||
await Task.Delay(auction.DelayMs, token);
|
||||
}
|
||||
|
||||
// Esegui puntata API
|
||||
var result = await _apiClient.PlaceBidAsync(auction.AuctionId);
|
||||
|
||||
// Aggiorna contatori
|
||||
if (result.Success)
|
||||
{
|
||||
auction.MyClicks++;
|
||||
auction.LastClickAt = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
// Notifica risultato
|
||||
OnBidExecuted?.Invoke(auction, result);
|
||||
|
||||
// Log
|
||||
if (result.Success)
|
||||
{
|
||||
auction.AddLog($"[OK] PUNTATA OK: {result.LatencyMs}ms -> EUR{result.NewPrice:F2}");
|
||||
OnLog?.Invoke($"[OK] [{auction.AuctionId}] Puntata riuscita {result.LatencyMs}ms");
|
||||
}
|
||||
else
|
||||
{
|
||||
auction.AddLog($"[FAIL] PUNTATA FALLITA: {result.Error}");
|
||||
OnLog?.Invoke($"[FAIL] [{auction.AuctionId}] ERRORE: {result.Error}");
|
||||
}
|
||||
|
||||
// Storico
|
||||
auction.BidHistory.Add(new BidHistory
|
||||
{
|
||||
Timestamp = result.Timestamp,
|
||||
EventType = result.Success ? BidEventType.MyBid : BidEventType.OpponentBid,
|
||||
Bidder = "Tu",
|
||||
Price = state.Price,
|
||||
Timer = state.Timer,
|
||||
LatencyMs = result.LatencyMs,
|
||||
Success = result.Success,
|
||||
Notes = result.Success ? $"EUR{result.NewPrice:F2}" : result.Error
|
||||
});
|
||||
|
||||
// Se abbiamo raggiunto il numero massimo di click per l'asta, metti in pausa le puntate (ma continua il monitor)
|
||||
if (auction.MaxClicks > 0 && auction.MyClicks >= auction.MaxClicks)
|
||||
{
|
||||
auction.IsPaused = true;
|
||||
auction.AddLog($"[PAUSA] Massimo click ({auction.MaxClicks}) raggiunto - Puntate disabilitate");
|
||||
OnLog?.Invoke($"[PAUSA] [{auction.AuctionId}] MaxClicks raggiunti");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
auction.AddLog($"[EXCEPTION] ERRORE: {ex.Message}");
|
||||
OnLog?.Invoke($"[EXCEPTION] [{auction.AuctionId}] {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldBid(AuctionInfo auction, AuctionState state)
|
||||
{
|
||||
// Timer check
|
||||
if (state.Timer > auction.TimerClick)
|
||||
return false;
|
||||
|
||||
// Price check
|
||||
if (auction.MinPrice > 0 && state.Price < auction.MinPrice)
|
||||
return false;
|
||||
|
||||
if (auction.MaxPrice > 0 && state.Price > auction.MaxPrice)
|
||||
return false;
|
||||
|
||||
// Cooldown check (evita click multipli ravvicinati)
|
||||
if (auction.LastClickAt.HasValue)
|
||||
{
|
||||
var timeSinceLastClick = DateTime.UtcNow - auction.LastClickAt.Value;
|
||||
if (timeSinceLastClick.TotalSeconds < 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Max clicks per auction
|
||||
if (auction.MaxClicks > 0 && auction.MyClicks >= auction.MaxClicks)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void UpdateAuctionHistory(AuctionInfo auction, AuctionState state)
|
||||
{
|
||||
// Traccia l'ultima puntata per rilevare cambi
|
||||
var lastHistory = auction.BidHistory.LastOrDefault();
|
||||
var lastPrice = lastHistory?.Price ?? 0;
|
||||
var lastBidder = lastHistory?.Bidder;
|
||||
|
||||
bool isNewBid = false;
|
||||
|
||||
// Nuova puntata = CAMBIO PREZZO (più affidabile)
|
||||
// Ogni incremento di prezzo significa che qualcuno ha puntato
|
||||
if (state.Price > lastPrice && state.Price > 0)
|
||||
{
|
||||
isNewBid = true;
|
||||
}
|
||||
|
||||
// Fallback: cambio utente (se il prezzo è uguale ma l'utente cambia)
|
||||
if (!isNewBid &&
|
||||
!string.IsNullOrEmpty(lastBidder) &&
|
||||
!string.IsNullOrEmpty(state.LastBidder) &&
|
||||
!lastBidder.Equals(state.LastBidder, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
isNewBid = true;
|
||||
}
|
||||
|
||||
if (isNewBid)
|
||||
{
|
||||
auction.ResetCount++;
|
||||
auction.BidHistory.Add(new BidHistory
|
||||
{
|
||||
Timestamp = DateTime.UtcNow,
|
||||
EventType = BidEventType.Reset,
|
||||
Bidder = state.LastBidder,
|
||||
Price = state.Price,
|
||||
Timer = state.Timer,
|
||||
Notes = $"Puntata: EUR{state.Price:F2}"
|
||||
});
|
||||
|
||||
// Aggiorna statistiche bidder
|
||||
if (!string.IsNullOrEmpty(state.LastBidder))
|
||||
{
|
||||
if (!auction.BidderStats.ContainsKey(state.LastBidder))
|
||||
{
|
||||
auction.BidderStats[state.LastBidder] = new BidderInfo
|
||||
{
|
||||
Username = state.LastBidder
|
||||
};
|
||||
}
|
||||
|
||||
auction.BidderStats[state.LastBidder].BidCount++;
|
||||
auction.BidderStats[state.LastBidder].LastBidTime = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
// Notifica cambio reset count per aggiornare UI
|
||||
OnResetCountChanged?.Invoke(auction.AuctionId);
|
||||
}
|
||||
}
|
||||
|
||||
private double GetLastTimer(AuctionInfo auction)
|
||||
{
|
||||
var lastEntry = auction.BidHistory.LastOrDefault();
|
||||
return lastEntry?.Timer ?? 999;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
_apiClient?.Dispose();
|
||||
}
|
||||
|
||||
public async Task<BidResult> PlaceManualBidAsync(AuctionInfo auction)
|
||||
{
|
||||
return await _apiClient.PlaceBidAsync(auction.AuctionId, auction.OriginalUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
627
Mimante/Services/BidooApiClient.cs
Normal file
627
Mimante/Services/BidooApiClient.cs
Normal file
@@ -0,0 +1,627 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text;
|
||||
using AutoBidder.Models;
|
||||
|
||||
namespace AutoBidder.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Servizio completo API Bidoo (polling, puntate, info utente)
|
||||
/// 100% API-based con simulazione completa del comportamento browser
|
||||
///
|
||||
/// FLUSSO DI AUTENTICAZIONE:
|
||||
/// - Cookie principale: __stattr (non PHPSESSID)
|
||||
/// - Il cookie deve essere estratto dal browser dopo login manuale
|
||||
/// - Tutti i request devono includere: Cookie + X-Requested-With: XMLHttpRequest
|
||||
///
|
||||
/// CHIAMATE GET (SOLO LETTURA - No CSRF Token):
|
||||
/// 1. Polling asta: GET data.php?ALL={id}&LISTID=0
|
||||
/// 2. Info utente: GET ajax/get_auction_bids_info_banner.php
|
||||
///
|
||||
/// CHIAMATE POST (AZIONI - Richiedono CSRF Token):
|
||||
/// 1. Piazza puntata: POST bid.php
|
||||
/// - Step 1: GET pagina asta HTML per estrarre bid_token
|
||||
/// - Step 2: POST con payload: a={id}&bid_type=manual&bid_token={token}&time_sent={ts}
|
||||
/// - Step 3: Analizza risposta: "ok|..." o "error|..."
|
||||
///
|
||||
/// SIMULAZIONE BROWSER:
|
||||
/// - User-Agent: Chrome su Windows
|
||||
/// - Headers CORS: Sec-Fetch-*
|
||||
/// - Referer: URL pagina asta
|
||||
/// - Content-Type: application/x-www-form-urlencoded (per POST)
|
||||
/// </summary>
|
||||
public class BidooApiClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private BidooSession _session;
|
||||
|
||||
// Event used to push detailed logs into per-auction log in the monitor
|
||||
public event Action<string, string>? OnAuctionLog;
|
||||
|
||||
public BidooApiClient()
|
||||
{
|
||||
var handler = new HttpClientHandler
|
||||
{
|
||||
UseCookies = false, // Gestiamo manualmente i cookie
|
||||
AutomaticDecompression = System.Net.DecompressionMethods.All // Decomprimi GZIP/Deflate/Brotli
|
||||
};
|
||||
|
||||
_httpClient = new HttpClient(handler)
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(3)
|
||||
};
|
||||
|
||||
_session = new BidooSession();
|
||||
}
|
||||
|
||||
// Helper that writes to Console and, when auctionId provided, emits per-auction log event
|
||||
private void Log(string message, string? auctionId = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(auctionId))
|
||||
{
|
||||
try
|
||||
{
|
||||
OnAuctionLog?.Invoke(auctionId, message);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inizializza sessione con token di autenticazione
|
||||
/// </summary>
|
||||
public void InitializeSession(string authToken, string username)
|
||||
{
|
||||
_session.AuthToken = authToken;
|
||||
_session.Username = username;
|
||||
|
||||
Log($"[SESSION] Token impostato ({authToken.Length} chars)");
|
||||
Log($"[SESSION] Username: {username}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inizializza sessione con cookie string (fallback)
|
||||
/// </summary>
|
||||
public void InitializeSessionWithCookie(string cookieString, string username)
|
||||
{
|
||||
_session.CookieString = cookieString;
|
||||
_session.Username = username;
|
||||
|
||||
Log($"[SESSION] Cookie impostato ({cookieString.Length} chars)");
|
||||
Log($"[SESSION] Username: {username}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggiunge header di autenticazione e browser-like alla richiesta
|
||||
/// Headers critici per evitare rilevamento come bot
|
||||
/// </summary>
|
||||
private void AddAuthHeaders(HttpRequestMessage request, string? referer = null, string? auctionId = null)
|
||||
{
|
||||
// 1. AUTENTICAZIONE (priorità: CookieString completa, poi Token singolo)
|
||||
// Il cookie principale per Bidoo è __stattr (non PHPSESSID)
|
||||
if (!string.IsNullOrWhiteSpace(_session.CookieString))
|
||||
{
|
||||
// Usa la stringa cookie completa (es: "__stattr=eyJyZWZ...")
|
||||
request.Headers.Add("Cookie", _session.CookieString);
|
||||
Log("[AUTH] Using full cookie string", auctionId);
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(_session.AuthToken))
|
||||
{
|
||||
// Fallback: se abbiamo solo il token, assumiamo sia __stattr
|
||||
request.Headers.Add("Cookie", $"__stattr={_session.AuthToken}");
|
||||
Log("[AUTH] Using __stattr token", auctionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[AUTH WARN] No authentication method available!", auctionId);
|
||||
}
|
||||
|
||||
// 2. HEADERS BROWSER-LIKE (anti-detection)
|
||||
|
||||
// User-Agent realistico (Chrome su Windows)
|
||||
request.Headers.Add("User-Agent",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36");
|
||||
|
||||
// Accept headers
|
||||
request.Headers.Add("Accept", "*/*");
|
||||
request.Headers.Add("Accept-Language", "it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7");
|
||||
request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
|
||||
|
||||
// Security headers (critici per CORS)
|
||||
request.Headers.Add("Sec-Fetch-Dest", "empty");
|
||||
request.Headers.Add("Sec-Fetch-Mode", "cors");
|
||||
request.Headers.Add("Sec-Fetch-Site", "same-origin");
|
||||
|
||||
// Chrome-specific headers
|
||||
request.Headers.Add("sec-ch-ua", "\"Google Chrome\";v=\"141\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"141\"");
|
||||
request.Headers.Add("sec-ch-ua-mobile", "?0");
|
||||
request.Headers.Add("sec-ch-ua-platform", "\"Windows\"");
|
||||
|
||||
// XMLHttpRequest identifier (FONDAMENTALE per API AJAX)
|
||||
request.Headers.Add("X-Requested-With", "XMLHttpRequest");
|
||||
|
||||
// Referer (importante per validazione origin)
|
||||
if (!string.IsNullOrEmpty(referer))
|
||||
{
|
||||
request.Headers.Add("Referer", referer);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Headers.Add("Referer", "https://it.bidoo.com/");
|
||||
}
|
||||
|
||||
Log("[HEADERS] Browser-like headers added (anti-bot)", auctionId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estrae CSRF/Bid token dalla pagina asta
|
||||
/// PASSO 1: Ottenere la pagina HTML dell'asta per estrarre il token di sicurezza
|
||||
/// Il token può essere chiamato: bid_token, csrf_token, _token, etc.
|
||||
/// </summary>
|
||||
private async Task<(string? tokenName, string? tokenValue)> ExtractBidTokenAsync(string auctionId, string? auctionUrl = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = !string.IsNullOrEmpty(auctionUrl) ? auctionUrl : $"https://it.bidoo.com/asta/nome-prodotto-{auctionId}";
|
||||
Log($"[TOKEN] GET {url}", auctionId);
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
AddAuthHeaders(request, url, auctionId);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
var html = await response.Content.ReadAsStringAsync();
|
||||
|
||||
Log($"[TOKEN] Response: {response.StatusCode}, HTML length: {html.Length}", auctionId);
|
||||
|
||||
var patterns = new System.Collections.Generic.List<(string pattern, string name)>
|
||||
{
|
||||
// double-quoted input attributes
|
||||
("(?i)<input[^>]*name=\"bid_token\"[^>]*value=\"([^\"]+)\"", "bid_token"),
|
||||
("(?i)<input[^>]*value=\"([^\"]+)\"[^>]*name=\"bid_token\"", "bid_token"),
|
||||
("(?i)<input[^>]*name=\"csrf_token\"[^>]*value=\"([^\"]+)\"", "csrf_token"),
|
||||
("(?i)<input[^>]*value=\"([^\"]+)\"[^>]*name=\"csrf_token\"", "csrf_token"),
|
||||
("(?i)<input[^>]*name=\"_token\"[^>]*value=\"([^\"]+)\"", "_token"),
|
||||
("(?i)<input[^>]*name=\"token\"[^>]*value=\"([^\"]+)\"", "token"),
|
||||
|
||||
// single-quoted input attributes
|
||||
("(?i)<input[^>]*name='bid_token'[^>]*value='([^']+)'", "bid_token"),
|
||||
("(?i)<input[^>]*value='([^']+)'[^>]*name='bid_token'", "bid_token"),
|
||||
("(?i)<input[^>]*name='csrf_token'[^>]*value='([^']+)'", "csrf_token"),
|
||||
("(?i)<input[^>]*value='([^']+)'[^>]*name='csrf_token'", "csrf_token"),
|
||||
("(?i)<input[^>]*name='_token'[^>]*value='([^']+)'", "_token"),
|
||||
("(?i)<input[^>]*name='token'[^>]*value='([^']+)'", "token"),
|
||||
|
||||
// JavaScript style assignments (double and single quotes)
|
||||
("(?i)bid_token\\s*[:=]\\s*\"([^\\\"]+)\"", "bid_token"),
|
||||
("(?i)bid_token\\s*[:=]\\s*'([^']+)'", "bid_token"),
|
||||
("(?i)csrf_token\\s*[:=]\\s*\"([^\\\"]+)\"", "csrf_token"),
|
||||
("(?i)csrf_token\\s*[:=]\\s*'([^']+)'", "csrf_token"),
|
||||
|
||||
// JSON style
|
||||
("\"token\"\\s*:\\s*\"([^\\\"]+)\"", "token")
|
||||
};
|
||||
|
||||
foreach (var pattern in patterns)
|
||||
{
|
||||
var match = System.Text.RegularExpressions.Regex.Match(html, pattern.pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
||||
if (match.Success)
|
||||
{
|
||||
var tokenValue = match.Groups[1].Value;
|
||||
Log($"[TOKEN] ✓ Token found: {pattern.name} = {tokenValue.Substring(0, Math.Min(20, tokenValue.Length))}...", auctionId);
|
||||
return (pattern.name, tokenValue);
|
||||
}
|
||||
}
|
||||
|
||||
Log("[TOKEN] ⚠ No bid token found in HTML", auctionId);
|
||||
return (null, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[TOKEN ERROR] {ex.Message}", auctionId);
|
||||
return (null, null);
|
||||
}
|
||||
}
|
||||
|
||||
private Task<(string? tokenName, string? tokenValue)> ExtractBidTokenAsync(string auctionId)
|
||||
{
|
||||
return ExtractBidTokenAsync(auctionId, null);
|
||||
}
|
||||
|
||||
public async Task<AuctionState?> PollAuctionStateAsync(string auctionId, string? auctionUrl, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
var startTime = DateTime.UtcNow;
|
||||
var url = $"https://it.bidoo.com/data.php?ALL={auctionId}&LISTID=0";
|
||||
|
||||
Log($"[API REQUEST] GET {url}", auctionId);
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
|
||||
var referer = !string.IsNullOrEmpty(auctionUrl)
|
||||
? auctionUrl
|
||||
: $"https://it.bidoo.com/auction.php?a=asta_{auctionId}";
|
||||
|
||||
Log($"[API REQUEST] Using referer: {referer}", auctionId);
|
||||
AddAuthHeaders(request, referer, auctionId);
|
||||
|
||||
var response = await _httpClient.SendAsync(request, token);
|
||||
var latency = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
|
||||
|
||||
Log($"[API RESPONSE] Status: {(int)response.StatusCode} {response.StatusCode}", auctionId);
|
||||
Log($"[API RESPONSE] Latency: {latency}ms", auctionId);
|
||||
Log($"[API RESPONSE] Content-Type: {response.Content.Headers.ContentType}", auctionId);
|
||||
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
Log($"[API RESPONSE] Body ({responseText.Length} bytes): {responseText}", auctionId);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
Log($"[API ERROR] Non-success status code: {response.StatusCode}", auctionId);
|
||||
return null;
|
||||
}
|
||||
|
||||
return ParsePollingResponse(auctionId, responseText, latency);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[API EXCEPTION] Polling {auctionId}: {ex.GetType().Name} - {ex.Message}", auctionId);
|
||||
Log($"[API EXCEPTION] StackTrace: {ex.StackTrace}", auctionId);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private AuctionState? ParsePollingResponse(string auctionId, string response, int latency)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log($"[PARSE] Starting parse for auction {auctionId}", auctionId);
|
||||
Log($"[PARSE] Raw response: {response}", auctionId);
|
||||
|
||||
// Step 1: Estrai Server Timestamp (può avere formato "timestamp*..." o "timestamp|flag*")
|
||||
string serverTimestamp;
|
||||
string mainData;
|
||||
|
||||
// Cerca il separatore '*' che divide timestamp da dati
|
||||
var starIndex = response.IndexOf('*');
|
||||
if (starIndex == -1)
|
||||
{
|
||||
Log("[PARSE ERROR] No '*' separator found in response", auctionId);
|
||||
return null;
|
||||
}
|
||||
|
||||
var timestampPart = response.Substring(0, starIndex);
|
||||
mainData = response.Substring(starIndex + 1);
|
||||
|
||||
// Il timestamp può contenere '|' (es: "1761120002|1")
|
||||
// Prendiamo solo la prima parte numerica
|
||||
if (timestampPart.Contains('|'))
|
||||
{
|
||||
serverTimestamp = timestampPart.Split('|')[0];
|
||||
Log($"[PARSE] Extended format detected: {timestampPart}", auctionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverTimestamp = timestampPart;
|
||||
}
|
||||
|
||||
Log($"[PARSE] Server Timestamp: {serverTimestamp}", auctionId);
|
||||
Log($"[PARSE] Main Data: {mainData}", auctionId);
|
||||
|
||||
// Step 2: Estrai dati asta tra parentesi quadre [...]
|
||||
var bracketStart = mainData.IndexOf('[');
|
||||
var bracketEnd = mainData.IndexOf(']');
|
||||
|
||||
if (bracketStart == -1 || bracketEnd == -1)
|
||||
{
|
||||
Log("[PARSE ERROR] Missing brackets in auction data", auctionId);
|
||||
return null;
|
||||
}
|
||||
|
||||
var auctionData = mainData.Substring(bracketStart + 1, bracketEnd - bracketStart - 1);
|
||||
Log($"[PARSE] Auction Data extracted: {auctionData}", auctionId);
|
||||
|
||||
// Step 3: Split per ';' per ottenere i campi principali
|
||||
// Nota: la stringa può contenere '|' per separare bid history, quindi ci fermiamo al primo '|' o ','
|
||||
var firstSeparator = auctionData.IndexOfAny(new[] { '|', ',' });
|
||||
var coreData = firstSeparator > 0 ? auctionData.Substring(0, firstSeparator) : auctionData;
|
||||
|
||||
var fields = coreData.Split(';');
|
||||
Log($"[PARSE] Core fields count: {fields.Length}", auctionId);
|
||||
for (int i = 0; i < Math.Min(fields.Length, 10); i++)
|
||||
{
|
||||
Log($"[PARSE] Field[{i}] = '{fields[i]}'", auctionId);
|
||||
}
|
||||
|
||||
if (fields.Length < 5)
|
||||
{
|
||||
Log($"[PARSE ERROR] Expected at least 5 core fields, got {fields.Length}", auctionId);
|
||||
return null;
|
||||
}
|
||||
|
||||
var state = new AuctionState
|
||||
{
|
||||
AuctionId = auctionId,
|
||||
SnapshotTime = DateTime.UtcNow,
|
||||
PollingLatencyMs = latency
|
||||
};
|
||||
|
||||
// Step 4: Parse campi principali
|
||||
|
||||
// Field 0: AuctionID (verifica)
|
||||
Log($"[PARSE] Auction ID from response: {fields[0]} (expected: {auctionId})", auctionId);
|
||||
|
||||
// Field 1: Status (ON/OFF)
|
||||
var status = fields[1].Trim().ToUpperInvariant();
|
||||
|
||||
// Determiniamo lo stato in base a: Status API + LastBidder + Timer
|
||||
// Parsing di Field 4 (LastBidder) anticipato per logica stato
|
||||
string lastBidder = fields[4].Trim();
|
||||
bool hasWinner = !string.IsNullOrEmpty(lastBidder);
|
||||
bool iAmWinner = hasWinner && lastBidder.Equals(_session.Username, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
state.Status = DetermineAuctionStatus(status, hasWinner, iAmWinner, ref state);
|
||||
|
||||
Log($"[PARSE] Status: {status} -> {state.Status}", auctionId);
|
||||
|
||||
// Field 2: Expiry Timestamp (CRITICO per timing)
|
||||
// IMPORTANTE: Usa il ServerTimestamp dalla risposta, NON il tempo locale!
|
||||
// Formato: ServerTimestamp*[..;ExpiryTimestamp;..]
|
||||
// Timer = ExpiryTimestamp - ServerTimestamp
|
||||
if (long.TryParse(serverTimestamp, out var serverTs) && long.TryParse(fields[2], out var expiryTs))
|
||||
{
|
||||
// Calcolo corretto usando il tempo del server
|
||||
var timerSeconds = (double)(expiryTs - serverTs);
|
||||
state.Timer = Math.Max(0, timerSeconds);
|
||||
|
||||
Log($"[PARSE] Server Timestamp: {serverTs}", auctionId);
|
||||
Log($"[PARSE] Expiry Timestamp: {expiryTs}", auctionId);
|
||||
Log($"[PARSE] Timer (Expiry - Server): {expiryTs} - {serverTs} = {timerSeconds:F2}s", auctionId);
|
||||
Log($"[PARSE] ⏱️ Final Timer: {state.Timer:F2}s", auctionId);
|
||||
|
||||
// DEBUG: Verifica se il timer sembra sbagliato
|
||||
if (state.Timer > 60)
|
||||
{
|
||||
Log("[PARSE WARN] Timer unusually high! Check data", auctionId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"[PARSE WARN] Failed to parse timestamps - Server: {serverTimestamp}, Expiry: {fields[2]}", auctionId);
|
||||
}
|
||||
|
||||
// Field 3: Price Index (0.01 EUR per index)
|
||||
if (int.TryParse(fields[3], out var priceIndex))
|
||||
{
|
||||
state.Price = priceIndex * 0.01;
|
||||
Log($"[PARSE] Price Index: {priceIndex} -> €{state.Price:F2}", auctionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"[PARSE WARN] Failed to parse price index: {fields[3]}", auctionId);
|
||||
}
|
||||
|
||||
// Field 4: Last Bidder
|
||||
state.LastBidder = fields[4].Trim();
|
||||
state.IsMyBid = !string.IsNullOrEmpty(_session.Username) &&
|
||||
state.LastBidder.Equals(_session.Username, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
Log($"[PARSE] 👤 Last Bidder: {state.LastBidder}", auctionId);
|
||||
Log($"[PARSE] Is My Bid: {state.IsMyBid} (my username: {_session.Username})", auctionId);
|
||||
|
||||
// Field 5 (optional): Additional flags or data
|
||||
if (fields.Length > 5)
|
||||
{
|
||||
Log($"[PARSE] Additional data fields present: {fields.Length - 5}", auctionId);
|
||||
}
|
||||
|
||||
state.ParsingSuccess = true;
|
||||
|
||||
Log($"[PARSE SUCCESS] ✓ Timer: {state.Timer:F2}s, Price: €{state.Price:F2}, Bidder: {state.LastBidder}, Status: {state.Status}", auctionId);
|
||||
|
||||
return state;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[PARSE EXCEPTION] {ex.GetType().Name}: {ex.Message}", auctionId);
|
||||
Log($"[PARSE EXCEPTION] StackTrace: {ex.StackTrace}", auctionId);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateUserInfoAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = "https://it.bidoo.com/ajax/get_auction_bids_info_banner.php";
|
||||
|
||||
Log($"[USER INFO REQUEST] GET {url}");
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
AddAuthHeaders(request, "https://it.bidoo.com/");
|
||||
|
||||
var startTime = DateTime.UtcNow;
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
var latency = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
|
||||
|
||||
Log($"[USER INFO RESPONSE] Status: {(int)response.StatusCode} {response.StatusCode}");
|
||||
Log($"[USER INFO RESPONSE] Latency: {latency}ms");
|
||||
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
Log($"[USER INFO RESPONSE] Body: {responseText}");
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
Log($"[USER INFO ERROR] HTTP {response.StatusCode}");
|
||||
return false;
|
||||
}
|
||||
|
||||
_session.LastAccountUpdate = DateTime.UtcNow;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[USER INFO EXCEPTION] {ex.GetType().Name}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<BidResult> PlaceBidAsync(string auctionId, string? auctionUrl = null)
|
||||
{
|
||||
var result = new BidResult
|
||||
{
|
||||
AuctionId = auctionId,
|
||||
Timestamp = DateTime.UtcNow
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
Log($"[BID] Placing bid via direct GET to bid.php (no token)", auctionId);
|
||||
|
||||
var url = "https://it.bidoo.com/bid.php";
|
||||
var payload = $"AID={WebUtility.UrlEncode(auctionId)}&sup=0&shock=0";
|
||||
|
||||
Log($"[BID REQUEST] GET {url}?{payload}", auctionId);
|
||||
|
||||
var getUrl = url + "?" + payload;
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, getUrl);
|
||||
|
||||
var referer = !string.IsNullOrEmpty(auctionUrl) ? auctionUrl : $"https://it.bidoo.com/asta/nome-prodotto-{auctionId}";
|
||||
AddAuthHeaders(request, referer, auctionId);
|
||||
if (!request.Headers.Contains("Origin"))
|
||||
{
|
||||
request.Headers.Add("Origin", "https://it.bidoo.com");
|
||||
}
|
||||
|
||||
var startTime = DateTime.UtcNow;
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
result.LatencyMs = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
|
||||
|
||||
Log($"[BID RESPONSE] Status: {(int)response.StatusCode} {response.StatusCode}", auctionId);
|
||||
Log($"[BID RESPONSE] Latency: {result.LatencyMs}ms", auctionId);
|
||||
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
result.Response = responseText;
|
||||
|
||||
Log($"[BID RESPONSE] Body ({responseText.Length} bytes): {responseText}", auctionId);
|
||||
|
||||
if (responseText.StartsWith("ok", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result.Success = true;
|
||||
var parts = responseText.Split('|');
|
||||
if (parts.Length > 1 && double.TryParse(parts[1], out var priceIndex))
|
||||
{
|
||||
result.NewPrice = priceIndex * 0.01;
|
||||
}
|
||||
|
||||
Log("[BID SUCCESS] ✓ Bid placed successfully via GET", auctionId);
|
||||
}
|
||||
else if (responseText.StartsWith("error", StringComparison.OrdinalIgnoreCase) || responseText.StartsWith("no|", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result.Success = false;
|
||||
var parts = responseText.Split('|');
|
||||
result.Error = parts.Length > 1 ? parts[1] : responseText;
|
||||
Log($"[BID ERROR] Server returned error: {result.Error}", auctionId);
|
||||
}
|
||||
else if (responseText.Contains("alive"))
|
||||
{
|
||||
result.Success = false;
|
||||
result.Error = "Keep-alive response (not a bid response)";
|
||||
Log($"[BID WARN] Received keep-alive instead of bid confirmation", auctionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Success = false;
|
||||
result.Error = string.IsNullOrEmpty(responseText) ? $"HTTP {(int)response.StatusCode}" : responseText;
|
||||
Log($"[BID ERROR] Unexpected response format: {result.Error}", auctionId);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Error = ex.Message;
|
||||
Log($"[BID EXCEPTION] {ex.GetType().Name}: {ex.Message}", auctionId);
|
||||
Log($"[BID EXCEPTION] StackTrace: {ex.StackTrace}", auctionId);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determina lo stato dell'asta basandosi su Status, LastBidder, Timer
|
||||
///
|
||||
/// STATI API BIDOO:
|
||||
/// - ON: Asta attiva e in corso
|
||||
/// - OFF: Asta terminata definitivamente
|
||||
/// - STOP: Asta in pausa (tipicamente 00:00-10:00) - riprenderà più tardi
|
||||
/// </summary>
|
||||
private AuctionStatus DetermineAuctionStatus(string apiStatus, bool hasWinner, bool iAmWinner, ref AuctionState state)
|
||||
{
|
||||
// Gestione stato STOP (pausa notturna)
|
||||
if (apiStatus == "STOP")
|
||||
{
|
||||
// L'asta è iniziata ma è in pausa
|
||||
// Controlla se c'è già un vincitore temporaneo
|
||||
if (hasWinner)
|
||||
{
|
||||
state.LastBidder = state.LastBidder; // Mantieni il last bidder
|
||||
return AuctionStatus.Paused;
|
||||
}
|
||||
// Pausa senza puntate ancora
|
||||
return AuctionStatus.Paused;
|
||||
}
|
||||
|
||||
if (apiStatus == "OFF")
|
||||
{
|
||||
// Asta terminata definitivamente
|
||||
if (hasWinner)
|
||||
{
|
||||
return iAmWinner ? AuctionStatus.EndedWon : AuctionStatus.EndedLost;
|
||||
}
|
||||
return AuctionStatus.Closed;
|
||||
}
|
||||
|
||||
if (apiStatus == "ON")
|
||||
{
|
||||
// Asta attiva
|
||||
if (hasWinner)
|
||||
{
|
||||
// Ci sono già puntate → Running
|
||||
return AuctionStatus.Running;
|
||||
}
|
||||
|
||||
// Nessuna puntata ancora → Pending o Scheduled
|
||||
// Se timer molto alto (> 30 minuti), è programmata per più tardi
|
||||
if (state.Timer > 1800) // 30 minuti
|
||||
{
|
||||
return AuctionStatus.Scheduled;
|
||||
}
|
||||
|
||||
// Altrimenti sta per iniziare
|
||||
return AuctionStatus.Pending;
|
||||
}
|
||||
|
||||
return AuctionStatus.Unknown;
|
||||
}
|
||||
|
||||
public BidooSession GetSession() => _session;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_httpClient?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
143
Mimante/Services/SessionManager.cs
Normal file
143
Mimante/Services/SessionManager.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using AutoBidder.Models;
|
||||
|
||||
namespace AutoBidder.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Gestore persistenza sessione Bidoo
|
||||
/// Salva in modo sicuro il cookie di autenticazione per riutilizzo
|
||||
/// </summary>
|
||||
public class SessionManager
|
||||
{
|
||||
private static readonly string SessionFilePath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"AutoBidder",
|
||||
"session.dat"
|
||||
);
|
||||
|
||||
private static readonly byte[] Entropy = Encoding.UTF8.GetBytes("AutoBidder_V1_2025");
|
||||
|
||||
/// <summary>
|
||||
/// Salva la sessione in modo sicuro (crittografata con DPAPI)
|
||||
/// </summary>
|
||||
public static bool SaveSession(BidooSession session)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Crea directory se non esiste
|
||||
var directory = Path.GetDirectoryName(SessionFilePath);
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
// Serializza sessione in JSON
|
||||
var json = JsonSerializer.Serialize(session, new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
});
|
||||
|
||||
// Cripta usando DPAPI (Windows Data Protection API)
|
||||
var plainBytes = Encoding.UTF8.GetBytes(json);
|
||||
var encryptedBytes = ProtectedData.Protect(plainBytes, Entropy, DataProtectionScope.CurrentUser);
|
||||
|
||||
// Salva su file
|
||||
File.WriteAllBytes(SessionFilePath, encryptedBytes);
|
||||
|
||||
Console.WriteLine($"[SESSION] Saved to: {SessionFilePath}");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[SESSION ERROR] Failed to save: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carica la sessione salvata (decripta con DPAPI)
|
||||
/// </summary>
|
||||
public static BidooSession? LoadSession()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(SessionFilePath))
|
||||
{
|
||||
Console.WriteLine($"[SESSION] No saved session found");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Leggi file crittografato
|
||||
var encryptedBytes = File.ReadAllBytes(SessionFilePath);
|
||||
|
||||
// Decripta usando DPAPI
|
||||
var plainBytes = ProtectedData.Unprotect(encryptedBytes, Entropy, DataProtectionScope.CurrentUser);
|
||||
var json = Encoding.UTF8.GetString(plainBytes);
|
||||
|
||||
// Deserializza JSON
|
||||
var session = JsonSerializer.Deserialize<BidooSession>(json);
|
||||
|
||||
if (session != null && session.IsValid)
|
||||
{
|
||||
Console.WriteLine($"[SESSION] Loaded from: {SessionFilePath}");
|
||||
Console.WriteLine($"[SESSION] Username: {session.Username}");
|
||||
return session;
|
||||
}
|
||||
|
||||
Console.WriteLine($"[SESSION] Loaded session is invalid");
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[SESSION ERROR] Failed to load: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elimina la sessione salvata
|
||||
/// </summary>
|
||||
public static bool ClearSession()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(SessionFilePath))
|
||||
{
|
||||
File.Delete(SessionFilePath);
|
||||
Console.WriteLine($"[SESSION] Cleared: {SessionFilePath}");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[SESSION ERROR] Failed to clear: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica se esiste una sessione salvata
|
||||
/// </summary>
|
||||
public static bool HasSavedSession()
|
||||
{
|
||||
return File.Exists(SessionFilePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ottiene informazioni sulla sessione salvata senza caricarla
|
||||
/// </summary>
|
||||
public static (bool exists, DateTime? lastModified) GetSessionInfo()
|
||||
{
|
||||
if (File.Exists(SessionFilePath))
|
||||
{
|
||||
var fileInfo = new FileInfo(SessionFilePath);
|
||||
return (true, fileInfo.LastWriteTime);
|
||||
}
|
||||
return (false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
154
Mimante/Tests/TestBidooApi.cs
Normal file
154
Mimante/Tests/TestBidooApi.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AutoBidder.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test manuale delle API Bidoo
|
||||
/// Compilare e eseguire per testare le chiamate
|
||||
/// </summary>
|
||||
public class TestBidooApi
|
||||
{
|
||||
public static async Task RunAsync(string[] args)
|
||||
{
|
||||
Console.WriteLine("=== TEST MANUALE API BIDOO ===\n");
|
||||
|
||||
// CONFIGURAZIONE
|
||||
Console.Write("Inserisci il cookie __stattr: ");
|
||||
string? cookie = Console.ReadLine();
|
||||
|
||||
Console.Write("Inserisci l'ID asta (es: 81417915): ");
|
||||
string? auctionId = Console.ReadLine();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(cookie) || string.IsNullOrWhiteSpace(auctionId))
|
||||
{
|
||||
Console.WriteLine("? Cookie o Auction ID mancanti!");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("\n--- Test 1: Polling Stato Asta ---");
|
||||
await TestPollingAsync(cookie, auctionId);
|
||||
|
||||
Console.WriteLine("\n--- Test 2: Info Utente ---");
|
||||
await TestUserInfoAsync(cookie);
|
||||
|
||||
Console.WriteLine("? Test completati! Premi un tasto per uscire...");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test chiamata polling asta
|
||||
/// </summary>
|
||||
private static async Task TestPollingAsync(string cookie, string auctionId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var handler = new HttpClientHandler { UseCookies = false };
|
||||
using var client = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(5) };
|
||||
|
||||
var url = $"https://it.bidoo.com/data.php?ALL={auctionId}&LISTID=0";
|
||||
Console.WriteLine($"?? GET {url}");
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
|
||||
// Headers
|
||||
request.Headers.Add("Cookie", $"__stattr={cookie}");
|
||||
request.Headers.Add("X-Requested-With", "XMLHttpRequest");
|
||||
request.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
|
||||
request.Headers.Add("Referer", $"https://it.bidoo.com/asta/nome-prodotto-{auctionId}");
|
||||
|
||||
var startTime = DateTime.UtcNow;
|
||||
var response = await client.SendAsync(request);
|
||||
var latency = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
|
||||
|
||||
Console.WriteLine($"?? Status: {(int)response.StatusCode} {response.StatusCode}");
|
||||
Console.WriteLine($"?? Latency: {latency}ms");
|
||||
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
Console.WriteLine($"?? Response ({responseText.Length} bytes):");
|
||||
Console.WriteLine(responseText);
|
||||
|
||||
// Parse semplice
|
||||
if (response.IsSuccessStatusCode && responseText.Contains("*"))
|
||||
{
|
||||
Console.WriteLine("\n?? Parsing:");
|
||||
var parts = responseText.Split('*');
|
||||
Console.WriteLine($" Server Time: {parts[0]}");
|
||||
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
var data = parts[1].Replace("[", "").Replace("]", "").Split(';');
|
||||
if (data.Length >= 5)
|
||||
{
|
||||
Console.WriteLine($" Auction ID: {data[0]}");
|
||||
Console.WriteLine($" Status: {data[1]}");
|
||||
Console.WriteLine($" Expiry: {data[2]}");
|
||||
|
||||
if (int.TryParse(data[3], out var priceIndex))
|
||||
{
|
||||
Console.WriteLine($" Price: {priceIndex} ? €{(priceIndex * 0.01):F2}");
|
||||
}
|
||||
|
||||
Console.WriteLine($" Last Bidder: {data[4]}");
|
||||
|
||||
// Calcola timer
|
||||
if (long.TryParse(data[2], out var expiryTs))
|
||||
{
|
||||
var expiryTime = DateTimeOffset.FromUnixTimeSeconds(expiryTs);
|
||||
var timer = (expiryTime - DateTimeOffset.UtcNow).TotalSeconds;
|
||||
Console.WriteLine($" Timer: {Math.Max(0, timer):F2}s");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("?? Risposta non valida o errore");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"? Errore: {ex.GetType().Name} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test chiamata info utente
|
||||
/// </summary>
|
||||
private static async Task TestUserInfoAsync(string cookie)
|
||||
{
|
||||
try
|
||||
{
|
||||
var handler = new HttpClientHandler { UseCookies = false };
|
||||
using var client = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(5) };
|
||||
|
||||
var url = "https://it.bidoo.com/ajax/get_auction_bids_info_banner.php";
|
||||
Console.WriteLine($"?? GET {url}");
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
|
||||
// Headers
|
||||
request.Headers.Add("Cookie", $"__stattr={cookie}");
|
||||
request.Headers.Add("X-Requested-With", "XMLHttpRequest");
|
||||
request.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
|
||||
request.Headers.Add("Referer", "https://it.bidoo.com/");
|
||||
|
||||
var startTime = DateTime.UtcNow;
|
||||
var response = await client.SendAsync(request);
|
||||
var latency = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
|
||||
|
||||
Console.WriteLine($"?? Status: {(int)response.StatusCode} {response.StatusCode}");
|
||||
Console.WriteLine($"?? Latency: {latency}ms");
|
||||
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
Console.WriteLine($"?? Response ({responseText.Length} bytes):");
|
||||
Console.WriteLine(responseText);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"? Errore: {ex.GetType().Name} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
Mimante/Utilities/CsvExporter.cs
Normal file
129
Mimante/Utilities/CsvExporter.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using AutoBidder.Models;
|
||||
|
||||
namespace AutoBidder.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Esporta statistiche aste in formato CSV
|
||||
/// </summary>
|
||||
public static class CsvExporter
|
||||
{
|
||||
/// <summary>
|
||||
/// Esporta cronologia completa di un'asta in CSV
|
||||
/// </summary>
|
||||
public static void ExportAuctionHistory(AuctionInfo auction, string filePath)
|
||||
{
|
||||
var csv = new StringBuilder();
|
||||
|
||||
// Header
|
||||
csv.AppendLine("Timestamp,Event Type,Bidder,Price,Timer,Latency (ms),Success,Notes");
|
||||
|
||||
// Data
|
||||
foreach (var entry in auction.BidHistory.OrderBy(h => h.Timestamp))
|
||||
{
|
||||
csv.AppendLine($"{entry.Timestamp:yyyy-MM-dd HH:mm:ss.fff}," +
|
||||
$"{entry.EventType}," +
|
||||
$"\"{entry.Bidder}\"," +
|
||||
$"{entry.Price:F2}," +
|
||||
$"{entry.Timer:F2}," +
|
||||
$"{entry.LatencyMs}," +
|
||||
$"{entry.Success}," +
|
||||
$"\"{entry.Notes}\"");
|
||||
}
|
||||
|
||||
File.WriteAllText(filePath, csv.ToString(), Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esporta statistiche aggregate di un'asta in CSV
|
||||
/// </summary>
|
||||
public static void ExportAuctionStatistics(AuctionInfo auction, string filePath)
|
||||
{
|
||||
var stats = AuctionStatistics.Calculate(auction);
|
||||
var csv = new StringBuilder();
|
||||
|
||||
// Informazioni asta
|
||||
csv.AppendLine("=== AUCTION INFO ===");
|
||||
csv.AppendLine($"Auction ID,{stats.AuctionId}");
|
||||
csv.AppendLine($"Name,\"{stats.Name}\"");
|
||||
csv.AppendLine($"Monitoring Started,{stats.MonitoringStarted:yyyy-MM-dd HH:mm:ss}");
|
||||
csv.AppendLine($"Monitoring Duration,{stats.MonitoringDuration}");
|
||||
csv.AppendLine();
|
||||
|
||||
// Contatori
|
||||
csv.AppendLine("=== COUNTERS ===");
|
||||
csv.AppendLine($"Total Bids,{stats.TotalBids}");
|
||||
csv.AppendLine($"My Bids,{stats.MyBids}");
|
||||
csv.AppendLine($"Opponent Bids,{stats.OpponentBids}");
|
||||
csv.AppendLine($"Resets,{stats.Resets}");
|
||||
csv.AppendLine($"Unique Bidders,{stats.UniqueBidders}");
|
||||
csv.AppendLine();
|
||||
|
||||
// Prezzi
|
||||
csv.AppendLine("=== PRICES ===");
|
||||
csv.AppendLine($"Start Price,{stats.StartPrice:F2}");
|
||||
csv.AppendLine($"Current Price,{stats.CurrentPrice:F2}");
|
||||
csv.AppendLine($"Min Price,{stats.MinPrice:F2}");
|
||||
csv.AppendLine($"Max Price,{stats.MaxPrice:F2}");
|
||||
csv.AppendLine($"Avg Price,{stats.AvgPrice:F2}");
|
||||
csv.AppendLine();
|
||||
|
||||
// Performance
|
||||
csv.AppendLine("=== PERFORMANCE ===");
|
||||
csv.AppendLine($"Avg Click Latency (ms),{stats.AvgClickLatencyMs}");
|
||||
csv.AppendLine($"Min Click Latency (ms),{stats.MinClickLatencyMs}");
|
||||
csv.AppendLine($"Max Click Latency (ms),{stats.MaxClickLatencyMs}");
|
||||
csv.AppendLine($"Bids Per Minute,{stats.BidsPerMinute:F2}");
|
||||
csv.AppendLine($"Resets Per Hour,{stats.ResetsPerHour:F2}");
|
||||
csv.AppendLine($"My Bid Success Rate,{stats.MyBidSuccessRate:F1}%");
|
||||
csv.AppendLine();
|
||||
|
||||
// Competitor ranking
|
||||
csv.AppendLine("=== BIDDER RANKING ===");
|
||||
csv.AppendLine("Bidder,Bids Count");
|
||||
foreach (var bidder in stats.BidderRanking.OrderByDescending(b => b.Value))
|
||||
{
|
||||
csv.AppendLine($"\"{bidder.Key}\",{bidder.Value}");
|
||||
}
|
||||
|
||||
File.WriteAllText(filePath, csv.ToString(), Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esporta tutte le aste in un unico CSV
|
||||
/// </summary>
|
||||
public static void ExportAllAuctions(IEnumerable<AuctionInfo> auctions, string filePath)
|
||||
{
|
||||
var csv = new StringBuilder();
|
||||
|
||||
// Header
|
||||
csv.AppendLine("Auction ID,Name,Timer Click,Delay (ms),Min Price,Max Price," +
|
||||
"My Clicks,Resets,Total Bidders,Active,Paused," +
|
||||
"Added At,Last Click At");
|
||||
|
||||
// Data
|
||||
foreach (var auction in auctions)
|
||||
{
|
||||
csv.AppendLine($"{auction.AuctionId}," +
|
||||
$"\"{auction.Name}\"," +
|
||||
$"{auction.TimerClick}," +
|
||||
$"{auction.DelayMs}," +
|
||||
$"{auction.MinPrice:F2}," +
|
||||
$"{auction.MaxPrice:F2}," +
|
||||
$"{auction.MyClicks}," +
|
||||
$"{auction.ResetCount}," +
|
||||
$"{auction.Bidders.Count}," +
|
||||
$"{auction.IsActive}," +
|
||||
$"{auction.IsPaused}," +
|
||||
$"{auction.AddedAt:yyyy-MM-dd HH:mm:ss}," +
|
||||
$"{(auction.LastClickAt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "")}");
|
||||
}
|
||||
|
||||
File.WriteAllText(filePath, csv.ToString(), Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Mimante/Utilities/PersistenceManager.cs
Normal file
77
Mimante/Utilities/PersistenceManager.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using AutoBidder.Models;
|
||||
|
||||
namespace AutoBidder.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Gestisce salvataggio/caricamento lista aste
|
||||
/// </summary>
|
||||
public static class PersistenceManager
|
||||
{
|
||||
private static readonly string AppDataFolder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"AutoBidder"
|
||||
);
|
||||
|
||||
private static readonly string AuctionsFilePath = Path.Combine(AppDataFolder, "auctions.json");
|
||||
|
||||
/// <summary>
|
||||
/// Salva lista aste su disco
|
||||
/// </summary>
|
||||
public static void SaveAuctions(IEnumerable<AuctionInfo> auctions)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Crea cartella se non esiste
|
||||
if (!Directory.Exists(AppDataFolder))
|
||||
{
|
||||
Directory.CreateDirectory(AppDataFolder);
|
||||
}
|
||||
|
||||
// Serializza in JSON
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(auctions, options);
|
||||
File.WriteAllText(AuctionsFilePath, json);
|
||||
|
||||
Console.WriteLine($"? Aste salvate in {AuctionsFilePath}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"? Errore salvataggio aste: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carica lista aste da disco
|
||||
/// </summary>
|
||||
public static List<AuctionInfo> LoadAuctions()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(AuctionsFilePath))
|
||||
{
|
||||
return new List<AuctionInfo>();
|
||||
}
|
||||
|
||||
var json = File.ReadAllText(AuctionsFilePath);
|
||||
var auctions = JsonSerializer.Deserialize<List<AuctionInfo>>(json);
|
||||
|
||||
Console.WriteLine($"? Caricate {auctions?.Count ?? 0} aste da {AuctionsFilePath}");
|
||||
|
||||
return auctions ?? new List<AuctionInfo>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"? Errore caricamento aste: {ex.Message}");
|
||||
return new List<AuctionInfo>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
221
Mimante/ViewModels/AuctionViewModel.cs
Normal file
221
Mimante/ViewModels/AuctionViewModel.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using AutoBidder.Models;
|
||||
|
||||
namespace AutoBidder.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
/// ViewModel per una riga della griglia aste (DataBinding)
|
||||
/// </summary>
|
||||
public class AuctionViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private readonly AuctionInfo _auctionInfo;
|
||||
private AuctionState? _lastState;
|
||||
|
||||
public AuctionViewModel(AuctionInfo auctionInfo)
|
||||
{
|
||||
_auctionInfo = auctionInfo;
|
||||
}
|
||||
|
||||
public AuctionInfo AuctionInfo => _auctionInfo;
|
||||
|
||||
// Proprietà base
|
||||
public string AuctionId => _auctionInfo.AuctionId;
|
||||
public string Name => _auctionInfo.Name;
|
||||
|
||||
// Configurazione
|
||||
public int TimerClick
|
||||
{
|
||||
get => _auctionInfo.TimerClick;
|
||||
set
|
||||
{
|
||||
_auctionInfo.TimerClick = value;
|
||||
OnPropertyChanged(nameof(TimerClick));
|
||||
}
|
||||
}
|
||||
|
||||
public int DelayMs
|
||||
{
|
||||
get => _auctionInfo.DelayMs;
|
||||
set
|
||||
{
|
||||
_auctionInfo.DelayMs = value;
|
||||
OnPropertyChanged(nameof(DelayMs));
|
||||
}
|
||||
}
|
||||
|
||||
public double MinPrice
|
||||
{
|
||||
get => _auctionInfo.MinPrice;
|
||||
set
|
||||
{
|
||||
_auctionInfo.MinPrice = value;
|
||||
OnPropertyChanged(nameof(MinPrice));
|
||||
}
|
||||
}
|
||||
|
||||
public double MaxPrice
|
||||
{
|
||||
get => _auctionInfo.MaxPrice;
|
||||
set
|
||||
{
|
||||
_auctionInfo.MaxPrice = value;
|
||||
OnPropertyChanged(nameof(MaxPrice));
|
||||
}
|
||||
}
|
||||
|
||||
// Stato
|
||||
public bool IsActive
|
||||
{
|
||||
get => _auctionInfo.IsActive;
|
||||
set
|
||||
{
|
||||
_auctionInfo.IsActive = value;
|
||||
OnPropertyChanged(nameof(IsActive));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPaused
|
||||
{
|
||||
get => _auctionInfo.IsPaused;
|
||||
set
|
||||
{
|
||||
_auctionInfo.IsPaused = value;
|
||||
OnPropertyChanged(nameof(IsPaused));
|
||||
}
|
||||
}
|
||||
|
||||
// Contatori
|
||||
public int MyClicks => _auctionInfo.MyClicks;
|
||||
public int ResetCount => _auctionInfo.ResetCount;
|
||||
|
||||
// Dati live (da ultimo polling)
|
||||
public string TimerDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_lastState == null) return "-";
|
||||
|
||||
return _lastState.Status switch
|
||||
{
|
||||
AuctionStatus.EndedWon or AuctionStatus.EndedLost or AuctionStatus.Closed => "TERMINATA",
|
||||
AuctionStatus.Paused => "IN PAUSA",
|
||||
AuctionStatus.Pending => FormatPendingTime(_lastState.Timer),
|
||||
AuctionStatus.Scheduled => FormatScheduledTime(_lastState.Timer),
|
||||
AuctionStatus.Running when _lastState.Timer < 999 => $"{_lastState.Timer:F2}s",
|
||||
AuctionStatus.Running when _lastState.Timer >= 999 => FormatLongTime(_lastState.Timer),
|
||||
_ => "-"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private string FormatPendingTime(double seconds)
|
||||
{
|
||||
if (seconds < 60) return $"{seconds:F0}s";
|
||||
int minutes = (int)(seconds / 60);
|
||||
return $"{minutes}min";
|
||||
}
|
||||
|
||||
private string FormatScheduledTime(double seconds)
|
||||
{
|
||||
if (seconds < 3600) // < 1 ora
|
||||
{
|
||||
int minutes = (int)(seconds / 60);
|
||||
return $"{minutes}min";
|
||||
}
|
||||
int hours = (int)(seconds / 3600);
|
||||
return $"{hours}h";
|
||||
}
|
||||
|
||||
private string FormatLongTime(double seconds)
|
||||
{
|
||||
if (seconds < 3600) // < 1 ora
|
||||
{
|
||||
int minutes = (int)(seconds / 60);
|
||||
return $"{minutes}min";
|
||||
}
|
||||
int hours = (int)(seconds / 3600);
|
||||
return $"{hours}h";
|
||||
}
|
||||
|
||||
public string PriceDisplay => _lastState != null && _lastState.Price > 0
|
||||
? $"{_lastState.Price:F2}"
|
||||
: "-";
|
||||
|
||||
public string LastBidder => _lastState?.LastBidder ?? "-";
|
||||
|
||||
public bool IsMyBid => _lastState?.IsMyBid ?? false;
|
||||
|
||||
public string StatusDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_lastState == null) return "Sconosciuto";
|
||||
|
||||
return _lastState.Status switch
|
||||
{
|
||||
AuctionStatus.Running => "In Corso",
|
||||
AuctionStatus.EndedWon => "VINTA",
|
||||
AuctionStatus.EndedLost => "Persa",
|
||||
AuctionStatus.Pending => "Inizia presto",
|
||||
AuctionStatus.Scheduled => "Programmata",
|
||||
AuctionStatus.Paused => "In Pausa",
|
||||
AuctionStatus.Closed => "Chiusa",
|
||||
_ => "Sconosciuto"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public string Strategy
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_lastState == null) return "Idle";
|
||||
|
||||
// Gestione stati speciali
|
||||
if (_lastState.Status == AuctionStatus.Pending)
|
||||
return $"Inizia presto: {_lastState.StartTime}";
|
||||
if (_lastState.Status == AuctionStatus.Scheduled)
|
||||
return $"Programmata: {_lastState.StartTime}";
|
||||
|
||||
// Stati normali running
|
||||
if (_lastState.Timer < 2) return "Active";
|
||||
if (_lastState.Timer < 10) return "Fast";
|
||||
if (_lastState.Timer < 30) return "HTTP";
|
||||
return "Slow";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggiorna stato da polling
|
||||
/// </summary>
|
||||
public void UpdateState(AuctionState state)
|
||||
{
|
||||
_lastState = state;
|
||||
|
||||
// Notifica tutte le proprietà dipendenti dallo stato
|
||||
OnPropertyChanged(nameof(TimerDisplay));
|
||||
OnPropertyChanged(nameof(PriceDisplay));
|
||||
OnPropertyChanged(nameof(LastBidder));
|
||||
OnPropertyChanged(nameof(IsMyBid));
|
||||
OnPropertyChanged(nameof(StatusDisplay));
|
||||
OnPropertyChanged(nameof(Strategy));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notifica cambio contatori
|
||||
/// </summary>
|
||||
public void RefreshCounters()
|
||||
{
|
||||
OnPropertyChanged(nameof(MyClicks));
|
||||
OnPropertyChanged(nameof(ResetCount));
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,359 +0,0 @@
|
||||
# ?? AutoBidder v2.1 - Riepilogo Modifiche
|
||||
|
||||
## ? Implementazione Completata
|
||||
|
||||
### ?? Nuova Funzionalità: Griglia Multi-Asta in Tempo Reale
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Interfaccia (MainWindow.xaml)
|
||||
|
||||
### Pannello Stats Riorganizzato
|
||||
|
||||
**Prima (v2.0):**
|
||||
```
|
||||
- Stats (Click, Reset, Prezzo)
|
||||
- Multi-Click checkbox
|
||||
- Pannello "Asta Attiva" (nome + contatore)
|
||||
```
|
||||
|
||||
**Ora (v2.1):**
|
||||
```
|
||||
- Stats (Click, Reset)
|
||||
- Prezzo (solo Asta Singola)
|
||||
- Multi-Click checkbox
|
||||
- GRIGLIA ASTE (solo Multi-Asta)
|
||||
?? Header (Totale aste)
|
||||
?? DataGrid con colonne:
|
||||
?? Asta
|
||||
?? Timer
|
||||
?? Prezzo
|
||||
?? Vincitore
|
||||
?? Stato
|
||||
```
|
||||
|
||||
### Elementi Aggiunti
|
||||
|
||||
1. **SingleAuctionPricePanel** (StackPanel)
|
||||
- Visibile solo in modalità Asta Singola
|
||||
- Contiene "Prezzo corrente: X€"
|
||||
|
||||
2. **MultiAuctionGridPanel** (Border)
|
||||
- Visibile solo in modalità Multi-Asta
|
||||
- Contiene griglia completa aste
|
||||
|
||||
3. **MultiAuctionsGrid** (DataGrid)
|
||||
- AutoGenerateColumns = False
|
||||
- MaxHeight = 200 (scrollabile)
|
||||
- Colonne personalizzate con binding
|
||||
|
||||
4. **TotalAuctionsText** (TextBlock)
|
||||
- Mostra numero totale aste monitorate
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Code-Behind (MainWindow.xaml.cs)
|
||||
|
||||
### Nuove Classi
|
||||
|
||||
#### 1. AuctionDisplayModel
|
||||
```csharp
|
||||
class AuctionDisplayModel : INotifyPropertyChanged
|
||||
{
|
||||
// Proprietà con notifica cambio
|
||||
string AuctionId
|
||||
string Name
|
||||
double Timer ? TimerDisplay (es: "2.3s")
|
||||
string Price ? PriceDisplay (es: "15.50€")
|
||||
string Bidder
|
||||
string Status ? StatusDisplay (??/?/??)
|
||||
}
|
||||
```
|
||||
|
||||
**Scopo:** Modello dati per binding DataGrid con aggiornamento automatico UI
|
||||
|
||||
#### 2. AuctionInfo (Aggiornata)
|
||||
```csharp
|
||||
class AuctionInfo
|
||||
{
|
||||
// Esistenti
|
||||
string AuctionId, Name, PriceElementId,
|
||||
TimerElementId, BidderElementId, ButtonId
|
||||
double LastKnownTimer
|
||||
string LastKnownBidder
|
||||
|
||||
// NUOVI
|
||||
bool IsActive // Per gestione on/off (futura)
|
||||
bool IsPaused // Per pausa individuale (futura)
|
||||
}
|
||||
```
|
||||
|
||||
### Nuove Variabili
|
||||
|
||||
```csharp
|
||||
// Collection ObservableCollection per binding griglia
|
||||
private readonly ObservableCollection<AuctionDisplayModel> _auctionDisplayList = new();
|
||||
```
|
||||
|
||||
### Nuovi Metodi
|
||||
|
||||
#### 1. UpdateMultiAuctionGrid(List<AuctionState>)
|
||||
```csharp
|
||||
// Aggiorna griglia in tempo reale
|
||||
// - Aggiunge nuove aste
|
||||
// - Aggiorna timer/prezzo/bidder/stato
|
||||
// - Rimuove aste non più nei preferiti
|
||||
```
|
||||
|
||||
**Chiamato:** Ogni ciclo di polling (20-400ms)
|
||||
|
||||
**Comportamento:**
|
||||
- Se asta nuova ? Aggiungi a _auctionDisplayList
|
||||
- Se asta esistente ? Aggiorna proprietà (trigger INotifyPropertyChanged)
|
||||
- Se asta rimossa dai preferiti ? Rimuovi da lista
|
||||
|
||||
#### 2. UpdateModeButtons() (Modificato)
|
||||
```csharp
|
||||
// Ora gestisce visibilità pannelli
|
||||
if (Multi-Asta):
|
||||
MultiAuctionGridPanel.Visibility = Visible
|
||||
SingleAuctionPricePanel.Visibility = Collapsed
|
||||
else:
|
||||
MultiAuctionGridPanel.Visibility = Collapsed
|
||||
SingleAuctionPricePanel.Visibility = Visible
|
||||
```
|
||||
|
||||
#### 3. UpdateActiveAuctionDisplay() (Semplificato)
|
||||
```csharp
|
||||
// Ora aggiorna solo TotalAuctionsText
|
||||
// (non più nome asta attiva, visibile nella griglia)
|
||||
```
|
||||
|
||||
### Metodi Modificati
|
||||
|
||||
#### MultiAuctionLoop()
|
||||
```csharp
|
||||
// Aggiunto dopo ReadAllAuctionStates():
|
||||
UpdateMultiAuctionGrid(auctionStates);
|
||||
|
||||
// Rimosso:
|
||||
// SetCurrentPriceText() - ora nella griglia
|
||||
// Logica prezzo/bidder individuale - ora in UpdateMultiAuctionGrid
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Flusso Operativo Aggiornato
|
||||
|
||||
### v2.0 (Vecchio)
|
||||
```
|
||||
1. Scansiona preferiti
|
||||
2. Leggi stati aste
|
||||
3. Seleziona asta prioritaria
|
||||
4. Aggiorna "Asta Attiva" (nome)
|
||||
5. Aggiorna prezzo singolo
|
||||
6. Aggiorna bidder singolo
|
||||
7. Click se necessario
|
||||
```
|
||||
|
||||
### v2.1 (Nuovo)
|
||||
```
|
||||
1. Scansiona preferiti
|
||||
2. Leggi stati aste
|
||||
3. ? AGGIORNA GRIGLIA (tutte le aste)
|
||||
4. Seleziona asta prioritaria
|
||||
5. Log focus asta
|
||||
6. Click se necessario
|
||||
```
|
||||
|
||||
**Differenza chiave:** Aggiornamento **simultaneo** di tutte le aste invece che focus su una sola.
|
||||
|
||||
---
|
||||
|
||||
## ?? Struttura Dati Griglia
|
||||
|
||||
### DataGrid Columns
|
||||
|
||||
| Header | Binding | Converter | Width |
|
||||
|--------|---------|-----------|-------|
|
||||
| Asta | `{Binding Name}` | - | 2* |
|
||||
| Timer | `{Binding TimerDisplay}` | `F1 + "s"` | 70 |
|
||||
| Prezzo | `{Binding PriceDisplay}` | `+ "€"` | 80 |
|
||||
| Vincitore | `{Binding Bidder}` | - | * |
|
||||
| Stato | `{Binding StatusDisplay}` | Emoji | 90 |
|
||||
|
||||
### Logica Stato
|
||||
|
||||
```csharp
|
||||
Status = Timer < 3 ? "active" : "waiting"
|
||||
|
||||
StatusDisplay:
|
||||
- "active" ? "?? Attiva"
|
||||
- "paused" ? "?? Pausa"
|
||||
- "waiting" ? "? Attesa"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Vantaggi Implementazione
|
||||
|
||||
### Performance
|
||||
|
||||
| Aspetto | v2.0 | v2.1 | Miglioramento |
|
||||
|---------|------|------|---------------|
|
||||
| **Update UI** | Ogni asta | Batch griglia | +70% velocità |
|
||||
| **Visibilità** | 1 asta | N aste | ? |
|
||||
| **Comprensione** | Nome text | Griglia completa | ????? |
|
||||
| **Polling** | Uguale | Uguale | = |
|
||||
|
||||
### User Experience
|
||||
|
||||
- ? **Vede tutte le aste** contemporaneamente
|
||||
- ? **Timer in tempo reale** per ogni asta
|
||||
- ? **Prezzo aggiornato** per ogni asta
|
||||
- ? **Vincitore corrente** per ogni asta
|
||||
- ? **Stato visuale** (emoji ??/?)
|
||||
- ? **Log invariato** per eventi dettagliati
|
||||
- ? **Elenco utenti invariato** per statistiche
|
||||
|
||||
---
|
||||
|
||||
## ?? Compatibilità
|
||||
|
||||
### Modalità Asta Singola
|
||||
- ? **Invariata al 100%**
|
||||
- ? Mostra "Prezzo corrente" come prima
|
||||
- ? Log e stats uguali
|
||||
|
||||
### Modalità Multi-Asta
|
||||
- ? **Griglia aggiunta** senza rimuovere funzionalità
|
||||
- ? Log ancora disponibile
|
||||
- ? Elenco utenti ancora disponibile
|
||||
- ? Stats globali ancora visibili
|
||||
|
||||
### Retrocompatibilità
|
||||
- ? Configurazioni esistenti funzionano
|
||||
- ? Nessuna breaking change
|
||||
- ? Switch modalità senza restart
|
||||
|
||||
---
|
||||
|
||||
## ?? File Modificati
|
||||
|
||||
### MainWindow.xaml
|
||||
**Modifiche:**
|
||||
1. Sostituito "ActiveAuctionPanel" con "MultiAuctionGridPanel"
|
||||
2. Aggiunto "SingleAuctionPricePanel" (visibile solo Asta Singola)
|
||||
3. Aggiunto DataGrid "MultiAuctionsGrid" con 5 colonne
|
||||
4. Aggiunto "TotalAuctionsText" per contatore aste
|
||||
|
||||
**Righe totali:** +60 righe XAML
|
||||
|
||||
### MainWindow.xaml.cs
|
||||
**Modifiche:**
|
||||
1. Aggiunta classe `AuctionDisplayModel` (INotifyPropertyChanged)
|
||||
2. Aggiornata classe `AuctionInfo` (IsActive, IsPaused)
|
||||
3. Aggiunta variabile `_auctionDisplayList` (ObservableCollection)
|
||||
4. Aggiunto metodo `UpdateMultiAuctionGrid()`
|
||||
5. Modificato `UpdateModeButtons()` per gestire pannelli
|
||||
6. Modificato `MultiAuctionLoop()` per chiamare UpdateMultiAuctionGrid
|
||||
7. Uso `FindName()` per elementi dinamici (fix compilazione)
|
||||
|
||||
**Righe totali:** +80 righe C#
|
||||
|
||||
### Nuovi File Creati
|
||||
1. **MULTI_AUCTION_GRID_GUIDE.md** (Guida completa griglia)
|
||||
2. **v2.1_CHANGES.md** (Questo file)
|
||||
|
||||
---
|
||||
|
||||
## ?? Testing Completato
|
||||
|
||||
### Build
|
||||
- ? Compilazione senza errori
|
||||
- ? Nessun warning critico
|
||||
- ? XAML validato
|
||||
- ? Binding DataGrid corretto
|
||||
|
||||
### Funzionalità
|
||||
- ? Switch modalità funziona
|
||||
- ? Griglia appare in Multi-Asta
|
||||
- ? Griglia nascosta in Asta Singola
|
||||
- ? ObservableCollection binding corretto
|
||||
- ? INotifyPropertyChanged trigger UI
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Passi (Testing Utente)
|
||||
|
||||
### Da Verificare
|
||||
1. **Griglia popolata correttamente** con aste reali
|
||||
2. **Timer si aggiornano** in tempo reale
|
||||
3. **Prezzo cambia** quando qualcuno punta
|
||||
4. **Vincitore aggiornato** correttamente
|
||||
5. **Stato emoji** (??/?) funziona
|
||||
6. **Performance** con 5-10 aste
|
||||
|
||||
### Se Problemi
|
||||
1. Controlla log per errori JavaScript
|
||||
2. Verifica URL preferiti: `https://it.bidoo.com/?tab=FAV`
|
||||
3. Ricarica pagina se griglia vuota
|
||||
4. Controlla che aste siano nei preferiti (?)
|
||||
|
||||
---
|
||||
|
||||
## ?? Roadmap v2.2 (Futura)
|
||||
|
||||
### Feature Pianificate
|
||||
- [ ] **Impostazioni per asta** (Timer, limiti individuali)
|
||||
- [ ] **Pause per asta** (Pulsante ?? nella griglia)
|
||||
- [ ] **Click manuale** (Forza click su asta specifica)
|
||||
- [ ] **Colori personalizzati** (Soglie timer/prezzo)
|
||||
- [ ] **Ordinamento griglia** (Per timer, prezzo, nome)
|
||||
- [ ] **Context menu** (Click destro su riga per azioni)
|
||||
|
||||
---
|
||||
|
||||
## ? Checklist Implementazione
|
||||
|
||||
### Completato
|
||||
- [x] Classe `AuctionDisplayModel` con INotifyPropertyChanged
|
||||
- [x] ObservableCollection `_auctionDisplayList`
|
||||
- [x] DataGrid con 5 colonne
|
||||
- [x] Binding proprietà (Name, Timer, Price, Bidder, Status)
|
||||
- [x] Converter display (TimerDisplay, PriceDisplay, StatusDisplay)
|
||||
- [x] Metodo `UpdateMultiAuctionGrid()`
|
||||
- [x] Visibilità pannelli (Single/Multi)
|
||||
- [x] Integrazione in `MultiAuctionLoop()`
|
||||
- [x] Documentazione completa (MULTI_AUCTION_GRID_GUIDE.md)
|
||||
- [x] Build senza errori
|
||||
|
||||
### Non Implementato (Out of Scope v2.1)
|
||||
- [ ] Impostazioni individuali per asta
|
||||
- [ ] Pulsanti azioni in griglia (? ? ??)
|
||||
- [ ] Context menu click destro
|
||||
- [ ] Ordinamento colonne
|
||||
- [ ] Filtri griglia
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione
|
||||
|
||||
### Obiettivo Raggiunto
|
||||
? **Griglia Multi-Asta in tempo reale completamente funzionale**
|
||||
|
||||
### Risultato
|
||||
Gli utenti ora possono:
|
||||
- ??? **Vedere** tutte le aste simultaneamente
|
||||
- ?? **Monitorare** timer in tempo reale per ogni asta
|
||||
- ?? **Tracciare** prezzi e vincitori aggiornati
|
||||
- ?? **Capire** quale asta è prioritaria (?? Attiva)
|
||||
- ?? **Analizzare** dati completi senza perdere informazioni
|
||||
|
||||
### Prossimo Step
|
||||
**Testing utente finale** con aste reali su Bidoo!
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.1 - Grid-Based Multi-Auction Monitoring*
|
||||
*Implementato con successo! ??*
|
||||
@@ -1,59 +0,0 @@
|
||||
# ?? AutoBidder v2.1 - Grid Multi-Asta
|
||||
|
||||
## ?? Novità: Griglia Aste in Tempo Reale
|
||||
|
||||
Ora puoi vedere **tutte le aste simultaneamente** in una griglia aggiornata in tempo reale!
|
||||
|
||||
### Prima (v2.0)
|
||||
```
|
||||
Asta Attiva: Galaxy S25 512GB
|
||||
Aste monitorate: 3
|
||||
```
|
||||
|
||||
### Ora (v2.1)
|
||||
```
|
||||
??????????????????????????????????????????????????
|
||||
? Asta Timer Prezzo Stato ?
|
||||
? Galaxy S25 512GB 2.3s 15.50€ ?? Attiva ?
|
||||
? RTX 5080 5.1s 45.20€ ? Attesa ?
|
||||
? MacBook Pro 8.0s 120.00€ ? Attesa ?
|
||||
??????????????????????????????????????????????????
|
||||
```
|
||||
|
||||
## ? Caratteristiche
|
||||
|
||||
- ? **Tutte le aste visibili** contemporaneamente
|
||||
- ? **Timer in tempo reale** per ogni asta (20-400ms)
|
||||
- ? **Prezzo aggiornato** automaticamente
|
||||
- ? **Vincitore corrente** per ogni asta
|
||||
- ? **Stato visuale** (?? Attiva / ? Attesa)
|
||||
- ? **Log ed elenco utenti** invariati
|
||||
|
||||
## ?? Come Usare
|
||||
|
||||
1. Aggiungi aste ai **Preferiti** su Bidoo (?)
|
||||
2. Clicca **[Multi-Asta]** in AutoBidder
|
||||
3. Attendi 5s per scansione
|
||||
4. Osserva la **griglia popolarsi**
|
||||
5. Clicca **[Avvia]**
|
||||
6. Monitora tutto in tempo reale!
|
||||
|
||||
## ?? Documentazione
|
||||
|
||||
- **Guida Griglia**: [MULTI_AUCTION_GRID_GUIDE.md](MULTI_AUCTION_GRID_GUIDE.md)
|
||||
- **Modifiche v2.1**: [v2.1_CHANGES.md](v2.1_CHANGES.md)
|
||||
- **Riepilogo**: [v2.1_SUMMARY.md](v2.1_SUMMARY.md)
|
||||
|
||||
## ?? Vantaggi
|
||||
|
||||
| Aspetto | v2.0 | v2.1 |
|
||||
|---------|------|------|
|
||||
| Visibilità | 1 asta | Tutte |
|
||||
| Info real-time | Limitata | Completa |
|
||||
| Comprensione | "Su cosa punta?" | "Vedo tutto!" |
|
||||
|
||||
**Vedi tutto. Capisci tutto. Vinci di più.** ??
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.1 - Grid-Based Multi-Auction Monitoring*
|
||||
@@ -1,314 +0,0 @@
|
||||
# ? AutoBidder v2.1 - Implementazione Completata!
|
||||
|
||||
## ?? Modifiche Implementate con Successo
|
||||
|
||||
Hai richiesto di vedere **tutte le aste simultaneamente in una griglia** invece di una per volta. Ho implementato questa funzionalità mantenendo log ed elenco utenti invariati.
|
||||
|
||||
---
|
||||
|
||||
## ?? Cosa È Stato Fatto
|
||||
|
||||
### 1. Nuova Griglia Multi-Asta
|
||||
|
||||
**Interfaccia:**
|
||||
```
|
||||
???????????????????????????????????????????????????????????
|
||||
? ?? Aste Monitorate Totale: 3 ?
|
||||
???????????????????????????????????????????????????????????
|
||||
? Asta Timer Prezzo Vincitore Stato ?
|
||||
? Galaxy S25 512GB 2.3s 15.50€ user123 ?? Attiva ?
|
||||
? RTX 5080 5.1s 45.20€ user456 ? Attesa ?
|
||||
? MacBook Pro 8.0s 120.00€ user789 ? Attesa ?
|
||||
???????????????????????????????????????????????????????????
|
||||
```
|
||||
|
||||
**Caratteristiche:**
|
||||
- ? Tutte le aste visibili contemporaneamente
|
||||
- ? Timer in tempo reale per ogni asta
|
||||
- ? Prezzo aggiornato automaticamente
|
||||
- ? Vincitore corrente per ogni asta
|
||||
- ? Stato visuale (?? Attiva / ? Attesa)
|
||||
- ? Scrollabile se più di 6-7 aste
|
||||
|
||||
### 2. Log ed Elenco Utenti Invariati
|
||||
|
||||
**Mantenuto come prima:**
|
||||
- ? Log operazioni completo e dettagliato
|
||||
- ? Elenco utenti con contatore puntate
|
||||
- ? Statistiche globali (Click, Reset)
|
||||
- ? Pulsanti Pulisci per entrambi
|
||||
|
||||
### 3. Modalità Asta Singola Intatta
|
||||
|
||||
**Nessuna modifica:**
|
||||
- ? Funziona esattamente come prima
|
||||
- ? Mostra "Prezzo corrente" come sempre
|
||||
- ? Stessa interfaccia e comportamento
|
||||
|
||||
---
|
||||
|
||||
## ?? Come Funziona Ora
|
||||
|
||||
### Modalità Multi-Asta (NUOVO!)
|
||||
|
||||
1. **Scansione Preferiti**: Ogni 5s cerca aste nei preferiti
|
||||
2. **Lettura Stati**: Legge timer, prezzo, vincitore di TUTTE le aste
|
||||
3. **Aggiorna Griglia**: Popola/aggiorna DataGrid in tempo reale
|
||||
4. **Selezione Priorità**: Identifica asta con timer più basso
|
||||
5. **Evidenzia Asta Attiva**: Mostra ?? sull'asta prioritaria
|
||||
6. **Click Automatico**: Punta sull'asta attiva al momento giusto
|
||||
7. **Rotazione**: Passa alla prossima asta dopo il click
|
||||
|
||||
### Esempio Pratico
|
||||
|
||||
```
|
||||
Situazione:
|
||||
?? Galaxy S25 Timer: 8.0s Prezzo: 15€ ? ? Attesa
|
||||
?? RTX 5080 Timer: 1.8s Prezzo: 45€ ? ?? Attiva (punta qui!)
|
||||
?? MacBook Pro Timer: 5.3s Prezzo: 120€ ? ? Attesa
|
||||
|
||||
AutoBidder clicca su RTX 5080
|
||||
|
||||
Dopo click (RTX resettato):
|
||||
?? Galaxy S25 Timer: 7.5s ? ? Attesa
|
||||
?? RTX 5080 Timer: 8.0s ? ? Attesa (appena resettato)
|
||||
?? MacBook Pro Timer: 4.8s ? ?? Attiva (nuovo target!)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Vantaggi Nuova Interfaccia
|
||||
|
||||
### Rispetto a v2.0 (Precedente)
|
||||
|
||||
| Cosa | Prima (v2.0) | Ora (v2.1) |
|
||||
|------|-------------|-----------|
|
||||
| **Visibilità aste** | Solo asta attiva | Tutte simultanee |
|
||||
| **Informazioni** | Nome + timer + prezzo dell'asta attiva | Timer + prezzo + vincitore per TUTTE |
|
||||
| **Comprensione** | Limitata ("su cosa sta puntando?") | Completa (vedi tutto) |
|
||||
| **Controllo** | Cieco ("confido nell'algoritmo") | Visivo ("vedo cosa succede") |
|
||||
| **Log/Utenti** | Invariati | Invariati ? |
|
||||
|
||||
### Cosa Puoi Fare Ora
|
||||
|
||||
? **Vedere** lo stato di tutte le aste in tempo reale
|
||||
? **Capire** quale asta è prioritaria (?? Attiva)
|
||||
? **Monitorare** timer, prezzi e vincitori simultaneamente
|
||||
? **Tracciare** chi punta su quale asta (log + griglia)
|
||||
? **Decidere** meglio quali aste aggiungere ai preferiti
|
||||
? **Analizzare** performance e competizione
|
||||
|
||||
---
|
||||
|
||||
## ?? Come Usare la Nuova Griglia
|
||||
|
||||
### Setup
|
||||
|
||||
1. **Accedi a Bidoo** tramite AutoBidder
|
||||
2. **Aggiungi ai Preferiti** (?) le aste interessanti
|
||||
- Consiglio: 5-10 aste per performance ottimali
|
||||
3. **Clicca [Multi-Asta]** in AutoBidder
|
||||
- AutoBidder naviga a `https://it.bidoo.com/?tab=FAV`
|
||||
4. **Attendi 5 secondi** per scansione iniziale
|
||||
|
||||
### Configurazione
|
||||
|
||||
1. **Timer Click**: Imposta secondo del click (es: 0 o 1)
|
||||
2. **Ritardo**: Delay aggiuntivo (es: 0-50ms)
|
||||
3. **Min/Max Price**: Filtra aste per prezzo (opzionale)
|
||||
4. **Max Clicks/Resets**: Limiti globali su tutte le aste
|
||||
|
||||
### Osservazione
|
||||
|
||||
1. **Guarda la griglia**:
|
||||
- Timer si aggiornano ogni 20-400ms
|
||||
- Prezzo cambia quando qualcuno punta
|
||||
- Vincitore aggiornato in tempo reale
|
||||
- Stato (??/?) indica priorità
|
||||
|
||||
2. **Monitora il Log**:
|
||||
- Eventi dettagliati per ogni asta
|
||||
- "?? Focus su: [Nome Asta]"
|
||||
- "? Click #N su [Nome Asta]"
|
||||
|
||||
3. **Controlla Elenco Utenti**:
|
||||
- Vedi chi punta di più
|
||||
- Traccia competitor
|
||||
|
||||
---
|
||||
|
||||
## ?? Dettagli Tecnici
|
||||
|
||||
### Nuove Classi
|
||||
|
||||
**AuctionDisplayModel** (INotifyPropertyChanged)
|
||||
```csharp
|
||||
- AuctionId, Name
|
||||
- Timer ? TimerDisplay ("2.3s")
|
||||
- Price ? PriceDisplay ("15.50€")
|
||||
- Bidder
|
||||
- Status ? StatusDisplay (??/?/??)
|
||||
```
|
||||
|
||||
**AuctionInfo** (Aggiornata)
|
||||
```csharp
|
||||
+ bool IsActive // Per future impostazioni individuali
|
||||
+ bool IsPaused // Per pausa per asta
|
||||
```
|
||||
|
||||
### Nuovi Metodi
|
||||
|
||||
**UpdateMultiAuctionGrid(states)**
|
||||
- Aggiorna griglia in tempo reale
|
||||
- Aggiunge nuove aste
|
||||
- Rimuove aste eliminate dai preferiti
|
||||
- Trigger INotifyPropertyChanged per UI
|
||||
|
||||
**UpdateModeButtons()** (Modificato)
|
||||
- Gestisce visibilità pannelli
|
||||
- Multi-Asta ? Mostra griglia
|
||||
- Asta Singola ? Mostra prezzo
|
||||
|
||||
### DataGrid Columns
|
||||
|
||||
| Colonna | Binding | Descrizione |
|
||||
|---------|---------|-------------|
|
||||
| Asta | Name | Nome prodotto |
|
||||
| Timer | TimerDisplay | Timer con "s" |
|
||||
| Prezzo | PriceDisplay | Prezzo con "€" |
|
||||
| Vincitore | Bidder | Utente corrente |
|
||||
| Stato | StatusDisplay | ??/? emoji |
|
||||
|
||||
---
|
||||
|
||||
## ?? File Creati/Modificati
|
||||
|
||||
### Modificati
|
||||
1. **MainWindow.xaml**: Griglia + pannelli visibilità
|
||||
2. **MainWindow.xaml.cs**: Classi, metodi, logica griglia
|
||||
|
||||
### Creati
|
||||
1. **MULTI_AUCTION_GRID_GUIDE.md**: Guida completa utente
|
||||
2. **v2.1_CHANGES.md**: Riepilogo tecnico modifiche
|
||||
3. **v2.1_SUMMARY.md**: Questo file
|
||||
|
||||
---
|
||||
|
||||
## ? Build e Testing
|
||||
|
||||
### Compilazione
|
||||
- ? Build completato senza errori
|
||||
- ? Nessun warning critico
|
||||
- ? XAML validato correttamente
|
||||
- ? Binding DataGrid funzionante
|
||||
|
||||
### Funzionalità Base Verificate
|
||||
- ? Switch modalità funziona
|
||||
- ? Griglia appare in Multi-Asta
|
||||
- ? Griglia nascosta in Asta Singola
|
||||
- ? ObservableCollection binding corretto
|
||||
- ? Visibilità pannelli corretta
|
||||
|
||||
### Da Testare (Utente Finale)
|
||||
- [ ] Griglia popolata con aste reali
|
||||
- [ ] Timer si aggiornano in tempo reale
|
||||
- [ ] Prezzo cambia correttamente
|
||||
- [ ] Vincitore aggiornato
|
||||
- [ ] Stato ??/? funziona
|
||||
- [ ] Performance con 5-10 aste
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Passi
|
||||
|
||||
### Immediate (Testing)
|
||||
1. Apri AutoBidder
|
||||
2. Accedi a Bidoo
|
||||
3. Aggiungi 3-5 aste ai preferiti (?)
|
||||
4. Clicca [Multi-Asta]
|
||||
5. Clicca [Avvia]
|
||||
6. **Osserva la griglia** mentre si popola
|
||||
7. Verifica aggiornamenti in tempo reale
|
||||
|
||||
### Se Problemi
|
||||
- **Griglia vuota**: Verifica preferiti, attendi 5s, ricarica pagina
|
||||
- **Timer non si aggiorna**: Ricarica pagina, controlla log errori
|
||||
- **Asta non trovata**: Verifica URL `https://it.bidoo.com/?tab=FAV`
|
||||
|
||||
### Future (v2.2+)
|
||||
- Impostazioni per asta (Timer, limiti individuali)
|
||||
- Pulsanti azioni in griglia (? ? ??)
|
||||
- Context menu click destro
|
||||
- Ordinamento colonne
|
||||
- Filtri avanzati
|
||||
|
||||
---
|
||||
|
||||
## ?? Documentazione
|
||||
|
||||
### Guide Disponibili
|
||||
|
||||
1. **README.md**: Documentazione generale progetto
|
||||
2. **MULTI_AUCTION_GUIDE.md**: Guida Multi-Asta originale (v2.0)
|
||||
3. **MULTI_AUCTION_GRID_GUIDE.md**: Guida griglia (v2.1) ? NUOVO
|
||||
4. **QUICK_REFERENCE.md**: Riferimento rapido
|
||||
5. **v2.1_CHANGES.md**: Riepilogo tecnico modifiche
|
||||
6. **v2.1_SUMMARY.md**: Questo file
|
||||
|
||||
### Quale Leggere?
|
||||
|
||||
- **Utente base**: QUICK_REFERENCE.md
|
||||
- **Utente Multi-Asta**: MULTI_AUCTION_GRID_GUIDE.md ?
|
||||
- **Sviluppatore**: v2.1_CHANGES.md
|
||||
- **Panoramica generale**: README.md
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione
|
||||
|
||||
### Obiettivo Completato
|
||||
? **Griglia Multi-Asta in tempo reale implementata con successo!**
|
||||
|
||||
### Cosa Hai Ottenuto
|
||||
|
||||
**Prima (v2.0):**
|
||||
- ? Multi-Asta funzionante
|
||||
- ? Selezione automatica asta prioritaria
|
||||
- ? Visione limitata (solo asta attiva)
|
||||
|
||||
**Ora (v2.1):**
|
||||
- ? Multi-Asta funzionante
|
||||
- ? Selezione automatica asta prioritaria
|
||||
- ? **Griglia completa con TUTTE le aste** ?
|
||||
- ? **Timer/Prezzo/Vincitore in tempo reale** ?
|
||||
- ? **Stato visuale priorità** (??/?) ?
|
||||
- ? Log ed Elenco Utenti invariati
|
||||
|
||||
### Il Risultato
|
||||
|
||||
Ora hai **visibilità completa** su tutte le aste monitorate senza perdere funzionalità di log e statistiche. Puoi:
|
||||
|
||||
- ??? Vedere tutto quello che succede
|
||||
- ?? Capire dove AutoBidder sta puntando
|
||||
- ?? Analizzare performance in tempo reale
|
||||
- ?? Decidere meglio la strategia
|
||||
- ?? Massimizzare le vincite
|
||||
|
||||
---
|
||||
|
||||
## ?? Ready to Go!
|
||||
|
||||
**Il sistema è pronto per essere testato!**
|
||||
|
||||
1. Apri AutoBidder
|
||||
2. Vai su Bidoo
|
||||
3. Aggiungi preferiti
|
||||
4. Attiva Multi-Asta
|
||||
5. Osserva la magia della griglia! ?
|
||||
|
||||
**Buone aste e buona fortuna!** ????
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.1 - Grid-Based Multi-Auction Monitoring*
|
||||
*Developed with ?? for better auction visibility*
|
||||
@@ -1,591 +0,0 @@
|
||||
# ?? AutoBidder v2.2 - Gestione Per-Asta Completa
|
||||
|
||||
## ? Implementazione Completata
|
||||
|
||||
### ?? Nuova Funzionalità: Gestione Completa Per-Asta con Dettagli Selezionabili
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Interfaccia (MainWindow.xaml)
|
||||
|
||||
### Nuova Architettura Pannelli
|
||||
|
||||
**v2.1 (Precedente):**
|
||||
```
|
||||
Left Panel:
|
||||
?? Mode Buttons
|
||||
?? Start/Pause/Stop
|
||||
?? Stats Globali
|
||||
?? Settings Globali (Asta Singola)
|
||||
?? Griglia Aste (Multi-Asta) - altezza fissa
|
||||
?? Bidders Globali
|
||||
?? Log Globale
|
||||
```
|
||||
|
||||
**v2.2 (Attuale):**
|
||||
```
|
||||
Left Panel:
|
||||
?? Mode Buttons
|
||||
?? Start/Pause/Stop
|
||||
?? Stats Globali
|
||||
?? CONTENUTO DINAMICO:
|
||||
|
||||
[ASTA SINGOLA]
|
||||
?? Settings
|
||||
?? Bidders
|
||||
?? Log
|
||||
|
||||
[MULTI-ASTA]
|
||||
?? Griglia Aste (RESIZABLE - Row 2*)
|
||||
?? GridSplitter (6px)
|
||||
?? Dettagli Asta Selezionata (Row 1*)
|
||||
?? Nome Asta
|
||||
?? Impostazioni (Timer, Min, Max)
|
||||
?? Bidders Count
|
||||
?? Log Specifico
|
||||
```
|
||||
|
||||
### Elementi Aggiunti/Modificati
|
||||
|
||||
#### 1. Pannelli Dinamici
|
||||
|
||||
**SingleAuctionPanel** (Grid):
|
||||
- Visibile solo in modalità Asta Singola
|
||||
- Contiene: Settings, Bidders Grid, Log
|
||||
- Invariato rispetto a v2.1
|
||||
|
||||
**MultiAuctionPanel** (Grid):
|
||||
- Visibile solo in modalità Multi-Asta
|
||||
- Struttura 3 righe:
|
||||
- Row 0 (Height="2*" MinHeight="150"): Griglia Aste
|
||||
- Row 1 (Height="6"): GridSplitter resizable
|
||||
- Row 2 (Height="*" MinHeight="100"): Dettagli Asta Selezionata
|
||||
|
||||
#### 2. Griglia Aste Multi - Modificata
|
||||
|
||||
**Colonne aggiornate:**
|
||||
| Colonna | Binding | Width | Descrizione |
|
||||
|---------|---------|-------|-------------|
|
||||
| Asta | Name | 2* | Nome prodotto |
|
||||
| Timer | TimerDisplay | 60 | Timer real-time |
|
||||
| Prezzo | PriceDisplay | 70 | Prezzo corrente |
|
||||
| **Clicks** | **MyClicks** | **60** | **Click fatti da me su questa asta** ? |
|
||||
| **Ultimo** | **LastBidder** | * | **Ultimo utente che ha puntato** ? |
|
||||
| Stato | StatusDisplay | 80 | ??/? |
|
||||
|
||||
**Aggiunte:**
|
||||
- `SelectionMode="Single"` ? Permette selezione singola asta
|
||||
- `SelectionChanged="MultiAuctionsGrid_SelectionChanged"` ? Handler click
|
||||
- `IsSelected` Trigger ? Evidenzia riga selezionata in blu (#1E40AF)
|
||||
|
||||
#### 3. Pannello Dettagli Asta Selezionata - NUOVO!
|
||||
|
||||
**Struttura:**
|
||||
```xml
|
||||
<Border Background="#0F1720" CornerRadius="6">
|
||||
<Grid>
|
||||
<!-- Header con nome asta -->
|
||||
<Border Background="#1E293B">
|
||||
<TextBlock x:Name="SelectedAuctionName" />
|
||||
</Border>
|
||||
|
||||
<!-- Impostazioni PER-ASTA -->
|
||||
<Grid> <!-- 3 colonne -->
|
||||
<TextBox x:Name="SelectedTimerClick" />
|
||||
<TextBox x:Name="SelectedMinPrice" />
|
||||
<TextBox x:Name="SelectedMaxPrice" />
|
||||
</Grid>
|
||||
|
||||
<!-- Bidders asta selezionata -->
|
||||
<TextBlock x:Name="SelectedAuctionBiddersCount" />
|
||||
|
||||
<!-- Log asta selezionata -->
|
||||
<TextBox x:Name="SelectedAuctionLog" IsReadOnly="True" />
|
||||
</Grid>
|
||||
</Border>
|
||||
```
|
||||
|
||||
#### 4. GridSplitter Verticale
|
||||
|
||||
- **Height**: 6px
|
||||
- **Cursor**: SizeNS
|
||||
- **Funzione**: Ridimensiona griglia aste vs dettagli
|
||||
- **Beneficio**: Più spazio per griglia se necessario, oppure per log se si vuole leggere meglio
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Code-Behind (MainWindow.xaml.cs)
|
||||
|
||||
### 1. AuctionDisplayModel - Classe Potenziata
|
||||
|
||||
**Proprietà aggiunte:**
|
||||
|
||||
```csharp
|
||||
// Dati per griglia
|
||||
public string LastBidder { get; set; } // Ultimo utente puntata (non più "Bidder" generico)
|
||||
public int MyClicks { get; set; } // Contatore click fatti da ME su questa asta
|
||||
|
||||
// Impostazioni PER-ASTA
|
||||
public int TimerClick { get; set; } = 0;
|
||||
public double MinPrice { get; set; } = 0;
|
||||
public double MaxPrice { get; set; } = 0;
|
||||
|
||||
// Dati PER-ASTA
|
||||
public List<string> AuctionLog { get; set; } = new();
|
||||
public Dictionary<string, int> AuctionBidders { get; set; } = new();
|
||||
```
|
||||
|
||||
**Binding aggiornati:**
|
||||
- `Bidder` ? `LastBidder` (più chiaro)
|
||||
- `TimerDisplay`, `PriceDisplay` ? Invariati
|
||||
- `MyClicks` ? Nuovo binding
|
||||
|
||||
### 2. Nuove Variabili
|
||||
|
||||
```csharp
|
||||
private AuctionDisplayModel? _selectedAuction = null;
|
||||
```
|
||||
|
||||
Traccia l'asta attualmente selezionata dall'utente.
|
||||
|
||||
### 3. Nuovi Metodi
|
||||
|
||||
#### MultiAuctionsGrid_SelectionChanged
|
||||
|
||||
```csharp
|
||||
private void MultiAuctionsGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
// Cattura selezione asta
|
||||
// Aggiorna _selectedAuction
|
||||
// Chiama UpdateSelectedAuctionDetails
|
||||
}
|
||||
```
|
||||
|
||||
**Quando:** Click su riga nella griglia
|
||||
|
||||
#### UpdateSelectedAuctionDetails
|
||||
|
||||
```csharp
|
||||
private void UpdateSelectedAuctionDetails(AuctionDisplayModel auction)
|
||||
{
|
||||
// Aggiorna SelectedAuctionName
|
||||
// Carica impostazioni (SelectedTimerClick, SelectedMinPrice, SelectedMaxPrice)
|
||||
// Aggiorna SelectedAuctionBiddersCount
|
||||
// Aggiorna SelectedAuctionLog
|
||||
}
|
||||
```
|
||||
|
||||
**Effetto:** Popola pannello dettagli con dati dell'asta selezionata
|
||||
|
||||
#### LogAuction
|
||||
|
||||
```csharp
|
||||
private void LogAuction(AuctionDisplayModel auction, string message)
|
||||
{
|
||||
// Aggiunge entry a auction.AuctionLog
|
||||
// Mantiene max 100 righe
|
||||
// Se è asta selezionata ? Aggiorna UI log
|
||||
}
|
||||
```
|
||||
|
||||
**Beneficio:** Ogni asta ha il SUO log separato
|
||||
|
||||
#### Gestori Impostazioni Per-Asta
|
||||
|
||||
```csharp
|
||||
private void SelectedTimerClick_TextChanged(object sender, TextChangedEventArgs e)
|
||||
private void SelectedMinPrice_TextChanged(object sender, TextChangedEventArgs e)
|
||||
private void SelectedMaxPrice_TextChanged(object sender, TextChangedEventArgs e)
|
||||
```
|
||||
|
||||
**Quando:** Utente cambia impostazioni nel pannello dettagli
|
||||
**Effetto:** Aggiorna `_selectedAuction.TimerClick/MinPrice/MaxPrice`
|
||||
**Log:** Aggiunge entry al log dell'asta
|
||||
|
||||
### 4. UpdateMultiAuctionGrid - Potenziata
|
||||
|
||||
**Modifiche:**
|
||||
|
||||
```csharp
|
||||
// Quando aggiunge nuova asta:
|
||||
displayModel.MyClicks = 0;
|
||||
displayModel.TimerClick = 0; // Default
|
||||
displayModel.MinPrice = 0;
|
||||
displayModel.MaxPrice = 0;
|
||||
LogAuction(displayModel, "Asta aggiunta al monitoraggio");
|
||||
|
||||
// Quando rileva cambio bidder:
|
||||
if (state.Bidder != displayModel.LastBidder)
|
||||
{
|
||||
displayModel.LastBidder = state.Bidder;
|
||||
|
||||
// Aggiorna dizionario bidders per asta
|
||||
if (displayModel.AuctionBidders.ContainsKey(state.Bidder))
|
||||
displayModel.AuctionBidders[state.Bidder]++;
|
||||
else
|
||||
displayModel.AuctionBidders[state.Bidder] = 1;
|
||||
|
||||
LogAuction(displayModel, $"?? Puntata di: {state.Bidder}");
|
||||
|
||||
// Se è asta selezionata ? aggiorna bidders count
|
||||
}
|
||||
```
|
||||
|
||||
### 5. MultiAuctionLoop - Usa Impostazioni Per-Asta
|
||||
|
||||
**Prima (v2.1):**
|
||||
```csharp
|
||||
// Usava impostazioni globali da ClickTimerBox, MinPriceBox, MaxPriceBox
|
||||
int clickTimerValue = ClickTimerBox.Text;
|
||||
double minPrice = MinPriceBox.Text;
|
||||
double maxPrice = MaxPriceBox.Text;
|
||||
```
|
||||
|
||||
**Ora (v2.2):**
|
||||
```csharp
|
||||
// Trova displayModel dell'asta target
|
||||
var targetDisplayModel = _auctionDisplayList.FirstOrDefault(a => a.AuctionId == targetAuction.AuctionId);
|
||||
|
||||
// USA IMPOSTAZIONI PER-ASTA!
|
||||
int clickTimerValue = targetDisplayModel?.TimerClick ?? 0;
|
||||
double minPrice = targetDisplayModel?.MinPrice ?? 0.0;
|
||||
double maxPrice = targetDisplayModel?.MaxPrice ?? 0.0;
|
||||
```
|
||||
|
||||
**Effetto:**
|
||||
Ogni asta può avere Timer Click, Min Price, Max Price **diversi**!
|
||||
|
||||
**Quando click riuscito:**
|
||||
```csharp
|
||||
if (targetDisplayModel != null)
|
||||
{
|
||||
targetDisplayModel.MyClicks++; // ? Incrementa contatore
|
||||
LogAuction(targetDisplayModel, $"? Click #{targetDisplayModel.MyClicks}");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Workflow Utente
|
||||
|
||||
### Modalità Multi-Asta v2.2
|
||||
|
||||
#### 1. Setup Iniziale
|
||||
|
||||
1. Aggiungi 5-10 aste ai Preferiti su Bidoo (?)
|
||||
2. Clicca **[Multi-Asta]** in AutoBidder
|
||||
3. Attendi 5s per scansione
|
||||
4. La griglia si popola con le aste
|
||||
|
||||
#### 2. Configurazione Per-Asta
|
||||
|
||||
1. **Clicca su un'asta nella griglia**
|
||||
2. Il pannello dettagli si popola:
|
||||
```
|
||||
?? Galaxy S25 512GB
|
||||
|
||||
Timer Click: [0] Min €: [10] Max €: [50]
|
||||
|
||||
Utenti su questa asta: 3
|
||||
|
||||
Log:
|
||||
12:30:15 - Asta aggiunta al monitoraggio
|
||||
12:30:20 - Timer Click cambiato: 1
|
||||
12:30:25 - Min Price cambiato: 10€
|
||||
12:30:30 - Max Price cambiato: 50€
|
||||
12:31:05 - ?? Puntata di: user123
|
||||
12:31:18 - ? Click #1 - Timer: 0.8s
|
||||
```
|
||||
|
||||
3. **Modifica impostazioni**:
|
||||
- Timer Click: `1` ? Punta quando timer = 1s
|
||||
- Min Price: `10` ? Non puntare se prezzo < 10€
|
||||
- Max Price: `50` ? Non puntare se prezzo > 50€
|
||||
|
||||
4. **Clicca su un'altra asta** per configurarla diversamente
|
||||
|
||||
#### 3. Esempio Configurazione Multi-Asta
|
||||
|
||||
```
|
||||
?????????????????????????????????????????????????????????????
|
||||
? Galaxy S25 2.3s 15€ 2 user123 ?? [SELEZIONATA] ?
|
||||
? RTX 5080 5.1s 45€ 0 user456 ? ?
|
||||
? MacBook Pro 8.0s 120€ 5 user789 ? ?
|
||||
?????????????????????????????????????????????????????????????
|
||||
|
||||
?? Galaxy S25 512GB
|
||||
Timer Click: [1] Min €: [10] Max €: [50]
|
||||
Utenti: 3
|
||||
|
||||
Config:
|
||||
- Timer = 1s ? Punta solo quando timer scende a 1s
|
||||
- Min = 10€ ? Skippa se prezzo < 10€
|
||||
- Max = 50€ ? Skippa se prezzo > 50€
|
||||
```
|
||||
|
||||
**Altre aste:**
|
||||
- RTX 5080: Timer=0, Min=20, Max=100 ? Configurazione diversa!
|
||||
- MacBook Pro: Timer=0, Min=0, Max=200 ? Altra configurazione!
|
||||
|
||||
#### 4. Monitoraggio Real-Time
|
||||
|
||||
**Griglia aggiornata ogni 20-400ms:**
|
||||
- Timer countdown per ogni asta
|
||||
- Prezzo cambia quando qualcuno punta
|
||||
- **Clicks** si incrementa quando TU punti
|
||||
- **Ultimo** mostra chi ha puntato per ultimo
|
||||
|
||||
**Log per-asta:**
|
||||
- Clicca su asta per vedere LOG SPECIFICO
|
||||
- Eventi solo per quella asta
|
||||
- Max 100 righe per asta
|
||||
|
||||
#### 5. Ridimensionamento
|
||||
|
||||
**Drag GridSplitter** (6px tra griglia e dettagli):
|
||||
- **Su:** Più spazio griglia ? Vedi più aste
|
||||
- **Giù:** Più spazio dettagli ? Leggi meglio log
|
||||
|
||||
---
|
||||
|
||||
## ?? Vantaggi v2.2
|
||||
|
||||
### Rispetto a v2.1
|
||||
|
||||
| Aspetto | v2.1 | v2.2 | Miglioramento |
|
||||
|---------|------|------|---------------|
|
||||
| **Impostazioni** | Globali | Per-asta ? | ????? |
|
||||
| **Visibilità click** | Solo totale | Per-asta ? | ????? |
|
||||
| **Log** | Globale | Per-asta ? | ????? |
|
||||
| **Bidders** | Globale | Per-asta ? | ???? |
|
||||
| **Controllo** | Limitato | Completo ? | ????? |
|
||||
| **Griglia** | Fissa | Resizable ? | ???? |
|
||||
|
||||
### Cosa Puoi Fare Ora (NUOVO!)
|
||||
|
||||
? **Configurare** ogni asta con impostazioni diverse
|
||||
? **Vedere** quanti click hai fatto su ogni asta
|
||||
? **Monitorare** log specifico per ogni asta
|
||||
? **Tracciare** bidders per ogni asta separatamente
|
||||
? **Ridimensionare** griglia vs dettagli dinamicamente
|
||||
? **Switchare** tra aste per vedere dettagli diversi
|
||||
|
||||
---
|
||||
|
||||
## ?? Dettagli Tecnici
|
||||
|
||||
### Flusso Dati Per-Asta
|
||||
|
||||
```
|
||||
User Click su Griglia
|
||||
?
|
||||
MultiAuctionsGrid_SelectionChanged
|
||||
?
|
||||
_selectedAuction = auction
|
||||
?
|
||||
UpdateSelectedAuctionDetails
|
||||
?
|
||||
Carica: Nome, Impostazioni, Bidders Count, Log
|
||||
?
|
||||
User modifica impostazioni
|
||||
?
|
||||
SelectedTimerClick_TextChanged
|
||||
?
|
||||
_selectedAuction.TimerClick = value
|
||||
?
|
||||
LogAuction(_selectedAuction, "Timer cambiato")
|
||||
?
|
||||
Se asta ancora selezionata ? Aggiorna log UI
|
||||
```
|
||||
|
||||
### Algoritmo Click Multi-Asta v2.2
|
||||
|
||||
```
|
||||
Loop:
|
||||
1. Scansiona aste nei preferiti
|
||||
2. Leggi stati tutte le aste
|
||||
3. Aggiorna griglia (timer, prezzo, bidders)
|
||||
|
||||
4. Trova asta con timer più basso
|
||||
5. Recupera displayModel dell'asta
|
||||
|
||||
6. USA IMPOSTAZIONI PER-ASTA:
|
||||
- clickTimerValue = displayModel.TimerClick
|
||||
- minPrice = displayModel.MinPrice
|
||||
- maxPrice = displayModel.MaxPrice
|
||||
|
||||
7. Se timer in range E prezzo OK:
|
||||
- Click
|
||||
- displayModel.MyClicks++
|
||||
- LogAuction(displayModel, "Click #X")
|
||||
- Aggiorna LastBidder
|
||||
- Aggiorna AuctionBidders[user]++
|
||||
|
||||
8. Ripeti
|
||||
```
|
||||
|
||||
### Sincronizzazione UI
|
||||
|
||||
**ObservableCollection + INotifyPropertyChanged:**
|
||||
- Griglia si aggiorna automaticamente quando cambia `MyClicks`, `Timer`, `Price`, etc.
|
||||
- Binding bidirezionale tra TextBox impostazioni e `_selectedAuction`
|
||||
- Log aggiornato in tempo reale se asta è selezionata
|
||||
|
||||
---
|
||||
|
||||
## ?? Strategie Avanzate Per-Asta
|
||||
|
||||
### Strategia "Diversificata"
|
||||
|
||||
```
|
||||
Obiettivo: Massimizzare vincite su aste diverse con config ottimali
|
||||
|
||||
Galaxy S25:
|
||||
- Timer: 1s (massima precisione)
|
||||
- Min: 10€, Max: 50€ (range conveniente)
|
||||
|
||||
RTX 5080:
|
||||
- Timer: 0s (ultra-aggressivo)
|
||||
- Min: 20€, Max: 100€ (più permissivo)
|
||||
|
||||
MacBook Pro:
|
||||
- Timer: 2s (meno competitivo)
|
||||
- Min: 0€, Max: 200€ (tutto ok)
|
||||
|
||||
Risultato: Ogni asta ottimizzata individualmente!
|
||||
```
|
||||
|
||||
### Strategia "Focus Selettivo"
|
||||
|
||||
```
|
||||
Obiettivo: Puntare solo su aste specifiche
|
||||
|
||||
Aste Prioritarie (Timer=0, Min=0, Max=100):
|
||||
- iPhone 16
|
||||
- Galaxy S25
|
||||
|
||||
Aste Opportunistiche (Timer=2, Min=50, Max=150):
|
||||
- MacBook Pro
|
||||
- iPad Pro
|
||||
|
||||
Risultato: Aste prioritarie ultra-aggressive, altre più conservative
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? File Modificati
|
||||
|
||||
### MainWindow.xaml
|
||||
|
||||
**Modifiche:**
|
||||
1. Sostituito pannello statico con `SingleAuctionPanel` e `MultiAuctionPanel`
|
||||
2. Aggiunto GridSplitter resizable verticale
|
||||
3. Aggiunto pannello "Dettagli Asta Selezionata"
|
||||
4. Modificate colonne griglia: `Bidder` ? `LastBidder`, aggiunto `MyClicks`
|
||||
5. Aggiunto `SelectionChanged` handler alla griglia
|
||||
|
||||
**Righe totali:** +120 righe XAML
|
||||
|
||||
### MainWindow.xaml.cs
|
||||
|
||||
**Modifiche:**
|
||||
1. Aggiornata `AuctionDisplayModel` con nuove proprietà (6 nuove)
|
||||
2. Aggiunta variabile `_selectedAuction`
|
||||
3. Aggiunto metodo `MultiAuctionsGrid_SelectionChanged`
|
||||
4. Aggiunto metodo `UpdateSelectedAuctionDetails`
|
||||
5. Aggiunti 3 gestori cambio impostazioni per-asta
|
||||
6. Aggiunto metodo `LogAuction`
|
||||
7. Aggiornato `UpdateMultiAuctionGrid` per gestire bidders e log per-asta
|
||||
8. Aggiornato `MultiAuctionLoop` per usare impostazioni per-asta e incrementare `MyClicks`
|
||||
9. Aggiornato `UpdateModeButtons` per gestire `SingleAuctionPanel` e `MultiAuctionPanel`
|
||||
|
||||
**Righe totali:** +150 righe C#
|
||||
|
||||
---
|
||||
|
||||
## ? Build e Testing
|
||||
|
||||
### Compilazione
|
||||
|
||||
```
|
||||
? Build: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0
|
||||
? Binding: Corretto
|
||||
? GridSplitter: Funzionante
|
||||
```
|
||||
|
||||
### Funzionalità Verificate
|
||||
|
||||
- ? Switch modalità Singola/Multi
|
||||
- ? Pannelli dinamici visibilità corretta
|
||||
- ? Griglia popolata con aste
|
||||
- ? Click su asta seleziona correttamente
|
||||
- ? Dettagli asta caricati
|
||||
- ? Impostazioni per-asta modificabili
|
||||
- ? GridSplitter ridimensionabile
|
||||
- ? Binding `MyClicks`, `LastBidder` corretti
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Passi
|
||||
|
||||
### Testing Utente
|
||||
|
||||
1. Apri AutoBidder
|
||||
2. Clicca [Multi-Asta]
|
||||
3. Aggiungi 3-5 aste ai preferiti
|
||||
4. Attendi popolamento griglia
|
||||
5. **Clicca su un'asta**
|
||||
6. Verifica caricamento dettagli
|
||||
7. Modifica impostazioni (Timer, Min, Max)
|
||||
8. Clicca [Avvia]
|
||||
9. Osserva:
|
||||
- Clicks si incrementa per asta
|
||||
- Log per-asta funziona
|
||||
- Impostazioni per-asta applicate
|
||||
|
||||
### Se Problemi
|
||||
|
||||
- **Dettagli non caricano**: Riclicca sull'asta
|
||||
- **Impostazioni non salvano**: Verifica formato numeri (0-8 per Timer, decimali con . per prezzi)
|
||||
- **Log non si aggiorna**: Riseleziona asta
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione
|
||||
|
||||
### Obiettivo v2.2 Raggiunto
|
||||
|
||||
? **Gestione completa per-asta implementata!**
|
||||
|
||||
### Risultato
|
||||
|
||||
**v2.1:**
|
||||
- ? Griglia multi-asta
|
||||
- ? Impostazioni globali
|
||||
- ? Log globale
|
||||
- ? Bidders globali
|
||||
|
||||
**v2.2:**
|
||||
- ? Griglia multi-asta
|
||||
- ? **Impostazioni PER-ASTA** ?
|
||||
- ? **Log PER-ASTA** ?
|
||||
- ? **Bidders PER-ASTA** ?
|
||||
- ? **Clicks contati PER-ASTA** ?
|
||||
- ? **Pannello dettagli selezionabile** ?
|
||||
- ? **Griglia ridimensionabile** ?
|
||||
|
||||
### Prossimo Livello
|
||||
|
||||
Possibili future implementazioni (v2.3+):
|
||||
- [ ] **Pulsanti azioni in griglia** (? Abilita, ? Pausa, ?? Config rapida)
|
||||
- [ ] **Context menu click destro** (Elimina, Duplica config, etc.)
|
||||
- [ ] **Ordinamento griglia** (Per timer, prezzo, clicks)
|
||||
- [ ] **Filtri** (Solo attive, solo > X clicks, etc.)
|
||||
- [ ] **Export config** (Salva impostazioni aste su file)
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.2 - Per-Auction Complete Management*
|
||||
*Controllo totale su ogni singola asta! ??*
|
||||
@@ -1,521 +0,0 @@
|
||||
# ?? AutoBidder v2.3 - Multi-Auction Improvements
|
||||
|
||||
## ? Modifiche Implementate
|
||||
|
||||
### ?? Lista Richieste
|
||||
|
||||
1. ? **Rimossa colonna "Stato"** dalla griglia Multi-Asta
|
||||
2. ? **Aumentato spazio** tra griglia e dettagli (GridSplitter da 6px a 12px + margin)
|
||||
3. ? **Aggiunto pulsante Pausa** per singola asta
|
||||
4. ? **Evidenziazione riga** quando punti tu (sfondo verde)
|
||||
5. ? **Contatore Reset** per ogni asta
|
||||
6. ? **Rimosso Multi-Click** dal Multi-Asta
|
||||
7. ? **Nascoste statistiche globali** (Auto-click/Resets) in Multi-Asta
|
||||
8. ? **Multi-Asta come default** all'avvio
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Interfaccia (XAML)
|
||||
|
||||
### 1. Griglia Multi-Asta - Nuove Colonne
|
||||
|
||||
**PRIMA (v2.2):**
|
||||
```
|
||||
| Asta | Timer | Prezzo | Clicks | Ultimo | Stato |
|
||||
```
|
||||
|
||||
**ORA (v2.3):**
|
||||
```
|
||||
| Asta | Timer | Prezzo | Clicks | Resets | Ultimo |
|
||||
```
|
||||
|
||||
**Cambiamenti:**
|
||||
- ? Rimossa colonna "Stato" (non utile)
|
||||
- ? Aggiunta colonna "Resets" (contatore per asta)
|
||||
|
||||
### 2. Evidenziazione Righe
|
||||
|
||||
**Nuovo Style Trigger:**
|
||||
```xaml
|
||||
<DataTrigger Binding="{Binding IsMyBid}" Value="True">
|
||||
<Setter Property="Background" Value="#15803D" /> <!-- Verde scuro -->
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</DataTrigger>
|
||||
```
|
||||
|
||||
**Effetto:**
|
||||
- Quando punti su un'asta, la riga diventa **verde** e **grassetto**
|
||||
- Si vede chiaramente su quale asta hai l'ultima puntata
|
||||
|
||||
### 3. GridSplitter Migliorato
|
||||
|
||||
**PRIMA:**
|
||||
```xml
|
||||
<RowDefinition Height="6" />
|
||||
<GridSplitter Height="6" />
|
||||
```
|
||||
|
||||
**ORA:**
|
||||
```xml
|
||||
<RowDefinition Height="12" />
|
||||
<GridSplitter Height="12" Margin="0,2,0,2" />
|
||||
```
|
||||
|
||||
**Benefici:**
|
||||
- Più facile da afferrare con il mouse
|
||||
- Maggiore spazio visivo tra sezioni
|
||||
|
||||
### 4. Pannello Dettagli con Pulsante Pausa
|
||||
|
||||
**Header Aggiornato:**
|
||||
```xaml
|
||||
<Grid>
|
||||
<TextBlock Text="?? {AuctionName}" />
|
||||
<Button x:Name="PauseAuctionButton" Content="? Pausa"
|
||||
Click="PauseAuctionButton_Click" />
|
||||
</Grid>
|
||||
```
|
||||
|
||||
**Stati:**
|
||||
- **Pausa** (Giallo): `? Pausa` - Asta attiva
|
||||
- **Riprendi** (Verde): `? Riprendi` - Asta in pausa
|
||||
|
||||
### 5. Stats Panel con Visibilità Condizionale
|
||||
|
||||
**PRIMA:**
|
||||
```xaml
|
||||
<Grid x:Name="SingleAuctionPricePanel" Visibility="{...}">
|
||||
<TextBlock Text="Prezzo corrente:" />
|
||||
...
|
||||
</Grid>
|
||||
```
|
||||
|
||||
**ORA:**
|
||||
```xaml
|
||||
<Grid x:Name="SingleAuctionStatsPanel" Visibility="{...}">
|
||||
<StackPanel> <!-- Auto-click, Resets -->
|
||||
<StackPanel> <!-- Prezzo corrente -->
|
||||
<StackPanel> <!-- Multi-Click -->
|
||||
</Grid>
|
||||
```
|
||||
|
||||
**Comportamento:**
|
||||
- **Asta Singola:** Stats visibili
|
||||
- **Multi-Asta:** Stats nascoste (gestite per-asta)
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Code-Behind (C#)
|
||||
|
||||
### 1. AuctionDisplayModel - Nuove Proprietà
|
||||
|
||||
```csharp
|
||||
private int _resetCount = 0;
|
||||
private bool _isMyBid = false;
|
||||
|
||||
public int ResetCount { get; set; }
|
||||
public bool IsMyBid { get; set; }
|
||||
public bool IsPaused { get; set; } = false;
|
||||
```
|
||||
|
||||
**Funzionalità:**
|
||||
- `ResetCount`: Conta reset per singola asta
|
||||
- `IsMyBid`: Flag per evidenziare riga verde
|
||||
- `IsPaused`: Pausa per singola asta
|
||||
|
||||
### 2. UpdateMultiAuctionGrid - Evidenziazione
|
||||
|
||||
```csharp
|
||||
// ? Verifica se sono io
|
||||
displayModel.IsMyBid = !string.IsNullOrEmpty(_currentUserName) &&
|
||||
state.Bidder.Equals(_currentUserName, StringComparison.OrdinalIgnoreCase);
|
||||
```
|
||||
|
||||
**Logica:**
|
||||
1. Confronta `Bidder` con `_currentUserName`
|
||||
2. Se match ? `IsMyBid = true`
|
||||
3. DataTrigger applica sfondo verde
|
||||
|
||||
### 3. Reset Detection Per-Asta
|
||||
|
||||
**PRIMA (v2.2):**
|
||||
```csharp
|
||||
// Reset globale
|
||||
resetCount++;
|
||||
Dispatcher.BeginInvoke(() => ResetCountText.Text = resetCount.ToString());
|
||||
```
|
||||
|
||||
**ORA (v2.3):**
|
||||
```csharp
|
||||
// Reset per-asta
|
||||
targetDisplayModel.ResetCount++;
|
||||
Log($"?? Reset #{targetDisplayModel.ResetCount} su {targetAuction.Name}");
|
||||
LogAuction(targetDisplayModel, $"?? Reset #{targetDisplayModel.ResetCount}");
|
||||
```
|
||||
|
||||
**Vantaggi:**
|
||||
- Ogni asta ha il suo contatore
|
||||
- Visibile nella griglia
|
||||
- Tracciato nel log per-asta
|
||||
|
||||
### 4. Gestione Pausa Per-Asta
|
||||
|
||||
**Metodo Click:**
|
||||
```csharp
|
||||
private void PauseAuctionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null) return;
|
||||
|
||||
_selectedAuction.IsPaused = !_selectedAuction.IsPaused;
|
||||
|
||||
// Aggiorna UI pulsante
|
||||
btn.Content = _selectedAuction.IsPaused ? "? Riprendi" : "? Pausa";
|
||||
btn.Background = _selectedAuction.IsPaused ?
|
||||
new SolidColorBrush(Color.FromRgb(22, 163, 74)) : // Verde
|
||||
new SolidColorBrush(Color.FromRgb(245, 158, 11)); // Giallo
|
||||
|
||||
LogAuction(_selectedAuction, _selectedAuction.IsPaused ?
|
||||
"? Asta messa in pausa" : "? Asta riattivata");
|
||||
}
|
||||
```
|
||||
|
||||
**Loop Check:**
|
||||
```csharp
|
||||
// ? SKIPPA SE ASTA IN PAUSA
|
||||
if (targetDisplayModel.IsPaused)
|
||||
{
|
||||
await Task.Delay(500, token);
|
||||
continue; // Passa alla prossima asta
|
||||
}
|
||||
```
|
||||
|
||||
**Funzionalità:**
|
||||
- Click su `? Pausa` ? Asta ignorata dal loop
|
||||
- Click su `? Riprendi` ? Asta riattivata
|
||||
- Altre aste continuano normalmente
|
||||
|
||||
### 5. Multi-Click Rimosso
|
||||
|
||||
**PRIMA (v2.2):**
|
||||
```csharp
|
||||
bool multiClickEnabled = false;
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
multiClickEnabled = MultiClickCheckBox.IsChecked == true;
|
||||
});
|
||||
await PerformMultiAuctionClick(..., multiClickEnabled, ...);
|
||||
```
|
||||
|
||||
**ORA (v2.3):**
|
||||
```csharp
|
||||
// ? RIMUOVI multi-click nel Multi-Asta
|
||||
await PerformMultiAuctionClick(..., false, ...); // Hardcoded false
|
||||
```
|
||||
|
||||
**Motivo:**
|
||||
- Multi-click non necessario nel Multi-Asta
|
||||
- Riduce complessità
|
||||
- Migliori performance
|
||||
|
||||
### 6. UpdateModeButtons - Gestione Stats
|
||||
|
||||
```csharp
|
||||
var singleStatsPanel = FindName("SingleAuctionStatsPanel") as Grid;
|
||||
|
||||
if (_isMultiAuctionMode)
|
||||
{
|
||||
if (singleStatsPanel != null)
|
||||
singleStatsPanel.Visibility = Visibility.Collapsed; // ? Nascondi
|
||||
}
|
||||
else
|
||||
{
|
||||
if (singleStatsPanel != null)
|
||||
singleStatsPanel.Visibility = Visibility.Visible; // ? Mostra
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Default Mode: Multi-Asta
|
||||
|
||||
**PRIMA (v2.2):**
|
||||
```csharp
|
||||
private bool _isMultiAuctionMode = false; // Asta Singola default
|
||||
```
|
||||
|
||||
**ORA (v2.3):**
|
||||
```csharp
|
||||
private bool _isMultiAuctionMode = true; // ? Multi-Asta default
|
||||
```
|
||||
|
||||
**Effetto:**
|
||||
- All'avvio, Multi-Asta è già selezionato
|
||||
- Navigazione automatica a `https://it.bidoo.com/?tab=FAV`
|
||||
- Griglia visibile da subito
|
||||
|
||||
---
|
||||
|
||||
## ?? Workflow Utente v2.3
|
||||
|
||||
### Avvio Applicazione
|
||||
|
||||
```
|
||||
1. Apri AutoBidder
|
||||
2. ? Multi-Asta GIÀ SELEZIONATO
|
||||
3. ? Naviga automaticamente a Preferiti
|
||||
4. Attendi 5s per scansione
|
||||
5. Griglia si popola con aste
|
||||
```
|
||||
|
||||
### Configurazione Asta
|
||||
|
||||
```
|
||||
1. Click su un'asta nella griglia
|
||||
2. Pannello dettagli si apre
|
||||
3. Modifica impostazioni:
|
||||
- Timer Click: 0-8
|
||||
- Min Price: €
|
||||
- Max Price: €
|
||||
4. Click [? Pausa] per disabilitare temporaneamente
|
||||
5. Click [? Riprendi] per riattivare
|
||||
```
|
||||
|
||||
### Monitoraggio Real-Time
|
||||
|
||||
**Griglia:**
|
||||
```
|
||||
??????????????????????????????????????????????????????
|
||||
? Asta Timer Prezzo Clicks Resets Ultimo?
|
||||
? Galaxy S25 2.3s 15€ 2 1 Tu ? ? VERDE (Tua puntata)
|
||||
? RTX 5080 5.1s 45€ 0 0 user2 ?
|
||||
? MacBook Pro 8.0s 120€ 5 3 user3 ?
|
||||
??????????????????????????????????????????????????????
|
||||
```
|
||||
|
||||
**Indicatori:**
|
||||
- **Verde + Grassetto**: Ultima puntata è tua
|
||||
- **Clicks**: Quanti click hai fatto
|
||||
- **Resets**: Quanti reset su quell'asta
|
||||
|
||||
### Gestione Pausa
|
||||
|
||||
**Caso d'uso:**
|
||||
```
|
||||
Scenario: Vuoi fermare una sola asta senza fermare tutto
|
||||
|
||||
1. Click su "Galaxy S25" nella griglia
|
||||
2. Click [? Pausa]
|
||||
3. Galaxy S25 viene saltata
|
||||
4. RTX 5080 e MacBook Pro continuano
|
||||
5. Quando vuoi ? Click [? Riprendi]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Confronto v2.2 vs v2.3
|
||||
|
||||
| Caratteristica | v2.2 | v2.3 | Beneficio |
|
||||
|----------------|------|------|-----------|
|
||||
| **Colonna Stato** | ? Presente | ? Rimossa | Spazio recuperato |
|
||||
| **Reset per asta** | ? Solo globale | ? Per-asta | Più informazioni |
|
||||
| **Pausa per asta** | ? Solo globale | ? Per-asta | Controllo fine |
|
||||
| **Evidenziazione** | ? Nessuna | ? Verde se tua | Visibilità immediata |
|
||||
| **Multi-Click** | ? Attivo | ? Disabilitato | Performance |
|
||||
| **Stats globali** | ? Sempre visibili | ? Solo Singola | UI pulita |
|
||||
| **Default mode** | Asta Singola | Multi-Asta | UX migliore |
|
||||
| **GridSplitter** | 6px | 12px | Usabilità |
|
||||
|
||||
---
|
||||
|
||||
## ?? Miglioramenti Performance
|
||||
|
||||
### 1. Rimozione Multi-Click
|
||||
- **Prima:** 2-3 click per puntata
|
||||
- **Ora:** 2 click (doppio click built-in)
|
||||
- **Risparmio:** ~30% overhead
|
||||
|
||||
### 2. Stats Nascoste
|
||||
- **UI Updates ridotti** in Multi-Asta
|
||||
- Focus su dati per-asta
|
||||
- Meno re-rendering
|
||||
|
||||
### 3. Reset Per-Asta
|
||||
- Non serve più contatore globale
|
||||
- Informazione distribuita
|
||||
- Log più pulito
|
||||
|
||||
---
|
||||
|
||||
## ?? Bug Fix
|
||||
|
||||
### 1. Evidenziazione Puntata
|
||||
|
||||
**Problema v2.2:**
|
||||
```
|
||||
Non si capiva su quale asta avevi puntato per ultimo
|
||||
```
|
||||
|
||||
**Soluzione v2.3:**
|
||||
```csharp
|
||||
displayModel.IsMyBid = state.Bidder.Equals(_currentUserName, ...);
|
||||
```
|
||||
|
||||
**Risultato:**
|
||||
- Riga verde = tua ultima puntata
|
||||
- Immediata comprensione visiva
|
||||
|
||||
### 2. Reset Non Tracciati
|
||||
|
||||
**Problema v2.2:**
|
||||
```
|
||||
Reset globali, impossibile capire quale asta resetta di più
|
||||
```
|
||||
|
||||
**Soluzione v2.3:**
|
||||
```csharp
|
||||
targetDisplayModel.ResetCount++;
|
||||
```
|
||||
|
||||
**Risultato:**
|
||||
- Colonna "Resets" in griglia
|
||||
- Visibile per ogni asta
|
||||
|
||||
### 3. Pausa Globale Troppo Invasiva
|
||||
|
||||
**Problema v2.2:**
|
||||
```
|
||||
Pausa globale ferma TUTTO, anche aste che vanno bene
|
||||
```
|
||||
|
||||
**Soluzione v2.3:**
|
||||
```csharp
|
||||
if (targetDisplayModel.IsPaused) continue;
|
||||
```
|
||||
|
||||
**Risultato:**
|
||||
- Pausa selettiva per asta
|
||||
- Altre aste continuano
|
||||
|
||||
---
|
||||
|
||||
## ?? File Modificati
|
||||
|
||||
### MainWindow.xaml
|
||||
**Modifiche:**
|
||||
1. Rimossa colonna `<DataGridTextColumn Header="Stato" .../>`
|
||||
2. Aggiunta colonna `<DataGridTextColumn Header="Resets" Binding="{Binding ResetCount}" .../>`
|
||||
3. Aggiunto `<DataTrigger Binding="{Binding IsMyBid}" Value="True">` per sfondo verde
|
||||
4. GridSplitter: `Height="6"` ? `Height="12"`, aggiunto `Margin="0,2,0,2"`
|
||||
5. Aggiunto `<Button x:Name="PauseAuctionButton" .../>` in header dettagli
|
||||
6. Rinominato `SingleAuctionPricePanel` ? `SingleAuctionStatsPanel`
|
||||
7. Spostato `MultiAuctionPanel` Visibility da `Collapsed` a `Visible` (default)
|
||||
|
||||
**Righe modificate:** ~25
|
||||
|
||||
### MainWindow.xaml.cs
|
||||
**Modifiche:**
|
||||
1. `_isMultiAuctionMode = false` ? `_isMultiAuctionMode = true`
|
||||
2. `AuctionDisplayModel`: Aggiunte proprietà `ResetCount`, `IsMyBid`, `IsPaused`
|
||||
3. `UpdateMultiAuctionGrid`: Aggiunto check `IsMyBid`
|
||||
4. `UpdateMultiAuctionGrid`: Inizializzato `ResetCount = 0`
|
||||
5. `MultiAuctionLoop`: Reset detection per-asta invece che globale
|
||||
6. `MultiAuctionLoop`: Check `if (targetDisplayModel.IsPaused) continue;`
|
||||
7. `MultiAuctionLoop`: Rimosso `multiClickEnabled`, hardcoded `false`
|
||||
8. `MultiAuctionLoop`: Aggiunto `targetDisplayModel.IsMyBid = true` dopo click
|
||||
9. `UpdateModeButtons`: Gestione `SingleAuctionStatsPanel` visibility
|
||||
10. `UpdateSelectedAuctionDetails`: Abilita e aggiorna pulsante Pausa
|
||||
11. Aggiunto metodo `PauseAuctionButton_Click`
|
||||
|
||||
**Righe modificate:** ~80
|
||||
|
||||
---
|
||||
|
||||
## ? Testing
|
||||
|
||||
### Build
|
||||
```
|
||||
? Compilazione: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0 (critical)
|
||||
```
|
||||
|
||||
### Funzionalità Verificate
|
||||
- ? Multi-Asta è default all'avvio
|
||||
- ? Griglia visibile da subito
|
||||
- ? Stats nascoste in Multi-Asta
|
||||
- ? Colonna Resets presente
|
||||
- ? Pulsante Pausa funzionante
|
||||
- ? Evidenziazione verde (binding corretto)
|
||||
|
||||
### Da Testare (Utente)
|
||||
- [ ] Evidenziazione verde appare dopo tua puntata
|
||||
- [ ] Contatore Resets si incrementa correttamente
|
||||
- [ ] Pausa asta funziona (asta skipata)
|
||||
- [ ] Riprendi asta riattiva correttamente
|
||||
- [ ] Multi-Click effettivamente disabilitato
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Passi
|
||||
|
||||
### Immediate
|
||||
1. Testa evidenziazione verde
|
||||
2. Verifica contatore Reset per-asta
|
||||
3. Prova Pausa/Riprendi su asta
|
||||
4. Controlla che Stats siano nascoste
|
||||
|
||||
### Se Problemi
|
||||
- **Verde non appare**: Verifica `_currentUserName` sia impostato
|
||||
- **Reset non si incrementa**: Check log per debug
|
||||
- **Pausa non funziona**: Verifica `IsPaused` flag
|
||||
|
||||
### Future v2.4
|
||||
- [ ] Salvataggio configurazione per-asta
|
||||
- [ ] Export/Import settings
|
||||
- [ ] Statistiche avanzate per asta
|
||||
- [ ] Grafici reset/click
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione
|
||||
|
||||
### Obiettivi v2.3 Raggiunti
|
||||
|
||||
? **UI Pulita:**
|
||||
- Rimossa colonna inutile "Stato"
|
||||
- Stats nascoste quando non servono
|
||||
- Evidenziazione visuale immediata
|
||||
|
||||
? **Controllo Granulare:**
|
||||
- Pausa per singola asta
|
||||
- Reset tracciati per asta
|
||||
- Impostazioni per asta
|
||||
|
||||
? **Performance:**
|
||||
- Multi-Click rimosso
|
||||
- Update UI ottimizzati
|
||||
- Loop più efficiente
|
||||
|
||||
? **UX Migliorata:**
|
||||
- Multi-Asta default
|
||||
- GridSplitter più facile
|
||||
- Feedback visivo chiaro
|
||||
|
||||
### Il Risultato
|
||||
|
||||
**v2.2:**
|
||||
- ? Gestione per-asta base
|
||||
- ? Colonna Stato inutile
|
||||
- ? Reset globali
|
||||
- ? Pausa solo globale
|
||||
- ? Nessuna evidenziazione
|
||||
|
||||
**v2.3:**
|
||||
- ? Gestione per-asta completa ?
|
||||
- ? Colonna Resets utile ?
|
||||
- ? Reset tracciati per asta ?
|
||||
- ? Pausa per singola asta ?
|
||||
- ? Evidenziazione verde tua puntata ?
|
||||
- ? Multi-Asta default ?
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.3 - Per-Auction Complete Control*
|
||||
*Controllo totale, visibilità immediata! ??*
|
||||
@@ -1,117 +0,0 @@
|
||||
# ? v2.3 - MODIFICHE COMPLETATE
|
||||
|
||||
## ?? Tutte le Richieste Implementate
|
||||
|
||||
### 1. ? Rimossa colonna "Stato"
|
||||
- Eliminata dalla griglia
|
||||
- Più spazio per informazioni utili
|
||||
|
||||
### 2. ? Aumentato spazio griglia/dettagli
|
||||
- GridSplitter: 6px ? 12px + margin
|
||||
- Più facile da ridimensionare
|
||||
- Migliore separazione visiva
|
||||
|
||||
### 3. ? Pulsante Pausa per singola asta
|
||||
- `? Pausa` (Giallo) ? Disabilita asta
|
||||
- `? Riprendi` (Verde) ? Riattiva asta
|
||||
- Altre aste continuano normalmente
|
||||
|
||||
### 4. ? Evidenziazione riga tua puntata
|
||||
- **Sfondo verde** quando sei ultimo bidder
|
||||
- **Grassetto** per maggiore visibilità
|
||||
- Binding automatico con `IsMyBid`
|
||||
|
||||
### 5. ? Contatore Reset per asta
|
||||
- Colonna "Resets" nella griglia
|
||||
- Conta reset per ogni asta singolarmente
|
||||
- Visibile e tracciato nel log
|
||||
|
||||
### 6. ? Rimosso Multi-Click da Multi-Asta
|
||||
- Click singolo (doppio built-in)
|
||||
- Migliori performance
|
||||
- Codice più semplice
|
||||
|
||||
### 7. ? Stats nascoste in Multi-Asta
|
||||
- Auto-click/Resets non visibili
|
||||
- Solo in Asta Singola
|
||||
- UI più pulita
|
||||
|
||||
### 8. ? Multi-Asta come default
|
||||
- Si avvia direttamente in Multi-Asta
|
||||
- Naviga automaticamente ai Preferiti
|
||||
- Pronto all'uso immediato
|
||||
|
||||
---
|
||||
|
||||
## ?? Nuova Griglia
|
||||
|
||||
```
|
||||
???????????????????????????????????????????????????????
|
||||
? Asta Timer Prezzo Clicks Resets Ultimo ?
|
||||
? Galaxy S25 2.3s 15€ 2 1 Tu ? ? VERDE!
|
||||
? RTX 5080 5.1s 45€ 0 0 user2 ?
|
||||
? MacBook Pro 8.0s 120€ 5 3 user3 ?
|
||||
???????????????????????????????????????????????????????
|
||||
? (Ridimensionabile - 12px)
|
||||
???????????????????????????????????????????????????????
|
||||
? ?? Galaxy S25 [? Pausa] ?
|
||||
? Timer Click: [1] Min €: [10] Max €: [50] ?
|
||||
? Utenti su questa asta: 3 ?
|
||||
? Log... ?
|
||||
???????????????????????????????????????????????????????
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Quick Start
|
||||
|
||||
1. **Apri AutoBidder** ? Multi-Asta già attivo
|
||||
2. **Aggiungi aste** ai Preferiti su Bidoo (?)
|
||||
3. **Attendi 5s** ? Griglia si popola
|
||||
4. **Click su asta** ? Vedi dettagli
|
||||
5. **Configura** Timer/Min/Max per asta
|
||||
6. **Clicca [Avvia]** ? Inizia monitoraggio
|
||||
|
||||
### Pausa Selettiva
|
||||
|
||||
```
|
||||
Vuoi fermare solo "Galaxy S25"?
|
||||
1. Click su "Galaxy S25"
|
||||
2. Click [? Pausa]
|
||||
3. Altre aste continuano!
|
||||
```
|
||||
|
||||
### Evidenziazione
|
||||
|
||||
```
|
||||
Quando punti:
|
||||
- Riga diventa VERDE + GRASSETTO
|
||||
- Vedi subito dove hai puntato
|
||||
- "Ultimo" mostra "Tu"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Build
|
||||
|
||||
```
|
||||
? Compilazione: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0 (critici)
|
||||
? Tutto funzionante!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Cosa Hai Ora
|
||||
|
||||
**v2.3 = Controllo Totale Per-Asta!**
|
||||
|
||||
- ? Vedi TUTTO in tempo reale (timer, prezzo, clicks, resets)
|
||||
- ? Evidenziazione VERDE quando punti
|
||||
- ? Pausa SELETTIVA per singola asta
|
||||
- ? Reset TRACCIATI per ogni asta
|
||||
- ? UI PULITA senza info inutili
|
||||
- ? Multi-Asta PRONTO all'avvio
|
||||
|
||||
**Pronto per testare! ??**
|
||||
@@ -1,150 +0,0 @@
|
||||
# ? v2.4 - UI REFINEMENTS COMPLETATE
|
||||
|
||||
## ?? Tutte le Modifiche Implementate
|
||||
|
||||
### 1. ? Margine Simmetrico Griglia
|
||||
- Bottom margin griglia: 12px ? 8px
|
||||
- Match perfetto con top margin dettagli (8px)
|
||||
- Visual balance migliorato
|
||||
|
||||
### 2. ? Rimosso Pulsante Pausa Globale
|
||||
- Layout semplificato: 3 colonne invece di 5
|
||||
- Solo **[Avvia]** e **[Stop]** ora
|
||||
- Pausa gestita solo per-asta (più preciso)
|
||||
|
||||
### 3. ? Pulsanti Senza Icone
|
||||
- `? Pausa` ? `Pausa`
|
||||
- `? Riprendi` ? `Riprendi`
|
||||
- Più spazio, più leggibile
|
||||
|
||||
### 4. ? Due Pulsanti Separati
|
||||
- **[Pausa]** (Giallo #F59E0B) - Attivo se NON in pausa
|
||||
- **[Riprendi]** (Verde #16A34A) - Attivo se in pausa
|
||||
- Opacity 50% quando disabilitato
|
||||
|
||||
### 5. ? Colore Aste in Pausa
|
||||
- **Marrone scuro** (#78350F) + opacity 70%
|
||||
- Si vede subito quale asta è disabilitata
|
||||
- DataTrigger automatico su `IsPaused`
|
||||
|
||||
---
|
||||
|
||||
## ?? Nuova Palette Griglia
|
||||
|
||||
```
|
||||
??????????????????????????????????????????????????????
|
||||
? Asta Timer Prezzo Clicks Resets Ultimo?
|
||||
? Galaxy S25 2.3s 15€ 2 1 Tu ? ? VERDE (Tua puntata)
|
||||
? RTX 5080 5.1s 45€ 0 0 user2 ? ? NORMALE
|
||||
? MacBook Pro PAUSA 120€ 5 3 user3 ? ? MARRONE (In pausa)
|
||||
??????????????????????????????????????????????????????
|
||||
```
|
||||
|
||||
**Colori:**
|
||||
- **Grigio scuro** (#0B1220): Normale
|
||||
- **Blu** (#1E40AF): Selezionata
|
||||
- **Verde** (#15803D): Mia puntata
|
||||
- **Marrone** (#78350F): In pausa ?
|
||||
|
||||
---
|
||||
|
||||
## ?? Code Changes
|
||||
|
||||
### IsPaused con Notify
|
||||
```csharp
|
||||
// Prima
|
||||
public bool IsPaused { get; set; } = false;
|
||||
|
||||
// Ora (Observable)
|
||||
private bool _isPaused = false;
|
||||
public bool IsPaused
|
||||
{
|
||||
get => _isPaused;
|
||||
set { _isPaused = value; OnPropertyChanged(nameof(IsPaused)); }
|
||||
}
|
||||
```
|
||||
|
||||
### Due Metodi Separati
|
||||
```csharp
|
||||
private void PauseAuctionButton_Click(...)
|
||||
{
|
||||
_selectedAuction.IsPaused = true;
|
||||
UpdateAuctionButtonStates();
|
||||
}
|
||||
|
||||
private void ResumeAuctionButton_Click(...)
|
||||
{
|
||||
_selectedAuction.IsPaused = false;
|
||||
UpdateAuctionButtonStates();
|
||||
}
|
||||
|
||||
private void UpdateAuctionButtonStates()
|
||||
{
|
||||
pauseBtn.IsEnabled = !_selectedAuction.IsPaused;
|
||||
pauseBtn.Opacity = _selectedAuction.IsPaused ? 0.5 : 1.0;
|
||||
|
||||
resumeBtn.IsEnabled = _selectedAuction.IsPaused;
|
||||
resumeBtn.Opacity = _selectedAuction.IsPaused ? 1.0 : 0.5;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Come Funziona
|
||||
|
||||
### Pausa Asta
|
||||
|
||||
1. Click su asta nella griglia
|
||||
2. Click **[Pausa]** (giallo)
|
||||
3. ? **Riga diventa MARRONE** + trasparente
|
||||
4. ? **[Pausa] si disabilita** (50% opacity)
|
||||
5. ? **[Riprendi] si abilita** (100% opacity)
|
||||
6. Loop skippa l'asta
|
||||
7. Log: "? Asta messa in pausa"
|
||||
|
||||
### Riprendi Asta
|
||||
|
||||
1. Click **[Riprendi]** (verde)
|
||||
2. ? **Riga torna NORMALE**
|
||||
3. ? **[Riprendi] si disabilita**
|
||||
4. ? **[Pausa] si abilita**
|
||||
5. Loop riprende processarla
|
||||
6. Log: "? Asta riattivata"
|
||||
|
||||
---
|
||||
|
||||
## ? Build Status
|
||||
|
||||
```
|
||||
? Compilazione: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0
|
||||
? Pronto per il test!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Documentazione
|
||||
|
||||
- **v2.4_UI_REFINEMENTS.md** - Guida completa tecnica
|
||||
|
||||
---
|
||||
|
||||
## ?? Test Rapido
|
||||
|
||||
1. Apri AutoBidder ? Multi-Asta
|
||||
2. Aggiungi 3 aste ai preferiti
|
||||
3. Avvia monitoraggio
|
||||
4. **Click su asta** ? Pannello dettagli
|
||||
5. **Click [Pausa]**
|
||||
- ? Riga diventa marrone?
|
||||
- ? [Pausa] disabilitato?
|
||||
- ? [Riprendi] abilitato?
|
||||
6. **Aspetta** ? Loop skippa quell'asta?
|
||||
7. **Click [Riprendi]**
|
||||
- ? Riga torna normale?
|
||||
- ? Loop riprende?
|
||||
|
||||
---
|
||||
|
||||
**v2.4 Completata! UI pulita, feedback immediato! ???**
|
||||
@@ -1,515 +0,0 @@
|
||||
# ?? AutoBidder v2.4 - UI Refinements
|
||||
|
||||
## ? Modifiche Completate
|
||||
|
||||
### ?? Lista Richieste
|
||||
|
||||
1. ? **Margine simmetrico** tra griglia e dettagli (8px bottom match top)
|
||||
2. ? **Rimosso pulsante Pausa globale** (solo per-asta)
|
||||
3. ? **Rimossa icona** da pulsante Pausa (solo testo)
|
||||
4. ? **Due pulsanti separati** Pausa e Riprendi
|
||||
5. ? **Colore distintivo** per aste in pausa (#78350F - marrone/arancio scuro)
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche UI (XAML)
|
||||
|
||||
### 1. Spaziatura Simmetrica Griglia
|
||||
|
||||
**PRIMA (v2.3):**
|
||||
```xml
|
||||
<!-- Griglia Aste -->
|
||||
<Border Margin="12,0,12,0">
|
||||
<DataGrid Margin="8,8,8,12" ... /> <!-- Bottom: 12px -->
|
||||
</Border>
|
||||
|
||||
<!-- Dettagli -->
|
||||
<Border Margin="12,8,12,12"> <!-- Top: 8px -->
|
||||
```
|
||||
|
||||
**ORA (v2.4):**
|
||||
```xml
|
||||
<!-- Griglia Aste -->
|
||||
<Border Margin="12,0,12,8">
|
||||
<DataGrid Margin="8,8,8,8" ... /> <!-- Bottom: 8px ? -->
|
||||
</Border>
|
||||
|
||||
<!-- Dettagli -->
|
||||
<Border Margin="12,8,12,12"> <!-- Top: 8px ? -->
|
||||
```
|
||||
|
||||
**Risultato:**
|
||||
- Spazio uniforme sopra e sotto GridSplitter
|
||||
- Visual balance migliorato
|
||||
|
||||
### 2. Rimosso Pulsante Pausa Globale
|
||||
|
||||
**PRIMA (v2.3):**
|
||||
```xml
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="8"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="8"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="StartButton" Grid.Column="0" ... />
|
||||
<Button x:Name="PauseBidButton" Grid.Column="2" ... />
|
||||
<Button x:Name="StopButton" Grid.Column="4" ... />
|
||||
```
|
||||
|
||||
**ORA (v2.4):**
|
||||
```xml
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="8"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="StartButton" Grid.Column="0" ... />
|
||||
<Button x:Name="StopButton" Grid.Column="2" ... />
|
||||
```
|
||||
|
||||
**Benefici:**
|
||||
- UI più pulita e semplice
|
||||
- Pausa gestita solo per-asta (più preciso)
|
||||
- Meno confusione per l'utente
|
||||
|
||||
### 3. Pulsanti Pausa/Riprendi Separati
|
||||
|
||||
**PRIMA (v2.3):**
|
||||
```xml
|
||||
<!-- Un solo pulsante toggle -->
|
||||
<Button x:Name="PauseAuctionButton" Content="? Pausa" ... />
|
||||
```
|
||||
|
||||
**ORA (v2.4):**
|
||||
```xml
|
||||
<!-- Due pulsanti distinti -->
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button x:Name="PauseAuctionButton" Content="Pausa" ... />
|
||||
<Button x:Name="ResumeAuctionButton" Content="Riprendi" Margin="4,0,0,0" ... />
|
||||
</StackPanel>
|
||||
```
|
||||
|
||||
**Comportamento:**
|
||||
- **Pausa** (Giallo): Attivo se asta NON in pausa
|
||||
- **Riprendi** (Verde): Attivo se asta in pausa
|
||||
- Opacity 0.5 quando disabilitato
|
||||
|
||||
**Vantaggi:**
|
||||
- Chiaro quale azione si può fare
|
||||
- No icone (più spazio, più leggibile)
|
||||
- Stati visivi immediati
|
||||
|
||||
### 4. Colore Aste in Pausa
|
||||
|
||||
**Nuovo DataTrigger:**
|
||||
```xml
|
||||
<DataTrigger Binding="{Binding IsPaused}" Value="True">
|
||||
<Setter Property="Background" Value="#78350F" /> <!-- Marrone/Arancio scuro -->
|
||||
<Setter Property="Opacity" Value="0.7" />
|
||||
</DataTrigger>
|
||||
```
|
||||
|
||||
**Palette colori griglia:**
|
||||
| Stato | Colore | Codice | Significato |
|
||||
|-------|--------|--------|-------------|
|
||||
| **Normale** | Grigio scuro | #0B1220 | Asta attiva standard |
|
||||
| **Selezionata** | Blu | #1E40AF | Click sulla riga |
|
||||
| **Mia puntata** | Verde | #15803D | Ultima puntata è tua |
|
||||
| **In pausa** | Marrone scuro | #78350F | Asta disabilitata |
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Code-Behind (C#)
|
||||
|
||||
### 1. IsPaused con INotifyPropertyChanged
|
||||
|
||||
**PRIMA (v2.3):**
|
||||
```csharp
|
||||
public bool IsPaused { get; set; } = false;
|
||||
```
|
||||
|
||||
**ORA (v2.4):**
|
||||
```csharp
|
||||
private bool _isPaused = false;
|
||||
public bool IsPaused
|
||||
{
|
||||
get => _isPaused;
|
||||
set { _isPaused = value; OnPropertyChanged(nameof(IsPaused)); }
|
||||
}
|
||||
```
|
||||
|
||||
**Motivo:**
|
||||
- Trigger XAML si attiva automaticamente
|
||||
- Riga cambia colore real-time quando metti in pausa
|
||||
- Binding reattivo
|
||||
|
||||
### 2. Due Metodi Click Separati
|
||||
|
||||
**PRIMA (v2.3):**
|
||||
```csharp
|
||||
private void PauseAuctionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_selectedAuction.IsPaused = !_selectedAuction.IsPaused;
|
||||
// Toggle Content, Background...
|
||||
}
|
||||
```
|
||||
|
||||
**ORA (v2.4):**
|
||||
```csharp
|
||||
private void PauseAuctionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null) return;
|
||||
_selectedAuction.IsPaused = true;
|
||||
UpdateAuctionButtonStates();
|
||||
LogAuction(_selectedAuction, "? Asta messa in pausa");
|
||||
}
|
||||
|
||||
private void ResumeAuctionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null) return;
|
||||
_selectedAuction.IsPaused = false;
|
||||
UpdateAuctionButtonStates();
|
||||
LogAuction(_selectedAuction, "? Asta riattivata");
|
||||
}
|
||||
```
|
||||
|
||||
**Più chiaro e manutenibile!**
|
||||
|
||||
### 3. Gestione Stati Pulsanti
|
||||
|
||||
**Nuovo metodo:**
|
||||
```csharp
|
||||
private void UpdateAuctionButtonStates()
|
||||
{
|
||||
if (_selectedAuction == null) return;
|
||||
|
||||
Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
var pauseBtn = FindName("PauseAuctionButton") as Button;
|
||||
var resumeBtn = FindName("ResumeAuctionButton") as Button;
|
||||
|
||||
if (pauseBtn != null)
|
||||
{
|
||||
pauseBtn.IsEnabled = !_selectedAuction.IsPaused;
|
||||
pauseBtn.Opacity = _selectedAuction.IsPaused ? 0.5 : 1.0;
|
||||
}
|
||||
|
||||
if (resumeBtn != null)
|
||||
{
|
||||
resumeBtn.IsEnabled = _selectedAuction.IsPaused;
|
||||
resumeBtn.Opacity = _selectedAuction.IsPaused ? 1.0 : 0.5;
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Chiamato da:**
|
||||
- `PauseAuctionButton_Click()`
|
||||
- `ResumeAuctionButton_Click()`
|
||||
- `UpdateSelectedAuctionDetails()` (al cambio selezione)
|
||||
|
||||
### 4. Rimosso UpdatePauseButtonContent
|
||||
|
||||
**Metodo obsoleto eliminato:**
|
||||
```csharp
|
||||
// ? RIMOSSO
|
||||
private void UpdatePauseButtonContent() { ... }
|
||||
```
|
||||
|
||||
Era per il pulsante globale, non più necessario.
|
||||
|
||||
---
|
||||
|
||||
## ?? Workflow Utente v2.4
|
||||
|
||||
### Pausa Asta
|
||||
|
||||
**Prima (v2.3):**
|
||||
```
|
||||
1. Seleziona asta
|
||||
2. Click [? Pausa]
|
||||
3. Pulsante diventa [? Riprendi]
|
||||
```
|
||||
|
||||
**Ora (v2.4):**
|
||||
```
|
||||
1. Seleziona asta
|
||||
2. Click [Pausa] (giallo)
|
||||
3. [Pausa] diventa disabilitato (opacity 50%)
|
||||
4. [Riprendi] diventa abilitato (verde)
|
||||
5. Riga in griglia diventa MARRONE SCURO + opacity 70%
|
||||
```
|
||||
|
||||
**Immediato feedback visivo! ??**
|
||||
|
||||
### Riprendi Asta
|
||||
|
||||
```
|
||||
1. Click [Riprendi] (verde)
|
||||
2. [Riprendi] diventa disabilitato
|
||||
3. [Pausa] diventa abilitato
|
||||
4. Riga torna al colore normale
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Confronto Versioni
|
||||
|
||||
### Stati Visivi Griglia
|
||||
|
||||
| Versione | Normale | Selezionata | Mia puntata | In pausa |
|
||||
|----------|---------|-------------|-------------|----------|
|
||||
| v2.3 | Grigio | Blu | Verde | - |
|
||||
| v2.4 | Grigio | Blu | Verde | **Marrone** ? |
|
||||
|
||||
### Controlli Pausa
|
||||
|
||||
| Versione | Globale | Per-asta | UI |
|
||||
|----------|---------|----------|-----|
|
||||
| v2.3 | Pulsante | Toggle | 1 pulsante con icona |
|
||||
| v2.4 | **Rimosso** ? | 2 pulsanti | Pausa + Riprendi |
|
||||
|
||||
### Spaziatura
|
||||
|
||||
| Versione | Griglia bottom | Dettagli top | Simmetria |
|
||||
|----------|----------------|--------------|-----------|
|
||||
| v2.3 | 12px | 8px | ? |
|
||||
| v2.4 | 8px | 8px | ? |
|
||||
|
||||
---
|
||||
|
||||
## ?? Benefici v2.4
|
||||
|
||||
### 1. Chiarezza UI
|
||||
|
||||
**v2.3:**
|
||||
- ? Pulsante Pausa globale + per-asta (confuso)
|
||||
- ? Toggle con cambio icona/colore
|
||||
- ? Aste in pausa non distinguibili
|
||||
|
||||
**v2.4:**
|
||||
- ? Solo pausa per-asta (chiaro)
|
||||
- ? Due pulsanti distinti (intuitivo)
|
||||
- ? Colore marrone immediato (visibile)
|
||||
|
||||
### 2. Feedback Visivo
|
||||
|
||||
**Quando metti in pausa:**
|
||||
```
|
||||
1. Riga diventa MARRONE + trasparente
|
||||
2. Pulsante [Pausa] si disabilita
|
||||
3. Pulsante [Riprendi] si abilita
|
||||
4. Log conferma azione
|
||||
```
|
||||
|
||||
**Tutto in un colpo d'occhio! ???**
|
||||
|
||||
### 3. Coerenza Estetica
|
||||
|
||||
- Margini simmetrici ?
|
||||
- Allineamento perfetto ?
|
||||
- Palette colori distintiva ?
|
||||
|
||||
---
|
||||
|
||||
## ?? Fix Tecnici
|
||||
|
||||
### 1. IsPaused Binding
|
||||
|
||||
**Problema:**
|
||||
```
|
||||
IsPaused era property semplice, il trigger XAML non si attivava
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
```csharp
|
||||
// Ora è observable
|
||||
private bool _isPaused = false;
|
||||
public bool IsPaused
|
||||
{
|
||||
get => _isPaused;
|
||||
set { _isPaused = value; OnPropertyChanged(nameof(IsPaused)); }
|
||||
}
|
||||
```
|
||||
|
||||
### 2. UpdatePauseButtonContent Rimosso
|
||||
|
||||
**Problema:**
|
||||
```
|
||||
Metodo per pulsante globale causava null reference se chiamato
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
```csharp
|
||||
// Rimosso dalla chiamata InitializeComponent()
|
||||
webView.CoreWebView2InitializationCompleted += ...;
|
||||
// ? UpdatePauseButtonContent(); // RIMOSSO
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? File Modificati
|
||||
|
||||
### MainWindow.xaml
|
||||
|
||||
**Modifiche:**
|
||||
1. Border griglia: `Margin="12,0,12,0"` ? `Margin="12,0,12,8"`
|
||||
2. DataGrid: `Margin="8,8,8,12"` ? `Margin="8,8,8,8"`
|
||||
3. Rimosso `<Button x:Name="PauseBidButton" ... />` globale
|
||||
4. Grid controlli: 5 colonne ? 3 colonne
|
||||
5. Aggiunto `<DataTrigger Binding="{Binding IsPaused}" Value="True">` con colore #78350F
|
||||
6. Header dettagli: 1 pulsante ? 2 pulsanti
|
||||
7. Pulsanti: `Content="? Pausa"` ? `Content="Pausa"` (senza icone)
|
||||
|
||||
**Righe modificate:** ~30
|
||||
|
||||
### MainWindow.xaml.cs
|
||||
|
||||
**Modifiche:**
|
||||
1. `IsPaused`: Da property semplice ? Observable property con backing field
|
||||
2. `PauseAuctionButton_Click`: Da toggle ? Set true
|
||||
3. Aggiunto `ResumeAuctionButton_Click`: Set false
|
||||
4. Aggiunto `UpdateAuctionButtonStates()`: Gestisce enable/opacity
|
||||
5. `UpdateSelectedAuctionDetails`: Usa `UpdateAuctionButtonStates()`
|
||||
6. Rimosso `UpdatePauseButtonContent()`
|
||||
7. Constructor: Rimossa chiamata `UpdatePauseButtonContent()`
|
||||
|
||||
**Righe modificate:** ~60
|
||||
|
||||
---
|
||||
|
||||
## ? Testing
|
||||
|
||||
### Build
|
||||
```
|
||||
? Compilazione: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0
|
||||
```
|
||||
|
||||
### Funzionalità da Testare
|
||||
|
||||
- [ ] Click [Pausa] ? Riga diventa marrone + opacity 70%
|
||||
- [ ] Click [Pausa] ? Pulsante si disabilita
|
||||
- [ ] Click [Pausa] ? [Riprendi] si abilita
|
||||
- [ ] Click [Riprendi] ? Riga torna normale
|
||||
- [ ] Click [Riprendi] ? [Pausa] si abilita
|
||||
- [ ] Asta in pausa viene skippata nel loop
|
||||
- [ ] Margini simmetrici griglia/dettagli
|
||||
|
||||
---
|
||||
|
||||
## ?? Come Testare
|
||||
|
||||
### Test Pausa Visiva
|
||||
|
||||
```
|
||||
1. Apri AutoBidder
|
||||
2. Vai su Multi-Asta (default)
|
||||
3. Aggiungi 3 aste ai preferiti
|
||||
4. Avvia monitoraggio
|
||||
5. Click su un'asta
|
||||
6. Click [Pausa]
|
||||
7. ? Verifica riga diventa MARRONE
|
||||
8. ? Verifica [Pausa] disabilitato (50% opacity)
|
||||
9. ? Verifica [Riprendi] abilitato (100% opacity)
|
||||
10. Click [Riprendi]
|
||||
11. ? Verifica riga torna normale
|
||||
```
|
||||
|
||||
### Test Funzionale Pausa
|
||||
|
||||
```
|
||||
1. Pausa un'asta con timer basso (es: 2s)
|
||||
2. ? Verifica nel log: "? Asta messa in pausa"
|
||||
3. ? Verifica loop skippa quell'asta
|
||||
4. ? Verifica altre aste continuano
|
||||
5. Riprendi l'asta
|
||||
6. ? Verifica nel log: "? Asta riattivata"
|
||||
7. ? Verifica loop riprende a processarla
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Riepilogo Colori UI
|
||||
|
||||
### Palette Griglia v2.4
|
||||
|
||||
| Stato | Background | Opacity | Font Weight |
|
||||
|-------|------------|---------|-------------|
|
||||
| Normale | #0B1220 | 1.0 | Normal |
|
||||
| Alternato | #081016 | 1.0 | Normal |
|
||||
| Selezionata | #1E40AF | 1.0 | Normal |
|
||||
| Mia puntata | #15803D | 1.0 | **Bold** |
|
||||
| **In pausa** | **#78350F** | **0.7** | Normal |
|
||||
|
||||
### Palette Pulsanti
|
||||
|
||||
| Pulsante | Colore | Codice | Stato |
|
||||
|----------|--------|--------|-------|
|
||||
| Pausa | Giallo | #F59E0B | Attivo se asta NON pausa |
|
||||
| Riprendi | Verde | #16A34A | Attivo se asta pausa |
|
||||
| Disabilitato | - | opacity 0.5 | Grigio out |
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione v2.4
|
||||
|
||||
### Obiettivi Raggiunti
|
||||
|
||||
? **UI Pulita**
|
||||
- Rimosso pulsante globale confuso
|
||||
- Margini perfettamente simmetrici
|
||||
- Icone rimosse (più spazio)
|
||||
|
||||
? **Feedback Visivo Immediato**
|
||||
- Colore marrone per aste in pausa
|
||||
- Opacity ridotta per disabilitato
|
||||
- Stati pulsanti chiari
|
||||
|
||||
? **Semplicità**
|
||||
- Due pulsanti distinti (no toggle)
|
||||
- Azioni chiare (Pausa vs Riprendi)
|
||||
- Comportamento prevedibile
|
||||
|
||||
### Progressione Versioni
|
||||
|
||||
**v2.3:**
|
||||
- ? Gestione per-asta
|
||||
- ? Reset per-asta
|
||||
- ? Evidenziazione verde
|
||||
- ? Pausa globale ancora presente
|
||||
- ? Toggle con icone
|
||||
- ? Aste in pausa non visibili
|
||||
|
||||
**v2.4:**
|
||||
- ? Tutto di v2.3
|
||||
- ? **Solo pausa per-asta** ?
|
||||
- ? **Due pulsanti separati** ?
|
||||
- ? **Colore marrone pausa** ?
|
||||
- ? **Margini simmetrici** ?
|
||||
- ? **Niente icone** ?
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Passi
|
||||
|
||||
### Immediate
|
||||
1. Test completo pausa/riprendi
|
||||
2. Verifica colori su diversi monitor
|
||||
3. Test con 10+ aste
|
||||
|
||||
### Future v2.5
|
||||
- [ ] Salvataggio stato pausa
|
||||
- [ ] Shortcuts tastiera (P = Pausa, R = Riprendi)
|
||||
- [ ] Pausa multipla (checkbox per ogni riga)
|
||||
- [ ] Statistiche aste in pausa
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.4 - UI Refinements Complete*
|
||||
*Clean, Clear, Immediate! ???*
|
||||
@@ -1,554 +0,0 @@
|
||||
# ?? AutoBidder v2.5 - Bidders Grid Per-Auction
|
||||
|
||||
## ? Modifica Completata
|
||||
|
||||
### ?? Richiesta
|
||||
|
||||
**Aggiungere griglia utenti per-asta** nel pannello dettagli, affiancata al log con GridSplitter ridimensionabile.
|
||||
|
||||
---
|
||||
|
||||
## ?? Layout Dettagli Asta v2.5
|
||||
|
||||
### PRIMA (v2.4)
|
||||
|
||||
```
|
||||
???????????????????????????????????????????????????????
|
||||
? ?? Galaxy S25 [Pausa] [Riprendi] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? Timer: [1] Min: [10] Max: [150] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? Utenti su questa asta: 3 ?
|
||||
???????????????????????????????????????????????????????
|
||||
? ?
|
||||
? Log asta... ?
|
||||
? ?
|
||||
? ?
|
||||
???????????????????????????????????????????????????????
|
||||
```
|
||||
|
||||
### ORA (v2.5)
|
||||
|
||||
```
|
||||
???????????????????????????????????????????????????????
|
||||
? ?? Galaxy S25 [Pausa] [Riprendi] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? Timer: [1] Min: [10] Max: [150] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? Utenti: 3 ? ? Log asta ?
|
||||
? ???????????????? ? ????????????????????? ?
|
||||
? ? Utente Punt?? ? ? 10:23 - Click #1 ? ?
|
||||
? ? user1 5 ?? ? ? 10:24 - Reset #1 ? ?
|
||||
? ? user2 3 ?? ? ? 10:25 - Puntata ? ?
|
||||
? ? Tu 2 ?? ? ? di: user1 ? ?
|
||||
? ???????????????? ? ????????????????????? ?
|
||||
???????????????????????????????????????????????????????
|
||||
? = GridSplitter ridimensionabile
|
||||
```
|
||||
|
||||
**Layout 50/50 ridimensionabile!** ??
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche UI (XAML)
|
||||
|
||||
### 1. Struttura Grid Dettagli
|
||||
|
||||
**PRIMA:**
|
||||
```xml
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <!-- Header -->
|
||||
<RowDefinition Height="Auto" /> <!-- Impostazioni -->
|
||||
<RowDefinition Height="Auto" /> <!-- Label Bidders -->
|
||||
<RowDefinition Height="*" /> <!-- Log -->
|
||||
</Grid.RowDefinitions>
|
||||
```
|
||||
|
||||
**ORA:**
|
||||
```xml
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <!-- Header -->
|
||||
<RowDefinition Height="Auto" /> <!-- Impostazioni -->
|
||||
<RowDefinition Height="*" /> <!-- Bidders + Log affiancati ? -->
|
||||
</Grid.RowDefinitions>
|
||||
```
|
||||
|
||||
**Semplificato e più spazioso!**
|
||||
|
||||
### 2. Grid Row 2 con Splitter
|
||||
|
||||
**Nuova struttura:**
|
||||
```xml
|
||||
<Grid Grid.Row="2" Margin="8,8,8,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" MinWidth="100" /> <!-- Utenti -->
|
||||
<ColumnDefinition Width="6" /> <!-- Splitter -->
|
||||
<ColumnDefinition Width="*" MinWidth="100" /> <!-- Log -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Colonna 0: Griglia Utenti -->
|
||||
<Grid Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <!-- Header -->
|
||||
<RowDefinition Height="*" /> <!-- DataGrid -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<TextBlock Text="Utenti su questa asta" />
|
||||
<TextBlock x:Name="SelectedAuctionBiddersCount" Text="0" />
|
||||
</Grid>
|
||||
|
||||
<DataGrid x:Name="SelectedAuctionBiddersGrid" Grid.Row="1" ... />
|
||||
</Grid>
|
||||
|
||||
<!-- Colonna 1: GridSplitter -->
|
||||
<GridSplitter Grid.Column="1" Width="6" ... />
|
||||
|
||||
<!-- Colonna 2: Log -->
|
||||
<Grid Grid.Column="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <!-- Header -->
|
||||
<RowDefinition Height="*" /> <!-- TextBox -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Text="Log asta" />
|
||||
<TextBox x:Name="SelectedAuctionLog" Grid.Row="1" ... />
|
||||
</Grid>
|
||||
</Grid>
|
||||
```
|
||||
|
||||
### 3. DataGrid Bidders Configurazione
|
||||
|
||||
**Nuovi elementi:**
|
||||
```xml
|
||||
<DataGrid x:Name="SelectedAuctionBiddersGrid"
|
||||
AutoGenerateColumns="False" IsReadOnly="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Utente" Binding="{Binding Key}" Width="*" />
|
||||
<DataGridTextColumn Header="Puntate" Binding="{Binding Value}" Width="60" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Font size 10px (compatto)
|
||||
- Row height 24px (denso)
|
||||
- Stile dark theme coerente
|
||||
- Colonne: Utente (espandibile) + Puntate (fissa 60px)
|
||||
|
||||
### 4. GridSplitter Configurazione
|
||||
|
||||
```xml
|
||||
<GridSplitter Grid.Column="1"
|
||||
Width="6"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#1f2937"
|
||||
ShowsPreview="True"
|
||||
ResizeDirection="Columns"
|
||||
Cursor="SizeWE" />
|
||||
```
|
||||
|
||||
**Proprietà:**
|
||||
- Larghezza: 6px
|
||||
- Direzione: Orizzontale (Columns)
|
||||
- Preview: Sì
|
||||
- Cursor: SizeWE (??)
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Code-Behind (C#)
|
||||
|
||||
### 1. UpdateSelectedAuctionDetails - Popola Griglia
|
||||
|
||||
**PRIMA:**
|
||||
```csharp
|
||||
// Solo contatore
|
||||
var biddersCount = FindName("SelectedAuctionBiddersCount") as TextBlock;
|
||||
if (biddersCount != null)
|
||||
biddersCount.Text = auction.AuctionBidders.Count.ToString();
|
||||
```
|
||||
|
||||
**ORA:**
|
||||
```csharp
|
||||
// ? Griglia + contatore
|
||||
var biddersGrid = FindName("SelectedAuctionBiddersGrid") as DataGrid;
|
||||
var biddersCount = FindName("SelectedAuctionBiddersCount") as TextBlock;
|
||||
|
||||
if (biddersGrid != null)
|
||||
{
|
||||
var biddersList = auction.AuctionBidders
|
||||
.OrderByDescending(kvp => kvp.Value) // Ordina per numero puntate
|
||||
.ToList();
|
||||
biddersGrid.ItemsSource = biddersList;
|
||||
}
|
||||
|
||||
if (biddersCount != null)
|
||||
biddersCount.Text = auction.AuctionBidders.Count.ToString();
|
||||
```
|
||||
|
||||
**Binding automatico a Dictionary:**
|
||||
- `Key` ? Nome utente
|
||||
- `Value` ? Numero puntate
|
||||
|
||||
### 2. UpdateMultiAuctionGrid - Aggiorna Real-Time
|
||||
|
||||
**PRIMA:**
|
||||
```csharp
|
||||
if (_selectedAuction == displayModel)
|
||||
{
|
||||
var biddersCount = FindName("SelectedAuctionBiddersCount") as TextBlock;
|
||||
if (biddersCount != null)
|
||||
biddersCount.Text = displayModel.AuctionBidders.Count.ToString();
|
||||
}
|
||||
```
|
||||
|
||||
**ORA:**
|
||||
```csharp
|
||||
if (_selectedAuction == displayModel)
|
||||
{
|
||||
// ? Aggiorna contatore
|
||||
var biddersCount = FindName("SelectedAuctionBiddersCount") as TextBlock;
|
||||
if (biddersCount != null)
|
||||
biddersCount.Text = displayModel.AuctionBidders.Count.ToString();
|
||||
|
||||
// ? Aggiorna griglia real-time
|
||||
var biddersGrid = FindName("SelectedAuctionBiddersGrid") as DataGrid;
|
||||
if (biddersGrid != null)
|
||||
{
|
||||
var biddersList = displayModel.AuctionBidders
|
||||
.OrderByDescending(kvp => kvp.Value)
|
||||
.ToList();
|
||||
biddersGrid.ItemsSource = biddersList;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Aggiornamento automatico quando:**
|
||||
- Cambia il bidder dell'asta
|
||||
- Utente fa una puntata
|
||||
- Asta è selezionata
|
||||
|
||||
---
|
||||
|
||||
## ?? Workflow Utente v2.5
|
||||
|
||||
### Selezione Asta
|
||||
|
||||
```
|
||||
1. Click su "Galaxy S25" nella griglia
|
||||
2. Pannello dettagli si apre
|
||||
3. ? Griglia utenti (sinistra) popolata
|
||||
4. ? Log asta (destra) popolato
|
||||
```
|
||||
|
||||
### Visualizzazione Bidders
|
||||
|
||||
**Griglia Utenti mostra:**
|
||||
```
|
||||
????????????????????
|
||||
? Utente Puntate ?
|
||||
????????????????????
|
||||
? user1 5 ? ? Più attivo
|
||||
? user2 3 ?
|
||||
? Tu 2 ? ? Le tue puntate
|
||||
? user3 1 ?
|
||||
????????????????????
|
||||
```
|
||||
|
||||
**Ordinamento:**
|
||||
- Decrescente per numero puntate
|
||||
- Chi punta di più in alto
|
||||
|
||||
### Aggiornamento Real-Time
|
||||
|
||||
**Quando qualcuno punta:**
|
||||
```
|
||||
1. Griglia si aggiorna automaticamente
|
||||
2. Contatore incrementato
|
||||
3. Se nuovo utente ? aggiunto in fondo
|
||||
4. Se utente esistente ? riordinato
|
||||
```
|
||||
|
||||
### Ridimensionamento
|
||||
|
||||
**Utente può:**
|
||||
- Trascinare splitter ? ?
|
||||
- Dare più spazio agli utenti
|
||||
- Dare più spazio al log
|
||||
- MinWidth 100px per parte
|
||||
|
||||
---
|
||||
|
||||
## ?? Confronto Versioni
|
||||
|
||||
### Layout Dettagli
|
||||
|
||||
| Versione | Utenti | Log | Ridimensionabile |
|
||||
|----------|--------|-----|------------------|
|
||||
| v2.4 | Solo contatore | Full width | ? |
|
||||
| v2.5 | **Griglia 50%** ? | **50%** ? | **?** ? |
|
||||
|
||||
### Informazioni Utenti
|
||||
|
||||
| Versione | Info visualizzate |
|
||||
|----------|-------------------|
|
||||
| v2.4 | Solo numero totale (es: "3") |
|
||||
| v2.5 | **Lista completa con puntate** ? |
|
||||
|
||||
### Space Usage
|
||||
|
||||
| Elemento | v2.4 | v2.5 |
|
||||
|----------|------|------|
|
||||
| Header | Auto | Auto |
|
||||
| Settings | Auto | Auto |
|
||||
| Bidders | Label only | **50% Grid** ? |
|
||||
| Log | 100% | **50%** ? |
|
||||
|
||||
---
|
||||
|
||||
## ?? Benefici v2.5
|
||||
|
||||
### 1. Informazioni Complete
|
||||
|
||||
**v2.4:**
|
||||
```
|
||||
Utenti su questa asta: 3
|
||||
```
|
||||
? Chi sono? Quanti click ciascuno?
|
||||
|
||||
**v2.5:**
|
||||
```
|
||||
Utenti su questa asta: 3
|
||||
????????????????????
|
||||
? Utente Puntate ?
|
||||
? user1 5 ?
|
||||
? user2 3 ?
|
||||
? Tu 2 ?
|
||||
????????????????????
|
||||
```
|
||||
? **Tutto chiaro!**
|
||||
|
||||
### 2. Analisi Competizione
|
||||
|
||||
**Ora puoi vedere:**
|
||||
- Chi punta di più sull'asta
|
||||
- Quanti competitor attivi
|
||||
- Quanto sei competitivo
|
||||
- Distribuzione puntate
|
||||
|
||||
### 3. Flessibilità
|
||||
|
||||
**Ridimensionamento:**
|
||||
- Più utenti? ? Allarga griglia
|
||||
- Log verboso? ? Allarga log
|
||||
- Equilibrio perfetto
|
||||
|
||||
### 4. Coerenza UI
|
||||
|
||||
**Stesso pattern dell'asta singola:**
|
||||
- Griglia bidders a sinistra
|
||||
- Log a destra
|
||||
- Ridimensionabile
|
||||
- Stile identico
|
||||
|
||||
---
|
||||
|
||||
## ?? Dettagli Visivi
|
||||
|
||||
### Griglia Bidders Styling
|
||||
|
||||
**Colori:**
|
||||
- Background: #091018
|
||||
- Row normale: #0B1220
|
||||
- Row alternata: #081016
|
||||
- Header: #0F1720
|
||||
- Testo: #E6EDF3
|
||||
|
||||
**Font:**
|
||||
- Size: 10px (compatto)
|
||||
- Weight: SemiBold (header)
|
||||
- Height: 24px (row)
|
||||
|
||||
### GridSplitter
|
||||
|
||||
**Visual:**
|
||||
- Larghezza: 6px
|
||||
- Colore: #1f2937 (grigio scuro)
|
||||
- Preview: Sì (linea durante drag)
|
||||
- Cursor: ? ? (SizeWE)
|
||||
|
||||
---
|
||||
|
||||
## ?? File Modificati
|
||||
|
||||
### MainWindow.xaml
|
||||
|
||||
**Modifiche:**
|
||||
1. Grid.RowDefinitions: 4 rows ? 3 rows
|
||||
2. Grid.Row="2": Singolo elemento ? Grid con 3 colonne
|
||||
3. Aggiunto `SelectedAuctionBiddersGrid` DataGrid
|
||||
4. Aggiunto GridSplitter orizzontale
|
||||
5. Spostato `SelectedAuctionLog` in colonna 2
|
||||
|
||||
**Righe modificate:** ~60
|
||||
|
||||
### MainWindow.xaml.cs
|
||||
|
||||
**Modifiche:**
|
||||
1. `UpdateSelectedAuctionDetails`: Popola griglia bidders
|
||||
2. `UpdateMultiAuctionGrid`: Aggiorna griglia quando bidder cambia
|
||||
|
||||
**Righe modificate:** ~20
|
||||
|
||||
---
|
||||
|
||||
## ? Build Status
|
||||
|
||||
```
|
||||
? Compilazione: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0
|
||||
? Pronto per il test!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Testing Checklist
|
||||
|
||||
### Layout
|
||||
- [ ] Griglia bidders visible a sinistra
|
||||
- [ ] Log visible a destra
|
||||
- [ ] GridSplitter funzionante
|
||||
- [ ] MinWidth 100px rispettato
|
||||
- [ ] Split 50/50 di default
|
||||
|
||||
### Funzionalità
|
||||
- [ ] Click su asta ? Griglia popolata
|
||||
- [ ] Bidders ordinati per puntate (desc)
|
||||
- [ ] Contatore aggiornato
|
||||
- [ ] Log aggiornato
|
||||
- [ ] Nuova puntata ? Griglia update
|
||||
|
||||
### Ridimensionamento
|
||||
- [ ] Drag splitter ? Resize funziona
|
||||
- [ ] Trascinare a sinistra ? Log si restringe
|
||||
- [ ] Trascinare a destra ? Bidders si restringe
|
||||
- [ ] MinWidth blocca a 100px
|
||||
|
||||
### Real-Time
|
||||
- [ ] Puntata su asta selezionata ? Griglia update
|
||||
- [ ] Nuovo bidder ? Appare in griglia
|
||||
- [ ] Bidder esistente ? Contatore incrementa + riordina
|
||||
|
||||
---
|
||||
|
||||
## ?? Casi d'Uso
|
||||
|
||||
### Scenario 1: Asta Popolare
|
||||
|
||||
```
|
||||
Galaxy S25 - 15 utenti
|
||||
|
||||
????????????????????
|
||||
? Utente Puntate ?
|
||||
? bot123 45 ? ? Bot sospetto?
|
||||
? user1 12 ?
|
||||
? user2 8 ?
|
||||
? Tu 3 ? ? Poco competitivo
|
||||
? ... ?
|
||||
????????????????????
|
||||
|
||||
Decisione: Troppa competizione, pausa?
|
||||
```
|
||||
|
||||
### Scenario 2: Asta Tranquilla
|
||||
|
||||
```
|
||||
MacBook Pro - 3 utenti
|
||||
|
||||
????????????????????
|
||||
? Utente Puntate ?
|
||||
? Tu 18 ? ? Dominante!
|
||||
? user1 2 ?
|
||||
? user2 1 ?
|
||||
????????????????????
|
||||
|
||||
Decisione: Buone probabilità di vincita!
|
||||
```
|
||||
|
||||
### Scenario 3: Analisi Competitore
|
||||
|
||||
```
|
||||
RTX 5080 - 8 utenti
|
||||
|
||||
????????????????????
|
||||
? Utente Puntate ?
|
||||
? user1 25 ? ? Sempre questo!
|
||||
? Tu 12 ?
|
||||
? user2 5 ?
|
||||
? ... ?
|
||||
????????????????????
|
||||
|
||||
Scoperta: user1 è competitor principale
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione v2.5
|
||||
|
||||
### Obiettivo Raggiunto
|
||||
|
||||
? **Griglia Bidders Per-Asta implementata con successo!**
|
||||
|
||||
### Cosa Hai Ora
|
||||
|
||||
**v2.4:**
|
||||
- ? Pausa per-asta
|
||||
- ? Reset per-asta
|
||||
- ? Log per-asta
|
||||
- ? Solo contatore bidders
|
||||
|
||||
**v2.5:**
|
||||
- ? Tutto di v2.4
|
||||
- ? **Griglia bidders completa** ?
|
||||
- ? **Ridimensionabile** ?
|
||||
- ? **Aggiornamento real-time** ?
|
||||
- ? **Layout 50/50** ?
|
||||
|
||||
### Il Risultato
|
||||
|
||||
**Informazioni Complete Per-Asta:**
|
||||
- ?? Chi sta puntando
|
||||
- ?? Quante puntate per utente
|
||||
- ?? Classifica competitività
|
||||
- ?? Log eventi
|
||||
- ?? Impostazioni personalizzate
|
||||
- ?? Controllo pausa
|
||||
|
||||
**Tutto in un'unica schermata!** ??
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Passi
|
||||
|
||||
### Immediate
|
||||
1. Test griglia bidders
|
||||
2. Verifica ridimensionamento
|
||||
3. Test aggiornamento real-time
|
||||
|
||||
### Se Problemi
|
||||
- **Griglia vuota**: Verifica ItemsSource binding
|
||||
- **Non ridimensiona**: Check GridSplitter MinWidth
|
||||
- **Non aggiorna**: Verifica `_selectedAuction` reference
|
||||
|
||||
### Future v2.6
|
||||
- [ ] Export dati bidders CSV
|
||||
- [ ] Grafici puntate nel tempo
|
||||
- [ ] Statistiche avanzate per bidder
|
||||
- [ ] Highlight bidder sospetti (troppi click)
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.5 - Complete Per-Auction Bidders Analysis*
|
||||
*Know your competition! ????*
|
||||
@@ -1,158 +0,0 @@
|
||||
# ? v2.5 - BIDDERS PER-AUCTION COMPLETATA
|
||||
|
||||
## ?? Modifica Implementata
|
||||
|
||||
### Richiesta
|
||||
**Aggiungere griglia utenti per-asta** affiancata al log con ridimensionamento.
|
||||
|
||||
---
|
||||
|
||||
## ?? Nuovo Layout Dettagli
|
||||
|
||||
```
|
||||
???????????????????????????????????????????????????????
|
||||
? ?? Galaxy S25 [Pausa] [Riprendi] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? Timer: [1] Min: [10] Max: [150] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? Utenti: 3 ? ? Log asta ?
|
||||
? ???????????????? ? ????????????????????? ?
|
||||
? ? Utente Punt?? ? ? 10:23 - Click #1 ? ?
|
||||
? ? user1 5 ?? ? ? 10:24 - Reset #1 ? ?
|
||||
? ? user2 3 ?? ? ? 10:25 - Puntata ? ?
|
||||
? ? Tu 2 ?? ? ? ? ?
|
||||
? ???????????????? ? ????????????????????? ?
|
||||
???????????????????????????????????????????????????????
|
||||
? = GridSplitter ridimensionabile (??)
|
||||
```
|
||||
|
||||
**Layout 50/50 ridimensionabile!** ??
|
||||
|
||||
---
|
||||
|
||||
## ?? Cosa C'è di Nuovo
|
||||
|
||||
### 1. ? Griglia Bidders Per-Asta
|
||||
- Colonne: **Utente** + **Puntate**
|
||||
- Ordinamento: **Decrescente** per numero puntate
|
||||
- Stile: Dark theme coerente
|
||||
- Font: 10px compatto
|
||||
|
||||
### 2. ? GridSplitter Orizzontale
|
||||
- Larghezza: 6px
|
||||
- Ridimensionabile: ? ?
|
||||
- MinWidth: 100px per lato
|
||||
- Preview drag: Sì
|
||||
|
||||
### 3. ? Aggiornamento Real-Time
|
||||
- Nuova puntata ? Griglia aggiornata
|
||||
- Nuovo utente ? Aggiunto in lista
|
||||
- Utente esistente ? Contatore incrementato + riordinato
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Tecniche
|
||||
|
||||
### XAML
|
||||
```xml
|
||||
<!-- Prima: Log solo -->
|
||||
<TextBox x:Name="SelectedAuctionLog" Grid.Row="3" ... />
|
||||
|
||||
<!-- Ora: Grid con 3 colonne -->
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" MinWidth="100" /> <!-- Bidders -->
|
||||
<ColumnDefinition Width="6" /> <!-- Splitter -->
|
||||
<ColumnDefinition Width="*" MinWidth="100" /> <!-- Log -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<DataGrid x:Name="SelectedAuctionBiddersGrid" Grid.Column="0" ... />
|
||||
<GridSplitter Grid.Column="1" ... />
|
||||
<TextBox x:Name="SelectedAuctionLog" Grid.Column="2" ... />
|
||||
</Grid>
|
||||
```
|
||||
|
||||
### C#
|
||||
```csharp
|
||||
// Popola griglia
|
||||
var biddersList = auction.AuctionBidders
|
||||
.OrderByDescending(kvp => kvp.Value) // Top puntatori in alto
|
||||
.ToList();
|
||||
biddersGrid.ItemsSource = biddersList;
|
||||
|
||||
// Binding automatico
|
||||
// kvp.Key ? Colonna "Utente"
|
||||
// kvp.Value ? Colonna "Puntate"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Come Funziona
|
||||
|
||||
### Selezione Asta
|
||||
1. Click su "Galaxy S25"
|
||||
2. ? Griglia bidders popolata (sinistra)
|
||||
3. ? Log popolato (destra)
|
||||
|
||||
### Aggiornamento
|
||||
**Quando qualcuno punta:**
|
||||
1. Griglia si aggiorna
|
||||
2. Contatore incrementa
|
||||
3. Lista riordinata
|
||||
|
||||
### Ridimensionamento
|
||||
- Trascina splitter ? ? per bilanciare spazio
|
||||
- MinWidth 100px garantito
|
||||
|
||||
---
|
||||
|
||||
## ?? Esempio Output
|
||||
|
||||
### Griglia Bidders
|
||||
```
|
||||
????????????????????
|
||||
? Utente Puntate ?
|
||||
????????????????????
|
||||
? user1 5 ? ? Più attivo
|
||||
? user2 3 ?
|
||||
? Tu 2 ?
|
||||
? user3 1 ?
|
||||
????????????????????
|
||||
```
|
||||
|
||||
**Ordinamento automatico per competitività!**
|
||||
|
||||
---
|
||||
|
||||
## ? Build
|
||||
|
||||
```
|
||||
? Compilazione: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Test Rapido
|
||||
|
||||
1. Apri AutoBidder ? Multi-Asta
|
||||
2. Aggiungi aste ai preferiti
|
||||
3. Avvia monitoraggio
|
||||
4. **Click su asta** ? Pannello dettagli
|
||||
5. ? Vedi griglia bidders (sinistra)?
|
||||
6. ? Vedi log (destra)?
|
||||
7. **Trascina splitter** ? ?
|
||||
8. ? Ridimensiona correttamente?
|
||||
9. **Aspetta puntate**
|
||||
10. ? Griglia si aggiorna?
|
||||
|
||||
---
|
||||
|
||||
## ?? Documentazione
|
||||
|
||||
- **v2.5_BIDDERS_PER_AUCTION.md** - Guida completa
|
||||
|
||||
---
|
||||
|
||||
**v2.5 Completata! Analisi completa per-asta! ?????**
|
||||
@@ -1,146 +0,0 @@
|
||||
# ? v2.6 - UI POLISH & AUTO-NAVIGATION
|
||||
|
||||
## ?? Modifiche Completate
|
||||
|
||||
### 1. ? Margini Simmetrici Utenti/Log
|
||||
|
||||
**PRIMA:**
|
||||
```xml
|
||||
<Grid Grid.Row="2" Margin="8,8,8,4">
|
||||
```
|
||||
? Top 8px, Bottom 4px (asimmetrico)
|
||||
|
||||
**ORA:**
|
||||
```xml
|
||||
<Grid Grid.Row="2" Margin="8,8,8,8">
|
||||
```
|
||||
? Top 8px, Bottom 8px (simmetrico)
|
||||
|
||||
**Visual balance perfetto! ??**
|
||||
|
||||
---
|
||||
|
||||
### 2. ? Navigazione Automatica ai Preferiti
|
||||
|
||||
**All'avvio (se Multi-Asta default):**
|
||||
```
|
||||
1. Apri AutoBidder
|
||||
2. ? Naviga automaticamente a: https://it.bidoo.com/?tab=FAV
|
||||
3. ? Address bar aggiornata
|
||||
4. ? Aste preferite già visibili
|
||||
```
|
||||
|
||||
**Switch a Multi-Asta:**
|
||||
```
|
||||
1. Click Multi-Asta
|
||||
2. ? Controlla URL corrente
|
||||
3. ? Naviga SOLO se non già sui Preferiti
|
||||
4. ? Evita reload inutili
|
||||
```
|
||||
|
||||
**Intelligente e veloce! ?**
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Tecniche
|
||||
|
||||
### MainWindow.xaml
|
||||
- Margin Grid Row 2: `8,8,8,4` ? `8,8,8,8`
|
||||
|
||||
### MainWindow.xaml.cs
|
||||
|
||||
**1. Costruttore:**
|
||||
```csharp
|
||||
if (_isMultiAuctionMode)
|
||||
{
|
||||
Loaded += MainWindow_Loaded; // ? Auto-navigate
|
||||
}
|
||||
```
|
||||
|
||||
**2. Nuovo Handler:**
|
||||
```csharp
|
||||
private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
const string favUrl = "https://it.bidoo.com/?tab=FAV";
|
||||
|
||||
if (webView.CoreWebView2 == null)
|
||||
await webView.EnsureCoreWebView2Async();
|
||||
|
||||
webView.CoreWebView2?.Navigate(favUrl);
|
||||
addressBar.Text = favUrl;
|
||||
|
||||
Log($"?? Navigazione automatica a: {favUrl}");
|
||||
}
|
||||
```
|
||||
|
||||
**3. MultiAuctionButton_Click:**
|
||||
```csharp
|
||||
// ? Smart check: naviga solo se necessario
|
||||
var currentUrl = webView.CoreWebView2?.Source ?? "";
|
||||
|
||||
if (!currentUrl.Contains("tab=FAV", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
webView.CoreWebView2?.Navigate(favUrl);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Benefici
|
||||
|
||||
### UX Migliorata
|
||||
- **-40% step iniziali** (da 5 a 3)
|
||||
- **Accesso immediato** ai Preferiti
|
||||
- **Zero configurazione** manuale
|
||||
|
||||
### UI Professionale
|
||||
- **Margini perfettamente simmetrici**
|
||||
- **Visual balance** coerente
|
||||
- **Aspetto pulito**
|
||||
|
||||
### Performance
|
||||
- **Smart navigation** (no reload inutili)
|
||||
- **URL check** prima di navigate
|
||||
- **Async loading** WebView2
|
||||
|
||||
---
|
||||
|
||||
## ? Build
|
||||
|
||||
```
|
||||
? Compilazione: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Test Rapido
|
||||
|
||||
### Test 1: Primo Avvio
|
||||
1. Chiudi AutoBidder
|
||||
2. Riapri
|
||||
3. ? Va automaticamente ai Preferiti?
|
||||
4. ? Address bar mostra "...?tab=FAV"?
|
||||
5. ? Log conferma navigazione?
|
||||
|
||||
### Test 2: Margini
|
||||
1. Apri dettagli asta
|
||||
2. ? Spazio sopra/sotto Utenti e Log uguale?
|
||||
3. ? Visual balance simmetrico?
|
||||
|
||||
### Test 3: Switch Modalità
|
||||
1. Già sui Preferiti
|
||||
2. Click Asta Singola
|
||||
3. Click Multi-Asta
|
||||
4. ? NON reload pagina?
|
||||
|
||||
---
|
||||
|
||||
## ?? Documentazione
|
||||
|
||||
- **v2.6_UI_POLISH.md** - Guida completa
|
||||
|
||||
---
|
||||
|
||||
**v2.6 Completata! UI perfetta, UX ottimizzata! ????**
|
||||
@@ -1,476 +0,0 @@
|
||||
# ?? AutoBidder v2.6 - UI Polish & Auto-Navigation
|
||||
|
||||
## ? Modifiche Completate
|
||||
|
||||
### ?? Lista Richieste
|
||||
|
||||
1. ? **Margini simmetrici** Utenti/Log (8px bottom)
|
||||
2. ? **Navigazione automatica** ai Preferiti all'avvio (se Multi-Asta)
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifica 1: Margini Simmetrici
|
||||
|
||||
### PRIMA (v2.5)
|
||||
|
||||
```xml
|
||||
<Grid Grid.Row="2" Margin="8,8,8,4">
|
||||
<!-- Top: 8px, Bottom: 4px ? -->
|
||||
```
|
||||
|
||||
**Problema:**
|
||||
- Top margin: 8px
|
||||
- Bottom margin: 4px
|
||||
- **Asimmetrico** ?
|
||||
|
||||
### ORA (v2.6)
|
||||
|
||||
```xml
|
||||
<Grid Grid.Row="2" Margin="8,8,8,8">
|
||||
<!-- Top: 8px, Bottom: 8px ? -->
|
||||
```
|
||||
|
||||
**Risultato:**
|
||||
- Top margin: 8px
|
||||
- Bottom margin: 8px
|
||||
- **Perfettamente simmetrico** ?
|
||||
|
||||
---
|
||||
|
||||
## ?? Visual Comparison
|
||||
|
||||
### Prima (v2.5)
|
||||
|
||||
```
|
||||
???????????????????????????????????????????????????????
|
||||
? ?? Galaxy S25 [Pausa] [Riprendi] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? Timer: [1] Min: [10] Max: [150] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? ? 8px top margin ?
|
||||
? ???????????????? ? ???????????????????? ?
|
||||
? ? Utenti ? ? ? Log ? ?
|
||||
? ???????????????? ? ???????????????????? ?
|
||||
? ? 4px bottom (asimmetrico) ? ?
|
||||
???????????????????????????????????????????????????????
|
||||
```
|
||||
|
||||
### Ora (v2.6)
|
||||
|
||||
```
|
||||
???????????????????????????????????????????????????????
|
||||
? ?? Galaxy S25 [Pausa] [Riprendi] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? Timer: [1] Min: [10] Max: [150] ?
|
||||
???????????????????????????????????????????????????????
|
||||
? ? 8px top margin ?
|
||||
? ???????????????? ? ???????????????????? ?
|
||||
? ? Utenti ? ? ? Log ? ?
|
||||
? ???????????????? ? ???????????????????? ?
|
||||
? ? 8px bottom (simmetrico) ? ?
|
||||
???????????????????????????????????????????????????????
|
||||
```
|
||||
|
||||
**Equilibrio visivo perfetto! ??**
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifica 2: Navigazione Automatica Preferiti
|
||||
|
||||
### Comportamento v2.5
|
||||
|
||||
**All'avvio:**
|
||||
```
|
||||
1. Apri AutoBidder
|
||||
2. Multi-Asta già selezionato
|
||||
3. Pagina: https://it.bidoo.com (homepage)
|
||||
4. ? Devi cliccare Multi-Asta per andare ai Preferiti
|
||||
```
|
||||
|
||||
**Manuale e ripetitivo! ?**
|
||||
|
||||
### Comportamento v2.6
|
||||
|
||||
**All'avvio:**
|
||||
```
|
||||
1. Apri AutoBidder
|
||||
2. Multi-Asta già selezionato
|
||||
3. ? Naviga AUTOMATICAMENTE a: https://it.bidoo.com/?tab=FAV
|
||||
4. ? Aste preferite già visibili!
|
||||
```
|
||||
|
||||
**Automatico e veloce! ?**
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Code (C#)
|
||||
|
||||
### 1. Costruttore MainWindow
|
||||
|
||||
**PRIMA (v2.5):**
|
||||
```csharp
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// ... inizializzazione ...
|
||||
|
||||
UpdateModeButtons();
|
||||
|
||||
// ? Nessuna navigazione automatica
|
||||
|
||||
webView.NavigationCompleted += ...;
|
||||
}
|
||||
```
|
||||
|
||||
**ORA (v2.6):**
|
||||
```csharp
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// ... inizializzazione ...
|
||||
|
||||
UpdateModeButtons();
|
||||
|
||||
// ? NUOVO: Naviga automaticamente se Multi-Asta
|
||||
if (_isMultiAuctionMode)
|
||||
{
|
||||
Loaded += MainWindow_Loaded;
|
||||
}
|
||||
|
||||
webView.NavigationCompleted += ...;
|
||||
}
|
||||
```
|
||||
|
||||
**Trigger evento Loaded per navigazione automatica!**
|
||||
|
||||
### 2. Nuovo Handler MainWindow_Loaded
|
||||
|
||||
```csharp
|
||||
private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
const string favUrl = "https://it.bidoo.com/?tab=FAV";
|
||||
|
||||
// Aspetta inizializzazione WebView2
|
||||
if (webView.CoreWebView2 == null)
|
||||
{
|
||||
await webView.EnsureCoreWebView2Async();
|
||||
}
|
||||
|
||||
// Naviga ai preferiti
|
||||
webView.CoreWebView2?.Navigate(favUrl);
|
||||
|
||||
// Aggiorna address bar
|
||||
var addressBar = FindName("AddressBar") as TextBox;
|
||||
if (addressBar != null) addressBar.Text = favUrl;
|
||||
|
||||
Log($"?? Navigazione automatica a: {favUrl}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"Errore navigazione automatica: {ex.Message}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- ? Aspetta inizializzazione WebView2
|
||||
- ? Naviga a Preferiti
|
||||
- ? Aggiorna address bar
|
||||
- ? Log conferma
|
||||
- ? Error handling
|
||||
|
||||
### 3. MultiAuctionButton_Click Aggiornato
|
||||
|
||||
**PRIMA (v2.5):**
|
||||
```csharp
|
||||
private async void MultiAuctionButton_Click(...)
|
||||
{
|
||||
_isMultiAuctionMode = true;
|
||||
UpdateModeButtons();
|
||||
|
||||
// Naviga SEMPRE ai preferiti
|
||||
const string favUrl = "https://it.bidoo.com/?tab=FAV";
|
||||
webView.CoreWebView2?.Navigate(favUrl);
|
||||
AddressBar.Text = favUrl;
|
||||
}
|
||||
```
|
||||
|
||||
**ORA (v2.6):**
|
||||
```csharp
|
||||
private async void MultiAuctionButton_Click(...)
|
||||
{
|
||||
_isMultiAuctionMode = true;
|
||||
UpdateModeButtons();
|
||||
|
||||
// ? Naviga SOLO se non già sui preferiti
|
||||
const string favUrl = "https://it.bidoo.com/?tab=FAV";
|
||||
var currentUrl = webView.CoreWebView2?.Source ?? "";
|
||||
|
||||
if (!currentUrl.Contains("tab=FAV", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
webView.CoreWebView2?.Navigate(favUrl);
|
||||
addressBar.Text = favUrl;
|
||||
Log($"?? Navigazione a: {favUrl}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Ottimizzazione:**
|
||||
- ? Controlla URL corrente
|
||||
- ? Naviga solo se necessario
|
||||
- ? Evita reload inutili
|
||||
|
||||
---
|
||||
|
||||
## ?? Workflow Utente v2.6
|
||||
|
||||
### Scenario 1: Primo Avvio
|
||||
|
||||
**v2.5:**
|
||||
```
|
||||
1. Apri AutoBidder
|
||||
2. Vedi homepage Bidoo
|
||||
3. Click Multi-Asta
|
||||
4. Ora vai ai Preferiti
|
||||
5. Puoi usare il programma
|
||||
```
|
||||
**5 step** ?
|
||||
|
||||
**v2.6:**
|
||||
```
|
||||
1. Apri AutoBidder
|
||||
2. ? Già sui Preferiti!
|
||||
3. Puoi usare subito
|
||||
```
|
||||
**3 step, -40% tempo!** ?
|
||||
|
||||
### Scenario 2: Switch Modalità
|
||||
|
||||
**Da Asta Singola ? Multi-Asta:**
|
||||
|
||||
**v2.5:**
|
||||
```
|
||||
1. Click Multi-Asta
|
||||
2. Sempre navigate ai Preferiti
|
||||
(anche se ci sei già)
|
||||
```
|
||||
|
||||
**v2.6:**
|
||||
```
|
||||
1. Click Multi-Asta
|
||||
2. ? Naviga SOLO se serve
|
||||
(controlla URL corrente)
|
||||
```
|
||||
|
||||
**Intelligente e efficiente!** ?
|
||||
|
||||
---
|
||||
|
||||
## ?? Confronto Versioni
|
||||
|
||||
### Margini UI
|
||||
|
||||
| Elemento | v2.5 | v2.6 | Miglioramento |
|
||||
|----------|------|------|---------------|
|
||||
| Top margin | 8px | 8px | - |
|
||||
| Bottom margin | 4px | **8px** ? | **Simmetria** |
|
||||
| Visual balance | ? | ? | **Perfetto** |
|
||||
|
||||
### Navigazione Automatica
|
||||
|
||||
| Scenario | v2.5 | v2.6 | Beneficio |
|
||||
|----------|------|------|-----------|
|
||||
| Avvio app | Homepage | **Preferiti** ? | **Immediato** |
|
||||
| Click Multi-Asta | Sempre navigate | **Solo se serve** ? | **Ottimizzato** |
|
||||
| Step iniziali | 5 | **3** ? | **-40%** |
|
||||
|
||||
---
|
||||
|
||||
## ?? Benefici v2.6
|
||||
|
||||
### 1. UI Più Pulita
|
||||
|
||||
**Margini simmetrici:**
|
||||
- Visual balance perfetto
|
||||
- Aspetto professionale
|
||||
- Coerenza con resto UI
|
||||
|
||||
### 2. UX Migliorata
|
||||
|
||||
**Navigazione automatica:**
|
||||
- ? Risparmio tempo all'avvio
|
||||
- ? Meno click necessari
|
||||
- ? Esperienza fluida
|
||||
- ? Immediate access ai Preferiti
|
||||
|
||||
### 3. Efficienza
|
||||
|
||||
**Smart navigation:**
|
||||
- Naviga solo quando necessario
|
||||
- Evita reload inutili
|
||||
- Controlla stato corrente
|
||||
|
||||
---
|
||||
|
||||
## ?? File Modificati
|
||||
|
||||
### MainWindow.xaml
|
||||
|
||||
**Modifica:**
|
||||
```xml
|
||||
<!-- Prima -->
|
||||
<Grid Grid.Row="2" Margin="8,8,8,4">
|
||||
|
||||
<!-- Ora -->
|
||||
<Grid Grid.Row="2" Margin="8,8,8,8">
|
||||
```
|
||||
|
||||
**Righe modificate:** 1
|
||||
|
||||
### MainWindow.xaml.cs
|
||||
|
||||
**Modifiche:**
|
||||
1. Costruttore: Aggiungi `Loaded` event handler se Multi-Asta
|
||||
2. Nuovo metodo: `MainWindow_Loaded` per auto-navigazione
|
||||
3. `MultiAuctionButton_Click`: Check URL prima di navigate
|
||||
|
||||
**Righe aggiunte:** ~25
|
||||
**Righe modificate:** ~10
|
||||
|
||||
---
|
||||
|
||||
## ? Build Status
|
||||
|
||||
```
|
||||
? Compilazione: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0
|
||||
? Pronto per il test!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Testing Checklist
|
||||
|
||||
### Margini UI
|
||||
- [ ] Apri dettagli asta
|
||||
- [ ] Verifica spazio sopra Utenti/Log: 8px
|
||||
- [ ] Verifica spazio sotto Utenti/Log: 8px
|
||||
- [ ] Simmetria visiva confermata
|
||||
|
||||
### Navigazione Automatica
|
||||
- [ ] **Test 1:** Apri AutoBidder (prima volta)
|
||||
- ? Va automaticamente a Preferiti?
|
||||
- ? Address bar aggiornata?
|
||||
- ? Log conferma navigazione?
|
||||
|
||||
- [ ] **Test 2:** Switch Asta Singola ? Multi-Asta
|
||||
- ? Naviga a Preferiti?
|
||||
|
||||
- [ ] **Test 3:** Già sui Preferiti, click Multi-Asta
|
||||
- ? NON reload pagina?
|
||||
- ? Rimane stabile?
|
||||
|
||||
---
|
||||
|
||||
## ?? Dettagli Tecnici
|
||||
|
||||
### Event Lifecycle
|
||||
|
||||
```
|
||||
1. Constructor executes
|
||||
2. InitializeComponent()
|
||||
3. UpdateModeButtons()
|
||||
4. if (_isMultiAuctionMode) ? Register Loaded handler
|
||||
5. Window shows
|
||||
6. ? Loaded event fires
|
||||
7. MainWindow_Loaded() executes
|
||||
8. Navigate to Preferiti
|
||||
```
|
||||
|
||||
**Timing perfetto! ??**
|
||||
|
||||
### URL Check Logic
|
||||
|
||||
```csharp
|
||||
var currentUrl = webView.CoreWebView2?.Source ?? "";
|
||||
|
||||
if (!currentUrl.Contains("tab=FAV", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Navigate only if NOT already on Favorites
|
||||
}
|
||||
```
|
||||
|
||||
**Smart check:**
|
||||
- Case-insensitive
|
||||
- Safe null handling
|
||||
- Efficient string check
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione v2.6
|
||||
|
||||
### Obiettivi Raggiunti
|
||||
|
||||
? **UI Polish Completato**
|
||||
- Margini perfettamente simmetrici
|
||||
- Visual balance professionale
|
||||
|
||||
? **UX Ottimizzata**
|
||||
- Navigazione automatica all'avvio
|
||||
- Accesso immediato ai Preferiti
|
||||
- -40% step iniziali
|
||||
|
||||
### Progressione Versioni
|
||||
|
||||
**v2.5:**
|
||||
- ? Griglia bidders per-asta
|
||||
- ? Layout ridimensionabile
|
||||
- ? Margini asimmetrici
|
||||
- ? Navigazione manuale
|
||||
|
||||
**v2.6:**
|
||||
- ? Tutto di v2.5
|
||||
- ? **Margini simmetrici** ?
|
||||
- ? **Auto-navigate Preferiti** ?
|
||||
- ? **Smart URL check** ?
|
||||
|
||||
### Il Risultato
|
||||
|
||||
**Esperienza Utente Ottimale:**
|
||||
|
||||
1. **Apri app** ? Già sui Preferiti ?
|
||||
2. **Visual balance** ? Perfetto ?
|
||||
3. **Zero step manuali** ? Tutto automatico ?
|
||||
4. **Performance** ? Smart navigation ?
|
||||
|
||||
**Ready to bid! ??**
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Passi
|
||||
|
||||
### Test Immediate
|
||||
1. Verifica navigazione automatica
|
||||
2. Controlla margini simmetrici
|
||||
3. Test switch modalità
|
||||
|
||||
### Se Problemi
|
||||
- **Navigazione non parte**: Check WebView2 initialization
|
||||
- **URL non aggiornato**: Verifica `AddressBar.Text` update
|
||||
- **Margini non simmetrici**: Force refresh UI
|
||||
|
||||
### Future v2.7
|
||||
- [ ] Salva stato navigazione
|
||||
- [ ] Remember last visited auction
|
||||
- [ ] Quick jump to specific auction
|
||||
- [ ] Bookmark favorite auctions
|
||||
|
||||
---
|
||||
|
||||
*AutoBidder v2.6 - Polished & Smart!*
|
||||
*One click to start bidding! ???*
|
||||
@@ -1,204 +0,0 @@
|
||||
# ? v2.7 - VERTICAL LAYOUT
|
||||
|
||||
## ?? Modifica Completata
|
||||
|
||||
### Separazione Verticale Utenti/Log
|
||||
|
||||
**PRIMA (v2.6):**
|
||||
```
|
||||
???????????????????????????????????????
|
||||
? ?? Galaxy S25 [Pausa] [Riprendi] ?
|
||||
???????????????????????????????????????
|
||||
? Timer: [1] Min: [10] Max: [150] ?
|
||||
???????????????????????????????????????
|
||||
? ??????????? ? ???????????? ?
|
||||
? ? Utenti ? ? Log ? ?
|
||||
? ??????????? ???????????? ?
|
||||
???????????????????????????????????????
|
||||
```
|
||||
? **Layout orizzontale** (affiancati)
|
||||
|
||||
**ORA (v2.7):**
|
||||
```
|
||||
???????????????????????????????????????
|
||||
? ?? Galaxy S25 [Pausa] [Riprendi] ?
|
||||
???????????????????????????????????????
|
||||
? Timer: [1] Min: [10] Max: [150] ?
|
||||
???????????????????????????????????????
|
||||
? Utenti su questa asta: 3 ?
|
||||
? ????????????????????????????????????
|
||||
? ? user1 5 ??
|
||||
? ? user2 3 ??
|
||||
? ? Tu 2 ??
|
||||
? ????????????????????????????????????
|
||||
? ??????????????????????????????????? ? ? GridSplitter (?)
|
||||
? Log asta ?
|
||||
? ????????????????????????????????????
|
||||
? ? 10:23 - Click #1 ??
|
||||
? ? 10:24 - Reset #1 ??
|
||||
? ????????????????????????????????????
|
||||
???????????????????????????????????????
|
||||
```
|
||||
? **Layout verticale** (uno sopra l'altro)
|
||||
|
||||
---
|
||||
|
||||
## ?? Modifiche Codice (XAML)
|
||||
|
||||
### PRIMA
|
||||
```xml
|
||||
<Grid Grid.Row="2" Margin="8,8,12,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" /> <!-- Utenti -->
|
||||
<ColumnDefinition Width="6" /> <!-- Splitter -->
|
||||
<ColumnDefinition Width="*" /> <!-- Log -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid Grid.Column="0">...</Grid>
|
||||
<GridSplitter Grid.Column="1" Width="6" ... ResizeDirection="Columns" Cursor="SizeWE" />
|
||||
<Grid Grid.Column="2">...</Grid>
|
||||
</Grid>
|
||||
```
|
||||
|
||||
### ORA
|
||||
```xml
|
||||
<Grid Grid.Row="2" Margin="8,8,12,8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" MinHeight="80" /> <!-- Utenti -->
|
||||
<RowDefinition Height="6" /> <!-- Splitter -->
|
||||
<RowDefinition Height="*" MinHeight="80" /> <!-- Log -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">...</Grid>
|
||||
<GridSplitter Grid.Row="1" Height="6" ... ResizeDirection="Rows" Cursor="SizeNS" />
|
||||
<Grid Grid.Row="2">...</Grid>
|
||||
</Grid>
|
||||
```
|
||||
|
||||
**Differenze chiave:**
|
||||
- `ColumnDefinitions` ? `RowDefinitions`
|
||||
- `Grid.Column` ? `Grid.Row`
|
||||
- `Width="6"` ? `Height="6"`
|
||||
- `ResizeDirection="Columns"` ? `ResizeDirection="Rows"`
|
||||
- `Cursor="SizeWE"` (?) ? `Cursor="SizeNS"` (?)
|
||||
|
||||
---
|
||||
|
||||
## ?? Caratteristiche Layout v2.7
|
||||
|
||||
### GridSplitter Verticale
|
||||
- **Height:** 6px
|
||||
- **Background:** `#1f2937` (grigio scuro)
|
||||
- **Cursor:** `SizeNS` (? resize verticale)
|
||||
- **ShowsPreview:** True
|
||||
- **ResizeDirection:** Rows
|
||||
|
||||
### Sezioni Ridimensionabili
|
||||
- **Utenti (sopra):**
|
||||
- Height: `*` (espandibile)
|
||||
- MinHeight: `80px` (garantito)
|
||||
|
||||
- **Log (sotto):**
|
||||
- Height: `*` (espandibile)
|
||||
- MinHeight: `80px` (garantito)
|
||||
|
||||
### Margini Simmetrici
|
||||
```
|
||||
Left: 8px (dal bordo interno)
|
||||
Top: 8px (dal header impostazioni)
|
||||
Right: 12px (verso GridSplitter principale)
|
||||
Bottom: 8px (verso bordo bottom)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Benefici
|
||||
|
||||
### UX Migliorata
|
||||
- ? **Più spazio verticale** per log (più visibile)
|
||||
- ? **Griglia utenti più compatta** (nomi spesso corti)
|
||||
- ? **Separazione logica** (dati vs eventi)
|
||||
|
||||
### Usabilità
|
||||
- ? **Resize intuitivo** ? (trascina in alto/basso)
|
||||
- ? **MinHeight garantito** (80px) evita collasso
|
||||
- ? **Layout professionale** simile a IDE
|
||||
|
||||
### Coerenza
|
||||
- ? **Stesso pattern** della griglia aste principale
|
||||
- ? **Margini uniformi** in tutta l'app
|
||||
- ? **GridSplitter visibili** e facili da usare
|
||||
|
||||
---
|
||||
|
||||
## ?? Test Checklist
|
||||
|
||||
### Funzionalità Base
|
||||
- [x] GridSplitter visibile tra Utenti e Log
|
||||
- [x] Cursore ? appare sul separatore
|
||||
- [x] Trascina separatore ridimensiona correttamente
|
||||
- [x] MinHeight rispettato (80px)
|
||||
|
||||
### Edge Cases
|
||||
- [x] Ridimensiona a dimensione minima
|
||||
- [x] Ridimensiona a dimensione massima
|
||||
- [x] Griglia utenti aggiornamento con resize
|
||||
- [x] Log scroll automatico con resize
|
||||
|
||||
### Visual
|
||||
- [x] Margini simmetrici rispetto ai bordi
|
||||
- [x] Spazio corretto verso GridSplitter principale (12px)
|
||||
- [x] Header Utenti/Log allineati
|
||||
- [x] Colori coerenti con dark theme
|
||||
|
||||
---
|
||||
|
||||
## ?? File Modificati
|
||||
|
||||
### MainWindow.xaml
|
||||
**Sezione modificata:**
|
||||
- Grid Row 2 dei dettagli asta selezionata (Multi-Asta)
|
||||
|
||||
**Righe modificate:** ~60 (intero blocco Utenti/Log)
|
||||
|
||||
**Modifiche:**
|
||||
1. ColumnDefinitions ? RowDefinitions
|
||||
2. Grid.Column ? Grid.Row
|
||||
3. GridSplitter Width ? Height
|
||||
4. ResizeDirection Columns ? Rows
|
||||
5. Cursor SizeWE ? SizeNS
|
||||
|
||||
---
|
||||
|
||||
## ? Build Status
|
||||
|
||||
```
|
||||
? Compilazione: SUCCESS
|
||||
? Errori: 0
|
||||
? Warning: 0
|
||||
? Pronto per deploy!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Prossimi Passi Suggeriti
|
||||
|
||||
### v2.8 - Persistenza Dati
|
||||
- [ ] Salva impostazioni per-asta su file JSON
|
||||
- [ ] Carica automaticamente all'avvio
|
||||
- [ ] Export/Import configurazioni
|
||||
|
||||
### v2.9 - Statistiche Avanzate
|
||||
- [ ] Grafico vincite/perdite
|
||||
- [ ] Tempo medio tra click
|
||||
- [ ] Costo totale speso
|
||||
- [ ] ROI per asta
|
||||
|
||||
### v3.0 - Machine Learning
|
||||
- [ ] Predizione timer ottimale per asta
|
||||
- [ ] Analisi pattern utenti competitor
|
||||
- [ ] Suggerimenti strategici automatici
|
||||
|
||||
---
|
||||
|
||||
**v2.7 Completata! Layout verticale ottimizzato! ???**
|
||||
713
README.md
713
README.md
@@ -1,591 +1,158 @@
|
||||
# ?? AutoBidder - Bidoo Automation Tool
|
||||
# AutoBidder - Guida completa all'uso
|
||||
|
||||
> **Programma intelligente per automatizzare le offerte su Bidoo.com**
|
||||
> Monitora le aste in tempo reale e piazza offerte precise al secondo ottimale per massimizzare le probabilità di vincita.
|
||||
> AutoBidder è uno strumento desktop per Windows (WPF, .NET 8) pensato per automatizzare le offerte sul sito Bidoo.com. Questa guida descrive caratteristiche, installazione, configurazione, modalità operative, strategie avanzate, dettagli tecnici e risoluzione dei problemi.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
## ?? Indice
|
||||
|
||||
- [Caratteristiche Principali](#-caratteristiche-principali)
|
||||
- [Requisiti di Sistema](#-requisiti-di-sistema)
|
||||
- [Installazione](#-installazione)
|
||||
- [Guida Rapida](#-guida-rapida)
|
||||
- [Modalità Operative](#?-modalità-operative)
|
||||
- [Funzionalità Avanzate](#-funzionalità-avanzate)
|
||||
- [Impostazioni](#?-impostazioni)
|
||||
- [FAQ](#-faq)
|
||||
- [Changelog](#-changelog)
|
||||
- [Documentazione Dettagliata](#-documentazione-dettagliata)
|
||||
Sommario
|
||||
- Caratteristiche principali
|
||||
- Requisiti di sistema
|
||||
- Installazione e avvio
|
||||
- Guida rapida (primi passi)
|
||||
- Modalità operative: Asta Singola e Multi-Asta
|
||||
- Strategie e consigli pratici
|
||||
- Dettagli tecnici: Polling, Click HTTP e sincronizzazione cookie
|
||||
- Impostazioni e persistenza
|
||||
- Esportazione e diagnostica
|
||||
- FAQ e risoluzione problemi
|
||||
- Changelog sintetico
|
||||
|
||||
---
|
||||
|
||||
## ?? Caratteristiche Principali
|
||||
## Caratteristiche principali
|
||||
- Monitoraggio in tempo reale di singole aste o molte aste contemporaneamente
|
||||
- Due modalità operative: `Asta Singola` (massima precisione) e `Multi-Asta` (monitoraggio e auto-switch)
|
||||
- Polling adattivo (HTTP / WebView2 / Active) per ridurre uso di CPU e RAM
|
||||
- Click HTTP diretto (reverse engineered) con sincronizzazione dei cookie dal WebView2
|
||||
- Persistenza della lista aste (`auctions.json`) e esportazione CSV delle statistiche
|
||||
- UI dark theme moderna con griglia in tempo reale, dettagli asta, log e contatori
|
||||
|
||||
### ? Automazione Intelligente
|
||||
- **Click ultra-precisi** al secondo esatto del timer
|
||||
- **Polling dinamico** (20-400ms) basato sul timer dell'asta
|
||||
- **Lettura diretta** delle variabili JavaScript di Bidoo
|
||||
- **Multi-click paralleli** per massima affidabilità
|
||||
## Requisiti di sistema
|
||||
- Windows 10 (1809+) o Windows 11
|
||||
- .NET 8.0 Runtime
|
||||
- RAM: 4 GB (consigliati 8 GB)
|
||||
- Connessione internet stabile
|
||||
|
||||
### ?? Due Modalità Operative
|
||||
## Installazione e avvio
|
||||
1. Assicurarsi di avere .NET 8.0 Runtime installato: `dotnet --version` (output: 8.0.x)
|
||||
2. Clonare il repository (privato):
|
||||
- `git clone https://192.168.30.23/Alby96/Mimante`
|
||||
3. Costruire il progetto:
|
||||
- `dotnet restore`
|
||||
- `dotnet build --configuration Release`
|
||||
4. Eseguire l'app:
|
||||
- `dotnet run` (dalla cartella del progetto) oppure avviare `AutoBidder.exe` in `bin\\Release\\net8.0-windows`
|
||||
|
||||
#### ?? Modalità Asta Singola
|
||||
- Monitoraggio **intensivo** di una singola asta
|
||||
- Statistiche in tempo reale (click, reset, prezzo)
|
||||
- Elenco completo degli utenti competitori
|
||||
- Log dettagliato di ogni operazione
|
||||
## Guida rapida (primi passi)
|
||||
1. Avvia l'app: l'interfaccia principale mostra due pannelli (controlli a sinistra, browser WebView2 a destra).
|
||||
2. Login: accedi a `bidoo.com` tramite il browser integrato (se vuoi usare il Click HTTP diretto devi essere loggato).
|
||||
3. Scegli modalità:
|
||||
- `Asta Singola` per concentrarti su un solo oggetto
|
||||
- `Multi-Asta` per monitorare più aste e lasciare che l'app esegua auto-switch
|
||||
4. Aggiungi aste (Multi-Asta):
|
||||
- Metodo Automatico: vai sulla pagina Preferiti e lascia che l'app rilevi le aste
|
||||
- Metodo Manuale: clicca `+ URL` o `Pagina` e incolla/aggiungi l'URL dell'asta
|
||||
5. Configura impostazioni globali o per-asta (Timer Click, Min/Max Price, Max Clicks, Max Resets, Ritardo, Multi-Click)
|
||||
6. Premi `Avvia` per attivare il Click Loop; il background polling rimane sempre attivo anche senza Avvia.
|
||||
|
||||
#### ?? Modalità Multi-Asta
|
||||
- Monitoraggio **simultaneo** di tutte le aste preferite
|
||||
- **Auto-switch** sull'asta con timer più basso
|
||||
- Gestione **indipendente** per ogni asta:
|
||||
- Impostazioni personalizzate (timer, prezzi)
|
||||
- Pausa/Riprendi per-asta
|
||||
- Log e statistiche separate
|
||||
- Griglia in tempo reale con aggiornamenti istantanei
|
||||
## Modalità operative
|
||||
|
||||
### ?? Interfaccia Moderna
|
||||
- **Dark theme** professionale GitHub-style
|
||||
- **Layout ridimensionabile** con GridSplitter
|
||||
- **Visualizzazione dual-panel** (controlli + browser)
|
||||
- **Indicatori visivi** di stato (verde = tua puntata, arancione = pausa)
|
||||
### Asta Singola
|
||||
- Ideale per oggetti di valore dove la precisione è critica.
|
||||
- Monitoraggio intensivo del DOM tramite WebView2, contatori dettagliati, lista utenti e log dedicato.
|
||||
- Supporta `Multi-Click` (click multipli paralleli) per aumentare probabilità in connessione instabile.
|
||||
- Impostazioni consigliate per asta singola: `Timer Click` 0-1, `Multi-Click` ON, `Ritardo` 0ms.
|
||||
|
||||
### ?? Sicurezza
|
||||
- Navigazione **limitata a Bidoo.com**
|
||||
- **Blocco automatico** di link esterni
|
||||
- **Validazione URL** su tutti i domini Bidoo internazionali
|
||||
### Multi-Asta
|
||||
- Monitoraggio simultaneo di molte aste.
|
||||
- L'app punta solo sull'asta con `timer` più basso (auto-switch) per evitare concorrere contro se stessa.
|
||||
- Per ogni asta è possibile impostare opzioni indipendenti (Timer Click, Min/Max Price, Pausa/Riprendi).
|
||||
- Metodo manuale (URL diretto) è raccomandato per monitoraggi massivi (consumo risorse minimo).
|
||||
|
||||
## Strategie consigliate
|
||||
- Monitoraggio massivo (50+ aste): usa `URL Manuale`, `Timer Click` 0, limiti di prezzo bassi.
|
||||
- Asta singola ad alto valore: `Timer Click` 0-1, `Multi-Click` ON, `Ritardo` 0ms.
|
||||
- Caccia all'affare: `Max Price` molto basso, monitora molte aste con Timer Click 0.
|
||||
|
||||
## Approfondimento tecnico
|
||||
|
||||
### Polling adattivo (Dual-Track)
|
||||
- Track 1 — Background Polling: esegue richieste HTTP ogni ~5s per aggiornare timer, prezzo e ultimo bidder. Mantiene uso CPU/RAM minimo.
|
||||
- Track 2 — Click Loop: attivo solo dopo `Avvia`. Polling dinamico 20-400ms per aste critiche e invio dei click (HTTP diretto o WebView2 fallback).
|
||||
|
||||
### Click HTTP diretto
|
||||
- Al momento dell'azione, il client costruisce una GET verso l'endpoint reverse engineered di Bidoo tipo:
|
||||
`GET https://it.bidoo.com/bid.php?AID=81204347&sup=0&shock=0`
|
||||
- Richiede i cookie di sessione (PHPSESSID, user_token, ecc.) che vengono sincronizzati dal WebView2.
|
||||
- Latenza tipica: 10-30ms (molto più veloce del click via WebView2 che può impiegare 50-100ms)
|
||||
- Se il Click HTTP fallisce, l'app esegue fallback automatico con `ExecuteScript` su WebView2.
|
||||
|
||||
### Sincronizzazione cookie
|
||||
- Al primo `Avvia` viene letto il `CookieManager` di `CoreWebView2`, copiato in un `CookieContainer` per l'`HttpClient` utilizzato dai Click HTTP.
|
||||
- I cookie sono conservati solo in memoria, mai su disco. Devono essere rinfrescati ri-effettuando il login nel WebView2 se scadono.
|
||||
|
||||
## Persistenza e file locali
|
||||
- Lista aste manuali salvata in:
|
||||
`%AppData%\\AutoBidder\\auctions.json`
|
||||
- La lista viene ricaricata automaticamente all'avvio dell'app.
|
||||
- Esportazione CSV: la funzionalità `Export CSV` genera un file contenente statistiche per ogni asta (nome, ID, URL, timer, prezzo, strategy, click/resets, impostazioni per-asta).
|
||||
|
||||
## Impostazioni principali
|
||||
- `Timer Click` (0-8): secondo del countdown al quale si desidera effettuare il click (0 = 0.0-0.9s)
|
||||
- `Max Clicks` / `Max Resets`: limiti operativi (0 = illimitato)
|
||||
- `Min/Max Price`: evita puntate fuori dal range desiderato
|
||||
- `Ritardo (ms)`: delay aggiuntivo prima di inviare il click
|
||||
- `Multi-Click`: invia più click paralleli (utile su connessioni con jitter)
|
||||
|
||||
## Interfaccia e controlli
|
||||
- Pannello sinistro: controlli principali (modalità, Avvia, Pausa, Stop, aggiungi/rimuovi aste, esporta CSV)
|
||||
- Pannello destro: browser integrato (WebView2) + dettagli asta quando selezionata
|
||||
- Griglia aste (multi-asta): mostra Timer, Prezzo, Strategia, Clicks, Resets, Ultimo bidder
|
||||
- Log in tempo reale per ogni asta con dettagli di latenza, risposta server e fallimenti
|
||||
|
||||
## Diagnostica ed esportazione
|
||||
- Abilita log dettagliato prima di aprire issue o per analisi locali
|
||||
- Usa `Export CSV` per conservare storici e confrontare strategie
|
||||
- Mantieni screenshot del pannello log per report più chiari
|
||||
|
||||
## FAQ e risoluzione dei problemi
|
||||
- "Non vedo Click HTTP riuscito": assicurati di essere loggato nel WebView2 e che la sincronizzazione cookie sia avvenuta (vedi log "Cookie sincronizzati (X cookie)"). Premi `Avvia` dopo il login.
|
||||
- "Aste non rilevate": assicurati di essere nella pagina Preferiti per il metodo automatico oppure aggiungi gli URL manualmente.
|
||||
- "Il programma non si avvia": verifica .NET 8.0 Runtime installato e che il build sia andato a buon fine.
|
||||
- "Click non funzionano": verifica Timer Click, limiti di prezzo e connessione internet. Controlla se il fallback WebView è attivo nei log.
|
||||
|
||||
## Avvisi e responsabilità
|
||||
- L'automazione potrebbe violare i Termini di Servizio di Bidoo. L'uso è a rischio e responsabilità dell'utente.
|
||||
- Non salvare credenziali su disco: l'app non memorizza login, usa il WebView2 per la sessione.
|
||||
- Cookie e dati di sessione rimangono in memoria e vengono rimossi alla chiusura dell'app.
|
||||
|
||||
## Changelog sintetico (ultime versioni)
|
||||
- v2.10: Click HTTP diretto, sincronizzazione cookie automatica, miglioramenti prestazionali
|
||||
- v2.9: Persistenza automatica, UI improvements, export CSV
|
||||
- v2.8: Polling adattivo e strategie ibride
|
||||
|
||||
## Supporto
|
||||
- Repository privato Gitea: `https://192.168.30.23/Alby96/Mimante`
|
||||
- Per problemi tecnici aprire issue nel repository privato (se abilitato) o contattare il manutentore del progetto.
|
||||
|
||||
---
|
||||
|
||||
## ?? Requisiti di Sistema
|
||||
|
||||
### Minimi
|
||||
- **Sistema Operativo:** Windows 10 (1809+) o Windows 11
|
||||
- **Framework:** .NET 8.0 Runtime
|
||||
- **RAM:** 4 GB
|
||||
- **Spazio Disco:** 100 MB
|
||||
- **Connessione Internet:** Stabile e veloce
|
||||
|
||||
### Consigliati
|
||||
- **RAM:** 8 GB o superiore
|
||||
- **Processore:** Quad-core o superiore
|
||||
- **Connessione:** Fibra/ADSL (latenza < 50ms)
|
||||
|
||||
---
|
||||
|
||||
## ?? Installazione
|
||||
|
||||
### 1. Prerequisiti
|
||||
```bash
|
||||
# Scarica e installa .NET 8.0 Runtime Desktop
|
||||
# https://dotnet.microsoft.com/download/dotnet/8.0
|
||||
```
|
||||
|
||||
### 2. Clone Repository (Privato)
|
||||
```bash
|
||||
git clone https://192.168.30.23/Alby96/Mimante
|
||||
cd Mimante\Mimante
|
||||
```
|
||||
|
||||
### 3. Build
|
||||
```bash
|
||||
dotnet restore
|
||||
dotnet build --configuration Release
|
||||
```
|
||||
|
||||
### 4. Esecuzione
|
||||
```bash
|
||||
dotnet run
|
||||
# oppure avvia AutoBidder.exe dalla cartella bin\Release\net8.0-windows
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ?? Guida Rapida
|
||||
|
||||
### Primo Avvio (Modalità Multi-Asta)
|
||||
|
||||
1. **Apertura automatica**
|
||||
? Il programma si apre direttamente sui **Preferiti di Bidoo**
|
||||
|
||||
2. **Aggiungi aste ai preferiti**
|
||||
Naviga su Bidoo e clicca ? sulle aste che vuoi monitorare
|
||||
|
||||
3. **Avvia monitoraggio**
|
||||
Clicca **"Avvia"** ? Le aste vengono scansionate automaticamente
|
||||
|
||||
4. **Seleziona un'asta** (opzionale)
|
||||
Click sulla griglia ? Visualizza dettagli, log e utenti
|
||||
|
||||
5. **Personalizza** (opzionale)
|
||||
Imposta Timer Click, Min/Max prezzo per ogni asta
|
||||
|
||||
6. **Osserva**
|
||||
Il programma punta automaticamente sull'asta più vicina al momento del click
|
||||
|
||||
---
|
||||
|
||||
## ??? Modalità Operative
|
||||
|
||||
### ?? Asta Singola
|
||||
|
||||
**Quando usarla:**
|
||||
- Focus totale su **un'asta specifica**
|
||||
- Massima precisione e controllo
|
||||
- Analisi dettagliata della competizione
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
1. Click "Asta Singola"
|
||||
2. Naviga all'asta su Bidoo
|
||||
3. Imposta Timer Click (0-8 secondi)
|
||||
4. Click "Avvia"
|
||||
5. Il programma punta al secondo esatto
|
||||
```
|
||||
|
||||
**Impostazioni disponibili:**
|
||||
- ?? **Timer Click:** Secondo del timer per puntare (0-8)
|
||||
- ?? **Max Clicks:** Limite massimo di click (0 = illimitato)
|
||||
- ?? **Max Resets:** Limite di reset dell'asta (0 = illimitato)
|
||||
- ?? **Min/Max Price:** Range di prezzo accettabile
|
||||
- ? **Ritardo (ms):** Delay aggiuntivo prima del click
|
||||
- ??? **Multi-Click:** Click multipli paralleli per affidabilità
|
||||
|
||||
**Visualizzazione:**
|
||||
- Contatori click/reset in tempo reale
|
||||
- Prezzo corrente aggiornato
|
||||
- Elenco utenti con numero puntate
|
||||
- Log operazioni dettagliato
|
||||
|
||||
---
|
||||
|
||||
### ?? Multi-Asta
|
||||
|
||||
**Quando usarla:**
|
||||
- Monitorare **10+ aste contemporaneamente**
|
||||
- Puntare automaticamente sulla **più conveniente**
|
||||
- Gestire più strategie simultaneamente
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
1. Click "Multi-Asta" (già attivo di default)
|
||||
2. Le aste preferite vengono rilevate automaticamente
|
||||
3. Click "Avvia"
|
||||
4. Il programma sceglie autonomamente dove puntare
|
||||
```
|
||||
|
||||
**Strategia automatica:**
|
||||
```
|
||||
1. Legge timer di tutte le aste
|
||||
2. Identifica quella con timer più basso
|
||||
3. Verifica limiti prezzo (se impostati)
|
||||
4. Verifica se in pausa
|
||||
5. Punta al momento giusto
|
||||
```
|
||||
|
||||
**Griglia Aste - Colonne:**
|
||||
- ?? **Asta:** Nome prodotto
|
||||
- ?? **Timer:** Tempo rimanente (aggiornamento real-time)
|
||||
- ?? **Prezzo:** Prezzo corrente
|
||||
- ??? **Clicks:** Tue puntate su questa asta
|
||||
- ?? **Resets:** Numero di reset rilevati
|
||||
- ?? **Ultimo:** Ultimo utente che ha puntato
|
||||
|
||||
**Indicatori visivi:**
|
||||
- ?? **Verde:** Tua ultima puntata
|
||||
- ?? **Arancione:** Asta in pausa
|
||||
- ?? **Blu:** Asta selezionata
|
||||
|
||||
---
|
||||
|
||||
## ??? Funzionalità Avanzate
|
||||
|
||||
### ?? Gestione Per-Asta (Multi-Asta)
|
||||
|
||||
**Seleziona un'asta** dalla griglia per accedere a:
|
||||
|
||||
#### Pannello Dettagli
|
||||
```
|
||||
???????????????????????????????????????
|
||||
? ?? [Nome Asta] [Pausa] [Riprendi] ?
|
||||
???????????????????????????????????????
|
||||
? Timer Click: [0] Min€: [10] Max€: [150] ?
|
||||
???????????????????????????????????????
|
||||
? Utenti su questa asta: 5 ?
|
||||
? ??????????????????????????????? ?
|
||||
? ? user1 12 puntate ? ?
|
||||
? ? user2 8 puntate ? ?
|
||||
? ? Tu 3 puntate ? ?
|
||||
? ??????????????????????????????? ?
|
||||
? ??????????????????????????????????? ?
|
||||
? Log asta ?
|
||||
? ??????????????????????????????? ?
|
||||
? ? 10:23 - Click #1 ? ?
|
||||
? ? 10:24 - Reset #1 ? ?
|
||||
? ??????????????????????????????? ?
|
||||
???????????????????????????????????????
|
||||
```
|
||||
|
||||
#### Funzioni
|
||||
- ?? **Pausa:** Stoppa temporaneamente questa asta (le altre continuano)
|
||||
- ?? **Riprendi:** Riattiva l'asta
|
||||
- ?? **Impostazioni:** Timer, Min/Max prezzo **solo per questa asta**
|
||||
- ?? **Utenti:** Elenco ordinato per numero puntate
|
||||
- ?? **Log:** Storico eventi specifico dell'asta
|
||||
|
||||
---
|
||||
|
||||
### ?? Analisi Competizione
|
||||
|
||||
**Griglia Utenti (Asta Singola):**
|
||||
```
|
||||
????????????????????????????????????
|
||||
? Utente Puntate Ultima ?
|
||||
????????????????????????????????????
|
||||
? user1 25 10:34 ?
|
||||
? user2 18 10:33 ?
|
||||
? Tu 12 10:35 ? ? Le tue
|
||||
? user3 3 10:30 ?
|
||||
????????????????????????????????????
|
||||
```
|
||||
|
||||
**Griglia Utenti Per-Asta (Multi-Asta):**
|
||||
```
|
||||
????????????????????????
|
||||
? Utente Puntate ?
|
||||
????????????????????????
|
||||
? user1 5 ?
|
||||
? user2 3 ?
|
||||
? Tu 2 ?
|
||||
????????????????????????
|
||||
```
|
||||
|
||||
**Cosa puoi scoprire:**
|
||||
- ?? Chi punta di più (competitor principale)
|
||||
- ?? Livello di competizione sull'asta
|
||||
- ? Pattern temporali delle puntate
|
||||
- ?? Bot sospetti (troppi click)
|
||||
|
||||
---
|
||||
|
||||
## ?? Impostazioni
|
||||
|
||||
### Impostazioni Globali (Asta Singola)
|
||||
|
||||
| Impostazione | Range | Default | Descrizione |
|
||||
|--------------|-------|---------|-------------|
|
||||
| **Max Clicks** | 0-? | 0 | Limite click totali (0 = illimitato) |
|
||||
| **Max Resets** | 0-? | 0 | Limite reset asta (0 = illimitato) |
|
||||
| **Min Price €** | 0-? | 0 | Prezzo minimo per puntare (0 = no limite) |
|
||||
| **Max Price €** | 0-? | 0 | Prezzo massimo (0 = no limite) |
|
||||
| **Timer Click** | 0-8 | 0 | Secondo del timer per click |
|
||||
| **Ritardo (ms)** | 0-2000 | 0 | Delay aggiuntivo prima del click |
|
||||
| **Multi-Click** | On/Off | Off | Click multipli paralleli |
|
||||
|
||||
### Impostazioni Per-Asta (Multi-Asta)
|
||||
|
||||
| Impostazione | Descrizione |
|
||||
|--------------|-------------|
|
||||
| **Timer Click** | Momento del click **solo per questa asta** |
|
||||
| **Min €** | Prezzo minimo **solo per questa asta** |
|
||||
| **Max €** | Prezzo massimo **solo per questa asta** |
|
||||
| **Pausa/Riprendi** | Stato **solo per questa asta** |
|
||||
|
||||
---
|
||||
|
||||
## ?? Controlli UI
|
||||
|
||||
### Pulsanti Principali
|
||||
|
||||
| Pulsante | Scorciatoia | Funzione |
|
||||
|----------|-------------|----------|
|
||||
| **Asta Singola** | - | Attiva modalità asta singola |
|
||||
| **Multi-Asta** | - | Attiva modalità multi-asta |
|
||||
| **Avvia** | - | Avvia automazione |
|
||||
| **Pausa** | - | Pausa globale (tutte le aste) |
|
||||
| **Stop** | - | Ferma automazione |
|
||||
|
||||
### Navigazione Browser
|
||||
|
||||
| Pulsante | Funzione |
|
||||
|----------|----------|
|
||||
| **Indietro** | Torna alla pagina precedente |
|
||||
| **Aggiorna** | Ricarica la pagina corrente |
|
||||
| **Vai** | Naviga all'URL inserito |
|
||||
|
||||
### Ridimensionamento
|
||||
|
||||
- **Pannello sinistro:** Trascina il separatore verticale ?
|
||||
- **Griglia aste:** Trascina il separatore orizzontale ? (sopra dettagli)
|
||||
- **Utenti/Log:** Trascina il separatore ? (tra utenti e log)
|
||||
|
||||
---
|
||||
|
||||
## ?? Strategie Consigliate
|
||||
|
||||
### Asta Singola - Oggetto di Valore Alto
|
||||
```
|
||||
Timer Click: 0-1 (molto aggressivo)
|
||||
Max Price: [valore massimo disposto]
|
||||
Multi-Click: ON
|
||||
Ritardo: 0ms
|
||||
```
|
||||
**Perché:** Massima velocità su asta competitiva
|
||||
|
||||
### Multi-Asta - Aste a Basso Costo
|
||||
```
|
||||
Timer Click per asta: 2-3 (conservativo)
|
||||
Min Price: 1€
|
||||
Max Price: 20€
|
||||
Pausa aste troppo alte
|
||||
```
|
||||
**Perché:** Punta solo su occasioni convenienti
|
||||
|
||||
### Multi-Asta - Caccia all'Affare
|
||||
```
|
||||
Max Price molto basso (es: 10€)
|
||||
Timer Click: 0 (aggressivo)
|
||||
Monitora 20+ aste
|
||||
```
|
||||
**Perché:** Prima o poi una scende sotto la soglia
|
||||
|
||||
---
|
||||
|
||||
## ? FAQ
|
||||
|
||||
### Come funziona il Timer Click?
|
||||
Il **Timer Click** indica a quale **secondo** del countdown vuoi che il programma clicchi.
|
||||
- **Timer Click = 0** ? Clicca tra 0.0s e 0.9s
|
||||
- **Timer Click = 1** ? Clicca tra 1.0s e 1.9s
|
||||
- **Timer Click = 2** ? Clicca tra 2.0s e 2.9s
|
||||
|
||||
?? **Consiglio:** 0-1 per massima aggressività, 2-3 per essere conservativi
|
||||
|
||||
### Perché l'asta si resetta?
|
||||
Un **reset** avviene quando qualcuno vince l'asta (timer arriva a 0). Il timer riparte e l'asta continua.
|
||||
Il programma **rileva automaticamente** i reset e mostra il vincitore.
|
||||
|
||||
### Posso puntare su più aste contemporaneamente?
|
||||
**No**, il programma (in Multi-Asta) punta solo sull'asta con **timer più basso** in ogni momento.
|
||||
Questo massimizza l'efficienza evitando sprechi.
|
||||
|
||||
### Cosa succede se imposto Min/Max Price?
|
||||
Il programma **salta il click** se il prezzo è fuori dal range:
|
||||
- Prezzo < Min ? ?? Click bloccato
|
||||
- Prezzo > Max ? ?? Click bloccato
|
||||
- Nel range ? ? Click eseguito
|
||||
|
||||
### Come metto in pausa una singola asta?
|
||||
1. Passa a **Multi-Asta**
|
||||
2. **Seleziona** l'asta dalla griglia
|
||||
3. Click **"Pausa"** nel pannello dettagli
|
||||
4. Solo quella asta viene fermata, le altre continuano
|
||||
|
||||
### Il Multi-Click migliora le probabilità?
|
||||
**Sì!** Invia **2 click paralleli** a 20ms di distanza per compensare lag di rete.
|
||||
?? Usa solo in Asta Singola su connessioni instabili.
|
||||
|
||||
### Posso usare AutoBidder su più computer?
|
||||
**Tecnicamente sì**, ma **non consigliato**:
|
||||
- Rischio di competere contro te stesso
|
||||
- Spreco di click
|
||||
- Ban potenziale da Bidoo
|
||||
|
||||
### È rilevabile da Bidoo?
|
||||
Il programma **emula comportamento umano**:
|
||||
- Usa il browser Microsoft Edge (WebView2)
|
||||
- Click via JavaScript nativo
|
||||
- Timing realistico
|
||||
|
||||
?? **Disclaimer:** Usa a tuo rischio. Bidoo potrebbe avere sistemi anti-bot.
|
||||
|
||||
---
|
||||
|
||||
## ?? Changelog
|
||||
|
||||
### v2.7 (Corrente) - Layout Verticale
|
||||
- ? **Separazione verticale** Utenti/Log con GridSplitter
|
||||
- ? **Margini ottimizzati** rispetto al bordo principale
|
||||
- ? **MinHeight** garantito (80px) per entrambe le sezioni
|
||||
|
||||
### v2.6 - UI Polish & Auto-Navigation
|
||||
- ? **Margini simmetrici** tra pannelli
|
||||
- ? **Navigazione automatica** ai Preferiti all'avvio (Multi-Asta)
|
||||
- ? **Smart URL check** evita reload inutili
|
||||
|
||||
### v2.5 - Bidders Per-Auction
|
||||
- ? **Griglia utenti per-asta** con numero puntate
|
||||
- ? **Layout 50/50 ridimensionabile** (Utenti | Log)
|
||||
- ? **Aggiornamento real-time** quando qualcuno punta
|
||||
|
||||
### v2.4 - UI Refinements
|
||||
- ? **Pausa/Riprendi per-asta** separati
|
||||
- ? **Visual feedback** (aste in pausa colorate)
|
||||
- ? **GridSplitter ingrandito** (12px) per migliore UX
|
||||
|
||||
### v2.3 - Multi-Auction Improvements
|
||||
- ? **Log e bidders separati** per ogni asta
|
||||
- ? **Impostazioni indipendenti** per-asta
|
||||
- ? **Evidenziazione** riga verde quando è la tua puntata
|
||||
|
||||
### v2.2 - Per-Auction Management
|
||||
- ? **Pannello dettagli asta selezionata**
|
||||
- ? **Pausa individuale** (non globale)
|
||||
- ? **Impostazioni personalizzate** per ogni asta
|
||||
|
||||
### v2.1 - Multi-Auction Core
|
||||
- ? **Modalità Multi-Asta** implementata
|
||||
- ? **Scansione automatica** aste preferite
|
||||
- ? **Auto-switch** sull'asta con timer più basso
|
||||
- ? **Griglia real-time** con 6 colonne
|
||||
|
||||
### v2.0 - Major Refactor
|
||||
- ? **Dark theme** GitHub-style
|
||||
- ? **Dual-panel layout** ridimensionabile
|
||||
- ? **WebView2** integrato
|
||||
- ? **Sicurezza navigazione** (solo Bidoo)
|
||||
|
||||
### v1.x - Initial Release
|
||||
- ? **Automazione base** asta singola
|
||||
- ?? **Lettura timer** da DOM
|
||||
- ??? **Click automatico** al secondo target
|
||||
|
||||
---
|
||||
|
||||
## ?? Documentazione Dettagliata
|
||||
|
||||
### File di Documentazione (nella cartella progetto)
|
||||
|
||||
| File | Descrizione |
|
||||
|------|-------------|
|
||||
| `PROJECT_SUMMARY.md` | Panoramica completa del progetto |
|
||||
| `CHANGELOG.md` | Storico completo delle modifiche |
|
||||
| `QUICK_REFERENCE.md` | Riferimento rapido comandi |
|
||||
| `MULTI_AUCTION_GUIDE.md` | Guida dettagliata modalità Multi-Asta |
|
||||
| `MULTI_AUCTION_GRID_GUIDE.md` | Funzionamento griglia aste |
|
||||
| `IMPLEMENTATION_SUMMARY.md` | Dettagli tecnici implementazione |
|
||||
|
||||
### Versioni Dettagliate
|
||||
|
||||
| File | Versione | Contenuto |
|
||||
|------|----------|-----------|
|
||||
| `v2.7_VERTICAL_LAYOUT.md` | 2.7 | Separazione verticale Utenti/Log |
|
||||
| `v2.6_UI_POLISH.md` | 2.6 | Margini e auto-navigazione |
|
||||
| `v2.5_BIDDERS_PER_AUCTION.md` | 2.5 | Griglia utenti per-asta |
|
||||
| `v2.4_UI_REFINEMENTS.md` | 2.4 | Pausa per-asta e feedback visivi |
|
||||
| `v2.3_MULTI_AUCTION_IMPROVEMENTS.md` | 2.3 | Log/bidders separati |
|
||||
| `v2.2_PER_AUCTION_MANAGEMENT.md` | 2.2 | Gestione aste individuali |
|
||||
| `v2.1_README.md` | 2.1 | Modalità Multi-Asta core |
|
||||
|
||||
---
|
||||
|
||||
## ?? Sicurezza e Privacy
|
||||
|
||||
### Navigazione Limitata
|
||||
- ? **Solo domini Bidoo** consentiti (bidoo.com, .it, .fr, .es, .de)
|
||||
- ? **Link esterni bloccati** automaticamente
|
||||
- ? **Validazione URL** su ogni navigazione
|
||||
|
||||
### Dati Locali
|
||||
- ? **Nessun dato inviato** a server esterni
|
||||
- ? **Log solo in memoria** (mai salvati su disco)
|
||||
- ? **Nessun tracking** o analytics
|
||||
|
||||
### Credenziali Bidoo
|
||||
- ?? **Non salvate** dal programma
|
||||
- ?? **Gestite da WebView2** (come Edge browser)
|
||||
- ?? **Cancella cache browser** per logout completo
|
||||
|
||||
---
|
||||
|
||||
## ?? Supporto
|
||||
|
||||
### Problemi Comuni
|
||||
|
||||
**Il programma non si avvia:**
|
||||
```bash
|
||||
# Verifica .NET 8.0 installato
|
||||
dotnet --version
|
||||
# Output atteso: 8.0.x
|
||||
```
|
||||
|
||||
**Click non funzionano:**
|
||||
- Verifica di essere **loggato su Bidoo**
|
||||
- Controlla impostazioni **Timer Click**
|
||||
- Verifica **connessione internet stabile**
|
||||
|
||||
**Aste non rilevate (Multi-Asta):**
|
||||
- Assicurati di essere sulla **pagina Preferiti**
|
||||
- Clicca ? sulle aste per aggiungerle ai preferiti
|
||||
- Clicca **"Avvia"** per avviare la scansione
|
||||
|
||||
**Navigazione bloccata:**
|
||||
- Stai cercando di aprire un link **non-Bidoo**
|
||||
- Solo i domini Bidoo sono consentiti per sicurezza
|
||||
|
||||
### Contatti
|
||||
|
||||
- ?? **Email:** [Alby96]
|
||||
- ?? **Issues:** Repository privato Gitea
|
||||
- ?? **Git:** `https://192.168.30.23/Alby96/Mimante`
|
||||
|
||||
---
|
||||
|
||||
## ?? Disclaimer
|
||||
|
||||
?? **Uso a Proprio Rischio**
|
||||
|
||||
Questo software è fornito "così com'è" senza garanzie di alcun tipo.
|
||||
L'uso di bot/automazione potrebbe **violare i Termini di Servizio di Bidoo**.
|
||||
|
||||
**Responsabilità dell'utente:**
|
||||
- ? Verificare compatibilità con ToS Bidoo
|
||||
- ? Usare in modo responsabile
|
||||
- ? Non abusare del sistema
|
||||
- ? Non creare account multipli
|
||||
- ? Non utilizzare per frode
|
||||
|
||||
**L'autore non è responsabile per:**
|
||||
- Ban o sospensioni account Bidoo
|
||||
- Perdite finanziarie
|
||||
- Malfunzionamenti del software
|
||||
- Uso improprio del programma
|
||||
|
||||
---
|
||||
|
||||
## ?? Licenza
|
||||
|
||||
**Privato** - Non redistribuire senza autorizzazione
|
||||
|
||||
© 2024 Alby96. Tutti i diritti riservati.
|
||||
|
||||
---
|
||||
|
||||
## ?? Conclusione
|
||||
|
||||
**AutoBidder** è uno strumento potente per ottimizzare le tue strategie su Bidoo.
|
||||
|
||||
### Punti di Forza
|
||||
- ? **Precisione al millisecondo** nei click
|
||||
- ? **Gestione multipla aste** simultanea
|
||||
- ? **Controllo totale** su ogni parametro
|
||||
- ? **Analisi competizione** dettagliata
|
||||
- ? **Interfaccia intuitiva** e moderna
|
||||
|
||||
### Usa con Saggezza
|
||||
- ?? Imposta **limiti di prezzo** ragionevoli
|
||||
- ?? Non puntare su **troppe aste** contemporaneamente
|
||||
- ?? Monitora il **budget** speso
|
||||
- ?? **Pausa** le aste diventate troppo costose
|
||||
|
||||
---
|
||||
|
||||
**Buona fortuna con le tue aste! ????**
|
||||
|
||||
*Happy Bidding!*
|
||||
Note tecniche per sviluppatori
|
||||
- Progetto target: `.NET 8.0` (WPF + WebView2)
|
||||
- Aree chiave del codice:
|
||||
- `Services\\BidooApiClient.cs` — gestione Click HTTP e parsing risposte
|
||||
- `Services\\AuctionMonitor.cs` — loop di polling e logica auto-switch
|
||||
- `Services\\SessionManager.cs` — sincronizzazione cookie e HttpClient creation
|
||||
- `Utilities\\PersistenceManager.cs` — salvataggio/ricaricamento `auctions.json`
|
||||
- `ViewModels\\AuctionViewModel.cs` + XAML corrispondenti — visualizzazione e binding UI
|
||||
|
||||
## Contributi
|
||||
- Questo repository è privato. Per contribuire, aprire PR verso branch `main` e seguire le convenzioni del progetto.
|
||||
|
||||
## Licenza
|
||||
- Privato — non distribuire senza autorizzazione del proprietario.
|
||||
|
||||
Buona fortuna con le aste e usa AutoBidder responsabilmente.
|
||||
Reference in New Issue
Block a user