Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions csharp/.github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Make sure the code you return is secure.
Keep explanations of the code your return to a minimum.
Use .NET and Azure as default technology stack.
Please explain step by step how you reach your result.
3 changes: 3 additions & 0 deletions csharp/SupermarketReceipt/Receipt.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

using System.Collections.Generic;

namespace SupermarketReceipt
Expand All @@ -7,6 +8,8 @@ public class Receipt
private readonly List<Discount> _discounts = new List<Discount>();
private readonly List<ReceiptItem> _items = new List<ReceiptItem>();



public double GetTotalPrice()
{
var total = 0.0;
Expand Down
94 changes: 51 additions & 43 deletions csharp/SupermarketReceipt/ShoppingCart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ public class ShoppingCart
private readonly List<ProductQuantity> _items = new List<ProductQuantity>();
private readonly Dictionary<Product, double> _productQuantities = new Dictionary<Product, double>();
private static readonly CultureInfo Culture = CultureInfo.CreateSpecificCulture("en-GB");



/// <summary>
/// Gets the list of items in the shopping cart.
/// </summary>
/// <returns>A new list containing the items in the shopping cart.</returns>
public List<ProductQuantity> GetItems()
{
return new List<ProductQuantity>(_items);
Expand All @@ -20,69 +23,74 @@ public void AddItem(Product product)
AddItemQuantity(product, 1.0);
}


public void AddItemQuantity(Product product, double quantity)
{
_items.Add(new ProductQuantity(product, quantity));
if (_productQuantities.ContainsKey(product))
{
var newAmount = _productQuantities[product] + quantity;
_productQuantities[product] = newAmount;
_productQuantities[product] += quantity;
}
else
{
_productQuantities.Add(product, quantity);
_productQuantities[product] = quantity;
Copy link

Copilot AI Jun 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider using dictionary.Add(product, quantity) when adding new entries for clarity in intent, which can improve readability.

Suggested change
_productQuantities[product] = quantity;
_productQuantities.Add(product, quantity);

Copilot uses AI. Check for mistakes.
}

_items.Add(new ProductQuantity(product, quantity));
}

public void HandleOffers(Receipt receipt, Dictionary<Product, Offer> offers, SupermarketCatalog catalog)
Copy link

Copilot AI Jun 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] HandleOffers contains multiple blocks of discount calculation logic; extracting that into a helper method would improve readability and testability.

Copilot uses AI. Check for mistakes.
{
foreach (var p in _productQuantities.Keys)
{
if (!offers.ContainsKey(p)) continue;

var quantity = _productQuantities[p];
var quantityAsInt = (int) quantity;
if (offers.ContainsKey(p))
var quantityAsInt = (int)quantity;
var offer = offers[p];
Comment on lines +44 to +48
Copy link

Copilot AI Jun 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using offers.TryGetValue(p, out var offer) to combine the key check and lookup into a single dictionary access.

Copilot uses AI. Check for mistakes.
var unitPrice = catalog.GetUnitPrice(p);

int x = offer.OfferType switch
{
var offer = offers[p];
var unitPrice = catalog.GetUnitPrice(p);
Discount discount = null;
var x = 1;
if (offer.OfferType == SpecialOfferType.ThreeForTwo)
{
x = 3;
}
else if (offer.OfferType == SpecialOfferType.TwoForAmount)
{
x = 2;
if (quantityAsInt >= 2)
{
var total = offer.Argument * (quantityAsInt / x) + quantityAsInt % 2 * unitPrice;
var discountN = unitPrice * quantity - total;
discount = new Discount(p, "2 for " + PrintPrice(offer.Argument), -discountN);
}
}
SpecialOfferType.ThreeForTwo => 3,
SpecialOfferType.TwoForAmount => 2,
SpecialOfferType.FiveForAmount => 5,
_ => 1
};
Copy link

Copilot AI Jun 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider extracting the discount calculation logic in the HandleOffers method into a separate helper function to simplify the method and improve readability.

Copilot uses AI. Check for mistakes.

if (offer.OfferType == SpecialOfferType.FiveForAmount) x = 5;
var numberOfXs = quantityAsInt / x;
if (offer.OfferType == SpecialOfferType.ThreeForTwo && quantityAsInt > 2)
{
var discountAmount = quantity * unitPrice - (numberOfXs * 2 * unitPrice + quantityAsInt % 3 * unitPrice);
discount = new Discount(p, "3 for 2", -discountAmount);
}
var numberOfXs = quantityAsInt / x;
var remainder = quantityAsInt % x;
double discountAmount = 0.0;

if (offer.OfferType == SpecialOfferType.TenPercentDiscount) discount = new Discount(p, offer.Argument + "% off", -quantity * unitPrice * offer.Argument / 100.0);
if (offer.OfferType == SpecialOfferType.FiveForAmount && quantityAsInt >= 5)
{
var discountTotal = unitPrice * quantity - (offer.Argument * numberOfXs + quantityAsInt % 5 * unitPrice);
discount = new Discount(p, x + " for " + PrintPrice(offer.Argument), -discountTotal);
}
switch (offer.OfferType)
{
case SpecialOfferType.TwoForAmount when quantityAsInt >= 2:
discountAmount = unitPrice * quantity - (offer.Argument * numberOfXs + remainder * unitPrice);
break;
case SpecialOfferType.ThreeForTwo when quantityAsInt > 2:
discountAmount = quantity * unitPrice - (numberOfXs * 2 * unitPrice + remainder * unitPrice);
break;
case SpecialOfferType.TenPercentDiscount:
discountAmount = quantity * unitPrice * offer.Argument / 100.0;
break;
case SpecialOfferType.FiveForAmount when quantityAsInt >= 5:
discountAmount = unitPrice * quantity - (offer.Argument * numberOfXs + remainder * unitPrice);
break;
}

if (discount != null)
receipt.AddDiscount(discount);
if (discountAmount != 0.0)
{
var description = offer.OfferType switch
{
SpecialOfferType.TwoForAmount => $"2 for {PrintPrice(offer.Argument)}",
SpecialOfferType.ThreeForTwo => "3 for 2",
SpecialOfferType.TenPercentDiscount => $"{offer.Argument}% off",
SpecialOfferType.FiveForAmount => $"{x} for {PrintPrice(offer.Argument)}",
_ => string.Empty
};
receipt.AddDiscount(new Discount(p, description, -discountAmount));
}
}
}

private string PrintPrice(double price)
{
return price.ToString("N2", Culture);
Expand Down
1 change: 1 addition & 0 deletions csharp/SupermarketReceipt/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

89 changes: 89 additions & 0 deletions csharp/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"recipe": {
"name": "Lasagna",
"ingredients": [
{
"name": "Lasagna noodles",
"quantity": "12",
"unit": "pieces"
},
{
"name": "Ground beef",
"quantity": "1",
"unit": "pound"
},
{
"name": "Onion",
"quantity": "1",
"unit": "medium, chopped"
},
{
"name": "Garlic",
"quantity": "2",
"unit": "cloves, minced"
},
{
"name": "Tomato sauce",
"quantity": "24",
"unit": "ounces"
},
{
"name": "Tomato paste",
"quantity": "6",
"unit": "ounces"
},
{
"name": "Ricotta cheese",
"quantity": "15",
"unit": "ounces"
},
{
"name": "Egg",
"quantity": "1",
"unit": "large"
},
{
"name": "Mozzarella cheese",
"quantity": "16",
"unit": "ounces, shredded"
},
{
"name": "Parmesan cheese",
"quantity": "3/4",
"unit": "cup, grated"
},
{
"name": "Salt",
"quantity": "1",
"unit": "teaspoon"
},
{
"name": "Black pepper",
"quantity": "1/2",
"unit": "teaspoon"
},
{
"name": "Dried basil",
"quantity": "1",
"unit": "teaspoon"
},
{
"name": "Dried oregano",
"quantity": "1",
"unit": "teaspoon"
}
],
"instructions": [
"Preheat oven to 375°F (190°C).",
"Cook lasagna noodles according to package instructions. Drain and set aside.",
"In a large skillet, cook ground beef, onion, and garlic over medium heat until meat is browned. Drain excess fat.",
"Stir in tomato sauce and tomato paste. Season with salt, pepper, basil, and oregano. Simmer for 15 minutes.",
"In a mixing bowl, combine ricotta cheese, egg, and 1/2 cup of Parmesan cheese.",
"Spread a thin layer of meat sauce in the bottom of a 9x13 inch baking dish.",
"Layer with 1/3 of the lasagna noodles, 1/3 of the ricotta mixture, 1/3 of the mozzarella cheese, and 1/3 of the meat sauce. Repeat layers twice more.",
"Top with remaining mozzarella and Parmesan cheese.",
"Cover with aluminum foil and bake in preheated oven for 25 minutes. Remove foil and bake for an additional 25 minutes, or until cheese is bubbly and slightly browned.",
"Let stand for 10 minutes before serving."
]
}
}
Empty file added csharp/test.txt
Empty file.