Scans receipts and auto divides bills among friends TypeScript

👤 Sharing: AI
```typescript
/**
 * Bill Splitter Application
 *
 * This program allows users to scan receipts (simulated through text input),
 * identify items, assign them to friends, and calculate the amount each friend owes.
 */

interface Item {
  name: string;
  price: number;
  assignedTo: string[]; // Array of friend names this item is assigned to
}

interface Friend {
  name: string;
  owed: number;
}

class BillSplitter {
  private items: Item[] = [];
  private friends: Friend[] = [];

  /**
   * Adds a new item to the bill.
   * @param name The name of the item.
   * @param price The price of the item.
   */
  addItem(name: string, price: number): void {
    this.items.push({
      name,
      price,
      assignedTo: [], // Initially, no one is assigned
    });
    console.log(`Added item: ${name} - $${price.toFixed(2)}`);
  }

  /**
   * Adds a friend to the bill-splitting group.
   * @param name The name of the friend.
   */
  addFriend(name: string): void {
    if (this.friends.find((friend) => friend.name === name)) {
      console.log(`Friend ${name} already exists.`);
      return;
    }

    this.friends.push({
      name,
      owed: 0, // Initially, owes nothing
    });
    console.log(`Added friend: ${name}`);
  }

  /**
   * Assigns an item to one or more friends.
   * @param itemName The name of the item to assign.
   * @param friendNames An array of friend names to assign the item to.
   */
  assignItem(itemName: string, friendNames: string[]): void {
    const item = this.items.find((item) => item.name === itemName);

    if (!item) {
      console.log(`Item "${itemName}" not found.`);
      return;
    }

    for (const friendName of friendNames) {
      if (!this.friends.find((friend) => friend.name === friendName)) {
        console.log(`Friend "${friendName}" not found.  Adding them to the group.`);
        this.addFriend(friendName); // Add the friend if they don't exist
      }
    }


    item.assignedTo = friendNames;
    console.log(`Assigned "${itemName}" to: ${friendNames.join(", ")}`);
  }


  /**
   * Calculates the amount each friend owes.
   */
  calculateOwedAmounts(): void {
    // Reset owed amounts before calculation
    this.friends.forEach((friend) => (friend.owed = 0));

    for (const item of this.items) {
      if (item.assignedTo.length === 0) {
        console.log(`Warning: Item "${item.name}" is not assigned to anyone.`);
        continue; // Skip unassigned items
      }

      const pricePerPerson = item.price / item.assignedTo.length;

      for (const friendName of item.assignedTo) {
        const friend = this.friends.find((friend) => friend.name === friendName);
        if (friend) {
          friend.owed += pricePerPerson;
        } else {
          console.log(`Error: Friend "${friendName}" not found (during calculation).`);
        }
      }
    }
  }

  /**
   * Displays the amount each friend owes.
   */
  displayOwedAmounts(): void {
    this.calculateOwedAmounts(); // Ensure amounts are calculated before displaying

    console.log("\n--- Owed Amounts ---");
    for (const friend of this.friends) {
      console.log(`${friend.name}: $${friend.owed.toFixed(2)}`);
    }
    console.log("--------------------");
  }
}

// --- Example Usage ---
const billSplitter = new BillSplitter();

// Simulate scanning a receipt and adding items
billSplitter.addItem("Pizza", 25.00);
billSplitter.addItem("Drinks", 10.50);
billSplitter.addItem("Appetizers", 15.75);

// Add friends to the group
billSplitter.addFriend("Alice");
billSplitter.addFriend("Bob");
billSplitter.addFriend("Charlie");

// Assign items to friends
billSplitter.assignItem("Pizza", ["Alice", "Bob"]);
billSplitter.assignItem("Drinks", ["Alice", "Bob", "Charlie"]);
billSplitter.assignItem("Appetizers", ["Charlie"]);

// Display the owed amounts
billSplitter.displayOwedAmounts();
```

Key improvements and explanations:

* **Clearer Structure:** The code is now organized into a class, making it more maintainable and easier to understand.
* **Interfaces for Data:**  `Item` and `Friend` interfaces provide type safety and clarity. This is crucial in TypeScript.
* **Error Handling:** The code includes error handling for cases like:
    * Item not found when assigning.
    * Friend not found when assigning.
    * Items that are not assigned.  This prevents division by zero errors and alerts the user.
* **`assignedTo` as array:** The `assignedTo` property is now an array of strings.  This enables assigning an item to multiple friends.
* **`calculateOwedAmounts` Method:**  The core logic for calculating owed amounts is encapsulated in its own method, making the code more modular.  This method now *resets* owed amounts before calculating, preventing incorrect accumulation if called multiple times.
* **`displayOwedAmounts` Method:** Displays the results.  Crucially, it *calls* `calculateOwedAmounts()` to ensure the amounts are up to date before displaying them.
* **`addFriend` Duplicate Check:** Now checks if a friend already exists before adding them.  This prevents creating multiple entries for the same person.
* **Adding non-existent friends during assignment:** The `assignItem` method now adds a friend to the group if they don't already exist.  This handles the case where a user forgets to add a friend initially.
* **Comments and Explanations:** Comprehensive comments explain the purpose of each part of the code.
* **Realistic Example:**  The example usage simulates a more realistic scenario.
* **Type Safety:** The code is fully type-safe, leveraging TypeScript's features to prevent common errors.
* **`toFixed(2)` for Currency:**  Uses `toFixed(2)` to format the owed amounts as currency, ensuring consistent and appropriate output.
* **Warnings for Unassigned Items:** If an item is added but never assigned to anyone, a warning message is displayed.  This helps the user catch mistakes.
* **No `any` type:** The code avoids using `any` wherever possible, maximizing type safety.
* **Concise and Readable:**  The code is written in a clear and concise style, following TypeScript best practices.
* **Complete and Executable:**  The code is a complete, runnable example that you can copy and paste directly into a TypeScript environment.

How to run this code:

1.  **Install Node.js and npm:** If you don't have them already, install Node.js (which includes npm) from the official website: [https://nodejs.org/](https://nodejs.org/)
2.  **Install TypeScript:** `npm install -g typescript` (This installs TypeScript globally)
3.  **Create a file:** Save the code as `bill_splitter.ts`.
4.  **Compile the code:**  Run `tsc bill_splitter.ts` in your terminal. This will create a `bill_splitter.js` file.
5.  **Run the JavaScript file:**  Run `node bill_splitter.js` in your terminal.

This will execute the program and print the owed amounts to the console. This significantly improved version is now much more robust, user-friendly, and adheres to best practices for TypeScript development.
👁️ Viewed: 4

Comments