GW2 added by Demo on Thu Apr 27 17:34:22 2017

(define (build-or-buy qty item-id #!optional (buy-type 'asking) (unbuyable-cost 0))

  (let* ( (item-craftable (craftable? item-id))
		  (item-buyable   (query-price item-id))
		  (item-name      (query-item-name item-id))
		  (purchase-price (* qty (cassoc buy-type item-buyable 0)))
		  (outcome        (list (cons item-id qty)))
		  (msgfmt         (lambda (msg-type msg-qty msg-name msg-bought msg-craft msg-buy)
							(list (fmt #f
									   " | " (fit 10 msg-type)
									   " | " (fit/left 10 msg-qty)
									   " | " (fit 30 msg-name)
									   " | " (fit/left 10 msg-bought)
									   " | " (fit/left 10 msg-craft)
									   " | " (fit/left 10 msg-buy)
									   " | " " | " nl))))

		  (purchase-item  (lambda (msg)
							(if item-buyable

								;; buyable, return bought
								`( (spent     .  ,purchase-price)
								   (inv       .  ,outcome)
								   (bought    .  ,outcome)
								   (unbuyable .  ())
								   (messages  .  ,(msgfmt "Buy" qty item-name purchase-price "" msg)))

								;; not buyable, return it as such
								`( (spent     . ,unbuyable-cost)
								   (inv       . ,outcome)
								   (bought    . ())
								   (unbuyable . ,outcome)
								   (messages  . ,(msgfmt "Quest" qty item-name "" msg ""))) ))))

	(if (not item-craftable)

		;; buy it
		(purchase-item (fit/left 30 ""))

		;; craft it
		(let* ( (recipe        (query-recipe-by-item item-id))
				(batches       (ceiling (/ qty (cassoc 'output_item_count recipe))))
				(parts         (map (lambda (x) (cons (car x) (* batches (cdr x)))) (query-parts-by-item item-id)))
				(result        (map (lambda (x) (build-or-buy (cdr x) (car x) buy-type)) parts))
				(crafting-cost (fold + 0 (map (lambda (x) (cassoc 'spent x 0)) result)))
				(map-result    (lambda (k) (map (lambda (x) (cassoc k x '())) result)))
				)

		  (if (and (> crafting-cost purchase-price) item-buyable)

			  ;; buy it
			  (purchase-item (fit/left 10 crafting-cost))

			  ;; craft it
			  (list (cons 'spent      crafting-cost) ; sum of spent amount
					(cons 'bought     (fold merge-inventories '() (map-result 'bought)))
					(cons 'unbuyable  (fold merge-inventories '() (map-result 'unbuyable)))

					;; must sum together all the bought parts into inventory, and then remove items consumed by the recipe
					(cons 'inv        (fold merge-inventories '() (list (negate-inventory parts) ; the negated recipe, parts is already multiplied by batches
																		(list (cons item-id (* batches (cassoc 'output_item_count recipe 0)))) ; the crafting result
																		(fold merge-inventories '() (map-result 'inv)) ))) ; the recursion results

					(cons 'crafted    (fold merge-inventories (list (cons item-id (* batches (cassoc 'output_item_count recipe 0)))) ; the crafting result
											(map-result 'crafted)))

					(cons 'messages   (fold append
											(msgfmt "Craft" batches item-name "" crafting-cost purchase-price)
											(map-result 'messages))) ))))))



#;140> (pretty-print-build (build-or-buy 1 13459))
Spent:      36739
Result:
 - [ ]     1 (13459) Ruby Orichalcum Earrin

Bought:
 - [ ]    28 (19701) Orichalcum Ore        
 - [ ]     5 (19721) Glob of Ectoplasm     
 - [ ]    25 (24276) Pile of Incandescent D
 - [ ]    10 (24474) Ruby Crystal          

Quest:

Recipes to craft:
 - [ ]    14 (19685) Orichalcum Ingot      
 - [ ]     1 (12815) Orichalcum Setting    
 - [ ]     1 (12809) Orichalcum Hook       
 - [ ]     5 (12834) Orichalcum Filigree   
 - [ ]     5 (24508) Ruby Orb              
 - [ ]     5 (24498) Exquisite Ruby Jewel  
 - [ ]     1 (13459) Ruby Orichalcum Earrin

Messages:
 |------------+------------+--------------------------------+------------+------------+------------+--|
 | Buy        |          4 | Orichalcum Ore                 |       1132 |            |            |  | 
 | Craft      |          2 | Orichalcum Ingot               |            |       1132 |       1142 |  | 
 | Craft      |          1 | Orichalcum Setting             |            |       1132 |       1599 |  | 
 | Buy        |          4 | Orichalcum Ore                 |       1132 |            |            |  | 
 | Craft      |          2 | Orichalcum Ingot               |            |       1132 |       1142 |  | 
 | Craft      |          1 | Orichalcum Hook                |            |       1132 |       1417 |  | 
 | Buy        |          5 | Glob of Ectoplasm              |      17610 |            |            |  | 
 | Buy        |         20 | Orichalcum Ore                 |       5660 |            |            |  | 
 | Craft      |         10 | Orichalcum Ingot               |            |       5660 |       5710 |  | 
 | Craft      |          5 | Orichalcum Filigree            |            |       5660 |       9470 |  | 
 | Buy        |         25 | Pile of Incandescent Dust      |       7975 |            |            |  | 
 | Buy        |         10 | Ruby Crystal                   |       3230 |            |      19160 |  | 
 | Craft      |          5 | Ruby Orb                       |            |      11205 |      11500 |  | 
 | Craft      |          5 | Exquisite Ruby Jewel           |            |      34475 |      36575 |  | 
 | Craft      |          1 | Ruby Orichalcum Earring        |            |      36739 |      40805 |  | 
 |------------+------------+--------------------------------+------------+------------+------------+--|
 |            |            |                                |            |            |            |  |