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