Ejemplo n.º 1
0
        private void UpdateEnforcementActionTakenFromSqLite(SpaceStatusModel model, CustomerLogic result)
        {
            DateTime minDateCutoff = DateTime.MinValue;

            // Get the related space asset so we can obtain the AreaID
            SpaceAsset asset  = GetSpaceAsset(model.MeterID, model.BayID); // CustomerLogic.CustomerManager.GetSpaceAsset(_CustomerConfig, model.MeterID, model.BayID);
            int        areaID = 0;

            if (asset != null)
            {
                areaID = asset.AreaID_Internal;
            }


            if (((model.BayEnforcementState == EnforcementState.OverstayViolation) || (model.BayEnforcementState == EnforcementState.Discretionary)) &&
                (model.CurrentOverstayOrLatestDiscretionaryVio != null))
            {
                // For overstay condition, we only want the latest action taken if it happened after the violation started!
                minDateCutoff = model.CurrentOverstayOrLatestDiscretionaryVio.DateTime_StartOfOverstayViolation;

                // Get the most recent action taken for this space asset



                OverstayVioActionsDTO ActionTakenDTO = result.GetLatestVioActionForSpace(this._CustomerConfig.CustomerId, model.MeterID, areaID, model.BayID);
                if ((ActionTakenDTO != null) && (minDateCutoff > DateTime.MinValue))
                {
                    // If the action taken was recorded after the start of this violation, then it qualifies as being the action taken for this
                    // violation condition. If so, retain the "Action Taken" reason
                    if (ActionTakenDTO.EventTimestamp >= minDateCutoff)
                    {
                        model.EnforcementActionTaken = ActionTakenDTO.ActionTaken;
                    }
                }
            }
            else
            {
                minDateCutoff = model.BayVehicleSensingTimestamp;

                // Get the most recent action taken for this space asset
                OverstayVioActionsDTO ActionTakenDTO = result.GetLatestVioActionForSpace(this._CustomerConfig.CustomerId, model.MeterID, areaID, model.BayID);
                if ((ActionTakenDTO != null) && (minDateCutoff >= DateTime.MinValue))
                {
                    // If the action taken was recorded after the start of this violation, then it qualifies as being the action taken for this
                    // violation condition. If so, retain the "Action Taken" reason
                    if (ActionTakenDTO.EventTimestamp >= minDateCutoff)
                    {
                        model.EnforcementActionTaken = ActionTakenDTO.ActionTaken;
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public SpaceStatusModel GetOrCreateSpaceStatusModel(int meterID, int spaceID, SpaceAsset spaceAsset)
        {
            // Search our list for an existing model matching the MeterID and SpaceID
            SpaceStatusModel result = null;

            foreach (SpaceStatusModel nextModel in this.SpaceStatusModels)
            {
                if ((nextModel.MeterID == meterID) && (nextModel.BayID == spaceID))
                {
                    result = nextModel;
                    break;
                }
            }

            // If no match found, create a new object
            if (result == null)
            {
                result         = new SpaceStatusModel();
                result.MeterID = meterID;
                result.BayID   = spaceID;

                // If the associated space asset wasn't given to us, we will need to look it up
                if (spaceAsset == null)
                {
                    SpaceAsset nextSpaceAsset = GetSpaceAsset(meterID, spaceID); // CustomerLogic.CustomerManager.GetSpaceAsset(_CustomerConfig, meterID, spaceID);
                    if (nextSpaceAsset != null)
                    {
                        result.IsSensorOnly = nextSpaceAsset.IsSensorOnly;
                    }
                }
                else
                {
                    result.IsSensorOnly = spaceAsset.IsSensorOnly;
                }

                // Add the new object to our list
                this.SpaceStatusModels.Add(result);
            }

            return(result);
        }
Ejemplo n.º 3
0
        private SpaceAsset GetSpaceAsset(int meterID, int spaceID)
        {
            SpaceAsset result = null;

            // If we have a list of cached assets, look through it, which should be faster than constantly asking the customer manager for it
            // since we would have a local copy and not need to worry about concurrency issues
            if (_cachedSpaceAssets != null)
            {
                foreach (SpaceAsset asset in _cachedSpaceAssets)
                {
                    if ((asset.MeterID == meterID) && (asset.SpaceID == spaceID))
                    {
                        result = asset;
                        break;
                    }
                }
            }
            else
            {
                result = CustomerLogic.CustomerManager.GetSpaceAsset(_CustomerConfig, meterID, spaceID);
            }

            return(result);
        }
Ejemplo n.º 4
0
        public Object GetData(IDataReader reader)
        {
            // This is where we define the mapping between the object properties and the
            // data columns. The convention that should be used is that the object property
            // names are exactly the same as the column names. However if there is some
            // compelling reason for the names to be different, the mapping can be defined here.

            // We assume the reader has data and is already on the row that contains the data
            // we need. We don't need to call read. As a general rule, assume that every field must
            // be null  checked. If a field is null then the nullvalue for that field has already
            // been set by the DTO constructor, we don't have to change it.

            if (!_isInitialized)
            {
                InitializeMapper(reader);
            }

            // Now we can load the data into the DTO object from the DB reader
            SpaceAsset dto = new SpaceAsset();

            if (!reader.IsDBNull(_ordinal_ParkingSpaceID))
            {
                dto.ParkingSpaceId_Internal = Convert.ToInt64(reader[_ordinal_ParkingSpaceID]);
            }
            if (!reader.IsDBNull(_ordinal_BayNumber))
            {
                dto.SpaceID = Convert.ToInt32(reader[_ordinal_BayNumber]);
            }
            if (!reader.IsDBNull(_ordinal_AreaID))
            {
                dto.AreaID_Internal = Convert.ToInt32(reader[_ordinal_AreaID]);
            }
            if (!reader.IsDBNull(_ordinal_LibertyArea))
            {
                dto.AreaID_Liberty = Convert.ToInt32(reader[_ordinal_LibertyArea]);
            }
            if (!reader.IsDBNull(_ordinal_MeterID))
            {
                dto.MeterID = Convert.ToInt32(reader[_ordinal_MeterID]);
            }
            if (!reader.IsDBNull(_ordinal_ClusterID))
            {
                dto.PAMClusterID = Convert.ToInt32(reader[_ordinal_ClusterID]);
            }
            if (!reader.IsDBNull(_ordinal_HasSensor))
            {
                dto.HasSensor = Convert.ToBoolean(reader[_ordinal_HasSensor]);
            }
            if (!reader.IsDBNull(_ordinal_SpaceType))
            {
                dto.SpaceType = Convert.ToInt32(reader[_ordinal_SpaceType]);
            }
            if (!reader.IsDBNull(_ordinal_Latitude))
            {
                dto.Latitude = Convert.ToSingle(reader[_ordinal_Latitude]);
            }
            if (!reader.IsDBNull(_ordinal_Longitude))
            {
                dto.Longitude = Convert.ToSingle(reader[_ordinal_Longitude]);
            }
            if (!reader.IsDBNull(_ordinal_CollRouteID))
            {
                dto.CollectionRouteID = Convert.ToInt32(reader[_ordinal_CollRouteID]);
            }
            if (!reader.IsDBNull(_ordinal_EnfRouteID))
            {
                dto.EnforcementRouteID = Convert.ToInt32(reader[_ordinal_EnfRouteID]);
            }
            if (!reader.IsDBNull(_ordinal_MaintRouteID))
            {
                dto.MaintRouteID = Convert.ToInt32(reader[_ordinal_MaintRouteID]);
            }
            if (!reader.IsDBNull(_ordinal_CustomGroup1))
            {
                dto.CustomGroup1ID = Convert.ToInt32(reader[_ordinal_CustomGroup1]);
            }
            if (!reader.IsDBNull(_ordinal_CustomGroup2))
            {
                dto.CustomGroup2ID = Convert.ToInt32(reader[_ordinal_CustomGroup2]);
            }
            if (!reader.IsDBNull(_ordinal_CustomGroup3))
            {
                dto.CustomGroup3ID = Convert.ToInt32(reader[_ordinal_CustomGroup3]);
            }

            // We won't use an IsActive column from the database anymore.  Now we are using a local XML file in the webservice to keep track of inactive spaces

            /*
             * if (!reader.IsDBNull(_ordinal_IsActive)) { dto.IsActive = Convert.ToBoolean(reader[_ordinal_IsActive]); }
             *
             * // We might as well log the fact that we loaded a space that is marked as "inactive".  This might be useful info to have available when
             * // researching an issue in the future...
             * if (dto.IsActive == false)
             * {
             *  Duncan.PEMS.SpaceStatus.UtilityClasses.Logging.AddTextToGenericLog(UtilityClasses.Logging.LogLevel.Debug,
             *  string.Format("Space is flagged as inactive: ParkingSpaceID={0}, MID={1}, BAY={2} (Based on HousingMaster.IsActive)", dto.ParkingSpaceId_Internal, dto.MeterID, dto.SpaceID),
             *  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name,
             *  System.Threading.Thread.CurrentThread.ManagedThreadId);
             * }
             */

            return(dto);
        }
Ejemplo n.º 5
0
        protected void AnalyzeSpaceStatusModelForOverstayViolation(SpaceStatusModel model)
        {
            // There is nothing to do if this event is not for occupied status
            if ((model.BayOccupancyState == OccupancyState.Empty) || (model.BayOccupancyState == OccupancyState.NotAvailable) ||
                (model.BayOccupancyState == OccupancyState.OutOfDate) || (model.BayOccupancyState == OccupancyState.Unknown))
            {
                return;
            }

            // Find the space asset associated with this data model.  If the space is "inactive" (based on the "IsActive" column of "HousingMaster" table in database),
            // then we will not consider the space to be in a violating state, because the sensor is effectively marked as bad/untrusted
            SpaceAsset spcAsset = GetSpaceAsset(model.MeterID, model.BayID);

            if (spcAsset != null)
            {
                // Nothing more to do if the space isn't active
                if (spcAsset.IsActive == false)
                {
                    return;
                }
            }

            // Resolve the associated area for the meter
            int areaID = ResolveAreaIDForMeterID(model.MeterID);

            // Try to obtain the regulated hours applicable to this meter
            RegulatedHoursGroup regulatedHours = RegulatedHoursGroupRepository.Repository.GetBestGroupForMeter(this._CustomerConfig.CustomerId, areaID, model.MeterID);

            // If no regulated hour defintions came back, then we are unable to calculate any overstay violation, so just exit
            if ((regulatedHours == null) || (regulatedHours.Details == null) || (regulatedHours.Details.Count == 0))
            {
                return;
            }

            DateTime NowAtDestination = Convert.ToDateTime(this._CustomerConfig.DestinationTimeZoneDisplayName);
            DateTime ruleStart        = DateTime.MinValue;
            DateTime ruleEnd          = DateTime.MinValue;

            TimeSlot OccupiedSegment = new TimeSlot(model.BayVehicleSensingTimestamp, NowAtDestination);

            // We need to check if this single occupancy event is an overstay violation for multiple rules, or even for more than one day, etc.
            while (OccupiedSegment.Start < NowAtDestination)
            {
                // Determine the day of week that is involved
                int dayOfWeek = (int)OccupiedSegment.Start.DayOfWeek;

                // Loop through the daily rules and see which ones overlap with our occupied period
                foreach (RegulatedHoursDetail detail in regulatedHours.Details)
                {
                    // Skip this one if its for a different day of the week
                    if (detail.DayOfWeek != dayOfWeek)
                    {
                        continue;
                    }

                    // Determine if the occupied timeslot overlaps with the rule's timeslot
                    ruleStart = new DateTime(OccupiedSegment.Start.Year, OccupiedSegment.Start.Month, OccupiedSegment.Start.Day, detail.StartTime.Hour, detail.StartTime.Minute, 0);
                    ruleEnd   = new DateTime(OccupiedSegment.Start.Year, OccupiedSegment.Start.Month, OccupiedSegment.Start.Day, detail.EndTime.Hour, detail.EndTime.Minute, 59);
                    TimeSlot RuleSegment = new TimeSlot(ruleStart, ruleEnd);

                    // We only care about this overlapping rule if the MaxStayMinutes is greater than zero (zero or less means there is no MaxStay that is enforced),
                    // or if it's explicitly set as a "No Parking" regulation
                    if ((RuleSegment.OverlapsWith(OccupiedSegment) == true) &&
                        ((detail.MaxStayMinutes > 0) || (string.Compare(detail.Type, "No Parking", true) == 0))
                        )
                    {
                        // Normally we will use the verbatim value of the max stay minutes, but if its a "No Parking", we will always take that to mean 0 minutes is the actual max
                        int timeLimitMinutes = detail.MaxStayMinutes;
                        if (string.Compare(detail.Type, "No Parking", true) == 0)
                        {
                            timeLimitMinutes = 0;
                        }

                        // Get the intersection of the overlaps so we know how long the vehicle has been occupied during this rule
                        TimeSlot OccupiedIntersection = RuleSegment.GetIntersection(OccupiedSegment);

                        // Determine if the vehicle has been occupied during this rule segment in excess of the MaxStayMinutes
                        if (OccupiedIntersection != null)
                        {
                            if (OccupiedIntersection.Duration.TotalMinutes >= timeLimitMinutes)
                            {
                                // We will check to see if this violated regulated period matches the current regulated period.
                                // But since it could be occupied for a long time, we must also check the current date, in addition to day of week and time of day!
                                bool     currDetailMatchesCurrentRegulatedPeriod = false;
                                DateTime TodayAtDestination = Convert.ToDateTime(this._CustomerConfig.DestinationTimeZoneDisplayName); //UtilityClasses.TimeZoneInfo.ConvertTimeZoneToTimeZone(DateTime.Now, this._CustomerConfig.ServerTimeZone, this._CustomerConfig.CustomerTimeZone).Date;
                                if (OccupiedSegment.Start >= TodayAtDestination)
                                {
                                    if (model.ActiveRegulationPeriod != null)
                                    {
                                        RegulatedHoursDetailLogicalComparer comparer = new RegulatedHoursDetailLogicalComparer();
                                        currDetailMatchesCurrentRegulatedPeriod = (comparer.Compare(model.ActiveRegulationPeriod, detail) == 0);
                                    }
                                }

                                // Create a new Overstay Vio Info object and add to the overall list of violations
                                OverstayViolationInfo overstay = new OverstayViolationInfo();
                                overstay.IsForCurrentRegulationPeriod = currDetailMatchesCurrentRegulatedPeriod;
                                overstay.Regulation_Date                   = new DateTime(OccupiedSegment.Start.Year, OccupiedSegment.Start.Month, OccupiedSegment.Start.Day);
                                overstay.Regulation_DayOfWeek              = detail.DayOfWeek;
                                overstay.Regulation_EndTime                = detail.EndTime;
                                overstay.Regulation_MaxStayMinutes         = detail.MaxStayMinutes; // Instead of using our calculated time limit, we will record the configured max stay minutes here, because it will be displayed
                                overstay.Regulation_StartTime              = detail.StartTime;
                                overstay.Regulation_Type                   = detail.Type;
                                overstay.DateTime_StartOfOverstayViolation = new DateTime(OccupiedIntersection.Start.Ticks).AddMinutes(timeLimitMinutes);
                                overstay.DurationOfTimeBeyondStayLimits    = new TimeSpan(OccupiedIntersection.Duration.Ticks).Add(new TimeSpan(0, (-1) * timeLimitMinutes, 0));

                                // Add this overstay info to the model's list
                                model.AllOverstayViolations.Add(overstay);

                                // If its also for the current regulation period, retain a reference to it
                                if (overstay.IsForCurrentRegulationPeriod == true)
                                {
                                    model.CurrentOverstayViolation = overstay;
                                }

                                // Mark as "Overstay Violation" status if we have a current overstay violation.  Otherwise mark
                                // as "Discretionary" because there is an overstay violation, but not for the current enforcement period
                                if (model.CurrentOverstayViolation != null)
                                {
                                    model.BayEnforcementState = EnforcementState.OverstayViolation;
                                }
                                else
                                {
                                    model.BayEnforcementState = EnforcementState.Discretionary;
                                }
                            }
                        }
                    }
                }

                // Rules for current day of week have been processed.  So now we will advance to beginning of next day and see if there are more violations that we will use
                // to add accumulated time in violation state...
                OccupiedSegment = new TimeSlot(new DateTime(OccupiedSegment.Start.Year, OccupiedSegment.Start.Month, OccupiedSegment.Start.Day).AddDays(1),
                                               NowAtDestination);
            }
        }