diff --git a/Src/Discount_coupon_system/DiscountCoupon.cpp b/Src/Discount_coupon_system/DiscountCoupon.cpp new file mode 100644 index 0000000..b5b4695 --- /dev/null +++ b/Src/Discount_coupon_system/DiscountCoupon.cpp @@ -0,0 +1,460 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; + +// ---------------------------- +// Discount Strategy (Strategy Pattern) +// ---------------------------- +class DiscountStrategy { +public: + virtual ~DiscountStrategy() {} + virtual double calculate(double baseAmount) = 0; +}; + +class FlatDiscountStrategy : public DiscountStrategy { +private: + double amount; +public: + FlatDiscountStrategy(double amt) { + amount = amt; + } + double calculate(double baseAmount) override { + return min(amount, baseAmount); + } +}; + +class PercentageDiscountStrategy : public DiscountStrategy { +private: + double percent; +public: + PercentageDiscountStrategy(double pct) { + percent = pct; + } + double calculate(double baseAmount) override { + return (percent / 100.0) * baseAmount; + } +}; + +class PercentageWithCapStrategy : public DiscountStrategy { +private: + double percent; + double cap; +public: + PercentageWithCapStrategy(double pct, double capVal) { + percent = pct; + cap = capVal; + } + double calculate(double baseAmount) override { + double disc = (percent / 100.0) * baseAmount; + if (disc > cap) { + return cap; + } + return disc; + } +}; + +enum StrategyType { + FLAT, + PERCENT, + PERCENT_WITH_CAP +}; + +// ---------------------------- +// DiscountStrategyManager (Singleton) +// ---------------------------- +class DiscountStrategyManager { +private: + static DiscountStrategyManager* instance; + DiscountStrategyManager() {} + DiscountStrategyManager(const DiscountStrategyManager&) = delete; + DiscountStrategyManager& operator=(const DiscountStrategyManager&) = delete; +public: + static DiscountStrategyManager* getInstance() { + if (!instance) { + instance = new DiscountStrategyManager(); + } + return instance; + } + DiscountStrategy* getStrategy(StrategyType type, double param1, double param2 = 0.0) const { + if (type == StrategyType::FLAT) { + return new FlatDiscountStrategy(param1); + } + if (type == StrategyType::PERCENT) { + return new PercentageDiscountStrategy(param1); + } + if (type == StrategyType::PERCENT_WITH_CAP) { + return new PercentageWithCapStrategy(param1, param2); + } + return nullptr; + } +}; +// Initialize static member +DiscountStrategyManager* DiscountStrategyManager::instance = nullptr; + +// ---------------------------- +// Assume existing Cart and Product classes +// ---------------------------- +class Product { +private: + string name; + string category; + double price; +public: + Product(string name, string category, double price) { + this->name = name; + this->category = category; + this->price = price; + } + string getName() { + return name; + } + string getCategory() const { + return category; + } + double getPrice() { + return price; + } +}; + +class CartItem { +private: + Product* product; + int quantity; +public: + CartItem(Product* prod, int qty) { + product = prod; + quantity = qty; + } + double itemTotal() { + return product->getPrice() * quantity; + } + const Product* getProduct() { + return product; + } +}; + +class Cart { +private: + vector items; + double originalTotal; + double currentTotal; + bool loyaltyMember; + string paymentBank; +public: + Cart() { + originalTotal = 0.0; + currentTotal = 0.0; + loyaltyMember = false; + paymentBank = ""; + } + + void addProduct(Product* prod, int qty = 1) { + CartItem* item = new CartItem(prod, qty); + items.push_back(item); + originalTotal += item->itemTotal(); + currentTotal += item->itemTotal(); + } + + double getOriginalTotal() { + return originalTotal; + } + + double getCurrentTotal() { + return currentTotal; + } + + void applyDiscount(double d) { + currentTotal -= d; + if (currentTotal < 0) { + currentTotal = 0; + } + } + + void setLoyaltyMember(bool member) { + loyaltyMember = member; + } + + bool isLoyaltyMember() { + return loyaltyMember; + } + + void setPaymentBank(string bank) { + paymentBank = bank; + } + + string getPaymentBank() { + return paymentBank; + } + + vector getItems() { + return items; + } +}; + +// ---------------------------- +// Coupon base class (Chain of Responsibility) +// ---------------------------- +class Coupon { +private: + Coupon* next; +public: + Coupon() { + next = nullptr; + } + virtual ~Coupon() { + if (next) { + delete next; + } + } + void setNext(Coupon* nxt) { + next = nxt; + } + Coupon* getNext() { + return next; + } + + void applyDiscount(Cart* cart) { + if (isApplicable(cart)) { + double discount = getDiscount(cart); + cart->applyDiscount(discount); + cout << name() << " applied: " << discount << endl; + if (!isCombinable()) { + return; + } + } + if (next) { + next->applyDiscount(cart); + } + } + virtual bool isApplicable(Cart* cart) = 0; + virtual double getDiscount(Cart* cart) = 0; + virtual bool isCombinable() { + return true; + } + virtual string name() = 0; +}; + +// ---------------------------- +// Concrete Coupons +// ---------------------------- +class SeasonalOffer : public Coupon { +private: + double percent; + string category; + DiscountStrategy* strat; +public: + SeasonalOffer(double pct, string cat) { + percent = pct; + category = cat; + strat = DiscountStrategyManager::getInstance()->getStrategy(StrategyType::PERCENT, percent); + } + ~SeasonalOffer() { + delete strat; + } + bool isApplicable(Cart* cart) override { + for (CartItem* item : cart->getItems()) { + if (item->getProduct()->getCategory() == category) { + return true; + } + } + return false; + } + double getDiscount(Cart* cart) override { + double subtotal = 0.0; + for (CartItem* item : cart->getItems()) { + if (item->getProduct()->getCategory() == category) { + subtotal += item->itemTotal(); + } + } + return strat->calculate(subtotal); + } + bool isCombinable() override { + return true; + } + string name() override { + return "Seasonal Offer " + to_string((int)percent) + " % off " + category; + } +}; + +class LoyaltyDiscount : public Coupon { +private: + double percent; + DiscountStrategy* strat; +public: + LoyaltyDiscount(double pct) { + percent = pct; + strat = DiscountStrategyManager::getInstance()->getStrategy(StrategyType::PERCENT, percent); + } + ~LoyaltyDiscount() { + delete strat; + } + bool isApplicable(Cart* cart) override { + return cart->isLoyaltyMember(); + } + double getDiscount(Cart* cart) override { + return strat->calculate(cart->getCurrentTotal()); + } + string name() override { + return "Loyalty Discount " + to_string((int)percent) + "% off"; + } +}; + +class BulkPurchaseDiscount : public Coupon { +private: + double threshold; + double flatOff; + DiscountStrategy* strat; +public: + BulkPurchaseDiscount(double thr, double off) { + threshold = thr; + flatOff = off; + strat = DiscountStrategyManager::getInstance()->getStrategy(StrategyType::FLAT, flatOff); + } + ~BulkPurchaseDiscount() { + delete strat; + } + bool isApplicable(Cart* cart) override { + return cart->getOriginalTotal() >= threshold; + } + double getDiscount(Cart* cart) override { + return strat->calculate(cart->getCurrentTotal()); + } + string name() override { + return "Bulk Purchase Rs " + to_string((int)flatOff) + " off over " + + to_string((int)threshold); + } +}; + +class BankingCoupon : public Coupon { +private: + string bank; + double minSpend; + double percent; + double offCap; + DiscountStrategy* strat; +public: + BankingCoupon(const string& b, double ms, double percent, double offCap) { + bank = b; + minSpend = ms; + this->percent = percent; + this->offCap = percent; + strat = DiscountStrategyManager::getInstance()->getStrategy(StrategyType::PERCENT_WITH_CAP, percent, offCap); + } + ~BankingCoupon() { + delete strat; + } + bool isApplicable(Cart* cart) override { + return cart->getPaymentBank() == bank + && cart->getOriginalTotal() >= minSpend; + } + double getDiscount(Cart* cart) override { + return strat->calculate(cart->getCurrentTotal()); + } + string name() override { + return bank + " Bank Rs " + to_string((int)percent) + " off upto " + to_string((int) offCap); + } +}; + +// ---------------------------- +// CouponManager (Singleton) +// ---------------------------- +class CouponManager { +private: + static CouponManager* instance; + Coupon* head; + CouponManager() { + head = nullptr; + } +public: + static CouponManager* getInstance() { + if (!instance) { + instance = new CouponManager(); + } + return instance; + } + + void registerCoupon(Coupon* coupon) { + if (!head) { + head = coupon; + } else { + Coupon* cur = head; + while (cur->getNext()) { + cur = cur->getNext(); + } + cur->setNext(coupon); + } + } + + vector getApplicable(Cart* cart) const { + vector res; + Coupon* cur = head; + while (cur) { + if (cur->isApplicable(cart)) { + res.push_back(cur->name()); + } + cur = cur->getNext(); + } + return res; + } + + double applyAll(Cart* cart) { + if (head) { + head->applyDiscount(cart); + } + return cart->getCurrentTotal(); + } +}; +// Initialize static instance pointer +CouponManager* CouponManager::instance = nullptr; + +// ---------------------------- +// Main: Client code (heap allocations and pointers) +// ---------------------------- +int main() { + + CouponManager* mgr = CouponManager::getInstance(); + mgr->registerCoupon(new SeasonalOffer(10, "Clothing")); + mgr->registerCoupon(new LoyaltyDiscount(5)); + mgr->registerCoupon(new BulkPurchaseDiscount(1000, 100)); + mgr->registerCoupon(new BankingCoupon("ABC", 2000, 15, 500)); + + Product* p1 = new Product("Winter Jacket", "Clothing", 1000); + Product* p2 = new Product("Smartphone", "Electronics", 20000); + Product* p3 = new Product("Jeans", "Clothing", 1000); + Product* p4 = new Product("Headphones", "Electronics", 2000); + + Cart* cart = new Cart(); + cart->addProduct(p1, 1); + cart->addProduct(p2, 1); + cart->addProduct(p3, 2); + cart->addProduct(p4, 1); + cart->setLoyaltyMember(true); + cart->setPaymentBank("ABC"); + + cout << "Original Cart Total: " << cart->getOriginalTotal() << " Rs" << endl; + + + + vector applicable = mgr->getApplicable(cart); + cout << "Applicable Coupons:" << endl; + for (string name : applicable) { + cout << " - " << name << endl; + } + + double finalTotal = mgr->applyAll(cart); + cout << "Final Cart Total after discounts: " << finalTotal << " Rs" << endl; + + // Cleanup code + delete p1; + delete p2; + delete p3; + delete p4; + delete cart; + + return 0; +} diff --git a/Src/Discount_coupon_system/compile.bat b/Src/Discount_coupon_system/compile.bat new file mode 100644 index 0000000..de6a9ea --- /dev/null +++ b/Src/Discount_coupon_system/compile.bat @@ -0,0 +1,17 @@ +@echo off +echo Compiling C++ Discount Coupon Application... + +REM Compile the main program +g++ -std=c++11 -o discount_coupon DiscountCoupon.cpp + +if %errorlevel% equ 0 ( + echo Compilation successful! + echo Running the Discount Coupon application... + echo. + discount_coupon.exe +) else ( + echo Compilation failed! + echo Please check for any syntax errors. +) + +pause diff --git a/Src/Discount_coupon_system/discount_coupon.exe b/Src/Discount_coupon_system/discount_coupon.exe new file mode 100644 index 0000000..f877f65 Binary files /dev/null and b/Src/Discount_coupon_system/discount_coupon.exe differ diff --git a/Src/Payment_gateway_system/PaymentGatewayApplication.cpp b/Src/Payment_gateway_system/PaymentGatewayApplication.cpp new file mode 100644 index 0000000..6440cfd --- /dev/null +++ b/Src/Payment_gateway_system/PaymentGatewayApplication.cpp @@ -0,0 +1,313 @@ +#include +#include +#include +#include + + +using namespace std; + +// ---------------------------- +// Data structure for payment details +// ---------------------------- +struct PaymentRequest { + string sender; + string reciever; + double amount; + string currency; + + PaymentRequest(const string& sender, const string& reciever, double amt, const string& curr) { + this->sender = sender; + this->reciever = reciever; + this->amount = amt; + this->currency = curr; + } +}; + +// ---------------------------- +// Banking System interface and implementations (Strategy for actual payment logic) +// ---------------------------- +class BankingSystem { +public: + virtual bool processPayment(double amount) = 0; + virtual ~BankingSystem() {} +}; + +class PaytmBankingSystem : public BankingSystem { +public: + PaytmBankingSystem() {} + bool processPayment(double amount) override { + // Simulate 20% success + int r = rand() % 100; + return r < 80; + } +}; + +class RazorpayBankingSystem : public BankingSystem { +public: + RazorpayBankingSystem() {} + bool processPayment(double amount) override { + cout << "[BankingSystem-Razorpay] Processing payment of " << amount << "...\n"; + // Simulate 90% success + int r = rand() % 100; + return r < 90; + } +}; + +// ---------------------------- +// Abstract base class for Payment Gateway (Template Method Pattern) +// ---------------------------- +class PaymentGateway { +protected: + BankingSystem* bankingSystem; +public: + PaymentGateway() { + bankingSystem = nullptr; + } + virtual ~PaymentGateway() { + delete bankingSystem; + } + + // Template method defining the standard payment flow + virtual bool processPayment(PaymentRequest* request) { + if (!validatePayment(request)) { + cout << "[PaymentGateway] Validation failed for " << request->sender << ".\n"; + return false; + } + if (!initiatePayment(request)) { + cout << "[PaymentGateway] Initiation failed for " << request->sender << ".\n"; + return false; + } + if (!confirmPayment(request)) { + cout << "[PaymentGateway] Confirmation failed for " << request->sender << ".\n"; + return false; + } + return true; + } + + // Steps to be implemented by concrete gateways + virtual bool validatePayment(PaymentRequest* request) = 0; + virtual bool initiatePayment(PaymentRequest* request) = 0; + virtual bool confirmPayment(PaymentRequest* request) = 0; +}; + +// ---------------------------- +// Concrete Payment Gateway for Paytm +// ---------------------------- +class PaytmGateway : public PaymentGateway { +public: + PaytmGateway() { + bankingSystem = new PaytmBankingSystem(); + } + bool validatePayment(PaymentRequest* request) override { + cout << "[Paytm] Validating payment for " << request->sender << ".\n"; + + if (request->amount <= 0 || request->currency != "INR") { + return false; + } + return true; + } + bool initiatePayment(PaymentRequest* request) override { + cout << "[Paytm] Initiating payment of " << request->amount + << " " << request->currency << " for " << request->sender << ".\n"; + + return bankingSystem->processPayment(request->amount); + } + bool confirmPayment(PaymentRequest* request) override { + cout << "[Paytm] Confirming payment for " << request->sender << ".\n"; + + // Confirmation always succeeds in this simulation + return true; + } +}; + +// ---------------------------- +// Concrete Payment Gateway for Razorpay +// ---------------------------- +class RazorpayGateway : public PaymentGateway { +public: + RazorpayGateway() { + bankingSystem = new RazorpayBankingSystem(); + } + bool validatePayment(PaymentRequest* request) override { + cout << "[Razorpay] Validating payment for " << request->sender << ".\n"; + + if (request->amount <= 0) { + return false; + } + return true; + } + bool initiatePayment(PaymentRequest* request) override { + cout << "[Razorpay] Initiating payment of " << request->amount + << " " << request->currency << " for " << request->sender << ".\n"; + + return bankingSystem->processPayment(request->amount); + + } + bool confirmPayment(PaymentRequest* request) override { + cout << "[Razorpay] Confirming payment for " << request->sender << ".\n"; + + // Confirmation always succeeds in this simulation + return true; + } +}; + +// ---------------------------- +// Proxy class that wraps a PaymentGateway to add retries (Proxy Pattern) +// ---------------------------- +class PaymentGatewayProxy : public PaymentGateway { + PaymentGateway* realGateway; + int retries; +public: + PaymentGatewayProxy(PaymentGateway* gateway, int maxRetries) { + realGateway = gateway; + retries = maxRetries; + } + ~PaymentGatewayProxy() { + delete realGateway; + } + bool processPayment(PaymentRequest* request) override { + bool result = false; + for (int attempt = 0; attempt < retries; ++attempt) { + if (attempt > 0) { + cout << "[Proxy] Retrying payment (attempt " << (attempt+1) + << ") for " << request->sender << ".\n"; + } + result = realGateway->processPayment(request); + if (result) break; + } + if (!result) { + cout << "[Proxy] Payment failed after " << (retries) + << " attempts for " << request->sender << ".\n"; + } + return result; + } + bool validatePayment(PaymentRequest* request) override { + return realGateway->validatePayment(request); + } + bool initiatePayment(PaymentRequest* request) override { + return realGateway->initiatePayment(request); + } + bool confirmPayment(PaymentRequest* request) override { + return realGateway->confirmPayment(request); + } +}; + +// ---------------------------- +// Gateway Factory for creating gateway (Singleton) +// ---------------------------- +enum class GatewayType { + PAYTM, + RAZORPAY +}; + +class GatewayFactory { +private: + static GatewayFactory instance; + // Private constructor and delete copy/assignment to ensure no one can clone or reassign your singleton. + GatewayFactory() {} + GatewayFactory(const GatewayFactory&) = delete; + GatewayFactory& operator=(const GatewayFactory&) = delete; + +public: + static GatewayFactory& getInstance() { + return instance; + } + PaymentGateway* getGateway(GatewayType type) { + if (type == GatewayType::PAYTM) { + PaymentGateway* paymentGateway = new PaytmGateway(); + return new PaymentGatewayProxy(paymentGateway, 3); + } else { + PaymentGateway* paymentGateway = new RazorpayGateway(); + return new PaymentGatewayProxy(paymentGateway, 1); + } + } +}; + +// define static instance +GatewayFactory GatewayFactory::instance; + +// ---------------------------- +// Unified API service (Singleton) +// ---------------------------- +class PaymentService { +private: + static PaymentService instance; + PaymentGateway* gateway; + + PaymentService() { + gateway = nullptr; + } + ~PaymentService() { + delete gateway; + } + + // Private constructor and delete copy/assignment to ensure no one can clone or reassign your singleton. + PaymentService(const PaymentService&) = delete; + PaymentService& operator=(const PaymentService&) = delete; + +public: + static PaymentService& getInstance() { + return instance; + } + void setGateway(PaymentGateway* g) { + if (gateway) delete gateway; + gateway = g; + } + bool processPayment(PaymentRequest* request) { + if (!gateway) { + cout << "[PaymentService] No payment gateway selected.\n"; + return false; + } + return gateway->processPayment(request); + } +}; + +PaymentService PaymentService::instance; + +// ---------------------------- +// Controller class for all client requests (Singleton) +// ---------------------------- +class PaymentController { +private: + static PaymentController instance; + PaymentController() {} + PaymentController(const PaymentController&) = delete; + PaymentController& operator=(const PaymentController&) = delete; +public: + static PaymentController& getInstance() { + return instance; + } + bool handlePayment(GatewayType type, PaymentRequest* req) { + PaymentGateway* paymentGateway = GatewayFactory::getInstance().getGateway(type); + PaymentService::getInstance().setGateway(paymentGateway); + return PaymentService::getInstance().processPayment(req); + } +}; + +PaymentController PaymentController::instance; + +// ---------------------------- +// Main: Client code now goes through controller +// ---------------------------- +int main() { + + srand(static_cast(time(nullptr))); + + PaymentRequest* req1 = new PaymentRequest("Aditya", "Shubham", 1000.0, "INR"); + + cout << "Processing via Paytm\n"; + cout << "------------------------------\n"; + bool res1 = PaymentController::getInstance().handlePayment(GatewayType::PAYTM, req1); + cout << "Result: " << (res1 ? "SUCCESS" : "FAIL") << "\n"; + cout << "------------------------------\n\n"; + + PaymentRequest* req2 = new PaymentRequest("Shubham", "Aditya", 500.0, "USD"); + + cout << "Processing via Razorpay\n"; + cout << "------------------------------\n"; + bool res2 = PaymentController::getInstance().handlePayment(GatewayType::RAZORPAY, req2); + cout << "Result: " << (res2 ? "SUCCESS" : "FAIL") << "\n"; + cout << "------------------------------\n"; + + return 0; +} diff --git a/Src/Payment_gateway_system/compile.bat b/Src/Payment_gateway_system/compile.bat new file mode 100644 index 0000000..cb7bc44 --- /dev/null +++ b/Src/Payment_gateway_system/compile.bat @@ -0,0 +1,17 @@ +@echo off +echo C++ Payment Gateway Application... + +REM Compile the main program +g++ -std=c++11 -o payment_gateway PaymentGatewayApplication.cpp + +if %errorlevel% equ 0 ( + echo Compilation successful! + echo Running the Payment Gateway application... + echo. + payment_gateway.exe +) else ( + echo Compilation failed! + echo Please check for any syntax errors. +) + +pause diff --git a/Src/Payment_gateway_system/payment_gateway.exe b/Src/Payment_gateway_system/payment_gateway.exe new file mode 100644 index 0000000..662c9f1 Binary files /dev/null and b/Src/Payment_gateway_system/payment_gateway.exe differ