#include "ABConst.H" #include "BiddingAgentDefines.H" #include #include #include #include #include #include #include #include #include #include #include using namespace std; #include "TradAgent3.H" #include "CustomerData.H" #include "fcmp.h" #ifndef MAXNAMLEN #define MAXNAMLEN 1024 #endif #define FIRST_RESERVE_TIME 500 #define SECOND_RESERVE_TIME 300 double Max(double, double); double Min(double, double); string empty = "()"; char logLine[MAXNAMLEN+1]; map > entMaxPref; map > entMinPref; double epsilon = FLT_EPSILON; /******************************************************************************* Constructor. Just calles constructors for parent class and initalize workData. *******************************************************************************/ TradAgent::TradAgent(char *userName, char *password, unsigned int sleepTime, unsigned int instance, char *parFileName) :TradAgentShell(userName, password, sleepTime, instance), workData(instance), firstTime(true), mAllowBidForHotel(false) { if (gExitProgram) return; /* Open the log file */ char s[MAXNAMLEN+1]; (void)sprintf(s, "%s_%d.log", userName, instance); mLog.Open(s); mLog.Print("Begin Logging ....\n"); /* if parameter file is provided read it */ if (strcmp(parFileName,"\0") != 0) { if (mParams.ReadConfigFile(parFileName) == false) { gExitProgram = false; return; } } mTacData.ResetCustomerIter(); while(!mTacData.EndCustomer()) { CustomerData *myCust = mTacData.CurrentCustomer(); if (myCust != NULL) { myCust->ResetIter(); while(!myCust->EndIter()) { double tktPref = myCust->CurrentTktPref(); int tktType = myCust->CurrentTktType(); if (tktPref > entMaxPref[tktType]) entMaxPref[tktType] = tktPref; else if (tktPref < entMinPref[tktType]) entMinPref[tktType] = tktPref; myCust->NextIter(); } } mTacData.NextCustomer(); } mWaitForAllAuctionClose = false; } /******************************************************************************* Destructor Withdraws all bids placed by this agent. The Bidder class destructor disconnects from the AuctionBot. *******************************************************************************/ TradAgent::~TradAgent() { #ifdef TRACE_FUNCTION_LEVEL cout << "TradAgent::~TradAgent" << endl; #endif CustomerData* myCust = NULL; if (!gExitProgram) /* gExitProgram set to true only on error */ { /* Comment the next two lines to print to log the allocation */ mLog.Print("End logging ... \n"); mLog.Close(); mLog.Print("******************************************************\n"); mLog.Print("FINAL REPORT - based on last transaction info received\n"); mLog.Print("\n******************************************************\n"); if (mWaitForAllAuctionClose == true) { mLog.Print("All goods won by this agent in this game\n"); mLog.Print("------------------------------------------"); } else { mLog.Print("NOTE: The following is not a complete list of goods won\n"); mLog.Print("NOTE: This agent exits when last recorded server time\n"); mLog.Print(" is past the game end time. The agent has therefore\n"); mLog.Print(" has not gathered information about all goods won\n"); mLog.Print("NOTE: For a complete list of all goods won\n"); mLog.Print(" few minutes after the game has ended\n"); mLog.Print(" go to http://tac.eecs.umich.edu/auction and click on\n"); mLog.Print(" View My Account button. Authenticate with the same \n"); mLog.Print(" username and password used to run this agent \n"); mLog.Print(" Click on View My Transactions and last transactions \n"); mLog.Print(" to determine all the goods won \n"); mLog.Print(" We will soon integrate this information in the \n"); mLog.Print(" game Summary page for the game instance\n"); } /* Print all quantities won */ (void)mTacData.ResetIdIter(kInFlight); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); mInFlightWon[day] = (int) mBids[auctionId]->GetQuantityBought(); (void)snprintf(logLine, 1024, "Auction - InFlight, Day - %d Bought --> %d \n", day, mInFlightWon[day] ); mLog.Print(logLine); (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kOutFlight); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); mOutFlightWon[day] = (int) mBids[auctionId]->GetQuantityBought(); (void)snprintf(logLine, 1024, "Auction - OutFlight, Day - %d Bought --> %d \n", day, mOutFlightWon[day]); mLog.Print(logLine); (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kGoodHotel); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); mGoodHotelWon[day] = (int) mBids[auctionId]->GetQuantityBought(); (void)snprintf(logLine, 1024, "Auction - GrandHotel, Day - %d Bought --> %d \n", day, mGoodHotelWon[day]); mLog.Print(logLine); (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kBadHotel); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); mBadHotelWon[day] = (int) mBids[auctionId]->GetQuantityBought(); (void)snprintf(logLine, 1024, "Auction - Le FleaBag Inn, Day - %d Bought --> %d \n", day, mBadHotelWon[day]); mLog.Print(logLine); (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kEntertain); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); int type = mTacData.CurrentIdType(); int index = type*100 + day; mEntTktWon[index] = (int) mBids[auctionId]->GetQuantityBought(); mEntTktWon[index] -= (int) mBids[auctionId]->GetQuantitySold(); (void)mTacData.NextId(); } (void)mTacData.ResetEndowIter(); while(!mTacData.EndEndow()) { int day = mTacData.CurrentTktDay(); int type = mTacData.CurrentTktType(); long quant = mTacData.CurrentEndow(); int index = type*100 + day; mEntTktWon[index] += quant; (void)snprintf(logLine, 1024, "Entertainment Tickets - type %d day %d Own --> %d \n", type, day, mEntTktWon[index]); mLog.Print(logLine); (void)mTacData.NextEndow(); } mTacData.ResetCustomerIter(); while(!mTacData.EndCustomer()) { myCust = mTacData.CurrentCustomer(); mLog.Print("\n****\n"); (void)snprintf(logLine, 1024, "Trip for customer no : %d\n", myCust->GetCustomerNo()); mLog.Print(logLine); (void)snprintf(logLine, 1024, "Arrive in Boston on day %d\n", myCust->GetMyArrDay()); mLog.Print(logLine); (void)snprintf(logLine, 1024, "Depart from Boston on day %d\n", myCust->GetMyDepDay()); mLog.Print(logLine); if (myCust->GetMyHotelType() == kGoodHotel) mLog.Print("Staying in Grand Hotel\n"); else if (myCust->GetMyHotelType() == kBadHotel) mLog.Print("Staying in Le FleaBag Inn\n"); mLog.Print("Entertainment Events.. \n"); for(int i = myCust->GetMyArrDay(); i < myCust->GetMyDepDay(); i++) { switch(myCust->GetMyTicket(i)) { case 0: (void)snprintf(logLine, 1024, "Day %d --> No entertainment events booked\n", i); break; case 1: (void)snprintf(logLine, 1024, "Day %d --> Red Sox\n", i); break; case 2: (void)snprintf(logLine, 1024, "Day %d --> Symphony\n", i); break; case 3: (void)snprintf(logLine, 1024, "Day %d --> Phantom of the Opera\n", i); break; default: (void)snprintf(logLine, 1024, "Day %d --> Event Type %d\n", i, myCust->GetMyTicket(i)); break; } mLog.Print(logLine); } mTacData.NextCustomer(); } /* Submit allocation to AuctionBot */ mTacData.ReportAllocation(mSocketDescriptor); } /* deallocate workData customer list */ myCust = NULL; workData.ResetCustomerIter(); while(!workData.EndCustomer()) { myCust = workData.CurrentCustomer(); if (myCust != NULL) { /* set the corresponding pointer in mTacData to NULL */ int custno = myCust->GetCustomerNo(); mTacData.SetCustomer(custno, NULL); delete myCust; myCust = NULL; } workData.NextCustomer(); } mLog.Print("End logging ... \n"); mLog.Close(); } /******************************************************************************* Update Bids. Constructs bids for all auctions using a simple strategy and submits the bids *******************************************************************************/ void TradAgent::UpdateBids() { if (GetLastReceivedAuctionBotTime() >= mTacData.GetGameEndTime()) { return; } workData = mTacData; lasttime = GetLastReceivedAuctionBotTime(); if (firstTime) ConstructFirstBids(); else ConstructFirstBids(); SendBidsToAuctionBot(); } /******************************************************************************* Terminate Use TradAgentShell Terminate check logic. *******************************************************************************/ bool TradAgent::Terminate() { #ifdef TRACE_FUNCTION_LEVEL cout << "TradAgent::Terminate" << endl; #endif bool retval = TradAgentShell::Terminate(); return retval; } /******************************************************************************** SendBidsToAuctionBot Send the constructed bids to the auction Bot ******************************************************************************/ void TradAgent::SendBidsToAuctionBot() { AgentPointBidSchedule *bid; (void)mTacData.ResetIdIter(kInFlight); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int ret; bid = mBids[auctionId]; if (bidChanged[auctionId] == true && !bid->IsAuctionClosed()) { if (bid->GetState() == kUnsent) { (void)snprintf(logLine, 1024, "Submitting bid %s in auction for InFlight day %d \n\n", bid->GetBidString().c_str(), mTacData.CurrentIdDay()); mLog.Print(logLine); bid->SubmitBid(ret); } if (bid->GetState() == kActive) { (void)snprintf(logLine, 1024, "Replacing activebid with %s in auction for InFlight day %d \n\n", bid->GetBidString().c_str(), mTacData.CurrentIdDay()); mLog.Print(logLine); bid->ReplaceActiveBid(ret); } } bidChanged[auctionId] = false; (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kOutFlight); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int ret; bid = mBids[auctionId]; if (bidChanged[auctionId] == true && !bid->IsAuctionClosed()) { if (bid->GetState() == kUnsent) { (void)snprintf(logLine, 1024, "Submitting bid %s in auction for OutFlight day %d \n\n", bid->GetBidString().c_str(), mTacData.CurrentIdDay()); mLog.Print(logLine); bid->SubmitBid(ret); } if (bid->GetState() == kActive) { (void)snprintf(logLine, 1024, "Replacing activebid with %s in auction for OutFlight day %d \n\n", bid->GetBidString().c_str(), mTacData.CurrentIdDay()); mLog.Print(logLine); bid->ReplaceActiveBid(ret); } } bidChanged[auctionId] = false; (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kGoodHotel); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int ret; bid = mBids[auctionId]; CleanBid(bid); // check bid for bid dominance if (bidChanged[auctionId] == true && !bid->IsAuctionClosed()) { (void)snprintf(logLine, 1024, "Submitting bid %s in auction for GrandHotel day %d \n\n", bid->GetBidString().c_str(), mTacData.CurrentIdDay()); mLog.Print(logLine); bid->SubmitBid(ret); } bidChanged[auctionId] = false; (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kBadHotel); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int ret; bid = mBids[auctionId]; CleanBid(bid); // check bid for bid dominance if (bidChanged[auctionId] == true && !bid->IsAuctionClosed()) { (void)snprintf(logLine, 1024, "Submitting bid %s in auction for LeFleaBag Inn day %d \n\n", bid->GetBidString().c_str(), mTacData.CurrentIdDay()); mLog.Print(logLine); bid->SubmitBid(ret); } bidChanged[auctionId] = false; (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kEntertain); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int ret; bid = mBids[auctionId]; if (bidChanged[auctionId] == true && !bid->IsAuctionClosed()) { if (bid->GetState() == kUnsent) { (void)snprintf(logLine, 1024, "Submitting bid %s in auction for ent tkt type %d day %d \n\n", bid->GetBidString().c_str(), mTacData.CurrentIdType(), mTacData.CurrentIdDay()); mLog.Print(logLine); bid->SubmitBid(ret); } if (bid->GetState() == kActive) { (void)snprintf(logLine, 1024, "Replacing activebid with %s in auction for ent tkt type %d day %d \n\n", bid->GetBidString().c_str(), mTacData.CurrentIdType(), mTacData.CurrentIdDay()); mLog.Print(logLine); bid->ReplaceActiveBid(ret); } } bidChanged[auctionId] = false; (void)mTacData.NextId(); } } void TradAgent::ClearAllHotelBids() { AgentPointBidSchedule *bid; PQPoint *pqp; (void)mTacData.ResetIdIter(kGoodHotel); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); bid = mBids[auctionId]; hotelbidState[auctionId] = bid->GetState(); if (strcmp(bid->GetBidString().c_str(),"()") == 0) { /* no bids in this auction */ hotelbidQs[auctionId] = 0.0; hotelbidPs[auctionId] = -1.0; } else { bid->ResetIterator(); pqp = bid->CurrentPoint(); hotelbidQs[auctionId] = pqp->GetQuantity(); hotelbidPs[auctionId] = pqp->GetPrice(); } bid->SetBidString(empty); (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kBadHotel); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); bid = mBids[auctionId]; hotelbidState[auctionId] = bid->GetState(); if (strcmp(bid->GetBidString().c_str(),"()") == 0) { /* no bids in this auction */ hotelbidQs[auctionId] = 0.0; hotelbidPs[auctionId] = -1.0; } else { bid->ResetIterator(); pqp = bid->CurrentPoint(); hotelbidQs[auctionId] = pqp->GetQuantity(); hotelbidPs[auctionId] = pqp->GetPrice(); } bid->SetBidString(empty); (void)mTacData.NextId(); } return; } /* if I have buy my air ticket or hotel, I donot change my plan anymore */ /* currently single hotel will make true, later , will change to all hotel so, I can still change plan even if I just get some hotel */ bool TradAgent::GetSome(int custno) { CustomerData *myCust; long aucId; AgentPointBidSchedule *bid; myCust = mTacData.GetCustomer(custno); int ari_date = myCust->GetMyArrDay(); if (ari_date<1) return false; if (ari_date>5) return false; aucId = mTacData.GetId(kInFlight, ari_date); bid = mBids[aucId]; if (bid->GetState() == kTransacted) return true; int dep_date = myCust->GetMyDepDay(); if (dep_date<1) return false; if (dep_date>5) return false; aucId = mTacData.GetId(kOutFlight, dep_date); bid = mBids[aucId]; if (bid->GetState() == kTransacted) return true; for (int i = ari_date; i < dep_date; i++) { if (myCust->GetMyHotelType() == kBadHotel) { aucId = mTacData.GetId(kBadHotel,i); bid = mBids[aucId]; if (bid->GetState() == kTransacted) return true; } else { aucId = mTacData.GetId(kGoodHotel,i); bid = mBids[aucId]; if (bid->GetState() == kTransacted) return true; } } return false; } /* bool TradeAgent::MustChange(int custno) { CustomerData *myCust; long aucId; AgentPointBidSchedule *bid; myCust = mTacData.GetCustomer(custno); int ari_date = myCust->GetMyArrDay(); aucId = mTacData.GetId(kInFlight, ari_date); bid = mBids[aucId]; if (bid->IsAuctionClosed()) if (bid->GetState() == kTransacted) return true; int dep_date = myCust->GetMyDepDay(); aucId = mTacData.GetId(kOutFlight, dep_date); bid = mBids[aucId]; if (bid->GetState() == kTransacted) return true; return false; } */ double TradAgent::MyPrefer(int custno,int day, int tktType) { CustomerData *myCust; myCust = mTacData.GetCustomer(custno); if (dayGetMyArrDay()) return false; if (day>=myCust->GetMyDepDay()) return false; if (myCust->GetMyTicket(day)!=0) return false; for(int i = myCust->GetMyArrDay(); i < myCust->GetMyDepDay(); i++) { if (myCust->GetMyTicket(i)==tktType) return false; } return myCust->GetTktPref((EntertainTktType)tktType); } void TradAgent::BadGuy() { long aucId; AgentPointBidSchedule *bid; mTacData.ResetIdIter(kEntertain); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); bid = mBids[aucId]; bid->InsertPoint(1,1); int ret; bid->SubmitBid(ret); mTacData.NextId(); } } /******************************************************************************* ConstructFirstBids Goes through all client requirements and generates the best solution for all customers *****************************************************************************/ void TradAgent::ConstructFirstBids() { ClearAllHotelBids(); CustomerData* myCust; mTacData.ResetCustomerIter(); while(!mTacData.EndCustomer()) { myCust = mTacData.CurrentCustomer(); int custNo = myCust->GetCustomerNo(); int taci,tacj; int maxDepDate,maxAriDate; bool hotelPrefer; float maxTacValue = 0; long aucId; AgentPointBidSchedule *bid; if (GetSome(custNo)) /*if I get my ticket or hotel, donot change idea*/ { maxAriDate = myCust->GetMyArrDay(); maxDepDate = myCust->GetMyDepDay(); hotelPrefer = false; } else { for (taci = 1;taci<5;taci++) for (tacj = taci+1; tacj<6;tacj++) { /* compute Tacvalue , formula: u = 1000 - travel_penalty + hotel_bonus - air_tocket_price - hotel_price */ float TacValue = 10000 ; /* arrive penalty */ if (myCust->GetArrPref()>taci) TacValue = TacValue-(100*(myCust->GetArrPref()-taci)); else TacValue = TacValue-(100*(taci-myCust->GetArrPref())); /* departure penalty */ if (myCust->GetDepPref()>tacj) TacValue = TacValue -(100*(myCust->GetDepPref()-tacj)); else TacValue = TacValue -(100*(tacj-myCust->GetDepPref())); aucId = mTacData.GetId(kInFlight, taci); bid = mBids[aucId]; TacValue = TacValue - bid->GetAskPrice(); aucId = mTacData.GetId(kOutFlight, tacj); bid = mBids[aucId]; TacValue = TacValue - bid->GetAskPrice(); double badhotel = myCust->GetHotelPref() * mParams.GetGoodHotelBadHotelBias(); double goodhotel =0 ; for (int tack=taci;tackIsAuctionClosed()) goodhotel += 8000; else goodhotel += Max(0,bid->GetAskPrice()); aucId = mTacData.GetId(kBadHotel,tack); bid = mBids[aucId]; if (bid->IsAuctionClosed()) badhotel += 8000; else badhotel += Max(0,bid->GetAskPrice()); } /* if (goodhotel>badhotel) TacValue = TacValue-badhotel; else TacValue = TacValue-goodhotel; */ /* here we choose bad hotel */ TacValue = TacValue-badhotel; if (TacValue>maxTacValue) { maxDepDate = tacj; maxAriDate = taci; /* if (goodhotel>badhotel) hotelPrefer = false; else hotelPrefer = true; */ hotelPrefer = false; maxTacValue = TacValue; } } /* end of two for loop */ /* now we get the best solution for this customer */ } /* end of deciee if I get some thing */ /* Bid for the inflight */ aucId = mTacData.GetId(kInFlight, maxAriDate); myCust->SetMyArrDay(maxAriDate); bid = mBids[aucId]; PQPoint *pqp; UpdateBidString(aucId, myCust, bid, kInFlight, 0); /* Bid for the outflight */ aucId = mTacData.GetId(kOutFlight, maxDepDate); myCust->SetMyDepDay(maxDepDate); bid = mBids[aucId]; UpdateBidString(aucId, myCust, bid, kOutFlight, 0); /* Bid for hotels for nights between arrival and departure */ for (int i = maxAriDate; i < maxDepDate; i++) { if (hotelPrefer) { /* Good hotel affordable for all days */ myCust->SetMyHotelType(kGoodHotel); aucId = mTacData.GetId(kGoodHotel,i); bid = mBids[aucId]; myCust->SetLastHotelType(kGoodHotel); } else { /* Good Hotel not affordable , go to FleaBag */ myCust->SetMyHotelType(kBadHotel); aucId = mTacData.GetId(kBadHotel, i); bid = mBids[aucId]; myCust->SetLastHotelType(kBadHotel); } /* Agent has no bids in this auction for anybody */ if (strcmp(bid->GetBidString().c_str(),"()") == 0) { double price = CalcBuyBidPrice(bid, myCust->GetLastHotelType(), 0); bid->InsertPoint(1,price); myCust->SetBidPoint(aucId, price); } else { /* increment quantity of PQ Point by 1 */ bid->ResetIterator(); pqp = bid->CurrentPoint(); float quant = pqp->GetQuantity() + 1; pqp->SetQuantity(quant); myCust->SetBidPoint(aucId, pqp->GetPrice()); } bidChanged[aucId] = true; } /* end of for loop */ /* Bid for entertainment tickets */ int tktTypecount = 1; for (int i = myCust->GetArrPref(); i < myCust->GetDepPref(); i++) { bool foundTkt = FindEntertainmentTicketInEndow(myCust, i, &workData, &tktTypecount); if (foundTkt == false) { /* I don't have any tickets for this day Put Buy bid for an entertainment ticket */ int j = 1; myCust->ResetIter(); while(!myCust->EndIter()) { if (j == tktTypecount) { int tktType = myCust->CurrentTktType(); double tktPref = myCust->CurrentTktPref(); if (tktPref > 0) { aucId = mTacData.GetEntId((EntertainTktType)tktType,i); myCust->SetMyTicket(i, (EntertainTktType)tktType); bid = mBids[aucId]; UpdateBidString(aucId, myCust, bid, kEntertain, tktType); tktTypecount++; break; } else tktTypecount++; } j++; myCust->NextIter(); } } else tktTypecount ++; } mTacData.NextCustomer(); /* get next customer */ } /* Put remaining entertainment tickets for sale */ workData.ResetEndowIter(); while(!workData.EndEndow()) { int tktType = workData.CurrentTktType(); int day = workData.CurrentTktDay(); long qty = workData.CurrentEndow(); double k = mParams.GetEntertainInitialSellPriceFactor(); double tktDesSellPrice = entMinPref[tktType] + k*(entMaxPref[tktType] - entMinPref[tktType]); tktDesSellPrice = Max(90, tktDesSellPrice); if (qty > 0) { long aucId = workData.GetEntId((EntertainTktType)tktType, day); AgentPointBidSchedule *bid = mBids[aucId]; float bidPrice = bid->GetBidPrice(); bidPrice = bidPrice - 1; bidPrice = Max(1, bidPrice); if (bid->WasBidRejected() || ((!strcmp(bid->GetBidString().c_str(),"()")) && bid->GetState() != kTransacted)) { /* sell it for first time */ bid->SetBidString(empty); tktDesSellPrice = Max(150, tktDesSellPrice); bid->InsertPoint(-qty,tktDesSellPrice); bidChanged[aucId] = true; } else { if (bid->GetState() == kActive) { bid->ResetIterator(); PQPoint *pqp = bid->CurrentPoint(); if (fcmp(pqp->GetPrice(),bidPrice,epsilon) == 1) { bid->SetBidString(empty); /* decrease every ten second */ time_t now = GetLastReceivedAuctionBotTime(); time_t timeLeftInGame = mTacData.GetGameEndTime() - now; if (timeLeftInGame < SECOND_RESERVE_TIME) { time_t abc = now - lasttime; if (abc>5) { bidPrice = pqp->GetPrice()-2; lasttime = now; } else bidPrice = pqp->GetPrice(); bidPrice = Max(10,bidPrice); } else bidPrice = Max(90, bidPrice); bid->InsertPoint(-qty,bidPrice); bidChanged[aucId] = true; } } } } workData.NextEndow(); } /* end of sell ticket while loop */ /* print current result */ /*CurrentResult(); */ } void TradAgent::ConstructAllBids() { #ifdef TRACE_FUNCTION_LEVEL cout << "TradAgent::ConstructAllBids" << endl; #endif ClearAllHotelBids(); CustomerData* myCust; mTacData.ResetCustomerIter(); while(!mTacData.EndCustomer()) { myCust = mTacData.CurrentCustomer(); /***************** FLIGHT AUCTIONS *****************************/ /* Bid for the inflight */ long aucId = mTacData.GetId(kInFlight, myCust->GetArrPref()); myCust->SetMyArrDay(myCust->GetArrPref()); AgentPointBidSchedule *bid = mBids[aucId]; PQPoint *pqp; /* If previous bid was rejected or this is the first bid to be sent */ UpdateBidString(aucId, myCust, bid, kInFlight, 0); /* Bid for the outflight */ aucId = mTacData.GetId(kOutFlight, myCust->GetDepPref()); myCust->SetMyDepDay(myCust->GetDepPref()); bid = mBids[aucId]; UpdateBidString(aucId, myCust, bid, kOutFlight, 0); /***************** HOTEL AUCTIONS ****************************/ /* Bid for hotels for all nights between arrival and departure */ if (!CanBidForHotel()) { /* Check if past wait time for bidding in hotel auctions */ time_t now = GetLastReceivedAuctionBotTime(); time_t waitedTime = now - mTacData.GetGameStartTime(); if (waitedTime > mParams.GetWaitBeforeStartingHotelBidding() ) { (void)snprintf(logLine,1024, "Past wait time for starting hotel bidding - Start Bidding in Hotel Auctions. - %s\n\n", (char *)ctime(&now)); mLog.Print(logLine); SetCanBidForHotel(true); } } if (CanBidForHotel()) { /* Past waiting time for hotel auctions - can bid in this auction */ bool affordable = true; double hotel_pref = myCust->GetHotelPref() * mParams.GetGoodHotelBadHotelBias(); /* Check max switches between good and bad hotel */ int maxSwitches = mParams.GetMaxSwitchHotelType(); if (myCust->GetLastHotelType() != -1 && switchCount[myCust->GetCustomerNo()] > maxSwitches) { (void)snprintf(logLine,1024, "Reached max hotel switching count for customer %d \n\n", myCust->GetCustomerNo()); mLog.Print(logLine); if (myCust->GetLastHotelType() == kGoodHotel) { affordable = true; (void)snprintf(logLine,1024, "From this point will bid on GrandHotel for customer %d \n\n", myCust->GetCustomerNo()); mLog.Print(logLine); } else { affordable = false; (void)snprintf(logLine,1024, "From this point will bid on LeFleaBagInn for customer %d \n\n", myCust->GetCustomerNo()); mLog.Print(logLine); } } else { /* switch hotel type max count not reached - choose hotel type Find if given clients good hotel preference, he can get the good hotel for all days */ double goodHotelPrices = 0; double badHotelPrices = 0; for (int i = myCust->GetArrPref(); i < myCust->GetDepPref(); i++) { /** Sum hotel prices for all days between arrival and departure **/ aucId = mTacData.GetId(kGoodHotel,i); long aucId2 = mTacData.GetId(kBadHotel, i); bid = mBids[aucId]; AgentPointBidSchedule *bid2 = mBids[aucId2]; goodHotelPrices += Max(0, bid->GetAskPrice()); badHotelPrices += Max(0, bid2->GetAskPrice()); } /* = will bias towards the bad hotel */ if (goodHotelPrices - badHotelPrices >= hotel_pref) affordable = false; } if (myCust->GetLastHotelType() != -1) { if ((affordable && myCust->GetLastHotelType() == kBadHotel) || (!affordable && myCust->GetLastHotelType() == kGoodHotel)) { mLog.Print("Switching bidding from "); if (myCust->GetLastHotelType() == kBadHotel) (void)snprintf(logLine,1024, "Le FleaBag Inn to Grand Hotel for customer no %d\n\n", myCust->GetCustomerNo()); else (void)snprintf(logLine,1024, "Grand Hotel to Le FleaBag Inn for customer no %d\n\n", myCust->GetCustomerNo()); mLog.Print(logLine); switchCount[myCust->GetCustomerNo()]++; } } else { switchCount[myCust->GetCustomerNo()] = 0; } for (int i = myCust->GetArrPref(); i < myCust->GetDepPref(); i++) { if (affordable) { /* Good hotel affordable for all days */ (void)snprintf(logLine,1024, "Constructing bids for Grand Hotel for customer %d \n", myCust->GetCustomerNo()); /* mLog.Print(logLine); */ myCust->SetMyHotelType(kGoodHotel); aucId = mTacData.GetId(kGoodHotel,i); bid = mBids[aucId]; myCust->SetLastHotelType(kGoodHotel); } else { /* Good Hotel not affordable for all hotels go to FleaBag */ (void)snprintf(logLine,1024, "Constructing bids for Le FleaBag Inn for customer %d \n", myCust->GetCustomerNo()); /* mLog.Print(logLine); */ myCust->SetMyHotelType(kBadHotel); aucId = mTacData.GetId(kBadHotel, i); bid = mBids[aucId]; myCust->SetLastHotelType(kBadHotel); } /* Agent has no bids in this auction for anybody */ if (strcmp(bid->GetBidString().c_str(),"()") == 0) { double price = CalcBuyBidPrice(bid, myCust->GetLastHotelType(), 0); /* no bid string yet for this auction - insert new PQ Point */ bid->InsertPoint(1,price); myCust->SetBidPoint(aucId, price); } else { /* increment quantity of PQ Point by 1 */ bid->ResetIterator(); pqp = bid->CurrentPoint(); float quant = pqp->GetQuantity() + 1; pqp->SetQuantity(quant); myCust->SetBidPoint(aucId, pqp->GetPrice()); } bidChanged[aucId] = true; } } /*********************** ENTERTAINMENT TICKET AUCTIONS *****************/ /* Bid for entertainment tickets */ int tktTypecount = 1; for (int i = myCust->GetArrPref(); i < myCust->GetDepPref(); i++) { bool foundTkt = FindEntertainmentTicketInEndow(myCust, i, &workData, &tktTypecount); if (foundTkt == false) { /* I don't have any tickets for this day Put Buy bid for an entertainment ticket */ int j = 1; myCust->ResetIter(); while(!myCust->EndIter()) { if (j == tktTypecount) { int tktType = myCust->CurrentTktType(); double tktPref = myCust->CurrentTktPref(); if (tktPref > 0) { aucId = mTacData.GetEntId((EntertainTktType)tktType,i); myCust->SetMyTicket(i, (EntertainTktType)tktType); bid = mBids[aucId]; UpdateBidString(aucId, myCust, bid, kEntertain, tktType); tktTypecount++; break; } else tktTypecount++; } j++; myCust->NextIter(); } } else tktTypecount ++; } mTacData.NextCustomer(); } /* Put remaining entertainment tickets for sale */ workData.ResetEndowIter(); while(!workData.EndEndow()) { int tktType = workData.CurrentTktType(); int day = workData.CurrentTktDay(); long qty = workData.CurrentEndow(); double k = mParams.GetEntertainInitialSellPriceFactor(); double tktDesSellPrice = entMinPref[tktType] + k*(entMaxPref[tktType] - entMinPref[tktType]); tktDesSellPrice = Max(0.0, tktDesSellPrice); if (qty > 0) { long aucId = workData.GetEntId((EntertainTktType)tktType, day); AgentPointBidSchedule *bid = mBids[aucId]; float bidPrice = bid->GetBidPrice(); bidPrice = bidPrice - 1; bidPrice = Max(0.0, bidPrice); if (bid->WasBidRejected() || ((!strcmp(bid->GetBidString().c_str(),"()")) && bid->GetState() != kTransacted)) { /* First Bid - sell at price determined by the EntertainInitialSellPriceFactor */ bid->SetBidString(empty); bid->InsertPoint(-qty,tktDesSellPrice); bidChanged[aucId] = true; } else { if (bid->GetState() == kActive) { bid->ResetIterator(); PQPoint *pqp = bid->CurrentPoint(); if (fcmp(pqp->GetPrice(),bidPrice,epsilon) == 1) { bid->SetBidString(empty); bid->InsertPoint(-qty,bidPrice); bidChanged[aucId] = true; } } } } workData.NextEndow(); } } /******************************************************************************* UpdateBidString Adds 1 unit to the 'bid' if the bid state was unsent or rejected. Also updates the price to delta+AskPrice if the price offered by 'bid' is less than the auction's(aucId) stated AskPrice. Used to update buy bid strings for the flight and entertainment tkt auctions *******************************************************************************/ void TradAgent::UpdateBidString(long aucId, CustomerData* myCust, AgentPointBidSchedule *bid, AuctionCat cat, int tktType) { double reservePrice; if (cat == kEntertain) reservePrice = myCust->GetTktPref((EntertainTktType)tktType) * mParams.GetEntertainReserveBuyPriceFactor()/2; else reservePrice = 1; PQPoint *pqp; if (bid->WasBidRejected() || bid->GetState() == kUnsent) { if (strcmp(bid->GetBidString().c_str(),"()") == 0) { double price = CalcBuyBidPrice(bid, cat, reservePrice); /* no bids yet for this auction - insert new PQ Point*/ bid->InsertPoint(1,price); myCust->SetBidPoint(aucId, price); } else { /* increment quantity of PQ Point by 1 */ double price = CalcBuyBidPrice(bid, cat, reservePrice); bid->ResetIterator(); bool inserted = false; while(!bid->IteratorAtEnd()) { pqp = bid->CurrentPoint(); if (fcmp(pqp->GetPrice(),(float)price,epsilon) == 0) { /* found pqpoint with the same price */ float quant = pqp->GetQuantity() + 1; pqp->SetQuantity(quant); myCust->SetBidPoint(aucId, pqp->GetPrice()); inserted = true; break; } bid->AdvanceIterator(); } if (inserted == false) { /* no pqpoint in this bid at this price, create new pqpoint */ bid->InsertPoint(1,price); myCust->SetBidPoint(aucId, price); } } bidChanged[aucId] = true; } /* end Rejected bid or Unsent Bid case */ else { if (bid->GetState() == kActive) { double prevPrice = myCust->GetBidPoint(aucId); double price = CalcBuyBidPrice(bid, cat, reservePrice); /* if new price for bid same as prevPrice no point updating bid string */ if (fcmp((float)prevPrice,(float)price,epsilon) == 0) return; /* find myCust's prev offer - if that offer is below the ask price remove that offer and insert new updated offer */ bool prevPQremoved = false; myCust->SetBidPoint(aucId, -1.0); bid->ResetIterator(); while(!bid->IteratorAtEnd()) { pqp = bid->CurrentPoint(); /* this is myCust's pqPoint - update */ if (fcmp(pqp->GetPrice(),(float)prevPrice, epsilon) == 0) { /* If offer price is below the ask price */ if (fcmp(pqp->GetPrice(),bid->GetAskPrice(),epsilon) == -1) { float quant = pqp->GetQuantity(); quant--; if (fcmp(quant,0.0,epsilon) <= 0) bid->RemovePoint(pqp); else pqp->SetQuantity(quant); prevPQremoved = true; bidChanged[aucId] = true; } myCust->SetBidPoint(aucId, prevPrice); break; } bid->AdvanceIterator(); } if (prevPQremoved) { bool inserted = false; bid->ResetIterator(); while(!bid->IteratorAtEnd()) { pqp = bid->CurrentPoint(); if (fcmp(pqp->GetPrice(),(float)price,epsilon) == 0) { float quant = pqp->GetQuantity() + 1; pqp->SetQuantity(quant); myCust->SetBidPoint(aucId, pqp->GetPrice()); inserted = true; break; } bid->AdvanceIterator(); } if (inserted == false) { bid->InsertPoint(1,price); myCust->SetBidPoint(aucId, price); } } } /* end previous bid Active case */ } } /******************************************************************************* FindEntertainmentTicketInEndow Returns true if an entairment ticket is found for 'myCust' for day 'i' as part of the endowment stated in 'workData'. If a ticket is found the endowment for that ticket for day i in 'workData' is decremented by 1. *******************************************************************************/ bool TradAgent::FindEntertainmentTicketInEndow(CustomerData *myCust, int i, TACData *workData, int *tktTypecount) { bool foundTkt = false; int tktType; double tktPref; int j = 1; myCust->ResetIter(); while(!myCust->EndIter()) { if (j >= *tktTypecount) { tktType = myCust->CurrentTktType(); tktPref = myCust->CurrentTktPref(); /* Does customer want this entertainment ticket */ if (fcmp((float)tktPref,0.0,epsilon) <= 0) { /* No */ (*tktTypecount)++; j++; myCust->NextIter(); continue; } } else { j++; myCust->NextIter(); continue; } j++; int endow = workData->GetTicketEndowment((EntertainTktType)tktType,i); /* Do I have a ticket for this type */ if (endow > 0) { /* Yes I have Assign 1 ticket to this customer and decrement my endowment */ foundTkt = true; endow--; workData->SetTicketEndowment((EntertainTktType)tktType,i,endow); myCust->SetMyTicket(i, (EntertainTktType)tktType); break; } /* No I dont */ myCust->NextIter(); } return foundTkt; } /****************************************************************************** CalcBuyBidPrice given a bid, an auction category, determines price for a buy bid based on the ask price, the delta parameter for the agent, and the reserve price for the agent. ******************************************************************************/ double TradAgent::CalcBuyBidPrice(AgentPointBidSchedule *bid, int cat, double reservationPrice) { double delta; double price = 0; switch(cat) { case kInFlight: case kOutFlight: { delta = mParams.GetDeltaAirlinePrice(); time_t now = GetLastReceivedAuctionBotTime(); time_t timeLeftInGame = mTacData.GetGameEndTime() - now; if (timeLeftInGame > FIRST_RESERVE_TIME) reservationPrice = mParams.GetAirlineReservePrice0(); else if (timeLeftInGame > SECOND_RESERVE_TIME) reservationPrice = mParams.GetAirlineReservePrice1(); else reservationPrice = mParams.GetAirlineReservePrice2(); double price1 = 0.0; if (fcmp(bid->GetAskPrice(), 0.0, epsilon) == -1) price1 = Min(delta, reservationPrice); else price1 = Min(bid->GetAskPrice() + delta, reservationPrice); price = Max(10, price1); break; } case kGoodHotel: case kBadHotel: { delta = mParams.GetDeltaHotelPrice(); double price1 = 0.0; if (fcmp(bid->GetAskPrice(), 0.0, epsilon) == -1) price1 = delta; else price1 = bid->GetAskPrice() + 21 ; price = Max(1, price1); break; } case kEntertain: { delta = mParams.GetDeltaEntertainmentPrice(); double price1 = 0.0; /* zou, here it use air's price ? mad!!! */ if (fcmp(bid->GetAskPrice(), 0.0, epsilon) == -1) price1 = Min(delta, 100); else price1 = Min(bid->GetAskPrice() + delta, 100); price = Max(1, price1); break; } default: delta = 1; double price1 = 0.0; if (fcmp(bid->GetAskPrice(), 0.0, epsilon) == -1) price1 = delta; else price1 = bid->GetAskPrice() + delta; price = Max(0, price1); } return price; } /****************************************************************************** CleanBid Corrects bids for bid dominance and removes any pq points below ask price - Called for hotel auctions. ****************************************************************************/ void TradAgent::CleanBid(AgentPointBidSchedule *bid) { PQPoint *pqp; list< PQPoint* > removePoints; long aucId = bid->GetAuctionId(); float prevQuant = (float)hotelbidQs[aucId]; float prevPrice = (float)hotelbidPs[aucId]; int prevState = hotelbidState[aucId]; if (strcmp(bid->GetBidString().c_str(),"()") == 0) { /* Return bid is empty */ return; } bid->ResetIterator(); pqp = bid->CurrentPoint(); /* If the previous PQ Offer is identical to the constructed PQ Offer, and the previous bid is active or unprocessed do not send the newly constructed PQOffer */ if ((fcmp(pqp->GetQuantity(),prevQuant,epsilon) == 0) && (fcmp(pqp->GetPrice(),prevPrice,epsilon) == 0) && (prevState == kActive || prevState == kUnProcessed)) { bidChanged[aucId] = false; return; } /* Following done because as per auction rules the agent should always improve its offer */ if (fcmp(pqp->GetQuantity(), prevQuant, epsilon) == -1) pqp->SetQuantity(prevQuant); /* If my previous offer is already being matched, use prevPrice */ if ((fcmp(prevPrice,bid->GetAskPrice(),epsilon) > 0) && (fcmp(prevPrice,0.0,epsilon) >= 0)) pqp->SetPrice(prevPrice); /* If the previous PQ Offer is identical to the constructed PQ Offer, and the previous bid is active or unprocessed do not send the newly constructed PQOffer */ if ((fcmp(pqp->GetQuantity(),prevQuant,epsilon) == 0) && (fcmp(pqp->GetPrice(),prevPrice,epsilon) == 0) && (prevState == kActive || prevState == kUnProcessed)) { bidChanged[aucId] = false; return; } /* Sanity check - there shouldn't be more than one PQPoint */ bid->ResetIterator(); while(!bid->IteratorAtEnd()) { pqp = bid->CurrentPoint(); if (fcmp(pqp->GetPrice(),bid->GetAskPrice(),epsilon) == -1) removePoints.push_back(pqp); bid->AdvanceIterator(); } list< PQPoint* >::iterator iter; for(iter = removePoints.begin(); iter != removePoints.end(); iter++) { pqp = (PQPoint *)(* iter); (void)snprintf(logLine,1024, "Removing pqpoint (%f %f) from bid for auction %ld \n", pqp->GetQuantity(), pqp->GetPrice(), aucId); /* mLog.Print(logLine); */ bid->RemovePoint(pqp); } removePoints.clear(); } /****************************************************************************** CanBidForHotel returns true if you can start bidding in hotel auctions ****************************************************************************/ bool TradAgent::CanBidForHotel() { return mAllowBidForHotel; } /****************************************************************************** SetCanBidForHotel Sets the mAllowBidForHotel flag. ****************************************************************************/ void TradAgent::SetCanBidForHotel(bool flag) { mAllowBidForHotel = flag; } /****************************************************************************** Max returns maximum of two doubles ****************************************************************************/ double Max(double a, double b) { if (fcmp(a,b,DBL_EPSILON) == 1) return a; else return b; } /****************************************************************************** Max returns maximum of two doubles ****************************************************************************/ double Min(double a, double b) { if (fcmp(a,b,DBL_EPSILON) == -1) return a; else return b; } /******************************************************************************* main usage: programName userName password sleeptime instance Parameters: * userName - the user name for your AuctionBot account. * password - the password for your AuctionBot account. * sleeptime - time between calls to UpdateBids * instance - instance no of the game *******************************************************************************/ int main(int argc, char* argv[]) { if ((argc != 3) && (argc != 2)) { cerr << "usage: " << argv[0] << " userName:password:sleeptime:instance filename" << endl; exit(1); } char user[20]; char pw[36]; long t; int instance; char parfilename[MAXNAMLEN+1]; if (argc == 3) strncpy(parfilename, argv[2], MAXNAMLEN); else parfilename[0] = '\0'; sscanf(argv[1], "%[^:]:%[^:]:%ld:%d", user, pw, &t, &instance); /* Create the Bidder */ static TradAgent thisBidder(user, pw, t, instance, parfilename); if (thisBidder.gExitProgram == false) { /* run the bidder */ thisBidder.RunBidder(); } return 0; } void TradAgent::CurrentResult() { (void)mTacData.ResetIdIter(kInFlight); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); AgentPointBidSchedule *bid = mBids[auctionId]; if (bid->GetState() != kTransacted) { (void)snprintf(logLine, 1024, "Not transcated --> %d \n", bid->GetState()); mLog.Print(logLine); } else { (void)snprintf(logLine, 1024, "Transcated \n"); mLog.Print(logLine); } int num = (int) mBids[auctionId]->GetQuantityBought(); (void)snprintf(logLine, 1024, "Auction - InFlight, Day - %d Bought --> %d \n", day, num ); mLog.Print(logLine); (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kOutFlight); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); AgentPointBidSchedule *bid = mBids[auctionId]; if (bid->GetState() != kTransacted) { (void)snprintf(logLine, 1024, "Not transcated --> %d \n", bid->GetState()); mLog.Print(logLine); } else { (void)snprintf(logLine, 1024, "Transcated \n"); mLog.Print(logLine); } int num = (int) mBids[auctionId]->GetQuantityBought(); (void)snprintf(logLine, 1024, "Auction - OutFlight, Day - %d Bought --> %d \n", day, num); mLog.Print(logLine); (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kGoodHotel); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); AgentPointBidSchedule *bid = mBids[auctionId]; if (bid->GetState() != kTransacted) { (void)snprintf(logLine, 1024, "Not transcated --> %d \n", bid->GetState()); mLog.Print(logLine); } else { (void)snprintf(logLine, 1024, "Transcated \n"); mLog.Print(logLine); } int num = (int) mBids[auctionId]->GetQuantityBought(); (void)snprintf(logLine, 1024, "Auction - GrandHotel, Day - %d Bought --> %d \n", day, num); mLog.Print(logLine); (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kBadHotel); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); AgentPointBidSchedule *bid = mBids[auctionId]; if (bid->GetState() != kTransacted) { (void)snprintf(logLine, 1024, "Not transcated --> %d \n", bid->GetState()); mLog.Print(logLine); } else { (void)snprintf(logLine, 1024, "Transcated \n"); mLog.Print(logLine); } int num = (int) mBids[auctionId]->GetQuantityBought(); (void)snprintf(logLine, 1024, "Auction - Le FleaBag Inn, Day - %d Bought --> %d \n", day, num); mLog.Print(logLine); (void)mTacData.NextId(); } (void)mTacData.ResetIdIter(kEntertain); while(!mTacData.EndId()) { long auctionId = mTacData.CurrentId(); int day = mTacData.CurrentIdDay(); int type = mTacData.CurrentIdType(); AgentPointBidSchedule *bid = mBids[auctionId]; if (bid->GetState() != kTransacted) { (void)snprintf(logLine, 1024, "Not transcated --> %d \n", bid->GetState()); mLog.Print(logLine); } else { (void)snprintf(logLine, 1024, "Transcated \n"); mLog.Print(logLine); } int num = (int) mBids[auctionId]->GetQuantityBought(); num -= (int) mBids[auctionId]->GetQuantitySold(); (void)snprintf(logLine, 1024, "Entertainment Tickets - type %d day %d Own --> %d \n", type, day, num); mLog.Print(logLine); (void)mTacData.NextId(); } }