Add customer communication system
This commit is contained in:
308
TeleBot/TeleBotClient/BotSimulator.cs
Normal file
308
TeleBot/TeleBotClient/BotSimulator.cs
Normal file
@@ -0,0 +1,308 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bogus;
|
||||
using LittleShop.Client;
|
||||
using LittleShop.Client.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace TeleBotClient
|
||||
{
|
||||
public class BotSimulator
|
||||
{
|
||||
private readonly ILittleShopClient _client;
|
||||
private readonly ILogger<BotSimulator> _logger;
|
||||
private readonly Random _random;
|
||||
private readonly Faker _faker;
|
||||
private List<Category> _categories = new();
|
||||
private List<Product> _products = new();
|
||||
|
||||
public BotSimulator(ILittleShopClient client, ILogger<BotSimulator> logger)
|
||||
{
|
||||
_client = client;
|
||||
_logger = logger;
|
||||
_random = new Random();
|
||||
_faker = new Faker();
|
||||
}
|
||||
|
||||
public async Task<SimulationResult> SimulateUserSession()
|
||||
{
|
||||
var result = new SimulationResult
|
||||
{
|
||||
SessionId = Guid.NewGuid().ToString(),
|
||||
StartTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("🤖 Starting bot simulation session {SessionId}", result.SessionId);
|
||||
|
||||
// Step 1: Authenticate
|
||||
_logger.LogInformation("📝 Authenticating with API...");
|
||||
if (!await Authenticate())
|
||||
{
|
||||
result.Success = false;
|
||||
result.ErrorMessage = "Authentication failed";
|
||||
return result;
|
||||
}
|
||||
result.Steps.Add("✅ Authentication successful");
|
||||
|
||||
// Step 2: Browse categories
|
||||
_logger.LogInformation("📁 Browsing categories...");
|
||||
await BrowseCategories();
|
||||
result.Steps.Add($"✅ Found {_categories.Count} categories");
|
||||
|
||||
// Step 3: Select random category and browse products
|
||||
if (_categories.Any())
|
||||
{
|
||||
var selectedCategory = _categories[_random.Next(_categories.Count)];
|
||||
_logger.LogInformation("🔍 Selected category: {Category}", selectedCategory.Name);
|
||||
result.Steps.Add($"✅ Selected category: {selectedCategory.Name}");
|
||||
|
||||
await BrowseProducts(selectedCategory.Id);
|
||||
result.Steps.Add($"✅ Found {_products.Count} products in category");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Browse all products if no categories
|
||||
await BrowseProducts(null);
|
||||
result.Steps.Add($"✅ Found {_products.Count} total products");
|
||||
}
|
||||
|
||||
// Step 4: Build shopping cart
|
||||
_logger.LogInformation("🛒 Building shopping cart...");
|
||||
var cart = BuildRandomCart();
|
||||
result.Cart = cart;
|
||||
result.Steps.Add($"✅ Added {cart.Items.Count} items to cart (Total: ${cart.TotalAmount:F2})");
|
||||
|
||||
// Step 5: Generate shipping information
|
||||
_logger.LogInformation("📦 Generating shipping information...");
|
||||
var shippingInfo = GenerateShippingInfo();
|
||||
result.ShippingInfo = shippingInfo;
|
||||
result.Steps.Add($"✅ Generated shipping to {shippingInfo.City}, {shippingInfo.Country}");
|
||||
|
||||
// Step 6: Create order
|
||||
_logger.LogInformation("📝 Creating order...");
|
||||
var order = await CreateOrder(cart, shippingInfo);
|
||||
if (order != null)
|
||||
{
|
||||
result.OrderId = order.Id;
|
||||
result.OrderTotal = order.TotalAmount;
|
||||
result.Steps.Add($"✅ Order created: {order.Id}");
|
||||
|
||||
// Step 7: Select payment method
|
||||
var currency = SelectRandomCurrency();
|
||||
_logger.LogInformation("💰 Selected payment method: {Currency}", currency);
|
||||
result.PaymentCurrency = currency;
|
||||
result.Steps.Add($"✅ Selected payment: {currency}");
|
||||
|
||||
// Step 8: Create payment
|
||||
var payment = await CreatePayment(order.Id, currency);
|
||||
if (payment != null)
|
||||
{
|
||||
result.PaymentId = payment.Id;
|
||||
result.PaymentAddress = payment.WalletAddress;
|
||||
result.PaymentAmount = payment.RequiredAmount;
|
||||
result.Steps.Add($"✅ Payment created: {payment.RequiredAmount} {currency}");
|
||||
}
|
||||
}
|
||||
|
||||
result.Success = true;
|
||||
result.EndTime = DateTime.UtcNow;
|
||||
result.Duration = result.EndTime - result.StartTime;
|
||||
|
||||
_logger.LogInformation("✅ Simulation completed successfully in {Duration}", result.Duration);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "❌ Simulation failed");
|
||||
result.Success = false;
|
||||
result.ErrorMessage = ex.Message;
|
||||
result.EndTime = DateTime.UtcNow;
|
||||
result.Duration = result.EndTime - result.StartTime;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<bool> Authenticate()
|
||||
{
|
||||
var result = await _client.Authentication.LoginAsync("admin", "admin");
|
||||
if (result.IsSuccess && result.Data != null && !string.IsNullOrEmpty(result.Data.Token))
|
||||
{
|
||||
_client.Authentication.SetToken(result.Data.Token);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task BrowseCategories()
|
||||
{
|
||||
var result = await _client.Catalog.GetCategoriesAsync();
|
||||
if (result.IsSuccess && result.Data != null)
|
||||
{
|
||||
_categories = result.Data;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task BrowseProducts(Guid? categoryId)
|
||||
{
|
||||
var result = await _client.Catalog.GetProductsAsync(
|
||||
pageNumber: 1,
|
||||
pageSize: 50,
|
||||
categoryId: categoryId
|
||||
);
|
||||
|
||||
if (result.IsSuccess && result.Data != null)
|
||||
{
|
||||
_products = result.Data.Items;
|
||||
}
|
||||
}
|
||||
|
||||
private ShoppingCart BuildRandomCart()
|
||||
{
|
||||
var cart = new ShoppingCart();
|
||||
|
||||
if (!_products.Any())
|
||||
return cart;
|
||||
|
||||
// Random number of items (1-5)
|
||||
var itemCount = _random.Next(1, Math.Min(6, _products.Count + 1));
|
||||
var selectedProducts = _products.OrderBy(x => _random.Next()).Take(itemCount).ToList();
|
||||
|
||||
foreach (var product in selectedProducts)
|
||||
{
|
||||
var quantity = _random.Next(1, 4); // 1-3 items
|
||||
cart.AddItem(product.Id, product.Name, product.Price, quantity);
|
||||
_logger.LogDebug("Added {Quantity}x {Product} @ ${Price}",
|
||||
quantity, product.Name, product.Price);
|
||||
}
|
||||
|
||||
return cart;
|
||||
}
|
||||
|
||||
private ShippingInfo GenerateShippingInfo()
|
||||
{
|
||||
return new ShippingInfo
|
||||
{
|
||||
IdentityReference = $"SIM-{Guid.NewGuid().ToString().Substring(0, 8).ToUpper()}",
|
||||
Name = _faker.Name.FullName(),
|
||||
Address = _faker.Address.StreetAddress(),
|
||||
City = _faker.Address.City(),
|
||||
PostCode = _faker.Address.ZipCode(),
|
||||
Country = _faker.PickRandom(new[] { "United Kingdom", "Ireland", "France", "Germany", "Netherlands" }),
|
||||
Notes = _faker.Lorem.Sentence()
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<Order?> CreateOrder(ShoppingCart cart, ShippingInfo shipping)
|
||||
{
|
||||
var request = new CreateOrderRequest
|
||||
{
|
||||
IdentityReference = shipping.IdentityReference,
|
||||
ShippingName = shipping.Name,
|
||||
ShippingAddress = shipping.Address,
|
||||
ShippingCity = shipping.City,
|
||||
ShippingPostCode = shipping.PostCode,
|
||||
ShippingCountry = shipping.Country,
|
||||
Notes = shipping.Notes,
|
||||
Items = cart.Items.Select(i => new CreateOrderItem
|
||||
{
|
||||
ProductId = i.ProductId,
|
||||
Quantity = i.Quantity
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
var result = await _client.Orders.CreateOrderAsync(request);
|
||||
return result.IsSuccess ? result.Data : null;
|
||||
}
|
||||
|
||||
private string SelectRandomCurrency()
|
||||
{
|
||||
var currencies = new[] { "BTC", "XMR", "USDT", "LTC", "ETH", "ZEC", "DASH", "DOGE" };
|
||||
|
||||
// Weight towards BTC and XMR
|
||||
var weights = new[] { 30, 25, 15, 10, 10, 5, 3, 2 };
|
||||
var totalWeight = weights.Sum();
|
||||
var randomValue = _random.Next(totalWeight);
|
||||
|
||||
var currentWeight = 0;
|
||||
for (int i = 0; i < currencies.Length; i++)
|
||||
{
|
||||
currentWeight += weights[i];
|
||||
if (randomValue < currentWeight)
|
||||
return currencies[i];
|
||||
}
|
||||
|
||||
return "BTC";
|
||||
}
|
||||
|
||||
private async Task<CryptoPayment?> CreatePayment(Guid orderId, string currency)
|
||||
{
|
||||
var result = await _client.Orders.CreatePaymentAsync(orderId, currency);
|
||||
return result.IsSuccess ? result.Data : null;
|
||||
}
|
||||
}
|
||||
|
||||
public class SimulationResult
|
||||
{
|
||||
public string SessionId { get; set; } = string.Empty;
|
||||
public bool Success { get; set; }
|
||||
public string? ErrorMessage { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public TimeSpan Duration { get; set; }
|
||||
public List<string> Steps { get; set; } = new();
|
||||
|
||||
// Order details
|
||||
public Guid? OrderId { get; set; }
|
||||
public decimal OrderTotal { get; set; }
|
||||
public ShoppingCart? Cart { get; set; }
|
||||
public ShippingInfo? ShippingInfo { get; set; }
|
||||
|
||||
// Payment details
|
||||
public Guid? PaymentId { get; set; }
|
||||
public string? PaymentCurrency { get; set; }
|
||||
public string? PaymentAddress { get; set; }
|
||||
public decimal PaymentAmount { get; set; }
|
||||
}
|
||||
|
||||
public class ShoppingCart
|
||||
{
|
||||
public List<CartItem> Items { get; set; } = new();
|
||||
public decimal TotalAmount => Items.Sum(i => i.TotalPrice);
|
||||
|
||||
public void AddItem(Guid productId, string name, decimal price, int quantity)
|
||||
{
|
||||
Items.Add(new CartItem
|
||||
{
|
||||
ProductId = productId,
|
||||
ProductName = name,
|
||||
UnitPrice = price,
|
||||
Quantity = quantity,
|
||||
TotalPrice = price * quantity
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class CartItem
|
||||
{
|
||||
public Guid ProductId { get; set; }
|
||||
public string ProductName { get; set; } = string.Empty;
|
||||
public decimal UnitPrice { get; set; }
|
||||
public int Quantity { get; set; }
|
||||
public decimal TotalPrice { get; set; }
|
||||
}
|
||||
|
||||
public class ShippingInfo
|
||||
{
|
||||
public string IdentityReference { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Address { get; set; } = string.Empty;
|
||||
public string City { get; set; } = string.Empty;
|
||||
public string PostCode { get; set; } = string.Empty;
|
||||
public string Country { get; set; } = string.Empty;
|
||||
public string? Notes { get; set; }
|
||||
}
|
||||
}
|
||||
367
TeleBot/TeleBotClient/SimulatorProgram.cs
Normal file
367
TeleBot/TeleBotClient/SimulatorProgram.cs
Normal file
@@ -0,0 +1,367 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LittleShop.Client.Extensions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog;
|
||||
using TeleBotClient;
|
||||
|
||||
namespace TeleBotClient
|
||||
{
|
||||
public class SimulatorProgram
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
// Configure Serilog
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.MinimumLevel.Debug()
|
||||
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
|
||||
.WriteTo.File("logs/simulator-.txt", rollingInterval: RollingInterval.Day)
|
||||
.CreateLogger();
|
||||
|
||||
try
|
||||
{
|
||||
// Build configuration
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.SetBasePath(Directory.GetCurrentDirectory())
|
||||
.AddJsonFile("appsettings.json", optional: false)
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
// Configure services
|
||||
var services = new ServiceCollection();
|
||||
|
||||
// Add logging
|
||||
services.AddLogging(builder =>
|
||||
{
|
||||
builder.ClearProviders();
|
||||
builder.AddSerilog();
|
||||
});
|
||||
|
||||
// Add LittleShop client
|
||||
services.AddLittleShopClient(options =>
|
||||
{
|
||||
options.BaseUrl = configuration["LittleShop:ApiUrl"] ?? "https://localhost:5001";
|
||||
options.TimeoutSeconds = 30;
|
||||
options.MaxRetryAttempts = 3;
|
||||
});
|
||||
|
||||
// Add simulator
|
||||
services.AddTransient<BotSimulator>();
|
||||
services.AddTransient<TestRunner>();
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
// Run tests
|
||||
var runner = serviceProvider.GetRequiredService<TestRunner>();
|
||||
await runner.RunAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "Application terminated unexpectedly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TestRunner
|
||||
{
|
||||
private readonly BotSimulator _simulator;
|
||||
private readonly ILogger<TestRunner> _logger;
|
||||
private readonly List<SimulationResult> _allResults = new();
|
||||
|
||||
public TestRunner(BotSimulator simulator, ILogger<TestRunner> logger)
|
||||
{
|
||||
_simulator = simulator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task RunAsync()
|
||||
{
|
||||
_logger.LogInformation("===========================================");
|
||||
_logger.LogInformation("🚀 TeleBot Client Simulator");
|
||||
_logger.LogInformation("===========================================");
|
||||
|
||||
while (true)
|
||||
{
|
||||
Console.WriteLine("\n📋 Select an option:");
|
||||
Console.WriteLine("1. Run single simulation");
|
||||
Console.WriteLine("2. Run multiple simulations");
|
||||
Console.WriteLine("3. Run stress test");
|
||||
Console.WriteLine("4. View statistics");
|
||||
Console.WriteLine("5. Exit");
|
||||
Console.Write("\nChoice: ");
|
||||
|
||||
var choice = Console.ReadLine();
|
||||
|
||||
switch (choice)
|
||||
{
|
||||
case "1":
|
||||
await RunSingleSimulation();
|
||||
break;
|
||||
|
||||
case "2":
|
||||
await RunMultipleSimulations();
|
||||
break;
|
||||
|
||||
case "3":
|
||||
await RunStressTest();
|
||||
break;
|
||||
|
||||
case "4":
|
||||
DisplayStatistics();
|
||||
break;
|
||||
|
||||
case "5":
|
||||
_logger.LogInformation("Exiting simulator...");
|
||||
return;
|
||||
|
||||
default:
|
||||
Console.WriteLine("Invalid choice. Please try again.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunSingleSimulation()
|
||||
{
|
||||
_logger.LogInformation("\n🎯 Running single simulation...\n");
|
||||
|
||||
var result = await _simulator.SimulateUserSession();
|
||||
_allResults.Add(result);
|
||||
|
||||
DisplaySimulationResult(result);
|
||||
}
|
||||
|
||||
private async Task RunMultipleSimulations()
|
||||
{
|
||||
Console.Write("\nHow many simulations to run? ");
|
||||
if (!int.TryParse(Console.ReadLine(), out var count) || count <= 0)
|
||||
{
|
||||
Console.WriteLine("Invalid number.");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation("\n🎯 Running {Count} simulations...\n", count);
|
||||
|
||||
var results = new List<SimulationResult>();
|
||||
var successful = 0;
|
||||
var failed = 0;
|
||||
|
||||
for (int i = 1; i <= count; i++)
|
||||
{
|
||||
_logger.LogInformation("▶️ Simulation {Number}/{Total}", i, count);
|
||||
|
||||
var result = await _simulator.SimulateUserSession();
|
||||
results.Add(result);
|
||||
_allResults.Add(result);
|
||||
|
||||
if (result.Success)
|
||||
successful++;
|
||||
else
|
||||
failed++;
|
||||
|
||||
// Brief pause between simulations
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
DisplayBatchSummary(results, successful, failed);
|
||||
}
|
||||
|
||||
private async Task RunStressTest()
|
||||
{
|
||||
Console.Write("\nNumber of concurrent simulations: ");
|
||||
if (!int.TryParse(Console.ReadLine(), out var concurrent) || concurrent <= 0)
|
||||
{
|
||||
Console.WriteLine("Invalid number.");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Write("Total simulations to run: ");
|
||||
if (!int.TryParse(Console.ReadLine(), out var total) || total <= 0)
|
||||
{
|
||||
Console.WriteLine("Invalid number.");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation("\n⚡ Starting stress test: {Concurrent} concurrent, {Total} total\n",
|
||||
concurrent, total);
|
||||
|
||||
var semaphore = new SemaphoreSlim(concurrent);
|
||||
var tasks = new List<Task<SimulationResult>>();
|
||||
var startTime = DateTime.UtcNow;
|
||||
|
||||
for (int i = 0; i < total; i++)
|
||||
{
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
await semaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
return await _simulator.SimulateUserSession();
|
||||
}
|
||||
finally
|
||||
{
|
||||
semaphore.Release();
|
||||
}
|
||||
});
|
||||
tasks.Add(task);
|
||||
}
|
||||
|
||||
var allResults = await Task.WhenAll(tasks);
|
||||
var results = allResults.ToList();
|
||||
_allResults.AddRange(results);
|
||||
|
||||
var duration = DateTime.UtcNow - startTime;
|
||||
|
||||
DisplayStressTestResults(results, duration, concurrent, total);
|
||||
}
|
||||
|
||||
private void DisplayStatistics()
|
||||
{
|
||||
if (!_allResults.Any())
|
||||
{
|
||||
Console.WriteLine("\n📊 No simulation data available yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("\n📊 Session Statistics:");
|
||||
Console.WriteLine($" Total Simulations: {_allResults.Count}");
|
||||
Console.WriteLine($" Successful: {_allResults.Count(r => r.Success)}");
|
||||
Console.WriteLine($" Failed: {_allResults.Count(r => !r.Success)}");
|
||||
Console.WriteLine($" Success Rate: {(_allResults.Count(r => r.Success) * 100.0 / _allResults.Count):F1}%");
|
||||
|
||||
var successful = _allResults.Where(r => r.Success).ToList();
|
||||
if (successful.Any())
|
||||
{
|
||||
Console.WriteLine($"\n💰 Order Statistics:");
|
||||
Console.WriteLine($" Total Orders: {successful.Count}");
|
||||
Console.WriteLine($" Total Revenue: ${successful.Sum(r => r.OrderTotal):F2}");
|
||||
Console.WriteLine($" Average Order: ${successful.Average(r => r.OrderTotal):F2}");
|
||||
Console.WriteLine($" Min Order: ${successful.Min(r => r.OrderTotal):F2}");
|
||||
Console.WriteLine($" Max Order: ${successful.Max(r => r.OrderTotal):F2}");
|
||||
|
||||
// Payment distribution
|
||||
var payments = successful
|
||||
.Where(r => !string.IsNullOrEmpty(r.PaymentCurrency))
|
||||
.GroupBy(r => r.PaymentCurrency)
|
||||
.Select(g => new { Currency = g.Key, Count = g.Count() })
|
||||
.OrderByDescending(x => x.Count);
|
||||
|
||||
Console.WriteLine($"\n💳 Payment Methods:");
|
||||
foreach (var p in payments)
|
||||
{
|
||||
Console.WriteLine($" {p.Currency}: {p.Count} ({p.Count * 100.0 / successful.Count:F1}%)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DisplaySimulationResult(SimulationResult result)
|
||||
{
|
||||
Console.WriteLine("\n========================================");
|
||||
Console.WriteLine($"📋 Simulation Result: {result.SessionId}");
|
||||
Console.WriteLine("========================================");
|
||||
|
||||
if (result.Success)
|
||||
{
|
||||
Console.WriteLine("✅ Status: SUCCESS");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"❌ Status: FAILED - {result.ErrorMessage}");
|
||||
}
|
||||
|
||||
Console.WriteLine($"⏱️ Duration: {result.Duration.TotalSeconds:F2}s");
|
||||
|
||||
if (result.Steps.Any())
|
||||
{
|
||||
Console.WriteLine("\n📝 Steps Completed:");
|
||||
foreach (var step in result.Steps)
|
||||
{
|
||||
Console.WriteLine($" {step}");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.Cart != null && result.Cart.Items.Any())
|
||||
{
|
||||
Console.WriteLine($"\n🛒 Shopping Cart ({result.Cart.Items.Count} items):");
|
||||
foreach (var item in result.Cart.Items)
|
||||
{
|
||||
Console.WriteLine($" - {item.Quantity}x {item.ProductName} @ ${item.UnitPrice:F2} = ${item.TotalPrice:F2}");
|
||||
}
|
||||
Console.WriteLine($" Total: ${result.Cart.TotalAmount:F2}");
|
||||
}
|
||||
|
||||
if (result.OrderId.HasValue)
|
||||
{
|
||||
Console.WriteLine($"\n📝 Order Details:");
|
||||
Console.WriteLine($" Order ID: {result.OrderId}");
|
||||
Console.WriteLine($" Total: ${result.OrderTotal:F2}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(result.PaymentCurrency))
|
||||
{
|
||||
Console.WriteLine($"\n💰 Payment Details:");
|
||||
Console.WriteLine($" Currency: {result.PaymentCurrency}");
|
||||
Console.WriteLine($" Amount: {result.PaymentAmount}");
|
||||
}
|
||||
|
||||
Console.WriteLine("\n========================================");
|
||||
}
|
||||
|
||||
private void DisplayBatchSummary(List<SimulationResult> results, int successful, int failed)
|
||||
{
|
||||
Console.WriteLine("\n📊 Batch Summary:");
|
||||
Console.WriteLine($"✅ Successful: {successful}");
|
||||
Console.WriteLine($"❌ Failed: {failed}");
|
||||
Console.WriteLine($"📈 Success Rate: {(successful * 100.0 / results.Count):F1}%");
|
||||
|
||||
if (results.Any(r => r.Success))
|
||||
{
|
||||
var successfulResults = results.Where(r => r.Success).ToList();
|
||||
Console.WriteLine($"\n💰 Order Statistics:");
|
||||
Console.WriteLine($" Average Order: ${successfulResults.Average(r => r.OrderTotal):F2}");
|
||||
Console.WriteLine($" Total Revenue: ${successfulResults.Sum(r => r.OrderTotal):F2}");
|
||||
Console.WriteLine($" Average Duration: {successfulResults.Average(r => r.Duration.TotalSeconds):F1}s");
|
||||
}
|
||||
}
|
||||
|
||||
private void DisplayStressTestResults(List<SimulationResult> results, TimeSpan duration, int concurrent, int total)
|
||||
{
|
||||
var successful = results.Count(r => r.Success);
|
||||
var failed = results.Count(r => !r.Success);
|
||||
|
||||
Console.WriteLine("\n📊 Stress Test Results:");
|
||||
Console.WriteLine($"⏱️ Total Duration: {duration.TotalSeconds:F1}s");
|
||||
Console.WriteLine($"✅ Successful: {successful}");
|
||||
Console.WriteLine($"❌ Failed: {failed}");
|
||||
Console.WriteLine($"📈 Success Rate: {(successful * 100.0 / total):F1}%");
|
||||
Console.WriteLine($"⚡ Throughput: {(total / duration.TotalSeconds):F2} simulations/second");
|
||||
Console.WriteLine($"🔄 Concurrency: {concurrent} simultaneous connections");
|
||||
|
||||
if (failed > 0)
|
||||
{
|
||||
Console.WriteLine("\n❌ Failure Analysis:");
|
||||
var errors = results
|
||||
.Where(r => !r.Success && !string.IsNullOrEmpty(r.ErrorMessage))
|
||||
.GroupBy(r => r.ErrorMessage)
|
||||
.Select(g => new { Error = g.Key, Count = g.Count() })
|
||||
.OrderByDescending(x => x.Count)
|
||||
.Take(5);
|
||||
|
||||
foreach (var error in errors)
|
||||
{
|
||||
Console.WriteLine($" {error.Error}: {error.Count}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -7,4 +7,33 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Telegram.Bot" Version="22.5.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0" />
|
||||
<PackageReference Include="Bogus" Version="35.6.1" />
|
||||
<PackageReference Include="Serilog" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\LittleShop.Client\LittleShop.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Program.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
22
TeleBot/TeleBotClient/appsettings.json
Normal file
22
TeleBot/TeleBotClient/appsettings.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"LittleShop": {
|
||||
"ApiUrl": "https://localhost:5001",
|
||||
"Username": "admin",
|
||||
"Password": "admin"
|
||||
},
|
||||
"Simulator": {
|
||||
"MinItemsPerOrder": 1,
|
||||
"MaxItemsPerOrder": 5,
|
||||
"MinQuantityPerItem": 1,
|
||||
"MaxQuantityPerItem": 3,
|
||||
"DelayBetweenSimulations": 1000,
|
||||
"EnableDetailedLogging": true
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"System": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user