/// <inheritdoc />
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("Rally simulation background service is starting.");

            await Task.Delay(5000, stoppingToken);

            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Rally simulation background service is doing background work.");

                using IServiceScope scope = _serviceProvider.CreateScope();

                RallySimulatorDbContext dbContext = scope.ServiceProvider.GetRequiredService <RallySimulatorDbContext>();

                Maybe <Race> maybeRace = await dbContext.Set <Race>()
                                         .SingleOrDefaultAsync(x => x.Status == RaceStatus.Running, stoppingToken);

                if (maybeRace.HasValue)
                {
                    await SimulateOneHourPassing(maybeRace.Value, dbContext);
                }

                await Task.Delay(_backgroundTaskSettings.SleepTimeInMilliseconds, stoppingToken);
            }

            _logger.LogInformation("Rally simulation background service is stopping.");

            await Task.CompletedTask;
        }
        /// <summary>
        /// Simulates the passing of one hour for the specified running race.
        /// </summary>
        /// <param name="race">The race that is currently running.</param>
        /// <param name="dbContext">The database context.</param>
        private async Task SimulateOneHourPassing(Race race, RallySimulatorDbContext dbContext)
        {
            List <Vehicle> vehicles = await dbContext.Set <Vehicle>()
                                      .Include(x => x.RepairmentLength)
                                      .Include(x => x.Speed)
                                      .Include(x => x.MalfunctionProbability)
                                      .Include(x => x.Malfunctions)
                                      .Where(x => x.RaceId == race.Id)
                                      .ToListAsync();

            VehicleStatus[] brokenOrCompletedRace = { VehicleStatus.Broken, VehicleStatus.CompletedRace };

            foreach (Vehicle vehicle in vehicles.Where(x => !brokenOrCompletedRace.Contains(x.Status)))
            {
                vehicle.SimulateOneHourPassing();

                if (vehicle.Status == VehicleStatus.WaitingForRepair && !vehicle.TryRepair())
                {
                    continue;
                }

                decimal malfunctionProbability = (decimal)_random.NextDouble();

                if (vehicle.MalfunctionProbability.LightMalfunctionProbability >= malfunctionProbability)
                {
                    vehicle.AddLightMalfunction();

                    continue;
                }

                if (vehicle.MalfunctionProbability.HeavyMalfunctionProbability >= malfunctionProbability)
                {
                    vehicle.AddHeavyMalfunction();

                    continue;
                }

                vehicle.IncrementDistance(vehicle.Speed.SpeedInKilometersPerHour * 1.0m, race.LengthInKilometers);

                if (vehicle.Distance == race.LengthInKilometers)
                {
                    vehicle.CompleteRace();
                }
            }

            race.SimulateOneHourPassing();

            if (vehicles.All(x => brokenOrCompletedRace.Contains(x.Status)))
            {
                race.CompleteRace();
            }

            await dbContext.SaveChangesAsync();
        }
Esempio n. 3
0
        /// <summary>
        /// Ensures that the in-memory database is created.
        /// </summary>
        /// <param name="builder">The application builder.</param>
        /// <returns>The same application builder.</returns>
        internal static IApplicationBuilder EnsureDatabaseCreated(this IApplicationBuilder builder)
        {
            using IServiceScope serviceScope = builder.ApplicationServices.CreateScope();

            using RallySimulatorDbContext dbContext = serviceScope.ServiceProvider.GetRequiredService <RallySimulatorDbContext>();

            dbContext.Database.EnsureCreated();

            dbContext.SeedDatabase();

            return(builder);
        }
Esempio n. 4
0
        /// <summary>
        /// Seeds the database with initial data.
        /// </summary>
        /// <param name="dbContext">The database context.</param>
        public static void SeedDatabase(this RallySimulatorDbContext dbContext)
        {
            dbContext.Set <VehicleTypeRepairmentLength>().AddRange(new List <VehicleTypeRepairmentLength>
            {
                new VehicleTypeRepairmentLength(VehicleType.Truck, 7),
                new VehicleTypeRepairmentLength(VehicleType.Car, 5),
                new VehicleTypeRepairmentLength(VehicleType.Motorcycle, 3)
            });

            dbContext.Set <VehicleSubtypeSpeed>().AddRange(new List <VehicleSubtypeSpeed>
            {
                new VehicleSubtypeSpeed(VehicleSubtype.Truck, SpeedInKilometersPerHour.Create(80).Value),
                new VehicleSubtypeSpeed(VehicleSubtype.TerrainCar, SpeedInKilometersPerHour.Create(100).Value),
                new VehicleSubtypeSpeed(VehicleSubtype.SportsCar, SpeedInKilometersPerHour.Create(140).Value),
                new VehicleSubtypeSpeed(VehicleSubtype.CrossMotorcycle, SpeedInKilometersPerHour.Create(85).Value),
                new VehicleSubtypeSpeed(VehicleSubtype.SportMotorcycle, SpeedInKilometersPerHour.Create(130).Value),
            });

            dbContext.Set <VehicleSubtypeMalfunctionProbability>().AddRange(new List <VehicleSubtypeMalfunctionProbability>
            {
                new VehicleSubtypeMalfunctionProbability(
                    VehicleSubtype.Truck,
                    MalfunctionProbability.Create(0.06m).Value,
                    MalfunctionProbability.Create(0.04m).Value),
                new VehicleSubtypeMalfunctionProbability(
                    VehicleSubtype.TerrainCar,
                    MalfunctionProbability.Create(0.03m).Value,
                    MalfunctionProbability.Create(0.01m).Value),
                new VehicleSubtypeMalfunctionProbability(
                    VehicleSubtype.SportsCar,
                    MalfunctionProbability.Create(0.12m).Value,
                    MalfunctionProbability.Create(0.02m).Value),
                new VehicleSubtypeMalfunctionProbability(
                    VehicleSubtype.CrossMotorcycle,
                    MalfunctionProbability.Create(0.03m).Value,
                    MalfunctionProbability.Create(0.02m).Value),
                new VehicleSubtypeMalfunctionProbability(
                    VehicleSubtype.SportMotorcycle,
                    MalfunctionProbability.Create(0.18m).Value,
                    MalfunctionProbability.Create(0.10m).Value)
            });

            dbContext.SaveChanges();
        }