Skip to content

Commit 768e3e7

Browse files
committed
good handling of concurrent invalid actions such as both agents grabbing the same object
1 parent f4ae958 commit 768e3e7

File tree

2 files changed

+117
-46
lines changed

2 files changed

+117
-46
lines changed

Assets/Story Generator/Scripts/ScriptExecution.cs

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -813,11 +813,12 @@ public class ScriptExecutor
813813
private IObjectSelectorProvider objectSelectorProvider;
814814
private IGameObjectPropertiesCalculator propCalculator; // Class which can caclulate interaction positions
815815
public List<ScriptPair> script; // Script (filled with subsequent calls of AddAction)
816+
public List<ScriptLine> sLines; // Original Script
816817
private CharacterControl characterControl; // Class which can execute actions (Walk, Grab, etc.)
817818
private List<ICameraControl> cameraControls; // Camera control class
818819
private int gotoExecDepth;
819820
private System.Diagnostics.Stopwatch execStartTime;
820-
private ProcessingReport report;
821+
public ProcessingReport report;
821822
private bool randomizeExecution; // Randomize selection of interaction position
822823
private Recorder recorder;
823824
private int processingTimeLimit = 20 * 1000; // Max search time for admissible solution (in milliseconds)
@@ -830,11 +831,11 @@ public class ScriptExecutor
830831
public static Hashtable actionsPerLine = new Hashtable();
831832
public static int currRunlineNo = 0; // The line no being executed now
832833
public static int currActionsFinished = 0; // The number of actions finished for currRunLineNo. Moving to the next line if currActionsFinished == actionsPerLine[currRunlineNo];
834+
833835

834836
// *****
835837
private TestDriver caller;
836838

837-
//private IList<ScriptLine> sLines { get; set; }
838839

839840
public ScriptExecutor(IList<GameObject> nameList, RoomSelector roomSelector,
840841
IObjectSelectorProvider objectSelectorProvider, Recorder rcdr, int charIndex, InteractionCache interaction_cache, bool smooth_walk = false)
@@ -851,6 +852,7 @@ public ScriptExecutor(IList<GameObject> nameList, RoomSelector roomSelector,
851852

852853
propCalculator = new DefaultGameObjectPropertiesCalculator();
853854
script = new List<ScriptPair>();
855+
sLines = new List<ScriptLine>();
854856
recorder = rcdr;
855857
report = new ProcessingReport();
856858
}
@@ -881,11 +883,13 @@ public void Initialize(CharacterControl chc, List<ICameraControl> cac)
881883
chc.report = report;
882884
cameraControls = cac;
883885
script.Clear();
886+
sLines.Clear();
884887
}
885888

886889
public void ClearScript()
887890
{
888891
script.Clear();
892+
sLines.Clear();
889893
}
890894

891895
private IEnumerable<GameObject> SelectObjects(IObjectSelector selector)
@@ -3869,7 +3873,7 @@ public ScriptReaderException(string message) :
38693873
}
38703874
}
38713875

3872-
class ScriptLine
3876+
public class ScriptLine
38733877
{
38743878
public InteractionType Interaction { get; set; }
38753879
public IList<Tuple<string, int>> Parameters { get; set; }
@@ -3882,19 +3886,71 @@ internal bool CompareParameters(ScriptLine otherSl)
38823886
}
38833887
}
38843888

3885-
public class ScriptReader
3889+
public class ScriptChecker
38863890
{
3887-
3888-
public static void ReadScript(ScriptExecutor sExecutor, string fileName,
3889-
ActionEquivalenceProvider actionEquivProvider, string scriptPath = @"ActionScripts/")
3891+
public static List<Tuple<int, Tuple<String, String>>> SolveConflicts(List<ScriptExecutor> sExecutors)
38903892
{
3891-
IList<ScriptLine> sLines = ReadScriptLines(scriptPath + fileName, actionEquivProvider);
38923893

3893-
for (int i = 0; i < sLines.Count; i++)
3894+
// Solve conflicts when multiple agents are trying to open/grab the same object
3895+
Dictionary<int, List<int>> dict_conflicts = new Dictionary<int, List<int>>();
3896+
Dictionary<int, InteractionType> action_conflicts = new Dictionary<int, InteractionType> ();
3897+
List < Tuple<int, Tuple<String, String>> > conflict_messages = new List<Tuple<int, Tuple<String, String>>>();
3898+
for (int i = 0; i < sExecutors.Count(); i++)
38943899
{
3895-
ScriptLineToAction(sExecutor, i, sLines);
3900+
for (int script_index = 0; script_index < sExecutors[i].sLines.Count(); script_index++)
3901+
{
3902+
if (sExecutors[i].sLines[script_index].Interaction == InteractionType.OPEN ||
3903+
sExecutors[i].sLines[script_index].Interaction == InteractionType.CLOSE ||
3904+
sExecutors[i].sLines[script_index].Interaction == InteractionType.GRAB){
3905+
int index_object = sExecutors[i].sLines[script_index].Parameters[0].Item2;
3906+
if (!dict_conflicts.ContainsKey(index_object))
3907+
{
3908+
3909+
dict_conflicts[index_object] = new List<int>();
3910+
action_conflicts[index_object] = sExecutors[i].sLines[script_index].Interaction;
3911+
}
3912+
3913+
dict_conflicts[index_object].Add(i);
3914+
}
3915+
}
3916+
}
3917+
3918+
foreach (KeyValuePair<int, List<int>> kvp in dict_conflicts)
3919+
{
3920+
if (kvp.Value.Count() > 1)
3921+
{
3922+
InteractionType conflict_action = action_conflicts[kvp.Key];
3923+
int index_char_perform = RandomUtils.Choose(kvp.Value);
3924+
for (int i = 0; i < kvp.Value.Count(); i++)
3925+
{
3926+
int index_char = kvp.Value[i];
3927+
if (index_char != index_char_perform)
3928+
{
3929+
sExecutors[index_char].script.Clear();
3930+
sExecutors[index_char].sLines.Clear();
3931+
Tuple<String, String> ct = new Tuple<String, String> ("PROCESS UNDEF", $"Agent {index_char_perform} tried to do the same action");
3932+
if (conflict_action == InteractionType.OPEN)
3933+
ct = new Tuple<String, String>("PROCESS OPEN", $"Agent {index_char_perform} tried to open the object at the same time");
3934+
3935+
if (conflict_action == InteractionType.CLOSE)
3936+
ct = new Tuple<String, String>("PROCESS CLOSE", $"Agent {index_char_perform} tried to open the object at the same time");
3937+
3938+
3939+
if (conflict_action == InteractionType.GRAB)
3940+
ct = new Tuple<String, String>("PROCESS GRAB", $"Agent {index_char_perform} tried to grab the object at the same time");
3941+
3942+
3943+
conflict_messages.Add(new Tuple<int, Tuple<string, string>>(index_char, ct));
3944+
}
3945+
}
3946+
}
38963947
}
3948+
return conflict_messages;
38973949
}
3950+
}
3951+
3952+
public class ScriptReader
3953+
{
38983954

38993955
public static void ParseScript(List<ScriptExecutor> sExecutors, IList<string> scriptLines,
39003956
ActionEquivalenceProvider actionEquivProvider)
@@ -3918,7 +3974,7 @@ private static void ParseScriptForChar(ScriptExecutor sExecutor, IList<string> s
39183974
if (sl != null)
39193975
sLines.Add(sl);
39203976
}
3921-
//sExecutor.sLines = new List<ScriptLine>(sLines);
3977+
sExecutor.sLines = new List<ScriptLine>(sLines);
39223978
for (int i = 0; i < sLines.Count; i++)
39233979
{
39243980
ScriptLineToAction(sExecutor, i, sLines);
@@ -4048,25 +4104,6 @@ private static void ScriptLineToAction(ScriptExecutor sExecutor, int index, ILis
40484104

40494105
}
40504106

4051-
static IList<ScriptLine> ReadScriptLines(string fileName, ActionEquivalenceProvider actionEquivProvider)
4052-
{
4053-
var result = new List<ScriptLine>();
4054-
4055-
using (System.IO.StreamReader file = new System.IO.StreamReader(fileName))
4056-
{
4057-
string line;
4058-
int lineNo = 0;
4059-
4060-
while ((line = file.ReadLine()) != null)
4061-
{
4062-
var sl = ParseLine(line, lineNo++, actionEquivProvider);
4063-
4064-
if (sl != null)
4065-
result.Add(sl);
4066-
}
4067-
}
4068-
return result;
4069-
}
40704107

40714108
private static ScriptLine ParseLine(string line, int lineNo, ActionEquivalenceProvider actionEquivProvider)
40724109
{

Assets/Story Generator/Scripts/TestDriver.cs

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -611,25 +611,35 @@ IEnumerator ProcessNetworkRequest()
611611
parseSuccess = false;
612612
response.success = false;
613613
response.message = $"Error parsing script: {e.Message}";
614+
continue;
614615
}
615616

616617
//s_SimulatePerfMarker.Begin();
617-
618+
618619

619620
if (parseSuccess)
620621
{
622+
List<Tuple<int, Tuple<String, String>>> error_messages = new List<Tuple<int, Tuple<String, String>>>();
623+
if (!config.find_solution)
624+
error_messages = ScriptChecker.SolveConflicts(sExecutors);
621625
for (int i = 0; i < numCharacters; i++)
622626
{
623627
StartCoroutine(sExecutors[i].ProcessAndExecute(config.recording, this));
624-
//yield return sExecutors[i].ProcessAndExecute(true, this);
625628
}
626629

627630
while (finishedChars != numCharacters)
628631
{
629632
yield return new WaitForSeconds(0.01f);
630633
}
631-
}
632634

635+
// Add back errors from concurrent actions
636+
637+
for (int error_index = 0; error_index < error_messages.Count; error_index++)
638+
{
639+
sExecutors[error_messages[error_index].Item1].report.AddItem(error_messages[error_index].Item2.Item1, error_messages[error_index].Item2.Item2);
640+
}
641+
642+
}
633643

634644
//s_SimulatePerfMarker.End();
635645

@@ -641,49 +651,65 @@ IEnumerator ProcessNetworkRequest()
641651
response.message = "";
642652
response.success = false;
643653
bool[] success_per_agent = new bool[numCharacters];
644-
654+
655+
bool agent_failed_action = false;
656+
Dictionary <int, Dictionary <String, String> > messages = new Dictionary<int, Dictionary<String, String> > ();
645657
if (!config.recording)
646658
{
647659
for (int i = 0; i < numCharacters; i++)
648660
{
661+
Dictionary<String, String> current_message = new Dictionary<String, String>();
662+
649663
if (!sExecutors[i].Success)
650664
{
651-
//response.success = false;
652-
response.message += $"ScriptExcutor {i}: ";
653-
response.message += sExecutors[i].CreateReportString();
654-
response.message += "\n";
665+
String message = "";
666+
message += $"ScriptExcutor {i}: ";
667+
message += sExecutors[i].CreateReportString();
668+
message += "\n";
669+
current_message["message"] = message;
670+
655671
success_per_agent[i] = false;
672+
agent_failed_action = true;
656673
}
657674
else
658675
{
676+
current_message["message"] = "Success";
659677
response.success = true;
660678
success_per_agent[i] = true;
661679
}
680+
messages[i] = current_message;
662681
}
663682
}
664683
else
665684
{
666685
for (int i = 0; i < numCharacters; i++)
667686
{
687+
Dictionary<String, String> current_message = new Dictionary<String, String>();
668688
Recorder rec = recorders[i];
669689
if (!sExecutors[i].Success)
670690
{
671691
//response.success = false;
672-
response.message += $"ScriptExcutor {i}: ";
673-
response.message += sExecutors[i].CreateReportString();
674-
response.message += "\n";
692+
String message = "";
693+
message += $"ScriptExcutor {i}: ";
694+
message += sExecutors[i].CreateReportString();
695+
message += "\n";
696+
current_message["message"] = message;
675697
}
676698
else if (rec.Error != null)
677699
{
678700
//Directory.Delete(rec.OutputDirectory);
679701
//response.success = false;
680-
response.message += $"Recorder {i}: ";
681-
response.message += recorder.Error.Message;
682-
response.message += "\n";
702+
agent_failed_action = true;
703+
String message = "";
704+
message += $"Recorder {i}: ";
705+
message += recorder.Error.Message;
706+
message += "\n";
683707
rec.Recording = false;
708+
current_message["message"] = message;
684709
}
685710
else
686711
{
712+
current_message["message"] = "Success";
687713
response.success = true;
688714
success_per_agent[i] = true;
689715
rec.MarkTermination();
@@ -696,15 +722,23 @@ IEnumerator ProcessNetworkRequest()
696722
});
697723
rec.CreateTextualGTs();
698724
}
725+
726+
727+
messages[i] = current_message;
699728
}
700729
}
701730

702-
731+
// If any of the agent fails an action, report failure
732+
if (parseSuccess)
733+
{
734+
response.message = JsonConvert.SerializeObject(messages);
735+
}
736+
if (agent_failed_action)
737+
response.success = false;
703738
ISet<GameObject> changedObjs = new HashSet<GameObject>();
704739
IDictionary<Tuple<string, int>, ScriptObjectData> script_object_changed = new Dictionary<Tuple<string, int>, ScriptObjectData>();
705740
List<ActionObjectData> last_action = new List<ActionObjectData>();
706741
bool single_action = true;
707-
708742
for (int char_index = 0; char_index < numCharacters; char_index++)
709743
{
710744
if (success_per_agent[char_index])

0 commit comments

Comments
 (0)