Allow configuration on AutomationBots.

This commit is contained in:
2019-11-05 17:34:50 +01:00
parent 474757af5e
commit 0457466bd0
12 changed files with 575 additions and 170 deletions

View File

@@ -7,7 +7,12 @@ namespace VAR.ScreenAutomation.Bots
{
public string Name => "Dummy";
public void Init(IOutputHandler output)
public IConfiguration GetDefaultConfiguration()
{
return null;
}
public void Init(IOutputHandler output, IConfiguration config)
{
output.Clean();
}

View File

@@ -3,16 +3,17 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using VAR.ScreenAutomation.Code;
using VAR.ScreenAutomation.Interfaces;
namespace VAR.ScreenAutomation.Bots
{
public class TetrisBot : IAutomationBot
{
private TetrisGrid _grid = new TetrisGrid();
private TetrisGrid _grid;
private List<TetrisShape> _currentShape = new List<TetrisShape>();
private TetrisGrid _workGrid = new TetrisGrid();
private List<TetrisShape> _currentShape;
private TetrisGrid _workGrid;
private bool _shapeFound = false;
private int _shapeX;
@@ -23,12 +24,31 @@ namespace VAR.ScreenAutomation.Bots
public string Name => "Tetris";
public void Init(IOutputHandler output)
private const int DefaultGridWidth = 10;
private const int DefaultGridHeight = 20;
public IConfiguration GetDefaultConfiguration()
{
_currentShape.Add(new TetrisShape());
_currentShape.Add(new TetrisShape());
_currentShape.Add(new TetrisShape());
_currentShape.Add(new TetrisShape());
var defaultConfiguration = new MemoryBackedConfiguration();
defaultConfiguration.Set("GridWidth", DefaultGridWidth);
defaultConfiguration.Set("GridHeight", DefaultGridHeight);
return defaultConfiguration;
}
public void Init(IOutputHandler output, IConfiguration config)
{
int gridWidth = config.Get("GridWidth", DefaultGridWidth);
int gridHeight = config.Get("GridHeight", DefaultGridHeight);
_grid = new TetrisGrid(gridWidth, gridHeight);
_workGrid = new TetrisGrid(gridWidth, gridHeight);
_currentShape = new List<TetrisShape>
{
new TetrisShape(),
new TetrisShape(),
new TetrisShape(),
new TetrisShape(),
};
output.Clean();
}
@@ -509,50 +529,52 @@ namespace VAR.ScreenAutomation.Bots
public class TetrisGrid
{
public const int GridWidth = 10;
public const int GridHeight = 24;
private int _gridWidth;
private int _gridHeight;
private byte[][] _grid = null;
private int[] _heights = null;
public TetrisGrid()
public TetrisGrid(int gridWidth, int gridHeight)
{
_grid = new byte[GridHeight][];
for (int y = 0; y < GridHeight; y++)
_gridWidth = gridWidth;
_gridHeight = gridHeight;
_grid = new byte[_gridHeight][];
for (int y = 0; y < _gridHeight; y++)
{
_grid[y] = new byte[GridWidth];
_grid[y] = new byte[_gridWidth];
}
_heights = new int[GridWidth];
_heights = new int[_gridWidth];
}
public byte Get(int x, int y)
{
if (x >= GridWidth || x < 0) { return 0xFF; }
if (y >= GridHeight || y < 0) { return 0xFF; }
if (x >= _gridWidth || x < 0) { return 0xFF; }
if (y >= _gridHeight || y < 0) { return 0xFF; }
return _grid[y][x];
}
public void Set(int x, int y, byte value)
{
if (x >= GridWidth || x < 0) { return; }
if (y >= GridHeight || y < 0) { return; }
if (x >= _gridWidth || x < 0) { return; }
if (y >= _gridHeight || y < 0) { return; }
_grid[y][x] = value;
}
public void SampleFromBitmap(Bitmap bmp)
{
float xStep = bmp.Width / GridWidth;
float yStep = bmp.Height / GridHeight;
float xStep = bmp.Width / _gridWidth;
float yStep = bmp.Height / _gridHeight;
float xOff0 = xStep / 2;
float xOff1 = xOff0 / 2;
float xOff2 = xOff0 + xOff1;
float yOff0 = yStep / 2;
float yOff1 = yOff0 / 2;
float yOff2 = yOff0 + yOff1;
for (int y = 0; y < GridHeight; y++)
for (int y = 0; y < _gridHeight; y++)
{
for (int x = 0; x < GridWidth; x++)
for (int x = 0; x < _gridWidth; x++)
{
Color color = bmp.GetPixel(
x: (int)((x * xStep) + xOff0),
@@ -595,19 +617,19 @@ namespace VAR.ScreenAutomation.Bots
public void MarkGround()
{
for (int i = 0; i < GridWidth; i++)
for (int i = 0; i < _gridWidth; i++)
{
if (_grid[GridHeight - 1][i] == 1)
if (_grid[_gridHeight - 1][i] == 1)
{
FloodFill(i, GridHeight - 1, 1, 2);
FloodFill(i, _gridHeight - 1, 1, 2);
}
}
}
public void FloodFill(int x, int y, byte expectedValue, byte fillValue)
{
if (x >= GridWidth || x < 0) { return; }
if (y >= GridHeight || y < 0) { return; }
if (x >= _gridWidth || x < 0) { return; }
if (y >= _gridHeight || y < 0) { return; }
if (_grid[y][x] != expectedValue) { return; }
_grid[y][x] = fillValue;
FloodFill(x - 1, y - 1, expectedValue, fillValue);
@@ -622,9 +644,9 @@ namespace VAR.ScreenAutomation.Bots
public void SampleOther(TetrisGrid grid, byte value, byte setValue = 1)
{
for (int y = 0; y < GridHeight; y++)
for (int y = 0; y < _gridHeight; y++)
{
for (int x = 0; x < GridWidth; x++)
for (int x = 0; x < _gridWidth; x++)
{
if (grid._grid[y][x] == value)
{
@@ -642,9 +664,9 @@ namespace VAR.ScreenAutomation.Bots
{
x = -1;
y = -1;
for (int j = 0; j < GridHeight && y == -1; j++)
for (int j = 0; j < _gridHeight && y == -1; j++)
{
for (int i = 0; i < GridWidth && y == -1; i++)
for (int i = 0; i < _gridWidth && y == -1; i++)
{
if (_grid[j][i] == value)
{
@@ -653,9 +675,9 @@ namespace VAR.ScreenAutomation.Bots
}
}
if (y == -1) { return false; }
for (int i = 0; i < GridWidth && x == -1; i++)
for (int i = 0; i < _gridWidth && x == -1; i++)
{
for (int j = 0; j < GridHeight && x == -1; j++)
for (int j = 0; j < _gridHeight && x == -1; j++)
{
if (_grid[j][i] == value)
{
@@ -670,7 +692,7 @@ namespace VAR.ScreenAutomation.Bots
public bool IsCompleteLine(int y)
{
bool complete = true;
for (int x = 0; x < GridWidth; x++)
for (int x = 0; x < _gridWidth; x++)
{
if (_grid[y][x] == 0)
{
@@ -684,27 +706,27 @@ namespace VAR.ScreenAutomation.Bots
public double Evaluate(double aggregateHeightWeight, double completeLinesWeight, double holesWeight, double bumpinessWeight, double maxHeightWeight)
{
// Calculte aggregate height
for (int i = 0; i < GridWidth; i++)
for (int i = 0; i < _gridWidth; i++)
{
int j = 0;
while (j < GridHeight && _grid[j][i] == 0) { j++; }
_heights[i] = GridHeight - j;
while (j < _gridHeight && _grid[j][i] == 0) { j++; }
_heights[i] = _gridHeight - j;
}
double agregateHeight = _heights.Sum();
// Calculate complete lines
int completeLines = 0;
for (int y = 0; y < GridHeight; y++)
for (int y = 0; y < _gridHeight; y++)
{
if (IsCompleteLine(y)) { completeLines++; }
}
// Calculate holes
int holes = 0;
for (int x = 0; x < GridWidth; x++)
for (int x = 0; x < _gridWidth; x++)
{
bool block = false;
for (int y = 1; y < GridHeight; y++)
for (int y = 1; y < _gridHeight; y++)
{
if (_grid[y][x] != 0 && IsCompleteLine(y) == false)
{
@@ -719,7 +741,7 @@ namespace VAR.ScreenAutomation.Bots
// Calculate bumpiness
int bumpines = 0;
for (int i = 1; i < GridWidth; i++)
for (int i = 1; i < _gridWidth; i++)
{
bumpines += Math.Abs(_heights[i] - _heights[i - 1]);
}
@@ -740,10 +762,10 @@ namespace VAR.ScreenAutomation.Bots
public void Print(IOutputHandler output)
{
for (int y = 0; y < GridHeight; y++)
for (int y = 0; y < _gridHeight; y++)
{
StringBuilder sbLine = new StringBuilder();
for (int x = 0; x < GridWidth; x++)
for (int x = 0; x < _gridWidth; x++)
{
if (_grid[y][x] == 0)
{
@@ -764,8 +786,8 @@ namespace VAR.ScreenAutomation.Bots
public void Draw(Bitmap bmp)
{
float xStep = bmp.Width / (float)GridWidth;
float yStep = bmp.Height / (float)GridHeight;
float xStep = bmp.Width / (float)_gridWidth;
float yStep = bmp.Height / (float)_gridHeight;
float halfXStep = xStep / 2;
float halfYStep = yStep / 2;
float offX = halfXStep / 2;
@@ -774,9 +796,9 @@ namespace VAR.ScreenAutomation.Bots
using (Pen borderPen = new Pen(Color.DarkGray))
using (Graphics g = Graphics.FromImage(bmp))
{
for (int y = 0; y < GridHeight; y++)
for (int y = 0; y < _gridHeight; y++)
{
for (int x = 0; x < GridWidth; x++)
for (int x = 0; x < _gridWidth; x++)
{
Brush br;
if (_grid[y][x] == 0)

View File

@@ -1,17 +1,17 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Text;
using VAR.ScreenAutomation.Interfaces;
namespace VAR.ScreenAutomation.Code
{
public class Configuration
public class FileBackedConfiguration : IConfiguration
{
private Dictionary<string, string> _configItems = new Dictionary<string, string>();
private MemoryBackedConfiguration _config = new MemoryBackedConfiguration();
private string _name = null;
public Configuration(string name = null)
public FileBackedConfiguration(string name = null)
{
_name = name;
}
@@ -48,9 +48,16 @@ namespace VAR.ScreenAutomation.Code
return config;
}
public void Load()
public void Load(IConfiguration other = null)
{
_configItems.Clear();
_config.Clear();
if (other != null)
{
foreach (string key in other.GetKeys())
{
_config.Set(key, other.Get(key, null));
}
}
string[] configLines = GetConfigurationLines(_name);
foreach (string configLine in configLines)
{
@@ -59,100 +66,59 @@ namespace VAR.ScreenAutomation.Code
string configName = configLine.Substring(0, idxSplit);
string configData = configLine.Substring(idxSplit + 1);
if (_configItems.ContainsKey(configName))
{
_configItems[configName] = configData;
}
else
{
_configItems.Add(configName, configData);
}
_config.Set(configName, configData);
}
}
public void Save()
{
StringBuilder sbConfig = new StringBuilder();
foreach (KeyValuePair<string, string> pair in _configItems)
foreach (string key in _config.GetKeys())
{
sbConfig.AppendFormat("{0}|{1}\n", pair.Key, pair.Value);
sbConfig.AppendFormat("{0}|{1}\n", key, _config.Get(key, string.Empty));
}
string configFileName = GetConfigFileName(_name);
File.WriteAllText(configFileName, sbConfig.ToString());
}
public IEnumerable<string> GetKeys()
{
return _config.GetKeys();
}
public void Clear()
{
_config.Clear();
}
public string Get(string key, string defaultValue)
{
if (_configItems == null) { return defaultValue; }
if (_configItems.ContainsKey(key))
{
return _configItems[key];
}
return defaultValue;
return _config.Get(key, defaultValue);
}
public int Get(string key, int defaultValue)
{
if (_configItems == null) { return defaultValue; }
if (_configItems.ContainsKey(key))
{
if (int.TryParse(_configItems[key], out int value))
{
return value;
}
return defaultValue;
}
return defaultValue;
return _config.Get(key, defaultValue);
}
public bool Get(string key, bool defaultValue)
{
if (_configItems == null) { return defaultValue; }
if (_configItems.ContainsKey(key))
{
string value = _configItems[key];
return (value == "true");
}
return defaultValue;
return _config.Get(key, defaultValue);
}
public void Set(string key, string value)
{
if (_configItems == null) { return; }
if (_configItems.ContainsKey(key))
{
_configItems[key] = value;
}
else
{
_configItems.Add(key, value);
}
_config.Set(key, value);
}
public void Set(string key, int value)
{
if (_configItems == null) { return; }
if (_configItems.ContainsKey(key))
{
_configItems[key] = Convert.ToString(value);
}
else
{
_configItems.Add(key, Convert.ToString(value));
}
_config.Set(key, value);
}
public void Set(string key, bool value)
{
if (_configItems == null) { return; }
if (_configItems.ContainsKey(key))
{
_configItems[key] = value ? "true" : "false";
}
else
{
_configItems.Add(key, value ? "true" : "false");
}
_config.Set(key, value);
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using VAR.ScreenAutomation.Interfaces;
namespace VAR.ScreenAutomation.Code
{
public class MemoryBackedConfiguration : IConfiguration
{
private Dictionary<string, string> _configItems = new Dictionary<string, string>();
public IEnumerable<string> GetKeys()
{
if (_configItems == null) { return new List<string>(); }
return _configItems.Select(p => p.Key);
}
public void Clear()
{
_configItems.Clear();
}
public string Get(string key, string defaultValue)
{
if (_configItems == null) { return defaultValue; }
if (_configItems.ContainsKey(key))
{
return _configItems[key];
}
return defaultValue;
}
public int Get(string key, int defaultValue)
{
if (_configItems == null) { return defaultValue; }
if (_configItems.ContainsKey(key))
{
if (int.TryParse(_configItems[key], out int value))
{
return value;
}
return defaultValue;
}
return defaultValue;
}
public bool Get(string key, bool defaultValue)
{
if (_configItems == null) { return defaultValue; }
if (_configItems.ContainsKey(key))
{
string value = _configItems[key];
return (value == "true");
}
return defaultValue;
}
public void Set(string key, string value)
{
if (_configItems == null) { return; }
if (_configItems.ContainsKey(key))
{
_configItems[key] = value;
}
else
{
_configItems.Add(key, value);
}
}
public void Set(string key, int value)
{
if (_configItems == null) { return; }
if (_configItems.ContainsKey(key))
{
_configItems[key] = Convert.ToString(value);
}
else
{
_configItems.Add(key, Convert.ToString(value));
}
}
public void Set(string key, bool value)
{
if (_configItems == null) { return; }
if (_configItems.ContainsKey(key))
{
_configItems[key] = value ? "true" : "false";
}
else
{
_configItems.Add(key, value ? "true" : "false");
}
}
}
}

View File

@@ -0,0 +1,48 @@
namespace VAR.ScreenAutomation
{
partial class FrmAutomationBotParams
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FrmAutomationBotParams
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(297, 473);
this.Name = "FrmAutomationBotParams";
this.Text = "AutomationBotParams";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmAutomationBotParams_FormClosing);
this.Load += new System.EventHandler(this.FrmAutomationBotParams_Load);
this.ResumeLayout(false);
}
#endregion
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using VAR.ScreenAutomation.Code;
namespace VAR.ScreenAutomation
{
public partial class FrmAutomationBotParams : Form
{
private FileBackedConfiguration _config = null;
private BindingList<Pair> pairs = null;
private DataGridView dgvParams = null;
public FrmAutomationBotParams(FileBackedConfiguration config)
{
_config = config;
InitializeComponent();
}
private void FrmAutomationBotParams_Load(object sender, EventArgs e)
{
pairs = new BindingList<Pair>();
foreach (string key in _config.GetKeys())
{
pairs.Add(new Pair { Key = key, Value = _config.Get(key, string.Empty), });
}
pairs.AddingNew += (s, a) =>
{
a.NewObject = new Pair { Parent = pairs };
};
dgvParams = new DataGridView();
dgvParams.Dock = DockStyle.Fill;
dgvParams.DataSource = pairs;
Controls.Add(dgvParams);
}
private void FrmAutomationBotParams_FormClosing(object sender, FormClosingEventArgs e)
{
var parms = new Dictionary<string, string>();
foreach (Pair pair in pairs)
{
if (string.IsNullOrEmpty(pair.Key)) { continue; }
_config.Set(pair.Key, pair.Value);
}
_config.Save();
}
internal class Pair : IDataErrorInfo
{
internal IList<Pair> Parent { get; set; }
public string Key { get; set; }
public string Value { get; set; }
string IDataErrorInfo.Error
{
get { return string.Empty; }
}
string IDataErrorInfo.this[string columnName]
{
get
{
if (columnName == "Key" && Parent != null && Parent.Any(
x => x.Key == this.Key && !ReferenceEquals(x, this)))
{
return "duplicate key";
}
return string.Empty;
}
}
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -31,9 +31,10 @@
this.picCapturer = new System.Windows.Forms.PictureBox();
this.splitMain = new System.Windows.Forms.SplitContainer();
this.splitOutput = new System.Windows.Forms.SplitContainer();
this.numFPS = new System.Windows.Forms.NumericUpDown();
this.ddlAutomationBot = new System.Windows.Forms.ComboBox();
this.btnStartEnd = new System.Windows.Forms.Button();
this.numFPS = new System.Windows.Forms.NumericUpDown();
this.btnAutomationBotConfig = new System.Windows.Forms.Button();
this.picPreview = new VAR.ScreenAutomation.Controls.CtrImageViewer();
this.ctrOutput = new VAR.ScreenAutomation.Controls.CtrOutput();
((System.ComponentModel.ISupportInitialize)(this.picCapturer)).BeginInit();
@@ -54,11 +55,10 @@
this.picCapturer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.picCapturer.Location = new System.Drawing.Point(4, 4);
this.picCapturer.Margin = new System.Windows.Forms.Padding(4);
this.picCapturer.Location = new System.Drawing.Point(3, 3);
this.picCapturer.Name = "picCapturer";
this.picCapturer.Padding = new System.Windows.Forms.Padding(10);
this.picCapturer.Size = new System.Drawing.Size(501, 799);
this.picCapturer.Padding = new System.Windows.Forms.Padding(8, 8, 8, 8);
this.picCapturer.Size = new System.Drawing.Size(319, 649);
this.picCapturer.TabIndex = 0;
this.picCapturer.TabStop = false;
//
@@ -67,7 +67,7 @@
this.splitMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitMain.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
this.splitMain.Location = new System.Drawing.Point(0, 0);
this.splitMain.Margin = new System.Windows.Forms.Padding(10);
this.splitMain.Margin = new System.Windows.Forms.Padding(8, 8, 8, 8);
this.splitMain.Name = "splitMain";
//
// splitMain.Panel1
@@ -77,14 +77,16 @@
// splitMain.Panel2
//
this.splitMain.Panel2.Controls.Add(this.picCapturer);
this.splitMain.Size = new System.Drawing.Size(754, 816);
this.splitMain.Size = new System.Drawing.Size(566, 663);
this.splitMain.SplitterDistance = 232;
this.splitMain.SplitterWidth = 3;
this.splitMain.TabIndex = 3;
//
// splitOutput
//
this.splitOutput.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitOutput.Location = new System.Drawing.Point(0, 0);
this.splitOutput.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.splitOutput.Name = "splitOutput";
this.splitOutput.Orientation = System.Windows.Forms.Orientation.Horizontal;
//
@@ -94,43 +96,21 @@
//
// splitOutput.Panel2
//
this.splitOutput.Panel2.Controls.Add(this.btnAutomationBotConfig);
this.splitOutput.Panel2.Controls.Add(this.numFPS);
this.splitOutput.Panel2.Controls.Add(this.ddlAutomationBot);
this.splitOutput.Panel2.Controls.Add(this.btnStartEnd);
this.splitOutput.Panel2.Controls.Add(this.ctrOutput);
this.splitOutput.Size = new System.Drawing.Size(232, 816);
this.splitOutput.SplitterDistance = 283;
this.splitOutput.Size = new System.Drawing.Size(232, 663);
this.splitOutput.SplitterDistance = 229;
this.splitOutput.SplitterWidth = 3;
this.splitOutput.TabIndex = 4;
//
// ddlAutomationBot
//
this.ddlAutomationBot.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ddlAutomationBot.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.ddlAutomationBot.FormattingEnabled = true;
this.ddlAutomationBot.Location = new System.Drawing.Point(13, 4);
this.ddlAutomationBot.Name = "ddlAutomationBot";
this.ddlAutomationBot.Size = new System.Drawing.Size(216, 24);
this.ddlAutomationBot.TabIndex = 4;
this.ddlAutomationBot.SelectedIndexChanged += new System.EventHandler(this.DdlAutomationBot_SelectedIndexChanged);
//
// btnStartEnd
//
this.btnStartEnd.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.btnStartEnd.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnStartEnd.Location = new System.Drawing.Point(15, 34);
this.btnStartEnd.Name = "btnStartEnd";
this.btnStartEnd.Size = new System.Drawing.Size(149, 39);
this.btnStartEnd.TabIndex = 3;
this.btnStartEnd.Text = "Start";
this.btnStartEnd.UseVisualStyleBackColor = true;
this.btnStartEnd.Click += new System.EventHandler(this.BtnStartEnd_Click);
//
// numFPS
//
this.numFPS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.numFPS.Location = new System.Drawing.Point(170, 50);
this.numFPS.Location = new System.Drawing.Point(186, 41);
this.numFPS.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.numFPS.Maximum = new decimal(new int[] {
60,
0,
@@ -142,7 +122,7 @@
0,
0});
this.numFPS.Name = "numFPS";
this.numFPS.Size = new System.Drawing.Size(59, 22);
this.numFPS.Size = new System.Drawing.Size(44, 20);
this.numFPS.TabIndex = 5;
this.numFPS.Value = new decimal(new int[] {
20,
@@ -150,6 +130,44 @@
0,
0});
//
// ddlAutomationBot
//
this.ddlAutomationBot.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ddlAutomationBot.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.ddlAutomationBot.FormattingEnabled = true;
this.ddlAutomationBot.Location = new System.Drawing.Point(10, 3);
this.ddlAutomationBot.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.ddlAutomationBot.Name = "ddlAutomationBot";
this.ddlAutomationBot.Size = new System.Drawing.Size(171, 21);
this.ddlAutomationBot.TabIndex = 4;
this.ddlAutomationBot.SelectedIndexChanged += new System.EventHandler(this.DdlAutomationBot_SelectedIndexChanged);
//
// btnStartEnd
//
this.btnStartEnd.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.btnStartEnd.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnStartEnd.Location = new System.Drawing.Point(11, 28);
this.btnStartEnd.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btnStartEnd.Name = "btnStartEnd";
this.btnStartEnd.Size = new System.Drawing.Size(170, 32);
this.btnStartEnd.TabIndex = 3;
this.btnStartEnd.Text = "Start";
this.btnStartEnd.UseVisualStyleBackColor = true;
this.btnStartEnd.Click += new System.EventHandler(this.BtnStartEnd_Click);
//
// btnAutomationBotConfig
//
this.btnAutomationBotConfig.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnAutomationBotConfig.Location = new System.Drawing.Point(187, 3);
this.btnAutomationBotConfig.Name = "btnAutomationBotConfig";
this.btnAutomationBotConfig.Size = new System.Drawing.Size(45, 23);
this.btnAutomationBotConfig.TabIndex = 6;
this.btnAutomationBotConfig.Text = "Cfg.";
this.btnAutomationBotConfig.UseVisualStyleBackColor = true;
this.btnAutomationBotConfig.Click += new System.EventHandler(this.btnAutomationBotConfig_Click);
//
// picPreview
//
this.picPreview.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@@ -157,9 +175,10 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.picPreview.BackColor = System.Drawing.Color.Black;
this.picPreview.ImageShow = null;
this.picPreview.Location = new System.Drawing.Point(12, 12);
this.picPreview.Location = new System.Drawing.Point(9, 10);
this.picPreview.Margin = new System.Windows.Forms.Padding(2);
this.picPreview.Name = "picPreview";
this.picPreview.Size = new System.Drawing.Size(217, 268);
this.picPreview.Size = new System.Drawing.Size(221, 217);
this.picPreview.TabIndex = 1;
this.picPreview.TabStop = false;
//
@@ -168,19 +187,19 @@
this.ctrOutput.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ctrOutput.Location = new System.Drawing.Point(12, 79);
this.ctrOutput.Location = new System.Drawing.Point(9, 64);
this.ctrOutput.Margin = new System.Windows.Forms.Padding(2);
this.ctrOutput.Name = "ctrOutput";
this.ctrOutput.Size = new System.Drawing.Size(217, 437);
this.ctrOutput.Size = new System.Drawing.Size(221, 356);
this.ctrOutput.TabIndex = 2;
this.ctrOutput.Text = "ctrOutput1";
//
// FrmScreenAutomation
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(754, 816);
this.ClientSize = new System.Drawing.Size(566, 663);
this.Controls.Add(this.splitMain);
this.Margin = new System.Windows.Forms.Padding(4);
this.Name = "FrmScreenAutomation";
this.Text = "ScreenAutomation";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmScreenAutomation_FormClosing);
@@ -210,6 +229,7 @@
private System.Windows.Forms.Button btnStartEnd;
private System.Windows.Forms.ComboBox ddlAutomationBot;
private System.Windows.Forms.NumericUpDown numFPS;
private System.Windows.Forms.Button btnAutomationBotConfig;
}
}

View File

@@ -24,7 +24,7 @@ namespace VAR.ScreenAutomation
private void FrmScreenAutomation_Load(object sender, EventArgs e)
{
var configuration = new Configuration();
var configuration = new FileBackedConfiguration();
configuration.Load();
Top = configuration.Get("Top", Top);
Left = configuration.Get("Left", Left);
@@ -45,8 +45,7 @@ namespace VAR.ScreenAutomation
{
ddlAutomationBot.SelectedIndex = 0;
}
_automationBot = AutomationBotFactory.CreateFromName((string)ddlAutomationBot.SelectedItem);
_automationBot?.Init(ctrOutput);
InitBot((string)ddlAutomationBot.SelectedItem);
numFPS.Value = configuration.Get("numFPS", (int)numFPS.Value);
@@ -63,7 +62,7 @@ namespace VAR.ScreenAutomation
private void FrmScreenAutomation_FormClosing(object sender, FormClosingEventArgs e)
{
var configuration = new Configuration();
var configuration = new FileBackedConfiguration();
configuration.Set("Top", Top);
configuration.Set("Left", Left);
configuration.Set("Width", Width);
@@ -113,14 +112,32 @@ namespace VAR.ScreenAutomation
}
}
private void DdlAutomationBot_SelectedIndexChanged(object sender, EventArgs e)
{
InitBot((string)ddlAutomationBot.SelectedItem);
}
private void btnAutomationBotConfig_Click(object sender, EventArgs e)
{
if (_automationBot == null) { return; }
IConfiguration defaultConfig = _automationBot.GetDefaultConfiguration();
var config = new FileBackedConfiguration(_automationBot.Name);
config.Load(defaultConfig);
var frmAutomationBotParameters = new FrmAutomationBotParams(config)
{
StartPosition = FormStartPosition.CenterParent
};
frmAutomationBotParameters.ShowDialog();
InitBot(_automationBot.Name);
}
private void Start()
{
if (_running) { return; }
_running = true;
WindowHandling.WindowSetTopLevel(this);
btnStartEnd.Text = "End";
_automationBot = AutomationBotFactory.CreateFromName((string)ddlAutomationBot.SelectedItem);
_automationBot?.Init(ctrOutput);
InitBot((string)ddlAutomationBot.SelectedItem);
Point pointCapturerCenter = picCapturer.PointToScreen(new Point(picCapturer.Width / 2, picCapturer.Height / 2));
Mouse.SetPosition((uint)pointCapturerCenter.X, (uint)pointCapturerCenter.Y);
Mouse.Click(Mouse.MouseButtons.Left);
@@ -134,10 +151,12 @@ namespace VAR.ScreenAutomation
WindowHandling.WindowSetTopLevel(this, false);
}
private void DdlAutomationBot_SelectedIndexChanged(object sender, EventArgs e)
private void InitBot(string botName)
{
_automationBot = AutomationBotFactory.CreateFromName((string)ddlAutomationBot.SelectedItem);
_automationBot?.Init(ctrOutput);
_automationBot = AutomationBotFactory.CreateFromName(botName);
var botConfiguration = new FileBackedConfiguration(botName);
botConfiguration.Load();
_automationBot?.Init(ctrOutput, botConfiguration);
}
}
}

View File

@@ -5,7 +5,8 @@ namespace VAR.ScreenAutomation.Interfaces
public interface IAutomationBot
{
string Name { get; }
void Init(IOutputHandler output);
IConfiguration GetDefaultConfiguration();
void Init(IOutputHandler output, IConfiguration config);
Bitmap Process(Bitmap bmpInput, IOutputHandler output);
string ResponseKeys();
}

View File

@@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace VAR.ScreenAutomation.Interfaces
{
public interface IConfiguration
{
IEnumerable<string> GetKeys();
void Clear();
bool Get(string key, bool defaultValue);
int Get(string key, int defaultValue);
string Get(string key, string defaultValue);
void Set(string key, bool value);
void Set(string key, int value);
void Set(string key, string value);
}
}

View File

@@ -52,7 +52,15 @@
<Compile Include="Bots\DummyBot.cs" />
<Compile Include="Bots\TetrisBot.cs" />
<Compile Include="Code\AutomationBotFactory.cs" />
<Compile Include="Code\Configuration.cs" />
<Compile Include="Code\FileBackedConfiguration.cs" />
<Compile Include="Code\MemoryBackedConfiguration.cs" />
<Compile Include="FrmAutomationBotParams.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FrmAutomationBotParams.Designer.cs">
<DependentUpon>FrmAutomationBotParams.cs</DependentUpon>
</Compile>
<Compile Include="Interfaces\IConfiguration.cs" />
<Compile Include="Code\Mouse.cs" />
<Compile Include="Code\Screenshoter.cs" />
<Compile Include="Code\WindowHandling.cs" />
@@ -72,6 +80,9 @@
<Compile Include="Interfaces\IOutputHandler.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="FrmAutomationBotParams.resx">
<DependentUpon>FrmAutomationBotParams.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FrmScreenAutomation.resx">
<DependentUpon>FrmScreenAutomation.cs</DependentUpon>
</EmbeddedResource>