Inheritance: ModelBase
        internal HybridDictionary<int, ProgressInfo> Reload()
        {
            using (var rCommand = Connection.CreateCommand())
            {
                rCommand.CommandText = "SELECT * FROM quest;";

                using (var rReader = rCommand.ExecuteReader())
                    while (rReader.Read())
                    {
                        var rID = Convert.ToInt32(rReader["id"]);
                        var rResetType = (QuestType)Convert.ToInt32(rReader["type"]);
                        var rState = (QuestState)Convert.ToInt32(rReader["state"]);
                        var rProgress = Convert.ToInt32(rReader["progress"]);
                        var rUpdateTime = DateTimeUtil.FromUnixTime(Convert.ToUInt64(rReader["update_time"]));

                        ProgressInfo rInfo;
                        if (!r_Progresses.TryGetValue(rID, out rInfo))
                            r_Progresses.Add(rID, rInfo = new ProgressInfo(rID, rResetType, rState, rProgress, rUpdateTime));
                        else
                        {
                            rInfo.State = rState;
                            rInfo.Progress = rProgress;
                            rInfo.UpdateTime = rUpdateTime;
                        }
                    }
            }

            return r_Progresses;
        }
        internal void UpdateResetType(ProgressInfo rpProgress)
        {
            using (var rCommand = Connection.CreateCommand())
            {
                rCommand.CommandText = "UPDATE quest SET type = @type WHERE id = @id;";
                rCommand.Parameters.AddWithValue("@id", rpProgress.Quest.ID);
                rCommand.Parameters.AddWithValue("@type", rpProgress.ResetType);

                rCommand.ExecuteNonQuery();
            }
        }
        internal void UpdateState(ProgressInfo rpProgress)
        {
            using (var rCommand = Connection.CreateCommand())
            {
                rCommand.CommandText = "UPDATE quest SET state = @state, update_time = strftime('%s', 'now') WHERE id = @id;";
                rCommand.Parameters.AddWithValue("@id", rpProgress.Quest.ID);
                rCommand.Parameters.AddWithValue("@state", rpProgress.State);

                rCommand.ExecuteNonQuery();
            }
        }
        void Increase()
        {
            var rProgress = r_Quest.RealtimeProgress;
            if (rProgress == null)
            {
                RecordService.Instance.QuestProgress.InsertRecord(r_Quest.RawData, 0);
                rProgress = new ProgressInfo(r_Quest.ID, r_Quest.Type, QuestState.Executing, 0);
                QuestProgressService.Instance.Progresses.Add(r_Quest.ID, rProgress);
                r_Quest.RealtimeProgress = rProgress;
            }

            rProgress.Progress++;
        }
        void ProcessQuestList(RawQuestList rpData)
        {
            if (GetResetTime(QuestType.Daily) > r_LastProcessTime)
            {
                var rQuests = KanColleGame.Current.Port.Quests.Table;
                var rOutdatedProgresses = Progresses.Values.Where(r => GetResetTime(!r.Quest.IsDailyReset ? r.ResetType : QuestType.Daily) > r.UpdateTime).ToArray();

                foreach (var rProgressInfo in rOutdatedProgresses)
                {
                    var rID = rProgressInfo.Quest.ID;

                    rQuests.Remove(rID);
                    Progresses.Remove(rID);
                }
            }

            if (rpData == null)
                return;

            foreach (var rQuest in rpData.Quests)
            {
                var rID = rQuest.ID;

                QuestInfo rInfo;
                if (!Infos.TryGetValue(rID, out rInfo))
                    continue;

                var rTotal = rInfo.Total;
                int rProgress;

                ProgressInfo rProgressInfo;
                if (Progresses.TryGetValue(rID, out rProgressInfo))
                {
                    rProgress = rProgressInfo.Progress;

                    if (rQuest.State == QuestState.Completed)
                        rProgress = rTotal;
                    else
                        switch (rQuest.Progress)
                        {
                            case QuestProgress.Progress50: rProgress = Math.Max(rProgress, (int)Math.Ceiling(rTotal * 0.5) - rInfo.StartFrom); break;
                            case QuestProgress.Progress80: rProgress = Math.Max(rProgress, (int)Math.Ceiling(rTotal * 0.8) - rInfo.StartFrom); break;
                        }

                    rProgressInfo.Progress = rProgress;
                    rProgressInfo.State = rQuest.State;
                }
                else
                {
                    rProgress = 0;

                    if (rQuest.State == QuestState.Completed)
                        rProgress = rTotal;
                    else
                        switch (rQuest.Progress)
                        {
                            case QuestProgress.Progress50: rProgress = (int)Math.Ceiling(rTotal * 0.5) - rInfo.StartFrom; break;
                            case QuestProgress.Progress80: rProgress = (int)Math.Ceiling(rTotal * 0.8) - rInfo.StartFrom; break;
                        }

                    Progresses.Add(rID, rProgressInfo = new ProgressInfo(rID, rQuest.Type, rQuest.State, rProgress));
                }

                if (rQuest.State == QuestState.Executing)
                    RecordService.Instance.QuestProgress.InsertRecord(rQuest, rProgress);

                KanColleGame.Current.Port.Quests[rID].RealtimeProgress = rProgressInfo;
            }

            r_LastProcessTime = DateTimeOffset.Now.ToOffset(Offset);
        }
        void ProcessQuestList(RawQuestList rpData)
        {
            if (rpData != null && rpData.Quests != null)
                foreach (var rRawQuest in rpData.Quests)
                {
                    ProgressInfo rProgressInfo;
                    if (Progresses.TryGetValue(rRawQuest.ID, out rProgressInfo))
                        rProgressInfo.ResetType = rRawQuest.Type;
                }

            var rQuests = KanColleGame.Current.Port.Quests.Table;
            if (GetResetTime(QuestType.Daily) > r_LastProcessTime)
            {
                var rOutdatedProgresses = Progresses.Values.Where(r => GetResetTime(!r.Quest.IsDailyReset ? r.ResetType : QuestType.Daily) > r.UpdateTime).ToArray();
                foreach (var rProgressInfo in rOutdatedProgresses)
                {
                    var rID = rProgressInfo.Quest.ID;

                    rQuests.Remove(rID);
                    Progresses.Remove(rID);
                    RecordService.Instance.QuestProgress.DeleteRecord(rID);
                }
                var rOutdatedQuests = rQuests.Values.Where(r => GetResetTime(r.Type) > r.CreationTime).ToArray();
                foreach (var rQuest in rOutdatedQuests)
                    rQuests.Remove(rQuest);
            }

            if (rpData == null || rpData.Quests == null)
                return;

            foreach (var rRawQuest in rpData.Quests)
            {
                var rID = rRawQuest.ID;

                QuestInfo rInfo;
                ProgressInfo rProgressInfo = null;
                if (!Infos.TryGetValue(rID, out rInfo))
                    Progresses.TryGetValue(rID, out rProgressInfo);
                else
                {
                    var rTotal = rInfo.Total;
                    if (rTotal > 0)
                    {
                        int rProgress;
                        if (Progresses.TryGetValue(rID, out rProgressInfo) && rQuests.ContainsKey(rID))
                        {
                            rProgress = rProgressInfo.Progress;

                            if (rRawQuest.State == QuestState.Completed)
                                rProgress = rTotal;
                            else if (rID != 214)
                                switch (rRawQuest.Progress)
                                {
                                    case QuestProgress.Progress50: rProgress = Math.Max(rProgress, (int)Math.Ceiling(rTotal * 0.5) - rInfo.StartFrom); break;
                                    case QuestProgress.Progress80: rProgress = Math.Max(rProgress, (int)Math.Ceiling(rTotal * 0.8) - rInfo.StartFrom); break;
                                }

                            rProgressInfo.Progress = rProgress;
                            rProgressInfo.State = rRawQuest.State;
                        }
                        else
                        {
                            rProgress = 0;

                            if (rRawQuest.State == QuestState.Completed)
                                rProgress = rTotal;
                            else if (rID != 214)
                                switch (rRawQuest.Progress)
                                {
                                    case QuestProgress.Progress50: rProgress = (int)Math.Ceiling(rTotal * 0.5) - rInfo.StartFrom; break;
                                    case QuestProgress.Progress80: rProgress = (int)Math.Ceiling(rTotal * 0.8) - rInfo.StartFrom; break;
                                }

                            Progresses.Add(rID, rProgressInfo = new ProgressInfo(rID, rRawQuest.Type, rRawQuest.State, rProgress));
                        }

                        if (rID == 214)
                        {
                            OSSQuestProgressRule rOSSRule;
                            if (OSSQuestProgressRule.Maps.TryGetValue(214, out rOSSRule))
                                ((OperationA)rOSSRule).UpdatePercentage(rProgressInfo);
                        }

                        if (rRawQuest.State == QuestState.Active)
                            RecordService.Instance.QuestProgress.InsertRecord(rRawQuest, rProgress);
                    }
                }

                QuestClass rQuest;
                if (!rQuests.TryGetValue(rID, out rQuest))
                    rQuests.Add(rQuest = new QuestClass(rRawQuest));

                rQuest.RealtimeProgress = rProgressInfo;
                rQuest.Extra = rInfo;
            }

            r_LastProcessTime = DateTimeOffset.Now.ToOffset(Offset);
        }