< Summary

Class:DCL.QuestsController.QuestsController
Assembly:QuestsController
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/QuestsController/QuestsController.cs
Covered lines:82
Uncovered lines:13
Coverable lines:95
Total lines:233
Line coverage:86.3% (82 of 95)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
QuestsController()0%110100%
QuestsController()0%220100%
InitializeQuests(...)0%880100%
UpdateQuestProgress(...)0%39.436086.21%
RestoreProgressFlags(...)0%330100%
RemoveQuest(...)0%2100%
OnPinnedQuestUpdated(...)0%110100%
Dispose()0%2100%
HasProgressed(...)0%880100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/QuestsController/QuestsController.cs

#LineLine coverage
 1using DCL.Helpers;
 2using Newtonsoft.Json;
 3using System;
 4using System.Collections.Generic;
 5using System.Linq;
 6using UnityEngine;
 7
 8namespace DCL.QuestsController
 9{
 10    public delegate void NewQuest(string questId);
 11
 12    public delegate void QuestUpdated(string questId, bool hasProgress);
 13
 14    public delegate void QuestCompleted(string questId);
 15
 16    public delegate void RewardObtained(string questId, string rewardId);
 17
 18    public interface IQuestsController : IDisposable
 19    {
 20        event NewQuest OnNewQuest;
 21        event QuestUpdated OnQuestUpdated;
 22        event RewardObtained OnRewardObtained;
 23
 24        void InitializeQuests(List<QuestModel> parsedQuests);
 25        void UpdateQuestProgress(QuestModel progressedQuest);
 26        void RemoveQuest(QuestModel quest);
 27    }
 28
 29    public class QuestsController : IQuestsController
 30    {
 31        private const string PINNED_QUESTS_KEY = "PinnedQuests";
 32
 1433        public static IQuestsController i { get; internal set; }
 34
 35        public event NewQuest OnNewQuest;
 36        public event QuestUpdated OnQuestUpdated;
 37        public event RewardObtained OnRewardObtained;
 38
 2539        private static BaseCollection<string> pinnedQuests => DataStore.i.Quests.pinnedQuests;
 040        private static BaseDictionary<string, QuestModel> quests => DataStore.i.Quests.quests;
 41
 242        static QuestsController() { i = new QuestsController(); }
 43
 1044        public QuestsController()
 45        {
 1046            var savedPinnedQuests = PlayerPrefs.GetString(PINNED_QUESTS_KEY, null);
 1047            if (!string.IsNullOrEmpty(savedPinnedQuests))
 48            {
 549                pinnedQuests.Set(Utils.ParseJsonArray<string[]>(savedPinnedQuests));
 50            }
 51
 1052            pinnedQuests.OnAdded += OnPinnedQuestUpdated;
 1053            pinnedQuests.OnRemoved += OnPinnedQuestUpdated;
 1054        }
 55
 56        /// <summary>
 57        /// Bulk initialization of quests
 58        /// </summary>
 59        /// <param name="parsedQuests"></param>
 60        public void InitializeQuests(List<QuestModel> parsedQuests)
 61        {
 1162            List<QuestModel> filteredQuests = parsedQuests.Where(x => x.sections != null && x.sections.Length > 0).ToLis
 463            if (filteredQuests.Count == 0) //We ignore quests without sections/tasks
 164                return;
 65
 1166            var questsToUnpin = parsedQuests.Where(x => !x.canBePinned).Select(x => x.id);
 1267            foreach (string questId in questsToUnpin)
 68            {
 369                pinnedQuests.Remove(questId);
 70            }
 71
 372            filteredQuests.ForEach(RestoreProgressFlags);
 873            quests.Set(filteredQuests.Select(x => (x.id, x)));
 374        }
 75
 76        /// <summary>
 77        /// Update progress in a quest
 78        /// </summary>
 79        /// <param name="progressedQuest"></param>
 80        public void UpdateQuestProgress(QuestModel progressedQuest)
 81        {
 682            if (!progressedQuest.canBePinned)
 383                pinnedQuests.Remove(progressedQuest.id);
 84
 85            //Alex: Edge case. Quests has no sections/tasks, we ignore the UpdateQuestProgress and remove the cached one
 686            if (progressedQuest.sections == null || progressedQuest.sections.Length == 0)
 87            {
 088                quests.Remove(progressedQuest.id);
 089                return;
 90            }
 91
 92            //Alex: Edge case. Progressed quest was not included in the initialization. We dont invoke quests events
 693            if (!quests.TryGetValue(progressedQuest.id, out QuestModel oldQuest))
 94            {
 395                RestoreProgressFlags(progressedQuest);
 396                quests.Add(progressedQuest.id, progressedQuest);
 397                if (!progressedQuest.isCompleted)
 98                {
 299                    OnNewQuest?.Invoke(progressedQuest.id);
 2100                    QuestsControllerAnalytics.SendQuestDiscovered(progressedQuest);
 101                }
 102
 3103                return;
 104            }
 105
 3106            quests[progressedQuest.id] = progressedQuest;
 3107            progressedQuest.oldProgress = oldQuest.progress;
 108
 12109            for (int index = 0; index < progressedQuest.sections.Length; index++)
 110            {
 3111                QuestSection newQuestSection = progressedQuest.sections[index];
 112
 3113                bool oldQuestSectionFound = oldQuest.TryGetSection(newQuestSection.id, out QuestSection oldQuestSection)
 114
 12115                for (int index2 = 0; index2 < newQuestSection.tasks.Length; index2++)
 116                {
 3117                    QuestTask currentTask = newQuestSection.tasks[index2];
 3118                    if (oldQuestSectionFound)
 119                    {
 3120                        bool oldTaskFound = oldQuestSection.TryGetTask(currentTask.id, out QuestTask oldTask);
 3121                        currentTask.justProgressed = !oldTaskFound || currentTask.progress != oldTask.progress;
 3122                        if (currentTask.justProgressed)
 2123                            QuestsControllerAnalytics.SendTaskProgressed(progressedQuest, newQuestSection, currentTask);
 124
 3125                        currentTask.justUnlocked = !oldTaskFound || (currentTask.status != QuestsLiterals.Status.BLOCKED
 3126                        currentTask.oldProgress = oldTaskFound ? oldTask.progress : 0;
 3127                        if (oldTaskFound && oldTask.status != QuestsLiterals.Status.COMPLETED && currentTask.status == Q
 1128                            QuestsControllerAnalytics.SendTaskCompleted(progressedQuest, newQuestSection, currentTask);
 1129                    }
 130                    else
 131                    {
 0132                        currentTask.justProgressed = false;
 0133                        currentTask.justUnlocked = false;
 0134                        currentTask.oldProgress = 0;
 135                    }
 136                }
 137            }
 138
 139
 140            // If quest is not blocked anymore or being secret has been just started, we call NewQuest event.
 3141            if (!progressedQuest.isCompleted &&
 142                ((oldQuest.status == QuestsLiterals.Status.BLOCKED && progressedQuest.status != QuestsLiterals.Status.BL
 143                 (progressedQuest.visibility == QuestsLiterals.Visibility.SECRET && oldQuest.status == QuestsLiterals.St
 144            {
 0145                OnNewQuest?.Invoke(progressedQuest.id);
 0146                QuestsControllerAnalytics.SendQuestDiscovered(progressedQuest);
 147            }
 148
 3149            OnQuestUpdated?.Invoke(progressedQuest.id, HasProgressed(progressedQuest, oldQuest));
 3150            if (!oldQuest.isCompleted && progressedQuest.isCompleted)
 1151                QuestsControllerAnalytics.SendQuestCompleted(progressedQuest);
 152
 3153            if (progressedQuest.rewards == null)
 0154                progressedQuest.rewards = new QuestReward[0];
 155
 12156            for (int index = 0; index < progressedQuest.rewards.Length; index++)
 157            {
 3158                QuestReward newReward = progressedQuest.rewards[index];
 159
 3160                bool rewardObtained = false;
 3161                if (oldQuest.TryGetReward(newReward.id, out QuestReward oldReward))
 162                {
 2163                    rewardObtained = newReward.status != oldReward.status && newReward.status == QuestsLiterals.RewardSt
 2164                }
 165                else
 166                {
 167                    //Alex: Edge case. New quest reported contains a reward that was previously not contained.
 168                    // If it's completed, we call the RewardObtained event
 1169                    rewardObtained = newReward.status == QuestsLiterals.RewardStatus.OK;
 170                }
 171
 3172                if (rewardObtained)
 173                {
 1174                    OnRewardObtained?.Invoke(progressedQuest.id, newReward.id);
 1175                    QuestsControllerAnalytics.SendRewardObtained(progressedQuest, newReward);
 176                }
 177            }
 178
 3179            RestoreProgressFlags(progressedQuest);
 3180        }
 181
 182        private void RestoreProgressFlags(QuestModel progressedQuest)
 183        {
 11184            progressedQuest.oldProgress = progressedQuest.progress;
 44185            for (int index = 0; index < progressedQuest.sections.Length; index++)
 186            {
 11187                QuestSection section = progressedQuest.sections[index];
 44188                for (var index2 = 0; index2 < section.tasks.Length; index2++)
 189                {
 11190                    section.tasks[index2].justProgressed = false;
 11191                    section.tasks[index2].justUnlocked = false;
 11192                    section.tasks[index2].oldProgress = section.tasks[index2].progress;
 193                }
 194            }
 11195        }
 196
 0197        public void RemoveQuest(QuestModel quest) { quests.Remove(quest.id); }
 198
 16199        private void OnPinnedQuestUpdated(string questId) { PlayerPrefs.SetString(PINNED_QUESTS_KEY, JsonConvert.Seriali
 200
 201        public void Dispose()
 202        {
 0203            pinnedQuests.OnAdded -= OnPinnedQuestUpdated;
 0204            pinnedQuests.OnRemoved -= OnPinnedQuestUpdated;
 0205        }
 206
 207        private bool HasProgressed(QuestModel newQuest, QuestModel oldQuest)
 208        {
 3209            if (newQuest.rewards != null)
 210            {
 11211                foreach (QuestReward newQuestReward in newQuest.rewards)
 212                {
 3213                    if (!oldQuest.TryGetReward(newQuestReward.id, out var oldReward))
 214                        continue;
 215
 2216                    if (newQuestReward.status != oldReward.status)
 1217                        return true;
 218                }
 219            }
 220
 7221            foreach (QuestSection newQuestSection in newQuest.sections)
 222            {
 2223                if (!oldQuest.TryGetSection(newQuestSection.id, out var oldSection))
 224                    continue;
 225
 2226                if (Math.Abs(newQuestSection.progress - oldSection.progress) > Mathf.Epsilon)
 1227                    return true;
 228            }
 229
 1230            return false;
 231        }
 232    }
 233}