Skip to content
This repository was archived by the owner on Jun 10, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/build*
docs/build*
/xml
docs/xml
out
mpich
cmake-build-*
.idea/
.vs/
.vscode/
scripts/variants*.csv
scripts/variants*.xlsx
*venv*
sln/
CMakeSettings.json
.DS_Store
.cache
install
*.pyc
14 changes: 14 additions & 0 deletions BugPro/BugPro.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Stateless" Version="5.13.0" />
</ItemGroup>

</Project>
193 changes: 193 additions & 0 deletions BugPro/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
using System;
using Stateless;

namespace BugWorkflow
{
public sealed class Bug
{
public enum BugState
{
New,
Triage,
WaitingInfo,
Fixing,
WaitFixApprove,
Returned,
Reopened,
Closed
}

public enum BugTrigger
{
StartTriage,
RequestMoreInfo,
BackToTriage,
StartFix,
FinisFix,
MarkNotABug,
MarkWontFix,
MarkDuplicate,
MarkCannotReproduce,
ResolveFix,
RejectFix,
Reopen
}

private readonly StateMachine<BugState, BugTrigger> _machine;

public BugState State => _machine.State;

public Bug()
{
_machine = new StateMachine<BugState, BugTrigger>(BugState.New);
ConfigureStateMachine();
}

private void ConfigureStateMachine()
{
_machine.OnUnhandledTrigger((state, trigger) =>
{
throw new InvalidOperationException(
$"триггер '{trigger}' недопустим в состоянии '{state}'.");
});

_machine.Configure(BugState.New)
.Permit(BugTrigger.StartTriage, BugState.Triage);

_machine.Configure(BugState.Triage)
.Permit(BugTrigger.RequestMoreInfo, BugState.WaitingInfo)
.Permit(BugTrigger.StartFix, BugState.Fixing)
.Permit(BugTrigger.MarkNotABug, BugState.Closed)
.Permit(BugTrigger.MarkWontFix, BugState.Closed)
.Permit(BugTrigger.MarkDuplicate, BugState.Closed);

_machine.Configure(BugState.WaitingInfo)
.Permit(BugTrigger.BackToTriage, BugState.Triage)
.Permit(BugTrigger.StartFix, BugState.Fixing);

_machine.Configure(BugState.Fixing)
.Permit(BugTrigger.FinisFix, BugState.WaitFixApprove)
.Permit(BugTrigger.RequestMoreInfo, BugState.WaitingInfo)
.Permit(BugTrigger.MarkCannotReproduce, BugState.Returned);

_machine.Configure(BugState.WaitFixApprove)
.Permit(BugTrigger.ResolveFix, BugState.Closed)
.Permit(BugTrigger.RejectFix, BugState.Returned);

_machine.Configure(BugState.Reopened)
.Permit(BugTrigger.BackToTriage, BugState.Triage);

_machine.Configure(BugState.Closed)
.Permit(BugTrigger.Reopen, BugState.Reopened);
}

public void StartTriage()
{
_machine.Fire(BugTrigger.StartTriage);
}

public void RequestMoreInfo()
{
_machine.Fire(BugTrigger.RequestMoreInfo);
}

public void BackToTriage()
{
_machine.Fire(BugTrigger.BackToTriage);
}

public void StartFix()
{
_machine.Fire(BugTrigger.StartFix);
}

public void FinishFix()
{
_machine.Fire(BugTrigger.FinisFix);
}

public void MarkNotABug()
{
_machine.Fire(BugTrigger.MarkNotABug);
}

public void MarkWontFix()
{
_machine.Fire(BugTrigger.MarkWontFix);
}

public void MarkDuplicate()
{
_machine.Fire(BugTrigger.MarkDuplicate);
}

public void MarkCannotReproduce()
{
_machine.Fire(BugTrigger.MarkCannotReproduce);
}

public void ResolveFix()
{
_machine.Fire(BugTrigger.ResolveFix);
}

public void RejectFix()
{
_machine.Fire(BugTrigger.RejectFix);
}

public void Reopen()
{
_machine.Fire(BugTrigger.Reopen);
}

public void CheckFixResult(bool solved)
{
if (solved)
ResolveFix();
else
RejectFix();
}

public override string ToString()
{
return $"State = {State}";
}
}

public static class Program
{
public static void Main()
{
var bug = new Bug();
Console.WriteLine("начальное состояние: " + bug);

bug.StartTriage();
Console.WriteLine("после StartTriage: " + bug);

bug.StartFix();
Console.WriteLine("после StartFix: " + bug);

bug.FinishFix();
Console.WriteLine("после FinishFix: " + bug);

bug.CheckFixResult(solved: true);
Console.WriteLine("после CheckFixResult(true): " + bug);

bug.Reopen();
Console.WriteLine("после Reopen: " + bug);

bug.BackToTriage();
Console.WriteLine("после BackToTriage: " + bug);

try
{
bug.ResolveFix();
}
catch (InvalidOperationException ex)
{
Console.WriteLine("Ожидаемая ошибка: " + ex.Message);
}
}
}
}
27 changes: 27 additions & 0 deletions BugTests/BugTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
</ItemGroup>

<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\BugPro\BugPro.csproj" />
</ItemGroup>

</Project>
Loading
Loading