public override void StatusHandler(CommandSetState state) { foreach (object selectedObject in state.CurrentSelection) { if (selectedObject is PageShape) { SelectedPage = (PageShape)selectedObject; MenuCommand.Visible = true; var store = state.CurrentDocView.CurrentDiagram.Store; MenuCommand.Enabled = true; return; } else { MenuCommand.Visible = false; MenuCommand.Enabled = false; } } }
public void TestMethod1() { using (Canvas canvas = new Canvas(100, 50)) { using (Tesseract tess = Tesseract.Create(null)) { canvas.DrawText("TEST", new Rectangle(0, 0, 100, 50), HorizontalAlignment.Left); ////Imaging.Image image = canvas.ToImage(Rectangle.Empty); ////Pix pix = Pix.FromImage(image/*.Convert1To8()*/); ////Bitmap bitmap = pix.ToBitmap(); ////Imaging.Image image = canvas.ToImage(Rectangle.Empty/*new Rectangle(0, 0, 100, 50)*/); ////tess.SetImage(image.Convert1To8()); foreach ((Imaging.Image image, _, _) in Imaging.Image.FromFile(@"L:\FormXtra\HCFA\BW\SET1\07227200002.tif")) { PageShape answer = tess.Recognize(image.Convert1To8(null), PageSegmentationMode.PSM_AUTO_OSD); } } } }
/// <inheritdoc /> public BayesFeatures BuildFeatures(ImageSource source, CancellationToken cancellationToken) { PageShape page = this.ocr.Recognize(source.Image); return(this.BuildFeatures(new PageSource(source.Id, page), cancellationToken)); }
private PageShape ExtractResults(Rectangle pageBounds, int horizontalResolution, int verticalResolution) { List <TextBlockShape> textBlocks = new List <TextBlockShape>(); using (ResultIterator iterator = NativeMethods.TessBaseAPIGetIterator(this.handle)) { TextBlockShape textBlock = ExtractTextBlock(); if (textBlock != null) { textBlocks.Add(textBlock); } TextBlockShape ExtractTextBlock() { Rectangle bounds = iterator.GetBoundingBox(PageIteratorLevel.TextBlock); if (bounds.IsEmpty) { return(null); } List <Shape> shapes = new List <Shape>(); do { PolyBlockType type = iterator.GetBlockType(); switch (type) { case PolyBlockType.HorizontalLine: case PolyBlockType.VerticalLine: bounds = iterator.GetBoundingBox(PageIteratorLevel.TextBlock); if (!bounds.IsEmpty) { LineShape line = type == PolyBlockType.HorizontalLine ? new LineShape(bounds, bounds.Height, LineTypes.Horizontal) : new LineShape(bounds, bounds.Width, LineTypes.Vertical); shapes.Add(line); } break; default: do { ParagraphShape shape = ExtractParagraph(); if (shape != null) { shapes.Add(shape); } }while (!iterator.IsAtFinalElement(PageIteratorLevel.TextBlock, PageIteratorLevel.Paragraph) && iterator.Next(PageIteratorLevel.Paragraph)); break; } }while (iterator.Next(PageIteratorLevel.TextBlock)); return(shapes.Count > 0 ? new TextBlockShape(bounds, shapes) : null); } ParagraphShape ExtractParagraph() { Rectangle bounds = iterator.GetBoundingBox(PageIteratorLevel.Paragraph); if (bounds.IsEmpty) { return(null); } List <TextLineShape> shapes = new List <TextLineShape>(); do { TextLineShape shape = ExtractTextLine(); if (shape != null) { shapes.Add(shape); } }while (!iterator.IsAtFinalElement(PageIteratorLevel.Paragraph, PageIteratorLevel.TextLine) && iterator.Next(PageIteratorLevel.TextLine)); return(shapes.Count > 0 ? new ParagraphShape(bounds, shapes) : null); } TextLineShape ExtractTextLine() { Rectangle bounds = iterator.GetBoundingBox(PageIteratorLevel.TextLine); if (bounds.IsEmpty) { return(null); } List <TextShape> shapes = new List <TextShape>(); do { TextShape shape = ExtractWord(); if (shape != null) { shapes.Add(shape); } }while (!iterator.IsAtFinalElement(PageIteratorLevel.TextLine, PageIteratorLevel.Word) && iterator.Next(PageIteratorLevel.Word)); return(shapes.Count > 0 ? new TextLineShape(bounds, shapes) : null); } TextShape ExtractWord() { Rectangle bounds = iterator.GetBoundingBox(PageIteratorLevel.Word); if (bounds.IsEmpty) { return(null); } /*List<CharacterAnswer> ^ characters = gcnew List<CharacterAnswer>(); * do * { * CharacterAnswer character; * if (ExtractCharacter(iterator, character)) * { * characters->Add(character); * } * * if (iterator->IsAtFinalElement(level, RIL_SYMBOL)) * { * break; * } * } * while (iterator->Next(RIL_SYMBOL)); * * if (!Enumerable::Any(characters)) * { * return nullptr; * } * * int confidence = MakeConfidence(iterator->Confidence(level));*/ string text = iterator.GetUTF8Text(PageIteratorLevel.Word); if (string.IsNullOrWhiteSpace(text)) { return(null); } float confidence = iterator.GetConfidence(PageIteratorLevel.Word) / 100.0f; return(new TextShape(bounds, text, confidence)); } } PageShape page = new PageShape(pageBounds, horizontalResolution, verticalResolution); page.AddShapes(textBlocks); return(page); }
private void BuildProcessFileVisioToSubProcess(string visioFilePath) { var store = new Store(typeof(CloudCoreArchitectSubProcessDomainModel)); var partition = new Partition(store); btnNext.Enabled = false; IList<SubProcess> subProcessList = new List<SubProcess>(); var vReader = new ProcessVisioReader(visioFilePath); foreach (VisioPage btVisioPage in vReader.Pages) { using (Transaction transaction = store.TransactionManager.BeginTransaction("create new model")) { SubProcess btProcess = new SubProcess(store); try { _projectFolderPath = lstProjects.SelectedValue.ToString().Substring(0, lstProjects.SelectedValue.ToString().LastIndexOf(@"\")); _folderPath = string.Format(@"{0}\processes\", _projectFolderPath); btProcess = ImportHelper.ProcessExists(btVisioPage.VisioId, _folderPath); _filePath = string.Format("{0}{1}.subprocess", _folderPath, btVisioPage.ProcessName.Replace(" ", "_")); //Read From Visio File List<ProcessVisioShape> shapes = btVisioPage.ReadDocument(); shapes.ForEach(p => p.Initialise(shapes)); if (btProcess == null) { #region Create new .subprocess process file from visio import btProcess = CloudCoreArchitectSubProcessSerializationHelper.Instance.CreateModelHelper(partition); _btProcessList.Add(btProcess); _bDiagram = CloudCoreArchitectSubProcessSerializationHelper.Instance.CreateDiagramHelper(partition, btProcess); _bDiagram.ModelElement = btProcess; btProcess.SubProcessName = btVisioPage.ProcessName; btProcess.VisioId = btVisioPage.VisioId; _bDiagram.ModelElement = btProcess; var modelElementActivityList = new List<Activity>(); foreach (ProcessVisioShape activity in shapes.FindAll(p => p.ShapeCategory == ShapeTypeCategory.Activity)) { List<ProcessVisioShape> attachments = shapes.FindAll(p => p.ShapeCategory == ShapeTypeCategory.Attachment && p.AttachedTo == activity); var isStart = (attachments.FirstOrDefault(p => p.Type == ShapeTypes.Start) != null); //TODO: Check if Activity already exists in returned Diagram, Update returned diagram, or create new Activity if it doesn't exist if (activity.Type == ShapeTypes.PageActivity) { if (isStart) { var PageShape = new PageShape(store); var btPage = new CloudcoreUser(store) { IsMenuItem = activity.IsMenuItem, VisioId = activity.VisioId, Name = activity.DescriptiveText, Height = PageShape.DefaultSize.Height, Width = PageShape.DefaultSize.Width, Left = activity.TopLeft.X, Top = activity.TopLeft.Y, IsStartable = true }; btProcess.Activities.Add(btPage); modelElementActivityList.Add(btPage); } else { var pageShape = new PageShape(store); var btPage = new CloudcoreUser(store) { IsMenuItem = activity.IsMenuItem, VisioId = activity.VisioId, Name = activity.DescriptiveText, Height = pageShape.DefaultSize.Height, Width = pageShape.DefaultSize.Width, Left = activity.TopLeft.X, Top = activity.TopLeft.Y, IsStartable = false }; btProcess.Activities.Add(btPage); modelElementActivityList.Add(btPage); } } else if (activity.Type == ShapeTypes.BusinessRule) { var ruleShape = new WorkflowRuleShape(store); var btRule = new WorkflowRule(store) { VisioId = activity.VisioId, Name = activity.DescriptiveText, Height = ruleShape.DefaultSize.Height, Width = ruleShape.DefaultSize.Width, Left = activity.TopLeft.X, Top = activity.TopLeft.Y }; btProcess.Activities.Add(btRule); modelElementActivityList.Add(btRule); } else if (activity.Type == ShapeTypes.SubProcess) { var subProcessShape = new ToProcessConnectorShape(store); Visio.Hyperlinks hl = activity.VisShape.Hyperlinks; Visio.Shape sp = hl.Shape; var visioShape = new ProcessVisioShape(sp); var btSubProcess = new ToProcessConnector(store) { VisioId = activity.VisioId, Name = activity.DescriptiveText, Height = subProcessShape.DefaultSize.Height, Width = subProcessShape.DefaultSize.Width, Left = activity.TopLeft.X, Top = activity.TopLeft.Y, ExternalActivityRef = null, ToProcessConnectorRef = null, ToActivityId = visioShape.VisioId.ToString(), ToProcessId = btProcess.VisioId.ToString() }; btProcess.Activities.Add(btSubProcess); modelElementActivityList.Add(btSubProcess); } else if (activity.Type == ShapeTypes.DatabaseActivity) { if (isStart) { //var startEventShape = new StartEventShape(store); //var btEvent = new StartEvent(store) //{ // VisioId = activity.VisioId, // Name = activity.DescriptiveText, // Height = startEventShape.DefaultSize.Height, // Width = startEventShape.DefaultSize.Width, // Left = activity.TopLeft.X, // Top = activity.TopLeft.Y //}; //btProcess.Activities.Add(btEvent); //modelElementActivityList.Add(btEvent); } else { //var eventShape = new EventShape(store); //var btEvent = new Event(store) //{ // VisioId = activity.VisioId, // Name = activity.DescriptiveText, // Height = eventShape.DefaultSize.Height, // Width = eventShape.DefaultSize.Width, // Left = activity.TopLeft.X, // Top = activity.TopLeft.Y //}; //btProcess.Activities.Add(btEvent); //modelElementActivityList.Add(btEvent); } } else if (activity.Type == ShapeTypes.Completed) { var stopShape = new StopShape(store); var btStop = new Stop(store) { VisioId = activity.VisioId, Name = activity.DescriptiveText, Height = stopShape.DefaultSize.Height, Width = stopShape.DefaultSize.Width, Left = activity.TopLeft.X, Top = activity.TopLeft.Y }; btProcess.Activities.Add(btStop); modelElementActivityList.Add(btStop); } else if (activity.Type == ShapeTypes.Parked) { //var parkShape = new DBParkShape(store); //var btParked = new DBPark(store) //{ // VisioId = activity.VisioId, // Name = activity.DescriptiveText, // Height = parkShape.DefaultSize.Height, // Width = parkShape.DefaultSize.Width, // Left = activity.TopLeft.X, // Top = activity.TopLeft.Y //}; //btProcess.Activities.Add(btParked); //modelElementActivityList.Add(btParked); } } #region Create Activity Flows foreach (ProcessVisioShape activity in shapes.FindAll(p => p.ShapeCategory == ShapeTypeCategory.Activity)) { if (activity.Targets == null) break; Activity sourceElement = modelElementActivityList.FirstOrDefault(p => p.VisioId == activity.VisioId); foreach (ProcessVisioShape target in activity.Targets) { Activity targetElement = modelElementActivityList.FirstOrDefault(p => p.VisioId == target.VisioId); if (sourceElement != null && targetElement != null) { foreach (var b in target.GetConnectors(activity).Where(b => b != null)) { CreateNewFlow(sourceElement, targetElement, b.Outcome, b.StoryLine, b.VisioId, DetermineFlowType(b.FlowType)); } } } } #endregion //vReader.CloseVisio(); subProcessList.Add(btProcess); CreateNewProcessFile(btProcess); #endregion } else { #region Update found .subprocess process file from visio import #region Code Folder Variables var processFolderPath = string.Format(@"{0}BTProcess_{1}\", _folderPath, btProcess.VisioId.ToString().Replace("-", "_")); var pagesFolderPath = string.Format(@"{0}Pages\", processFolderPath); var eventsFolderPath = string.Format(@"{0}Events\", processFolderPath); var rulesFolderPath = string.Format(@"{0}Rules\", processFolderPath); #endregion _btProcessList.Add(btProcess); _bDiagram = ImportHelper.GetSubProcessDiagram(btProcess); //Update Process Details btProcess.SubProcessName = btVisioPage.ProcessName; #region Delete Elements that don't exist anymore #region Build Activities List and delete from process diagram that don't exist in the Visio file activityList.AddRange(from activity in btProcess.Activities where shapes.FirstOrDefault(a => (a.VisioId == activity.VisioId) && (a.ShapeCategory == ShapeTypeCategory.Activity)) == null select activity); #region Complete Activity Deletion Process foreach (var act in activityList) { using (Transaction trans = btProcess.Store.TransactionManager.BeginTransaction("delete activity")) { #region Check if link between activity and source activities //Check if link between activity and source activities foreach (Activity sAct in act.SourceActs) { if (sAct != null) { var fMCollection = new List<dynamic>(); //if (sAct is Rule) //{ // fMCollection.AddRange(Flow.GetLinks(sAct, act)); //} //else //{ // fMCollection.AddRange(FlowMinimal.GetLinks(sAct, act)); //} } } #endregion var actName = string.Format("{0} ({1})", act.Name, act.GetType()).Replace("Architect.BT", string.Empty); #region Build ActivityDelete //if (act is Rule) //{ // string ruleFileName = string.Format(@"{0}BTRule_{1}.sql", rulesFolderPath, act.VisioId.Replace("-", "_")); // if (File.Exists(ruleFileName)) // { // deletedCode.Add(new DeletedInfo { Name = actName, Path = ruleFileName, Id = act.VisioId }); // } //} #endregion act.Delete(); trans.Commit(); } } #endregion #endregion #region delete flows that don't exists anymore List<string> connectorList = new List<string>(); foreach (var shapeSource in shapes.FindAll(x => (x.ShapeCategory == ShapeTypeCategory.Activity) && (x.Targets != null))) { foreach (var shapeTarget in shapeSource.Targets) { foreach (var connector in shapeSource.GetConnectors(shapeTarget)) { if (connector != null) connectorList.Add(connector.VisioId); } } } foreach (var vtAct in btProcess.Activities) { var fL = FlowBase.GetLinksToTargetActs(vtAct); foreach (var s in fL) { if (connectorList.FindAll(f => f == s.VisioId).Count == 0) { using (Transaction trans = s.Store.TransactionManager.BeginTransaction("delete non-existing Flow Minimal")) { s.Delete(); trans.Commit(); } } } } #endregion #endregion #region Create/Update Current Task's Activities #region Loop through all activities in the process foreach (ProcessVisioShape activity in shapes.FindAll(p => p.ShapeCategory == ShapeTypeCategory.Activity)) { List<ProcessVisioShape> attachments = shapes.FindAll(p => p.ShapeCategory == ShapeTypeCategory.Attachment && p.AttachedTo == activity); var isStart = (attachments.FirstOrDefault(p => p.Type == ShapeTypes.Start) != null); Activity btActivity = btProcess.Activities.FirstOrDefault(a => a.VisioId == activity.VisioId); //TODO: Check if Activity already exists in returned Diagram, Update returned diagram, or create new Activity if it doesn't exist if (btActivity == null) { #region Create New Activity using (Transaction trans = btProcess.Store.TransactionManager.BeginTransaction("Create activity")) { if (activity.Type == ShapeTypes.PageActivity) { if (isStart) { //var btPage = new StartPage(store) //{ // IsMenuItem = activity.IsMenuItem, // VisioId = activity.VisioId, // Name = activity.DescriptiveText, // Height = activity.Height, // Width = activity.Width, // Left = activity.TopLeft.X, // Top = activity.TopLeft.Y //}; //startPagesList.Add(btPage); //btProcess.Activities.Add(btPage); } else { var btPage = new CloudcoreUser(store) { IsMenuItem = activity.IsMenuItem, VisioId = activity.VisioId, Name = activity.DescriptiveText, Height = activity.Height, Width = activity.Width, Left = activity.TopLeft.X, Top = activity.TopLeft.Y }; btProcess.Activities.Add(btPage); } } else if (activity.Type == ShapeTypes.BusinessRule) { //var btRule = new Rule(store) //{ // VisioId = activity.VisioId, // Name = activity.DescriptiveText, // Height = activity.Height, // Width = activity.Width, // Left = activity.TopLeft.X, // Top = activity.TopLeft.Y //}; //btProcess.Activities.Add(btRule); } else if (activity.Type == ShapeTypes.DatabaseActivity) { if (isStart) { //var btEvent = new StartEvent(store) //{ // VisioId = activity.VisioId, // Name = activity.DescriptiveText, // Height = activity.Height, // Width = activity.Width, // Left = activity.TopLeft.X, // Top = activity.TopLeft.Y //}; //btProcess.Activities.Add(btEvent); } else { //var btEvent = new Event(store) //{ // VisioId = activity.VisioId, // Name = activity.DescriptiveText, // Height = activity.Height, // Width = activity.Width, // Left = activity.TopLeft.X, // Top = activity.TopLeft.Y //}; //btProcess.Activities.Add(btEvent); } } else if (activity.Type == ShapeTypes.Completed) { var btStop = new Stop(store) { VisioId = activity.VisioId, Name = activity.DescriptiveText, Height = activity.Height, Width = activity.Width, Left = activity.TopLeft.X, Top = activity.TopLeft.Y }; btProcess.Activities.Add(btStop); } trans.Commit(); } #endregion } else { #region Update Existing Activity //if (activity.Type == ShapeTypes.PageActivity && isStart) // startPagesList.Add((StartPage)btActivity); using (Transaction trans = btActivity.Store.TransactionManager.BeginTransaction("update task")) { btActivity.Name = activity.DescriptiveText; btActivity.Height = activity.Height; btActivity.Width = activity.Width; btActivity.Left = activity.TopLeft.X; btActivity.Top = activity.TopLeft.Y; trans.Commit(); } #endregion } } #endregion #endregion #region Create/Update Activity Flows #region Create ActivityList in current diagram var modelElementActivityList = new List<Activity>(); modelElementActivityList.AddRange(from Activity a in ((SubProcess)_bDiagram.ModelElement).Activities select a); #endregion //#region Create Flow List in current diagram //List<dynamic> modelElementActivityFlowList = (from activitySource in modelElementActivityList // from activityTarget in modelElementActivityList.Where(a => a != activitySource) // select GetFlowDetermined(activitySource, activityTarget) // into fFlow // where fFlow != null // select fFlow).ToList(); //#endregion foreach (var shapeSource in shapes.FindAll(x => (x.ShapeCategory == ShapeTypeCategory.Activity) && (x.Targets != null))) { foreach (var shapeTarget in shapeSource.Targets) { foreach (var connector in shapeSource.GetConnectors(shapeTarget)) { if (connector != null) { //dynamic fMinimal = modelElementActivityFlowList.FirstOrDefault(f => f.VisioId == connector.VisioId); //if (fMinimal != null) //{ // #region Update existing flow // var source = modelElementActivityList.FirstOrDefault(p => p.VisioId == shapeSource.VisioId); // var target = modelElementActivityList.FirstOrDefault(p => p.VisioId == shapeTarget.VisioId); // if (fMinimal.SourceBTActivity != source && fMinimal.TargetBTActivity != target) // { // using (Transaction trans = fMinimal.Store.TransactionManager.BeginTransaction("update Flow")) // { // fMinimal.Delete(); // trans.Commit(); // } // } // //Check if the source and the target are the same // if ((source.VisioId != shapeSource.VisioId) || (target.VisioId != shapeTarget.VisioId)) // { // #region The activity(source) connecting to current activity or activity(target) connected to this activity is different // using (Transaction trans = fMinimal.Store.TransactionManager.BeginTransaction("update Flow")) // { // fMinimal.Delete(); // trans.Commit(); // } // Activity start, end; // //Source is an activity // //Get existing in and outports for task to task flow // start = fMinimal.TargetBTActivity; // end = start.TargetActs[0]; // #region create new flow // using (Transaction trans = fMinimal.Store.TransactionManager.BeginTransaction("Create New Flow")) // { // CreateNewFlow(source, target, connector.Outcome, connector.StoryLine, fMinimal.VisioId, fMinimal.Type); // trans.Commit(); // } // #endregion // #endregion // } // else // { // #region The activity(source) connecting to current activity or or activity(target) connected to this activity is the same // //if (source is Rule) // //{ // // Flow f = Flow.GetLink(source, target); // // if (f != null) // // { // // using (Transaction trans = fMinimal.Store.TransactionManager.BeginTransaction("update Flow Minimal")) // // { // // f.Storyline = connector.StoryLine; // // f.Outcome = connector.Outcome; // // trans.Commit(); // // } // // } // // else // // { // // using (Transaction trans = source.Store.TransactionManager.BeginTransaction("Create Link")) // // { // // CreateNewFlow(source, target, connector.Outcome, connector.StoryLine, connector.VisioId, DetermineFlowType(connector.FlowType)); // // trans.Commit(); // // } // // } // //} // //else // //{ // // FlowMinimal f = FlowMinimal.GetLink(source, target); // // using (Transaction trans = fMinimal.Store.TransactionManager.BeginTransaction("update Flow Minimal")) // // { // // f.Storyline = connector.StoryLine; // // trans.Commit(); // // } // //} // #endregion // } // #endregion //} //else //{ // #region Create new flow // if (shapeSource.Targets != null && shapeTarget.Sources != null) // { // Activity source = modelElementActivityList.FirstOrDefault(p => p.VisioId == shapeSource.VisioId); // Activity target = modelElementActivityList.FirstOrDefault(p => p.VisioId == shapeTarget.VisioId); // #region Source Activity's Parent Task equal to Target Activity's Parent Task // using (Transaction trans = source.Store.TransactionManager.BeginTransaction("update Flow Minimal")) // { // CreateNewFlow(source, target, connector.Outcome, connector.StoryLine, connector.VisioId, DetermineFlowType(connector.FlowType)); // trans.Commit(); // } // #endregion // } // #endregion //} } } } } #endregion //vReader.CloseVisio(); if (deletedCode.Count > 0) { pnlBackup.Enabled = true; } else { deletedCode.Add(new DeletedInfo { Name = "No items will be deleted." }); pnlBackup.Enabled = false; } lstDeleted.DataSource = deletedCode; lstDeleted.DisplayMember = "Name"; pnlDeleted.Visible = true; #endregion } transaction.Commit(); } catch (Exception ex) { throw ex; } } } IModelBus modelBus = store.GetService(typeof(SModelBus)) as IModelBus; if (modelBus != null) { foreach (SubProcess process in subProcessList) { using (Transaction transaction = process.Store.TransactionManager.BeginTransaction("update modelbus")) { //List<Activity> subProcessActivities = process.Activities.Where(a => a is SubProcessActivity).ToList(); //foreach (Activity act in subProcessActivities) //{ // var _act = (SubProcessActivity)act; // string toProc = ((SubProcessActivity)act).ToProcessId; // string toAct = ((SubProcessActivity)act).ToActivityId; // var toProcess = (SubProcess)subProcessList.Where(p => p.VisioId.ToString() == toProc).SingleOrDefault(); // var toActivity = (SubProcessActivity)toProcess.Activities.Where(a => a.VisioId.ToString() == toAct).SingleOrDefault(); // string projectPath = lstProjects.SelectedValue.ToString().Substring(0, lstProjects.SelectedValue.ToString().LastIndexOf(@"\")); // string folderPath = string.Format(@"{0}\processes\", _projectFolderPath); // string filePath = string.Format("{0}{1}.subprocess", _folderPath, toActivity.SubProcess.SubProcessName.Replace(" ", "_")); // ModelBusAdapterManager manager = modelBus.FindAdapterManagers(filePath).First(); // ModelBusReference reference = manager.CreateReference(filePath); // using (ModelBusAdapter adapter = modelBus.CreateAdapter(reference)) // { // _act.ExternalActivityRef = adapter.GetElementReference(toActivity); // _act.SubProcessActivityRef = adapter.GetElementReference(toActivity); // } //} transaction.Commit(); } } } vReader.CloseVisio(); Close(); }