Example #1
0
        /// <summary>
        /// Fills the dialog placeholders
        /// </summary>
        /// <param name="code">Code</param>
        /// <param name="npc">Npc</param>
        /// <returns>Filled code</returns>
        private async Task <string> FillDialogPlaceholders(string code, KortistoNpc npc)
        {
            GoNorthProject project = await _cachedDbAccess.GetDefaultProject();

            TaleDialog dialog = await _taleDbAccess.GetDialogByRelatedObjectId(npc.Id);

            try
            {
                _errorCollection.CurrentErrorContext = _localizer["DialogErrorContext"].Value;
                _dialogParser.SetErrorCollection(_errorCollection);
                _dialogRenderer.SetErrorCollection(_errorCollection);
                ExportDialogData exportDialog   = null;
                bool             hasValidDialog = HasValidDialog(dialog);
                if (hasValidDialog)
                {
                    exportDialog = _dialogParser.ParseDialog(dialog);
                    if (exportDialog == null)
                    {
                        return(string.Empty);
                    }
                    exportDialog = await _dialogFunctionGenerator.GenerateFunctions(project.Id, npc.Id, exportDialog, _errorCollection);
                }

                code = ExportUtil.RenderPlaceholderIfTrue(code, Placeholder_HasDialog_Start, Placeholder_HasDialog_End, hasValidDialog);

                code = await RenderDialog(project, code, exportDialog, dialog, npc);
            }
            finally
            {
                _errorCollection.CurrentErrorContext = "";
            }

            return(code);
        }
Example #2
0
        public async Task <IActionResult> FlagDialogAsImplemented(string dialogId)
        {
            // Check Data
            TaleDialog dialog = await _dialogDbAccess.GetDialogById(dialogId);

            if (dialog == null)
            {
                return(StatusCode((int)HttpStatusCode.NotFound));
            }

            // Flag dialog as implemented
            dialog.IsImplemented = true;
            await _dialogSnapshotDbAccess.SaveSnapshot(dialog);

            await _dialogDbAccess.UpdateDialog(dialog);

            // Add Timeline entry
            List <KortistoNpc> npcNames = await _npcDbAccess.ResolveFlexFieldObjectNames(new List <string> {
                dialog.RelatedObjectId
            });

            string npcName = "";

            if (npcNames.Count > 0)
            {
                npcName = npcNames[0].Name;
            }
            await _timelineService.AddTimelineEntry(TimelineEvent.ImplementedDialog, dialog.RelatedObjectId, npcName);

            return(Ok());
        }
        /// <summary>
        /// Deletes additional depencendies for a flex field object
        /// </summary>
        /// <param name="flexFieldObject">Flex field object to delete</param>
        /// <returns>Task</returns>
        protected override async Task DeleteAdditionalFlexFieldObjectDependencies(KortistoNpc flexFieldObject)
        {
            TaleDialog dialog = await _taleDbAccess.GetDialogByRelatedObjectId(flexFieldObject.Id);

            if (dialog != null)
            {
                await _taleDbAccess.DeleteDialog(dialog);
            }
            _logger.LogInformation("Dialog was deleted.");
        }
Example #4
0
        /// <summary>
        /// Compares a dialog
        /// </summary>
        /// <param name="dialogId">Id of the dialog</param>
        /// <param name="currentDialog">Current dialog, if null the dialog will be loaded</param>
        /// <returns>Compare Result</returns>
        public async Task <CompareResult> CompareDialog(string dialogId, TaleDialog currentDialog = null)
        {
            if (currentDialog == null)
            {
                currentDialog = await _dialogDbAccess.GetDialogById(dialogId);
            }

            TaleDialog oldDialog = await _dialogSnapshotDbAccess.GetSnapshotById(dialogId);

            return(CompareObjects(currentDialog, oldDialog));
        }
Example #5
0
        public async Task <IActionResult> IsDialogImplementedByRelatedObjectId(string relatedObjectId)
        {
            DialogImplementedResponse response = new DialogImplementedResponse();

            TaleDialog dialog = await _taleDbAccess.GetDialogByRelatedObjectId(relatedObjectId);

            if (dialog != null)
            {
                response.Exists        = true;
                response.IsImplemented = dialog.IsImplemented;
            }

            return(Ok(response));
        }
Example #6
0
        /// <summary>
        /// Returns true if a valid dialog exists, else false
        /// </summary>
        /// <param name="dialog">Dialog to check</param>
        /// <returns>true if a valid dialog exists, else false</returns>
        private bool HasValidDialog(TaleDialog dialog)
        {
            if (dialog == null)
            {
                return(false);
            }

            if (!dialog.NpcText.Any() && !dialog.PlayerText.Any() && !dialog.Choice.Any() && !dialog.Condition.Any() && !dialog.Action.Any())
            {
                return(false);
            }

            return(true);
        }
Example #7
0
        /// <summary>
        /// Parses a dialog for exporting
        /// </summary>
        /// <param name="dialog">Dialog to parse</param>
        /// <returns>Parsed dialog</returns>
        public ExportDialogData ParseDialog(TaleDialog dialog)
        {
            _currentNodeIndex = 0;
            ExportDialogData exportDialog = SearchDialogRootNode(dialog);

            if (exportDialog == null)
            {
                return(null);
            }

            IterateDialogTree(exportDialog, dialog);

            EnsureNoInfinityLoopExists(exportDialog);

            return(exportDialog);
        }
Example #8
0
        /// <summary>
        /// Searches the dialog root node
        /// </summary>
        /// <param name="dialog">Dialog to search</param>
        /// <returns>Dialog root node</returns>
        private ExportDialogData SearchDialogRootNode(TaleDialog dialog)
        {
            List <ExportDialogData> rootNodes = new List <ExportDialogData>();

            rootNodes.AddRange(GetRootNodesFromList(dialog.PlayerText, dialog.Link, (e, n) => e.PlayerText = n));
            rootNodes.AddRange(GetRootNodesFromList(dialog.NpcText, dialog.Link, (e, n) => e.NpcText       = n));
            rootNodes.AddRange(GetRootNodesFromList(dialog.Choice, dialog.Link, (e, n) => e.Choice         = n));
            rootNodes.AddRange(GetRootNodesFromList(dialog.Action, dialog.Link, (e, n) => e.Action         = n));
            rootNodes.AddRange(GetRootNodesFromList(dialog.Condition, dialog.Link, (e, n) => e.Condition   = n));

            if (rootNodes.Count != 1)
            {
                _errorCollection.AddDialogRootNodeCountNotOne(rootNodes.Count);
                return(null);
            }

            return(rootNodes.First());
        }
Example #9
0
        /// <summary>
        /// Collects the values for an export
        /// </summary>
        /// <param name="templateType">Template type</param>
        /// <param name="parsedTemplate">Parsed scriban template</param>
        /// <param name="scriptObject">Scriban script object to fill</param>
        /// <param name="data">Export Data</param>
        /// <returns>Task</returns>
        public override async Task CollectValues(TemplateType templateType, Template parsedTemplate, ScriptObject scriptObject, ExportObjectData data)
        {
            KortistoNpc inputNpc = data.ExportData[ExportConstants.ExportDataObject] as KortistoNpc;

            if (inputNpc == null)
            {
                return;
            }

            _languageKeyGenerator.SetErrorCollection(_errorCollection);

            GoNorthProject project = await _exportCachedDbAccess.GetUserProject();

            TaleDialog dialog = await _taleDbAccess.GetDialogByRelatedObjectId(inputNpc.Id);

            ExportDialogData parsedDialog = await ParseDialog(inputNpc, project, dialog);

            ScribanExportDialog exportDialog = await BuildExportDialog(parsedDialog, inputNpc);

            scriptObject.AddOrUpdate(ExportConstants.ScribanDialogKey, exportDialog);
            scriptObject.AddOrUpdate(DialogFunctionRenderer.DialogFunctionName, new DialogFunctionRenderer(_templatePlaceholderResolver, _exportCachedDbAccess, _defaultTemplateProvider, _errorCollection, data));
        }
Example #10
0
        /// <summary>
        /// Iterates the dialog tree
        /// </summary>
        /// <param name="exportDialog">Export Dialog Data at the moment</param>
        /// <param name="dialog">Dialog</param>
        private void IterateDialogTree(ExportDialogData exportDialog, TaleDialog dialog)
        {
            Dictionary <string, ExportDialogData> convertedDialogNodes = new Dictionary <string, ExportDialogData>();

            convertedDialogNodes.Add(exportDialog.Id, exportDialog);

            Queue <ExportDialogData> dialogDataToQueue = new Queue <ExportDialogData>();

            dialogDataToQueue.Enqueue(exportDialog);

            while (dialogDataToQueue.Any())
            {
                ExportDialogData curData = dialogDataToQueue.Dequeue();

                List <ExportDialogDataChild> children = FindDialogElementChildren(convertedDialogNodes, curData, dialog);
                if (curData.Choice != null)
                {
                    children = SortChildrenByChoices(children, curData.Choice);
                }
                else if (curData.Condition != null)
                {
                    children = SortChildrenByConditions(children, curData.Condition);
                }
                curData.Children.AddRange(children);

                foreach (ExportDialogDataChild curChild in children)
                {
                    curChild.Child.Parents.Add(curData);
                    if (!convertedDialogNodes.ContainsKey(curChild.Child.Id))
                    {
                        dialogDataToQueue.Enqueue(curChild.Child);
                        convertedDialogNodes.Add(curChild.Child.Id, curChild.Child);
                    }
                }
            }
        }
Example #11
0
        /// <summary>
        /// Finds the children of da dialog element
        /// </summary>
        /// <param name="convertedDialogNodes">Already converted nodes</param>
        /// <param name="dialogData">Dialog data whichs children are searched</param>
        /// <param name="dialog">Dialog</param>
        /// <returns>Children of the element</returns>
        private List <ExportDialogDataChild> FindDialogElementChildren(Dictionary <string, ExportDialogData> convertedDialogNodes, ExportDialogData dialogData, TaleDialog dialog)
        {
            List <NodeLink> childLinks = dialog.Link.Where(l => l.SourceNodeId == dialogData.Id).ToList();

            List <ExportDialogDataChild> childNodes = new List <ExportDialogDataChild>();

            childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, dialog.PlayerText, childLinks, (e, n) => e.PlayerText = n));
            childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, dialog.NpcText, childLinks, (e, n) => e.NpcText       = n));
            childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, dialog.Choice, childLinks, (e, n) => e.Choice         = n));
            childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, dialog.Action, childLinks, (e, n) => e.Action         = n));
            childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, dialog.Condition, childLinks, (e, n) => e.Condition   = n));

            return(childNodes);
        }
Example #12
0
        /// <summary>
        /// Renders the dialog
        /// </summary>
        /// <param name="project">Current Project</param>
        /// <param name="code">Template code</param>
        /// <param name="exportDialog">Export dialog data</param>
        /// <param name="dialog">Dialog</param>
        /// <param name="npc">Npc to which the dialog belongs</param>
        /// <returns>Filled code</returns>
        private async Task <string> RenderDialog(GoNorthProject project, string code, ExportDialogData exportDialog, TaleDialog dialog, KortistoNpc npc)
        {
            if (exportDialog == null)
            {
                code = ExportUtil.BuildPlaceholderRegex(Placeholder_Start).Replace(code, string.Empty);
                code = ExportUtil.BuildPlaceholderRegex(Placeholder_Additional_Functions).Replace(code, string.Empty);
                return(code);
            }

            ExportDialogRenderResult dialogRenderResult = await _dialogRenderer.RenderDialog(exportDialog, npc);

            code = ExportUtil.BuildPlaceholderRegex(Placeholder_Start, ExportConstants.ListIndentPrefix).Replace(code, m => {
                return(ExportUtil.TrimEmptyLines(ExportUtil.IndentListTemplate(dialogRenderResult.StartStepCode, m.Groups[1].Value)));
            });
            code = ExportUtil.BuildPlaceholderRegex(Placeholder_Additional_Functions, ExportConstants.ListIndentPrefix).Replace(code, m => {
                return(ExportUtil.TrimEmptyLines(ExportUtil.IndentListTemplate(dialogRenderResult.AdditionalFunctionsCode, m.Groups[1].Value)));
            });

            return(code);
        }
        /// <summary>
        /// Renders the dialog
        /// </summary>
        /// <param name="project">Current Project</param>
        /// <param name="code">Template code</param>
        /// <param name="exportDialog">Export dialog data</param>
        /// <param name="dialog">Dialog</param>
        /// <param name="npc">Npc to which the dialog belongs</param>
        /// <returns>Filled code</returns>
        private async Task <string> RenderDialog(GoNorthProject project, string code, ExportDialogData exportDialog, TaleDialog dialog, KortistoNpc npc)
        {
            if (exportDialog == null)
            {
                code = ExportUtil.BuildPlaceholderRegex(Placeholder_Start).Replace(code, string.Empty);
                code = ExportUtil.BuildPlaceholderRegex(Placeholder_Additional_Functions).Replace(code, string.Empty);
                return(code);
            }

            List <ExportDialogFunctionCode> dialogRenderResult = await _dialogRenderer.RenderDialogSteps(exportDialog, npc);

            code = ExportUtil.BuildPlaceholderRegex(Placeholder_Start, ExportConstants.ListIndentPrefix).Replace(code, m => {
                if (dialogRenderResult.Any())
                {
                    return(ExportUtil.TrimEmptyLines(ExportUtil.IndentListTemplate(dialogRenderResult[0].Code, m.Groups[1].Value)));
                }

                return(string.Empty);
            });
            code = await ExportUtil.BuildPlaceholderRegex(Placeholder_Additional_Functions, ExportConstants.ListIndentPrefix).ReplaceAsync(code, async m => {
                string finalCode = string.Empty;
                foreach (ExportDialogFunctionCode curFunction in dialogRenderResult.Skip(1))
                {
                    finalCode += await RenderFunctionForList(project, curFunction);
                }
                return(ExportUtil.TrimEmptyLines(ExportUtil.IndentListTemplate(finalCode, m.Groups[1].Value)));
            });

            return(code);
        }
Example #14
0
        public async Task <IActionResult> GetDialogByRelatedObjectId(string relatedObjectId)
        {
            TaleDialog dialog = await _taleDbAccess.GetDialogByRelatedObjectId(relatedObjectId);

            return(Ok(dialog));
        }
Example #15
0
        public async Task <IActionResult> SaveDialog(string relatedObjectId, [FromBody] TaleDialog dialog)
        {
            // Validate data
            if (string.IsNullOrEmpty(relatedObjectId))
            {
                return(BadRequest());
            }

            List <KortistoNpc> npcNames = await _npcDbAccess.ResolveFlexFieldObjectNames(new List <string> {
                relatedObjectId
            });

            if (npcNames.Count == 0)
            {
                return(BadRequest());
            }
            string npcName = npcNames[0].Name;

            // Update or create dialog
            TaleDialog existingDialog = await _taleDbAccess.GetDialogByRelatedObjectId(relatedObjectId);

            bool isCreate = false;

            if (existingDialog == null)
            {
                KortistoNpc npc = await _npcDbAccess.GetFlexFieldObjectById(relatedObjectId);

                existingDialog = new TaleDialog();
                existingDialog.RelatedObjectId = relatedObjectId;
                existingDialog.ProjectId       = npc.ProjectId;
                isCreate = true;
            }

            existingDialog.Link       = dialog.Link != null ? dialog.Link : new List <NodeLink>();
            existingDialog.PlayerText = dialog.PlayerText != null ? dialog.PlayerText : new List <TextNode>();
            existingDialog.NpcText    = dialog.NpcText != null ? dialog.NpcText : new List <TextNode>();
            existingDialog.Choice     = dialog.Choice != null ? dialog.Choice : new List <TaleChoiceNode>();
            existingDialog.Action     = dialog.Action != null ? dialog.Action : new List <ActionNode>();
            existingDialog.Condition  = dialog.Condition != null ? dialog.Condition : new List <ConditionNode>();
            existingDialog.Reference  = dialog.Reference != null ? dialog.Reference : new List <ReferenceNode>();

            await this.SetModifiedData(_userManager, existingDialog);

            // Save Data
            if (isCreate)
            {
                existingDialog = await _taleDbAccess.CreateDialog(existingDialog);

                await _timelineService.AddTimelineEntry(existingDialog.ProjectId, TimelineEvent.TaleDialogCreated, relatedObjectId, npcName);
            }
            else
            {
                // Check implementation state
                if (existingDialog.IsImplemented)
                {
                    CompareResult result = await _implementationStatusComparer.CompareDialog(existingDialog.Id, existingDialog);

                    if (result.CompareDifference != null && result.CompareDifference.Count > 0)
                    {
                        existingDialog.IsImplemented = false;
                    }
                }

                await _taleDbAccess.UpdateDialog(existingDialog);

                await _timelineService.AddTimelineEntry(existingDialog.ProjectId, TimelineEvent.TaleDialogUpdated, relatedObjectId, npcName);
            }

            return(Ok(existingDialog));
        }
Example #16
0
        /// <summary>
        /// Exports an object
        /// </summary>
        /// <param name="exportFormat">Format to export (Script, JSON or LanguageFile)</param>
        /// <param name="id">Id of the object to export</param>
        /// <param name="templateType">Template type</param>
        /// <returns>Export result</returns>
        private async Task <ExportObjectResult> RunExportObject(string exportFormat, string id, TemplateType templateType)
        {
            // Check Access
            if ((templateType == TemplateType.ObjectNpc && !User.IsInRole(RoleNames.Kortisto)) ||
                (templateType == TemplateType.ObjectItem && !User.IsInRole(RoleNames.Styr)) ||
                (templateType == TemplateType.ObjectSkill && !User.IsInRole(RoleNames.Evne)))
            {
                throw new UnauthorizedAccessException();
            }

            // Get Exporter
            string exporterKey = exportFormat.ToLowerInvariant();

            if (!_exporters.ContainsKey(exporterKey))
            {
                throw new InvalidOperationException("Unknown Export Format");
            }
            IObjectExporter exporter = _exporters[exporterKey];

            // Get Objects
            bool             objectFound = false;
            ExportObjectData objectData  = new ExportObjectData();

            if (templateType == TemplateType.ObjectNpc)
            {
                KortistoNpc npc = await _npcDbAccess.GetFlexFieldObjectById(id);

                if (npc != null)
                {
                    objectData.ExportData.Add(ExportConstants.ExportDataObject, npc);
                    objectData.ExportData.Add(ExportConstants.ExportDataObjectType, ExportConstants.ExportObjectTypeNpc);

                    TaleDialog dialog = await _dialogDbAccess.GetDialogByRelatedObjectId(id);

                    objectData.ExportData.Add(ExportConstants.ExportDataDialog, dialog);

                    objectFound = true;
                }
            }
            else if (templateType == TemplateType.ObjectItem)
            {
                StyrItem item = await _itemDbAccess.GetFlexFieldObjectById(id);

                if (item != null)
                {
                    objectData.ExportData.Add(ExportConstants.ExportDataObject, item);
                    objectData.ExportData.Add(ExportConstants.ExportDataObjectType, ExportConstants.ExportObjectTypeItem);
                    objectFound = true;
                }
            }
            else if (templateType == TemplateType.ObjectSkill)
            {
                EvneSkill skill = await _skillDbAccess.GetFlexFieldObjectById(id);

                if (skill != null)
                {
                    objectData.ExportData.Add(ExportConstants.ExportDataObject, skill);
                    objectData.ExportData.Add(ExportConstants.ExportDataObjectType, ExportConstants.ExportObjectTypeSkill);
                    objectFound = true;
                }
            }
            else
            {
                throw new InvalidOperationException("Template Type not supported for exporting");
            }

            if (!objectFound)
            {
                throw new KeyNotFoundException();
            }

            // Get Template
            ExportTemplateByObjectIdResult template = await GetValidExportTemplateByIdAndType(id, templateType);

            // Run Export
            ExportObjectResult result = await exporter.ExportObject(template.Template, objectData);

            result.ObjectFilename = ((FlexFieldObject)objectData.ExportData[ExportConstants.ExportDataObject]).Name;
            string regexSearch      = Regex.Escape(new string(Path.GetInvalidFileNameChars()));
            Regex  illegalCharRegex = new Regex(string.Format("[{0}]", regexSearch));

            result.ObjectFilename = illegalCharRegex.Replace(result.ObjectFilename, string.Empty);
            return(result);
        }
Example #17
0
        /// <summary>
        /// Parses a dialog
        /// </summary>
        /// <param name="inputNpc">Input npc</param>
        /// <param name="project">Project</param>
        /// <param name="dialog">Dialog</param>
        /// <returns>Export dialog data</returns>
        private async Task <ExportDialogData> ParseDialog(KortistoNpc inputNpc, GoNorthProject project, TaleDialog dialog)
        {
            ExportDialogData parsedDialog = null;
            IStringLocalizer localizer    = _localizerFactory.Create(typeof(DialogValueCollector));

            try
            {
                _errorCollection.CurrentErrorContext = localizer["DialogErrorContext"].Value;
                _dialogParser.SetErrorCollection(_errorCollection);
                _dialogRenderer.SetErrorCollection(_errorCollection);
                bool hasValidDialog = SharedDialogExportUtil.HasValidDialog(dialog);
                if (hasValidDialog)
                {
                    parsedDialog = _dialogParser.ParseDialog(dialog);
                    if (parsedDialog != null)
                    {
                        parsedDialog = await _dialogFunctionGenerator.GenerateFunctions(project.Id, inputNpc.Id, parsedDialog, _errorCollection);
                    }
                }
            }
            finally
            {
                _errorCollection.CurrentErrorContext = "";
            }

            return(parsedDialog);
        }