/// want_list(user asking, user target) - Return a list of cards which target wants. Data Server::want_list(const Data& args) { if(!args.IsList(2) || !args[0].IsString() || !args[1].IsString()) ArgumentError("want_list",args); if(!IsUser(args[0])) throw LangErr("want_list","invalid user "+tostr(args[0]).String()); if(!IsUser(args[1])) throw LangErr("want_list","invalid user "+tostr(args[0]).String()); VAR(asker,"users"); // asker=users{args} MAP(asker,args[0]); // asker=users{args[0]} VEC(asker,2); // asker=users{args[0]}[2] VAR(user,"users"); MAP(user,args[1]); // users=users{args[1]} // Check all cards Data ret; Data *cards,*entry; VECTO(user,2,cards); // cards=users{args}[2] ret.MakeList(); for(size_t i=0; i<cards->Size(); i++) { // Add only cards that asker have MAPTO(asker,(*cards)[i][0],entry); if(entry->IsNull()) *entry=NewCard(); if((*cards)[i][1][1] < 0 && (*entry)[0] > 0) ret.AddList((*cards)[i][0]); } return ret; }
Data Data::operator-(const Data& arg) const { if(type==NullType || arg.type==NullType) return Null; if(type==IntegerType && arg.type==IntegerType) return Data(n - arg.n); if(type==RealType && arg.type==RealType) return Data(r - arg.r); if(type==IntegerType && arg.type==RealType) return Data(double(n) - arg.r); if(arg.type==IntegerType && type==RealType) return Data(r - double(arg.n)); if(type==ListType) { set<Data> remove; Data ret; if(arg.type!=ListType) throw LangErr("Data::operator-(const Data& )","Cannot substract list and non-list"); ret.MakeList(); if(IsDatabase() || arg.IsDatabase()) { for(size_t i=0; i<arg.Size(); i++) remove.insert(arg[i]); for(size_t i=0; i<Size(); i++) if(remove.find((*this)[i])==remove.end()) ret.AddList((*this)[i]); } else { vector<Data>::const_iterator i; for(i=arg.vec.begin(); i!=arg.vec.end(); i++) remove.insert(*i); for(i=vec.begin(); i!=vec.end(); i++) if(remove.find(*i)==remove.end()) ret.AddList(*i); } return ret; } throw LangErr("Data::operator-const Data& )","Incompatible operands"); }
/// have_list(user asking, user target) - Return a list of cards which target user has more than /// his trade_limit or has at least one for sale; and asking user has in his want list. Data Server::have_list(const Data& args) { if(!args.IsList(2) || !args[0].IsString() || !args[1].IsString()) ArgumentError("have_list",args); if(!IsUser(args[0])) throw LangErr("have_list","invalid user "+tostr(args[0]).String()); if(!IsUser(args[1])) throw LangErr("have_list","invalid user "+tostr(args[0]).String()); VAR(asker,"users"); // asker=users{args} MAP(asker,args[0]); // asker=users{args[0]} VEC(asker,2); // asker=users{args[0]}[2] VAR(user,"users"); MAP(user,args[1]); // users=users{args[1]} // Find the limit Data *limit; VECTO(user,3,limit); // limit=users{args[1]}[3] VEC(limit,0); // limit=users{args[1]}[3][0] MAP(limit,Data("trade_limit"));// limit=users{args[1]}[3][0]{"trade_limit"} int trade_limit; if(limit->IsNull()) trade_limit=4; else trade_limit=limit->Integer(); // Check all cards Data ret; Data *cards,*entry; VECTO(user,2,cards); // cards=users{args}[2] ret.MakeList(); for(size_t i=0; i<cards->Size(); i++) { if((*cards)[i][1][1] > 0 || (*cards)[i][1][0].Integer() > trade_limit) { // Add only wanted cards MAPTO(asker,(*cards)[i][0],entry); if(entry->IsNull()) *entry=NewCard(); if((*entry)[1] < 0) ret.AddList((*cards)[i][0]); } } return ret; }
/// get_card_data(user,card list) - Return a list of full update entries for cards given. /// check the validity of all arguments and return NULL if some of the arguments /// are not valid. Data Server::get_card_data(const Data& args) { if(!args.IsList(2) || !args[0].IsString()) ArgumentError("get_card_data",args); if(!IsUser(args[0])) throw LangErr("get_card_data","invalid user "+args.String()); if(!args[1].IsList()) return Data(); VAR(collection,"users"); MAP(collection,args[0]); VEC(collection,2); const Data& L=args[1]; Data ret; ret.MakeList(); Data entry; entry.MakeList(5); Data price; Data* card_data; for(size_t i=0; i<L.Size(); i++) { if(!L[i].IsInteger()) return Data(); int card=L[i].Integer(); if(card < 0) return Data(); // Get price data price=price_list(L[i]); if(price.IsNull()) { entry[1]=0.0; entry[2]=""; } else { entry[1]=price[1][1]; entry[2]=price[1][0]; } // Get collection data if(collection->HasKey(L[i])) { MAPTO(collection,L[i],card_data); entry[0]=(*card_data)[0]; entry[3]=(*card_data)[2]; entry[4]=(*card_data)[1]; } else { entry[0]=0; entry[3]=0.0; entry[4]=0; } ret.AddList(Data(L[i],entry)); } if(ret.Size()) return ret; return Data(); }
/// price_list(list of card numbers or single card number) - With /// single card number argument, return the best offer for the card /// in format (card numer,(seller,price)). If there are not any /// cards for sale, return NULL. If a list of card numbers /// is given, return list of the prices for those cards. Without any /// arguments, return the full list of all prices. NULLs are removed /// when returning a list. Data Server::price_list(const Data& args) { if(args.IsInteger()) { int card_number=args.Integer(); VAR(prices,"prices"); // Create empty return value entry: // // (card number,("",0.0)) // Data ret(card_number,Data(string(""),0.0)); // Check if there are any prices. if(!prices->HasKey(card_number)) return Null; // Price list for the card Data& P=(*prices->FindKey(args))[1]; double price,minprice=0.0; bool first=true; list<string> sellers; list<int> seller_index; // Scan through pairs P[j]=(seller,price) and find the best offer for(size_t j=0; j<P.Size(); j++) { price=P[j][1].Real(); if(first || price < minprice) { first=false; minprice=price; sellers.clear(); seller_index.clear(); sellers.push_back(P[j][0].String()); seller_index.push_back(j); } else if(price==minprice) { sellers.push_back(P[j][0].String()); seller_index.push_back(j); } } ret[1][1]=minprice; if(sellers.size()==0) return Null; else if(sellers.size()==1) ret[1][0]=sellers.front(); else ret[1][0]=string(ToString(sellers.size())+" sellers"); return ret; } else if(args.IsList()) { Data ret; ret.MakeList(); Data e; for(size_t i=0; i<args.Size(); i++) { e=price_list(args[i]); if(!e.IsNull()) ret.AddList(e); } return ret; } else if(args.IsNull()) { VAR(prices,"prices"); return price_list(prices->Keys()); } else ArgumentError("price_list",args); return Null; }