Example #1
0
        public async Task <IActionResult> Edit(int id, [Bind("Id,RaceId,VehicleId,HasTowStrap,AcceptableTireWear,AcceptableLift")] RaceVehicle raceVehicle)
        {
            if (id != raceVehicle.Id)
            {
                return(NotFound());
            }

            if (ModelState.IsValid)
            {
                try
                {
                    await _service.UpdateAsync(raceVehicle);
                }
                catch (Exception ex)
                {
                    if (!RaceVehicleExists(raceVehicle.Id))
                    {
                        return(NotFound());
                    }
                    else
                    {
                        ModelState.AddModelError("", ex.Message);
                        ViewData["RaceId"]    = new SelectList(_context.Races, "Id", "Name", raceVehicle.RaceId);
                        ViewData["VehicleId"] = new SelectList(_context.Vehicles, "Id", "VehicleAlias", raceVehicle.VehicleId);
                        return(View(raceVehicle));
                    }
                }
                return(RedirectToAction(nameof(Index)));
            }
            ViewData["RaceId"]    = new SelectList(_context.Races, "Id", "Name", raceVehicle.RaceId);
            ViewData["VehicleId"] = new SelectList(_context.Vehicles, "Id", "VehicleAlias", raceVehicle.VehicleId);
            return(View(raceVehicle));
        }
Example #2
0
        public async Task RaceVehicle_Add_Success()
        {
            var raceVehicle = new RaceVehicle {
                RaceId = 2, VehicleId = 2, AcceptableLift = true, AcceptableTireWear = false, HasTowStrap = true
            };
            await _service.AddAsync(raceVehicle);

            Assert.IsTrue((await _service.GetAllAsync()).Where(x => x.RaceId == raceVehicle.RaceId && x.VehicleId == raceVehicle.VehicleId).FirstOrDefault() != null);
        }
        /// <summary>
        /// Processes custom business rules for adding a vehicle to a race
        /// </summary>
        /// <exception cref="Exception ex">Custom exception message that is used for validation feedback</exception>
        /// <param name="raceVehicle">The model of the record being handled</param>
        /// <param name="action">The action being made on the record to decide what to validate</param>
        internal async Task ValidateVehicle(RaceVehicle raceVehicle, string action = "add")
        {
            if (action == "add")
            {
                // Check if car is not already in race
                var duplicateRecord = await _context.RaceVehicles.Where(r => r.VehicleId == raceVehicle.VehicleId && r.RaceId == raceVehicle.RaceId).FirstOrDefaultAsync();

                if (duplicateRecord != null)
                {
                    throw new Exception("This vehicle is already present on this race");
                }
            }

            // Get all vehicles currently in the race
            var vehiclesInRace = await _context.RaceVehicles.Where(r => r.RaceId == raceVehicle.RaceId).ToListAsync();

            // Check for the count of vehicles, if we already have 5 for that race do not add the new one

            if (vehiclesInRace.Count == 5)
            {
                throw new Exception("Can't add more than 5 vehicles to a race");
            }

            // Check inspection of vehicle with following criteria:
            // Truck Inspections:
            // Tow strap on the vehicle
            // Not lifted more than 5 inches

            // Car Inspections:
            // Tow strap on the vehicle
            // Less than 85 % tire wear

            var vehicleInfo = await _context.Vehicles.Include(v => v.VehicleType).Where(x => x.Id == raceVehicle.VehicleId).FirstOrDefaultAsync();

            var vehicleType = vehicleInfo.VehicleType.Description;

            if (vehicleType == "Truck")
            {
                if (!raceVehicle.HasTowStrap || !raceVehicle.AcceptableLift)
                {
                    throw new Exception("A truck needs to have a tow strap and cannot be lifted more than 5 inches to participate in the race");
                }
            }
            else
            {
                if (!raceVehicle.HasTowStrap || !raceVehicle.AcceptableTireWear)
                {
                    throw new Exception("A car needs to have a tow strap and cannot have less than 85% of tire wear to participate in the race");
                }
            }
        }
Example #4
0
        public void RaceVehicle_Add_Fail_CarNoPassInspection(bool acceptableLift, bool acceptableTireWear, bool hasTowStrap)
        {
            var raceVehicle = new RaceVehicle
            {
                RaceId             = 2,
                VehicleId          = 3,
                AcceptableLift     = acceptableLift,
                AcceptableTireWear = acceptableTireWear,
                HasTowStrap        = hasTowStrap
            };
            var ex = Assert.ThrowsAsync <Exception>(async() => await _service.AddAsync(raceVehicle));

            Assert.That(ex.Message, Is.EqualTo("A car needs to have a tow strap and cannot have less than 85% of tire wear to participate in the race"));
        }
Example #5
0
        public void RaceVehicle_Add_Fail_MoreThanFiveVehicles()
        {
            var raceVehicle = new RaceVehicle
            {
                RaceId             = 1,
                VehicleId          = 6,
                AcceptableLift     = true,
                AcceptableTireWear = false,
                HasTowStrap        = true
            };
            var ex = Assert.ThrowsAsync <Exception>(async() => await _service.AddAsync(raceVehicle));

            Assert.That(ex.Message, Is.EqualTo("Can't add more than 5 vehicles to a race"));
        }
        /// <summary>
        /// Updates a record from the database
        /// </summary>
        /// <param name="raceVehicle">A Race Vehicle model to be modified</param>
        public async Task UpdateAsync(RaceVehicle raceVehicle)
        {
            try
            {
                await ValidateVehicle(raceVehicle, "update");

                var e = _context.Update(raceVehicle);
                e.State = EntityState.Modified;
                await _context.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                throw;
                // In here we would log the exception and return an error message to the user
            }
        }
        /// <summary>
        /// Adds the record to the database
        /// </summary>
        /// <param name="raceVehicle">A Race Vehicle model</param>
        public async Task AddAsync(RaceVehicle raceVehicle)
        {
            try
            {
                await ValidateVehicle(raceVehicle);

                await _context.AddAsync(raceVehicle);

                await _context.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                throw;
                // In here we would log the exception and return an error message to the user
            }
        }
        private decimal GetVehiclesRaceTimeInSeconds(RaceVehicle raceVehicle, DateTime leaderboardDate, DateTime raceStartAt)
        {
            var malfunction = raceVehicle.Malfunctions.FirstOrDefault(x => x.StartAt <= leaderboardDate &&
                                                                      (x.EndAt == null || x.EndAt >= leaderboardDate));

            double totalSecondsForRepairment = raceVehicle.Malfunctions.Where(x => x.StartAt <= leaderboardDate &&
                                                                              x.EndAt.HasValue &&
                                                                              x.EndAt <= leaderboardDate)
                                               .Sum(x => (x.EndAt.Value - x.StartAt).TotalSeconds);

            raceVehicle.MalfunctionStatus = MalfunctionStatus.None;
            if (malfunction != null)
            {
                totalSecondsForRepairment    += (leaderboardDate - malfunction.StartAt).TotalSeconds;
                raceVehicle.MalfunctionStatus = (MalfunctionStatus)malfunction.Status;
            }
            return((decimal)(leaderboardDate - raceStartAt).TotalSeconds - (decimal)totalSecondsForRepairment);
        }
Example #9
0
        public async Task <IActionResult> Create([Bind("RaceId,VehicleId,HasTowStrap,AcceptableTireWear,AcceptableLift")] RaceVehicle raceVehicle)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    await _service.AddAsync(raceVehicle);

                    return(RedirectToAction(nameof(Index)));
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError("", ex.Message);
                    ViewData["RaceId"]    = new SelectList(_context.Races, "Id", "Name", raceVehicle.RaceId);
                    ViewData["VehicleId"] = new SelectList(_context.Vehicles, "Id", "VehicleAlias", raceVehicle.VehicleId);
                    return(View(raceVehicle));
                }
            }
            ViewData["RaceId"]    = new SelectList(_context.Races, "Id", "Name", raceVehicle.RaceId);
            ViewData["VehicleId"] = new SelectList(_context.Vehicles, "Id", "VehicleAlias", raceVehicle.VehicleId);
            return(View(raceVehicle));
        }
Example #10
0
        /// <summary>
        /// Creates an light malfunction for vehicle
        /// </summary>
        /// <param name="rand">Random object reference</param>
        /// <param name="startAt">Date from which malfunction can happen</param>
        /// <param name="vehicle">Vehicle for which malfunction is created</param>
        /// <param name="to">Number of seconds in which this malfunction can happen</param>
        /// <returns>New light malfunction</returns>
        private static MalfunctionStats CreateLightMalfunction(Random rand, DateTime startAt, RaceVehicle vehicle, int to)
        {
            MalfunctionStats malfunction = new MalfunctionStats();
            int lightMalfunctionAt       = rand.Next(to);

            malfunction.Status  = (short)MalfunctionStatus.Light;
            malfunction.StartAt = startAt.AddSeconds(lightMalfunctionAt);
            malfunction.EndAt   = malfunction.StartAt.AddHours(vehicle.VehicleTypeParameters.LightMalfunctionTime);
            return(malfunction);
        }
Example #11
0
        /// <summary>
        /// Creates a list of all malfunctions that will happen in the race. Recursive function that exits if heavy malfunction happens or vehicle ends the race.
        /// </summary>
        /// <param name="malfunctions"></param>
        /// <param name="rand"></param>
        /// <param name="raceStartAt"></param>
        /// <param name="raceEndsAt"></param>
        /// <param name="startAt"></param>
        /// <param name="endAt"></param>
        /// <param name="vehicle"></param>
        /// <returns></returns>
        private List <MalfunctionStats> CreateVehicleMalfunctions(List <MalfunctionStats> malfunctions, Random rand, DateTime raceStartAt, ref DateTime raceEndsAt, DateTime startAt, DateTime endAt, RaceVehicle vehicle)
        {
            if (startAt >= raceEndsAt)
            {
                return(malfunctions);
            }

            int hourInSeconds = 3600;

            if (endAt > raceEndsAt)
            {
                endAt         = raceEndsAt;
                hourInSeconds = (int)(endAt - startAt).TotalSeconds;
            }

            var nextPeriodStart = endAt;

            if (rand.Next(100) < vehicle.VehicleTypeParameters.HeavyMalfunctionPercentage * 100)
            {
                var malfunction = CreateHeavyMalfunction(rand, startAt, hourInSeconds);
                malfunctions.Add(malfunction);
                raceEndsAt = malfunction.StartAt;
                return(malfunctions);
            }
            else if (rand.Next(100) < vehicle.VehicleTypeParameters.LightMalfunctionPercentage * 100)
            {
                var malfunction = CreateLightMalfunction(rand, startAt, vehicle, hourInSeconds);
                malfunctions.Add(malfunction);
                nextPeriodStart = malfunction.EndAt.Value;
                raceEndsAt      = raceEndsAt.AddSeconds(vehicle.VehicleTypeParameters.LightMalfunctionTime * 3600);
            }
            return(CreateVehicleMalfunctions(malfunctions, rand, raceStartAt, ref raceEndsAt, nextPeriodStart, nextPeriodStart.AddHours(1), vehicle));
        }
Example #12
0
        private void CalculateVehicleFinishStatistics(DateTime startDate, Random rand, int raceDistance, RaceVehicle vehicle)
        {
            decimal finishTimeSeconds = ((decimal)raceDistance / (decimal)vehicle.VehicleTypeParameters.TopSpeed) * 3600m;
            var     raceEndsAt        = startDate.AddSeconds((double)finishTimeSeconds);
            int     finishTime        = (int)finishTimeSeconds;

            vehicle.Malfunctions = CreateVehicleMalfunctions(new List <MalfunctionStats>(), rand, startDate, ref raceEndsAt, startDate, startDate.AddHours(1), vehicle);
            vehicle.EndsRaceAt   = raceEndsAt;
            decimal totalSecondsForRepairment = vehicle.Malfunctions.Where(x => x.EndAt.HasValue)
                                                .Sum(x => (decimal)(x.EndAt.Value - x.StartAt).TotalSeconds);

            if (vehicle.Malfunctions.Any(x => x.Status == (short)MalfunctionStatus.Heavy))
            {
                vehicle.FinishTime = null;
                decimal raceTimeInSeconds = (decimal)(raceEndsAt - startDate).TotalSeconds - totalSecondsForRepairment;
                decimal distance          = (((decimal)vehicle.VehicleTypeParameters.TopSpeed * 1000m) / 3600m) * raceTimeInSeconds;
                vehicle.DistanceInMeters = distance;
            }
            else
            {
                vehicle.FinishTime       = (decimal)(raceEndsAt - startDate).TotalSeconds;
                vehicle.DistanceInMeters = raceDistance * 1000;
            }
        }