diff --git a/WebServer/Controllers/Automation.cs b/WebServer/Controllers/Automation.cs index 85a18f8e..f19f5491 100644 --- a/WebServer/Controllers/Automation.cs +++ b/WebServer/Controllers/Automation.cs @@ -1,22 +1,26 @@ using Controllers.DataBase; +using Controllers.Payment; +using Controllers.PythonInterop; using Entities; using Newtonsoft.Json; -namespace Controllers.PythonInterop { +namespace Controllers.Automation { - public class Automation { + public class AutomationController { AIModule _aiModule; DbDriver _dbDriver; - public Automation(AIModule aiModule, DbDriver dbDriver) { + IPayment _paymentProcessor; + public AutomationController(AIModule aiModule, DbDriver dbDriver, IPayment PaymentProcessor) { _aiModule = aiModule; _dbDriver = dbDriver; + _paymentProcessor = PaymentProcessor; } public void GlobalPredictAI() { // Start this process on a background thread so its non-blocking - Task thread = new Task(async () => { + Task thread = new Task(() => { // Load the userlist List? UserList = JsonConvert.DeserializeObject>(_dbDriver.Get("Users")); @@ -54,6 +58,7 @@ namespace Controllers.PythonInterop { await Task.WhenAll(threadpool); // Process Stocks -> Buy Sell Hold / Based on the global data from earlier + sellStock(username); // Save the new scores to the database for reference from the UI _dbDriver.Set( dbPrefix + "watched", JsonConvert.SerializeObject( VerifiedTrackedStocks ) ); @@ -64,82 +69,89 @@ namespace Controllers.PythonInterop { } public void GlobalTrainAI(){ - Task thread = new Task(async () => { + Task thread = new Task(() => { + _aiModule.PullAI(); _aiModule.TrainAI(); }); thread.Start(); } - void sellStock(PurchasedStock stock){ - string dbPrefix = $"[{userName.ToLower()}]:"; - if (Session != null){ + void sellStock(string username){ + string dbPrefix = $"[{username.ToLower()}]:"; - // Get sell price - float sellPrice = stock.Quantity * aiModule.GetCurrentPrice( stock.Symbol ); + // Get all stock history + List? PurchaseHistory = JsonConvert.DeserializeObject>( _dbDriver.Get( dbPrefix + "history" ) ); + List VerifiedPurchaseHistory = PurchaseHistory != null ? PurchaseHistory : new List(); - // Try to sell the stock - (bool, string) result = PaymentProcessor.TrySell(PaymentKey, sellPrice); - if (!result.Item1){ - resultError = result.Item2; - return; + // Find the stocks that need to be sold + foreach(PurchasedStock cur in VerifiedPurchaseHistory) { + if (cur.Sold == false) { + + // Get sell price + float sellPrice = cur.Quantity * _aiModule.GetCurrentPrice( cur.Symbol ); + + // Try create payment session + (bool, string) createResult = _paymentProcessor.CreatePayment(username); + if (!createResult.Item1) { + Console.WriteLine("Create Payment Failure: " + createResult.Item2); + return; + } + + // Try to sell the stock + (bool, string) paymentResult = _paymentProcessor.TrySell(createResult.Item2, sellPrice); + if (!paymentResult.Item1){ + Console.WriteLine("Process Payment Failure: " + paymentResult.Item2); + return; + } } - - // Remove Stock - Session.TradeHistory.Remove(stock); - dbDriver.Set( dbPrefix + "Stocks", Newtonsoft.Json.JsonConvert.SerializeObject(Session.TradeHistory) ); - - // Reload the users money - bool moneyLoaded = float.TryParse(dbDriver.Get( dbPrefix + "money" ), out float moneyResult); - Session.Money = moneyLoaded ? moneyResult : 1000; - - // Reset the Impodent Key - result = PaymentProcessor.CreatePayment(Session.UserName); - if (!result.Item1){ - resultError = "[New payment session failed] : " + result.Item2; - return; - } - PaymentKey = result.Item2; } + + // Save the stock history + _dbDriver.Set( dbPrefix + "Stocks", JsonConvert.SerializeObject(VerifiedPurchaseHistory) ); } - void buyStock(string StockSymbol){ - if (Session != null){ - string dbPrefix = $"[{userName.ToLower()}]:"; - - // Try Parse the quantitiy input - // Get the max quantity that I can Afford - float QuantityResult = 0; + void buyStock(string username, string stockSymbol){ + string dbPrefix = $"[{username.ToLower()}]:"; + + // Get all stock history + List? PurchaseHistory = JsonConvert.DeserializeObject>( _dbDriver.Get( dbPrefix + "history" ) ); + List VerifiedPurchaseHistory = PurchaseHistory != null ? PurchaseHistory : new List(); - // Get Stock Price - float stockPrice = aiModule.GetCurrentPrice( StockSymbol ); - - // Try Pay for the stock - (bool, string) result = PaymentProcessor.TryPayment(PaymentKey, QuantityResult * stockPrice); - if (!result.Item1){ - resultError = result.Item2; - return; - } - - // Add the stock - Session.TradeHistory.Add( new PurchasedStock(){ - Symbol = StockSymbol.ToUpper(), - PurchasePrice = stockPrice, - Quantity = QuantityResult, - } ); - dbDriver.Set( dbPrefix + "Stocks", Newtonsoft.Json.JsonConvert.SerializeObject(Session.TradeHistory) ); - - // Reload the users money - bool moneyLoaded = float.TryParse(dbDriver.Get( dbPrefix + "money" ), out float moneyResult); - Session.Money = moneyLoaded ? moneyResult : 1000; - - // Reset the Impodent Key - result = PaymentProcessor.CreatePayment(Session.UserName); - if (!result.Item1){ - resultError = "[New payment session failed] : " + result.Item2; - return; - } - PaymentKey = result.Item2; + // Get users money + string MoneyStr = _dbDriver.Get( dbPrefix + "money"); + bool Money = float.TryParse( MoneyStr, out float VerifiedMoney ); + if (!Money) { + Console.WriteLine( "Unable to load users money" ); + VerifiedMoney = 0; } + + // Get Stock Price + float stockPrice = _aiModule.GetCurrentPrice( stockSymbol ); + + // Get max stocks user can purchase [ int cast truncates the decimal ] + int MaxQty = (int)( VerifiedMoney / stockPrice ); + + // Try create payment session + (bool, string) createResult = _paymentProcessor.CreatePayment(username); + if (!createResult.Item1) { + Console.WriteLine("Create Payment Failure: " + createResult.Item2); + return; + } + + // Try Pay for the stock + (bool, string) result = _paymentProcessor.TryPayment(createResult.Item2, stockPrice * MaxQty); + if (!result.Item1){ + Console.WriteLine("Process Payment Failure: " + result.Item2); + return; + } + + // Add the stock + VerifiedPurchaseHistory.Add( new PurchasedStock(){ + Symbol = stockSymbol.ToUpper(), + PurchasePrice = stockPrice, + Quantity = MaxQty, + } ); + _dbDriver.Set( dbPrefix + "Stocks", JsonConvert.SerializeObject(VerifiedPurchaseHistory) ); } } } \ No newline at end of file diff --git a/WebServer/Controllers/Payments/IPayments.cs b/WebServer/Controllers/Payments/IPayments.cs index 974728eb..8fca7adf 100644 --- a/WebServer/Controllers/Payments/IPayments.cs +++ b/WebServer/Controllers/Payments/IPayments.cs @@ -8,7 +8,7 @@ namespace Controllers.Payment { // [ Success, ErrorMessage ] public (bool, string) TryPayment(string ImpodentKey, float Price); - // + // [ Success, ErrorMessage ] public (bool, string) TrySell(string ImpodentKey, float Price); } diff --git a/WebServer/Controllers/PythonInterop.cs b/WebServer/Controllers/PythonInterop.cs index 4b66f01a..fed83587 100644 --- a/WebServer/Controllers/PythonInterop.cs +++ b/WebServer/Controllers/PythonInterop.cs @@ -7,8 +7,8 @@ namespace Controllers.PythonInterop { string _PyPath = ""; string _ExecPath = ""; - public AIModule() { - _PyPath = "/usr/bin/python3.11"; + public AIModule(string pypath = "/usr/bin/python3.11") { + _PyPath = pypath; _ExecPath = $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AIPython")}"; } diff --git a/WebServer/Entities/PurchasedStock.cs b/WebServer/Entities/PurchasedStock.cs index 1cfd5046..bf1f6f3e 100644 --- a/WebServer/Entities/PurchasedStock.cs +++ b/WebServer/Entities/PurchasedStock.cs @@ -5,6 +5,7 @@ namespace Entities { public float Quantity { get; set; } = 0; public float PurchasePrice { get; set; } = 0; public float SellPrice { get; set; } = 0; + public bool Sold = false; } } \ No newline at end of file