public void AddActivation(TrainActivation activation)
        {
            var tiplocs = _tiplocRepository.GetTiplocsByStanox(activation.ScheduleOriginStanox);
            if (tiplocs.Any())
            {
                Trace.TraceInformation("Saving Activation: {0}", activation.TrainId);
                const string insertActivation = @"
                INSERT INTO [natrail].[dbo].[LiveTrain]
                    ([TrainId]
                    ,[Headcode]
                    ,[CreationTimestamp]
                    ,[OriginDepartTimestamp]
                    ,[TrainServiceCode]
                    ,[OriginTiplocId]
                    ,[TrainStateId])
                OUTPUT [inserted].[Id]
                VALUES
                    (@trainId
                    ,@headcode
                    ,@activationDate
                    ,@originTime
                    ,@serviceCode
                    ,@originTiplocId
                    ,@trainStateId)";

                Guid id = ExecuteInsert(insertActivation, new
                {
                    trainId = activation.TrainId,
                    headcode = activation.WorkingTTId.Substring(0, 4),
                    activationDate = activation.Activated,
                    originTime = activation.ScheduleOriginDeparture,
                    serviceCode = activation.ServiceCode,
                    originTiplocId = tiplocs.First().TiplocId,
                    trainStateId = TrainState.Activated
                });

                _trainActivationCache.Add(activation.TrainId, new Activation(id, activation.TrainId)
                {
                    ScheduleDbId = null,
                    CurrentStopNumber = 0
                }, _trainActivationCachePolicy);

                activation.UniqueId = id;

                SetLiveTrainSchedule(activation, tiplocs);
            }
        }
        private void SetLiveTrainSchedule(TrainActivation activation, IEnumerable<TiplocCode> tiplocs)
        {
            Trace.TraceInformation("Finding Schedule for activation {0},{1} with departure date {2:dd/MM/yy}",
                activation.TrainId, activation.TrainUid, activation.ScheduleOriginDeparture);

            MatchSchedule scheduleData = GetMatchingSchedule(activation);
            if (scheduleData != null)
            {
                Trace.TraceInformation("Associating Schedule '{0}' for activation '{1}'",
                    scheduleData.ScheduleId,
                    activation.TrainId);

                const string updateSql = @"
                        UPDATE [LiveTrain]
                        SET
                            [ScheduleTrain] = @scheduleId,
                            [ScheduleTrainUid] = @scheduleUid,
                            [ScheduleTrainAtocCode] = @scheduleAtocId,
                            [ScheduleTrainCategoryTypeId] = @categoryTypeId,
                            [ScheduleTrainDestinationTiplocId] = @destinationStopTiplocId
                        WHERE [Id] = @UniqueId";

                ExecuteNonQuery(updateSql, new
                {
                    scheduleId = scheduleData.ScheduleId,
                    scheduleUid = activation.TrainUid,
                    scheduleAtocId = scheduleData.AtocCode,
                    categoryTypeId = scheduleData.CategoryTypeId,
                    destinationStopTiplocId = scheduleData.DestinationStopTiplocId,
                    UniqueId = activation.UniqueId
                });

                ((Activation)_trainActivationCache[activation.TrainId]).ScheduleDbId = scheduleData.ScheduleId;
                if (!((Activation)_trainActivationCache[activation.TrainId]).Stops.Any())
                {
                    ((Activation)_trainActivationCache[activation.TrainId]).Stops = _scheduleRepository.GetStopsById(scheduleData.ScheduleId);
                }
                if (((Activation)_trainActivationCache[activation.TrainId]).Stops.Any())
                {
                    AddFirstArrivalMovement(activation.UniqueId, activation.ScheduleOriginDeparture,
                        ((Activation)_trainActivationCache[activation.TrainId]).Stops.ElementAt(0));
                }

                // if there was more than 1 tiploc see if we can find the correct one
                if (tiplocs.Count() > 1)
                {
                    foreach (var stop in ((Activation)_trainActivationCache[activation.TrainId]).Stops)
                    {
                        TiplocCode matchedTiploc = tiplocs.FirstOrDefault(t => t.TiplocId == stop.Tiploc.TiplocId);
                        if (matchedTiploc != null)
                        {
                            if (matchedTiploc.TiplocId != tiplocs.First().TiplocId)
                            {
                                UpdateLiveTrainOrigin(activation.UniqueId, matchedTiploc.TiplocId);
                            }

                            break;
                        }
                    }
                }
                if (!string.IsNullOrWhiteSpace(scheduleData.AtocCode))
                {
                    try
                    {
                        // if VSTP update toc
                        const string vstpTocSql = @"
                                UPDATE [ScheduleTrain]
                                SET [AtocCode] = @atocCode
                                WHERE [ScheduleId] = @scheduleId
                                AND [Source] = 1";

                        ExecuteNonQuery(vstpTocSql, new
                        {
                            scheduleData.ScheduleId,
                            atocCode = scheduleData.AtocCode
                        });
                    }
                    catch { }
                }
            }
            else
            {
                Trace.TraceWarning("Could not find matching schedule for activation: {0}, {1}", activation.TrainId, activation.TrainUid);
            }
        }
        public MatchSchedule GetMatchingSchedule(TrainActivation activation)
        {
            const string sql = @"
                    SELECT TOP 1
                        [ScheduleId]
                        ,[CategoryTypeId]
                        ,[AtocCode]
                        ,[DestinationStopTiplocId]
                    FROM [ScheduleTrain]
                    WHERE
                            [TrainUid] = @trainUid
                        AND [StartDate] = @startDate
                        AND [EndDate] = @endDate
                    ORDER BY [Deleted], [STPIndicatorId], [PowerTypeId] DESC";

            var result = ExecuteScalar<MatchSchedule>(sql, new
            {
                // need to trim as schedule inserted trimmed at present
                trainUid = activation.TrainUid.Trim(),
                startDate = activation.ScheduleStartDate.Date,
                endDate = activation.ScheduleEndDate.Date
            });

            if (result != null && string.IsNullOrWhiteSpace(result.AtocCode) && !string.IsNullOrWhiteSpace(activation.TocId))
            {
                try
                {
                    var code = _atocCodeRepository.GetByNumericCode(Convert.ToByte(activation.TocId));
                    if (code != null)
                    {
                        result.AtocCode = code.Code;
                    }
                }
                catch { }
            }

            return result;
        }