Yuyuqt commited on
Commit
1a7e978
·
1 Parent(s): f81f07d

add: loyalty reward system

Browse files
Backend/Features/Borrowing/BorrowingService.cs CHANGED
@@ -1,5 +1,6 @@
1
  using Database.Models;
2
  using Microsoft.EntityFrameworkCore;
 
3
 
4
  namespace Backend.Features.Borrowings
5
  {
@@ -14,11 +15,13 @@ namespace Backend.Features.Borrowings
14
  public class BorrowingService : IBorrowingService
15
  {
16
  private readonly LibraryManagementContext _context;
 
17
  private const decimal FinePerDay = 500;
18
 
19
- public BorrowingService(LibraryManagementContext context)
20
  {
21
  _context = context;
 
22
  }
23
 
24
  public async Task<BorrowingDto> BorrowBookAsync(int userId, int bookId)
@@ -86,6 +89,21 @@ namespace Backend.Features.Borrowings
86
  await _context.Entry(borrowing).Reference(b => b.Book).LoadAsync();
87
  await _context.Entry(borrowing).Reference(b => b.User).LoadAsync();
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  return MapToDto(borrowing);
90
  }
91
 
 
1
  using Database.Models;
2
  using Microsoft.EntityFrameworkCore;
3
+ using Backend.Features.Loyalty;
4
 
5
  namespace Backend.Features.Borrowings
6
  {
 
15
  public class BorrowingService : IBorrowingService
16
  {
17
  private readonly LibraryManagementContext _context;
18
+ private readonly ILoyaltyService _loyaltyService;
19
  private const decimal FinePerDay = 500;
20
 
21
+ public BorrowingService(LibraryManagementContext context, ILoyaltyService loyaltyService)
22
  {
23
  _context = context;
24
+ _loyaltyService = loyaltyService;
25
  }
26
 
27
  public async Task<BorrowingDto> BorrowBookAsync(int userId, int bookId)
 
89
  await _context.Entry(borrowing).Reference(b => b.Book).LoadAsync();
90
  await _context.Entry(borrowing).Reference(b => b.User).LoadAsync();
91
 
92
+ // Loyalty Integration: Send BORROW event
93
+ string externalUserId = userId.ToString();
94
+ string userMobile = borrowing.User?.PhoneNumber ?? "0000000000";
95
+ string userEmail = borrowing.User?.Email ?? "No Email";
96
+
97
+ await _loyaltyService.ProcessEventAsync(
98
+ externalUserId: externalUserId,
99
+ eventKey: "BORROW",
100
+ eventValue: 0,
101
+ referenceId: $"BRW-{borrowing.Id}",
102
+ description: $"Borrowed Book: {borrowing.Book?.Title}",
103
+ email: userEmail,
104
+ mobile: userMobile
105
+ );
106
+
107
  return MapToDto(borrowing);
108
  }
109
 
Backend/Features/Loyalty/LoyaltyController.cs ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ using Microsoft.AspNetCore.Authorization;
2
+ using Microsoft.AspNetCore.Mvc;
3
+ using System.Security.Claims;
4
+ using System.Threading.Tasks;
5
+
6
+ namespace Backend.Features.Loyalty
7
+ {
8
+ [ApiController]
9
+ [Route("api/[controller]")]
10
+ [Authorize]
11
+ public class LoyaltyController : ControllerBase
12
+ {
13
+ private readonly ILoyaltyService _loyaltyService;
14
+
15
+ public LoyaltyController(ILoyaltyService loyaltyService)
16
+ {
17
+ _loyaltyService = loyaltyService;
18
+ }
19
+
20
+ [HttpGet("my-account")]
21
+ public async Task<IActionResult> GetMyAccount()
22
+ {
23
+ var userIdStr = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
24
+ if (string.IsNullOrEmpty(userIdStr))
25
+ {
26
+ return Unauthorized();
27
+ }
28
+
29
+ var account = await _loyaltyService.GetUserAccountAsync(userIdStr);
30
+ if (account == null)
31
+ {
32
+ return NotFound("Loyalty account not found.");
33
+ }
34
+
35
+ return Ok(account);
36
+ }
37
+ }
38
+ }
Backend/Features/Loyalty/LoyaltyService.cs ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ using System;
2
+ using System.Net.Http;
3
+ using System.Net.Http.Json;
4
+ using System.Threading.Tasks;
5
+ using Microsoft.Extensions.Logging;
6
+
7
+ namespace Backend.Features.Loyalty
8
+ {
9
+ public interface ILoyaltyService
10
+ {
11
+ Task<bool> RegisterUserAsync(string externalUserId, string email, string mobile);
12
+ Task<bool> ProcessEventAsync(string externalUserId, string eventKey, double eventValue, string referenceId, string description, string email, string mobile);
13
+ Task<AccountLookupResponse?> GetUserAccountAsync(string externalUserId);
14
+ }
15
+
16
+ public class LoyaltyService : ILoyaltyService
17
+ {
18
+ private readonly HttpClient _httpClient;
19
+ private readonly ILogger<LoyaltyService> _logger;
20
+ private const string SystemId = "THS-LMS";
21
+
22
+ public LoyaltyService(HttpClient httpClient, ILogger<LoyaltyService> logger)
23
+ {
24
+ _httpClient = httpClient;
25
+ _logger = logger;
26
+ _httpClient.DefaultRequestHeaders.Add("x-system-id", SystemId);
27
+ }
28
+
29
+ public async Task<bool> RegisterUserAsync(string externalUserId, string email, string mobile)
30
+ {
31
+ try
32
+ {
33
+ var payload = new
34
+ {
35
+ systemId = SystemId,
36
+ externalUserId = externalUserId,
37
+ email = email,
38
+ mobile = mobile,
39
+ tier = "Member" // Default
40
+ };
41
+
42
+ var response = await _httpClient.PostAsJsonAsync("/api/v1/accounts", payload);
43
+ if (!response.IsSuccessStatusCode)
44
+ {
45
+ var error = await response.Content.ReadAsStringAsync();
46
+ _logger.LogWarning($"Failed to register user in loyalty system: {error}");
47
+ return false;
48
+ }
49
+ return true;
50
+ }
51
+ catch (Exception ex)
52
+ {
53
+ _logger.LogError(ex, "Error registering user in loyalty system.");
54
+ return false;
55
+ }
56
+ }
57
+
58
+ public async Task<bool> ProcessEventAsync(string externalUserId, string eventKey, double eventValue, string referenceId, string description, string email, string mobile)
59
+ {
60
+ try
61
+ {
62
+ var payload = new
63
+ {
64
+ externalUserId = externalUserId,
65
+ eventKey = eventKey,
66
+ eventValue = eventValue,
67
+ referenceId = referenceId,
68
+ description = description,
69
+ email = email,
70
+ mobile = mobile
71
+ };
72
+
73
+ var response = await _httpClient.PostAsJsonAsync("/api/v1/events/process", payload);
74
+ if (!response.IsSuccessStatusCode)
75
+ {
76
+ var error = await response.Content.ReadAsStringAsync();
77
+ _logger.LogWarning($"Failed to process loyalty event {eventKey} for user {externalUserId}: {error}");
78
+ return false;
79
+ }
80
+ return true;
81
+ }
82
+ catch (Exception ex)
83
+ {
84
+ _logger.LogError(ex, $"Error processing loyalty event {eventKey}.");
85
+ return false;
86
+ }
87
+ }
88
+
89
+ public async Task<AccountLookupResponse?> GetUserAccountAsync(string externalUserId)
90
+ {
91
+ try
92
+ {
93
+ var response = await _httpClient.GetAsync($"/api/v1/accounts/lookup/{SystemId}/{externalUserId}");
94
+ if (response.IsSuccessStatusCode)
95
+ {
96
+ return await response.Content.ReadFromJsonAsync<AccountLookupResponse>();
97
+ }
98
+ return null;
99
+ }
100
+ catch (Exception ex)
101
+ {
102
+ _logger.LogError(ex, $"Error fetching loyalty account for user {externalUserId}.");
103
+ return null;
104
+ }
105
+ }
106
+ }
107
+
108
+ public class AccountLookupResponse
109
+ {
110
+ public string Id { get; set; } = string.Empty;
111
+ public string ExternalUserId { get; set; } = string.Empty;
112
+ public double CurrentBalance { get; set; }
113
+ public string Tier { get; set; } = string.Empty;
114
+ public double LifetimePoints { get; set; }
115
+ }
116
+ }
Backend/Features/Subscriptions/SubscriptionService.cs CHANGED
@@ -1,5 +1,6 @@
1
  using Database.Models;
2
  using Microsoft.EntityFrameworkCore;
 
3
 
4
  namespace Backend.Features.Subscriptions
5
  {
@@ -13,10 +14,12 @@ namespace Backend.Features.Subscriptions
13
  public class SubscriptionService : ISubscriptionService
14
  {
15
  private readonly LibraryManagementContext _context;
 
16
 
17
- public SubscriptionService(LibraryManagementContext context)
18
  {
19
  _context = context;
 
20
  }
21
 
22
  public async Task<IEnumerable<MembershipDto>> GetMembershipsAsync()
@@ -75,6 +78,22 @@ namespace Backend.Features.Subscriptions
75
 
76
  // Explicitly load the membership data for the DTO mapping
77
  await _context.Entry(subscription).Reference(s => s.Membership).LoadAsync();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  return MapToDto(subscription);
80
  }
 
1
  using Database.Models;
2
  using Microsoft.EntityFrameworkCore;
3
+ using Backend.Features.Loyalty;
4
 
5
  namespace Backend.Features.Subscriptions
6
  {
 
14
  public class SubscriptionService : ISubscriptionService
15
  {
16
  private readonly LibraryManagementContext _context;
17
+ private readonly ILoyaltyService _loyaltyService;
18
 
19
+ public SubscriptionService(LibraryManagementContext context, ILoyaltyService loyaltyService)
20
  {
21
  _context = context;
22
+ _loyaltyService = loyaltyService;
23
  }
24
 
25
  public async Task<IEnumerable<MembershipDto>> GetMembershipsAsync()
 
78
 
79
  // Explicitly load the membership data for the DTO mapping
80
  await _context.Entry(subscription).Reference(s => s.Membership).LoadAsync();
81
+ await _context.Entry(subscription).Reference(s => s.User).LoadAsync();
82
+
83
+ // Loyalty Integration: Send SUBSCRIBE event
84
+ string externalUserId = userId.ToString();
85
+ string userMobile = subscription.User?.PhoneNumber ?? "0000000000";
86
+ string userEmail = subscription.User?.Email ?? "No Email";
87
+
88
+ await _loyaltyService.ProcessEventAsync(
89
+ externalUserId: externalUserId,
90
+ eventKey: "SUBSCRIBE",
91
+ eventValue: (double)membership.Price,
92
+ referenceId: $"SUB-{subscription.Id}",
93
+ description: $"Purchased Membership: {membership.Type}",
94
+ email: userEmail,
95
+ mobile: userMobile
96
+ );
97
 
98
  return MapToDto(subscription);
99
  }
Backend/Features/Users/UserService.cs CHANGED
@@ -1,6 +1,7 @@
1
  using Database.Models;
2
  using Microsoft.EntityFrameworkCore;
3
  using Backend.Features.Subscriptions;
 
4
  using System;
5
  using System.Collections.Generic;
6
  using System.Linq;
@@ -22,11 +23,13 @@ namespace Backend.Features.Users
22
  {
23
  private readonly LibraryManagementContext _context;
24
  private readonly ISubscriptionService _subscriptionService;
 
25
 
26
- public UserService(LibraryManagementContext context, ISubscriptionService subscriptionService)
27
  {
28
  _context = context;
29
  _subscriptionService = subscriptionService;
 
30
  }
31
 
32
  public async Task<IEnumerable<UserDto>> GetAllUsersAsync()
@@ -69,6 +72,20 @@ namespace Backend.Features.Users
69
  await _subscriptionService.SubscribeUserAsync(user.Id, 3); // 3 is "Basic Yearly"
70
  }
71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  return MapToDto(user);
73
  }
74
 
 
1
  using Database.Models;
2
  using Microsoft.EntityFrameworkCore;
3
  using Backend.Features.Subscriptions;
4
+ using Backend.Features.Loyalty;
5
  using System;
6
  using System.Collections.Generic;
7
  using System.Linq;
 
23
  {
24
  private readonly LibraryManagementContext _context;
25
  private readonly ISubscriptionService _subscriptionService;
26
+ private readonly ILoyaltyService _loyaltyService;
27
 
28
+ public UserService(LibraryManagementContext context, ISubscriptionService subscriptionService, ILoyaltyService loyaltyService)
29
  {
30
  _context = context;
31
  _subscriptionService = subscriptionService;
32
+ _loyaltyService = loyaltyService;
33
  }
34
 
35
  public async Task<IEnumerable<UserDto>> GetAllUsersAsync()
 
72
  await _subscriptionService.SubscribeUserAsync(user.Id, 3); // 3 is "Basic Yearly"
73
  }
74
 
75
+ // Loyalty Integration: Register the new user and process SIGNUP event
76
+ string externalUserId = user.Id.ToString();
77
+ string userMobile = user.PhoneNumber ?? "0000000000";
78
+ await _loyaltyService.RegisterUserAsync(externalUserId, user.Email, userMobile);
79
+ await _loyaltyService.ProcessEventAsync(
80
+ externalUserId: externalUserId,
81
+ eventKey: "SIGNUP",
82
+ eventValue: 0,
83
+ referenceId: $"USR-{user.Id}",
84
+ description: "New User Registration",
85
+ email: user.Email,
86
+ mobile: userMobile
87
+ );
88
+
89
  return MapToDto(user);
90
  }
91
 
Backend/Program.cs CHANGED
@@ -10,9 +10,11 @@ using Microsoft.OpenApi.Models;
10
  using Backend.Features.Subscriptions;
11
  using Backend.Features.Categories;
12
  using Backend.Features.Borrowings;
 
13
 
14
  var builder = WebApplication.CreateBuilder(args);
15
 
 
16
  builder.Services.AddControllers();
17
  builder.Services.AddAuthorization();
18
  builder.Services.AddEndpointsApiExplorer();
@@ -55,6 +57,12 @@ builder.Services.AddScoped<ISubscriptionService, SubscriptionService>();
55
  builder.Services.AddScoped<ICategoryService, CategoryService>();
56
  builder.Services.AddScoped<IBorrowingService, BorrowingService>();
57
 
 
 
 
 
 
 
58
  // Configure JWT Authentication
59
  var key = Encoding.ASCII.GetBytes(builder.Configuration["Jwt:Secret"] ?? "YourSuperSecretKeyForLibraryManagementSystem_AtLeast32CharsLong");
60
  builder.Services.AddAuthentication(x =>
 
10
  using Backend.Features.Subscriptions;
11
  using Backend.Features.Categories;
12
  using Backend.Features.Borrowings;
13
+ using Backend.Features.Loyalty;
14
 
15
  var builder = WebApplication.CreateBuilder(args);
16
 
17
+
18
  builder.Services.AddControllers();
19
  builder.Services.AddAuthorization();
20
  builder.Services.AddEndpointsApiExplorer();
 
57
  builder.Services.AddScoped<ICategoryService, CategoryService>();
58
  builder.Services.AddScoped<IBorrowingService, BorrowingService>();
59
 
60
+ // Register Loyalty API Client
61
+ builder.Services.AddHttpClient<ILoyaltyService, LoyaltyService>(client =>
62
+ {
63
+ client.BaseAddress = new Uri("http://150.95.88.91:4100");
64
+ });
65
+
66
  // Configure JWT Authentication
67
  var key = Encoding.ASCII.GetBytes(builder.Configuration["Jwt:Secret"] ?? "YourSuperSecretKeyForLibraryManagementSystem_AtLeast32CharsLong");
68
  builder.Services.AddAuthentication(x =>
Frontend/Controllers/HomeController.cs CHANGED
@@ -24,6 +24,14 @@ namespace Frontend.Controllers
24
  var borrowings = await _apiClient.GetMyBorrowingsAsync();
25
  var members = await _apiClient.GetUsersAsync();
26
 
 
 
 
 
 
 
 
 
27
  ViewBag.TotalBooks = books.Count();
28
  ViewBag.ActiveLoans = borrowings.Count(b => !b.ReturnDate.HasValue);
29
  ViewBag.OverdueLoans = borrowings.Count(b => !b.ReturnDate.HasValue && b.DueDate < DateTime.UtcNow);
@@ -37,9 +45,10 @@ namespace Frontend.Controllers
37
  // Set default values if API fails
38
  ViewBag.TotalBooks = 0;
39
  ViewBag.ActiveLoans = 0;
40
- ViewBag.OverdueLoans = 0;
41
  ViewBag.TotalMembers = 0;
42
  ViewBag.RecentBooks = Enumerable.Empty<Frontend.Models.Dtos.BookDto>();
 
 
43
  }
44
 
45
  return View();
 
24
  var borrowings = await _apiClient.GetMyBorrowingsAsync();
25
  var members = await _apiClient.GetUsersAsync();
26
 
27
+ // Fetch loyalty points (if user is logged in)
28
+ if (User.Identity?.IsAuthenticated == true)
29
+ {
30
+ var loyaltyAccount = await _apiClient.GetMyLoyaltyAccountAsync();
31
+ ViewBag.LoyaltyPoints = loyaltyAccount?.CurrentBalance ?? 0;
32
+ ViewBag.LoyaltyTier = loyaltyAccount?.Tier ?? "Member";
33
+ }
34
+
35
  ViewBag.TotalBooks = books.Count();
36
  ViewBag.ActiveLoans = borrowings.Count(b => !b.ReturnDate.HasValue);
37
  ViewBag.OverdueLoans = borrowings.Count(b => !b.ReturnDate.HasValue && b.DueDate < DateTime.UtcNow);
 
45
  // Set default values if API fails
46
  ViewBag.TotalBooks = 0;
47
  ViewBag.ActiveLoans = 0;
 
48
  ViewBag.TotalMembers = 0;
49
  ViewBag.RecentBooks = Enumerable.Empty<Frontend.Models.Dtos.BookDto>();
50
+ ViewBag.LoyaltyPoints = 0;
51
+ ViewBag.LoyaltyTier = "Member";
52
  }
53
 
54
  return View();
Frontend/Frontend.csproj CHANGED
@@ -7,3 +7,4 @@
7
  </PropertyGroup>
8
 
9
  </Project>
 
 
7
  </PropertyGroup>
8
 
9
  </Project>
10
+
Frontend/Models/Dtos/LibraryDtos.cs CHANGED
@@ -124,6 +124,16 @@ namespace Frontend.Models.Dtos
124
  public int MembershipId { get; set; }
125
  }
126
 
 
 
 
 
 
 
 
 
 
 
127
  // User DTOs
128
  public class UserDto
129
  {
 
124
  public int MembershipId { get; set; }
125
  }
126
 
127
+ // Loyalty DTOs
128
+ public class LoyaltyAccountDto
129
+ {
130
+ public string Id { get; set; } = string.Empty;
131
+ public string ExternalUserId { get; set; } = string.Empty;
132
+ public double CurrentBalance { get; set; }
133
+ public string Tier { get; set; } = string.Empty;
134
+ public double LifetimePoints { get; set; }
135
+ }
136
+
137
  // User DTOs
138
  public class UserDto
139
  {
Frontend/Services/LibraryApiClient.cs CHANGED
@@ -158,6 +158,15 @@ namespace Frontend.Services
158
  }
159
  #endregion
160
 
 
 
 
 
 
 
 
 
 
161
  #region Users
162
  public async Task<IEnumerable<UserDto>> GetUsersAsync()
163
  {
 
158
  }
159
  #endregion
160
 
161
+ #region Loyalty
162
+ public async Task<LoyaltyAccountDto?> GetMyLoyaltyAccountAsync()
163
+ {
164
+ try {
165
+ return await _httpClient.GetFromJsonAsync<LoyaltyAccountDto>("api/loyalty/my-account");
166
+ } catch { return null; }
167
+ }
168
+ #endregion
169
+
170
  #region Users
171
  public async Task<IEnumerable<UserDto>> GetUsersAsync()
172
  {
Frontend/Views/Home/Index.cshtml CHANGED
@@ -7,6 +7,30 @@
7
  <p class="text-slate-500 font-medium">Here's what's happening with the library today.</p>
8
  </div>
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  <!-- Stats Grid -->
11
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
12
  <div class="card p-6 flex flex-col gap-3 group hover:border-slate-300">
 
7
  <p class="text-slate-500 font-medium">Here's what's happening with the library today.</p>
8
  </div>
9
 
10
+ @if (User.Identity?.IsAuthenticated == true)
11
+ {
12
+ <!-- Loyalty Banner -->
13
+ <div class="bg-gradient-to-r from-amber-500 to-amber-700 rounded-2xl p-6 mb-10 text-white shadow-lg relative overflow-hidden group">
14
+ <div class="relative z-10 flex items-center justify-between">
15
+ <div>
16
+ <p class="text-amber-100 text-sm font-bold uppercase tracking-widest mb-1">Your Loyalty Status</p>
17
+ <div class="flex items-baseline gap-3">
18
+ <h2 class="text-4xl font-extrabold">@ViewBag.LoyaltyPoints</h2>
19
+ <span class="text-amber-200 font-medium tracking-wide">Points</span>
20
+ </div>
21
+ </div>
22
+ <div class="text-right">
23
+ <div class="inline-flex items-center gap-2 bg-black/20 backdrop-blur-sm px-4 py-2 rounded-full border border-white/10 shadow-inner">
24
+ <svg class="w-5 h-5 text-amber-200" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"></path></svg>
25
+ <span class="font-bold text-lg">@ViewBag.LoyaltyTier</span>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ <!-- Decorative Background -->
30
+ <div class="absolute -right-10 -top-10 w-48 h-48 bg-white/10 rounded-full blur-2xl transform group-hover:scale-110 transition-transform duration-700"></div>
31
+ </div>
32
+ }
33
+
34
  <!-- Stats Grid -->
35
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
36
  <div class="card p-6 flex flex-col gap-3 group hover:border-slate-300">
LibraryManagement.slnx CHANGED
@@ -1,5 +1,5 @@
1
  <Solution>
 
2
  <Project Path="Database/Database.csproj" Id="1ec23dc7-355d-4456-a503-cfd0fb81cd5c" />
3
  <Project Path="Frontend/Frontend.csproj" Id="824d7fed-4fd3-41c5-8c5e-acd458ccbcdb" />
4
- <Project Path="Backend/Backend.csproj" Id="82e311b1-ce76-4235-9d5f-0d06a942d038" />
5
  </Solution>
 
1
  <Solution>
2
+ <Project Path="Backend/Backend.csproj" Id="82e311b1-ce76-4235-9d5f-0d06a942d038" />
3
  <Project Path="Database/Database.csproj" Id="1ec23dc7-355d-4456-a503-cfd0fb81cd5c" />
4
  <Project Path="Frontend/Frontend.csproj" Id="824d7fed-4fd3-41c5-8c5e-acd458ccbcdb" />
 
5
  </Solution>