diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 0000000..945c9b4 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/common-lisp/source/shopping-cart.lisp b/common-lisp/source/shopping-cart.lisp index 51631a2..1167c78 100644 --- a/common-lisp/source/shopping-cart.lisp +++ b/common-lisp/source/shopping-cart.lisp @@ -2,6 +2,10 @@ (in-package :supermarket-receipt) +;; Discount description constants +(defconstant +three-for-two-description+ "3 for 2") +(defconstant +percent-off-suffix+ " % off") + (defclass shopping-cart () ((items :initform nil :type list @@ -56,12 +60,12 @@ (* (mod floored-quantity 3) a-unit-price))))) (setf a-discount (make-instance 'discount :product a-product - :description "3 for 2" + :description +three-for-two-description+ :amount (- discount-amount))))) (when (eq the-offer-type 'ten-percent-discount) (setf a-discount (make-instance 'discount :product a-product - :description (format nil "~S % off" (offer-argument offer-for-product)) + :description (format nil "~A~A" (offer-argument offer-for-product) +percent-off-suffix+) :amount (/ (* (- a-quantity) a-unit-price (offer-argument offer-for-product)) 100.0)))) (when (and (eq the-offer-type 'five-for-amount) (>= floored-quantity 5)) diff --git a/cpp/src/ShoppingCart.cpp b/cpp/src/ShoppingCart.cpp index 3c3a523..5834f35 100644 --- a/cpp/src/ShoppingCart.cpp +++ b/cpp/src/ShoppingCart.cpp @@ -1,5 +1,9 @@ #include "ShoppingCart.h" +// Discount description constants +static const std::string THREE_FOR_TWO_DESCRIPTION = "3 for 2"; +static const std::string PERCENT_OFF_SUFFIX = " % off"; + void addItemQuantity(const Product& product, double quantity); std::vector ShoppingCart::getItems() const { @@ -49,10 +53,10 @@ void ShoppingCart::handleOffers(Receipt& receipt, std::map offer int numberOfXs = quantityAsInt / x; if (offer.getOfferType() == SpecialOfferType::ThreeForTwo && quantityAsInt > 2) { double discountAmount = quantity * unitPrice - ((numberOfXs * 2 * unitPrice) + quantityAsInt % 3 * unitPrice); - discount = new Discount("3 for 2", -discountAmount, product); + discount = new Discount(THREE_FOR_TWO_DESCRIPTION, -discountAmount, product); } if (offer.getOfferType() == SpecialOfferType::TenPercentDiscount) { - discount = new Discount(std::to_string(offer.getArgument()) + "% off", -quantity * unitPrice * offer.getArgument() / 100.0, product); + discount = new Discount(std::to_string(offer.getArgument()) + PERCENT_OFF_SUFFIX, -quantity * unitPrice * offer.getArgument() / 100.0, product); } if (offer.getOfferType() == SpecialOfferType::FiveForAmount && quantityAsInt >= 5) { double discountTotal = unitPrice * quantity - (offer.getArgument() * numberOfXs + quantityAsInt % 5 * unitPrice); diff --git a/csharp-ms/SupermarketReceipt/ShoppingCart.cs b/csharp-ms/SupermarketReceipt/ShoppingCart.cs index 28abbe7..05c7d88 100644 --- a/csharp-ms/SupermarketReceipt/ShoppingCart.cs +++ b/csharp-ms/SupermarketReceipt/ShoppingCart.cs @@ -4,6 +4,10 @@ namespace SupermarketReceipt { public class ShoppingCart { + // Discount description constants + private const string THREE_FOR_TWO_DESCRIPTION = "3 for 2"; + private const string PERCENT_OFF_SUFFIX = " % off"; + private readonly List _items = new List(); private readonly Dictionary _productQuantities = new Dictionary(); @@ -65,10 +69,10 @@ public void HandleOffers(Receipt receipt, Dictionary offers, Sup 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); + discount = new Discount(p, THREE_FOR_TWO_DESCRIPTION, -discountAmount); } - if (offer.OfferType == SpecialOfferType.TenPercentDiscount) discount = new Discount(p, offer.Argument + "% off", -quantity * unitPrice * offer.Argument / 100.0); + if (offer.OfferType == SpecialOfferType.TenPercentDiscount) discount = new Discount(p, offer.Argument + PERCENT_OFF_SUFFIX, -quantity * unitPrice * offer.Argument / 100.0); if (offer.OfferType == SpecialOfferType.FiveForAmount && quantityAsInt >= 5) { var discountTotal = unitPrice * quantity - (offer.Argument * numberOfXs + quantityAsInt % 5 * unitPrice); diff --git a/csharp/SupermarketReceipt/ShoppingCart.cs b/csharp/SupermarketReceipt/ShoppingCart.cs index 72b6b4a..ef032d3 100644 --- a/csharp/SupermarketReceipt/ShoppingCart.cs +++ b/csharp/SupermarketReceipt/ShoppingCart.cs @@ -5,6 +5,10 @@ namespace SupermarketReceipt { public class ShoppingCart { + // Discount description constants + private const string THREE_FOR_TWO_DESCRIPTION = "3 for 2"; + private const string PERCENT_OFF_SUFFIX = " % off"; + private readonly List _items = new List(); private readonly Dictionary _productQuantities = new Dictionary(); private static readonly CultureInfo Culture = CultureInfo.CreateSpecificCulture("en-GB"); @@ -67,10 +71,10 @@ public void HandleOffers(Receipt receipt, Dictionary offers, Sup 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); + discount = new Discount(p, THREE_FOR_TWO_DESCRIPTION, -discountAmount); } - if (offer.OfferType == SpecialOfferType.TenPercentDiscount) discount = new Discount(p, offer.Argument + "% off", -quantity * unitPrice * offer.Argument / 100.0); + if (offer.OfferType == SpecialOfferType.TenPercentDiscount) discount = new Discount(p, offer.Argument + PERCENT_OFF_SUFFIX, -quantity * unitPrice * offer.Argument / 100.0); if (offer.OfferType == SpecialOfferType.FiveForAmount && quantityAsInt >= 5) { var discountTotal = unitPrice * quantity - (offer.Argument * numberOfXs + quantityAsInt % 5 * unitPrice); diff --git a/elixir/lib/supermarket/model/shopping_cart.ex b/elixir/lib/supermarket/model/shopping_cart.ex index b0fc089..df03fd9 100644 --- a/elixir/lib/supermarket/model/shopping_cart.ex +++ b/elixir/lib/supermarket/model/shopping_cart.ex @@ -5,6 +5,10 @@ defmodule Supermarket.Model.ShoppingCart do alias Supermarket.Model.Receipt alias Supermarket.Model.SupermarketCatalog + # Discount description constants + @three_for_two_description "3 for 2" + @percent_off_suffix " % off" + defstruct [:items, :product_quantities] def new, do: %__MODULE__{items: [], product_quantities: %{}} @@ -70,12 +74,12 @@ defmodule Supermarket.Model.ShoppingCart do quantity * unit_price - (number_of_xs * 2 * unit_price + Integer.mod(quantity_as_int, 3) * unit_price) - Discount.new(p, "3 for 2", -discount_amount) + Discount.new(p, @three_for_two_description, -discount_amount) offer.offer_type == :ten_percent_discount -> Discount.new( p, - "#{offer.argument}% off", + "#{offer.argument}#{@percent_off_suffix}", -quantity * unit_price * offer.argument / 100.0 ) diff --git a/go/supermarket/shopping_cart.go b/go/supermarket/shopping_cart.go index 3079f92..a676ecb 100644 --- a/go/supermarket/shopping_cart.go +++ b/go/supermarket/shopping_cart.go @@ -5,6 +5,12 @@ import ( "math" ) +// Discount description constants +const ( + threeForTwoDescription = "3 for 2" + percentOffSuffix = " % off" +) + type ProductQuantity struct { product Product quantity float64 @@ -62,10 +68,10 @@ func (c *ShoppingCart) handleOffers(receipt *Receipt, offers map[Product]Special var numberOfXs int = quantityAsInt / x; if offer.offerType == ThreeForTwo && quantityAsInt > 2 { var discountAmount = quantity * unitPrice - (float64(numberOfXs * 2) * unitPrice + float64(quantityAsInt % 3) * unitPrice) - discount = &Discount{product: p, description: "3 for 2", discountAmount: -discountAmount} + discount = &Discount{product: p, description: threeForTwoDescription, discountAmount: -discountAmount} } if offer.offerType == TenPercentDiscount { - discount = &Discount{product: p, description: fmt.Sprintf("%.0f %% off", offer.argument), discountAmount: -quantity * unitPrice * offer.argument / 100.0} + discount = &Discount{product: p, description: fmt.Sprintf("%.0f%s", offer.argument, percentOffSuffix), discountAmount: -quantity * unitPrice * offer.argument / 100.0} } if offer.offerType == FiveForAmount && quantityAsInt >= 5 { var discountTotal = unitPrice * quantity - (offer.argument * float64(numberOfXs) + float64(quantityAsInt % 5) * unitPrice) diff --git a/java/src/main/java/dojo/supermarket/model/ShoppingCart.java b/java/src/main/java/dojo/supermarket/model/ShoppingCart.java index 9293086..1cbf26b 100644 --- a/java/src/main/java/dojo/supermarket/model/ShoppingCart.java +++ b/java/src/main/java/dojo/supermarket/model/ShoppingCart.java @@ -8,6 +8,10 @@ public class ShoppingCart { + // Discount description constants + private static final String THREE_FOR_TWO_DESCRIPTION = "3 for 2"; + private static final String PERCENT_OFF_SUFFIX = " % off"; + private final List items = new ArrayList<>(); private final Map productQuantities = new HashMap<>(); @@ -58,10 +62,10 @@ void handleOffers(Receipt receipt, Map offers, SupermarketCatalo int numberOfXs = quantityAsInt / x; if (offer.offerType == SpecialOfferType.THREE_FOR_TWO && quantityAsInt > 2) { double discountAmount = quantity * unitPrice - ((numberOfXs * 2 * unitPrice) + quantityAsInt % 3 * unitPrice); - discount = new Discount(p, "3 for 2", -discountAmount); + discount = new Discount(p, THREE_FOR_TWO_DESCRIPTION, -discountAmount); } if (offer.offerType == SpecialOfferType.TEN_PERCENT_DISCOUNT) { - discount = new Discount(p, offer.argument + "% off", -quantity * unitPrice * offer.argument / 100.0); + discount = new Discount(p, offer.argument + PERCENT_OFF_SUFFIX, -quantity * unitPrice * offer.argument / 100.0); } if (offer.offerType == SpecialOfferType.FIVE_FOR_AMOUNT && quantityAsInt >= 5) { double discountTotal = unitPrice * quantity - (offer.argument * numberOfXs + quantityAsInt % 5 * unitPrice); diff --git a/kotlin/src/main/kotlin/supermarket/model/ShoppingCart.kt b/kotlin/src/main/kotlin/supermarket/model/ShoppingCart.kt index 83e7f30..92e2d3f 100644 --- a/kotlin/src/main/kotlin/supermarket/model/ShoppingCart.kt +++ b/kotlin/src/main/kotlin/supermarket/model/ShoppingCart.kt @@ -5,6 +5,12 @@ import java.util.HashMap class ShoppingCart { + // Discount description constants + companion object { + private const val THREE_FOR_TWO_DESCRIPTION = "3 for 2" + private const val PERCENT_OFF_SUFFIX = " % off" + } + private val items = ArrayList() internal var productQuantities: MutableMap = HashMap() @@ -59,11 +65,11 @@ class ShoppingCart { if (offer.offerType === SpecialOfferType.ThreeForTwo && quantityAsInt > 2) { val discountAmount = quantity * unitPrice - (numberOfXs.toDouble() * 2.0 * unitPrice + quantityAsInt % 3 * unitPrice) - discount = Discount(p, "3 for 2", discountAmount) + discount = Discount(p, THREE_FOR_TWO_DESCRIPTION, discountAmount) } if (offer.offerType === SpecialOfferType.TenPercentDiscount) { discount = - Discount(p, offer.argument.toString() + "% off", quantity * unitPrice * offer.argument / 100.0) + Discount(p, offer.argument.toString() + PERCENT_OFF_SUFFIX, quantity * unitPrice * offer.argument / 100.0) } if (offer.offerType === SpecialOfferType.FiveForAmount && quantityAsInt >= 5) { val discountTotal = diff --git a/php/src/Model/ShoppingCart.php b/php/src/Model/ShoppingCart.php index d2f6c78..1130bf7 100644 --- a/php/src/Model/ShoppingCart.php +++ b/php/src/Model/ShoppingCart.php @@ -8,6 +8,10 @@ class ShoppingCart { + // Discount description constants + private const THREE_FOR_TWO_DESCRIPTION = '3 for 2'; + private const PERCENT_OFF_SUFFIX = ' % off'; + /** * @var ProductQuantity[] */ @@ -81,13 +85,13 @@ public function handleOffers(Receipt $receipt, Map $offers, SupermarketCatalog $ $numberOfXs = intdiv($quantityAsInt, $x); if ($offer->getOfferType()->equals(SpecialOfferType::THREE_FOR_TWO()) && $quantityAsInt > 2) { $discountAmount = $quantity * $unitPrice - ($numberOfXs * 2 * $unitPrice + $quantityAsInt % 3 * $unitPrice); - $discount = new Discount($p, '3 for 2', -$discountAmount); + $discount = new Discount($p, self::THREE_FOR_TWO_DESCRIPTION, -$discountAmount); } if ($offer->getOfferType()->equals(SpecialOfferType::TEN_PERCENT_DISCOUNT())) { $discount = new Discount( $p, - "{$offer->getArgument()}% off", + "{$offer->getArgument()}" . self::PERCENT_OFF_SUFFIX, -$quantity * $unitPrice * $offer->getArgument() / 100.0 ); } diff --git a/python/shopping_cart.py b/python/shopping_cart.py index 4e36cc5..705a3dd 100644 --- a/python/shopping_cart.py +++ b/python/shopping_cart.py @@ -3,6 +3,11 @@ from model_objects import ProductQuantity, SpecialOfferType, Discount +# Discount description constants +THREE_FOR_TWO_DESCRIPTION = "3 for 2" +PERCENT_OFF_SUFFIX = " % off" + + class ShoppingCart: def __init__(self): @@ -44,7 +49,7 @@ def handle_offers(self, receipt, offers, catalog): if quantity_as_int >= 2: total = offer.argument * (quantity_as_int / x) + quantity_as_int % 2 * unit_price discount_n = unit_price * quantity - total - discount = Discount(p, "2 for " + str(offer.argument), -discount_n) + discount = Discount(p, f"2 for {offer.argument}", -discount_n) if offer.offer_type == SpecialOfferType.FIVE_FOR_AMOUNT: x = 5 @@ -53,16 +58,16 @@ def handle_offers(self, receipt, offers, catalog): if offer.offer_type == SpecialOfferType.THREE_FOR_TWO and quantity_as_int > 2: discount_amount = quantity * unit_price - ( (number_of_x * 2 * unit_price) + quantity_as_int % 3 * unit_price) - discount = Discount(p, "3 for 2", -discount_amount) + discount = Discount(p, THREE_FOR_TWO_DESCRIPTION, -discount_amount) if offer.offer_type == SpecialOfferType.TEN_PERCENT_DISCOUNT: - discount = Discount(p, str(offer.argument) + "% off", + discount = Discount(p, f"{offer.argument}{PERCENT_OFF_SUFFIX}", -quantity * unit_price * offer.argument / 100.0) if offer.offer_type == SpecialOfferType.FIVE_FOR_AMOUNT and quantity_as_int >= 5: discount_total = unit_price * quantity - ( offer.argument * number_of_x + quantity_as_int % 5 * unit_price) - discount = Discount(p, str(x) + " for " + str(offer.argument), -discount_total) + discount = Discount(p, f"{x} for {offer.argument}", -discount_total) if discount: receipt.add_discount(discount) diff --git a/python_pytest/src/shopping_cart.py b/python_pytest/src/shopping_cart.py index 4e36cc5..705a3dd 100644 --- a/python_pytest/src/shopping_cart.py +++ b/python_pytest/src/shopping_cart.py @@ -3,6 +3,11 @@ from model_objects import ProductQuantity, SpecialOfferType, Discount +# Discount description constants +THREE_FOR_TWO_DESCRIPTION = "3 for 2" +PERCENT_OFF_SUFFIX = " % off" + + class ShoppingCart: def __init__(self): @@ -44,7 +49,7 @@ def handle_offers(self, receipt, offers, catalog): if quantity_as_int >= 2: total = offer.argument * (quantity_as_int / x) + quantity_as_int % 2 * unit_price discount_n = unit_price * quantity - total - discount = Discount(p, "2 for " + str(offer.argument), -discount_n) + discount = Discount(p, f"2 for {offer.argument}", -discount_n) if offer.offer_type == SpecialOfferType.FIVE_FOR_AMOUNT: x = 5 @@ -53,16 +58,16 @@ def handle_offers(self, receipt, offers, catalog): if offer.offer_type == SpecialOfferType.THREE_FOR_TWO and quantity_as_int > 2: discount_amount = quantity * unit_price - ( (number_of_x * 2 * unit_price) + quantity_as_int % 3 * unit_price) - discount = Discount(p, "3 for 2", -discount_amount) + discount = Discount(p, THREE_FOR_TWO_DESCRIPTION, -discount_amount) if offer.offer_type == SpecialOfferType.TEN_PERCENT_DISCOUNT: - discount = Discount(p, str(offer.argument) + "% off", + discount = Discount(p, f"{offer.argument}{PERCENT_OFF_SUFFIX}", -quantity * unit_price * offer.argument / 100.0) if offer.offer_type == SpecialOfferType.FIVE_FOR_AMOUNT and quantity_as_int >= 5: discount_total = unit_price * quantity - ( offer.argument * number_of_x + quantity_as_int % 5 * unit_price) - discount = Discount(p, str(x) + " for " + str(offer.argument), -discount_total) + discount = Discount(p, f"{x} for {offer.argument}", -discount_total) if discount: receipt.add_discount(discount) diff --git a/ruby/lib/models/shopping_cart.rb b/ruby/lib/models/shopping_cart.rb index 6eea42e..fbaf734 100644 --- a/ruby/lib/models/shopping_cart.rb +++ b/ruby/lib/models/shopping_cart.rb @@ -1,5 +1,9 @@ class ShoppingCart + # Discount description constants + THREE_FOR_TWO_DESCRIPTION = "3 for 2" + PERCENT_OFF_SUFFIX = " % off" + def initialize @items = [] @product_quantities = {} @@ -54,10 +58,10 @@ def handle_offers(receipt, offers, catalog) number_of_x = quantity_as_int / x if offer.offer_type == SpecialOfferType::THREE_FOR_TWO && quantity_as_int > 2 discount_amount = quantity * unit_price - ((number_of_x * 2 * unit_price) + quantity_as_int % 3 * unit_price) - discount = Discount.new(p, "3 for 2", discount_amount) + discount = Discount.new(p, THREE_FOR_TWO_DESCRIPTION, discount_amount) end if offer.offer_type == SpecialOfferType::TEN_PERCENT_DISCOUNT - discount = Discount.new(p, offer.argument.to_s + "% off", quantity * unit_price * offer.argument / 100.0) + discount = Discount.new(p, offer.argument.to_s + PERCENT_OFF_SUFFIX, quantity * unit_price * offer.argument / 100.0) end if offer.offer_type == SpecialOfferType::FIVE_FOR_AMOUNT && quantity_as_int >= 5 discount_total = unit_price * quantity - (offer.argument * number_of_x + quantity_as_int % 5 * unit_price) diff --git a/swift/SupermarketReceipt/ShoppingCart.swift b/swift/SupermarketReceipt/ShoppingCart.swift index d34c8bc..18a472d 100644 --- a/swift/SupermarketReceipt/ShoppingCart.swift +++ b/swift/SupermarketReceipt/ShoppingCart.swift @@ -1,5 +1,9 @@ public class ShoppingCart { + // Discount description constants + private static let threeForTwoDescription = "3 for 2" + private static let percentOffSuffix = " % off" + public var items = [ProductQuantity]() public var productQuantities = [Product: Double]() @@ -52,10 +56,10 @@ public class ShoppingCart { var right = Double(quantityAsInt % 3) * unitPrice var lastPart = left + right var discountAmount = ((quantity ?? 1) * unitPrice) - lastPart - discount = Discount(description: "3 for 2", discountAmount: discountAmount, product: p) + discount = Discount(description: ShoppingCart.threeForTwoDescription, discountAmount: discountAmount, product: p) } if offer?.offerType == SpecialOfferType.TenPercentDiscount { - discount = Discount(description: "\(offer!.argument)% off", discountAmount: (quantity ?? 1) * unitPrice * (offer?.argument ?? 1) / 100.0, product: p) + discount = Discount(description: "\(offer!.argument)\(ShoppingCart.percentOffSuffix)", discountAmount: (quantity ?? 1) * unitPrice * (offer?.argument ?? 1) / 100.0, product: p) } if offer?.offerType == SpecialOfferType.FiveForAmount && quantityAsInt >= 5 { var left = (unitPrice * (quantity ?? 1)) diff --git a/typescript/src/model/ShoppingCart.ts b/typescript/src/model/ShoppingCart.ts index ac090cc..fedb23c 100644 --- a/typescript/src/model/ShoppingCart.ts +++ b/typescript/src/model/ShoppingCart.ts @@ -7,6 +7,10 @@ import {Receipt} from "./Receipt" import {Offer} from "./Offer" import {SpecialOfferType} from "./SpecialOfferType" +// Discount description constants +const THREE_FOR_TWO_DESCRIPTION = "3 for 2"; +const PERCENT_OFF_SUFFIX = " % off"; + type ProductQuantities = { [productName: string]: ProductQuantity } export type OffersByProduct = {[productName: string]: Offer}; @@ -73,10 +77,10 @@ export class ShoppingCart { const numberOfXs = Math.floor(quantityAsInt / x); if (offer.offerType == SpecialOfferType.ThreeForTwo && quantityAsInt > 2) { const discountAmount = quantity * unitPrice - ((numberOfXs * 2 * unitPrice) + quantityAsInt % 3 * unitPrice); - discount = new Discount(product, "3 for 2", discountAmount); + discount = new Discount(product, THREE_FOR_TWO_DESCRIPTION, discountAmount); } if (offer.offerType == SpecialOfferType.TenPercentDiscount) { - discount = new Discount(product, offer.argument + "% off", quantity * unitPrice * offer.argument / 100.0); + discount = new Discount(product, offer.argument + PERCENT_OFF_SUFFIX, quantity * unitPrice * offer.argument / 100.0); } if (offer.offerType == SpecialOfferType.FiveForAmount && quantityAsInt >= 5) { const discountTotal = unitPrice * quantity - (offer.argument * numberOfXs + quantityAsInt % 5 * unitPrice);