< 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:78
Uncovered lines:14
Coverable lines:92
Total lines:225
Line coverage:84.7% (78 of 92)
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%42.4538085.45%
RestoreProgressFlags(...)0%330100%
RemoveQuest(...)0%2100%
OnPinnedQuestUpdated(...)0%110100%
Dispose()0%2100%
HasProgressed(...)0%8.028092.86%

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
 2239        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
 944        public QuestsController()
 45        {
 946            var savedPinnedQuests = PlayerPrefs.GetString(PINNED_QUESTS_KEY, null);
 947            if (!string.IsNullOrEmpty(savedPinnedQuests))
 48            {
 449                pinnedQuests.Set(Utils.ParseJsonArray<string[]>(savedPinnedQuests));
 50            }
 51
 952            pinnedQuests.OnAdded += OnPinnedQuestUpdated;
 953            pinnedQuests.OnRemoved += OnPinnedQuestUpdated;
 954        }
 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        {
 582            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
 586            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
 593            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
 2106            quests[progressedQuest.id] = progressedQuest;
 2107            progressedQuest.oldProgress = oldQuest.progress;
 108
 8109            for (int index = 0; index < progressedQuest.sections.Length; index++)
 110            {
 2111                QuestSection newQuestSection = progressedQuest.sections[index];
 112
 2113                bool oldQuestSectionFound = oldQuest.TryGetSection(newQuestSection.id, out QuestSection oldQuestSection)
 114
 8115                for (int index2 = 0; index2 < newQuestSection.tasks.Length; index2++)
 116                {
 2117                    QuestTask currentTask = newQuestSection.tasks[index2];
 2118                    if (oldQuestSectionFound)
 119                    {
 2120                        bool oldTaskFound = oldQuestSection.TryGetTask(currentTask.id, out QuestTask oldTask);
 2121                        currentTask.justProgressed = !oldTaskFound || currentTask.progress != oldTask.progress;
 2122                        if (currentTask.justProgressed)
 2123                            QuestsControllerAnalytics.SendTaskProgressed(progressedQuest, newQuestSection, currentTask);
 124
 2125                        currentTask.justUnlocked = !oldTaskFound || (currentTask.status != QuestsLiterals.Status.BLOCKED
 2126                        currentTask.oldProgress = oldTaskFound ? oldTask.progress : 0;
 2127                        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.
 2141            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
 2149            OnQuestUpdated?.Invoke(progressedQuest.id, HasProgressed(progressedQuest, oldQuest));
 2150            if (!oldQuest.isCompleted && progressedQuest.isCompleted)
 1151                QuestsControllerAnalytics.SendQuestCompleted(progressedQuest);
 152
 2153            if (progressedQuest.rewards == null)
 0154                progressedQuest.rewards = new QuestReward[0];
 155
 8156            for (int index = 0; index < progressedQuest.rewards.Length; index++)
 157            {
 2158                QuestReward newReward = progressedQuest.rewards[index];
 159
 160                //Alex: Edge case. New quest reported contains a reward that was previously not contained.
 161                // If it's completed, we call the RewardObtained event
 2162                bool oldRewardFound = oldQuest.TryGetReward(newReward.id, out QuestReward oldReward);
 2163                bool rewardObtained = (!oldRewardFound && newReward.status == QuestsLiterals.RewardStatus.OK) || ( newRe
 2164                if (rewardObtained)
 165                {
 1166                    OnRewardObtained?.Invoke(progressedQuest.id, newReward.id);
 1167                    QuestsControllerAnalytics.SendRewardObtained(progressedQuest, newReward);
 168                }
 169            }
 170
 2171            RestoreProgressFlags(progressedQuest);
 2172        }
 173
 174        private void RestoreProgressFlags(QuestModel progressedQuest)
 175        {
 10176            progressedQuest.oldProgress = progressedQuest.progress;
 40177            for (int index = 0; index < progressedQuest.sections.Length; index++)
 178            {
 10179                QuestSection section = progressedQuest.sections[index];
 40180                for (var index2 = 0; index2 < section.tasks.Length; index2++)
 181                {
 10182                    section.tasks[index2].justProgressed = false;
 10183                    section.tasks[index2].justUnlocked = false;
 10184                    section.tasks[index2].oldProgress = section.tasks[index2].progress;
 185                }
 186            }
 10187        }
 188
 0189        public void RemoveQuest(QuestModel quest) { quests.Remove(quest.id); }
 190
 16191        private void OnPinnedQuestUpdated(string questId) { PlayerPrefs.SetString(PINNED_QUESTS_KEY, JsonConvert.Seriali
 192
 193        public void Dispose()
 194        {
 0195            pinnedQuests.OnAdded -= OnPinnedQuestUpdated;
 0196            pinnedQuests.OnRemoved -= OnPinnedQuestUpdated;
 0197        }
 198
 199        private bool HasProgressed(QuestModel newQuest, QuestModel oldQuest)
 200        {
 2201            if (newQuest.rewards != null)
 202            {
 7203                foreach (QuestReward newQuestReward in newQuest.rewards)
 204                {
 2205                    if (!oldQuest.TryGetReward(newQuestReward.id, out var oldReward))
 206                        continue;
 207
 2208                    if (newQuestReward.status != oldReward.status)
 1209                        return true;
 210                }
 211            }
 212
 3213            foreach (QuestSection newQuestSection in newQuest.sections)
 214            {
 1215                if (!oldQuest.TryGetSection(newQuestSection.id, out var oldSection))
 216                    continue;
 217
 1218                if (Math.Abs(newQuestSection.progress - oldSection.progress) > Mathf.Epsilon)
 1219                    return true;
 220            }
 221
 0222            return false;
 223        }
 224    }
 225}