SMS full reset & Analyzer indicator

This commit is contained in:
HojouFotytu 2024-01-28 02:39:47 +09:00
parent 6aa6928376
commit 1669534044
9 changed files with 181 additions and 18 deletions

View File

@ -59,6 +59,7 @@ namespace Core.Main
private Dictionary<string, int> _singleMarketSettingsCount = new Dictionary<string, int>();
Dictionary<string, List<SingleMarketSetting>> _triggeredSingleMarketSettings = new Dictionary<string, List<SingleMarketSetting>>();
private static volatile object _lockObj = new object();
private Mutex mutex = new Mutex(false, "analyzerStateMutex");
public LogHelper Log
{
@ -122,6 +123,22 @@ namespace Core.Main
_state = value;
}
}
public void WriteStateToFile()
{
try
{
mutex.WaitOne(); // Acquire the mutex
string filePath = "_data/AnalyzerState.";
File.WriteAllText(filePath, this.State.ToString());
}
finally
{
mutex.ReleaseMutex(); // Release the mutex even if exceptions occur
}
}
public int RunCount
{
@ -840,6 +857,7 @@ namespace Core.Main
{
// Change state to "Running"
this.State = Constants.PTMagicBotState_Running;
this.WriteStateToFile();
this.RunCount++;
this.LastRuntime = DateTime.UtcNow;
@ -975,6 +993,7 @@ namespace Core.Main
// Change state to Finished / Stopped
this.State = Constants.PTMagicBotState_Idle;
this.WriteStateToFile();
}
}
}
@ -991,6 +1010,7 @@ namespace Core.Main
{
Log.DoLogWarn("PTMagic raid " + this.RunCount.ToString() + " is taking longer than expected. Consider increasing your IntervalMinues setting, reducing other processes on your PC, or raising PTMagic's priority.");
this.State = Constants.PTMagicBotState_Idle;
this.WriteStateToFile();
Log.DoLogInfo("PTMagic status reset, waiting for the next raid to be good to go again.");
}
}
@ -998,6 +1018,7 @@ namespace Core.Main
{
Log.DoLogWarn("No LastRuntimeSummary.json found after raid " + this.RunCount.ToString() + ", trying to reset PT Magic status...");
this.State = Constants.PTMagicBotState_Idle;
this.WriteStateToFile();
Log.DoLogInfo("PTMagic status reset, waiting for the next raid to be good to go again.");
}
}

View File

@ -26,6 +26,7 @@
<script type="text/javascript">
var errCountIndex = [];
var counterIndex = []; // Add this line
var intervalDashboardTop;
var intervalDashboardBottom;
@ -80,8 +81,11 @@
} else {
errCountIndex["DashboardBottom"] = 0;
// Destroy all d3 svg graph to avoid memory leak
setTimeout(function() {
// Increment the counter
counterIndex["DashboardBottom"] = (counterIndex["DashboardBottom"] || 0) + 1;
// Destroy all d3 svg graph to avoid memory leak every 30 refreshes of Dashboard Bottom
if (counterIndex["DashboardBottom"] >= 30) {
$(".nvtooltip").remove();
$("svg > *").remove();
$("svg").remove();
@ -89,7 +93,9 @@
nv.graphs = [];
nv.logs = {};
nv.tooltip = {};
}, 30 * @Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000); // every 30 refreshes
// Reset the counter
counterIndex["DashboardBottom"] = 0;
}
}
// Reinstate the interval.

View File

@ -29,6 +29,11 @@
}
<td><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)SettingsAnalyzer#SingleMarketSetting_@sms">@sms</a>:&nbsp;@smsCount &emsp; &emsp;</td>
}
@if (Model.PTMagicConfiguration.GeneralSettings.Monitor.IsPasswordProtected) {
<a class="btn btn-danger btn-sm btn-custom btn-block text-uppercase btn-deletefile" style="margin-top: 10px;" data-filename="SingleMarketSettingSummary.json" href="#">Reset ALL Single MarketSettings</a>
} else {
<a class="btn btn-danger btn-custom btn-block text-uppercase" data-toggle="tooltip" data-placement="top" title="This is only accessible when you protect your monitor with a password!"><i class="fa fa-lock text-danger"></i> Delete File</a>
}
}
</tr>
</p>
@ -197,7 +202,7 @@
</button>
</div>
<div class="modal-body">
Do you really want to reset this Single Market Setting during the next run of PT Magic?
Do you really want to reset ALL Single Market Settings for the next Analyzer run?
<p class="m-t-10"><span class="text-warning">Please note:</span> Even if you reset a setting, it may get triggered again on the next run depending on current market conditions.</p>
</div>
<div class="modal-footer">
@ -208,7 +213,66 @@
</div>
</div>
<div class="modal fade" id="modalDeleteFile" tabindex="-1" role="dialog" aria-labelledby="modalDeleteFile" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalDeleteFile">Are you sure?</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
Do you really want to reset ALL Single Market Settings for the next Analyzer run?
<p class="m-t-10"><span class="text-warning">Please note:</span> Even if you reset your settings, they may get triggered again on the next run depending on current market conditions.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-ptmagic text-uppercase waves-effect waves-light btn-resetsetting" data-datatarget="" data-setting="">Yes, do it!</button>
<button type="button" class="btn btn-secondary text-uppercase" data-dismiss="modal">No...</button>
</div>
</div>
</div>
</div>
@section Scripts {
<script type="text/javascript">
$(document).on('click', '.btn-deletefile', function(e) {
e.preventDefault();
var filename = $(this).data("filename");
// Show the modal
$('#modalDeleteFile').modal('show');
// Attach a one-time event handler for the 'Yes, do it!' button in the modal
$('.btn-deletefile').one('click', function() {
var baseUrl = "@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)";
var endpoint = "ManageSMS?handler=DeleteFile";
var url = baseUrl + endpoint;
$.ajax({
url: url,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: { filename: filename },
success: function(result) {
// Update the modal's content
$('#modalDeleteFile .modal-title').text('Success');
$('#modalDeleteFile .modal-body').html(result.message);
},
error: function(xhr, status, error) {
var response = JSON.parse(xhr.responseText);
// Show an alert for error
alert(response.message);
}
});
});
});
</script>
<script type="text/javascript">
$(function () {

View File

@ -3,7 +3,8 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Hosting;
using Core.Main;
using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json;
@ -13,7 +14,12 @@ namespace Monitor.Pages
public class ManageSMSModel : _Internal.BasePageModelSecure
{
public List<SingleMarketSettingSummary> SingleMarketSettingSummaries = new List<SingleMarketSettingSummary>();
private readonly IWebHostEnvironment _hostingEnvironment;
public ManageSMSModel(IWebHostEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
}
public void OnGet()
{
base.Init();
@ -35,6 +41,39 @@ namespace Monitor.Pages
}
}
public IActionResult OnPostDeleteFile(string filename)
{
string webRootParent = Directory.GetParent(_hostingEnvironment.WebRootPath).FullName;
string ptMagicRoot = Directory.GetParent(webRootParent).FullName;
string analyzerStatePath = Path.Combine(ptMagicRoot, "_data", "AnalyzerState");
Console.WriteLine("analyzerStatePath: " + analyzerStatePath);
// Read the AnalyzerState file
if (System.IO.File.Exists(analyzerStatePath))
{
string state = System.IO.File.ReadAllText(analyzerStatePath);
if (state != "0")
{
return new JsonResult(new { success = false, message = "Tha Analyzer is in the middle of a run. Try again in a moment." });
}
}
// If state is "0", proceed to delete the file
try
{
string path = Path.Combine(ptMagicRoot, "_data", filename);
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
return new JsonResult(new { success = true, message = "All SMS settings reset!" });
}
catch (Exception ex)
{
return new JsonResult(new { success = false, message = ex.Message });
}
}
private void BindData()
{
if (System.IO.File.Exists(PTMagicBasePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar + "SingleMarketSettingSummary.json"))

View File

@ -202,28 +202,28 @@
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Market Trend Chart Interval (Minutes) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The time interval for the market trend graph (Dashboard and Sales Analyzer) between data points. Very small intervals on large timeframe graphs can significantly impact performance."></i></label>
<label class="col-md-4 col-form-label">Trend Chart Interval (Minutes) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The time interval for the market trend graph (Dashboard and Sales Analyzer) between data points. Very small intervals on large timeframe graphs can significantly impact performance."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Monitor_GraphIntervalMinutes" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes.ToString(new System.Globalization.CultureInfo("en-US"))">
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Market Trend Chart Max Timeframe (Hours) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the total timeframe for the market trends graph (Dashboard and Sales Analyzer) in hours. Large timeframe graphs can significantly impact performance."></i></label>
<label class="col-md-4 col-form-label">Trend Chart Timeframe (Hours) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the total timeframe for the market trends graph (Dashboard and Sales Analyzer) in hours. Large timeframe graphs can significantly impact performance."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Monitor_GraphMaxTimeframeHours" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours.ToString(new System.Globalization.CultureInfo("en-US"))">
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Daily Profit Graph Max Timeframe (Days) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the total timeframe for the daily profits graph on the dashboard in days. Large timeframes can significantly impact performance."></i></label>
<label class="col-md-4 col-form-label">Daily Profit Chart Timeframe (Days) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the total timeframe for the daily profits graph on the dashboard in days. Large timeframes can significantly impact performance."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Monitor_ProfitsMaxTimeframeDays" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.ProfitsMaxTimeframeDays.ToString(new System.Globalization.CultureInfo("en-US"))">
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Dashboard Bottom Refresh (Seconds) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval in seconds, of the charts and graphs on then main page."></i></label>
<label class="col-md-4 col-form-label">Dashboard Charts Refresh (Seconds) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval in seconds, of the charts and graphs on then main page."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Monitor_RefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))">
</div>

View File

@ -192,7 +192,7 @@
}
// Reinstate the interval.
interval = setInterval(function () { loadWidgets(); }, 5000);
interval = setInterval(function () { loadWidgets(); }, 3000);
});
};

View File

@ -224,7 +224,7 @@
double TargetGain = leverageValue * dcaLogEntry.TargetGainValue.Value;
<td>@TargetGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))%
<br>
<div class="text-autocolor">@profitPercentage.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</div>
<div class="text-autocolor" style="font-size: 1.2em; white-space: nowrap;">@profitPercentage.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</div>
</td>
}
else

View File

@ -31,6 +31,9 @@
ptMagicHealthTooltip = "PT Magic seems to have problems, check the logs! Time elapsed since last run: " + Math.Round(elapsedSecondsSinceRuntime / 60, 1) + " mins.";
healthIconColor = "text-danger";
}
if (Model.IsAnalyzerRunning()) {
ptMagicHealthIcon = "fa-cog fa-spin";
}
}
<div class="card-box card-box-mini card-box-ptmagic-outlined @globalIconColor">

View File

@ -1,16 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Core.Main;
using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData;
using Core.MarketAnalyzer;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using System.Threading;
namespace Monitor.Pages {
public class TickerWidgetsModel : _Internal.BasePageModelSecureAJAX {
public ProfitTrailerData PTData = null;
public List<string> MarketsWithSingleSettings = new List<string>();
private readonly IWebHostEnvironment _hostingEnvironment;
private Mutex mutex = new Mutex(false, "analyzerStateMutex");
public TickerWidgetsModel(IWebHostEnvironment hostingEnvironment) // Add this constructor
{
_hostingEnvironment = hostingEnvironment;
}
public void OnGet() {
// Initialize Config
@ -18,6 +25,29 @@ namespace Monitor.Pages {
BindData();
}
public bool IsAnalyzerRunning()
{
// Acquire the mutex before accessing the file
try
{
mutex.WaitOne(0);
string webRootParent = Directory.GetParent(_hostingEnvironment.WebRootPath).FullName;
string ptMagicRoot = Directory.GetParent(webRootParent).FullName;
string analyzerStatePath = Path.Combine(ptMagicRoot, "_data", "AnalyzerState");
if (System.IO.File.Exists(analyzerStatePath))
{
string state = System.IO.File.ReadAllText(analyzerStatePath);
return state == "1";
}
return false;
}
finally
{
mutex.ReleaseMutex(); // Always release the mutex
}
}
private void BindData() {
PTData = this.PtDataObject;