mirror of
https://github.com/chylex/Discord-History-Tracker.git
synced 2025-04-14 15:47:14 +03:00
Add debug tab with random database data generator
This commit is contained in:
parent
461e403733
commit
9341988017
@ -14,6 +14,7 @@
|
||||
<entry key="Desktop/Main/MainWindow.axaml" value="Desktop/Desktop.csproj" />
|
||||
<entry key="Desktop/Main/Pages/AdvancedPage.axaml" value="Desktop/Desktop.csproj" />
|
||||
<entry key="Desktop/Main/Pages/DatabasePage.axaml" value="Desktop/Desktop.csproj" />
|
||||
<entry key="Desktop/Main/Pages/DebugPage.axaml" value="Desktop/Desktop.csproj" />
|
||||
<entry key="Desktop/Main/Pages/TrackingPage.axaml" value="Desktop/Desktop.csproj" />
|
||||
<entry key="Desktop/Main/Pages/ViewerPage.axaml" value="Desktop/Desktop.csproj" />
|
||||
<entry key="Desktop/Main/Screens/MainContentScreen.axaml" value="Desktop/Desktop.csproj" />
|
||||
|
45
app/Desktop/Main/Pages/DebugPage.axaml
Normal file
45
app/Desktop/Main/Pages/DebugPage.axaml
Normal file
@ -0,0 +1,45 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pages="clr-namespace:DHT.Desktop.Main.Pages"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.Pages.DebugPage">
|
||||
|
||||
<Design.DataContext>
|
||||
<pages:DebugPageModel />
|
||||
</Design.DataContext>
|
||||
|
||||
<UserControl.Styles>
|
||||
<Style Selector="TextBox">
|
||||
<Setter Property="FontFamily" Value="Consolas,Courier" />
|
||||
<Setter Property="FontSize" Value="15" />
|
||||
</Style>
|
||||
<Style Selector="WrapPanel > StackPanel">
|
||||
<Setter Property="Orientation" Value="Vertical" />
|
||||
<Setter Property="Margin" Value="0 0 10 10" />
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
|
||||
<StackPanel Orientation="Vertical" Spacing="10">
|
||||
<Expander Header="Generate Random Data" IsExpanded="True">
|
||||
<WrapPanel>
|
||||
<StackPanel>
|
||||
<Label Target="Channels">Channels</Label>
|
||||
<TextBox x:Name="Channels" Width="100" Text="{Binding GenerateChannels}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<Label Target="Users">Users</Label>
|
||||
<TextBox x:Name="Users" Width="100" Text="{Binding GenerateUsers}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<Label Target="Messages">Messages</Label>
|
||||
<TextBox x:Name="Messages" Width="100" Text="{Binding GenerateMessages}" />
|
||||
</StackPanel>
|
||||
<StackPanel VerticalAlignment="Bottom">
|
||||
<Button Command="{Binding OnClickAddRandomDataToDatabase}">Add to Database</Button>
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
</Expander>
|
||||
</StackPanel>
|
||||
</UserControl>
|
16
app/Desktop/Main/Pages/DebugPage.axaml.cs
Normal file
16
app/Desktop/Main/Pages/DebugPage.axaml.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace DHT.Desktop.Main.Pages {
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
public sealed class DebugPage : UserControl {
|
||||
public DebugPage() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent() {
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
185
app/Desktop/Main/Pages/DebugPageModel.cs
Normal file
185
app/Desktop/Main/Pages/DebugPageModel.cs
Normal file
@ -0,0 +1,185 @@
|
||||
#if DEBUG
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using DHT.Desktop.Dialogs.Message;
|
||||
using DHT.Desktop.Dialogs.Progress;
|
||||
using DHT.Server.Data;
|
||||
using DHT.Server.Database;
|
||||
using DHT.Server.Service;
|
||||
using DHT.Utils.Models;
|
||||
|
||||
namespace DHT.Desktop.Main.Pages {
|
||||
sealed class DebugPageModel : BaseModel {
|
||||
public string GenerateChannels { get; set; } = "0";
|
||||
public string GenerateUsers { get; set; } = "0";
|
||||
public string GenerateMessages { get; set; } = "0";
|
||||
|
||||
private readonly Window window;
|
||||
private readonly IDatabaseFile db;
|
||||
|
||||
[Obsolete("Designer")]
|
||||
public DebugPageModel() : this(null!, DummyDatabaseFile.Instance) {}
|
||||
|
||||
public DebugPageModel(Window window, IDatabaseFile db) {
|
||||
this.window = window;
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
public async void OnClickAddRandomDataToDatabase() {
|
||||
if (!int.TryParse(GenerateChannels, out int channels) || channels < 1) {
|
||||
await Dialog.ShowOk(window, "Generate Random Data", "Amount of channels must be at least 1!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!int.TryParse(GenerateUsers, out int users) || users < 1) {
|
||||
await Dialog.ShowOk(window, "Generate Random Data", "Amount of users must be at least 1!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!int.TryParse(GenerateMessages, out int messages) || messages < 1) {
|
||||
await Dialog.ShowOk(window, "Generate Random Data", "Amount of messages must be at least 1!");
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressDialog progressDialog = new ProgressDialog {
|
||||
DataContext = new ProgressDialogModel(async callback => await GenerateRandomData(channels, users, messages, callback)) {
|
||||
Title = "Generating Random Data"
|
||||
}
|
||||
};
|
||||
|
||||
await progressDialog.ShowDialog(window);
|
||||
}
|
||||
|
||||
private const int BatchSize = 100;
|
||||
|
||||
private async Task GenerateRandomData(int channelCount, int userCount, int messageCount, IProgressCallback callback) {
|
||||
var rand = new Random();
|
||||
var server = new DHT.Server.Data.Server {
|
||||
Id = RandomId(rand),
|
||||
Name = RandomName("s"),
|
||||
Type = ServerType.Server
|
||||
};
|
||||
|
||||
var channels = Enumerable.Range(0, channelCount).Select(i => new Channel {
|
||||
Id = RandomId(rand),
|
||||
Server = server.Id,
|
||||
Name = RandomName("c"),
|
||||
ParentId = null,
|
||||
Position = i,
|
||||
Topic = RandomText(rand, 10),
|
||||
Nsfw = rand.Next(4) == 0
|
||||
}).ToArray();
|
||||
|
||||
var users = Enumerable.Range(0, userCount).Select(_ => new User {
|
||||
Id = RandomId(rand),
|
||||
Name = RandomName("u"),
|
||||
AvatarUrl = null,
|
||||
Discriminator = rand.Next(0, 9999).ToString()
|
||||
}).ToArray();
|
||||
|
||||
db.AddServer(server);
|
||||
db.AddUsers(users);
|
||||
|
||||
foreach (var channel in channels) {
|
||||
db.AddChannel(channel);
|
||||
}
|
||||
|
||||
int batchCount = (messageCount + BatchSize - 1) / BatchSize;
|
||||
await callback.Update("Adding messages in batches of 100", 0, batchCount);
|
||||
|
||||
var now = DateTimeOffset.Now;
|
||||
int batchIndex = 0;
|
||||
|
||||
while (messageCount > 0) {
|
||||
int hourOffset = batchIndex;
|
||||
|
||||
var messages = Enumerable.Range(0, Math.Min(messageCount, BatchSize)).Select(i => {
|
||||
DateTimeOffset time = now.AddHours(hourOffset).AddMinutes((i * 60.0) / BatchSize);
|
||||
DateTimeOffset? edit = rand.Next(100) == 0 ? time.AddSeconds(rand.Next(1, 60)) : null;
|
||||
|
||||
var timeMillis = time.ToUnixTimeMilliseconds();
|
||||
var editMillis = edit?.ToUnixTimeMilliseconds();
|
||||
|
||||
return new Message {
|
||||
Id = (ulong) timeMillis,
|
||||
Sender = RandomBiasedIndex(rand, users).Id,
|
||||
Channel = RandomBiasedIndex(rand, channels).Id,
|
||||
Text = RandomText(rand, 100),
|
||||
Timestamp = timeMillis,
|
||||
EditTimestamp = editMillis,
|
||||
RepliedToId = null,
|
||||
Attachments = ImmutableArray<Attachment>.Empty,
|
||||
Embeds = ImmutableArray<Embed>.Empty,
|
||||
Reactions = ImmutableArray<Reaction>.Empty
|
||||
};
|
||||
}).ToArray();
|
||||
|
||||
db.AddMessages(messages);
|
||||
|
||||
messageCount -= 100;
|
||||
await callback.Update("Adding messages in batches of 100", ++batchIndex, batchCount);
|
||||
}
|
||||
}
|
||||
|
||||
private static ulong RandomId(Random rand) {
|
||||
ulong h = unchecked((ulong) rand.Next());
|
||||
ulong l = unchecked((ulong) rand.Next());
|
||||
return (h << 32) | l;
|
||||
}
|
||||
|
||||
private static string RandomName(string prefix) {
|
||||
return prefix + "-" + ServerUtils.GenerateRandomToken(5);
|
||||
}
|
||||
|
||||
private static T RandomBiasedIndex<T>(Random rand, T[] options) {
|
||||
return options[(int) Math.Floor(options.Length * rand.NextDouble() * rand.NextDouble())];
|
||||
}
|
||||
|
||||
private static readonly string[] RandomWords = {
|
||||
"apple", "apricot", "artichoke", "arugula", "asparagus", "avocado",
|
||||
"banana", "bean", "beechnut", "beet", "blackberry", "blackcurrant", "blueberry", "boysenberry", "bramble", "broccoli",
|
||||
"cabbage", "cacao", "cantaloupe", "caper", "carambola", "carrot", "cauliflower", "celery", "chard", "cherry", "chokeberry", "citron", "clementine", "coconut", "corn", "crabapple", "cranberry", "cucumber", "currant",
|
||||
"daikon", "date", "dewberry", "durian",
|
||||
"edamame", "eggplant", "elderberry", "endive",
|
||||
"fig",
|
||||
"garlic", "ginger", "gooseberry", "grape", "grapefruit", "guava",
|
||||
"honeysuckle", "horseradish", "huckleberry",
|
||||
"jackfruit", "jicama",
|
||||
"kale", "kiwi", "kohlrabi", "kumquat",
|
||||
"leek", "lemon", "lentil", "lettuce", "lime",
|
||||
"mandarin", "mango", "mushroom", "myrtle",
|
||||
"nectarine", "nut",
|
||||
"olive", "okra", "onion", "orange",
|
||||
"papaya", "parsnip", "pawpaw", "peach", "pear", "pea", "pepper", "persimmon", "pineapple", "plum", "plantain", "pomegranate", "pomelo", "potato", "prune", "pumpkin",
|
||||
"quandong", "quinoa",
|
||||
"radicchio", "radish", "raisin", "raspberry", "redcurrant", "rhubarb", "rutabaga",
|
||||
"spinach", "strawberry", "squash",
|
||||
"tamarind", "tangerine", "tomatillo", "tomato", "turnip",
|
||||
"vanilla",
|
||||
"watercress", "watermelon",
|
||||
"yam",
|
||||
"zucchini"
|
||||
};
|
||||
|
||||
private static string RandomText(Random rand, int maxWords) {
|
||||
int wordCount = 1 + (int) Math.Floor(maxWords * Math.Pow(rand.NextDouble(), 3));
|
||||
return string.Join(' ', Enumerable.Range(0, wordCount).Select(_ => RandomWords[rand.Next(RandomWords.Length)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
using DHT.Utils.Models;
|
||||
|
||||
namespace DHT.Desktop.Main.Pages {
|
||||
sealed class DebugPageModel : BaseModel {
|
||||
public string GenerateChannels { get; set; } = "0";
|
||||
public string GenerateUsers { get; set; } = "0";
|
||||
public string GenerateMessages { get; set; } = "0";
|
||||
|
||||
public void OnClickAddRandomDataToDatabase() {}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -80,7 +80,7 @@
|
||||
<TabControl x:Name="TabControl" TabStripPlacement="Left" DockPanel.Dock="Top">
|
||||
<TabControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Grid ColumnDefinitions="Auto" RowDefinitions="Auto,Auto,Auto,*,Auto" />
|
||||
<Grid ColumnDefinitions="Auto" RowDefinitions="Auto,Auto,Auto,*,Auto,Auto" />
|
||||
</ItemsPanelTemplate>
|
||||
</TabControl.ItemsPanel>
|
||||
<TabItem x:Name="TabDatabase" Header="Database" Classes="first" Grid.Row="0">
|
||||
@ -103,6 +103,11 @@
|
||||
<ContentPresenter Content="{Binding AdvancedPage}" Classes="page" />
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
<TabItem x:Name="TabDebug" Header="Debug" Grid.Row="5" IsVisible="{Binding HasDebugPage}">
|
||||
<ScrollViewer>
|
||||
<ContentPresenter Content="{Binding DebugPage}" Classes="page" />
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</DockPanel>
|
||||
|
||||
|
@ -25,6 +25,15 @@ namespace DHT.Desktop.Main.Screens {
|
||||
public AdvancedPage AdvancedPage { get; }
|
||||
private AdvancedPageModel AdvancedPageModel { get; }
|
||||
|
||||
public DebugPage? DebugPage { get; }
|
||||
|
||||
#if DEBUG
|
||||
public bool HasDebugPage => true;
|
||||
private DebugPageModel DebugPageModel { get; }
|
||||
#else
|
||||
public bool HasDebugPage => false;
|
||||
#endif
|
||||
|
||||
public StatusBarModel StatusBarModel { get; }
|
||||
|
||||
public event EventHandler? DatabaseClosed {
|
||||
@ -35,7 +44,7 @@ namespace DHT.Desktop.Main.Screens {
|
||||
DatabasePageModel.DatabaseClosed -= value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private readonly Window window;
|
||||
private readonly ServerManager serverManager;
|
||||
|
||||
@ -45,9 +54,9 @@ namespace DHT.Desktop.Main.Screens {
|
||||
public MainContentScreenModel(Window window, IDatabaseFile db) {
|
||||
this.window = window;
|
||||
this.serverManager = new ServerManager(db);
|
||||
|
||||
|
||||
ServerLauncher.ServerManagementExceptionCaught += ServerLauncherOnServerManagementExceptionCaught;
|
||||
|
||||
|
||||
DatabasePageModel = new DatabasePageModel(window, db);
|
||||
DatabasePage = new DatabasePage { DataContext = DatabasePageModel };
|
||||
|
||||
@ -56,15 +65,22 @@ namespace DHT.Desktop.Main.Screens {
|
||||
|
||||
ViewerPageModel = new ViewerPageModel(window, db);
|
||||
ViewerPage = new ViewerPage { DataContext = ViewerPageModel };
|
||||
|
||||
|
||||
AdvancedPageModel = new AdvancedPageModel(window, serverManager);
|
||||
AdvancedPage = new AdvancedPage { DataContext = AdvancedPageModel };
|
||||
|
||||
StatusBarModel = new StatusBarModel(db.Statistics);
|
||||
#if DEBUG
|
||||
DebugPageModel = new DebugPageModel(window, db);
|
||||
DebugPage = new DebugPage { DataContext = DebugPageModel };
|
||||
#else
|
||||
DebugPage = null;
|
||||
#endif
|
||||
|
||||
StatusBarModel = new StatusBarModel(db.Statistics);
|
||||
|
||||
AdvancedPageModel.ServerConfigurationModel.ServerStatusChanged += OnServerStatusChanged;
|
||||
DatabaseClosed += OnDatabaseClosed;
|
||||
|
||||
|
||||
StatusBarModel.CurrentStatus = serverManager.IsRunning ? StatusBarModel.Status.Ready : StatusBarModel.Status.Stopped;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
namespace DHT.Server.Data {
|
||||
public readonly struct Channel {
|
||||
public ulong Id { get; internal init; }
|
||||
public ulong Server { get; internal init; }
|
||||
public string Name { get; internal init; }
|
||||
public ulong? ParentId { get; internal init; }
|
||||
public int? Position { get; internal init; }
|
||||
public string? Topic { get; internal init; }
|
||||
public bool? Nsfw { get; internal init; }
|
||||
public ulong Id { get; init; }
|
||||
public ulong Server { get; init; }
|
||||
public string Name { get; init; }
|
||||
public ulong? ParentId { get; init; }
|
||||
public int? Position { get; init; }
|
||||
public string? Topic { get; init; }
|
||||
public bool? Nsfw { get; init; }
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,15 @@ using System.Collections.Immutable;
|
||||
|
||||
namespace DHT.Server.Data {
|
||||
public readonly struct Message {
|
||||
public ulong Id { get; internal init; }
|
||||
public ulong Sender { get; internal init; }
|
||||
public ulong Channel { get; internal init; }
|
||||
public string Text { get; internal init; }
|
||||
public long Timestamp { get; internal init; }
|
||||
public long? EditTimestamp { get; internal init; }
|
||||
public ulong? RepliedToId { get; internal init; }
|
||||
public ImmutableArray<Attachment> Attachments { get; internal init; }
|
||||
public ImmutableArray<Embed> Embeds { get; internal init; }
|
||||
public ImmutableArray<Reaction> Reactions { get; internal init; }
|
||||
public ulong Id { get; init; }
|
||||
public ulong Sender { get; init; }
|
||||
public ulong Channel { get; init; }
|
||||
public string Text { get; init; }
|
||||
public long Timestamp { get; init; }
|
||||
public long? EditTimestamp { get; init; }
|
||||
public ulong? RepliedToId { get; init; }
|
||||
public ImmutableArray<Attachment> Attachments { get; init; }
|
||||
public ImmutableArray<Embed> Embeds { get; init; }
|
||||
public ImmutableArray<Reaction> Reactions { get; init; }
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
namespace DHT.Server.Data {
|
||||
public readonly struct Server {
|
||||
public ulong Id { get; internal init; }
|
||||
public string Name { get; internal init; }
|
||||
public ServerType? Type { get; internal init; }
|
||||
public ulong Id { get; init; }
|
||||
public string Name { get; init; }
|
||||
public ServerType? Type { get; init; }
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
namespace DHT.Server.Data {
|
||||
public readonly struct User {
|
||||
public ulong Id { get; internal init; }
|
||||
public string Name { get; internal init; }
|
||||
public string? AvatarUrl { get; internal init; }
|
||||
public string? Discriminator { get; internal init; }
|
||||
public ulong Id { get; init; }
|
||||
public string Name { get; init; }
|
||||
public string? AvatarUrl { get; init; }
|
||||
public string? Discriminator { get; init; }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user