diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..701fe1f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+################################################################################
+# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
+################################################################################
+
+/.vs
+/OnScreenKeyboardScripter/.vs/OnScreenKeyboardScripter/v15
+/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/bin/Debug
+/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/obj
+/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/bin/Debug
+/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/obj
+/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/bin/Debug
+/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/obj
+/OnScreenKeyboardScripter/packages
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/App.config b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/App.config
new file mode 100644
index 0000000..731f6de
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/OnScreenKeyboardScripter.Demo.csproj b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/OnScreenKeyboardScripter.Demo.csproj
new file mode 100644
index 0000000..56c4e78
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/OnScreenKeyboardScripter.Demo.csproj
@@ -0,0 +1,61 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {DBA825CE-715D-4F3A-BD08-BDD8A3490CAA}
+ Exe
+ OnScreenKeyboardScripter.Demo
+ OnScreenKeyboardScripter.Demo
+ v4.6.1
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+ {67c25f06-53a5-4536-8fe2-c8c92795b95a}
+ OnScreenKeyboardScripter.Lib
+
+
+
+
\ No newline at end of file
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/Program.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/Program.cs
new file mode 100644
index 0000000..2cd5b6c
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/Program.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using lib = OnScreenKeyboardScripter.Lib;
+
+namespace OnScreenKeyboardScripter.Demo
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ if (System.IO.File.Exists("sample.txt"))
+ {
+ lib.IKeyboard keyboard = lib.Factory.GetKeyboard();
+ lib.IScripter scripter = lib.Factory.GetScripter();
+
+ System.IO.File.ReadAllLines("sample.txt")
+ .ToList()
+ .ForEach(line =>
+ {
+ string output = string.Empty;
+ try
+ {
+ output = scripter.GetPath(keyboard, line);
+ }
+ catch (Exception e)
+ {
+ output = string.Format("ERROR - unable to translate input:\n\t'{0}'\n{1}", line, e.Message);
+ }
+ Console.WriteLine(output);
+ });
+ }
+
+ Console.Write("Press key to exit");
+ Console.ReadKey();
+ }
+ }
+}
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/Properties/AssemblyInfo.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..809eefd
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("OnScreenKeyboardScripter.Demo")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("OnScreenKeyboardScripter.Demo")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("dba825ce-715d-4f3a-bd08-bdd8a3490caa")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/sample.txt b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/sample.txt
new file mode 100644
index 0000000..8d1ca5a
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Demo/sample.txt
@@ -0,0 +1,2 @@
+IT Crowd
+This has s*me b@d input
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Factory.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Factory.cs
new file mode 100644
index 0000000..909d389
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Factory.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OnScreenKeyboardScripter.Lib
+{
+ ///
+ /// Single source for keyboards and scripters
+ ///
+ public sealed class Factory
+ {
+ static StructureMap.IContainer container = null;
+
+ ///
+ /// Gets the currently-registered class.
+ ///
+ ///
+ static public IKeyboard GetKeyboard() { return container.GetInstance(); }
+ ///
+ /// Gets the currently-registered class.
+ ///
+ ///
+ static public IScripter GetScripter() { return container.GetInstance(); }
+
+ ///
+ /// Initializes the class.
+ ///
+ static Factory()
+ {
+ container = new StructureMap.Container(cfg =>
+ {
+ cfg.For().Use();
+ cfg.For().Use();
+ });
+ }
+ }
+}
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/IKeyboard.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/IKeyboard.cs
new file mode 100644
index 0000000..6bd1bce
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/IKeyboard.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OnScreenKeyboardScripter.Lib
+{
+ public enum MoveCursor
+ {
+ Up,
+ Down,
+ Left,
+ Right
+ }
+
+ public interface IKeyboard
+ {
+ List GetCursorPath(char fromKey, char toKey);
+ }
+}
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/IScripter.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/IScripter.cs
new file mode 100644
index 0000000..9f1653b
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/IScripter.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OnScreenKeyboardScripter.Lib
+{
+ public interface IScripter
+ {
+ string GetPath(IKeyboard keyboard, string input);
+ }
+}
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Keyboard.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Keyboard.cs
new file mode 100644
index 0000000..220f016
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Keyboard.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OnScreenKeyboardScripter.Lib
+{
+ ///
+ /// Represents the on-screen keyboard layout and cursor-movement behavior.
+ ///
+ ///
+ public class Keyboard : IKeyboard
+ {
+ public bool CursorWrapsHorizontally { get; set; } = true;
+ public bool CursorWrapsVertically { get; set; } = true;
+
+ const int rowWidth = 6;
+ const int rows = 6;
+
+ const string layout =
+ "ABCDEF" +
+ "GHIJKL" +
+ "MNOPQR" +
+ "STUVWX" +
+ "YZ0123" +
+ "456789";
+
+ ///
+ /// Gets the cursor path from current key-location on keyboard to next key-location
+ ///
+ /// Starting key (cursor position) on keyboard
+ /// Destination key (cursor position) on keyboard
+ ///
+ /// Unrecognized keyboard key
+ public List GetCursorPath(char fromKey, char toKey)
+ {
+ int idxFrom = layout.IndexOf(fromKey),
+ idxTo = layout.IndexOf(toKey);
+
+ if (idxFrom < 0 || idxTo < 0)
+ {
+ throw new NotImplementedException("Unrecognized keyboard key");
+ }
+
+ List cursorMovements = new List();
+
+ int fromY = (int)Math.Floor((double)idxFrom / (double)rowWidth),
+ fromX = idxFrom - (fromY * rowWidth),
+ toY = (int)Math.Floor((double)idxTo / (double)rowWidth),
+ toX = idxTo - (toY * rowWidth);
+
+ while (fromKey != toKey)
+ {
+ // go up instead of down if wrapping?
+ var upOverDown = (CursorWrapsVertically && ((fromY + rows - toY) < toY - fromY));
+ // go down instead of up if wrapping?
+ var downOverUp = (CursorWrapsVertically && (toY + rows - fromY) < fromY - toY);
+ // go left instead of right if wrapping
+ var leftOverRight = (CursorWrapsHorizontally && ((fromX + rowWidth - toX) < toX - fromX));
+ // go right instead of left if wrapping
+ var rightOverLeft = (CursorWrapsHorizontally && ((toX + rowWidth - fromX) < fromX - toX));
+
+ if ((toY < fromY && !downOverUp) || upOverDown)
+ {
+ cursorMovements.Add(MoveCursor.Up);
+ fromY = (fromY + rows - 1) % rows;
+ }
+ // go down?
+ else if (fromY < toY || downOverUp)
+ {
+ cursorMovements.Add(MoveCursor.Down);
+ fromY = (fromY + 1) % rows;
+ }
+ // go left? toX < fromX
+ else if ((fromX > toX && !rightOverLeft) || leftOverRight)
+ {
+ cursorMovements.Add(MoveCursor.Left);
+ fromX = (fromX + rowWidth - 1) % rowWidth;
+ }
+ // go right? toX > fromX
+ else if ((toX > fromX) || rightOverLeft)
+ {
+ cursorMovements.Add(MoveCursor.Right);
+ fromX = (fromX + 1) % rowWidth;
+ }
+
+ fromKey = layout[(fromY * rowWidth) + fromX];
+ }
+
+ return cursorMovements;
+ }
+ }
+}
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/OnScreenKeyboardScripter.Lib.csproj b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/OnScreenKeyboardScripter.Lib.csproj
new file mode 100644
index 0000000..f52e045
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/OnScreenKeyboardScripter.Lib.csproj
@@ -0,0 +1,57 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {67C25F06-53A5-4536-8FE2-C8C92795B95A}
+ Library
+ Properties
+ OnScreenKeyboardScripter.Lib
+ OnScreenKeyboardScripter.Lib
+ v4.6.1
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\StructureMap.4.6.1\lib\net45\StructureMap.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Properties/AssemblyInfo.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b9bd70e
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("OnScreenKeyboardScripter.Lib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("OnScreenKeyboardScripter.Lib")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("67c25f06-53a5-4536-8fe2-c8c92795b95a")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Scripter.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Scripter.cs
new file mode 100644
index 0000000..6eb6d64
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/Scripter.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OnScreenKeyboardScripter.Lib
+{
+ ///
+ /// Translates keyboard cursor movements and DVR actions into comma-separated "action" sequence of characters
+ ///
+ ///
+ public class Scripter : IScripter
+ {
+ ///
+ /// Gets the comma-separated "action" sequence of characters from
+ ///
+ /// The on-screen keyboard representation
+ /// The text input to translate
+ ///
+ ///
+ public string GetPath(IKeyboard keyboard, string input)
+ {
+ List path = new List();
+
+ if (keyboard == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ if (!string.IsNullOrEmpty(input))
+ {
+ char lastkey = 'A';
+ foreach(var nextkey in input.ToUpper())
+ {
+ if (nextkey == ' ')
+ {
+ path.Add('S');
+ }
+ else
+ {
+ var cursorPath = keyboard.GetCursorPath(lastkey, nextkey)
+ .Select(mc => Enum.GetName(typeof(MoveCursor), mc)[0])
+ .ToArray();
+ if (cursorPath.Length > 0)
+ {
+ path.AddRange(cursorPath);
+ path.Add('#');
+ }
+ lastkey = nextkey;
+ }
+ }
+ }
+
+ return string.Join(",", path);
+ }
+ }
+}
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/packages.config b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/packages.config
new file mode 100644
index 0000000..58ae58e
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Lib/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/KeyboardTests.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/KeyboardTests.cs
new file mode 100644
index 0000000..a1b621b
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/KeyboardTests.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace OnScreenKeyboardScripter.Test
+{
+ [TestClass]
+ public class KeyboardTests
+ {
+ [TestMethod]
+ public void GetCursorPath_fromKeyNotRecognized_Fail_NotImplementedException()
+ {
+ Assert.ThrowsException(
+ () =>
+ {
+ new OnScreenKeyboardScripter.Lib.Keyboard().GetCursorPath('\0', 'A');
+ });
+ }
+ [TestMethod]
+ public void GetCursorPath_toKeyNotRecognized_Fail_NotImplementedException()
+ {
+ Assert.ThrowsException(
+ () =>
+ {
+ new OnScreenKeyboardScripter.Lib.Keyboard().GetCursorPath('A', '\0');
+ });
+ }
+ [TestMethod]
+ public void GetCursorPath_fromGtoA_Success_Up()
+ {
+ var path = new OnScreenKeyboardScripter.Lib.Keyboard()
+ .GetCursorPath('G', 'A');
+
+ var expected = new List()
+ { Lib.MoveCursor.Up };
+ Assert.IsTrue(expected.SequenceEqual(path));
+ }
+ [TestMethod]
+ public void GetCursorPath_fromAto4_Success_Up()
+ {
+ var path = new OnScreenKeyboardScripter.Lib.Keyboard()
+ .GetCursorPath('A', '4');
+
+ var expected = new List()
+ { Lib.MoveCursor.Up };
+ Assert.IsTrue(expected.SequenceEqual(path));
+ }
+ [TestMethod]
+ public void GetCursorPath_from5toB_Success_Down()
+ {
+ var path = new OnScreenKeyboardScripter.Lib.Keyboard()
+ .GetCursorPath('5', 'B');
+
+ var expected = new List()
+ { Lib.MoveCursor.Down };
+ Assert.IsTrue(expected.SequenceEqual(path));
+ }
+ [TestMethod]
+ public void GetCursorPath_fromBtoH_Success_Down()
+ {
+ var path = new OnScreenKeyboardScripter.Lib.Keyboard()
+ .GetCursorPath('B', 'H');
+
+ var expected = new List()
+ { Lib.MoveCursor.Down };
+ Assert.IsTrue(expected.SequenceEqual(path));
+ }
+
+ [TestMethod]
+ public void GetCursorPath_fromGtoL_Success_Left()
+ {
+ var path = new OnScreenKeyboardScripter.Lib.Keyboard()
+ .GetCursorPath('G', 'L');
+
+ var expected = new List()
+ { Lib.MoveCursor.Left };
+ Assert.IsTrue(expected.SequenceEqual(path));
+ }
+ [TestMethod]
+ public void GetCursorPath_fromLtoK_Success_Left()
+ {
+ var path = new OnScreenKeyboardScripter.Lib.Keyboard()
+ .GetCursorPath('L', 'K');
+
+ var expected = new List()
+ { Lib.MoveCursor.Left };
+ Assert.IsTrue(expected.SequenceEqual(path));
+ }
+ [TestMethod]
+ public void GetCursorPath_fromRtoM_Success_Right()
+ {
+ var path = new OnScreenKeyboardScripter.Lib.Keyboard()
+ .GetCursorPath('R', 'M');
+
+ var expected = new List()
+ { Lib.MoveCursor.Right };
+ Assert.IsTrue(expected.SequenceEqual(path));
+ }
+ [TestMethod]
+ public void GetCursorPath_fromMtoN_Success_Right()
+ {
+ var path = new OnScreenKeyboardScripter.Lib.Keyboard()
+ .GetCursorPath('M', 'N');
+
+ var expected = new List()
+ { Lib.MoveCursor.Right };
+ Assert.IsTrue(expected.SequenceEqual(path));
+ }
+ }
+}
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/OnScreenKeyboardScripter.Test.csproj b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/OnScreenKeyboardScripter.Test.csproj
new file mode 100644
index 0000000..3411b5e
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/OnScreenKeyboardScripter.Test.csproj
@@ -0,0 +1,87 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {35A77BDB-46AE-40CC-A750-CB57157DA6B3}
+ Library
+ Properties
+ OnScreenKeyboardScripter.Test
+ OnScreenKeyboardScripter.Test
+ v4.6.1
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 15.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Castle.Core.4.2.1\lib\net45\Castle.Core.dll
+
+
+ ..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
+
+
+ ..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
+
+
+ ..\packages\Moq.4.8.2\lib\net45\Moq.dll
+
+
+
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+ {67c25f06-53a5-4536-8fe2-c8c92795b95a}
+ OnScreenKeyboardScripter.Lib
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/Properties/AssemblyInfo.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1f4a31c
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("OnScreenKeyboardScripter.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("OnScreenKeyboardScripter.Test")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+
+[assembly: Guid("35a77bdb-46ae-40cc-a750-cb57157da6b3")]
+
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/ScripterTests.cs b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/ScripterTests.cs
new file mode 100644
index 0000000..5dba490
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/ScripterTests.cs
@@ -0,0 +1,44 @@
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace OnScreenKeyboardScripter.Test
+{
+ [TestClass]
+ public class ScripterTests
+ {
+ [TestMethod]
+ public void GetPath_keyboardParamNull_Fail_ArgumentNullException()
+ {
+ Assert.ThrowsException(
+ () =>
+ {
+ new OnScreenKeyboardScripter.Lib.Scripter().GetPath(null, "splat");
+ });
+ }
+
+ [TestMethod]
+ public void GetPath_inputNullOrEmpty_Success_EmptyString()
+ {
+ var moqKeyboard = new Moq.Mock();
+ var result = new OnScreenKeyboardScripter.Lib.Scripter().GetPath(moqKeyboard.Object, "");
+ Assert.AreEqual(string.Empty, result);
+ }
+
+ [TestMethod]
+ public void GetPath_keyboardGetCursorPathException_Fail_AllowExceptionToBubbleThrough()
+ {
+ var moqKeyboard = new Moq.Mock();
+
+ // pick and exception that won't be thrown from library
+ moqKeyboard.Setup(fn => fn.GetCursorPath(Moq.It.IsAny(), Moq.It.IsAny()))
+ .Throws(new DuplicateWaitObjectException("splat"));
+
+ // make sure we get THAT exception
+ Assert.ThrowsException(
+ () =>
+ {
+ new OnScreenKeyboardScripter.Lib.Scripter().GetPath(moqKeyboard.Object, "splat");
+ });
+ }
+ }
+}
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/packages.config b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/packages.config
new file mode 100644
index 0000000..de82217
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.Test/packages.config
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OnScreenKeyboardScripter/OnScreenKeyboardScripter.sln b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.sln
new file mode 100644
index 0000000..b788d0b
--- /dev/null
+++ b/OnScreenKeyboardScripter/OnScreenKeyboardScripter.sln
@@ -0,0 +1,42 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27428.2002
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnScreenKeyboardScripter.Lib", "OnScreenKeyboardScripter.Lib\OnScreenKeyboardScripter.Lib.csproj", "{67C25F06-53A5-4536-8FE2-C8C92795B95A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnScreenKeyboardScripter.Demo", "OnScreenKeyboardScripter.Demo\OnScreenKeyboardScripter.Demo.csproj", "{DBA825CE-715D-4F3A-BD08-BDD8A3490CAA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnScreenKeyboardScripter.Test", "OnScreenKeyboardScripter.Test\OnScreenKeyboardScripter.Test.csproj", "{35A77BDB-46AE-40CC-A750-CB57157DA6B3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2F6C9256-F13A-43B8-AB14-726587EDFE24}"
+ ProjectSection(SolutionItems) = preProject
+ ..\README.md = ..\README.md
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {67C25F06-53A5-4536-8FE2-C8C92795B95A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {67C25F06-53A5-4536-8FE2-C8C92795B95A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {67C25F06-53A5-4536-8FE2-C8C92795B95A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {67C25F06-53A5-4536-8FE2-C8C92795B95A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DBA825CE-715D-4F3A-BD08-BDD8A3490CAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DBA825CE-715D-4F3A-BD08-BDD8A3490CAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DBA825CE-715D-4F3A-BD08-BDD8A3490CAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DBA825CE-715D-4F3A-BD08-BDD8A3490CAA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {35A77BDB-46AE-40CC-A750-CB57157DA6B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {35A77BDB-46AE-40CC-A750-CB57157DA6B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {35A77BDB-46AE-40CC-A750-CB57157DA6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {35A77BDB-46AE-40CC-A750-CB57157DA6B3}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B8391A64-9B34-4907-ADFD-71CBE4DBEC57}
+ EndGlobalSection
+EndGlobal
diff --git a/README.md b/README.md
index 2c16e5c..8854f06 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,26 @@
On Screen Keyboard
==================
+The Solution
+------------
+There are three source folders to the solution:
+
+##### OnScreenKeyboardScripter.Demo
+
+Simple console application built off OnScreenKeyboardScripter.Lib that reads in a text file and writes out screen keyboard action "path" per line.
+
+##### OnScreenKeyboardScripter.Lib
+
+The library for transforming an input into keyboard actions. Keyboard and scripting are decoupled so other keyboard and scripting algorithms can be used.
+
+NOTE: exceptions are not handled here - they are allowed to bubble out of OnScreenKeyboardScripter.Lib. An example of handling exceptions from there can be seen in the OnScreenKeyboardScripter.Demo project.
+
+##### OnScreenKeyboardScripter.Test
+
+Unit tests for OnScreenKeyboardScripter.Lib.
+
+
+
The Problem
-----------
On screen keyboards are the bane of DVR users. To help alleviate the pain, one local company is asking you to implement part of a voice to text search for their DVR by developing an algorithm to script the on screen keyboard.