Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REG-2230, REG-2231] Implement Validations Within Segments #370

Merged
merged 18 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 8 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
3 changes: 3 additions & 0 deletions src/gg.regression.unity.bots/Editor/Scripts/Validation.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using RegressionGames.Validation;
using StateRecorder.BotSegments.Models.SegmentValidations;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

namespace RegressionGames.Editor.Validation
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not related or relevant to the current PR... will remove in a moment, so you can ignore this for now

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been removed

{
public class RGValidationPane : EditorWindow
{
private ScrollView _mainScrollPane;

[MenuItem("Regression Games/Validation Results")]
public static void ShowMyEditor()
{
// This method is called when the user selects the menu item in the Editor
EditorWindow wnd = GetWindow<RGValidationPane>();
wnd.titleContent = new GUIContent("RG Validation Results");
wnd.Focus();
}

void CreateGUI()
{

_mainScrollPane = new ScrollView(ScrollViewMode.VerticalAndHorizontal);
rootVisualElement.Add(_mainScrollPane);

UpdateGUI();

}

void UpdateGUI()
{

_mainScrollPane.Clear();
UnsubscribeFromValidationEvents();

var validationScripts = FindObjectsOfType<RGValidateBehaviour>();

foreach (var validationScript in validationScripts)
{
var scriptContainer = new VisualElement();
scriptContainer.Add(new Label("Suite: " + validationScript.GetType().Name));
_mainScrollPane.Add(scriptContainer);

validationScript.OnValidationsUpdated += UpdateGUI;

foreach (var validator in validationScript.Validators)
{
var validatorContainer = new VisualElement();
validatorContainer.style.paddingLeft = 20;

scriptContainer.Add(validatorContainer);

var testText = "";
Color? color = null;

switch (validator.Status)
{
case SegmentValidationStatus.UNKNOWN:
testText += "? ";
break;
case SegmentValidationStatus.PASSED:
// If pass, show a green checkmark
testText += "PASS ";
color = Color.green;
break;
case SegmentValidationStatus.FAILED:
testText += "FAIL ";
color = Color.red;
break;
}

testText += validator.Method.Name;
var testLabel = new Label(testText);
if (color != null)
{
testLabel.style.color = color.Value;
}

validatorContainer.Add(testLabel);
}
}

}

private void UnsubscribeFromValidationEvents()
{
var validationScripts = FindObjectsOfType<RGValidateBehaviour>();
foreach (var validationScript in validationScripts)
{
validationScript.OnValidationsUpdated -= UpdateGUI;
}
}

}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ namespace RegressionGames.StateRecorder.BotSegments
{
public static class AndKeyFrameCriteriaEvaluator
{
public static bool Matched(bool firstSegment, int segmentNumber, bool botActionCompleted, KeyFrameCriteria criteria)
public static bool Matched(bool firstSegment, int segmentNumber, bool botActionCompleted, bool validationsCompleted, KeyFrameCriteria criteria)
{
if (criteria.data is AndKeyFrameCriteriaData { criteriaList: not null } andCriteria)
{
try
{
return KeyFrameEvaluator.Evaluator.MatchedHelper(firstSegment, segmentNumber, botActionCompleted, BooleanCriteria.And, andCriteria.criteriaList);
return KeyFrameEvaluator.Evaluator.MatchedHelper(firstSegment, segmentNumber, botActionCompleted, validationsCompleted, BooleanCriteria.And, andCriteria.criteriaList);
}
catch (Exception)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class BotSegmentsPlaybackController : MonoBehaviour

private Action<int> _loopCountCallback;

private string _lastSegmentPlaybackWarning = null;
private string _lastSegmentPlaybackWarning = null;

// We track this as a list instead of a single entry to allow the UI and game object conditions to evaluate separately
// We still only unlock the input sequences for a key frame once both UI and game object conditions are met
Expand Down Expand Up @@ -201,6 +201,7 @@ public void Pause()
foreach (var nextBotSegment in _nextBotSegments)
{
nextBotSegment.PauseAction();
nextBotSegment.PauseValidations();
}
}
}
Expand All @@ -225,6 +226,7 @@ public void Play()
foreach (var nextBotSegment in _nextBotSegments)
{
nextBotSegment.UnPauseAction();
nextBotSegment.UnPauseValidations();
}
}
}
Expand Down Expand Up @@ -253,6 +255,7 @@ public void UnloadSegmentsAndReset()
{
// stop any action
nextBotSegment.AbortAction();
nextBotSegment.StopValidations();
}
}

Expand Down Expand Up @@ -455,6 +458,7 @@ private void EvaluateBotSegments()
BotSegment firstActionSegment = _nextBotSegments[0];
try
{
firstActionSegment.ProcessValidation();
nAmKcAz marked this conversation as resolved.
Show resolved Hide resolved
var didAction = firstActionSegment.ProcessAction(transformStatuses, entityStatuses, out var error);
// only log this if we're really stuck on it
if (error == null && didAction)
Expand Down Expand Up @@ -486,6 +490,7 @@ private void EvaluateBotSegments()
nextBotSegmentIndex == 0,
nextBotSegment.Replay_SegmentNumber,
nextBotSegment.Replay_ActionCompleted,
nextBotSegment.Replay_ValidationsCompleted,
nextBotSegment.endCriteria
);

nAmKcAz marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Newtonsoft.Json.Linq;
using RegressionGames.StateRecorder.BotSegments.Models;
using RegressionGames.StateRecorder.BotSegments.Models.BotCriteria;
using StateRecorder.BotSegments.Models;

namespace RegressionGames.StateRecorder.BotSegments.JsonConverters
{
Expand Down Expand Up @@ -48,6 +49,18 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
botSegment.endCriteria = new List<KeyFrameCriteria>();
}

if (jObject.ContainsKey("validations"))
{
botSegment.validations =
new List<SegmentValidation>(jObject.GetValue("validations")
.ToObject<SegmentValidation[]>(serializer));
}
else
{
// default value of validation is an empty list if not present
botSegment.validations = new List<SegmentValidation>();
}

return botSegment;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
case KeyFrameCriteriaType.ActionComplete:
data = jObject["data"].ToObject<ActionCompleteKeyFrameCriteriaData>(serializer);
break;
case KeyFrameCriteriaType.ValidationsComplete:
data = jObject["data"].ToObject<ValidationsCompleteKeyFrameCriteriaData>(serializer);
break;
case KeyFrameCriteriaType.CVObjectDetection:
data = jObject["data"].ToObject<CVObjectDetectionKeyFrameCriteriaData>(serializer);
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using StateRecorder.BotSegments.Models.SegmentValidations;

namespace RegressionGames.StateRecorder.BotSegments.JsonConverters
{
public class ScriptSegmentValidationDataJsonConverter: JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(ScriptSegmentValidationData).IsAssignableFrom(objectType);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
// ReSharper disable once UseObjectOrCollectionInitializer - easier to debug lines without this
ScriptSegmentValidationData data = new();
data.classFullName = jObject.GetValue("classFullName").ToObject<string>(serializer);
if (jObject.ContainsKey("apiVersion"))
{
data.apiVersion = jObject.GetValue("apiVersion").ToObject<int>(serializer);
}
return data;
}

public override bool CanWrite => false;

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RegressionGames.StateRecorder.BotSegments.Models;
using RegressionGames.StateRecorder.BotSegments.Models.BotCriteria;
using StateRecorder.BotSegments.Models;
using StateRecorder.BotSegments.Models.SegmentValidations;

namespace RegressionGames.StateRecorder.BotSegments.JsonConverters
{
public class SegmentValidationJsonConverter: JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(SegmentValidation).IsAssignableFrom(objectType);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
SegmentValidation validation = new();
validation.type = jObject["type"].ToObject<SegmentValidationType>(serializer);
if (jObject.ContainsKey("apiVersion"))
{
validation.apiVersion = jObject["apiVersion"].ToObject<int>(serializer);
}
IRGSegmentValidationData data = null;
switch (validation.type)
{
case SegmentValidationType.Script:
data = jObject["data"].ToObject<ScriptSegmentValidationData>(serializer);
break;
default:
throw new JsonSerializationException($"Unsupported SegmentValidation type: '{validation.type}'");
}

validation.data = data;
return validation;
}

public override bool CanWrite => false;

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ public void PersistPriorFrameStatus()
/**
* <summary>Publicly callable.. caches the statuses of the last passed key frame for computing delta counts from</summary>
*/
public bool Matched(bool firstSegment, int segmentNumber, bool botActionCompleted, List<KeyFrameCriteria> criteriaList)
public bool Matched(bool firstSegment, int segmentNumber, bool botActionCompleted, bool validationsCompleted, List<KeyFrameCriteria> criteriaList)
{
_newUnmatchedCriteria.Clear();
bool matched = MatchedHelper(firstSegment, segmentNumber, botActionCompleted, BooleanCriteria.And, criteriaList);
bool matched = MatchedHelper(firstSegment, segmentNumber, botActionCompleted, validationsCompleted, BooleanCriteria.And, criteriaList);
if (matched)
{
CVTextCriteriaEvaluator.Cleanup(segmentNumber);
Expand All @@ -106,7 +106,7 @@ public bool Matched(bool firstSegment, int segmentNumber, bool botActionComplete
/**
* <summary>Only to be called internally by KeyFrameEvaluator. firstSegment represents if this is the first segment in the current pass's list of segments to evaluate</summary>
*/
internal bool MatchedHelper(bool firstSegment, int segmentNumber, bool botActionCompleted, BooleanCriteria andOr, List<KeyFrameCriteria> criteriaList)
internal bool MatchedHelper(bool firstSegment, int segmentNumber, bool botActionCompleted, bool validationsCompleted, BooleanCriteria andOr, List<KeyFrameCriteria> criteriaList)
{
var objectFinders = Object.FindObjectsByType<ObjectFinder>(FindObjectsSortMode.None);
var currentFrameCount = Time.frameCount;
Expand Down Expand Up @@ -194,6 +194,13 @@ internal bool MatchedHelper(bool firstSegment, int segmentNumber, bool botAction
return false;
}
break;
case KeyFrameCriteriaType.ValidationsComplete:
if (!validationsCompleted)
{
_newUnmatchedCriteria.Add("Waiting for validations to complete...");
return false;
}
break;
}
}

Expand Down Expand Up @@ -368,7 +375,7 @@ internal bool MatchedHelper(bool firstSegment, int segmentNumber, bool botAction
for (var j = 0; j < orCount; j++)
{
var orEntry = orsToMatch[j];
var m = OrKeyFrameCriteriaEvaluator.Matched(firstSegment, segmentNumber, botActionCompleted, orEntry);
var m = OrKeyFrameCriteriaEvaluator.Matched(firstSegment, segmentNumber, botActionCompleted, validationsCompleted, orEntry);
if (m)
{
if (andOr == BooleanCriteria.Or)
Expand All @@ -394,7 +401,7 @@ internal bool MatchedHelper(bool firstSegment, int segmentNumber, bool botAction
for (var j = 0; j < andCount; j++)
{
var andEntry = andsToMatch[j];
var m = AndKeyFrameCriteriaEvaluator.Matched(firstSegment, segmentNumber, botActionCompleted, andEntry);
var m = AndKeyFrameCriteriaEvaluator.Matched(firstSegment, segmentNumber, botActionCompleted, validationsCompleted, andEntry);
if (m)
{
if (andOr == BooleanCriteria.Or)
Expand Down
Loading
Loading