using System.IO; using System.IO.Abstractions; using Google.Protobuf; using MLAgents.CommunicatorObjects; namespace MLAgents { /// /// Responsible for writing demonstration data to file. /// public class DemonstrationStore { public const int MetaDataBytes = 32; // Number of bytes allocated to metadata in demo file. private readonly IFileSystem fileSystem; private const string DemoDirecory = "Assets/Demonstrations/"; private const string ExtensionType = ".demo"; private string filePath; private DemonstrationMetaData metaData; private Stream writer; private float cumulativeReward; public DemonstrationStore(IFileSystem fileSystem) { this.fileSystem = fileSystem; } public DemonstrationStore() { fileSystem = new FileSystem(); } /// /// Initializes the Demonstration Store, and writes initial data. /// public void Initialize( string demonstrationName, BrainParameters brainParameters, string brainName) { CreateDirectory(); CreateDemonstrationFile(demonstrationName); WriteBrainParameters(brainName, brainParameters); } /// /// Checks for the existence of the Demonstrations directory /// and creates it if it does not exist. /// private void CreateDirectory() { if (!fileSystem.Directory.Exists(DemoDirecory)) { fileSystem.Directory.CreateDirectory(DemoDirecory); } } /// /// Creates demonstration file. /// private void CreateDemonstrationFile(string demonstrationName) { // Creates demonstration file. var literalName = demonstrationName; filePath = DemoDirecory + literalName + ExtensionType; var uniqueNameCounter = 0; while (fileSystem.File.Exists(filePath)) { literalName = demonstrationName + "_" + uniqueNameCounter; filePath = DemoDirecory + literalName + ExtensionType; uniqueNameCounter++; } writer = fileSystem.File.Create(filePath); metaData = new DemonstrationMetaData {demonstrationName = demonstrationName}; var metaProto = metaData.ToProto(); metaProto.WriteDelimitedTo(writer); } /// /// Writes brain parameters to file. /// private void WriteBrainParameters(string brainName, BrainParameters brainParameters) { // Writes BrainParameters to file. writer.Seek(MetaDataBytes + 1, 0); var brainProto = brainParameters.ToProto(brainName, false); brainProto.WriteDelimitedTo(writer); } /// /// Write AgentInfo experience to file. /// public void Record(AgentInfo info) { // Increment meta-data counters. metaData.numberExperiences++; cumulativeReward += info.reward; if (info.done) { EndEpisode(); } // Write AgentInfo to file. var agentProto = info.ToProto(); agentProto.WriteDelimitedTo(writer); } /// /// Performs all clean-up necessary /// public void Close() { EndEpisode(); metaData.meanReward = cumulativeReward / metaData.numberEpisodes; WriteMetadata(); writer.Close(); } /// /// Performs necessary episode-completion steps. /// private void EndEpisode() { metaData.numberEpisodes += 1; } /// /// Writes meta-data. /// private void WriteMetadata() { var metaProto = metaData.ToProto(); var metaProtoBytes = metaProto.ToByteArray(); writer.Write(metaProtoBytes, 0, metaProtoBytes.Length); writer.Seek(0, 0); metaProto.WriteDelimitedTo(writer); } } }