nitai/projects
rblxtool / src / ui / RblxTool / Views / SweepPage.xaml.cs
120 lines · 3.6 KB Raw
1using System.Collections.ObjectModel;
2using Microsoft.UI.Xaml;
3using Microsoft.UI.Xaml.Controls;
4using RblxTool.Models;
5using RblxTool.Services;
6
7namespace RblxTool.Views;
8
9public sealed partial class SweepPage : Page
10{
11 private const int MaxFeedLines = 4000;
12
13 private readonly ObservableCollection<FeedLine> _feed = new();
14 private JobRunner? _runner;
15 private DispatcherTimer? _metricsTimer;
16
17 public SweepPage()
18 {
19 InitializeComponent();
20 FeedList.ItemsSource = _feed;
21 Loaded += OnLoaded;
22 Unloaded += OnUnloaded;
23 }
24
25 private void OnLoaded(object sender, RoutedEventArgs e)
26 {
27 _runner = AppState.Current.CreateRunner(DispatcherQueue);
28 _runner.EventReceived += OnEvent;
29 _runner.Completed += OnCompleted;
30 _metricsTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(750) };
31 _metricsTimer.Tick += (_, _) => RefreshMetrics();
32 }
33
34 private void OnUnloaded(object sender, RoutedEventArgs e)
35 {
36 _metricsTimer?.Stop();
37 _runner?.Stop();
38 }
39
40 private void OnStart(object sender, RoutedEventArgs e)
41 {
42 if (AppState.Current.Active is null)
43 {
44 Append(new FeedLine(" select an account first", FeedTone.Bad));
45 return;
46 }
47 var request = new SweepRequest
48 {
49 MaxPrice = (ulong)Math.Max(0, MaxPriceBox.Value),
50 Pages = (int)Math.Max(1, PagesBox.Value),
51 Limit = (int)Math.Max(0, LimitBox.Value),
52 ScanThreads = (int)Math.Max(1, ScanThreadsBox.Value),
53 DetailThreads = (int)Math.Max(1, DetailThreadsBox.Value),
54 BuyThreads = (int)Math.Max(1, BuyThreadsBox.Value),
55 Buy = BuyToggle.IsOn,
56 DryRun = DryRunToggle.IsOn,
57 SkipOwned = SkipOwnedToggle.IsOn,
58 IncludeCollectibles = CollectiblesToggle.IsOn,
59 };
60 _feed.Clear();
61 Append(new FeedLine(
62 $" sweeping as {AppState.Current.Active.Username} (max {request.MaxPrice} R$)",
63 FeedTone.Accent));
64 var jobId = AppState.Current.Engine.StartSweep(request);
65 _runner?.Start(jobId);
66 StartButton.IsEnabled = false;
67 StopButton.IsEnabled = true;
68 _metricsTimer?.Start();
69 }
70
71 private void OnStop(object sender, RoutedEventArgs e)
72 {
73 _runner?.Cancel();
74 Append(new FeedLine(" stopping after in flight requests settle", FeedTone.Warn));
75 }
76
77 private void OnEvent(JobEvent item)
78 {
79 if (item.Type == "progress")
80 {
81 ScannedText.Text = item.Scanned.ToString("N0");
82 MatchedText.Text = item.Matched.ToString("N0");
83 return;
84 }
85 if (item.Type == "purchase" && item.Success)
86 {
87 PurchasedText.Text = (ulong.Parse(PurchasedText.Text.Replace(",", "")) + 1).ToString("N0");
88 }
89 Append(FeedLine.From(item));
90 }
91
92 private void OnCompleted(string result)
93 {
94 StartButton.IsEnabled = true;
95 StopButton.IsEnabled = false;
96 _metricsTimer?.Stop();
97 RefreshMetrics();
98 Append(new FeedLine(" job finished", FeedTone.Good));
99 }
100
101 private void RefreshMetrics()
102 {
103 var metrics = AppState.Current.Engine.Metrics();
104 RequestsText.Text = metrics.Requests.ToString("N0");
105 LatencyText.Text = $"{metrics.AverageLatencyMs:F0} ms";
106 }
107
108 private void Append(FeedLine line)
109 {
110 if (_feed.Count >= MaxFeedLines)
111 {
112 _feed.RemoveAt(0);
113 }
114 _feed.Add(line);
115 if (_feed.Count > 0)
116 {
117 FeedList.ScrollIntoView(_feed[^1]);
118 }
119 }
120}