|
|
| 956 |
962 |
|
| 47 | 47 |
|
| 48 | 48 | /** @noinspection FieldCanBeLocal*/
|
| 49 | 49 | private TimerHandler eQueue;
|
| 50 | | private Map<String, AuctionQObject> snipeMap = new HashMap<String, AuctionQObject>();
|
| 51 | 50 |
|
| 52 | 51 | /**< The full amount of time it takes to request a single page from this site. */
|
| 53 | 52 | private long mPageRequestTime =0;
|
| --- | --- | |
| 199 | 198 | return;
|
| 200 | 199 | }
|
| 201 | 200 | break;
|
| 202 | | case AuctionQObject.CANCEL_SNIPE:
|
| 203 | | cancelSnipe((EntryInterface) ac.getData());
|
| 204 | | return;
|
| 205 | | case AuctionQObject.SET_SNIPE:
|
| 206 | | setSnipe((AuctionEntry) ac.getData());
|
| 207 | | return;
|
| 208 | 201 | case AuctionQObject.BID:
|
| 209 | 202 | bidMsg(ac);
|
| 210 | 203 | return;
|
| --- | --- | |
| 293 | 286 | MQFactory.getConcrete("Swing").enqueue("IGNORE " + configBidMsg + ' ' + bidResultString);
|
| 294 | 287 | }
|
| 295 | 288 |
|
| 289 | private static final int THIRTY_SECONDS = 30 * Constants.ONE_SECOND;
|
| 290 | private static final long TWO_MINUTES = Constants.ONE_MINUTE * 2;
|
| 291 |
|
| 296 | 292 | public void setSnipe(AuctionEntry snipeOn) {
|
| 297 | | AuctionQObject currentlyExists = snipeMap.get(snipeOn.getIdentifier());
|
| 293 | String identifier = snipeOn.getIdentifier();
|
| 294 | Date endDate = snipeOn.getEndDate();
|
| 295 | long snipeDelta = snipeOn.getSnipeTime();
|
| 298 | 296 | // If we already have a snipe set for it, first cancel the old one, and then set up the new.
|
| 299 | | if(currentlyExists != null) {
|
| 300 | | _etqm.erase(null, currentlyExists);
|
| 301 | | _etqm.erase(null, snipeOn);
|
| 302 | | snipeMap.remove(snipeOn.getIdentifier());
|
| 303 | | }
|
| 297 | _etqm.erase(identifier);
|
| 304 | 298 |
|
| 305 | | long two_minutes = Constants.ONE_MINUTE*2;
|
| 306 | | AuctionQObject payload = new AuctionQObject(AuctionQObject.SNIPE, new Snipe(mLogin, mBidder, snipeOn), null);
|
| 307 | |
|
| 308 | | if (snipeOn.getEndDate() != null && snipeOn.getEndDate() != Constants.FAR_FUTURE) {
|
| 309 | | _etqm.add(payload, mSnipeQueue, (snipeOn.getEndDate().getTime() - snipeOn.getSnipeTime()) - two_minutes);
|
| 310 | | _etqm.add(payload, mSnipeQueue, (snipeOn.getEndDate().getTime() - snipeOn.getSnipeTime()));
|
| 311 | | _etqm.add(snipeOn.getIdentifier(), "drop", snipeOn.getEndDate().getTime() + 30 * Constants.ONE_SECOND);
|
| 312 | | snipeMap.put(snipeOn.getIdentifier(), payload);
|
| 299 | if (endDate != null && endDate != Constants.FAR_FUTURE) {
|
| 300 | _etqm.add(identifier, mSnipeQueue, (endDate.getTime() - snipeDelta) - TWO_MINUTES);
|
| 301 | _etqm.add(identifier, mSnipeQueue, (endDate.getTime() - snipeDelta));
|
| 302 | _etqm.add(identifier, "drop", endDate.getTime() + THIRTY_SECONDS);
|
| 313 | 303 | }
|
| 314 | 304 | }
|
| 315 | 305 |
|
| 316 | | public void cancelSnipe(EntryInterface snipeCancel) {
|
| 317 | | String identifier = snipeCancel.getIdentifier();
|
| 318 | | AuctionQObject cancellable = snipeMap.get(identifier);
|
| 319 | |
|
| 306 | public void cancelSnipe(String identifier) {
|
| 320 | 307 | // Erase the pending snipe
|
| 321 | | _etqm.erase(null, cancellable);
|
| 322 | | // Erase the 30 seconds post-completion update
|
| 323 | | _etqm.erase(null, snipeCancel);
|
| 324 | |
|
| 325 | | snipeMap.remove(identifier);
|
| 308 | _etqm.erase(identifier);
|
| 326 | 309 | }
|
| 327 | 310 |
|
| 328 | 311 | public ebayServer(String site, String username, String password) {
|
| --- | --- | |
| 613 | 596 | MQFactory.getConcrete("Swing").enqueue("Done Getting Selling Items for " + userId);
|
| 614 | 597 | }
|
| 615 | 598 |
|
| 616 | | // TODO -- Wouldn't it be nice if this took an item number, and looked it up, instead of keeping a reference to the actual (potentially duplicated) object?
|
| 617 | 599 | private class SnipeListener implements MessageQueue.Listener {
|
| 600 | private Map<String, Snipe> mSnipeMap = new HashMap<String, Snipe>();
|
| 601 |
|
| 602 | /**
|
| 603 | * Retrieve a stored Snipe object if one exists (containing the cookie information),
|
| 604 | * or create a new one if one doesn't exist.
|
| 605 | *
|
| 606 | * @param identifier - The auction identifier to create the snipe for.
|
| 607 | *
|
| 608 | * @return - A Snipe object, either with a cookie object, or w/o. Returns
|
| 609 | * null if the AuctionEntry associated with the identifier does not exist
|
| 610 | * or is not sniped.
|
| 611 | */
|
| 612 | private Snipe getSnipe(String identifier) {
|
| 613 | AuctionEntry ae = EntryCorral.getInstance().takeForRead(identifier);
|
| 614 | if (ae == null || !ae.isSniped()) return null;
|
| 615 |
|
| 616 | Snipe snipe;
|
| 617 | if (mSnipeMap.containsKey(identifier)) {
|
| 618 | snipe = mSnipeMap.get(identifier);
|
| 619 | } else {
|
| 620 | snipe = new Snipe(mLogin, mBidder, ae);
|
| 621 | mSnipeMap.put(identifier, snipe);
|
| 622 | }
|
| 623 | return snipe;
|
| 624 | }
|
| 625 |
|
| 618 | 626 | public void messageAction(Object deQ) {
|
| 619 | | AuctionQObject ac = (AuctionQObject) deQ;
|
| 620 | | if (ac.getCommand() == AuctionQObject.SNIPE) {
|
| 621 | | Snipe snipe = (Snipe) ac.getData();
|
| 622 | | int snipeResult = snipe.fire();
|
| 623 | | switch(snipeResult) {
|
| 624 | | case Snipe.RESNIPE:
|
| 625 | | /**
|
| 626 | | * The formula for 'when' the next resnipe is, is a little complex.
|
| 627 | | * It's all in the code, though. If we're 3 seconds or less away,
|
| 628 | | * give up. Otherwise wait another 20% of the remaining time
|
| 629 | | * (minimum of 3 seconds), and retry.
|
| 630 | | */
|
| 631 | | long snipeIn = snipe.getItem().getEndDate().getTime() - _etqm.getCurrentTime();
|
| 632 | | if(snipeIn > Constants.THREE_SECONDS) {
|
| 633 | | long retry_wait = (snipeIn / 10) * 2;
|
| 634 | | if(retry_wait < Constants.THREE_SECONDS) retry_wait = Constants.THREE_SECONDS;
|
| 627 | String identifier = (String)deQ;
|
| 628 | Snipe snipe = getSnipe(identifier);
|
| 629 | if(snipe == null) return;
|
| 635 | 630 |
|
| 636 | | _etqm.add(deQ, mSnipeQueue, _etqm.getCurrentTime()+retry_wait);
|
| 637 | | break;
|
| 638 | | }
|
| 639 | | // If there are less than 3 seconds left, give up by falling through to FAIL and DONE.
|
| 640 | | JConfig.log().logDebug("Resnipes failed, and less than 3 seconds away. Giving up.");
|
| 641 | | case Snipe.FAIL:
|
| 642 | | _etqm.erase(null, deQ);
|
| 643 | | JConfig.log().logDebug("Snipe appears to have failed; cancelling.");
|
| 644 | | snipe.getItem().snipeFailed();
|
| 645 | | // A failed snipe is a serious, hard error, and should fall through to being removed from the snipe map.
|
| 646 | | case Snipe.DONE:
|
| 647 | | snipeMap.remove(snipe.getItem().getIdentifier());
|
| 631 | int snipeResult = snipe.fire();
|
| 632 | switch (snipeResult) {
|
| 633 | case Snipe.RESNIPE:
|
| 634 | /**
|
| 635 | * The formula for 'when' the next resnipe is, is a little complex.
|
| 636 | * It's all in the code, though. If we're 3 seconds or less away,
|
| 637 | * give up. Otherwise wait another 20% of the remaining time
|
| 638 | * (minimum of 3 seconds), and retry.
|
| 639 | */
|
| 640 | long snipeIn = snipe.getItem().getEndDate().getTime() - _etqm.getCurrentTime();
|
| 641 | if (snipeIn > Constants.THREE_SECONDS) {
|
| 642 | long retry_wait = (snipeIn / 10) * 2;
|
| 643 | if (retry_wait < Constants.THREE_SECONDS) retry_wait = Constants.THREE_SECONDS;
|
| 644 |
|
| 645 | _etqm.add(identifier, mSnipeQueue, _etqm.getCurrentTime() + retry_wait);
|
| 648 | 646 | break;
|
| 649 | | case Snipe.SUCCESSFUL:
|
| 650 | | default:
|
| 651 | | break;
|
| 652 | | }
|
| 647 | }
|
| 648 | // If there are less than 3 seconds left, give up by falling through to FAIL and DONE.
|
| 649 | JConfig.log().logDebug("Resnipes failed, and less than 3 seconds away. Giving up.");
|
| 650 | case Snipe.FAIL:
|
| 651 | _etqm.erase(identifier);
|
| 652 | JConfig.log().logDebug("Snipe appears to have failed; cancelling.");
|
| 653 | snipe.getItem().snipeFailed();
|
| 654 | // A failed snipe is a serious, hard error, and should fall through to being removed from any other lists.
|
| 655 | case Snipe.DONE:
|
| 656 | mSnipeMap.remove(identifier);
|
| 657 | break;
|
| 658 | case Snipe.SUCCESSFUL:
|
| 659 | default:
|
| 660 | break;
|
| 653 | 661 | }
|
| 654 | 662 | }
|
| 655 | 663 | }
|