using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.EntityFrameworkCore; using System; using System.Globalization; using System.Threading; using System.Threading.Tasks; using Parking_space_WebAPI.Services; using WebApi_data_value.Models; using Microsoft.Extensions.Logging; // 確保引用 using System.Linq; #region 從進入車輛獲取最新的月租名單 public class ParkingService : BackgroundService { private readonly IServiceScopeFactory _scopeFactory; private readonly ILogger _logger; public ParkingService(IServiceScopeFactory scopeFactory, ILogger logger) { _scopeFactory = scopeFactory; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await PerformParkingCheckAsync(stoppingToken); while (!stoppingToken.IsCancellationRequested) { await Task.Delay(TimeSpan.FromSeconds(60), stoppingToken); // 每60秒執行 await PerformParkingCheckAsync(stoppingToken); } } private async Task PerformParkingCheckAsync(CancellationToken stoppingToken) { using (var scope = _scopeFactory.CreateScope()) { var _context = scope.ServiceProvider.GetRequiredService(); var now = DateTime.Now; var startTime = now.AddDays(-2); // 獲取最近兩天內進入的車輛 var inCars = await _context.yuntech_in_car_table .Where(car => car.in_time >= startTime) .ToListAsync(stoppingToken); // 獲取月租名單 var monthlyUsers = await _context.yuntech_parking_user_list.ToListAsync(stoppingToken); int monthlycar = 0; int temporarycar = 0; foreach (var car in inCars) { bool isMonthlyUser = monthlyUsers.Any(user => user.user_license_plate_number == car.license_plate_number); if (isMonthlyUser) { int monthlyNum = 0; if (car.in_time.HasValue && !car.out_time.HasValue) { if ((now - car.in_time.Value).TotalHours > 15) { monthlyNum = 0; } else { int countWithin15Hours = inCars.Count(c => c.license_plate_number == car.license_plate_number && c.in_time.HasValue && (now - c.in_time.Value).TotalHours <= 15); monthlyNum = countWithin15Hours % 2 == 1 ? 1 : 0; } } else if (car.out_time.HasValue) { monthlyNum = 0; } monthlycar += monthlyNum; } else // 臨停車輛 { int temporaryNum = 0; if (car.in_time.HasValue && !car.out_time.HasValue) { if ((now - car.in_time.Value).TotalHours > 15) { temporaryNum = 0; } else { int countWithin15Hours = inCars.Count(c => c.license_plate_number == car.license_plate_number && c.in_time.HasValue && (now - c.in_time.Value).TotalHours <= 15); temporaryNum = countWithin15Hours % 2 == 1 ? 1 : 0; } } else if (car.out_time.HasValue) { temporaryNum = 0; } temporarycar += temporaryNum; } } // 絕對值 monthlycar = Math.Abs(monthlycar); temporarycar = Math.Abs(temporarycar); _logger.LogInformation($"月租車位數量: {monthlycar}"); _logger.LogInformation($"臨停車位數量: {temporarycar}"); await UpdateMonthly(_context, monthlycar, temporarycar, stoppingToken); } } private async Task UpdateMonthly(SqlContext context, int monthlycar, int temporarycar, CancellationToken stoppingToken) { var monthlyRentData = await context.yuntech_monthly_rent_number .FirstOrDefaultAsync(rent => rent.category == "月租", stoppingToken); if (monthlyRentData != null) { monthlyRentData.number = monthlycar.ToString(); } var temporaryRentData = await context.yuntech_monthly_rent_number .FirstOrDefaultAsync(rent => rent.category == "臨停", stoppingToken); if (temporaryRentData != null) { temporaryRentData.number = temporarycar.ToString(); } await context.SaveChangesAsync(stoppingToken); } } #endregion #region 執行計算剩餘車位並不為負數存入資料庫ParkingLogs public class ParkingUpdateService : BackgroundService { private readonly IServiceScopeFactory _scopeFactory; public ParkingUpdateService(IServiceScopeFactory scopeFactory) { _scopeFactory = scopeFactory; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { using (var scope = _scopeFactory.CreateScope()) { var _context = scope.ServiceProvider.GetRequiredService(); try { var yuntech_parking = await _context.yuntech_parking.FirstOrDefaultAsync(); if (yuntech_parking != null) { if (Int32.TryParse(yuntech_parking.all_num, out int totalParkingSpaces)) { var monthly_rent_data = await _context.yuntech_monthly_rent_number .FirstOrDefaultAsync(rent => rent.category == "月租"); int monthlyRentNumber = 0; if (monthly_rent_data != null) { Int32.TryParse(monthly_rent_data.number, out monthlyRentNumber); } var temporary_rent_data = await _context.yuntech_monthly_rent_number .FirstOrDefaultAsync(rent => rent.category == "臨停"); int temporaryRentNumber = 0; if (temporary_rent_data != null) { Int32.TryParse(temporary_rent_data.number, out temporaryRentNumber); } int totalOccupiedSpaces = monthlyRentNumber + Math.Abs(temporaryRentNumber); //確保絕對值 int remainingSpaces = totalParkingSpaces - totalOccupiedSpaces; // 確保剩餘車位數不為負數 yuntech_parking.now_num = Math.Max(remainingSpaces, 0).ToString(); await _context.SaveChangesAsync(); var log = new ParkingLog { Timestamp = DateTime.Now, TotalParkingSpaces = totalParkingSpaces, RemainingSpaces = Math.Max(remainingSpaces, 0), // 確保儲存時不為負數 MonthlyRentSpaces = monthlyRentNumber, TemporaryRentSpaces = Math.Abs(temporaryRentNumber), DayOfWeek = DateTime.Now.ToString("dddd", new CultureInfo("zh-TW")) }; // 儲存資料庫ParkingLogs _context.ParkingLogs.Add(log); await _context.SaveChangesAsync(); } } } catch (Exception ex) { // 錯誤顯示 Console.WriteLine($"An error occurred: {ex.Message}"); } } // 每 30 秒執行一次 await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken); } } } #endregion