private static void FetchPoolProfit(CancellationToken ct) { try { WriteInfo(" Fetching profit data.."); Dictionary <Pool, Profit> poolProfitData = new Dictionary <Pool, Profit>(); Dictionary <ProfitProvider, List <Pool> > profitProviderFetches = new Dictionary <ProfitProvider, List <Pool> >(); foreach (Algorithm algorithm in Config.Algorithms) { if (algorithm.Enabled) { foreach (Pool algorithmPool in algorithm.Pools.Where(p => p.Enabled)) { if (!profitProviderFetches.ContainsKey(algorithmPool.ProfitProvider)) { profitProviderFetches[algorithmPool.ProfitProvider] = new List <Pool>() { algorithmPool }; } else { profitProviderFetches[algorithmPool.ProfitProvider].Add(algorithmPool); } } } } foreach (var profitProviderFetch in profitProviderFetches) { var profitProvider = PoolProfitProviderFactory.GetPoolProfitProvider(profitProviderFetch.Key); var profits = profitProvider.GetProfits(profitProviderFetch.Value, Config.EnableCaching, AppFolder, ct); foreach (var profit in profits) { poolProfitData[profit.Key] = profit.Value; } } _poolProfitData = poolProfitData; } catch (Exception e) { Log.Debug("Fetching profit data failed: " + e); } }
private static Task ProfitSwitcherTaskAsync(string appFolderPath, DirectoryInfo appRootFolder, Settings settings, List <Coin> coins, List <NicehashAlgorithm> nicehashAlgorithms, CancellationToken token) { return(Task.Run(() => { //Get pool profit data while (!token.IsCancellationRequested) { var statusCts = new CancellationTokenSource(); var watchdogCts = new CancellationTokenSource(); try { ResetConsole(); // Get pool mined coins profitability var timeoutCts = new CancellationTokenSource(60000); var childCts = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutCts.Token); var profitProviders = Helpers.GetPoolProfitProviders(settings, null); foreach (var coin in coins.Where(c => !String.IsNullOrEmpty(c.OverridePoolProfitProviders))) { foreach (var profitProviderString in coin.OverridePoolProfitProviders.Split(",")) { ProfitProvider profitProvider; if (Enum.TryParse(profitProviderString, out profitProvider)) { if (!profitProviders.Contains(profitProvider)) { profitProviders.Add(profitProvider); } } } } var poolProfitsDictionaryUnordered = new Dictionary <ProfitProvider, Dictionary <string, Profit> >(); var profitProviderTasks = new List <Task>(); foreach (var profitProvider in profitProviders) { if (!poolProfitsDictionaryUnordered.ContainsKey(profitProvider)) { profitProviderTasks.Add(Task.Run(() => { IPoolProfitProvider profitProviderClass = PoolProfitProviderFactory.GetPoolProfitProvider(profitProvider); poolProfitsDictionaryUnordered[profitProvider] = profitProviderClass.GetProfits(appRootFolder, settings, coins, childCts.Token); }, childCts.Token)); } } #if DEBUG Stopwatch sw = new Stopwatch(); sw.Start(); #endif Task.WhenAll(profitProviderTasks).Wait(childCts.Token); #if DEBUG sw.Stop(); Console.WriteLine($"Fetching profit data took {(int)sw.Elapsed.TotalSeconds} seconds."); #endif //Reorder because of async var poolProfitsDictionary = new Dictionary <ProfitProvider, Dictionary <string, Profit> >(); foreach (var profitProvider in profitProviders) { if (poolProfitsDictionaryUnordered.ContainsKey(profitProvider)) { poolProfitsDictionary[profitProvider] = poolProfitsDictionaryUnordered[profitProvider]; } } IProfitSwitchingStrategy profitSwitchingStrategy = ProfitSwitchingStrategyFactory.GetProfitSwitchingStrategy(settings.ProfitSwitchingStrategy); MineableReward currentReward = null; // Get best pool mined coin MineableReward bestPoolminedCoin = null; if (!token.IsCancellationRequested) { var result = profitSwitchingStrategy.GetBestPoolminedCoin(coins, _currentMineable, poolProfitsDictionary, settings); bestPoolminedCoin = result?.Result; if (currentReward == null) { currentReward = result?.Current; } if (bestPoolminedCoin?.Mineable != null) { Console.WriteLine("Got best pool mined coin: " + bestPoolminedCoin.Mineable.DisplayName); } else { Console.WriteLine("Couldn't determine best pool mined coin."); } } //Get Nicehash Profit Dictionary <int, Profit> nicehashProfitsDictionary = null; if (!token.IsCancellationRequested) { nicehashProfitsDictionary = NicehashApi.GetProfits(appRootFolder, settings, nicehashAlgorithms, childCts.Token); } //Get best nicehash algorithm MineableReward bestNicehashAlgorithm = null; if (!token.IsCancellationRequested && nicehashProfitsDictionary != null) { var result = profitSwitchingStrategy.GetBestNicehashAlgorithm(nicehashAlgorithms, _currentMineable, nicehashProfitsDictionary, settings); bestNicehashAlgorithm = result?.Result; if (currentReward == null) { currentReward = result?.Current; } if (bestNicehashAlgorithm?.Mineable != null) { Console.WriteLine("Got best nicehash algorithm: " + bestNicehashAlgorithm.Mineable.DisplayName); } else { Console.WriteLine("Couldn't determine best nicehash algorithm."); } } //Sort profit table if (settings.ProfitSorting != SortingMode.None) { var coinProfitComparer = new CoinProfitComparer(settings.ProfitSorting, poolProfitsDictionary); coins.Sort(coinProfitComparer); var nicehashProfitComparer = new NicehashProfitComparer(settings.ProfitSorting, nicehashProfitsDictionary); nicehashAlgorithms.Sort(nicehashProfitComparer); } //Print table if (!token.IsCancellationRequested && nicehashProfitsDictionary != null) { PrintProfitTable(coins, poolProfitsDictionary, nicehashAlgorithms, nicehashProfitsDictionary, settings); } //Mine using best algorithm/coin if (!token.IsCancellationRequested) { Console.WriteLine(); Mineable bestOverallMineable = null; if (_manualSelection && _manualSelectedMineable != null) { bestOverallMineable = _manualSelectedMineable; } else { bestOverallMineable = profitSwitchingStrategy.GetBestMineable(bestPoolminedCoin, bestNicehashAlgorithm, currentReward, settings)?.Mineable; } if (bestOverallMineable != null) { Console.WriteLine($"Determined best mining method: {bestOverallMineable.DisplayName}"); if (_currentMineable == null || _currentMineable.Id != bestOverallMineable.Id) { StartMiner(bestOverallMineable, settings, appFolderPath, appRootFolder); } } else { Log.Information("Couldn't determine best mining method."); } } var statusUpdaterTask = StatusUpdaterTaskAsync(DateTimeOffset.Now.AddSeconds(settings.ProfitCheckInterval), settings, appRootFolder, coins, poolProfitsDictionary, nicehashAlgorithms, nicehashProfitsDictionary, statusCts.Token); if (!token.IsCancellationRequested) { if (settings.ProfitCheckInterval > 0) { Task.Delay(TimeSpan.FromSeconds(settings.ProfitCheckInterval), token).Wait(token); } else { token.WaitHandle.WaitOne(); } } statusCts.Cancel(); } catch (TaskCanceledException) { Log.Information("Cancelled profit task."); statusCts.Cancel(); } catch (AggregateException) { Log.Information("Cancelled profit task 2."); statusCts.Cancel(); } catch (OperationCanceledException) { Log.Information("Cancelled profit task 3."); statusCts.Cancel(); } catch (Exception ex) { Log.Error("Profit switcher task failed: " + ex); statusCts.Cancel(); } } }, token)); }