add an option for Ping tests (disabled by default) and improve the readability of the code
This commit is contained in:
@@ -19,84 +19,87 @@ namespace Shadowsocks.Controller
|
||||
public sealed class AvailabilityStatistics : IDisposable
|
||||
{
|
||||
public const string DateTimePattern = "yyyy-MM-dd HH:mm:ss";
|
||||
public static readonly DateTime UnknownDateTime;
|
||||
private const string StatisticsFilesName = "shadowsocks.availability.json";
|
||||
private const int TimeoutMilliseconds = 500;
|
||||
|
||||
public static readonly DateTime UnknownDateTime = new DateTime(1970, 1, 1);
|
||||
|
||||
public static string AvailabilityStatisticsFile;
|
||||
private readonly TimeSpan _delayBeforeStart = TimeSpan.FromSeconds(1);
|
||||
private readonly TimeSpan _monitorInterval = TimeSpan.FromSeconds(1);
|
||||
private readonly TimeSpan _retryInterval = TimeSpan.FromMinutes(2); //retry 2 minutes after failed
|
||||
private readonly TimeSpan _writingInterval = TimeSpan.FromMinutes(1);
|
||||
private StatisticsStrategyConfiguration _config;
|
||||
private ShadowsocksController _controller;
|
||||
private Server _currentServer;
|
||||
//speed in KiB/s
|
||||
private List<int> _inboundSpeedRecords;
|
||||
private long _lastInboundCounter;
|
||||
private long _lastOutboundCounter;
|
||||
private List<int> _latencyRecords;
|
||||
private List<int> _outboundSpeedRecords;
|
||||
private Timer _recorder;
|
||||
private List<Server> _servers;
|
||||
private Timer _speedMonior;
|
||||
private Timer _writer;
|
||||
|
||||
//static constructor to initialize every public static fields before refereced
|
||||
static AvailabilityStatistics()
|
||||
{
|
||||
AvailabilityStatisticsFile = Utils.GetTempPath(StatisticsFilesName);
|
||||
UnknownDateTime = new DateTime(1970, 1, 1);
|
||||
}
|
||||
|
||||
//arguments for ICMP tests
|
||||
private int Repeat => Config.RepeatTimesNum;
|
||||
private const int TimeoutMilliseconds = 500;
|
||||
|
||||
//records cache for current server in {_monitorInterval} minutes
|
||||
private List<int> _latencyRecords;
|
||||
//speed in KiB/s
|
||||
private long _lastInboundCounter;
|
||||
private List<int> _inboundSpeedRecords;
|
||||
private long _lastOutboundCounter;
|
||||
private List<int> _outboundSpeedRecords;
|
||||
|
||||
//tasks
|
||||
private readonly TimeSpan _delayBeforeStart = TimeSpan.FromSeconds(1);
|
||||
private readonly TimeSpan _retryInterval = TimeSpan.FromMinutes(2);
|
||||
private Timer _recorder; //analyze and save cached records to RawStatistics and filter records
|
||||
private TimeSpan RecordingInterval => TimeSpan.FromMinutes(Config.DataCollectionMinutes);
|
||||
private Timer _speedMonior;
|
||||
private readonly TimeSpan _monitorInterval = TimeSpan.FromSeconds(1);
|
||||
private Timer _writer; //write RawStatistics to file
|
||||
private readonly TimeSpan _writingInterval = TimeSpan.FromMinutes(1);
|
||||
|
||||
private ShadowsocksController _controller;
|
||||
private StatisticsStrategyConfiguration Config => _controller.StatisticsConfiguration;
|
||||
private Server CurrentServer => _controller.GetCurrentServer();
|
||||
|
||||
// Static Singleton Initialization
|
||||
public static AvailabilityStatistics Instance { get; } = new AvailabilityStatistics();
|
||||
public Statistics RawStatistics { get; private set; }
|
||||
public Statistics FilteredStatistics { get; private set; }
|
||||
|
||||
private AvailabilityStatistics()
|
||||
{
|
||||
RawStatistics = new Statistics();
|
||||
}
|
||||
|
||||
// Static Singleton Initialization
|
||||
public static AvailabilityStatistics Instance { get; } = new AvailabilityStatistics();
|
||||
public Statistics RawStatistics { get; private set; }
|
||||
public Statistics FilteredStatistics { get; private set; }
|
||||
private int Repeat => _config.RepeatTimesNum;
|
||||
private TimeSpan RecordingInterval => TimeSpan.FromMinutes(_config.DataCollectionMinutes);
|
||||
|
||||
public bool Set(StatisticsStrategyConfiguration config)
|
||||
internal void UpdateConfiguration(ShadowsocksController controller)
|
||||
{
|
||||
_config = config;
|
||||
_controller = controller;
|
||||
Reset();
|
||||
try
|
||||
{
|
||||
if (config.StatisticsEnabled)
|
||||
if (Config.StatisticsEnabled)
|
||||
{
|
||||
if (_recorder?.Change(_delayBeforeStart, RecordingInterval) == null)
|
||||
{
|
||||
_recorder = new Timer(Run, null, _delayBeforeStart, RecordingInterval);
|
||||
}
|
||||
StartTimerWithoutState(ref _recorder, Run, RecordingInterval);
|
||||
LoadRawStatistics();
|
||||
if (_speedMonior?.Change(_delayBeforeStart, _monitorInterval) == null)
|
||||
{
|
||||
_speedMonior = new Timer(UpdateSpeed, null, _delayBeforeStart, _monitorInterval);
|
||||
}
|
||||
if (_writer?.Change(_delayBeforeStart, RecordingInterval) == null)
|
||||
{
|
||||
_writer = new Timer(Save, null, _delayBeforeStart, RecordingInterval);
|
||||
}
|
||||
StartTimerWithoutState(ref _speedMonior, UpdateSpeed, _monitorInterval);
|
||||
StartTimerWithoutState(ref _writer, Save, _writingInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
_recorder?.Dispose();
|
||||
_speedMonior?.Dispose();
|
||||
_writer?.Dispose();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.LogUsefulException(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSpeed(object state)
|
||||
private void StartTimerWithoutState(ref Timer timer, TimerCallback callback, TimeSpan interval)
|
||||
{
|
||||
if (timer?.Change(_delayBeforeStart, interval) == null)
|
||||
{
|
||||
timer = new Timer(callback, null, _delayBeforeStart, interval);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSpeed(object _)
|
||||
{
|
||||
var bytes = _controller.inboundCounter - _lastInboundCounter;
|
||||
_lastInboundCounter = _controller.inboundCounter;
|
||||
@@ -109,7 +112,7 @@ namespace Shadowsocks.Controller
|
||||
_outboundSpeedRecords.Add(outboundSpeed);
|
||||
|
||||
Logging.Debug(
|
||||
$"{_currentServer.FriendlyName()}: current/max inbound {inboundSpeed}/{_inboundSpeedRecords.Max()} KiB/s, current/max outbound {outboundSpeed}/{_outboundSpeedRecords.Max()} KiB/s");
|
||||
$"{CurrentServer.FriendlyName()}: current/max inbound {inboundSpeed}/{_inboundSpeedRecords.Max()} KiB/s, current/max outbound {outboundSpeed}/{_outboundSpeedRecords.Max()} KiB/s");
|
||||
}
|
||||
|
||||
private async Task<ICMPResult> ICMPTest(Server server)
|
||||
@@ -168,40 +171,48 @@ namespace Shadowsocks.Controller
|
||||
|
||||
private void Run(object _)
|
||||
{
|
||||
AppendRecord();
|
||||
UpdateRecords();
|
||||
Reset();
|
||||
FilterRawStatistics();
|
||||
}
|
||||
|
||||
private async void AppendRecord()
|
||||
private async void UpdateRecords()
|
||||
{
|
||||
//todo: option for icmp test
|
||||
var icmpResults = TaskEx.WhenAll(_servers.Select(ICMPTest));
|
||||
var currentServerRecord = new StatisticsRecord(CurrentServer.Identifier(), _inboundSpeedRecords, _outboundSpeedRecords, _latencyRecords);
|
||||
|
||||
var currentServerRecord = new StatisticsRecord(_currentServer.Identifier(),
|
||||
_inboundSpeedRecords, _outboundSpeedRecords, _latencyRecords);
|
||||
if (!Config.Ping)
|
||||
{
|
||||
AppendRecord(CurrentServer, currentServerRecord);
|
||||
return;
|
||||
}
|
||||
|
||||
var icmpResults = TaskEx.WhenAll(_controller.GetCurrentConfiguration().configs.Select(ICMPTest));
|
||||
|
||||
foreach (var result in (await icmpResults).Where(result => result != null))
|
||||
{
|
||||
List<StatisticsRecord> records;
|
||||
if (!RawStatistics.TryGetValue(result.Server.Identifier(), out records))
|
||||
{
|
||||
records = new List<StatisticsRecord>();
|
||||
}
|
||||
|
||||
if (result.Server.Equals(_currentServer))
|
||||
if (result.Server.Equals(CurrentServer))
|
||||
{
|
||||
currentServerRecord.setResponse(result.RoundtripTime);
|
||||
records.Add(currentServerRecord);
|
||||
AppendRecord(CurrentServer, currentServerRecord);
|
||||
}
|
||||
else
|
||||
{
|
||||
records.Add(new StatisticsRecord(result.Server.Identifier(), result.RoundtripTime));
|
||||
AppendRecord(result.Server, new StatisticsRecord(result.Server.Identifier(), result.RoundtripTime));
|
||||
}
|
||||
RawStatistics[result.Server.Identifier()] = records;
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendRecord(Server server, StatisticsRecord record)
|
||||
{
|
||||
List<StatisticsRecord> records;
|
||||
if (!RawStatistics.TryGetValue(server.Identifier(), out records))
|
||||
{
|
||||
records = new List<StatisticsRecord>();
|
||||
}
|
||||
records.Add(record);
|
||||
RawStatistics[server.Identifier()] = records;
|
||||
}
|
||||
|
||||
private void Save(object _)
|
||||
{
|
||||
try
|
||||
@@ -216,46 +227,10 @@ namespace Shadowsocks.Controller
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private static void Append(DataList dataList, IEnumerable<DataUnit> extra)
|
||||
{
|
||||
var data = dataList.Concat(extra);
|
||||
var dataLine = string.Join(Delimiter, data.Select(kv => kv.Value).ToArray());
|
||||
string[] lines;
|
||||
if (!File.Exists(AvailabilityStatisticsFile))
|
||||
{
|
||||
var headerLine = string.Join(Delimiter, data.Select(kv => kv.Key).ToArray());
|
||||
lines = new[] { headerLine, dataLine };
|
||||
}
|
||||
else
|
||||
{
|
||||
lines = new[] { dataLine };
|
||||
}
|
||||
try
|
||||
{
|
||||
File.AppendAllLines(AvailabilityStatisticsFile, lines);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Logging.LogUsefulException(e);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
internal void UpdateConfiguration(ShadowsocksController controller)
|
||||
{
|
||||
_controller = controller;
|
||||
_currentServer = _controller.GetCurrentServer();
|
||||
Reset();
|
||||
Set(controller.StatisticsConfiguration);
|
||||
_servers = _controller.GetCurrentConfiguration().configs;
|
||||
}
|
||||
|
||||
private bool IsValidRecord(StatisticsRecord record)
|
||||
{
|
||||
if (_config.ByHourOfDay)
|
||||
if (Config.ByHourOfDay)
|
||||
{
|
||||
var currentHour = DateTime.Now.Hour;
|
||||
if (record.Timestamp == UnknownDateTime) return false;
|
||||
if (!record.Timestamp.Hour.Equals(DateTime.Now.Hour)) return false;
|
||||
}
|
||||
@@ -288,7 +263,7 @@ namespace Shadowsocks.Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var fs = File.Create(path))
|
||||
using (File.Create(path))
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
@@ -313,14 +288,6 @@ namespace Shadowsocks.Controller
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime ParseExactOrUnknown(string str)
|
||||
{
|
||||
DateTime dateTime;
|
||||
return !DateTime.TryParseExact(str, DateTimePattern, null, DateTimeStyles.None, out dateTime)
|
||||
? UnknownDateTime
|
||||
: dateTime;
|
||||
}
|
||||
|
||||
public void UpdateLatency(int latency)
|
||||
{
|
||||
_latencyRecords.Add(latency);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Threading;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
@@ -27,7 +26,7 @@ namespace Shadowsocks.Controller.Strategy
|
||||
{
|
||||
_controller = controller;
|
||||
var servers = controller.GetCurrentConfiguration().configs;
|
||||
var randomIndex = new Random().Next() % servers.Count();
|
||||
var randomIndex = new Random().Next() % servers.Count;
|
||||
_currentServer = servers[randomIndex]; //choose a server randomly at first
|
||||
_timer = new Timer(ReloadStatisticsAndChooseAServer);
|
||||
}
|
||||
@@ -117,14 +116,10 @@ namespace Shadowsocks.Controller.Strategy
|
||||
|
||||
public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint)
|
||||
{
|
||||
var oldServer = _currentServer;
|
||||
if (oldServer == null)
|
||||
if (_currentServer == null)
|
||||
{
|
||||
ChooseNewServer(_controller.GetCurrentConfiguration().configs);
|
||||
}
|
||||
if (oldServer != _currentServer)
|
||||
{
|
||||
}
|
||||
return _currentServer; //current server cached for CachedInterval
|
||||
}
|
||||
|
||||
@@ -141,17 +136,14 @@ namespace Shadowsocks.Controller.Strategy
|
||||
|
||||
public void UpdateLastRead(Server server)
|
||||
{
|
||||
//TODO: combine this part of data with ICMP statics
|
||||
}
|
||||
|
||||
public void UpdateLastWrite(Server server)
|
||||
{
|
||||
//TODO: combine this part of data with ICMP statics
|
||||
}
|
||||
|
||||
public void UpdateLatency(Server server, TimeSpan latency)
|
||||
{
|
||||
//TODO: combine this part of data with ICMP statics
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -13,13 +13,13 @@ namespace Shadowsocks.Model
|
||||
[Serializable]
|
||||
public class StatisticsStrategyConfiguration
|
||||
{
|
||||
public static readonly string ID = "com.shadowsocks.strategy.statistics";
|
||||
private bool _statisticsEnabled = true;
|
||||
private bool _byIsp = false;
|
||||
private bool _byHourOfDay = false;
|
||||
private int _choiceKeptMinutes = 10;
|
||||
private int _dataCollectionMinutes = 10;
|
||||
private int _repeatTimesNum = 4;
|
||||
public static readonly string ID = "com.shadowsocks.strategy.statistics";
|
||||
public bool StatisticsEnabled { get; } = true;
|
||||
public bool ByHourOfDay { get; } = true;
|
||||
public bool Ping { get; set; }
|
||||
public int ChoiceKeptMinutes { get; } = 10;
|
||||
public int DataCollectionMinutes { get; } = 10;
|
||||
public int RepeatTimesNum { get; } = 4;
|
||||
|
||||
private const string ConfigFile = "statistics-config.json";
|
||||
|
||||
@@ -64,41 +64,5 @@ namespace Shadowsocks.Model
|
||||
var properties = typeof(StatisticsRecord).GetFields(BindingFlags.Instance | BindingFlags.Public);
|
||||
Calculations = properties.ToDictionary(p => p.Name, _ => (float)0);
|
||||
}
|
||||
|
||||
public bool StatisticsEnabled
|
||||
{
|
||||
get { return _statisticsEnabled; }
|
||||
set { _statisticsEnabled = value; }
|
||||
}
|
||||
|
||||
public bool ByIsp
|
||||
{
|
||||
get { return _byIsp; }
|
||||
set { _byIsp = value; }
|
||||
}
|
||||
|
||||
public bool ByHourOfDay
|
||||
{
|
||||
get { return _byHourOfDay; }
|
||||
set { _byHourOfDay = value; }
|
||||
}
|
||||
|
||||
public int ChoiceKeptMinutes
|
||||
{
|
||||
get { return _choiceKeptMinutes; }
|
||||
set { _choiceKeptMinutes = value; }
|
||||
}
|
||||
|
||||
public int DataCollectionMinutes
|
||||
{
|
||||
get { return _dataCollectionMinutes; }
|
||||
set { _dataCollectionMinutes = value; }
|
||||
}
|
||||
|
||||
public int RepeatTimesNum
|
||||
{
|
||||
get { return _repeatTimesNum; }
|
||||
set { _repeatTimesNum = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,9 @@
|
||||
System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
|
||||
System.Windows.Forms.DataVisualization.Charting.Series series2 = new System.Windows.Forms.DataVisualization.Charting.Series();
|
||||
this.StatisticsChart = new System.Windows.Forms.DataVisualization.Charting.Chart();
|
||||
this.byISPCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.PingCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.chartModeSelector = new System.Windows.Forms.GroupBox();
|
||||
this.allMode = new System.Windows.Forms.RadioButton();
|
||||
this.dayMode = new System.Windows.Forms.RadioButton();
|
||||
@@ -111,57 +110,48 @@
|
||||
series2.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime;
|
||||
this.StatisticsChart.Series.Add(series1);
|
||||
this.StatisticsChart.Series.Add(series2);
|
||||
this.StatisticsChart.Size = new System.Drawing.Size(1077, 303);
|
||||
this.StatisticsChart.Size = new System.Drawing.Size(1089, 303);
|
||||
this.StatisticsChart.TabIndex = 2;
|
||||
//
|
||||
// byISPCheckBox
|
||||
// PingCheckBox
|
||||
//
|
||||
this.byISPCheckBox.AutoSize = true;
|
||||
this.byISPCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.bindingConfiguration, "ByIsp", true));
|
||||
this.byISPCheckBox.Location = new System.Drawing.Point(13, 54);
|
||||
this.byISPCheckBox.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
this.byISPCheckBox.Name = "byISPCheckBox";
|
||||
this.byISPCheckBox.Size = new System.Drawing.Size(220, 31);
|
||||
this.byISPCheckBox.TabIndex = 5;
|
||||
this.byISPCheckBox.Text = "By ISP/geolocation";
|
||||
this.byISPCheckBox.UseVisualStyleBackColor = true;
|
||||
this.PingCheckBox.AutoSize = true;
|
||||
this.PingCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.bindingConfiguration, "Ping", true));
|
||||
this.PingCheckBox.Location = new System.Drawing.Point(13, 54);
|
||||
this.PingCheckBox.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
this.PingCheckBox.Name = "PingCheckBox";
|
||||
this.PingCheckBox.Size = new System.Drawing.Size(107, 27);
|
||||
this.PingCheckBox.TabIndex = 5;
|
||||
this.PingCheckBox.Text = "Ping Test";
|
||||
this.PingCheckBox.UseVisualStyleBackColor = true;
|
||||
this.PingCheckBox.CheckedChanged += new System.EventHandler(this.PingCheckBox_CheckedChanged);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(8, 136);
|
||||
this.label2.Location = new System.Drawing.Point(9, 267);
|
||||
this.label2.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(167, 27);
|
||||
this.label2.Size = new System.Drawing.Size(144, 23);
|
||||
this.label2.TabIndex = 8;
|
||||
this.label2.Text = "Keep choice for ";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(285, 136);
|
||||
this.label3.Location = new System.Drawing.Point(286, 267);
|
||||
this.label3.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(87, 27);
|
||||
this.label3.Size = new System.Drawing.Size(75, 23);
|
||||
this.label3.TabIndex = 9;
|
||||
this.label3.Text = "minutes";
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(8, 218);
|
||||
this.label4.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(54, 27);
|
||||
this.label4.TabIndex = 10;
|
||||
this.label4.Text = "Ping";
|
||||
//
|
||||
// chartModeSelector
|
||||
//
|
||||
this.chartModeSelector.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.chartModeSelector.Controls.Add(this.allMode);
|
||||
this.chartModeSelector.Controls.Add(this.dayMode);
|
||||
this.chartModeSelector.Location = new System.Drawing.Point(801, 104);
|
||||
this.chartModeSelector.Location = new System.Drawing.Point(813, 98);
|
||||
this.chartModeSelector.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
this.chartModeSelector.Name = "chartModeSelector";
|
||||
this.chartModeSelector.Padding = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
@@ -178,7 +168,7 @@
|
||||
this.allMode.Location = new System.Drawing.Point(11, 61);
|
||||
this.allMode.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
this.allMode.Name = "allMode";
|
||||
this.allMode.Size = new System.Drawing.Size(58, 31);
|
||||
this.allMode.Size = new System.Drawing.Size(50, 27);
|
||||
this.allMode.TabIndex = 1;
|
||||
this.allMode.TabStop = true;
|
||||
this.allMode.Text = "all";
|
||||
@@ -191,7 +181,7 @@
|
||||
this.dayMode.Location = new System.Drawing.Point(11, 29);
|
||||
this.dayMode.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
this.dayMode.Name = "dayMode";
|
||||
this.dayMode.Size = new System.Drawing.Size(73, 31);
|
||||
this.dayMode.Size = new System.Drawing.Size(61, 27);
|
||||
this.dayMode.TabIndex = 0;
|
||||
this.dayMode.Text = "24h";
|
||||
this.dayMode.UseVisualStyleBackColor = true;
|
||||
@@ -217,7 +207,7 @@
|
||||
this.splitContainer1.Panel2.Controls.Add(this.OKButton);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.chartModeSelector);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.StatisticsChart);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(1077, 614);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(1089, 614);
|
||||
this.splitContainer1.SplitterDistance = 301;
|
||||
this.splitContainer1.SplitterWidth = 10;
|
||||
this.splitContainer1.TabIndex = 12;
|
||||
@@ -242,14 +232,13 @@
|
||||
this.splitContainer2.Panel1.Controls.Add(this.repeatTimesNum);
|
||||
this.splitContainer2.Panel1.Controls.Add(this.label6);
|
||||
this.splitContainer2.Panel1.Controls.Add(this.label2);
|
||||
this.splitContainer2.Panel1.Controls.Add(this.label4);
|
||||
this.splitContainer2.Panel1.Controls.Add(this.byISPCheckBox);
|
||||
this.splitContainer2.Panel1.Controls.Add(this.PingCheckBox);
|
||||
this.splitContainer2.Panel1.Controls.Add(this.label3);
|
||||
//
|
||||
// splitContainer2.Panel2
|
||||
//
|
||||
this.splitContainer2.Panel2.Controls.Add(this.splitContainer3);
|
||||
this.splitContainer2.Size = new System.Drawing.Size(1077, 301);
|
||||
this.splitContainer2.Size = new System.Drawing.Size(1089, 301);
|
||||
this.splitContainer2.SplitterDistance = 384;
|
||||
this.splitContainer2.SplitterWidth = 5;
|
||||
this.splitContainer2.TabIndex = 7;
|
||||
@@ -257,10 +246,10 @@
|
||||
// label9
|
||||
//
|
||||
this.label9.AutoSize = true;
|
||||
this.label9.Location = new System.Drawing.Point(8, 175);
|
||||
this.label9.Location = new System.Drawing.Point(9, 164);
|
||||
this.label9.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
|
||||
this.label9.Name = "label9";
|
||||
this.label9.Size = new System.Drawing.Size(162, 27);
|
||||
this.label9.Size = new System.Drawing.Size(139, 23);
|
||||
this.label9.TabIndex = 20;
|
||||
this.label9.Text = "Collect data per";
|
||||
//
|
||||
@@ -268,10 +257,10 @@
|
||||
//
|
||||
this.label8.AutoSize = true;
|
||||
this.label8.Font = new System.Drawing.Font("Microsoft YaHei", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label8.Location = new System.Drawing.Point(285, 176);
|
||||
this.label8.Location = new System.Drawing.Point(286, 165);
|
||||
this.label8.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
|
||||
this.label8.Name = "label8";
|
||||
this.label8.Size = new System.Drawing.Size(87, 27);
|
||||
this.label8.Size = new System.Drawing.Size(75, 23);
|
||||
this.label8.TabIndex = 19;
|
||||
this.label8.Text = "minutes";
|
||||
//
|
||||
@@ -283,7 +272,7 @@
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.dataCollectionMinutesNum.Location = new System.Drawing.Point(176, 173);
|
||||
this.dataCollectionMinutesNum.Location = new System.Drawing.Point(177, 162);
|
||||
this.dataCollectionMinutesNum.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.dataCollectionMinutesNum.Maximum = new decimal(new int[] {
|
||||
120,
|
||||
@@ -296,7 +285,7 @@
|
||||
0,
|
||||
0});
|
||||
this.dataCollectionMinutesNum.Name = "dataCollectionMinutesNum";
|
||||
this.dataCollectionMinutesNum.Size = new System.Drawing.Size(100, 34);
|
||||
this.dataCollectionMinutesNum.Size = new System.Drawing.Size(100, 29);
|
||||
this.dataCollectionMinutesNum.TabIndex = 18;
|
||||
this.dataCollectionMinutesNum.Value = new decimal(new int[] {
|
||||
10,
|
||||
@@ -311,7 +300,7 @@
|
||||
this.StatisticsEnabledCheckBox.Location = new System.Drawing.Point(13, 12);
|
||||
this.StatisticsEnabledCheckBox.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
this.StatisticsEnabledCheckBox.Name = "StatisticsEnabledCheckBox";
|
||||
this.StatisticsEnabledCheckBox.Size = new System.Drawing.Size(189, 31);
|
||||
this.StatisticsEnabledCheckBox.Size = new System.Drawing.Size(163, 27);
|
||||
this.StatisticsEnabledCheckBox.TabIndex = 17;
|
||||
this.StatisticsEnabledCheckBox.Text = "Enable Statistics";
|
||||
this.StatisticsEnabledCheckBox.UseVisualStyleBackColor = true;
|
||||
@@ -324,7 +313,7 @@
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.choiceKeptMinutesNum.Location = new System.Drawing.Point(176, 134);
|
||||
this.choiceKeptMinutesNum.Location = new System.Drawing.Point(177, 265);
|
||||
this.choiceKeptMinutesNum.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.choiceKeptMinutesNum.Maximum = new decimal(new int[] {
|
||||
120,
|
||||
@@ -337,7 +326,7 @@
|
||||
0,
|
||||
0});
|
||||
this.choiceKeptMinutesNum.Name = "choiceKeptMinutesNum";
|
||||
this.choiceKeptMinutesNum.Size = new System.Drawing.Size(100, 34);
|
||||
this.choiceKeptMinutesNum.Size = new System.Drawing.Size(100, 29);
|
||||
this.choiceKeptMinutesNum.TabIndex = 16;
|
||||
this.choiceKeptMinutesNum.Value = new decimal(new int[] {
|
||||
10,
|
||||
@@ -349,10 +338,10 @@
|
||||
//
|
||||
this.byHourOfDayCheckBox.AutoSize = true;
|
||||
this.byHourOfDayCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.bindingConfiguration, "ByHourOfDay", true));
|
||||
this.byHourOfDayCheckBox.Location = new System.Drawing.Point(13, 95);
|
||||
this.byHourOfDayCheckBox.Location = new System.Drawing.Point(13, 127);
|
||||
this.byHourOfDayCheckBox.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
this.byHourOfDayCheckBox.Name = "byHourOfDayCheckBox";
|
||||
this.byHourOfDayCheckBox.Size = new System.Drawing.Size(180, 31);
|
||||
this.byHourOfDayCheckBox.Size = new System.Drawing.Size(150, 27);
|
||||
this.byHourOfDayCheckBox.TabIndex = 15;
|
||||
this.byHourOfDayCheckBox.Text = "By hour of day";
|
||||
this.byHourOfDayCheckBox.UseVisualStyleBackColor = true;
|
||||
@@ -360,7 +349,7 @@
|
||||
// repeatTimesNum
|
||||
//
|
||||
this.repeatTimesNum.DataBindings.Add(new System.Windows.Forms.Binding("Value", this.bindingConfiguration, "RepeatTimesNum", true));
|
||||
this.repeatTimesNum.Location = new System.Drawing.Point(72, 216);
|
||||
this.repeatTimesNum.Location = new System.Drawing.Point(34, 84);
|
||||
this.repeatTimesNum.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.repeatTimesNum.Maximum = new decimal(new int[] {
|
||||
10,
|
||||
@@ -368,7 +357,7 @@
|
||||
0,
|
||||
0});
|
||||
this.repeatTimesNum.Name = "repeatTimesNum";
|
||||
this.repeatTimesNum.Size = new System.Drawing.Size(99, 34);
|
||||
this.repeatTimesNum.Size = new System.Drawing.Size(99, 29);
|
||||
this.repeatTimesNum.TabIndex = 14;
|
||||
this.repeatTimesNum.Value = new decimal(new int[] {
|
||||
4,
|
||||
@@ -380,9 +369,9 @@
|
||||
//
|
||||
this.label6.AutoSize = true;
|
||||
this.label6.Font = new System.Drawing.Font("Microsoft YaHei", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label6.Location = new System.Drawing.Point(178, 218);
|
||||
this.label6.Location = new System.Drawing.Point(139, 86);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(201, 27);
|
||||
this.label6.Size = new System.Drawing.Size(172, 23);
|
||||
this.label6.TabIndex = 13;
|
||||
this.label6.Text = "packages everytime";
|
||||
//
|
||||
@@ -403,7 +392,7 @@
|
||||
// splitContainer3.Panel2
|
||||
//
|
||||
this.splitContainer3.Panel2.Controls.Add(this.calculationContainer);
|
||||
this.splitContainer3.Size = new System.Drawing.Size(688, 301);
|
||||
this.splitContainer3.Size = new System.Drawing.Size(700, 301);
|
||||
this.splitContainer3.SplitterDistance = 46;
|
||||
this.splitContainer3.SplitterWidth = 10;
|
||||
this.splitContainer3.TabIndex = 6;
|
||||
@@ -414,7 +403,7 @@
|
||||
this.label1.Location = new System.Drawing.Point(5, 12);
|
||||
this.label1.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(262, 27);
|
||||
this.label1.Size = new System.Drawing.Size(225, 23);
|
||||
this.label1.TabIndex = 0;
|
||||
this.label1.Text = "Design evaluation method";
|
||||
//
|
||||
@@ -425,23 +414,23 @@
|
||||
this.calculationContainer.Location = new System.Drawing.Point(0, 0);
|
||||
this.calculationContainer.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
this.calculationContainer.Name = "calculationContainer";
|
||||
this.calculationContainer.Size = new System.Drawing.Size(688, 245);
|
||||
this.calculationContainer.Size = new System.Drawing.Size(700, 245);
|
||||
this.calculationContainer.TabIndex = 1;
|
||||
//
|
||||
// serverSelector
|
||||
//
|
||||
this.serverSelector.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.serverSelector.FormattingEnabled = true;
|
||||
this.serverSelector.Location = new System.Drawing.Point(801, 67);
|
||||
this.serverSelector.Location = new System.Drawing.Point(813, 61);
|
||||
this.serverSelector.Name = "serverSelector";
|
||||
this.serverSelector.Size = new System.Drawing.Size(260, 35);
|
||||
this.serverSelector.Size = new System.Drawing.Size(260, 31);
|
||||
this.serverSelector.TabIndex = 6;
|
||||
this.serverSelector.SelectedIndexChanged += new System.EventHandler(this.serverSelector_SelectedIndexChanged);
|
||||
//
|
||||
// CancelButton
|
||||
//
|
||||
this.CancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.CancelButton.Location = new System.Drawing.Point(960, 220);
|
||||
this.CancelButton.Location = new System.Drawing.Point(972, 214);
|
||||
this.CancelButton.Name = "CancelButton";
|
||||
this.CancelButton.Size = new System.Drawing.Size(101, 41);
|
||||
this.CancelButton.TabIndex = 5;
|
||||
@@ -452,7 +441,7 @@
|
||||
// OKButton
|
||||
//
|
||||
this.OKButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.OKButton.Location = new System.Drawing.Point(852, 220);
|
||||
this.OKButton.Location = new System.Drawing.Point(864, 214);
|
||||
this.OKButton.Name = "OKButton";
|
||||
this.OKButton.Size = new System.Drawing.Size(101, 41);
|
||||
this.OKButton.TabIndex = 4;
|
||||
@@ -466,10 +455,10 @@
|
||||
//
|
||||
// StatisticsStrategyConfigurationForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 27F);
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 23F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.AutoSize = true;
|
||||
this.ClientSize = new System.Drawing.Size(1077, 614);
|
||||
this.ClientSize = new System.Drawing.Size(1089, 614);
|
||||
this.Controls.Add(this.splitContainer1);
|
||||
this.Font = new System.Drawing.Font("Microsoft YaHei", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10);
|
||||
@@ -503,10 +492,9 @@
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.DataVisualization.Charting.Chart StatisticsChart;
|
||||
private System.Windows.Forms.CheckBox byISPCheckBox;
|
||||
private System.Windows.Forms.CheckBox PingCheckBox;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.GroupBox chartModeSelector;
|
||||
private System.Windows.Forms.RadioButton allMode;
|
||||
private System.Windows.Forms.RadioButton dayMode;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Shadowsocks.View
|
||||
{
|
||||
private readonly ShadowsocksController _controller;
|
||||
private StatisticsStrategyConfiguration _configuration;
|
||||
private DataTable _dataTable = new DataTable();
|
||||
private readonly DataTable _dataTable = new DataTable();
|
||||
private List<string> _servers;
|
||||
|
||||
public StatisticsStrategyConfigurationForm(ShadowsocksController controller)
|
||||
@@ -135,5 +135,10 @@ namespace Shadowsocks.View
|
||||
{
|
||||
loadChartData();
|
||||
}
|
||||
|
||||
private void PingCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
repeatTimesNum.ReadOnly = !PingCheckBox.Checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user