189 lines
7.1 KiB
C#
189 lines
7.1 KiB
C#
using BankSampahApp.Models;
|
|
|
|
namespace BankSampahApp.Services;
|
|
|
|
/// <summary>
|
|
/// Service implementation untuk menangani statistik aplikasi
|
|
/// Menggunakan base service untuk common functionality
|
|
/// </summary>
|
|
public class StatisticsService : BaseService, IStatisticsService
|
|
{
|
|
private readonly ICacheService _cacheService;
|
|
private readonly IAppConfigurationService _appConfig;
|
|
private readonly IValidationService _validationService;
|
|
|
|
/// <summary>
|
|
/// Cache key untuk statistik
|
|
/// </summary>
|
|
private const string StatisticsCacheKey = "current_statistics";
|
|
|
|
/// <summary>
|
|
/// Constructor dengan dependency injection
|
|
/// </summary>
|
|
/// <param name="logger">Logger untuk logging</param>
|
|
/// <param name="cache">Memory cache untuk caching</param>
|
|
/// <param name="configuration">Configuration untuk settings</param>
|
|
/// <param name="cacheService">Cache service</param>
|
|
/// <param name="appConfig">Application configuration service</param>
|
|
/// <param name="validationService">Validation service</param>
|
|
public StatisticsService(
|
|
ILogger<StatisticsService> logger,
|
|
Microsoft.Extensions.Caching.Memory.IMemoryCache cache,
|
|
IConfiguration configuration,
|
|
ICacheService cacheService,
|
|
IAppConfigurationService appConfig,
|
|
IValidationService validationService) : base(logger, cache, configuration)
|
|
{
|
|
_cacheService = cacheService ?? throw new ArgumentNullException(nameof(cacheService));
|
|
_appConfig = appConfig ?? throw new ArgumentNullException(nameof(appConfig));
|
|
_validationService = validationService ?? throw new ArgumentNullException(nameof(validationService));
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async Task<StatisticsModel> GetCurrentStatisticsAsync()
|
|
{
|
|
return await ExecuteWithErrorHandlingAsync(
|
|
async () => await _cacheService.GetOrSetWithSlidingAsync(
|
|
StatisticsCacheKey,
|
|
LoadStatisticsFromSourceAsync,
|
|
_appConfig.CacheSettings.StatisticsSlidingExpiration,
|
|
_appConfig.CacheSettings.StatisticsExpiration,
|
|
Microsoft.Extensions.Caching.Memory.CacheItemPriority.High),
|
|
"Fetching current statistics",
|
|
GetDefaultStatistics());
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async Task<StatisticsModel> GetStatisticsByPeriodAsync(DateTime startDate, DateTime endDate)
|
|
{
|
|
return await ExecuteWithErrorHandlingAsync(
|
|
async () =>
|
|
{
|
|
var validation = _validationService.ValidateDateRange(startDate, endDate);
|
|
if (!validation.IsValid)
|
|
{
|
|
throw new ArgumentException(string.Join("; ", validation.Errors));
|
|
}
|
|
|
|
return await LoadStatisticsByPeriodFromSourceAsync(startDate, endDate);
|
|
},
|
|
$"Fetching statistics for period {startDate:yyyy-MM-dd} to {endDate:yyyy-MM-dd}");
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async Task<bool> UpdateStatisticsAsync(StatisticsModel statistics)
|
|
{
|
|
return await ExecuteWithErrorHandlingAsync(
|
|
async () =>
|
|
{
|
|
ArgumentNullException.ThrowIfNull(statistics);
|
|
|
|
var validation = _validationService.ValidateStatistics(statistics);
|
|
if (!validation.IsValid)
|
|
{
|
|
_logger.LogWarning("Invalid statistics data: {Errors}", string.Join("; ", validation.Errors));
|
|
return false;
|
|
}
|
|
|
|
// Simulate async update operation
|
|
if (_appConfig.DevelopmentSettings.SimulatedDelayMs > 0)
|
|
{
|
|
await Task.Delay(_appConfig.DevelopmentSettings.SimulatedDelayMs);
|
|
}
|
|
else
|
|
{
|
|
await Task.Delay(10);
|
|
}
|
|
|
|
// Clear cache after update
|
|
_cacheService.Remove(StatisticsCacheKey);
|
|
|
|
return true;
|
|
},
|
|
"Updating statistics",
|
|
false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load statistics from data source (placeholder for actual implementation)
|
|
/// </summary>
|
|
/// <returns>Current statistics</returns>
|
|
private async Task<StatisticsModel> LoadStatisticsFromSourceAsync()
|
|
{
|
|
// In a real application, this would load from database, API, etc.
|
|
await Task.CompletedTask;
|
|
|
|
// Get base values from configuration
|
|
var baseUsers = _appConfig.StatisticsSettings.BaseUsers;
|
|
var baseWaste = _appConfig.StatisticsSettings.BaseWaste;
|
|
|
|
// Simulate some growth over time
|
|
var daysSinceStart = (DateTime.UtcNow - new DateTime(2024, 1, 1)).Days;
|
|
var growthFactor = Math.Min(_appConfig.StatisticsSettings.MaxGrowthFactor,
|
|
1.0 + (daysSinceStart * _appConfig.StatisticsSettings.GrowthFactorMultiplier));
|
|
|
|
return new StatisticsModel
|
|
{
|
|
TotalUsers = (int)(baseUsers * growthFactor),
|
|
WasteCollected = baseWaste * (decimal)growthFactor,
|
|
RewardsDistributed = (int)(_appConfig.StatisticsSettings.BaseRewards * growthFactor),
|
|
EnvironmentImpact = Math.Min(99.9m, _appConfig.StatisticsSettings.BaseEnvironmentImpact + (decimal)(growthFactor * 2))
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load statistics for specific period (placeholder)
|
|
/// </summary>
|
|
/// <param name="startDate">Start date</param>
|
|
/// <param name="endDate">End date</param>
|
|
/// <returns>Period statistics</returns>
|
|
private async Task<StatisticsModel> LoadStatisticsByPeriodFromSourceAsync(DateTime startDate, DateTime endDate)
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
// Calculate period-specific statistics
|
|
var days = (endDate - startDate).Days + 1;
|
|
var dailyAverage = await GetDailyAverageAsync();
|
|
|
|
return new StatisticsModel
|
|
{
|
|
TotalUsers = dailyAverage.TotalUsers * days / 365,
|
|
WasteCollected = dailyAverage.WasteCollected * days,
|
|
RewardsDistributed = dailyAverage.RewardsDistributed * days,
|
|
EnvironmentImpact = dailyAverage.EnvironmentImpact
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get daily average statistics
|
|
/// </summary>
|
|
/// <returns>Daily average statistics</returns>
|
|
private async Task<StatisticsModel> GetDailyAverageAsync()
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
return new StatisticsModel
|
|
{
|
|
TotalUsers = 3, // New users per day
|
|
WasteCollected = 0.1m, // Tons per day
|
|
RewardsDistributed = 5, // Rewards per day
|
|
EnvironmentImpact = 98.5m // Overall impact
|
|
};
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get default statistics when error occurs
|
|
/// </summary>
|
|
/// <returns>Default statistics</returns>
|
|
private StatisticsModel GetDefaultStatistics()
|
|
{
|
|
return new StatisticsModel
|
|
{
|
|
TotalUsers = _appConfig.StatisticsSettings.BaseUsers,
|
|
WasteCollected = _appConfig.StatisticsSettings.BaseWaste,
|
|
RewardsDistributed = _appConfig.StatisticsSettings.BaseRewards,
|
|
EnvironmentImpact = _appConfig.StatisticsSettings.BaseEnvironmentImpact
|
|
};
|
|
}
|
|
} |