shop.py
  1  from typing import Any
  2  
  3  from .command import command, CommandError
  4  from .help import print_help
  5  from .morphcoin import get_wallet_from_file
  6  from ..client import Client
  7  from ..context import DeviceContext
  8  from ..exceptions import ItemNotFoundError, NotEnoughCoinsError
  9  from ..models import Wallet, ShopCategory, ShopProduct
 10  from ..util import strip_float, print_tree
 11  
 12  
 13  def list_shop_products(client: Client) -> dict[str, ShopProduct]:
 14      out = {}
 15      for category in ShopCategory.shop_list(client):
 16          for subcategory in category.subcategories:
 17              for item in subcategory.items:
 18                  out[item.name.replace(" ", "")] = item
 19          for item in category.items:
 20              out[item.name.replace(" ", "")] = item
 21      return out
 22  
 23  
 24  @command("shop", [DeviceContext])
 25  def handle_shop(context: DeviceContext, args: list[str]) -> None:
 26      """
 27      Buy new hardware and more in the shop
 28      """
 29  
 30      if args:
 31          raise CommandError("Unknown subcommand.")
 32      print_help(context, handle_shop)
 33  
 34  
 35  @handle_shop.subcommand("list")
 36  def handle_shop_list(context: DeviceContext, _: Any) -> None:
 37      """
 38      List shop prodcuts
 39      """
 40  
 41      categories: list[ShopCategory] = ShopCategory.shop_list(context.client)
 42      maxlength = max(
 43          *[len(item.name) + 4 for category in categories for item in category.items],
 44          *[
 45              len(item.name)
 46              for category in categories
 47              for subcategory in category.subcategories
 48              for item in subcategory.items
 49          ],
 50      )
 51      tree = []
 52      for category in categories:
 53          category_tree = []
 54          for subcategory in category.subcategories:
 55              subcategory_tree: list[tuple[str, list[Any]]] = [
 56                  (item.name.ljust(maxlength) + strip_float(item.price / 1000, 3) + " MC", [])
 57                  for item in subcategory.items
 58              ]
 59              category_tree.append((subcategory.name, subcategory_tree))
 60  
 61          for item in category.items:
 62              category_tree.append((item.name.ljust(maxlength + 4) + strip_float(item.price / 1000, 3) + " MC", []))
 63  
 64          tree.append((category.name, category_tree))
 65  
 66      print("Shop")
 67      print_tree(tree)
 68  
 69  
 70  @handle_shop.subcommand("buy")
 71  def handle_shop_buy(context: DeviceContext, args: list[str]) -> None:
 72      """
 73      Buy something in the shop
 74      """
 75  
 76      if len(args) != 2:
 77          raise CommandError("usage: shop buy <product> <wallet>")
 78  
 79      product_name, wallet_filepath = args
 80  
 81      wallet: Wallet = get_wallet_from_file(context, wallet_filepath)
 82  
 83      shop_products: dict[str, ShopProduct] = list_shop_products(context.client)
 84      if product_name not in shop_products:
 85          raise CommandError("This product does not exist in the shop.")
 86      product: ShopProduct = shop_products[product_name]
 87  
 88      try:
 89          product.buy(wallet)
 90      except ItemNotFoundError:
 91          raise CommandError("This product does not exist in the shop.")
 92      except NotEnoughCoinsError:
 93          raise CommandError("You don't have enough coins on your wallet to buy this product.")
 94  
 95  
 96  @handle_shop_buy.completer()
 97  def shop_completer(context: DeviceContext, args: list[str]) -> list[str]:
 98      if len(args) == 1:
 99          return list(list_shop_products(context.client))
100      if len(args) == 2:
101          return context.file_path_completer(args[1])
102      return []