Пример #1
0
 public void RemoveActivity(ActivityInformation activityInformation)
 {
     if (!allProcessingActivies.Remove(activityInformation.activityID))
     {
         Debug.LogError("Remove Activity Failed.");
     }
 }
        /// <summary>
        /// Copies values from signed activity information to properties of this instance of the activity.
        /// </summary>
        /// <param name="SignedActivity">Signed description of the activity.</param>
        /// <param name="PrimaryServerId">In case of NeighborActivity, this is identifier of the primary proximity server of the activity.</param>
        public void CopyFromSignedActivityInformation(SignedActivityInformation SignedActivity, byte[] PrimaryServerId = null)
        {
            ActivityInformation activity         = SignedActivity.Activity;
            GpsLocation         activityLocation = new GpsLocation(activity.Latitude, activity.Longitude);

            byte[] pubKey     = activity.OwnerPublicKey.ToByteArray();
            byte[] identityId = Crypto.Sha256(pubKey);

            this.Version                       = new SemVer(activity.Version).ToByteArray();
            this.ActivityId                    = activity.Id;
            this.OwnerIdentityId               = identityId;
            this.OwnerPublicKey                = pubKey;
            this.OwnerProfileServerId          = activity.ProfileServerContact.NetworkId.ToByteArray();
            this.OwnerProfileServerIpAddress   = activity.ProfileServerContact.IpAddress.ToByteArray();
            this.OwnerProfileServerPrimaryPort = (ushort)activity.ProfileServerContact.PrimaryPort;
            this.Type              = activity.Type;
            this.LocationLatitude  = activityLocation.Latitude;
            this.LocationLongitude = activityLocation.Longitude;
            this.PrecisionRadius   = activity.Precision;
            this.StartTime         = ProtocolHelper.UnixTimestampMsToDateTime(activity.StartTime).Value;
            this.ExpirationTime    = ProtocolHelper.UnixTimestampMsToDateTime(activity.ExpirationTime).Value;
            this.Signature         = SignedActivity.Signature.ToByteArray();
            this.ExtraData         = activity.ExtraData;
            if (this is NeighborActivity)
            {
                (this as NeighborActivity).PrimaryServerId = PrimaryServerId;
            }
        }
Пример #3
0
    public void OnActivityAssigned(ActivityInformation activityInformation)
    {
        switch (activityInformation.activityType)
        {
        case ActivityType.Quest:
        {
            GameObject ActivityTimerGO = new GameObject(activityInformation.activityID.ToString());
            ActivityTimerGO.transform.SetParent(NotificationManager.Instance.gameObject.transform.Find("ActivitiesList"));

            ClockTimer questTimer = ActivityTimerGO.AddComponent <ClockTimer>();
            questTimer.activityInformation = activityInformation;
            break;
        }

        case ActivityType.Craft:
        {
            GameObject ActivityTimerGO = new GameObject(activityInformation.activityID.ToString());
            ActivityTimerGO.transform.SetParent(NotificationManager.Instance.gameObject.transform.Find("ActivitiesList"));

            PointTimer craftTimer = ActivityTimerGO.AddComponent <PointTimer>();
            craftTimer.activityInformation = (activityInformation);
            break;
        }

        case ActivityType.Build:
        {
            Builder builder = BuildingManager.Instance.AllBuildings.SingleOrDefault(b => b.ID == activityInformation.informationID);

            builder.representGameObject.GetComponent <BuildTimer>().activityInformation = activityInformation;
            Debug.Log($"{builder.representGameObject.GetComponent<BuildTimer>().activityInformation.activityID}");
            break;
        }

        case ActivityType.Pregnancy:
        {
            GameObject ActivityTimerGO = new GameObject(activityInformation.activityID.ToString());
            ActivityTimerGO.transform.SetParent(NotificationManager.Instance.gameObject.transform.Find("ActivitiesList"));

            ClockTimer questTimer = ActivityTimerGO.AddComponent <ClockTimer>();
            questTimer.activityInformation = activityInformation;
            break;
        }

        case ActivityType.CharacterGrowing:
        {
            GameObject ActivityTimerGO = new GameObject(activityInformation.activityID.ToString());
            ActivityTimerGO.transform.SetParent(NotificationManager.Instance.gameObject.transform.Find("ActivitiesList"));

            ClockTimer questTimer = ActivityTimerGO.AddComponent <ClockTimer>();
            questTimer.activityInformation = activityInformation;
            break;
        }

        default:
        {
            Debug.LogWarning($"{activityInformation.activityType} is currently unhandled.");
            break;
        }
        }
    }
        /// <summary>
        /// Creates a new instance of activity information from the activity.
        /// </summary>
        /// <returns>New instance of the ActivityInformation structure.</returns>
        public ActivityInformation ToActivityInformation()
        {
            GpsLocation         activityLocation = this.GetLocation();
            ActivityInformation res = new ActivityInformation()
            {
                Version              = new SemVer(this.Version).ToByteString(),
                Id                   = this.ActivityId,
                OwnerPublicKey       = ProtocolHelper.ByteArrayToByteString(this.OwnerPublicKey),
                ProfileServerContact = new ServerContactInfo()
                {
                    IpAddress   = ProtocolHelper.ByteArrayToByteString(this.OwnerProfileServerIpAddress),
                    NetworkId   = ProtocolHelper.ByteArrayToByteString(this.OwnerProfileServerId),
                    PrimaryPort = this.OwnerProfileServerPrimaryPort,
                },
                Type           = this.Type != null ? this.Type : "",
                Latitude       = activityLocation.GetLocationTypeLatitude(),
                Longitude      = activityLocation.GetLocationTypeLongitude(),
                Precision      = this.PrecisionRadius,
                StartTime      = ProtocolHelper.DateTimeToUnixTimestampMs(this.StartTime),
                ExpirationTime = ProtocolHelper.DateTimeToUnixTimestampMs(this.ExpirationTime),
                ExtraData      = this.ExtraData != null ? this.ExtraData : ""
            };

            return(res);
        }
Пример #5
0
 void OnActivityFinished(ActivityInformation activityInformation)
 {
     if (activityInformation.activityType == ActivityType.Build)
     {
         RefreshProductionAmount();
     }
 }
 void OnActivityFinished(ActivityInformation activity)
 {
     if (activity.activityType == ActivityType.Build)
     {
         RefreshInformationCanvas();
     }
 }
 public void ChangeSpeedUpCost(ActivityInformation activity, int cost)
 {
     if (gameObject.activeSelf)
     {
         Text text = transform.Find("ScrollPanel/Container/" + activity.activityID + "/SpeedUpButton/Text").GetComponent <Text>();
         text.text = $"<color=blue>{cost}</color> D";
     }
 }
Пример #8
0
    public void CancelMobileNotification(ActivityInformation activityInformation)
    {
        if (activityInformation == null)
        {
            return;
        }
#if UNITY_ANDROID
        AndroidNotificationCenter.CancelScheduledNotification(activityInformation.androidNotificationID);
#endif
    }
Пример #9
0
        /// <summary>
        /// The business logic to process the import is written here
        /// </summary>
        /// <param name="data">The input byte[] to be processed</param>
        /// <returns>An instance of ActivityDataResponse</returns>
        public override async Task <ActivityDataResponse> Import(byte[] data)
        {
            try
            {
                var content = Encoding.Default.GetString(data);

                List <string>        invalidData;
                List <CalendarChart> calendarCharts = _scheduleService.ParseCalenderCharts(content, out invalidData, true);

                if (calendarCharts.Any())
                {
                    ActivityInformation activityInformation = new ActivityInformation
                    {
                        Origin = ActivityOrigin.EStart,
                        Status = ActivityStatus.Updated,
                        Type   = ActivityType.SchedulingmanagerGrid
                    };

                    List <ScheduleManagerDetails> scheduleManagerDetailsList = await _scheduleService.GenerateAgentScheduleManagerCharts(calendarCharts, activityInformation);

                    var agentScheduleManagers = _mapper.Map <List <AgentScheduleManager> >(scheduleManagerDetailsList).ToList();
                    _agentScheduleManagerRepository.UpsertAgentScheduleManagers(agentScheduleManagers);

                    var activityLogs = _mapper.Map <List <ActivityLog> >(scheduleManagerDetailsList).ToList();
                    _activityLogRepository.CreateActivityLogs(activityLogs);

                    await _uow.Commit();
                }

                if (invalidData.Any())
                {
                    return(new ActivityDataResponse()
                    {
                        Status = (int)ProcessStatus.Partial,
                        Metadata = string.Join("\r\n", invalidData)
                    });
                }

                return(new ActivityDataResponse()
                {
                    Status = (int)ProcessStatus.Success
                });
            }
            catch (Exception ex)
            {
                return(new ActivityDataResponse()
                {
                    Status = (int)ProcessStatus.Failed,
                    Metadata = ex.Message + "at - \n\n" + ex.StackTrace
                });
            }
        }
Пример #10
0
    public void UpdateMobileNotification(ActivityInformation activityInformation)
    {
#if UNITY_ANDROID
        AndroidNotification androidNotification = new AndroidNotification()
        {
            Title    = activityInformation.activityName,
            Text     = $"{activityInformation.activityName} is already finished !",
            FireTime = new DateTime(activityInformation.finishTime),
            // ShouldAutoCancel = true
        };
        Debug.Log($"Update noti {activityInformation.activityName} to {new DateTime(activityInformation.finishTime)}");
        AndroidNotificationCenter.UpdateScheduledNotification(activityInformation.androidNotificationID, androidNotification, "Channel1");
#endif
    }
Пример #11
0
    protected override void OnActivityAssigned(ActivityInformation activityInformation)
    {
        base.OnActivityAssigned(activityInformation);
        if (slider != null)
        {
            long timer = ((finishTime - activityInformation.startPoint) / TimeSpan.TicksPerSecond) - (((finishTime - activityInformation.startPoint) - timeLeft) / TimeSpan.TicksPerSecond);

            int hours   = Mathf.FloorToInt(timer / 3600);
            int minutes = Mathf.FloorToInt(timer % 3600 / 60);
            int seconds = Mathf.FloorToInt(timer % 3600 % 60f);

            slider.GetComponentInChildren <Text>().text = String.Format("{0:00}:{1:00}:{2:00}", hours, minutes, seconds);
        }
    }
Пример #12
0
    public void AddActivity(ActivityInformation activityInformation)
    {
        if (!LoadManager.Instance.playerData.completeTutorial)
        {
            return;
        }

        activityInformation.activityID = GetActivityID();

        allProcessingActivies.Add(activityInformation.activityID, activityInformation);

        StartCoroutine(SetMobileNotificationSchedule(activityInformation));
        EventManager.Instance.ActivityAssigned(activityInformation);
    }
Пример #13
0
    IEnumerator SetMobileNotificationSchedule(ActivityInformation activityInformation)
    {
        yield return(new WaitForEndOfFrame());

        yield return(new WaitForEndOfFrame());

#if UNITY_ANDROID
        Debug.Log($"{activityInformation.activityName} Notification in {new DateTime(activityInformation.finishTime)} : {activityInformation.finishTime}");
        AndroidNotification androidNotification = new AndroidNotification()
        {
            Title    = activityInformation.activityName,
            Text     = $"{activityInformation.activityName} is already finished !",
            FireTime = new DateTime(activityInformation.finishTime),
            // ShouldAutoCancel = true
        };
        activityInformation.androidNotificationID = AndroidNotificationCenter.SendNotification(androidNotification, "Channel1");
#endif
    }
Пример #14
0
    //ตอนกดตอนสุดท้ายที่นับเวลาเสร็จ
    public void FinishQuest(ActivityInformation quest)
    {
        //  Debug.Log(quest.activityID);
        //ดึงข้อมูลเควสมา
        QuestData questData = LoadManager.Instance.allQuestData[quest.informationID];
        //สร้างลิส เก็บคาร์ทุกตัวในทีมที่ทำเควสนี้
        List <Character> characters = new List <Character>();

        characters.AddRange(townBase.CharacterInBuilding[quest.teamNumber].Characters);
        //เปลี่ยนสถานะลับเป็นปกติ
        foreach (Character character in characters)
        {
            character.workStatus = Character.WorkStatus.Working;
        }
        //เอาไว้ไปโชว์หน้า result panel
        StringBuilder questLog;

        questLog = new StringBuilder();
        //เอาไว้ไปโชว์หน้า result panel
        StringBuilder detailLog;

        detailLog = new StringBuilder();

        questLog.AppendLine($"\n<color=red> QUEST LOG </color>");
        questLog.AppendLine($"\nStarting {questData.questName} . . .");
        detailLog.AppendLine($"\n<color=red> FIGHT LOG </color>");
        detailLog.AppendLine($"\nStarting {questData.questName} . . .");

        //เกี่ยวกับการต่อสู้
        DoBattle(characters, questLog, detailLog, questData, quest);

        //โชว์ ResultPanel
        ShowResultPanel(GetQuestReward(characters, questLog, questData), questLog, detailLog);

        //เลิก lock team
        BuildManager.Instance.AllBuildings.SingleOrDefault(b => b.Type == Building.BuildingType.TownBase).TeamLockState.Remove(quest.teamNumber);

        NotificationManager.Instance.RemoveActivity(quest);

        LoadManager.Instance.SavePlayerDataToJson();

        return;
    }
Пример #15
0
    void OnActivityFinished(ActivityInformation activityInformation)
    {
        if (activityInformation.activityType == ActivityType.Build)
        {
            if (BuildingManager.Instance.AllBuildings.SingleOrDefault(b =>
                                                                      b.ID == activityInformation.informationID).Type != Building.BuildingType.Residence)
            {
                return;
            }

            List <Builder> allResidences = BuildingManager.Instance.AllBuildings.Where(b
                                                                                       => b.Type == Building.BuildingType.Residence).ToList();
            Building residenceData = LoadManager.Instance.allBuildingData[Building.BuildingType.Residence];

            int maxCharacter = 0;
            foreach (Builder residence in allResidences)
            {
                maxCharacter += residenceData.production[residence.Level]["MaxCharacterStored"];
            }
            MaxCharacterInGame = maxCharacter;
        }
    }
 public void OnActivityFinished(ActivityInformation activityInformation)
 {
     RefreshCanvas();
 }
Пример #17
0
 public void InitializeData(ActivityInformation information)
 {
     this.builder             = BuildingManager.Instance.AllBuildings.SingleOrDefault(b => b.ID == information.builderReferenceID);
     this.activityInformation = information;
 }
 public void OnActivityAssigned(ActivityInformation activityInformation)
 {
     RefreshCanvas();
 }
Пример #19
0
 public void ActivityAssigned(ActivityInformation activityInformation)
 {
     OnActivityAssigned?.Invoke(activityInformation);
 }
Пример #20
0
    void DoBattle(List <Character> characters, StringBuilder questLog, StringBuilder detailLog, QuestData questData, ActivityInformation quest)
    {
        //สร้างลืสมาเก็บศัตรูของเควสนั้นๆ
        List <Enemy> enemies = new List <Enemy>();

        foreach (Enemy enemy in LoadManager.Instance.allEnemyData.Where(e => questData.enemiesIDList.Contains(e.ID)))
        {
            //ใช้การโคลน จะทำให้ทุกครั้งที่เข้าด่านเดิม ศัตรูจะเป็นเหมือนตัวใหม่เลือดเต้มตลอด
            enemies.Add(ObjectCopier.Clone(enemy));
        }


        //เอาลีดเดอร์มาคิดคำนวณอะไรด้านล่าง
        Character leader = characters[0];

        int teamSpeed    = characters.Sum(c => c.Stats.speed);
        int enemiesSpeed = enemies.Sum(e => e.Stats.speed);


        //ลูปนี้ไว้ใช้กับ questLog
        foreach (Enemy enemy in enemies)
        {
            Debug.Log("enemy CurrentHp" + enemy.CurrentHp.ToString());
            questLog.AppendLine($"Wild {enemy.Name} appears !");
        }

        //ถ้าตรงตามเงื่อนไข จะถือว่าจบเควสนั้นเลย ได้ของ บลาๆ เพราะหลบหลีกได้
        if ((leader.Stats.intelligence >= enemies[0].Stats.intelligence * 5) && (teamSpeed > enemiesSpeed))  // ****************
        {
            foreach (Enemy enemy in enemies)
            {
                // Debug.Log($"Thanks to leader({leader.Name}) intelligence({leader.Stats.intelligence}), \nteam successfully avoid encountering {enemy.Name}({enemy.Stats.intelligence}).");
                questLog.AppendLine($"Thanks to leader({leader.Name}) intelligence({leader.Stats.intelligence}),\n team successfully avoid encountering {enemy.Name}({enemy.Stats.intelligence}).");
                detailLog.AppendLine($"Thanks to leader({leader.Name}) intelligence({leader.Stats.intelligence}),\n team successfully avoid encountering {enemy.Name}({enemy.Stats.intelligence}).");
            }
        }

        //ถ้าไม่ได้ก็ต้องสู้จ้า
        else
        {
            //สำหรัวหน้า result panel
            foreach (Enemy enemy in enemies)
            {
                questLog.AppendLine($"Start a battle with {enemy.Name} !");
                detailLog.AppendLine($"\nStart a battle with {enemy.Name} !");
            }

            //ค่าเริ่มต้นของ ActionPoint
            InitActionPoint(characters, enemies);

            //ถ้าเลือกหลีกเลี่ยงการสู้
            if (quest.AvoidBattle)
            {
                Debug.Log("AvoidBattle");

                detailLog.AppendLine($"Try to run away from {(enemies.Count > 1 ? "enemies" : "enemy")} !");

                //ถ้าหนีไม่ได้
                if (!TryRunForLife())
                {
                    Debug.Log("Fail to run away");

                    detailLog.AppendLine($"Fail to run away from the {(enemies.Count > 1 ? "enemies" : "enemy")}!");

                    //เริ่มเทิร์น
                    while (!CalculateBattleTurn(characters, enemies, questLog, detailLog, questData))
                    {
                        ;
                    }
                    //พอเสร็จเซทเทิร์นเป็น 0 ก่อน
                    turn = 0;
                }
                else
                {
                    Debug.Log("Avoid success.");

                    detailLog.AppendLine($"Successfully run away from the {(enemies.Count > 1 ? "enemies" : "enemy")}.");

                    //หนีได้ไปโชว์หน้าสรุปเลย
                    ShowCharactersHP(characters, questData.EXPreceived, questLog, detailLog);
                }
            }
            else //ถ้าไม่เลือกหลีกเลี่ยง มันจะต่อสู้เลย
            {
                //เริ่มเทิร์น  m
                Debug.Log("DidntAvoidBattle");
                while (!CalculateBattleTurn(characters, enemies, questLog, detailLog, questData))
                {
                    ;
                }
                turn = 0;
            }
        }
    }
Пример #21
0
 public void ActivityFinished(ActivityInformation activityInformation)
 {
     OnActivityFinished?.Invoke(activityInformation);
 }
Пример #22
0
    public void OnActivityFinished(ActivityInformation activityInformation)
    {
        switch (activityInformation.activityType)
        {
        case ActivityType.Quest:
        {
            /// Update in Notification Panel
            break;
        }

        case ActivityType.Craft:
        {
            Resource resource = LoadManager.Instance.allResourceData.SingleOrDefault(r => r.Value.ID == activityInformation.informationID).Value;

            ItemManager.Instance.AddResource(resource.Name, 1);

            PointTimer craftTimer = NotificationManager.Instance.gameObject.transform.Find("ActivitiesList/"
                                                                                           + activityInformation.activityID).GetComponent <PointTimer>();
            Destroy(craftTimer.gameObject);
            RemoveActivity(activityInformation);

            break;
        }

        case ActivityType.Build:
        {
            RemoveActivity(activityInformation);
            break;
        }

        case ActivityType.Pregnancy:
        {
            Character femaleCharacter = CharacterManager.Instance.AllCharacters.SingleOrDefault(c => c.ID == activityInformation.informationID);
            Character maleCharacter   = CharacterManager.Instance.AllCharacters.SingleOrDefault(c => c.ID == activityInformation.informationID2);
            femaleCharacter.workStatus = Character.WorkStatus.Working;

            CharacterManager.Instance.CreateChildCharacter(maleCharacter, femaleCharacter);

            ClockTimer timer = NotificationManager.Instance.gameObject.transform.Find("ActivitiesList/" + activityInformation.activityID).GetComponent <ClockTimer>();
            Destroy(timer.gameObject);
            RemoveActivity(activityInformation);
            break;
        }

        case ActivityType.CharacterGrowing:
        {
            ClockTimer timer = NotificationManager.Instance.gameObject.transform.Find("ActivitiesList/" + activityInformation.activityID).GetComponent <ClockTimer>();
            Destroy(timer.gameObject);

            RemoveActivity(activityInformation);

            Character character = CharacterManager.Instance.AllCharacters.SingleOrDefault(c => c.ID == activityInformation.informationID);
            character.workStatus = Character.WorkStatus.Idle;

            break;
        }

        default:
        {
            Debug.LogWarning($"{activityInformation.activityType} is currently unhandled.");
            break;
        }
        }
    }
Пример #23
0
 protected virtual void OnActivityAssigned(ActivityInformation activityInformation)
 {
 }
Пример #24
0
 private void OnActivityAssigned(ActivityInformation activityInformation)
 {
 }
Пример #25
0
 private void OnActivityFinished(ActivityInformation activityInformation)
 {
     RefreshNotificationAmount();
 }
Пример #26
0
        /// <summary>
        /// Updates an existing activity in the database. Then a new neighborhood action is created to propagate the changes to the neighborhood
        /// if this is required. If the update is rejected, the action is deleted from the database and this is propagated to the neighborhood.
        /// <para>Note that the change in activity is not propagated if the client sets no propagation flag in the request, or if only the activity
        /// expiration date or its location is changed.</para>
        /// </summary>
        /// <param name="UpdateRequest">Update request received from the client.</param>
        /// <param name="Signature">Signature of the updated activity data from the client.</param>
        /// <param name="OwnerIdentityId">Network ID of the client who requested the update.</param>
        /// <param name="CloserServerId">If the result is Status.ErrorRejected, this is filled with network identifier of a neighbor server that is closer to the target location.</param>
        /// <returns>Status.Ok if the function succeeds,
        /// Status.ErrorNotFound if the activity to update does not exist,
        /// Status.ErrorRejected if the update was rejected and the client should migrate the activity to closest proximity server,
        /// Status.ErrorInvalidValue if the update attempted to change activity's type,
        /// Status.ErrorInternal otherwise.</returns>
        public async Task <Status> UpdateAndPropagateAsync(UpdateActivityRequest UpdateRequest, byte[] Signature, byte[] OwnerIdentityId, StrongBox <byte[]> CloserServerId)
        {
            log.Trace("(UpdateRequest.Activity.Id:{0},OwnerIdentityId:'{1}')", UpdateRequest.Activity.Id, OwnerIdentityId.ToHex());

            Status res = Status.ErrorInternal;

            bool success = false;
            bool signalNeighborhoodAction           = false;
            bool migrateActivity                    = false;
            ActivityInformation activityInformation = UpdateRequest.Activity;

            DatabaseLock[] lockObjects = new DatabaseLock[] { UnitOfWork.PrimaryActivityLock, UnitOfWork.FollowerLock, UnitOfWork.NeighborhoodActionLock };
            using (IDbContextTransaction transaction = await unitOfWork.BeginTransactionWithLockAsync(lockObjects))
            {
                try
                {
                    PrimaryActivity existingActivity = (await GetAsync(a => (a.ActivityId == activityInformation.Id) && (a.OwnerIdentityId == OwnerIdentityId))).FirstOrDefault();
                    if (existingActivity != null)
                    {
                        // First, we check whether the activity should be migrated to closer proximity server.
                        GpsLocation oldLocation     = existingActivity.GetLocation();
                        GpsLocation newLocation     = new GpsLocation(activityInformation.Latitude, activityInformation.Longitude);
                        bool        locationChanged = !oldLocation.Equals(newLocation);

                        bool error = false;
                        if (locationChanged)
                        {
                            List <byte[]> ignoreServerIds = new List <byte[]>(UpdateRequest.IgnoreServerIds.Select(i => i.ToByteArray()));
                            if (!await unitOfWork.NeighborRepository.IsServerNearestToLocationAsync(newLocation, ignoreServerIds, CloserServerId, ProxMessageBuilder.ActivityMigrationDistanceTolerance))
                            {
                                if (CloserServerId.Value != null)
                                {
                                    migrateActivity = true;
                                    log.Debug("Activity's new location is outside the reach of this proximity server, the activity will be deleted from the database.");
                                }
                                else
                                {
                                    error = true;
                                }
                            }
                            // else No migration needed
                        }

                        if (!error)
                        {
                            // If it should not be migrated, we update the activity in our database.
                            if (!migrateActivity)
                            {
                                SignedActivityInformation signedActivityInformation = new SignedActivityInformation()
                                {
                                    Activity  = activityInformation,
                                    Signature = ProtocolHelper.ByteArrayToByteString(Signature)
                                };

                                PrimaryActivity updatedActivity = ActivityBase.FromSignedActivityInformation <PrimaryActivity>(signedActivityInformation);
                                ActivityChange  changes         = existingActivity.CompareChangeTo(updatedActivity);

                                if ((changes & ActivityChange.Type) == 0)
                                {
                                    bool propagateChange = false;
                                    if (!UpdateRequest.NoPropagation)
                                    {
                                        // If only changes in the activity are related to location or expiration time, the activity update is not propagated to the neighborhood.
                                        propagateChange = (changes & ~(ActivityChange.LocationLatitude | ActivityChange.LocationLongitude | ActivityChange.PrecisionRadius | ActivityChange.ExpirationTime)) != 0;
                                    }

                                    existingActivity.CopyFromSignedActivityInformation(signedActivityInformation);

                                    Update(existingActivity);

                                    if (propagateChange)
                                    {
                                        // The activity has to be propagated to all our followers we create database actions that will be processed by dedicated thread.
                                        signalNeighborhoodAction = await unitOfWork.NeighborhoodActionRepository.AddActivityFollowerActionsAsync(NeighborhoodActionType.ChangeActivity, existingActivity.ActivityId, existingActivity.OwnerIdentityId);
                                    }
                                    else
                                    {
                                        log.Trace("Change of activity ID {0}, owner identity ID '{1}' won't be propagated to neighborhood.", existingActivity.ActivityId, existingActivity.OwnerIdentityId.ToHex());
                                    }

                                    await unitOfWork.SaveThrowAsync();

                                    transaction.Commit();
                                    success = true;
                                }
                                else
                                {
                                    log.Debug("Activity ID {0}, owner identity ID '{1}' attempt to change type.", activityInformation.Id, OwnerIdentityId.ToHex());
                                    res = Status.ErrorInvalidValue;
                                }
                            }
                            // else this is handled below separately, out of locked section
                        }
                        // else Internal error
                    }
                    else
                    {
                        log.Debug("Activity ID {0}, owner identity ID '{1}' does not exist.", activityInformation.Id, OwnerIdentityId.ToHex());
                        res = Status.ErrorNotFound;
                    }
                }
                catch (Exception e)
                {
                    log.Error("Exception occurred: {0}", e.ToString());
                }

                if (!success)
                {
                    log.Warn("Rolling back transaction.");
                    unitOfWork.SafeTransactionRollback(transaction);
                }

                unitOfWork.ReleaseLock(lockObjects);
            }


            if (migrateActivity)
            {
                // If activity should be migrated, we delete it from our database and inform our neighbors.
                StrongBox <bool> notFound = new StrongBox <bool>(false);
                if (await DeleteAndPropagateAsync(activityInformation.Id, OwnerIdentityId, notFound))
                {
                    if (!notFound.Value)
                    {
                        // The activity was deleted from the database and this change will be propagated to the neighborhood.
                        log.Debug("Update rejected, activity ID {0}, owner identity ID '{1}' deleted.", activityInformation.Id, OwnerIdentityId.ToHex());
                        res = Status.ErrorRejected;
                    }
                    else
                    {
                        // Activity of given ID not found among activities created by the client.
                        res = Status.ErrorNotFound;
                    }
                }
            }

            if (success)
            {
                // Send signal to neighborhood action processor to process the new series of actions.
                if (signalNeighborhoodAction)
                {
                    Network.NeighborhoodActionProcessor neighborhoodActionProcessor = (Network.NeighborhoodActionProcessor)Base.ComponentDictionary[Network.NeighborhoodActionProcessor.ComponentName];
                    neighborhoodActionProcessor.Signal();
                }

                res = Status.Ok;
            }


            log.Trace("(-):{0}", res);
            return(res);
        }
        /// <summary>
        /// Validates ActivityInformation structure by itself. This function does not touch database and does not validate
        /// anything that depends on the context.
        /// </summary>
        /// <param name="Activity">Description of the activity to validate.</param>
        /// <param name="OwnerIdentityPublicKey">Public key of the activity's owner identity.</param>
        /// <param name="MessageBuilder">Network message builder of the client who sent this activity description.</param>
        /// <param name="RequestMessage">Full request message from client.</param>
        /// <param name="ErrorPrefix">Prefix to add to the validation error details.</param>
        /// <param name="ErrorResponse">If the function fails, this is filled with error response message that is ready to be sent to the client.</param>
        /// <returns>true if the activity information is valid, false otherwise.</returns>
        public static bool ValidateActivityInformation(ActivityInformation Activity, byte[] OwnerIdentityPublicKey, ProxMessageBuilder MessageBuilder, ProxProtocolMessage RequestMessage, string ErrorPrefix, out ProxProtocolMessage ErrorResponse)
        {
            log.Trace("()");

            bool res = false;

            ErrorResponse = null;
            string details = null;

            if (Activity == null)
            {
                Activity = new ActivityInformation();
            }
            if (Activity.ProfileServerContact == null)
            {
                Activity.ProfileServerContact = new ServerContactInfo();
            }

            SemVer version = new SemVer(Activity.Version);

            // Currently only supported version is 1.0.0.
            if (!version.Equals(SemVer.V100))
            {
                log.Debug("Unsupported version '{0}'.", version);
                details = "version";
            }


            if (details == null)
            {
                uint activityId = Activity.Id;

                // 0 is not a valid activity identifier.
                if (activityId == 0)
                {
                    log.Debug("Invalid activity ID '{0}'.", activityId);
                    details = "id";
                }
            }

            if (details == null)
            {
                byte[] pubKey      = Activity.OwnerPublicKey.ToByteArray();
                bool   pubKeyValid = (0 < pubKey.Length) && (pubKey.Length <= ProtocolHelper.MaxPublicKeyLengthBytes) && ByteArrayComparer.Equals(OwnerIdentityPublicKey, pubKey);
                if (!pubKeyValid)
                {
                    log.Debug("Invalid public key '{0}' does not match identity public key '{1}'.", pubKey.ToHex(), OwnerIdentityPublicKey.ToHex());
                    details = "ownerPublicKey";
                }
            }


            if (details == null)
            {
                ServerContactInfo sci    = Activity.ProfileServerContact;
                bool      networkIdValid = sci.NetworkId.Length == ProtocolHelper.NetworkIdentifierLength;
                IPAddress ipAddress      = IPAddressExtensions.IpFromBytes(sci.IpAddress.ToByteArray());
                bool      ipAddressValid = (ipAddress != null) && (Config.Configuration.TestModeEnabled || !ipAddress.IsReservedOrLocal());
                bool      portValid      = (1 <= sci.PrimaryPort) && (sci.PrimaryPort <= 65535);

                if (!networkIdValid || !ipAddressValid || !portValid)
                {
                    log.Debug("Profile server contact's network ID is {0}, IP address is {1}, port is {2}.", networkIdValid ? "valid" : "invalid", ipAddressValid ? "valid" : "invalid", portValid ? "valid" : "invalid");

                    if (!networkIdValid)
                    {
                        details = "profileServerContact.networkId";
                    }
                    else if (!ipAddressValid)
                    {
                        details = "profileServerContact.ipAddress";
                    }
                    else if (!portValid)
                    {
                        details = "profileServerContact.primaryPort";
                    }
                }
            }

            if (details == null)
            {
                string activityType = Activity.Type;
                if (activityType == null)
                {
                    activityType = "";
                }

                int  byteLen           = Encoding.UTF8.GetByteCount(activityType);
                bool activityTypeValid = (0 < byteLen) && (byteLen <= ProxMessageBuilder.MaxActivityTypeLengthBytes);
                if (!activityTypeValid)
                {
                    log.Debug("Activity type too long or zero length ({0} bytes, limit is {1}).", byteLen, ProxMessageBuilder.MaxActivityTypeLengthBytes);
                    details = "type";
                }
            }

            if (details == null)
            {
                GpsLocation locLat  = new GpsLocation(Activity.Latitude, 0);
                GpsLocation locLong = new GpsLocation(0, Activity.Longitude);
                if (!locLat.IsValid())
                {
                    log.Debug("Latitude '{0}' is not a valid GPS latitude value.", Activity.Latitude);
                    details = "latitude";
                }
                else if (!locLong.IsValid())
                {
                    log.Debug("Longitude '{0}' is not a valid GPS longitude value.", Activity.Longitude);
                    details = "longitude";
                }
            }

            if (details == null)
            {
                uint precision      = Activity.Precision;
                bool precisionValid = (0 <= precision) && (precision <= ProxMessageBuilder.MaxLocationPrecision);
                if (!precisionValid)
                {
                    log.Debug("Precision '{0}' is not an integer between 0 and {1}.", precision, ProxMessageBuilder.MaxLocationPrecision);
                    details = "precision";
                }
            }


            if (details == null)
            {
                DateTime?startTime      = ProtocolHelper.UnixTimestampMsToDateTime(Activity.StartTime);
                DateTime?expirationTime = ProtocolHelper.UnixTimestampMsToDateTime(Activity.ExpirationTime);

                if (startTime == null)
                {
                    log.Debug("Invalid activity start time timestamp '{0}'.", Activity.StartTime);
                    details = "startTime";
                }
                else if (expirationTime == null)
                {
                    log.Debug("Invalid activity expiration time timestamp '{0}'.", Activity.ExpirationTime);
                    details = "expirationTime";
                }
                else
                {
                    if (startTime > expirationTime)
                    {
                        log.Debug("Activity expiration time has to be greater than or equal to its start time.");
                        details = "expirationTime";
                    }
                    else if (expirationTime.Value > DateTime.UtcNow.AddHours(ActivityBase.MaxActivityLifeTimeHours))
                    {
                        log.Debug("Activity expiration time {0} is more than {1} hours in the future.", expirationTime.Value.ToString("yyyy-MM-dd HH:mm:ss"), ActivityBase.MaxActivityLifeTimeHours);
                        details = "expirationTime";
                    }
                }
            }

            if (details == null)
            {
                string extraData = Activity.ExtraData;
                if (extraData == null)
                {
                    extraData = "";
                }


                // Extra data is semicolon separated 'key=value' list, max ActivityBase.MaxActivityExtraDataLengthBytes bytes long.
                int byteLen = Encoding.UTF8.GetByteCount(extraData);
                if (byteLen > ProxMessageBuilder.MaxActivityExtraDataLengthBytes)
                {
                    log.Debug("Extra data too large ({0} bytes, limit is {1}).", byteLen, ProxMessageBuilder.MaxActivityExtraDataLengthBytes);
                    details = "extraData";
                }
            }

            if (details == null)
            {
                res = true;
            }
            else
            {
                ErrorResponse = MessageBuilder.CreateErrorInvalidValueResponse(RequestMessage, ErrorPrefix + details);
            }

            log.Trace("(-):{0}", res);
            return(res);
        }