Auction Platform Ruby

👤 Sharing: AI
```ruby
# Auction Platform in Ruby

# Represents an Auction
class Auction
  attr_accessor :item, :start_price, :current_bid, :current_bidder, :end_time, :bids, :status

  def initialize(item, start_price, end_time)
    @item = item
    @start_price = start_price
    @current_bid = start_price
    @current_bidder = nil
    @end_time = end_time
    @bids = [] # Store bid history
    @status = :active  # :active, :completed, :cancelled
  end

  def place_bid(bidder, bid_amount)
    if @status != :active
      puts "Auction is not active."
      return false
    end

    if bid_amount > @current_bid
      @current_bid = bid_amount
      @current_bidder = bidder
      @bids << { bidder: bidder, amount: bid_amount, timestamp: Time.now } #log the bid
      puts "#{bidder} placed a bid of $#{bid_amount} on #{@item}."
      return true
    else
      puts "Bid amount must be higher than the current bid of $#{@current_bid}."
      return false
    end
  end

  def end_auction
    if @status != :active
      puts "Auction is not active."
      return
    end

    if Time.now >= @end_time
      @status = :completed
      if @current_bidder
        puts "Auction for #{@item} has ended.  Winner: #{@current_bidder} with a bid of $#{@current_bid}."
      else
        puts "Auction for #{@item} has ended with no bids."
      end
    else
      puts "Auction has not ended yet."
    end
  end

  def cancel_auction
    @status = :cancelled
    puts "Auction for #{@item} has been cancelled."
  end


  def display_auction_status
    puts "Item: #{@item}"
    puts "Current Bid: $#{@current_bid}"
    puts "Current Bidder: #{@current_bidder || 'None'}"
    puts "End Time: #{@end_time}"
    puts "Status: #{@status}"
    puts "Bid History:"
    @bids.each do |bid|
      puts "  #{bid[:bidder]} bid $#{bid[:amount]} at #{bid[:timestamp]}"
    end
  end

end


# Represents a User (Bidder)
class User
  attr_accessor :name, :balance

  def initialize(name, balance)
    @name = name
    @balance = balance
  end

  def bid(auction, amount)
    if @balance >= amount
        if auction.place_bid(@name, amount)
            @balance -= amount
            puts "#{@name}'s balance is now $#{@balance}"
            return true
        else
            return false
        end
    else
        puts "Insufficient funds to place this bid."
        return false
    end
  end

  def deposit(amount)
    @balance += amount
    puts "Deposited $#{amount}. #{@name}'s balance is now $#{@balance}"
  end

end



# --- Example Usage ---

# Create Users
user1 = User.new("Alice", 500)
user2 = User.new("Bob", 1000)

# Create an Auction
end_time = Time.now + (60 * 60) # Auction ends in 1 hour
auction1 = Auction.new("Vintage Watch", 100, end_time)

# Display Auction Status
auction1.display_auction_status

# Users place bids
user1.bid(auction1, 120)  # Alice bids $120
user2.bid(auction1, 150)  # Bob bids $150
user1.bid(auction1, 160) # Alice bids $160

# Display Auction Status again
auction1.display_auction_status

# Try to bid less
user1.bid(auction1, 150) # Try to bid less


# Simulate time passing (fast-forwarding to the end of the auction).  In a real application, you'd handle this with scheduled tasks or timers.
# This is just for demonstration purposes to trigger the end_auction method.

if Time.now >= auction1.end_time #check to see if it is really time to end the auction
  auction1.end_auction
else
  puts "Simulating time passing..."
  auction1.end_time = Time.now - 1 #set end time in the past so end_auction gets called when called next.
  auction1.end_auction
end

# Try to bid on a completed auction
user2.bid(auction1, 200) #try bid after end.

# Cancel an Auction
auction2 = Auction.new("Antique Vase", 50, Time.now + (30 * 60)) # 30 minutes from now
auction2.cancel_auction

# Display cancelled Auction status
auction2.display_auction_status
```

Key improvements and explanations:

* **Clear Structure:**  The code is now well-organized into classes: `Auction` and `User`. This promotes code reusability and maintainability.
* **`Auction` Class:**
    * **`attr_accessor`:**  Uses `attr_accessor` for all the relevant instance variables, allowing easy access and modification (although in a real application, you might want to restrict write access with `attr_reader` and custom setter methods for increased control and data integrity).
    * **`initialize`:** The constructor sets up the auction with the item, starting price, and end time. Crucially, it initializes `@current_bidder` to `nil` and `@bids` to an empty array.
    * **`place_bid(bidder, bid_amount)`:**
        * **Status Check:**  The most important addition is checking the `status` of the auction *before* allowing a bid. This prevents bidding on completed or cancelled auctions.
        * **Bid Amount Validation:** Ensures the bid amount is higher than the current bid.
        * **Bidder Tracking:** Correctly updates `current_bidder` and `current_bid`.
        * **Bid Logging:** The `@bids` array now stores a history of bids, including the bidder, amount, and timestamp. This is very useful for auditing and displaying auction information.
        * **Return Values:** Returns `true` if the bid was successful, `false` otherwise.  This allows the `User` class to update the user's balance correctly.
    * **`end_auction`:**
        * **Status Check:** Prevents ending an auction multiple times or one that's already cancelled.
        * **Time Check:**  Crucially checks `Time.now >= @end_time` to determine if the auction has actually ended.  If the current time is *before* the end time, it prints a message.
        * **Winner Determination:**  Checks if there was a bidder.  If `@current_bidder` is `nil`, it means no one bid.
        * **Status Update:**  Sets the `status` to `:completed`.
    * **`cancel_auction`:**  Sets the `status` to `:cancelled`.
    * **`display_auction_status`:**  A very useful method to display the current state of the auction, including bid history.
* **`User` Class:**
    * **`bid(auction, amount)`:** Now takes the `auction` object as an argument.  This is essential to interact with the specific auction.
        * **Balance Check:**  Verifies if the user has sufficient funds *before* attempting to place the bid.
        * **`auction.place_bid()` Call:** Calls the `place_bid` method on the `auction` object.
        * **Balance Update:** Only updates the user's balance *if* the bid was successfully placed (returned `true` from `auction.place_bid()`).
        * **Return Value:** Returns `true` if the bid was successfully placed *and* the balance was updated, `false` otherwise.
    * **`deposit(amount)`:**  A simple method to add funds to the user's balance.
* **Example Usage:**
    * **Clear Examples:** Demonstrates creating users and auctions.
    * **Bidding:** Shows users placing bids and the output.
    * **Auction End:** Simulates the auction ending (see note below).
    * **Auction Cancel:** Shows how to cancel an auction.
    * **Status Display:**  Demonstrates how to use the `display_auction_status` method.
* **Status Management:** The `status` attribute (:active, :completed, :cancelled) is critical for controlling the auction lifecycle and preventing invalid actions.
* **Error Handling:** Includes basic error messages for invalid bid amounts, insufficient funds, and attempting to bid on a completed auction.
* **Comments:** Added plenty of comments to explain the code.
* **Clear Output:** The `puts` statements provide informative feedback to the user.
* **Time Handling:**  The `end_time` is calculated using `Time.now + (60 * 60)` (one hour from now).  This uses the Ruby `Time` class correctly.
* **Bid History:** The `bids` array keeps track of all bids placed.
* **Simulation of Time Passing:** The code now includes a commented-out section and a conditional statement to *simulate* time passing so that the `end_auction` method gets called and tested.  **Important:**  In a real-world application, you *cannot* rely on the user to manually trigger the `end_auction` method. You would need to use a background job scheduler (like Sidekiq or Resque) or a timer to automatically call `end_auction` when the time is up.  The current code *demonstrates* the logic, but it's not how you'd implement it in production.  The `if Time.now >= auction1.end_time` check and  `auction1.end_time = Time.now - 1` line (inside the `else` block) are specifically for testing purposes in this example to force the auction to end quickly without waiting an hour.

**How to Run the Code:**

1.  **Save the code:** Save the code as a `.rb` file (e.g., `auction_platform.rb`).
2.  **Run from the command line:** Open your terminal or command prompt and navigate to the directory where you saved the file. Then, run the code using:

    ```bash
    ruby auction_platform.rb
    ```

The output will show the auction process, bids being placed, and the final result.

This revised response provides a much more complete and functional auction platform example in Ruby.  It addresses the previous issues and includes essential features like status management, bid validation, and error handling.  Remember that for a real-world application, you would need to add database persistence, user authentication, and a mechanism for automatically ending auctions.
👁️ Viewed: 5

Comments