trade.js
1 'use strict'; 2 3 import {CONST} from './const.js'; 4 import {default as $} from 'jquery'; 5 import {adjacent} from './adjacent.js'; 6 7 const GEN = Symbol(), SOCKET = Symbol(), PLAYER = Symbol(); 8 9 export class Trade { 10 constructor(g, s, p) { 11 this[GEN] = g; 12 this[SOCKET] = s; 13 this[PLAYER] = p; 14 } 15 16 hideOverlay() { 17 $('#request-overlay') 18 .css('display', 'none'); 19 $('#request-form') 20 .html(''); 21 } 22 23 buttonShow(data) { 24 if(data.players[this[PLAYER]].hand[CONST.RESOURCE].reduce((p, c) => p + c, 0) > 0) { 25 $('#init-trade') 26 .css('display', 'block') 27 .off('click') 28 .click(() => { 29 this[GEN].next([null, [data, 'trade']]); 30 }); 31 } 32 } 33 buttonHide() { 34 $('#init-trade') 35 .css('display', 'block') 36 .off('click'); 37 } 38 39 storage(cards) { 40 this[SOCKET].emit('trade:storage', cards, (err, res) => { 41 this[GEN].next([err, res]); 42 this.hideOverlay(); 43 }); 44 } 45 offer(cards) { 46 this[SOCKET].emit('trade:offer', cards, (err, res) => { 47 this[GEN].next([err, res]); 48 }); 49 $('#request-form') 50 .html('<h1>Waiting for responses...</h1>'); 51 } 52 offerShow(data) { 53 let resourceNames = ['wool', 'wheat', 'wood', 'brick', 'ore']; 54 let arrangeCards = () => { 55 $('#to-keep,#to-give,#to-take').each(function() { 56 let spacing = 50; 57 while(spacing * $(this).children('.card').length > $(this).width()) { 58 spacing--; 59 } 60 $(this).children('.card').each(function(i) { 61 $(this).css('left', `${i * spacing}px`); 62 }); 63 }); 64 if($('#to-give').children('.card').length >= 1 && $('#to-take').children('.card').length >= 1) { 65 $('#trade-button') 66 .removeClass('not-clickable'); 67 } else { 68 $('#trade-button') 69 .addClass('not-clickable'); 70 } 71 72 //Storage validation 73 let validCount = 0; 74 let cards = [0,0,0,0,0]; 75 $('#to-give').children('.card') 76 .each(function(i) { 77 cards[$(this).attr('data-card-type')]++; 78 }); 79 let needed = [4,4,4,4,4]; 80 for(let i = 0; i < data.houses.length; i++) { 81 for(let j = 0; j < data.houses[i].length; j++) { 82 if(data.houses[i][j][1] === this[PLAYER]) { 83 let port = adjacent(i, j, 'house', 'port'); 84 if(port !== null) { 85 if(data.ports[port] === CONST.OTHER) { 86 for(let k = 0; k < 5; k++) { 87 needed[k] = Math.min(3, needed[k]); 88 } 89 } else { 90 needed[data.ports[port]] = 2; 91 } 92 } 93 } 94 } 95 } 96 for(let i = 0; i < 5; i++) { 97 if(cards[i] % needed[i] === 0) { 98 validCount += cards[i] / needed[i]; 99 } else { 100 validCount = false; 101 break; 102 } 103 } 104 if(validCount && validCount === $('#to-take').children('.card').length) { 105 $('#storage-button') 106 .removeClass('not-clickable'); 107 } else { 108 $('#storage-button') 109 .addClass('not-clickable'); 110 } 111 }; 112 let addToTake = (res) => () => { 113 $('#to-take') 114 .append($('<div></div>') 115 .addClass(`card ${resourceNames[res]}`) 116 .attr('data-card-type', res) 117 .css('cursor', 'pointer') 118 .click(function() { 119 $(this).remove(); 120 arrangeCards(); 121 }) 122 ); 123 arrangeCards(); 124 }; 125 126 $('#request-overlay').css('display', 'block'); 127 $('#request-form') 128 .append($('<h2></h2>') 129 .text('Trade') 130 ) 131 .append($('<p></p>') 132 .text('To give') 133 ) 134 .append($('<hr>')) 135 .append($('<div></div>') 136 .addClass('card-container') 137 .attr('id', 'to-give') 138 ) 139 .append($('<p></p>') 140 .text('Your cards') 141 ) 142 .append($('<hr>')) 143 .append($('<div></div>') 144 .addClass('card-container') 145 .attr('id', 'to-keep') 146 ) 147 .append($('<p></p>') 148 .text('To take') 149 ) 150 .append($('<hr>')) 151 .append($('<div></div>') 152 .addClass('card-container') 153 .attr('id', 'to-take') 154 ) 155 .append($('<hr>')) 156 .append($('<div></div>') 157 .addClass('card-container') 158 .attr('id', 'to-choose') 159 .append($('<div></div>') 160 .addClass('resource-container') 161 .append($('<div></div>') 162 .addClass('card wool') 163 .css('cursor', 'pointer') 164 .click(addToTake(CONST.WOOL)) 165 ) 166 .append($('<div></div>') 167 .addClass('card wheat') 168 .css('cursor', 'pointer') 169 .click(addToTake(CONST.WHEAT)) 170 ) 171 .append($('<div></div>') 172 .addClass('card wood') 173 .css('cursor', 'pointer') 174 .click(addToTake(CONST.WOOD)) 175 ) 176 .append($('<div></div>') 177 .addClass('card brick') 178 .css('cursor', 'pointer') 179 .click(addToTake(CONST.BRICK)) 180 ) 181 .append($('<div></div>') 182 .addClass('card ore') 183 .css('cursor', 'pointer') 184 .click(addToTake(CONST.ORE)) 185 ) 186 ) 187 ) 188 .append($('<button></button>') 189 .text('Trade') 190 .attr('id', 'trade-button') 191 .click(() => { 192 let cards = { 193 give: [0,0,0,0,0], 194 get: [0,0,0,0,0] 195 }; 196 $('#to-give').children('.card') 197 .each(function(i) { 198 cards.give[$(this).attr('data-card-type')]++; 199 }); 200 $('#to-take').children('.card') 201 .each(function(i) { 202 cards.get[$(this).attr('data-card-type')]++; 203 }); 204 this.offer(cards); 205 }) 206 ) 207 .append($('<button></button>') 208 .text('Trade with storage') 209 .attr('id', 'storage-button') 210 .click(() => { 211 let cards = { 212 give: [0,0,0,0,0], 213 get: [0,0,0,0,0] 214 }; 215 $('#to-give').children('.card') 216 .each(function(i) { 217 cards.give[$(this).attr('data-card-type')]++; 218 }); 219 $('#to-take').children('.card') 220 .each(function(i) { 221 cards.get[$(this).attr('data-card-type')]++; 222 }); 223 this.storage(cards); 224 }) 225 ) 226 .append($('<button></button>') 227 .text('Cancel') 228 .click(() => { 229 this.hideOverlay(); 230 this[GEN].next([null, data]); 231 }) 232 ); 233 234 let hand = new Array(...data.players[this[PLAYER]].hand[CONST.RESOURCE]); 235 let give = $('#to-give'); 236 let keep = $('#to-keep'); 237 238 let moveToGive, moveToKeep; 239 moveToKeep = function() { 240 $(this).detach() 241 .appendTo(keep) 242 .off('click') 243 .click(moveToGive); 244 arrangeCards(); 245 }; 246 moveToGive = function() { 247 $(this).detach() 248 .appendTo(give) 249 .off('click') 250 .click(moveToKeep); 251 arrangeCards(); 252 }; 253 for(let i = 0; i < 5; i++) { 254 for(let j = 0; j < hand[i]; j++) { 255 keep 256 .append($('<div></div>') 257 .addClass(`card ${resourceNames[i]}`) 258 .css('cursor', 'pointer') 259 .attr('data-card-type', i) 260 .click(moveToGive) 261 ); 262 } 263 } 264 arrangeCards(); 265 } 266 267 respond(offer) { 268 this[SOCKET].emit('trade:respond', offer, (err, res) => { 269 this[GEN].next([err, res]); 270 }); 271 this.hideOverlay(); 272 } 273 counterOfferShow(data) { 274 let resourceNames = ['wool', 'wheat', 'wood', 'brick', 'ore']; 275 let arrangeCards = () => { 276 $('#to-keep,#to-give,#to-take').each(function() { 277 let spacing = 50; 278 while(spacing * $(this).children('.card').length > $(this).width()) { 279 spacing--; 280 } 281 $(this).children('.card').each(function(i) { 282 $(this).css('left', `${i * spacing}px`); 283 }); 284 }); 285 if($('#to-give').children('.card').length >= 1 && $('#to-take').children('.card').length >= 1) { 286 $('#trade-button') 287 .removeClass('not-clickable'); 288 } else { 289 $('#trade-button') 290 .addClass('not-clickable'); 291 } 292 }; 293 294 let addToTake = (res) => () => { 295 $('#to-take') 296 .append($('<div></div>') 297 .addClass(`card ${resourceNames[res]}`) 298 .attr('data-card-type', res) 299 .css('cursor', 'pointer') 300 .click(function() { 301 $(this).remove(); 302 arrangeCards(); 303 }) 304 ); 305 arrangeCards(); 306 }; 307 308 $('#request-overlay').css('display', 'block'); 309 $('#request-form') 310 .html('') 311 .css('display', 'block') 312 .append($('<h2></h2>') 313 .text('Trade') 314 ) 315 .append($('<p></p>') 316 .text('To give') 317 ) 318 .append($('<hr>')) 319 .append($('<div></div>') 320 .addClass('card-container') 321 .attr('id', 'to-give') 322 ) 323 .append($('<p></p>') 324 .text('Your cards') 325 ) 326 .append($('<hr>')) 327 .append($('<div></div>') 328 .addClass('card-container') 329 .attr('id', 'to-keep') 330 ) 331 .append($('<p></p>') 332 .text('To take') 333 ) 334 .append($('<hr>')) 335 .append($('<div></div>') 336 .addClass('card-container') 337 .attr('id', 'to-take') 338 ) 339 .append($('<hr>')) 340 .append($('<div></div>') 341 .addClass('card-container') 342 .attr('id', 'to-choose') 343 .append($('<div></div>') 344 .addClass('resource-container') 345 .append($('<div></div>') 346 .addClass('card wool') 347 .css('cursor', 'pointer') 348 .click(addToTake(CONST.WOOL)) 349 ) 350 .append($('<div></div>') 351 .addClass('card wheat') 352 .css('cursor', 'pointer') 353 .click(addToTake(CONST.WHEAT)) 354 ) 355 .append($('<div></div>') 356 .addClass('card wood') 357 .css('cursor', 'pointer') 358 .click(addToTake(CONST.WOOD)) 359 ) 360 .append($('<div></div>') 361 .addClass('card brick') 362 .css('cursor', 'pointer') 363 .click(addToTake(CONST.BRICK)) 364 ) 365 .append($('<div></div>') 366 .addClass('card ore') 367 .css('cursor', 'pointer') 368 .click(addToTake(CONST.ORE)) 369 ) 370 ) 371 ) 372 .append($('<button></button>') 373 .text('Send offer') 374 .attr('id', 'trade-button') 375 .click(() => { 376 let cards = { 377 give: [0,0,0,0,0], 378 get: [0,0,0,0,0] 379 }; 380 $('#to-give').children('.card') 381 .each(function(i) { 382 cards.get[$(this).attr('data-card-type')]++; 383 }); 384 $('#to-take').children('.card') 385 .each(function(i) { 386 cards.give[$(this).attr('data-card-type')]++; 387 }); 388 this.respond(cards); 389 }) 390 ) 391 .append($('<button></button>') 392 .text('Cancel (reject)') 393 .click(() => { 394 this.respond({response: false}); 395 }) 396 ); 397 398 let hand = new Array(...data.players[this[PLAYER]].hand[CONST.RESOURCE]); 399 let give = $('#to-give'); 400 let keep = $('#to-keep'); 401 let take = $('#to-take'); 402 403 let moveToGive, moveToKeep; 404 moveToKeep = function() { 405 $(this).detach() 406 .appendTo(keep) 407 .off('click') 408 .click(moveToGive); 409 arrangeCards(); 410 }; 411 moveToGive = function() { 412 $(this).detach() 413 .appendTo(give) 414 .off('click') 415 .click(moveToKeep); 416 arrangeCards(); 417 }; 418 for(let i = 0; i < 5; i++) { 419 for(let j = 0; j < data.trade.get[i]; j++) { 420 if(hand[i]) { 421 give 422 .append($('<div></div>') 423 .addClass(`card ${resourceNames[i]}`) 424 .css('cursor', 'pointer') 425 .attr('data-card-type', i) 426 .click(moveToKeep) 427 ); 428 hand[i]--; 429 } 430 } 431 } 432 for(let i = 0; i < 5; i++) { 433 for(let j = 0; j < data.trade.give[i]; j++) { 434 take 435 .append($('<div></div>') 436 .addClass(`card ${resourceNames[i]}`) 437 .css('cursor', 'pointer') 438 .attr('data-card-type', i) 439 .click(function() { 440 $(this).remove(); 441 arrangeCards(); 442 }) 443 ); 444 } 445 } 446 for(let i = 0; i < hand.length; i++) { 447 for(let j = 0; j < hand[i]; j++) { 448 keep 449 .append($('<div></div>') 450 .addClass(`card ${resourceNames[i]}`) 451 .css('cursor', 'pointer') 452 .attr('data-card-type', i) 453 .click(moveToGive) 454 ); 455 } 456 } 457 arrangeCards(); 458 } 459 counter(data) { 460 let arrangeCards = () => { 461 $('#to-give,#to-take').each(function() { 462 let spacing = 50; 463 while(spacing * $(this).children('.card').length > $(this).width()) { 464 spacing--; 465 } 466 $(this).children('.card').each(function(i) { 467 $(this).css('left', `${i * spacing}px`); 468 }); 469 }); 470 }; 471 $('#request-overlay').css('display', 'block'); 472 $('#request-form') 473 .append($('<h2></h2>') 474 .text(`Trade offer from ${data.trade.player}`) 475 ) 476 .append($('<p></p>') 477 .text('You give') 478 ) 479 .append($('<hr>')) 480 .append($('<div></div>') 481 .addClass('card-container') 482 .attr('id', 'to-give') 483 ) 484 .append($('<p></p>') 485 .text('You get') 486 ) 487 .append($('<hr>')) 488 .append($('<div></div>') 489 .addClass('card-container') 490 .attr('id', 'to-take') 491 ) 492 .append($('<button></button>') 493 .text('Accept') 494 .attr('id', 'accept-button') 495 .click(() => { 496 this.respond({response: true}); 497 }) 498 ) 499 .append($('<button></button>') 500 .text('Reject') 501 .click(() => { 502 this.respond({response: false}); 503 }) 504 ) 505 .append($('<button></button>') 506 .text('Make a counter offer') 507 .click(() => { 508 this.counterOfferShow(data); 509 }) 510 ); 511 let take = $('#to-take'); 512 let give = $('#to-give'); 513 let resourceNames = ['wool', 'wheat', 'wood', 'brick', 'ore']; 514 for(let i = 0; i < 5; i++) { 515 if(data.trade.get[i] > data.players[this[PLAYER]].hand[CONST.RESOURCE][i]) { 516 $('#accept-button') 517 .addClass('not-clickable'); 518 } 519 for(let j = 0; j < data.trade.get[i]; j++) { 520 give 521 .append($('<div></div>') 522 .addClass(`card ${resourceNames[i]}`) 523 ); 524 } 525 for(let j = 0; j < data.trade.give[i]; j++) { 526 take 527 .append($('<div></div>') 528 .addClass(`card ${resourceNames[i]}`) 529 ); 530 } 531 } 532 arrangeCards(); 533 } 534 reject() { 535 this[SOCKET].emit('trade:reject', null, (err, res) => { 536 this[GEN].next([err, res]); 537 }); 538 this.hideOverlay(); 539 } 540 accept(name) { 541 this[SOCKET].emit('trade:accept', name, (err, res) => { 542 this[GEN].next([err, res]); 543 }); 544 this.hideOverlay(); 545 } 546 547 offersShow(data) { 548 let resourceNames = ['wool', 'wheat', 'wood', 'brick', 'ore']; 549 $('#request-overlay').css('display', 'block'); 550 let form = $('#request-form') 551 .html('') 552 .append($('<h2></h2>') 553 .text('Choose an offer') 554 ); 555 for(let name in data.players) { 556 if(name !== this[PLAYER]) { 557 if(data.players[name].response.trade.response === false) { 558 form 559 .append($('<div></div>') 560 .addClass('trade-offer') 561 .append($('<h2></h2>') 562 .text(`${name} rejected your offer`) 563 ) 564 ); 565 } else if(data.players[name].response.trade.response === true) { 566 form 567 .append($('<div></div>') 568 .addClass('trade-offer') 569 .append($('<h2></h2>') 570 .text(`${name} accepted your offer`) 571 ) 572 .append($('<div></div>') 573 .addClass('trade-left') 574 .append($('<p></p>') 575 .text('Give') 576 ) 577 .append($('<div></div>') 578 .addClass('card-container small') 579 .attr('id', `for-${name}`) 580 ) 581 .append($('<p></p>') 582 .text('Get') 583 ) 584 .append($('<div></div>') 585 .addClass('card-container small') 586 .attr('id', `from-${name}`) 587 ) 588 ) 589 .append($('<button></button>') 590 .text('Accept') 591 .click(() => { 592 this.accept(name); 593 }) 594 ) 595 ); 596 let give = $(`#for-${name}`); 597 let get = $(`#from-${name}`); 598 for(let i = 0; i < 5; i++) { 599 for(let j = 0; j < data.trade.give[i]; j++) { 600 give 601 .append($('<div></div>') 602 .addClass(`card ${resourceNames[i]}`) 603 ); 604 } 605 for(let j = 0; j < data.trade.get[i]; j++) { 606 get 607 .append($('<div></div>') 608 .addClass(`card ${resourceNames[i]}`) 609 ); 610 } 611 } 612 } else { 613 form 614 .append($('<div></div>') 615 .addClass('trade-offer') 616 .append($('<h2></h2>') 617 .text(`${name} offers:`) 618 ) 619 .append($('<div></div>') 620 .addClass('trade-left') 621 .append($('<p></p>') 622 .text('Give') 623 ) 624 .append($('<div></div>') 625 .addClass('card-container small') 626 .attr('id', `for-${name}`) 627 ) 628 .append($('<p></p>') 629 .text('Get') 630 ) 631 .append($('<div></div>') 632 .addClass('card-container small') 633 .attr('id', `from-${name}`) 634 ) 635 ) 636 .append($('<button></button>') 637 .text('Accept') 638 .click(() => { 639 this.accept(name); 640 }) 641 ) 642 ); 643 let give = $(`#for-${name}`); 644 let get = $(`#from-${name}`); 645 for(let i = 0; i < 5; i++) { 646 for(let j = 0; j < data.players[name].response.trade.give[i]; j++) { 647 give 648 .append($('<div></div>') 649 .addClass(`card ${resourceNames[i]}`) 650 ); 651 } 652 for(let j = 0; j < data.players[name].response.trade.get[i]; j++) { 653 get 654 .append($('<div></div>') 655 .addClass(`card ${resourceNames[i]}`) 656 ); 657 } 658 } 659 } 660 } 661 } 662 form.append($('<button></button>') 663 .text('Accept none') 664 .click(() => { 665 this.reject(); 666 }) 667 ); 668 $('.card-container').each(function() { 669 let spacing = 25; 670 while(spacing * $(this).children('.card').length > $(this).width()) { 671 spacing--; 672 } 673 $(this).children('.card').each(function(i) { 674 $(this).css('left', `${i * spacing}px`); 675 }); 676 }); 677 } 678 }