Beispiel #1
0
 /// <summary>
 /// Save the changes into the real model system structure.
 /// This should only be called by ModelSystemEditingSession.
 /// </summary>
 /// <param name="error">The error if there was one</param>
 internal bool Save(ref string error)
 {
     if (!Root.Save(ref error))
     {
         return(false);
     }
     if (ModelSystem != null)
     {
         ModelSystem.ModelSystemStructure = ClonedModelSystemRoot;
         ModelSystem.Description          = Description;
         ModelSystem.LinkedParameters     = LinkedParameters.LinkedParameters.Select(lp => (ILinkedParameter)lp.RealLinkedParameter).ToList();
         return(ModelSystem.Save(ref error));
     }
     else if (ModelSystemIndex >= 0)
     {
         Name = ClonedModelSystemRoot.Name;
         Project.ModelSystemStructure[ModelSystemIndex]    = ClonedModelSystemRoot;
         Project.ModelSystemDescriptions[ModelSystemIndex] = Description;
         Project.LinkedParameters[ModelSystemIndex]        = LinkedParameters.LinkedParameters.Select(lp => (ILinkedParameter)lp.RealLinkedParameter).ToList();
         return(Project.Save(ref error));
     }
     else
     {
         error = "You can not save over previous runs!";
         return(false);
     }
 }
Beispiel #2
0
 /// <summary>
 /// Save the changes into the real model system structure.
 /// This should only be called by ModelSystemEditingSession.
 /// </summary>
 /// <param name="error">The error if there was one</param>
 internal bool Save(ref string error)
 {
     if (!Root.Save(ref error))
     {
         return(false);
     }
     if (ModelSystem != null)
     {
         ModelSystem.ModelSystemStructure = ClonedModelSystemRoot;
         ModelSystem.Description          = Description;
         ModelSystem.LinkedParameters     = LinkedParameters.LinkedParameters.Select(lp => (ILinkedParameter)lp.RealLinkedParameter).ToList();
         return(ModelSystem.Save(ref error));
     }
     else if (ModelSystemIndex >= 0)
     {
         Project.ModelSystemStructure[ModelSystemIndex]    = ClonedModelSystemRoot;
         Project.ModelSystemDescriptions[ModelSystemIndex] = Description;
         Project.LinkedParameters[ModelSystemIndex]        = LinkedParameters.LinkedParameters.Select(lp => (ILinkedParameter)lp.RealLinkedParameter).ToList();
         // changing the name should go last because it will bubble up to the GUI and if the models are not in the right place the old name still be read in
         Name = ClonedModelSystemRoot.Name;
         return(Project.Save(ref error));
     }
     else
     {
         error = "You can not save over previous runs!";
         return(false);
     }
 }
 /// <summary>
 /// Create a new session to edit a model system
 /// </summary>
 /// <param name="modelSystem">The model system to edit</param>
 public ModelSystemEditingSession(XTMFRuntime runtime, ModelSystem modelSystem)
 {
     Runtime = runtime;
     ModelSystem = modelSystem;
     ModelSystemModel = new ModelSystemModel(this, modelSystem);
     ModelSystemModel.PropertyChanged += ModelSystemModel_PropertyChanged;
 }
Beispiel #4
0
        /// <summary>
        /// Load a model system into memory with no
        /// references to the model system repository.
        /// </summary>
        /// <param name="stream">The stream to read from</param>
        /// <param name="config">The XTMF configuration to use</param>
        /// <param name="error">A description of the error if there is one.</param>
        /// <returns>The loaded model system, null if there was an error loading the model system.</returns>
        public static ModelSystem LoadDetachedModelSystem(Stream stream, IConfiguration config, ref string error)
        {
            var ms = new ModelSystem(config);

            ms.LoadFromStream(stream, config, ref error);
            return(ms);
        }
        /// <summary>
        /// Renames the model system if possible
        /// </summary>
        /// <param name="modelSystem">The model system to rename</param>
        /// <param name="newName">The name to save it as</param>
        /// <param name="error">An error message if the operation fails</param>
        /// <returns>True if the operation succeeds, false otherwise with a message.</returns>
        public bool Rename(ModelSystem modelSystem, string newName, ref string error)
        {
            var newNameLower = newName.ToLowerInvariant();

            if (ModelSystems.Any(ms => ms.Name.ToLowerInvariant() == newNameLower))
            {
                error = "There was already a model system with the name " + newName + "!";
                return(false);
            }
            var oldName = modelSystem.Name;

            modelSystem.Name = newName;
            var success = modelSystem.Save(ref error);

            // if the rename worked we need to cleanup the old save file
            if (success)
            {
                try
                {
                    File.Delete(Path.Combine(this.Config.ModelSystemDirectory, oldName + ".xml"));
                }
                catch (IOException)
                {
                    // if we were unable to delete the file that means it was already removed, so there is nothing to do
                }
            }
            return(success);
        }
Beispiel #6
0
 /// <summary>
 /// Create a new session to edit a model system
 /// </summary>
 /// <param name="modelSystem">The model system to edit</param>
 public ModelSystemEditingSession(XTMFRuntime runtime, ModelSystem modelSystem)
 {
     Runtime          = runtime;
     ModelSystem      = modelSystem;
     ModelSystemModel = new ModelSystemModel(this, modelSystem);
     ModelSystemModel.PropertyChanged += ModelSystemModel_PropertyChanged;
 }
Beispiel #7
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="session"></param>
 /// <param name="modelSystem"></param>
 public ModelSystemModel(ModelSystemEditingSession session, ModelSystem modelSystem)
 {
     ModelSystem  = modelSystem;
     Name         = modelSystem.Name;
     _Description = modelSystem.Description;
     LoadModelSystemFromModelSystem(session, modelSystem);
 }
Beispiel #8
0
        /// <summary>
        /// Load all of the model systems from the disk
        /// </summary>
        private void LoadModelSystemsFromDisk()
        {
            if (!Directory.Exists(_Config.ModelSystemDirectory))
            {
                return;
            }
            string[] files = Directory.GetFiles(_Config.ModelSystemDirectory);
            ConcurrentQueue <IModelSystem> temp = new ConcurrentQueue <IModelSystem>();

            Parallel.For(0, files.Length, (int i) =>
            {
                // Load the ModelSystem structure from disk
                // After we have it, then we can just go and create a new model system from it
                try
                {
                    var ms = new ModelSystem(_Config, Path.GetFileNameWithoutExtension(files[i]));
                    if (ms != null)
                    {
                        temp.Enqueue(ms);
                    }
                }
                catch
                {
                }
            });
            while (temp.TryDequeue(out IModelSystem dequeueMe))
            {
                ModelSystems.Add(dequeueMe);
            }
            (ModelSystems as List <IModelSystem>).Sort(delegate(IModelSystem first, IModelSystem second)
            {
                return(first.Name.CompareTo(second.Name));
            });
        }
 /// <summary>
 ///     Create a new session to edit a model system
 /// </summary>
 /// <param name="modelSystem">The model system to edit</param>
 public ModelSystemEditingSession(XTMFRuntime runtime, ModelSystem modelSystem)
 {
     _Runtime         = runtime;
     _ModelSystem     = modelSystem;
     ModelSystemModel = new ModelSystemModel(this, modelSystem);
     ModelSystemModel.PropertyChanged += ModelSystemModel_PropertyChanged;
     _saveSemaphor = new Semaphore(1, 1);
 }
Beispiel #10
0
 public ModelSystemModel(ModelSystemEditingSession session, ModelSystem modelSystem)
 {
     ModelSystem      = modelSystem;
     Name             = modelSystem.Name;
     _Description     = modelSystem.Description;
     Root             = new ModelSystemStructureModel(session, modelSystem.CreateEditingClone(out List <ILinkedParameter> editingLinkedParameters) as ModelSystemStructure);
     LinkedParameters = new LinkedParametersModel(session, this, editingLinkedParameters);
 }
Beispiel #11
0
 public ModelSystemModel(ModelSystemEditingSession session, ModelSystem modelSystem)
 {
     ModelSystem = modelSystem;
     Name = modelSystem.Name;
     _Description = modelSystem.Description;
     List<ILinkedParameter> editingLinkedParameters;
     Root = new ModelSystemStructureModel(session, modelSystem.CreateEditingClone(out editingLinkedParameters) as ModelSystemStructure);
     LinkedParameters = new LinkedParametersModel(session, this, editingLinkedParameters);
 }
Beispiel #12
0
 /// <summary>
 /// Load a model system that has been saved into a string
 /// </summary>
 /// <param name="modelSystemAsText">The model system stored as a string.</param>
 /// <param name="modelSystem">The model system loaded</param>
 /// <param name="error">A description of the error if the operation fails.</param>
 /// <returns>True if the model system was loaded, false otherwise with a description of the failure in error.</returns>
 public bool LoadDetachedModelSystemFromString(string modelSystemAsText, out ModelSystem modelSystem, ref string error)
 {
     using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(modelSystemAsText)))
     {
         stream.Seek(0, SeekOrigin.Begin);
         modelSystem = ModelSystem.LoadDetachedModelSystem(stream, Runtime.Configuration, ref error);
         return(modelSystem != null);
     }
 }
Beispiel #13
0
 /// <summary>
 /// Export a model system to a string
 /// </summary>
 /// <param name="ms">The model system to export</param>
 /// <param name="modelSystemAsString">The string to save the model system into</param>
 /// <param name="error">A description of the error if one occurs</param>
 /// <returns>True if the export was successful, false with description otherwise</returns>
 public bool ExportModelSystemAsString(ModelSystem ms, out string modelSystemAsString, ref string error)
 {
     using (var stream = new MemoryStream())
     {
         if (!ms.Save(stream, ref error))
         {
             modelSystemAsString = null;
             return(false);
         }
         var buffer = stream.ToArray();
         modelSystemAsString = new string(Encoding.Unicode.GetChars(buffer, 0, buffer.Length));
         return(true);
     }
 }
Beispiel #14
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="modelSystem"></param>
 /// <returns></returns>
 public bool Delete(ModelSystem modelSystem)
 {
     lock (RepositoryLock)
     {
         lock (EditingLock)
         {
             // as long as it isn't being edited
             if (this.EditingSessions.Any((session) => session.IsEditing(modelSystem as ModelSystem)))
             {
                 // we can't delete a model system that is currently being edited
                 return(false);
             }
         }
         // just use the repositories model system remove
         return(this.Repository.Remove(modelSystem));
     }
 }
Beispiel #15
0
 /// <summary>
 /// Add a model system to the project
 /// </summary>
 /// <param name="modelSystem">The model system to add to the project</param>
 /// <param name="newName">The name to use for this new model system</param>
 /// <param name="error">An error message in case of failure</param>
 /// <returns>True if the model system was added successfully</returns>
 public bool AddModelSystem(ModelSystem modelSystem, string newName, ref string error)
 {
     if (modelSystem == null)
     {
         throw new ArgumentNullException(nameof(modelSystem));
     }
     lock (_EditingSessionsLock)
     {
         if (!Project.AddModelSystem(modelSystem, newName, ref error))
         {
             return(false);
         }
         var temp = new SessionData[_EditingSessions.Length + 1];
         Array.Copy(_EditingSessions, temp, _EditingSessions.Length);
         _EditingSessions = temp;
         return(true);
     }
 }
Beispiel #16
0
 /// <summary>
 /// Add a model system to the project
 /// </summary>
 /// <param name="modelSystem">The model system to add to the project</param>
 /// <param name="error">An error message in case of failure</param>
 /// <returns>True if the model system was added successfully</returns>
 public bool AddModelSystem(ModelSystem modelSystem, ref string error)
 {
     if (modelSystem == null)
     {
         throw new ArgumentNullException("modelSystem");
     }
     lock (EditingSessionsLock)
     {
         if (!this.Project.AddModelSystem(modelSystem, modelSystem.Name, ref error))
         {
             return(false);
         }
         var temp = new SessionData[EditingSessions.Length + 1];
         Array.Copy(EditingSessions, temp, EditingSessions.Length);
         EditingSessions = temp;
         return(true);
     }
 }
Beispiel #17
0
 /// <summary>
 /// Loads a model system given its name.  It will create a new blank model system if it doesn't exist.
 /// </summary>
 /// <param name="name">The name of the model system to get.</param>
 /// <returns>The model system with the given name.</returns>
 public ModelSystem LoadOrCreate(string name)
 {
     VetName(name);
     lock (RepositoryLock)
     {
         // if another model system with the same name already exists
         IModelSystem alreadyMade;
         if ((alreadyMade = this.Repository.ModelSystems.FirstOrDefault((other) => other.Name.Equals(name, StringComparison.OrdinalIgnoreCase))) != null)
         {
             //then we can't make this new model system
             return(alreadyMade as ModelSystem);
         }
         // if no one else has the same name we can go and make the model system and add it to the repository
         var ms = new ModelSystem(Runtime.Configuration, name);
         this.Repository.Add(ms);
         return(ms);
     }
 }
Beispiel #18
0
 /// <summary>
 /// Add a model system to the project
 /// </summary>
 /// <param name="modelSystem">The model system to add to the project</param>
 /// <param name="error">An error message in case of failure</param>
 /// <returns>True if the model system was added successfully</returns>
 public bool AddModelSystem(ModelSystem modelSystem, ref string error)
 {
     if(modelSystem == null)
     {
         throw new ArgumentNullException("modelSystem");
     }
     lock (EditingSessionsLock)
     {
         if(!this.Project.AddModelSystem(modelSystem, ref error))
         {
             return false;
         }
         var temp = new SessionData[EditingSessions.Length + 1];
         Array.Copy(EditingSessions, temp, EditingSessions.Length);
         EditingSessions = temp;
         return true;
     }
 }
Beispiel #19
0
 /// <summary>
 /// Start a new editing session for the given model system
 /// </summary>
 public ModelSystemEditingSession EditModelSystem(ModelSystem modelSystem)
 {
     if (modelSystem == null)
     {
         throw new ArgumentNullException("modelSystem");
     }
     lock (EditingLock)
     {
         for (int i = 0; i < EditingSessions.Count; i++)
         {
             if (EditingSessions[i].IsEditing(modelSystem))
             {
                 References[i]++;
                 return(EditingSessions[i]);
             }
         }
         var newSession = new ModelSystemEditingSession(Runtime, modelSystem);
         References.Add(1);
         EditingSessions.Add(newSession);
         return(newSession);
     }
 }
        /// <summary>
        /// Makes a copy of the model system with the given new name
        /// </summary>
        /// <param name="modelSystem">The model system to create a clone of</param>
        /// <param name="newName">The name to give the model system</param>
        /// <param name="error">An error message if the operation fails</param>
        /// <returns>True if successful, false otherwise with an error message.</returns>
        public bool CloneModelSystem(ModelSystem modelSystem, string newName, ref string error)
        {
            var newNameLower = newName.ToLowerInvariant();

            if (ModelSystems.Any(ms => ms.Name.ToLowerInvariant() == newNameLower))
            {
                error = "There was already a model system with the name " + newName + "!";
                return(false);
            }
            ModelSystem clone = new ModelSystem(Config, newName);

            clone.Description          = modelSystem.Description;
            clone.LinkedParameters     = modelSystem.LinkedParameters;
            clone.Name                 = newName;
            clone.ModelSystemStructure = modelSystem.ModelSystemStructure;
            var saved = clone.Save(ref error);

            // unload so there are no references to the current model system
            clone.Unload();
            Add(clone);
            return(saved);
        }
Beispiel #21
0
 /// <summary>
 /// Makes a copy of the model system with the given new name
 /// </summary>
 /// <param name="modelSystem">The model system to create a clone of</param>
 /// <param name="newName">The name to give the model system</param>
 /// <param name="error">An error message if the operation fails</param>
 /// <returns>True if successful, false otherwise with an error message.</returns>
 public bool CloneModelSystem(ModelSystem modelSystem, string newName, ref string error)
 {
     if (!Project.ValidateProjectName(newName))
     {
         error = "The new name contained characters that are not valid!";
         return(false);
     }
     lock (RepositoryLock)
     {
         lock (EditingLock)
         {
             // as long as it isn't being edited
             if (EditingSessions.Any((session) => session.IsEditing(modelSystem as ModelSystem)))
             {
                 // we can't delete a model system that is currently being edited
                 error = "A model system can not be cloned while being edited!";
                 return(false);
             }
             return(Repository.CloneModelSystem(modelSystem, newName, ref error));
         }
     }
 }
Beispiel #22
0
 /// <summary>
 /// Create a new model system
 /// </summary>
 /// <param name="name">The name of the model system, must not be empty</param>
 /// <returns>The model system, null if it failed.</returns>
 public ModelSystem CreateModelSystem(string name)
 {
     if (String.IsNullOrWhiteSpace(name))
     {
         throw new ArgumentException("The name of a model system can not be null, empty or just whitespace!", "name");
     }
     if (!ValidateName(name))
     {
         throw new ArgumentException("The given name '" + name + "' was an invalid name for a model system!.", "name");
     }
     lock (RepositoryLock)
     {
         // if another model system with the same name already exists
         if (this.Repository.ModelSystems.Any((other) => other.Name.Equals(name, StringComparison.OrdinalIgnoreCase)))
         {
             //then we can't make this new model system
             return(null);
         }
         // if no one else has the same name we can go and make the model system and add it to the repository
         var ms = new ModelSystem(Runtime.Configuration, name);
         this.Repository.Add(ms);
         return(ms);
     }
 }
Beispiel #23
0
 /// <summary>
 /// Load a model system that has been saved in a file
 /// </summary>
 /// <param name="fileName">The path of the file to load.</param>
 /// <param name="modelSystem">The resulting model system if successful.</param>
 /// <param name="error">A description of the error if the operation fails.</param>
 /// <returns>True if the model system was loaded, false otherwise with a description of the failure in error.</returns>
 public bool LoadDetachedModelSystemFromFile(string fileName, out ModelSystem modelSystem, ref string error)
 {
     try
     {
         FileInfo fileInfo = new FileInfo(fileName);
         if (!fileInfo.Exists)
         {
             error       = $"File does not exist '{fileName}'";
             modelSystem = null;
             return(false);
         }
         using (var stream = fileInfo.OpenRead())
         {
             modelSystem = ModelSystem.LoadDetachedModelSystem(stream, Runtime.Configuration, ref error);
             return(modelSystem != null);
         }
     }
     catch (IOException e)
     {
         error       = e.Message;
         modelSystem = null;
         return(false);
     }
 }
Beispiel #24
0
 /// <summary>
 /// Load all of the model systems from the disk
 /// </summary>
 private void LoadModelSystemsFromDisk()
 {
     if ( !Directory.Exists( this.Config.ModelSystemDirectory ) ) return;
     string[] files = Directory.GetFiles( this.Config.ModelSystemDirectory );
     ConcurrentQueue<IModelSystem> temp = new ConcurrentQueue<IModelSystem>();
     Parallel.For( 0, files.Length, (int i) =>
     {
         // Load the ModelSystem structure from disk
         // After we have it, then we can just go and create a new model system from it
         try
         {
             var ms = new ModelSystem( this.Config, Path.GetFileNameWithoutExtension( files[i] ) );
             if ( ms != null )
             {
                 temp.Enqueue( ms );
             }
         }
         catch
         {
         }
     } );
     IModelSystem dequeueMe;
     while ( temp.TryDequeue( out dequeueMe ) )
     {
         this.ModelSystems.Add( dequeueMe );
     }
     ( this.ModelSystems as List<IModelSystem> ).Sort( delegate(IModelSystem first, IModelSystem second)
     {
         return first.Name.CompareTo( second.Name );
     } );
 }
Beispiel #25
0
 private ModelSystemStructure CloneModelSystemStructure(ModelSystem modelSystem, out List<ILinkedParameter> list)
 {
     return modelSystem.CreateEditingClone(out list);
 }
 /// <summary>
 /// Create a new session to edit a model system
 /// </summary>
 /// <param name="modelSystem">The model system to edit</param>
 public ModelSystemEditingSession(XTMFRuntime runtime, ModelSystem modelSystem)
 {
     Runtime = runtime;
     ModelSystem = modelSystem;
     ModelSystemModel = new ModelSystemModel(this, modelSystem);
 }
 /// <summary>
 ///     Check to see if we are editing the given model system
 /// </summary>
 /// <param name="modelSystem"></param>
 /// <returns></returns>
 internal bool IsEditing(ModelSystem modelSystem)
 {
     return(_ModelSystem == modelSystem);
 }
Beispiel #28
0
 /// <summary>
 /// Start a new editing session for the given model system
 /// </summary>
 public ModelSystemEditingSession EditModelSystem(ModelSystem modelSystem)
 {
     if(modelSystem == null)
     {
         throw new ArgumentNullException("modelSystem");
     }
     lock (EditingLock)
     {
         for(int i = 0; i < EditingSessions.Count; i++)
         {
             if(EditingSessions[i].IsEditing(modelSystem))
             {
                 References[i]++;
                 return EditingSessions[i];
             }
         }
         var newSession = new ModelSystemEditingSession(Runtime, modelSystem);
         References.Add(1);
         EditingSessions.Add(newSession);
         return newSession;
     }
 }
Beispiel #29
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="modelSystem"></param>
 /// <returns></returns>
 public bool Delete(ModelSystem modelSystem)
 {
     lock (RepositoryLock)
     {
         lock (EditingLock)
         {
             // as long as it isn't being edited
             if(this.EditingSessions.Any((session) => session.IsEditing(modelSystem as ModelSystem)))
             {
                 // we can't delete a model system that is currently being edited
                 return false;
             }
         }
         // just use the repositories model system remove
         return this.Repository.Remove(modelSystem);
     }
 }
        internal bool ExportModelSystem(string fileName, Project project, int modelSystemIndex, ref string error)
        {
            var root = project.ModelSystemStructure[modelSystemIndex];

            return(ModelSystem.Save(fileName, root, root.Description, project.LinkedParameters[modelSystemIndex], ref error));
        }
Beispiel #31
0
 /// <summary>
 /// Loads a model system given its name.  It will create a new blank model system if it doesn't exist.
 /// </summary>
 /// <param name="name">The name of the model system to get.</param>
 /// <returns>The model system with the given name.</returns>
 public ModelSystem LoadOrCreate(string name)
 {
     VetName(name);
     lock (RepositoryLock)
     {
         // if another model system with the same name already exists
         IModelSystem alreadyMade;
         if((alreadyMade = this.Repository.ModelSystems.FirstOrDefault((other) => other.Name.Equals(name, StringComparison.OrdinalIgnoreCase))) != null)
         {
             //then we can't make this new model system
             return alreadyMade as ModelSystem;
         }
         // if no one else has the same name we can go and make the model system and add it to the repository
         var ms = new ModelSystem(Runtime.Configuration, name);
         this.Repository.Add(ms);
         return ms;
     }
 }
Beispiel #32
0
 internal bool AddModelSystem(ModelSystem modelSystem, string newName, ref string error)
 {
     if (modelSystem == null)
     {
         throw new ArgumentNullException("modelSystem");
     }
     List<ILinkedParameter> linkedParameters;
     var clone = CloneModelSystemStructure(modelSystem, out linkedParameters);
     if (clone == null)
     {
         error = "Unable to clone the model system.";
         return false;
     }
     clone.Name = newName;
     ModelSystemStructure.Add(clone);
     ModelSystemDescriptions.Add(modelSystem.Description);
     LinkedParameters.Add(linkedParameters);
     return Save(ref error);
 }
Beispiel #33
0
 /// <summary>
 /// Create a new model system
 /// </summary>
 /// <param name="name">The name of the model system, must not be empty</param>
 /// <returns>The model system, null if it failed.</returns>
 public ModelSystem CreateModelSystem(string name)
 {
     if(String.IsNullOrWhiteSpace(name))
     {
         throw new ArgumentException("The name of a model system can not be null, empty or just whitespace!", "name");
     }
     if(!ValidateName(name))
     {
         throw new ArgumentException("The given name '" + name + "' was an invalid name for a model system!.", "name");
     }
     lock (RepositoryLock)
     {
         // if another model system with the same name already exists
         if(this.Repository.ModelSystems.Any((other) => other.Name.Equals(name, StringComparison.OrdinalIgnoreCase)))
         {
             //then we can't make this new model system
             return null;
         }
         // if no one else has the same name we can go and make the model system and add it to the repository
         var ms = new ModelSystem(Runtime.Configuration, name);
         this.Repository.Add(ms);
         return ms;
     }
 }
 /// <summary>
 /// Check to see if we are editing the given model system
 /// </summary>
 /// <param name="modelSystem"></param>
 /// <returns></returns>
 internal bool IsEditing(ModelSystem modelSystem)
 {
     return ModelSystem == modelSystem;
 }