Beispiel #1
0
def finance_fromusatoeu():
    editions = Gatherer.getEditions()
    usdtoeu = ExchangeRate.get("USDEUR=X")
    comisionmkm = 0.05  # comision que se queda mkm de las ventas
    undercut = 0.05  # undercut para vender
    ajustebeneficio = 0.15  # margen de perdida que asumo al vender de usa a eur (store credit me da 0.3)
    storecreditbonus = 0.3
    with open("output/usatoeu.csv", "w", newline='\n') as f:
        writer = csv.DictWriter(
            f,
            fieldnames=["set", "name", "foil", "ck", "mkm", "available"],
            delimiter=',',
            quotechar='"',
            quoting=csv.QUOTE_MINIMAL)
        writer.writeheader()
    # TODO: DEFINIR LO QUE ES POTENTIAL ---> marcar cuando es un staple y etc.
    sql = "select s.name as set, c.name as name, truefalse.value as foil, round(cast(ck.price * {} as numeric), 2) as ck, round(cast(mkm.price * {} as numeric), 2) as mkm, ck.available as available from scr_cards c CROSS JOIN truefalse left join scr_sets s on c.set = s.code left join ck_cardprices ck on c.idck = ck.card and truefalse.value = ck.foil left join mkm_cardpricesmin mkm on c.idmkm = mkm.id and truefalse.value = mkm.foil where (not mkm.name is null and not ck.card is null) and not s.digital and ck.available > 0 and ck.condition = 'NM'".format(
        usdtoeu, 1 - comisionmkm - undercut)
    cards = phppgadmin.query(sql)
    with open("output/usatoeu.csv", "a", newline='\n') as f:
        writer = csv.DictWriter(
            f,
            fieldnames=["set", "name", "foil", "ck", "mkm", "available"],
            delimiter=',',
            quotechar='"',
            quoting=csv.QUOTE_MINIMAL)
        for card in cards:
            card["ck"] = card["ck"].replace(".", ",")
            card["mkm"] = card["mkm"].replace(".", ",")
            writer.writerow(card)
Beispiel #2
0
 def normalizeEditions():
     print("TOTAL", len(phppgadmin.query("SELECT code FROM editions")))
     print(
         "CK UPDATES",
         phppgadmin.execute(
             "UPDATE editions SET code_ck = ck.id FROM ck_editions ck WHERE lower(ck.name) = lower(editions.name)"
         ))
     print(
         "MKM UPDATES",
         phppgadmin.execute(
             "UPDATE editions SET code_mkm = mkm.id FROM mkm_editions mkm WHERE lower(mkm.name) = lower(editions.name)"
         ))
Beispiel #3
0
 def getEditions():
     editions = []
     try:
         editions = phppgadmin.query(
             "select id, name, url from ck_editions")
     except:  #TODO: capturar excepcion que corresponda
         print("Using cached editions")
         editions = []
         with open("data/ck/editions.csv") as csvfile:
             reader = csv.DictReader(csvfile, delimiter="|")
             for row in reader:
                 editions.append(row)
     if (len(editions) == 0):
         CK.crawlEditions()
     return editions
Beispiel #4
0
 def getEditions():
     editions = []
     datadir = "data/mkm"
     datafile = "{}/editions.csv".format(datadir)
     try:
         editions = phppgadmin.query(
             "select id, name, url from mkm_editions")
     except:  #TODO: capturar excepcion que corresponda
         try:
             with open(datafile) as csvfile:
                 reader = csv.DictReader(csvfile, delimiter="|")
                 for row in reader:
                     editions.append(row)
         except:
             pass
     if (len(editions) == 0):
         editions = MKM.crawlEditions()
     return editions
def getAllPrices():
    cards = phppgadmin.query(
        "SELECT c.name, s.name as set, c.idmkm, s.isfoil FROM scr_cards c LEFT JOIN (select s1.code, s1.name, s1.set_type, s1.digital, false as isfoil from scr_sets s1 union all select s2.code, s2.name, s2.set_type, s2.digital, true as isfoil from scr_sets s2 where code not in ('lea','leb','2ed','cei','ced','arn','atq','3ed','leg','sum','drk','fem','4ed','ice','chr','hml','all','rqs','mir','mgb','itp','vis','5ed','por','wth','tmp','sth','p02','exo','ugl','usg','ath','6ed','ptk','s99','brb','s00','btd','dkm','phpr') and not foil) s on c.set = s.code WHERE	NOT idmkm IS NULL AND NOT s.digital	AND s.set_type in ('archenemy','commander','conspiracy','core','duel_deck','expansion','from_the_vault','masterpiece','planechase','premium_deck','starter')"
    )
    n = 1000
    # with open("output.csv", "w", newline='\n') as f:
    #     writer = csv.DictWriter(f, fieldnames=["idmkm", "price", "isfoil", "available", "seller", "itemlocation"], delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
    #     writer.writeheader()
    q = Queue()
    startTGetPriceData(6, q)
    for i in range((int)(len(cards) / n) + 1):
        print("i=", i)
        cardswprices = cards[i * n:i * n + n]
        try:
            for card in cardswprices:
                card["isFoil"] = True if card["isfoil"] == "TRUE" else False
                card["idLanguage"] = 1
                q.put(card)
            q.join()
        except KeyboardInterrupt:
            sys.exit(1)
        # a csv
        # with open("output.csv", "a", newline='\n') as f:
        #     writer = csv.DictWriter(f, fieldnames=["idmkm", "price", "isfoil", "available", "seller", "itemlocation"], delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
        #     for card in cardswprices:
        #         for price in card["prices"]:
        #             writer.writerow({ "idmkm": card["idmkm"], "price": price["price"], "isfoil": card["isfoil"], "available": price["available"], "seller": price["seller"], "itemlocation": price["itemlocation"] })
        # a db
        sql = ""
        for card in cardswprices:
            for price in card["prices"]:
                sql += "('{}',{},{},{},'{}','{}'),".format(
                    card["idmkm"], price["price"], card["isfoil"],
                    price["available"], price["seller"].replace("'", "''"),
                    price["itemlocation"])
        if sql != "":
            affected = phppgadmin.execute(
                "INSERT INTO mkm_cardprices(id,price,foil,available,seller,itemlocation) VALUES"
                + sql[:-1])
            print("Total prices inserted: {}".format(affected))
    # materialized view completa
    phppgadmin.execute(
        "DROP MATERIALIZED VIEW mkm_cardpricesranked;CREATE MATERIALIZED VIEW mkm_cardpricesranked AS SELECT id, price, foil, available, seller, itemlocation, dense_rank() OVER (PARTITION BY id,foil ORDER BY price ASC),first_value(price) OVER (PARTITION BY id,foil ORDER BY price ASC),lead(price) OVER (PARTITION BY id,foil ORDER BY price ASC) FROM mkm_cardprices WITH DATA; ALTER TABLE mkm_cardpricesranked OWNER TO postgres;"
    )
Beispiel #6
0
def mkmprocess_savestore():
    #phppgadmin.execute("delete from mkm_cardprices")
    sqlnextedition = "select e.code_mkm as id, e.name from editions e inner join mkm_editions mkm on e.code_mkm = mkm.id left join mkm_cardprices p on p.edition = mkm.id group by e.code_mkm, e.name, mkm.locked having count(p.card) = 0 and not mkm.locked limit 1"
    while True:
        editions = phppgadmin.query(sqlnextedition)
        if (len(editions) == 1):
            edition = editions[0]
            phppgadmin.execute(
                "update mkm_editions set locked = true where id = '{}'".format(
                    edition["id"]))
            print(edition["name"])
            cards = MKM.getPrices(edition)
            sql = ""
            for card in cards:
                for entry in card.entries:
                    sql += "('{}','{}',{},{},{},'{}','{}'),".format(
                        card.id, card.edition,
                        entry.price, entry.foil, entry.count,
                        entry.seller.replace("'", "''"), entry.location)
            if sql != "":
                affected = phppgadmin.execute(
                    "INSERT INTO mkm_cardprices(card,edition,price,foil,available,seller,itemlocation) VALUES"
                    + sql[:-1])
                print("Total prices inserted: {}".format(affected))
            else:
                print("No price data")
            phppgadmin.execute(
                "update mkm_editions set locked = false where id = '{}'".
                format(edition["id"]))
        else:
            break
    # Rehacer tabla de precios minimos cuando no hay mas ediciones a procesar
    if (phppgadmin.count("select id from mkm_editions where locked") == 0):
        print("Creando tabla de precios min para hoy (unos 5 minutos)")
        phppgadmin.execute(
            "DROP MATERIALIZED VIEW mkm_cardpricesmin;CREATE MATERIALIZED VIEW mkm_cardpricesmin AS SELECT mkm_cardprices.edition,mkm_cardprices.card as name, mkm_cardprices.foil, min(mkm_cardprices.price) AS price FROM mkm_cardprices GROUP BY mkm_cardprices.edition, mkm_cardprices.card, mkm_cardprices.foil WITH DATA; ALTER TABLE mkm_cardpricesmin OWNER TO postgres;"
        )
        print("Finished")
Beispiel #7
0
def finance_fromeutousa():
    editions = Gatherer.getEditions()
    usdtoeu = ExchangeRate.get("USDEUR=X")
    comisionporgastosdeenvio = 0.05
    precioparaenviocertificado = 25
    profittargetpct = 1.1

    sql = "select s.name as set, c.name as card, ck.foil as foil, ck.price * {0} as ck, mkm_offers.price as mkm, mkm_offers.seller as seller, mkm_offers.available as available from ck_buylist ck left join scr_cards c on ck.id = c.idck left join scr_sets s on c.set = s.code inner join (select id, foil, round(cast(((price * LEAST(available, 17)) + (select cost from mkm_shippingcosts sc where sc.from = itemlocation and sc.itemcount <= LEAST(available, 17) and tracked = price >= 25 order by itemcount desc limit 1)) / LEAST(available, 17) as numeric), 2) as price, LEAST(available, 17) as available, seller from mkm_cardprices) mkm_offers on mkm_offers.id = c.idmkm and mkm_offers.foil = ck.foil where mkm_offers.price < ck.price * {0}".format(
        usdtoeu - comisionporgastosdeenvio)
    cards = phppgadmin.query(sql)

    with open("output/eutousa.csv", "w", newline='\n') as f:
        writer = csv.DictWriter(f,
                                fieldnames=[
                                    "set", "card", "foil", "ck", "mkm",
                                    "seller", "available"
                                ],
                                delimiter=',',
                                quotechar='"',
                                quoting=csv.QUOTE_MINIMAL)
        writer.writeheader()
        for card in cards:
            writer.writerow(card)
Beispiel #8
0
 def getEditions():
     return phppgadmin.query(
         "SELECT code as id, name, code_ck, code_mkm FROM editions")
Beispiel #9
0
    def getPrices(edition=None):
        def do_work(item):
            carddir = MKM.cachedir.format("prices/{}/{}".format(
                edition["id"], item["card"].id))
            try:
                if not os.path.exists(carddir):
                    os.makedirs(carddir)
            except:
                pass
            cardpagecache = "{}/{}.html".format(
                carddir, "foil" if item["foil"] else "normal")
            try:
                f = open(cardpagecache, "r", encoding="utf8")
                data = f.read()
                f.close()
            except IOError:
                if item["foil"]:
                    filter = copy.copy(productFilter)
                    filter["productFilter[isFoil]"] = "Y"
                else:
                    filter = productFilter
                try:
                    resp = requests.post("{}/Products/Singles/{}/{}".format(
                        MKM.baseurl, item["card"].edition, item["card"].id),
                                         filter,
                                         headers={},
                                         timeout=10)
                    data = resp.text
                except:
                    data = ""
                # Proteccion contra respuestas vacias, encolamos de nuevo la solicitud
                if data != "":
                    with open(cardpagecache, "w", encoding="utf8") as f:
                        f.write(data)
                else:
                    print("Me tiran solicitud, relanzo en 10s")
                    q.put(item, True, 10)
            if data != "":
                tree = html.fromstring(data)
                for row in tree.xpath(
                        '//tbody[@id="articlesTable"]/tr[not(@class)]'):
                    itemlocation = row.xpath(
                        ".//td[@class='Seller']/span/span/span[@class='icon']"
                    )[0].attrib["onmouseover"]
                    itemlocation = re.search(reItemLocation,
                                             itemlocation).group(1)
                    seller = row.xpath(".//td[@class='Seller']/span/span/a"
                                       )[0].attrib["href"].replace(
                                           "/en/Magic/Users/", "")
                    price = row.xpath(".//td[contains(@class,'st_price')]"
                                      )[0].text_content().replace(",",
                                                                  ".").replace(
                                                                      "€", "")
                    available = row.xpath(
                        ".//td[contains(@class,'st_ItemCount')]"
                    )[0].text_content()
                    ppu = re.search(rPPU, price)
                    if not ppu is None:
                        price = ppu.group(1)
                        available = "4"
                    item["card"].entries.append(
                        CardDetails((float)(price), (int)(available),
                                    True if item["foil"] else False, "en",
                                    "NM", seller, itemlocation))
            sys.stdout.write("Elementos restantes: %d   \r" % q.qsize())
            sys.stdout.flush()

        def worker():
            while True:
                do_work(q.get())
                time.sleep(0.05)
                q.task_done()

        if (edition is None):
            editions = MKM.selectEdition()
        else:
            editions = [edition]
        sql = "select c.id as id, c.name as name, c.edition as edition, e.type as type from editions e left join mkm_cards c on c.edition = e.code_mkm where not e.code_mkm is null"
        if (len(editions) == 1):
            sql += " AND c.edition = '{}'".format(editions[0]["id"])
        dbcards = phppgadmin.query(sql)
        q = Queue()
        for i in range(MKM.maxthreads):
            t = threading.Thread(target=worker)
            t.daemon = True
            t.start()
        cards = []
        productFilter = {
            "productFilter[sellerRatings][]": ["1", "2"],
            "productFilter[idLanguage][]": [1],
            "productFilter[condition][]": ["MT", "NM"]
        }
        rPPU = '\(PPU: (.*?)\)'
        reItemLocation = "'Item location: (.*)'"
        for dbcard in dbcards:
            card = InventoryCard(dbcard["id"], dbcard["name"],
                                 dbcard["edition"])
            cards.append(card)
            q.put({"card": card, "foil": False})
            if dbcard["type"] == "3":
                q.put({"card": card, "foil": True})
        q.join()
        print("==[     END     ]==   ")
        return cards
Beispiel #10
0
    def buylist(writecsv=False):
        #TODO: numero dinamico de paginas
        print("==[ CK BUYLIST  ]==")

        def addCards(pagehtml):
            tree = html.fromstring(pagehtml)
            cardshtml = tree.xpath(
                "//div[contains(@class,'itemContentWrapper')]")
            for cardhtml in cardshtml:
                pricewrapper = cardhtml.xpath(".//span[@class='stylePrice']")
                # si no tiene precio es una premium card de las que hay que preguntar precio
                if len(pricewrapper) == 1:
                    pricewrapper = pricewrapper[0]
                    id = pricewrapper.xpath(
                        './/form/input[@class="product_id"]'
                    )[0].attrib["value"]
                    #name = cardhtml.xpath(".//span[@class='productDetailTitle']/text()")[0]
                    #edition = cardhtml.xpath(".//div[@class='productDetailSet']/text()")[0]
                    #edition = re.search(reEdition, edition).group(1).strip()
                    #editionid = None
                    # traducimos nombre de edicion a id
                    # for e in editions:
                    #     if (e["name"] == edition):
                    #         editionid = e["id"]
                    #         break
                    # if not editionid is None:
                    #     edition = editionid
                    # else:
                    #     print("Edicion no encontrada", edition, name)
                    #     edition = 0
                    price = "{}.{}".format(
                        pricewrapper.xpath(
                            ".//div[@class='usdSellPrice']/span[@class='sellDollarAmount']"
                        )[0].text_content().replace(",", ""),
                        pricewrapper.xpath(
                            ".//div[@class='usdSellPrice']/span[@class='sellCentsAmount']"
                        )[0].text_content())
                    # el credit se puede sacar multiplicando por 1.3
                    maxQty = pricewrapper.xpath(
                        './/form/input[@class="maxQty"]')[0].attrib["value"]
                    foil = len(cardhtml.xpath(".//div[@class='foil']")) > 0
                    #TODO: algunas veces se meten repetidas (mirar tokens)
                    # traducir id de la foil a la normal
                    if foil:
                        for translation in idtranslations:
                            if id == translation["foil"]:
                                id = translation["normal"]
                                break
                    inventorycard = InventoryCard(id, "", "")
                    inventorycard.entries.append(
                        CardDetails(price, maxQty, foil, "en", "NM"))
                    buylist.append(inventorycard)

        def do_work(page):
            sys.stdout.write("Paginas procesadas: %d%%   \r" %
                             (page * 100 / npages))
            sys.stdout.flush()
            filename = "{}/page{}.html".format(cachedir, page)
            try:
                f = open(filename, "r", encoding="utf8")
                data = f.read()
                f.close()
            except:
                page = requests.get("{}{}".format(baseurl, page))
                data = page.text
                with open(filename, "w", encoding="utf8") as f:
                    f.write(data)
            addCards(data)

        def worker():
            while True:
                item = q.get()
                do_work(item)
                q.task_done()

        baseurl = "https://www.cardkingdom.com/purchasing/mtg_singles?filter%5Bipp%5D=100&filter%5Bsort%5D=name&filter%5Bsearch%5D=mtg_advanced&filter%5Bname%5D=&filter%5Bcategory_id%5D=0&filter%5Bfoil%5D=1&filter%5Bnonfoil%5D=1&filter%5Bprice_op%5D=&filter%5Bprice%5D=&page="

        # cuantas paginas?
        req = requests.get(baseurl + "1")
        tree = html.fromstring(req.text)
        results = tree.xpath("//span[@class='resultsHeader']/text()")[0]
        npages = (int)((
            (int)(re.search("(\d*) results", results).group(1)) / 100) + 1)
        print("Paginas:", npages)

        today = time.strftime("%Y%m%d")

        cachedir = CK.cachedir.format("buylist/" + today)

        if not os.path.exists(cachedir):
            os.makedirs(cachedir)

        #reEdition = "(.*)\("
        lock = threading.Lock()

        buylist = []
        #sys.stdout.write("Obteniendo ediciones CK...")
        #sys.stdout.flush()
        #editions = CK.getEditions()
        idtranslations = phppgadmin.query(
            "SELECT foil,normal FROM ck_idtranslator")
        #sys.stdout.write("OK [{} ediciones]".format(len(editions)))
        #print("")

        q = Queue()
        for i in range(10):
            t = threading.Thread(target=worker)
            t.daemon = True
            t.start()

        start = time.perf_counter()

        for p in range(npages):
            q.put(p)

        q.join()

        print("Crawling finalizado          ")
        if (writecsv):
            print("Guardando .csv en disco...")
            filename = "{}/buylist.csv".format(cachedir)
            with open(filename, "w", newline='\n') as f:
                writer = csv.DictWriter(f,
                                        fieldnames=[
                                            "id", "name", "edition", "price",
                                            "count", "foil", "language",
                                            "condition"
                                        ],
                                        delimiter=',',
                                        quotechar='"',
                                        quoting=csv.QUOTE_MINIMAL)
                writer.writeheader()
                for card in buylist:
                    for entry in card.entries:
                        writer.writerow({
                            "id": card.id,
                            "name": card.name,
                            "edition": card.edition,
                            "price": entry.price,
                            "count": entry.count,
                            "foil": "true" if entry.foil else "false",
                            "language": entry.language,
                            "condition": entry.condition
                        })
        print("==[     END     ]==")

        return buylist
Beispiel #11
0
		self.edition = edition
		self.foil = foil
		self.page = page

class Edition:
	def __init__(self, id=0, name='', url=''):
		self.id=id
		self.name=name
		self.url=url
		self.cards = []

exectime = time.time()

editions = []
try:
    dbeditions = phppgadmin.query("select id, name, url from ck_editions")
    #dbeditions = phppgadmin.query("select id, name, url from ck_editions where name = 'Zendikar'")
except:
    print ("Using cached editions")
    dbeditions = []
    with open("data/ck/editions.csv") as csvfile:
        reader = csv.DictReader(csvfile, delimiter="|")
        for row in reader:
            dbeditions.append(row)

for edition in dbeditions:
    editions.append(Edition(edition["id"], edition["name"], edition["url"]))

sales = []

def getCards(page):
Beispiel #12
0
def finance_dondevendo():
    def obtenseleccion(candidatos, myset):
        if myset == "":
            return None
        else:
            for i, cand in reversed(list(enumerate(candidatos))):
                if cand["set"] == myset or (myset in son
                                            and cand["set"] == son[myset]):
                    return cand
                elif (myset in noson and cand["set"] in noson[myset]):
                    candidatos.pop(i)
            if len(candidatos) == 0:
                return None
            elif len(candidatos) == 1:
                return candidatos[0]
            else:
                print(":: {} [{}] ::".format(icard.name, icard.edition))
                for i, cand in list(enumerate(candidatos)):
                    print("{}. {}".format(i, cand["set"]))
                while True:
                    sel = input("Opcion: ")
                    print("")
                    # meterlas todas en noson
                    if sel == "":
                        if not myset in noson:
                            noson[myset] = []
                        noson[myset].extend(candidatos)
                        return None
                    else:
                        sel = (int)(sel)
                        cand = candidatos[sel]
                        son[myset] = cand["set"]
                        return cand

    usdtoeu = ExchangeRate.get("USDEUR=X")
    comisionmkm = 0.05  # comision que se queda mkm de las ventas
    undercut = 0.05  # undercut para vender
    inventory = Deckbox.inventory(True)
    vender = []
    print("Inventario: {} cartas diferentes".format(len(inventory)))
    sql = "select s.name as set, c.name as name, truefalse.value as foil, round(cast(ck.price * {} as numeric), 2) as ck, round(cast(mkm.price * {} as numeric), 2) as mkm from scr_cards c CROSS JOIN truefalse left join scr_sets s on c.set = s.code left join ck_buylist ck on c.idck = ck.card and truefalse.value = ck.foil left join mkm_cardpricesmin mkm on c.idmkm = mkm.id and truefalse.value = mkm.foil where (not mkm.name is null and not ck.card is null) and not s.digital".format(
        usdtoeu, 1 - comisionmkm - undercut)
    allcards = phppgadmin.query(sql)
    son = {}
    noson = {}
    for icard in inventory:
        for entry in icard.entries:
            # solo comparamos las cartas en ingles
            if (entry.language == "English"):
                candidatos = []
                for card in allcards:
                    if icard.name.lower() == card["name"].lower(
                    ) and entry.foil == (card["foil"] == "TRUE"):
                        candidatos.append(card)
                seleccion = obtenseleccion(candidatos, icard.edition)
                if not seleccion is None:
                    vender.append(seleccion)

    with open("output/dondevendo.csv", "w", newline='\n') as f:
        writer = csv.DictWriter(
            f,
            fieldnames=["set", "name", "foil", "ck", "mkm"],
            delimiter=',',
            quotechar='"',
            quoting=csv.QUOTE_MINIMAL)
        writer.writeheader()
        for card in vender:
            card["ck"] = card["ck"].replace(".", ",")
            card["mkm"] = card["mkm"].replace(".", ",")
            writer.writerow(card)