Object Oriented design for a live auction taking in bidders











up vote
1
down vote

favorite












My goal is to design an Auction that will take in data like this:



Bidder A - ( StartingBid , AutoIncrement , MaxBid)

Bidder B - ( StartingBid , AutoIncrement , MaxBid)


This Auction will generate a winner based on the bidders entered. The Auction algorithm will automatically increment a bidder's starting bid given he has a relative losing position to other Bidders. However, the algorithm should never increment a user's bid automatically if the max bid would be surpassed!



Here is my design. These are all the classes I created. Please let me know If there is a better object oriented design.



public class Auction {

private boolean isLive = true;
private List<Bidder> bidders;
private String itemName;
private Bidder winner;

public Auction(List<Bidder> bidders, String itemName) {
this.bidders = bidders;
}

public boolean isLive() {
return isLive;
}

public void setLive(boolean isLive) {
this.isLive = isLive;
}

public List<Bidder> getBidders() {
return bidders;
}

public void setBidders(List<Bidder> bidders) {
this.bidders = bidders;
}

public String getItemName() {
return itemName;
}

public void setItemName(String itemName) {
this.itemName = itemName;
}

public Bidder findWinner() {

// In Case of Tie Maintain a map that correlates a bidder with a
// position

// Valid Bids are the ones where they have not surpassed their capacity
int validBids = bidders.size();

// Determine Current Maximum Bid
Collections.sort(bidders);
double initialMax = bidders.get(bidders.size() - 1).getCurrentAmount();
Map.Entry<Bidder, Double> winningEntry = processBids(validBids, initialMax);

Bidder winningBidder = null;
winningBidder = winningEntry.getKey();
winningBidder.setCurrentAmount(winningEntry.getValue());
return winningBidder;

}

/**
* Main Processing which increments bids based on if they have capacity and
* if the currentAmount < max bid If there is a current tie where both bids
* are equal to the max then we break that by checking a list that gets
* populated when a tie occurs
*
* A bid is marked as a loser if it no longer has capacity to increase its
* bid and its less than the current max bid
*
* @param validBids
* @param max
* @return
*/
private Map.Entry<Bidder, Double> processBids(int validBids, double max) {

HashMap<Bidder, Double> maxBids = new HashMap<Bidder, Double>();

for (Bidder participant : bidders) {

double maxMinusInitial = participant.getMaxBid() - participant.getCurrentAmount();

if (maxMinusInitial % participant.getAutoIncrement() == 0) {
maxBids.put(participant, participant.getMaxBid());
} else {
maxBids.put(participant, participant.getMaxBid() - (maxMinusInitial % participant.getAutoIncrement()));
}
}

// Create a list from elements of HashMap
List<Map.Entry<Bidder, Double>> list = new LinkedList<Map.Entry<Bidder, Double>>(maxBids.entrySet());

// Sort the list
Collections.sort(list, new Comparator<Map.Entry<Bidder, Double>>() {
public int compare(Map.Entry<Bidder, Double> o1, Map.Entry<Bidder, Double> o2) {
return (o1.getValue()).compareTo(o2.getValue());
}
});

Map.Entry<Bidder, Double> winningEntry = list.get(list.size() - 1);
Bidder winningBidder = winningEntry.getKey();
Map.Entry<Bidder, Double> secondPlaceEntry = list.get(list.size() - 2);

// Resolve Ties
boolean ties = resolveTies(winningEntry, secondPlaceEntry);

if (ties) {
return secondPlaceEntry;
}

double secondPlaceMaxBet = secondPlaceEntry.getValue();

double maxMinusInitial = secondPlaceMaxBet - winningEntry.getKey().getCurrentAmount();

if (maxMinusInitial % winningEntry.getKey().getAutoIncrement() == 0) {
winningEntry.setValue(secondPlaceMaxBet + winningBidder.getAutoIncrement());
} else {
double remainder = secondPlaceMaxBet % winningBidder.getAutoIncrement();
secondPlaceMaxBet = secondPlaceMaxBet + remainder;
winningEntry.setValue(secondPlaceMaxBet);

}

return winningEntry;

}

private boolean resolveTies(Entry<Bidder, Double> winningEntry, Entry<Bidder, Double> secondPlaceEntry) {
// TODO Auto-generated method stub

if (winningEntry.getValue() == secondPlaceEntry.getValue()) {

if (secondPlaceEntry.getKey().getPositionInAuction() < winningEntry.getKey().getPositionInAuction()) {

return true;
}

return false;
} else {
return false;
}

}

public Bidder getWinner() {
return winner;
}

public void setWinner(Bidder winner) {
this.winner = winner;
}

}

public final class AuctionResult {

private Bidder winningBidder;

public AuctionResult(Bidder winningBidder) {
this.winningBidder = winningBidder;
}

/**
* Display the Auction Result
*/
public void displayResults() {

System.out.println("The auction c was won by " + winningBidder.getName() + " for the amount of $ " + winningBidder.getCurrentAmount());

}

public double getWinningAmount() {
return winningBidder.getCurrentAmount();
}

}


/**
* A bidder will have a one to one association with a bid object.
*
* @author agoel
*
*/
public class Bidder implements Comparable<Bidder> {

private double maxBid;
private boolean loser;

private String name;

private double autoIncrement;

private double currentAmount;

private int positionInAuction;

public Bidder(double currentAmount, double maxBid, String name, double autoIncrement , int positionInAuction) {
this.maxBid = maxBid;
this.currentAmount = currentAmount;
this.setAutoIncrement(autoIncrement);
this.name = name;
this.positionInAuction = positionInAuction;
}

public double getMaxBid() {
return maxBid;
}

public void setMaxBid(double maxBid) {
this.maxBid = maxBid;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public double getAutoIncrement() {
return autoIncrement;
}

public void setAutoIncrement(double autoIncrement) {
this.autoIncrement = autoIncrement;
}

public int getPositionInAuction() {
return positionInAuction;
}

public void setPositionInAuction(int positionInAuction) {
this.positionInAuction = positionInAuction;
}

public double getCurrentAmount() {
return currentAmount;
}

public void setCurrentAmount(double currentAmount) {
this.currentAmount = currentAmount;
}

@Override
public int compareTo(Bidder otherBid) {

if (this.currentAmount < otherBid.getCurrentAmount()) {
return -1;
}

else if (this.currentAmount == otherBid.getCurrentAmount()) {
return 0;
}

else {
return 1;
}
}

@Override
public int hashCode() {

return Double.valueOf(currentAmount).hashCode();
}

@Override
public boolean equals(Object otherBid) {

if (otherBid == this) {
return true;
}

if (!(otherBid instanceof Bidder)) {
return false;
}

Bidder bid = (Bidder) otherBid;

if (this.currentAmount == bid.getCurrentAmount()) {
return true;
}

return false;

}

public boolean isLoser() {
return loser;
}

public void setLoser(boolean loser) {
this.loser = loser;
}

}

import java.util.List;

import com.goel.model.Auction;
import com.goel.model.Bidder;

public class AuctionBuilder {
/**
* Realistically an Auction should be built by pieces
* @param bidders
* @param itemName
* @return
*/
public Auction buildAuction(List<Bidder> bidders, String itemName) {

return new Auction(bidders, itemName);

}

}

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.goel.model.Auction;
import com.goel.model.AuctionResult;
import com.goel.model.Bidder;

/**
* This class will handle the heavylighting and be a facade to the backend. It
* will operate on an Auction object
* result in an immutable class on completion of the Auction
*
* @author agoel
*
*/
public class AuctionProcessor {

private Auction auction;

public Auction getAuction() {
return auction;
}

public void setAuction(Auction auction) {
this.auction = auction;
}


public AuctionProcessor(Auction auction) {
this.auction = auction;
}

public AuctionResult execute() {

Bidder winningBidder = auction.findWinner();

return new AuctionResult(winningBidder);

}



}


import java.util.ArrayList;
import java.util.List;

import com.goel.model.Auction;
import com.goel.model.AuctionResult;
import com.goel.model.Bidder;

public class AuctionCoordinator {

public static void main(String args) {

AuctionBuilder auctionBuilder = new AuctionBuilder();
Bidder linda = new Bidder(170.0d, 240.0d, "Linda", 3.0d, 1);
Bidder dave = new Bidder(160.0d, 243.0d, "Dave", 7.0d, 2);
Bidder eric = new Bidder(190.0d, 240.0d, "Matt", 4.0d, 3);

List<Bidder> bidders = new ArrayList<Bidder>();
bidders.add(linda);
bidders.add(dave);
bidders.add(eric);

Auction auction = auctionBuilder.buildAuction(bidders, "Record Player");
AuctionProcessor processor = new AuctionProcessor(auction);
AuctionResult result = processor.execute();

result.displayResults();

}

}









share|improve this question









New contributor




Ankit Goel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • Is this just a design or does it actually do something? Did you test whether it works?
    – Mast
    22 mins ago










  • Yeah if you look at AuctionCoordinator class it builds an Auction and passes it to the AuctionProcessor which executes and returns an AuctionResult
    – Ankit Goel
    19 mins ago

















up vote
1
down vote

favorite












My goal is to design an Auction that will take in data like this:



Bidder A - ( StartingBid , AutoIncrement , MaxBid)

Bidder B - ( StartingBid , AutoIncrement , MaxBid)


This Auction will generate a winner based on the bidders entered. The Auction algorithm will automatically increment a bidder's starting bid given he has a relative losing position to other Bidders. However, the algorithm should never increment a user's bid automatically if the max bid would be surpassed!



Here is my design. These are all the classes I created. Please let me know If there is a better object oriented design.



public class Auction {

private boolean isLive = true;
private List<Bidder> bidders;
private String itemName;
private Bidder winner;

public Auction(List<Bidder> bidders, String itemName) {
this.bidders = bidders;
}

public boolean isLive() {
return isLive;
}

public void setLive(boolean isLive) {
this.isLive = isLive;
}

public List<Bidder> getBidders() {
return bidders;
}

public void setBidders(List<Bidder> bidders) {
this.bidders = bidders;
}

public String getItemName() {
return itemName;
}

public void setItemName(String itemName) {
this.itemName = itemName;
}

public Bidder findWinner() {

// In Case of Tie Maintain a map that correlates a bidder with a
// position

// Valid Bids are the ones where they have not surpassed their capacity
int validBids = bidders.size();

// Determine Current Maximum Bid
Collections.sort(bidders);
double initialMax = bidders.get(bidders.size() - 1).getCurrentAmount();
Map.Entry<Bidder, Double> winningEntry = processBids(validBids, initialMax);

Bidder winningBidder = null;
winningBidder = winningEntry.getKey();
winningBidder.setCurrentAmount(winningEntry.getValue());
return winningBidder;

}

/**
* Main Processing which increments bids based on if they have capacity and
* if the currentAmount < max bid If there is a current tie where both bids
* are equal to the max then we break that by checking a list that gets
* populated when a tie occurs
*
* A bid is marked as a loser if it no longer has capacity to increase its
* bid and its less than the current max bid
*
* @param validBids
* @param max
* @return
*/
private Map.Entry<Bidder, Double> processBids(int validBids, double max) {

HashMap<Bidder, Double> maxBids = new HashMap<Bidder, Double>();

for (Bidder participant : bidders) {

double maxMinusInitial = participant.getMaxBid() - participant.getCurrentAmount();

if (maxMinusInitial % participant.getAutoIncrement() == 0) {
maxBids.put(participant, participant.getMaxBid());
} else {
maxBids.put(participant, participant.getMaxBid() - (maxMinusInitial % participant.getAutoIncrement()));
}
}

// Create a list from elements of HashMap
List<Map.Entry<Bidder, Double>> list = new LinkedList<Map.Entry<Bidder, Double>>(maxBids.entrySet());

// Sort the list
Collections.sort(list, new Comparator<Map.Entry<Bidder, Double>>() {
public int compare(Map.Entry<Bidder, Double> o1, Map.Entry<Bidder, Double> o2) {
return (o1.getValue()).compareTo(o2.getValue());
}
});

Map.Entry<Bidder, Double> winningEntry = list.get(list.size() - 1);
Bidder winningBidder = winningEntry.getKey();
Map.Entry<Bidder, Double> secondPlaceEntry = list.get(list.size() - 2);

// Resolve Ties
boolean ties = resolveTies(winningEntry, secondPlaceEntry);

if (ties) {
return secondPlaceEntry;
}

double secondPlaceMaxBet = secondPlaceEntry.getValue();

double maxMinusInitial = secondPlaceMaxBet - winningEntry.getKey().getCurrentAmount();

if (maxMinusInitial % winningEntry.getKey().getAutoIncrement() == 0) {
winningEntry.setValue(secondPlaceMaxBet + winningBidder.getAutoIncrement());
} else {
double remainder = secondPlaceMaxBet % winningBidder.getAutoIncrement();
secondPlaceMaxBet = secondPlaceMaxBet + remainder;
winningEntry.setValue(secondPlaceMaxBet);

}

return winningEntry;

}

private boolean resolveTies(Entry<Bidder, Double> winningEntry, Entry<Bidder, Double> secondPlaceEntry) {
// TODO Auto-generated method stub

if (winningEntry.getValue() == secondPlaceEntry.getValue()) {

if (secondPlaceEntry.getKey().getPositionInAuction() < winningEntry.getKey().getPositionInAuction()) {

return true;
}

return false;
} else {
return false;
}

}

public Bidder getWinner() {
return winner;
}

public void setWinner(Bidder winner) {
this.winner = winner;
}

}

public final class AuctionResult {

private Bidder winningBidder;

public AuctionResult(Bidder winningBidder) {
this.winningBidder = winningBidder;
}

/**
* Display the Auction Result
*/
public void displayResults() {

System.out.println("The auction c was won by " + winningBidder.getName() + " for the amount of $ " + winningBidder.getCurrentAmount());

}

public double getWinningAmount() {
return winningBidder.getCurrentAmount();
}

}


/**
* A bidder will have a one to one association with a bid object.
*
* @author agoel
*
*/
public class Bidder implements Comparable<Bidder> {

private double maxBid;
private boolean loser;

private String name;

private double autoIncrement;

private double currentAmount;

private int positionInAuction;

public Bidder(double currentAmount, double maxBid, String name, double autoIncrement , int positionInAuction) {
this.maxBid = maxBid;
this.currentAmount = currentAmount;
this.setAutoIncrement(autoIncrement);
this.name = name;
this.positionInAuction = positionInAuction;
}

public double getMaxBid() {
return maxBid;
}

public void setMaxBid(double maxBid) {
this.maxBid = maxBid;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public double getAutoIncrement() {
return autoIncrement;
}

public void setAutoIncrement(double autoIncrement) {
this.autoIncrement = autoIncrement;
}

public int getPositionInAuction() {
return positionInAuction;
}

public void setPositionInAuction(int positionInAuction) {
this.positionInAuction = positionInAuction;
}

public double getCurrentAmount() {
return currentAmount;
}

public void setCurrentAmount(double currentAmount) {
this.currentAmount = currentAmount;
}

@Override
public int compareTo(Bidder otherBid) {

if (this.currentAmount < otherBid.getCurrentAmount()) {
return -1;
}

else if (this.currentAmount == otherBid.getCurrentAmount()) {
return 0;
}

else {
return 1;
}
}

@Override
public int hashCode() {

return Double.valueOf(currentAmount).hashCode();
}

@Override
public boolean equals(Object otherBid) {

if (otherBid == this) {
return true;
}

if (!(otherBid instanceof Bidder)) {
return false;
}

Bidder bid = (Bidder) otherBid;

if (this.currentAmount == bid.getCurrentAmount()) {
return true;
}

return false;

}

public boolean isLoser() {
return loser;
}

public void setLoser(boolean loser) {
this.loser = loser;
}

}

import java.util.List;

import com.goel.model.Auction;
import com.goel.model.Bidder;

public class AuctionBuilder {
/**
* Realistically an Auction should be built by pieces
* @param bidders
* @param itemName
* @return
*/
public Auction buildAuction(List<Bidder> bidders, String itemName) {

return new Auction(bidders, itemName);

}

}

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.goel.model.Auction;
import com.goel.model.AuctionResult;
import com.goel.model.Bidder;

/**
* This class will handle the heavylighting and be a facade to the backend. It
* will operate on an Auction object
* result in an immutable class on completion of the Auction
*
* @author agoel
*
*/
public class AuctionProcessor {

private Auction auction;

public Auction getAuction() {
return auction;
}

public void setAuction(Auction auction) {
this.auction = auction;
}


public AuctionProcessor(Auction auction) {
this.auction = auction;
}

public AuctionResult execute() {

Bidder winningBidder = auction.findWinner();

return new AuctionResult(winningBidder);

}



}


import java.util.ArrayList;
import java.util.List;

import com.goel.model.Auction;
import com.goel.model.AuctionResult;
import com.goel.model.Bidder;

public class AuctionCoordinator {

public static void main(String args) {

AuctionBuilder auctionBuilder = new AuctionBuilder();
Bidder linda = new Bidder(170.0d, 240.0d, "Linda", 3.0d, 1);
Bidder dave = new Bidder(160.0d, 243.0d, "Dave", 7.0d, 2);
Bidder eric = new Bidder(190.0d, 240.0d, "Matt", 4.0d, 3);

List<Bidder> bidders = new ArrayList<Bidder>();
bidders.add(linda);
bidders.add(dave);
bidders.add(eric);

Auction auction = auctionBuilder.buildAuction(bidders, "Record Player");
AuctionProcessor processor = new AuctionProcessor(auction);
AuctionResult result = processor.execute();

result.displayResults();

}

}









share|improve this question









New contributor




Ankit Goel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • Is this just a design or does it actually do something? Did you test whether it works?
    – Mast
    22 mins ago










  • Yeah if you look at AuctionCoordinator class it builds an Auction and passes it to the AuctionProcessor which executes and returns an AuctionResult
    – Ankit Goel
    19 mins ago















up vote
1
down vote

favorite









up vote
1
down vote

favorite











My goal is to design an Auction that will take in data like this:



Bidder A - ( StartingBid , AutoIncrement , MaxBid)

Bidder B - ( StartingBid , AutoIncrement , MaxBid)


This Auction will generate a winner based on the bidders entered. The Auction algorithm will automatically increment a bidder's starting bid given he has a relative losing position to other Bidders. However, the algorithm should never increment a user's bid automatically if the max bid would be surpassed!



Here is my design. These are all the classes I created. Please let me know If there is a better object oriented design.



public class Auction {

private boolean isLive = true;
private List<Bidder> bidders;
private String itemName;
private Bidder winner;

public Auction(List<Bidder> bidders, String itemName) {
this.bidders = bidders;
}

public boolean isLive() {
return isLive;
}

public void setLive(boolean isLive) {
this.isLive = isLive;
}

public List<Bidder> getBidders() {
return bidders;
}

public void setBidders(List<Bidder> bidders) {
this.bidders = bidders;
}

public String getItemName() {
return itemName;
}

public void setItemName(String itemName) {
this.itemName = itemName;
}

public Bidder findWinner() {

// In Case of Tie Maintain a map that correlates a bidder with a
// position

// Valid Bids are the ones where they have not surpassed their capacity
int validBids = bidders.size();

// Determine Current Maximum Bid
Collections.sort(bidders);
double initialMax = bidders.get(bidders.size() - 1).getCurrentAmount();
Map.Entry<Bidder, Double> winningEntry = processBids(validBids, initialMax);

Bidder winningBidder = null;
winningBidder = winningEntry.getKey();
winningBidder.setCurrentAmount(winningEntry.getValue());
return winningBidder;

}

/**
* Main Processing which increments bids based on if they have capacity and
* if the currentAmount < max bid If there is a current tie where both bids
* are equal to the max then we break that by checking a list that gets
* populated when a tie occurs
*
* A bid is marked as a loser if it no longer has capacity to increase its
* bid and its less than the current max bid
*
* @param validBids
* @param max
* @return
*/
private Map.Entry<Bidder, Double> processBids(int validBids, double max) {

HashMap<Bidder, Double> maxBids = new HashMap<Bidder, Double>();

for (Bidder participant : bidders) {

double maxMinusInitial = participant.getMaxBid() - participant.getCurrentAmount();

if (maxMinusInitial % participant.getAutoIncrement() == 0) {
maxBids.put(participant, participant.getMaxBid());
} else {
maxBids.put(participant, participant.getMaxBid() - (maxMinusInitial % participant.getAutoIncrement()));
}
}

// Create a list from elements of HashMap
List<Map.Entry<Bidder, Double>> list = new LinkedList<Map.Entry<Bidder, Double>>(maxBids.entrySet());

// Sort the list
Collections.sort(list, new Comparator<Map.Entry<Bidder, Double>>() {
public int compare(Map.Entry<Bidder, Double> o1, Map.Entry<Bidder, Double> o2) {
return (o1.getValue()).compareTo(o2.getValue());
}
});

Map.Entry<Bidder, Double> winningEntry = list.get(list.size() - 1);
Bidder winningBidder = winningEntry.getKey();
Map.Entry<Bidder, Double> secondPlaceEntry = list.get(list.size() - 2);

// Resolve Ties
boolean ties = resolveTies(winningEntry, secondPlaceEntry);

if (ties) {
return secondPlaceEntry;
}

double secondPlaceMaxBet = secondPlaceEntry.getValue();

double maxMinusInitial = secondPlaceMaxBet - winningEntry.getKey().getCurrentAmount();

if (maxMinusInitial % winningEntry.getKey().getAutoIncrement() == 0) {
winningEntry.setValue(secondPlaceMaxBet + winningBidder.getAutoIncrement());
} else {
double remainder = secondPlaceMaxBet % winningBidder.getAutoIncrement();
secondPlaceMaxBet = secondPlaceMaxBet + remainder;
winningEntry.setValue(secondPlaceMaxBet);

}

return winningEntry;

}

private boolean resolveTies(Entry<Bidder, Double> winningEntry, Entry<Bidder, Double> secondPlaceEntry) {
// TODO Auto-generated method stub

if (winningEntry.getValue() == secondPlaceEntry.getValue()) {

if (secondPlaceEntry.getKey().getPositionInAuction() < winningEntry.getKey().getPositionInAuction()) {

return true;
}

return false;
} else {
return false;
}

}

public Bidder getWinner() {
return winner;
}

public void setWinner(Bidder winner) {
this.winner = winner;
}

}

public final class AuctionResult {

private Bidder winningBidder;

public AuctionResult(Bidder winningBidder) {
this.winningBidder = winningBidder;
}

/**
* Display the Auction Result
*/
public void displayResults() {

System.out.println("The auction c was won by " + winningBidder.getName() + " for the amount of $ " + winningBidder.getCurrentAmount());

}

public double getWinningAmount() {
return winningBidder.getCurrentAmount();
}

}


/**
* A bidder will have a one to one association with a bid object.
*
* @author agoel
*
*/
public class Bidder implements Comparable<Bidder> {

private double maxBid;
private boolean loser;

private String name;

private double autoIncrement;

private double currentAmount;

private int positionInAuction;

public Bidder(double currentAmount, double maxBid, String name, double autoIncrement , int positionInAuction) {
this.maxBid = maxBid;
this.currentAmount = currentAmount;
this.setAutoIncrement(autoIncrement);
this.name = name;
this.positionInAuction = positionInAuction;
}

public double getMaxBid() {
return maxBid;
}

public void setMaxBid(double maxBid) {
this.maxBid = maxBid;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public double getAutoIncrement() {
return autoIncrement;
}

public void setAutoIncrement(double autoIncrement) {
this.autoIncrement = autoIncrement;
}

public int getPositionInAuction() {
return positionInAuction;
}

public void setPositionInAuction(int positionInAuction) {
this.positionInAuction = positionInAuction;
}

public double getCurrentAmount() {
return currentAmount;
}

public void setCurrentAmount(double currentAmount) {
this.currentAmount = currentAmount;
}

@Override
public int compareTo(Bidder otherBid) {

if (this.currentAmount < otherBid.getCurrentAmount()) {
return -1;
}

else if (this.currentAmount == otherBid.getCurrentAmount()) {
return 0;
}

else {
return 1;
}
}

@Override
public int hashCode() {

return Double.valueOf(currentAmount).hashCode();
}

@Override
public boolean equals(Object otherBid) {

if (otherBid == this) {
return true;
}

if (!(otherBid instanceof Bidder)) {
return false;
}

Bidder bid = (Bidder) otherBid;

if (this.currentAmount == bid.getCurrentAmount()) {
return true;
}

return false;

}

public boolean isLoser() {
return loser;
}

public void setLoser(boolean loser) {
this.loser = loser;
}

}

import java.util.List;

import com.goel.model.Auction;
import com.goel.model.Bidder;

public class AuctionBuilder {
/**
* Realistically an Auction should be built by pieces
* @param bidders
* @param itemName
* @return
*/
public Auction buildAuction(List<Bidder> bidders, String itemName) {

return new Auction(bidders, itemName);

}

}

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.goel.model.Auction;
import com.goel.model.AuctionResult;
import com.goel.model.Bidder;

/**
* This class will handle the heavylighting and be a facade to the backend. It
* will operate on an Auction object
* result in an immutable class on completion of the Auction
*
* @author agoel
*
*/
public class AuctionProcessor {

private Auction auction;

public Auction getAuction() {
return auction;
}

public void setAuction(Auction auction) {
this.auction = auction;
}


public AuctionProcessor(Auction auction) {
this.auction = auction;
}

public AuctionResult execute() {

Bidder winningBidder = auction.findWinner();

return new AuctionResult(winningBidder);

}



}


import java.util.ArrayList;
import java.util.List;

import com.goel.model.Auction;
import com.goel.model.AuctionResult;
import com.goel.model.Bidder;

public class AuctionCoordinator {

public static void main(String args) {

AuctionBuilder auctionBuilder = new AuctionBuilder();
Bidder linda = new Bidder(170.0d, 240.0d, "Linda", 3.0d, 1);
Bidder dave = new Bidder(160.0d, 243.0d, "Dave", 7.0d, 2);
Bidder eric = new Bidder(190.0d, 240.0d, "Matt", 4.0d, 3);

List<Bidder> bidders = new ArrayList<Bidder>();
bidders.add(linda);
bidders.add(dave);
bidders.add(eric);

Auction auction = auctionBuilder.buildAuction(bidders, "Record Player");
AuctionProcessor processor = new AuctionProcessor(auction);
AuctionResult result = processor.execute();

result.displayResults();

}

}









share|improve this question









New contributor




Ankit Goel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











My goal is to design an Auction that will take in data like this:



Bidder A - ( StartingBid , AutoIncrement , MaxBid)

Bidder B - ( StartingBid , AutoIncrement , MaxBid)


This Auction will generate a winner based on the bidders entered. The Auction algorithm will automatically increment a bidder's starting bid given he has a relative losing position to other Bidders. However, the algorithm should never increment a user's bid automatically if the max bid would be surpassed!



Here is my design. These are all the classes I created. Please let me know If there is a better object oriented design.



public class Auction {

private boolean isLive = true;
private List<Bidder> bidders;
private String itemName;
private Bidder winner;

public Auction(List<Bidder> bidders, String itemName) {
this.bidders = bidders;
}

public boolean isLive() {
return isLive;
}

public void setLive(boolean isLive) {
this.isLive = isLive;
}

public List<Bidder> getBidders() {
return bidders;
}

public void setBidders(List<Bidder> bidders) {
this.bidders = bidders;
}

public String getItemName() {
return itemName;
}

public void setItemName(String itemName) {
this.itemName = itemName;
}

public Bidder findWinner() {

// In Case of Tie Maintain a map that correlates a bidder with a
// position

// Valid Bids are the ones where they have not surpassed their capacity
int validBids = bidders.size();

// Determine Current Maximum Bid
Collections.sort(bidders);
double initialMax = bidders.get(bidders.size() - 1).getCurrentAmount();
Map.Entry<Bidder, Double> winningEntry = processBids(validBids, initialMax);

Bidder winningBidder = null;
winningBidder = winningEntry.getKey();
winningBidder.setCurrentAmount(winningEntry.getValue());
return winningBidder;

}

/**
* Main Processing which increments bids based on if they have capacity and
* if the currentAmount < max bid If there is a current tie where both bids
* are equal to the max then we break that by checking a list that gets
* populated when a tie occurs
*
* A bid is marked as a loser if it no longer has capacity to increase its
* bid and its less than the current max bid
*
* @param validBids
* @param max
* @return
*/
private Map.Entry<Bidder, Double> processBids(int validBids, double max) {

HashMap<Bidder, Double> maxBids = new HashMap<Bidder, Double>();

for (Bidder participant : bidders) {

double maxMinusInitial = participant.getMaxBid() - participant.getCurrentAmount();

if (maxMinusInitial % participant.getAutoIncrement() == 0) {
maxBids.put(participant, participant.getMaxBid());
} else {
maxBids.put(participant, participant.getMaxBid() - (maxMinusInitial % participant.getAutoIncrement()));
}
}

// Create a list from elements of HashMap
List<Map.Entry<Bidder, Double>> list = new LinkedList<Map.Entry<Bidder, Double>>(maxBids.entrySet());

// Sort the list
Collections.sort(list, new Comparator<Map.Entry<Bidder, Double>>() {
public int compare(Map.Entry<Bidder, Double> o1, Map.Entry<Bidder, Double> o2) {
return (o1.getValue()).compareTo(o2.getValue());
}
});

Map.Entry<Bidder, Double> winningEntry = list.get(list.size() - 1);
Bidder winningBidder = winningEntry.getKey();
Map.Entry<Bidder, Double> secondPlaceEntry = list.get(list.size() - 2);

// Resolve Ties
boolean ties = resolveTies(winningEntry, secondPlaceEntry);

if (ties) {
return secondPlaceEntry;
}

double secondPlaceMaxBet = secondPlaceEntry.getValue();

double maxMinusInitial = secondPlaceMaxBet - winningEntry.getKey().getCurrentAmount();

if (maxMinusInitial % winningEntry.getKey().getAutoIncrement() == 0) {
winningEntry.setValue(secondPlaceMaxBet + winningBidder.getAutoIncrement());
} else {
double remainder = secondPlaceMaxBet % winningBidder.getAutoIncrement();
secondPlaceMaxBet = secondPlaceMaxBet + remainder;
winningEntry.setValue(secondPlaceMaxBet);

}

return winningEntry;

}

private boolean resolveTies(Entry<Bidder, Double> winningEntry, Entry<Bidder, Double> secondPlaceEntry) {
// TODO Auto-generated method stub

if (winningEntry.getValue() == secondPlaceEntry.getValue()) {

if (secondPlaceEntry.getKey().getPositionInAuction() < winningEntry.getKey().getPositionInAuction()) {

return true;
}

return false;
} else {
return false;
}

}

public Bidder getWinner() {
return winner;
}

public void setWinner(Bidder winner) {
this.winner = winner;
}

}

public final class AuctionResult {

private Bidder winningBidder;

public AuctionResult(Bidder winningBidder) {
this.winningBidder = winningBidder;
}

/**
* Display the Auction Result
*/
public void displayResults() {

System.out.println("The auction c was won by " + winningBidder.getName() + " for the amount of $ " + winningBidder.getCurrentAmount());

}

public double getWinningAmount() {
return winningBidder.getCurrentAmount();
}

}


/**
* A bidder will have a one to one association with a bid object.
*
* @author agoel
*
*/
public class Bidder implements Comparable<Bidder> {

private double maxBid;
private boolean loser;

private String name;

private double autoIncrement;

private double currentAmount;

private int positionInAuction;

public Bidder(double currentAmount, double maxBid, String name, double autoIncrement , int positionInAuction) {
this.maxBid = maxBid;
this.currentAmount = currentAmount;
this.setAutoIncrement(autoIncrement);
this.name = name;
this.positionInAuction = positionInAuction;
}

public double getMaxBid() {
return maxBid;
}

public void setMaxBid(double maxBid) {
this.maxBid = maxBid;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public double getAutoIncrement() {
return autoIncrement;
}

public void setAutoIncrement(double autoIncrement) {
this.autoIncrement = autoIncrement;
}

public int getPositionInAuction() {
return positionInAuction;
}

public void setPositionInAuction(int positionInAuction) {
this.positionInAuction = positionInAuction;
}

public double getCurrentAmount() {
return currentAmount;
}

public void setCurrentAmount(double currentAmount) {
this.currentAmount = currentAmount;
}

@Override
public int compareTo(Bidder otherBid) {

if (this.currentAmount < otherBid.getCurrentAmount()) {
return -1;
}

else if (this.currentAmount == otherBid.getCurrentAmount()) {
return 0;
}

else {
return 1;
}
}

@Override
public int hashCode() {

return Double.valueOf(currentAmount).hashCode();
}

@Override
public boolean equals(Object otherBid) {

if (otherBid == this) {
return true;
}

if (!(otherBid instanceof Bidder)) {
return false;
}

Bidder bid = (Bidder) otherBid;

if (this.currentAmount == bid.getCurrentAmount()) {
return true;
}

return false;

}

public boolean isLoser() {
return loser;
}

public void setLoser(boolean loser) {
this.loser = loser;
}

}

import java.util.List;

import com.goel.model.Auction;
import com.goel.model.Bidder;

public class AuctionBuilder {
/**
* Realistically an Auction should be built by pieces
* @param bidders
* @param itemName
* @return
*/
public Auction buildAuction(List<Bidder> bidders, String itemName) {

return new Auction(bidders, itemName);

}

}

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.goel.model.Auction;
import com.goel.model.AuctionResult;
import com.goel.model.Bidder;

/**
* This class will handle the heavylighting and be a facade to the backend. It
* will operate on an Auction object
* result in an immutable class on completion of the Auction
*
* @author agoel
*
*/
public class AuctionProcessor {

private Auction auction;

public Auction getAuction() {
return auction;
}

public void setAuction(Auction auction) {
this.auction = auction;
}


public AuctionProcessor(Auction auction) {
this.auction = auction;
}

public AuctionResult execute() {

Bidder winningBidder = auction.findWinner();

return new AuctionResult(winningBidder);

}



}


import java.util.ArrayList;
import java.util.List;

import com.goel.model.Auction;
import com.goel.model.AuctionResult;
import com.goel.model.Bidder;

public class AuctionCoordinator {

public static void main(String args) {

AuctionBuilder auctionBuilder = new AuctionBuilder();
Bidder linda = new Bidder(170.0d, 240.0d, "Linda", 3.0d, 1);
Bidder dave = new Bidder(160.0d, 243.0d, "Dave", 7.0d, 2);
Bidder eric = new Bidder(190.0d, 240.0d, "Matt", 4.0d, 3);

List<Bidder> bidders = new ArrayList<Bidder>();
bidders.add(linda);
bidders.add(dave);
bidders.add(eric);

Auction auction = auctionBuilder.buildAuction(bidders, "Record Player");
AuctionProcessor processor = new AuctionProcessor(auction);
AuctionResult result = processor.execute();

result.displayResults();

}

}






java object-oriented






share|improve this question









New contributor




Ankit Goel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




Ankit Goel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 21 mins ago









Mast

7,43863686




7,43863686






New contributor




Ankit Goel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 3 hours ago









Ankit Goel

62




62




New contributor




Ankit Goel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Ankit Goel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Ankit Goel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • Is this just a design or does it actually do something? Did you test whether it works?
    – Mast
    22 mins ago










  • Yeah if you look at AuctionCoordinator class it builds an Auction and passes it to the AuctionProcessor which executes and returns an AuctionResult
    – Ankit Goel
    19 mins ago




















  • Is this just a design or does it actually do something? Did you test whether it works?
    – Mast
    22 mins ago










  • Yeah if you look at AuctionCoordinator class it builds an Auction and passes it to the AuctionProcessor which executes and returns an AuctionResult
    – Ankit Goel
    19 mins ago


















Is this just a design or does it actually do something? Did you test whether it works?
– Mast
22 mins ago




Is this just a design or does it actually do something? Did you test whether it works?
– Mast
22 mins ago












Yeah if you look at AuctionCoordinator class it builds an Auction and passes it to the AuctionProcessor which executes and returns an AuctionResult
– Ankit Goel
19 mins ago






Yeah if you look at AuctionCoordinator class it builds an Auction and passes it to the AuctionProcessor which executes and returns an AuctionResult
– Ankit Goel
19 mins ago

















active

oldest

votes











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});






Ankit Goel is a new contributor. Be nice, and check out our Code of Conduct.










 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208400%2fobject-oriented-design-for-a-live-auction-taking-in-bidders%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes








Ankit Goel is a new contributor. Be nice, and check out our Code of Conduct.










 

draft saved


draft discarded


















Ankit Goel is a new contributor. Be nice, and check out our Code of Conduct.













Ankit Goel is a new contributor. Be nice, and check out our Code of Conduct.












Ankit Goel is a new contributor. Be nice, and check out our Code of Conduct.















 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208400%2fobject-oriented-design-for-a-live-auction-taking-in-bidders%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Ottavio Pratesi

Tricia Helfer

15 giugno