Skip to content

Commit

Permalink
feat: add GoalStructure (#25)
Browse files Browse the repository at this point in the history
* wip: overgave aan Thijs

* feat: implement GoalStructure

* chore: fix .editorconfig

* feat: add interfaces for easy testing

* feat: simplify goal structure

* feat: make Goal and Goalstructure inherit from interfaces.

* feat: change implementation of goal structures.

The goal structures have been altered so that they now first update the state, and then choose a goal. They also have a mechanism for interrupting and reinstating them.

* test: test the goal structures, and rework some of the tests to work with moq

* chore: conform to sonar

* fix: conform to Jens

* test: fix tests

* feat: make goal structure type contravariant

* feat: remove interruptable

* docs: fix the wording of CompletionStatus.cs

* chore: conform to sonar

* fix: improve GoalStructure tests

* refactor: rename State to Status

* fix: conform to tboefijn

Co-authored-by: Thijs Boerefijn <[email protected]>

* fix: conform to tboefijn, again

Co-authored-by: Thijs Boerefijn <[email protected]>

---------

Co-authored-by: Joachim Dekker <[email protected]>
Co-authored-by: Jens Steenmetz <[email protected]>
Co-authored-by: Thijs Boerefijn <[email protected]>
  • Loading branch information
4 people authored Apr 1, 2024
1 parent aa8db8c commit 33ea7e2
Show file tree
Hide file tree
Showing 18 changed files with 1,025 additions and 264 deletions.
72 changes: 35 additions & 37 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true

# XMLDOC settings
xmldoc_indent_size = 0

# C# files
[*.cs]

# XMLDoc settings
resharper_xmldoc_indent_size = 0

#### Core EditorConfig Options ####

# Indentation and spacing
Expand Down Expand Up @@ -107,7 +107,7 @@ csharp_style_conditional_delegate_call = true

# Modifier preferences
csharp_prefer_static_local_function = true
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
csharp_preferred_modifier_order = public, private, protected, internal, file, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, required, volatile, async
csharp_style_prefer_readonly_struct = true
csharp_style_prefer_readonly_struct_member = true

Expand Down Expand Up @@ -195,6 +195,10 @@ csharp_preserve_single_line_statements = true

# Naming rules

dotnet_naming_rule.private_members_with_underscore.severity = warning
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore

dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
Expand All @@ -203,64 +207,58 @@ dotnet_naming_rule.types_should_be_pascal_case.severity = warning
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case

dotnet_naming_rule.classes_should_be_pascal_case.severity = warning
dotnet_naming_rule.classes_should_be_pascal_case.symbols = classes
dotnet_naming_rule.classes_should_be_pascal_case.style = pascal_case

dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case

dotnet_naming_rule.private_members_with_underscore.severity = warning
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
dotnet_naming_rule.public_fields_should_be_pascal_case.severity = warning
dotnet_naming_rule.public_fields_should_be_pascal_case.symbols = public_fields
dotnet_naming_rule.public_fields_should_be_pascal_case.style = pascal_case

# Symbol specifications

dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.interface.required_modifiers =

dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum, field
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.types.required_modifiers =

dotnet_naming_symbols.classes.applicable_kinds = class, struct, enum
dotnet_naming_symbols.classes.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.classes.required_modifiers =

dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_symbols.non_field_members.required_modifiers =

dotnet_naming_symbols.private_fields.applicable_kinds = field, property
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_symbols.public_fields.applicable_kinds = field, property
dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal, protected_internal

dotnet_naming_symbols.private_fields.applicable_kinds = field, property
dotnet_naming_symbols.private_fields.applicable_accessibilities = protected, private_protected, private

# Naming styles

dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case

dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case

dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _

[*.{cs,vb}]
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
indent_size = 4
end_of_line = crlf

# Use underscores for private fields
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = internal, protected_internal, private

dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _

dotnet_naming_rule.private_fields_with_underscore.symbols = private_fields
dotnet_naming_rule.private_fields_with_underscore.style = prefix_underscore
dotnet_naming_rule.private_fields_with_underscore.symbols = private_fields
dotnet_naming_rule.private_fields_with_underscore.style = prefix_underscore
dotnet_naming_rule.private_fields_with_underscore.severity = warning
23 changes: 23 additions & 0 deletions Aplib.Core/CompletionStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Aplib.Core
{
/// <summary>
/// Represents the state of a completable object.
/// </summary>
public enum CompletionStatus
{
/// <summary>
/// Represents the status of a completable object that is not yet completed.
/// </summary>
Unfinished,

/// <summary>
/// Represents the status of a completable object that has been successfully completed.
/// </summary>
Success,

/// <summary>
/// Represents the status of a completable object that has failed to complete.
/// </summary>
Failure
}
}
80 changes: 80 additions & 0 deletions Aplib.Core/Desire/FirstOfGoalStructure.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using Aplib.Core.Belief;
using Aplib.Core.Desire.Goals;
using System;
using System.Collections.Generic;

namespace Aplib.Core.Desire
{
/// <summary>
/// Represents a goal structure that will complete if any of its children complete.
/// </summary>
/// <remarks>
/// The children of this goal structure will be executed in the order they are given.
/// </remarks>
/// <typeparam name="TBeliefSet">The beliefset of the agent.</typeparam>
public class FirstOfGoalStructure<TBeliefSet> : GoalStructure<TBeliefSet>, IDisposable
where TBeliefSet : IBeliefSet
{
private IEnumerator<IGoalStructure<TBeliefSet>> _childrenEnumerator { get; }

/// <summary>
/// Initializes a new instance of the <see cref="FirstOfGoalStructure{TBeliefSet}" /> class.
/// </summary>
/// <param name="children">The children of the goal structure.</param>
public FirstOfGoalStructure(IList<IGoalStructure<TBeliefSet>> children) : base(children)
{
_childrenEnumerator = children.GetEnumerator();
_childrenEnumerator.MoveNext();
_currentGoalStructure = _childrenEnumerator.Current;
}

/// <inheritdoc />
public override IGoal GetCurrentGoal(TBeliefSet beliefSet) => _currentGoalStructure!.GetCurrentGoal(beliefSet);

/// <inheritdoc />
public override void UpdateStatus(TBeliefSet beliefSet)
{
// Loop through all the children until one of them is unfinished or successful.
// This loop is here to prevent tail recursion.
while (true)
{
if (Status == CompletionStatus.Success) return;
_currentGoalStructure!.UpdateStatus(beliefSet);

switch (_currentGoalStructure.Status)
{
case CompletionStatus.Unfinished:
return;
case CompletionStatus.Success:
Status = CompletionStatus.Success;
return;
}

if (_childrenEnumerator.MoveNext())
{
_currentGoalStructure = _childrenEnumerator.Current;
Status = CompletionStatus.Unfinished;

// Update the Status of the new goal structure
continue;
}

Status = CompletionStatus.Failure;
return;
}
}

/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Disposes of the goal structure.
/// </summary>
/// <param name="disposing">Whether we are actually disposing.</param>
protected virtual void Dispose(bool disposing) => _childrenEnumerator.Dispose();
}
}
44 changes: 44 additions & 0 deletions Aplib.Core/Desire/GoalStructure.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Aplib.Core.Belief;
using Aplib.Core.Desire.Goals;
using System.Collections.Generic;

namespace Aplib.Core.Desire
{
/// <summary>
/// Describes a structure of goals that need to be fulfilled.
/// </summary>
public abstract class GoalStructure<TBeliefSet> : IGoalStructure<TBeliefSet> where TBeliefSet : IBeliefSet
{
/// <inheritdoc />
public CompletionStatus Status { get; protected set; }

/// <summary>
/// The children of the goal structure.
/// </summary>
protected readonly IEnumerable<IGoalStructure<TBeliefSet>> _children;

/// <summary>
/// The goal structure that is currently being fulfilled.
/// </summary>
protected IGoalStructure<TBeliefSet>? _currentGoalStructure;

/// <summary>
/// Initializes a new instance of the <see cref="GoalStructure{TBeliefSet}" /> class.
/// </summary>
/// <param name="children">The children of the goal structure.</param>
protected GoalStructure(IEnumerable<IGoalStructure<TBeliefSet>> children) => _children = children;

/// <summary>
/// Gets the current goal using the given <see cref="IBeliefSet" />.
/// </summary>
/// <param name="beliefSet">The belief set of the agent.</param>
/// <returns>The current goal to be fulfilled.</returns>
public abstract IGoal GetCurrentGoal(TBeliefSet beliefSet);

/// <summary>
/// Updates the state of the goal structure.
/// </summary>
/// <param name="beliefSet">The belief set of the agent.</param>
public abstract void UpdateStatus(TBeliefSet beliefSet);
}
}
Loading

0 comments on commit 33ea7e2

Please sign in to comment.