diff --git a/spacebattle/game.tests/Features/MoveCommand.feature b/spacebattle/game.tests/Features/MoveCommand.feature
new file mode 100644
index 0000000..42e203d
--- /dev/null
+++ b/spacebattle/game.tests/Features/MoveCommand.feature
@@ -0,0 +1,24 @@
+Функция: Прямолинейное равномерное движение без деформации
+
+Сценарий: Объект, имеющий мгновенную скорость, перемещается в пространсте
+ Дано объект находится в точке (12, 5)
+ И объект имеет мгновенную скорость (-2, 4)
+ Когда происходит прямолинейное равномерное движение без деформации
+ Тогда объект перемещается в точку (10, 9)
+
+Сценарий: Объект, положение в пространстве которого определить невозможно, невозможно переместить
+ Дано объект, положение в пространстве которого, определить невозможно
+ Когда происходит прямолинейное равномерное движение без деформации
+ Тогда операция прерывается выбросом исключения
+
+Сценарий: Объект, который не имеет мгновенную скорость, невозможно переместить
+ Дано объект, который не имеет мгновенную скорость
+ Когда происходит прямолинейное равномерное движение без деформации
+ Тогда операция прерывается выбросом исключения
+
+Сценарий: Объект, положение в пространстве измнеить невозможно, невозможно переместить
+ Дано объект находится в точке (12, 5)
+ И объект имеет мгновенную скорость (-2, 4)
+ И объект, положение в пространстке которого изменить нельзя
+ Когда происходит прямолинейное равномерное движение без деформации
+ Тогда операция прерывается выбросом исключения
\ No newline at end of file
diff --git a/spacebattle/game.tests/Features/MoveCommand.feature.cs b/spacebattle/game.tests/Features/MoveCommand.feature.cs
new file mode 100644
index 0000000..ad47353
--- /dev/null
+++ b/spacebattle/game.tests/Features/MoveCommand.feature.cs
@@ -0,0 +1,277 @@
+// ------------------------------------------------------------------------------
+//
+// This code was generated by SpecFlow (https://www.specflow.org/).
+// SpecFlow Version:3.9.0.0
+// SpecFlow Generator Version:3.9.0.0
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+#region Designer generated code
+#pragma warning disable
+namespace game.tests.Features
+{
+ using TechTalk.SpecFlow;
+ using System;
+ using System.Linq;
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ public partial class ПрямолинейноеРавномерноеДвижениеБезДеформацииFeature : object, Xunit.IClassFixture<ПрямолинейноеРавномерноеДвижениеБезДеформацииFeature.FixtureData>, System.IDisposable
+ {
+
+ private static TechTalk.SpecFlow.ITestRunner testRunner;
+
+ private string[] _featureTags = ((string[])(null));
+
+ private Xunit.Abstractions.ITestOutputHelper _testOutputHelper;
+
+#line 1 "MoveCommand.feature"
+#line hidden
+
+ public ПрямолинейноеРавномерноеДвижениеБезДеформацииFeature(ПрямолинейноеРавномерноеДвижениеБезДеформацииFeature.FixtureData fixtureData, game_tests_XUnitAssemblyFixture assemblyFixture, Xunit.Abstractions.ITestOutputHelper testOutputHelper)
+ {
+ this._testOutputHelper = testOutputHelper;
+ this.TestInitialize();
+ }
+
+ public static void FeatureSetup()
+ {
+ testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
+ TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("ru-RU"), "Features", "Прямолинейное равномерное движение без деформации", null, ProgrammingLanguage.CSharp, ((string[])(null)));
+ testRunner.OnFeatureStart(featureInfo);
+ }
+
+ public static void FeatureTearDown()
+ {
+ testRunner.OnFeatureEnd();
+ testRunner = null;
+ }
+
+ public virtual void TestInitialize()
+ {
+ }
+
+ public virtual void TestTearDown()
+ {
+ testRunner.OnScenarioEnd();
+ }
+
+ public virtual void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
+ {
+ testRunner.OnScenarioInitialize(scenarioInfo);
+ testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(_testOutputHelper);
+ }
+
+ public virtual void ScenarioStart()
+ {
+ testRunner.OnScenarioStart();
+ }
+
+ public virtual void ScenarioCleanup()
+ {
+ testRunner.CollectScenarioErrors();
+ }
+
+ void System.IDisposable.Dispose()
+ {
+ this.TestTearDown();
+ }
+
+ [Xunit.SkippableFactAttribute(DisplayName="Объект, имеющий мгновенную скорость, перемещается в пространсте")]
+ [Xunit.TraitAttribute("FeatureTitle", "Прямолинейное равномерное движение без деформации")]
+ [Xunit.TraitAttribute("Description", "Объект, имеющий мгновенную скорость, перемещается в пространсте")]
+ public virtual void ОбъектИмеющийМгновеннуюСкоростьПеремещаетсяВПространсте()
+ {
+ string[] tagsOfScenario = ((string[])(null));
+ System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary();
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Объект, имеющий мгновенную скорость, перемещается в пространсте", null, tagsOfScenario, argumentsOfScenario, this._featureTags);
+#line 3
+this.ScenarioInitialize(scenarioInfo);
+#line hidden
+ bool isScenarioIgnored = default(bool);
+ bool isFeatureIgnored = default(bool);
+ if ((tagsOfScenario != null))
+ {
+ isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((this._featureTags != null))
+ {
+ isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((isScenarioIgnored || isFeatureIgnored))
+ {
+ testRunner.SkipScenario();
+ }
+ else
+ {
+ this.ScenarioStart();
+#line 4
+ testRunner.Given("объект находится в точке (12, 5)", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Дано ");
+#line hidden
+#line 5
+ testRunner.And("объект имеет мгновенную скорость (-2, 4)", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "И ");
+#line hidden
+#line 6
+ testRunner.When("происходит прямолинейное равномерное движение без деформации", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Когда ");
+#line hidden
+#line 7
+ testRunner.Then("объект перемещается в точку (10, 9)", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Тогда ");
+#line hidden
+ }
+ this.ScenarioCleanup();
+ }
+
+ [Xunit.SkippableFactAttribute(DisplayName="Объект, положение в пространстве которого определить невозможно, невозможно перем" +
+ "естить")]
+ [Xunit.TraitAttribute("FeatureTitle", "Прямолинейное равномерное движение без деформации")]
+ [Xunit.TraitAttribute("Description", "Объект, положение в пространстве которого определить невозможно, невозможно перем" +
+ "естить")]
+ public virtual void ОбъектПоложениеВПространствеКоторогоОпределитьНевозможноНевозможноПереместить()
+ {
+ string[] tagsOfScenario = ((string[])(null));
+ System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary();
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Объект, положение в пространстве которого определить невозможно, невозможно перем" +
+ "естить", null, tagsOfScenario, argumentsOfScenario, this._featureTags);
+#line 9
+this.ScenarioInitialize(scenarioInfo);
+#line hidden
+ bool isScenarioIgnored = default(bool);
+ bool isFeatureIgnored = default(bool);
+ if ((tagsOfScenario != null))
+ {
+ isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((this._featureTags != null))
+ {
+ isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((isScenarioIgnored || isFeatureIgnored))
+ {
+ testRunner.SkipScenario();
+ }
+ else
+ {
+ this.ScenarioStart();
+#line 10
+ testRunner.Given("объект, положение в пространстве которого, определить невозможно", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Дано ");
+#line hidden
+#line 11
+ testRunner.When("происходит прямолинейное равномерное движение без деформации", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Когда ");
+#line hidden
+#line 12
+ testRunner.Then("операция прерывается выбросом исключения", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Тогда ");
+#line hidden
+ }
+ this.ScenarioCleanup();
+ }
+
+ [Xunit.SkippableFactAttribute(DisplayName="Объект, который не имеет мгновенную скорость, невозможно переместить")]
+ [Xunit.TraitAttribute("FeatureTitle", "Прямолинейное равномерное движение без деформации")]
+ [Xunit.TraitAttribute("Description", "Объект, который не имеет мгновенную скорость, невозможно переместить")]
+ public virtual void ОбъектКоторыйНеИмеетМгновеннуюСкоростьНевозможноПереместить()
+ {
+ string[] tagsOfScenario = ((string[])(null));
+ System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary();
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Объект, который не имеет мгновенную скорость, невозможно переместить", null, tagsOfScenario, argumentsOfScenario, this._featureTags);
+#line 14
+this.ScenarioInitialize(scenarioInfo);
+#line hidden
+ bool isScenarioIgnored = default(bool);
+ bool isFeatureIgnored = default(bool);
+ if ((tagsOfScenario != null))
+ {
+ isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((this._featureTags != null))
+ {
+ isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((isScenarioIgnored || isFeatureIgnored))
+ {
+ testRunner.SkipScenario();
+ }
+ else
+ {
+ this.ScenarioStart();
+#line 15
+ testRunner.Given("объект, который не имеет мгновенную скорость", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Дано ");
+#line hidden
+#line 16
+ testRunner.When("происходит прямолинейное равномерное движение без деформации", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Когда ");
+#line hidden
+#line 17
+ testRunner.Then("операция прерывается выбросом исключения", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Тогда ");
+#line hidden
+ }
+ this.ScenarioCleanup();
+ }
+
+ [Xunit.SkippableFactAttribute(DisplayName="Объект, положение в пространстве измнеить невозможно, невозможно переместить")]
+ [Xunit.TraitAttribute("FeatureTitle", "Прямолинейное равномерное движение без деформации")]
+ [Xunit.TraitAttribute("Description", "Объект, положение в пространстве измнеить невозможно, невозможно переместить")]
+ public virtual void ОбъектПоложениеВПространствеИзмнеитьНевозможноНевозможноПереместить()
+ {
+ string[] tagsOfScenario = ((string[])(null));
+ System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary();
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Объект, положение в пространстве измнеить невозможно, невозможно переместить", null, tagsOfScenario, argumentsOfScenario, this._featureTags);
+#line 19
+this.ScenarioInitialize(scenarioInfo);
+#line hidden
+ bool isScenarioIgnored = default(bool);
+ bool isFeatureIgnored = default(bool);
+ if ((tagsOfScenario != null))
+ {
+ isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((this._featureTags != null))
+ {
+ isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((isScenarioIgnored || isFeatureIgnored))
+ {
+ testRunner.SkipScenario();
+ }
+ else
+ {
+ this.ScenarioStart();
+#line 20
+ testRunner.Given("объект находится в точке (12, 5)", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Дано ");
+#line hidden
+#line 21
+ testRunner.And("объект имеет мгновенную скорость (-2, 4)", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "И ");
+#line hidden
+#line 22
+ testRunner.And("объект, положение в пространстке которого изменить нельзя", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "И ");
+#line hidden
+#line 23
+ testRunner.When("происходит прямолинейное равномерное движение без деформации", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Когда ");
+#line hidden
+#line 24
+ testRunner.Then("операция прерывается выбросом исключения", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Тогда ");
+#line hidden
+ }
+ this.ScenarioCleanup();
+ }
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ public class FixtureData : System.IDisposable
+ {
+
+ public FixtureData()
+ {
+ ПрямолинейноеРавномерноеДвижениеБезДеформацииFeature.FeatureSetup();
+ }
+
+ void System.IDisposable.Dispose()
+ {
+ ПрямолинейноеРавномерноеДвижениеБезДеформацииFeature.FeatureTearDown();
+ }
+ }
+ }
+}
+#pragma warning restore
+#endregion
diff --git a/spacebattle/game.tests/Features/Vector.feature b/spacebattle/game.tests/Features/Vector.feature
new file mode 100644
index 0000000..d7d41fd
--- /dev/null
+++ b/spacebattle/game.tests/Features/Vector.feature
@@ -0,0 +1,17 @@
+Функция: Вектор n-мерного веторного пространства
+Для описания атрибутов объекта - положение в пространстве, мгновенная скоровть
+используются объекты класса Vector.
+
+@позитивный
+Сценарий: Два веткора можно сложить
+ Дано двухмерный вектор a с координатами (2, 3)
+ И двухмерный вектор b с координатами (2, -1)
+ Когда складываем веторы a и b
+ Тогда получаем вектор с координатами (4, 2).
+
+@негативный
+Сценарий: Два вектора разной размерности складывать нельзя
+ Дано двухмерный вектор a с координатами (2, 3)
+ И трехмерный вектор b с координатами (2, -1, 0)
+ Когда складываем веторы a и b
+ Тогда выбрасывается исключение
\ No newline at end of file
diff --git a/spacebattle/game.tests/Features/Vector.feature.cs b/spacebattle/game.tests/Features/Vector.feature.cs
new file mode 100644
index 0000000..5fbaefc
--- /dev/null
+++ b/spacebattle/game.tests/Features/Vector.feature.cs
@@ -0,0 +1,194 @@
+// ------------------------------------------------------------------------------
+//
+// This code was generated by SpecFlow (https://www.specflow.org/).
+// SpecFlow Version:3.9.0.0
+// SpecFlow Generator Version:3.9.0.0
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+#region Designer generated code
+#pragma warning disable
+namespace game.tests.Features
+{
+ using TechTalk.SpecFlow;
+ using System;
+ using System.Linq;
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ public partial class ВекторN_МерногоВеторногоПространстваFeature : object, Xunit.IClassFixture<ВекторN_МерногоВеторногоПространстваFeature.FixtureData>, System.IDisposable
+ {
+
+ private static TechTalk.SpecFlow.ITestRunner testRunner;
+
+ private string[] _featureTags = ((string[])(null));
+
+ private Xunit.Abstractions.ITestOutputHelper _testOutputHelper;
+
+#line 1 "Vector.feature"
+#line hidden
+
+ public ВекторN_МерногоВеторногоПространстваFeature(ВекторN_МерногоВеторногоПространстваFeature.FixtureData fixtureData, game_tests_XUnitAssemblyFixture assemblyFixture, Xunit.Abstractions.ITestOutputHelper testOutputHelper)
+ {
+ this._testOutputHelper = testOutputHelper;
+ this.TestInitialize();
+ }
+
+ public static void FeatureSetup()
+ {
+ testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
+ TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("ru-RU"), "Features", "Вектор n-мерного веторного пространства", "Для описания атрибутов объекта - положение в пространстве, мгновенная скоровть \r\n" +
+ "используются объекты класса Vector.", ProgrammingLanguage.CSharp, ((string[])(null)));
+ testRunner.OnFeatureStart(featureInfo);
+ }
+
+ public static void FeatureTearDown()
+ {
+ testRunner.OnFeatureEnd();
+ testRunner = null;
+ }
+
+ public virtual void TestInitialize()
+ {
+ }
+
+ public virtual void TestTearDown()
+ {
+ testRunner.OnScenarioEnd();
+ }
+
+ public virtual void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
+ {
+ testRunner.OnScenarioInitialize(scenarioInfo);
+ testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(_testOutputHelper);
+ }
+
+ public virtual void ScenarioStart()
+ {
+ testRunner.OnScenarioStart();
+ }
+
+ public virtual void ScenarioCleanup()
+ {
+ testRunner.CollectScenarioErrors();
+ }
+
+ void System.IDisposable.Dispose()
+ {
+ this.TestTearDown();
+ }
+
+ [Xunit.SkippableFactAttribute(DisplayName="Два веткора можно сложить")]
+ [Xunit.TraitAttribute("FeatureTitle", "Вектор n-мерного веторного пространства")]
+ [Xunit.TraitAttribute("Description", "Два веткора можно сложить")]
+ [Xunit.TraitAttribute("Category", "позитивный")]
+ public virtual void ДваВеткораМожноСложить()
+ {
+ string[] tagsOfScenario = new string[] {
+ "позитивный"};
+ System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary();
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Два веткора можно сложить", null, tagsOfScenario, argumentsOfScenario, this._featureTags);
+#line 6
+this.ScenarioInitialize(scenarioInfo);
+#line hidden
+ bool isScenarioIgnored = default(bool);
+ bool isFeatureIgnored = default(bool);
+ if ((tagsOfScenario != null))
+ {
+ isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((this._featureTags != null))
+ {
+ isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((isScenarioIgnored || isFeatureIgnored))
+ {
+ testRunner.SkipScenario();
+ }
+ else
+ {
+ this.ScenarioStart();
+#line 7
+ testRunner.Given("двухмерный вектор a с координатами (2, 3)", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Дано ");
+#line hidden
+#line 8
+ testRunner.And("двухмерный вектор b с координатами (2, -1)", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "И ");
+#line hidden
+#line 9
+ testRunner.When("складываем веторы a и b", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Когда ");
+#line hidden
+#line 10
+ testRunner.Then("получаем вектор с координатами (4, 2).", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Тогда ");
+#line hidden
+ }
+ this.ScenarioCleanup();
+ }
+
+ [Xunit.SkippableFactAttribute(DisplayName="Два вектора разной размерности складывать нельзя")]
+ [Xunit.TraitAttribute("FeatureTitle", "Вектор n-мерного веторного пространства")]
+ [Xunit.TraitAttribute("Description", "Два вектора разной размерности складывать нельзя")]
+ [Xunit.TraitAttribute("Category", "негативный")]
+ public virtual void ДваВектораРазнойРазмерностиСкладыватьНельзя()
+ {
+ string[] tagsOfScenario = new string[] {
+ "негативный"};
+ System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary();
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Два вектора разной размерности складывать нельзя", null, tagsOfScenario, argumentsOfScenario, this._featureTags);
+#line 13
+this.ScenarioInitialize(scenarioInfo);
+#line hidden
+ bool isScenarioIgnored = default(bool);
+ bool isFeatureIgnored = default(bool);
+ if ((tagsOfScenario != null))
+ {
+ isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((this._featureTags != null))
+ {
+ isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
+ }
+ if ((isScenarioIgnored || isFeatureIgnored))
+ {
+ testRunner.SkipScenario();
+ }
+ else
+ {
+ this.ScenarioStart();
+#line 14
+ testRunner.Given("двухмерный вектор a с координатами (2, 3)", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Дано ");
+#line hidden
+#line 15
+ testRunner.And("трехмерный вектор b с координатами (2, -1, 0)", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "И ");
+#line hidden
+#line 16
+ testRunner.When("складываем веторы a и b", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Когда ");
+#line hidden
+#line 17
+ testRunner.Then("выбрасывается исключение", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Тогда ");
+#line hidden
+ }
+ this.ScenarioCleanup();
+ }
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ public class FixtureData : System.IDisposable
+ {
+
+ public FixtureData()
+ {
+ ВекторN_МерногоВеторногоПространстваFeature.FeatureSetup();
+ }
+
+ void System.IDisposable.Dispose()
+ {
+ ВекторN_МерногоВеторногоПространстваFeature.FeatureTearDown();
+ }
+ }
+ }
+}
+#pragma warning restore
+#endregion
diff --git a/spacebattle/game.tests/ImplicitUsings.cs b/spacebattle/game.tests/ImplicitUsings.cs
new file mode 100644
index 0000000..d255cb1
--- /dev/null
+++ b/spacebattle/game.tests/ImplicitUsings.cs
@@ -0,0 +1,3 @@
+global using FluentAssertions;
+global using TechTalk.SpecFlow;
+global using Xunit;
diff --git "a/spacebattle/game.tests/StepDefinitions/\320\222\320\265\320\272\321\202\320\276\321\200N_\320\234\320\265\321\200\320\275\320\276\320\263\320\276\320\222\320\265\321\202\320\276\321\200\320\275\320\276\320\263\320\276\320\237\321\200\320\276\321\201\321\202\321\200\320\260\320\275\321\201\321\202\320\262\320\260StepDefinitions.cs" "b/spacebattle/game.tests/StepDefinitions/\320\222\320\265\320\272\321\202\320\276\321\200N_\320\234\320\265\321\200\320\275\320\276\320\263\320\276\320\222\320\265\321\202\320\276\321\200\320\275\320\276\320\263\320\276\320\237\321\200\320\276\321\201\321\202\321\200\320\260\320\275\321\201\321\202\320\262\320\260StepDefinitions.cs"
new file mode 100644
index 0000000..519ed1b
--- /dev/null
+++ "b/spacebattle/game.tests/StepDefinitions/\320\222\320\265\320\272\321\202\320\276\321\200N_\320\234\320\265\321\200\320\275\320\276\320\263\320\276\320\222\320\265\321\202\320\276\321\200\320\275\320\276\320\263\320\276\320\237\321\200\320\276\321\201\321\202\321\200\320\260\320\275\321\201\321\202\320\262\320\260StepDefinitions.cs"
@@ -0,0 +1,56 @@
+namespace SpaceBattle.Tests.StepDefinitions
+{
+ [Binding]
+ public class ВекторN_МерногоВеторногоПространстваStepDefinitions
+ {
+ Vector a;
+ Vector b;
+ Vector result;
+ Exception _ex;
+
+
+ [Given(@"двухмерный вектор a с координатами \((.*), (.*)\)")]
+ public void GivenВекторAСКоординатами(int x, int y)
+ {
+ a = new Vector(x, y);
+ }
+
+ [Given(@"двухмерный вектор b с координатами \((.*), (.*)\)")]
+ public void GivenВекторBСКоординатами(int x, int y)
+ {
+ b = new Vector(x, y);
+ }
+
+ [Given(@"трехмерный вектор b с координатами \((.*), (.*), (.*)\)")]
+ public void GivenВекторBСКоординатами(int x, int y, int z)
+ {
+ b = new Vector(x, y, z);
+ }
+
+ [When(@"складываем веторы a и b")]
+ public void WhenСкладываемВеторыAИB()
+ {
+ try
+ {
+ result = a + b;
+ }
+ catch(Exception ex)
+ {
+ _ex = ex;
+ }
+ }
+
+ [Then(@"получаем вектор с координатами \((.*), (.*)\)\.")]
+ public void ThenПолучаемВекторСКоординатами_(int x, int y)
+ {
+ Assert.Equal(new Vector(x, y), result);
+ }
+
+ [Then(@"выбрасывается исключение")]
+ public void ThenВыбрасываетсяИсключение()
+ {
+ Assert.ThrowsAny(() => throw _ex);
+ }
+
+ }
+}
diff --git "a/spacebattle/game.tests/StepDefinitions/\320\237\321\200\321\217\320\274\320\276\320\273\320\270\320\275\320\265\320\271\320\275\320\276\320\265\320\240\320\260\320\262\320\275\320\276\320\274\320\265\321\200\320\275\320\276\320\265\320\224\320\262\320\270\320\266\320\265\320\275\320\270\320\265\320\221\320\265\320\267\320\224\320\265\321\204\320\276\321\200\320\274\320\260\321\206\320\270\320\270StepDefinitions.cs" "b/spacebattle/game.tests/StepDefinitions/\320\237\321\200\321\217\320\274\320\276\320\273\320\270\320\275\320\265\320\271\320\275\320\276\320\265\320\240\320\260\320\262\320\275\320\276\320\274\320\265\321\200\320\275\320\276\320\265\320\224\320\262\320\270\320\266\320\265\320\275\320\270\320\265\320\221\320\265\320\267\320\224\320\265\321\204\320\276\321\200\320\274\320\260\321\206\320\270\320\270StepDefinitions.cs"
new file mode 100644
index 0000000..dc79496
--- /dev/null
+++ "b/spacebattle/game.tests/StepDefinitions/\320\237\321\200\321\217\320\274\320\276\320\273\320\270\320\275\320\265\320\271\320\275\320\276\320\265\320\240\320\260\320\262\320\275\320\276\320\274\320\265\321\200\320\275\320\276\320\265\320\224\320\262\320\270\320\266\320\265\320\275\320\270\320\265\320\221\320\265\320\267\320\224\320\265\321\204\320\276\321\200\320\274\320\260\321\206\320\270\320\270StepDefinitions.cs"
@@ -0,0 +1,85 @@
+using Moq;
+using SpaceBattle;
+
+namespace Spacebattle.tests.StepDefinitions
+{
+ [Binding]
+ public class ПрямолинейноеРавномерноеДвижениеБезДеформацииStepDefinitions
+ {
+ Mock _obj = new Mock();
+ Exception? _ex = null;
+
+ [Given(@"объект находится в точке \((.*), (.*)\)")]
+ public void GivenОбъектНаходитсяВТочке(int p0, int p1)
+ {
+ _obj.SetupGet(
+ o => o.Location
+ )
+ .Returns(new Vector(p0, p1))
+ .Verifiable();
+ }
+
+ [Given(@"объект имеет мгновенную скорость \((.*), (.*)\)")]
+ public void GivenОбъектИмеетМгновеннуюСкорость(int p0, int p1)
+ {
+ _obj.SetupGet(
+ o => o.Velocity
+ )
+ .Returns(new Vector(p0, p1))
+ .Verifiable();
+ }
+
+ [When(@"происходит прямолинейное равномерное движение без деформации")]
+ public void WhenПроисходитПрямолинейноеРавномерноеДвижениеБезДеформации()
+ {
+ try
+ {
+ new MoveCommand(_obj.Object).Execute();
+ }
+ catch (Exception ex)
+ {
+ _ex = ex;
+ }
+ }
+
+ [Then(@"объект перемещается в точку \((.*), (.*)\)")]
+ public void ThenОбъектПеремещаетсяВТочку(int p0, int p1)
+ {
+ _obj.VerifySet(o => o.Location = new Vector(p0, p1));
+ Assert.Null(_ex);
+ }
+
+ [Given("объект, положение в пространстве которого, определить невозможно")]
+ public void GivenОбъектПоложениеВПространствеКоторогоОпределитьНевозможно()
+ {
+ _obj.SetupGet(
+ o => o.Location
+ )
+ .Throws()
+ .Verifiable();
+ }
+
+
+ [Given(@"объект, который не имеет мгновенную скорость")]
+ public void GivenОбъектКоторыйНеИмеетМгновеннуюСкорость()
+ {
+ _obj.SetupGet(
+ o => o.Velocity
+ )
+ .Throws()
+ .Verifiable();
+ }
+
+ [Given("объект, положение в пространстке которого изменить нельзя")]
+ public void GivenОбъектПоложениеВПространсткеКоторогоИзменитьНельзя()
+ {
+ _obj.SetupSet(o => o.Location = It.IsAny()).Throws().Verifiable();
+ }
+
+ [Then(@"операция прерывается выбросом исключения")]
+ public void ThenОперацияПрерываетсяВыбросомИсключения()
+ {
+ Assert.NotNull(_ex);
+ }
+ }
+}
diff --git a/spacebattle/game.tests/game.tests.csproj b/spacebattle/game.tests/game.tests.csproj
new file mode 100644
index 0000000..d770025
--- /dev/null
+++ b/spacebattle/game.tests/game.tests.csproj
@@ -0,0 +1,36 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spacebattle/game.tests/specflow.json b/spacebattle/game.tests/specflow.json
new file mode 100644
index 0000000..569efb8
--- /dev/null
+++ b/spacebattle/game.tests/specflow.json
@@ -0,0 +1,13 @@
+{
+ "exclude": [
+ "**/bin",
+ "**/bower_components",
+ "**/jspm_packages",
+ "**/node_modules",
+ "**/obj",
+ "**/platforms"
+ ],
+ "language": {
+ "feature": "ru-RU"
+ }
+}
diff --git a/spacebattle/game/IMovable.cs b/spacebattle/game/IMovable.cs
new file mode 100644
index 0000000..23a8809
--- /dev/null
+++ b/spacebattle/game/IMovable.cs
@@ -0,0 +1,16 @@
+namespace SpaceBattle
+{
+ public interface IMovable
+ {
+ Vector Location
+ {
+ get;
+ set;
+ }
+
+ Vector Velocity
+ {
+ get;
+ }
+ }
+}
diff --git a/spacebattle/game/MoveCommand.cs b/spacebattle/game/MoveCommand.cs
new file mode 100644
index 0000000..fd0fe8a
--- /dev/null
+++ b/spacebattle/game/MoveCommand.cs
@@ -0,0 +1,15 @@
+using AppServer;
+
+namespace SpaceBattle
+{
+ public class MoveCommand : ICommand
+ {
+ IMovable _movable;
+ public MoveCommand(IMovable movable) => _movable = movable;
+
+ public void Execute()
+ {
+ _movable.Location += _movable.Velocity;
+ }
+ }
+}
\ No newline at end of file
diff --git a/spacebattle/game/Vector.cs b/spacebattle/game/Vector.cs
new file mode 100644
index 0000000..747502b
--- /dev/null
+++ b/spacebattle/game/Vector.cs
@@ -0,0 +1,32 @@
+namespace SpaceBattle
+{
+ public class Vector
+ {
+ int[] _coords;
+
+ public Vector(params int[] coords) => _coords = coords;
+
+ public override bool Equals(object? obj)
+ {
+ if(obj is Vector)
+ {
+ return _coords.SequenceEqual((obj as Vector)!._coords);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return _coords.GetHashCode();
+ }
+
+ public static Vector operator+ (Vector addition1, Vector addition2)
+ {
+ return new Vector(addition1._coords.Zip(addition2._coords, (x, y) => x + y).ToArray());
+ }
+
+ }
+}
diff --git a/spacebattle/game/game.csproj b/spacebattle/game/game.csproj
new file mode 100644
index 0000000..ab9da5e
--- /dev/null
+++ b/spacebattle/game/game.csproj
@@ -0,0 +1,15 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+ ..\..\Common\core.dll
+
+
+
+
diff --git a/spacebattle/spacebattle.sln b/spacebattle/spacebattle.sln
new file mode 100644
index 0000000..b559289
--- /dev/null
+++ b/spacebattle/spacebattle.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.6.33815.320
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "game", "game\game.csproj", "{A5156887-0D6E-4F79-B83E-8E768B728F0C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "game.tests", "game.tests\game.tests.csproj", "{EADD7F79-799A-4D34-B534-3FC3E49E05FC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A5156887-0D6E-4F79-B83E-8E768B728F0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A5156887-0D6E-4F79-B83E-8E768B728F0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A5156887-0D6E-4F79-B83E-8E768B728F0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A5156887-0D6E-4F79-B83E-8E768B728F0C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EADD7F79-799A-4D34-B534-3FC3E49E05FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EADD7F79-799A-4D34-B534-3FC3E49E05FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EADD7F79-799A-4D34-B534-3FC3E49E05FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EADD7F79-799A-4D34-B534-3FC3E49E05FC}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {D2CE1A83-0742-49B7-AEC4-442288328BE3}
+ EndGlobalSection
+EndGlobal